diff options
-rw-r--r-- | arch/x86/Makefile | 2 | ||||
-rw-r--r-- | arch/x86/machine/acpi.c | 1 | ||||
-rw-r--r-- | arch/x86/machine/cpu.c | 977 | ||||
-rw-r--r-- | arch/x86/machine/cpu.h | 373 | ||||
-rw-r--r-- | arch/x86/machine/cpu_asm.S | 728 | ||||
-rw-r--r-- | arch/x86/machine/cpu_i.h | 196 | ||||
-rw-r--r-- | arch/x86/machine/ioapic.c | 15 | ||||
-rw-r--r-- | arch/x86/machine/lapic.c | 111 | ||||
-rw-r--r-- | arch/x86/machine/lapic.h | 12 | ||||
-rw-r--r-- | arch/x86/machine/pic.c | 13 | ||||
-rw-r--r-- | arch/x86/machine/pmap.c | 2 | ||||
-rw-r--r-- | arch/x86/machine/trap.c | 354 | ||||
-rw-r--r-- | arch/x86/machine/trap.h | 186 | ||||
-rw-r--r-- | arch/x86/machine/trap_asm.S | 693 | ||||
-rw-r--r-- | arch/x86/machine/uart.c | 1 | ||||
-rw-r--r-- | kern/intr.c | 3 |
16 files changed, 1847 insertions, 1820 deletions
diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 226f4a90..daf862d8 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -58,8 +58,6 @@ x15_SOURCES-y += \ arch/x86/machine/string.c \ arch/x86/machine/tcb_asm.S \ arch/x86/machine/tcb.c \ - arch/x86/machine/trap_asm.S \ - arch/x86/machine/trap.c \ arch/x86/machine/uart.c x15_SOURCES-$(CONFIG_X86_PMU_AMD) += arch/x86/machine/pmu_amd.c diff --git a/arch/x86/machine/acpi.c b/arch/x86/machine/acpi.c index f088f2c8..3e6bbad8 100644 --- a/arch/x86/machine/acpi.c +++ b/arch/x86/machine/acpi.c @@ -708,5 +708,4 @@ INIT_OP_DEFINE(acpi_setup, INIT_OP_DEP(log_setup, true), INIT_OP_DEP(percpu_setup, true), INIT_OP_DEP(shutdown_bootstrap, true), - INIT_OP_DEP(trap_setup, true), INIT_OP_DEP(vm_kmem_setup, true)); diff --git a/arch/x86/machine/cpu.c b/arch/x86/machine/cpu.c index 6cbe168a..fc8fde3f 100644 --- a/arch/x86/machine/cpu.c +++ b/arch/x86/machine/cpu.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2017 Richard Braun. + * Copyright (c) 2010-2018 Richard Braun. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,15 +17,19 @@ #include <assert.h> #include <stdalign.h> +#include <stdbool.h> #include <stddef.h> #include <stdint.h> +#include <stdio.h> #include <string.h> #include <kern/init.h> +#include <kern/kmem.h> #include <kern/log.h> #include <kern/macros.h> #include <kern/panic.h> #include <kern/percpu.h> +#include <kern/spinlock.h> #include <kern/shutdown.h> #include <kern/thread.h> #include <kern/xcall.h> @@ -36,11 +40,10 @@ #include <machine/io.h> #include <machine/lapic.h> #include <machine/page.h> -#include <machine/pic.h> #include <machine/pit.h> #include <machine/pmap.h> #include <machine/ssp.h> -#include <machine/trap.h> +#include <machine/strace.h> #include <vm/vm_page.h> /* @@ -48,24 +51,24 @@ */ #define CPU_FREQ_CAL_DELAY 1000000 -#define CPU_TYPE_MASK 0x00003000 -#define CPU_TYPE_SHIFT 12 -#define CPU_FAMILY_MASK 0x00000f00 -#define CPU_FAMILY_SHIFT 8 -#define CPU_EXTFAMILY_MASK 0x0ff00000 -#define CPU_EXTFAMILY_SHIFT 20 -#define CPU_MODEL_MASK 0x000000f0 -#define CPU_MODEL_SHIFT 4 -#define CPU_EXTMODEL_MASK 0x000f0000 -#define CPU_EXTMODEL_SHIFT 16 -#define CPU_STEPPING_MASK 0x0000000f -#define CPU_STEPPING_SHIFT 0 -#define CPU_BRAND_MASK 0x000000ff -#define CPU_BRAND_SHIFT 0 -#define CPU_CLFLUSH_MASK 0x0000ff00 -#define CPU_CLFLUSH_SHIFT 8 -#define CPU_APIC_ID_MASK 0xff000000 -#define CPU_APIC_ID_SHIFT 24 +#define CPU_CPUID_TYPE_MASK 0x00003000 +#define CPU_CPUID_TYPE_SHIFT 12 +#define CPU_CPUID_FAMILY_MASK 0x00000f00 +#define CPU_CPUID_FAMILY_SHIFT 8 +#define CPU_CPUID_EXTFAMILY_MASK 0x0ff00000 +#define CPU_CPUID_EXTFAMILY_SHIFT 20 +#define CPU_CPUID_MODEL_MASK 0x000000f0 +#define CPU_CPUID_MODEL_SHIFT 4 +#define CPU_CPUID_EXTMODEL_MASK 0x000f0000 +#define CPU_CPUID_EXTMODEL_SHIFT 16 +#define CPU_CPUID_STEPPING_MASK 0x0000000f +#define CPU_CPUID_STEPPING_SHIFT 0 +#define CPU_CPUID_BRAND_MASK 0x000000ff +#define CPU_CPUID_BRAND_SHIFT 0 +#define CPU_CPUID_CLFLUSH_MASK 0x0000ff00 +#define CPU_CPUID_CLFLUSH_SHIFT 8 +#define CPU_CPUID_APIC_ID_MASK 0xff000000 +#define CPU_CPUID_APIC_ID_SHIFT 24 #define CPU_INVALID_APIC_ID ((unsigned int)-1) @@ -75,6 +78,11 @@ struct cpu_vendor { }; /* + * IST indexes (0 is reserved). + */ +#define CPU_TSS_IST_DF 1 + +/* * MP related CMOS ports, registers and values. */ #define CPU_MP_CMOS_PORT_REG 0x70 @@ -90,9 +98,6 @@ struct cpu_vendor { */ #define CPU_SHUTDOWN_PRIORITY 0 -/* - * Gate descriptor. - */ struct cpu_gate_desc { uint32_t word1; uint32_t word2; @@ -102,16 +107,8 @@ struct cpu_gate_desc { #endif /* __LP64__ */ }; -/* - * LDT or TSS system segment descriptor. - */ -struct cpu_sysseg_desc { - uint32_t word1; - uint32_t word2; -#ifdef __LP64__ - uint32_t word3; - uint32_t word4; -#endif /* __LP64__ */ +struct cpu_idt { + alignas(CPU_L1_SIZE) struct cpu_gate_desc descs[CPU_NR_EXC_VECTORS]; }; struct cpu_pseudo_desc { @@ -119,10 +116,106 @@ struct cpu_pseudo_desc { uintptr_t address; } __packed; +#ifdef __LP64__ + +struct cpu_exc_frame { + uint64_t rax; + uint64_t rbx; + uint64_t rcx; + uint64_t rdx; + uint64_t rbp; + uint64_t rsi; + uint64_t rdi; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t vector; + uint64_t error; + uint64_t rip; + uint64_t cs; + uint64_t rflags; + uint64_t rsp; + uint64_t ss; +} __packed; + +#else /* __LP64__ */ + +struct cpu_exc_frame { + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint16_t ds; + uint16_t es; + uint16_t fs; + uint16_t gs; + uint32_t vector; + uint32_t error; + uint32_t eip; + uint32_t cs; + uint32_t eflags; + uint32_t esp; /* esp and ss are undefined if trapped in kernel */ + uint32_t ss; +} __packed; + +#endif /* __LP64__ */ + +/* + * Type for low level exception handlers. + * + * Low level exception handlers are directly installed in the IDT and are + * first run by the processor when an exception occurs. They route execution + * through either the main exception or interrupt handler. + */ +typedef void (*cpu_ll_exc_fn_t)(void); + +typedef void (*cpu_exc_handler_fn_t)(const struct cpu_exc_frame *frame); + +struct cpu_exc_handler { + cpu_exc_handler_fn_t fn; +}; + +struct cpu_intr_handler { + cpu_intr_handler_fn_t fn; +}; + +/* + * Set the given GDT for the current processor. + * + * On i386, the ds, es and ss segment registers are reloaded. + * + * The fs and gs segment registers, which point to the percpu and the TLS + * areas respectively, must be set separately. + */ +void cpu_load_gdt(struct cpu_pseudo_desc *gdtr); + +/* + * Return a pointer to the processor-local interrupt stack. + * + * This function is called by the low level exception handling code. + * + * Return NULL if no stack switching is required. + */ +void * cpu_get_intr_stack(void); + +/* + * Common entry points for exceptions and interrupts. + */ +void cpu_exc_main(const struct cpu_exc_frame *frame); +void cpu_intr_main(const struct cpu_exc_frame *frame); + void *cpu_local_area __percpu; /* - * Processor descriptor, one per CPU. + * CPU descriptor, one per CPU. */ struct cpu cpu_desc __percpu; @@ -136,29 +229,162 @@ unsigned int cpu_nr_active __read_mostly = 1; */ static uint64_t cpu_freq __read_mostly; -/* - * TLS segment, as expected by the compiler. - * - * TLS isn't actually used inside the kernel. The current purpose of this - * segment is to implement stack protection. - */ static const struct cpu_tls_seg cpu_tls_seg = { .ssp_guard_word = SSP_GUARD_WORD, }; -/* - * Interrupt descriptor table. - */ -static alignas(8) struct cpu_gate_desc cpu_idt[CPU_IDT_SIZE] __read_mostly; +static struct cpu_idt cpu_idt; /* - * Double fault handler, and stack for the main processor. - * - * TODO Declare as init data, and replace the BSP stack with kernel virtual - * memory. + * This table only exists during initialization, and is a way to + * communicate the list of low level handlers from assembly to C. */ -static unsigned long cpu_double_fault_handler; -static alignas(CPU_DATA_ALIGN) char cpu_double_fault_stack[TRAP_STACK_SIZE]; +extern cpu_ll_exc_fn_t cpu_ll_exc_handler_addrs[CPU_NR_EXC_VECTORS]; + +static struct cpu_exc_handler cpu_exc_handlers[CPU_NR_EXC_VECTORS] + __read_mostly; + +static struct cpu_intr_handler cpu_intr_handlers[CPU_NR_EXC_VECTORS] + __read_mostly; + +static const struct cpu_vendor cpu_vendors[] = { + { CPU_VENDOR_INTEL, "GenuineIntel" }, + { CPU_VENDOR_AMD, "AuthenticAMD" }, +}; + +static void __init +cpu_exc_handler_init(struct cpu_exc_handler *handler, cpu_exc_handler_fn_t fn) +{ + handler->fn = fn; +} + +static void +cpu_exc_handler_run(const struct cpu_exc_handler *handler, + const struct cpu_exc_frame *frame) +{ + handler->fn(frame); +} + +static void __init +cpu_intr_handler_init(struct cpu_intr_handler *handler, + cpu_intr_handler_fn_t fn) +{ + handler->fn = fn; +} + +static void +cpu_intr_handler_run(const struct cpu_intr_handler *handler, + unsigned int vector) +{ + handler->fn(vector); +} + +static cpu_ll_exc_fn_t __init +cpu_get_ll_exc_handler(unsigned int vector) +{ + assert(vector < ARRAY_SIZE(cpu_ll_exc_handler_addrs)); + return cpu_ll_exc_handler_addrs[vector]; +} + +static struct cpu_exc_handler * +cpu_get_exc_handler(unsigned int vector) +{ + assert(vector < ARRAY_SIZE(cpu_exc_handlers)); + return &cpu_exc_handlers[vector]; +} + +static void __init +cpu_register_exc(unsigned int vector, cpu_exc_handler_fn_t fn) +{ + cpu_exc_handler_init(cpu_get_exc_handler(vector), fn); +} + +static struct cpu_intr_handler * +cpu_get_intr_handler(unsigned int vector) +{ + assert(vector < ARRAY_SIZE(cpu_intr_handlers)); + return &cpu_intr_handlers[vector]; +} + +void __init +cpu_register_intr(unsigned int vector, cpu_intr_handler_fn_t fn) +{ + cpu_intr_handler_init(cpu_get_intr_handler(vector), fn); +} + +static void __init +cpu_gate_desc_init_intr(struct cpu_gate_desc *desc, cpu_ll_exc_fn_t fn, + unsigned int ist_index) +{ + uintptr_t addr; + + addr = (uintptr_t)fn; + desc->word1 = (CPU_GDT_SEL_CODE << 16) + | (addr & CPU_DESC_GATE_OFFSET_LOW_MASK); + desc->word2 = (addr & CPU_DESC_GATE_OFFSET_HIGH_MASK) + | CPU_DESC_PRESENT | CPU_DESC_TYPE_GATE_INTR; + +#ifdef __LP64__ + desc->word2 |= ist_index & CPU_DESC_SEG_IST_MASK; + desc->word3 = addr >> 32; + desc->word4 = 0; +#else /* __LP64__ */ + assert(ist_index == 0); +#endif /* __LP64__ */ +} + +#ifndef __LP64__ +static void __init +cpu_gate_desc_init_task(struct cpu_gate_desc *desc, unsigned int tss_seg_sel) +{ + desc->word2 = CPU_DESC_PRESENT | CPU_DESC_TYPE_GATE_TASK; + desc->word1 = tss_seg_sel << 16; +} +#endif /* __LP64__ */ + +static struct cpu_gate_desc * __init +cpu_idt_get_desc(struct cpu_idt *idt, unsigned int vector) +{ + assert(vector < ARRAY_SIZE(idt->descs)); + return &idt->descs[vector]; +} + +static void __init +cpu_idt_set_intr_gate(struct cpu_idt *idt, unsigned int vector, + cpu_ll_exc_fn_t fn) +{ + struct cpu_gate_desc *desc; + + desc = cpu_idt_get_desc(idt, vector); + cpu_gate_desc_init_intr(desc, fn, 0); +} + +static void __init +cpu_idt_setup_double_fault(struct cpu_idt *idt) +{ + struct cpu_gate_desc *desc; + + desc = cpu_idt_get_desc(idt, CPU_EXC_DF); + +#ifdef __LP64__ + cpu_ll_exc_fn_t fn; + + fn = cpu_get_ll_exc_handler(CPU_EXC_DF); + cpu_gate_desc_init_intr(desc, fn, CPU_TSS_IST_DF); +#else /* __LP64__ */ + cpu_gate_desc_init_task(desc, CPU_GDT_SEL_DF_TSS); +#endif /* __LP64__ */ +} + +static void +cpu_idt_load(const struct cpu_idt *idt) +{ + struct cpu_pseudo_desc idtr; + + idtr.address = (uintptr_t)idt->descs; + idtr.limit = sizeof(idt->descs) - 1; + asm volatile("lidt %0" : : "m" (idtr)); +} uint64_t cpu_get_freq(void) @@ -166,6 +392,15 @@ cpu_get_freq(void) return cpu_freq; } +static uint64_t +cpu_get_tsc(void) +{ + uint32_t high, low; + + asm volatile("rdtsc" : "=a" (low), "=d" (high)); + return ((uint64_t)high << 32) | low; +} + void cpu_delay(unsigned long usecs) { @@ -184,42 +419,286 @@ cpu_delay(unsigned long usecs) } while (total > 0); } -static const struct cpu_vendor cpu_vendors[] = { - { CPU_VENDOR_INTEL, "GenuineIntel" }, - { CPU_VENDOR_AMD, "AuthenticAMD" }, -}; - void * __init cpu_get_boot_stack(void) { - return percpu_var(cpu_desc.boot_stack, boot_ap_id); + return percpu_var(cpu_desc.boot_stack, boot_ap_id); // TODO Pass as argument } -static void __init -cpu_preinit(struct cpu *cpu, unsigned int id, unsigned int apic_id) +void * +cpu_get_intr_stack(void) { - memset(cpu, 0, sizeof(*cpu)); - cpu->id = id; - cpu->apic_id = apic_id; + struct cpu *cpu; + + if (thread_interrupted()) { + return NULL; + } + + cpu = cpu_local_ptr(cpu_desc); + return cpu->intr_stack + sizeof(cpu->intr_stack); } static void -cpu_seg_set_null(char *table, unsigned int selector) +cpu_show_thread(void) { - struct cpu_seg_desc *desc; + struct thread *thread; - desc = (struct cpu_seg_desc *)(table + selector); - desc->high = 0; - desc->low = 0; + thread = thread_self(); + + /* TODO Thread name accessor */ + printf("cpu: interrupted thread: %p (%s)\n", thread, thread->name); } +#ifdef __LP64__ + static void -cpu_seg_set_code(char *table, unsigned int selector) +cpu_show_frame(const struct cpu_exc_frame *frame) { - struct cpu_seg_desc *desc; + printf("cpu: rax: %016lx rbx: %016lx rcx: %016lx\n" + "cpu: rdx: %016lx rbp: %016lx rsi: %016lx\n" + "cpu: rdi: %016lx r8: %016lx r9: %016lx\n" + "cpu: r10: %016lx r11: %016lx r12: %016lx\n" + "cpu: r13: %016lx r14: %016lx r15: %016lx\n" + "cpu: vector: %lu error: %08lx\n" + "cpu: rip: %016lx cs: %lu rflags: %016lx\n" + "cpu: rsp: %016lx ss: %lu\n", + (unsigned long)frame->rax, (unsigned long)frame->rbx, + (unsigned long)frame->rcx, (unsigned long)frame->rdx, + (unsigned long)frame->rbp, (unsigned long)frame->rsi, + (unsigned long)frame->rdi, (unsigned long)frame->r8, + (unsigned long)frame->r9, (unsigned long)frame->r10, + (unsigned long)frame->r11, (unsigned long)frame->r12, + (unsigned long)frame->r13, (unsigned long)frame->r14, + (unsigned long)frame->r15, (unsigned long)frame->vector, + (unsigned long)frame->error, (unsigned long)frame->rip, + (unsigned long)frame->cs, (unsigned long)frame->rflags, + (unsigned long)frame->rsp, (unsigned long)frame->ss); + + /* XXX Until the page fault handler is written */ + if (frame->vector == 14) { + printf("cpu: cr2: %016lx\n", (unsigned long)cpu_get_cr2()); + } +} + +#else /* __LP64__ */ - desc = (struct cpu_seg_desc *)(table + selector); +static void +cpu_show_frame(const struct cpu_exc_frame *frame) +{ + unsigned long esp, ss; + if ((frame->cs & CPU_PL_USER) || (frame->vector == CPU_EXC_DF)) { + esp = frame->esp; + ss = frame->ss; + } else { + esp = 0; + ss = 0; + } + + printf("cpu: eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n" + "cpu: ebp: %08lx esi: %08lx edi: %08lx\n" + "cpu: ds: %hu es: %hu fs: %hu gs: %hu\n" + "cpu: vector: %lu error: %08lx\n" + "cpu: eip: %08lx cs: %lu eflags: %08lx\n" + "cpu: esp: %08lx ss: %lu\n", + (unsigned long)frame->eax, (unsigned long)frame->ebx, + (unsigned long)frame->ecx, (unsigned long)frame->edx, + (unsigned long)frame->ebp, (unsigned long)frame->esi, + (unsigned long)frame->edi, (unsigned short)frame->ds, + (unsigned short)frame->es, (unsigned short)frame->fs, + (unsigned short)frame->gs, (unsigned long)frame->vector, + (unsigned long)frame->error, (unsigned long)frame->eip, + (unsigned long)frame->cs, (unsigned long)frame->eflags, + (unsigned long)esp, (unsigned long)ss); + + + /* XXX Until the page fault handler is written */ + if (frame->vector == 14) { + printf("cpu: cr2: %08lx\n", (unsigned long)cpu_get_cr2()); + } +} + +#endif /* __LP64__ */ + +static void +cpu_show_stack(const struct cpu_exc_frame *frame) +{ +#ifdef __LP64__ + strace_show(frame->rip, frame->rbp); +#else /* __LP64__ */ + strace_show(frame->eip, frame->ebp); +#endif /* __LP64__ */ +} + +static void +cpu_exc_double_fault(const struct cpu_exc_frame *frame) +{ + cpu_halt_broadcast(); + +#ifndef __LP64__ + struct cpu_exc_frame frame_store; + struct cpu *cpu; + + /* + * Double faults are catched through a task gate, which makes the given + * frame useless. The interrupted state is automatically saved in the + * main TSS by the processor. Build a proper exception frame from there. + */ + cpu = cpu_current(); + frame_store.eax = cpu->tss.eax; + frame_store.ebx = cpu->tss.ebx; + frame_store.ecx = cpu->tss.ecx; + frame_store.edx = cpu->tss.edx; + frame_store.ebp = cpu->tss.ebp; + frame_store.esi = cpu->tss.esi; + frame_store.edi = cpu->tss.edi; + frame_store.ds = cpu->tss.ds; + frame_store.es = cpu->tss.es; + frame_store.fs = cpu->tss.fs; + frame_store.gs = cpu->tss.gs; + frame_store.vector = CPU_EXC_DF; + frame_store.error = 0; + frame_store.eip = cpu->tss.eip; + frame_store.cs = cpu->tss.cs; + frame_store.eflags = cpu->tss.eflags; + frame_store.esp = cpu->tss.esp; + frame_store.ss = cpu->tss.ss; + frame = &frame_store; +#endif /* __LP64__ */ + + printf("cpu: double fault (cpu%u):\n", cpu_id()); + cpu_show_thread(); + cpu_show_frame(frame); + cpu_show_stack(frame); + cpu_halt(); +} + +void +cpu_exc_main(const struct cpu_exc_frame *frame) +{ + const struct cpu_exc_handler *handler; + + handler = cpu_get_exc_handler(frame->vector); + cpu_exc_handler_run(handler, frame); + assert(!cpu_intr_enabled()); +} + +void +cpu_intr_main(const struct cpu_exc_frame *frame) +{ + const struct cpu_intr_handler *handler; + + handler = cpu_get_intr_handler(frame->vector); + + thread_intr_enter(); + cpu_intr_handler_run(handler, frame->vector); + thread_intr_leave(); + + assert(!cpu_intr_enabled()); +} + +static void +cpu_exc_default(const struct cpu_exc_frame *frame) +{ + cpu_halt_broadcast(); + printf("cpu: unregistered exception (cpu%u):\n", cpu_id()); + cpu_show_thread(); + cpu_show_frame(frame); + cpu_show_stack(frame); + cpu_halt(); +} + +static void +cpu_intr_default(unsigned int vector) +{ + cpu_halt_broadcast(); + printf("cpu: unregistered interrupt %u (cpu%u):\n", vector, cpu_id()); + cpu_show_thread(); + cpu_halt(); +} + +static void +cpu_xcall_intr(unsigned int vector) +{ + (void)vector; + + lapic_eoi(); + xcall_intr(); +} + +static void +cpu_thread_schedule_intr(unsigned int vector) +{ + (void)vector; + + lapic_eoi(); + thread_schedule_intr(); +} + +static void +cpu_halt_intr(unsigned int vector) +{ + (void)vector; + + lapic_eoi(); + cpu_halt(); +} + +static void __init +cpu_setup_idt(void) +{ + for (size_t i = 0; i < ARRAY_SIZE(cpu_ll_exc_handler_addrs); i++) { + cpu_idt_set_intr_gate(&cpu_idt, i, cpu_get_ll_exc_handler(i)); + } + + cpu_idt_setup_double_fault(&cpu_idt); +} + +static void __init +cpu_setup_intr(void) +{ + cpu_setup_idt(); + + for (size_t i = 0; i < ARRAY_SIZE(cpu_exc_handlers); i++) { + cpu_register_exc(i, cpu_exc_default); + } + + /* Architecture defined exceptions */ + cpu_register_exc(CPU_EXC_DE, cpu_exc_default); + cpu_register_exc(CPU_EXC_DB, cpu_exc_default); + cpu_register_intr(CPU_EXC_NMI, cpu_intr_default); + cpu_register_exc(CPU_EXC_BP, cpu_exc_default); + cpu_register_exc(CPU_EXC_OF, cpu_exc_default); + cpu_register_exc(CPU_EXC_BR, cpu_exc_default); + cpu_register_exc(CPU_EXC_UD, cpu_exc_default); + cpu_register_exc(CPU_EXC_NM, cpu_exc_default); + cpu_register_exc(CPU_EXC_DF, cpu_exc_double_fault); + cpu_register_exc(CPU_EXC_TS, cpu_exc_default); + cpu_register_exc(CPU_EXC_NP, cpu_exc_default); + cpu_register_exc(CPU_EXC_SS, cpu_exc_default); + cpu_register_exc(CPU_EXC_GP, cpu_exc_default); + cpu_register_exc(CPU_EXC_PF, cpu_exc_default); + cpu_register_exc(CPU_EXC_MF, cpu_exc_default); + cpu_register_exc(CPU_EXC_AC, cpu_exc_default); + cpu_register_intr(CPU_EXC_MC, cpu_intr_default); + cpu_register_exc(CPU_EXC_XM, cpu_exc_default); + + /* System defined exceptions */ + cpu_register_intr(CPU_EXC_XCALL, cpu_xcall_intr); + cpu_register_intr(CPU_EXC_THREAD_SCHEDULE, cpu_thread_schedule_intr); + cpu_register_intr(CPU_EXC_HALT, cpu_halt_intr); +} + +static void __init +cpu_seg_desc_init_null(struct cpu_seg_desc *desc) +{ + desc->high = 0; + desc->low = 0; +} + +static void __init +cpu_seg_desc_init_code(struct cpu_seg_desc *desc) +{ #ifdef __LP64__ desc->high = CPU_DESC_LONG | CPU_DESC_PRESENT | CPU_DESC_S | CPU_DESC_TYPE_CODE; @@ -232,13 +711,9 @@ cpu_seg_set_code(char *table, unsigned int selector) #endif /* __LP64__ */ } -static void -cpu_seg_set_data(char *table, unsigned int selector, uint32_t base) +static void __init +cpu_seg_desc_init_data(struct cpu_seg_desc *desc, uintptr_t base) { - struct cpu_seg_desc *desc; - - desc = (struct cpu_seg_desc *)(table + selector); - #ifdef __LP64__ (void)base; @@ -256,21 +731,19 @@ cpu_seg_set_data(char *table, unsigned int selector, uint32_t base) #endif /* __LP64__ */ } -static void -cpu_seg_set_tss(char *table, unsigned int selector, struct cpu_tss *tss) +static void __init +cpu_sysseg_desc_init_tss(struct cpu_sysseg_desc *desc, + const struct cpu_tss *tss) { - struct cpu_sysseg_desc *desc; - unsigned long base, limit; + uintptr_t base, limit; - desc = (struct cpu_sysseg_desc *)(table + selector); - base = (unsigned long)tss; + base = (uintptr_t)tss; limit = base + sizeof(*tss) - 1; #ifdef __LP64__ desc->word4 = 0; desc->word3 = (base >> 32); #endif /* __LP64__ */ - desc->word2 = (base & CPU_DESC_SEG_BASE_HIGH_MASK) | (limit & CPU_DESC_SEG_LIMIT_HIGH_MASK) | CPU_DESC_PRESENT | CPU_DESC_TYPE_TSS @@ -279,114 +752,101 @@ cpu_seg_set_tss(char *table, unsigned int selector, struct cpu_tss *tss) | (limit & CPU_DESC_SEG_LIMIT_LOW_MASK); } -/* - * Set the given GDT for the current processor. - * - * On i386, the ds, es and ss segment registers are reloaded. - * - * The fs and gs segment registers, which point to the percpu and the TLS - * areas respectively, must be set separately. - */ -void cpu_load_gdt(struct cpu_pseudo_desc *gdtr); - -static inline void __init -cpu_set_percpu_area(const struct cpu *cpu, void *area) +static void * __init +cpu_gdt_get_desc(struct cpu_gdt *gdt, unsigned int selector) { -#ifdef __LP64__ - unsigned long va; + assert((selector % sizeof(struct cpu_seg_desc)) == 0); + assert(selector < sizeof(gdt->descs)); + return gdt->descs + selector; +} - va = (unsigned long)area; - cpu_set_msr(CPU_MSR_FSBASE, (uint32_t)(va >> 32), (uint32_t)va); -#else /* __LP64__ */ - asm volatile("mov %0, %%fs" : : "r" (CPU_GDT_SEL_PERCPU)); -#endif /* __LP64__ */ +static void __init +cpu_gdt_set_null(struct cpu_gdt *gdt, unsigned int selector) +{ + struct cpu_seg_desc *desc; - percpu_var(cpu_local_area, cpu->id) = area; + desc = cpu_gdt_get_desc(gdt, selector); + cpu_seg_desc_init_null(desc); } -static inline void __init -cpu_set_tls_area(void) +static void __init +cpu_gdt_set_code(struct cpu_gdt *gdt, unsigned int selector) { -#ifdef __LP64__ - unsigned long va; + struct cpu_seg_desc *desc; - va = (unsigned long)&cpu_tls_seg; - cpu_set_msr(CPU_MSR_GSBASE, (uint32_t)(va >> 32), (uint32_t)va); -#else /* __LP64__ */ - asm volatile("mov %0, %%gs" : : "r" (CPU_GDT_SEL_TLS)); -#endif /* __LP64__ */ + desc = cpu_gdt_get_desc(gdt, selector); + cpu_seg_desc_init_code(desc); } static void __init -cpu_init_gdtr(struct cpu_pseudo_desc *gdtr, const struct cpu *cpu) +cpu_gdt_set_data(struct cpu_gdt *gdt, unsigned int selector, const void *base) { - gdtr->address = (unsigned long)cpu->gdt; - gdtr->limit = sizeof(cpu->gdt) - 1; + struct cpu_seg_desc *desc; + + desc = cpu_gdt_get_desc(gdt, selector); + cpu_seg_desc_init_data(desc, (uintptr_t)base); } static void __init -cpu_init_gdt(struct cpu *cpu) +cpu_gdt_set_tss(struct cpu_gdt *gdt, unsigned int selector, + const struct cpu_tss *tss) { - struct cpu_pseudo_desc gdtr; - void *pcpu_area; + struct cpu_sysseg_desc *desc; - pcpu_area = percpu_area(cpu->id); + desc = cpu_gdt_get_desc(gdt, selector); + cpu_sysseg_desc_init_tss(desc, tss); +} - cpu_seg_set_null(cpu->gdt, CPU_GDT_SEL_NULL); - cpu_seg_set_code(cpu->gdt, CPU_GDT_SEL_CODE); - cpu_seg_set_data(cpu->gdt, CPU_GDT_SEL_DATA, 0); - cpu_seg_set_tss(cpu->gdt, CPU_GDT_SEL_TSS, &cpu->tss); +static void __init +cpu_gdt_init(struct cpu_gdt *gdt, const struct cpu_tss *tss, + const struct cpu_tss *df_tss, void *pcpu_area) +{ + cpu_gdt_set_null(gdt, CPU_GDT_SEL_NULL); + cpu_gdt_set_code(gdt, CPU_GDT_SEL_CODE); + cpu_gdt_set_data(gdt, CPU_GDT_SEL_DATA, 0); + cpu_gdt_set_tss(gdt, CPU_GDT_SEL_TSS, tss); -#ifndef __LP64__ - cpu_seg_set_tss(cpu->gdt, CPU_GDT_SEL_DF_TSS, &cpu->double_fault_tss); - cpu_seg_set_data(cpu->gdt, CPU_GDT_SEL_PERCPU, (unsigned long)pcpu_area); - cpu_seg_set_data(cpu->gdt, CPU_GDT_SEL_TLS, (unsigned long)&cpu_tls_seg); +#ifdef __LP64__ + (void)df_tss; + (void)pcpu_area; +#else /* __LP64__ */ + cpu_gdt_set_tss(gdt, CPU_GDT_SEL_DF_TSS, df_tss); + cpu_gdt_set_data(gdt, CPU_GDT_SEL_PERCPU, pcpu_area); + cpu_gdt_set_data(gdt, CPU_GDT_SEL_TLS, &cpu_tls_seg); #endif /* __LP64__ */ - - cpu_init_gdtr(&gdtr, cpu); - cpu_load_gdt(&gdtr); - cpu_set_percpu_area(cpu, pcpu_area); - cpu_set_tls_area(); } static void __init -cpu_init_ldt(void) +cpu_gdt_load(const struct cpu_gdt *gdt) { - asm volatile("lldt %w0" : : "q" (CPU_GDT_SEL_NULL)); + struct cpu_pseudo_desc gdtr; + + gdtr.address = (uintptr_t)gdt->descs; + gdtr.limit = sizeof(gdt->descs) - 1; + cpu_load_gdt(&gdtr); } static void __init -cpu_init_tss(struct cpu *cpu) +cpu_tss_init(struct cpu_tss *tss, const void *df_stack_top) { - struct cpu_tss *tss; - - tss = &cpu->tss; memset(tss, 0, sizeof(*tss)); #ifdef __LP64__ - assert(cpu->double_fault_stack != NULL); - tss->ist[CPU_TSS_IST_DF] = (unsigned long)cpu->double_fault_stack - + TRAP_STACK_SIZE; + tss->ist[CPU_TSS_IST_DF] = (uintptr_t)df_stack_top; +#else /* __LP64__ */ + (void)df_stack_top; #endif /* __LP64__ */ - - asm volatile("ltr %w0" : : "q" (CPU_GDT_SEL_TSS)); } #ifndef __LP64__ static void __init -cpu_init_double_fault_tss(struct cpu *cpu) +cpu_tss_init_i386_double_fault(struct cpu_tss *tss, const void *df_stack_top) { - struct cpu_tss *tss; - - assert(cpu_double_fault_handler != 0); - assert(cpu->double_fault_stack != NULL); - - tss = &cpu->double_fault_tss; memset(tss, 0, sizeof(*tss)); tss->cr3 = cpu_get_cr3(); - tss->eip = cpu_double_fault_handler; + tss->eip = (uintptr_t)cpu_get_ll_exc_handler(CPU_EXC_DF); tss->eflags = CPU_EFL_ONE; - tss->ebp = (unsigned long)cpu->double_fault_stack + TRAP_STACK_SIZE; + tss->ebp = (uintptr_t)df_stack_top; tss->esp = tss->ebp; tss->es = CPU_GDT_SEL_DATA; tss->cs = CPU_GDT_SEL_CODE; @@ -396,56 +856,78 @@ cpu_init_double_fault_tss(struct cpu *cpu) } #endif /* __LP64__ */ -void -cpu_idt_set_gate(unsigned int vector, void (*isr)(void)) +static struct cpu_tss * __init +cpu_get_tss(struct cpu *cpu) { - struct cpu_gate_desc *desc; - - assert(vector < ARRAY_SIZE(cpu_idt)); - - desc = &cpu_idt[vector]; + return &cpu->tss; +} +static struct cpu_tss * __init +cpu_get_df_tss(struct cpu *cpu) +{ #ifdef __LP64__ - desc->word4 = 0; - desc->word3 = (unsigned long)isr >> 32; + (void)cpu; + return NULL; +#else /* __LP64__ */ + return &cpu->df_tss; #endif /* __LP64__ */ +} - /* Use interrupt gates only to simplify trap handling */ - desc->word2 = ((unsigned long)isr & CPU_DESC_GATE_OFFSET_HIGH_MASK) - | CPU_DESC_PRESENT | CPU_DESC_TYPE_GATE_INTR; - desc->word1 = (CPU_GDT_SEL_CODE << 16) - | ((unsigned long)isr & CPU_DESC_GATE_OFFSET_LOW_MASK); +static void * __init +cpu_get_df_stack_top(struct cpu *cpu) +{ + return &cpu->df_stack[sizeof(cpu->df_stack)]; } -void -cpu_idt_set_double_fault(void (*isr)(void)) +static void __init +cpu_init(struct cpu *cpu, unsigned int id, unsigned int apic_id) { - struct cpu_gate_desc *desc; + memset(cpu, 0, sizeof(*cpu)); + cpu->id = id; + cpu->apic_id = apic_id; +} + +static void __init +cpu_load_ldt(void) +{ + asm volatile("lldt %w0" : : "q" (CPU_GDT_SEL_NULL)); +} - cpu_double_fault_handler = (unsigned long)isr; +static void __init +cpu_load_tss(void) +{ + asm volatile("ltr %w0" : : "q" (CPU_GDT_SEL_TSS)); +} +static void __init +cpu_set_percpu_area(const struct cpu *cpu, void *area) +{ #ifdef __LP64__ - cpu_idt_set_gate(TRAP_DF, isr); - desc = &cpu_idt[TRAP_DF]; - desc->word2 |= CPU_TSS_IST_DF & CPU_DESC_SEG_IST_MASK; + unsigned long va; + + va = (unsigned long)area; + cpu_set_msr(CPU_MSR_FSBASE, (uint32_t)(va >> 32), (uint32_t)va); #else /* __LP64__ */ - desc = &cpu_idt[TRAP_DF]; - desc->word2 = CPU_DESC_PRESENT | CPU_DESC_TYPE_GATE_TASK; - desc->word1 = CPU_GDT_SEL_DF_TSS << 16; + asm volatile("mov %0, %%fs" : : "r" (CPU_GDT_SEL_PERCPU)); #endif /* __LP64__ */ + + percpu_var(cpu_local_area, cpu->id) = area; } -static void -cpu_load_idt(const void *idt, size_t size) +static void __init +cpu_set_tls_area(void) { - struct cpu_pseudo_desc idtr; +#ifdef __LP64__ + uintptr_t va; - idtr.address = (uintptr_t)idt; - idtr.limit = size - 1; - asm volatile("lidt %0" : : "m" (idtr)); + va = (uintptr_t)&cpu_tls_seg; + cpu_set_msr(CPU_MSR_GSBASE, (uint32_t)(va >> 32), (uint32_t)va); +#else /* __LP64__ */ + asm volatile("mov %0, %%gs" : : "r" (CPU_GDT_SEL_TLS)); +#endif /* __LP64__ */ } -static const struct cpu_vendor * +static const struct cpu_vendor * __init cpu_vendor_lookup(const char *str) { for (size_t i = 0; i < ARRAY_SIZE(cpu_vendors); i++) { @@ -471,13 +953,13 @@ cpu_init_vendor_id(struct cpu *cpu) cpu->vendor_id = vendor->id; } -/* - * Initialize the given cpu structure for the current processor. - */ static void __init -cpu_init(struct cpu *cpu) +cpu_build(struct cpu *cpu) { unsigned int eax, ebx, ecx, edx, max_basic, max_extended; + void *pcpu_area; + + pcpu_area = percpu_area(cpu->id); /* * Assume at least an i586 processor. @@ -486,13 +968,23 @@ cpu_init(struct cpu *cpu) cpu_intr_restore(CPU_EFL_ONE); cpu_set_cr0(CPU_CR0_PG | CPU_CR0_AM | CPU_CR0_WP | CPU_CR0_NE | CPU_CR0_ET | CPU_CR0_TS | CPU_CR0_MP | CPU_CR0_PE); - cpu_init_gdt(cpu); - cpu_init_ldt(); - cpu_init_tss(cpu); + cpu_gdt_init(&cpu->gdt, cpu_get_tss(cpu), cpu_get_df_tss(cpu), pcpu_area); + cpu_gdt_load(&cpu->gdt); + cpu_load_ldt(); + cpu_tss_init(&cpu->tss, cpu_get_df_stack_top(cpu)); #ifndef __LP64__ - cpu_init_double_fault_tss(cpu); + cpu_tss_init_i386_double_fault(&cpu->df_tss, cpu_get_df_stack_top(cpu)); #endif /* __LP64__ */ - cpu_load_idt(cpu_idt, sizeof(cpu_idt)); + cpu_load_tss(); + cpu_idt_load(&cpu_idt); + cpu_set_percpu_area(cpu, pcpu_area); + cpu_set_tls_area(); + + /* + * Perform the check after initializing the GDT and the per-CPU area + * since cpu_id() relies on them to correctly work. + */ + assert(cpu->id == cpu_id()); eax = 0; cpu_cpuid(&eax, &ebx, &ecx, &edx); @@ -513,22 +1005,27 @@ cpu_init(struct cpu *cpu) eax = 1; cpu_cpuid(&eax, &ebx, &ecx, &edx); - cpu->type = (eax & CPU_TYPE_MASK) >> CPU_TYPE_SHIFT; - cpu->family = (eax & CPU_FAMILY_MASK) >> CPU_FAMILY_SHIFT; + cpu->type = (eax & CPU_CPUID_TYPE_MASK) >> CPU_CPUID_TYPE_SHIFT; + cpu->family = (eax & CPU_CPUID_FAMILY_MASK) >> CPU_CPUID_FAMILY_SHIFT; if (cpu->family == 0xf) { - cpu->family += (eax & CPU_EXTFAMILY_MASK) >> CPU_EXTFAMILY_SHIFT; + cpu->family += (eax & CPU_CPUID_EXTFAMILY_MASK) + >> CPU_CPUID_EXTFAMILY_SHIFT; } - cpu->model = (eax & CPU_MODEL_MASK) >> CPU_MODEL_SHIFT; + cpu->model = (eax & CPU_CPUID_MODEL_MASK) >> CPU_CPUID_MODEL_SHIFT; if ((cpu->model == 6) || (cpu->model == 0xf)) { - cpu->model += (eax & CPU_EXTMODEL_MASK) >> CPU_EXTMODEL_SHIFT; + cpu->model += (eax & CPU_CPUID_EXTMODEL_MASK) + >> CPU_CPUID_EXTMODEL_SHIFT; } - cpu->stepping = (eax & CPU_STEPPING_MASK) >> CPU_STEPPING_SHIFT; - cpu->clflush_size = ((ebx & CPU_CLFLUSH_MASK) >> CPU_CLFLUSH_SHIFT) * 8; - cpu->initial_apic_id = (ebx & CPU_APIC_ID_MASK) >> CPU_APIC_ID_SHIFT; + cpu->stepping = (eax & CPU_CPUID_STEPPING_MASK) + >> CPU_CPUID_STEPPING_SHIFT; + cpu->clflush_size = ((ebx & CPU_CPUID_CLFLUSH_MASK) + >> CPU_CPUID_CLFLUSH_SHIFT) * 8; + cpu->initial_apic_id = (ebx & CPU_CPUID_APIC_ID_MASK) + >> CPU_CPUID_APIC_ID_SHIFT; cpu->features1 = ecx; cpu->features2 = edx; @@ -607,10 +1104,11 @@ cpu_setup(void) { struct cpu *cpu; + cpu_setup_intr(); + cpu = percpu_ptr(cpu_desc, 0); - cpu_preinit(cpu, 0, CPU_INVALID_APIC_ID); - cpu->double_fault_stack = cpu_double_fault_stack; /* XXX */ - cpu_init(cpu); + cpu_init(cpu, 0, CPU_INVALID_APIC_ID); + cpu_build(cpu); cpu_measure_freq(); @@ -618,8 +1116,7 @@ cpu_setup(void) } INIT_OP_DEFINE(cpu_setup, - INIT_OP_DEP(percpu_bootstrap, true), - INIT_OP_DEP(trap_setup, true)); + INIT_OP_DEP(percpu_bootstrap, true)); static void __init cpu_panic_on_missing_feature(const char *feature) @@ -654,11 +1151,12 @@ cpu_check_bsp(void) return 0; } +// TODO Remove panic_setup INIT_OP_DEFINE(cpu_check_bsp, INIT_OP_DEP(cpu_setup, true), INIT_OP_DEP(panic_setup, true)); -void +void __init cpu_log_info(const struct cpu *cpu) { log_info("cpu%u: %s, type %u, family %u, model %u, stepping %u", @@ -680,7 +1178,7 @@ cpu_log_info(const struct cpu *cpu) } void __init -cpu_mp_register_lapic(unsigned int apic_id, int is_bsp) +cpu_mp_register_lapic(unsigned int apic_id, bool is_bsp) { struct cpu *cpu; int error; @@ -703,15 +1201,22 @@ cpu_mp_register_lapic(unsigned int apic_id, int is_bsp) } cpu = percpu_ptr(cpu_desc, cpu_nr_active); - cpu_preinit(cpu, cpu_nr_active, apic_id); + cpu_init(cpu, cpu_nr_active, apic_id); cpu_nr_active++; } static void +cpu_trigger_double_fault(void) +{ + asm volatile("movl $0xdead, %esp; push $0"); +} + +static void cpu_shutdown_reset(void) { - cpu_load_idt(NULL, 1); - trap_trigger_double_fault(); + /* Generate a triple fault */ + cpu_idt_load(NULL); + cpu_trigger_double_fault(); } static struct shutdown_ops cpu_shutdown_ops = { @@ -747,7 +1252,6 @@ INIT_OP_DEFINE(cpu_setup_shutdown, void __init cpu_mp_setup(void) { - struct vm_page *page; uint16_t reset_vector[2]; struct cpu *cpu; unsigned int i; @@ -775,26 +1279,13 @@ cpu_mp_setup(void) io_write_byte(CPU_MP_CMOS_PORT_REG, CPU_MP_CMOS_REG_RESET); io_write_byte(CPU_MP_CMOS_PORT_DATA, CPU_MP_CMOS_DATA_RESET_WARM); - /* TODO Allocate stacks out of the slab allocator for sub-page sizes */ - for (i = 1; i < cpu_count(); i++) { cpu = percpu_ptr(cpu_desc, i); - page = vm_page_alloc(vm_page_order(BOOT_STACK_SIZE), - VM_PAGE_SEL_DIRECTMAP, VM_PAGE_KERNEL); + cpu->boot_stack = kmem_alloc(BOOT_STACK_SIZE); - if (page == NULL) { + if (!cpu->boot_stack) { panic("cpu: unable to allocate boot stack for cpu%u", i); } - - cpu->boot_stack = vm_page_direct_ptr(page); - page = vm_page_alloc(vm_page_order(TRAP_STACK_SIZE), - VM_PAGE_SEL_DIRECTMAP, VM_PAGE_KERNEL); - - if (page == NULL) { - panic("cpu: unable to allocate double fault stack for cpu%u", i); - } - - cpu->double_fault_stack = vm_page_direct_ptr(page); } /* @@ -829,7 +1320,7 @@ cpu_ap_setup(void) struct cpu *cpu; cpu = percpu_ptr(cpu_desc, boot_ap_id); - cpu_init(cpu); + cpu_build(cpu); cpu_check(cpu_current()); lapic_ap_setup(); } @@ -847,35 +1338,5 @@ cpu_halt_broadcast(void) return; } - lapic_ipi_broadcast(TRAP_CPU_HALT); -} - -void -cpu_halt_intr(struct trap_frame *frame) -{ - (void)frame; - - lapic_eoi(); - - cpu_halt(); -} - -void -cpu_xcall_intr(struct trap_frame *frame) -{ - (void)frame; - - lapic_eoi(); - - xcall_intr(); -} - -void -cpu_thread_schedule_intr(struct trap_frame *frame) -{ - (void)frame; - - lapic_eoi(); - - thread_schedule_intr(); + lapic_ipi_broadcast(CPU_EXC_HALT); } diff --git a/arch/x86/machine/cpu.h b/arch/x86/machine/cpu.h index 0c4e6e1d..78857cdc 100644 --- a/arch/x86/machine/cpu.h +++ b/arch/x86/machine/cpu.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2017 Richard Braun. + * Copyright (c) 2010-2018 Richard Braun. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +20,60 @@ #include <limits.h> +#include <machine/page.h> + +/* + * Architecture defined exception vectors. + */ +#define CPU_EXC_DE 0 /* Divide Error */ +#define CPU_EXC_DB 1 /* Debug */ +#define CPU_EXC_NMI 2 /* NMI Interrupt */ +#define CPU_EXC_BP 3 /* Breakpoint */ +#define CPU_EXC_OF 4 /* Overflow */ +#define CPU_EXC_BR 5 /* BOUND Range Exceeded */ +#define CPU_EXC_UD 6 /* Undefined Opcode */ +#define CPU_EXC_NM 7 /* No Math Coprocessor */ +#define CPU_EXC_DF 8 /* Double Fault */ +#define CPU_EXC_TS 10 /* Invalid TSS */ +#define CPU_EXC_NP 11 /* Segment Not Present */ +#define CPU_EXC_SS 12 /* Stack-Segment Fault */ +#define CPU_EXC_GP 13 /* General Protection */ +#define CPU_EXC_PF 14 /* Page Fault */ +#define CPU_EXC_MF 16 /* Math Fault */ +#define CPU_EXC_AC 17 /* Alignment Check */ +#define CPU_EXC_MC 18 /* Machine Check */ +#define CPU_EXC_XM 19 /* SIMD Floating-Point Exception */ + +/* + * Exception vectors used for external interrupts. + */ +#define CPU_EXC_INTR_FIRST 32 +#define CPU_EXC_INTR_LAST 223 + +/* + * System defined exception vectors. + * + * The local APIC assigns one priority every 16 vectors. + */ +#define CPU_EXC_XCALL 238 +#define CPU_EXC_THREAD_SCHEDULE 239 +#define CPU_EXC_HALT 240 +#define CPU_EXC_LAPIC_PMC_OF 252 +#define CPU_EXC_LAPIC_TIMER 253 +#define CPU_EXC_LAPIC_ERROR 254 +#define CPU_EXC_LAPIC_SPURIOUS 255 + +#define CPU_NR_EXC_VECTORS 256 + +#define CPU_INTR_STACK_SIZE PAGE_SIZE + +#define CPU_VENDOR_STR_SIZE 13 +#define CPU_MODEL_NAME_SIZE 49 + +#define CPU_VENDOR_UNKNOWN 0 +#define CPU_VENDOR_INTEL 1 +#define CPU_VENDOR_AMD 2 + /* * L1 cache line size. * @@ -49,80 +103,57 @@ /* * Processor privilege levels. */ -#define CPU_PL_KERNEL 0 -#define CPU_PL_USER 3 +#define CPU_PL_KERNEL 0 +#define CPU_PL_USER 3 /* * Control register 0 flags. */ -#define CPU_CR0_PE 0x00000001 -#define CPU_CR0_MP 0x00000002 -#define CPU_CR0_TS 0x00000008 -#define CPU_CR0_ET 0x00000010 -#define CPU_CR0_NE 0x00000020 -#define CPU_CR0_WP 0x00010000 -#define CPU_CR0_AM 0x00040000 -#define CPU_CR0_PG 0x80000000 +#define CPU_CR0_PE 0x00000001 +#define CPU_CR0_MP 0x00000002 +#define CPU_CR0_TS 0x00000008 +#define CPU_CR0_ET 0x00000010 +#define CPU_CR0_NE 0x00000020 +#define CPU_CR0_WP 0x00010000 +#define CPU_CR0_AM 0x00040000 +#define CPU_CR0_PG 0x80000000 /* * Control register 4 flags. */ -#define CPU_CR4_PSE 0x00000010 -#define CPU_CR4_PAE 0x00000020 -#define CPU_CR4_PGE 0x00000080 - -/* - * EFLAGS register flags. - */ -#define CPU_EFL_ONE 0x00000002 /* Reserved, must be one */ -#define CPU_EFL_IF 0x00000200 +#define CPU_CR4_PSE 0x00000010 +#define CPU_CR4_PAE 0x00000020 +#define CPU_CR4_PGE 0x00000080 /* * Model specific registers. */ -#define CPU_MSR_EFER 0xc0000080 -#define CPU_MSR_FSBASE 0xc0000100 -#define CPU_MSR_GSBASE 0xc0000101 +#define CPU_MSR_EFER 0xc0000080 +#define CPU_MSR_FSBASE 0xc0000100 +#define CPU_MSR_GSBASE 0xc0000101 /* * EFER MSR flags. */ -#define CPU_EFER_LME 0x00000100 +#define CPU_EFER_LME 0x00000100 /* * Feature2 flags. * * TODO Better names. */ -#define CPU_FEATURE2_FPU 0x00000001 -#define CPU_FEATURE2_PSE 0x00000008 -#define CPU_FEATURE2_PAE 0x00000040 -#define CPU_FEATURE2_MSR 0x00000020 -#define CPU_FEATURE2_CX8 0x00000100 -#define CPU_FEATURE2_APIC 0x00000200 -#define CPU_FEATURE2_PGE 0x00002000 - -#define CPU_FEATURE4_1GP 0x04000000 -#define CPU_FEATURE4_LM 0x20000000 - -/* - * GDT segment selectors. - */ -#define CPU_GDT_SEL_NULL 0 -#define CPU_GDT_SEL_CODE 8 -#define CPU_GDT_SEL_DATA 16 -#define CPU_GDT_SEL_TSS 24 +#define CPU_FEATURE2_FPU 0x00000001 +#define CPU_FEATURE2_PSE 0x00000008 +#define CPU_FEATURE2_PAE 0x00000040 +#define CPU_FEATURE2_MSR 0x00000020 +#define CPU_FEATURE2_CX8 0x00000100 +#define CPU_FEATURE2_APIC 0x00000200 +#define CPU_FEATURE2_PGE 0x00002000 -#ifdef __LP64__ -#define CPU_GDT_SIZE 40 -#else /* __LP64__ */ -#define CPU_GDT_SEL_DF_TSS 32 -#define CPU_GDT_SEL_PERCPU 40 -#define CPU_GDT_SEL_TLS 48 -#define CPU_GDT_SIZE 56 -#endif /* __LP64__ */ +#define CPU_FEATURE4_1GP 0x04000000 +#define CPU_FEATURE4_LM 0x20000000 -#define CPU_IDT_SIZE 256 +#include <machine/cpu_i.h> #ifndef __ASSEMBLER__ @@ -137,137 +168,65 @@ #include <machine/pit.h> #include <machine/ssp.h> +#define CPU_INTR_TABLE_SIZE (CPU_EXC_INTR_LAST - CPU_EXC_INTR_FIRST) + /* * Gate/segment descriptor bits and masks. */ -#define CPU_DESC_TYPE_DATA 0x00000200 -#define CPU_DESC_TYPE_CODE 0x00000a00 -#define CPU_DESC_TYPE_TSS 0x00000900 -#define CPU_DESC_TYPE_GATE_INTR 0x00000e00 -#define CPU_DESC_TYPE_GATE_TASK 0x00000500 -#define CPU_DESC_S 0x00001000 -#define CPU_DESC_PRESENT 0x00008000 -#define CPU_DESC_LONG 0x00200000 -#define CPU_DESC_DB 0x00400000 -#define CPU_DESC_GRAN_4KB 0x00800000 - -#define CPU_DESC_GATE_OFFSET_LOW_MASK 0x0000ffff -#define CPU_DESC_GATE_OFFSET_HIGH_MASK 0xffff0000 -#define CPU_DESC_SEG_IST_MASK 0x00000007 -#define CPU_DESC_SEG_BASE_LOW_MASK 0x0000ffff -#define CPU_DESC_SEG_BASE_MID_MASK 0x00ff0000 -#define CPU_DESC_SEG_BASE_HIGH_MASK 0xff000000 -#define CPU_DESC_SEG_LIMIT_LOW_MASK 0x0000ffff -#define CPU_DESC_SEG_LIMIT_HIGH_MASK 0x000f0000 +#define CPU_DESC_TYPE_DATA 0x00000200 +#define CPU_DESC_TYPE_CODE 0x00000a00 +#define CPU_DESC_TYPE_TSS 0x00000900 +#define CPU_DESC_TYPE_GATE_INTR 0x00000e00 +#define CPU_DESC_TYPE_GATE_TASK 0x00000500 +#define CPU_DESC_S 0x00001000 +#define CPU_DESC_PRESENT 0x00008000 +#define CPU_DESC_LONG 0x00200000 +#define CPU_DESC_DB 0x00400000 +#define CPU_DESC_GRAN_4KB 0x00800000 -/* - * Code or data segment descriptor. - */ -struct cpu_seg_desc { - uint32_t low; - uint32_t high; -}; +#define CPU_DESC_GATE_OFFSET_LOW_MASK 0x0000ffff +#define CPU_DESC_GATE_OFFSET_HIGH_MASK 0xffff0000 +#define CPU_DESC_SEG_IST_MASK 0x00000007 +#define CPU_DESC_SEG_BASE_LOW_MASK 0x0000ffff +#define CPU_DESC_SEG_BASE_MID_MASK 0x00ff0000 +#define CPU_DESC_SEG_BASE_HIGH_MASK 0xff000000 +#define CPU_DESC_SEG_LIMIT_LOW_MASK 0x0000ffff +#define CPU_DESC_SEG_LIMIT_HIGH_MASK 0x000f0000 /* - * Forward declaration. - */ -struct trap_frame; - -/* - * IST indexes (0 is reserved). - */ -#define CPU_TSS_IST_DF 1 - -struct cpu_tss { -#ifdef __LP64__ - uint32_t reserved0; - uint64_t rsp0; - uint64_t rsp1; - uint64_t rsp2; - uint64_t ist[8]; - uint64_t reserved1; - uint16_t reserved2; -#else /* __LP64__ */ - uint32_t link; - uint32_t esp0; - uint32_t ss0; - uint32_t esp1; - uint32_t ss1; - uint32_t esp2; - uint32_t ss2; - uint32_t cr3; - uint32_t eip; - uint32_t eflags; - uint32_t eax; - uint32_t ecx; - uint32_t edx; - uint32_t ebx; - uint32_t esp; - uint32_t ebp; - uint32_t esi; - uint32_t edi; - uint32_t es; - uint32_t cs; - uint32_t ss; - uint32_t ds; - uint32_t fs; - uint32_t gs; - uint32_t ldt; - uint16_t trap_bit; -#endif /* __LP64__ */ - uint16_t iobp_base; -} __packed; - -#define CPU_VENDOR_STR_SIZE 13 -#define CPU_MODEL_NAME_SIZE 49 - -#define CPU_VENDOR_UNKNOWN 0 -#define CPU_VENDOR_INTEL 1 -#define CPU_VENDOR_AMD 2 + * Type for interrupt handler functions. + */ +typedef void (*cpu_intr_handler_fn_t)(unsigned int vector); /* - * CPU states. - */ -#define CPU_STATE_OFF 0 -#define CPU_STATE_ON 1 - -struct cpu { - unsigned int id; - unsigned int apic_id; - char vendor_str[CPU_VENDOR_STR_SIZE]; - char model_name[CPU_MODEL_NAME_SIZE]; - unsigned int cpuid_max_basic; - unsigned int cpuid_max_extended; - unsigned int vendor_id; - unsigned int type; - unsigned int family; - unsigned int model; - unsigned int stepping; - unsigned int clflush_size; - unsigned int initial_apic_id; - unsigned int features1; - unsigned int features2; - unsigned int features3; - unsigned int features4; - unsigned short phys_addr_width; - unsigned short virt_addr_width; - alignas(8) char gdt[CPU_GDT_SIZE]; - struct cpu_tss tss; -#ifndef __LP64__ - struct cpu_tss double_fault_tss; -#endif /* __LP64__ */ - volatile int state; - void *boot_stack; - void *double_fault_stack; -}; - + * TLS segment, as expected by the compiler. + * + * TLS isn't actually used inside the kernel. The current purpose of this + * segment is to implement stack protection. + * + * This is a public structure, made available to the boot module so that + * C code that runs early correctly works when built with stack protection. + */ struct cpu_tls_seg { uintptr_t unused[SSP_WORD_TLS_OFFSET]; uintptr_t ssp_guard_word; }; /* + * Code or data segment descriptor. + * + * See Intel 64 and IA-32 Architecture Software Developer's Manual, + * Volume 3 System Programming Guide, 3.4.5 Segment Descriptors. + */ +struct cpu_seg_desc { + uint32_t low; + uint32_t high; +}; + +/* * Macro to create functions that read/write control registers. + * + * TODO Break down. */ #define CPU_DECL_GETSET_CR(name) \ static __always_inline unsigned long \ @@ -300,24 +259,6 @@ CPU_DECL_GETSET_CR(cr3) CPU_DECL_GETSET_CR(cr4) /* - * Return the content of the EFLAGS register. - * - * Implies a compiler barrier. - */ -static __always_inline unsigned long -cpu_get_eflags(void) -{ - unsigned long eflags; - - asm volatile("pushf\n" - "pop %0\n" - : "=r" (eflags) - : : "memory"); - - return eflags; -} - -/* * Enable local interrupts. * * Implies a compiler barrier. @@ -428,17 +369,7 @@ cpu_halt(void) */ void cpu_halt_broadcast(void); -/* - * Interrupt handler for inter-processor halt requests. - */ -void cpu_halt_intr(struct trap_frame *frame); - -/* - * This percpu variable contains the address of the percpu area for the local - * processor. This is normally the same value stored in the percpu module, but - * it can be directly accessed through a segment register. - */ -extern void *cpu_local_area; +/* Generic percpu accessors */ #define cpu_local_ptr(var) \ MACRO_BEGIN \ @@ -453,7 +384,7 @@ MACRO_END #define cpu_local_var(var) (*cpu_local_ptr(var)) -/* Interrupt-safe percpu accessors for basic types */ +/* Generic interrupt-safe percpu accessors */ #define cpu_local_assign(var, val) \ asm("mov %0, %%fs:%1" \ @@ -523,6 +454,7 @@ cpu_has_global_pages(void) * pages were previously disabled. * * Implies a full memory barrier. + * TODO Update barrier description. */ static __always_inline void cpu_enable_global_pages(void) @@ -533,8 +465,7 @@ cpu_enable_global_pages(void) /* * CPUID instruction wrapper. * - * The CPUID instruction is a serializing instruction, implying a full - * memory barrier. + * The CPUID instruction is a serializing instruction. */ static __always_inline void cpu_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx, @@ -581,19 +512,11 @@ cpu_set_msr64(uint32_t msr, uint64_t value) cpu_set_msr(msr, high, low); } -static __always_inline uint64_t -cpu_get_tsc(void) -{ - uint32_t high, low; - - asm volatile("rdtsc" : "=a" (low), "=d" (high)); - return ((uint64_t)high << 32) | low; -} - /* * Flush non-global TLB entries. * * Implies a full memory barrier. + * TODO Update barrier description. */ static __always_inline void cpu_tlb_flush(void) @@ -605,6 +528,7 @@ cpu_tlb_flush(void) * Flush all TLB entries, including global ones. * * Implies a full memory barrier. + * TODO Update barrier description. */ static __always_inline void cpu_tlb_flush_all(void) @@ -631,6 +555,7 @@ cpu_tlb_flush_all(void) * Flush a single page table entry in the TLB. * * Implies a full memory barrier. + * TODO Update barrier description. */ static __always_inline void cpu_tlb_flush_va(unsigned long va) @@ -678,22 +603,14 @@ void cpu_delay(unsigned long usecs); void * cpu_get_boot_stack(void); /* - * Install an interrupt handler in the IDT. - * - * These functions may be called before the cpu module is initialized. - */ -void cpu_idt_set_gate(unsigned int vector, void (*isr)(void)); -void cpu_idt_set_double_fault(void (*isr)(void)); - -/* * Log processor information. */ void cpu_log_info(const struct cpu *cpu); /* - * Register the presence of a local APIC. + * Register a local APIC. */ -void cpu_mp_register_lapic(unsigned int apic_id, int is_bsp); +void cpu_mp_register_lapic(unsigned int apic_id, bool is_bsp); /* * Start application processors. @@ -724,27 +641,29 @@ cpu_apic_id(unsigned int cpu) static inline void cpu_send_xcall(unsigned int cpu) { - lapic_ipi_send(cpu_apic_id(cpu), TRAP_XCALL); + lapic_ipi_send(cpu_apic_id(cpu), CPU_EXC_XCALL); } /* - * Interrupt handler for cross-calls. - */ -void cpu_xcall_intr(struct trap_frame *frame); - -/* * Send a scheduling interrupt to a remote processor. */ static inline void cpu_send_thread_schedule(unsigned int cpu) { - lapic_ipi_send(cpu_apic_id(cpu), TRAP_THREAD_SCHEDULE); + lapic_ipi_send(cpu_apic_id(cpu), CPU_EXC_THREAD_SCHEDULE); } /* - * Interrupt handler for scheduling requests. + * Register an interrupt handler. + * + * This function is only available during system initialization, before the + * scheduler is started. It is meant for architectural interrupts, including + * interrupt controllers, and not directly for drivers, which should use + * the machine-independent intr module instead. + * + * Registration is system-wide. */ -void cpu_thread_schedule_intr(struct trap_frame *frame); +void cpu_register_intr(unsigned int vector, cpu_intr_handler_fn_t fn); /* * This init operation provides : diff --git a/arch/x86/machine/cpu_asm.S b/arch/x86/machine/cpu_asm.S index 9d479913..96511b14 100644 --- a/arch/x86/machine/cpu_asm.S +++ b/arch/x86/machine/cpu_asm.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014 Richard Braun. + * Copyright (c) 2011-2018 Richard Braun. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,31 +19,723 @@ #include <machine/asm.h> #include <machine/cpu.h> -.section INIT_SECTION +.text + +#ifdef __LP64__ + +.macro cpu_ll_exc_store_registers + pushq %r15 + pushq %r14 + pushq %r13 + pushq %r12 + pushq %r11 + pushq %r10 + pushq %r9 + pushq %r8 + pushq %rdi + pushq %rsi + pushq %rbp + pushq %rdx + pushq %rcx + pushq %rbx + pushq %rax +.endm + +.macro cpu_ll_exc_load_registers + popq %rax + popq %rbx + popq %rcx + popq %rdx + popq %rbp + popq %rsi + popq %rdi + popq %r8 + popq %r9 + popq %r10 + popq %r11 + popq %r12 + popq %r13 + popq %r14 + popq %r15 + addq $16, %rsp /* skip vector and error */ +.endm + +.macro cpu_ll_exc_enter vector + pushq $\vector + cpu_ll_exc_store_registers + xorq %rbp, %rbp /* block stack tracing */ + movq %rsp, %rbx /* save frame */ +.endm + +.macro cpu_ll_exc_leave + movq %rbx, %rsp /* restore stack */ + call thread_schedule /* schedule threads */ + cpu_ll_exc_load_registers + iretq +.endm + +.macro cpu_ll_exc_handle vector + cpu_ll_exc_enter \vector + movq %rbx, %rdi + call cpu_exc_main + cpu_ll_exc_leave +.endm + +.macro cpu_ll_intr_handle vector + cpu_ll_exc_enter \vector + movq %rbx, %rdi + call cpu_get_intr_stack + testq %rax, %rax /* switch stack ? */ + jz 1f + movq %rax, %rsp /* switch to interrupt stack */ +1: + movq %rbx, %rdi + call cpu_intr_main + cpu_ll_exc_leave +.endm + +#else /* __LP64__ */ + +.macro cpu_ll_exc_store_registers + pushw %gs + pushw %fs + pushw %es + pushw %ds + pushl %edi + pushl %esi + pushl %ebp + pushl %edx + pushl %ecx + pushl %ebx + pushl %eax +.endm + +/* XXX Don't load segment registers for now */ +.macro cpu_ll_exc_load_registers + popl %eax + popl %ebx + popl %ecx + popl %edx + popl %ebp + popl %esi + popl %edi + addl $16, %esp /* skip segment registers, vector and error */ +.endm + +.macro cpu_ll_exc_enter vector + pushl $\vector + cpu_ll_exc_store_registers + xorl %ebp, %ebp /* block stack tracing */ + movl %esp, %ebx /* save frame */ +.endm + +.macro cpu_ll_exc_leave + movl %ebx, %esp /* restore stack */ + call thread_schedule /* schedule threads */ + cpu_ll_exc_load_registers + iretl +.endm + +.macro cpu_ll_exc_handle vector + cpu_ll_exc_enter \vector + pushl %ebx + call cpu_exc_main + cpu_ll_exc_leave +.endm + +.macro cpu_ll_intr_handle vector + cpu_ll_exc_enter \vector + pushl %ebx + call cpu_get_intr_stack + addl $4, %esp /* fix up stack pointer */ + testl %eax, %eax /* switch stack ? */ + jz 1f + movl %eax, %esp /* switch to interrupt stack */ +1: + pushl %ebx + call cpu_intr_main + cpu_ll_exc_leave +.endm + +#endif /* __LP64__ */ + +#define CPU_LL_EXC_HANDLER(vector, name) \ +ASM_ENTRY(name) \ + push $0; \ + cpu_ll_exc_handle vector; \ +ASM_END(name) + +#define CPU_LL_EXC_HANDLER_WITH_ERROR(vector, name) \ +ASM_ENTRY(name) \ + cpu_ll_exc_handle vector; \ +ASM_END(name) + +#define CPU_LL_INTR_HANDLER(vector, name) \ +ASM_ENTRY(name) \ + push $0; \ + cpu_ll_intr_handle vector; \ +ASM_END(name) + +/* + * Low level handlers for architectural exceptions. + */ +CPU_LL_EXC_HANDLER(CPU_EXC_DE, cpu_ll_exc_divide_error) +CPU_LL_EXC_HANDLER(CPU_EXC_DB, cpu_ll_exc_debug) +CPU_LL_INTR_HANDLER(CPU_EXC_NMI, cpu_ll_exc_nmi) +CPU_LL_EXC_HANDLER(CPU_EXC_BP, cpu_ll_exc_breakpoint) +CPU_LL_EXC_HANDLER(CPU_EXC_OF, cpu_ll_exc_overflow) +CPU_LL_EXC_HANDLER(CPU_EXC_BR, cpu_ll_exc_bound_range) +CPU_LL_EXC_HANDLER(CPU_EXC_UD, cpu_ll_exc_undefined_opcode) +CPU_LL_EXC_HANDLER(CPU_EXC_NM, cpu_ll_exc_no_math_coprocessor) +CPU_LL_EXC_HANDLER_WITH_ERROR(CPU_EXC_DF, cpu_ll_exc_double_fault) +CPU_LL_EXC_HANDLER_WITH_ERROR(CPU_EXC_TS, cpu_ll_exc_invalid_tss) +CPU_LL_EXC_HANDLER_WITH_ERROR(CPU_EXC_NP, cpu_ll_exc_segment_not_present) +CPU_LL_EXC_HANDLER_WITH_ERROR(CPU_EXC_SS, cpu_ll_exc_stack_segment_fault) +CPU_LL_EXC_HANDLER_WITH_ERROR(CPU_EXC_GP, cpu_ll_exc_general_protection) +CPU_LL_EXC_HANDLER_WITH_ERROR(CPU_EXC_PF, cpu_ll_exc_page_fault) +CPU_LL_EXC_HANDLER(CPU_EXC_MF, cpu_ll_exc_math_fault) +CPU_LL_EXC_HANDLER_WITH_ERROR(CPU_EXC_AC, cpu_ll_exc_alignment_check) +CPU_LL_INTR_HANDLER(CPU_EXC_MC, cpu_ll_exc_machine_check) +CPU_LL_EXC_HANDLER(CPU_EXC_XM, cpu_ll_exc_simd_fp_exception) + +/* + * Low level handlers for reserved exceptions. + * + * These exceptions should normally never occur, but have handlers ready just + * in case. + */ +CPU_LL_EXC_HANDLER(9, cpu_ll_exc_9) +CPU_LL_EXC_HANDLER(15, cpu_ll_exc_15) +CPU_LL_EXC_HANDLER(20, cpu_ll_exc_20) +CPU_LL_EXC_HANDLER(21, cpu_ll_exc_21) +CPU_LL_EXC_HANDLER(22, cpu_ll_exc_22) +CPU_LL_EXC_HANDLER(23, cpu_ll_exc_23) +CPU_LL_EXC_HANDLER(24, cpu_ll_exc_24) +CPU_LL_EXC_HANDLER(25, cpu_ll_exc_25) +CPU_LL_EXC_HANDLER(26, cpu_ll_exc_26) +CPU_LL_EXC_HANDLER(27, cpu_ll_exc_27) +CPU_LL_EXC_HANDLER(28, cpu_ll_exc_28) +CPU_LL_EXC_HANDLER(29, cpu_ll_exc_29) +CPU_LL_EXC_HANDLER(30, cpu_ll_exc_30) +CPU_LL_EXC_HANDLER(31, cpu_ll_exc_31) + +/* Generic low level interrupt handlers */ +CPU_LL_INTR_HANDLER(32, cpu_ll_exc_32) +CPU_LL_INTR_HANDLER(33, cpu_ll_exc_33) +CPU_LL_INTR_HANDLER(34, cpu_ll_exc_34) +CPU_LL_INTR_HANDLER(35, cpu_ll_exc_35) +CPU_LL_INTR_HANDLER(36, cpu_ll_exc_36) +CPU_LL_INTR_HANDLER(37, cpu_ll_exc_37) +CPU_LL_INTR_HANDLER(38, cpu_ll_exc_38) +CPU_LL_INTR_HANDLER(39, cpu_ll_exc_39) +CPU_LL_INTR_HANDLER(40, cpu_ll_exc_40) +CPU_LL_INTR_HANDLER(41, cpu_ll_exc_41) +CPU_LL_INTR_HANDLER(42, cpu_ll_exc_42) +CPU_LL_INTR_HANDLER(43, cpu_ll_exc_43) +CPU_LL_INTR_HANDLER(44, cpu_ll_exc_44) +CPU_LL_INTR_HANDLER(45, cpu_ll_exc_45) +CPU_LL_INTR_HANDLER(46, cpu_ll_exc_46) +CPU_LL_INTR_HANDLER(47, cpu_ll_exc_47) +CPU_LL_INTR_HANDLER(48, cpu_ll_exc_48) +CPU_LL_INTR_HANDLER(49, cpu_ll_exc_49) +CPU_LL_INTR_HANDLER(50, cpu_ll_exc_50) +CPU_LL_INTR_HANDLER(51, cpu_ll_exc_51) +CPU_LL_INTR_HANDLER(52, cpu_ll_exc_52) +CPU_LL_INTR_HANDLER(53, cpu_ll_exc_53) +CPU_LL_INTR_HANDLER(54, cpu_ll_exc_54) +CPU_LL_INTR_HANDLER(55, cpu_ll_exc_55) +CPU_LL_INTR_HANDLER(56, cpu_ll_exc_56) +CPU_LL_INTR_HANDLER(57, cpu_ll_exc_57) +CPU_LL_INTR_HANDLER(58, cpu_ll_exc_58) +CPU_LL_INTR_HANDLER(59, cpu_ll_exc_59) +CPU_LL_INTR_HANDLER(60, cpu_ll_exc_60) +CPU_LL_INTR_HANDLER(61, cpu_ll_exc_61) +CPU_LL_INTR_HANDLER(62, cpu_ll_exc_62) +CPU_LL_INTR_HANDLER(63, cpu_ll_exc_63) +CPU_LL_INTR_HANDLER(64, cpu_ll_exc_64) +CPU_LL_INTR_HANDLER(65, cpu_ll_exc_65) +CPU_LL_INTR_HANDLER(66, cpu_ll_exc_66) +CPU_LL_INTR_HANDLER(67, cpu_ll_exc_67) +CPU_LL_INTR_HANDLER(68, cpu_ll_exc_68) +CPU_LL_INTR_HANDLER(69, cpu_ll_exc_69) +CPU_LL_INTR_HANDLER(70, cpu_ll_exc_70) +CPU_LL_INTR_HANDLER(71, cpu_ll_exc_71) +CPU_LL_INTR_HANDLER(72, cpu_ll_exc_72) +CPU_LL_INTR_HANDLER(73, cpu_ll_exc_73) +CPU_LL_INTR_HANDLER(74, cpu_ll_exc_74) +CPU_LL_INTR_HANDLER(75, cpu_ll_exc_75) +CPU_LL_INTR_HANDLER(76, cpu_ll_exc_76) +CPU_LL_INTR_HANDLER(77, cpu_ll_exc_77) +CPU_LL_INTR_HANDLER(78, cpu_ll_exc_78) +CPU_LL_INTR_HANDLER(79, cpu_ll_exc_79) +CPU_LL_INTR_HANDLER(80, cpu_ll_exc_80) +CPU_LL_INTR_HANDLER(81, cpu_ll_exc_81) +CPU_LL_INTR_HANDLER(82, cpu_ll_exc_82) +CPU_LL_INTR_HANDLER(83, cpu_ll_exc_83) +CPU_LL_INTR_HANDLER(84, cpu_ll_exc_84) +CPU_LL_INTR_HANDLER(85, cpu_ll_exc_85) +CPU_LL_INTR_HANDLER(86, cpu_ll_exc_86) +CPU_LL_INTR_HANDLER(87, cpu_ll_exc_87) +CPU_LL_INTR_HANDLER(88, cpu_ll_exc_88) +CPU_LL_INTR_HANDLER(89, cpu_ll_exc_89) +CPU_LL_INTR_HANDLER(90, cpu_ll_exc_90) +CPU_LL_INTR_HANDLER(91, cpu_ll_exc_91) +CPU_LL_INTR_HANDLER(92, cpu_ll_exc_92) +CPU_LL_INTR_HANDLER(93, cpu_ll_exc_93) +CPU_LL_INTR_HANDLER(94, cpu_ll_exc_94) +CPU_LL_INTR_HANDLER(95, cpu_ll_exc_95) +CPU_LL_INTR_HANDLER(96, cpu_ll_exc_96) +CPU_LL_INTR_HANDLER(97, cpu_ll_exc_97) +CPU_LL_INTR_HANDLER(98, cpu_ll_exc_98) +CPU_LL_INTR_HANDLER(99, cpu_ll_exc_99) +CPU_LL_INTR_HANDLER(100, cpu_ll_exc_100) +CPU_LL_INTR_HANDLER(101, cpu_ll_exc_101) +CPU_LL_INTR_HANDLER(102, cpu_ll_exc_102) +CPU_LL_INTR_HANDLER(103, cpu_ll_exc_103) +CPU_LL_INTR_HANDLER(104, cpu_ll_exc_104) +CPU_LL_INTR_HANDLER(105, cpu_ll_exc_105) +CPU_LL_INTR_HANDLER(106, cpu_ll_exc_106) +CPU_LL_INTR_HANDLER(107, cpu_ll_exc_107) +CPU_LL_INTR_HANDLER(108, cpu_ll_exc_108) +CPU_LL_INTR_HANDLER(109, cpu_ll_exc_109) +CPU_LL_INTR_HANDLER(110, cpu_ll_exc_110) +CPU_LL_INTR_HANDLER(111, cpu_ll_exc_111) +CPU_LL_INTR_HANDLER(112, cpu_ll_exc_112) +CPU_LL_INTR_HANDLER(113, cpu_ll_exc_113) +CPU_LL_INTR_HANDLER(114, cpu_ll_exc_114) +CPU_LL_INTR_HANDLER(115, cpu_ll_exc_115) +CPU_LL_INTR_HANDLER(116, cpu_ll_exc_116) +CPU_LL_INTR_HANDLER(117, cpu_ll_exc_117) +CPU_LL_INTR_HANDLER(118, cpu_ll_exc_118) +CPU_LL_INTR_HANDLER(119, cpu_ll_exc_119) +CPU_LL_INTR_HANDLER(120, cpu_ll_exc_120) +CPU_LL_INTR_HANDLER(121, cpu_ll_exc_121) +CPU_LL_INTR_HANDLER(122, cpu_ll_exc_122) +CPU_LL_INTR_HANDLER(123, cpu_ll_exc_123) +CPU_LL_INTR_HANDLER(124, cpu_ll_exc_124) +CPU_LL_INTR_HANDLER(125, cpu_ll_exc_125) +CPU_LL_INTR_HANDLER(126, cpu_ll_exc_126) +CPU_LL_INTR_HANDLER(127, cpu_ll_exc_127) +CPU_LL_INTR_HANDLER(128, cpu_ll_exc_128) +CPU_LL_INTR_HANDLER(129, cpu_ll_exc_129) +CPU_LL_INTR_HANDLER(130, cpu_ll_exc_130) +CPU_LL_INTR_HANDLER(131, cpu_ll_exc_131) +CPU_LL_INTR_HANDLER(132, cpu_ll_exc_132) +CPU_LL_INTR_HANDLER(133, cpu_ll_exc_133) +CPU_LL_INTR_HANDLER(134, cpu_ll_exc_134) +CPU_LL_INTR_HANDLER(135, cpu_ll_exc_135) +CPU_LL_INTR_HANDLER(136, cpu_ll_exc_136) +CPU_LL_INTR_HANDLER(137, cpu_ll_exc_137) +CPU_LL_INTR_HANDLER(138, cpu_ll_exc_138) +CPU_LL_INTR_HANDLER(139, cpu_ll_exc_139) +CPU_LL_INTR_HANDLER(140, cpu_ll_exc_140) +CPU_LL_INTR_HANDLER(141, cpu_ll_exc_141) +CPU_LL_INTR_HANDLER(142, cpu_ll_exc_142) +CPU_LL_INTR_HANDLER(143, cpu_ll_exc_143) +CPU_LL_INTR_HANDLER(144, cpu_ll_exc_144) +CPU_LL_INTR_HANDLER(145, cpu_ll_exc_145) +CPU_LL_INTR_HANDLER(146, cpu_ll_exc_146) +CPU_LL_INTR_HANDLER(147, cpu_ll_exc_147) +CPU_LL_INTR_HANDLER(148, cpu_ll_exc_148) +CPU_LL_INTR_HANDLER(149, cpu_ll_exc_149) +CPU_LL_INTR_HANDLER(150, cpu_ll_exc_150) +CPU_LL_INTR_HANDLER(151, cpu_ll_exc_151) +CPU_LL_INTR_HANDLER(152, cpu_ll_exc_152) +CPU_LL_INTR_HANDLER(153, cpu_ll_exc_153) +CPU_LL_INTR_HANDLER(154, cpu_ll_exc_154) +CPU_LL_INTR_HANDLER(155, cpu_ll_exc_155) +CPU_LL_INTR_HANDLER(156, cpu_ll_exc_156) +CPU_LL_INTR_HANDLER(157, cpu_ll_exc_157) +CPU_LL_INTR_HANDLER(158, cpu_ll_exc_158) +CPU_LL_INTR_HANDLER(159, cpu_ll_exc_159) +CPU_LL_INTR_HANDLER(160, cpu_ll_exc_160) +CPU_LL_INTR_HANDLER(161, cpu_ll_exc_161) +CPU_LL_INTR_HANDLER(162, cpu_ll_exc_162) +CPU_LL_INTR_HANDLER(163, cpu_ll_exc_163) +CPU_LL_INTR_HANDLER(164, cpu_ll_exc_164) +CPU_LL_INTR_HANDLER(165, cpu_ll_exc_165) +CPU_LL_INTR_HANDLER(166, cpu_ll_exc_166) +CPU_LL_INTR_HANDLER(167, cpu_ll_exc_167) +CPU_LL_INTR_HANDLER(168, cpu_ll_exc_168) +CPU_LL_INTR_HANDLER(169, cpu_ll_exc_169) +CPU_LL_INTR_HANDLER(170, cpu_ll_exc_170) +CPU_LL_INTR_HANDLER(171, cpu_ll_exc_171) +CPU_LL_INTR_HANDLER(172, cpu_ll_exc_172) +CPU_LL_INTR_HANDLER(173, cpu_ll_exc_173) +CPU_LL_INTR_HANDLER(174, cpu_ll_exc_174) +CPU_LL_INTR_HANDLER(175, cpu_ll_exc_175) +CPU_LL_INTR_HANDLER(176, cpu_ll_exc_176) +CPU_LL_INTR_HANDLER(177, cpu_ll_exc_177) +CPU_LL_INTR_HANDLER(178, cpu_ll_exc_178) +CPU_LL_INTR_HANDLER(179, cpu_ll_exc_179) +CPU_LL_INTR_HANDLER(180, cpu_ll_exc_180) +CPU_LL_INTR_HANDLER(181, cpu_ll_exc_181) +CPU_LL_INTR_HANDLER(182, cpu_ll_exc_182) +CPU_LL_INTR_HANDLER(183, cpu_ll_exc_183) +CPU_LL_INTR_HANDLER(184, cpu_ll_exc_184) +CPU_LL_INTR_HANDLER(185, cpu_ll_exc_185) +CPU_LL_INTR_HANDLER(186, cpu_ll_exc_186) +CPU_LL_INTR_HANDLER(187, cpu_ll_exc_187) +CPU_LL_INTR_HANDLER(188, cpu_ll_exc_188) +CPU_LL_INTR_HANDLER(189, cpu_ll_exc_189) +CPU_LL_INTR_HANDLER(190, cpu_ll_exc_190) +CPU_LL_INTR_HANDLER(191, cpu_ll_exc_191) +CPU_LL_INTR_HANDLER(192, cpu_ll_exc_192) +CPU_LL_INTR_HANDLER(193, cpu_ll_exc_193) +CPU_LL_INTR_HANDLER(194, cpu_ll_exc_194) +CPU_LL_INTR_HANDLER(195, cpu_ll_exc_195) +CPU_LL_INTR_HANDLER(196, cpu_ll_exc_196) +CPU_LL_INTR_HANDLER(197, cpu_ll_exc_197) +CPU_LL_INTR_HANDLER(198, cpu_ll_exc_198) +CPU_LL_INTR_HANDLER(199, cpu_ll_exc_199) +CPU_LL_INTR_HANDLER(200, cpu_ll_exc_200) +CPU_LL_INTR_HANDLER(201, cpu_ll_exc_201) +CPU_LL_INTR_HANDLER(202, cpu_ll_exc_202) +CPU_LL_INTR_HANDLER(203, cpu_ll_exc_203) +CPU_LL_INTR_HANDLER(204, cpu_ll_exc_204) +CPU_LL_INTR_HANDLER(205, cpu_ll_exc_205) +CPU_LL_INTR_HANDLER(206, cpu_ll_exc_206) +CPU_LL_INTR_HANDLER(207, cpu_ll_exc_207) +CPU_LL_INTR_HANDLER(208, cpu_ll_exc_208) +CPU_LL_INTR_HANDLER(209, cpu_ll_exc_209) +CPU_LL_INTR_HANDLER(210, cpu_ll_exc_210) +CPU_LL_INTR_HANDLER(211, cpu_ll_exc_211) +CPU_LL_INTR_HANDLER(212, cpu_ll_exc_212) +CPU_LL_INTR_HANDLER(213, cpu_ll_exc_213) +CPU_LL_INTR_HANDLER(214, cpu_ll_exc_214) +CPU_LL_INTR_HANDLER(215, cpu_ll_exc_215) +CPU_LL_INTR_HANDLER(216, cpu_ll_exc_216) +CPU_LL_INTR_HANDLER(217, cpu_ll_exc_217) +CPU_LL_INTR_HANDLER(218, cpu_ll_exc_218) +CPU_LL_INTR_HANDLER(219, cpu_ll_exc_219) +CPU_LL_INTR_HANDLER(220, cpu_ll_exc_220) +CPU_LL_INTR_HANDLER(221, cpu_ll_exc_221) +CPU_LL_INTR_HANDLER(222, cpu_ll_exc_222) +CPU_LL_INTR_HANDLER(223, cpu_ll_exc_223) +CPU_LL_INTR_HANDLER(224, cpu_ll_exc_224) +CPU_LL_INTR_HANDLER(225, cpu_ll_exc_225) +CPU_LL_INTR_HANDLER(226, cpu_ll_exc_226) +CPU_LL_INTR_HANDLER(227, cpu_ll_exc_227) +CPU_LL_INTR_HANDLER(228, cpu_ll_exc_228) +CPU_LL_INTR_HANDLER(229, cpu_ll_exc_229) +CPU_LL_INTR_HANDLER(230, cpu_ll_exc_230) +CPU_LL_INTR_HANDLER(231, cpu_ll_exc_231) +CPU_LL_INTR_HANDLER(232, cpu_ll_exc_232) +CPU_LL_INTR_HANDLER(233, cpu_ll_exc_233) +CPU_LL_INTR_HANDLER(234, cpu_ll_exc_234) +CPU_LL_INTR_HANDLER(235, cpu_ll_exc_235) +CPU_LL_INTR_HANDLER(236, cpu_ll_exc_236) +CPU_LL_INTR_HANDLER(237, cpu_ll_exc_237) +CPU_LL_INTR_HANDLER(238, cpu_ll_exc_238) +CPU_LL_INTR_HANDLER(239, cpu_ll_exc_239) +CPU_LL_INTR_HANDLER(240, cpu_ll_exc_240) +CPU_LL_INTR_HANDLER(241, cpu_ll_exc_241) +CPU_LL_INTR_HANDLER(242, cpu_ll_exc_242) +CPU_LL_INTR_HANDLER(243, cpu_ll_exc_243) +CPU_LL_INTR_HANDLER(244, cpu_ll_exc_244) +CPU_LL_INTR_HANDLER(245, cpu_ll_exc_245) +CPU_LL_INTR_HANDLER(246, cpu_ll_exc_246) +CPU_LL_INTR_HANDLER(247, cpu_ll_exc_247) +CPU_LL_INTR_HANDLER(248, cpu_ll_exc_248) +CPU_LL_INTR_HANDLER(249, cpu_ll_exc_249) +CPU_LL_INTR_HANDLER(250, cpu_ll_exc_250) +CPU_LL_INTR_HANDLER(251, cpu_ll_exc_251) +CPU_LL_INTR_HANDLER(252, cpu_ll_exc_252) +CPU_LL_INTR_HANDLER(253, cpu_ll_exc_253) +CPU_LL_INTR_HANDLER(254, cpu_ll_exc_254) +CPU_LL_INTR_HANDLER(255, cpu_ll_exc_255) + +#ifdef __LP64__ +#define CPU_LL_EXC_HANDLER_ADDR(name) .quad name +#else /* __LP64__ */ +#define CPU_LL_EXC_HANDLER_ADDR(name) .long name +#endif /* __LP64__ */ + +.section INIT_DATA_SECTION + +/* See the C declaration */ +ASM_DATA(cpu_ll_exc_handler_addrs) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_divide_error) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_debug) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_nmi) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_breakpoint) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_overflow) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_bound_range) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_undefined_opcode) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_no_math_coprocessor) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_double_fault) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_9) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_invalid_tss) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_segment_not_present) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_stack_segment_fault) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_general_protection) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_page_fault) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_15) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_math_fault) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_alignment_check) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_machine_check) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_simd_fp_exception) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_20) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_21) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_22) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_23) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_24) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_25) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_26) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_27) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_28) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_29) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_30) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_31) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_32) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_33) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_34) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_35) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_36) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_37) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_38) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_39) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_40) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_41) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_42) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_43) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_44) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_45) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_46) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_47) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_48) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_49) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_50) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_51) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_52) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_53) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_54) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_55) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_56) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_57) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_58) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_59) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_60) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_61) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_62) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_63) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_64) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_65) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_66) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_67) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_68) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_69) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_70) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_71) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_72) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_73) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_74) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_75) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_76) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_77) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_78) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_79) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_80) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_81) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_82) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_83) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_84) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_85) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_86) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_87) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_88) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_89) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_90) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_91) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_92) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_93) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_94) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_95) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_96) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_97) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_98) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_99) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_100) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_101) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_102) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_103) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_104) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_105) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_106) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_107) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_108) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_109) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_110) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_111) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_112) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_113) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_114) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_115) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_116) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_117) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_118) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_119) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_120) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_121) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_122) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_123) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_124) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_125) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_126) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_127) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_128) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_129) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_130) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_131) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_132) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_133) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_134) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_135) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_136) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_137) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_138) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_139) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_140) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_141) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_142) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_143) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_144) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_145) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_146) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_147) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_148) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_149) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_150) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_151) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_152) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_153) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_154) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_155) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_156) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_157) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_158) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_159) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_160) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_161) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_162) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_163) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_164) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_165) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_166) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_167) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_168) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_169) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_170) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_171) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_172) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_173) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_174) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_175) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_176) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_177) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_178) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_179) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_180) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_181) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_182) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_183) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_184) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_185) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_186) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_187) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_188) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_189) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_190) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_191) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_192) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_193) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_194) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_195) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_196) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_197) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_198) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_199) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_200) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_201) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_202) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_203) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_204) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_205) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_206) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_207) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_208) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_209) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_210) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_211) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_212) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_213) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_214) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_215) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_216) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_217) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_218) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_219) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_220) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_221) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_222) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_223) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_224) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_225) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_226) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_227) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_228) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_229) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_230) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_231) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_232) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_233) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_234) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_235) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_236) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_237) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_238) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_239) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_240) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_241) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_242) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_243) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_244) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_245) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_246) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_247) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_248) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_249) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_250) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_251) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_252) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_253) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_254) + CPU_LL_EXC_HANDLER_ADDR(cpu_ll_exc_255) +ASM_END(cpu_ll_exc_handler_addrs) ASM_ENTRY(cpu_load_gdt) #ifdef __LP64__ - lgdt (%rdi) + lgdt (%rdi) #else /* __LP64__ */ - movl 4(%esp), %eax - lgdt (%eax) + movl 4(%esp), %eax + lgdt (%eax) #endif /* __LP64__ */ - movl $CPU_GDT_SEL_DATA, %eax - movl %eax, %ds - movl %eax, %es - movl %eax, %ss + movl $CPU_GDT_SEL_DATA, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %ss - /* Alter the stack to reload the code segment using a far return */ + /* Alter the stack to reload the code segment using a far return */ #ifdef __LP64__ - popq %rax - pushq $CPU_GDT_SEL_CODE - pushq %rax - lretq + popq %rax + pushq $CPU_GDT_SEL_CODE + pushq %rax + lretq #else /* __LP64__ */ - popl %eax - pushl $CPU_GDT_SEL_CODE - pushl %eax - lret + popl %eax + pushl $CPU_GDT_SEL_CODE + pushl %eax + lret #endif /* __LP64__ */ ASM_END(cpu_load_gdt) diff --git a/arch/x86/machine/cpu_i.h b/arch/x86/machine/cpu_i.h new file mode 100644 index 00000000..2c28573e --- /dev/null +++ b/arch/x86/machine/cpu_i.h @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2018 Richard Braun. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef X86_CPU_I_H +#define X86_CPU_I_H + +/* + * EFLAGS register flags. + */ +#define CPU_EFL_ONE 0x00000002 /* Reserved, must be set */ +#define CPU_EFL_IF 0x00000200 + +/* + * GDT segment selectors. + * + * Keep in mind that, on amd64, the size of a GDT entry referred to + * by a selector depends on the descriptor type. + */ +#define CPU_GDT_SEL_NULL 0 +#define CPU_GDT_SEL_CODE 8 +#define CPU_GDT_SEL_DATA 16 +#define CPU_GDT_SEL_TSS 24 + +#ifdef __LP64__ +#define CPU_GDT_SIZE 40 +#else /* __LP64__ */ +#define CPU_GDT_SEL_DF_TSS 32 +#define CPU_GDT_SEL_PERCPU 40 +#define CPU_GDT_SEL_TLS 48 +#define CPU_GDT_SIZE 56 +#endif /* __LP64__ */ + +#ifndef __ASSEMBLER__ + +#include <stdalign.h> +#include <stdint.h> + +struct cpu_tss { +#ifdef __LP64__ + uint32_t reserved0; + uint64_t rsp0; + uint64_t rsp1; + uint64_t rsp2; + uint64_t ist[8]; + uint64_t reserved1; + uint16_t reserved2; +#else /* __LP64__ */ + uint32_t link; + uint32_t esp0; + uint32_t ss0; + uint32_t esp1; + uint32_t ss1; + uint32_t esp2; + uint32_t ss2; + uint32_t cr3; + uint32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t es; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t fs; + uint32_t gs; + uint32_t ldt; + uint16_t trap_bit; +#endif /* __LP64__ */ + uint16_t iobp_base; +} __packed; + +/* + * LDT or TSS system segment descriptor. + */ +struct cpu_sysseg_desc { + uint32_t word1; + uint32_t word2; +#ifdef __LP64__ + uint32_t word3; + uint32_t word4; +#endif /* __LP64__ */ +}; + +struct cpu_gdt { + alignas(CPU_L1_SIZE) char descs[CPU_GDT_SIZE]; +}; + +#define CPU_VENDOR_ID_SIZE 13 +#define CPU_MODEL_NAME_SIZE 49 + +/* + * CPU states. + * TODO Boolean. + */ +#define CPU_STATE_OFF 0 +#define CPU_STATE_ON 1 + +struct cpu { + unsigned int id; + unsigned int apic_id; + char vendor_str[CPU_VENDOR_STR_SIZE]; + char model_name[CPU_MODEL_NAME_SIZE]; + unsigned int cpuid_max_basic; + unsigned int cpuid_max_extended; + unsigned int vendor_id; + unsigned int type; + unsigned int family; + unsigned int model; + unsigned int stepping; + unsigned int clflush_size; + unsigned int initial_apic_id; + unsigned int features1; // TODO Use a struct bitmap + unsigned int features2; + unsigned int features3; + unsigned int features4; + unsigned short phys_addr_width; + unsigned short virt_addr_width; + + struct cpu_gdt gdt; + + /* + * TSS segments, one set per CPU. + * + * One TSS at least is required per processor to provide the following : + * - stacks for double fault handlers, implemented with task switching + * on i386, interrupt stack tables on amd64 + * - stacks for each privilege level + * - I/O permission bitmaps + * + * See Intel 64 and IA-32 Architecture Software Developer's Manual, + * Volume 3 System Programming Guide : + * - 6.12.2 Interrupt tasks + * - 7.3 Task switching + */ + struct cpu_tss tss; +#ifndef __LP64__ + struct cpu_tss df_tss; +#endif /* __LP64__ */ + + volatile int state; // TODO Atomic accessors + void *boot_stack; + + alignas(CPU_DATA_ALIGN) char intr_stack[CPU_INTR_STACK_SIZE]; + alignas(CPU_DATA_ALIGN) char df_stack[CPU_INTR_STACK_SIZE]; +}; + +/* + * This percpu variable contains the address of the percpu area for the local + * processor. This is normally the same value stored in the percpu module, but + * it can be directly accessed through a segment register. + */ +extern void *cpu_local_area; + +/* + * Return the content of the EFLAGS register. + * + * Implies a compiler barrier. + * + * TODO Add cpu_flags_t type. + */ +static __always_inline unsigned long +cpu_get_eflags(void) +{ + unsigned long eflags; + + asm volatile("pushf\n" + "pop %0\n" + : "=r" (eflags) + : : "memory"); + + return eflags; +} + +#endif /* __ASSEMBLER__ */ + +#endif /* X86_CPU_I_H */ diff --git a/arch/x86/machine/ioapic.c b/arch/x86/machine/ioapic.c index f90e1209..2b74ed17 100644 --- a/arch/x86/machine/ioapic.c +++ b/arch/x86/machine/ioapic.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Richard Braun. + * Copyright (c) 2017-2018 Richard Braun. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,7 +31,6 @@ #include <machine/ioapic.h> #include <machine/lapic.h> #include <machine/pic.h> -#include <machine/trap.h> #include <vm/vm_kmem.h> #define IOAPIC_REG_VERSION 0x01 @@ -157,9 +156,9 @@ ioapic_write_entry_high(struct ioapic *ioapic, unsigned int id, uint32_t value) } static void -ioapic_intr(struct trap_frame *frame) +ioapic_intr(unsigned int vector) { - intr_handle(frame->vector - TRAP_INTR_FIRST); + intr_handle(vector - CPU_EXC_INTR_FIRST); } static struct ioapic * __init @@ -194,12 +193,12 @@ ioapic_create(unsigned int apic_id, uintptr_t addr, unsigned int gsi_base) ioapic->last_gsi = ioapic->first_gsi + nr_gsis - 1; /* XXX This assumes that interrupts are mapped 1:1 to traps */ - if (ioapic->last_gsi > (TRAP_INTR_LAST - TRAP_INTR_FIRST)) { + if (ioapic->last_gsi > (CPU_EXC_INTR_LAST - CPU_EXC_INTR_FIRST)) { panic("ioapic: invalid interrupt range"); } for (i = ioapic->first_gsi; i < ioapic->last_gsi; i++) { - trap_register(TRAP_INTR_FIRST + i, ioapic_intr); + cpu_register_intr(CPU_EXC_INTR_FIRST + i, ioapic_intr); } log_info("ioapic%u: version:%#x gsis:%u-%u", ioapic->id, @@ -228,14 +227,14 @@ ioapic_compute_entry(uint32_t *highp, uint32_t *lowp, bool active_high, bool edge_triggered) { assert(apic_id < 16); - assert(intr < (TRAP_NR_VECTORS - TRAP_INTR_FIRST)); + assert(intr < (CPU_NR_EXC_VECTORS - CPU_EXC_INTR_FIRST)); *highp = apic_id << 24; *lowp = (!edge_triggered ? IOAPIC_ENTLOW_LEVEL : 0) | (!active_high ? IOAPIC_ENTLOW_ACTIVE_LOW : 0) | IOAPIC_ENTLOW_PHYS_DELIVERY | IOAPIC_ENTLOW_FIXED_DEST - | (TRAP_INTR_FIRST + intr); + | (CPU_EXC_INTR_FIRST + intr); } static void diff --git a/arch/x86/machine/lapic.c b/arch/x86/machine/lapic.c index a15bd5f1..ed5bba3f 100644 --- a/arch/x86/machine/lapic.c +++ b/arch/x86/machine/lapic.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 Richard Braun. + * Copyright (c) 2011-2018 Richard Braun. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,7 +29,6 @@ #include <machine/cpu.h> #include <machine/lapic.h> #include <machine/pmap.h> -#include <machine/trap.h> #include <vm/vm_kmem.h> /* @@ -201,7 +200,7 @@ lapic_compute_freq(void) { uint32_t c1, c2; - lapic_write(&lapic_map->svr, LAPIC_SVR_SOFT_EN | TRAP_LAPIC_SPURIOUS); + lapic_write(&lapic_map->svr, LAPIC_SVR_SOFT_EN | CPU_EXC_LAPIC_SPURIOUS); lapic_write(&lapic_map->timer_dcr, LAPIC_TIMER_DCR_DIV1); /* The APIC timer counter should never wrap around here */ @@ -222,6 +221,52 @@ lapic_eoi(void) lapic_write(&lapic_map->eoi, 0); } +#ifdef CONFIG_PERFMON +static void +lapic_pmc_overflow_intr(unsigned int vector) +{ + (void)vector; + + lapic_eoi(); + + /* Reset the LVT entry as it is automatically cleared when triggered */ + lapic_write(&lapic_map->lvt_pmc, CPU_EXC_LAPIC_PMC_OF); + + perfmon_overflow_intr(); +} +#endif /* CONFIG_PERFMON */ + +static void +lapic_timer_intr(unsigned int vector) +{ + (void)vector; + + lapic_eoi(); + clock_tick_intr(); +} + +static void +lapic_error_intr(unsigned int vector) +{ + uint32_t esr; + + (void)vector; + + esr = lapic_read(&lapic_map->esr); + log_err("lapic: error on cpu%u: esr:%08x", cpu_id(), esr); + lapic_write(&lapic_map->esr, 0); + lapic_eoi(); +} + +static void +lapic_spurious_intr(unsigned int vector) +{ + (void)vector; + log_warning("lapic: spurious interrupt"); + + /* No EOI for this interrupt */ +} + static void __init lapic_setup_registers(void) { @@ -229,18 +274,18 @@ lapic_setup_registers(void) * LVT mask bits can only be cleared when the local APIC is enabled. * They are kept disabled while the local APIC is disabled. */ - lapic_write(&lapic_map->svr, LAPIC_SVR_SOFT_EN | TRAP_LAPIC_SPURIOUS); + lapic_write(&lapic_map->svr, LAPIC_SVR_SOFT_EN | CPU_EXC_LAPIC_SPURIOUS); lapic_write(&lapic_map->tpr, 0); lapic_write(&lapic_map->eoi, 0); lapic_write(&lapic_map->esr, 0); lapic_write(&lapic_map->lvt_timer, LAPIC_LVT_TIMER_PERIODIC - | TRAP_LAPIC_TIMER); + | CPU_EXC_LAPIC_TIMER); lapic_write(&lapic_map->lvt_lint0, LAPIC_LVT_MASK_INTR); lapic_write(&lapic_map->lvt_lint1, LAPIC_LVT_MASK_INTR); - lapic_write(&lapic_map->lvt_error, TRAP_LAPIC_ERROR); + lapic_write(&lapic_map->lvt_error, CPU_EXC_LAPIC_ERROR); lapic_write(&lapic_map->timer_dcr, LAPIC_TIMER_DCR_DIV1); lapic_write(&lapic_map->timer_icr, lapic_bus_freq / CLOCK_FREQ); - lapic_write(&lapic_map->lvt_pmc, TRAP_LAPIC_PMC_OF); + lapic_write(&lapic_map->lvt_pmc, CPU_EXC_LAPIC_PMC_OF); } void __init @@ -248,6 +293,13 @@ lapic_setup(uint32_t map_addr) { uint32_t value; +#ifdef CONFIG_PERFMON + cpu_register_intr(CPU_EXC_LAPIC_PMC_OF, lapic_pmc_overflow_intr); +#endif + cpu_register_intr(CPU_EXC_LAPIC_TIMER, lapic_timer_intr); + cpu_register_intr(CPU_EXC_LAPIC_ERROR, lapic_error_intr); + cpu_register_intr(CPU_EXC_LAPIC_SPURIOUS, lapic_spurious_intr); + lapic_map = vm_kmem_map_pa(map_addr, sizeof(*lapic_map), NULL, NULL); if (lapic_map == NULL) { @@ -334,48 +386,3 @@ lapic_ipi_broadcast(uint32_t vector) lapic_ipi(0, LAPIC_ICR_DEST_ALL_EXCEPT_SELF | (vector & LAPIC_ICR_VECTOR_MASK)); } - -#ifdef CONFIG_PERFMON -void -lapic_pmc_overflow_intr(struct trap_frame *frame) -{ - (void)frame; - - lapic_eoi(); - - /* Reset the LVT entry as it is automatically cleared when triggered */ - lapic_write(&lapic_map->lvt_pmc, TRAP_LAPIC_PMC_OF); - - perfmon_overflow_intr(); -} -#endif /* CONFIG_PERFMON */ - -void -lapic_timer_intr(struct trap_frame *frame) -{ - (void)frame; - - lapic_eoi(); - clock_tick_intr(); -} - -void -lapic_error_intr(struct trap_frame *frame) -{ - uint32_t esr; - - (void)frame; - esr = lapic_read(&lapic_map->esr); - log_err("lapic: error on cpu%u: esr:%08x", cpu_id(), esr); - lapic_write(&lapic_map->esr, 0); - lapic_eoi(); -} - -void -lapic_spurious_intr(struct trap_frame *frame) -{ - (void)frame; - log_warning("lapic: spurious interrupt"); - - /* No EOI for this interrupt */ -} diff --git a/arch/x86/machine/lapic.h b/arch/x86/machine/lapic.h index eac225d7..259bee51 100644 --- a/arch/x86/machine/lapic.h +++ b/arch/x86/machine/lapic.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 Richard Braun. + * Copyright (c) 2011-2018 Richard Braun. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,8 +21,6 @@ #include <stdbool.h> #include <stdint.h> -#include <machine/trap.h> - /* * Send an end-of-interrupt message to the local APIC. */ @@ -51,12 +49,4 @@ void lapic_ipi_startup(uint32_t apic_id, uint32_t vector); void lapic_ipi_send(uint32_t apic_id, uint32_t vector); void lapic_ipi_broadcast(uint32_t vector); -/* - * Interrupt handlers. - */ -void lapic_pmc_overflow_intr(struct trap_frame *frame); -void lapic_timer_intr(struct trap_frame *frame); -void lapic_error_intr(struct trap_frame *frame); -void lapic_spurious_intr(struct trap_frame *frame); - #endif /* X86_LAPIC_H */ diff --git a/arch/x86/machine/pic.c b/arch/x86/machine/pic.c index 3c7e7623..6240e4f8 100644 --- a/arch/x86/machine/pic.c +++ b/arch/x86/machine/pic.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 Richard Braun. + * Copyright (c) 2012-2018 Richard Braun. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,7 +28,6 @@ #include <machine/io.h> #include <machine/lapic.h> #include <machine/pic.h> -#include <machine/trap.h> /* * I/O ports. @@ -155,9 +154,9 @@ static const struct intr_ops pic_ops = { }; static void -pic_intr(struct trap_frame *frame) +pic_intr(unsigned int vector) { - intr_handle(frame->vector - TRAP_INTR_FIRST); + intr_handle(vector - CPU_EXC_INTR_FIRST); } static void __init @@ -168,7 +167,7 @@ pic_register(void) intr_register_ctl(&pic_ops, NULL, 0, PIC_MAX_INTR); for (intr = 0; intr <= PIC_MAX_INTR; intr++) { - trap_register(TRAP_INTR_FIRST + intr, pic_intr); + cpu_register_intr(CPU_EXC_INTR_FIRST + intr, pic_intr); } } @@ -212,8 +211,8 @@ pic_setup_common(bool register_ctl) io_write_byte(PIC_SLAVE_CMD, PIC_ICW1_INIT | PIC_ICW1_IC4); /* ICW 2 */ - io_write_byte(PIC_MASTER_IMR, TRAP_INTR_FIRST); - io_write_byte(PIC_SLAVE_IMR, TRAP_INTR_FIRST + PIC_NR_INTRS); + io_write_byte(PIC_MASTER_IMR, CPU_EXC_INTR_FIRST); + io_write_byte(PIC_SLAVE_IMR, CPU_EXC_INTR_FIRST + PIC_NR_INTRS); /* ICW 3 - Set up cascading */ io_write_byte(PIC_MASTER_IMR, 1 << PIC_SLAVE_INTR); diff --git a/arch/x86/machine/pmap.c b/arch/x86/machine/pmap.c index 182c765c..c8f0437d 100644 --- a/arch/x86/machine/pmap.c +++ b/arch/x86/machine/pmap.c @@ -23,6 +23,7 @@ #include <stdalign.h> #include <stddef.h> #include <stdint.h> +#include <stdio.h> #include <string.h> #include <kern/cpumap.h> @@ -43,7 +44,6 @@ #include <machine/page.h> #include <machine/pmap.h> #include <machine/tcb.h> -#include <machine/trap.h> #include <machine/types.h> #include <vm/vm_kmem.h> #include <vm/vm_page.h> diff --git a/arch/x86/machine/trap.c b/arch/x86/machine/trap.c deleted file mode 100644 index 90c8bf66..00000000 --- a/arch/x86/machine/trap.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright (c) 2012-2014 Richard Braun. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * - * XXX Many traps have not been tested. Some, such as NMIs, are known to need - * additional configuration and resources to be properly handled. - */ - -#include <assert.h> -#include <stdalign.h> -#include <stdint.h> -#include <stdio.h> - -#include <kern/atomic.h> -#include <kern/init.h> -#include <kern/macros.h> -#include <kern/spinlock.h> -#include <kern/thread.h> -#include <machine/cpu.h> -#include <machine/lapic.h> -#include <machine/pic.h> -#include <machine/pmap.h> -#include <machine/strace.h> -#include <machine/trap.h> - -struct trap_cpu_data { - alignas(CPU_DATA_ALIGN) unsigned char intr_stack[TRAP_STACK_SIZE]; -}; - -static struct trap_cpu_data trap_cpu_data __percpu; - -/* - * Type for interrupt service routines and trap handler functions. - */ -typedef void (*trap_isr_fn_t)(void); - -/* - * Trap handler flags. - */ -#define TRAP_HF_INTR 0x1 /* Enter interrupt context */ - -/* - * Properties of a trap handler. - */ -struct trap_handler { - int flags; - trap_handler_fn_t fn; -}; - -/* - * Table of ISR addresses. - */ -extern trap_isr_fn_t trap_isr_table[CPU_IDT_SIZE]; - -/* - * Array of trap handlers. - */ -static struct trap_handler trap_handlers[CPU_IDT_SIZE] __read_mostly; - -/* - * Global trap lock. - * - * This lock is currently only used to serialize concurrent trap handler - * updates. - * - * Interrupts must be disabled when holding this lock. - */ -static struct spinlock trap_lock; - -static struct trap_handler * -trap_handler_get(unsigned int vector) -{ - assert(vector < ARRAY_SIZE(trap_handlers)); - return &trap_handlers[vector]; -} - -static void __init -trap_handler_init(struct trap_handler *handler, int flags, trap_handler_fn_t fn) -{ - handler->flags = flags; - handler->fn = fn; -} - -static void __init -trap_install(unsigned int vector, int flags, trap_handler_fn_t fn) -{ - assert(vector < ARRAY_SIZE(trap_handlers)); - trap_handler_init(trap_handler_get(vector), flags, fn); -} - -static void -trap_show_thread(void) -{ - struct thread *thread; - - thread = thread_self(); - printf("trap: interrupted thread: %p (%s)\n", thread, thread->name); -} - -static void -trap_double_fault(struct trap_frame *frame) -{ - cpu_halt_broadcast(); - -#ifndef __LP64__ - struct trap_frame frame_store; - struct cpu *cpu; - - /* - * Double faults are catched through a task gate, which makes the given - * frame useless. The interrupted state is automatically saved in the - * main TSS by the processor. Build a proper trap frame from there. - */ - frame = &frame_store; - cpu = cpu_current(); - frame->eax = cpu->tss.eax; - frame->ebx = cpu->tss.ebx; - frame->ecx = cpu->tss.ecx; - frame->edx = cpu->tss.edx; - frame->ebp = cpu->tss.ebp; - frame->esi = cpu->tss.esi; - frame->edi = cpu->tss.edi; - frame->ds = cpu->tss.ds; - frame->es = cpu->tss.es; - frame->fs = cpu->tss.fs; - frame->gs = cpu->tss.gs; - frame->vector = TRAP_DF; - frame->error = 0; - frame->eip = cpu->tss.eip; - frame->cs = cpu->tss.cs; - frame->eflags = cpu->tss.eflags; - frame->esp = cpu->tss.esp; - frame->ss = cpu->tss.ss; -#endif /* __LP64__ */ - - printf("trap: double fault (cpu%u):\n", cpu_id()); - trap_show_thread(); - trap_frame_show(frame); - trap_stack_show(frame); - cpu_halt(); -} - -static void __init -trap_install_double_fault(void) -{ - trap_install(TRAP_DF, TRAP_HF_INTR, trap_double_fault); - cpu_idt_set_double_fault(trap_isr_table[TRAP_DF]); -} - -static void -trap_default(struct trap_frame *frame) -{ - cpu_halt_broadcast(); - printf("trap: unhandled interrupt or exception (cpu%u):\n", cpu_id()); - trap_show_thread(); - trap_frame_show(frame); - trap_stack_show(frame); - cpu_halt(); -} - -static int __init -trap_setup(void) -{ - size_t i; - - spinlock_init(&trap_lock); - - for (i = 0; i < ARRAY_SIZE(trap_isr_table); i++) { - cpu_idt_set_gate(i, trap_isr_table[i]); - } - - for (i = 0; i < ARRAY_SIZE(trap_handlers); i++) { - trap_install(i, TRAP_HF_INTR, trap_default); - } - - /* Architecture defined traps */ - trap_install(TRAP_DE, 0, trap_default); - trap_install(TRAP_DB, 0, trap_default); - trap_install(TRAP_NMI, TRAP_HF_INTR, trap_default); - trap_install(TRAP_BP, 0, trap_default); - trap_install(TRAP_OF, 0, trap_default); - trap_install(TRAP_BR, 0, trap_default); - trap_install(TRAP_UD, 0, trap_default); - trap_install(TRAP_NM, 0, trap_default); - trap_install_double_fault(); - trap_install(TRAP_TS, 0, trap_default); - trap_install(TRAP_NP, 0, trap_default); - trap_install(TRAP_SS, 0, trap_default); - trap_install(TRAP_GP, 0, trap_default); - trap_install(TRAP_PF, 0, trap_default); - trap_install(TRAP_MF, 0, trap_default); - trap_install(TRAP_AC, 0, trap_default); - trap_install(TRAP_MC, TRAP_HF_INTR, trap_default); - trap_install(TRAP_XM, 0, trap_default); - - /* System defined traps */ - trap_install(TRAP_XCALL, TRAP_HF_INTR, cpu_xcall_intr); - trap_install(TRAP_THREAD_SCHEDULE, TRAP_HF_INTR, cpu_thread_schedule_intr); - trap_install(TRAP_CPU_HALT, TRAP_HF_INTR, cpu_halt_intr); -#ifdef CONFIG_PERFMON - trap_install(TRAP_LAPIC_PMC_OF, TRAP_HF_INTR, lapic_pmc_overflow_intr); -#endif - trap_install(TRAP_LAPIC_TIMER, TRAP_HF_INTR, lapic_timer_intr); - trap_install(TRAP_LAPIC_ERROR, TRAP_HF_INTR, lapic_error_intr); - trap_install(TRAP_LAPIC_SPURIOUS, TRAP_HF_INTR, lapic_spurious_intr); - - return 0; -} - -INIT_OP_DEFINE(trap_setup); - -void -trap_main(struct trap_frame *frame) -{ - struct trap_handler *handler; - trap_handler_fn_t fn; - - assert(!cpu_intr_enabled()); - - handler = trap_handler_get(frame->vector); - - if (handler->flags & TRAP_HF_INTR) { - thread_intr_enter(); - } - - fn = atomic_load(&handler->fn, ATOMIC_RELAXED); - fn(frame); - - if (handler->flags & TRAP_HF_INTR) { - thread_intr_leave(); - } - - assert(!cpu_intr_enabled()); -} - -void -trap_register(unsigned int vector, trap_handler_fn_t handler_fn) -{ - unsigned long flags; - - spinlock_lock_intr_save(&trap_lock, &flags); - trap_install(vector, TRAP_HF_INTR, handler_fn); - spinlock_unlock_intr_restore(&trap_lock, flags); -} - -#ifdef __LP64__ - -void -trap_frame_show(struct trap_frame *frame) -{ - printf("trap: rax: %016lx rbx: %016lx rcx: %016lx\n" - "trap: rdx: %016lx rbp: %016lx rsi: %016lx\n" - "trap: rdi: %016lx r8: %016lx r9: %016lx\n" - "trap: r10: %016lx r11: %016lx r12: %016lx\n" - "trap: r13: %016lx r14: %016lx r15: %016lx\n" - "trap: vector: %lu error: %08lx\n" - "trap: rip: %016lx cs: %lu rflags: %016lx\n" - "trap: rsp: %016lx ss: %lu\n", - (unsigned long)frame->rax, (unsigned long)frame->rbx, - (unsigned long)frame->rcx, (unsigned long)frame->rdx, - (unsigned long)frame->rbp, (unsigned long)frame->rsi, - (unsigned long)frame->rdi, (unsigned long)frame->r8, - (unsigned long)frame->r9, (unsigned long)frame->r10, - (unsigned long)frame->r11, (unsigned long)frame->r12, - (unsigned long)frame->r13, (unsigned long)frame->r14, - (unsigned long)frame->r15, (unsigned long)frame->vector, - (unsigned long)frame->error, (unsigned long)frame->rip, - (unsigned long)frame->cs, (unsigned long)frame->rflags, - (unsigned long)frame->rsp, (unsigned long)frame->ss); - - /* XXX Until the page fault handler is written */ - if (frame->vector == 14) { - printf("trap: cr2: %016lx\n", (unsigned long)cpu_get_cr2()); - } -} - -#else /* __LP64__ */ - -void -trap_frame_show(struct trap_frame *frame) -{ - unsigned long esp, ss; - - if ((frame->cs & CPU_PL_USER) || (frame->vector == TRAP_DF)) { - esp = frame->esp; - ss = frame->ss; - } else { - esp = 0; - ss = 0; - } - - printf("trap: eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n" - "trap: ebp: %08lx esi: %08lx edi: %08lx\n" - "trap: ds: %hu es: %hu fs: %hu gs: %hu\n" - "trap: vector: %lu error: %08lx\n" - "trap: eip: %08lx cs: %lu eflags: %08lx\n" - "trap: esp: %08lx ss: %lu\n", - (unsigned long)frame->eax, (unsigned long)frame->ebx, - (unsigned long)frame->ecx, (unsigned long)frame->edx, - (unsigned long)frame->ebp, (unsigned long)frame->esi, - (unsigned long)frame->edi, (unsigned short)frame->ds, - (unsigned short)frame->es, (unsigned short)frame->fs, - (unsigned short)frame->gs, (unsigned long)frame->vector, - (unsigned long)frame->error, (unsigned long)frame->eip, - (unsigned long)frame->cs, (unsigned long)frame->eflags, - (unsigned long)esp, (unsigned long)ss); - - - /* XXX Until the page fault handler is written */ - if (frame->vector == 14) { - printf("trap: cr2: %08lx\n", (unsigned long)cpu_get_cr2()); - } -} - -#endif /* __LP64__ */ - -void -trap_stack_show(struct trap_frame *frame) -{ -#ifdef __LP64__ - strace_show(frame->rip, frame->rbp); -#else /* __LP64__ */ - strace_show(frame->eip, frame->ebp); -#endif /* __LP64__ */ -} - -void * -trap_get_interrupt_stack(const struct trap_frame *frame) -{ - struct trap_cpu_data *cpu_data; - struct trap_handler *handler; - - handler = trap_handler_get(frame->vector); - - if ((handler->flags & TRAP_HF_INTR) && !thread_interrupted()) { - cpu_data = cpu_local_ptr(trap_cpu_data); - return cpu_data->intr_stack + sizeof(cpu_data->intr_stack); - } else { - return NULL; - } -} diff --git a/arch/x86/machine/trap.h b/arch/x86/machine/trap.h deleted file mode 100644 index c5bdc1f2..00000000 --- a/arch/x86/machine/trap.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2011-2014 Richard Braun. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * - * Trap (interrupt and exception) handling. - * - * This file is a top header in the inclusion hierarchy, and shouldn't include - * other headers that may cause circular dependencies. - */ - -#ifndef X86_TRAP_H -#define X86_TRAP_H - -#include <machine/page.h> - -/* - * Architecture defined traps. - */ -#define TRAP_DE 0 /* Divide Error */ -#define TRAP_DB 1 /* Debug */ -#define TRAP_NMI 2 /* NMI Interrupt */ -#define TRAP_BP 3 /* Breakpoint */ -#define TRAP_OF 4 /* Overflow */ -#define TRAP_BR 5 /* BOUND Range Exceeded */ -#define TRAP_UD 6 /* Invalid Opcode (Undefined Opcode) */ -#define TRAP_NM 7 /* Device Not Available (No Math Coprocessor) */ -#define TRAP_DF 8 /* Double Fault */ -#define TRAP_TS 10 /* Invalid TSS */ -#define TRAP_NP 11 /* Segment Not Present */ -#define TRAP_SS 12 /* Stack-Segment Fault */ -#define TRAP_GP 13 /* General Protection */ -#define TRAP_PF 14 /* Page Fault */ -#define TRAP_MF 16 /* x87 FPU Floating-Point Error (Math Fault) */ -#define TRAP_AC 17 /* Alignment Check */ -#define TRAP_MC 18 /* Machine Check */ -#define TRAP_XM 19 /* SIMD Floating-Point Exception */ - -/* - * Traps used for handling external interrupts. - */ -#define TRAP_INTR_FIRST 32 -#define TRAP_INTR_LAST 223 - -/* - * System defined traps. - * - * The local APIC assigns one priority every 16 vectors. - */ -#define TRAP_XCALL 238 -#define TRAP_THREAD_SCHEDULE 239 -#define TRAP_CPU_HALT 240 -#define TRAP_LAPIC_PMC_OF 252 -#define TRAP_LAPIC_TIMER 253 -#define TRAP_LAPIC_ERROR 254 -#define TRAP_LAPIC_SPURIOUS 255 - -#define TRAP_NR_VECTORS 256 - -#define TRAP_INTR_TABLE_SIZE 256 - -#define TRAP_STACK_SIZE PAGE_SIZE - -#ifndef __ASSEMBLER__ - -#include <stdint.h> -#include <stdio.h> - -#include <kern/init.h> -#include <kern/macros.h> - -#ifdef __LP64__ - -struct trap_frame { - uint64_t rax; - uint64_t rbx; - uint64_t rcx; - uint64_t rdx; - uint64_t rbp; - uint64_t rsi; - uint64_t rdi; - uint64_t r8; - uint64_t r9; - uint64_t r10; - uint64_t r11; - uint64_t r12; - uint64_t r13; - uint64_t r14; - uint64_t r15; - uint64_t vector; - uint64_t error; - uint64_t rip; - uint64_t cs; - uint64_t rflags; - uint64_t rsp; - uint64_t ss; -} __packed; - -#else /* __LP64__ */ - -struct trap_frame { - uint32_t eax; - uint32_t ebx; - uint32_t ecx; - uint32_t edx; - uint32_t ebp; - uint32_t esi; - uint32_t edi; - uint16_t ds; - uint16_t es; - uint16_t fs; - uint16_t gs; - uint32_t vector; - uint32_t error; - uint32_t eip; - uint32_t cs; - uint32_t eflags; - uint32_t esp; /* esp and ss are undefined if trapped in kernel */ - uint32_t ss; -} __packed; - -#endif /* __LP64__ */ - -/* - * Type for trap handler functions. - */ -typedef void (*trap_handler_fn_t)(struct trap_frame *); - -static inline void -trap_trigger_double_fault(void) -{ - printf("trap: double fault test\n"); - asm volatile("movl $0xdead, %esp; push $0"); -} - -/* - * Unified trap entry point. - */ -void trap_main(struct trap_frame *frame); - -/* - * Register a trap handler. - */ -void trap_register(unsigned int vector, trap_handler_fn_t handler_fn); - -/* - * Display the content of a trap frame. - */ -void trap_frame_show(struct trap_frame *frame); - -/* - * Display the call trace interrupted by the trap of the given frame. - */ -void trap_stack_show(struct trap_frame *frame); - -/* - * Return a pointer to the local interrupt stack. - * - * This function is called by the low level trap handling code. - * - * Return NULL if no stack switching is required. - */ -void * trap_get_interrupt_stack(const struct trap_frame *frame); - -/* - * This init operation provides : - * - initialization of all IDT entries and trap handlers - * - double fault exception support - */ -INIT_OP_DECLARE(trap_setup); - -#endif /* __ASSEMBLER__ */ - -#endif /* X86_TRAP_H */ diff --git a/arch/x86/machine/trap_asm.S b/arch/x86/machine/trap_asm.S deleted file mode 100644 index 2f683bd7..00000000 --- a/arch/x86/machine/trap_asm.S +++ /dev/null @@ -1,693 +0,0 @@ -/* - * Copyright (c) 2012-2017 Richard Braun. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <kern/init.h> -#include <machine/asm.h> -#include <machine/boot.h> -#include <machine/trap.h> - -.text - -#ifdef __LP64__ - -.macro TRAP_STORE_REGISTERS - pushq %r15 - pushq %r14 - pushq %r13 - pushq %r12 - pushq %r11 - pushq %r10 - pushq %r9 - pushq %r8 - pushq %rdi - pushq %rsi - pushq %rbp - pushq %rdx - pushq %rcx - pushq %rbx - pushq %rax -.endm - -.macro TRAP_LOAD_REGISTERS - popq %rax - popq %rbx - popq %rcx - popq %rdx - popq %rbp - popq %rsi - popq %rdi - popq %r8 - popq %r9 - popq %r10 - popq %r11 - popq %r12 - popq %r13 - popq %r14 - popq %r15 - addq $16, %rsp /* skip vector and error */ -.endm - -#define TRAP(vector, name) \ -ASM_ENTRY(name) \ - pushq $0; \ - pushq $(vector); \ - jmp trap_common; \ -ASM_END(name) - -#define TRAP_ERROR(vector, name) \ -ASM_ENTRY(name) \ - pushq $(vector); \ - jmp trap_common; \ -ASM_END(name) - -ASM_ENTRY(trap_common) - TRAP_STORE_REGISTERS - movq %rsp, %rbx /* save frame */ - movq %rbx, %rdi - call trap_get_interrupt_stack - testq %rax, %rax /* switch stack ? */ - jz 1f - movq %rax, %rsp /* switch to interrupt stack ? */ -1: - xorq %rbp, %rbp /* block stack tracing */ - movq %rbx, %rdi - call trap_main - movq %rbx, %rsp /* restore stack */ - call thread_schedule /* schedule threads */ - TRAP_LOAD_REGISTERS - iretq -ASM_END(trap_common) - -#else /* __LP64__ */ - -.macro TRAP_STORE_REGISTERS - pushw %gs - pushw %fs - pushw %es - pushw %ds - pushl %edi - pushl %esi - pushl %ebp - pushl %edx - pushl %ecx - pushl %ebx - pushl %eax -.endm - -/* XXX Don't load segment registers for now */ -.macro TRAP_LOAD_REGISTERS - popl %eax - popl %ebx - popl %ecx - popl %edx - popl %ebp - popl %esi - popl %edi - addl $16, %esp /* skip segment registers, vector and error */ -.endm - -#define TRAP(vector, name) \ -ASM_ENTRY(name) \ - pushl $0; \ - pushl $(vector); \ - jmp trap_common; \ -ASM_END(name) - -#define TRAP_ERROR(vector, name) \ -ASM_ENTRY(name) \ - pushl $(vector); \ - jmp trap_common; \ -ASM_END(name) - -ASM_ENTRY(trap_common) - TRAP_STORE_REGISTERS - movl %esp, %ebx /* save frame */ - pushl %ebx - call trap_get_interrupt_stack - addl $4, %esp - testl %eax, %eax /* switch stack ? */ - jz 1f - movl %eax, %esp /* switch to interrupt stack */ -1: - xorl %ebp, %ebp /* block stack tracing */ - pushl %ebx - call trap_main - movl %ebx, %esp /* restore stack */ - call thread_schedule /* schedule threads */ - TRAP_LOAD_REGISTERS - iret -ASM_END(trap_common) - -#endif /* __LP64__ */ - -/* Architecture defined traps */ -TRAP(TRAP_DE, trap_isr_divide_error) -TRAP(TRAP_DB, trap_isr_debug) -TRAP(TRAP_NMI, trap_isr_nmi) -TRAP(TRAP_BP, trap_isr_breakpoint) -TRAP(TRAP_OF, trap_isr_overflow) -TRAP(TRAP_BR, trap_isr_bound_range) -TRAP(TRAP_UD, trap_isr_invalid_opcode) -TRAP(TRAP_NM, trap_isr_device_not_available) -TRAP_ERROR(TRAP_DF, trap_isr_double_fault) -TRAP_ERROR(TRAP_TS, trap_isr_invalid_tss) -TRAP_ERROR(TRAP_NP, trap_isr_segment_not_present) -TRAP_ERROR(TRAP_SS, trap_isr_stack_segment_fault) -TRAP_ERROR(TRAP_GP, trap_isr_general_protection) -TRAP_ERROR(TRAP_PF, trap_isr_page_fault) -TRAP(TRAP_MF, trap_isr_math_fault) -TRAP_ERROR(TRAP_AC, trap_isr_alignment_check) -TRAP(TRAP_MC, trap_isr_machine_check) -TRAP(TRAP_XM, trap_isr_simd_fp_exception) - -/* - * Handlers for reserved exceptions. - * - * These exceptions should normally never occur, but have handlers ready just - * in case. - */ -TRAP(9, trap_isr_9) -TRAP(15, trap_isr_15) -TRAP(20, trap_isr_20) -TRAP(21, trap_isr_21) -TRAP(22, trap_isr_22) -TRAP(23, trap_isr_23) -TRAP(24, trap_isr_24) -TRAP(25, trap_isr_25) -TRAP(26, trap_isr_26) -TRAP(27, trap_isr_27) -TRAP(28, trap_isr_28) -TRAP(29, trap_isr_29) -TRAP(31, trap_isr_31) - -/* Generic trap handlers */ -TRAP(30, trap_isr_30) -TRAP(32, trap_isr_32) -TRAP(33, trap_isr_33) -TRAP(34, trap_isr_34) -TRAP(35, trap_isr_35) -TRAP(36, trap_isr_36) -TRAP(37, trap_isr_37) -TRAP(38, trap_isr_38) -TRAP(39, trap_isr_39) -TRAP(40, trap_isr_40) -TRAP(41, trap_isr_41) -TRAP(42, trap_isr_42) -TRAP(43, trap_isr_43) -TRAP(44, trap_isr_44) -TRAP(45, trap_isr_45) -TRAP(46, trap_isr_46) -TRAP(47, trap_isr_47) -TRAP(48, trap_isr_48) -TRAP(49, trap_isr_49) -TRAP(50, trap_isr_50) -TRAP(51, trap_isr_51) -TRAP(52, trap_isr_52) -TRAP(53, trap_isr_53) -TRAP(54, trap_isr_54) -TRAP(55, trap_isr_55) -TRAP(56, trap_isr_56) -TRAP(57, trap_isr_57) -TRAP(58, trap_isr_58) -TRAP(59, trap_isr_59) -TRAP(60, trap_isr_60) -TRAP(61, trap_isr_61) -TRAP(62, trap_isr_62) -TRAP(63, trap_isr_63) -TRAP(64, trap_isr_64) -TRAP(65, trap_isr_65) -TRAP(66, trap_isr_66) -TRAP(67, trap_isr_67) -TRAP(68, trap_isr_68) -TRAP(69, trap_isr_69) -TRAP(70, trap_isr_70) -TRAP(71, trap_isr_71) -TRAP(72, trap_isr_72) -TRAP(73, trap_isr_73) -TRAP(74, trap_isr_74) -TRAP(75, trap_isr_75) -TRAP(76, trap_isr_76) -TRAP(77, trap_isr_77) -TRAP(78, trap_isr_78) -TRAP(79, trap_isr_79) -TRAP(80, trap_isr_80) -TRAP(81, trap_isr_81) -TRAP(82, trap_isr_82) -TRAP(83, trap_isr_83) -TRAP(84, trap_isr_84) -TRAP(85, trap_isr_85) -TRAP(86, trap_isr_86) -TRAP(87, trap_isr_87) -TRAP(88, trap_isr_88) -TRAP(89, trap_isr_89) -TRAP(90, trap_isr_90) -TRAP(91, trap_isr_91) -TRAP(92, trap_isr_92) -TRAP(93, trap_isr_93) -TRAP(94, trap_isr_94) -TRAP(95, trap_isr_95) -TRAP(96, trap_isr_96) -TRAP(97, trap_isr_97) -TRAP(98, trap_isr_98) -TRAP(99, trap_isr_99) -TRAP(100, trap_isr_100) -TRAP(101, trap_isr_101) -TRAP(102, trap_isr_102) -TRAP(103, trap_isr_103) -TRAP(104, trap_isr_104) -TRAP(105, trap_isr_105) -TRAP(106, trap_isr_106) -TRAP(107, trap_isr_107) -TRAP(108, trap_isr_108) -TRAP(109, trap_isr_109) -TRAP(110, trap_isr_110) -TRAP(111, trap_isr_111) -TRAP(112, trap_isr_112) -TRAP(113, trap_isr_113) -TRAP(114, trap_isr_114) -TRAP(115, trap_isr_115) -TRAP(116, trap_isr_116) -TRAP(117, trap_isr_117) -TRAP(118, trap_isr_118) -TRAP(119, trap_isr_119) -TRAP(120, trap_isr_120) -TRAP(121, trap_isr_121) -TRAP(122, trap_isr_122) -TRAP(123, trap_isr_123) -TRAP(124, trap_isr_124) -TRAP(125, trap_isr_125) -TRAP(126, trap_isr_126) -TRAP(127, trap_isr_127) -TRAP(128, trap_isr_128) -TRAP(129, trap_isr_129) -TRAP(130, trap_isr_130) -TRAP(131, trap_isr_131) -TRAP(132, trap_isr_132) -TRAP(133, trap_isr_133) -TRAP(134, trap_isr_134) -TRAP(135, trap_isr_135) -TRAP(136, trap_isr_136) -TRAP(137, trap_isr_137) -TRAP(138, trap_isr_138) -TRAP(139, trap_isr_139) -TRAP(140, trap_isr_140) -TRAP(141, trap_isr_141) -TRAP(142, trap_isr_142) -TRAP(143, trap_isr_143) -TRAP(144, trap_isr_144) -TRAP(145, trap_isr_145) -TRAP(146, trap_isr_146) -TRAP(147, trap_isr_147) -TRAP(148, trap_isr_148) -TRAP(149, trap_isr_149) -TRAP(150, trap_isr_150) -TRAP(151, trap_isr_151) -TRAP(152, trap_isr_152) -TRAP(153, trap_isr_153) -TRAP(154, trap_isr_154) -TRAP(155, trap_isr_155) -TRAP(156, trap_isr_156) -TRAP(157, trap_isr_157) -TRAP(158, trap_isr_158) -TRAP(159, trap_isr_159) -TRAP(160, trap_isr_160) -TRAP(161, trap_isr_161) -TRAP(162, trap_isr_162) -TRAP(163, trap_isr_163) -TRAP(164, trap_isr_164) -TRAP(165, trap_isr_165) -TRAP(166, trap_isr_166) -TRAP(167, trap_isr_167) -TRAP(168, trap_isr_168) -TRAP(169, trap_isr_169) -TRAP(170, trap_isr_170) -TRAP(171, trap_isr_171) -TRAP(172, trap_isr_172) -TRAP(173, trap_isr_173) -TRAP(174, trap_isr_174) -TRAP(175, trap_isr_175) -TRAP(176, trap_isr_176) -TRAP(177, trap_isr_177) -TRAP(178, trap_isr_178) -TRAP(179, trap_isr_179) -TRAP(180, trap_isr_180) -TRAP(181, trap_isr_181) -TRAP(182, trap_isr_182) -TRAP(183, trap_isr_183) -TRAP(184, trap_isr_184) -TRAP(185, trap_isr_185) -TRAP(186, trap_isr_186) -TRAP(187, trap_isr_187) -TRAP(188, trap_isr_188) -TRAP(189, trap_isr_189) -TRAP(190, trap_isr_190) -TRAP(191, trap_isr_191) -TRAP(192, trap_isr_192) -TRAP(193, trap_isr_193) -TRAP(194, trap_isr_194) -TRAP(195, trap_isr_195) -TRAP(196, trap_isr_196) -TRAP(197, trap_isr_197) -TRAP(198, trap_isr_198) -TRAP(199, trap_isr_199) -TRAP(200, trap_isr_200) -TRAP(201, trap_isr_201) -TRAP(202, trap_isr_202) -TRAP(203, trap_isr_203) -TRAP(204, trap_isr_204) -TRAP(205, trap_isr_205) -TRAP(206, trap_isr_206) -TRAP(207, trap_isr_207) -TRAP(208, trap_isr_208) -TRAP(209, trap_isr_209) -TRAP(210, trap_isr_210) -TRAP(211, trap_isr_211) -TRAP(212, trap_isr_212) -TRAP(213, trap_isr_213) -TRAP(214, trap_isr_214) -TRAP(215, trap_isr_215) -TRAP(216, trap_isr_216) -TRAP(217, trap_isr_217) -TRAP(218, trap_isr_218) -TRAP(219, trap_isr_219) -TRAP(220, trap_isr_220) -TRAP(221, trap_isr_221) -TRAP(222, trap_isr_222) -TRAP(223, trap_isr_223) -TRAP(224, trap_isr_224) -TRAP(225, trap_isr_225) -TRAP(226, trap_isr_226) -TRAP(227, trap_isr_227) -TRAP(228, trap_isr_228) -TRAP(229, trap_isr_229) -TRAP(230, trap_isr_230) -TRAP(231, trap_isr_231) -TRAP(232, trap_isr_232) -TRAP(233, trap_isr_233) -TRAP(234, trap_isr_234) -TRAP(235, trap_isr_235) -TRAP(236, trap_isr_236) -TRAP(237, trap_isr_237) -TRAP(238, trap_isr_238) -TRAP(239, trap_isr_239) -TRAP(240, trap_isr_240) -TRAP(241, trap_isr_241) -TRAP(242, trap_isr_242) -TRAP(243, trap_isr_243) -TRAP(244, trap_isr_244) -TRAP(245, trap_isr_245) -TRAP(246, trap_isr_246) -TRAP(247, trap_isr_247) -TRAP(248, trap_isr_248) -TRAP(249, trap_isr_249) -TRAP(250, trap_isr_250) -TRAP(251, trap_isr_251) -TRAP(252, trap_isr_252) -TRAP(253, trap_isr_253) -TRAP(254, trap_isr_254) -TRAP(255, trap_isr_255) - -#ifdef __LP64__ -#define TRAP_TABLE_ENTRY(name) .quad name -#else /* __LP64__ */ -#define TRAP_TABLE_ENTRY(name) .long name -#endif /* __LP64__ */ - -.section INIT_DATA_SECTION - -/* - * This table lists all interrupt service routines as installed in the - * IDT. - */ -ASM_DATA(trap_isr_table) -TRAP_TABLE_ENTRY(trap_isr_divide_error) -TRAP_TABLE_ENTRY(trap_isr_debug) -TRAP_TABLE_ENTRY(trap_isr_nmi) -TRAP_TABLE_ENTRY(trap_isr_breakpoint) -TRAP_TABLE_ENTRY(trap_isr_overflow) -TRAP_TABLE_ENTRY(trap_isr_bound_range) -TRAP_TABLE_ENTRY(trap_isr_invalid_opcode) -TRAP_TABLE_ENTRY(trap_isr_device_not_available) -TRAP_TABLE_ENTRY(trap_isr_double_fault) -TRAP_TABLE_ENTRY(trap_isr_9) -TRAP_TABLE_ENTRY(trap_isr_invalid_tss) -TRAP_TABLE_ENTRY(trap_isr_segment_not_present) -TRAP_TABLE_ENTRY(trap_isr_stack_segment_fault) -TRAP_TABLE_ENTRY(trap_isr_general_protection) -TRAP_TABLE_ENTRY(trap_isr_page_fault) -TRAP_TABLE_ENTRY(trap_isr_15) -TRAP_TABLE_ENTRY(trap_isr_math_fault) -TRAP_TABLE_ENTRY(trap_isr_alignment_check) -TRAP_TABLE_ENTRY(trap_isr_machine_check) -TRAP_TABLE_ENTRY(trap_isr_simd_fp_exception) -TRAP_TABLE_ENTRY(trap_isr_20) -TRAP_TABLE_ENTRY(trap_isr_21) -TRAP_TABLE_ENTRY(trap_isr_22) -TRAP_TABLE_ENTRY(trap_isr_23) -TRAP_TABLE_ENTRY(trap_isr_24) -TRAP_TABLE_ENTRY(trap_isr_25) -TRAP_TABLE_ENTRY(trap_isr_26) -TRAP_TABLE_ENTRY(trap_isr_27) -TRAP_TABLE_ENTRY(trap_isr_28) -TRAP_TABLE_ENTRY(trap_isr_29) -TRAP_TABLE_ENTRY(trap_isr_30) -TRAP_TABLE_ENTRY(trap_isr_31) -TRAP_TABLE_ENTRY(trap_isr_32) -TRAP_TABLE_ENTRY(trap_isr_33) -TRAP_TABLE_ENTRY(trap_isr_34) -TRAP_TABLE_ENTRY(trap_isr_35) -TRAP_TABLE_ENTRY(trap_isr_36) -TRAP_TABLE_ENTRY(trap_isr_37) -TRAP_TABLE_ENTRY(trap_isr_38) -TRAP_TABLE_ENTRY(trap_isr_39) -TRAP_TABLE_ENTRY(trap_isr_40) -TRAP_TABLE_ENTRY(trap_isr_41) -TRAP_TABLE_ENTRY(trap_isr_42) -TRAP_TABLE_ENTRY(trap_isr_43) -TRAP_TABLE_ENTRY(trap_isr_44) -TRAP_TABLE_ENTRY(trap_isr_45) -TRAP_TABLE_ENTRY(trap_isr_46) -TRAP_TABLE_ENTRY(trap_isr_47) -TRAP_TABLE_ENTRY(trap_isr_48) -TRAP_TABLE_ENTRY(trap_isr_49) -TRAP_TABLE_ENTRY(trap_isr_50) -TRAP_TABLE_ENTRY(trap_isr_51) -TRAP_TABLE_ENTRY(trap_isr_52) -TRAP_TABLE_ENTRY(trap_isr_53) -TRAP_TABLE_ENTRY(trap_isr_54) -TRAP_TABLE_ENTRY(trap_isr_55) -TRAP_TABLE_ENTRY(trap_isr_56) -TRAP_TABLE_ENTRY(trap_isr_57) -TRAP_TABLE_ENTRY(trap_isr_58) -TRAP_TABLE_ENTRY(trap_isr_59) -TRAP_TABLE_ENTRY(trap_isr_60) -TRAP_TABLE_ENTRY(trap_isr_61) -TRAP_TABLE_ENTRY(trap_isr_62) -TRAP_TABLE_ENTRY(trap_isr_63) -TRAP_TABLE_ENTRY(trap_isr_64) -TRAP_TABLE_ENTRY(trap_isr_65) -TRAP_TABLE_ENTRY(trap_isr_66) -TRAP_TABLE_ENTRY(trap_isr_67) -TRAP_TABLE_ENTRY(trap_isr_68) -TRAP_TABLE_ENTRY(trap_isr_69) -TRAP_TABLE_ENTRY(trap_isr_70) -TRAP_TABLE_ENTRY(trap_isr_71) -TRAP_TABLE_ENTRY(trap_isr_72) -TRAP_TABLE_ENTRY(trap_isr_73) -TRAP_TABLE_ENTRY(trap_isr_74) -TRAP_TABLE_ENTRY(trap_isr_75) -TRAP_TABLE_ENTRY(trap_isr_76) -TRAP_TABLE_ENTRY(trap_isr_77) -TRAP_TABLE_ENTRY(trap_isr_78) -TRAP_TABLE_ENTRY(trap_isr_79) -TRAP_TABLE_ENTRY(trap_isr_80) -TRAP_TABLE_ENTRY(trap_isr_81) -TRAP_TABLE_ENTRY(trap_isr_82) -TRAP_TABLE_ENTRY(trap_isr_83) -TRAP_TABLE_ENTRY(trap_isr_84) -TRAP_TABLE_ENTRY(trap_isr_85) -TRAP_TABLE_ENTRY(trap_isr_86) -TRAP_TABLE_ENTRY(trap_isr_87) -TRAP_TABLE_ENTRY(trap_isr_88) -TRAP_TABLE_ENTRY(trap_isr_89) -TRAP_TABLE_ENTRY(trap_isr_90) -TRAP_TABLE_ENTRY(trap_isr_91) -TRAP_TABLE_ENTRY(trap_isr_92) -TRAP_TABLE_ENTRY(trap_isr_93) -TRAP_TABLE_ENTRY(trap_isr_94) -TRAP_TABLE_ENTRY(trap_isr_95) -TRAP_TABLE_ENTRY(trap_isr_96) -TRAP_TABLE_ENTRY(trap_isr_97) -TRAP_TABLE_ENTRY(trap_isr_98) -TRAP_TABLE_ENTRY(trap_isr_99) -TRAP_TABLE_ENTRY(trap_isr_100) -TRAP_TABLE_ENTRY(trap_isr_101) -TRAP_TABLE_ENTRY(trap_isr_102) -TRAP_TABLE_ENTRY(trap_isr_103) -TRAP_TABLE_ENTRY(trap_isr_104) -TRAP_TABLE_ENTRY(trap_isr_105) -TRAP_TABLE_ENTRY(trap_isr_106) -TRAP_TABLE_ENTRY(trap_isr_107) -TRAP_TABLE_ENTRY(trap_isr_108) -TRAP_TABLE_ENTRY(trap_isr_109) -TRAP_TABLE_ENTRY(trap_isr_110) -TRAP_TABLE_ENTRY(trap_isr_111) -TRAP_TABLE_ENTRY(trap_isr_112) -TRAP_TABLE_ENTRY(trap_isr_113) -TRAP_TABLE_ENTRY(trap_isr_114) -TRAP_TABLE_ENTRY(trap_isr_115) -TRAP_TABLE_ENTRY(trap_isr_116) -TRAP_TABLE_ENTRY(trap_isr_117) -TRAP_TABLE_ENTRY(trap_isr_118) -TRAP_TABLE_ENTRY(trap_isr_119) -TRAP_TABLE_ENTRY(trap_isr_120) -TRAP_TABLE_ENTRY(trap_isr_121) -TRAP_TABLE_ENTRY(trap_isr_122) -TRAP_TABLE_ENTRY(trap_isr_123) -TRAP_TABLE_ENTRY(trap_isr_124) -TRAP_TABLE_ENTRY(trap_isr_125) -TRAP_TABLE_ENTRY(trap_isr_126) -TRAP_TABLE_ENTRY(trap_isr_127) -TRAP_TABLE_ENTRY(trap_isr_128) -TRAP_TABLE_ENTRY(trap_isr_129) -TRAP_TABLE_ENTRY(trap_isr_130) -TRAP_TABLE_ENTRY(trap_isr_131) -TRAP_TABLE_ENTRY(trap_isr_132) -TRAP_TABLE_ENTRY(trap_isr_133) -TRAP_TABLE_ENTRY(trap_isr_134) -TRAP_TABLE_ENTRY(trap_isr_135) -TRAP_TABLE_ENTRY(trap_isr_136) -TRAP_TABLE_ENTRY(trap_isr_137) -TRAP_TABLE_ENTRY(trap_isr_138) -TRAP_TABLE_ENTRY(trap_isr_139) -TRAP_TABLE_ENTRY(trap_isr_140) -TRAP_TABLE_ENTRY(trap_isr_141) -TRAP_TABLE_ENTRY(trap_isr_142) -TRAP_TABLE_ENTRY(trap_isr_143) -TRAP_TABLE_ENTRY(trap_isr_144) -TRAP_TABLE_ENTRY(trap_isr_145) -TRAP_TABLE_ENTRY(trap_isr_146) -TRAP_TABLE_ENTRY(trap_isr_147) -TRAP_TABLE_ENTRY(trap_isr_148) -TRAP_TABLE_ENTRY(trap_isr_149) -TRAP_TABLE_ENTRY(trap_isr_150) -TRAP_TABLE_ENTRY(trap_isr_151) -TRAP_TABLE_ENTRY(trap_isr_152) -TRAP_TABLE_ENTRY(trap_isr_153) -TRAP_TABLE_ENTRY(trap_isr_154) -TRAP_TABLE_ENTRY(trap_isr_155) -TRAP_TABLE_ENTRY(trap_isr_156) -TRAP_TABLE_ENTRY(trap_isr_157) -TRAP_TABLE_ENTRY(trap_isr_158) -TRAP_TABLE_ENTRY(trap_isr_159) -TRAP_TABLE_ENTRY(trap_isr_160) -TRAP_TABLE_ENTRY(trap_isr_161) -TRAP_TABLE_ENTRY(trap_isr_162) -TRAP_TABLE_ENTRY(trap_isr_163) -TRAP_TABLE_ENTRY(trap_isr_164) -TRAP_TABLE_ENTRY(trap_isr_165) -TRAP_TABLE_ENTRY(trap_isr_166) -TRAP_TABLE_ENTRY(trap_isr_167) -TRAP_TABLE_ENTRY(trap_isr_168) -TRAP_TABLE_ENTRY(trap_isr_169) -TRAP_TABLE_ENTRY(trap_isr_170) -TRAP_TABLE_ENTRY(trap_isr_171) -TRAP_TABLE_ENTRY(trap_isr_172) -TRAP_TABLE_ENTRY(trap_isr_173) -TRAP_TABLE_ENTRY(trap_isr_174) -TRAP_TABLE_ENTRY(trap_isr_175) -TRAP_TABLE_ENTRY(trap_isr_176) -TRAP_TABLE_ENTRY(trap_isr_177) -TRAP_TABLE_ENTRY(trap_isr_178) -TRAP_TABLE_ENTRY(trap_isr_179) -TRAP_TABLE_ENTRY(trap_isr_180) -TRAP_TABLE_ENTRY(trap_isr_181) -TRAP_TABLE_ENTRY(trap_isr_182) -TRAP_TABLE_ENTRY(trap_isr_183) -TRAP_TABLE_ENTRY(trap_isr_184) -TRAP_TABLE_ENTRY(trap_isr_185) -TRAP_TABLE_ENTRY(trap_isr_186) -TRAP_TABLE_ENTRY(trap_isr_187) -TRAP_TABLE_ENTRY(trap_isr_188) -TRAP_TABLE_ENTRY(trap_isr_189) -TRAP_TABLE_ENTRY(trap_isr_190) -TRAP_TABLE_ENTRY(trap_isr_191) -TRAP_TABLE_ENTRY(trap_isr_192) -TRAP_TABLE_ENTRY(trap_isr_193) -TRAP_TABLE_ENTRY(trap_isr_194) -TRAP_TABLE_ENTRY(trap_isr_195) -TRAP_TABLE_ENTRY(trap_isr_196) -TRAP_TABLE_ENTRY(trap_isr_197) -TRAP_TABLE_ENTRY(trap_isr_198) -TRAP_TABLE_ENTRY(trap_isr_199) -TRAP_TABLE_ENTRY(trap_isr_200) -TRAP_TABLE_ENTRY(trap_isr_201) -TRAP_TABLE_ENTRY(trap_isr_202) -TRAP_TABLE_ENTRY(trap_isr_203) -TRAP_TABLE_ENTRY(trap_isr_204) -TRAP_TABLE_ENTRY(trap_isr_205) -TRAP_TABLE_ENTRY(trap_isr_206) -TRAP_TABLE_ENTRY(trap_isr_207) -TRAP_TABLE_ENTRY(trap_isr_208) -TRAP_TABLE_ENTRY(trap_isr_209) -TRAP_TABLE_ENTRY(trap_isr_210) -TRAP_TABLE_ENTRY(trap_isr_211) -TRAP_TABLE_ENTRY(trap_isr_212) -TRAP_TABLE_ENTRY(trap_isr_213) -TRAP_TABLE_ENTRY(trap_isr_214) -TRAP_TABLE_ENTRY(trap_isr_215) -TRAP_TABLE_ENTRY(trap_isr_216) -TRAP_TABLE_ENTRY(trap_isr_217) -TRAP_TABLE_ENTRY(trap_isr_218) -TRAP_TABLE_ENTRY(trap_isr_219) -TRAP_TABLE_ENTRY(trap_isr_220) -TRAP_TABLE_ENTRY(trap_isr_221) -TRAP_TABLE_ENTRY(trap_isr_222) -TRAP_TABLE_ENTRY(trap_isr_223) -TRAP_TABLE_ENTRY(trap_isr_224) -TRAP_TABLE_ENTRY(trap_isr_225) -TRAP_TABLE_ENTRY(trap_isr_226) -TRAP_TABLE_ENTRY(trap_isr_227) -TRAP_TABLE_ENTRY(trap_isr_228) -TRAP_TABLE_ENTRY(trap_isr_229) -TRAP_TABLE_ENTRY(trap_isr_230) -TRAP_TABLE_ENTRY(trap_isr_231) -TRAP_TABLE_ENTRY(trap_isr_232) -TRAP_TABLE_ENTRY(trap_isr_233) -TRAP_TABLE_ENTRY(trap_isr_234) -TRAP_TABLE_ENTRY(trap_isr_235) -TRAP_TABLE_ENTRY(trap_isr_236) -TRAP_TABLE_ENTRY(trap_isr_237) -TRAP_TABLE_ENTRY(trap_isr_238) -TRAP_TABLE_ENTRY(trap_isr_239) -TRAP_TABLE_ENTRY(trap_isr_240) -TRAP_TABLE_ENTRY(trap_isr_241) -TRAP_TABLE_ENTRY(trap_isr_242) -TRAP_TABLE_ENTRY(trap_isr_243) -TRAP_TABLE_ENTRY(trap_isr_244) -TRAP_TABLE_ENTRY(trap_isr_245) -TRAP_TABLE_ENTRY(trap_isr_246) -TRAP_TABLE_ENTRY(trap_isr_247) -TRAP_TABLE_ENTRY(trap_isr_248) -TRAP_TABLE_ENTRY(trap_isr_249) -TRAP_TABLE_ENTRY(trap_isr_250) -TRAP_TABLE_ENTRY(trap_isr_251) -TRAP_TABLE_ENTRY(trap_isr_252) -TRAP_TABLE_ENTRY(trap_isr_253) -TRAP_TABLE_ENTRY(trap_isr_254) -TRAP_TABLE_ENTRY(trap_isr_255) -ASM_END(trap_isr_table) diff --git a/arch/x86/machine/uart.c b/arch/x86/machine/uart.c index be9ad725..b60c128b 100644 --- a/arch/x86/machine/uart.c +++ b/arch/x86/machine/uart.c @@ -18,6 +18,7 @@ #include <assert.h> #include <errno.h> #include <stdint.h> +#include <stdio.h> #include <kern/arg.h> #include <kern/console.h> diff --git a/kern/intr.c b/kern/intr.c index 541dc5cb..ac2cea6f 100644 --- a/kern/intr.c +++ b/kern/intr.c @@ -39,7 +39,6 @@ #include <kern/thread.h> #include <machine/boot.h> #include <machine/cpu.h> -#include <machine/trap.h> struct intr_handler { alignas(CPU_L1_SIZE) struct list node; @@ -79,7 +78,7 @@ struct intr_entry { /* * Interrupt table. */ -static struct intr_entry intr_table[TRAP_INTR_TABLE_SIZE]; +static struct intr_entry intr_table[CPU_INTR_TABLE_SIZE]; /* * List of registered controllers. |