Setup TSS.
This commit is contained in:
parent
1e326bddc1
commit
7a2cc02ba8
54
cpu/gdt.c
54
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)));
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user