The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/powerpc/powerpc/platform.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2005 Peter Grehan
    3  * Copyright (c) 2009 Nathan Whitehorn
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD: releng/11.2/sys/powerpc/powerpc/platform.c 331722 2018-03-29 02:50:57Z eadler $");
   31 
   32 /*
   33  * Dispatch platform calls to the appropriate platform implementation
   34  * through a previously registered kernel object.
   35  */
   36 
   37 #include <sys/param.h>
   38 #include <sys/kernel.h>
   39 #include <sys/lock.h>
   40 #include <sys/ktr.h>
   41 #include <sys/mutex.h>
   42 #include <sys/proc.h>
   43 #include <sys/systm.h>
   44 #include <sys/smp.h>
   45 #include <sys/sysctl.h>
   46 #include <sys/types.h>
   47 
   48 #include <vm/vm.h>
   49 #include <vm/vm_page.h>
   50 
   51 #include <machine/cpu.h>
   52 #include <machine/md_var.h>
   53 #include <machine/platform.h>
   54 #include <machine/platformvar.h>
   55 #include <machine/smp.h>
   56 
   57 #include "platform_if.h"
   58 
   59 static platform_def_t   *plat_def_impl;
   60 static platform_t       plat_obj;
   61 static struct kobj_ops  plat_kernel_kops;
   62 static struct platform_kobj     plat_kernel_obj;
   63 
   64 static char plat_name[64] = "";
   65 SYSCTL_STRING(_hw, OID_AUTO, platform, CTLFLAG_RD | CTLFLAG_TUN,
   66     plat_name, 0, "Platform currently in use");
   67 
   68 static struct mem_region pregions[PHYS_AVAIL_SZ];
   69 static struct mem_region aregions[PHYS_AVAIL_SZ];
   70 static int npregions, naregions;
   71 
   72 /*
   73  * Memory region utilities: determine if two regions overlap,
   74  * and merge two overlapping regions into one
   75  */
   76 static int
   77 memr_overlap(struct mem_region *r1, struct mem_region *r2)
   78 {
   79         if ((r1->mr_start + r1->mr_size) < r2->mr_start ||
   80             (r2->mr_start + r2->mr_size) < r1->mr_start)
   81                 return (FALSE);
   82 
   83         return (TRUE);
   84 }
   85 
   86 static void
   87 memr_merge(struct mem_region *from, struct mem_region *to)
   88 {
   89         vm_offset_t end;
   90         end = uqmax(to->mr_start + to->mr_size, from->mr_start + from->mr_size);
   91         to->mr_start = uqmin(from->mr_start, to->mr_start);
   92         to->mr_size = end - to->mr_start;
   93 }
   94 
   95 /*
   96  * Quick sort callout for comparing memory regions.
   97  */
   98 static int
   99 mr_cmp(const void *a, const void *b)
  100 {
  101         const struct mem_region *regiona, *regionb;
  102 
  103         regiona = a;
  104         regionb = b;
  105         if (regiona->mr_start < regionb->mr_start)
  106                 return (-1);
  107         else if (regiona->mr_start > regionb->mr_start)
  108                 return (1);
  109         else
  110                 return (0);
  111 }
  112 
  113 void
  114 mem_regions(struct mem_region **phys, int *physsz, struct mem_region **avail,
  115     int *availsz)
  116 {
  117         int i, j, still_merging;
  118 
  119         if (npregions == 0) {
  120                 PLATFORM_MEM_REGIONS(plat_obj, pregions, &npregions,
  121                     aregions, &naregions);
  122                 qsort(pregions, npregions, sizeof(*pregions), mr_cmp);
  123                 qsort(aregions, naregions, sizeof(*aregions), mr_cmp);
  124 
  125                 /* Remove overlapping available regions */
  126                 do {
  127                         still_merging = FALSE;
  128                         for (i = 0; i < naregions; i++) {
  129                                 if (aregions[i].mr_size == 0)
  130                                         continue;
  131                                 for (j = i+1; j < naregions; j++) {
  132                                         if (aregions[j].mr_size == 0)
  133                                                 continue;
  134                                         if (!memr_overlap(&aregions[j],
  135                                             &aregions[i]))
  136                                                 continue;
  137 
  138                                         memr_merge(&aregions[j], &aregions[i]);
  139                                         /* mark inactive */
  140                                         aregions[j].mr_size = 0;
  141                                         still_merging = TRUE;
  142                                 }
  143                         }
  144                 } while (still_merging == TRUE);
  145 
  146                 /* Collapse zero-length available regions */
  147                 for (i = 0; i < naregions; i++) {
  148                         if (aregions[i].mr_size == 0) {
  149                                 memcpy(&aregions[i], &aregions[i+1],
  150                                     (naregions - i - 1)*sizeof(*aregions));
  151                                 naregions--;
  152                                 i--;
  153                         }
  154                 }
  155         }
  156 
  157         *phys = pregions;
  158         *avail = aregions;
  159         *physsz = npregions;
  160         *availsz = naregions;
  161 }
  162 
  163 int
  164 mem_valid(vm_offset_t addr, int len)
  165 {
  166         int i;
  167 
  168         if (npregions == 0) {
  169                 struct mem_region *p, *a;
  170                 int na, np;
  171                 mem_regions(&p, &np, &a, &na);
  172         }
  173 
  174         for (i = 0; i < npregions; i++)
  175                 if ((addr >= pregions[i].mr_start)
  176                    && (addr + len <= pregions[i].mr_start + pregions[i].mr_size))
  177                         return (0);
  178 
  179         return (EFAULT);
  180 }
  181 
  182 vm_offset_t
  183 platform_real_maxaddr(void)
  184 {
  185         return (PLATFORM_REAL_MAXADDR(plat_obj));
  186 }
  187 
  188 const char *
  189 installed_platform()
  190 {
  191         return (plat_def_impl->name);
  192 }
  193 
  194 u_long
  195 platform_timebase_freq(struct cpuref *cpu)
  196 {
  197         return (PLATFORM_TIMEBASE_FREQ(plat_obj, cpu));
  198 }
  199 
  200 /*
  201  * Put the current CPU, as last step in suspend, to sleep
  202  */
  203 void
  204 platform_sleep()
  205 {
  206         PLATFORM_SLEEP(plat_obj);
  207 }
  208 
  209 int
  210 platform_smp_first_cpu(struct cpuref *cpu)
  211 {
  212         return (PLATFORM_SMP_FIRST_CPU(plat_obj, cpu));
  213 }
  214 
  215 int
  216 platform_smp_next_cpu(struct cpuref *cpu)
  217 {
  218         return (PLATFORM_SMP_NEXT_CPU(plat_obj, cpu));
  219 }
  220 
  221 int
  222 platform_smp_get_bsp(struct cpuref *cpu)
  223 {
  224         return (PLATFORM_SMP_GET_BSP(plat_obj, cpu));
  225 }
  226 
  227 int
  228 platform_smp_start_cpu(struct pcpu *cpu)
  229 {
  230         return (PLATFORM_SMP_START_CPU(plat_obj, cpu));
  231 }
  232 
  233 void
  234 platform_smp_ap_init()
  235 {
  236         PLATFORM_SMP_AP_INIT(plat_obj);
  237 }
  238 
  239 #ifdef SMP
  240 struct cpu_group *
  241 cpu_topo(void)
  242 {
  243         return (PLATFORM_SMP_TOPO(plat_obj));
  244 }
  245 #endif
  246 
  247 /*
  248  * Reset back to firmware.
  249  */
  250 void
  251 cpu_reset()
  252 {
  253         PLATFORM_RESET(plat_obj);
  254 }
  255 
  256 int
  257 cpu_idle_wakeup(int cpu)
  258 {
  259         return (PLATFORM_IDLE_WAKEUP(plat_obj, cpu));
  260 }
  261 
  262 void
  263 platform_cpu_idle(int cpu)
  264 {
  265 
  266         PLATFORM_IDLE(plat_obj, cpu);
  267 }
  268 
  269 /*
  270  * Platform install routines. Highest priority wins, using the same
  271  * algorithm as bus attachment.
  272  */
  273 SET_DECLARE(platform_set, platform_def_t);
  274 
  275 void
  276 platform_probe_and_attach()
  277 {
  278         platform_def_t  **platpp, *platp;
  279         int             prio, best_prio;
  280 
  281         plat_obj = &plat_kernel_obj;
  282         best_prio = 0;
  283 
  284         /*
  285          * Try to locate the best platform kobj
  286          */
  287         SET_FOREACH(platpp, platform_set) {
  288                 platp = *platpp;
  289 
  290                 /*
  291                  * Take care of compiling the selected class, and
  292                  * then statically initialise the MMU object
  293                  */
  294                 kobj_class_compile_static(platp, &plat_kernel_kops);
  295                 kobj_init_static((kobj_t)plat_obj, platp);
  296 
  297                 prio = PLATFORM_PROBE(plat_obj);
  298 
  299                 /* Check for errors */
  300                 if (prio > 0)
  301                         continue;
  302 
  303                 /*
  304                  * Check if this module was specifically requested through
  305                  * the loader tunable we provide.
  306                  */
  307                 if (strcmp(platp->name,plat_name) == 0) {
  308                         plat_def_impl = platp;
  309                         break;
  310                 }
  311 
  312                 /* Otherwise, see if it is better than our current best */
  313                 if (plat_def_impl == NULL || prio > best_prio) {
  314                         best_prio = prio;
  315                         plat_def_impl = platp;
  316                 }
  317 
  318                 /*
  319                  * We can't free the KOBJ, since it is static. Reset the ops
  320                  * member of this class so that we can come back later.
  321                  */
  322                 platp->ops = NULL;
  323         }
  324 
  325         if (plat_def_impl == NULL)
  326                 panic("No platform module found!");
  327 
  328         /*
  329          * Recompile to make sure we ended with the
  330          * correct one, and then attach.
  331          */
  332 
  333         kobj_class_compile_static(plat_def_impl, &plat_kernel_kops);
  334         kobj_init_static((kobj_t)plat_obj, plat_def_impl);
  335 
  336         strlcpy(plat_name,plat_def_impl->name,sizeof(plat_name));
  337 
  338         PLATFORM_ATTACH(plat_obj);
  339 }
  340 

Cache object: 231c7bba5bd1b8595fa5fec3934d56ec


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.