From dad1de186507445360aa9fc94bdc91dddcd054f8 Mon Sep 17 00:00:00 2001 From: Piotr Tworek Date: Thu, 28 Nov 2019 23:29:21 +0100 Subject: [PATCH] hw: Add interface for making basic ARM PSCI calls. So far this only exposes two functions allowing the code to turn on additional CPUs. There is much more functionality defined by PSCI spec but so far its not needed by Genode. Fixes #3672 --- repos/base-hw/src/include/hw/spec/arm/psci.h | 61 +++++++++++++++++++ .../src/include/hw/spec/arm/psci_call.h | 42 +++++++++++++ .../src/include/hw/spec/arm_64/psci_call.h | 43 +++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 repos/base-hw/src/include/hw/spec/arm/psci.h create mode 100644 repos/base-hw/src/include/hw/spec/arm/psci_call.h create mode 100644 repos/base-hw/src/include/hw/spec/arm_64/psci_call.h diff --git a/repos/base-hw/src/include/hw/spec/arm/psci.h b/repos/base-hw/src/include/hw/spec/arm/psci.h new file mode 100644 index 000000000..6950ff447 --- /dev/null +++ b/repos/base-hw/src/include/hw/spec/arm/psci.h @@ -0,0 +1,61 @@ +/** + * \brief Power State Coordination Interface 1.0 + * \author Piotr Tworek + * \date 2019-11-27 + */ + +/* + * Copyright (C) 2019 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__INCLUDE__HW__SPEC__ARM__PSCI_H_ +#define _SRC__INCLUDE__HW__SPEC__ARM__PSCI_H_ + +namespace Hw { template class Psci; } + +template +class Hw::Psci +{ + private: + + enum { + PSCI_32_BASE = 0x84000000, + PSCI_64_BASE = 0xC4000000, + }; + + enum { + CPU_OFF = 2, + CPU_ON = 3, + }; + + static inline constexpr bool _arch_32() { + return sizeof(unsigned long) == 4; } + + static inline constexpr unsigned long _psci_func(int func, + bool only_32) + { + return ((only_32 || _arch_32()) ? PSCI_32_BASE + : PSCI_64_BASE) + func; + } + + public: + + static bool cpu_on(unsigned long cpu_id, void *entrypoint) + { + return CONDUIT_FUNCTOR::call(_psci_func(CPU_ON, false), + cpu_id, + (unsigned long)entrypoint, + cpu_id) == 0; + } + + static bool cpu_off() + { + return CONDUIT_FUNCTOR::call(_psci_func(CPU_OFF, true), + 0, 0, 0) == 0; + } +}; + +#endif /* _SRC__INCLUDE__HW__SPEC__ARM__PSCI_H_ */ diff --git a/repos/base-hw/src/include/hw/spec/arm/psci_call.h b/repos/base-hw/src/include/hw/spec/arm/psci_call.h new file mode 100644 index 000000000..aaeb99be2 --- /dev/null +++ b/repos/base-hw/src/include/hw/spec/arm/psci_call.h @@ -0,0 +1,42 @@ +/** + * \brief PSCI call macro for arm_v7 + * \author Piotr Tworek + * \date 2019-11-27 + */ + +/* + * Copyright (C) 2019 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__INCLUDE__HW__SPEC__ARM__PSCI_CALL_H_ +#define _SRC__INCLUDE__HW__SPEC__ARM__PSCI_CALL_H_ + +#include + +#define PSCI_CALL_IMPL(instr) \ + static inline int call(unsigned int func, unsigned long a0, \ + unsigned int a1, unsigned int a2) { \ + unsigned long result = 0; \ + asm volatile ("mov r0, %1 \n" \ + "mov r1, %2 \n" \ + "mov r2, %3 \n" \ + "mov r3, %4 \n" \ + #instr " #0 \n" \ + "mov %0, r0 \n" \ + : "=r"(result) \ + : "r"(func), "r"(a0), "r"(a1), "r"(a2) \ + : "r0", "r1", "r2", "r3"); \ + return result; \ + } + +namespace Hw { + struct Psci_hvc_functor { PSCI_CALL_IMPL(hvc); }; + struct Psci_smc_functor { PSCI_CALL_IMPL(smc); }; +} + +#undef PSCI_CALL_IMPL + +#endif /* _SRC__INCLUDE__HW__SPEC__ARM__PSCI_CALL_H_ */ diff --git a/repos/base-hw/src/include/hw/spec/arm_64/psci_call.h b/repos/base-hw/src/include/hw/spec/arm_64/psci_call.h new file mode 100644 index 000000000..5b1e7706e --- /dev/null +++ b/repos/base-hw/src/include/hw/spec/arm_64/psci_call.h @@ -0,0 +1,43 @@ +/** + * \brief PSCI call macro for arm_v8 + * \author Piotr Tworek + * \date 2019-11-27 + */ + +/* + * Copyright (C) 2019 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__INCLUDE__HW__SPEC__ARM__PSCI_CALL_H_ +#define _SRC__INCLUDE__HW__SPEC__ARM__PSCI_CALL_H_ + +#include + +#define PSCI_CALL_IMPL(instr) \ + static inline int call(unsigned int func, unsigned long a0, \ + unsigned int a1, unsigned int a2) { \ + unsigned long result = 0; \ + asm volatile ("mov x0, %1 \n" \ + "mov x1, %2 \n" \ + "mov x2, %3 \n" \ + "mov x3, %4 \n" \ + #instr " #0 \n" \ + "mov %0, x0 \n" \ + : "=r"(result) \ + : "r"(func), "r"(a0), "r"(a1), "r"(a2) \ + : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", \ + "x8", "x9", "x10", "x11", "x12", "x13", "x14"); \ + return result; \ + } + +namespace Hw { + struct Psci_hvc_functor { PSCI_CALL_IMPL(hvc); }; + struct Psci_smc_functor { PSCI_CALL_IMPL(smc); }; +} + +#undef PSCI_CALL_IMPL + +#endif /* _SRC__INCLUDE__HW__SPEC__ARM__PSCI_CALL_H_ */