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
This commit is contained in:
Piotr Tworek 2019-11-28 23:29:21 +01:00 committed by Christian Helmuth
parent 6f1357c6f8
commit dad1de1865
3 changed files with 146 additions and 0 deletions

View File

@ -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 <typename CONDUIT_FUNCTOR> class Psci; }
template <typename CONDUIT_FUNCTOR>
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_ */

View File

@ -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 <hw/spec/arm/psci.h>
#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_ */

View File

@ -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 <hw/spec/arm/psci.h>
#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_ */