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$");
   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/systm.h>
   43 #include <sys/smp.h>
   44 #include <sys/sysctl.h>
   45 #include <sys/types.h>
   46 
   47 #include <vm/vm.h>
   48 #include <vm/vm_page.h>
   49 
   50 #include <machine/cpu.h>
   51 #include <machine/md_var.h>
   52 #include <machine/platform.h>
   53 #include <machine/platformvar.h>
   54 #include <machine/smp.h>
   55 
   56 #include "platform_if.h"
   57 
   58 static platform_def_t   *plat_def_impl;
   59 static platform_t       plat_obj;
   60 static struct kobj_ops  plat_kernel_kops;
   61 static struct platform_kobj     plat_kernel_obj;
   62 
   63 static char plat_name[64] = "";
   64 SYSCTL_STRING(_hw, OID_AUTO, platform, CTLFLAG_RD | CTLFLAG_TUN,
   65     plat_name, 0, "Platform currently in use");
   66 
   67 static struct mem_region pregions[PHYS_AVAIL_SZ];
   68 static struct mem_region aregions[PHYS_AVAIL_SZ];
   69 static int npregions, naregions;
   70 
   71 /*
   72  * Memory region utilities: determine if two regions overlap,
   73  * and merge two overlapping regions into one
   74  */
   75 static int
   76 memr_overlap(struct mem_region *r1, struct mem_region *r2)
   77 {
   78         if ((r1->mr_start + r1->mr_size) < r2->mr_start ||
   79             (r2->mr_start + r2->mr_size) < r1->mr_start)
   80                 return (FALSE);
   81 
   82         return (TRUE);
   83 }
   84 
   85 static void
   86 memr_merge(struct mem_region *from, struct mem_region *to)
   87 {
   88         vm_offset_t end;
   89         end = ulmax(to->mr_start + to->mr_size, from->mr_start + from->mr_size);
   90         to->mr_start = ulmin(from->mr_start, to->mr_start);
   91         to->mr_size = end - to->mr_start;
   92 }
   93 
   94 /*
   95  * Quick sort callout for comparing memory regions.
   96  */
   97 static int
   98 mr_cmp(const void *a, const void *b)
   99 {
  100         const struct mem_region *regiona, *regionb;
  101 
  102         regiona = a;
  103         regionb = b;
  104         if (regiona->mr_start < regionb->mr_start)
  105                 return (-1);
  106         else if (regiona->mr_start > regionb->mr_start)
  107                 return (1);
  108         else
  109                 return (0);
  110 }
  111 
  112 void
  113 mem_regions(struct mem_region **phys, int *physsz, struct mem_region **avail,
  114     int *availsz)
  115 {
  116         int i, j, still_merging;
  117 
  118         if (npregions == 0) {
  119                 PLATFORM_MEM_REGIONS(plat_obj, &pregions[0], &npregions,
  120                     aregions, &naregions);
  121                 qsort(pregions, npregions, sizeof(*pregions), mr_cmp);
  122                 qsort(aregions, naregions, sizeof(*aregions), mr_cmp);
  123 
  124                 /* Remove overlapping available regions */
  125                 do {
  126                         still_merging = FALSE;
  127                         for (i = 0; i < naregions; i++) {
  128                                 if (aregions[i].mr_size == 0)
  129                                         continue;
  130                                 for (j = i+1; j < naregions; j++) {
  131                                         if (aregions[j].mr_size == 0)
  132                                                 continue;
  133                                         if (!memr_overlap(&aregions[j],
  134                                             &aregions[i]))
  135                                                 continue;
  136 
  137                                         memr_merge(&aregions[j], &aregions[i]);
  138                                         /* mark inactive */
  139                                         aregions[j].mr_size = 0;
  140                                         still_merging = TRUE;
  141                                 }
  142                         }
  143                 } while (still_merging == TRUE);
  144 
  145                 /* Collapse zero-length available regions */
  146                 for (i = 0; i < naregions; i++) {
  147                         if (aregions[i].mr_size == 0) {
  148                                 memcpy(&aregions[i], &aregions[i+1],
  149                                     (naregions - i - 1)*sizeof(*aregions));
  150                                 naregions--;
  151                         }
  152                 }
  153         }
  154 
  155         *phys = pregions;
  156         *avail = aregions;
  157         *physsz = npregions;
  158         *availsz = naregions;
  159 }
  160 
  161 int
  162 mem_valid(vm_offset_t addr, int len)
  163 {
  164         int i;
  165 
  166         if (npregions == 0) {
  167                 struct mem_region *p, *a;
  168                 int na, np;
  169                 mem_regions(&p, &np, &a, &na);
  170         }
  171 
  172         for (i = 0; i < npregions; i++)
  173                 if ((addr >= pregions[i].mr_start)
  174                    && (addr + len <= pregions[i].mr_start + pregions[i].mr_size))
  175                         return (0);
  176 
  177         return (EFAULT);
  178 }
  179 
  180 vm_offset_t
  181 platform_real_maxaddr(void)
  182 {
  183         return (PLATFORM_REAL_MAXADDR(plat_obj));
  184 }
  185 
  186 const char *
  187 installed_platform()
  188 {
  189         return (plat_def_impl->name);
  190 }
  191 
  192 u_long
  193 platform_timebase_freq(struct cpuref *cpu)
  194 {
  195         return (PLATFORM_TIMEBASE_FREQ(plat_obj, cpu));
  196 }
  197 
  198 /*
  199  * Put the current CPU, as last step in suspend, to sleep
  200  */
  201 void
  202 platform_sleep()
  203 {
  204         PLATFORM_SLEEP(plat_obj);
  205 }
  206 
  207 int
  208 platform_smp_first_cpu(struct cpuref *cpu)
  209 {
  210         return (PLATFORM_SMP_FIRST_CPU(plat_obj, cpu));
  211 }
  212 
  213 int
  214 platform_smp_next_cpu(struct cpuref *cpu)
  215 {
  216         return (PLATFORM_SMP_NEXT_CPU(plat_obj, cpu));
  217 }
  218 
  219 int
  220 platform_smp_get_bsp(struct cpuref *cpu)
  221 {
  222         return (PLATFORM_SMP_GET_BSP(plat_obj, cpu));
  223 }
  224 
  225 int
  226 platform_smp_start_cpu(struct pcpu *cpu)
  227 {
  228         return (PLATFORM_SMP_START_CPU(plat_obj, cpu));
  229 }
  230 
  231 void
  232 platform_smp_ap_init()
  233 {
  234         PLATFORM_SMP_AP_INIT(plat_obj);
  235 }
  236 
  237 #ifdef SMP
  238 struct cpu_group *
  239 cpu_topo(void)
  240 {
  241         return (PLATFORM_SMP_TOPO(plat_obj));
  242 }
  243 #endif
  244 
  245 /*
  246  * Reset back to firmware.
  247  */
  248 void
  249 cpu_reset()
  250 {
  251         PLATFORM_RESET(plat_obj);
  252 }
  253 
  254 /*
  255  * Platform install routines. Highest priority wins, using the same
  256  * algorithm as bus attachment.
  257  */
  258 SET_DECLARE(platform_set, platform_def_t);
  259 
  260 void
  261 platform_probe_and_attach()
  262 {
  263         platform_def_t  **platpp, *platp;
  264         int             prio, best_prio;
  265 
  266         plat_obj = &plat_kernel_obj;
  267         best_prio = 0;
  268 
  269         /*
  270          * Try to locate the best platform kobj
  271          */
  272         SET_FOREACH(platpp, platform_set) {
  273                 platp = *platpp;
  274 
  275                 /*
  276                  * Take care of compiling the selected class, and
  277                  * then statically initialise the MMU object
  278                  */
  279                 kobj_class_compile_static(platp, &plat_kernel_kops);
  280                 kobj_init_static((kobj_t)plat_obj, platp);
  281 
  282                 prio = PLATFORM_PROBE(plat_obj);
  283 
  284                 /* Check for errors */
  285                 if (prio > 0)
  286                         continue;
  287 
  288                 /*
  289                  * Check if this module was specifically requested through
  290                  * the loader tunable we provide.
  291                  */
  292                 if (strcmp(platp->name,plat_name) == 0) {
  293                         plat_def_impl = platp;
  294                         break;
  295                 }
  296 
  297                 /* Otherwise, see if it is better than our current best */
  298                 if (plat_def_impl == NULL || prio > best_prio) {
  299                         best_prio = prio;
  300                         plat_def_impl = platp;
  301                 }
  302 
  303                 /*
  304                  * We can't free the KOBJ, since it is static. Reset the ops
  305                  * member of this class so that we can come back later.
  306                  */
  307                 platp->ops = NULL;
  308         }
  309 
  310         if (plat_def_impl == NULL)
  311                 panic("No platform module found!");
  312 
  313         /*
  314          * Recompile to make sure we ended with the
  315          * correct one, and then attach.
  316          */
  317 
  318         kobj_class_compile_static(plat_def_impl, &plat_kernel_kops);
  319         kobj_init_static((kobj_t)plat_obj, plat_def_impl);
  320 
  321         strlcpy(plat_name,plat_def_impl->name,sizeof(plat_name));
  322 
  323         PLATFORM_ATTACH(plat_obj);
  324 }
  325 

Cache object: fa5617f1fa3d2d1b6301e4533d84e28a


[ 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.