- 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
This commit is contained in:
stefan 2010-11-29 02:39:10 +00:00
parent 3e1c151b5f
commit f28fd84c68
6 changed files with 386 additions and 55 deletions

View file

@ -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

View file

@ -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; i<apic_config->entry_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; i<apic_config->entry_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;
}

View file

@ -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:

View file

@ -17,6 +17,7 @@
* This file is part of MetalSVM.
*/
#include <metalsvm/stdio.h>
#include <metalsvm/string.h>
#include <metalsvm/tasks.h>
#include <metalsvm/errno.h>
@ -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;
}

View file

@ -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);

View file

@ -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.