From dbd8d95a83249fe2ba471baddc625f246bff5397 Mon Sep 17 00:00:00 2001 From: mlarkin Date: Tue, 2 May 2017 02:57:46 +0000 Subject: [PATCH] Allow setting of guest MSRs from vmd(8). This change is the first part of a larger effort to implement vmctl send/vmctl receive (snapshot and VM migration). From Pratik Vyas, Siri Chandana, Harshada Mone and Ashwin Agrawal, a group of students I am supervising. ok kettenis --- sys/arch/amd64/amd64/vmm.c | 59 ++++++++++++++++++++------------- sys/arch/amd64/include/vmmvar.h | 15 +++++++-- 2 files changed, 49 insertions(+), 25 deletions(-) diff --git a/sys/arch/amd64/amd64/vmm.c b/sys/arch/amd64/amd64/vmm.c index 88c6020df64..2c9142d51ea 100644 --- a/sys/arch/amd64/amd64/vmm.c +++ b/sys/arch/amd64/amd64/vmm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmm.c,v 1.137 2017/04/28 10:09:37 mlarkin Exp $ */ +/* $OpenBSD: vmm.c,v 1.138 2017/05/02 02:57:46 mlarkin Exp $ */ /* * Copyright (c) 2014 Mike Larkin * @@ -1334,7 +1334,9 @@ vcpu_readregs_vmx(struct vcpu *vcpu, uint64_t regmask, uint64_t sel, limit, ar; uint64_t *gprs = vrs->vrs_gprs; uint64_t *crs = vrs->vrs_crs; + uint64_t *msrs = vrs->vrs_msrs; struct vcpu_segment_info *sregs = vrs->vrs_sregs; + struct vmx_msr_store *msr_store; if (vcpu_reload_vmcs_vmx(&vcpu->vc_control_pa)) return (EINVAL); @@ -1402,6 +1404,14 @@ vcpu_readregs_vmx(struct vcpu *vcpu, uint64_t regmask, goto errout; } + msr_store = (struct vmx_msr_store *)vcpu->vc_vmx_msr_exit_save_va; + + if (regmask & VM_RWREGS_MSRS) { + for (i = 0; i < VCPU_REGS_NMSRS; i++) { + msrs[i] = msr_store[i].vms_data; + } + } + goto out; errout: @@ -1448,7 +1458,9 @@ vcpu_writeregs_vmx(struct vcpu *vcpu, uint64_t regmask, int loadvmcs, uint64_t limit, ar; uint64_t *gprs = vrs->vrs_gprs; uint64_t *crs = vrs->vrs_crs; + uint64_t *msrs = vrs->vrs_msrs; struct vcpu_segment_info *sregs = vrs->vrs_sregs; + struct vmx_msr_store *msr_store; if (loadvmcs) { if (vcpu_reload_vmcs_vmx(&vcpu->vc_control_pa)) @@ -1518,6 +1530,14 @@ vcpu_writeregs_vmx(struct vcpu *vcpu, uint64_t regmask, int loadvmcs, goto errout; } + msr_store = (struct vmx_msr_store *)vcpu->vc_vmx_msr_exit_save_va; + + if (regmask & VM_RWREGS_MSRS) { + for (i = 0; i < VCPU_REGS_NMSRS; i++) { + msr_store[i].vms_data = msrs[i]; + } + } + goto out; errout: @@ -2128,7 +2148,7 @@ vcpu_reset_regs_vmx(struct vcpu *vcpu, struct vcpu_reg_state *vrs) * IA32_VMX_LOAD_DEBUG_CONTROLS * IA32_VMX_LOAD_IA32_PERF_GLOBAL_CTRL_ON_ENTRY */ - if (ug == 1) + if (ug == 1 && !(vrs->vrs_msrs[VCPU_REGS_EFER] & EFER_LMA)) want1 = 0; else want1 = IA32_VMX_IA32E_MODE_GUEST; @@ -2277,26 +2297,12 @@ vcpu_reset_regs_vmx(struct vcpu *vcpu, struct vcpu_reg_state *vrs) */ msr_store = (struct vmx_msr_store *)vcpu->vc_vmx_msr_exit_save_va; - /* - * Make sure LME is enabled in EFER if restricted guest mode is - * needed. - */ - msr_store[0].vms_index = MSR_EFER; - if (ug == 1) - msr_store[0].vms_data = 0ULL; /* Initial value */ - else - msr_store[0].vms_data = EFER_LME; - - msr_store[1].vms_index = MSR_STAR; - msr_store[1].vms_data = 0ULL; /* Initial value */ - msr_store[2].vms_index = MSR_LSTAR; - msr_store[2].vms_data = 0ULL; /* Initial value */ - msr_store[3].vms_index = MSR_CSTAR; - msr_store[3].vms_data = 0ULL; /* Initial value */ - msr_store[4].vms_index = MSR_SFMASK; - msr_store[4].vms_data = 0ULL; /* Initial value */ - msr_store[5].vms_index = MSR_KERNELGSBASE; - msr_store[5].vms_data = 0ULL; /* Initial value */ + msr_store[VCPU_REGS_EFER].vms_index = MSR_EFER; + msr_store[VCPU_REGS_STAR].vms_index = MSR_STAR; + msr_store[VCPU_REGS_LSTAR].vms_index = MSR_LSTAR; + msr_store[VCPU_REGS_CSTAR].vms_index = MSR_CSTAR; + msr_store[VCPU_REGS_SFMASK].vms_index = MSR_SFMASK; + msr_store[VCPU_REGS_KGSBASE].vms_index = MSR_KERNELGSBASE; /* * Currently we have the same count of entry/exit MSRs loads/stores @@ -2358,6 +2364,13 @@ vcpu_reset_regs_vmx(struct vcpu *vcpu, struct vcpu_reg_state *vrs) */ ret = vcpu_writeregs_vmx(vcpu, VM_RWREGS_ALL, 0, vrs); + /* + * Make sure LME is enabled in EFER if restricted guest mode is + * needed. + */ + if (ug == 0) + msr_store[VCPU_REGS_EFER].vms_data |= EFER_LME; + /* * Set up the MSR bitmap */ @@ -4317,7 +4330,7 @@ vmx_handle_cr0_write(struct vcpu *vcpu, uint64_t r) return (EINVAL); } - if (msr_store[0].vms_data & EFER_LME) + if (msr_store[VCPU_REGS_EFER].vms_data & EFER_LME) ectls |= IA32_VMX_IA32E_MODE_GUEST; else ectls &= ~IA32_VMX_IA32E_MODE_GUEST; diff --git a/sys/arch/amd64/include/vmmvar.h b/sys/arch/amd64/include/vmmvar.h index b3d6ec39622..27ecd66ce2e 100644 --- a/sys/arch/amd64/include/vmmvar.h +++ b/sys/arch/amd64/include/vmmvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmmvar.h,v 1.35 2017/04/28 07:44:36 mlarkin Exp $ */ +/* $OpenBSD: vmmvar.h,v 1.36 2017/05/02 02:57:46 mlarkin Exp $ */ /* * Copyright (c) 2014 Mike Larkin * @@ -340,9 +340,18 @@ struct vcpu_segment_info { #define VCPU_REGS_TR 7 #define VCPU_REGS_NSREGS (VCPU_REGS_TR + 1) +#define VCPU_REGS_EFER 0 +#define VCPU_REGS_STAR 1 +#define VCPU_REGS_LSTAR 2 +#define VCPU_REGS_CSTAR 3 +#define VCPU_REGS_SFMASK 4 +#define VCPU_REGS_KGSBASE 5 +#define VCPU_REGS_NMSRS (VCPU_REGS_KGSBASE + 1) + struct vcpu_reg_state { uint64_t vrs_gprs[VCPU_REGS_NGPRS]; uint64_t vrs_crs[VCPU_REGS_NCRS]; + uint64_t vrs_msrs[VCPU_REGS_NMSRS]; struct vcpu_segment_info vrs_sregs[VCPU_REGS_NSREGS]; struct vcpu_segment_info vrs_gdtr; struct vcpu_segment_info vrs_idtr; @@ -427,7 +436,9 @@ struct vm_intr_params { #define VM_RWREGS_GPRS 0x1 /* read/write GPRs */ #define VM_RWREGS_SREGS 0x2 /* read/write segment registers */ #define VM_RWREGS_CRS 0x4 /* read/write CRs */ -#define VM_RWREGS_ALL (VM_RWREGS_GPRS | VM_RWREGS_SREGS | VM_RWREGS_CRS) +#define VM_RWREGS_MSRS 0x8 /* read/write MSRs */ +#define VM_RWREGS_ALL (VM_RWREGS_GPRS | VM_RWREGS_SREGS | VM_RWREGS_CRS | \ + VM_RWREGS_MSRS) struct vm_rwregs_params { uint32_t vrwp_vm_id; -- 2.20.1