From: kettenis Date: Fri, 29 Dec 2017 14:45:15 +0000 (+0000) Subject: Use register_t instead of uint32_t in smc/hmc calls such that arguments X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=8bcbf207052f8f0d705ffddf70db076453884689;p=openbsd Use register_t instead of uint32_t in smc/hmc calls such that arguments to SMC64 functions don't get truncated. Implement support for the CPU_ON call. --- diff --git a/sys/arch/arm/arm/cpu.c b/sys/arch/arm/arm/cpu.c index 6ca966885f0..d51f20e9849 100644 --- a/sys/arch/arm/arm/cpu.c +++ b/sys/arch/arm/arm/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.42 2017/12/24 19:43:51 kettenis Exp $ */ +/* $OpenBSD: cpu.c,v 1.43 2017/12/29 14:45:15 kettenis Exp $ */ /* $NetBSD: cpu.c,v 1.56 2004/04/14 04:01:49 bsh Exp $ */ @@ -339,4 +339,4 @@ intr_barrier(void *ih) sched_barrier(NULL); } -/* End of cpu.c */ +int (*cpu_on_fn)(register_t, register_t); diff --git a/sys/arch/arm64/arm64/cpu.c b/sys/arch/arm64/arm64/cpu.c index 169a21f25ea..73ec87d00d3 100644 --- a/sys/arch/arm64/arm64/cpu.c +++ b/sys/arch/arm64/arm64/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.8 2017/12/24 19:42:51 kettenis Exp $ */ +/* $OpenBSD: cpu.c,v 1.9 2017/12/29 14:45:15 kettenis Exp $ */ /* * Copyright (c) 2016 Dale Rahn @@ -196,3 +196,5 @@ cpu_clockspeed(int *freq) *freq = clock_get_frequency(cpu_node, NULL) / 1000000; return 0; } + +int (*cpu_on_fn)(register_t, register_t); diff --git a/sys/dev/fdt/psci.c b/sys/dev/fdt/psci.c index b24613a275c..e5761a8aa33 100644 --- a/sys/dev/fdt/psci.c +++ b/sys/dev/fdt/psci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: psci.c,v 1.2 2017/02/27 08:39:25 patrick Exp $ */ +/* $OpenBSD: psci.c,v 1.3 2017/12/29 14:45:15 kettenis Exp $ */ /* * Copyright (c) 2016 Jonathan Gray @@ -28,15 +28,23 @@ extern void (*cpuresetfn)(void); extern void (*powerdownfn)(void); +extern int (*cpu_on_fn)(register_t, register_t); #define SYSTEM_OFF 0x84000008 #define SYSTEM_RESET 0x84000009 +#ifdef __LP64__ +#define CPU_ON 0xc4000003 +#else +#define CPU_ON 0x84000003 +#endif struct psci_softc { - struct device sc_dev; - void (*callfn)(uint32_t, uint32_t, uint32_t, uint32_t); - int sc_system_off; - int sc_system_reset; + struct device sc_dev; + register_t (*sc_callfn)(register_t, register_t, register_t, + register_t); + int sc_system_off; + int sc_system_reset; + int sc_cpu_on; }; struct psci_softc *psci_sc; @@ -45,9 +53,10 @@ 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_on(register_t, register_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 register_t hvc_call(register_t, register_t, register_t, register_t); +extern register_t smc_call(register_t, register_t, register_t, register_t); struct cfattach psci_ca = { sizeof(struct psci_softc), psci_match, psci_attach @@ -70,15 +79,15 @@ psci_match(struct device *parent, void *match, void *aux) void psci_attach(struct device *parent, struct device *self, void *aux) { - struct psci_softc *sc = (struct psci_softc *) self; - struct fdt_attach_args *faa = aux; - char method[128]; + struct psci_softc *sc = (struct psci_softc *)self; + struct fdt_attach_args *faa = aux; + char method[128]; if (OF_getprop(faa->fa_node, "method", method, sizeof(method))) { if (strcmp(method, "hvc") == 0) - sc->callfn = hvc_call; + sc->sc_callfn = hvc_call; else if (strcmp(method, "smc") == 0) - sc->callfn = smc_call; + sc->sc_callfn = smc_call; } /* @@ -90,11 +99,13 @@ psci_attach(struct device *parent, struct device *self, void *aux) OF_is_compatible(faa->fa_node, "arm,psci-1.0")) { sc->sc_system_off = SYSTEM_OFF; sc->sc_system_reset = SYSTEM_RESET; + sc->sc_cpu_on = CPU_ON; } else if (OF_is_compatible(faa->fa_node, "arm,psci")) { sc->sc_system_off = OF_getpropint(faa->fa_node, "system_off", 0); sc->sc_system_reset = OF_getpropint(faa->fa_node, "system_reset", 0); + sc->sc_cpu_on = OF_getpropint(faa->fa_node, "cpu_on", 0); } printf("\n"); @@ -104,20 +115,31 @@ psci_attach(struct device *parent, struct device *self, void *aux) powerdownfn = psci_powerdown; if (sc->sc_system_reset != 0) cpuresetfn = psci_reset; + if (sc->sc_cpu_on != 0) + cpu_on_fn = psci_cpu_on; } void psci_reset(void) { struct psci_softc *sc = psci_sc; - if (sc->callfn) - (*sc->callfn)(sc->sc_system_reset, 0, 0, 0); + if (sc->sc_callfn) + (*sc->sc_callfn)(sc->sc_system_reset, 0, 0, 0); } void psci_powerdown(void) { struct psci_softc *sc = psci_sc; - if (sc->callfn) - (*sc->callfn)(sc->sc_system_off, 0, 0, 0); + if (sc->sc_callfn) + (*sc->sc_callfn)(sc->sc_system_off, 0, 0, 0); +} + +int +psci_cpu_on(register_t mpidr, register_t pc) +{ + struct psci_softc *sc = psci_sc; + if (sc->sc_callfn) + return (*sc->sc_callfn)(sc->sc_cpu_on, mpidr, pc, 0); + return -1; }