PCI drivers took their interrupt from INTERRUPT_LINE. On real hardware that is the 8259's number, not the IOAPIC pin the device is wired to (that is in ACPI _PRT, which needs AML), so nothing ever arrived. xHCI is entirely interrupt-driven, so the USB keyboard and a USB root would have hung even on a clean boot. Under QEMU the two numbers agree, which is why it never showed. - pci_irq_attach()/pci_irq_detach(): MSI, then MSI-X if the driver allows it, then INTx. The handler is registered before MSI is enabled, so no edge is lost. xHCI, e1000, r8169 and rtl8139 use it. - Lines 24-29 are MSI vectors. The LAPIC error vector moves from 19, which is a PCI pin on Intel chipsets, to 30. Nothing is placed at or above vector 64 (T_SYSCALL). - A storming line is masked and its handlers are polled instead of being left to eat the CPU. A level line that has had a handler for 2 s and never fired is polled every tick by a kernel thread. Tested in QEMU q35 with the root on a USB stick: xHCI and e1000e on MSI; then MSI disabled and INTx deliberately misrouted, where xHCI got zero interrupts and the root still mounted through the poller. i440fx INTx and the rtl8139 hand-over are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HH7xukt4aaiGj1nQEAoQf1
71 lines
2 KiB
C
71 lines
2 KiB
C
#pragma once
|
|
|
|
// x86 trap and interrupt constants.
|
|
|
|
// Processor-defined exceptions:
|
|
#define T_DIVIDE 0 // divide error
|
|
#define T_DEBUG 1 // debug exception
|
|
#define T_NMI 2 // non-maskable interrupt
|
|
#define T_BRKPT 3 // breakpoint
|
|
#define T_OFLOW 4 // overflow
|
|
#define T_BOUND 5 // bounds check
|
|
#define T_ILLOP 6 // illegal opcode
|
|
#define T_DEVICE 7 // device not available
|
|
#define T_DBLFLT 8 // double fault
|
|
#define T_TSS 10 // invalid task switch segment
|
|
#define T_SEGNP 11 // segment not present
|
|
#define T_STACK 12 // stack exception
|
|
#define T_GPFLT 13 // general protection fault
|
|
#define T_PGFLT 14 // page fault
|
|
#define T_FPERR 16 // floating point error
|
|
#define T_ALIGN 17 // aligment check
|
|
#define T_MCHK 18 // machine check
|
|
#define T_SIMDERR 19 // SIMD floating point error
|
|
|
|
// IRQ offsets
|
|
#define T_IRQ0 32 // IRQ 0 corresponds to int T_IRQ
|
|
|
|
#define IRQ_TIMER 0
|
|
#define IRQ_KBD 1
|
|
#define IRQ_COM1 4
|
|
#define IRQ_MOUSE 12
|
|
#define IRQ_IDE 14
|
|
// 30, not xv6's 19. Vector T_IRQ0+19 is IOAPIC pin 19, which real chipsets
|
|
// use for PCI; the LAPIC error interrupt would have shared it.
|
|
#define IRQ_ERROR 30
|
|
#define IRQ_SPURIOUS 31
|
|
|
|
// System call interrupt number for legacy int 0x40 or 0x80 if used
|
|
// although syscall/sysret is preferred for x64
|
|
#define T_SYSCALL 0x40
|
|
|
|
#ifndef __ASSEMBLER__
|
|
struct trapframe {
|
|
// Registers saved by trapasm.S
|
|
uint64 rax;
|
|
uint64 rbx;
|
|
uint64 rcx;
|
|
uint64 rdx;
|
|
uint64 rbp;
|
|
uint64 rsi;
|
|
uint64 rdi;
|
|
uint64 r8;
|
|
uint64 r9;
|
|
uint64 r10;
|
|
uint64 r11;
|
|
uint64 r12;
|
|
uint64 r13;
|
|
uint64 r14;
|
|
uint64 r15;
|
|
|
|
uint64 trapno;
|
|
|
|
// Error code and info saved by hardware
|
|
uint64 err;
|
|
uint64 rip;
|
|
uint64 cs;
|
|
uint64 rflags;
|
|
uint64 rsp;
|
|
uint64 ss;
|
|
};
|
|
#endif
|