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/pseries/platform_chrp.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2008 Marcel Moolenaar
    5  * Copyright (c) 2009 Nathan Whitehorn
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  *
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 #include <sys/endian.h>
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/kernel.h>
   37 #include <sys/bus.h>
   38 #include <sys/pcpu.h>
   39 #include <sys/proc.h>
   40 #include <sys/sched.h>
   41 #include <sys/smp.h>
   42 #include <vm/vm.h>
   43 #include <vm/pmap.h>
   44 
   45 #include <machine/bus.h>
   46 #include <machine/cpu.h>
   47 #include <machine/hid.h>
   48 #include <machine/platformvar.h>
   49 #include <machine/rtas.h>
   50 #include <machine/smp.h>
   51 #include <machine/spr.h>
   52 #include <machine/trap.h>
   53 
   54 #include <dev/ofw/openfirm.h>
   55 #include <machine/ofw_machdep.h>
   56 
   57 #include "platform_if.h"
   58 
   59 #ifdef SMP
   60 extern void *ap_pcpu;
   61 #endif
   62 
   63 #ifdef __powerpc64__
   64 static uint8_t splpar_vpa[MAXCPU][640] __aligned(128); /* XXX: dpcpu */
   65 #endif
   66 
   67 static vm_offset_t realmaxaddr = VM_MAX_ADDRESS;
   68 
   69 static int chrp_probe(platform_t);
   70 static int chrp_attach(platform_t);
   71 void chrp_mem_regions(platform_t, struct mem_region *phys, int *physsz,
   72     struct mem_region *avail, int *availsz);
   73 static vm_offset_t chrp_real_maxaddr(platform_t);
   74 static u_long chrp_timebase_freq(platform_t, struct cpuref *cpuref);
   75 static int chrp_smp_first_cpu(platform_t, struct cpuref *cpuref);
   76 static int chrp_smp_next_cpu(platform_t, struct cpuref *cpuref);
   77 static int chrp_smp_get_bsp(platform_t, struct cpuref *cpuref);
   78 static void chrp_smp_ap_init(platform_t);
   79 static int chrp_cpuref_init(void);
   80 #ifdef SMP
   81 static int chrp_smp_start_cpu(platform_t, struct pcpu *cpu);
   82 static void chrp_smp_probe_threads(platform_t plat);
   83 static struct cpu_group *chrp_smp_topo(platform_t plat);
   84 #endif
   85 static void chrp_reset(platform_t);
   86 #ifdef __powerpc64__
   87 #include "phyp-hvcall.h"
   88 static void phyp_cpu_idle(sbintime_t sbt);
   89 #endif
   90 
   91 static struct cpuref platform_cpuref[MAXCPU];
   92 static int platform_cpuref_cnt;
   93 static int platform_cpuref_valid;
   94 
   95 static platform_method_t chrp_methods[] = {
   96         PLATFORMMETHOD(platform_probe,          chrp_probe),
   97         PLATFORMMETHOD(platform_attach,         chrp_attach),
   98         PLATFORMMETHOD(platform_mem_regions,    chrp_mem_regions),
   99         PLATFORMMETHOD(platform_real_maxaddr,   chrp_real_maxaddr),
  100         PLATFORMMETHOD(platform_timebase_freq,  chrp_timebase_freq),
  101 
  102         PLATFORMMETHOD(platform_smp_ap_init,    chrp_smp_ap_init),
  103         PLATFORMMETHOD(platform_smp_first_cpu,  chrp_smp_first_cpu),
  104         PLATFORMMETHOD(platform_smp_next_cpu,   chrp_smp_next_cpu),
  105         PLATFORMMETHOD(platform_smp_get_bsp,    chrp_smp_get_bsp),
  106 #ifdef SMP
  107         PLATFORMMETHOD(platform_smp_start_cpu,  chrp_smp_start_cpu),
  108         PLATFORMMETHOD(platform_smp_probe_threads,      chrp_smp_probe_threads),
  109         PLATFORMMETHOD(platform_smp_topo,       chrp_smp_topo),
  110 #endif
  111 
  112         PLATFORMMETHOD(platform_reset,          chrp_reset),
  113         { 0, 0 }
  114 };
  115 
  116 static platform_def_t chrp_platform = {
  117         "chrp",
  118         chrp_methods,
  119         0
  120 };
  121 
  122 PLATFORM_DEF(chrp_platform);
  123 
  124 static int
  125 chrp_probe(platform_t plat)
  126 {
  127         if (OF_finddevice("/memory") != -1 || OF_finddevice("/memory@0") != -1)
  128                 return (BUS_PROBE_GENERIC);
  129 
  130         return (ENXIO);
  131 }
  132 
  133 static int
  134 chrp_attach(platform_t plat)
  135 {
  136         int quiesce;
  137 #ifdef __powerpc64__
  138         int i;
  139 #if BYTE_ORDER == LITTLE_ENDIAN
  140         int result;
  141 #endif
  142 
  143         /* XXX: check for /rtas/ibm,hypertas-functions? */
  144         if (!(mfmsr() & PSL_HV)) {
  145                 struct mem_region *phys, *avail;
  146                 int nphys, navail;
  147                 vm_offset_t off;
  148 
  149                 mem_regions(&phys, &nphys, &avail, &navail);
  150 
  151                 realmaxaddr = 0;
  152                 for (i = 0; i < nphys; i++) {
  153                         off = phys[i].mr_start + phys[i].mr_size;
  154                         realmaxaddr = MAX(off, realmaxaddr);
  155                 }
  156 
  157                 if (!radix_mmu)
  158                         pmap_mmu_install("mmu_phyp", BUS_PROBE_SPECIFIC);
  159                 cpu_idle_hook = phyp_cpu_idle;
  160 
  161                 /* Set up important VPA fields */
  162                 for (i = 0; i < MAXCPU; i++) {
  163                         /* First two: VPA size */
  164                         splpar_vpa[i][4] =
  165                             (uint8_t)((sizeof(splpar_vpa[i]) >> 8) & 0xff);
  166                         splpar_vpa[i][5] =
  167                             (uint8_t)(sizeof(splpar_vpa[i]) & 0xff);
  168                         splpar_vpa[i][0xba] = 1;        /* Maintain FPRs */
  169                         splpar_vpa[i][0xbb] = 1;        /* Maintain PMCs */
  170                         splpar_vpa[i][0xfc] = 0xff;     /* Maintain full SLB */
  171                         splpar_vpa[i][0xfd] = 0xff;
  172                         splpar_vpa[i][0xff] = 1;        /* Maintain Altivec */
  173                 }
  174                 mb();
  175 
  176                 /* Set up hypervisor CPU stuff */
  177                 chrp_smp_ap_init(plat);
  178 
  179 #if BYTE_ORDER == LITTLE_ENDIAN
  180                 /*
  181                  * Ask the hypervisor to update the LPAR ILE bit.
  182                  *
  183                  * This involves all processors reentering the hypervisor
  184                  * so the change appears simultaneously in all processors.
  185                  * This can take a long time.
  186                  */
  187                 for(;;) {
  188                         result = phyp_hcall(H_SET_MODE, 1UL,
  189                             H_SET_MODE_RSRC_ILE, 0, 0);
  190                         if (result == H_SUCCESS)
  191                                 break;
  192                         DELAY(1000);
  193                 }
  194 #endif
  195 
  196         }
  197 #endif
  198         chrp_cpuref_init();
  199 
  200         /* Some systems (e.g. QEMU) need Open Firmware to stand down */
  201         quiesce = 1;
  202         TUNABLE_INT_FETCH("debug.quiesce_ofw", &quiesce);
  203         if (quiesce)
  204                 ofw_quiesce();
  205 
  206         return (0);
  207 }
  208 
  209 static int
  210 parse_drconf_memory(struct mem_region *ofmem, int *msz,
  211                     struct mem_region *ofavail, int *asz)
  212 {
  213         phandle_t phandle;
  214         vm_offset_t base;
  215         int i, idx, len, lasz, lmsz, res;
  216         uint32_t flags, lmb_size[2];
  217         uint32_t *dmem;
  218 
  219         lmsz = *msz;
  220         lasz = *asz;
  221 
  222         phandle = OF_finddevice("/ibm,dynamic-reconfiguration-memory");
  223         if (phandle == -1)
  224                 /* No drconf node, return. */
  225                 return (0);
  226 
  227         res = OF_getencprop(phandle, "ibm,lmb-size", lmb_size,
  228             sizeof(lmb_size));
  229         if (res == -1)
  230                 return (0);
  231         printf("Logical Memory Block size: %d MB\n", lmb_size[1] >> 20);
  232 
  233         /* Parse the /ibm,dynamic-memory.
  234            The first position gives the # of entries. The next two words
  235            reflect the address of the memory block. The next four words are
  236            the DRC index, reserved, list index and flags.
  237            (see PAPR C.6.6.2 ibm,dynamic-reconfiguration-memory)
  238            
  239             #el  Addr   DRC-idx  res   list-idx  flags
  240            -------------------------------------------------
  241            | 4 |   8   |   4   |   4   |   4   |   4   |....
  242            -------------------------------------------------
  243         */
  244 
  245         len = OF_getproplen(phandle, "ibm,dynamic-memory");
  246         if (len > 0) {
  247                 /* We have to use a variable length array on the stack
  248                    since we have very limited stack space.
  249                 */
  250                 cell_t arr[len/sizeof(cell_t)];
  251 
  252                 res = OF_getencprop(phandle, "ibm,dynamic-memory", arr,
  253                     sizeof(arr));
  254                 if (res == -1)
  255                         return (0);
  256 
  257                 /* Number of elements */
  258                 idx = arr[0];
  259 
  260                 /* First address, in arr[1], arr[2]*/
  261                 dmem = &arr[1];
  262 
  263                 for (i = 0; i < idx; i++) {
  264                         base = ((uint64_t)dmem[0] << 32) + dmem[1];
  265                         dmem += 4;
  266                         flags = dmem[1];
  267                         /* Use region only if available and not reserved. */
  268                         if ((flags & 0x8) && !(flags & 0x80)) {
  269                                 ofmem[lmsz].mr_start = base;
  270                                 ofmem[lmsz].mr_size = (vm_size_t)lmb_size[1];
  271                                 ofavail[lasz].mr_start = base;
  272                                 ofavail[lasz].mr_size = (vm_size_t)lmb_size[1];
  273                                 lmsz++;
  274                                 lasz++;
  275                         }
  276                         dmem += 2;
  277                 }
  278         }
  279 
  280         *msz = lmsz;
  281         *asz = lasz;
  282 
  283         return (1);
  284 }
  285 
  286 void
  287 chrp_mem_regions(platform_t plat, struct mem_region *phys, int *physsz,
  288     struct mem_region *avail, int *availsz)
  289 {
  290         vm_offset_t maxphysaddr;
  291         int i;
  292 
  293         ofw_mem_regions(phys, physsz, avail, availsz);
  294         parse_drconf_memory(phys, physsz, avail, availsz);
  295 
  296         /*
  297          * On some firmwares (SLOF), some memory may be marked available that
  298          * doesn't actually exist. This manifests as an extension of the last
  299          * available segment past the end of physical memory, so truncate that
  300          * one.
  301          */
  302         maxphysaddr = 0;
  303         for (i = 0; i < *physsz; i++)
  304                 if (phys[i].mr_start + phys[i].mr_size > maxphysaddr)
  305                         maxphysaddr = phys[i].mr_start + phys[i].mr_size;
  306 
  307         for (i = 0; i < *availsz; i++)
  308                 if (avail[i].mr_start + avail[i].mr_size > maxphysaddr)
  309                         avail[i].mr_size = maxphysaddr - avail[i].mr_start;
  310 }
  311 
  312 static vm_offset_t
  313 chrp_real_maxaddr(platform_t plat)
  314 {
  315         return (realmaxaddr);
  316 }
  317 
  318 static u_long
  319 chrp_timebase_freq(platform_t plat, struct cpuref *cpuref)
  320 {
  321         phandle_t cpus, cpunode;
  322         int32_t ticks = -1;
  323         int res;
  324         char buf[8];
  325 
  326         cpus = OF_finddevice("/cpus");
  327         if (cpus == -1)
  328                 panic("CPU tree not found on Open Firmware\n");
  329 
  330         for (cpunode = OF_child(cpus); cpunode != 0; cpunode = OF_peer(cpunode)) {
  331                 res = OF_getprop(cpunode, "device_type", buf, sizeof(buf));
  332                 if (res > 0 && strcmp(buf, "cpu") == 0)
  333                         break;
  334         }
  335         if (cpunode <= 0)
  336                 panic("CPU node not found on Open Firmware\n");
  337 
  338         OF_getencprop(cpunode, "timebase-frequency", &ticks, sizeof(ticks));
  339 
  340         if (ticks <= 0)
  341                 panic("Unable to determine timebase frequency!");
  342 
  343         return (ticks);
  344 }
  345 
  346 static int
  347 chrp_smp_first_cpu(platform_t plat, struct cpuref *cpuref)
  348 {
  349 
  350         if (platform_cpuref_valid == 0)
  351                 return (EINVAL);
  352 
  353         cpuref->cr_cpuid = 0;
  354         cpuref->cr_hwref = platform_cpuref[0].cr_hwref;
  355 
  356         return (0);
  357 }
  358 
  359 static int
  360 chrp_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
  361 {
  362         int id;
  363 
  364         if (platform_cpuref_valid == 0)
  365                 return (EINVAL);
  366 
  367         id = cpuref->cr_cpuid + 1;
  368         if (id >= platform_cpuref_cnt)
  369                 return (ENOENT);
  370 
  371         cpuref->cr_cpuid = platform_cpuref[id].cr_cpuid;
  372         cpuref->cr_hwref = platform_cpuref[id].cr_hwref;
  373 
  374         return (0);
  375 }
  376 
  377 static int
  378 chrp_smp_get_bsp(platform_t plat, struct cpuref *cpuref)
  379 {
  380 
  381         cpuref->cr_cpuid = platform_cpuref[0].cr_cpuid;
  382         cpuref->cr_hwref = platform_cpuref[0].cr_hwref;
  383         return (0);
  384 }
  385 
  386 static void
  387 get_cpu_reg(phandle_t cpu, cell_t *reg)
  388 {
  389         int res;
  390 
  391         res = OF_getproplen(cpu, "reg");
  392         if (res != sizeof(cell_t))
  393                 panic("Unexpected length for CPU property reg on Open Firmware\n");
  394         OF_getencprop(cpu, "reg", reg, res);
  395 }
  396 
  397 static int
  398 chrp_cpuref_init(void)
  399 {
  400         phandle_t cpu, dev, chosen, pbsp;
  401         ihandle_t ibsp;
  402         char buf[32];
  403         int a, bsp, res, res2, tmp_cpuref_cnt;
  404         static struct cpuref tmp_cpuref[MAXCPU];
  405         cell_t interrupt_servers[32], addr_cells, size_cells, reg, bsp_reg;
  406 
  407         if (platform_cpuref_valid)
  408                 return (0);
  409 
  410         dev = OF_peer(0);
  411         dev = OF_child(dev);
  412         while (dev != 0) {
  413                 res = OF_getprop(dev, "name", buf, sizeof(buf));
  414                 if (res > 0 && strcmp(buf, "cpus") == 0)
  415                         break;
  416                 dev = OF_peer(dev);
  417         }
  418 
  419         /* Make sure that cpus reg property have 1 address cell and 0 size cells */
  420         res = OF_getproplen(dev, "#address-cells");
  421         res2 = OF_getproplen(dev, "#size-cells");
  422         if (res != res2 || res != sizeof(cell_t))
  423                 panic("CPU properties #address-cells and #size-cells not found on Open Firmware\n");
  424         OF_getencprop(dev, "#address-cells", &addr_cells, sizeof(addr_cells));
  425         OF_getencprop(dev, "#size-cells", &size_cells, sizeof(size_cells));
  426         if (addr_cells != 1 || size_cells != 0)
  427                 panic("Unexpected values for CPU properties #address-cells and #size-cells on Open Firmware\n");
  428 
  429         /* Look for boot CPU in /chosen/cpu and /chosen/fdtbootcpu */
  430 
  431         chosen = OF_finddevice("/chosen");
  432         if (chosen == -1)
  433                 panic("Device /chosen not found on Open Firmware\n");
  434 
  435         bsp_reg = -1;
  436 
  437         /* /chosen/cpu */
  438         if (OF_getproplen(chosen, "cpu") == sizeof(ihandle_t)) {
  439                 OF_getprop(chosen, "cpu", &ibsp, sizeof(ibsp));
  440                 pbsp = OF_instance_to_package(be32toh(ibsp));
  441                 if (pbsp != -1)
  442                         get_cpu_reg(pbsp, &bsp_reg);
  443         }
  444 
  445         /* /chosen/fdtbootcpu */
  446         if (bsp_reg == -1) {
  447                 if (OF_getproplen(chosen, "fdtbootcpu") == sizeof(cell_t))
  448                         OF_getprop(chosen, "fdtbootcpu", &bsp_reg, sizeof(bsp_reg));
  449         }
  450 
  451         if (bsp_reg == -1)
  452                 panic("Boot CPU not found on Open Firmware\n");
  453 
  454         bsp = -1;
  455         tmp_cpuref_cnt = 0;
  456         for (cpu = OF_child(dev); cpu != 0; cpu = OF_peer(cpu)) {
  457                 res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
  458                 if (res > 0 && strcmp(buf, "cpu") == 0) {
  459                         res = OF_getproplen(cpu, "ibm,ppc-interrupt-server#s");
  460                         if (res > 0) {
  461                                 OF_getencprop(cpu, "ibm,ppc-interrupt-server#s",
  462                                     interrupt_servers, res);
  463 
  464                                 get_cpu_reg(cpu, &reg);
  465                                 if (reg == bsp_reg)
  466                                         bsp = tmp_cpuref_cnt;
  467 
  468                                 for (a = 0; a < res/sizeof(cell_t); a++) {
  469                                         tmp_cpuref[tmp_cpuref_cnt].cr_hwref = interrupt_servers[a];
  470                                         tmp_cpuref[tmp_cpuref_cnt].cr_cpuid = tmp_cpuref_cnt;
  471                                         tmp_cpuref_cnt++;
  472                                 }
  473                         }
  474                 }
  475         }
  476 
  477         if (bsp == -1)
  478                 panic("Boot CPU not found\n");
  479 
  480         /* Map IDs, so BSP has CPUID 0 regardless of hwref */
  481         for (a = bsp; a < tmp_cpuref_cnt; a++) {
  482                 platform_cpuref[platform_cpuref_cnt].cr_hwref = tmp_cpuref[a].cr_hwref;
  483                 platform_cpuref[platform_cpuref_cnt].cr_cpuid = platform_cpuref_cnt;
  484                 platform_cpuref_cnt++;
  485         }
  486         for (a = 0; a < bsp; a++) {
  487                 platform_cpuref[platform_cpuref_cnt].cr_hwref = tmp_cpuref[a].cr_hwref;
  488                 platform_cpuref[platform_cpuref_cnt].cr_cpuid = platform_cpuref_cnt;
  489                 platform_cpuref_cnt++;
  490         }
  491 
  492         platform_cpuref_valid = 1;
  493 
  494         return (0);
  495 }
  496 
  497 #ifdef SMP
  498 static int
  499 chrp_smp_start_cpu(platform_t plat, struct pcpu *pc)
  500 {
  501         cell_t start_cpu;
  502         int result, err, timeout;
  503 
  504         if (!rtas_exists()) {
  505                 printf("RTAS uninitialized: unable to start AP %d\n",
  506                     pc->pc_cpuid);
  507                 return (ENXIO);
  508         }
  509 
  510         start_cpu = rtas_token_lookup("start-cpu");
  511         if (start_cpu == -1) {
  512                 printf("RTAS unknown method: unable to start AP %d\n",
  513                     pc->pc_cpuid);
  514                 return (ENXIO);
  515         }
  516 
  517         ap_pcpu = pc;
  518         powerpc_sync();
  519 
  520         result = rtas_call_method(start_cpu, 3, 1, pc->pc_hwref, EXC_RST, pc,
  521             &err);
  522         if (result < 0 || err != 0) {
  523                 printf("RTAS error (%d/%d): unable to start AP %d\n",
  524                     result, err, pc->pc_cpuid);
  525                 return (ENXIO);
  526         }
  527 
  528         timeout = 10000;
  529         while (!pc->pc_awake && timeout--)
  530                 DELAY(100);
  531 
  532         return ((pc->pc_awake) ? 0 : EBUSY);
  533 }
  534 
  535 static void
  536 chrp_smp_probe_threads(platform_t plat)
  537 {
  538         struct pcpu *pc, *last_pc;
  539         int i, ncores;
  540 
  541         ncores = 0;
  542         last_pc = NULL;
  543         for (i = 0; i <= mp_maxid; i++) {
  544                 pc = pcpu_find(i);
  545                 if (pc == NULL)
  546                         continue;
  547                 if (last_pc == NULL || pc->pc_hwref != last_pc->pc_hwref)
  548                         ncores++;
  549                 last_pc = pc;
  550         }
  551 
  552         mp_ncores = ncores;
  553         if (mp_ncpus % ncores == 0)
  554                 smp_threads_per_core = mp_ncpus / ncores;
  555 }
  556 
  557 static struct cpu_group *
  558 chrp_smp_topo(platform_t plat)
  559 {
  560 
  561         if (mp_ncpus % mp_ncores != 0) {
  562                 printf("WARNING: Irregular SMP topology. Performance may be "
  563                      "suboptimal (%d CPUS, %d cores)\n", mp_ncpus, mp_ncores);
  564                 return (smp_topo_none());
  565         }
  566 
  567         /* Don't do anything fancier for non-threaded SMP */
  568         if (mp_ncpus == mp_ncores)
  569                 return (smp_topo_none());
  570 
  571         return (smp_topo_1level(CG_SHARE_L1, smp_threads_per_core,
  572             CG_FLAG_SMT));
  573 }
  574 #endif
  575 
  576 static void
  577 chrp_reset(platform_t platform)
  578 {
  579         OF_reboot();
  580 }
  581 
  582 #ifdef __powerpc64__
  583 static void
  584 phyp_cpu_idle(sbintime_t sbt)
  585 {
  586         register_t msr;
  587 
  588         msr = mfmsr();
  589 
  590         mtmsr(msr & ~PSL_EE);
  591         if (sched_runnable()) {
  592                 mtmsr(msr);
  593                 return;
  594         }
  595 
  596         phyp_hcall(H_CEDE); /* Re-enables interrupts internally */
  597         mtmsr(msr);
  598 }
  599 
  600 static void
  601 chrp_smp_ap_init(platform_t platform)
  602 {
  603         if (!(mfmsr() & PSL_HV)) {
  604                 /* Register VPA */
  605                 phyp_hcall(H_REGISTER_VPA, 1UL, PCPU_GET(hwref),
  606                     splpar_vpa[PCPU_GET(hwref)]);
  607 
  608                 /* Set interrupt priority */
  609                 phyp_hcall(H_CPPR, 0xff);
  610         }
  611 }
  612 #else
  613 static void
  614 chrp_smp_ap_init(platform_t platform)
  615 {
  616 }
  617 #endif

Cache object: 2b029d6c221b61db88cf047061a32fe2


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