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