Index: conf/files.powerpc =================================================================== --- conf/files.powerpc (revision 191935) +++ conf/files.powerpc (working copy) @@ -81,6 +81,7 @@ powerpc/aim/nexus.c optional aim powerpc/aim/ofw_machdep.c optional aim powerpc/aim/ofwmagic.S optional aim +powerpc/aim/platform_chrp.c optional aim powerpc/aim/swtch.S optional aim powerpc/aim/trap.c optional aim powerpc/aim/uma_machdep.c optional aim @@ -155,6 +156,8 @@ powerpc/powerpc/openpic.c standard powerpc/powerpc/pic_if.m standard powerpc/powerpc/pmap_dispatch.c standard +powerpc/powerpc/platform.c standard +powerpc/powerpc/platform_if.m standard powerpc/powerpc/sc_machdep.c optional sc powerpc/powerpc/setjmp.S standard powerpc/powerpc/sigcode.S standard Index: powerpc/booke/machdep.c =================================================================== --- powerpc/booke/machdep.c (revision 191935) +++ powerpc/booke/machdep.c (working copy) @@ -131,7 +131,7 @@ #include #include #include -#include +#include #include #include Index: powerpc/booke/vm_machdep.c =================================================================== --- powerpc/booke/vm_machdep.c (revision 191935) +++ powerpc/booke/vm_machdep.c (working copy) @@ -124,7 +124,7 @@ #include #include #include -#include +#include #include #include Index: powerpc/booke/pmap.c =================================================================== --- powerpc/booke/pmap.c (revision 191935) +++ powerpc/booke/pmap.c (working copy) @@ -79,7 +79,7 @@ #include #include #include -#include +#include #include #include Index: powerpc/powerpc/platform_if.m =================================================================== --- powerpc/powerpc/platform_if.m (revision 0) +++ powerpc/powerpc/platform_if.m (revision 0) @@ -0,0 +1,163 @@ +#- +# Copyright (c) 2009 Nathan Whitehorn +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD: head/sys/powerpc/powerpc/mmu_if.m 190684 2009-04-04 02:12:37Z marcel $ +# + +#include +#include +#include +#include + +#include +#include +#include + +/** + * @defgroup PLATFORM platform - KObj methods for PowerPC platform + * implementations + * @brief A set of methods required by all platform implementations. + * These are used to bring up secondary CPUs, supply the physical memory + * map, etc. + *@{ + */ + +INTERFACE platform; + +# +# Default implementations +# +CODE { + static void platform_null_attach(platform_t plat) + { + return; + } + static int platform_null_smp_first_cpu(platform_t plat, + struct cpuref *cpuref) + { + cpuref->cr_hwref = -1; + cpuref->cr_cpuid = 0; + return (0); + } + static int platform_null_smp_next_cpu(platform_t plat, + struct cpuref *_cpuref) + { + return (ENOENT); + } +}; + +/** + * @brief Probe for whether we are on this platform, returning the standard + * newbus probe codes. If we have Open Firmware or a flattened device tree, + * it is guaranteed to be available at this point. + */ +METHOD int probe { + platform_t _plat; +}; + + +/** + * @brief Attach this platform module. This happens before the MMU is online, + * so the platform module can install its own high-priority MMU module at + * this point. + */ +METHOD int attach { + platform_t _plat; +} DEFAULT platform_null_attach; + + +/** + * @brief Return the system's physical memory map. + * + * It shall provide the total and the available regions of RAM. + * The available regions need not take the kernel into account. + * + * @param _memp Array of physical memory chunks + * @param _memsz Number of physical memory chunks + * @param _availp Array of available physical memory chunks + * @param _availsz Number of available physical memory chunks + */ + +METHOD void mem_regions { + platform_t _plat; + struct mem_region **_memp; + int *_memsz; + struct mem_region **_availp; + int *_availsz; +}; + +/** + * @brief Get the CPU's timebase frequency, in ticks per second. + * + * @param _cpu CPU whose timebase to query + */ + +METHOD u_long timebase_freq { + platform_t _plat; + struct cpuref *_cpu; +}; + +# SMP bits + +/** + * @brief Fill the first CPU's cpuref + * + * @param _cpuref CPU + */ +METHOD int smp_first_cpu { + platform_t _plat; + struct cpuref *_cpuref; +} DEFAULT platform_null_smp_first_cpu; + +/** + * @brief Fill the next CPU's cpuref + * + * @param _cpuref CPU + */ +METHOD int smp_next_cpu { + platform_t _plat; + struct cpuref *_cpuref; +} DEFAULT platform_null_smp_next_cpu; + +/** + * @brief Find the boot processor + * + * @param _cpuref CPU + */ +METHOD int smp_get_bsp { + platform_t _plat; + struct cpuref *_cpuref; +} DEFAULT platform_null_smp_first_cpu; + +/** + * @brief Start a CPU + * + * @param _cpuref CPU + */ +METHOD int smp_start_cpu { + platform_t _plat; + struct pcpu *_cpu; +}; + Index: powerpc/powerpc/platform.c =================================================================== --- powerpc/powerpc/platform.c (revision 0) +++ powerpc/powerpc/platform.c (revision 0) @@ -0,0 +1,177 @@ +/*- + * Copyright (c) 2005 Peter Grehan + * Copyright (c) 2009 Nathan Whitehorn + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include +__FBSDID("$FreeBSD: head/sys/powerpc/powerpc/pmap_dispatch.c 190684 2009-04-04 02:12:37Z marcel $"); + +/* + * Dispatch platform calls to the appropriate platform implementation + * through a previously registered kernel object. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "platform_if.h" + +static platform_def_t *plat_def_impl; +static platform_t plat_obj; +static struct kobj_ops plat_kernel_kops; +static struct platform_kobj plat_kernel_obj; + +static char plat_name[64] = ""; +SYSCTL_STRING(_hw, OID_AUTO, platform, CTLFLAG_RD | CTLFLAG_TUN, + plat_name, 0, "Platform currently in use"); + +void +mem_regions(struct mem_region **phys, int *physsz, struct mem_region **avail, + int *availsz) +{ + PLATFORM_MEM_REGIONS(plat_obj, phys, physsz, avail, availsz); +} + +const char * +installed_platform() +{ + return (plat_def_impl->name); +} + +u_long +platform_timebase_freq(struct cpuref *cpu) +{ + return (PLATFORM_TIMEBASE_FREQ(plat_obj, cpu)); +} + +int +platform_smp_first_cpu(struct cpuref *cpu) +{ + return (PLATFORM_SMP_FIRST_CPU(plat_obj, cpu)); +} + +int +platform_smp_next_cpu(struct cpuref *cpu) +{ + return (PLATFORM_SMP_NEXT_CPU(plat_obj, cpu)); +} + +int +platform_smp_get_bsp(struct cpuref *cpu) +{ + return (PLATFORM_SMP_GET_BSP(plat_obj, cpu)); +} + +int +platform_smp_start_cpu(struct pcpu *cpu) +{ + return (PLATFORM_SMP_START_CPU(plat_obj, cpu)); +} + +/* + * Platform install routines. Highest priority wins, using the same + * algorithm as bus attachment. + */ +SET_DECLARE(platform_set, platform_def_t); + +void +platform_probe_and_attach() +{ + platform_def_t **platpp, *platp; + int prio, best_prio; + + plat_obj = &plat_kernel_obj; + best_prio = 0; + + /* + * Try to locate the best platform kobj + */ + SET_FOREACH(platpp, platform_set) { + platp = *platpp; + + /* + * Take care of compiling the selected class, and + * then statically initialise the MMU object + */ + kobj_class_compile_static(platp, &plat_kernel_kops); + kobj_init((kobj_t)plat_obj, platp); + + prio = PLATFORM_PROBE(plat_obj); + + /* Check for errors */ + if (prio > 0) + continue; + + /* + * Check if this module was specifically requested through + * the loader tunable we provide. + */ + if (strcmp(platp->name,plat_name) == 0) { + plat_def_impl = platp; + break; + } + + /* Otherwise, see if it is better than our current best */ + if (plat_def_impl == NULL || prio > best_prio) { + best_prio = prio; + plat_def_impl = platp; + } + + /* + * We can't free the KOBJ, since it is static. Luckily, + * this has no ill effects since it gets reset every time. + */ + } + + if (plat_def_impl == NULL) + panic("No platform module found!"); + + /* + * Recompile to make sure we ended with the + * correct one, and then attach. + */ + + kobj_class_compile_static(plat_def_impl, &plat_kernel_kops); + kobj_init((kobj_t)plat_obj, plat_def_impl); + + strlcpy(plat_name,plat_def_impl->name,sizeof(plat_name)); + + PLATFORM_ATTACH(plat_obj); +} + Index: powerpc/powerpc/mp_machdep.c =================================================================== --- powerpc/powerpc/mp_machdep.c (revision 191935) +++ powerpc/powerpc/mp_machdep.c (working copy) @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "pic_if.h" @@ -88,10 +89,10 @@ int error; mp_ncpus = 0; - error = powerpc_smp_first_cpu(&cpuref); + error = platform_smp_first_cpu(&cpuref); while (!error) { mp_ncpus++; - error = powerpc_smp_next_cpu(&cpuref); + error = platform_smp_next_cpu(&cpuref); } /* Sanity. */ if (mp_ncpus == 0) @@ -121,11 +122,11 @@ struct pcpu *pc; int error; - error = powerpc_smp_get_bsp(&bsp); + error = platform_smp_get_bsp(&bsp); KASSERT(error == 0, ("Don't know BSP")); KASSERT(bsp.cr_cpuid == 0, ("%s: cpuid != 0", __func__)); - error = powerpc_smp_first_cpu(&cpu); + error = platform_smp_first_cpu(&cpu); while (!error) { if (cpu.cr_cpuid >= MAXCPU) { printf("SMP: cpu%d: skipped -- ID out of range\n", @@ -150,7 +151,7 @@ all_cpus |= pc->pc_cpumask; next: - error = powerpc_smp_next_cpu(&cpu); + error = platform_smp_next_cpu(&cpu); } } @@ -188,7 +189,7 @@ if (!pc->pc_bsp) { printf("Waking up CPU %d (dev=%x)\n", pc->pc_cpuid, pc->pc_hwref); - powerpc_smp_start_cpu(pc); + platform_smp_start_cpu(pc); } else { __asm __volatile("mfspr %0,1023" : "=r"(pc->pc_pir)); pc->pc_awake = 1; Index: powerpc/powerpc/pmap_dispatch.c =================================================================== --- powerpc/powerpc/pmap_dispatch.c (revision 191935) +++ powerpc/powerpc/pmap_dispatch.c (working copy) @@ -509,7 +509,7 @@ if (mmup->name && !strcmp(mmup->name, name) && - prio >= curr_prio) { + (prio >= curr_prio || mmu_def_impl == NULL)) { curr_prio = prio; mmu_def_impl = mmup; return (TRUE); Index: powerpc/include/smp.h =================================================================== --- powerpc/include/smp.h (revision 191935) +++ powerpc/include/smp.h (working copy) @@ -46,11 +46,6 @@ u_int cr_cpuid; }; -int powerpc_smp_first_cpu(struct cpuref *); -int powerpc_smp_get_bsp(struct cpuref *); -int powerpc_smp_next_cpu(struct cpuref *); -int powerpc_smp_start_cpu(struct pcpu *); - void pmap_cpu_bootstrap(int); uint32_t cpudep_ap_bootstrap(void); void machdep_ap_bootstrap(void); Index: powerpc/include/powerpc.h =================================================================== --- powerpc/include/powerpc.h (revision 191935) +++ powerpc/include/powerpc.h (working copy) @@ -1,59 +0,0 @@ -/*- - * Copyright (C) 1996 Wolfgang Solfrank. - * Copyright (C) 1996 TooLs GmbH. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by TooLs GmbH. - * 4. The name of TooLs GmbH may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $NetBSD: powerpc.h,v 1.3 2000/06/01 00:49:59 matt Exp $ - * $FreeBSD$ - */ - -#ifndef _MACHINE_POWERPC_H_ -#define _MACHINE_POWERPC_H_ - -struct mem_region { - vm_offset_t mr_start; - vm_size_t mr_size; -}; - -void mem_regions(struct mem_region **, int *, struct mem_region **, int *); - -/* - * These two functions get used solely in boot() in machdep.c. - * - * Not sure whether boot itself should be implementation dependent instead. XXX - */ -void OF_halt(void); -void OF_reboot(void); - -int dk_match(char *name); - -void ofrootfound(void); - -extern int booted_partition; - -#endif /* _MACHINE_POWERPC_H_ */ Index: powerpc/include/ofw_machdep.h =================================================================== --- powerpc/include/ofw_machdep.h (revision 191935) +++ powerpc/include/ofw_machdep.h (working copy) @@ -33,6 +33,7 @@ #include #include #include +#include typedef uint32_t cell_t; @@ -42,4 +43,9 @@ void OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *)); boolean_t OF_bootstrap(void); +void OF_halt(void); +void OF_reboot(void); + +void ofw_mem_regions(struct mem_region **, int *, struct mem_region **, int *); + #endif /* _MACHINE_OFW_MACHDEP_H_ */ Index: powerpc/include/platform.h =================================================================== --- powerpc/include/platform.h (revision 191935) +++ powerpc/include/platform.h (working copy) @@ -32,9 +32,12 @@ * $FreeBSD$ */ -#ifndef _MACHINE_POWERPC_H_ -#define _MACHINE_POWERPC_H_ +#ifndef _MACHINE_PLATFORM_H_ +#define _MACHINE_PLATFORM_H_ +#include +#include + struct mem_region { vm_offset_t mr_start; vm_size_t mr_size; @@ -42,18 +45,15 @@ void mem_regions(struct mem_region **, int *, struct mem_region **, int *); -/* - * These two functions get used solely in boot() in machdep.c. - * - * Not sure whether boot itself should be implementation dependent instead. XXX - */ -void OF_halt(void); -void OF_reboot(void); +u_long platform_timebase_freq(struct cpuref *); -int dk_match(char *name); +int platform_smp_first_cpu(struct cpuref *); +int platform_smp_next_cpu(struct cpuref *); +int platform_smp_get_bsp(struct cpuref *); +int platform_smp_start_cpu(struct pcpu *); -void ofrootfound(void); +const char *installed_platform(void); +void platform_probe_and_attach(void); -extern int booted_partition; +#endif /* _MACHINE_PLATFORM_H_ */ -#endif /* _MACHINE_POWERPC_H_ */ Index: powerpc/include/platformvar.h =================================================================== --- powerpc/include/platformvar.h (revision 0) +++ powerpc/include/platformvar.h (revision 0) @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 2005 Peter Grehan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/sys/powerpc/include/mmuvar.h 176771 2008-03-03 17:17:00Z raj $ + */ + +#ifndef _MACHINE_PLATFORMVAR_H_ +#define _MACHINE_PLATFORMVAR_H_ + +/* + * A PowerPC platform implementation is declared with a kernel object and + * an associated method table, similar to a device driver. + * + * e.g. + * + * static platform_method_t chrp_methods[] = { + * PLATFORMMETHOD(platform_probe, chrp_probe), + * PLATFORMMETHOD(platform_mem_regions, ofw_mem_regions), + * ... + * PLATFORMMETHOD(platform_smp_first_cpu, chrp_smp_first_cpu), + * { 0, 0 } + * }; + * + * static platform_def_t chrp_platform = { + * "chrp", + * chrp_methods, + * sizeof(chrp_platform_softc), // or 0 if no softc + * }; + * + * PLATFORM_DEF(chrp_platform); + */ + +#include + +struct platform_kobj { + /* + * A platform instance is a kernel object + */ + KOBJ_FIELDS; + + /* + * Utility elements that an instance may use + */ + struct mtx platform_mtx; /* available for instance use */ + void *platform_iptr; /* instance data pointer */ + + /* + * Opaque data that can be overlaid with an instance-private + * structure. Platform code can test that this is large enough at + * compile time with a sizeof() test againt it's softc. There + * is also a run-time test when the platform kernel object is + * registered. + */ +#define PLATFORM_OPAQUESZ 64 + u_int platform_opaque[PLATFORM_OPAQUESZ]; +}; + +typedef struct platform_kobj *platform_t; +typedef struct kobj_class platform_def_t; +#define platform_method_t kobj_method_t + +#define PLATFORMMETHOD KOBJMETHOD + +#define PLATFORM_DEF(name) DATA_SET(platform_set, name) + +#endif /* _MACHINE_PLATFORMVAR_H_ */ Index: powerpc/aim/platform_chrp.c =================================================================== --- powerpc/aim/platform_chrp.c (revision 0) +++ powerpc/aim/platform_chrp.c (revision 0) @@ -0,0 +1,236 @@ +/*- + * Copyright (c) 2008 Marcel Moolenaar + * Copyright (c) 2009 Nathan Whitehorn + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: head/sys/powerpc/aim/mp_cpudep.c 190681 2009-04-04 00:22:44Z nwhitehorn $"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "platform_if.h" + +#ifdef SMP +extern void *ap_pcpu; +#endif + +static int chrp_probe(platform_t); +void chrp_mem_regions(platform_t, struct mem_region **phys, int *physsz, + struct mem_region **avail, int *availsz); +static u_long chrp_timebase_freq(platform_t, struct cpuref *cpuref); +static int chrp_smp_first_cpu(platform_t, struct cpuref *cpuref); +static int chrp_smp_next_cpu(platform_t, struct cpuref *cpuref); +static int chrp_smp_get_bsp(platform_t, struct cpuref *cpuref); +static int chrp_smp_start_cpu(platform_t, struct pcpu *cpu); + +static platform_method_t chrp_methods[] = { + PLATFORMMETHOD(platform_probe, chrp_probe), + PLATFORMMETHOD(platform_mem_regions, chrp_mem_regions), + PLATFORMMETHOD(platform_timebase_freq, chrp_timebase_freq), + + PLATFORMMETHOD(platform_smp_first_cpu, chrp_smp_first_cpu), + PLATFORMMETHOD(platform_smp_next_cpu, chrp_smp_next_cpu), + PLATFORMMETHOD(platform_smp_get_bsp, chrp_smp_get_bsp), + PLATFORMMETHOD(platform_smp_start_cpu, chrp_smp_start_cpu), + + { 0, 0 } +}; + +static platform_def_t chrp_platform = { + "chrp", + chrp_methods, + 0 +}; + +PLATFORM_DEF(chrp_platform); + +static int +chrp_probe(platform_t plat) +{ + if (OF_finddevice("/memory") != -1) + return (BUS_PROBE_GENERIC); + + return (ENXIO); +} + +void +chrp_mem_regions(platform_t plat, struct mem_region **phys, int *physsz, + struct mem_region **avail, int *availsz) +{ + ofw_mem_regions(phys,physsz,avail,availsz); +} + +static u_long +chrp_timebase_freq(platform_t plat, struct cpuref *cpuref) +{ + phandle_t phandle; + u_long ticks = -1; + + phandle = cpuref->cr_hwref; + + OF_getprop(phandle, "timebase-frequency", &ticks, sizeof(ticks)); + + if (ticks <= 0) + panic("Unable to determine timebase frequency!"); + + return (ticks); +} + + +static int +chrp_smp_fill_cpuref(struct cpuref *cpuref, phandle_t cpu) +{ + int cpuid, res; + + cpuref->cr_hwref = cpu; + res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid)); + if (res < 0) + return (ENOENT); + + cpuref->cr_cpuid = cpuid & 0xff; + return (0); +} + +static int +chrp_smp_first_cpu(platform_t plat, struct cpuref *cpuref) +{ + char buf[8]; + phandle_t cpu, dev, root; + int res; + + root = OF_peer(0); + + dev = OF_child(root); + while (dev != 0) { + res = OF_getprop(dev, "name", buf, sizeof(buf)); + if (res > 0 && strcmp(buf, "cpus") == 0) + break; + dev = OF_peer(dev); + } + if (dev == 0) + return (ENOENT); + + cpu = OF_child(dev); + while (cpu != 0) { + res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); + if (res > 0 && strcmp(buf, "cpu") == 0) + break; + cpu = OF_peer(cpu); + } + if (cpu == 0) + return (ENOENT); + + return (chrp_smp_fill_cpuref(cpuref, cpu)); +} + +static int +chrp_smp_next_cpu(platform_t plat, struct cpuref *cpuref) +{ + char buf[8]; + phandle_t cpu; + int res; + + cpu = OF_peer(cpuref->cr_hwref); + while (cpu != 0) { + res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); + if (res > 0 && strcmp(buf, "cpu") == 0) + break; + cpu = OF_peer(cpu); + } + if (cpu == 0) + return (ENOENT); + + return (chrp_smp_fill_cpuref(cpuref, cpu)); +} + +static int +chrp_smp_get_bsp(platform_t plat, struct cpuref *cpuref) +{ + ihandle_t inst; + phandle_t bsp, chosen; + int res; + + chosen = OF_finddevice("/chosen"); + if (chosen == 0) + return (ENXIO); + + res = OF_getprop(chosen, "cpu", &inst, sizeof(inst)); + if (res < 0) + return (ENXIO); + + bsp = OF_instance_to_package(inst); + return (chrp_smp_fill_cpuref(cpuref, bsp)); +} + +static int +chrp_smp_start_cpu(platform_t plat, struct pcpu *pc) +{ +#ifdef SMP + phandle_t cpu; + volatile uint8_t *rstvec; + int res, reset, timeout; + + cpu = pc->pc_hwref; + res = OF_getprop(cpu, "soft-reset", &reset, sizeof(reset)); + if (res < 0) + return (ENXIO); + + ap_pcpu = pc; + + rstvec = (uint8_t *)(0x80000000 + reset); + + *rstvec = 4; + powerpc_sync(); + DELAY(1); + *rstvec = 0; + powerpc_sync(); + + timeout = 1000; + while (!pc->pc_awake && timeout--) + DELAY(100); + + return ((pc->pc_awake) ? 0 : EBUSY); +#else + /* No SMP support */ + return (ENXIO); +#endif +} + Index: powerpc/aim/machdep.c =================================================================== --- powerpc/aim/machdep.c (revision 191935) +++ powerpc/aim/machdep.c (working copy) @@ -114,7 +114,6 @@ #include #include #include -#include #include #include #include @@ -472,14 +471,22 @@ */ mtmsr(msr); isync(); + + /* + * Choose a platform module so we can get the physical memory map. + */ + + platform_probe_and_attach(); /* - * Initialise virtual memory. + * Initialise virtual memory. Use BUS_PROBE_GENERIC priority + * in case the platform module had a better idea of what we + * should do. */ if (ppc64) - pmap_mmu_install(MMU_TYPE_G5, 0); + pmap_mmu_install(MMU_TYPE_G5, BUS_PROBE_GENERIC); else - pmap_mmu_install(MMU_TYPE_OEA, 0); + pmap_mmu_install(MMU_TYPE_OEA, BUS_PROBE_GENERIC); pmap_bootstrap(startkernel, endkernel); mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI); Index: powerpc/aim/vm_machdep.c =================================================================== --- powerpc/aim/vm_machdep.c (revision 191935) +++ powerpc/aim/vm_machdep.c (working copy) @@ -89,7 +89,6 @@ #include #include #include -#include #include Index: powerpc/aim/mp_cpudep.c =================================================================== --- powerpc/aim/mp_cpudep.c (revision 191935) +++ powerpc/aim/mp_cpudep.c (working copy) @@ -54,91 +54,6 @@ void *ap_pcpu; -static int -powerpc_smp_fill_cpuref(struct cpuref *cpuref, phandle_t cpu) -{ - int cpuid, res; - - cpuref->cr_hwref = cpu; - res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid)); - if (res < 0) - return (ENOENT); - - cpuref->cr_cpuid = cpuid & 0xff; - return (0); -} - -int -powerpc_smp_first_cpu(struct cpuref *cpuref) -{ - char buf[8]; - phandle_t cpu, dev, root; - int res; - - root = OF_peer(0); - - dev = OF_child(root); - while (dev != 0) { - res = OF_getprop(dev, "name", buf, sizeof(buf)); - if (res > 0 && strcmp(buf, "cpus") == 0) - break; - dev = OF_peer(dev); - } - if (dev == 0) - return (ENOENT); - - cpu = OF_child(dev); - while (cpu != 0) { - res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); - if (res > 0 && strcmp(buf, "cpu") == 0) - break; - cpu = OF_peer(cpu); - } - if (cpu == 0) - return (ENOENT); - - return (powerpc_smp_fill_cpuref(cpuref, cpu)); -} - -int -powerpc_smp_next_cpu(struct cpuref *cpuref) -{ - char buf[8]; - phandle_t cpu; - int res; - - cpu = OF_peer(cpuref->cr_hwref); - while (cpu != 0) { - res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); - if (res > 0 && strcmp(buf, "cpu") == 0) - break; - cpu = OF_peer(cpu); - } - if (cpu == 0) - return (ENOENT); - - return (powerpc_smp_fill_cpuref(cpuref, cpu)); -} - -int -powerpc_smp_get_bsp(struct cpuref *cpuref) -{ - ihandle_t inst; - phandle_t bsp, chosen; - int res; - - chosen = OF_finddevice("/chosen"); - if (chosen == 0) - return (ENXIO); - - res = OF_getprop(chosen, "cpu", &inst, sizeof(inst)); - if (res < 0) - return (ENXIO); - - bsp = OF_instance_to_package(inst); - return (powerpc_smp_fill_cpuref(cpuref, bsp)); -} - static register_t l2_enable(void) { @@ -269,31 +184,3 @@ return (sp); } -int -powerpc_smp_start_cpu(struct pcpu *pc) -{ - phandle_t cpu; - volatile uint8_t *rstvec; - int res, reset, timeout; - - cpu = pc->pc_hwref; - res = OF_getprop(cpu, "soft-reset", &reset, sizeof(reset)); - if (res < 0) - return (ENXIO); - - ap_pcpu = pc; - - rstvec = (uint8_t *)(0x80000000 + reset); - - *rstvec = 4; - powerpc_sync(); - DELAY(1); - *rstvec = 0; - powerpc_sync(); - - timeout = 1000; - while (!pc->pc_awake && timeout--) - DELAY(100); - - return ((pc->pc_awake) ? 0 : EBUSY); -} Index: powerpc/aim/ofw_machdep.c =================================================================== --- powerpc/aim/ofw_machdep.c (revision 191935) +++ powerpc/aim/ofw_machdep.c (working copy) @@ -55,7 +55,7 @@ #include #include -#include +#include #include #define OFMEM_REGIONS 32 @@ -144,7 +144,7 @@ * to provide space for two additional entry beyond the terminating one. */ void -mem_regions(struct mem_region **memp, int *memsz, +ofw_mem_regions(struct mem_region **memp, int *memsz, struct mem_region **availp, int *availsz) { phandle_t phandle; Index: powerpc/aim/mmu_oea.c =================================================================== --- powerpc/aim/mmu_oea.c (revision 191935) +++ powerpc/aim/mmu_oea.c (working copy) @@ -141,7 +141,7 @@ #include #include -#include +#include #include #include #include Index: powerpc/aim/clock.c =================================================================== --- powerpc/aim/clock.c (revision 191935) +++ powerpc/aim/clock.c (working copy) @@ -125,44 +125,27 @@ void decr_init(void) { - int qhandle, phandle; - char name[32]; - unsigned int msr; + struct cpuref cpu; + register_t msr; - phandle = 0; - /* - * Get this info during autoconf? XXX + * Check the BSP's timebase frequency. Sometimes we can't find the BSP, so fall + * back to the first CPU in this case. */ - for (qhandle = OF_peer(0); qhandle; qhandle = phandle) { - if (OF_getprop(qhandle, "device_type", name, sizeof name) >= 0 - && !strcmp(name, "cpu") - && OF_getprop(qhandle, "timebase-frequency", - &ticks_per_sec, sizeof ticks_per_sec) >= 0) { - /* - * Should check for correct CPU here? XXX - */ - msr = mfmsr(); - mtmsr(msr & ~PSL_EE); - ns_per_tick = 1000000000 / ticks_per_sec; - ticks_per_intr = ticks_per_sec / hz; - mtdec(ticks_per_intr); + if (platform_smp_get_bsp(&cpu) != 0) + platform_smp_first_cpu(&cpu); - mtmsr(msr); + ticks_per_sec = platform_timebase_freq(&cpu); - break; - } - if ((phandle = OF_child(qhandle))) - continue; - while (qhandle) { - if ((phandle = OF_peer(qhandle))) - break; - qhandle = OF_parent(qhandle); - } - } - if (!phandle) - panic("no cpu node"); + msr = mfmsr(); + mtmsr(msr & ~PSL_EE); + + ns_per_tick = 1000000000 / ticks_per_sec; + ticks_per_intr = ticks_per_sec / hz; + mtdec(ticks_per_intr); + + mtmsr(msr); } void Index: powerpc/aim/mmu_oea64.c =================================================================== --- powerpc/aim/mmu_oea64.c (revision 191935) +++ powerpc/aim/mmu_oea64.c (working copy) @@ -143,7 +143,7 @@ #include #include -#include +#include #include #include #include