Author: kib
Date: Fri May 15 07:57:47 2015
New Revision: 282945
URL: https://svnweb.freebsd.org/changeset/base/282945

Log:
  Implement the support for PCID in UP kernels.
  
  Requested by: alc
  Tested by:    pho
  Sponsored by: The FreeBSD Foundation
  MFC after:    3 weeks

Modified:
  head/sys/amd64/amd64/pmap.c

Modified: head/sys/amd64/amd64/pmap.c
==============================================================================
--- head/sys/amd64/amd64/pmap.c Fri May 15 07:54:31 2015        (r282944)
+++ head/sys/amd64/amd64/pmap.c Fri May 15 07:57:47 2015        (r282945)
@@ -909,11 +909,7 @@ pmap_bootstrap(vm_paddr_t *firstaddr)
                 * pc_pcid_next and pc_pcid_gen are initialized by AP
                 * during pcpu setup.
                 */
-#ifdef SMP
                load_cr4(rcr4() | CR4_PCIDE);
-#else
-               pmap_pcid_enabled = 0;
-#endif
        } else {
                pmap_pcid_enabled = 0;
        }
@@ -1559,61 +1555,79 @@ pmap_update_pde(pmap_t pmap, vm_offset_t
 #else /* !SMP */
 /*
  * Normal, non-SMP, invalidation functions.
- * We inline these within pmap.c for speed.
  */
-PMAP_INLINE void
+void
 pmap_invalidate_page(pmap_t pmap, vm_offset_t va)
 {
 
-       switch (pmap->pm_type) {
-       case PT_X86:
-               if (pmap == kernel_pmap || !CPU_EMPTY(&pmap->pm_active))
-                       invlpg(va);
-               break;
-       case PT_RVI:
-       case PT_EPT:
+       if (pmap->pm_type == PT_RVI || pmap->pm_type == PT_EPT) {
                pmap->pm_eptgen++;
-               break;
-       default:
-               panic("pmap_invalidate_page: unknown type: %d", pmap->pm_type);
+               return;
        }
+       KASSERT(pmap->pm_type == PT_X86,
+           ("pmap_invalidate_range: unknown type %d", pmap->pm_type));
+
+       if (pmap == kernel_pmap || pmap == PCPU_GET(curpmap))
+               invlpg(va);
+       else if (pmap_pcid_enabled)
+               pmap->pm_pcids[0].pm_gen = 0;
 }
 
-PMAP_INLINE void
+void
 pmap_invalidate_range(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
 {
        vm_offset_t addr;
 
-       switch (pmap->pm_type) {
-       case PT_X86:
-               if (pmap == kernel_pmap || !CPU_EMPTY(&pmap->pm_active))
-                       for (addr = sva; addr < eva; addr += PAGE_SIZE)
-                               invlpg(addr);
-               break;
-       case PT_RVI:
-       case PT_EPT:
+       if (pmap->pm_type == PT_RVI || pmap->pm_type == PT_EPT) {
                pmap->pm_eptgen++;
-               break;
-       default:
-               panic("pmap_invalidate_range: unknown type: %d", pmap->pm_type);
+               return;
+       }
+       KASSERT(pmap->pm_type == PT_X86,
+           ("pmap_invalidate_range: unknown type %d", pmap->pm_type));
+
+       if (pmap == kernel_pmap || pmap == PCPU_GET(curpmap)) {
+               for (addr = sva; addr < eva; addr += PAGE_SIZE)
+                       invlpg(addr);
+       } else if (pmap_pcid_enabled) {
+               pmap->pm_pcids[0].pm_gen = 0;
        }
 }
 
-PMAP_INLINE void
+void
 pmap_invalidate_all(pmap_t pmap)
 {
+       struct invpcid_descr d;
 
-       switch (pmap->pm_type) {
-       case PT_X86:
-               if (pmap == kernel_pmap || !CPU_EMPTY(&pmap->pm_active))
-                       invltlb();
-               break;
-       case PT_RVI:
-       case PT_EPT:
+       if (pmap->pm_type == PT_RVI || pmap->pm_type == PT_EPT) {
                pmap->pm_eptgen++;
-               break;
-       default:
-               panic("pmap_invalidate_all: unknown type %d", pmap->pm_type);
+               return;
+       }
+       KASSERT(pmap->pm_type == PT_X86,
+           ("pmap_invalidate_all: unknown type %d", pmap->pm_type));
+
+       if (pmap == kernel_pmap) {
+               if (pmap_pcid_enabled && invpcid_works) {
+                       bzero(&d, sizeof(d));
+                       invpcid(&d, INVPCID_CTXGLOB);
+               } else {
+                       invltlb_globpcid();
+               }
+       } else if (pmap == PCPU_GET(curpmap)) {
+               if (pmap_pcid_enabled) {
+                       if (invpcid_works) {
+                               d.pcid = pmap->pm_pcids[0].pm_pcid;
+                               d.pad = 0;
+                               d.addr = 0;
+                               invpcid(&d, INVPCID_CTX);
+                       } else {
+                               load_cr3(pmap->pm_cr3 | pmap->pm_pcids[0].
+                                   pm_pcid);
+                       }
+               } else {
+                       invltlb();
+               }
+       } else if (pmap_pcid_enabled) {
+               pmap->pm_pcids[0].pm_gen = 0;
        }
 }
 
@@ -1629,10 +1643,10 @@ pmap_update_pde(pmap_t pmap, vm_offset_t
 {
 
        pmap_update_pde_store(pmap, pde, newpde);
-       if (pmap == kernel_pmap || !CPU_EMPTY(&pmap->pm_active))
+       if (pmap == kernel_pmap || pmap == PCPU_GET(curpmap))
                pmap_update_pde_invalidate(pmap, va, newpde);
        else
-               CPU_ZERO(&pmap->pm_save);
+               pmap->pm_pcids[0].pm_gen = 0;
 }
 #endif /* !SMP */
 
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to