Author: neel
Date: Tue Feb 24 05:35:15 2015
New Revision: 279228
URL: https://svnweb.freebsd.org/changeset/base/279228

Log:
  Always emulate MSR_PAT on Intel processors and don't rely on PAT save/restore
  capability of VT-x. This lets bhyve run nested in older VMware versions that
  don't support the PAT save/restore capability.
  
  Note that the actual value programmed by the guest in MSR_PAT is irrelevant
  because bhyve sets the 'Ignore PAT' bit in the nested PTE.
  
  Reported by:  marcel
  Tested by:    Leon Dang (ld...@nahannisys.com)
  Sponsored by: Nahanni Systems
  MFC after:    2 weeks

Modified:
  head/sys/amd64/vmm/intel/vmcs.c
  head/sys/amd64/vmm/intel/vmx.c
  head/sys/amd64/vmm/intel/vmx.h
  head/sys/amd64/vmm/intel/vmx_msr.c

Modified: head/sys/amd64/vmm/intel/vmcs.c
==============================================================================
--- head/sys/amd64/vmm/intel/vmcs.c     Tue Feb 24 05:15:40 2015        
(r279227)
+++ head/sys/amd64/vmm/intel/vmcs.c     Tue Feb 24 05:35:15 2015        
(r279228)
@@ -342,18 +342,6 @@ vmcs_init(struct vmcs *vmcs)
         */
        VMPTRLD(vmcs);
 
-       /* Initialize guest IA32_PAT MSR with the default value */
-       pat = PAT_VALUE(0, PAT_WRITE_BACK)      |
-             PAT_VALUE(1, PAT_WRITE_THROUGH)   |
-             PAT_VALUE(2, PAT_UNCACHED)        |
-             PAT_VALUE(3, PAT_UNCACHEABLE)     |
-             PAT_VALUE(4, PAT_WRITE_BACK)      |
-             PAT_VALUE(5, PAT_WRITE_THROUGH)   |
-             PAT_VALUE(6, PAT_UNCACHED)        |
-             PAT_VALUE(7, PAT_UNCACHEABLE);
-       if ((error = vmwrite(VMCS_GUEST_IA32_PAT, pat)) != 0)
-               goto done;
-
        /* Host state */
 
        /* Initialize host IA32_PAT MSR */

Modified: head/sys/amd64/vmm/intel/vmx.c
==============================================================================
--- head/sys/amd64/vmm/intel/vmx.c      Tue Feb 24 05:15:40 2015        
(r279227)
+++ head/sys/amd64/vmm/intel/vmx.c      Tue Feb 24 05:35:15 2015        
(r279228)
@@ -100,13 +100,11 @@ __FBSDID("$FreeBSD$");
        (VM_EXIT_HOST_LMA                       |                       \
        VM_EXIT_SAVE_EFER                       |                       \
        VM_EXIT_LOAD_EFER                       |                       \
-       VM_EXIT_ACKNOWLEDGE_INTERRUPT           |                       \
-       VM_EXIT_SAVE_PAT                        |                       \
-       VM_EXIT_LOAD_PAT)
+       VM_EXIT_ACKNOWLEDGE_INTERRUPT)
 
 #define        VM_EXIT_CTLS_ZERO_SETTING       VM_EXIT_SAVE_DEBUG_CONTROLS
 
-#define        VM_ENTRY_CTLS_ONE_SETTING       (VM_ENTRY_LOAD_EFER | 
VM_ENTRY_LOAD_PAT)
+#define        VM_ENTRY_CTLS_ONE_SETTING       (VM_ENTRY_LOAD_EFER)
 
 #define        VM_ENTRY_CTLS_ZERO_SETTING                                      
\
        (VM_ENTRY_LOAD_DEBUG_CONTROLS           |                       \
@@ -859,10 +857,6 @@ vmx_vminit(struct vm *vm, pmap_t pmap)
         * VM exit and entry respectively. It is also restored from the
         * host VMCS area on a VM exit.
         *
-        * MSR_PAT is saved and restored in the guest VMCS are on a VM exit
-        * and entry respectively. It is also restored from the host VMCS
-        * area on a VM exit.
-        *
         * The TSC MSR is exposed read-only. Writes are disallowed as that
         * will impact the host TSC.
         * XXX Writes would be implemented with a wrmsr trap, and
@@ -874,7 +868,6 @@ vmx_vminit(struct vm *vm, pmap_t pmap)
            guest_msr_rw(vmx, MSR_SYSENTER_ESP_MSR) ||
            guest_msr_rw(vmx, MSR_SYSENTER_EIP_MSR) ||
            guest_msr_rw(vmx, MSR_EFER) ||
-           guest_msr_rw(vmx, MSR_PAT) ||
            guest_msr_ro(vmx, MSR_TSC))
                panic("vmx_vminit: error setting guest msr access");
 

Modified: head/sys/amd64/vmm/intel/vmx.h
==============================================================================
--- head/sys/amd64/vmm/intel/vmx.h      Tue Feb 24 05:15:40 2015        
(r279227)
+++ head/sys/amd64/vmm/intel/vmx.h      Tue Feb 24 05:35:15 2015        
(r279228)
@@ -103,6 +103,7 @@ enum {
        IDX_MSR_STAR,
        IDX_MSR_SF_MASK,
        IDX_MSR_KGSBASE,
+       IDX_MSR_PAT,
        GUEST_MSR_NUM           /* must be the last enumeration */
 };
 

Modified: head/sys/amd64/vmm/intel/vmx_msr.c
==============================================================================
--- head/sys/amd64/vmm/intel/vmx_msr.c  Tue Feb 24 05:15:40 2015        
(r279227)
+++ head/sys/amd64/vmm/intel/vmx_msr.c  Tue Feb 24 05:35:15 2015        
(r279228)
@@ -230,6 +230,25 @@ westmere_cpu(void)
        return (false);
 }
 
+static bool
+pat_valid(uint64_t val)
+{
+       int i, pa;
+
+       /*
+        * From Intel SDM: Table "Memory Types That Can Be Encoded With PAT"
+        *
+        * Extract PA0 through PA7 and validate that each one encodes a
+        * valid memory type.
+        */
+       for (i = 0; i < 8; i++) {
+               pa = (val >> (i * 8)) & 0xff;
+               if (pa == 2 || pa == 3 || pa >= 8)
+                       return (false);
+       }
+       return (true);
+}
+
 void
 vmx_msr_init(void)
 {
@@ -302,6 +321,10 @@ vmx_msr_init(void)
 void
 vmx_msr_guest_init(struct vmx *vmx, int vcpuid)
 {
+       uint64_t *guest_msrs;
+
+       guest_msrs = vmx->guest_msrs[vcpuid];
+
        /*
         * The permissions bitmap is shared between all vcpus so initialize it
         * once when initializing the vBSP.
@@ -313,6 +336,19 @@ vmx_msr_guest_init(struct vmx *vmx, int 
                guest_msr_rw(vmx, MSR_SF_MASK);
                guest_msr_rw(vmx, MSR_KGSBASE);
        }
+
+       /*
+        * Initialize guest IA32_PAT MSR with default value after reset.
+        */
+       guest_msrs[IDX_MSR_PAT] = PAT_VALUE(0, PAT_WRITE_BACK) |
+           PAT_VALUE(1, PAT_WRITE_THROUGH)     |
+           PAT_VALUE(2, PAT_UNCACHED)          |
+           PAT_VALUE(3, PAT_UNCACHEABLE)       |
+           PAT_VALUE(4, PAT_WRITE_BACK)        |
+           PAT_VALUE(5, PAT_WRITE_THROUGH)     |
+           PAT_VALUE(6, PAT_UNCACHED)          |
+           PAT_VALUE(7, PAT_UNCACHEABLE);
+
        return;
 }
 
@@ -353,7 +389,11 @@ vmx_msr_guest_exit(struct vmx *vmx, int 
 int
 vmx_rdmsr(struct vmx *vmx, int vcpuid, u_int num, uint64_t *val, bool *retu)
 {
-       int error = 0;
+       const uint64_t *guest_msrs;
+       int error;
+
+       guest_msrs = vmx->guest_msrs[vcpuid];
+       error = 0;
 
        switch (num) {
        case MSR_IA32_MISC_ENABLE:
@@ -366,6 +406,9 @@ vmx_rdmsr(struct vmx *vmx, int vcpuid, u
        case MSR_TURBO_RATIO_LIMIT1:
                *val = turbo_ratio_limit;
                break;
+       case MSR_PAT:
+               *val = guest_msrs[IDX_MSR_PAT];
+               break;
        default:
                error = EINVAL;
                break;
@@ -376,10 +419,13 @@ vmx_rdmsr(struct vmx *vmx, int vcpuid, u
 int
 vmx_wrmsr(struct vmx *vmx, int vcpuid, u_int num, uint64_t val, bool *retu)
 {
+       uint64_t *guest_msrs;
        uint64_t changed;
        int error;
        
+       guest_msrs = vmx->guest_msrs[vcpuid];
        error = 0;
+
        switch (num) {
        case MSR_IA32_MISC_ENABLE:
                changed = val ^ misc_enable;
@@ -401,6 +447,12 @@ vmx_wrmsr(struct vmx *vmx, int vcpuid, u
                        error = EINVAL;
 
                break;
+       case MSR_PAT:
+               if (pat_valid(val))
+                       guest_msrs[IDX_MSR_PAT] = val;
+               else
+                       vm_inject_gp(vmx->vm, vcpuid);
+               break;
        default:
                error = EINVAL;
                break;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to