From c761ab95591acbb530afc3bd90f2dba3e6070b41 Mon Sep 17 00:00:00 2001 From: Diego Ongaro Date: Thu, 2 Oct 2008 14:23:36 -0500 Subject: [PATCH] fkvm_vcpu_run(): really messy and largely copied from kvm --- sys/kern/kern_fkvm.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 180 insertions(+), 2 deletions(-) diff --git a/sys/kern/kern_fkvm.c b/sys/kern/kern_fkvm.c index 81b431e5e2c..6a94fa6a88d 100644 --- a/sys/kern/kern_fkvm.c +++ b/sys/kern/kern_fkvm.c @@ -39,11 +39,187 @@ #define IOPM_SIZE (8*1024 + 1) /* TODO: ensure that this need not be 12Kbtes, not just 8Kb+1 */ #define MSRPM_SIZE (8*1024) -static void *hsave_area = NULL; -static struct vmcb *vmcb = NULL; +/* fkvm data */ static void *iopm = NULL; /* Should I allocate a vm_object_t instead? */ static void * msrpm = NULL; /* Should I allocate a vm_object_t instead? */ +/* per-guest data */ + +/* VCPU data */ +static void *hsave_area = NULL; +static struct vmcb *vmcb = NULL; + +enum { + VCPU_REGS_RAX = 0, + VCPU_REGS_RCX = 1, + VCPU_REGS_RDX = 2, + VCPU_REGS_RBX = 3, + VCPU_REGS_RSP = 4, + VCPU_REGS_RBP = 5, + VCPU_REGS_RSI = 6, + VCPU_REGS_RDI = 7, + VCPU_REGS_R8 = 8, + VCPU_REGS_R9 = 9, + VCPU_REGS_R10 = 10, + VCPU_REGS_R11 = 11, + VCPU_REGS_R12 = 12, + VCPU_REGS_R13 = 13, + VCPU_REGS_R14 = 14, + VCPU_REGS_R15 = 15, + VCPU_REGS_RIP, + NR_VCPU_REGS +}; + +static struct vcpu { + unsigned long vmcb_pa; + unsigned long regs[NR_VCPU_REGS]; + u_int64_t host_gs_base; + u_int64_t cr2; + u_int64_t cr3; +} vcpu; + +#define SVM_VMLOAD ".byte 0x0f, 0x01, 0xda" +#define SVM_VMRUN ".byte 0x0f, 0x01, 0xd8" +#define SVM_VMSAVE ".byte 0x0f, 0x01, 0xdb" +#define SVM_CLGI ".byte 0x0f, 0x01, 0xdd" +#define SVM_STGI ".byte 0x0f, 0x01, 0xdc" +#define SVM_INVLPGA ".byte 0x0f, 0x01, 0xdf" + + +static void +fkvm_vcpu_run(struct vcpu *vcpu, struct vmcb *vmcb) +{ + u_short fs_selector; + u_short gs_selector; + u_short ldt_selector; + unsigned long host_cr2; + unsigned long host_dr6; + unsigned long host_dr7; + + vcpu->vmcb_pa = vtophys(vmcb); + + vmcb->save.rax = vcpu->regs[VCPU_REGS_RAX]; + vmcb->save.rsp = vcpu->regs[VCPU_REGS_RSP]; + vmcb->save.rip = vcpu->regs[VCPU_REGS_RIP]; + + /* meh: kvm has pre_svm_run(svm); */ + + vcpu->host_gs_base = rdmsr(MSR_GSBASE); + + fs_selector = rfs(); + gs_selector = rgs(); + ldt_selector = rldt(); + + host_cr2 = rcr2(); + + host_dr6 = rdr6(); + host_dr7 = rdr7(); + + vmcb->save.cr2 = vcpu->cr2; + /* meh: cr3? */ + + /* meh: dr7? db_regs? */ + + __asm __volatile (SVM_CLGI); + + enable_intr(); + +#define R "r" + __asm __volatile ( + "push %%"R"bp; \n\t" + "mov %c[rbx](%[svm]), %%"R"bx \n\t" + "mov %c[rcx](%[svm]), %%"R"cx \n\t" + "mov %c[rdx](%[svm]), %%"R"dx \n\t" + "mov %c[rsi](%[svm]), %%"R"si \n\t" + "mov %c[rdi](%[svm]), %%"R"di \n\t" + "mov %c[rbp](%[svm]), %%"R"bp \n\t" + "mov %c[r8](%[svm]), %%r8 \n\t" + "mov %c[r9](%[svm]), %%r9 \n\t" + "mov %c[r10](%[svm]), %%r10 \n\t" + "mov %c[r11](%[svm]), %%r11 \n\t" + "mov %c[r12](%[svm]), %%r12 \n\t" + "mov %c[r13](%[svm]), %%r13 \n\t" + "mov %c[r14](%[svm]), %%r14 \n\t" + "mov %c[r15](%[svm]), %%r15 \n\t" + + /* Enter guest mode */ + "push %%"R"ax \n\t" + "mov %c[vmcb](%[svm]), %%"R"ax \n\t" + SVM_VMLOAD "\n\t" + SVM_VMRUN "\n\t" + SVM_VMSAVE "\n\t" + "pop %%"R"ax \n\t" + + /* Save guest registers, load host registers */ + "mov %%"R"bx, %c[rbx](%[svm]) \n\t" + "mov %%"R"cx, %c[rcx](%[svm]) \n\t" + "mov %%"R"dx, %c[rdx](%[svm]) \n\t" + "mov %%"R"si, %c[rsi](%[svm]) \n\t" + "mov %%"R"di, %c[rdi](%[svm]) \n\t" + "mov %%"R"bp, %c[rbp](%[svm]) \n\t" + "mov %%r8, %c[r8](%[svm]) \n\t" + "mov %%r9, %c[r9](%[svm]) \n\t" + "mov %%r10, %c[r10](%[svm]) \n\t" + "mov %%r11, %c[r11](%[svm]) \n\t" + "mov %%r12, %c[r12](%[svm]) \n\t" + "mov %%r13, %c[r13](%[svm]) \n\t" + "mov %%r14, %c[r14](%[svm]) \n\t" + "mov %%r15, %c[r15](%[svm]) \n\t" + "pop %%"R"bp" + : + : [svm]"a"(vcpu), + [vmcb]"i"(offsetof(struct vcpu, vmcb_pa)), + [rbx]"i"(offsetof(struct vcpu, regs[VCPU_REGS_RBX])), + [rcx]"i"(offsetof(struct vcpu, regs[VCPU_REGS_RCX])), + [rdx]"i"(offsetof(struct vcpu, regs[VCPU_REGS_RDX])), + [rsi]"i"(offsetof(struct vcpu, regs[VCPU_REGS_RSI])), + [rdi]"i"(offsetof(struct vcpu, regs[VCPU_REGS_RDI])), + [rbp]"i"(offsetof(struct vcpu, regs[VCPU_REGS_RBP])), + [r8 ]"i"(offsetof(struct vcpu, regs[VCPU_REGS_R8 ])), + [r9 ]"i"(offsetof(struct vcpu, regs[VCPU_REGS_R9 ])), + [r10]"i"(offsetof(struct vcpu, regs[VCPU_REGS_R10])), + [r11]"i"(offsetof(struct vcpu, regs[VCPU_REGS_R11])), + [r12]"i"(offsetof(struct vcpu, regs[VCPU_REGS_R12])), + [r13]"i"(offsetof(struct vcpu, regs[VCPU_REGS_R13])), + [r14]"i"(offsetof(struct vcpu, regs[VCPU_REGS_R14])), + [r15]"i"(offsetof(struct vcpu, regs[VCPU_REGS_R15])) + : "cc", "memory", + R"bx", R"cx", R"dx", R"si", R"di", + "r8", "r9", "r10", "r11" , "r12", "r13", "r14", "r15" + ); + + + /* meh: dr7? db_regs? */ + + vcpu->cr2 = vmcb->save.cr2; + + vcpu->regs[VCPU_REGS_RAX] = vmcb->save.rax; + vcpu->regs[VCPU_REGS_RSP] = vmcb->save.rsp; + vcpu->regs[VCPU_REGS_RIP] = vmcb->save.rip; + + load_dr6(host_dr6); + load_dr7(host_dr7); + + load_cr2(host_cr2); + + load_fs(fs_selector); + load_gs(gs_selector); + lldt(ldt_selector); + + wrmsr(MSR_GSBASE, vcpu->host_gs_base); + + /* TODO + tss_desc->type = 9; + ltr(GSEL(GPROC0_SEL, SEL_KPL)); + */ + + disable_intr(); + + __asm __volatile (SVM_STGI); + + /* meh: next_rip */ +} + static void _fkvm_init_seg(struct vmcb_seg *seg, uint16_t attrib) { @@ -160,6 +336,8 @@ fkvm_vmcb_init(struct vmcb *vmcb) save->dr7 = 0x400; //save->rflags = 2; /* It seems like bit 1 is reserved. This line makes no sense. */ save->rip = 0x0000fff0; + + fkvm_vcpu_run(&vcpu, vmcb); } static void -- 2.11.4.GIT