Hello tech@,

This is a patch that extends the readregs and writeregs vmm(4) ioctl to
read and write MSRs as well.

It also sets the IA32_VMX_IA32E_MODE_GUEST entry control in
vcpu_reset_regs based on the value of EFER_LMA.

There are changes to vmmvar.h and would require a `make includes` step
to build vmd(8). This should also not alter any behaviour of vmd(8).

Context: These are the kernel changes required to implement vmctl send
and vmctl receive. vmctl send / receive are two new options that will
support snapshotting VMs and migrating VMs from one host to another.
This project was undertaken at San Jose State University along with my
three teammates CCed with mlarkin@ as our advisor.

Patches to vmd(8) that implement vmctl send and vmctl receive are
forthcoming.


Thanks,
Pratik



Index: sys/arch/amd64/amd64/vmm.c
===================================================================
RCS file: /home/pdvyas/cvs/src/sys/arch/amd64/amd64/vmm.c,v
retrieving revision 1.137
diff -u -p -a -u -r1.137 vmm.c
--- sys/arch/amd64/amd64/vmm.c  28 Apr 2017 10:09:37 -0000      1.137
+++ sys/arch/amd64/amd64/vmm.c  30 Apr 2017 00:01:21 -0000
@@ -1334,7 +1334,9 @@ vcpu_readregs_vmx(struct vcpu *vcpu, uin
        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, uin
                        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, ui
        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, ui
                        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, s
         * 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, s
         */
        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
@@ -2359,6 +2365,13 @@ vcpu_reset_regs_vmx(struct vcpu *vcpu, s
        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
         */
        memset((uint8_t *)vcpu->vc_msr_bitmap_va, 0xFF, PAGE_SIZE);
@@ -4317,7 +4330,7 @@ vmx_handle_cr0_write(struct vcpu *vcpu, 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: sys/arch/amd64/include/vmmvar.h
===================================================================
RCS file: /home/pdvyas/cvs/src/sys/arch/amd64/include/vmmvar.h,v
retrieving revision 1.35
diff -u -p -a -u -r1.35 vmmvar.h
--- sys/arch/amd64/include/vmmvar.h     28 Apr 2017 07:44:36 -0000      1.35
+++ sys/arch/amd64/include/vmmvar.h     30 Apr 2017 00:01:21 -0000
@@ -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;
Index: usr.sbin/vmd/vm.c
===================================================================
RCS file: /home/pdvyas/cvs/src/usr.sbin/vmd/vm.c,v
retrieving revision 1.13
diff -u -p -a -u -r1.13 vm.c
--- usr.sbin/vmd/vm.c   25 Apr 2017 06:44:35 -0000      1.13
+++ usr.sbin/vmd/vm.c   30 Apr 2017 00:01:21 -0000
@@ -133,6 +133,12 @@ static const struct vcpu_reg_state vcpu_
        .vrs_idtr = { 0x0, 0xFFFF, 0x0, 0x0},
        .vrs_sregs[VCPU_REGS_LDTR] = { 0x0, 0xFFFF, 0x0082, 0x0},
        .vrs_sregs[VCPU_REGS_TR] = { 0x0, 0xFFFF, 0x008B, 0x0},
+       .vrs_msrs[VCPU_REGS_EFER] = 0ULL,
+       .vrs_msrs[VCPU_REGS_STAR] = 0ULL,
+       .vrs_msrs[VCPU_REGS_LSTAR] = 0ULL,
+       .vrs_msrs[VCPU_REGS_CSTAR] = 0ULL,
+       .vrs_msrs[VCPU_REGS_SFMASK] = 0ULL,
+       .vrs_msrs[VCPU_REGS_KGSBASE] = 0ULL
};

/*
@@ -161,6 +167,12 @@ static const struct vcpu_reg_state vcpu_
        .vrs_idtr = { 0x0, 0xFFFF, 0x0, 0x0},
        .vrs_sregs[VCPU_REGS_LDTR] = { 0x0, 0xFFFF, 0x0082, 0x0},
        .vrs_sregs[VCPU_REGS_TR] = { 0x0, 0xFFFF, 0x008B, 0x0},
+       .vrs_msrs[VCPU_REGS_EFER] = 0ULL,
+       .vrs_msrs[VCPU_REGS_STAR] = 0ULL,
+       .vrs_msrs[VCPU_REGS_LSTAR] = 0ULL,
+       .vrs_msrs[VCPU_REGS_CSTAR] = 0ULL,
+       .vrs_msrs[VCPU_REGS_SFMASK] = 0ULL,
+       .vrs_msrs[VCPU_REGS_KGSBASE] = 0ULL
};

/*

Reply via email to