Setup TSS.

This commit is contained in:
Alexander Myltsev 2022-11-22 22:40:10 +03:00
parent 1e326bddc1
commit 7a2cc02ba8
3 changed files with 61 additions and 1 deletions

View File

@ -24,6 +24,10 @@ typedef unsigned uint;
{ ((lim) >> 12) & 0xffff, (uint)(base) & 0xffff, \ { ((lim) >> 12) & 0xffff, (uint)(base) & 0xffff, \
((uint)(base) >> 16) & 0xff, type, 1, dpl, 1, \ ((uint)(base) >> 16) & 0xff, type, 1, dpl, 1, \
(uint)(lim) >> 28, 0, 0, 1, 1, (uint)(base) >> 24 } (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]; 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); 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 { struct gdt_desc_t {
uint16_t size; uint16_t size;
void* ptr; void* ptr;
} __attribute__((packed)); } __attribute__((packed));
void load_gdt() { 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(); init_seg_desc();
struct gdt_desc_t gdt_desc; struct gdt_desc_t gdt_desc;
gdt_desc.size = sizeof(seg_desc) - 1; gdt_desc.size = sizeof(seg_desc) - 1;
gdt_desc.ptr = seg_desc; gdt_desc.ptr = seg_desc;
asm("lgdt %0": : "m"(gdt_desc)); asm("lgdt %0": : "m"(gdt_desc));
asm("ltr %0": : "r"((ushort)(SEG_TSS << 3)));
} }

View File

@ -4,6 +4,11 @@
#define STA_W 0x2 // Writeable (non-executable segments) #define STA_W 0x2 // Writeable (non-executable segments)
#define STA_R 0x2 // Readable (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 DPL_USER 3
#define SEG_KCODE 1 #define SEG_KCODE 1
@ -18,6 +23,7 @@
(0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff) (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)
#define USER_BASE 0x400000 // 4 MB #define USER_BASE 0x400000 // 4 MB
#define KERN_STACK_BASE 0x90000
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
void load_gdt(); void load_gdt();

2
mbr.S
View File

@ -116,7 +116,7 @@ init_32bit:
mov %ax, %fs mov %ax, %fs
mov %ax, %gs mov %ax, %gs
mov $0x90000, %ebp // 6. setup stack mov $KERN_STACK_BASE, %ebp // 6. setup stack
mov %ebp, %esp mov %ebp, %esp
movzwl entry, %esi movzwl entry, %esi