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_ */