VMM: Use safe MSR accessors
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 28 Apr 2016 20:24:23 +0000 (16:24 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 2 May 2016 21:11:15 +0000 (17:11 -0400)
We clearly need write_msr_safe.  The guest could give us an unacceptable
value that could trigger a GPF.  For read, better safe than sorry.  It's
possible we add an MSR that we allow the guest to read, but that isn't on
every piece of hardware.  In that case, we could also trigger a GPF.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/x86/vmm/vmm.c
kern/arch/x86/x86.h

index 818e26c..552f2c1 100644 (file)
@@ -295,8 +295,11 @@ bool emsr_miscenable(struct emmsr *msr, uint64_t *rcx, uint64_t *rdx,
                      uint64_t *rax, uint32_t opcode)
 {
        uint32_t eax, edx;
+       uint64_t val;
 
-       rdmsr(msr->reg, eax, edx);
+       if (read_msr_safe(msr->reg, &val))
+               return FALSE;
+       split_msr_val(val, &edx, &eax);
        /* we just let them read the misc msr for now. */
        if (opcode == VMM_MSR_EMU_READ) {
                *rax = eax;
@@ -320,8 +323,11 @@ bool emsr_mustmatch(struct emmsr *msr, uint64_t *rcx, uint64_t *rdx,
                     uint64_t *rax, uint32_t opcode)
 {
        uint32_t eax, edx;
+       uint64_t val;
 
-       rdmsr(msr->reg, eax, edx);
+       if (read_msr_safe(msr->reg, &val))
+               return FALSE;
+       split_msr_val(val, &edx, &eax);
        /* we just let them read the misc msr for now. */
        if (opcode == VMM_MSR_EMU_READ) {
                *rax = eax;
@@ -342,8 +348,11 @@ bool emsr_readonly(struct emmsr *msr, uint64_t *rcx, uint64_t *rdx,
                    uint64_t *rax, uint32_t opcode)
 {
        uint32_t eax, edx;
+       uint64_t val;
 
-       rdmsr((uint32_t) *rcx, eax, edx);
+       if (read_msr_safe(msr->reg, &val))
+               return FALSE;
+       split_msr_val(val, &edx, &eax);
        if (opcode == VMM_MSR_EMU_READ) {
                *rax = eax;
                *rdx = edx;
@@ -372,9 +381,12 @@ bool emsr_fakewrite(struct emmsr *msr, uint64_t *rcx, uint64_t *rdx,
                     uint64_t *rax, uint32_t opcode)
 {
        uint32_t eax, edx;
+       uint64_t val;
 
        if (!msr->written) {
-               rdmsr(msr->reg, eax, edx);
+               if (read_msr_safe(msr->reg, &val))
+                       return FALSE;
+               split_msr_val(val, &edx, &eax);
        } else {
                edx = msr->edx;
                eax = msr->eax;
@@ -399,15 +411,18 @@ bool emsr_ok(struct emmsr *msr, uint64_t *rcx, uint64_t *rdx,
              uint64_t *rax, uint32_t opcode)
 {
        uint32_t eax, edx;
+       uint64_t val;
 
        if (opcode == VMM_MSR_EMU_READ) {
-               rdmsr(msr->reg, eax, edx);
+               if (read_msr_safe(msr->reg, &val))
+                       return FALSE;
+               split_msr_val(val, &edx, &eax);
                *rax = eax;
                *rdx = edx;
        } else {
-               uint64_t val = (*rdx << 32) | (*rax & 0xffffffff);
-
-               write_msr(msr->reg, val);
+               val = (*rdx << 32) | (*rax & 0xffffffff);
+               if (write_msr_safe(msr->reg, val))
+                       return FALSE;
        }
        return TRUE;
 }
@@ -419,7 +434,6 @@ bool emsr_fake_apicbase(struct emmsr *msr, uint64_t *rcx, uint64_t *rdx,
        uint32_t eax, edx;
 
        if (!msr->written) {
-               //rdmsr(msr->reg, eax, edx);
                /* TODO: tightly coupled to the addr in vmrunkernel.  We want this func
                 * to return the val that vmrunkernel put into the VMCS. */
                eax = 0xfee00900;
index 81fa735..9c49ef0 100644 (file)
@@ -449,6 +449,12 @@ static inline uint64_t read_msr(uint32_t reg)
        return (uint64_t)edx << 32 | eax;
 }
 
+static void split_msr_val(uint64_t val, uint32_t *high32, uint32_t *low32)
+{
+       *high32 = val >> 32;
+       *low32 = val & 0xffffffff;
+}
+
 static inline void write_msr(uint32_t reg, uint64_t val)
 {
        asm volatile("wrmsr" : : "d"(val >> 32), "a"(val & 0xFFFFFFFF), "c"(reg));