Implement support for the PSCI_VERSION call and export the function such that
authorkettenis <kettenis@openbsd.org>
Wed, 17 Jan 2018 10:17:33 +0000 (10:17 +0000)
committerkettenis <kettenis@openbsd.org>
Wed, 17 Jan 2018 10:17:33 +0000 (10:17 +0000)
we can use it to defend against branch target injection attacks.

ok patrick@, visa@

sys/dev/fdt/files.fdt
sys/dev/fdt/psci.c
sys/dev/fdt/pscivar.h [new file with mode: 0644]

index f2aee89..65286f9 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files.fdt,v 1.36 2018/01/06 13:04:47 kettenis Exp $
+#      $OpenBSD: files.fdt,v 1.37 2018/01/17 10:17:33 kettenis Exp $
 #
 # Config file and device description for machine-independent FDT code.
 # Included by ports that need it.
@@ -69,7 +69,7 @@ file  dev/fdt/plrtc.c                 plrtc
 # ARM Power State Coordination Interface
 device psci
 attach psci at fdt
-file   dev/fdt/psci.c                  psci
+file   dev/fdt/psci.c                  psci needs-flag
 
 attach virtio at fdt with virtio_mmio
 file   dev/fdt/virtio_mmio.c           virtio_mmio
index e5761a8..69d20dd 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: psci.c,v 1.3 2017/12/29 14:45:15 kettenis Exp $       */
+/*     $OpenBSD: psci.c,v 1.4 2018/01/17 10:17:33 kettenis Exp $       */
 
 /*
  * Copyright (c) 2016 Jonathan Gray <jsg@openbsd.org>
 #include <dev/ofw/openfirm.h>
 #include <dev/ofw/fdt.h>
 
+#include <dev/fdt/pscivar.h>
+
 extern void (*cpuresetfn)(void);
 extern void (*powerdownfn)(void);
 extern int (*cpu_on_fn)(register_t, register_t);
 
+#define PSCI_VERSION   0x84000000
 #define SYSTEM_OFF     0x84000008
 #define SYSTEM_RESET   0x84000009
 #ifdef __LP64__
@@ -42,6 +45,7 @@ struct psci_softc {
        struct device    sc_dev;
        register_t       (*sc_callfn)(register_t, register_t, register_t,
                             register_t);
+       int              sc_psci_version; 
        int              sc_system_off;
        int              sc_system_reset;
        int              sc_cpu_on;
@@ -82,6 +86,7 @@ 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];
+       uint32_t version;
 
        if (OF_getprop(faa->fa_node, "method", method, sizeof(method))) {
                if (strcmp(method, "hvc") == 0)
@@ -97,6 +102,7 @@ psci_attach(struct device *parent, struct device *self, void *aux)
         */
        if (OF_is_compatible(faa->fa_node, "arm,psci-0.2") ||
            OF_is_compatible(faa->fa_node, "arm,psci-1.0")) {
+               sc->sc_psci_version = PSCI_VERSION;
                sc->sc_system_off = SYSTEM_OFF;
                sc->sc_system_reset = SYSTEM_RESET;
                sc->sc_cpu_on = CPU_ON;
@@ -108,9 +114,11 @@ psci_attach(struct device *parent, struct device *self, void *aux)
                sc->sc_cpu_on = OF_getpropint(faa->fa_node, "cpu_on", 0);
        }
 
-       printf("\n");
-
        psci_sc = sc;
+
+       version = psci_version();
+       printf(": PSCI %d.%d\n", version >> 16, version & 0xffff);
+
        if (sc->sc_system_off != 0)
                powerdownfn = psci_powerdown;
        if (sc->sc_system_reset != 0)
@@ -119,6 +127,18 @@ psci_attach(struct device *parent, struct device *self, void *aux)
                cpu_on_fn = psci_cpu_on;
 }
 
+uint32_t
+psci_version(void)
+{
+       struct psci_softc *sc = psci_sc;
+
+       if (sc && sc->sc_callfn && sc->sc_psci_version != 0)
+               return (*sc->sc_callfn)(sc->sc_psci_version, 0, 0, 0);
+
+       /* No version support; return 0.0. */
+       return 0;
+}
+
 void
 psci_reset(void)
 {
diff --git a/sys/dev/fdt/pscivar.h b/sys/dev/fdt/pscivar.h
new file mode 100644 (file)
index 0000000..77551db
--- /dev/null
@@ -0,0 +1,8 @@
+/* Public Domain */
+
+#ifndef _SYS_DEV_FDT_PSCIVAR_H_
+#define _SYS_DEV_FDT_PSCIVAR_H_
+
+uint32_t psci_version(void);
+
+#endif /* _SYS_DEV_FDT_PSCIVAR_H_ */