Author: jah
Date: Fri Dec 23 15:14:56 2016
New Revision: 310481
URL: https://svnweb.freebsd.org/changeset/base/310481

Log:
  Move the objects used to create temporary mappings for i386 pmap zero and copy
  operations to the MD PCPU region.  Change sysmap initialization to only
  allocate KVA pages for CPUs that are actually present.  As a minor
  optimization, this also prevents false sharing between adjacent sysmap objects
  since the pcpu struct is already cacheline-aligned.
  
  While here, move pc_qmap_addr initialization for the BSP into
  pmap_bootstrap(), which allows use of pmap_quick* functions during early boot.
  
  Reviewed by:  kib
  MFC after:    2 weeks
  Differential Revision:        https://reviews.freebsd.org/D8833

Modified:
  head/sys/i386/i386/pmap.c
  head/sys/i386/include/pcpu.h

Modified: head/sys/i386/i386/pmap.c
==============================================================================
--- head/sys/i386/i386/pmap.c   Fri Dec 23 15:05:41 2016        (r310480)
+++ head/sys/i386/i386/pmap.c   Fri Dec 23 15:14:56 2016        (r310481)
@@ -257,14 +257,6 @@ vm_offset_t pv_vafree;                     /* freelist sto
 /*
  * All those kernel PT submaps that BSD is so fond of
  */
-struct sysmaps {
-       struct  mtx lock;
-       pt_entry_t *CMAP1;
-       pt_entry_t *CMAP2;
-       caddr_t CADDR1;
-       caddr_t CADDR2;
-};
-static struct sysmaps sysmaps_pcpu[MAXCPU];
 pt_entry_t *CMAP3;
 static pd_entry_t *KPTD;
 caddr_t ptvmmap = 0;
@@ -379,7 +371,7 @@ pmap_bootstrap(vm_paddr_t firstaddr)
 {
        vm_offset_t va;
        pt_entry_t *pte, *unused;
-       struct sysmaps *sysmaps;
+       struct pcpu *pc;
        int i;
 
        /*
@@ -441,16 +433,19 @@ pmap_bootstrap(vm_paddr_t firstaddr)
        va = virtual_avail;
        pte = vtopte(va);
 
+
        /*
+        * Initialize temporary map objects on the current CPU for use
+        * during early boot.
         * CMAP1/CMAP2 are used for zeroing and copying pages.
         * CMAP3 is used for the boot-time memory test.
         */
-       for (i = 0; i < MAXCPU; i++) {
-               sysmaps = &sysmaps_pcpu[i];
-               mtx_init(&sysmaps->lock, "SYSMAPS", NULL, MTX_DEF);
-               SYSMAP(caddr_t, sysmaps->CMAP1, sysmaps->CADDR1, 1)
-               SYSMAP(caddr_t, sysmaps->CMAP2, sysmaps->CADDR2, 1)
-       }
+       pc = pcpu_find(curcpu);
+       mtx_init(&pc->pc_cmap_lock, "SYSMAPS", NULL, MTX_DEF);
+       SYSMAP(caddr_t, pc->pc_cmap_pte1, pc->pc_cmap_addr1, 1)
+       SYSMAP(caddr_t, pc->pc_cmap_pte2, pc->pc_cmap_addr2, 1)
+       SYSMAP(vm_offset_t, pte, pc->pc_qmap_addr, 1)
+
        SYSMAP(caddr_t, CMAP3, CADDR3, 1);
 
        /*
@@ -520,20 +515,33 @@ pmap_bootstrap(vm_paddr_t firstaddr)
 }
 
 static void
-pmap_init_qpages(void)
+pmap_init_reserved_pages(void)
 {
        struct pcpu *pc;
+       vm_offset_t pages;
        int i;
 
        CPU_FOREACH(i) {
                pc = pcpu_find(i);
-               pc->pc_qmap_addr = kva_alloc(PAGE_SIZE);
-               if (pc->pc_qmap_addr == 0)
-                       panic("pmap_init_qpages: unable to allocate KVA");
+               /*
+                * Skip if the mapping has already been initialized,
+                * i.e. this is the BSP.
+                */
+               if (pc->pc_cmap_addr1 != 0)
+                       continue;
+               mtx_init(&pc->pc_cmap_lock, "SYSMAPS", NULL, MTX_DEF);
+               pages = kva_alloc(PAGE_SIZE * 3);
+               if (pages == 0)
+                       panic("%s: unable to allocate KVA", __func__);
+               pc->pc_cmap_pte1 = vtopte(pages);
+               pc->pc_cmap_pte2 = vtopte(pages + PAGE_SIZE);
+               pc->pc_cmap_addr1 = (caddr_t)pages;
+               pc->pc_cmap_addr2 = (caddr_t)(pages + PAGE_SIZE);
+               pc->pc_qmap_addr = pages + (PAGE_SIZE * 2);
        }
 }
-
-SYSINIT(qpages_init, SI_SUB_CPU, SI_ORDER_ANY, pmap_init_qpages, NULL);
+ 
+SYSINIT(rpages_init, SI_SUB_CPU, SI_ORDER_ANY, pmap_init_reserved_pages, NULL);
 
 /*
  * Setup the PAT MSR.
@@ -4194,20 +4202,22 @@ pagezero(void *page)
 void
 pmap_zero_page(vm_page_t m)
 {
-       struct sysmaps *sysmaps;
+       pt_entry_t *cmap_pte2;
+       struct pcpu *pc;
 
-       sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
-       mtx_lock(&sysmaps->lock);
-       if (*sysmaps->CMAP2)
-               panic("pmap_zero_page: CMAP2 busy");
        sched_pin();
-       *sysmaps->CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M |
+       pc = pcpu_find(curcpu);
+       cmap_pte2 = pc->pc_cmap_pte2;
+       mtx_lock(&pc->pc_cmap_lock);
+       if (*cmap_pte2)
+               panic("pmap_zero_page: CMAP2 busy");
+       *cmap_pte2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M |
            pmap_cache_bits(m->md.pat_mode, 0);
-       invlcaddr(sysmaps->CADDR2);
-       pagezero(sysmaps->CADDR2);
-       *sysmaps->CMAP2 = 0;
+       invlcaddr(pc->pc_cmap_addr2);
+       pagezero(pc->pc_cmap_addr2);
+       *cmap_pte2 = 0;
+       mtx_unlock(&pc->pc_cmap_lock);
        sched_unpin();
-       mtx_unlock(&sysmaps->lock);
 }
 
 /*
@@ -4217,23 +4227,25 @@ pmap_zero_page(vm_page_t m)
 void
 pmap_zero_page_area(vm_page_t m, int off, int size)
 {
-       struct sysmaps *sysmaps;
+       pt_entry_t *cmap_pte2;
+       struct pcpu *pc;
 
-       sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
-       mtx_lock(&sysmaps->lock);
-       if (*sysmaps->CMAP2)
-               panic("pmap_zero_page_area: CMAP2 busy");
        sched_pin();
-       *sysmaps->CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M |
+       pc = pcpu_find(curcpu);
+       cmap_pte2 = pc->pc_cmap_pte2;
+       mtx_lock(&pc->pc_cmap_lock);
+       if (*cmap_pte2)
+               panic("pmap_zero_page_area: CMAP2 busy");
+       *cmap_pte2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M |
            pmap_cache_bits(m->md.pat_mode, 0);
-       invlcaddr(sysmaps->CADDR2);
+       invlcaddr(pc->pc_cmap_addr2);
        if (off == 0 && size == PAGE_SIZE) 
-               pagezero(sysmaps->CADDR2);
+               pagezero(pc->pc_cmap_addr2);
        else
-               bzero((char *)sysmaps->CADDR2 + off, size);
-       *sysmaps->CMAP2 = 0;
+               bzero(pc->pc_cmap_addr2 + off, size);
+       *cmap_pte2 = 0;
+       mtx_unlock(&pc->pc_cmap_lock);
        sched_unpin();
-       mtx_unlock(&sysmaps->lock);
 }
 
 /*
@@ -4242,26 +4254,29 @@ pmap_zero_page_area(vm_page_t m, int off
 void
 pmap_copy_page(vm_page_t src, vm_page_t dst)
 {
-       struct sysmaps *sysmaps;
+       pt_entry_t *cmap_pte1, *cmap_pte2;
+       struct pcpu *pc;
 
-       sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
-       mtx_lock(&sysmaps->lock);
-       if (*sysmaps->CMAP1)
+       sched_pin();
+       pc = pcpu_find(curcpu);
+       cmap_pte1 = pc->pc_cmap_pte1; 
+       cmap_pte2 = pc->pc_cmap_pte2;
+       mtx_lock(&pc->pc_cmap_lock);
+       if (*cmap_pte1)
                panic("pmap_copy_page: CMAP1 busy");
-       if (*sysmaps->CMAP2)
+       if (*cmap_pte2)
                panic("pmap_copy_page: CMAP2 busy");
-       sched_pin();
-       *sysmaps->CMAP1 = PG_V | VM_PAGE_TO_PHYS(src) | PG_A |
+       *cmap_pte1 = PG_V | VM_PAGE_TO_PHYS(src) | PG_A |
            pmap_cache_bits(src->md.pat_mode, 0);
-       invlcaddr(sysmaps->CADDR1);
-       *sysmaps->CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(dst) | PG_A | PG_M |
+       invlcaddr(pc->pc_cmap_addr1);
+       *cmap_pte2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(dst) | PG_A | PG_M |
            pmap_cache_bits(dst->md.pat_mode, 0);
-       invlcaddr(sysmaps->CADDR2);
-       bcopy(sysmaps->CADDR1, sysmaps->CADDR2, PAGE_SIZE);
-       *sysmaps->CMAP1 = 0;
-       *sysmaps->CMAP2 = 0;
+       invlcaddr(pc->pc_cmap_addr2);
+       bcopy(pc->pc_cmap_addr1, pc->pc_cmap_addr2, PAGE_SIZE);
+       *cmap_pte1 = 0;
+       *cmap_pte2 = 0;
+       mtx_unlock(&pc->pc_cmap_lock);
        sched_unpin();
-       mtx_unlock(&sysmaps->lock);
 }
 
 int unmapped_buf_allowed = 1;
@@ -4270,19 +4285,22 @@ void
 pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[],
     vm_offset_t b_offset, int xfersize)
 {
-       struct sysmaps *sysmaps;
        vm_page_t a_pg, b_pg;
        char *a_cp, *b_cp;
        vm_offset_t a_pg_offset, b_pg_offset;
+       pt_entry_t *cmap_pte1, *cmap_pte2;
+       struct pcpu *pc;
        int cnt;
 
-       sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
-       mtx_lock(&sysmaps->lock);
-       if (*sysmaps->CMAP1 != 0)
+       sched_pin();
+       pc = pcpu_find(curcpu);
+       cmap_pte1 = pc->pc_cmap_pte1; 
+       cmap_pte2 = pc->pc_cmap_pte2;
+       mtx_lock(&pc->pc_cmap_lock);
+       if (*cmap_pte1 != 0)
                panic("pmap_copy_pages: CMAP1 busy");
-       if (*sysmaps->CMAP2 != 0)
+       if (*cmap_pte2 != 0)
                panic("pmap_copy_pages: CMAP2 busy");
-       sched_pin();
        while (xfersize > 0) {
                a_pg = ma[a_offset >> PAGE_SHIFT];
                a_pg_offset = a_offset & PAGE_MASK;
@@ -4290,23 +4308,23 @@ pmap_copy_pages(vm_page_t ma[], vm_offse
                b_pg = mb[b_offset >> PAGE_SHIFT];
                b_pg_offset = b_offset & PAGE_MASK;
                cnt = min(cnt, PAGE_SIZE - b_pg_offset);
-               *sysmaps->CMAP1 = PG_V | VM_PAGE_TO_PHYS(a_pg) | PG_A |
+               *cmap_pte1 = PG_V | VM_PAGE_TO_PHYS(a_pg) | PG_A |
                    pmap_cache_bits(a_pg->md.pat_mode, 0);
-               invlcaddr(sysmaps->CADDR1);
-               *sysmaps->CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(b_pg) | PG_A |
+               invlcaddr(pc->pc_cmap_addr1);
+               *cmap_pte2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(b_pg) | PG_A |
                    PG_M | pmap_cache_bits(b_pg->md.pat_mode, 0);
-               invlcaddr(sysmaps->CADDR2);
-               a_cp = sysmaps->CADDR1 + a_pg_offset;
-               b_cp = sysmaps->CADDR2 + b_pg_offset;
+               invlcaddr(pc->pc_cmap_addr2);
+               a_cp = pc->pc_cmap_addr1 + a_pg_offset;
+               b_cp = pc->pc_cmap_addr2 + b_pg_offset;
                bcopy(a_cp, b_cp, cnt);
                a_offset += cnt;
                b_offset += cnt;
                xfersize -= cnt;
        }
-       *sysmaps->CMAP1 = 0;
-       *sysmaps->CMAP2 = 0;
+       *cmap_pte1 = 0;
+       *cmap_pte2 = 0;
+       mtx_unlock(&pc->pc_cmap_lock);
        sched_unpin();
-       mtx_unlock(&sysmaps->lock);
 }
 
 /*
@@ -5247,21 +5265,23 @@ pmap_page_set_memattr(vm_page_t m, vm_me
 static void
 pmap_flush_page(vm_page_t m)
 {
-       struct sysmaps *sysmaps;
+       pt_entry_t *cmap_pte2;
+       struct pcpu *pc;
        vm_offset_t sva, eva;
        bool useclflushopt;
 
        useclflushopt = (cpu_stdext_feature & CPUID_STDEXT_CLFLUSHOPT) != 0;
        if (useclflushopt || (cpu_feature & CPUID_CLFSH) != 0) {
-               sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
-               mtx_lock(&sysmaps->lock);
-               if (*sysmaps->CMAP2)
-                       panic("pmap_flush_page: CMAP2 busy");
                sched_pin();
-               *sysmaps->CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) |
+               pc = pcpu_find(curcpu);
+               cmap_pte2 = pc->pc_cmap_pte2; 
+               mtx_lock(&pc->pc_cmap_lock);
+               if (*cmap_pte2)
+                       panic("pmap_flush_page: CMAP2 busy");
+               *cmap_pte2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) |
                    PG_A | PG_M | pmap_cache_bits(m->md.pat_mode, 0);
-               invlcaddr(sysmaps->CADDR2);
-               sva = (vm_offset_t)sysmaps->CADDR2;
+               invlcaddr(pc->pc_cmap_addr2);
+               sva = (vm_offset_t)pc->pc_cmap_addr2;
                eva = sva + PAGE_SIZE;
 
                /*
@@ -5280,9 +5300,9 @@ pmap_flush_page(vm_page_t m)
                }
                if (useclflushopt || cpu_vendor_id != CPU_VENDOR_INTEL)
                        mfence();
-               *sysmaps->CMAP2 = 0;
+               *cmap_pte2 = 0;
+               mtx_unlock(&pc->pc_cmap_lock);
                sched_unpin();
-               mtx_unlock(&sysmaps->lock);
        } else
                pmap_invalidate_cache();
 }

Modified: head/sys/i386/include/pcpu.h
==============================================================================
--- head/sys/i386/include/pcpu.h        Fri Dec 23 15:05:41 2016        
(r310480)
+++ head/sys/i386/include/pcpu.h        Fri Dec 23 15:14:56 2016        
(r310481)
@@ -36,6 +36,9 @@
 #include <machine/segments.h>
 #include <machine/tss.h>
 
+#include <sys/_lock.h>
+#include <sys/_mutex.h>
+
 /*
  * The SMP parts are setup in pmap.c and locore.s for the BSP, and
  * mp_machdep.c sets up the data for the AP's to "see" when they awake.
@@ -58,9 +61,14 @@
        int     pc_private_tss;         /* Flag indicating private tss*/\
        u_int   pc_cmci_mask;           /* MCx banks for CMCI */        \
        u_int   pc_vcpu_id;             /* Xen vCPU ID */               \
+       struct  mtx pc_cmap_lock;                                       \
+       void    *pc_cmap_pte1;                                          \
+       void    *pc_cmap_pte2;                                          \
+       caddr_t pc_cmap_addr1;                                          \
+       caddr_t pc_cmap_addr2;                                          \
        vm_offset_t pc_qmap_addr;       /* KVA for temporary mappings */\
        uint32_t pc_smp_tlb_done;       /* TLB op acknowledgement */    \
-       char    __pad[225]
+       char    __pad[189]
 
 #ifdef _KERNEL
 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to