check_masked_interrupts(cpu *processor) { if (cpu_registers(processor)->msr & msr_external_interrupt_enable) { if (cpu_interrupts(processor)->pending_interrupts) schedule_hardware_interrupt_delivery(processor); } }
decrementer_interrupt(cpu *processor) { interrupts *ints = cpu_interrupts(processor); ints->pending_interrupts |= decrementer_interrupt_pending; if (cpu_registers(processor)->msr & msr_external_interrupt_enable) { schedule_hardware_interrupt_delivery(processor); } }
schedule_hardware_interrupt_delivery(cpu *processor) { interrupts *ints = cpu_interrupts(processor); if (ints->delivery_scheduled == NULL) { ints->delivery_scheduled = event_queue_schedule(psim_event_queue(cpu_system(processor)), 0, deliver_hardware_interrupt, processor); } }
external_interrupt(cpu *processor, int is_asserted) { interrupts *ints = cpu_interrupts(processor); if (is_asserted) { if (!ints->pending_interrupts & external_interrupt_pending) { ints->pending_interrupts |= external_interrupt_pending; if (cpu_registers(processor)->msr & msr_external_interrupt_enable) schedule_hardware_interrupt_delivery(processor); } else { /* check that we haven't missed out on a chance to deliver an interrupt */ ASSERT(!(cpu_registers(processor)->msr & msr_external_interrupt_enable)); } } else { ints->pending_interrupts &= ~external_interrupt_pending; } }
void ProcThread::run() { this->interrupts_pre_ptr = NULL; this->interrupts_post_ptr = NULL; uint32_t *interr_diff = NULL; uint16_t i = 0; this->running = true; interr_diff =(uint32_t*) calloc(cpun, sizeof(uint32_t)); while(this->running) { this->interrupts_post_ptr = cpu_interrupts(); if(this->interrupts_pre_ptr) for(i = 0; i < this->cpun; ++i) interr_diff[i] = this->interrupts_post_ptr[i] - this->interrupts_pre_ptr[i]; emit send_interrupts(interr_diff); sleep(1); /* Now we should free this :) */ if(this->interrupts_pre_ptr) { free(this->interrupts_pre_ptr); this->interrupts_pre_ptr = NULL; } /* And get the next pointer*/ this->interrupts_pre_ptr = this->interrupts_post_ptr; } /* When we finish, free all */ if(this->interrupts_post_ptr) free(this->interrupts_post_ptr); this->interrupts_pre_ptr = NULL; this->interrupts_post_ptr = NULL; }
deliver_hardware_interrupt(void *data) { cpu *processor = (cpu*)data; interrupts *ints = cpu_interrupts(processor); ints->delivery_scheduled = NULL; if (cpu_registers(processor)->msr & msr_external_interrupt_enable) { /* external interrupts have a high priority and remain pending */ if (ints->pending_interrupts & external_interrupt_pending) { unsigned_word cia = cpu_get_program_counter(processor); unsigned_word nia = perform_oea_interrupt(processor, cia, 0x00500, 0, 0, 0, 0); cpu_set_program_counter(processor, nia); } /* decrementer interrupts have a lower priority and are once only */ else if (ints->pending_interrupts & decrementer_interrupt_pending) { unsigned_word cia = cpu_get_program_counter(processor); unsigned_word nia = perform_oea_interrupt(processor, cia, 0x00900, 0, 0, 0, 0); cpu_set_program_counter(processor, nia); ints->pending_interrupts &= ~decrementer_interrupt_pending; } } }