Differentiate Hypervisor and SPMC platform power management
Provide independent platform power management implementations
depending on whether building for the normal world Hypervisor
or the secure world SPMC. The Hypervisor relies on directly
calling EL3 PSCI services whereas SPMC relies on FF-A interfaces
and SPMD call-backs.
Change-Id: I89739b01f03c37077b6c95a9ae09d4d1bfc847fe
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/inc/hf/arch/plat/psci.h b/inc/hf/arch/plat/psci.h
index 9ea5c2d..d42cbc7 100644
--- a/inc/hf/arch/plat/psci.h
+++ b/inc/hf/arch/plat/psci.h
@@ -11,6 +11,16 @@
#include "hf/vcpu.h"
/**
+ * Returns the platform specific PSCI version value.
+ */
+uint32_t plat_psci_version_get(void);
+
+/**
+ * Called once at boot time to initialize the platform power management module.
+ */
+void plat_psci_init(void);
+
+/**
* Called before the PSCI_CPU_SUSPEND SMC is forwarded. The power state is
* provided to allow actions to be taken based on the implementation defined
* meaning of this field.
diff --git a/project/reference b/project/reference
index 59e35f7..cf03990 160000
--- a/project/reference
+++ b/project/reference
@@ -1 +1 @@
-Subproject commit 59e35f7890bed57bcad59abdc0fa2a387b81eb6e
+Subproject commit cf03990877a2895ba2d6cda86cc9e65ce44bd507
diff --git a/src/arch/aarch64/args.gni b/src/arch/aarch64/args.gni
index 1430f85..521715e 100644
--- a/src/arch/aarch64/args.gni
+++ b/src/arch/aarch64/args.gni
@@ -6,7 +6,7 @@
declare_args() {
# PSCI hooks to be used for the platform, specified as build target.
- plat_psci = "//src/arch/aarch64/plat/psci:absent"
+ plat_psci = "//src/arch/aarch64/plat/psci:hypervisor"
# SMC hooks to be used for the platform, specified as build target.
plat_smc = "//src/arch/aarch64/plat/smc:absent"
diff --git a/src/arch/aarch64/hypervisor/psci_handler.c b/src/arch/aarch64/hypervisor/psci_handler.c
index 55704d4..825ec9f 100644
--- a/src/arch/aarch64/hypervisor/psci_handler.c
+++ b/src/arch/aarch64/hypervisor/psci_handler.c
@@ -21,35 +21,13 @@
#include "hf/vm.h"
#include "psci.h"
-#include "smc.h"
-
-static uint32_t el3_psci_version;
void cpu_entry(struct cpu *c);
/* Performs arch specific boot time initialisation. */
void arch_one_time_init(void)
{
- struct ffa_value smc_res =
- smc32(PSCI_VERSION, 0, 0, 0, 0, 0, 0, SMCCC_CALLER_HYPERVISOR);
-
- el3_psci_version = smc_res.func;
-
- /* Check there's nothing unexpected about PSCI. */
- switch (el3_psci_version) {
- case PSCI_VERSION_0_2:
- case PSCI_VERSION_1_0:
- case PSCI_VERSION_1_1:
- /* Supported EL3 PSCI version. */
- dlog_info("Found PSCI version: %#x\n", el3_psci_version);
- break;
-
- default:
- /* Unsupported EL3 PSCI version. Log a warning but continue. */
- dlog_warning("Unknown PSCI version: %#x\n", el3_psci_version);
- el3_psci_version = 0;
- break;
- }
+ plat_psci_init();
}
/**
@@ -75,7 +53,7 @@
* This blocks more calls than just PSCI so it may need to be made more
* lenient in future.
*/
- if (el3_psci_version == 0) {
+ if (plat_psci_version_get() == 0) {
*ret = SMCCC_ERROR_UNKNOWN;
return (func & SMCCC_SERVICE_CALL_MASK) ==
SMCCC_STANDARD_SECURE_SERVICE_CALL;
@@ -89,7 +67,7 @@
case PSCI_FEATURES:
switch (arg0 & ~SMCCC_CONVENTION_MASK) {
case PSCI_CPU_SUSPEND:
- if (el3_psci_version == PSCI_VERSION_0_2) {
+ if (plat_psci_version_get() == PSCI_VERSION_0_2) {
/*
* PSCI 0.2 doesn't support PSCI_FEATURES so
* report PSCI 0.2 compatible features.
diff --git a/src/arch/aarch64/plat/psci/BUILD.gn b/src/arch/aarch64/plat/psci/BUILD.gn
index 4ec1394..1cf223e 100644
--- a/src/arch/aarch64/plat/psci/BUILD.gn
+++ b/src/arch/aarch64/plat/psci/BUILD.gn
@@ -4,8 +4,18 @@
# license that can be found in the LICENSE file or at
# https://opensource.org/licenses/BSD-3-Clause.
-source_set("absent") {
+import("//build/toolchain/platform.gni")
+
+source_set("hypervisor") {
+ public_configs = [ "//src/arch/${plat_arch}:config" ]
sources = [
- "absent.c",
+ "hypervisor.c",
+ ]
+}
+
+source_set("spmc") {
+ public_configs = [ "//src/arch/${plat_arch}:config" ]
+ sources = [
+ "spmc.c",
]
}
diff --git a/src/arch/aarch64/plat/psci/absent.c b/src/arch/aarch64/plat/psci/absent.c
deleted file mode 100644
index a2a761a..0000000
--- a/src/arch/aarch64/plat/psci/absent.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright 2020 The Hafnium Authors.
- *
- * Use of this source code is governed by a BSD-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/BSD-3-Clause.
- */
-
-#include "hf/arch/plat/psci.h"
-
-void plat_psci_cpu_suspend(uint32_t power_state)
-{
- (void)power_state;
-}
-
-void plat_psci_cpu_resume(void)
-{
-}
diff --git a/src/arch/aarch64/plat/psci/hypervisor.c b/src/arch/aarch64/plat/psci/hypervisor.c
new file mode 100644
index 0000000..9f1b5bf
--- /dev/null
+++ b/src/arch/aarch64/plat/psci/hypervisor.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2020 The Hafnium Authors.
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/BSD-3-Clause.
+ */
+
+#include "hf/cpu.h"
+#include "hf/dlog.h"
+
+#include "psci.h"
+
+static uint32_t el3_psci_version;
+
+/**
+ * Returns the PSCI version gathered from the EL3 PSCI layer during init.
+ */
+uint32_t plat_psci_version_get(void)
+{
+ return el3_psci_version;
+}
+
+/**
+ * Initialize the platform power managment module in context of
+ * running the Hypervisor. In particular it gathers the PSCI version
+ * from the EL3 PSCI firmware.
+ */
+void plat_psci_init(void)
+{
+ struct ffa_value smc_res =
+ smc32(PSCI_VERSION, 0, 0, 0, 0, 0, 0, SMCCC_CALLER_HYPERVISOR);
+
+ el3_psci_version = smc_res.func;
+
+ /* Check there's nothing unexpected about PSCI. */
+ switch (el3_psci_version) {
+ case PSCI_VERSION_0_2:
+ case PSCI_VERSION_1_0:
+ case PSCI_VERSION_1_1:
+ /* Supported EL3 PSCI version. */
+ dlog_info("Found PSCI version: %#x\n", el3_psci_version);
+ break;
+
+ default:
+ /* Unsupported EL3 PSCI version. Log a warning but continue. */
+ dlog_warning("Unknown PSCI version: %#x\n", el3_psci_version);
+ el3_psci_version = 0;
+ break;
+ }
+}
+
+void plat_psci_cpu_suspend(uint32_t power_state)
+{
+ (void)power_state;
+}
+
+void plat_psci_cpu_resume(void)
+{
+}
diff --git a/src/arch/aarch64/plat/psci/spmc.c b/src/arch/aarch64/plat/psci/spmc.c
new file mode 100644
index 0000000..cc43ea3
--- /dev/null
+++ b/src/arch/aarch64/plat/psci/spmc.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 The Hafnium Authors.
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/BSD-3-Clause.
+ */
+
+#include "hf/cpu.h"
+#include "hf/dlog.h"
+
+#include "psci.h"
+
+/**
+ * Returns zero in context of the SPMC as it does not rely
+ * on the EL3 PSCI framework.
+ */
+uint32_t plat_psci_version_get(void)
+{
+ return 0;
+}
+
+/**
+ * Initialize the platform power managment module in context of
+ * running the SPMC.
+ */
+void plat_psci_init(void)
+{
+}
+
+void plat_psci_cpu_suspend(uint32_t power_state)
+{
+ (void)power_state;
+}
+
+void plat_psci_cpu_resume(void)
+{
+}