diff --git a/arch/x86/include/asm/gdt.h b/arch/x86/include/asm/gdt.h index 8df3115f..75f8ffe8 100644 --- a/arch/x86/include/asm/gdt.h +++ b/arch/x86/include/asm/gdt.h @@ -101,7 +101,12 @@ typedef struct { } __attribute__ ((packed)) gdt_ptr_t; /// Defines the maximum number of GDT entries -#define GDT_ENTRIES (5+MAX_TASKS) +#ifdef CONFIG_X86_32 +#define GDT_ENTRIES (5+MAX_TASKS) +#else +// a TSS descriptor is twice larger than a code/data descriptor +#define GDT_ENTRIES (5+MAX_TASKS*2) +#endif #if GDT_ENTRIES > 8192 #error Too many GDT entries! #endif diff --git a/arch/x86/include/asm/tasks.h b/arch/x86/include/asm/tasks.h index fc138802..cc548423 100644 --- a/arch/x86/include/asm/tasks.h +++ b/arch/x86/include/asm/tasks.h @@ -77,9 +77,18 @@ int create_default_frame(task_t* task, entry_point_t ep, void* arg); * * @return * - 0 on success - * - -EINVAL (-22) on failure */ -int register_task(void); +static inline int register_task(void) +{ +#ifdef CONFIG_X86_32 + uint16_t sel = (CORE_ID+5) << 3; +#else + uint16_t sel = (CORE_ID*2+5) << 3; +#endif + asm volatile ("ltr %%ax" : : "a"(sel)); + + return 0; +} /** @brief Jump back to user code * diff --git a/arch/x86/include/asm/tss.h b/arch/x86/include/asm/tss.h index 17b2e8ab..03540957 100644 --- a/arch/x86/include/asm/tss.h +++ b/arch/x86/include/asm/tss.h @@ -70,8 +70,7 @@ typedef struct { uint64_t ist_rsp5; uint64_t ist_rsp6; uint64_t ist_rsp7; - uint32_t res4; // reserved entries - uint32_t res5; // reserved entries + uint32_t res4, res5; // reserved entries uint16_t res6, bitmap; #endif } __attribute__ ((packed)) tss_t; diff --git a/arch/x86/kernel/entry32.asm b/arch/x86/kernel/entry32.asm index 49e30351..7443ff7f 100644 --- a/arch/x86/kernel/entry32.asm +++ b/arch/x86/kernel/entry32.asm @@ -48,14 +48,6 @@ mboot: dd MULTIBOOT_HEADER_MAGIC dd MULTIBOOT_HEADER_FLAGS dd MULTIBOOT_CHECKSUM - - ; AOUT kludge - must be physical addresses. Make a note of these: - ; The linker script fills in the data for these ones! - ; dd mboot - ; dd code - ; dd bss - ; dd end - ; dd start msg db "?ello from MetalSVM kernel!!", 0 diff --git a/arch/x86/kernel/gdt.c b/arch/x86/kernel/gdt.c index 9dce69ac..c625c8c1 100644 --- a/arch/x86/kernel/gdt.c +++ b/arch/x86/kernel/gdt.c @@ -29,7 +29,7 @@ gdt_ptr_t gp; tss_t task_state_segments[MAX_CORES] __attribute__ ((aligned (PAGE_SIZE))); static unsigned char kstacks[MAX_TASKS][KERNEL_STACK_SIZE] __attribute__ ((aligned (PAGE_SIZE))) = {[0 ... MAX_TASKS-1][0 ... KERNEL_STACK_SIZE-1] = 0xCD}; -size_t default_stack_pointer = (size_t) kstacks[0] + KERNEL_STACK_SIZE - sizeof(size_t); +size_t default_stack_pointer = (size_t) kstacks[0] + KERNEL_STACK_SIZE - 16; // => stack is 16byte aligned // 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}}; @@ -52,17 +52,7 @@ size_t get_stack(uint32_t id) { if (BUILTIN_EXPECT(id >= MAX_TASKS, 0)) return -EINVAL; - return (size_t) kstacks[id] + KERNEL_STACK_SIZE - sizeof(size_t); -} - -int register_task(void) -{ - uint16_t sel; - - sel = (CORE_ID+5) << 3; - asm volatile ("ltr %%ax" : : "a"(sel)); - - return 0; + return (size_t) kstacks[id] + KERNEL_STACK_SIZE - 16; // => stack is 16byte aligned } int arch_fork(task_t* task) @@ -229,14 +219,17 @@ static void gdt_set_gate(int num, unsigned long base, unsigned long limit, */ void gdt_install(void) { - unsigned int i, mode; + unsigned int i; + unsigned long mode, limit; memset(task_state_segments, 0x00, MAX_CORES*sizeof(tss_t)); #ifdef CONFIG_X86_32 mode = GDT_FLAG_32_BIT; + limit = 0xFFFFFFFF; #elif defined(CONFIG_X86_64) mode = GDT_FLAG_64_BIT; + limit = 0; #else #error invalid mode #endif @@ -253,7 +246,7 @@ void gdt_install(void) * is 0, the limit is 4 GByte, it uses 4KByte granularity, * uses 32-bit opcodes, and is a Code Segment descriptor. */ - gdt_set_gate(1, 0, 0xFFFFFFFF, + gdt_set_gate(1, 0, limit, GDT_FLAG_RING0 | GDT_FLAG_SEGMENT | GDT_FLAG_CODESEG | GDT_FLAG_PRESENT, GDT_FLAG_4K_GRAN | mode); @@ -262,21 +255,21 @@ void gdt_install(void) * same as our code segment, but the descriptor type in * this entry's access byte says it's a Data Segment */ - gdt_set_gate(2, 0, 0xFFFFFFFF, + gdt_set_gate(2, 0, limit, GDT_FLAG_RING0 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT, GDT_FLAG_4K_GRAN | mode); /* * Create code segement for userspace applications (ring 3) */ - gdt_set_gate(3, 0, 0xFFFFFFFF, + gdt_set_gate(3, 0, limit, GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_CODESEG | GDT_FLAG_PRESENT, GDT_FLAG_4K_GRAN | mode); /* * Create data segement for userspace applications (ring 3) */ - gdt_set_gate(4, 0, 0xFFFFFFFF, + gdt_set_gate(4, 0, limit, GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT, GDT_FLAG_4K_GRAN | mode); @@ -289,12 +282,13 @@ void gdt_install(void) task_state_segments[i].eflags = 0x1202; task_state_segments[i].ss0 = 0x10; // data segment task_state_segments[i].esp0 = 0xDEADBEEF; // invalid pseudo address + gdt_set_gate(5+i, (unsigned long) (task_state_segments+i), sizeof(tss_t)-1, + GDT_FLAG_PRESENT | GDT_FLAG_TSS | GDT_FLAG_RING0, mode); #elif defined(CONFIG_X86_64) task_state_segments[i].rsp0 = 0xDEADBEEF; // invalid pseudo address + gdt_set_gate(5+i*2, (unsigned long) (task_state_segments+i), sizeof(tss_t)-1, + GDT_FLAG_PRESENT | GDT_FLAG_TSS | GDT_FLAG_RING0, mode); #endif - - gdt_set_gate(5+i, (unsigned long) (task_state_segments+i), sizeof(tss_t)-1, - GDT_FLAG_PRESENT | GDT_FLAG_TSS | GDT_FLAG_RING0, 0); } /* Flush out the old GDT and install the new changes! */ diff --git a/arch/x86/kernel/idt.c b/arch/x86/kernel/idt.c index c14bfeea..aad89b70 100644 --- a/arch/x86/kernel/idt.c +++ b/arch/x86/kernel/idt.c @@ -39,7 +39,11 @@ * for which the 'presence' bit is cleared (0) will generate an * "Unhandled Interrupt" exception */ +#ifdef CONFIG_X86_64 +static idt_entry_t idt[256] = {[0 ... 255] = {0, 0, 0, 0, 0, 0, 0}}; +#else static idt_entry_t idt[256] = {[0 ... 255] = {0, 0, 0, 0, 0}}; +#endif static idt_ptr_t idtp; /* diff --git a/include/metalsvm/ctype.h b/include/metalsvm/ctype.h index 5ea30971..1bf5f7fd 100644 --- a/include/metalsvm/ctype.h +++ b/include/metalsvm/ctype.h @@ -35,7 +35,7 @@ static inline int isascii(int c) /** Applies an and-operation to * push the value of 'c' into the ASCII-range */ -static inline int toascii(c) +static inline int toascii(int c) { return (((unsigned char)(c))&0x7f); }