Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Add support for CPUs that don't have the EPT_{A, D} bits.



details:   https://anonhg.NetBSD.org/src/rev/2f8c1b07bc28
branches:  trunk
changeset: 449114:2f8c1b07bc28
user:      maxv <maxv%NetBSD.org@localhost>
date:      Sat Feb 23 10:43:36 2019 +0000

description:
Add support for CPUs that don't have the EPT_{A,D} bits.

On such CPUs, these bits are ignored by the hardware. We don't care about
setting them, however, we must always assume they are set. Modify the pmap
code to do that.

While here, in pmap_ept_remove_pte, don't flush the TLB when it's not
needed.

Tested on an old Intel Celeron.

diffstat:

 sys/arch/x86/x86/pmap.c         |  53 +++++++++++++++++++++++++++++++---------
 sys/dev/nvmm/x86/nvmm_x86_vmx.c |  14 ++++++---
 2 files changed, 50 insertions(+), 17 deletions(-)

diffs (179 lines):

diff -r 40c01e4dfd11 -r 2f8c1b07bc28 sys/arch/x86/x86/pmap.c
--- a/sys/arch/x86/x86/pmap.c   Sat Feb 23 10:43:25 2019 +0000
+++ b/sys/arch/x86/x86/pmap.c   Sat Feb 23 10:43:36 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pmap.c,v 1.325 2019/02/21 14:31:54 maxv Exp $  */
+/*     $NetBSD: pmap.c,v 1.326 2019/02/23 10:43:37 maxv Exp $  */
 
 /*
  * Copyright (c) 2008, 2010, 2016, 2017 The NetBSD Foundation, Inc.
@@ -130,7 +130,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.325 2019/02/21 14:31:54 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.326 2019/02/23 10:43:37 maxv Exp $");
 
 #include "opt_user_ldt.h"
 #include "opt_lockdebug.h"
@@ -4857,6 +4857,8 @@
 
 #define pmap_ept_valid_entry(pte)      (pte & EPT_R)
 
+bool pmap_ept_has_ad __read_mostly;
+
 static inline void
 pmap_ept_stats_update_bypte(struct pmap *pmap, pt_entry_t npte, pt_entry_t opte)
 {
@@ -4912,10 +4914,14 @@
 pmap_ept_to_pp_attrs(pt_entry_t ept)
 {
        uint8_t ret = 0;
-       if (ept & EPT_D)
-               ret |= PP_ATTRS_M;
-       if (ept & EPT_A)
-               ret |= PP_ATTRS_U;
+       if (pmap_ept_has_ad) {
+               if (ept & EPT_D)
+                       ret |= PP_ATTRS_M;
+               if (ept & EPT_A)
+                       ret |= PP_ATTRS_U;
+       } else {
+               ret |= (PP_ATTRS_M|PP_ATTRS_U);
+       }
        if (ept & EPT_W)
                ret |= PP_ATTRS_W;
        return ret;
@@ -5098,6 +5104,7 @@
        struct pv_entry *new_pve;
        struct pv_entry *new_sparepve;
        bool wired = (flags & PMAP_WIRED) != 0;
+       bool accessed;
        int error;
 
        KASSERT(pmap_initialized);
@@ -5238,8 +5245,12 @@
 same_pa:
        mutex_exit(pmap->pm_lock);
 
-       if ((~opte & (EPT_R | EPT_A)) == 0 &&
-           ((opte ^ npte) & (PG_FRAME | EPT_W)) != 0) {
+       if (pmap_ept_has_ad) {
+               accessed = (~opte & (EPT_R | EPT_A)) == 0;
+       } else {
+               accessed = (opte & EPT_R) != 0;
+       }
+       if (accessed && ((opte ^ npte) & (PG_FRAME | EPT_W)) != 0) {
                pmap_tlb_shootdown(pmap, va, 0, TLBSHOOT_ENTER);
        }
 
@@ -5334,6 +5345,7 @@
        struct vm_page *pg;
        struct pmap_page *pp;
        pt_entry_t opte;
+       bool accessed;
 
        KASSERT(pmap != pmap_kernel());
        KASSERT(mutex_owned(pmap->pm_lock));
@@ -5362,7 +5374,14 @@
                }
        }
 
-       pmap_tlb_shootdown(pmap, va, 0, TLBSHOOT_REMOVE_PTE);
+       if (pmap_ept_has_ad) {
+               accessed = (opte & EPT_A) != 0;
+       } else {
+               accessed = true;
+       }
+       if (accessed) {
+               pmap_tlb_shootdown(pmap, va, 0, TLBSHOOT_REMOVE_PTE);
+       }
 
        /*
         * If we are not on a pv_head list - we are done.
@@ -5530,8 +5549,12 @@
                 * ... Unless we are clearing only the PG_RW bit and
                 * it isn't cached as RW (PG_M).
                 */
-               need_shootdown = (opte & EPT_A) != 0 &&
-                   !(clearbits == EPT_W && (opte & EPT_D) == 0);
+               if (pmap_ept_has_ad) {
+                       need_shootdown = (opte & EPT_A) != 0 &&
+                           !(clearbits == EPT_W && (opte & EPT_D) == 0);
+               } else {
+                       need_shootdown = true;
+               }
 
                npte = opte & ~clearbits;
 
@@ -5579,6 +5602,7 @@
        pd_entry_t pde;
        paddr_t ptppa;
        vaddr_t va;
+       bool modified;
 
        bit_rem = 0;
        if (!(prot & VM_PROT_WRITE))
@@ -5609,7 +5633,12 @@
                        npte = (opte & ~bit_rem);
                } while (pmap_pte_cas(spte, opte, npte) != opte);
 
-               if ((opte & EPT_D) != 0) {
+               if (pmap_ept_has_ad) {
+                       modified = (opte & EPT_D) != 0;
+               } else {
+                       modified = true;
+               }
+               if (modified) {
                        vaddr_t tva = x86_ptob(spte - ptes);
                        pmap_tlb_shootdown(pmap, tva, 0,
                            TLBSHOOT_WRITE_PROTECT);
diff -r 40c01e4dfd11 -r 2f8c1b07bc28 sys/dev/nvmm/x86/nvmm_x86_vmx.c
--- a/sys/dev/nvmm/x86/nvmm_x86_vmx.c   Sat Feb 23 10:43:25 2019 +0000
+++ b/sys/dev/nvmm/x86/nvmm_x86_vmx.c   Sat Feb 23 10:43:36 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvmm_x86_vmx.c,v 1.12 2019/02/23 08:19:16 maxv Exp $   */
+/*     $NetBSD: nvmm_x86_vmx.c,v 1.13 2019/02/23 10:43:36 maxv Exp $   */
 
 /*
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.12 2019/02/23 08:19:16 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.13 2019/02/23 10:43:36 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -551,6 +551,8 @@
 static uint64_t vmx_cr4_fixed0 __read_mostly;
 static uint64_t vmx_cr4_fixed1 __read_mostly;
 
+extern bool pmap_ept_has_ad;
+
 #define VMX_PINBASED_CTLS_ONE  \
        (PIN_CTLS_INT_EXITING| \
         PIN_CTLS_NMI_EXITING| \
@@ -2396,7 +2398,7 @@
        eptp =
            __SHIFTIN(vmx_eptp_type, EPTP_TYPE) |
            __SHIFTIN(4-1, EPTP_WALKLEN) |
-           EPTP_FLAGS_AD |
+           (pmap_ept_has_ad ? EPTP_FLAGS_AD : 0) |
            mach->vm->vm_map.pmap->pm_pdirpa[0];
        vmx_vmwrite(VMCS_EPTP, eptp);
 
@@ -2725,8 +2727,10 @@
        if ((msr & IA32_VMX_EPT_VPID_INVVPID) == 0) {
                return false;
        }
-       if ((msr & IA32_VMX_EPT_VPID_FLAGS_AD) == 0) {
-               return false;
+       if ((msr & IA32_VMX_EPT_VPID_FLAGS_AD) != 0) {
+               pmap_ept_has_ad = true;
+       } else {
+               pmap_ept_has_ad = false;
        }
        if (!(msr & IA32_VMX_EPT_VPID_UC) && !(msr & IA32_VMX_EPT_VPID_WB)) {
                return false;



Home | Main Index | Thread Index | Old Index