17a8d25c0SNathan Whitehorn /*- 27a8d25c0SNathan Whitehorn * Copyright (c) 2008 Marcel Moolenaar 37a8d25c0SNathan Whitehorn * Copyright (c) 2009 Nathan Whitehorn 47a8d25c0SNathan Whitehorn * All rights reserved. 57a8d25c0SNathan Whitehorn * 67a8d25c0SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 77a8d25c0SNathan Whitehorn * modification, are permitted provided that the following conditions 87a8d25c0SNathan Whitehorn * are met: 97a8d25c0SNathan Whitehorn * 107a8d25c0SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 117a8d25c0SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 127a8d25c0SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 137a8d25c0SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 147a8d25c0SNathan Whitehorn * documentation and/or other materials provided with the distribution. 157a8d25c0SNathan Whitehorn * 167a8d25c0SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 177a8d25c0SNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 187a8d25c0SNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 197a8d25c0SNathan Whitehorn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 207a8d25c0SNathan Whitehorn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 217a8d25c0SNathan Whitehorn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 227a8d25c0SNathan Whitehorn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 237a8d25c0SNathan Whitehorn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 247a8d25c0SNathan Whitehorn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 257a8d25c0SNathan Whitehorn * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 267a8d25c0SNathan Whitehorn */ 277a8d25c0SNathan Whitehorn 287a8d25c0SNathan Whitehorn #include <sys/cdefs.h> 297a8d25c0SNathan Whitehorn __FBSDID("$FreeBSD$"); 307a8d25c0SNathan Whitehorn 317a8d25c0SNathan Whitehorn #include <sys/param.h> 327a8d25c0SNathan Whitehorn #include <sys/systm.h> 337a8d25c0SNathan Whitehorn #include <sys/kernel.h> 347a8d25c0SNathan Whitehorn #include <sys/bus.h> 357a8d25c0SNathan Whitehorn #include <sys/pcpu.h> 367a8d25c0SNathan Whitehorn #include <sys/proc.h> 377a8d25c0SNathan Whitehorn #include <sys/smp.h> 387a8d25c0SNathan Whitehorn #include <vm/vm.h> 397a8d25c0SNathan Whitehorn #include <vm/pmap.h> 407a8d25c0SNathan Whitehorn 417a8d25c0SNathan Whitehorn #include <machine/bus.h> 427a8d25c0SNathan Whitehorn #include <machine/cpu.h> 437a8d25c0SNathan Whitehorn #include <machine/hid.h> 447a8d25c0SNathan Whitehorn #include <machine/platformvar.h> 457a8d25c0SNathan Whitehorn #include <machine/pmap.h> 467a8d25c0SNathan Whitehorn #include <machine/rtas.h> 477a8d25c0SNathan Whitehorn #include <machine/smp.h> 487a8d25c0SNathan Whitehorn #include <machine/spr.h> 497a8d25c0SNathan Whitehorn #include <machine/trap_aim.h> 507a8d25c0SNathan Whitehorn 517a8d25c0SNathan Whitehorn #include <dev/ofw/openfirm.h> 527a8d25c0SNathan Whitehorn #include <machine/ofw_machdep.h> 537a8d25c0SNathan Whitehorn 547a8d25c0SNathan Whitehorn #include "platform_if.h" 557a8d25c0SNathan Whitehorn 567a8d25c0SNathan Whitehorn #ifdef SMP 577a8d25c0SNathan Whitehorn extern void *ap_pcpu; 587a8d25c0SNathan Whitehorn #endif 597a8d25c0SNathan Whitehorn 607a8d25c0SNathan Whitehorn #ifdef __powerpc64__ 617a8d25c0SNathan Whitehorn static uint8_t splpar_vpa[640] __aligned(64); 627a8d25c0SNathan Whitehorn #endif 637a8d25c0SNathan Whitehorn 647a8d25c0SNathan Whitehorn static vm_offset_t realmaxaddr = VM_MAX_ADDRESS; 657a8d25c0SNathan Whitehorn 667a8d25c0SNathan Whitehorn static int chrp_probe(platform_t); 677a8d25c0SNathan Whitehorn static int chrp_attach(platform_t); 687a8d25c0SNathan Whitehorn void chrp_mem_regions(platform_t, struct mem_region **phys, int *physsz, 697a8d25c0SNathan Whitehorn struct mem_region **avail, int *availsz); 707a8d25c0SNathan Whitehorn static vm_offset_t chrp_real_maxaddr(platform_t); 717a8d25c0SNathan Whitehorn static u_long chrp_timebase_freq(platform_t, struct cpuref *cpuref); 727a8d25c0SNathan Whitehorn static int chrp_smp_first_cpu(platform_t, struct cpuref *cpuref); 737a8d25c0SNathan Whitehorn static int chrp_smp_next_cpu(platform_t, struct cpuref *cpuref); 747a8d25c0SNathan Whitehorn static int chrp_smp_get_bsp(platform_t, struct cpuref *cpuref); 757a8d25c0SNathan Whitehorn static void chrp_smp_ap_init(platform_t); 767a8d25c0SNathan Whitehorn #ifdef SMP 777a8d25c0SNathan Whitehorn static int chrp_smp_start_cpu(platform_t, struct pcpu *cpu); 787a8d25c0SNathan Whitehorn static struct cpu_group *chrp_smp_topo(platform_t plat); 797a8d25c0SNathan Whitehorn #endif 807a8d25c0SNathan Whitehorn static void chrp_reset(platform_t); 817a8d25c0SNathan Whitehorn #ifdef __powerpc64__ 827a8d25c0SNathan Whitehorn #include "phyp-hvcall.h" 837a8d25c0SNathan Whitehorn static void phyp_cpu_idle(sbintime_t sbt); 847a8d25c0SNathan Whitehorn #endif 857a8d25c0SNathan Whitehorn 867a8d25c0SNathan Whitehorn static platform_method_t chrp_methods[] = { 877a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_probe, chrp_probe), 887a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_attach, chrp_attach), 897a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_mem_regions, chrp_mem_regions), 907a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_real_maxaddr, chrp_real_maxaddr), 917a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_timebase_freq, chrp_timebase_freq), 927a8d25c0SNathan Whitehorn 937a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_smp_ap_init, chrp_smp_ap_init), 947a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_smp_first_cpu, chrp_smp_first_cpu), 957a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_smp_next_cpu, chrp_smp_next_cpu), 967a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_smp_get_bsp, chrp_smp_get_bsp), 977a8d25c0SNathan Whitehorn #ifdef SMP 987a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_smp_start_cpu, chrp_smp_start_cpu), 997a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_smp_topo, chrp_smp_topo), 1007a8d25c0SNathan Whitehorn #endif 1017a8d25c0SNathan Whitehorn 1027a8d25c0SNathan Whitehorn PLATFORMMETHOD(platform_reset, chrp_reset), 1037a8d25c0SNathan Whitehorn 1047a8d25c0SNathan Whitehorn { 0, 0 } 1057a8d25c0SNathan Whitehorn }; 1067a8d25c0SNathan Whitehorn 1077a8d25c0SNathan Whitehorn static platform_def_t chrp_platform = { 1087a8d25c0SNathan Whitehorn "chrp", 1097a8d25c0SNathan Whitehorn chrp_methods, 1107a8d25c0SNathan Whitehorn 0 1117a8d25c0SNathan Whitehorn }; 1127a8d25c0SNathan Whitehorn 1137a8d25c0SNathan Whitehorn PLATFORM_DEF(chrp_platform); 1147a8d25c0SNathan Whitehorn 1157a8d25c0SNathan Whitehorn static int 1167a8d25c0SNathan Whitehorn chrp_probe(platform_t plat) 1177a8d25c0SNathan Whitehorn { 1187a8d25c0SNathan Whitehorn if (OF_finddevice("/memory") != -1 || OF_finddevice("/memory@0") != -1) 1197a8d25c0SNathan Whitehorn return (BUS_PROBE_GENERIC); 1207a8d25c0SNathan Whitehorn 1217a8d25c0SNathan Whitehorn return (ENXIO); 1227a8d25c0SNathan Whitehorn } 1237a8d25c0SNathan Whitehorn 1247a8d25c0SNathan Whitehorn static int 1257a8d25c0SNathan Whitehorn chrp_attach(platform_t plat) 1267a8d25c0SNathan Whitehorn { 1277a8d25c0SNathan Whitehorn #ifdef __powerpc64__ 1287a8d25c0SNathan Whitehorn /* XXX: check for /rtas/ibm,hypertas-functions? */ 1297a8d25c0SNathan Whitehorn if (!(mfmsr() & PSL_HV)) { 1307a8d25c0SNathan Whitehorn struct mem_region *phys, *avail; 1317a8d25c0SNathan Whitehorn int nphys, navail; 1327a8d25c0SNathan Whitehorn mem_regions(&phys, &nphys, &avail, &navail); 1337a8d25c0SNathan Whitehorn realmaxaddr = phys[0].mr_size; 1347a8d25c0SNathan Whitehorn 1357a8d25c0SNathan Whitehorn pmap_mmu_install("mmu_phyp", BUS_PROBE_SPECIFIC); 1367a8d25c0SNathan Whitehorn cpu_idle_hook = phyp_cpu_idle; 1377a8d25c0SNathan Whitehorn 1387a8d25c0SNathan Whitehorn /* Set up important VPA fields */ 1397a8d25c0SNathan Whitehorn bzero(splpar_vpa, sizeof(splpar_vpa)); 1407a8d25c0SNathan Whitehorn splpar_vpa[4] = (uint8_t)((sizeof(splpar_vpa) >> 8) & 0xff); 1417a8d25c0SNathan Whitehorn splpar_vpa[5] = (uint8_t)(sizeof(splpar_vpa) & 0xff); 1427a8d25c0SNathan Whitehorn splpar_vpa[0xba] = 1; /* Maintain FPRs */ 1437a8d25c0SNathan Whitehorn splpar_vpa[0xbb] = 1; /* Maintain PMCs */ 1447a8d25c0SNathan Whitehorn splpar_vpa[0xfc] = 0xff; /* Maintain full SLB */ 1457a8d25c0SNathan Whitehorn splpar_vpa[0xfd] = 0xff; 1467a8d25c0SNathan Whitehorn splpar_vpa[0xff] = 1; /* Maintain Altivec */ 1477a8d25c0SNathan Whitehorn mb(); 1487a8d25c0SNathan Whitehorn 1497a8d25c0SNathan Whitehorn /* Set up hypervisor CPU stuff */ 1507a8d25c0SNathan Whitehorn chrp_smp_ap_init(plat); 1517a8d25c0SNathan Whitehorn } 1527a8d25c0SNathan Whitehorn #endif 1537a8d25c0SNathan Whitehorn 1549f706727SNathan Whitehorn /* Some systems (e.g. QEMU) need Open Firmware to stand down */ 1559f706727SNathan Whitehorn ofw_quiesce(); 1569f706727SNathan Whitehorn 1577a8d25c0SNathan Whitehorn return (0); 1587a8d25c0SNathan Whitehorn } 1597a8d25c0SNathan Whitehorn 1607a8d25c0SNathan Whitehorn void 1617a8d25c0SNathan Whitehorn chrp_mem_regions(platform_t plat, struct mem_region **phys, int *physsz, 1627a8d25c0SNathan Whitehorn struct mem_region **avail, int *availsz) 1637a8d25c0SNathan Whitehorn { 1647a8d25c0SNathan Whitehorn ofw_mem_regions(phys,physsz,avail,availsz); 1657a8d25c0SNathan Whitehorn } 1667a8d25c0SNathan Whitehorn 1677a8d25c0SNathan Whitehorn static vm_offset_t 1687a8d25c0SNathan Whitehorn chrp_real_maxaddr(platform_t plat) 1697a8d25c0SNathan Whitehorn { 1707a8d25c0SNathan Whitehorn return (realmaxaddr); 1717a8d25c0SNathan Whitehorn } 1727a8d25c0SNathan Whitehorn 1737a8d25c0SNathan Whitehorn static u_long 1747a8d25c0SNathan Whitehorn chrp_timebase_freq(platform_t plat, struct cpuref *cpuref) 1757a8d25c0SNathan Whitehorn { 1767a8d25c0SNathan Whitehorn phandle_t phandle; 1777a8d25c0SNathan Whitehorn int32_t ticks = -1; 1787a8d25c0SNathan Whitehorn 1797a8d25c0SNathan Whitehorn phandle = cpuref->cr_hwref; 1807a8d25c0SNathan Whitehorn 1817a8d25c0SNathan Whitehorn OF_getprop(phandle, "timebase-frequency", &ticks, sizeof(ticks)); 1827a8d25c0SNathan Whitehorn 1837a8d25c0SNathan Whitehorn if (ticks <= 0) 1847a8d25c0SNathan Whitehorn panic("Unable to determine timebase frequency!"); 1857a8d25c0SNathan Whitehorn 1867a8d25c0SNathan Whitehorn return (ticks); 1877a8d25c0SNathan Whitehorn } 1887a8d25c0SNathan Whitehorn 1897a8d25c0SNathan Whitehorn static int 1907a8d25c0SNathan Whitehorn chrp_smp_first_cpu(platform_t plat, struct cpuref *cpuref) 1917a8d25c0SNathan Whitehorn { 1927a8d25c0SNathan Whitehorn char buf[8]; 1937a8d25c0SNathan Whitehorn phandle_t cpu, dev, root; 1947a8d25c0SNathan Whitehorn int res, cpuid; 1957a8d25c0SNathan Whitehorn 1967a8d25c0SNathan Whitehorn root = OF_peer(0); 1977a8d25c0SNathan Whitehorn 1987a8d25c0SNathan Whitehorn dev = OF_child(root); 1997a8d25c0SNathan Whitehorn while (dev != 0) { 2007a8d25c0SNathan Whitehorn res = OF_getprop(dev, "name", buf, sizeof(buf)); 2017a8d25c0SNathan Whitehorn if (res > 0 && strcmp(buf, "cpus") == 0) 2027a8d25c0SNathan Whitehorn break; 2037a8d25c0SNathan Whitehorn dev = OF_peer(dev); 2047a8d25c0SNathan Whitehorn } 2057a8d25c0SNathan Whitehorn if (dev == 0) { 2067a8d25c0SNathan Whitehorn /* 2077a8d25c0SNathan Whitehorn * psim doesn't have a name property on the /cpus node, 2087a8d25c0SNathan Whitehorn * but it can be found directly 2097a8d25c0SNathan Whitehorn */ 2107a8d25c0SNathan Whitehorn dev = OF_finddevice("/cpus"); 2117a8d25c0SNathan Whitehorn if (dev == 0) 2127a8d25c0SNathan Whitehorn return (ENOENT); 2137a8d25c0SNathan Whitehorn } 2147a8d25c0SNathan Whitehorn 2157a8d25c0SNathan Whitehorn cpu = OF_child(dev); 2167a8d25c0SNathan Whitehorn 2177a8d25c0SNathan Whitehorn while (cpu != 0) { 2187a8d25c0SNathan Whitehorn res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); 2197a8d25c0SNathan Whitehorn if (res > 0 && strcmp(buf, "cpu") == 0) 2207a8d25c0SNathan Whitehorn break; 2217a8d25c0SNathan Whitehorn cpu = OF_peer(cpu); 2227a8d25c0SNathan Whitehorn } 2237a8d25c0SNathan Whitehorn if (cpu == 0) 2247a8d25c0SNathan Whitehorn return (ENOENT); 2257a8d25c0SNathan Whitehorn 2267a8d25c0SNathan Whitehorn cpuref->cr_hwref = cpu; 2277a8d25c0SNathan Whitehorn res = OF_getprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid, 2287a8d25c0SNathan Whitehorn sizeof(cpuid)); 2297a8d25c0SNathan Whitehorn if (res <= 0) 2307a8d25c0SNathan Whitehorn res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid)); 2317a8d25c0SNathan Whitehorn if (res <= 0) 2327a8d25c0SNathan Whitehorn cpuid = 0; 2337a8d25c0SNathan Whitehorn cpuref->cr_cpuid = cpuid; 2347a8d25c0SNathan Whitehorn 2357a8d25c0SNathan Whitehorn return (0); 2367a8d25c0SNathan Whitehorn } 2377a8d25c0SNathan Whitehorn 2387a8d25c0SNathan Whitehorn static int 2397a8d25c0SNathan Whitehorn chrp_smp_next_cpu(platform_t plat, struct cpuref *cpuref) 2407a8d25c0SNathan Whitehorn { 2417a8d25c0SNathan Whitehorn char buf[8]; 2427a8d25c0SNathan Whitehorn phandle_t cpu; 2437a8d25c0SNathan Whitehorn int i, res, cpuid; 2447a8d25c0SNathan Whitehorn 2457a8d25c0SNathan Whitehorn /* Check for whether it should be the next thread */ 2467a8d25c0SNathan Whitehorn res = OF_getproplen(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s"); 2477a8d25c0SNathan Whitehorn if (res > 0) { 2487a8d25c0SNathan Whitehorn cell_t interrupt_servers[res/sizeof(cell_t)]; 2497a8d25c0SNathan Whitehorn OF_getprop(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s", 2507a8d25c0SNathan Whitehorn interrupt_servers, res); 2517a8d25c0SNathan Whitehorn for (i = 0; i < res/sizeof(cell_t) - 1; i++) { 2527a8d25c0SNathan Whitehorn if (interrupt_servers[i] == cpuref->cr_cpuid) { 2537a8d25c0SNathan Whitehorn cpuref->cr_cpuid = interrupt_servers[i+1]; 2547a8d25c0SNathan Whitehorn return (0); 2557a8d25c0SNathan Whitehorn } 2567a8d25c0SNathan Whitehorn } 2577a8d25c0SNathan Whitehorn } 2587a8d25c0SNathan Whitehorn 2597a8d25c0SNathan Whitehorn /* Next CPU core/package */ 2607a8d25c0SNathan Whitehorn cpu = OF_peer(cpuref->cr_hwref); 2617a8d25c0SNathan Whitehorn while (cpu != 0) { 2627a8d25c0SNathan Whitehorn res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); 2637a8d25c0SNathan Whitehorn if (res > 0 && strcmp(buf, "cpu") == 0) 2647a8d25c0SNathan Whitehorn break; 2657a8d25c0SNathan Whitehorn cpu = OF_peer(cpu); 2667a8d25c0SNathan Whitehorn } 2677a8d25c0SNathan Whitehorn if (cpu == 0) 2687a8d25c0SNathan Whitehorn return (ENOENT); 2697a8d25c0SNathan Whitehorn 2707a8d25c0SNathan Whitehorn cpuref->cr_hwref = cpu; 2717a8d25c0SNathan Whitehorn res = OF_getprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid, 2727a8d25c0SNathan Whitehorn sizeof(cpuid)); 2737a8d25c0SNathan Whitehorn if (res <= 0) 2747a8d25c0SNathan Whitehorn res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid)); 2757a8d25c0SNathan Whitehorn if (res <= 0) 2767a8d25c0SNathan Whitehorn cpuid = 0; 2777a8d25c0SNathan Whitehorn cpuref->cr_cpuid = cpuid; 2787a8d25c0SNathan Whitehorn 2797a8d25c0SNathan Whitehorn return (0); 2807a8d25c0SNathan Whitehorn } 2817a8d25c0SNathan Whitehorn 2827a8d25c0SNathan Whitehorn static int 2837a8d25c0SNathan Whitehorn chrp_smp_get_bsp(platform_t plat, struct cpuref *cpuref) 2847a8d25c0SNathan Whitehorn { 2857a8d25c0SNathan Whitehorn ihandle_t inst; 2867a8d25c0SNathan Whitehorn phandle_t bsp, chosen; 2877a8d25c0SNathan Whitehorn int res, cpuid; 2887a8d25c0SNathan Whitehorn 2897a8d25c0SNathan Whitehorn chosen = OF_finddevice("/chosen"); 2907a8d25c0SNathan Whitehorn if (chosen == 0) 2917a8d25c0SNathan Whitehorn return (ENXIO); 2927a8d25c0SNathan Whitehorn 2937a8d25c0SNathan Whitehorn res = OF_getprop(chosen, "cpu", &inst, sizeof(inst)); 2947a8d25c0SNathan Whitehorn if (res < 0) 2957a8d25c0SNathan Whitehorn return (ENXIO); 2967a8d25c0SNathan Whitehorn 2977a8d25c0SNathan Whitehorn bsp = OF_instance_to_package(inst); 2987a8d25c0SNathan Whitehorn 2997a8d25c0SNathan Whitehorn /* Pick the primary thread. Can it be any other? */ 3007a8d25c0SNathan Whitehorn cpuref->cr_hwref = bsp; 3017a8d25c0SNathan Whitehorn res = OF_getprop(bsp, "ibm,ppc-interrupt-server#s", &cpuid, 3027a8d25c0SNathan Whitehorn sizeof(cpuid)); 3037a8d25c0SNathan Whitehorn if (res <= 0) 3047a8d25c0SNathan Whitehorn res = OF_getprop(bsp, "reg", &cpuid, sizeof(cpuid)); 3057a8d25c0SNathan Whitehorn if (res <= 0) 3067a8d25c0SNathan Whitehorn cpuid = 0; 3077a8d25c0SNathan Whitehorn cpuref->cr_cpuid = cpuid; 3087a8d25c0SNathan Whitehorn 3097a8d25c0SNathan Whitehorn return (0); 3107a8d25c0SNathan Whitehorn } 3117a8d25c0SNathan Whitehorn 3127a8d25c0SNathan Whitehorn #ifdef SMP 3137a8d25c0SNathan Whitehorn static int 3147a8d25c0SNathan Whitehorn chrp_smp_start_cpu(platform_t plat, struct pcpu *pc) 3157a8d25c0SNathan Whitehorn { 3167a8d25c0SNathan Whitehorn cell_t start_cpu; 3177a8d25c0SNathan Whitehorn int result, err, timeout; 3187a8d25c0SNathan Whitehorn 3197a8d25c0SNathan Whitehorn if (!rtas_exists()) { 3207a8d25c0SNathan Whitehorn printf("RTAS uninitialized: unable to start AP %d\n", 3217a8d25c0SNathan Whitehorn pc->pc_cpuid); 3227a8d25c0SNathan Whitehorn return (ENXIO); 3237a8d25c0SNathan Whitehorn } 3247a8d25c0SNathan Whitehorn 3257a8d25c0SNathan Whitehorn start_cpu = rtas_token_lookup("start-cpu"); 3267a8d25c0SNathan Whitehorn if (start_cpu == -1) { 3277a8d25c0SNathan Whitehorn printf("RTAS unknown method: unable to start AP %d\n", 3287a8d25c0SNathan Whitehorn pc->pc_cpuid); 3297a8d25c0SNathan Whitehorn return (ENXIO); 3307a8d25c0SNathan Whitehorn } 3317a8d25c0SNathan Whitehorn 3327a8d25c0SNathan Whitehorn ap_pcpu = pc; 3337a8d25c0SNathan Whitehorn powerpc_sync(); 3347a8d25c0SNathan Whitehorn 3357a8d25c0SNathan Whitehorn result = rtas_call_method(start_cpu, 3, 1, pc->pc_cpuid, EXC_RST, pc, 3367a8d25c0SNathan Whitehorn &err); 3377a8d25c0SNathan Whitehorn if (result < 0 || err != 0) { 3387a8d25c0SNathan Whitehorn printf("RTAS error (%d/%d): unable to start AP %d\n", 3397a8d25c0SNathan Whitehorn result, err, pc->pc_cpuid); 3407a8d25c0SNathan Whitehorn return (ENXIO); 3417a8d25c0SNathan Whitehorn } 3427a8d25c0SNathan Whitehorn 3437a8d25c0SNathan Whitehorn timeout = 10000; 3447a8d25c0SNathan Whitehorn while (!pc->pc_awake && timeout--) 3457a8d25c0SNathan Whitehorn DELAY(100); 3467a8d25c0SNathan Whitehorn 3477a8d25c0SNathan Whitehorn return ((pc->pc_awake) ? 0 : EBUSY); 3487a8d25c0SNathan Whitehorn } 3497a8d25c0SNathan Whitehorn 3507a8d25c0SNathan Whitehorn static struct cpu_group * 3517a8d25c0SNathan Whitehorn chrp_smp_topo(platform_t plat) 3527a8d25c0SNathan Whitehorn { 3537a8d25c0SNathan Whitehorn struct pcpu *pc, *last_pc; 3547a8d25c0SNathan Whitehorn int i, ncores, ncpus; 3557a8d25c0SNathan Whitehorn 3567a8d25c0SNathan Whitehorn ncores = ncpus = 0; 3577a8d25c0SNathan Whitehorn last_pc = NULL; 3587a8d25c0SNathan Whitehorn for (i = 0; i <= mp_maxid; i++) { 3597a8d25c0SNathan Whitehorn pc = pcpu_find(i); 3607a8d25c0SNathan Whitehorn if (pc == NULL) 3617a8d25c0SNathan Whitehorn continue; 3627a8d25c0SNathan Whitehorn if (last_pc == NULL || pc->pc_hwref != last_pc->pc_hwref) 3637a8d25c0SNathan Whitehorn ncores++; 3647a8d25c0SNathan Whitehorn last_pc = pc; 3657a8d25c0SNathan Whitehorn ncpus++; 3667a8d25c0SNathan Whitehorn } 3677a8d25c0SNathan Whitehorn 3687a8d25c0SNathan Whitehorn if (ncpus % ncores != 0) { 3697a8d25c0SNathan Whitehorn printf("WARNING: Irregular SMP topology. Performance may be " 3707a8d25c0SNathan Whitehorn "suboptimal (%d CPUS, %d cores)\n", ncpus, ncores); 3717a8d25c0SNathan Whitehorn return (smp_topo_none()); 3727a8d25c0SNathan Whitehorn } 3737a8d25c0SNathan Whitehorn 3747a8d25c0SNathan Whitehorn /* Don't do anything fancier for non-threaded SMP */ 3757a8d25c0SNathan Whitehorn if (ncpus == ncores) 3767a8d25c0SNathan Whitehorn return (smp_topo_none()); 3777a8d25c0SNathan Whitehorn 3787a8d25c0SNathan Whitehorn return (smp_topo_1level(CG_SHARE_L1, ncpus / ncores, CG_FLAG_SMT)); 3797a8d25c0SNathan Whitehorn } 3807a8d25c0SNathan Whitehorn #endif 3817a8d25c0SNathan Whitehorn 3827a8d25c0SNathan Whitehorn static void 3837a8d25c0SNathan Whitehorn chrp_reset(platform_t platform) 3847a8d25c0SNathan Whitehorn { 3857a8d25c0SNathan Whitehorn OF_reboot(); 3867a8d25c0SNathan Whitehorn } 3877a8d25c0SNathan Whitehorn 3887a8d25c0SNathan Whitehorn #ifdef __powerpc64__ 3897a8d25c0SNathan Whitehorn static void 3907a8d25c0SNathan Whitehorn phyp_cpu_idle(sbintime_t sbt) 3917a8d25c0SNathan Whitehorn { 3927a8d25c0SNathan Whitehorn phyp_hcall(H_CEDE); 3937a8d25c0SNathan Whitehorn } 3947a8d25c0SNathan Whitehorn 3957a8d25c0SNathan Whitehorn static void 3967a8d25c0SNathan Whitehorn chrp_smp_ap_init(platform_t platform) 3977a8d25c0SNathan Whitehorn { 3987a8d25c0SNathan Whitehorn if (!(mfmsr() & PSL_HV)) { 3997a8d25c0SNathan Whitehorn /* Set interrupt priority */ 4007a8d25c0SNathan Whitehorn phyp_hcall(H_CPPR, 0xff); 4017a8d25c0SNathan Whitehorn 4027a8d25c0SNathan Whitehorn /* Register VPA */ 4037a8d25c0SNathan Whitehorn phyp_hcall(H_REGISTER_VPA, 1UL, PCPU_GET(cpuid), splpar_vpa); 4047a8d25c0SNathan Whitehorn } 4057a8d25c0SNathan Whitehorn } 4067a8d25c0SNathan Whitehorn #else 4077a8d25c0SNathan Whitehorn static void 4087a8d25c0SNathan Whitehorn chrp_smp_ap_init(platform_t platform) 4097a8d25c0SNathan Whitehorn { 4107a8d25c0SNathan Whitehorn } 4117a8d25c0SNathan Whitehorn #endif 4127a8d25c0SNathan Whitehorn 413