Allow setting of guest MSRs from vmd(8). This change is the first part of
authormlarkin <mlarkin@openbsd.org>
Tue, 2 May 2017 02:57:46 +0000 (02:57 +0000)
committermlarkin <mlarkin@openbsd.org>
Tue, 2 May 2017 02:57:46 +0000 (02:57 +0000)
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
sys/arch/amd64/include/vmmvar.h

index 88c6020..2c9142d 100644 (file)
@@ -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 <mlarkin@openbsd.org>
  *
@@ -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;
index b3d6ec3..27ecd66 100644 (file)
@@ -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 <mlarkin@openbsd.org>
  *
@@ -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;