Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 13 Mar 2010 21:28:14 +0000 (UTC)
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r205131 - in projects/ppc64/sys/powerpc: aim include
Message-ID:  <201003132128.o2DLSEiv038196@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nwhitehorn
Date: Sat Mar 13 21:28:14 2010
New Revision: 205131
URL: http://svn.freebsd.org/changeset/base/205131

Log:
  Provide a mechanism for handling kernel SLB spills that does not fill me
  with terror to imagine.

Modified:
  projects/ppc64/sys/powerpc/aim/machdep.c
  projects/ppc64/sys/powerpc/aim/trap.c
  projects/ppc64/sys/powerpc/include/pmap.h
  projects/ppc64/sys/powerpc/include/vmparam.h

Modified: projects/ppc64/sys/powerpc/aim/machdep.c
==============================================================================
--- projects/ppc64/sys/powerpc/aim/machdep.c	Sat Mar 13 20:43:11 2010	(r205130)
+++ projects/ppc64/sys/powerpc/aim/machdep.c	Sat Mar 13 21:28:14 2010	(r205131)
@@ -822,56 +822,7 @@ db_trap_glue(struct trapframe *frame)
 	return (0);
 }
 
-#ifdef __powerpc64__
-uintptr_t moea64_get_unique_vsid(void);
-
-uint64_t
-va_to_vsid(pmap_t pm, vm_offset_t va)
-{
-	uint64_t slbe, slbv, i;
-
-	slbe = (uintptr_t)va >> ADDR_SR_SHFT;
-	slbe = (slbe << SLBE_ESID_SHIFT) | SLBE_VALID;
-	slbv = 0;
-
-	for (i = 0; i < sizeof(pm->pm_slb)/sizeof(pm->pm_slb[0]); i++) {
-		if (pm->pm_slb[i].slbe == (slbe | i)) {
-			slbv = pm->pm_slb[i].slbv;
-			break;
-		}
-	}
-
-	/* XXX: Have a long list for processes mapping more than 16 GB */
-
-	/*
-	 * If there is no vsid for this VA, we need to add a new entry
-	 * to the PMAP's segment table.
-	 */
-
-	if (slbv == 0) {
-		slbv = moea64_get_unique_vsid() << SLBV_VSID_SHIFT;
-		for (i = 0; i < sizeof(pm->pm_slb)/sizeof(pm->pm_slb[0]); i++) {
-			if (pm == kernel_pmap && i == USER_SR)
-				continue;
-
-			if (!(pm->pm_slb[i].slbe & SLBE_VALID)) {
-				pm->pm_slb[i].slbv = slbv;
-				pm->pm_slb[i].slbe = slbe | i;
-
-				if (pm == kernel_pmap && pmap_bootstrapped) {
-					__asm __volatile ("slbmte %0, %1" :: 
-					    "r"(kernel_pmap->pm_slb[i].slbv),
-					    "r"(kernel_pmap->pm_slb[i].slbe)); 
-				}
-				break;
-			}
-		}
-	}
-
-	return ((slbv & SLBV_VSID_MASK) >> SLBV_VSID_SHIFT);
-}
-
-#else
+#ifndef __powerpc64__
 
 uint64_t
 va_to_vsid(pmap_t pm, vm_offset_t va)

Modified: projects/ppc64/sys/powerpc/aim/trap.c
==============================================================================
--- projects/ppc64/sys/powerpc/aim/trap.c	Sat Mar 13 20:43:11 2010	(r205130)
+++ projects/ppc64/sys/powerpc/aim/trap.c	Sat Mar 13 21:28:14 2010	(r205131)
@@ -87,6 +87,11 @@ static int	ppc_instr_emulate(struct trap
 static int	handle_onfault(struct trapframe *frame);
 static void	syscall(struct trapframe *frame);
 
+#ifdef __powerpc64__
+static void	handle_slb_spill(pmap_t pm, vm_offset_t addr);
+static uint64_t	slb_esid_lookup(pmap_t pm, uint64_t vsid);
+#endif
+
 int	setfault(faultbuf);		/* defined in locore.S */
 
 /* Why are these not defined in a header? */
@@ -182,22 +187,9 @@ trap(struct trapframe *frame)
 #ifdef __powerpc64__
 		case EXC_ISE:
 		case EXC_DSE:
-			/*
-			 * Once we support more segments per process
-			 * than the SLB size, we should reload the SLB
-			 * cache here from the longer segment list.
-			 *
-			 * For now, we assume a miss, and call va_to_vsid()
-			 * to allocate a new segment. This will then likely
-			 * trigger a page fault immediately after.
-			 */
-
-			PMAP_LOCK(&p->p_vmspace->vm_pmap);
-			(void)va_to_vsid(&p->p_vmspace->vm_pmap,
+			handle_slb_spill(&p->p_vmspace->vm_pmap,
 			    (type == EXC_ISE) ? frame->srr0 :
 			    frame->cpu.aim.dar);
-			PMAP_UNLOCK(&p->p_vmspace->vm_pmap);
-
 			break;
 #endif
 		case EXC_DSI:
@@ -259,11 +251,9 @@ trap(struct trapframe *frame)
 #ifdef __powerpc64__
 		case EXC_ISE:
 		case EXC_DSE:
-			PMAP_LOCK(kernel_pmap);
-			(void)va_to_vsid(kernel_pmap,
+			handle_slb_spill(kernel_pmap,
 			    (type == EXC_ISE) ? frame->srr0 :
 			    frame->cpu.aim.dar);
-			PMAP_UNLOCK(kernel_pmap);
 			return;
 #endif
 		case EXC_MCHK:
@@ -531,6 +521,21 @@ slb_esid_lookup(pmap_t pm, uint64_t vsid
 
 	return (0);
 }
+
+static void
+handle_slb_spill(pmap_t pm, vm_offset_t addr)
+{
+	uint64_t vsid, esid;
+
+	PMAP_LOCK(pm);
+	esid = addr >> ADDR_SR_SHFT;
+	vsid = va_to_vsid_noalloc(pm, addr);
+	if (vsid == 0)
+		(void)va_to_vsid(pm, addr);
+	else
+		slb_spill(pm, esid, vsid);
+	PMAP_UNLOCK(pm);
+}
 #endif
 
 static int

Modified: projects/ppc64/sys/powerpc/include/pmap.h
==============================================================================
--- projects/ppc64/sys/powerpc/include/pmap.h	Sat Mar 13 20:43:11 2010	(r205130)
+++ projects/ppc64/sys/powerpc/include/pmap.h	Sat Mar 13 21:28:14 2010	(r205131)
@@ -69,8 +69,8 @@
 #include <sys/_mutex.h>
 #include <machine/sr.h>
 #include <machine/pte.h>
-#include <machine/tlb.h>
 #include <machine/slb.h>
+#include <machine/tlb.h>
 
 struct pmap_md {
 	u_int		md_index;
@@ -124,12 +124,16 @@ struct	md_page {
 
 /*
  * Return the VSID corresponding to a given virtual address.
- * If no VSID is currently defined, it will allocate one, and add it to
- * a free SLB slot if available.
+ * If no VSID is currently defined, it will allocate one, and add
+ * it to a free slot if available.
  *
  * NB: The PMAP MUST be locked already.
  */
 uint64_t va_to_vsid(pmap_t pm, vm_offset_t va);
+uint64_t va_to_vsid_noalloc(pmap_t pm, vm_offset_t va);
+
+uint64_t allocate_vsid(pmap_t pm, uint64_t esid);
+void     slb_spill(pmap_t pm, uint64_t esid, uint64_t vsid);
 
 #else
 

Modified: projects/ppc64/sys/powerpc/include/vmparam.h
==============================================================================
--- projects/ppc64/sys/powerpc/include/vmparam.h	Sat Mar 13 20:43:11 2010	(r205130)
+++ projects/ppc64/sys/powerpc/include/vmparam.h	Sat Mar 13 21:28:14 2010	(r205131)
@@ -79,28 +79,26 @@
  * Would like to have MAX addresses = 0, but this doesn't (currently) work
  */
 #if !defined(LOCORE)
-#define	VM_MIN_ADDRESS		((vm_offset_t)0)
 #ifdef __powerpc64__
-#define	VM_MAXUSER_ADDRESS	((vm_offset_t)0x4fffff000)
+#define	VM_MIN_ADDRESS		(0x0000000000000000UL)
+#define	VM_MAXUSER_ADDRESS	(0x00000004fffff000UL)
+#define	VM_MAX_ADDRESS		(0xffffffffffffffffUL)
 #else
+#define	VM_MIN_ADDRESS		((vm_offset_t)0)
 #define	VM_MAXUSER_ADDRESS	((vm_offset_t)0x7ffff000)
+#define	VM_MAX_ADDRESS		VM_MAXUSER_ADDRESS
 #endif
-#else
-#define	VM_MIN_ADDRESS		0
-#define	VM_MAXUSER_ADDRESS	0x7ffff000
 #endif /* LOCORE */
 
-#define	VM_MAX_ADDRESS		VM_MAXUSER_ADDRESS
 #define	FREEBSD32_USRSTACK	0x7ffff000
 
 
-#if defined(AIM)	/* AIM */
-
+#ifdef AIM
 #define	KERNBASE		0x00100000UL	/* start of kernel virtual */
 
 #ifdef __powerpc64__
 #define	VM_MIN_KERNEL_ADDRESS		0xc000000000000000UL
-#define	VM_MAX_KERNEL_ADDRESS		0xcfffffffefffffffUL
+#define	VM_MAX_KERNEL_ADDRESS		0xc0000001c8000000UL
 #define	VM_MAX_SAFE_KERNEL_ADDRESS	VM_MAX_KERNEL_ADDRESS
 #else
 #define	VM_MIN_KERNEL_ADDRESS	((vm_offset_t)KERNEL_SR << ADDR_SR_SHFT)
@@ -114,7 +112,7 @@
  */
 #define UMA_MD_SMALL_ALLOC
 
-#else
+#else /* Book-E */
 
 /*
  * Kernel CCSRBAR location. We make this the reset location.
@@ -195,7 +193,7 @@ struct pmap_physseg {
 #endif
 
 #ifndef VM_KMEM_SIZE_MAX
-#define VM_KMEM_SIZE_MAX        0x200000000  /* XXX: 8 GB until SLB long list */
+#define VM_KMEM_SIZE_MAX        0x1c0000000  /* 7 GB */
 #endif
 #endif
 



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