void isr_apic_bottom(struct x86_exregs *regs) { struct lapic_info *apic = &cpu_apics[0]; #if 0 printf("%s: frame at %p, exregs=%p, frame_len=%u (size=%u)\n", __func__, &apic, regs, (unsigned)x86_frame_len(regs), (unsigned)sizeof(*regs)); #endif /* figure out which interrupt this is from the ISRs. */ int vecnum; bool vec_found = false; for(int i=0; i <= apic->max_vector; i += 32) { uint32_t isr_limb = mm_inl(apic->base_addr + APIC_ISR(i >> 5)); if(i == 0) isr_limb &= ~0xffffu; if(isr_limb != 0) { vecnum = i + ffsl(isr_limb) - 1; vec_found = true; break; } } if(!vec_found) { apic->num_spurious++; ioapic_send_eoi(0); /* just in case. */ return; } #if 0 if(vecnum == 0x21) { printf("i'm a keyboard, toot toot\n"); #define KBD_STATUS_REG 0x64 #define KBD_DATA_REG 0x60 #define KBD_STAT_OBF 0x01 for(;;) { uint8_t st = inb(KBD_STATUS_REG); if((st & KBD_STAT_OBF) == 0) break; inb(KBD_DATA_REG); /* and throw it away */ } } else { printf("APIC interrupt vector %d\n", vecnum); } #endif regs->reason = vecnum; isr_irq_bottom(regs); return; #if 0 /* TODO: move this into an x86_print_exregs() function */ printf("exregs: reason=%#lx, es=%#lx, ds=%#lx, cs=%#lx, ss=%#lx\n" "\tedi=%#lx, esi=%#lx, ebp=%#lx, __esp=%#lx\n" "\tebx=%#lx, edx=%#lx, ecx=%#lx, eax=%#lx\n" "\terror=%#lx, eip=%#lx, eflags=%#lx, esp=%#lx\n", regs->reason, regs->es, regs->ds, regs->cs, regs->ss, regs->edi, regs->esi, regs->ebp, regs->__esp, regs->ebx, regs->edx, regs->ecx, regs->eax, regs->error, regs->eip, regs->eflags, regs->esp); #endif }
static inline bool irq_in_kernel(const struct x86_exregs *frame) { /* ring0 interrupts push a short stack frame. */ return x86_frame_len(frame) < sizeof(*frame); }