diff --git a/hypervisor/arch/x86/cpu.c b/hypervisor/arch/x86/cpu.c index 0eca62f72..59f6d3464 100644 --- a/hypervisor/arch/x86/cpu.c +++ b/hypervisor/arch/x86/cpu.c @@ -431,6 +431,18 @@ void bsp_boot_init(void) ASSERT(offsetof(struct run_context, ia32_spec_ctrl) == CPU_CONTEXT_OFFSET_IA32_SPEC_CTRL, "run_context ia32_spec_ctrl offset not match"); + ASSERT(offsetof(struct run_context, rflags) == + CPU_CONTEXT_OFFSET_RFLAGS, + "run_context rflags offset not match"); + ASSERT(offsetof(struct ext_context, cr3) == + CPU_CONTEXT_OFFSET_CR3 - CPU_CONTEXT_OFFSET_EXTCTX_START, + "ext_context cr3 offset not match"); + ASSERT(offsetof(struct ext_context, idtr) == + CPU_CONTEXT_OFFSET_IDTR - CPU_CONTEXT_OFFSET_EXTCTX_START, + "ext_context idtr offset not match"); + ASSERT(offsetof(struct ext_context, ldtr) == + CPU_CONTEXT_OFFSET_LDTR - CPU_CONTEXT_OFFSET_EXTCTX_START, + "ext_context ldtr offset not match"); bitmap_set_nolock(BOOT_CPU_ID, &pcpu_active_bitmap); diff --git a/hypervisor/arch/x86/guest/vcpu.c b/hypervisor/arch/x86/guest/vcpu.c index bea38ecec..4cce59582 100644 --- a/hypervisor/arch/x86/guest/vcpu.c +++ b/hypervisor/arch/x86/guest/vcpu.c @@ -16,94 +16,103 @@ vm_sw_loader_t vm_sw_loader; inline uint64_t vcpu_get_gpreg(struct vcpu *vcpu, uint32_t reg) { - struct run_context *cur_context = - &vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context]; + struct run_context *ctx = + &vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].run_ctx; - return cur_context->guest_cpu_regs.longs[reg]; + return ctx->guest_cpu_regs.longs[reg]; } inline void vcpu_set_gpreg(struct vcpu *vcpu, uint32_t reg, uint64_t val) { - struct run_context *cur_context = - &vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context]; + struct run_context *ctx = + &vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].run_ctx; - cur_context->guest_cpu_regs.longs[reg] = val; + ctx->guest_cpu_regs.longs[reg] = val; } inline uint64_t vcpu_get_rip(struct vcpu *vcpu) { + struct run_context *ctx = + &vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].run_ctx; + if (bitmap_test(CPU_REG_RIP, &vcpu->reg_updated) == 0 && bitmap_test_and_set_lock(CPU_REG_RIP, &vcpu->reg_cached) == 0) - vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].rip = - exec_vmread(VMX_GUEST_RIP); - return vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].rip; + ctx->rip = exec_vmread(VMX_GUEST_RIP); + return ctx->rip; } inline void vcpu_set_rip(struct vcpu *vcpu, uint64_t val) { - vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].rip = val; + vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].run_ctx.rip = val; bitmap_set_lock(CPU_REG_RIP, &vcpu->reg_updated); } inline uint64_t vcpu_get_rsp(struct vcpu *vcpu) { - struct run_context *cur_context = - &vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context]; + struct run_context *ctx = + &vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].run_ctx; - return cur_context->guest_cpu_regs.regs.rsp; + return ctx->guest_cpu_regs.regs.rsp; } inline void vcpu_set_rsp(struct vcpu *vcpu, uint64_t val) { - struct run_context *cur_context = - &vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context]; + struct run_context *ctx = + &vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].run_ctx; - cur_context->guest_cpu_regs.regs.rsp = val; + ctx->guest_cpu_regs.regs.rsp = val; bitmap_set_lock(CPU_REG_RSP, &vcpu->reg_updated); } inline uint64_t vcpu_get_efer(struct vcpu *vcpu) { + struct run_context *ctx = + &vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].run_ctx; + if (bitmap_test(CPU_REG_EFER, &vcpu->reg_updated) == 0 && bitmap_test_and_set_lock(CPU_REG_EFER, &vcpu->reg_cached) == 0) - vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].ia32_efer - = exec_vmread64(VMX_GUEST_IA32_EFER_FULL); - return vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].ia32_efer; + ctx->ia32_efer = exec_vmread64(VMX_GUEST_IA32_EFER_FULL); + return ctx->ia32_efer; } inline void vcpu_set_efer(struct vcpu *vcpu, uint64_t val) { - vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].ia32_efer = val; + vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].run_ctx.ia32_efer + = val; bitmap_set_lock(CPU_REG_EFER, &vcpu->reg_updated); } inline uint64_t vcpu_get_rflags(struct vcpu *vcpu) { + struct run_context *ctx = + &vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].run_ctx; + if (bitmap_test(CPU_REG_RFLAGS, &vcpu->reg_updated) == 0 && bitmap_test_and_set_lock(CPU_REG_RFLAGS, &vcpu->reg_cached) == 0 && vcpu->launched) - vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].rflags = - exec_vmread(VMX_GUEST_RFLAGS); - return vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].rflags; + ctx->rflags = exec_vmread(VMX_GUEST_RFLAGS); + return ctx->rflags; } inline void vcpu_set_rflags(struct vcpu *vcpu, uint64_t val) { - vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].rflags = val; + vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].run_ctx.rflags = + val; bitmap_set_lock(CPU_REG_RFLAGS, &vcpu->reg_updated); } inline uint64_t vcpu_get_cr0(struct vcpu *vcpu) { uint64_t mask; + struct run_context *ctx = + &vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].run_ctx; if (bitmap_test_and_set_lock(CPU_REG_CR0, &vcpu->reg_cached) == 0) { mask = exec_vmread(VMX_CR0_MASK); - vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr0 = - (exec_vmread(VMX_CR0_READ_SHADOW) & mask) | + ctx->cr0 = (exec_vmread(VMX_CR0_READ_SHADOW) & mask) | (exec_vmread(VMX_GUEST_CR0) & (~mask)); } - return vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr0; + return ctx->cr0; } inline int vcpu_set_cr0(struct vcpu *vcpu, uint64_t val) @@ -113,25 +122,27 @@ inline int vcpu_set_cr0(struct vcpu *vcpu, uint64_t val) inline uint64_t vcpu_get_cr2(struct vcpu *vcpu) { - return vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr2; + return vcpu-> + arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].run_ctx.cr2; } inline void vcpu_set_cr2(struct vcpu *vcpu, uint64_t val) { - vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr2 = val; + vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].run_ctx.cr2 = val; } inline uint64_t vcpu_get_cr4(struct vcpu *vcpu) { uint64_t mask; + struct run_context *ctx = + &vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].run_ctx; if (bitmap_test_and_set_lock(CPU_REG_CR4, &vcpu->reg_cached) == 0) { mask = exec_vmread(VMX_CR4_MASK); - vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr4 = - (exec_vmread(VMX_CR4_READ_SHADOW) & mask) | + ctx->cr4 = (exec_vmread(VMX_CR4_READ_SHADOW) & mask) | (exec_vmread(VMX_GUEST_CR4) & (~mask)); } - return vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr4; + return ctx->cr4; } inline int vcpu_set_cr4(struct vcpu *vcpu, uint64_t val) @@ -141,12 +152,14 @@ inline int vcpu_set_cr4(struct vcpu *vcpu, uint64_t val) inline uint64_t vcpu_get_pat_ext(struct vcpu *vcpu) { - return vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].ia32_pat; + return vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context]. + ext_ctx.ia32_pat; } inline void vcpu_set_pat_ext(struct vcpu *vcpu, uint64_t val) { - vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].ia32_pat = val; + vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].ext_ctx.ia32_pat + = val; } struct vcpu *get_ever_run_vcpu(uint16_t pcpu_id) @@ -279,22 +292,20 @@ int start_vcpu(struct vcpu *vcpu) { uint32_t instlen; uint64_t rip; - struct run_context *cur_context = - &vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context]; + struct run_context *ctx = + &vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].run_ctx; int64_t status = 0; ASSERT(vcpu != NULL, "Incorrect arguments"); if (bitmap_test_and_clear_lock(CPU_REG_RIP, &vcpu->reg_updated)) - exec_vmwrite(VMX_GUEST_RIP, cur_context->rip); + exec_vmwrite(VMX_GUEST_RIP, ctx->rip); if (bitmap_test_and_clear_lock(CPU_REG_RSP, &vcpu->reg_updated)) - exec_vmwrite(VMX_GUEST_RSP, - cur_context->guest_cpu_regs.regs.rsp); + exec_vmwrite(VMX_GUEST_RSP, ctx->guest_cpu_regs.regs.rsp); if (bitmap_test_and_clear_lock(CPU_REG_EFER, &vcpu->reg_updated)) - exec_vmwrite64(VMX_GUEST_IA32_EFER_FULL, - cur_context->ia32_efer); + exec_vmwrite64(VMX_GUEST_IA32_EFER_FULL, ctx->ia32_efer); if (bitmap_test_and_clear_lock(CPU_REG_RFLAGS, &vcpu->reg_updated)) - exec_vmwrite(VMX_GUEST_RFLAGS, cur_context->rflags); + exec_vmwrite(VMX_GUEST_RFLAGS, ctx->rflags); /* If this VCPU is not already launched, launch it */ if (!vcpu->launched) { @@ -322,7 +333,7 @@ int start_vcpu(struct vcpu *vcpu) msr_write(MSR_IA32_PRED_CMD, PRED_SET_IBPB); /* Launch the VM */ - status = vmx_vmrun(cur_context, VM_LAUNCH, ibrs_type); + status = vmx_vmrun(ctx, VM_LAUNCH, ibrs_type); /* See if VM launched successfully */ if (status == 0) { @@ -341,7 +352,7 @@ int start_vcpu(struct vcpu *vcpu) 0xFFFFFFFFFFFFFFFFUL)); /* Resume the VM */ - status = vmx_vmrun(cur_context, VM_RESUME, ibrs_type); + status = vmx_vmrun(ctx, VM_RESUME, ibrs_type); } vcpu->reg_cached = 0UL; @@ -351,7 +362,7 @@ int start_vcpu(struct vcpu *vcpu) /* Obtain current VCPU instruction length */ vcpu->arch_vcpu.inst_len = exec_vmread32(VMX_EXIT_INSTR_LEN); - cur_context->guest_cpu_regs.regs.rsp = exec_vmread(VMX_GUEST_RSP); + ctx->guest_cpu_regs.regs.rsp = exec_vmread(VMX_GUEST_RSP); /* Obtain VM exit reason */ vcpu->arch_vcpu.exit_reason = exec_vmread32(VMX_EXIT_REASON); diff --git a/hypervisor/arch/x86/trusty.c b/hypervisor/arch/x86/trusty.c index 235d4519f..568aa82cb 100644 --- a/hypervisor/arch/x86/trusty.c +++ b/hypervisor/arch/x86/trusty.c @@ -206,98 +206,105 @@ void destroy_secure_world(struct vm *vm) } #endif -static void save_world_ctx(struct run_context *context) +static void save_world_ctx(struct vcpu *vcpu, struct ext_context *ext_ctx) { + /* cache on-demand run_context for efer/rflags/rsp/rip */ + vcpu_get_efer(vcpu); + vcpu_get_rflags(vcpu); + vcpu_get_rsp(vcpu); + vcpu_get_rip(vcpu); + /* VMCS GUEST field */ - /* TSC_OFFSET, CR3, RIP, RSP, RFLAGS already saved on VMEXIT */ - context->cr0 = exec_vmread(VMX_CR0_READ_SHADOW); - context->cr4 = exec_vmread(VMX_CR4_READ_SHADOW); - context->vmx_cr0 = exec_vmread(VMX_GUEST_CR0); - context->vmx_cr4 = exec_vmread(VMX_GUEST_CR4); - context->dr7 = exec_vmread(VMX_GUEST_DR7); - context->ia32_debugctl = exec_vmread64(VMX_GUEST_IA32_DEBUGCTL_FULL); + ext_ctx->vmx_cr0 = exec_vmread(VMX_GUEST_CR0); + ext_ctx->vmx_cr4 = exec_vmread(VMX_GUEST_CR4); + ext_ctx->vmx_cr0_read_shadow = exec_vmread(VMX_CR0_READ_SHADOW); + ext_ctx->vmx_cr4_read_shadow = exec_vmread(VMX_CR4_READ_SHADOW); + ext_ctx->cr3 = exec_vmread(VMX_GUEST_CR3); + ext_ctx->dr7 = exec_vmread(VMX_GUEST_DR7); + ext_ctx->ia32_debugctl = exec_vmread64(VMX_GUEST_IA32_DEBUGCTL_FULL); /* * Similar to CR0 and CR4, the actual value of guest's IA32_PAT MSR - * (represented by context->vmx_ia32_pat) could be different from the - * value that guest reads (represented by context->ia32_pat). + * (represented by ext_ctx->vmx_ia32_pat) could be different from the + * value that guest reads (represented by ext_ctx->ia32_pat). * * the wrmsr handler keeps track of 'ia32_pat', and we only * need to load 'vmx_ia32_pat' here. */ - context->vmx_ia32_pat = exec_vmread64(VMX_GUEST_IA32_PAT_FULL); - context->ia32_efer = exec_vmread64(VMX_GUEST_IA32_EFER_FULL); - context->ia32_sysenter_esp = exec_vmread(VMX_GUEST_IA32_SYSENTER_ESP); - context->ia32_sysenter_eip = exec_vmread(VMX_GUEST_IA32_SYSENTER_EIP); - context->ia32_sysenter_cs = exec_vmread32(VMX_GUEST_IA32_SYSENTER_CS); - save_segment(context->cs, VMX_GUEST_CS); - save_segment(context->ss, VMX_GUEST_SS); - save_segment(context->ds, VMX_GUEST_DS); - save_segment(context->es, VMX_GUEST_ES); - save_segment(context->fs, VMX_GUEST_FS); - save_segment(context->gs, VMX_GUEST_GS); - save_segment(context->tr, VMX_GUEST_TR); - save_segment(context->ldtr, VMX_GUEST_LDTR); + ext_ctx->vmx_ia32_pat = exec_vmread64(VMX_GUEST_IA32_PAT_FULL); + ext_ctx->ia32_sysenter_esp = exec_vmread(VMX_GUEST_IA32_SYSENTER_ESP); + ext_ctx->ia32_sysenter_eip = exec_vmread(VMX_GUEST_IA32_SYSENTER_EIP); + ext_ctx->ia32_sysenter_cs = exec_vmread32(VMX_GUEST_IA32_SYSENTER_CS); + save_segment(ext_ctx->cs, VMX_GUEST_CS); + save_segment(ext_ctx->ss, VMX_GUEST_SS); + save_segment(ext_ctx->ds, VMX_GUEST_DS); + save_segment(ext_ctx->es, VMX_GUEST_ES); + save_segment(ext_ctx->fs, VMX_GUEST_FS); + save_segment(ext_ctx->gs, VMX_GUEST_GS); + save_segment(ext_ctx->tr, VMX_GUEST_TR); + save_segment(ext_ctx->ldtr, VMX_GUEST_LDTR); /* Only base and limit for IDTR and GDTR */ - context->idtr.base = exec_vmread(VMX_GUEST_IDTR_BASE); - context->gdtr.base = exec_vmread(VMX_GUEST_GDTR_BASE); - context->idtr.limit = exec_vmread32(VMX_GUEST_IDTR_LIMIT); - context->gdtr.limit = exec_vmread32(VMX_GUEST_GDTR_LIMIT); + ext_ctx->idtr.base = exec_vmread(VMX_GUEST_IDTR_BASE); + ext_ctx->gdtr.base = exec_vmread(VMX_GUEST_GDTR_BASE); + ext_ctx->idtr.limit = exec_vmread32(VMX_GUEST_IDTR_LIMIT); + ext_ctx->gdtr.limit = exec_vmread32(VMX_GUEST_GDTR_LIMIT); /* MSRs which not in the VMCS */ - context->ia32_star = msr_read(MSR_IA32_STAR); - context->ia32_lstar = msr_read(MSR_IA32_LSTAR); - context->ia32_fmask = msr_read(MSR_IA32_FMASK); - context->ia32_kernel_gs_base = msr_read(MSR_IA32_KERNEL_GS_BASE); + ext_ctx->ia32_star = msr_read(MSR_IA32_STAR); + ext_ctx->ia32_lstar = msr_read(MSR_IA32_LSTAR); + ext_ctx->ia32_fmask = msr_read(MSR_IA32_FMASK); + ext_ctx->ia32_kernel_gs_base = msr_read(MSR_IA32_KERNEL_GS_BASE); /* FX area */ asm volatile("fxsave (%0)" - : : "r" (context->fxstore_guest_area) : "memory"); + : : "r" (ext_ctx->fxstore_guest_area) : "memory"); } -static void load_world_ctx(struct run_context *context) +static void load_world_ctx(struct vcpu *vcpu, struct ext_context *ext_ctx) { + /* mark to update on-demand run_context for efer/rflags/rsp */ + bitmap_set_lock(CPU_REG_EFER, &vcpu->reg_updated); + bitmap_set_lock(CPU_REG_RFLAGS, &vcpu->reg_updated); + bitmap_set_lock(CPU_REG_RSP, &vcpu->reg_updated); + bitmap_set_lock(CPU_REG_RIP, &vcpu->reg_updated); + /* VMCS Execution field */ - exec_vmwrite64(VMX_TSC_OFFSET_FULL, context->tsc_offset); + exec_vmwrite64(VMX_TSC_OFFSET_FULL, ext_ctx->tsc_offset); /* VMCS GUEST field */ - exec_vmwrite(VMX_CR0_READ_SHADOW, context->cr0); - exec_vmwrite(VMX_GUEST_CR3, context->cr3); - exec_vmwrite(VMX_CR4_READ_SHADOW, context->cr4); - exec_vmwrite(VMX_GUEST_CR0, context->vmx_cr0); - exec_vmwrite(VMX_GUEST_CR4, context->vmx_cr4); - exec_vmwrite(VMX_GUEST_RIP, context->rip); - exec_vmwrite(VMX_GUEST_RSP, context->guest_cpu_regs.regs.rsp); - exec_vmwrite(VMX_GUEST_RFLAGS, context->rflags); - exec_vmwrite(VMX_GUEST_DR7, context->dr7); - exec_vmwrite64(VMX_GUEST_IA32_DEBUGCTL_FULL, context->ia32_debugctl); - exec_vmwrite64(VMX_GUEST_IA32_PAT_FULL, context->vmx_ia32_pat); - exec_vmwrite64(VMX_GUEST_IA32_EFER_FULL, context->ia32_efer); - exec_vmwrite32(VMX_GUEST_IA32_SYSENTER_CS, context->ia32_sysenter_cs); - exec_vmwrite(VMX_GUEST_IA32_SYSENTER_ESP, context->ia32_sysenter_esp); - exec_vmwrite(VMX_GUEST_IA32_SYSENTER_EIP, context->ia32_sysenter_eip); - load_segment(context->cs, VMX_GUEST_CS); - load_segment(context->ss, VMX_GUEST_SS); - load_segment(context->ds, VMX_GUEST_DS); - load_segment(context->es, VMX_GUEST_ES); - load_segment(context->fs, VMX_GUEST_FS); - load_segment(context->gs, VMX_GUEST_GS); - load_segment(context->tr, VMX_GUEST_TR); - load_segment(context->ldtr, VMX_GUEST_LDTR); + exec_vmwrite(VMX_GUEST_CR0, ext_ctx->vmx_cr0); + exec_vmwrite(VMX_GUEST_CR4, ext_ctx->vmx_cr4); + exec_vmwrite(VMX_CR0_READ_SHADOW, ext_ctx->vmx_cr0_read_shadow); + exec_vmwrite(VMX_CR4_READ_SHADOW, ext_ctx->vmx_cr4_read_shadow); + exec_vmwrite(VMX_GUEST_CR3, ext_ctx->cr3); + exec_vmwrite(VMX_GUEST_DR7, ext_ctx->dr7); + exec_vmwrite64(VMX_GUEST_IA32_DEBUGCTL_FULL, ext_ctx->ia32_debugctl); + exec_vmwrite64(VMX_GUEST_IA32_PAT_FULL, ext_ctx->vmx_ia32_pat); + exec_vmwrite32(VMX_GUEST_IA32_SYSENTER_CS, ext_ctx->ia32_sysenter_cs); + exec_vmwrite(VMX_GUEST_IA32_SYSENTER_ESP, ext_ctx->ia32_sysenter_esp); + exec_vmwrite(VMX_GUEST_IA32_SYSENTER_EIP, ext_ctx->ia32_sysenter_eip); + load_segment(ext_ctx->cs, VMX_GUEST_CS); + load_segment(ext_ctx->ss, VMX_GUEST_SS); + load_segment(ext_ctx->ds, VMX_GUEST_DS); + load_segment(ext_ctx->es, VMX_GUEST_ES); + load_segment(ext_ctx->fs, VMX_GUEST_FS); + load_segment(ext_ctx->gs, VMX_GUEST_GS); + load_segment(ext_ctx->tr, VMX_GUEST_TR); + load_segment(ext_ctx->ldtr, VMX_GUEST_LDTR); /* Only base and limit for IDTR and GDTR */ - exec_vmwrite(VMX_GUEST_IDTR_BASE, context->idtr.base); - exec_vmwrite(VMX_GUEST_GDTR_BASE, context->gdtr.base); - exec_vmwrite32(VMX_GUEST_IDTR_LIMIT, context->idtr.limit); - exec_vmwrite32(VMX_GUEST_GDTR_LIMIT, context->gdtr.limit); + exec_vmwrite(VMX_GUEST_IDTR_BASE, ext_ctx->idtr.base); + exec_vmwrite(VMX_GUEST_GDTR_BASE, ext_ctx->gdtr.base); + exec_vmwrite32(VMX_GUEST_IDTR_LIMIT, ext_ctx->idtr.limit); + exec_vmwrite32(VMX_GUEST_GDTR_LIMIT, ext_ctx->gdtr.limit); /* MSRs which not in the VMCS */ - msr_write(MSR_IA32_STAR, context->ia32_star); - msr_write(MSR_IA32_LSTAR, context->ia32_lstar); - msr_write(MSR_IA32_FMASK, context->ia32_fmask); - msr_write(MSR_IA32_KERNEL_GS_BASE, context->ia32_kernel_gs_base); + msr_write(MSR_IA32_STAR, ext_ctx->ia32_star); + msr_write(MSR_IA32_LSTAR, ext_ctx->ia32_lstar); + msr_write(MSR_IA32_FMASK, ext_ctx->ia32_fmask); + msr_write(MSR_IA32_KERNEL_GS_BASE, ext_ctx->ia32_kernel_gs_base); /* FX area */ - asm volatile("fxrstor (%0)" : : "r" (context->fxstore_guest_area)); + asm volatile("fxrstor (%0)" : : "r" (ext_ctx->fxstore_guest_area)); } static void copy_smc_param(struct run_context *prev_ctx, @@ -314,14 +321,14 @@ void switch_world(struct vcpu *vcpu, int next_world) struct vcpu_arch *arch_vcpu = &vcpu->arch_vcpu; /* save previous world context */ - save_world_ctx(&arch_vcpu->contexts[!next_world]); + save_world_ctx(vcpu, &arch_vcpu->contexts[!next_world].ext_ctx); /* load next world context */ - load_world_ctx(&arch_vcpu->contexts[next_world]); + load_world_ctx(vcpu, &arch_vcpu->contexts[next_world].ext_ctx); /* Copy SMC parameters: RDI, RSI, RDX, RBX */ - copy_smc_param(&arch_vcpu->contexts[!next_world], - &arch_vcpu->contexts[next_world]); + copy_smc_param(&arch_vcpu->contexts[!next_world].run_ctx, + &arch_vcpu->contexts[next_world].run_ctx); /* load EPTP for next world */ if (next_world == NORMAL_WORLD) { @@ -383,7 +390,7 @@ static bool setup_trusty_info(struct vcpu *vcpu, * address(GPA) of startup_param on boot. Currently, the startup_param * is put in the first page of trusty memory just followed by key_info. */ - vcpu->arch_vcpu.contexts[SECURE_WORLD].guest_cpu_regs.regs.rdi + vcpu->arch_vcpu.contexts[SECURE_WORLD].run_ctx.guest_cpu_regs.regs.rdi = (uint64_t)TRUSTY_EPT_REBASE_GPA + sizeof(struct trusty_key_info); return true; @@ -400,29 +407,13 @@ static bool init_secure_world_env(struct vcpu *vcpu, uint32_t size) { vcpu->arch_vcpu.inst_len = 0U; - vcpu->arch_vcpu.contexts[SECURE_WORLD].rip = entry_gpa; - vcpu->arch_vcpu.contexts[SECURE_WORLD].guest_cpu_regs.regs.rsp = + vcpu->arch_vcpu.contexts[SECURE_WORLD].run_ctx.rip = entry_gpa; + vcpu->arch_vcpu.contexts[SECURE_WORLD].run_ctx.guest_cpu_regs.regs.rsp = TRUSTY_EPT_REBASE_GPA + size; - vcpu->arch_vcpu.contexts[SECURE_WORLD].tsc_offset = 0UL; - vcpu->arch_vcpu.contexts[SECURE_WORLD].cr0 = - vcpu->arch_vcpu.contexts[NORMAL_WORLD].cr0; - vcpu->arch_vcpu.contexts[SECURE_WORLD].cr4 = - vcpu->arch_vcpu.contexts[NORMAL_WORLD].cr4; - vcpu->arch_vcpu.contexts[SECURE_WORLD].vmx_cr0 = - vcpu->arch_vcpu.contexts[NORMAL_WORLD].vmx_cr0; - vcpu->arch_vcpu.contexts[SECURE_WORLD].vmx_cr4 = - vcpu->arch_vcpu.contexts[NORMAL_WORLD].vmx_cr4; - - vcpu->arch_vcpu.contexts[SECURE_WORLD].ia32_pat = - vcpu->arch_vcpu.contexts[NORMAL_WORLD].ia32_pat; - vcpu->arch_vcpu.contexts[SECURE_WORLD].vmx_ia32_pat = - vcpu->arch_vcpu.contexts[NORMAL_WORLD].vmx_ia32_pat; - - exec_vmwrite(VMX_GUEST_RSP, - TRUSTY_EPT_REBASE_GPA + size); - exec_vmwrite64(VMX_TSC_OFFSET_FULL, - vcpu->arch_vcpu.contexts[SECURE_WORLD].tsc_offset); + vcpu->arch_vcpu.contexts[SECURE_WORLD].ext_ctx.tsc_offset = 0UL; + vcpu->arch_vcpu.contexts[SECURE_WORLD].ext_ctx.ia32_pat = + vcpu->arch_vcpu.contexts[NORMAL_WORLD].ext_ctx.ia32_pat; return setup_trusty_info(vcpu, size, base_hpa); } @@ -470,7 +461,7 @@ bool initialize_trusty(struct vcpu *vcpu, uint64_t param) HVA2HPA(vm->arch_vm.sworld_eptp) | (3UL<<3) | 6UL); /* save Normal World context */ - save_world_ctx(&vcpu->arch_vcpu.contexts[NORMAL_WORLD]); + save_world_ctx(vcpu, &vcpu->arch_vcpu.contexts[NORMAL_WORLD].ext_ctx); /* init secure world environment */ if (init_secure_world_env(vcpu, diff --git a/hypervisor/arch/x86/vmx.c b/hypervisor/arch/x86/vmx.c index 918537cc1..7096ff823 100644 --- a/hypervisor/arch/x86/vmx.c +++ b/hypervisor/arch/x86/vmx.c @@ -317,7 +317,7 @@ uint64_t vmx_rdmsr_pat(struct vcpu *vcpu) /* * note: if context->cr0.CD is set, the actual value in guest's * IA32_PAT MSR is PAT_ALL_UC_VALUE, which may be different from - * the saved value context->ia32_pat + * the saved value saved_context->ia32_pat */ return vcpu_get_pat_ext(vcpu); } diff --git a/hypervisor/arch/x86/vmx_asm.S b/hypervisor/arch/x86/vmx_asm.S index 4afbcb595..88cb02fdd 100644 --- a/hypervisor/arch/x86/vmx_asm.S +++ b/hypervisor/arch/x86/vmx_asm.S @@ -59,8 +59,8 @@ vmx_vmrun: /* 0x00000048 = MSR_IA32_SPEC_CTRL */ movl $0x00000048,%ecx - /*0xc0=192=PU_CONTEXT_OFFSET_IA32_SPEC_CTRL*/ - mov 0xc0(%rdi),%rax + /*0xa0=168U=CPU_CONTEXT_OFFSET_IA32_SPEC_CTRL*/ + mov 0xa0(%rdi),%rax movl $0,%edx wrmsr @@ -231,8 +231,8 @@ vm_eval_error: */ movl $0x00000048,%ecx rdmsr - /*192U=0xc0=CPU_CONTEXT_OFFSET_IA32_SPEC_CTRL*/ - mov %rax,0xc0(%rsi) + /*168U=0xa0=CPU_CONTEXT_OFFSET_IA32_SPEC_CTRL*/ + mov %rax,0xa0(%rsi) /* 0x1 = SPEC_ENABLE_IBRS */ movl $0x1,%eax movl $0,%edx @@ -255,8 +255,8 @@ ibrs_opt: */ movl $0x00000048,%ecx rdmsr - /*192U=0xc0=CPU_CONTEXT_OFFSET_IA32_SPEC_CTRL*/ - mov %rax,0xc0(%rsi) + /*168U=0xa0=CPU_CONTEXT_OFFSET_IA32_SPEC_CTRL*/ + mov %rax,0xa0(%rsi) /* 0x2 = SPEC_ENABLE_STIBP */ movl $0x2,%eax movl $0,%edx diff --git a/hypervisor/include/arch/x86/guest/vcpu.h b/hypervisor/include/arch/x86/guest/vcpu.h index 530724cee..4212c6f4b 100644 --- a/hypervisor/include/arch/x86/guest/vcpu.h +++ b/hypervisor/include/arch/x86/guest/vcpu.h @@ -34,27 +34,15 @@ #define CPU_CONTEXT_OFFSET_R15 120U #define CPU_CONTEXT_OFFSET_CR0 128U #define CPU_CONTEXT_OFFSET_CR2 136U -#define CPU_CONTEXT_OFFSET_CR3 144U -#define CPU_CONTEXT_OFFSET_CR4 152U -#define CPU_CONTEXT_OFFSET_RIP 160U -#define CPU_CONTEXT_OFFSET_RFLAGS 168U -#define CPU_CONTEXT_OFFSET_TSC_OFFSET 184U -#define CPU_CONTEXT_OFFSET_IA32_SPEC_CTRL 192U -#define CPU_CONTEXT_OFFSET_IA32_STAR 200U -#define CPU_CONTEXT_OFFSET_IA32_LSTAR 208U -#define CPU_CONTEXT_OFFSET_IA32_FMASK 216U -#define CPU_CONTEXT_OFFSET_IA32_KERNEL_GS_BASE 224U -#define CPU_CONTEXT_OFFSET_CS 280U -#define CPU_CONTEXT_OFFSET_SS 312U -#define CPU_CONTEXT_OFFSET_DS 344U -#define CPU_CONTEXT_OFFSET_ES 376U -#define CPU_CONTEXT_OFFSET_FS 408U -#define CPU_CONTEXT_OFFSET_GS 440U -#define CPU_CONTEXT_OFFSET_TR 472U -#define CPU_CONTEXT_OFFSET_IDTR 504U -#define CPU_CONTEXT_OFFSET_LDTR 536U -#define CPU_CONTEXT_OFFSET_GDTR 568U -#define CPU_CONTEXT_OFFSET_FXSTORE_GUEST_AREA 608U +#define CPU_CONTEXT_OFFSET_CR4 144U +#define CPU_CONTEXT_OFFSET_RIP 152U +#define CPU_CONTEXT_OFFSET_RFLAGS 160U +#define CPU_CONTEXT_OFFSET_IA32_SPEC_CTRL 168U +#define CPU_CONTEXT_OFFSET_IA32_EFER 176U +#define CPU_CONTEXT_OFFSET_EXTCTX_START 184U +#define CPU_CONTEXT_OFFSET_CR3 184U +#define CPU_CONTEXT_OFFSET_IDTR 192U +#define CPU_CONTEXT_OFFSET_LDTR 216U /*sizes of various registers within the VCPU data structure */ #define VMX_CPU_S_FXSAVE_GUEST_AREA_SIZE GUEST_STATE_AREA_SIZE @@ -120,24 +108,41 @@ struct run_context { /** The guests CR registers 0, 2, 3 and 4. */ uint64_t cr0; - /* VMX_MACHINE_T_GUEST_CR2_OFFSET = - * offsetof(struct run_context, cr2) = 128 + /* CPU_CONTEXT_OFFSET_CR2 = + * offsetof(struct run_context, cr2) = 136 */ uint64_t cr2; - uint64_t cr3; uint64_t cr4; uint64_t rip; uint64_t rflags; - uint64_t dr7; - uint64_t tsc_offset; - - /* MSRs */ - /* VMX_MACHINE_T_GUEST_SPEC_CTRL_OFFSET = - * offsetof(struct run_context, ia32_spec_ctrl) = 192 + /* CPU_CONTEXT_OFFSET_IA32_SPEC_CTRL = + * offsetof(struct run_context, ia32_spec_ctrl) = 168 */ uint64_t ia32_spec_ctrl; + uint64_t ia32_efer; +}; + +/* + * extended context does not save/restore during vm exity/entry, it's mainly + * used in trusty world switch + */ +struct ext_context { + uint64_t cr3; + + /* segment registers */ + struct segment_sel idtr; + struct segment_sel ldtr; + struct segment_sel gdtr; + struct segment_sel tr; + struct segment_sel cs; + struct segment_sel ss; + struct segment_sel ds; + struct segment_sel es; + struct segment_sel fs; + struct segment_sel gs; + uint64_t ia32_star; uint64_t ia32_lstar; uint64_t ia32_fmask; @@ -145,26 +150,18 @@ struct run_context { uint64_t ia32_pat; uint64_t vmx_ia32_pat; - uint64_t ia32_efer; uint32_t ia32_sysenter_cs; uint64_t ia32_sysenter_esp; uint64_t ia32_sysenter_eip; uint64_t ia32_debugctl; + uint64_t dr7; + uint64_t tsc_offset; + uint64_t vmx_cr0; uint64_t vmx_cr4; - - /* segment registers */ - struct segment_sel cs; - struct segment_sel ss; - struct segment_sel ds; - struct segment_sel es; - struct segment_sel fs; - struct segment_sel gs; - struct segment_sel tr; - struct segment_sel idtr; - struct segment_sel ldtr; - struct segment_sel gdtr; + uint64_t vmx_cr0_read_shadow; + uint64_t vmx_cr4_read_shadow; /* The 512 bytes area to save the FPU/MMX/SSE states for the guest */ uint64_t @@ -182,9 +179,14 @@ struct event_injection_info { uint32_t error_code; }; +struct cpu_context { + struct run_context run_ctx; + struct ext_context ext_ctx; +}; + struct vcpu_arch { int cur_context; - struct run_context contexts[NR_WORLD]; + struct cpu_context contexts[NR_WORLD]; /* A pointer to the VMCS for this CPU. */ void *vmcs;