diff --git a/base/usr/include/kernel/arch/x86_64/irq.h b/base/usr/include/kernel/arch/x86_64/irq.h index f2f4097..0db2d5b 100644 --- a/base/usr/include/kernel/arch/x86_64/irq.h +++ b/base/usr/include/kernel/arch/x86_64/irq.h @@ -50,7 +50,9 @@ extern struct regs * _irq12(struct regs*); extern struct regs * _irq13(struct regs*); extern struct regs * _irq14(struct regs*); extern struct regs * _irq15(struct regs*); -extern struct regs * _isr127(struct regs*); +extern struct regs * _isr125(struct regs*); /* Does not actually take regs */ +extern struct regs * _isr126(struct regs*); /* Does not actually take regs */ +extern struct regs * _isr127(struct regs*); /* Syscall entry point */ typedef struct regs * (*interrupt_handler_t)(struct regs *); diff --git a/base/usr/include/kernel/misc.h b/base/usr/include/kernel/misc.h index fb66210..260fedc 100644 --- a/base/usr/include/kernel/misc.h +++ b/base/usr/include/kernel/misc.h @@ -8,7 +8,6 @@ const char * arch_get_loader(void); void arch_pause(void); -__attribute__((noreturn)) void arch_fatal(void); void arch_set_tls_base(uintptr_t tlsbase); diff --git a/kernel/arch/x86_64/acpi.c b/kernel/arch/x86_64/acpi.c index 38e5bd8..223d795 100644 --- a/kernel/arch/x86_64/acpi.c +++ b/kernel/arch/x86_64/acpi.c @@ -95,6 +95,7 @@ static void short_delay(unsigned long amount) { } static volatile int _ap_current = 0; +uintptr_t lapic_final = 0; #define cpuid(in,a,b,c,d) do { asm volatile ("cpuid" : "=a"(a),"=b"(b),"=c"(c),"=d"(d) : "a"(in)); } while(0) @@ -113,6 +114,8 @@ void ap_main(void) { fpu_initialize(); pat_initialize(); + /* Enable our spurious vector register */ + *((volatile uint32_t*)(lapic_final + 0x0F0)) = 0x127; /* Set our pml pointers */ this_core->current_pml = &init_page_region[0]; @@ -160,13 +163,19 @@ void load_processor_info(void) { } } +void lapic_write(size_t addr, uint32_t value) { + *((volatile uint32_t*)(lapic_final + addr)) = value; + asm volatile ("":::"memory"); +} + +uint32_t lapic_read(size_t addr) { + return *((volatile uint32_t*)(lapic_final + addr)); +} -uintptr_t lapic_final = 0; void lapic_send_ipi(int i, uint32_t val) { - *((volatile uint32_t*)(lapic_final + 0x310)) = (i << 24); - asm volatile ("":::"memory"); - *((volatile uint32_t*)(lapic_final + 0x300)) = val; - do { asm volatile ("pause" : : : "memory"); } while (*((volatile uint32_t*)(lapic_final + 0x300)) & (1 << 12)); + lapic_write(0x310, i << 24); + lapic_write(0x300, val); + do { asm volatile ("pause" : : : "memory"); } while (lapic_read(0x300) & (1 << 12)); } void acpi_initialize(void) { @@ -238,15 +247,15 @@ void acpi_initialize(void) { } } - if (!lapic_base || cores <= 1) { - return; - } - processor_count = cores; + if (!lapic_base) return; + /* Allocate a virtual address with which we can poke the lapic */ lapic_final = (uintptr_t)mmu_map_mmio_region(lapic_base, 0x1000); + if (cores <= 1) return; + /* Map the bootstrap code */ memcpy(mmu_map_from_physical(0x1000), &_ap_bootstrap_start, (uintptr_t)&_ap_bootstrap_end - (uintptr_t)&_ap_bootstrap_start); diff --git a/kernel/arch/x86_64/idt.c b/kernel/arch/x86_64/idt.c index bdfa920..0784ceb 100644 --- a/kernel/arch/x86_64/idt.c +++ b/kernel/arch/x86_64/idt.c @@ -86,6 +86,8 @@ void idt_install(void) { idt_set_gate(46, _irq14, 0x08, 0x8E, 0); idt_set_gate(47, _irq15, 0x08, 0x8E, 0); + idt_set_gate(125, _isr125, 0x08, 0x8E, 0); /* Halts everyone. */ + idt_set_gate(126, _isr126, 0x08, 0x8E, 0); /* Intentionally does nothing. */ idt_set_gate(127, _isr127, 0x08, 0x8E, 1); asm volatile ( @@ -103,7 +105,6 @@ void idt_ap_install(void) { ); } -static spin_lock_t fault_lock = {0}; static spin_lock_t dump_lock = {0}; static void dump_regs(struct regs * r) { spin_lock(dump_lock); @@ -127,41 +128,6 @@ static void dump_regs(struct regs * r) { extern void syscall_handler(struct regs *); -static const char *exception_messages[32] = { - "Division by zero", - "Debug", - "Non-maskable interrupt", - "Breakpoint", - "Detected overflow", - "Out-of-bounds", - "Invalid opcode", - "No coprocessor", - "Double fault", - "Coprocessor segment overrun", - "Bad TSS", - "Segment not present", - "Stack fault", - "General protection fault", - "Page fault", - "Unknown interrupt", - "Coprocessor fault", - "Alignment check", - "Machine check", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved" -}; - #define IRQ_CHAIN_SIZE 16 #define IRQ_CHAIN_DEPTH 4 static irq_handler_chain_t irq_routines[IRQ_CHAIN_SIZE * IRQ_CHAIN_DEPTH] = { NULL }; @@ -189,15 +155,11 @@ void irq_uninstall_handler(size_t irq) { } struct regs * isr_handler(struct regs * r) { - this_core->current_process->interrupt_registers = r; - switch (r->int_no) { case 14: /* Page fault */ { uintptr_t faulting_address; asm volatile("mov %%cr2, %0" : "=r"(faulting_address)); if (!this_core->current_process || r->cs == 0x08) { - printf("Page fault in kernel (cpu=%d) at %#zx\n", this_core->cpu_id, faulting_address); - dump_regs(r); arch_fatal(); } if (faulting_address == 0xFFFFB00F) { @@ -210,10 +172,6 @@ struct regs * isr_handler(struct regs * r) { break; } #ifdef DEBUG_FAULTS - spin_lock(fault_lock); - printf("Page fault in pid=%d (%s; cpu=%d) at %#zx\n", (int)this_core->current_process->id, this_core->current_process->name, this_core->cpu_id, faulting_address); - dump_regs(r); - spin_unlock(fault_lock); arch_fatal(); #else # ifdef LOUD_SEGFAULTS @@ -225,18 +183,12 @@ struct regs * isr_handler(struct regs * r) { break; } case 13: /* GPF */ { - if (!this_core->current_process || r->cs == 0x08) { - printf("GPF in kernel (cpu=%d)\n", this_core->cpu_id); - dump_regs(r); - arch_fatal(); - } #ifdef DEBUG_FAULTS - spin_lock(fault_lock); - printf("GPF in userspace on CPU %d\n", this_core->cpu_id); - dump_regs(r); - spin_unlock(fault_lock); arch_fatal(); #else + if (!this_core->current_process || r->cs == 0x08) { + arch_fatal(); + } # ifdef LOUD_SEGFAULTS printf("GPF in userspace on CPU %d\n", this_core->cpu_id); dump_regs(r); @@ -246,11 +198,6 @@ struct regs * isr_handler(struct regs * r) { break; } case 8: /* Double fault */ { - printf("Double fault?\n"); - uintptr_t faulting_address; - asm volatile("mov %%cr2, %0" : "=r"(faulting_address)); - printf("cr2: 0x%016lx\n", faulting_address); - dump_regs(r); arch_fatal(); break; } @@ -265,18 +212,12 @@ struct regs * isr_handler(struct regs * r) { } default: { if (r->int_no < 32) { - if (!this_core->current_process || r->cs == 0x08) { - printf("Unhandled %s in kernel (cpu=%d)\n", exception_messages[r->int_no], this_core->cpu_id); - dump_regs(r); - arch_fatal(); - } #ifdef DEBUG_FAULTS - spin_lock(fault_lock); - printf("Unhandled %s in userspace (cpu=%d)\n", exception_messages[r->int_no], this_core->cpu_id); - dump_regs(r); - spin_unlock(fault_lock); arch_fatal(); #else + if (!this_core->current_process || r->cs == 0x08) { + arch_fatal(); + } send_signal(this_core->current_process->id, SIGILL, 1); #endif } else { @@ -295,7 +236,7 @@ struct regs * isr_handler(struct regs * r) { done: - if (this_core->current_process == this_core->kernel_idle_task && process_queue->head) { + if (this_core->current_process == this_core->kernel_idle_task && process_queue && process_queue->head) { /* If this is kidle and we got here, instead of finishing the interrupt * we can just switch task and there will probably be something else * to run that was awoken by the interrupt. */ diff --git a/kernel/arch/x86_64/irq.S b/kernel/arch/x86_64/irq.S index e84c2bb..69b01fb 100644 --- a/kernel/arch/x86_64/irq.S +++ b/kernel/arch/x86_64/irq.S @@ -30,7 +30,7 @@ /* Interrupt Requests */ ISR_NOERR 0 ISR_NOERR 1 -ISR_NOERR 2 +//ISR_NOERR 2 ISR_NOERR 3 ISR_NOERR 4 ISR_NOERR 5 @@ -76,8 +76,39 @@ IRQ 12, 44 IRQ 13, 45 IRQ 14, 46 IRQ 15, 47 + +/* syscall entry point */ ISR_NOERR 127 +/* No op, used to signal sleeping processor to wake and check the queue. */ +.extern lapic_final +.global _isr126 +.type _isr126, @function +_isr126: + pushq %r12 + mov (lapic_final), %r12 + movq $0, 0xb0(%r12) + popq %r12 + iretq + +/* Fatal signal, stop everything. */ +.global _isr125 +.type _isr125, @function +_isr125: + cli +1: + hlt + jmp 1b + +/* Fatal signal, stop everything. */ +.global _isr2 +.type _isr2, @function +_isr2: + cli +1: + hlt + jmp 1b + .macro _swapgs cmpq $8, 24(%rsp) je 1f diff --git a/kernel/arch/x86_64/user.c b/kernel/arch/x86_64/user.c index 03e107c..42ebf7f 100644 --- a/kernel/arch/x86_64/user.c +++ b/kernel/arch/x86_64/user.c @@ -87,10 +87,16 @@ void arch_pause(void) { asm volatile ( "sti\n" "hlt\n" + "cli\n" ); } +extern void lapic_send_ipi(int i, uint32_t val); void arch_fatal(void) { + for (int i = 0; i < processor_count; ++i) { + if (i == this_core->cpu_id) continue; + lapic_send_ipi(processor_local_data[i].lapic_id, 0x447D); + } while (1) { asm volatile ( "cli\n"