Fix TSS init.
This commit is contained in:
parent
dd9f5786c2
commit
5f3cbb988d
64
cpu/gdt.c
64
cpu/gdt.c
@ -1,4 +1,5 @@
|
|||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
|
#include "../lib/string.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@ -18,8 +19,6 @@ struct seg_desc_t {
|
|||||||
uint8_t base_31_24; // High bits of segment base address
|
uint8_t base_31_24; // High bits of segment base address
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
typedef unsigned uint;
|
|
||||||
|
|
||||||
#define SEG(type, base, lim, dpl) (struct seg_desc_t) \
|
#define SEG(type, base, lim, dpl) (struct seg_desc_t) \
|
||||||
{ ((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, \
|
||||||
@ -38,66 +37,29 @@ 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
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)));
|
asm("ltr %0": : "r"((ushort)(SEG_TSS << 3)));
|
||||||
}
|
}
|
||||||
|
|||||||
44
cpu/gdt.h
44
cpu/gdt.h
@ -29,5 +29,49 @@
|
|||||||
#define KERN_STACK_BASE 0x90000
|
#define KERN_STACK_BASE 0x90000
|
||||||
|
|
||||||
#ifndef __ASSEMBLER__
|
#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 load_gdt();
|
||||||
|
void switchuvm(struct taskstate *tss, void* esp);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
13
proc.c
13
proc.c
@ -17,12 +17,18 @@ struct kstack {
|
|||||||
uint32_t space[400];
|
uint32_t space[400];
|
||||||
struct context context;
|
struct context context;
|
||||||
registers_t trapframe;
|
registers_t trapframe;
|
||||||
|
char bottom[];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct task {
|
||||||
|
struct taskstate tss;
|
||||||
|
struct kstack stack;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vm {
|
struct vm {
|
||||||
void *kernel_thread;
|
void *kernel_thread;
|
||||||
void *user_thread;
|
void *user_thread;
|
||||||
struct kstack *user_kstack;
|
struct task *user_task;
|
||||||
} *vm;
|
} *vm;
|
||||||
|
|
||||||
void trapret();
|
void trapret();
|
||||||
@ -31,7 +37,8 @@ void swtch(void** oldstack, void* newstack);
|
|||||||
void run_elf(const char* name) {
|
void run_elf(const char* name) {
|
||||||
if (!vm) {
|
if (!vm) {
|
||||||
vm = kmalloc(sizeof(struct 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) {
|
if (read_file(name, (void*)USER_BASE, 100 << 20) <= 0) {
|
||||||
printk(name);
|
printk(name);
|
||||||
@ -40,7 +47,7 @@ void run_elf(const char* name) {
|
|||||||
}
|
}
|
||||||
Elf32_Ehdr *hdr = (void*)USER_BASE;
|
Elf32_Ehdr *hdr = (void*)USER_BASE;
|
||||||
|
|
||||||
struct kstack *u = vm->user_kstack;
|
struct kstack *u = &vm->user_task->stack;
|
||||||
memset(u, 0, sizeof(*u));
|
memset(u, 0, sizeof(*u));
|
||||||
u->context.eip = (uint32_t)trapret;
|
u->context.eip = (uint32_t)trapret;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user