On Thu, Feb 23, 2017 at 01:03:57PM +1100, Jonathan Gray wrote: > On Wed, Feb 22, 2017 at 06:45:52PM -0500, Dale Rahn wrote: > > Add psci 2.0 features to spin up/down/suspend processors. > > > > This change uses extern weak symbols to determine if the platform supports > > the cpu_on/cpu_off/cpu_suspend features. If available, it saves the fdt > > provided argument values. > > > > Some PSCI calls will return an int status, so the callfn has been updated > > to return that status (eg cpu_on fail) > > > > diff --git a/sys/dev/fdt/psci.c b/sys/dev/fdt/psci.c > > index fceafd0e9ba..3177ff06beb 100644 > > --- a/sys/dev/fdt/psci.c > > +++ b/sys/dev/fdt/psci.c > > @@ -29,12 +29,19 @@ > > extern void (*cpuresetfn)(void); > > extern void (*powerdownfn)(void); > > > > +extern int (*cpu_suspend_fn)(void) __attribute__((weak)) ; > > +extern int (*cpu_off_fn)(void) __attribute__((weak)) ; > > +extern int (*cpu_on_fn)(uint64_t, uint64_t) __attribute__((weak)) ; > > + > > #define SYSTEM_OFF 0x84000008 > > #define SYSTEM_RESET 0x84000009 > > > > struct psci_softc { > > struct device sc_dev; > > - void (*callfn)(uint32_t, uint32_t, uint32_t, > > uint32_t); > > + int (*callfn)(uint32_t, uint32_t, uint32_t, > > uint32_t); > > + int sc_cpu_on; > > + int sc_cpu_off; > > + int sc_cpu_suspend; > > }; > > spacing is out here > sure. > > > > struct psci_softc *psci_sc; > > @@ -43,9 +50,12 @@ int psci_match(struct device *, void *, void *); > > void psci_attach(struct device *, struct device *, void *); > > void psci_reset(void); > > void psci_powerdown(void); > > +int psci_cpu_suspend(void); > > +int psci_cpu_off(void); > > +int psci_cpu_on(uint64_t, uint64_t); > > > > -extern void hvc_call(uint32_t, uint32_t, uint32_t, uint32_t); > > -extern void smc_call(uint32_t, uint32_t, uint32_t, uint32_t); > > +extern int hvc_call(uint32_t, uint32_t, uint32_t, uint32_t); > > +extern int smc_call(uint32_t, uint32_t, uint32_t, uint32_t); > > > > struct cfattach psci_ca = { > > sizeof(struct psci_softc), psci_match, psci_attach > > @@ -83,6 +93,24 @@ psci_attach(struct device *parent, struct device *self, > > void *aux) > > psci_sc = sc; > > cpuresetfn = psci_reset; > > powerdownfn = psci_powerdown; > > + > > + if (&cpu_suspend_fn != NULL) { > > + sc->sc_cpu_suspend = OF_getpropint(faa->fa_node, "cpu_suspend", > > 0); > > + if (sc->sc_cpu_suspend != 0) > > + cpu_suspend_fn = psci_cpu_suspend; > > + } > > + > > + if (&cpu_on_fn != NULL) { > > + sc->sc_cpu_on = OF_getpropint(faa->fa_node, "cpu_on", 0); > > + if (sc->sc_cpu_on != 0) > > + cpu_on_fn = psci_cpu_on; > > + } > > + > > + if (&cpu_off_fn != NULL) { > > + sc->sc_cpu_off = OF_getpropint(faa->fa_node, "cpu_off", 0); > > + if (sc->sc_cpu_off != 0) > > + cpu_off_fn = psci_cpu_off; > > + } > > } > > Can these nodes be relied on as being present? > > Outside of qemu -M virt > > psci { > migrate = <0x84000005>; > cpu_on = <0x84000003>; > cpu_off = <0x84000002>; > cpu_suspend = <0x84000001>; > method = "hvc"; > compatible = "arm,psci-0.2", "arm,psci"; > }; > > I can only find > > arm/boot/dts/artpec6.dtsi: cpu_on = <0x84000003>; > arm/boot/dts/ecx-common.dtsi: cpu_on = <0x84000006>; > arm/boot/dts/keystone.dtsi: cpu_on = <0x84000003>; > arm/boot/dts/xenvm-4.2.dts: cpu_on = <2>; > arm64/boot/dts/al/alpine-v2.dtsi: cpu_on = <0x84000003>; > arm64/boot/dts/exynos/exynos5433.dtsi: cpu_on = <0xC4000003>; > arm64/boot/dts/lg/lg1312.dtsi: cpu_on = <0x84000003>; > arm64/boot/dts/lg/lg1313.dtsi: cpu_on = <0x84000003>; > arm64/boot/dts/mediatek/mt8173.dtsi: cpu_on = <0x84000003>; > arm64/boot/dts/sprd/sc9836.dtsi: cpu_on = > <0xc4000003>; > > 0x84000003 is SMC32, 0xC4000003 is SMC64 and there is actually > a different calling convention for these... > > The existing SYSTEM_OFF and SYSTEM_RESET uses are fine as they are just > a 32 bit function id with no arguments. But these new functions > need to care about the arguments. > > There is also PSCI_FEATURES in PSCI 1.0 that tests if function ids are > supported. >
No, these will not always be present, eg on the amd arm64 machines, it only implements PSCI 1.0 and uses a different method for cpu spinup. This was set up to only enable the callback if the property is present, however you have a point that it might be wise to check that the callback value matches the expected 64 bit callback value (0xc4000000 | callidx) It could make sense to only look for these if compatible indicates 2.0, but if it were only 1.0, why would it have the attribute? > > > void > > @@ -100,3 +128,31 @@ psci_powerdown(void) > > if (sc->callfn) > > (*sc->callfn)(SYSTEM_OFF, 0, 0, 0); > > } > > Shouldn't all of these have a sc->sc_cpu_suspend != 0 type test as well > to avoid calls with a function id of 0? > > You could skip the earlier != 0 tests and do them in these functions. If the property doesn't exist, the callback will not be registered. psci_cpu_on() et al should not be called directly , but only thru the callback. However, in the interest in preventing problems, either making the functions static or adding the check could make sense. > + if (sc->sc_cpu_off != 0) > + cpu_off_fn = psci_cpu_off; > > > + > > +int > > +psci_cpu_suspend() > > +{ > > + struct psci_softc *sc = psci_sc; > > + if (sc->callfn) > > + return (*sc->callfn)(sc->sc_cpu_suspend, 0, 0, 0); > > + return -1; > > +} > > + > > +int > > +psci_cpu_off() > > +{ > > + struct psci_softc *sc = psci_sc; > > + if (sc->callfn) > > + return (*sc->callfn)(sc->sc_cpu_off, 0, 0, 0); > > + return -1; > > + > > +} > > + > > +int > > +psci_cpu_on(uint64_t mpidr, uint64_t pc) > > +{ > > + struct psci_softc *sc = psci_sc; > > + if (sc->callfn) > > + return (*sc->callfn)(sc->sc_cpu_on, mpidr, pc, 0); > > + return -1; > > +} > > > > Dale Rahn dr...@dalerahn.com > > > Dale Rahn dr...@dalerahn.com