Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 28 Aug 2003 20:20:11 +0000 (GMT)
From:      Tor Egge <Tor.Egge@cvsup.no.freebsd.org>
To:        mike@sentex.net
Cc:        stable@freebsd.org
Subject:   Re: Ok, are all the panics fixed now?
Message-ID:  <20030828.202011.41715185.Tor.Egge@cvsup.no.freebsd.org>
In-Reply-To: <5.2.0.9.0.20030828153925.03f3ed80@209.112.4.2>
References:  <20030827133126.D4269@odysseus.silby.com> <20030828.161240.74667710.Tor.Egge@cvsup.no.freebsd.org> <5.2.0.9.0.20030828153925.03f3ed80@209.112.4.2>

next in thread | previous in thread | raw e-mail | index | archive | help
----Next_Part(Thu_Aug_28_20:20:11_2003_868)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

> 
> Hi,
>          Forgive the naive question, but is this an easy issue to solve ? 
> Or is it just scratching the surface of a larger more complex problem not 
> easily resolved by a simple patch or two ?

I'm enclosed a patch that introduces PADDR2/PMAP2 which is to be used
by pmap_pte() (should not be called from interrupts on noncurrent
pmaps) while pmap_pte_quick() (should not be called without splvm()
protection) will use PADDR1/PMAP1.

The patch also backs out revision 1.250.2.20 of
src/sys/i386/i386/pmap.c.

- Tor Egge


----Next_Part(Thu_Aug_28_20:20:11_2003_868)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="paefix.diff2"

Index: sys/i386/i386/mp_machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/i386/mp_machdep.c,v
retrieving revision 1.115.2.17
diff -u -r1.115.2.17 mp_machdep.c
--- sys/i386/i386/mp_machdep.c	9 Aug 2003 16:21:18 -0000	1.115.2.17
+++ sys/i386/i386/mp_machdep.c	28 Aug 2003 20:05:38 -0000
@@ -2133,13 +2133,14 @@
 		/* allocate and set up an idle stack data page */
 		stack = (char *)kmem_alloc(kernel_map, UPAGES*PAGE_SIZE);
 		for (i = 0; i < UPAGES; i++)
-			SMPpt[pg + 5 + i] = (pt_entry_t)
+			SMPpt[pg + 6 + i] = (pt_entry_t)
 			    (PG_V | PG_RW | vtophys(PAGE_SIZE * i + stack));
 
 		SMPpt[pg + 1] = 0;		/* *prv_CMAP1 */
 		SMPpt[pg + 2] = 0;		/* *prv_CMAP2 */
 		SMPpt[pg + 3] = 0;		/* *prv_CMAP3 */
 		SMPpt[pg + 4] = 0;		/* *prv_PMAP1 */
+		SMPpt[pg + 5] = 0;		/* *prv_PMAP2 */
 
 		/* prime data page for it to use */
 		gd->gd_cpuid = x;
@@ -2148,10 +2149,12 @@
 		gd->gd_prv_CMAP2 = &SMPpt[pg + 2];
 		gd->gd_prv_CMAP3 = &SMPpt[pg + 3];
 		gd->gd_prv_PMAP1 = (pd_entry_t *)&SMPpt[pg + 4];
+		gd->gd_prv_PMAP2 = (pd_entry_t *)&SMPpt[pg + 5];
 		gd->gd_prv_CADDR1 = SMP_prvspace[x].CPAGE1;
 		gd->gd_prv_CADDR2 = SMP_prvspace[x].CPAGE2;
 		gd->gd_prv_CADDR3 = SMP_prvspace[x].CPAGE3;
 		gd->gd_prv_PADDR1 = (pt_entry_t *)SMP_prvspace[x].PPAGE1;
+		gd->gd_prv_PADDR2 = (pt_entry_t *)SMP_prvspace[x].PPAGE2;
 
 		/* setup a vector to our boot code */
 		*((volatile u_short *) WARMBOOT_OFF) = WARMBOOT_TARGET;
@@ -2205,7 +2208,7 @@
 	/* Allocate and setup BSP idle stack */
 	stack = (char *)kmem_alloc(kernel_map, UPAGES * PAGE_SIZE);
 	for (i = 0; i < UPAGES; i++)
-		SMPpt[5 + i] = (pt_entry_t)
+		SMPpt[6 + i] = (pt_entry_t)
 		    (PG_V | PG_RW | vtophys(PAGE_SIZE * i + stack));
 
 	for (x = 0; x < NKPT; x++)
Index: sys/i386/i386/genassym.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/i386/genassym.c,v
retrieving revision 1.86.2.4
diff -u -r1.86.2.4 genassym.c
--- sys/i386/i386/genassym.c	9 Aug 2003 16:21:17 -0000	1.86.2.4
+++ sys/i386/i386/genassym.c	28 Aug 2003 20:05:38 -0000
@@ -198,10 +198,12 @@
 ASSYM(GD_PRV_CMAP2, offsetof(struct globaldata, gd_prv_CMAP2));
 ASSYM(GD_PRV_CMAP3, offsetof(struct globaldata, gd_prv_CMAP3));
 ASSYM(GD_PRV_PMAP1, offsetof(struct globaldata, gd_prv_PMAP1));
+ASSYM(GD_PRV_PMAP2, offsetof(struct globaldata, gd_prv_PMAP2));
 ASSYM(GD_PRV_CADDR1, offsetof(struct globaldata, gd_prv_CADDR1));
 ASSYM(GD_PRV_CADDR2, offsetof(struct globaldata, gd_prv_CADDR2));
 ASSYM(GD_PRV_CADDR3, offsetof(struct globaldata, gd_prv_CADDR3));
 ASSYM(GD_PRV_PADDR1, offsetof(struct globaldata, gd_prv_PADDR1));
+ASSYM(GD_PRV_PADDR2, offsetof(struct globaldata, gd_prv_PADDR2));
 ASSYM(PS_IDLESTACK, offsetof(struct privatespace, idlestack));
 ASSYM(PS_IDLESTACK_TOP, sizeof(struct privatespace));
 #endif
Index: sys/i386/i386/globals.s
===================================================================
RCS file: /home/ncvs/src/sys/i386/i386/Attic/globals.s,v
retrieving revision 1.13.2.1
diff -u -r1.13.2.1 globals.s
--- sys/i386/i386/globals.s	16 May 2000 06:58:06 -0000	1.13.2.1
+++ sys/i386/i386/globals.s	28 Aug 2003 20:05:38 -0000
@@ -109,7 +109,9 @@
 	.globl  gd_cpuid, gd_cpu_lockid, gd_other_cpus
 	.globl	gd_ss_eflags, gd_inside_intr
 	.globl  gd_prv_CMAP1, gd_prv_CMAP2, gd_prv_CMAP3, gd_prv_PMAP1
+        .globl  gd_prv_PMAP2
 	.globl  gd_prv_CADDR1, gd_prv_CADDR2, gd_prv_CADDR3, gd_prv_PADDR1
+        .globl  gd_prv_PADDR2
 
 	.set    gd_cpuid,globaldata + GD_CPUID
 	.set    gd_cpu_lockid,globaldata + GD_CPU_LOCKID
@@ -120,10 +122,12 @@
 	.set    gd_prv_CMAP2,globaldata + GD_PRV_CMAP2
 	.set    gd_prv_CMAP3,globaldata + GD_PRV_CMAP3
 	.set    gd_prv_PMAP1,globaldata + GD_PRV_PMAP1
+	.set    gd_prv_PMAP2,globaldata + GD_PRV_PMAP2
 	.set    gd_prv_CADDR1,globaldata + GD_PRV_CADDR1
 	.set    gd_prv_CADDR2,globaldata + GD_PRV_CADDR2
 	.set    gd_prv_CADDR3,globaldata + GD_PRV_CADDR3
 	.set    gd_prv_PADDR1,globaldata + GD_PRV_PADDR1
+	.set    gd_prv_PADDR2,globaldata + GD_PRV_PADDR2
 #endif
 
 #if defined(SMP) || defined(APIC_IO)
Index: sys/i386/i386/pmap.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/i386/pmap.c,v
retrieving revision 1.250.2.20
diff -u -r1.250.2.20 pmap.c
--- sys/i386/i386/pmap.c	26 Aug 2003 05:35:00 -0000	1.250.2.20
+++ sys/i386/i386/pmap.c	28 Aug 2003 20:05:38 -0000
@@ -114,6 +114,8 @@
 #include <sys/mman.h>
 #include <sys/malloc.h>
 
+#include <machine/cpu.h>
+#include <machine/ipl.h>
 #include <vm/vm.h>
 #include <vm/vm_param.h>
 #include <sys/sysctl.h>
@@ -215,15 +217,19 @@
 #define	CMAP2	prv_CMAP2
 #define	CMAP3	prv_CMAP3
 #define	PMAP1	prv_PMAP1
+#define	PMAP2	prv_PMAP2
 #define	CADDR1	prv_CADDR1
 #define	CADDR2	prv_CADDR2
 #define	CADDR3	prv_CADDR3
 #define	PADDR1	prv_PADDR1
+#define	PADDR2  prv_PADDR2
 #else
 static pt_entry_t *CMAP1, *CMAP2, *CMAP3;
 static caddr_t CADDR1, CADDR2, CADDR3;
 static pd_entry_t *PMAP1;
 static pt_entry_t *PADDR1;
+static pd_entry_t *PMAP2;
+static pt_entry_t *PADDR2;
 #endif
 
 static pt_entry_t *ptmmap;
@@ -257,6 +263,7 @@
 
 static vm_page_t pmap_allocpte __P((pmap_t pmap, vm_offset_t va));
 static vm_page_t _pmap_allocpte __P((pmap_t pmap, unsigned ptepindex));
+static pt_entry_t *pmap_pte_quick __P((pmap_t pmap, vm_offset_t va));
 static vm_page_t pmap_page_lookup __P((vm_object_t object, vm_pindex_t pindex));
 static int pmap_unuse_pt __P((pmap_t, vm_offset_t, vm_page_t));
 static vm_offset_t pmap_kmem_choose(vm_offset_t addr);
@@ -364,6 +371,7 @@
 	 * ptemap is used for pmap_pte
 	 */
 	SYSMAP(pd_entry_t *, PMAP1, PADDR1, 1);
+	SYSMAP(pd_entry_t *, PMAP2, PADDR2, 1);
 #endif
 
 	/*
@@ -454,10 +462,12 @@
 	gd->gd_prv_CMAP2 = &SMPpt[2];
 	gd->gd_prv_CMAP3 = &SMPpt[3];
 	gd->gd_prv_PMAP1 = &SMPpt[4];
+	gd->gd_prv_PMAP2 = &SMPpt[5];
 	gd->gd_prv_CADDR1 = SMP_prvspace[0].CPAGE1;
 	gd->gd_prv_CADDR2 = SMP_prvspace[0].CPAGE2;
 	gd->gd_prv_CADDR3 = SMP_prvspace[0].CPAGE3;
 	gd->gd_prv_PADDR1 = (pt_entry_t *)SMP_prvspace[0].PPAGE1;
+	gd->gd_prv_PADDR2 = (pt_entry_t *)SMP_prvspace[0].PPAGE2;
 #endif
 
 	invltlb();
@@ -663,13 +673,18 @@
  *	Function:
  *		Extract the page table entry associated
  *		with the given map/virtual_address pair.
+ *      Note: Must be protected by splvm()
  */
 
-pt_entry_t *
-pmap_pte(pmap_t pmap, vm_offset_t va)
+static pt_entry_t *
+pmap_pte_quick(pmap_t pmap, vm_offset_t va)
 {
 	pd_entry_t *pde, newpf;
 
+#ifdef INVARIANTS
+	if (~cpl & (net_imask | bio_imask | cam_imask))
+		panic("pmap_pte_quick not protected by splvm()");
+#endif
 	pde = pmap_pde(pmap, va);
 	if (*pde & PG_V) {
 		if (*pde & PG_PS)
@@ -691,6 +706,44 @@
 }
 
 /*
+ *	Routine:	pmap_pte
+ *	Function:
+ *		Extract the page table entry associated
+ *		with the given map/virtual_address pair.
+ *      Note: Must not be called from interrupts on non-current pmap
+ */
+
+pt_entry_t *
+pmap_pte(pmap_t pmap, vm_offset_t va)
+{
+	pd_entry_t *pde, newpf;
+
+	pde = pmap_pde(pmap, va);
+	if (*pde & PG_V) {
+		if (*pde & PG_PS)
+			return (pt_entry_t *)pde;
+		if (pmap_is_current(pmap))
+			return vtopte(va);
+#ifdef INVARIANTS
+		if (intr_nesting_level != 0) {
+			panic("pmap_pte called from interrupt");
+		}
+#endif
+		newpf = *pde & PG_FRAME;
+		if ((*PMAP2 & PG_FRAME) != newpf) {
+			*PMAP2 = newpf | PG_RW | PG_V;
+#ifdef SMP
+			cpu_invlpg(PADDR2);
+#else
+			invltlb_1pg((vm_offset_t) PADDR2);
+#endif
+		}
+		return PADDR2 + (i386_btop(va) & (NPTEPG - 1));
+	}
+	return (0);
+}
+
+/*
  *	Routine:	pmap_extract
  *	Function:
  *		Extract the physical page address associated
@@ -1635,8 +1688,8 @@
 		if (nva > eva)
 			nva = eva;
 
-		for (; sva < nva; sva += PAGE_SIZE) {
-			pte = pmap_pte(pmap, sva);
+		pte = pmap_pte(pmap, sva);
+		for (; sva < nva; sva += PAGE_SIZE, pte++) {
 			if ((*pte & PG_V) == 0)
 				continue;
 			
@@ -1684,7 +1737,7 @@
 	while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
 		pv->pv_pmap->pm_stats.resident_count--;
 
-		pte = pmap_pte(pv->pv_pmap, pv->pv_va);
+		pte = pmap_pte_quick(pv->pv_pmap, pv->pv_va);
 
 		tpte = pte_store(pte, 0);
 		if (tpte & PG_W)
@@ -2681,7 +2734,7 @@
 #ifdef PMAP_REMOVE_PAGES_CURPROC_ONLY
 		pte = vtopte(pv->pv_va);
 #else
-		pte = pmap_pte(pv->pv_pmap, pv->pv_va);
+		pte = pmap_pte_quick(pv->pv_pmap, pv->pv_va);
 #endif
 		tpte = *pte;
 
@@ -2762,7 +2815,7 @@
 			continue;
 		}
 #endif
-		pte = pmap_pte(pv->pv_pmap, pv->pv_va);
+		pte = pmap_pte_quick(pv->pv_pmap, pv->pv_va);
 		if (*pte & bit) {
 			splx(s);
 			return TRUE;
@@ -2807,7 +2860,7 @@
 		}
 #endif
 
-		pte = pmap_pte(pv->pv_pmap, pv->pv_va);
+		pte = pmap_pte_quick(pv->pv_pmap, pv->pv_va);
 
 		if (setem) {
 			*pte |= bit;
@@ -2893,7 +2946,7 @@
 			if (!pmap_track_modified(pv->pv_va))
 				continue;
 
-			pte = pmap_pte(pv->pv_pmap, pv->pv_va);
+			pte = pmap_pte_quick(pv->pv_pmap, pv->pv_va);
 
 			if (pte && (*pte & PG_A)) {
 				*pte &= ~PG_A;
@@ -3180,6 +3233,7 @@
 	struct proc *p;
 	int npte = 0;
 	int index;
+	int s;
 	LIST_FOREACH(p, &allproc, p_list) {
 		if (p->p_pid != pid)
 			continue;
@@ -3195,6 +3249,7 @@
 				
 				pde = &pmap->pm_pdir[i];
 				if (pde && pmap_pde_v(pde)) {
+					s = splvm();
 					for(j=0;j<1024;j++) {
 						unsigned va = base + (j << PAGE_SHIFT);
 						if (va >= (vm_offset_t) VM_MIN_KERNEL_ADDRESS) {
@@ -3202,9 +3257,10 @@
 								index = 0;
 								printf("\n");
 							}
+							splx(s);
 							return npte;
 						}
-						pte = pmap_pte( pmap, va);
+						pte = pmap_pte_quick(pmap, va);
 						if (pte && pmap_pte_v(pte)) {
 							vm_offset_t pa;
 							vm_page_t m;
@@ -3222,6 +3278,7 @@
 							}
 						}
 					}
+					splx(s);
 				}
 			}
 		}
@@ -3242,9 +3299,11 @@
 {
 	unsigned va, i, j;
 	unsigned *ptep;
+	int s;
 
 	if (pm == kernel_pmap)
 		return;
+	s = splvm();
 	for (i = 0; i < 1024; i++)
 		if (pm->pm_pdir[i])
 			for (j = 0; j < 1024; j++) {
@@ -3253,10 +3312,11 @@
 					continue;
 				if (pm != kernel_pmap && va > UPT_MAX_ADDRESS)
 					continue;
-				ptep = pmap_pte(pm, va);
+				ptep = pmap_pte_quick(pm, va);
 				if (pmap_pte_v(ptep))
 					printf("%x:%x ", va, *(int *) ptep);
 			};
+	splx(s);
 
 }
 
Index: sys/i386/include/globaldata.h
===================================================================
RCS file: /home/ncvs/src/sys/i386/include/Attic/globaldata.h,v
retrieving revision 1.11.2.2
diff -u -r1.11.2.2 globaldata.h
--- sys/i386/include/globaldata.h	9 Aug 2003 16:21:19 -0000	1.11.2.2
+++ sys/i386/include/globaldata.h	28 Aug 2003 20:05:38 -0000
@@ -61,10 +61,12 @@
 	pt_entry_t	*gd_prv_CMAP2;
 	pt_entry_t	*gd_prv_CMAP3;
 	pd_entry_t	*gd_prv_PMAP1;
+	pd_entry_t	*gd_prv_PMAP2;
 	caddr_t		gd_prv_CADDR1;
 	caddr_t		gd_prv_CADDR2;
 	caddr_t		gd_prv_CADDR3;
 	pt_entry_t	*gd_prv_PADDR1;
+	pt_entry_t	*gd_prv_PADDR2;
 #endif
 	u_int		gd_astpending;
 };
@@ -80,13 +82,14 @@
 	struct globaldata globaldata;
 	char		__filler0[PAGE_SIZE - sizeof(struct globaldata)];
 
-	/* page 1..4 - CPAGE1,CPAGE2,CPAGE3,PPAGE1 */
+	/* page 1..5 - CPAGE1,CPAGE2,CPAGE3,PPAGE1,PPAGE2 */
 	char		CPAGE1[PAGE_SIZE];
 	char		CPAGE2[PAGE_SIZE];
 	char		CPAGE3[PAGE_SIZE];
 	char		PPAGE1[PAGE_SIZE];
+	char		PPAGE2[PAGE_SIZE];
 
-	/* page 5..4+UPAGES - idle stack (UPAGES pages) */
+	/* page 6..5+UPAGES - idle stack (UPAGES pages) */
 	char		idlestack[UPAGES * PAGE_SIZE];
 };
 
Index: sys/i386/include/globals.h
===================================================================
RCS file: /home/ncvs/src/sys/i386/include/Attic/globals.h,v
retrieving revision 1.5.2.2
diff -u -r1.5.2.2 globals.h
--- sys/i386/include/globals.h	9 Aug 2003 16:21:19 -0000	1.5.2.2
+++ sys/i386/include/globals.h	28 Aug 2003 20:05:38 -0000
@@ -104,10 +104,12 @@
 #define	prv_CMAP2	GLOBAL_LVALUE(prv_CMAP2, pt_entry_t *)
 #define	prv_CMAP3	GLOBAL_LVALUE(prv_CMAP3, pt_entry_t *)
 #define	prv_PMAP1	GLOBAL_LVALUE(prv_PMAP1, pd_entry_t *)
+#define	prv_PMAP2	GLOBAL_LVALUE(prv_PMAP2, pd_entry_t *)
 #define	prv_CADDR1	GLOBAL_RVALUE(prv_CADDR1, caddr_t)
 #define	prv_CADDR2	GLOBAL_RVALUE(prv_CADDR2, caddr_t)
 #define	prv_CADDR3	GLOBAL_RVALUE(prv_CADDR3, caddr_t)
 #define	prv_PADDR1	GLOBAL_RVALUE(prv_PADDR1, pt_entry_t *)
+#define	prv_PADDR2	GLOBAL_RVALUE(prv_PADDR2, pt_entry_t *)
 #endif
 #endif	/*UP kernel*/
 
@@ -134,10 +136,12 @@
 GLOBAL_FUNC(prv_CMAP2)
 GLOBAL_FUNC(prv_CMAP3)
 GLOBAL_FUNC(prv_PMAP1)
+GLOBAL_FUNC(prv_PMAP2)
 GLOBAL_FUNC(prv_CADDR1)
 GLOBAL_FUNC(prv_CADDR2)
 GLOBAL_FUNC(prv_CADDR3)
 GLOBAL_FUNC(prv_PADDR1)
+GLOBAL_FUNC(prv_PADDR2)
 #endif
 
 #define	SET_CURPROC(x)	(_global_curproc_set_nv((int)x))

----Next_Part(Thu_Aug_28_20:20:11_2003_868)----



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030828.202011.41715185.Tor.Egge>