working ring3 x86-64
This commit is contained in:
parent
531ed1c3ac
commit
f3faa14908
2
am/am.h
2
am/am.h
|
@ -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) =================
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 .
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue