1*7a8d25c0SNathan Whitehorn /*- 2*7a8d25c0SNathan Whitehorn * Copyright (c) 2008 Marcel Moolenaar 3*7a8d25c0SNathan Whitehorn * Copyright (c) 2009 Nathan Whitehorn 4*7a8d25c0SNathan Whitehorn * All rights reserved. 5*7a8d25c0SNathan Whitehorn * 6*7a8d25c0SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 7*7a8d25c0SNathan Whitehorn * modification, are permitted provided that the following conditions 8*7a8d25c0SNathan Whitehorn * are met: 9*7a8d25c0SNathan Whitehorn * 10*7a8d25c0SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 11*7a8d25c0SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 12*7a8d25c0SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 13*7a8d25c0SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 14*7a8d25c0SNathan Whitehorn * documentation and/or other materials provided with the distribution. 15*7a8d25c0SNathan Whitehorn * 16*7a8d25c0SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17*7a8d25c0SNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18*7a8d25c0SNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19*7a8d25c0SNathan Whitehorn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20*7a8d25c0SNathan Whitehorn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21*7a8d25c0SNathan Whitehorn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22*7a8d25c0SNathan Whitehorn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23*7a8d25c0SNathan Whitehorn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24*7a8d25c0SNathan Whitehorn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25*7a8d25c0SNathan Whitehorn * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26*7a8d25c0SNathan Whitehorn */ 27*7a8d25c0SNathan Whitehorn 28*7a8d25c0SNathan Whitehorn #include <sys/cdefs.h> 29*7a8d25c0SNathan Whitehorn __FBSDID("$FreeBSD$"); 30*7a8d25c0SNathan Whitehorn 31*7a8d25c0SNathan Whitehorn #include <sys/param.h> 32*7a8d25c0SNathan Whitehorn #include <sys/systm.h> 33*7a8d25c0SNathan Whitehorn #include <sys/kernel.h> 34*7a8d25c0SNathan Whitehorn #include <sys/bus.h> 35*7a8d25c0SNathan Whitehorn #include <sys/pcpu.h> 36*7a8d25c0SNathan Whitehorn #include <sys/proc.h> 37*7a8d25c0SNathan Whitehorn #include <sys/smp.h> 38*7a8d25c0SNathan Whitehorn #include <vm/vm.h> 39*7a8d25c0SNathan Whitehorn #include <vm/pmap.h> 40*7a8d25c0SNathan Whitehorn 41*7a8d25c0SNathan Whitehorn #include <machine/bus.h> 42*7a8d25c0SNathan Whitehorn #include <machine/cpu.h> 43*7a8d25c0SNathan Whitehorn #include <machine/hid.h> 44*7a8d25c0SNathan Whitehorn #include <machine/platformvar.h> 45*7a8d25c0SNathan Whitehorn #include <machine/pmap.h> 46*7a8d25c0SNathan Whitehorn #include <machine/rtas.h> 47*7a8d25c0SNathan Whitehorn #include <machine/smp.h> 48*7a8d25c0SNathan Whitehorn #include <machine/spr.h> 49*7a8d25c0SNathan Whitehorn #include <machine/trap_aim.h> 50*7a8d25c0SNathan Whitehorn 51*7a8d25c0SNathan Whitehorn #include <dev/ofw/openfirm.h> 52*7a8d25c0SNathan Whitehorn #include <machine/ofw_machdep.h> 53*7a8d25c0SNathan Whitehorn 54*7a8d25c0SNathan Whitehorn #include "platform_if.h" 55*7a8d25c0SNathan Whitehorn 56*7a8d25c0SNathan Whitehorn #ifdef SMP 57*7a8d25c0SNathan Whitehorn extern void *ap_pcpu; 58*7a8d25c0SNathan Whitehorn #endif 59*7a8d25c0SNathan Whitehorn 60*7a8d25c0SNathan Whitehorn #ifdef __powerpc64__ 61*7a8d25c0SNathan Whitehorn static uint8_t splpar_vpa[640] __aligned(64); 62*7a8d25c0SNathan Whitehorn #endif 63*7a8d25c0SNathan Whitehorn 64*7a8d25c0SNathan Whitehorn static vm_offset_t realmaxaddr = VM_MAX_ADDRESS; 65*7a8d25c0SNathan Whitehorn 66*7a8d25c0SNathan Whitehorn static int chrp_probe(platform_t); 67*7a8d25c0SNathan Whitehorn static int chrp_attach(platform_t); 68*7a8d25c0SNathan Whitehorn void chrp_mem_regions(platform_t, struct mem_region **phys, int *physsz, 69*7a8d25c0SNathan Whitehorn struct mem_region **avail, int *availsz); 70*7a8d25c0SNathan Whitehorn static vm_offset_t chrp_real_maxaddr(platform_t); 71*7a8d25c0SNathan Whitehorn static u_long chrp_timebase_freq(platform_t, struct cpuref *cpuref); 72*7a8d25c0SNathan Whitehorn static int chrp_smp_first_cpu(platform_t, struct cpuref *cpuref); 73*7a8d25c0SNathan Whitehorn static int chrp_smp_next_cpu(platform_t, struct cpuref *cpuref); 74*7a8d25c0SNathan Whitehorn static int chrp_smp_get_bsp(platform_t, struct cpuref *cpuref); 75*7a8d25c0SNathan Whitehorn static void chrp_smp_ap_init(platform_t); 76*7a8d25c0SNathan Whitehorn #ifdef SMP 77*7a8d25c0SNathan Whitehorn static int chrp_smp_start_cpu(platform_t, struct pcpu *cpu); 78*7a8d25c0SNathan Whitehorn static struct cpu_group *chrp_smp_topo(platform_t plat); 79*7a8d25c0SNathan Whitehorn #endif 80*7a8d25c0SNathan Whitehorn static void chrp_reset(platform_t); 81*7a8d25c0SNathan Whitehorn #ifdef __powerpc64__ 82*7a8d25c0SNathan Whitehorn #include "phyp-hvcall.h" 83*7a8d25c0SNathan Whitehorn static void phyp_cpu_idle(sbintime_t sbt); 84*7a8d25c0SNathan Whitehorn #endif 85*7a8d25c0SNathan Whitehorn 86*7a8d25c0SNathan Whitehorn static platform_method_t chrp_methods[] = { 87*7a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_probe, chrp_probe), 88*7a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_attach, chrp_attach), 89*7a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_mem_regions, chrp_mem_regions), 90*7a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_real_maxaddr, chrp_real_maxaddr), 91*7a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_timebase_freq, chrp_timebase_freq), 92*7a8d25c0SNathan Whitehorn 93*7a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_smp_ap_init, chrp_smp_ap_init), 94*7a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_smp_first_cpu, chrp_smp_first_cpu), 95*7a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_smp_next_cpu, chrp_smp_next_cpu), 96*7a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_smp_get_bsp, chrp_smp_get_bsp), 97*7a8d25c0SNathan Whitehorn #ifdef SMP 98*7a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_smp_start_cpu, chrp_smp_start_cpu), 99*7a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_smp_topo, chrp_smp_topo), 100*7a8d25c0SNathan Whitehorn #endif 101*7a8d25c0SNathan Whitehorn 102*7a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_reset, chrp_reset), 103*7a8d25c0SNathan Whitehorn 104*7a8d25c0SNathan Whitehorn { 0, 0 } 105*7a8d25c0SNathan Whitehorn }; 106*7a8d25c0SNathan Whitehorn 107*7a8d25c0SNathan Whitehorn static platform_def_t chrp_platform = { 108*7a8d25c0SNathan Whitehorn "chrp", 109*7a8d25c0SNathan Whitehorn chrp_methods, 110*7a8d25c0SNathan Whitehorn 0 111*7a8d25c0SNathan Whitehorn }; 112*7a8d25c0SNathan Whitehorn 113*7a8d25c0SNathan Whitehorn PLATFORM_DEF(chrp_platform); 114*7a8d25c0SNathan Whitehorn 115*7a8d25c0SNathan Whitehorn static int 116*7a8d25c0SNathan Whitehorn chrp_probe(platform_t plat) 117*7a8d25c0SNathan Whitehorn { 118*7a8d25c0SNathan Whitehorn if (OF_finddevice("/memory") != -1 || OF_finddevice("/memory@0") != -1) 119*7a8d25c0SNathan Whitehorn return (BUS_PROBE_GENERIC); 120*7a8d25c0SNathan Whitehorn 121*7a8d25c0SNathan Whitehorn return (ENXIO); 122*7a8d25c0SNathan Whitehorn } 123*7a8d25c0SNathan Whitehorn 124*7a8d25c0SNathan Whitehorn static int 125*7a8d25c0SNathan Whitehorn chrp_attach(platform_t plat) 126*7a8d25c0SNathan Whitehorn { 127*7a8d25c0SNathan Whitehorn #ifdef __powerpc64__ 128*7a8d25c0SNathan Whitehorn /* XXX: check for /rtas/ibm,hypertas-functions? */ 129*7a8d25c0SNathan Whitehorn if (!(mfmsr() & PSL_HV)) { 130*7a8d25c0SNathan Whitehorn struct mem_region *phys, *avail; 131*7a8d25c0SNathan Whitehorn int nphys, navail; 132*7a8d25c0SNathan Whitehorn mem_regions(&phys, &nphys, &avail, &navail); 133*7a8d25c0SNathan Whitehorn realmaxaddr = phys[0].mr_size; 134*7a8d25c0SNathan Whitehorn 135*7a8d25c0SNathan Whitehorn pmap_mmu_install("mmu_phyp", BUS_PROBE_SPECIFIC); 136*7a8d25c0SNathan Whitehorn cpu_idle_hook = phyp_cpu_idle; 137*7a8d25c0SNathan Whitehorn 138*7a8d25c0SNathan Whitehorn /* Set up important VPA fields */ 139*7a8d25c0SNathan Whitehorn bzero(splpar_vpa, sizeof(splpar_vpa)); 140*7a8d25c0SNathan Whitehorn splpar_vpa[4] = (uint8_t)((sizeof(splpar_vpa) >> 8) & 0xff); 141*7a8d25c0SNathan Whitehorn splpar_vpa[5] = (uint8_t)(sizeof(splpar_vpa) & 0xff); 142*7a8d25c0SNathan Whitehorn splpar_vpa[0xba] = 1; /* Maintain FPRs */ 143*7a8d25c0SNathan Whitehorn splpar_vpa[0xbb] = 1; /* Maintain PMCs */ 144*7a8d25c0SNathan Whitehorn splpar_vpa[0xfc] = 0xff; /* Maintain full SLB */ 145*7a8d25c0SNathan Whitehorn splpar_vpa[0xfd] = 0xff; 146*7a8d25c0SNathan Whitehorn splpar_vpa[0xff] = 1; /* Maintain Altivec */ 147*7a8d25c0SNathan Whitehorn mb(); 148*7a8d25c0SNathan Whitehorn 149*7a8d25c0SNathan Whitehorn /* Set up hypervisor CPU stuff */ 150*7a8d25c0SNathan Whitehorn chrp_smp_ap_init(plat); 151*7a8d25c0SNathan Whitehorn } 152*7a8d25c0SNathan Whitehorn #endif 153*7a8d25c0SNathan Whitehorn 154*7a8d25c0SNathan Whitehorn return (0); 155*7a8d25c0SNathan Whitehorn } 156*7a8d25c0SNathan Whitehorn 157*7a8d25c0SNathan Whitehorn void 158*7a8d25c0SNathan Whitehorn chrp_mem_regions(platform_t plat, struct mem_region **phys, int *physsz, 159*7a8d25c0SNathan Whitehorn struct mem_region **avail, int *availsz) 160*7a8d25c0SNathan Whitehorn { 161*7a8d25c0SNathan Whitehorn ofw_mem_regions(phys,physsz,avail,availsz); 162*7a8d25c0SNathan Whitehorn } 163*7a8d25c0SNathan Whitehorn 164*7a8d25c0SNathan Whitehorn static vm_offset_t 165*7a8d25c0SNathan Whitehorn chrp_real_maxaddr(platform_t plat) 166*7a8d25c0SNathan Whitehorn { 167*7a8d25c0SNathan Whitehorn return (realmaxaddr); 168*7a8d25c0SNathan Whitehorn } 169*7a8d25c0SNathan Whitehorn 170*7a8d25c0SNathan Whitehorn static u_long 171*7a8d25c0SNathan Whitehorn chrp_timebase_freq(platform_t plat, struct cpuref *cpuref) 172*7a8d25c0SNathan Whitehorn { 173*7a8d25c0SNathan Whitehorn phandle_t phandle; 174*7a8d25c0SNathan Whitehorn int32_t ticks = -1; 175*7a8d25c0SNathan Whitehorn 176*7a8d25c0SNathan Whitehorn phandle = cpuref->cr_hwref; 177*7a8d25c0SNathan Whitehorn 178*7a8d25c0SNathan Whitehorn OF_getprop(phandle, "timebase-frequency", &ticks, sizeof(ticks)); 179*7a8d25c0SNathan Whitehorn 180*7a8d25c0SNathan Whitehorn if (ticks <= 0) 181*7a8d25c0SNathan Whitehorn panic("Unable to determine timebase frequency!"); 182*7a8d25c0SNathan Whitehorn 183*7a8d25c0SNathan Whitehorn return (ticks); 184*7a8d25c0SNathan Whitehorn } 185*7a8d25c0SNathan Whitehorn 186*7a8d25c0SNathan Whitehorn static int 187*7a8d25c0SNathan Whitehorn chrp_smp_first_cpu(platform_t plat, struct cpuref *cpuref) 188*7a8d25c0SNathan Whitehorn { 189*7a8d25c0SNathan Whitehorn char buf[8]; 190*7a8d25c0SNathan Whitehorn phandle_t cpu, dev, root; 191*7a8d25c0SNathan Whitehorn int res, cpuid; 192*7a8d25c0SNathan Whitehorn 193*7a8d25c0SNathan Whitehorn root = OF_peer(0); 194*7a8d25c0SNathan Whitehorn 195*7a8d25c0SNathan Whitehorn dev = OF_child(root); 196*7a8d25c0SNathan Whitehorn while (dev != 0) { 197*7a8d25c0SNathan Whitehorn res = OF_getprop(dev, "name", buf, sizeof(buf)); 198*7a8d25c0SNathan Whitehorn if (res > 0 && strcmp(buf, "cpus") == 0) 199*7a8d25c0SNathan Whitehorn break; 200*7a8d25c0SNathan Whitehorn dev = OF_peer(dev); 201*7a8d25c0SNathan Whitehorn } 202*7a8d25c0SNathan Whitehorn if (dev == 0) { 203*7a8d25c0SNathan Whitehorn /* 204*7a8d25c0SNathan Whitehorn * psim doesn't have a name property on the /cpus node, 205*7a8d25c0SNathan Whitehorn * but it can be found directly 206*7a8d25c0SNathan Whitehorn */ 207*7a8d25c0SNathan Whitehorn dev = OF_finddevice("/cpus"); 208*7a8d25c0SNathan Whitehorn if (dev == 0) 209*7a8d25c0SNathan Whitehorn return (ENOENT); 210*7a8d25c0SNathan Whitehorn } 211*7a8d25c0SNathan Whitehorn 212*7a8d25c0SNathan Whitehorn cpu = OF_child(dev); 213*7a8d25c0SNathan Whitehorn 214*7a8d25c0SNathan Whitehorn while (cpu != 0) { 215*7a8d25c0SNathan Whitehorn res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); 216*7a8d25c0SNathan Whitehorn if (res > 0 && strcmp(buf, "cpu") == 0) 217*7a8d25c0SNathan Whitehorn break; 218*7a8d25c0SNathan Whitehorn cpu = OF_peer(cpu); 219*7a8d25c0SNathan Whitehorn } 220*7a8d25c0SNathan Whitehorn if (cpu == 0) 221*7a8d25c0SNathan Whitehorn return (ENOENT); 222*7a8d25c0SNathan Whitehorn 223*7a8d25c0SNathan Whitehorn cpuref->cr_hwref = cpu; 224*7a8d25c0SNathan Whitehorn res = OF_getprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid, 225*7a8d25c0SNathan Whitehorn sizeof(cpuid)); 226*7a8d25c0SNathan Whitehorn if (res <= 0) 227*7a8d25c0SNathan Whitehorn res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid)); 228*7a8d25c0SNathan Whitehorn if (res <= 0) 229*7a8d25c0SNathan Whitehorn cpuid = 0; 230*7a8d25c0SNathan Whitehorn cpuref->cr_cpuid = cpuid; 231*7a8d25c0SNathan Whitehorn 232*7a8d25c0SNathan Whitehorn return (0); 233*7a8d25c0SNathan Whitehorn } 234*7a8d25c0SNathan Whitehorn 235*7a8d25c0SNathan Whitehorn static int 236*7a8d25c0SNathan Whitehorn chrp_smp_next_cpu(platform_t plat, struct cpuref *cpuref) 237*7a8d25c0SNathan Whitehorn { 238*7a8d25c0SNathan Whitehorn char buf[8]; 239*7a8d25c0SNathan Whitehorn phandle_t cpu; 240*7a8d25c0SNathan Whitehorn int i, res, cpuid; 241*7a8d25c0SNathan Whitehorn 242*7a8d25c0SNathan Whitehorn /* Check for whether it should be the next thread */ 243*7a8d25c0SNathan Whitehorn res = OF_getproplen(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s"); 244*7a8d25c0SNathan Whitehorn if (res > 0) { 245*7a8d25c0SNathan Whitehorn cell_t interrupt_servers[res/sizeof(cell_t)]; 246*7a8d25c0SNathan Whitehorn OF_getprop(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s", 247*7a8d25c0SNathan Whitehorn interrupt_servers, res); 248*7a8d25c0SNathan Whitehorn for (i = 0; i < res/sizeof(cell_t) - 1; i++) { 249*7a8d25c0SNathan Whitehorn if (interrupt_servers[i] == cpuref->cr_cpuid) { 250*7a8d25c0SNathan Whitehorn cpuref->cr_cpuid = interrupt_servers[i+1]; 251*7a8d25c0SNathan Whitehorn return (0); 252*7a8d25c0SNathan Whitehorn } 253*7a8d25c0SNathan Whitehorn } 254*7a8d25c0SNathan Whitehorn } 255*7a8d25c0SNathan Whitehorn 256*7a8d25c0SNathan Whitehorn /* Next CPU core/package */ 257*7a8d25c0SNathan Whitehorn cpu = OF_peer(cpuref->cr_hwref); 258*7a8d25c0SNathan Whitehorn while (cpu != 0) { 259*7a8d25c0SNathan Whitehorn res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); 260*7a8d25c0SNathan Whitehorn if (res > 0 && strcmp(buf, "cpu") == 0) 261*7a8d25c0SNathan Whitehorn break; 262*7a8d25c0SNathan Whitehorn cpu = OF_peer(cpu); 263*7a8d25c0SNathan Whitehorn } 264*7a8d25c0SNathan Whitehorn if (cpu == 0) 265*7a8d25c0SNathan Whitehorn return (ENOENT); 266*7a8d25c0SNathan Whitehorn 267*7a8d25c0SNathan Whitehorn cpuref->cr_hwref = cpu; 268*7a8d25c0SNathan Whitehorn res = OF_getprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid, 269*7a8d25c0SNathan Whitehorn sizeof(cpuid)); 270*7a8d25c0SNathan Whitehorn if (res <= 0) 271*7a8d25c0SNathan Whitehorn res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid)); 272*7a8d25c0SNathan Whitehorn if (res <= 0) 273*7a8d25c0SNathan Whitehorn cpuid = 0; 274*7a8d25c0SNathan Whitehorn cpuref->cr_cpuid = cpuid; 275*7a8d25c0SNathan Whitehorn 276*7a8d25c0SNathan Whitehorn return (0); 277*7a8d25c0SNathan Whitehorn } 278*7a8d25c0SNathan Whitehorn 279*7a8d25c0SNathan Whitehorn static int 280*7a8d25c0SNathan Whitehorn chrp_smp_get_bsp(platform_t plat, struct cpuref *cpuref) 281*7a8d25c0SNathan Whitehorn { 282*7a8d25c0SNathan Whitehorn ihandle_t inst; 283*7a8d25c0SNathan Whitehorn phandle_t bsp, chosen; 284*7a8d25c0SNathan Whitehorn int res, cpuid; 285*7a8d25c0SNathan Whitehorn 286*7a8d25c0SNathan Whitehorn chosen = OF_finddevice("/chosen"); 287*7a8d25c0SNathan Whitehorn if (chosen == 0) 288*7a8d25c0SNathan Whitehorn return (ENXIO); 289*7a8d25c0SNathan Whitehorn 290*7a8d25c0SNathan Whitehorn res = OF_getprop(chosen, "cpu", &inst, sizeof(inst)); 291*7a8d25c0SNathan Whitehorn if (res < 0) 292*7a8d25c0SNathan Whitehorn return (ENXIO); 293*7a8d25c0SNathan Whitehorn 294*7a8d25c0SNathan Whitehorn bsp = OF_instance_to_package(inst); 295*7a8d25c0SNathan Whitehorn 296*7a8d25c0SNathan Whitehorn /* Pick the primary thread. Can it be any other? */ 297*7a8d25c0SNathan Whitehorn cpuref->cr_hwref = bsp; 298*7a8d25c0SNathan Whitehorn res = OF_getprop(bsp, "ibm,ppc-interrupt-server#s", &cpuid, 299*7a8d25c0SNathan Whitehorn sizeof(cpuid)); 300*7a8d25c0SNathan Whitehorn if (res <= 0) 301*7a8d25c0SNathan Whitehorn res = OF_getprop(bsp, "reg", &cpuid, sizeof(cpuid)); 302*7a8d25c0SNathan Whitehorn if (res <= 0) 303*7a8d25c0SNathan Whitehorn cpuid = 0; 304*7a8d25c0SNathan Whitehorn cpuref->cr_cpuid = cpuid; 305*7a8d25c0SNathan Whitehorn 306*7a8d25c0SNathan Whitehorn return (0); 307*7a8d25c0SNathan Whitehorn } 308*7a8d25c0SNathan Whitehorn 309*7a8d25c0SNathan Whitehorn #ifdef SMP 310*7a8d25c0SNathan Whitehorn static int 311*7a8d25c0SNathan Whitehorn chrp_smp_start_cpu(platform_t plat, struct pcpu *pc) 312*7a8d25c0SNathan Whitehorn { 313*7a8d25c0SNathan Whitehorn cell_t start_cpu; 314*7a8d25c0SNathan Whitehorn int result, err, timeout; 315*7a8d25c0SNathan Whitehorn 316*7a8d25c0SNathan Whitehorn if (!rtas_exists()) { 317*7a8d25c0SNathan Whitehorn printf("RTAS uninitialized: unable to start AP %d\n", 318*7a8d25c0SNathan Whitehorn pc->pc_cpuid); 319*7a8d25c0SNathan Whitehorn return (ENXIO); 320*7a8d25c0SNathan Whitehorn } 321*7a8d25c0SNathan Whitehorn 322*7a8d25c0SNathan Whitehorn start_cpu = rtas_token_lookup("start-cpu"); 323*7a8d25c0SNathan Whitehorn if (start_cpu == -1) { 324*7a8d25c0SNathan Whitehorn printf("RTAS unknown method: unable to start AP %d\n", 325*7a8d25c0SNathan Whitehorn pc->pc_cpuid); 326*7a8d25c0SNathan Whitehorn return (ENXIO); 327*7a8d25c0SNathan Whitehorn } 328*7a8d25c0SNathan Whitehorn 329*7a8d25c0SNathan Whitehorn ap_pcpu = pc; 330*7a8d25c0SNathan Whitehorn powerpc_sync(); 331*7a8d25c0SNathan Whitehorn 332*7a8d25c0SNathan Whitehorn result = rtas_call_method(start_cpu, 3, 1, pc->pc_cpuid, EXC_RST, pc, 333*7a8d25c0SNathan Whitehorn &err); 334*7a8d25c0SNathan Whitehorn if (result < 0 || err != 0) { 335*7a8d25c0SNathan Whitehorn printf("RTAS error (%d/%d): unable to start AP %d\n", 336*7a8d25c0SNathan Whitehorn result, err, pc->pc_cpuid); 337*7a8d25c0SNathan Whitehorn return (ENXIO); 338*7a8d25c0SNathan Whitehorn } 339*7a8d25c0SNathan Whitehorn 340*7a8d25c0SNathan Whitehorn timeout = 10000; 341*7a8d25c0SNathan Whitehorn while (!pc->pc_awake && timeout--) 342*7a8d25c0SNathan Whitehorn DELAY(100); 343*7a8d25c0SNathan Whitehorn 344*7a8d25c0SNathan Whitehorn return ((pc->pc_awake) ? 0 : EBUSY); 345*7a8d25c0SNathan Whitehorn } 346*7a8d25c0SNathan Whitehorn 347*7a8d25c0SNathan Whitehorn static struct cpu_group * 348*7a8d25c0SNathan Whitehorn chrp_smp_topo(platform_t plat) 349*7a8d25c0SNathan Whitehorn { 350*7a8d25c0SNathan Whitehorn struct pcpu *pc, *last_pc; 351*7a8d25c0SNathan Whitehorn int i, ncores, ncpus; 352*7a8d25c0SNathan Whitehorn 353*7a8d25c0SNathan Whitehorn ncores = ncpus = 0; 354*7a8d25c0SNathan Whitehorn last_pc = NULL; 355*7a8d25c0SNathan Whitehorn for (i = 0; i <= mp_maxid; i++) { 356*7a8d25c0SNathan Whitehorn pc = pcpu_find(i); 357*7a8d25c0SNathan Whitehorn if (pc == NULL) 358*7a8d25c0SNathan Whitehorn continue; 359*7a8d25c0SNathan Whitehorn if (last_pc == NULL || pc->pc_hwref != last_pc->pc_hwref) 360*7a8d25c0SNathan Whitehorn ncores++; 361*7a8d25c0SNathan Whitehorn last_pc = pc; 362*7a8d25c0SNathan Whitehorn ncpus++; 363*7a8d25c0SNathan Whitehorn } 364*7a8d25c0SNathan Whitehorn 365*7a8d25c0SNathan Whitehorn if (ncpus % ncores != 0) { 366*7a8d25c0SNathan Whitehorn printf("WARNING: Irregular SMP topology. Performance may be " 367*7a8d25c0SNathan Whitehorn "suboptimal (%d CPUS, %d cores)\n", ncpus, ncores); 368*7a8d25c0SNathan Whitehorn return (smp_topo_none()); 369*7a8d25c0SNathan Whitehorn } 370*7a8d25c0SNathan Whitehorn 371*7a8d25c0SNathan Whitehorn /* Don't do anything fancier for non-threaded SMP */ 372*7a8d25c0SNathan Whitehorn if (ncpus == ncores) 373*7a8d25c0SNathan Whitehorn return (smp_topo_none()); 374*7a8d25c0SNathan Whitehorn 375*7a8d25c0SNathan Whitehorn return (smp_topo_1level(CG_SHARE_L1, ncpus / ncores, CG_FLAG_SMT)); 376*7a8d25c0SNathan Whitehorn } 377*7a8d25c0SNathan Whitehorn #endif 378*7a8d25c0SNathan Whitehorn 379*7a8d25c0SNathan Whitehorn static void 380*7a8d25c0SNathan Whitehorn chrp_reset(platform_t platform) 381*7a8d25c0SNathan Whitehorn { 382*7a8d25c0SNathan Whitehorn OF_reboot(); 383*7a8d25c0SNathan Whitehorn } 384*7a8d25c0SNathan Whitehorn 385*7a8d25c0SNathan Whitehorn #ifdef __powerpc64__ 386*7a8d25c0SNathan Whitehorn static void 387*7a8d25c0SNathan Whitehorn phyp_cpu_idle(sbintime_t sbt) 388*7a8d25c0SNathan Whitehorn { 389*7a8d25c0SNathan Whitehorn #ifdef NOTYET /* Causes hangs on QEMU */ 390*7a8d25c0SNathan Whitehorn phyp_hcall(H_CEDE); 391*7a8d25c0SNathan Whitehorn #endif 392*7a8d25c0SNathan Whitehorn } 393*7a8d25c0SNathan Whitehorn 394*7a8d25c0SNathan Whitehorn static void 395*7a8d25c0SNathan Whitehorn chrp_smp_ap_init(platform_t platform) 396*7a8d25c0SNathan Whitehorn { 397*7a8d25c0SNathan Whitehorn if (!(mfmsr() & PSL_HV)) { 398*7a8d25c0SNathan Whitehorn /* Set interrupt priority */ 399*7a8d25c0SNathan Whitehorn phyp_hcall(H_CPPR, 0xff); 400*7a8d25c0SNathan Whitehorn 401*7a8d25c0SNathan Whitehorn /* Register VPA */ 402*7a8d25c0SNathan Whitehorn phyp_hcall(H_REGISTER_VPA, 1UL, PCPU_GET(cpuid), splpar_vpa); 403*7a8d25c0SNathan Whitehorn } 404*7a8d25c0SNathan Whitehorn } 405*7a8d25c0SNathan Whitehorn #else 406*7a8d25c0SNathan Whitehorn static void 407*7a8d25c0SNathan Whitehorn chrp_smp_ap_init(platform_t platform) 408*7a8d25c0SNathan Whitehorn { 409*7a8d25c0SNathan Whitehorn } 410*7a8d25c0SNathan Whitehorn #endif 411*7a8d25c0SNathan Whitehorn 412