From 5f3cbb988dc3b9ead7165f3d77c41248e76f80b4 Mon Sep 17 00:00:00 2001 From: Alexander Myltsev Date: Wed, 14 Dec 2022 12:28:30 +0300 Subject: [PATCH] Fix TSS init. --- cpu/gdt.c | 64 +++++++++++-------------------------------------------- cpu/gdt.h | 44 ++++++++++++++++++++++++++++++++++++++ proc.c | 13 ++++++++--- 3 files changed, 67 insertions(+), 54 deletions(-) diff --git a/cpu/gdt.c b/cpu/gdt.c index f5b2572..f2356a3 100644 --- a/cpu/gdt.c +++ b/cpu/gdt.c @@ -1,4 +1,5 @@ #include "gdt.h" +#include "../lib/string.h" #include @@ -18,8 +19,6 @@ struct seg_desc_t { uint8_t base_31_24; // High bits of segment base address } __attribute__((packed)); -typedef unsigned uint; - #define SEG(type, base, lim, dpl) (struct seg_desc_t) \ { ((lim) >> 12) & 0xffff, (uint)(base) & 0xffff, \ ((uint)(base) >> 16) & 0xff, type, 1, dpl, 1, \ @@ -38,66 +37,29 @@ void init_seg_desc() { seg_desc[SEG_UDATA] = SEG(STA_W, USER_BASE, 0xffffffff - USER_BASE, DPL_USER); } -typedef uint16_t ushort; - -struct taskstate { - uint link; // Old ts selector - uint esp0; // Stack pointers and segment selectors - ushort ss0; // after an increase in privilege level - ushort padding1; - uint *esp1; - ushort ss1; - ushort padding2; - uint *esp2; - ushort ss2; - ushort padding3; - void *cr3; // Page directory base - uint *eip; // Saved state from last task switch - uint eflags; - uint eax; // More saved state (registers) - uint ecx; - uint edx; - uint ebx; - uint *esp; - uint *ebp; - uint esi; - uint edi; - ushort es; // Even more saved state (segment selectors) - ushort padding4; - ushort cs; - ushort padding5; - ushort ss; - ushort padding6; - ushort ds; - ushort padding7; - ushort fs; - ushort padding8; - ushort gs; - ushort padding9; - ushort ldt; - ushort padding10; - ushort t; // Trap on task switch - ushort iomb; // I/O map base address -} tss; - struct gdt_desc_t { uint16_t size; void* ptr; } __attribute__((packed)); void load_gdt() { - seg_desc[SEG_TSS] = SEG16(STS_T32A, &tss, sizeof(tss)-1, 0); - seg_desc[SEG_TSS].s = 0; - tss.ss0 = SEG_KDATA << 3; - tss.esp0 = KERN_STACK_BASE; - // setting IOPL=0 in eflags *and* iomb beyond the tss segment limit - // forbids I/O instructions (e.g., inb and outb) from user space - tss.iomb = (ushort) 0xFFFF; init_seg_desc(); struct gdt_desc_t gdt_desc; gdt_desc.size = sizeof(seg_desc) - 1; gdt_desc.ptr = seg_desc; asm("lgdt %0": : "m"(gdt_desc)); +} + +void switchuvm(struct taskstate *tss, void* esp) { + memset(tss, 0, sizeof(*tss)); + seg_desc[SEG_TSS] = SEG16(STS_T32A, tss, sizeof(*tss)-1, 0); + seg_desc[SEG_TSS].s = 0; + tss->ss0 = SEG_KDATA << 3; + tss->esp0 = (uint)esp; + // setting IOPL=0 in eflags *and* iomb beyond the tss segment limit + // forbids I/O instructions (e.g., inb and outb) from user space + tss->iomb = (ushort) 0xFFFF; + asm("ltr %0": : "r"((ushort)(SEG_TSS << 3))); } diff --git a/cpu/gdt.h b/cpu/gdt.h index 0f174b8..00dd40b 100644 --- a/cpu/gdt.h +++ b/cpu/gdt.h @@ -29,5 +29,49 @@ #define KERN_STACK_BASE 0x90000 #ifndef __ASSEMBLER__ +typedef unsigned uint; +typedef unsigned short ushort; + +struct taskstate { + uint link; // Old ts selector + uint esp0; // Stack pointers and segment selectors + ushort ss0; // after an increase in privilege level + ushort padding1; + uint *esp1; + ushort ss1; + ushort padding2; + uint *esp2; + ushort ss2; + ushort padding3; + void *cr3; // Page directory base + uint *eip; // Saved state from last task switch + uint eflags; + uint eax; // More saved state (registers) + uint ecx; + uint edx; + uint ebx; + uint *esp; + uint *ebp; + uint esi; + uint edi; + ushort es; // Even more saved state (segment selectors) + ushort padding4; + ushort cs; + ushort padding5; + ushort ss; + ushort padding6; + ushort ds; + ushort padding7; + ushort fs; + ushort padding8; + ushort gs; + ushort padding9; + ushort ldt; + ushort padding10; + ushort t; // Trap on task switch + ushort iomb; // I/O map base address +}; + void load_gdt(); +void switchuvm(struct taskstate *tss, void* esp); #endif diff --git a/proc.c b/proc.c index 3c19495..6b19510 100644 --- a/proc.c +++ b/proc.c @@ -17,12 +17,18 @@ struct kstack { uint32_t space[400]; struct context context; registers_t trapframe; + char bottom[]; +}; + +struct task { + struct taskstate tss; + struct kstack stack; }; struct vm { void *kernel_thread; void *user_thread; - struct kstack *user_kstack; + struct task *user_task; } *vm; void trapret(); @@ -31,7 +37,8 @@ void swtch(void** oldstack, void* newstack); void run_elf(const char* name) { if (!vm) { vm = kmalloc(sizeof(struct vm)); - vm->user_kstack = kmalloc(sizeof(struct kstack)); + vm->user_task = kmalloc(sizeof(struct task)); + switchuvm(&vm->user_task->tss, vm->user_task->stack.bottom); } if (read_file(name, (void*)USER_BASE, 100 << 20) <= 0) { printk(name); @@ -40,7 +47,7 @@ void run_elf(const char* name) { } Elf32_Ehdr *hdr = (void*)USER_BASE; - struct kstack *u = vm->user_kstack; + struct kstack *u = &vm->user_task->stack; memset(u, 0, sizeof(*u)); u->context.eip = (uint32_t)trapret;