From 6e160628d9cd630b41e75c1b48c67e88d135ff60 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sat, 12 Sep 2015 17:23:59 +0200 Subject: [PATCH] add support of interrupt stack table and fix usage of the kernel stack - some code cleanups - NMI , Double Fault and Machine Check Exceptions get its own clean stack in the interrupt stack table --- hermit/arch/x86/include/asm/idt.h | 18 ++---- hermit/arch/x86/include/asm/processor.h | 36 +++++------ hermit/arch/x86/include/asm/tss.h | 18 ++++-- hermit/arch/x86/kernel/gdt.c | 15 ++++- hermit/arch/x86/kernel/idt.c | 10 ++- hermit/arch/x86/kernel/irq.c | 62 +++++++++--------- hermit/arch/x86/kernel/isrs.c | 86 +++++++++++++------------ hermit/arch/x86/kernel/tasks.c | 16 ++++- 8 files changed, 140 insertions(+), 121 deletions(-) diff --git a/hermit/arch/x86/include/asm/idt.h b/hermit/arch/x86/include/asm/idt.h index 65dabc1de..065ddd8e0 100644 --- a/hermit/arch/x86/include/asm/idt.h +++ b/hermit/arch/x86/include/asm/idt.h @@ -82,8 +82,8 @@ typedef struct { uint16_t base_lo; /// Handler function's segment selector. uint16_t sel; - /// These bits are reserved by Intel - uint8_t always0; + /// index of the interrupt stack table + uint8_t ist_index; /// These 8 bits contain flags. Exact use depends on the type of interrupt gate. uint8_t flags; /// Higher 16 bits of handler function's base address @@ -121,19 +121,9 @@ void idt_install(void); * @param base base-address of the handler function being installed * @param sel Segment the IDT will use * @param flags Flags this entry will have + * @param idx Index of interrupt stack table */ -void idt_set_gate(unsigned char num, size_t base, unsigned short sel, - unsigned char flags); - -/** @brief Configures and returns a IDT entry with chosen attributes - * - * Just feed this function with base, selector and the flags - * you have seen in idt.h - * - * @return a preconfigured idt descriptor - */ -void configure_idt_entry(idt_entry_t *dest_entry, size_t base, - unsigned short sel, unsigned char flags); +void idt_set_gate(uint8_t num, size_t base, uint16_t sel, uint8_t flags, uint8_t idx); #ifdef __cplusplus } diff --git a/hermit/arch/x86/include/asm/processor.h b/hermit/arch/x86/include/asm/processor.h index 550eca1c4..bf773011e 100644 --- a/hermit/arch/x86/include/asm/processor.h +++ b/hermit/arch/x86/include/asm/processor.h @@ -87,24 +87,24 @@ extern "C" { /* * EFLAGS bits */ -#define EFLAGS_CF (1 << 0) /* Carry Flag */ -#define EFLAGS_FIXED (1 << 1) /* Bit 1 - always on */ -#define EFLAGS_PF (1 << 2) /* Parity Flag */ -#define EFLAGS_AF (1 << 4) /* Auxiliary carry Flag */ -#define EFLAGS_ZF (1 << 6) /* Zero Flag */ -#define EFLAGS_SF (1 << 7) /* Sign Flag */ -#define EFLAGS_TF (1 << 8) /* Trap Flag */ -#define EFLAGS_IF (1 << 9) /* Interrupt Flag */ -#define EFLAGS_DF (1 << 10) /* Direction Flag */ -#define EFLAGS_OF (1 << 11) /* Overflow Flag */ -#define EFLAGS_IOPL (1 << 12) /* I/O Privilege Level (2 bits) */ -#define EFLAGS_NT (1 << 14) /* Nested Task */ -#define EFLAGS_RF (1 << 16) /* Resume Flag */ -#define EFLAGS_VM (1 << 17) /* Virtual Mode */ -#define EFLAGS_AC (1 << 18) /* Alignment Check/Access Control */ -#define EFLAGS_VIF (1 << 19) /* Virtual Interrupt Flag */ -#define EFLAGS_VIP (1 << 20) /* Virtual Interrupt Pending */ -#define EFLAGS_ID (1 << 21) /* CPUID detection */ +#define EFLAGS_CF (1UL << 0) /* Carry Flag */ +#define EFLAGS_FIXED (1UL << 1) /* Bit 1 - always on */ +#define EFLAGS_PF (1UL << 2) /* Parity Flag */ +#define EFLAGS_AF (1UL << 4) /* Auxiliary carry Flag */ +#define EFLAGS_ZF (1UL << 6) /* Zero Flag */ +#define EFLAGS_SF (1UL << 7) /* Sign Flag */ +#define EFLAGS_TF (1UL << 8) /* Trap Flag */ +#define EFLAGS_IF (1UL << 9) /* Interrupt Flag */ +#define EFLAGS_DF (1UL << 10) /* Direction Flag */ +#define EFLAGS_OF (1UL << 11) /* Overflow Flag */ +#define EFLAGS_IOPL (1UL << 12) /* I/O Privilege Level (2 bits) */ +#define EFLAGS_NT (1UL << 14) /* Nested Task */ +#define EFLAGS_RF (1UL << 16) /* Resume Flag */ +#define EFLAGS_VM (1UL << 17) /* Virtual Mode */ +#define EFLAGS_AC (1UL << 18) /* Alignment Check/Access Control */ +#define EFLAGS_VIF (1UL << 19) /* Virtual Interrupt Flag */ +#define EFLAGS_VIP (1UL << 20) /* Virtual Interrupt Pending */ +#define EFLAGS_ID (1UL << 21) /* CPUID detection */ // x86 control registers diff --git a/hermit/arch/x86/include/asm/tss.h b/hermit/arch/x86/include/asm/tss.h index 4347502b8..43d4bdae1 100644 --- a/hermit/arch/x86/include/asm/tss.h +++ b/hermit/arch/x86/include/asm/tss.h @@ -48,17 +48,21 @@ typedef struct { uint64_t rsp1; uint64_t rsp2; uint32_t res2, res3; // reserved entries - uint64_t ist_rsp1; - uint64_t ist_rsp2; - uint64_t ist_rsp3; - uint64_t ist_rsp4; - uint64_t ist_rsp5; - uint64_t ist_rsp6; - uint64_t ist_rsp7; + uint64_t ist1; + uint64_t ist2; + uint64_t ist3; + uint64_t ist4; + uint64_t ist5; + uint64_t ist6; + uint64_t ist7; uint32_t res4, res5; // reserved entries uint16_t res6, bitmap; } __attribute__ ((packed)) tss_t; +/** @brief Set rsp0 in TSS of the current core + */ +void tss_set_rsp0(size_t ptr); + #ifdef __cplusplus } #endif diff --git a/hermit/arch/x86/kernel/gdt.c b/hermit/arch/x86/kernel/gdt.c index 957dd8170..99c10b87f 100644 --- a/hermit/arch/x86/kernel/gdt.c +++ b/hermit/arch/x86/kernel/gdt.c @@ -38,8 +38,10 @@ gdt_ptr_t gp; // currently, our kernel has full access to the ioports static gdt_entry_t gdt[GDT_ENTRIES] = {[0 ... GDT_ENTRIES-1] = {0, 0, 0, 0, 0, 0}}; -static uint8_t irq_stacks[MAX_CORES][KERNEL_STACK_SIZE] __attribute__ ((aligned (PAGE_SIZE))); static tss_t task_state_segments[MAX_CORES] __attribute__ ((aligned (PAGE_SIZE))); +static uint8_t stack_table[MAX_CORES*KERNEL_STACK_SIZE*3]; + +extern const void boot_stack; /* * This is defined in entry.asm. We use this to properly reload @@ -49,6 +51,11 @@ extern void gdt_flush(void); extern const void boot_stack; +void tss_set_rsp0(size_t stptr) +{ + task_state_segments[CORE_ID].rsp0 = stptr; +} + /* Setup a descriptor in the Global Descriptor Table */ void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran) @@ -137,7 +144,11 @@ void gdt_install(void) * Create TSS for each core (we use these segments for task switching) */ for(i=0; ibase_lo = (base & 0xFFFF); @@ -60,7 +59,7 @@ void configure_idt_entry(idt_entry_t *dest_entry, size_t base, /* The segment or 'selector' that this IDT entry will use * is set here, along with any access flags */ dest_entry->sel = sel; - dest_entry->always0 = 0; + dest_entry->ist_index = idx; dest_entry->flags = flags; } @@ -68,10 +67,9 @@ void configure_idt_entry(idt_entry_t *dest_entry, size_t base, * Use this function to set an entry in the IDT. Alot simpler * than twiddling with the GDT ;) */ -void idt_set_gate(unsigned char num, size_t base, unsigned short sel, - unsigned char flags) +void idt_set_gate(uint8_t num, size_t base, uint16_t sel, uint8_t flags, uint8_t idx) { - configure_idt_entry(&idt[num], base, sel, flags); + configure_idt_entry(&idt[num], base, sel, flags, idx); } #if 0 diff --git a/hermit/arch/x86/kernel/irq.c b/hermit/arch/x86/kernel/irq.c index fbab3f5dd..62d857dd3 100644 --- a/hermit/arch/x86/kernel/irq.c +++ b/hermit/arch/x86/kernel/irq.c @@ -164,70 +164,70 @@ static int irq_install(void) irq_remap(); idt_set_gate(32, (size_t)irq0, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(33, (size_t)irq1, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(34, (size_t)irq2, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(35, (size_t)irq3, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(36, (size_t)irq4, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(37, (size_t)irq5, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(38, (size_t)irq6, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(39, (size_t)irq7, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(40, (size_t)irq8, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(41, (size_t)irq9, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(42, (size_t)irq10, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(43, (size_t)irq11, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(44, (size_t)irq12, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(45, (size_t)irq13, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(46, (size_t)irq14, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(47, (size_t)irq15, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(48, (size_t)irq16, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(49, (size_t)irq17, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(50, (size_t)irq18, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(51, (size_t)irq19, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(52, (size_t)irq20, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(53, (size_t)irq21, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(54, (size_t)irq22, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(55, (size_t)irq23, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(112, (size_t)irq80, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(113, (size_t)irq81, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); // add APIC interrupt handler idt_set_gate(123, (size_t)apic_timer, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(124, (size_t)apic_lint0, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(125, (size_t)apic_lint1, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(126, (size_t)apic_error, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(127, (size_t)apic_svr, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); return 0; } diff --git a/hermit/arch/x86/kernel/isrs.c b/hermit/arch/x86/kernel/isrs.c index 31aa31ce4..2a8ea67da 100644 --- a/hermit/arch/x86/kernel/isrs.c +++ b/hermit/arch/x86/kernel/isrs.c @@ -99,69 +99,72 @@ void isrs_install(void) int i; idt_set_gate(0, (size_t)isr0, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(1, (size_t)isr1, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); + // NMI Exception gets its own stack (ist1) idt_set_gate(2, (size_t)isr2, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 1); idt_set_gate(3, (size_t)isr3, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(4, (size_t)isr4, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(5, (size_t)isr5, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(6, (size_t)isr6, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(7, (size_t)isr7, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); + // Double Fault Exception gets its own stack (ist2) idt_set_gate(8, (size_t)isr8, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 2); idt_set_gate(9, (size_t)isr9, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(10, (size_t)isr10, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(11, (size_t)isr11, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(12, (size_t)isr12, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(13, (size_t)isr13, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(14, (size_t)isr14, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(15, (size_t)isr15, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(16, (size_t)isr16, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(17, (size_t)isr17, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); + // Machine Check Exception gets its own stack (ist3) idt_set_gate(18, (size_t)isr18, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 3); idt_set_gate(19, (size_t)isr19, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(20, (size_t)isr20, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(21, (size_t)isr21, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(22, (size_t)isr22, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(23, (size_t)isr23, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(24, (size_t)isr24, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(25, (size_t)isr25, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(26, (size_t)isr26, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(27, (size_t)isr27, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(28, (size_t)isr28, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(29, (size_t)isr29, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(30, (size_t)isr30, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); idt_set_gate(31, (size_t)isr31, KERNEL_CODE_SELECTOR, - IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP); + IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0); // install the default handler for(i=0; i<32; i++) @@ -199,13 +202,16 @@ static const char *exception_messages[] = { */ static void fault_handler(struct state *s) { - if (s->int_no < 32) { - kputs(exception_messages[s->int_no]); - kprintf(" Exception (%d) on core %d at 0x%llx:0x%llx, error code 0x%llx, rflags 0x%llx\n", - s->int_no, CORE_ID, s->cs, s->rip, s->error, s->rflags); - apic_eoi(s->int_no); - irq_enable(); - abort(); - } + if (s->int_no < 32) + kputs(exception_messages[s->int_no]); + else + kprintf("Unknown exception %d", s->int_no); + + kprintf(" Exception (%d) on core %d at 0x%llx:0x%llx, error code 0x%llx, rflags 0x%llx\n", + s->int_no, CORE_ID, s->cs, s->rip, s->error, s->rflags); + + apic_eoi(s->int_no); + irq_enable(); + abort(); } diff --git a/hermit/arch/x86/kernel/tasks.c b/hermit/arch/x86/kernel/tasks.c index 05749fdf6..a355ca599 100644 --- a/hermit/arch/x86/kernel/tasks.c +++ b/hermit/arch/x86/kernel/tasks.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -100,6 +101,9 @@ static int thread_entry(void* arg, size_t ep) offset -= curr_task->tls_mem_size; if (curr_task->tls_file_size) memcpy((void*) (stack+offset), (void*) curr_task->tls_addr, curr_task->tls_file_size); + + // align stack to 16 byte boundary + offset = offset & ~0xFULL; } else writefs(0); // no TLS => clear fs register // set first argument @@ -112,9 +116,10 @@ static int thread_entry(void* arg, size_t ep) size_t* get_current_stack(void) { task_t* curr_task = per_core(current_task); - size_t stptr = ((size_t) curr_task->stack + KERNEL_STACK_SIZE - 0x10) & ~0xF; + size_t stptr = (size_t) curr_task->stack + KERNEL_STACK_SIZE - 0x10; set_per_core(kernel_stack, stptr); + tss_set_rsp0(stptr); // do we change the address space? if (read_cr3() != curr_task->page_map) @@ -430,16 +435,21 @@ static int load_task(load_args_t* largs) } ((char**) (stack+offset))[largs->envc] = NULL; + // align stack to be conform to the UNIX ABI + size_t old_offset = offset; + offset = offset & ~0xFULL; + offset -= sizeof(size_t); + // push pointer to env offset -= sizeof(char**); if (!(largs->envc)) *((char***) (stack+offset)) = NULL; else - *((char***) (stack+offset)) = (char**) (stack + offset + sizeof(char**)); + *((char***) (stack+offset)) = (char**) (stack + old_offset); // push pointer to argv offset -= sizeof(char**); - *((char***) (stack+offset)) = (char**) (stack + offset + 2*sizeof(char**) + (largs->envc+1) * sizeof(char*)); + *((char***) (stack+offset)) = (char**) (stack + old_offset + (largs->envc+1) * sizeof(char*)); // push argc on the stack offset -= sizeof(ssize_t);