Source-Changes-HG archive

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

[src/sommerfeld_i386mp_1]: src/sys/arch/i386 - Keep track of which CPUs are u...



details:   https://anonhg.NetBSD.org/src/rev/4018f51d7cf5
branches:  sommerfeld_i386mp_1
changeset: 482332:4018f51d7cf5
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Sun Dec 31 18:01:21 2000 +0000

description:
- Keep track of which CPUs are using a given pmap, and use this
  information to flush the APTE space of other CPUs as necessary.
- Use atomic operations in the appropriate places to avoid race
  conditions between the kernel and the CPU microcode which could
  lose modified/referenced information.

Reviewed by Bill Sommerfeld.

diffstat:

 sys/arch/i386/i386/locore.s     |   28 ++---
 sys/arch/i386/i386/pmap.c       |  165 +++++++++++++++++++++++----------------
 sys/arch/i386/i386/vm_machdep.c |   18 ++-
 sys/arch/i386/include/pmap.h    |   16 ++-
 4 files changed, 130 insertions(+), 97 deletions(-)

diffs (truncated from 521 to 300 lines):

diff -r f42d726cb2c1 -r 4018f51d7cf5 sys/arch/i386/i386/locore.s
--- a/sys/arch/i386/i386/locore.s       Sun Dec 31 17:45:51 2000 +0000
+++ b/sys/arch/i386/i386/locore.s       Sun Dec 31 18:01:21 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: locore.s,v 1.215.2.15 2000/11/18 22:52:24 sommerfeld Exp $     */
+/*     $NetBSD: locore.s,v 1.215.2.16 2000/12/31 18:01:21 thorpej Exp $        */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -2004,6 +2004,10 @@
         *   %edi - new process
         */
 
+       pushl   %esi
+       call    _C_LABEL(pmap_deactivate)       # pmap_deactivate(oldproc)
+       addl    $4,%esp
+
        movl    P_ADDR(%esi),%esi
 
        /* Save segment registers. */
@@ -2158,6 +2162,10 @@
         *   %edi - new process
         */
 
+       pushl   %esi
+       call    _C_LABEL(pmap_deactivate)       # pmap_deactivate(oldproc)
+       addl    $4,%esp
+
        movl    P_ADDR(%esi),%esi
 
        /* Save segment registers. */
@@ -2198,25 +2206,13 @@
        movl    _C_LABEL(gdt),%eax
        movl    PCB_TSS_SEL(%esi),%edx
 
-       /* Switch address space. */
-       movl    PCB_CR3(%esi),%ecx
-       movl    %ecx,%cr3
-
        /* Switch TSS. Reset "task busy" flag before */
        andl    $~0x0200,4(%eax,%edx, 1)
        ltr     %dx
 
-#ifdef USER_LDT
-       /*
-        * Switch LDT.
-        *
-        * XXX
-        * Always do this, because the LDT could have been swapped into a
-        * different selector after a process exited.  (See gdt_compact().)
-        */
-       movl    PCB_LDT_SEL(%esi),%edx
-       lldt    %dx
-#endif /* USER_LDT */
+       pushl   %edi
+       call    _C_LABEL(pmap_activate)         # pmap_activate(p)
+       addl    $4,%esp
 
        /* Restore segment registers. */
        movl    PCB_FS(%esi),%eax
diff -r f42d726cb2c1 -r 4018f51d7cf5 sys/arch/i386/i386/pmap.c
--- a/sys/arch/i386/i386/pmap.c Sun Dec 31 17:45:51 2000 +0000
+++ b/sys/arch/i386/i386/pmap.c Sun Dec 31 18:01:21 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pmap.c,v 1.83.2.13 2000/11/18 23:10:52 sommerfeld Exp $        */
+/*     $NetBSD: pmap.c,v 1.83.2.14 2000/12/31 18:01:21 thorpej Exp $   */
 
 /*
  *
@@ -73,6 +73,7 @@
 
 #include <uvm/uvm.h>
 
+#include <machine/atomic.h>
 #include <machine/cpu.h>
 #include <machine/specialreg.h>
 #include <machine/gdt.h>
@@ -509,14 +510,16 @@
 
 /*
  * pmap_is_active: is this pmap loaded into any processor's %cr3?
- *             XXX we assume it is for now.  
  */
 
 __inline static boolean_t
 pmap_is_active(pmap)
        struct pmap *pmap;
 {
-       return((pmap == pmap_kernel()) || 1);
+       int cpu_id = cpu_number();
+
+       return (pmap == pmap_kernel() ||
+           (pmap->pm_cpus & (1U << cpu_id)) != 0);
 }
 
 /*
@@ -603,6 +606,37 @@
        pmap_tmpunmap_pa();
 }
 
+__inline static void
+pmap_apte_flush(struct pmap *pmap)
+{
+#if defined(MULTIPROCESSOR)
+       struct pmap_tlb_shootdown_q *pq;
+       struct cpu_info *ci, *self = curcpu();
+       CPU_INFO_ITERATOR cii;
+#endif
+
+       tlbflush();             /* flush TLB on current processor */
+#if defined(MULTIPROCESSOR)
+       /*
+        * Flush the APTE mapping from all other CPUs that
+        * are using the pmap we are using (who's APTE space
+        * is the one we've just modified).
+        */
+       for (CPU_INFO_FOREACH(cii, ci)) {
+               if (ci == self)
+                       continue;
+               if (pmap == pmap_kernel() ||
+                   (pmap->pm_cpus & (1U << ci->ci_cpuid)) != 0) {
+                       pq = &pmap_tlb_shootdown_q[ci->ci_cpuid];
+                       simple_lock(&pq->pq_slock);
+                       pq->pq_flushu++;
+                       simple_unlock(&pq->pq_slock);
+                       i386_send_ipi(ci, I386_IPI_TLB);
+               }
+       }
+#endif
+}
+
 /*
  * pmap_map_ptes: map a pmap's PTEs into KVM and lock them in
  *
@@ -641,10 +675,8 @@
        opde = *APDP_PDE;
        if (!pmap_valid_entry(opde) || (opde & PG_FRAME) != pmap->pm_pdirpa) {
                *APDP_PDE = (pd_entry_t) (pmap->pm_pdirpa | PG_RW | PG_V);
-               if (pmap_valid_entry(opde)) {
-                       pmap_update();
-                       /* XXX MP do invalidate on all cpu's touching this pmap */
-               }
+               if (pmap_valid_entry(opde))
+                       pmap_apte_flush(curpcb->pcb_pmap);
        }
        return(APTE_BASE);
 }
@@ -663,10 +695,9 @@
        if (pmap_is_curpmap(pmap)) {
                simple_unlock(&pmap->pm_obj.vmobjlock);
        } else {
-#if 0
+#if defined(MULTIPROCESSOR)
                *APDP_PDE = 0;
-               pmap_update();
-               /* XXX MP need floosh here? */
+               pmap_apte_flush(curpcb->pcb_pmap);
 #endif
                COUNT(apdp_pde_unmap);
                simple_unlock(&pmap->pm_obj.vmobjlock);
@@ -695,12 +726,15 @@
        paddr_t pa;
        vm_prot_t prot;
 {
-       pt_entry_t *pte, opte;
+       pt_entry_t *pte, opte, npte;
 
        pte = vtopte(va);
-       opte = *pte;
-       *pte = pa | ((prot & VM_PROT_WRITE)? PG_RW : PG_RO) |
-               PG_V | pmap_pg_g;       /* zap! */
+
+       npte = pa | ((prot & VM_PROT_WRITE)? PG_RW : PG_RO) |
+            PG_V | pmap_pg_g;
+
+       opte = i386_atomic_testset_ul(pte, npte); /* zap! */
+
        if (pmap_valid_entry(opte)) {
                pmap_update_pg(va);
 #ifdef MULTIPROCESSOR
@@ -731,9 +765,7 @@
        len >>= PAGE_SHIFT;
        for ( /* null */ ; len ; len--, va += NBPG) {
                pte = vtopte(va);
-               /* XXX R/M update goo? */
-               opte = *pte;
-               *pte = 0;               /* zap! */
+               opte = i386_atomic_testset_ul(pte, 0); /* zap! */
 #ifdef DIAGNOSTIC
                if (opte & PG_PVLIST)
                        panic("pmap_kremove: PG_PVLIST mapping for 0x%lx\n",
@@ -777,7 +809,6 @@
        for (lcv = 0 ; lcv < npgs ; lcv++) {
                tva = va + lcv * NBPG;
                pte = vtopte(tva);
-               /* XXX pte update goo? R/M bits? */
                opte = *pte;
                *pte = VM_PAGE_TO_PHYS(pgs[lcv]) | PG_RW | PG_V | pmap_pg_g;
 #if defined(I386_CPU)
@@ -2036,7 +2067,10 @@
                uvm_pagefree(pg);
        }
 
-       /* XXX: need to flush it out of other processor's APTE space? */
+       /*
+        * MULTIPROCESSOR -- no need to flush out of other processors'
+        * APTE space because we do that in pmap_unmap_ptes().
+        */
        uvm_km_free(kernel_map, (vaddr_t)pmap->pm_pdir, NBPG);
 
 #ifdef USER_LDT
@@ -2153,22 +2187,31 @@
        pcb->pcb_pmap = pmap;
        pcb->pcb_ldt_sel = pmap->pm_ldt_sel;
        pcb->pcb_cr3 = pmap->pm_pdirpa;
-       if (p == curproc)
+       if (p == curproc) {
                lcr3(pcb->pcb_cr3);
-       if (pcb == curpcb)
                lldt(pcb->pcb_ldt_sel);
+
+               /*
+                * mark the pmap in use by this processor.
+                */
+               i386_atomic_setbits_l(&pmap->pm_cpus, (1U << cpu_number()));
+       }
 }
 
 /*
  * pmap_deactivate: deactivate a process' pmap
- *
- * => XXX: what should this do, if anything?
  */
 
 void
 pmap_deactivate(p)
        struct proc *p;
 {
+       struct pmap *pmap = p->p_vmspace->vm_map.pmap;
+
+       /*
+        * mark the pmap no longer in use by this processor.
+        */
+       i386_atomic_clearbits_l(&pmap->pm_cpus, (1U << cpu_number()));
 }
 
 /*
@@ -2430,9 +2473,9 @@
                if (!pmap_valid_entry(*pte))
                        continue;                       /* VA not mapped */
 
-               /* XXX use lock xchgl here */
-               opte = *pte;            /* save the old PTE */
-               *pte = 0;                       /* zap! */
+               /* atomically save the old PTE and zap! it */
+               opte = i386_atomic_testset_ul(pte, 0);
+
                if (opte & PG_W)
                        pmap->pm_stats.wired_count--;
                pmap->pm_stats.resident_count--;
@@ -2507,9 +2550,8 @@
        if (!pmap_valid_entry(*pte))
                return(FALSE);          /* VA not mapped */
 
-       /* XXX use lock xchgl here */
-       opte = *pte;                    /* save the old PTE */
-       *pte = 0;                       /* zap! */
+       /* atomically save the old PTE and zap! it */
+       opte = i386_atomic_testset_ul(pte, 0);
 
        if (opte & PG_W)
                pmap->pm_stats.wired_count--;
@@ -2796,8 +2838,8 @@
                }
 #endif
 
-               opte = ptes[i386_btop(pve->pv_va)];
-               ptes[i386_btop(pve->pv_va)] = 0;                /* zap! */
+               /* atomically save the old PTE and zap! it */
+               opte = i386_atomic_testset_ul(&ptes[i386_btop(pve->pv_va)], 0);
 
                if (opte & PG_W)
                        pve->pv_pmap->pm_stats.wired_count--;
@@ -2920,22 +2962,22 @@
 }
 
 /*
- * pmap_change_attrs: change a page's attributes
+ * pmap_clear_attrs: clear the specified attribute for a page.
  *
  * => we set pv_head => pmap locking
  * => we return TRUE if we cleared one of the bits we were asked to
  */
 
 boolean_t
-pmap_change_attrs(pg, setbits, clearbits)
+pmap_clear_attrs(pg, clearbits)
        struct vm_page *pg;
-       int setbits, clearbits;
+       int clearbits;



Home | Main Index | Thread Index | Old Index