From 7a2cc02ba8e7c3721bcb168ffeec9b6619f10e43 Mon Sep 17 00:00:00 2001 From: Alexander Myltsev Date: Tue, 22 Nov 2022 22:40:10 +0300 Subject: [PATCH] Setup TSS. --- cpu/gdt.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ cpu/gdt.h | 6 ++++++ mbr.S | 2 +- 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/cpu/gdt.c b/cpu/gdt.c index 4b1b6d2..f5b2572 100644 --- a/cpu/gdt.c +++ b/cpu/gdt.c @@ -24,6 +24,10 @@ typedef unsigned uint; { ((lim) >> 12) & 0xffff, (uint)(base) & 0xffff, \ ((uint)(base) >> 16) & 0xff, type, 1, dpl, 1, \ (uint)(lim) >> 28, 0, 0, 1, 1, (uint)(base) >> 24 } +#define SEG16(type, base, lim, dpl) (struct seg_desc_t) \ +{ (lim) & 0xffff, (uint)(base) & 0xffff, \ + ((uint)(base) >> 16) & 0xff, type, 1, dpl, 1, \ + (uint)(lim) >> 16, 0, 0, 1, 0, (uint)(base) >> 24 } struct seg_desc_t seg_desc[6]; @@ -34,16 +38,66 @@ 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)); + asm("ltr %0": : "r"((ushort)(SEG_TSS << 3))); } diff --git a/cpu/gdt.h b/cpu/gdt.h index ca1acba..6f3bce7 100644 --- a/cpu/gdt.h +++ b/cpu/gdt.h @@ -4,6 +4,11 @@ #define STA_W 0x2 // Writeable (non-executable segments) #define STA_R 0x2 // Readable (executable segments) +// System segment type bits +#define STS_T32A 0x9 // Available 32-bit TSS +#define STS_IG32 0xE // 32-bit Interrupt Gate +#define STS_TG32 0xF // 32-bit Trap Gate + #define DPL_USER 3 #define SEG_KCODE 1 @@ -18,6 +23,7 @@ (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff) #define USER_BASE 0x400000 // 4 MB +#define KERN_STACK_BASE 0x90000 #ifndef __ASSEMBLER__ void load_gdt(); diff --git a/mbr.S b/mbr.S index 34fa7c5..fea161f 100644 --- a/mbr.S +++ b/mbr.S @@ -116,7 +116,7 @@ init_32bit: mov %ax, %fs mov %ax, %gs - mov $0x90000, %ebp // 6. setup stack + mov $KERN_STACK_BASE, %ebp // 6. setup stack mov %ebp, %esp movzwl entry, %esi