working ring3 x86-64

This commit is contained in:
Yanyan Jiang 2020-01-30 15:29:29 +00:00
parent 531ed1c3ac
commit f3faa14908
9 changed files with 75 additions and 50 deletions

View File

@ -82,7 +82,7 @@ int _vme_init(void *(*pgalloc)(size_t size), void (*pgfree)(void *));
int _protect(_AddressSpace *as);
void _unprotect(_AddressSpace *as);
int _map(_AddressSpace *as, void *va, void *pa, int prot);
_Context *_ucontext(_AddressSpace *as, _Area kstack, void *entry, void *args);
_Context *_ucontext(_AddressSpace *as, _Area ustack, _Area kstack, void *entry, void *args);
// ================= Multi-Processor Extension (MPE) =================

View File

@ -186,7 +186,7 @@ typedef struct TSS32 {
uint32_t link; // Unused
uint32_t esp0; // Stack pointers and segment selectors
uint32_t ss0; // after an increase in privilege level
char padding[88];
uint32_t padding[23];
} __attribute__((packed)) TSS32;
typedef struct TSS64 {
@ -281,14 +281,14 @@ static inline uint32_t get_efl() {
return efl;
}
static inline uint32_t get_cr0(void) {
volatile uint32_t val;
asm volatile ("movl %%cr0, %0" : "=r"(val));
static inline uintptr_t get_cr0(void) {
volatile uintptr_t val;
asm volatile ("mov %%cr0, %0" : "=r"(val));
return val;
}
static inline void set_cr0(uint32_t cr0) {
asm volatile ("movl %0, %%cr0" : : "r"(cr0));
static inline void set_cr0(uintptr_t cr0) {
asm volatile ("mov %0, %%cr0" : : "r"(cr0));
}
@ -323,7 +323,7 @@ static inline uintptr_t get_cr2() {
}
static inline void set_cr3(void *pdir) {
asm volatile ("movl %0, %%cr3" : : "r"(pdir));
asm volatile ("mov %0, %%cr3" : : "r"(pdir));
}
static inline volatile struct boot_record *boot_record() {

View File

@ -14,10 +14,10 @@ static void __am_irq_handle_internal(struct trap_frame *tf) {
.msg = "(no message)",
};
printf("[%d/%d] ", tf->irq, _cpu());
// printf("[%d/%d] ", tf->irq, _cpu());
#define dump(ctx, name) printf("%s = %08x (%d) %p\n", #name, (ctx).name, (ctx).name, (ctx).name);
#define dump(name) printf("%s = %08x (%d)\n", #name, saved_ctx.name, saved_ctx.name);
#define offset(name) printf("%s @ %d\n", #name, (char *)&tf.name - (char*)tf);
#if __x86_64
saved_ctx = tf->saved_context;
saved_ctx.rip = tf->rip;
@ -26,11 +26,12 @@ static void __am_irq_handle_internal(struct trap_frame *tf) {
saved_ctx.rsp = tf->rsp;
saved_ctx.ss = tf->ss;
/*
dump(rax); dump(rbx); dump(rcx); dump(rdx); dump(rbp); dump(rsp); dump(rsi); dump(rdi);
dump(r8); dump(r9); dump(r10); dump(r11); dump(r12); dump(r13); dump(r14); dump(r15);
dump(cs); dump(ss); dump(rip); dump(rflags);
*/
#define DUMP(ctx) \
dump((ctx),rax); dump((ctx),rbx); dump((ctx),rcx); dump((ctx),rdx); dump((ctx),rbp); dump((ctx),rsi); dump((ctx),rdi); \
dump((ctx),r8); dump((ctx),r9); dump((ctx),r10); dump((ctx),r11); dump((ctx),r12); dump((ctx),r13); dump((ctx),r14); dump((ctx),r15); \
dump((ctx),cs); dump((ctx),ss); dump((ctx),rip); dump((ctx),rflags); \
dump((ctx),rsp); dump((ctx),rsp0); dump((ctx),uvm);
#else
saved_ctx = tf->saved_context;
saved_ctx.eip = tf->eip;
@ -41,11 +42,11 @@ static void __am_irq_handle_internal(struct trap_frame *tf) {
saved_ctx.esp = (uint32_t)(tf + 1) - 8; // no ss/esp saved
}
/*
dump(eax); dump(ebx); dump(ecx); dump(edx);
dump(ebp); dump(esp); dump(esi); dump(edi);
dump(cs); dump(ds); dump(eip); dump(eflags);
*/
#define DUMP(ctx) \
dump((ctx),eax); dump((ctx),ebx); dump((ctx),ecx); dump((ctx),edx); \
dump((ctx),ebp); dump((ctx),esi); dump((ctx),edi); \
dump((ctx),cs); dump((ctx),ds); dump((ctx),eip); dump((ctx),eflags); \
dump((ctx),esp); dump((ctx),esp0); dump((ctx),uvm);
#endif
#define IRQ T_IRQ0 +
@ -97,7 +98,16 @@ static void __am_irq_handle_internal(struct trap_frame *tf) {
}
_Context *ret_ctx = user_handler(ev, &saved_ctx);
printf("return to %x\n", ret_ctx->cs);
if (ret_ctx->uvm) {
bug_on(ret_ctx->cs != USEL(SEG_UCODE));
set_cr3(ret_ctx->uvm);
#if __x86_64__
__am_thiscpu_setstk0(0, ret_ctx->rsp0);
#else
__am_thiscpu_setstk0(ret_ctx->ds, ret_ctx->esp0);
#endif
}
__am_iret(ret_ctx ? ret_ctx : &saved_ctx);
}

View File

@ -313,7 +313,7 @@ size_t _io_write(uint32_t dev, uintptr_t reg, void *buf, size_t size) {
}
int _ioe_init() {
if (_cpu() != 0) panic("init IOE in non-bootstrap CPU");
panic_on(_cpu() != 0, "init IOE in non-bootstrap CPU");
__am_timer_init();
__am_vga_init();
return 0;

View File

@ -2,7 +2,7 @@
trap:
cli
subq $56, %rsp
subq $48, %rsp
pushq %r15
pushq %r14
pushq %r13
@ -26,6 +26,9 @@ trap:
.globl __am_iret
__am_iret:
movq %rdi, %rsp
movq 160(%rsp), %rax
movw %ax, %ds
movw %ax, %es
addq $8, %rsp
popq %rax
popq %rbx

View File

@ -38,7 +38,7 @@ struct vm_area {
static const struct vm_area vm_areas[] = {
#ifdef __x86_64__
{ RANGE(0x800000000000, 0x808000000000), 0 }, // 512 GiB user space
{ RANGE(0x100000000000, 0x108000000000), 0 }, // 512 GiB user space
{ RANGE(0x000000000000, 0x008000000000), 1 }, // 512 GiB kernel
#else
{ RANGE( 0x40000000, 0x80000000), 0 }, // 1 GiB user space
@ -104,6 +104,7 @@ static void teardown(int level, uintptr_t *pt) {
}
int _vme_init(void *(*f1)(size_t size), void (*f2)(void *)) {
panic_on(_cpu() != 0, "init VME in non-bootstrap CPU");
pgalloc = f1;
pgfree = f2;
@ -123,18 +124,15 @@ int _vme_init(void *(*f1)(size_t size), void (*f2)(void *)) {
}
}
kpt = (void *)baseof((uintptr_t)as.ptr);
#endif
set_cr3(kpt);
set_cr0(get_cr0() | CR0_PG);
#endif
return 0;
}
int _protect(_AddressSpace *as) {
*as = (_AddressSpace) {
.pgsize = mmu.pgsize,
.area = uvm_area,
.ptr = zalloc(mmu.pgsize),
};
uintptr_t *upt = zalloc(mmu.pgsize);
for (int i = 0; i < LENGTH(vm_areas); i++) {
const struct vm_area *vma = &vm_areas[i];
@ -144,10 +142,19 @@ int _protect(_AddressSpace *as) {
cur != (uintptr_t)vma->area.end;
cur += (1L << info->shift)) {
int index = indexof(cur, info);
((uintptr_t *)as->ptr)[index] = kpt[index];
upt[index] = kpt[index];
}
}
}
*as = (_AddressSpace) {
.pgsize = mmu.pgsize,
.area = uvm_area,
.ptr = (void *)((uintptr_t)upt | PTE_P),
};
set_cr3(as->ptr);
return 0;
}
@ -161,7 +168,9 @@ int _map(_AddressSpace *as, void *va, void *pa, int prot) {
panic_on((uintptr_t)va != ROUNDDOWN(va, mmu.pgsize) ||
(uintptr_t)pa != ROUNDDOWN(pa, mmu.pgsize), "non-page-boundary address");
printf("map %p -> %p, %d\n", va, pa, prot);
uintptr_t *ptentry = ptwalk(as, (uintptr_t)va, PTE_W | PTE_U);
printf("ptentry: %p\n", ptentry);
if (prot & _PROT_NONE) {
panic_on(!(*ptentry & PTE_P), "unmapping an non-mapped page");
*ptentry = 0;
@ -170,10 +179,11 @@ int _map(_AddressSpace *as, void *va, void *pa, int prot) {
uintptr_t pte = (uintptr_t)pa | PTE_P | PTE_U | ((prot & _PROT_WRITE) ? PTE_W : 0);
*ptentry = pte;
}
ptwalk(as, (uintptr_t)va, PTE_W | PTE_U);
return 0;
}
_Context *_ucontext(_AddressSpace *as, _Area kstack, void *entry, void *args) {
_Context *_ucontext(_AddressSpace *as, _Area ustack, _Area kstack, void *entry, void *args) {
_Area stk_aligned = {
(void *)ROUNDUP(kstack.start, 16),
(void *)ROUNDDOWN(kstack.end, 16),
@ -184,7 +194,9 @@ _Context *_ucontext(_AddressSpace *as, _Area kstack, void *entry, void *args) {
*ctx = (_Context) { 0 };
#if __x86_64__
ctx->cs = KSEL(SEG_KCODE);
ctx->cs = USEL(SEG_UCODE);
ctx->ss = USEL(SEG_UDATA);
ctx->rsp = ROUNDDOWN(ustack.end, 16);
ctx->rip = (uintptr_t)entry;
ctx->rsp0 = stk_top;
#else
@ -192,8 +204,10 @@ _Context *_ucontext(_AddressSpace *as, _Area kstack, void *entry, void *args) {
ctx->ds = ctx->ss3 = USEL(SEG_UDATA);
ctx->eip = (uint32_t)entry;
ctx->esp0 = stk_top;
ctx->esp = ROUNDDOWN(ustack.end, 16);
#endif
ctx->GPRx = (uintptr_t)args;
ctx->uvm = as;
ctx->uvm = as->ptr;
printf("uvm (cr3) = %p\n", ctx->uvm);
return ctx;
}

View File

@ -16,7 +16,6 @@ void __am_percpu_init() {
__am_percpu_initgdt();
__am_percpu_initlapic();
__am_percpu_initirq();
// __am_percpu_initpg();
}
_Area __am_heap_init() {
@ -61,7 +60,7 @@ void __am_percpu_initgdt() {
gdt[SEG_KDATA] = 0x0000920000000000LL;
gdt[SEG_UCODE] = 0x0020F80000000000LL;
gdt[SEG_UDATA] = 0x0000F20000000000LL;
gdt[SEG_TSS+0] = (0x0067) | ((tss & 0xffffff) << 16) |
gdt[SEG_TSS+0] = (sizeof(CPU->tss) - 1) | ((tss & 0xffffff) << 16) |
(0x00e9LL << 40) | (((tss >> 24) & 0xff) << 56);
gdt[SEG_TSS+1] = (tss >> 32);
set_gdt(gdt, sizeof(SegDesc64) * (NR_SEG + 1));
@ -79,12 +78,14 @@ void __am_percpu_initgdt() {
#endif
}
/*
void __am_thiscpu_setstk0(uintptr_t ss0, uintptr_t esp0) {
CPU->tss.ss0 = ss0;
CPU->tss.esp0 = esp0;
void __am_thiscpu_setstk0(uintptr_t ss, uintptr_t sp) {
#if __x86_64__
CPU->tss.rsp0 = sp;
#else
CPU->tss.ss0 = ss;
CPU->tss.esp0 = sp;
#endif
}
*/
void __am_stop_the_world() {
boot_record()->jmp_code = 0x0000feeb; // (16-bit) jmp .

View File

@ -45,9 +45,6 @@ struct trap_frame {
};
#endif
extern volatile uint32_t *__am_lapic;
extern int __am_ncpu;
extern struct cpu_local __am_cpuinfo[MAX_CPU];
@ -100,8 +97,7 @@ void __am_othercpu_entry();
void __am_percpu_initirq();
void __am_percpu_initgdt();
void __am_percpu_initlapic();
void __am_percpu_initpg();
void __am_thiscpu_setstk0(uintptr_t ss0, uintptr_t esp0);
void __am_thiscpu_setstk0(uintptr_t ss, uintptr_t sp);
void __am_stop_the_world();

View File

@ -31,7 +31,7 @@ _Context* vm_handler(_Event ev, _Context *ctx) {
(ev.cause & _PROT_WRITE) ? "[write fail]" : "");
break;
case _EVENT_SYSCALL:
printf("%d ", ctx->GPR1);
// printf("%d ", ctx->GPRx);
break;
default:
assert(0);
@ -69,11 +69,12 @@ void vm_test() {
_map(&prot, ptr, up1, _PROT_WRITE);
memcpy(up1, code, sizeof(code));
printf("Code copied to %x execute\n", ptr);
printf("Code copied to %p (physical %p) execute\n", ptr, up1);
static uint8_t kstk[4096];
_Area k = { .start = kstk, .end = kstk + 4096 };
uctx = _ucontext(&prot, k, ptr, 0);
_Area u = { .start = 0, .end = 0 };
uctx = _ucontext(&prot, u, k, ptr, 0);
_intr_write(1);
while (1) {