svn commit: r215159 - in head/sys: powerpc/aim powerpc/booke powerpc/include powerpc/powerpc sys

Nathan Whitehorn nwhitehorn at FreeBSD.org
Fri Nov 12 04:18:20 UTC 2010


Author: nwhitehorn
Date: Fri Nov 12 04:18:19 2010
New Revision: 215159
URL: http://svn.freebsd.org/changeset/base/215159

Log:
  Add some platform KOBJ extensions and continue integrating PowerPC
  hypervisor infrastructure support:
  - Fix coexistence of multiple platform modules in the same kernel
  - Allow platform modules to provide an SMP topology
  - PowerPC hypervisors limit the amount of memory accessible in real mode.
    Allow the platform modules to specify the maximum real-mode address,
    and modify the bits of the kernel that need to allocate
    real-mode-accessible buffers to respect this limits.

Modified:
  head/sys/powerpc/aim/mmu_oea64.c
  head/sys/powerpc/aim/ofw_machdep.c
  head/sys/powerpc/aim/slb.c
  head/sys/powerpc/booke/machdep.c
  head/sys/powerpc/include/platform.h
  head/sys/powerpc/powerpc/mp_machdep.c
  head/sys/powerpc/powerpc/platform.c
  head/sys/powerpc/powerpc/platform_if.m
  head/sys/sys/smp.h

Modified: head/sys/powerpc/aim/mmu_oea64.c
==============================================================================
--- head/sys/powerpc/aim/mmu_oea64.c	Fri Nov 12 04:13:48 2010	(r215158)
+++ head/sys/powerpc/aim/mmu_oea64.c	Fri Nov 12 04:18:19 2010	(r215159)
@@ -2385,6 +2385,9 @@ moea64_bootstrap_alloc(vm_size_t size, u
 		if (s < phys_avail[i] || e > phys_avail[i + 1])
 			continue;
 
+		if (s + size > platform_real_maxaddr())
+			continue;
+
 		if (s == phys_avail[i]) {
 			phys_avail[i] += size;
 		} else if (e == phys_avail[i + 1]) {

Modified: head/sys/powerpc/aim/ofw_machdep.c
==============================================================================
--- head/sys/powerpc/aim/ofw_machdep.c	Fri Nov 12 04:13:48 2010	(r215158)
+++ head/sys/powerpc/aim/ofw_machdep.c	Fri Nov 12 04:18:19 2010	(r215159)
@@ -692,16 +692,3 @@ OF_decode_addr(phandle_t dev, int regno,
 	return (bus_space_map(*tag, addr, size, 0, handle));
 }
 
-int
-mem_valid(vm_offset_t addr, int len)
-{
-	int i;
-
-	for (i = 0; i < nOFmem; i++)
-		if ((addr >= OFmem[i].mr_start) 
-		    && (addr + len < OFmem[i].mr_start + OFmem[i].mr_size))
-			return (0);
-
-	return (EFAULT);
-}
-

Modified: head/sys/powerpc/aim/slb.c
==============================================================================
--- head/sys/powerpc/aim/slb.c	Fri Nov 12 04:13:48 2010	(r215158)
+++ head/sys/powerpc/aim/slb.c	Fri Nov 12 04:18:19 2010	(r215159)
@@ -36,9 +36,14 @@
 #include <vm/vm.h>
 #include <vm/pmap.h>
 #include <vm/uma.h>
+#include <vm/vm.h>
 #include <vm/vm_map.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pageout.h>
+#include <vm/vm_phys.h>
 
 #include <machine/md_var.h>
+#include <machine/platform.h>
 #include <machine/pmap.h>
 #include <machine/vmparam.h>
 
@@ -474,6 +479,51 @@ slb_insert_user(pmap_t pm, struct slb *s
 	pm->pm_slb[i] = slb;
 }
 
+static void *
+slb_uma_real_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait)
+{
+	static vm_offset_t realmax = 0;
+	void *va;
+	vm_page_t m;
+	int pflags;
+
+	if (realmax == 0)
+		realmax = platform_real_maxaddr();
+
+	*flags = UMA_SLAB_PRIV;
+	if ((wait & (M_NOWAIT|M_USE_RESERVE)) == M_NOWAIT)
+		pflags = VM_ALLOC_INTERRUPT | VM_ALLOC_WIRED;
+	else    
+		pflags = VM_ALLOC_SYSTEM | VM_ALLOC_WIRED;
+	if (wait & M_ZERO)
+		pflags |= VM_ALLOC_ZERO;
+
+	for (;;) {
+		m = vm_phys_alloc_contig(1, 0, realmax, PAGE_SIZE,
+			    PAGE_SIZE);
+		if (m == NULL) {
+			if (wait & M_NOWAIT)
+				return (NULL);
+			VM_WAIT;
+		} else
+                        break;
+        }
+
+	va = (void *) VM_PAGE_TO_PHYS(m);
+
+	if (!hw_direct_map)
+		pmap_kenter((vm_offset_t)va, VM_PAGE_TO_PHYS(m));
+
+	if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0)
+		bzero(va, PAGE_SIZE);
+
+	/* vm_phys_alloc_contig does not track wiring */
+	atomic_add_int(&cnt.v_wire_count, 1);
+	m->wire_count = 1;
+
+	return (va);
+}
+
 static void
 slb_zone_init(void *dummy)
 {
@@ -482,6 +532,11 @@ slb_zone_init(void *dummy)
 	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM);
 	slb_cache_zone = uma_zcreate("SLB cache", 64*sizeof(struct slb *),
 	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM);
+
+	if (platform_real_maxaddr() != VM_MAX_ADDRESS) {
+		uma_zone_set_allocf(slb_cache_zone, slb_uma_real_alloc);
+		uma_zone_set_allocf(slbt_zone, slb_uma_real_alloc);
+	}
 }
 
 struct slb **

Modified: head/sys/powerpc/booke/machdep.c
==============================================================================
--- head/sys/powerpc/booke/machdep.c	Fri Nov 12 04:13:48 2010	(r215158)
+++ head/sys/powerpc/booke/machdep.c	Fri Nov 12 04:18:19 2010	(r215159)
@@ -597,12 +597,3 @@ bzero(void *buf, size_t len)
 	}
 }
 
-/*
- * XXX what is the better/proper place for this routine?
- */
-int
-mem_valid(vm_offset_t addr, int len)
-{
-
-	return (1);
-}

Modified: head/sys/powerpc/include/platform.h
==============================================================================
--- head/sys/powerpc/include/platform.h	Fri Nov 12 04:13:48 2010	(r215158)
+++ head/sys/powerpc/include/platform.h	Fri Nov 12 04:18:19 2010	(r215159)
@@ -44,6 +44,7 @@ struct mem_region {
 };
 
 void	mem_regions(struct mem_region **, int *, struct mem_region **, int *);
+vm_offset_t platform_real_maxaddr(void);
 
 u_long	platform_timebase_freq(struct cpuref *);
   

Modified: head/sys/powerpc/powerpc/mp_machdep.c
==============================================================================
--- head/sys/powerpc/powerpc/mp_machdep.c	Fri Nov 12 04:13:48 2010	(r215158)
+++ head/sys/powerpc/powerpc/mp_machdep.c	Fri Nov 12 04:18:19 2010	(r215159)
@@ -98,13 +98,6 @@ machdep_ap_bootstrap(void)
 	sched_throw(NULL);
 }
 
-struct cpu_group *
-cpu_topo(void)
-{
-
-	return (smp_topo_none());
-}
-
 void
 cpu_mp_setmaxid(void)
 {

Modified: head/sys/powerpc/powerpc/platform.c
==============================================================================
--- head/sys/powerpc/powerpc/platform.c	Fri Nov 12 04:13:48 2010	(r215158)
+++ head/sys/powerpc/powerpc/platform.c	Fri Nov 12 04:18:19 2010	(r215159)
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/ktr.h>
 #include <sys/mutex.h>
 #include <sys/systm.h>
+#include <sys/smp.h>
 #include <sys/sysctl.h>
 #include <sys/types.h>
 
@@ -47,6 +48,7 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_page.h>
 
 #include <machine/cpu.h>
+#include <machine/md_var.h>
 #include <machine/platform.h>
 #include <machine/platformvar.h>
 #include <machine/smp.h>
@@ -62,11 +64,45 @@ static char plat_name[64] = "";
 SYSCTL_STRING(_hw, OID_AUTO, platform, CTLFLAG_RD | CTLFLAG_TUN,
     plat_name, 0, "Platform currently in use");
 
+static struct mem_region *pregions = NULL;
+static struct mem_region *aregions = NULL;
+static int npregions, naregions;
+
 void
 mem_regions(struct mem_region **phys, int *physsz, struct mem_region **avail,
     int *availsz)
 {
-	PLATFORM_MEM_REGIONS(plat_obj, phys, physsz, avail, availsz);
+	if (pregions == NULL)
+		PLATFORM_MEM_REGIONS(plat_obj, &pregions, &npregions,
+		    &aregions, &naregions);
+
+	*phys = pregions;
+	*avail = aregions;
+	*physsz = npregions;
+	*availsz = naregions;
+}
+
+int
+mem_valid(vm_offset_t addr, int len)
+{
+	int i;
+
+	if (pregions == NULL)
+		PLATFORM_MEM_REGIONS(plat_obj, &pregions, &npregions,
+		    &aregions, &naregions);
+
+	for (i = 0; i < npregions; i++)
+		if ((addr >= pregions[i].mr_start) 
+		   && (addr + len < pregions[i].mr_start + pregions[i].mr_size))
+			return (0);
+
+	return (EFAULT);
+}
+
+vm_offset_t
+platform_real_maxaddr(void)
+{
+	return (PLATFORM_REAL_MAXADDR(plat_obj));
 }
 
 const char *
@@ -105,6 +141,14 @@ platform_smp_start_cpu(struct pcpu *cpu)
 	return (PLATFORM_SMP_START_CPU(plat_obj, cpu));
 }
 
+#ifdef SMP
+struct cpu_group *
+cpu_topo(void)
+{
+        return (PLATFORM_SMP_TOPO(plat_obj));
+}
+#endif
+
 /*
  * Reset back to firmware.
  */
@@ -164,9 +208,10 @@ platform_probe_and_attach()
 		}
 
 		/*
-		 * We can't free the KOBJ, since it is static. Luckily,
-		 * this has no ill effects since it gets reset every time.
+		 * We can't free the KOBJ, since it is static. Reset the ops
+		 * member of this class so that we can come back later.
 		 */
+		platp->ops = NULL;
 	}
 
 	if (plat_def_impl == NULL)

Modified: head/sys/powerpc/powerpc/platform_if.m
==============================================================================
--- head/sys/powerpc/powerpc/platform_if.m	Fri Nov 12 04:13:48 2010	(r215158)
+++ head/sys/powerpc/powerpc/platform_if.m	Fri Nov 12 04:18:19 2010	(r215159)
@@ -30,10 +30,12 @@
 #include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/systm.h>
+#include <sys/smp.h>
 
 #include <machine/platform.h>
 #include <machine/platformvar.h>
 #include <machine/smp.h>
+#include <machine/vmparam.h>
 
 /**
  * @defgroup PLATFORM platform - KObj methods for PowerPC platform
@@ -66,6 +68,18 @@ CODE {
 	{
 		return (ENOENT);
 	}
+	static struct cpu_group *platform_null_smp_topo(platform_t plat)
+	{
+#ifdef SMP
+		return (smp_topo_none());
+#else
+		return (NULL);
+#endif
+	}
+	static vm_offset_t platform_null_real_maxaddr(platform_t plat)
+	{
+		return (VM_MAX_ADDRESS);
+	}
 };
 
 /**
@@ -109,6 +123,15 @@ METHOD void mem_regions {
 };
 
 /**
+ * @brief Return the maximum address accessible in real mode
+ *   (for use with hypervisors)
+ */
+METHOD vm_offset_t real_maxaddr {
+	platform_t	_plat;
+} DEFAULT platform_null_real_maxaddr;
+
+
+/**
  * @brief Get the CPU's timebase frequency, in ticks per second.
  *
  * @param _cpu		CPU whose timebase to query
@@ -162,6 +185,13 @@ METHOD int smp_start_cpu {
 };
 
 /**
+ * @brief Return SMP topology
+ */
+METHOD cpu_group_t smp_topo {
+	platform_t	_plat;
+} DEFAULT platform_null_smp_topo;
+
+/**
  * @brief Reset system
  */
 METHOD void reset {

Modified: head/sys/sys/smp.h
==============================================================================
--- head/sys/sys/smp.h	Fri Nov 12 04:13:48 2010	(r215158)
+++ head/sys/sys/smp.h	Fri Nov 12 04:18:19 2010	(r215159)
@@ -16,8 +16,6 @@
 
 #ifndef LOCORE
 
-#ifdef SMP
-
 /*
  * Topology of a NUMA or HTT system.
  *
@@ -41,6 +39,8 @@ struct cpu_group {
 	int8_t		cg_flags;	/* Traversal modifiers. */
 };
 
+typedef struct cpu_group *cpu_group_t;
+
 /*
  * Defines common resources for CPUs in the group.  The highest level
  * resource should be used when multiple are shared.
@@ -60,6 +60,7 @@ struct cpu_group {
 /*
  * Convenience routines for building topologies.
  */
+#ifdef SMP
 struct cpu_group *smp_topo(void);
 struct cpu_group *smp_topo_none(void);
 struct cpu_group *smp_topo_1level(int l1share, int l1count, int l1flags);


More information about the svn-src-head mailing list