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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to