#include #include #include /* IO-APIC indirect register file */ #define IOAPIC_REGSEL 0x00 #define IOAPIC_WINDOW 0x10 #define REG_ID 0x00 #define REG_VER 0x01 #define REG_REDIR 0x10 /* bit 16 of a redirection entry masks that input */ #define REDIR_MASKED (1u << 16) /* redirection entry count lives in the version register's bits 23:16 */ #define IOAPIC_MAX_ENTRIES 24 static volatile uint32_t *ioapic(void) { return (volatile uint32_t *)(uint64_t)IOAPIC_DEFAULT_BASE; } static uint32_t ioapic_read(uint32_t reg) { /* * index-then-read: writing the register number to REGSEL selects it, and the * selected register is then read from WINDOW. */ *ioapic() = reg; return *(volatile uint32_t *)((uint64_t)IOAPIC_DEFAULT_BASE + IOAPIC_WINDOW); } static void ioapic_write(uint32_t reg, uint32_t value) { *ioapic() = reg; *(volatile uint32_t *)((uint64_t)IOAPIC_DEFAULT_BASE + IOAPIC_WINDOW) = value; } void ioapic_disarm(void) { uint32_t entries; uint32_t i; /* * mask first, before trusting the version register. entries are masked one * at a time, so if anything is already routed it stops as soon as we reach * it. */ for (i = 0; i < IOAPIC_MAX_ENTRIES; i++) { uint32_t entry = ioapic_read(REG_REDIR + 2 * i); ioapic_write(REG_REDIR + 2 * i, entry | REDIR_MASKED); } /* the version register encodes the entry count in bits 23:16 */ entries = (ioapic_read(REG_VER) >> 16) & 0xFF; if (entries == 0 || entries > IOAPIC_MAX_ENTRIES) { /* no usable count: mask everything the array can hold */ entries = IOAPIC_MAX_ENTRIES; } for (i = 0; i < entries; i++) { uint32_t entry = ioapic_read(REG_REDIR + 2 * i); ioapic_write(REG_REDIR + 2 * i, entry | REDIR_MASKED); } }