From f28fd84c68dab3edb2794ee8e9c1e1f70adb55b1 Mon Sep 17 00:00:00 2001 From: stefan Date: Mon, 29 Nov 2010 02:39:10 +0000 Subject: [PATCH] - redesign of the apic code - add ioapic support - currently, all irq will forwarded to the boot processor git-svn-id: http://svn.lfbs.rwth-aachen.de/svn/scc/trunk/MetalSVM@293 315a16e6-25f9-4109-90ae-ca3045a26c18 --- arch/x86/include/asm/apic.h | 64 +++++++++- arch/x86/kernel/apic.c | 234 +++++++++++++++++++++++++++++++----- arch/x86/kernel/entry.asm | 91 +++++++++++++- arch/x86/kernel/irq.c | 46 +++++-- arch/x86/kernel/isrs.c | 2 +- arch/x86/kernel/timer.c | 4 +- 6 files changed, 386 insertions(+), 55 deletions(-) diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 0d318c85..7b0e52e5 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -40,7 +40,7 @@ typedef struct { typedef struct { uint32_t signature; uint16_t length; - uint8_t revision; + uint8_t revision; uint8_t checksum; uint8_t oem_id[8]; uint8_t product_id[12]; @@ -49,15 +49,15 @@ typedef struct { uint16_t entry_count; uint32_t lapic; uint16_t extended_table_length; - uint8_t extended_table_checksum; + uint8_t extended_table_checksum; } __attribute__ ((packed)) apic_config_table_t; /* APIC Processor Entry */ typedef struct { - uint8_t type; + uint8_t type; uint8_t id; uint8_t version; - uint8_t cpu; + uint8_t cpu_flags; uint32_t cpu_signature; uint32_t cpu_feature; } __attribute__ ((packed)) apic_processor_entry_t; @@ -71,13 +71,67 @@ typedef struct { uint32_t addr; } __attribute__ ((packed)) apic_io_entry_t; +/* Bus Entry */ +typedef struct { + uint8_t type; + uint8_t bus_id; + char name[6]; +} __attribute__ ((packed)) apic_bus_entry_t; + +/* I/O Interrupt Assignment Entry */ +typedef struct { + uint8_t type; // type = 3 + uint8_t itype; // interrupt type + uint16_t flags; // flags , PO and EL + uint8_t src_bus; // source bus id + uint8_t src_irq; // source interrupt (from the old bus) + uint8_t dest_apic; // who it gets sent to 0xFF == all + uint8_t dest_intin; // which pin it gets sent to on the IO APIC +} __attribute__ ((packed)) apic_ioirq_entry_t; + +typedef struct { + union { + struct { + uint32_t vector : 8, + delivery_mode : 3, /* 000: FIXED + * 001: lowest prio + * 111: ExtINT + */ + dest_mode : 1, /* 0: physical, 1: logical */ + delivery_status : 1, + polarity : 1, + irr : 1, + trigger : 1, /* 0: edge, 1: level */ + mask : 1, /* 0: enabled, 1: disabled */ + __reserved_2 : 15; + } bitfield; + uint32_t whole; + } lower; + union { + struct { + uint32_t __reserved_1 : 24, + physical_dest : 4, + __reserved_2 : 4; + } physical; + + struct { + uint32_t __reserved_1 : 24, + logical_dest : 8; + } logical; + uint32_t upper; + } dest; +} __attribute__ ((packed)) ioapic_route_t; + int apic_init(void); void apic_eoi(void); +uint32_t apic_cpu_id(void); int apic_calibration(void); int has_apic(void); +int apic_is_enabled(void); +int ioapic_inton(uint8_t irq, uint8_t apicid); +int ioapic_intoff(uint8_t irq, uint8_t apicid); #ifdef __cplusplus } #endif - #endif diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 7649770d..4d1b0bcc 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -30,6 +30,7 @@ #define MP_FLT_SIGNATURE 0x5f504d5f +#define APIC_ID 0x0020 // Local APIC ID Register #define APIC_VERSION 0x0030 // Local APIC Version Register #define APIC_TPR 0x0080 // Task Priority Regster #define APIC_EOI 0x00B0 // EOI Register @@ -43,14 +44,58 @@ #define APIC_CCR 0x0390 // Current Count Register #define APIC_DCR 0x03E0 // Divide Configuration Register +#define IOAPIC_REG_ID 0x0000 // Register index: ID +#define IOAPIC_REG_VER 0x0001 // Register index: version +#define IOAPIC_REG_TABLE 0x0010 // Redirection table base + +// IO APIC MMIO structure: write reg, then read or write data. +typedef struct { + uint32_t reg; + uint32_t pad[3]; + uint32_t data; +} ioapic_t; + +static const apic_processor_entry_t* apic_processors[MAX_CORES] = {[0 ... MAX_CORES-1] = NULL}; +static uint32_t boot_processor = MAX_CORES; static apic_mp_t* apic_mp = NULL; static apic_config_table_t* apic_config = NULL; static uint32_t lapic = 0; +static volatile ioapic_t* ioapic = NULL; static uint32_t ncores = 1; +static uint8_t irq_redirect[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF}; +static uint8_t initialized = 0; -static inline void apic_write(uint32_t addr, uint32_t value) +static inline uint32_t lapic_read(uint32_t addr) { - asm volatile ("movl (%%eax), %%edx; movl %%ebx, (%%eax)" :: "a"(addr), "b"(value) : "%edx"); + return *((uint32_t*) (lapic+addr)); +} + +static inline void lapic_write(uint32_t addr, uint32_t value) +{ + /* + * to avoid ap entium bug, we have to read a apic register before + * before we write value to this register + */ + asm volatile ("movl (%%eax), %%edx; movl %%ebx, (%%eax)" :: "a"(addr+lapic), "b"(value) : "%edx"); + //*((uint32_t*) (lapic+addr)) = value; +} + +static inline uint32_t ioapic_read(uint32_t reg) +{ + ioapic->reg = reg; + + return ioapic->data; +} + +static inline void ioapic_write(uint32_t reg, uint32_t value) +{ + ioapic->reg = reg; + ioapic->data = value; +} + +uint32_t apic_cpu_id(void) +{ + return ((lapic_read(APIC_ID)) >> 24); } #ifndef CONFIG_MULTIBOOT @@ -73,8 +118,8 @@ static unsigned int* search_apic(unsigned int base, unsigned int limit) { */ void apic_eoi(void) { - if (lapic) - apic_write(lapic+APIC_EOI, 0); + if (BUILTIN_EXPECT(lapic, 1)) + lapic_write(APIC_EOI, 0); } /* @@ -83,6 +128,8 @@ void apic_eoi(void) */ int apic_calibration(void) { + uint8_t i; + #ifndef CONFIG_ROCKCREEK uint64_t ticks, old; uint32_t diff; @@ -96,9 +143,9 @@ int apic_calibration(void) while((ticks = get_clock_tick()) - old == 0) ; - apic_write(lapic+APIC_DCR, 0xB); // set it to 1 clock increments - apic_write(lapic+APIC_LVT_T, 0x20030); // connects the timer to 48 and enables it - apic_write(lapic+APIC_ICR, 0xFFFFFFFF); + lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments + lapic_write(APIC_LVT_T, 0x2007B); // connects the timer to 123 and enables it + lapic_write(APIC_ICR, 0xFFFFFFFF); /* wait 3 time slices to determine a ICR */ while(get_clock_tick() - ticks < 3) @@ -106,9 +153,9 @@ int apic_calibration(void) diff = 0xFFFFFFFF - *((uint32_t*) (lapic+APIC_CCR)); - apic_write(lapic+APIC_DCR, 0xB); // set it to 1 clock increments - apic_write(lapic+APIC_LVT_T, 0x20030); // connects the timer to 48 and enables it - apic_write(lapic+APIC_ICR, diff / 3); + lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments + lapic_write(APIC_LVT_T, 0x2007B); // connects the timer to 123 and enables it + lapic_write(APIC_ICR, diff / 3); // Now, MetalSVM is able to use the APIC => Therefore, we disable the PIC outportb(0xA1, 0xFF); @@ -125,9 +172,9 @@ int apic_calibration(void) if (!has_apic()) return -ENXIO; - apic_write(lapic+APIC_DCR, 0xB); // set it to 1 clock increments - apic_write(lapic+APIC_LVT_T, 0x20030); // connects the timer to 48 and enables it - apic_write(lapic+APIC_ICR, 0xFFFFFFFF); + lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments + lapic_write(APIC_LVT_T, 0x2007B); // connects the timer to 123 and enables it + lapic_write(APIC_ICR, 0xFFFFFFFF); /* wait 3 time slices to determine a ICR */ start = rdtsc(); @@ -139,13 +186,24 @@ int apic_calibration(void) diff = 0xFFFFFFFF - *((uint32_t*) (lapic+APIC_CCR)); - apic_write(lapic+APIC_DCR, 0xB); // set it to 1 clock increments - apic_write(lapic+APIC_LVT_T, 0x20030); // connects the timer to 48 and enables it - apic_write(lapic+APIC_ICR, diff / 3); + lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments + lapic_write(APIC_LVT_T, 0x2007B); // connects the timer to 123 and enables it + lapic_write(APIC_ICR, diff / 3); #endif kprintf("APIC calibration detects an ICR of 0x%x\n", diff / 3); + irq_disable(); + if (ioapic) { + // now, we don't longer need the IOAPIC timer and turn it off + ioapic_intoff(0, apic_processors[boot_processor]->id); + // now lets turn everything else on + for(i=1; i<24; i++) + ioapic_inton(i, apic_processors[boot_processor]->id); + } + initialized = 1; + irq_enable(); + return 0; } @@ -153,6 +211,7 @@ static int apic_probe(void) { size_t addr; uint32_t i, count; + int isa_bus = -1; // searching MP signature in the reserved memory areas #ifdef CONFIG_MULTIBOOT @@ -200,15 +259,59 @@ found_mp: goto no_mp; } + addr = (size_t) apic_config; + addr += sizeof(apic_config_table_t); + if (addr % 4) + addr += 4 - addr % 4; + + // search the ISA bus => required to redirect the IRQs + for(i=0; ientry_count; i++) { + switch(*((uint8_t*) addr)) { + case 0: + addr += 20; + break; + case 1: { + apic_bus_entry_t* mp_bus; + + mp_bus = (apic_bus_entry_t*) addr; + if (mp_bus->name[0] == 'I' && mp_bus->name[1] == 'S' && + mp_bus->name[2] == 'A') + isa_bus = i; + } + default: + addr += 8; + } + } + addr = (size_t) apic_config; addr += sizeof(apic_config_table_t); if (addr % 4) addr += 4 - addr % 4; for(i=0, count=0; ientry_count; i++) { - if (*((uint8_t*) addr) == 0) { + if (*((uint8_t*) addr) == 0) { // cpu entry + if (i < MAX_CORES) { + apic_processors[i] = (apic_processor_entry_t*) addr; + if (!(apic_processors[i]->cpu_flags & 0x01)) // is the processor usable? + apic_processors[i] = NULL; + else if (apic_processors[i]->cpu_flags & 0x02) + boot_processor = i; + } count++; addr += 20; + } else if (*((uint8_t*) addr) == 2) { // IO_APIC + apic_io_entry_t* io_entry = (apic_io_entry_t*) addr; + ioapic = (ioapic_t*) io_entry->addr; + addr += 8; + kprintf("Found IOAPIC at 0x%x (ver. 0x%x)\n", ioapic, + ioapic_read(IOAPIC_REG_VER)); + } else if (*((uint8_t*) addr) == 3) { // IO_INT + apic_ioirq_entry_t* extint = (apic_ioirq_entry_t*) addr; + if (extint->src_bus == isa_bus) { + irq_redirect[extint->src_irq] = extint->dest_intin; + kprintf("Redirect irq %u -> %u\n", extint->src_irq, extint->dest_intin); + } + addr += 8; } else addr += 8; } kprintf("Found %u cores\n", count); @@ -223,13 +326,11 @@ check_lapic: if (apic_config) { lapic = apic_config->lapic; } else { - uint32_t eax, edx, dummy; + uint32_t edx, dummy; - cpuid(0x1, &eax, &dummy, &dummy, &edx); + cpuid(0x1, &dummy, &dummy, &dummy, &edx); if (edx & (1 << 9)) lapic = 0xFEE00000; - - kprintf("Processor familiy %u, model %u, stepping %u\n", (eax>>8)&0xF, (eax>>4)&0xF, eax&0xF); } if (!lapic) @@ -259,18 +360,27 @@ no_mp: int apic_init(void) { int ret; + uint8_t i; ret = apic_probe(); if (!ret) return ret; - apic_write(lapic+APIC_TPR, 0x00); // allow all interrupts - apic_write(lapic+APIC_LVT_T, 0x10000); // disable timer interrupt - apic_write(lapic+APIC_LVT_PMC, 0x10000);// disable performance counter interrupt - apic_write(lapic+APIC_LINT0, 0x31); // connect LINT0 to idt entry 49 - apic_write(lapic+APIC_LINT1, 0x32); // connect LINT1 to idt entry 50 - apic_write(lapic+APIC_LVT_ER, 0x33); // connect error to idt entry 51 - apic_write(lapic+APIC_SVR, 0x17F); // enable the apic and connect to the idt entry 207 + lapic_write(APIC_TPR, 0x00); // allow all interrupts + lapic_write(APIC_LVT_T, 0x10000); // disable timer interrupt + lapic_write(APIC_LVT_PMC, 0x10000);// disable performance counter interrupt + lapic_write(APIC_LINT0, 0x7C); // connect LINT0 to idt entry 124 + lapic_write(APIC_LINT1, 0x7D); // connect LINT1 to idt entry 125 + lapic_write(APIC_LVT_ER, 0x7E); // connect error to idt entry 126 + lapic_write(APIC_SVR, 0x17F); // enable the apic and connect to the idt entry 127 + + if (ioapic) { + // enable timer interrupt + ioapic_inton(0, apic_processors[boot_processor]->id); + // now lets turn everything else off + for(i=1; i<24; i++) + ioapic_intoff(i, apic_processors[boot_processor]->id); + } return 0; } @@ -279,3 +389,71 @@ int has_apic(void) { return (lapic != 0); } + +int apic_is_enabled(void) +{ + return ((lapic != 0) && initialized); +} + +int ioapic_inton(uint8_t irq, uint8_t apicid) +{ + ioapic_route_t route; + uint32_t off; + + if (BUILTIN_EXPECT(irq > 24, 0)){ + kprintf("IOAPIC: trying to turn on irq %i which is too high\n", irq); + return -EINVAL; + } + + if (irq < 16) + off = irq_redirect[irq]*2; + else + off = irq*2; + + route.lower.bitfield.dest_mode = 0; + route.lower.bitfield.mask = 0; + route.dest.physical.physical_dest = apicid; // send to the boot processor + route.lower.bitfield.delivery_mode = 0; + route.lower.bitfield.polarity = 0; + route.lower.bitfield.trigger = 0; + route.lower.bitfield.vector = 0x20+irq; + route.lower.bitfield.mask = 0; // turn it on (stop masking) + + ioapic_write(IOAPIC_REG_TABLE+off, route.lower.whole); + ioapic_write(IOAPIC_REG_TABLE+1+off, route.dest.upper); + + route.dest.upper = ioapic_read(IOAPIC_REG_TABLE+1+off); + route.lower.whole = ioapic_read(IOAPIC_REG_TABLE+off); + + return 0; +} + +int ioapic_intoff(uint8_t irq, uint8_t apicid) +{ + ioapic_route_t route; + uint32_t off; + + if (BUILTIN_EXPECT(irq > 24, 0)){ + kprintf("IOAPIC: trying to turn on irq %i which is too high\n", irq); + return -EINVAL; + } + + if (irq < 16) + off = irq_redirect[irq]*2; + else + off = irq*2; + + route.lower.bitfield.dest_mode = 0; + route.lower.bitfield.mask = 0; + route.dest.physical.physical_dest = apicid; + route.lower.bitfield.delivery_mode = 0; + route.lower.bitfield.polarity = 0; + route.lower.bitfield.trigger = 0; + route.lower.bitfield.vector = 0x20+irq; + route.lower.bitfield.mask = 1; // turn it off (start masking) + + ioapic_write(IOAPIC_REG_TABLE+off, route.lower.whole); + ioapic_write(IOAPIC_REG_TABLE+1+off, route.dest.upper); + + return 0; +} diff --git a/arch/x86/kernel/entry.asm b/arch/x86/kernel/entry.asm index 54b215c7..e4063547 100644 --- a/arch/x86/kernel/entry.asm +++ b/arch/x86/kernel/entry.asm @@ -473,6 +473,14 @@ global irq12 global irq13 global irq14 global irq15 +global irq16 +global irq17 +global irq18 +global irq19 +global irq20 +global irq21 +global irq22 +global irq23 global apic_timer global apic_lint0 global apic_lint1 @@ -518,9 +526,9 @@ irq0: ; cli push byte 0 push byte 32 - pusha Lirq0: + pusha push esp call irq_handler add esp, 4 @@ -681,13 +689,84 @@ irq15: push byte 47 jmp irq_common_stub +; 48: IRQ16 +irq16: + ; irq16 - irq23 are registered as "Interrupt Gate" + ; Therefore, the interrupt flag (IF) is already cleared. + ; cli + push byte 0 + push byte 48 + jmp irq_common_stub + +; 49: IRQ17 +irq17: + ; irq16- irq23 are registered as "Interrupt Gate" + ; Therefore, the interrupt flag (IF) is already cleared. + ; cli + push byte 0 + push byte 49 + jmp irq_common_stub + +; 50: IRQ18 +irq18: + ; irq16 - irq23 are registered as "Interrupt Gate" + ; Therefore, the interrupt flag (IF) is already cleared. + ; cli + push byte 0 + push byte 50 + jmp irq_common_stub + +; 51: IRQ19 +irq19: + ; irq16 - irq23 are registered as "Interrupt Gate" + ; Therefore, the interrupt flag (IF) is already cleared. + ; cli + push byte 0 + push byte 51 + jmp irq_common_stub + +; 52: IRQ20 +irq20: + ; irq16- irq23 are registered as "Interrupt Gate" + ; Therefore, the interrupt flag (IF) is already cleared. + ; cli + push byte 0 + push byte 52 + jmp irq_common_stub + +; 53: IRQ21 +irq21: + ; irq16 - irq23 are registered as "Interrupt Gate" + ; Therefore, the interrupt flag (IF) is already cleared. + ; cli + push byte 0 + push byte 53 + jmp irq_common_stub + +; 54: IRQ22 +irq22: + ; irq16- irq23 are registered as "Interrupt Gate" + ; Therefore, the interrupt flag (IF) is already cleared. + ; cli + push byte 0 + push byte 54 + jmp irq_common_stub + +; 55: IRQ23 +irq23: + ; irq16 - irq23 are registered as "Interrupt Gate" + ; Therefore, the interrupt flag (IF) is already cleared. + ; cli + push byte 0 + push byte 55 + jmp irq_common_stub + apic_timer: ; apic timer is registered as "Interrupt Gate" ; Therefore, the interrupt flag (IF) is already cleared. ; cli push byte 0 - push byte 48 - pusha + push byte 123 ; we reuse code of the "traditional" timer interrupt (PIC) jmp Lirq0 @@ -696,7 +775,7 @@ apic_lint0: ; Therefore, the interrupt flag (IF) is already cleared. ; cli push byte 0 - push byte 49 + push byte 124 jmp irq_common_stub apic_lint1: @@ -704,7 +783,7 @@ apic_lint1: ; Therefore, the interrupt flag (IF) is already cleared. ; cli push byte 0 - push byte 50 + push byte 125 jmp irq_common_stub apic_error: @@ -712,7 +791,7 @@ apic_error: ; Therefore, the interrupt flag (IF) is already cleared. ; cli push byte 0 - push byte 51 + push byte 126 jmp irq_common_stub apic_svr: diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index e56bbab5..e43071d8 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -17,6 +17,7 @@ * This file is part of MetalSVM. */ +#include #include #include #include @@ -45,6 +46,14 @@ extern void irq12(void); extern void irq13(void); extern void irq14(void); extern void irq15(void); +extern void irq16(void); +extern void irq17(void); +extern void irq18(void); +extern void irq19(void); +extern void irq20(void); +extern void irq21(void); +extern void irq22(void); +extern void irq23(void); extern void apic_timer(void); extern void apic_lint0(void); extern void apic_lint1(void); @@ -57,7 +66,7 @@ extern void apic_svr(void); * This array is actually an array of function pointers. We use * this to handle custom IRQ handlers for a given IRQ */ -static void *irq_routines[MAX_HANDLERS] = {[0 ... MAX_HANDLERS-1] = NULL }; +static void* irq_routines[MAX_HANDLERS] = {[0 ... MAX_HANDLERS-1] = NULL }; /* This installs a custom IRQ handler for the given IRQ */ int irq_install_handler(unsigned int irq, irq_handler_t handler) @@ -152,13 +161,30 @@ static int irq_install(void) IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); if (has_apic()) { - idt_set_gate(48, (unsigned)apic_timer, KERNEL_CODE_SELECTOR, + idt_set_gate(48, (unsigned)irq16, KERNEL_CODE_SELECTOR, IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); - idt_set_gate(49, (unsigned)apic_lint0, KERNEL_CODE_SELECTOR, + idt_set_gate(49, (unsigned)irq17, KERNEL_CODE_SELECTOR, IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); - idt_set_gate(50, (unsigned)apic_lint1, KERNEL_CODE_SELECTOR, + idt_set_gate(50, (unsigned)irq18, KERNEL_CODE_SELECTOR, IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); - idt_set_gate(51, (unsigned)apic_error, KERNEL_CODE_SELECTOR, + idt_set_gate(51, (unsigned)irq19, KERNEL_CODE_SELECTOR, + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + idt_set_gate(52, (unsigned)irq20, KERNEL_CODE_SELECTOR, + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + idt_set_gate(53, (unsigned)irq21, KERNEL_CODE_SELECTOR, + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + idt_set_gate(54, (unsigned)irq22, KERNEL_CODE_SELECTOR, + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + idt_set_gate(55, (unsigned)irq23, KERNEL_CODE_SELECTOR, + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + + idt_set_gate(123, (unsigned)apic_timer, KERNEL_CODE_SELECTOR, + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + idt_set_gate(124, (unsigned)apic_lint0, KERNEL_CODE_SELECTOR, + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + idt_set_gate(125, (unsigned)apic_lint1, KERNEL_CODE_SELECTOR, + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + idt_set_gate(126, (unsigned)apic_error, KERNEL_CODE_SELECTOR, IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); idt_set_gate(127, (unsigned)apic_svr, KERNEL_CODE_SELECTOR, IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); @@ -196,16 +222,10 @@ void irq_handler(struct state *s) /* This is a blank function pointer */ void (*handler) (struct state * s); - if (s->int_no - 32 > MAX_HANDLERS) { - apic_eoi(); - return; - } - /* * Find out if we have a custom handler to run for this * IRQ and then finally, run it - */ - + */ handler = irq_routines[s->int_no - 32]; if (handler) handler(s); @@ -214,7 +234,7 @@ void irq_handler(struct state *s) * If the IDT entry that was invoked was greater-than-or-equal to 48, * then we use the APIC */ - if (s->int_no >= 48) { + if (apic_is_enabled() || s->int_no >= 123) { apic_eoi(); return; } diff --git a/arch/x86/kernel/isrs.c b/arch/x86/kernel/isrs.c index 9db010ae..355a21f2 100644 --- a/arch/x86/kernel/isrs.c +++ b/arch/x86/kernel/isrs.c @@ -173,7 +173,7 @@ void fault_handler(struct state *s) kputs(" Exception.\n"); /* Now, we signalize that we have handled the interrupt */ - if (has_apic()) + if (apic_is_enabled()) apic_eoi(); else outportb(0x20, 0x20); diff --git a/arch/x86/kernel/timer.c b/arch/x86/kernel/timer.c index fb113385..e7492534 100644 --- a/arch/x86/kernel/timer.c +++ b/arch/x86/kernel/timer.c @@ -81,11 +81,11 @@ int timer_init(void) uint64_t start; /* - * Installs 'timer_handler' for the PIC (0) and APIC timer (16), + * Installs 'timer_handler' for the PIC and APIC timer, * only one handler will be later used. */ irq_install_handler(0, timer_handler); - irq_install_handler(16, timer_handler); + irq_install_handler(123-32, timer_handler); /* * The Rock Creek processor doesn't posseess an tradional PIC.