diff --git a/kernel-src/arch/x86-64/hpet.c b/kernel-src/arch/x86-64/hpet.c index 802fde82..e175a2b5 100644 --- a/kernel-src/arch/x86-64/hpet.c +++ b/kernel-src/arch/x86-64/hpet.c @@ -116,7 +116,7 @@ time_t arch_hpet_init() { if (capabilities & HPET_CAP_LEGACYCAPABLE) { type = TYPE_LEGACY; - arch_ioapic_setirq(0, isr->id & 0xff, _cpu()->id, false); + arch_ioapic_setirq(0, isr->id & 0xff, current_cpu_id(), false); selectedtimer = 0; timerconfig = read64(HPET_TIMER_CONFIG(selectedtimer)); diff --git a/kernel-src/arch/x86-64/ps2kbd.c b/kernel-src/arch/x86-64/ps2kbd.c index 6b1e9c2b..f6b0c133 100644 --- a/kernel-src/arch/x86-64/ps2kbd.c +++ b/kernel-src/arch/x86-64/ps2kbd.c @@ -154,7 +154,7 @@ static void kbdisr(isr_t *isr, context_t *ctx) { void ps2kbd_init() { isr_t *isr = interrupt_allocate(kbdisr, arch_apic_eoi, IPL_KEYBOARD); __assert(isr); - arch_ioapic_setirq(KEYBOARDIRQ, isr->id & 0xff, _cpu()->id, false); + arch_ioapic_setirq(KEYBOARDIRQ, isr->id & 0xff, current_cpu_id(), false); kb = keyboard_new(); __assert(kb); printf("ps2kbd: irq enabled with vector %u\n", isr->id & 0xff); diff --git a/kernel-src/arch/x86-64/ps2mouse.c b/kernel-src/arch/x86-64/ps2mouse.c index b3affba7..8ed0de1c 100644 --- a/kernel-src/arch/x86-64/ps2mouse.c +++ b/kernel-src/arch/x86-64/ps2mouse.c @@ -111,7 +111,7 @@ void ps2mouse_init() { isr_t *isr = interrupt_allocate(mouseisr, arch_apic_eoi, IPL_MOUSE); __assert(isr); - arch_ioapic_setirq(PS2_MOUSEIRQ, isr->id & 0xff, _cpu()->id, false); + arch_ioapic_setirq(PS2_MOUSEIRQ, isr->id & 0xff, current_cpu_id(), false); mouse = mouse_new(); __assert(mouse); printf("ps2mouse: irq enabled with vector %u\n", isr->id & 0xff); diff --git a/kernel-src/include/x86-64/arch/cpu.h b/kernel-src/include/x86-64/arch/cpu.h index 29012fa3..454c4479 100644 --- a/kernel-src/include/x86-64/arch/cpu.h +++ b/kernel-src/include/x86-64/arch/cpu.h @@ -19,9 +19,9 @@ typedef struct cpu_t { thread_t *thread; struct cpu_t *self; vmmcontext_t *vmmctx; + long id; uint64_t gdt[7]; ist_t ist; - long id; isr_t isr[MAX_ISR_COUNT]; int acpiid; timer_t *timer; @@ -78,6 +78,12 @@ static inline void set_current_vmm_context(vmmcontext_t *context) { asm volatile ("mov %%rax, %%gs:16" : : "a"(context) : "memory"); } +static inline long current_cpu_id(void) { + long id; + asm volatile ("mov %%gs:24, %%rax" : "=a"(id) : : "memory"); + return id; +} + static inline void cpu_set(cpu_t *ptr) { ptr->self = ptr; wrmsr(MSR_GSBASE, (uint64_t)ptr); diff --git a/kernel-src/include/x86-64/arch/pci.h b/kernel-src/include/x86-64/arch/pci.h index 3603c9fd..0af39e7c 100644 --- a/kernel-src/include/x86-64/arch/pci.h +++ b/kernel-src/include/x86-64/arch/pci.h @@ -72,7 +72,7 @@ static void mcfg_write32(int bus, int device, int function, uint32_t offset, uin static uint64_t msiformatmessage(uint32_t *data, int vector, int edgetrigger, int deassert) { *data = (edgetrigger ? 0 : (1 << 15)) | (deassert ? 0 : (1 << 14)) | vector; - return 0xfee00000 | (_cpu()->id << 12); + return 0xfee00000 | (current_cpu_id() << 12); } // in PCIe, every function has 4096 bytes of config space for it. diff --git a/kernel-src/io/acpi/glue.c b/kernel-src/io/acpi/glue.c index 5ce17810..775ab73e 100644 --- a/kernel-src/io/acpi/glue.c +++ b/kernel-src/io/acpi/glue.c @@ -294,7 +294,7 @@ uacpi_status uacpi_kernel_install_interrupt_handler(uacpi_u32 irq, uacpi_interru actx->ctx = ctx; isr->priv = actx; - arch_ioapic_setirq(irq, isr->id & 0xff, _cpu()->id, false); + arch_ioapic_setirq(irq, isr->id & 0xff, current_cpu_id(), false); *outhandle = isr; return UACPI_STATUS_OK; diff --git a/kernel-src/lib/panic.c b/kernel-src/lib/panic.c index 9072df9e..4f70af50 100644 --- a/kernel-src/lib/panic.c +++ b/kernel-src/lib/panic.c @@ -4,7 +4,7 @@ #include __attribute__((noreturn)) void _panic(char *msg, context_t *ctx) { - printf("cpu%lu: Oops.\n", _cpu()->id); + printf("cpu%lu: Oops.\n", current_cpu_id()); if (msg) printf("%s\n", msg); diff --git a/kernel-src/sys/interrupt.c b/kernel-src/sys/interrupt.c index b26e7716..5fe74ef0 100644 --- a/kernel-src/sys/interrupt.c +++ b/kernel-src/sys/interrupt.c @@ -42,11 +42,9 @@ static void runisr(isr_t *isr, context_t *ctx) { } static void dopending(context_t *ctx, void *) { + arch_interrupt_disable(); bool entrystatus = _cpu()->intstatus; - if (entrystatus) { - arch_interrupt_disable(); - _cpu()->intstatus = false; - } + _cpu()->intstatus = false; isr_t *list = NULL; isr_t *iterator = _cpu()->isrqueue; @@ -135,15 +133,20 @@ void interrupt_raise(isr_t *isr) { } void interrupt_register(int vector, void (*func)(isr_t *self, context_t *ctx), void (*eoi)(isr_t *self), long priority) { + bool intstatus = interrupt_set(false); + isr_t *isr = &_cpu()->isr[vector]; isr->func = func; isr->eoi = eoi; - isr->id = (uint64_t)_cpu()->id << 32 | vector; + isr->id = (uint64_t)current_cpu_id() | vector; isr->priority = priority; isr->pending = false; + + interrupt_set(intstatus); } isr_t *interrupt_allocate(void (*func)(isr_t *self, context_t *ctx), void (*eoi)(isr_t *self), long priority) { + bool intstatus = interrupt_set(false); isr_t *isr = NULL; for (int i = 0; i < MAX_ISR_COUNT; ++i) { @@ -154,6 +157,7 @@ isr_t *interrupt_allocate(void (*func)(isr_t *self, context_t *ctx), void (*eoi) } } + interrupt_set(intstatus); return isr; } @@ -183,16 +187,14 @@ long interrupt_raiseipl(long ipl) { } bool interrupt_set(bool status) { + arch_interrupt_disable(); bool old = _cpu()->intstatus; _cpu()->intstatus = status; - if (status) + if (status) { arch_interrupt_enable(); - else - arch_interrupt_disable(); - - if (status) DOPENDING_SAVE(); + } return old; } diff --git a/kernel-src/sys/scheduler.c b/kernel-src/sys/scheduler.c index deae251a..b6475f87 100644 --- a/kernel-src/sys/scheduler.c +++ b/kernel-src/sys/scheduler.c @@ -574,10 +574,10 @@ static void yield(context_t *context, void *) { } int sched_yield() { - __assert(_cpu()->ipl == IPL_NORMAL); bool sleeping = current_thread()->flags & SCHED_THREAD_FLAGS_SLEEP; bool old = sleeping ? current_thread()->sleepintstatus : interrupt_set(false); arch_context_saveandcall(yield, _cpu()->schedulerstack, NULL); + __assert(_cpu()->ipl == IPL_NORMAL); interrupt_set(old); return sleeping ? current_thread()->wakeupreason : 0; }