aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Shvetsov <maksims.svecovs@arm.com>2020-08-27 12:37:57 +0100
committerOlivier Deprez <olivier.deprez@arm.com>2021-03-11 17:35:33 +0100
commit9c0ebe4ee0fbb02b5dc44110f9c1f1648548d51d (patch)
treea1fca9a1aa80fc36e8500bfc4b36817f664a73e2
parent3dbb856045a9131efedb239bfc7a9f3bb574d4ee (diff)
downloadhafnium-9c0ebe4ee0fbb02b5dc44110f9c1f1648548d51d.tar.gz
FF-A: Register SPMC secondary core entry point.
When the primary physical core boots, the SPMC registers the entry point (FFA_SECONDARY_EP_REGISTER at physical FF-A instance) used for secondary core cold boot to the SPMD. All Secure Partitions are then initialized on their primary Execution Context. When the NWd (Hypervisor or OS Kernel) boots, it calls PSCI_CPU_ON (into EL3) for waking up physical cores. The PSCI layer calls into SPMD PM hooks, then the SPMD calls into the SPMC by an exception return to the registered secondary entry point. The target secondary core then reaches vcpu_main. As follow-up to 56a62c96, PSCI service calls from within the SWd are prevented. Change-Id: I2bd42ea54e1a7feebff20e878345ec196ff352e9 Signed-off-by: Max Shvetsov <maksims.svecovs@arm.com> Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
-rw-r--r--inc/hf/addr.h2
-rw-r--r--inc/vmapi/hf/ffa.h3
-rw-r--r--src/arch/aarch64/hypervisor/hypervisor_entry.S50
-rw-r--r--src/arch/aarch64/hypervisor/offsets.c2
-rw-r--r--src/arch/aarch64/plat/psci/spmc.c21
-rw-r--r--src/cpu.c13
6 files changed, 83 insertions, 8 deletions
diff --git a/inc/hf/addr.h b/inc/hf/addr.h
index 59e1b7a82..1f1e2bf47 100644
--- a/inc/hf/addr.h
+++ b/inc/hf/addr.h
@@ -71,7 +71,7 @@ static inline size_t pa_difference(paddr_t start, paddr_t end)
}
/**
- * Initializes an intermeditate physical address.
+ * Initializes an intermediate physical address.
*/
static inline ipaddr_t ipa_init(uintpaddr_t ipa)
{
diff --git a/inc/vmapi/hf/ffa.h b/inc/vmapi/hf/ffa.h
index 4e09301a1..30d50b7f3 100644
--- a/inc/vmapi/hf/ffa.h
+++ b/inc/vmapi/hf/ffa.h
@@ -25,6 +25,7 @@
/* FF-A function identifiers. */
#define FFA_ERROR_32 0x84000060
#define FFA_SUCCESS_32 0x84000061
+#define FFA_SUCCESS_64 0xC4000061
#define FFA_INTERRUPT_32 0x84000062
#define FFA_VERSION_32 0x84000063
#define FFA_FEATURES_32 0x84000064
@@ -50,6 +51,8 @@
#define FFA_MEM_RECLAIM_32 0x84000077
#define FFA_MEM_FRAG_RX_32 0x8400007A
#define FFA_MEM_FRAG_TX_32 0x8400007B
+#define FFA_SECONDARY_EP_REGISTER_32 0x84000084
+#define FFA_SECONDARY_EP_REGISTER_64 0xC4000084
/* FF-A error codes. */
#define FFA_NOT_SUPPORTED INT32_C(-1)
diff --git a/src/arch/aarch64/hypervisor/hypervisor_entry.S b/src/arch/aarch64/hypervisor/hypervisor_entry.S
index e85510ac2..be7c0a707 100644
--- a/src/arch/aarch64/hypervisor/hypervisor_entry.S
+++ b/src/arch/aarch64/hypervisor/hypervisor_entry.S
@@ -9,6 +9,13 @@
#include "hf/arch/offsets.h"
#include "msr.h"
+.macro get_core_affinity reg1 reg2
+ mrs \reg1, mpidr_el1
+ ubfx \reg2, \reg1, 0, 24
+ ubfx \reg1, \reg1, 32, 8
+ orr \reg1, \reg2, \reg1, lsl #32
+.endm
+
/**
* Called only on first boot after the image has been relocated and BSS zeroed.
*
@@ -25,10 +32,7 @@ image_entry:
add x28, x28, :lo12:cpus
/* Set the ID of this CPU from the affinity bits of mpidr. */
- mrs x30, mpidr_el1
- ubfx x29, x30, 0, 24
- ubfx x30, x30, 32, 8
- orr x30, x29, x30, lsl #32
+ get_core_affinity x30, x29
str x30, [x28, CPU_ID]
mov x0, x28
@@ -59,6 +63,44 @@ image_entry:
.section .text.entry, "ax"
.global cpu_entry
cpu_entry:
+#if SECURE_WORLD == 1
+
+ /* Get number of cpus gathered from DT. */
+ adrp x3, cpu_count
+ add x3, x3, :lo12:cpu_count
+ ldr w3, [x3]
+
+ /* Prevent number of CPUs to be higher than supported by platform. */
+ cmp w3, #MAX_CPUS
+ bhi .
+
+ /* x0 points to first cpu in cpus array. */
+ adrp x0, cpus
+ add x0, x0, :lo12:cpus
+
+ /* Get current core affinity. */
+ get_core_affinity x1, x2
+
+ /* Dead stop here if no more cpu. */
+0: cbz w3, 0b
+
+ sub w3, w3, #1
+
+ /* Get cpu id pointed to by x0 in cpu array. */
+ ldr x2, [x0, CPU_ID]
+
+ /* Exit if current core id matches cpu id. */
+ cmp x1, x2
+ beq 1f
+
+ /* Point to next cpu in cpus array and loop. */
+ add x0, x0, #CPU_SIZE
+ b 0b
+
+1: /* x0 points to current cpu in cpus array */
+
+#endif
+
bl mm_enable
bl prepare_for_c
diff --git a/src/arch/aarch64/hypervisor/offsets.c b/src/arch/aarch64/hypervisor/offsets.c
index 6b9275ddd..2273678b9 100644
--- a/src/arch/aarch64/hypervisor/offsets.c
+++ b/src/arch/aarch64/hypervisor/offsets.c
@@ -10,6 +10,8 @@
#include "hf/offset_size_header.h"
#include "hf/vm.h"
+DEFINE_SIZEOF(CPU_SIZE, struct cpu)
+
DEFINE_OFFSETOF(CPU_ID, struct cpu, id)
DEFINE_OFFSETOF(CPU_STACK_BOTTOM, struct cpu, stack_bottom)
DEFINE_OFFSETOF(VCPU_VM, struct vcpu, vm)
diff --git a/src/arch/aarch64/plat/psci/spmc.c b/src/arch/aarch64/plat/psci/spmc.c
index fbee9520c..b92e48fe5 100644
--- a/src/arch/aarch64/plat/psci/spmc.c
+++ b/src/arch/aarch64/plat/psci/spmc.c
@@ -11,6 +11,8 @@
#include "psci.h"
+void cpu_entry(struct cpu *c);
+
/**
* Returns zero in context of the SPMC as it does not rely
* on the EL3 PSCI framework.
@@ -26,6 +28,16 @@ uint32_t plat_psci_version_get(void)
*/
void plat_psci_init(void)
{
+ struct ffa_value res;
+
+ /* Register SPMC secondary cold boot entry point */
+ res = smc_ffa_call(
+ (struct ffa_value){.func = FFA_SECONDARY_EP_REGISTER_64,
+ .arg1 = (uintreg_t)&cpu_entry});
+
+ if (res.func != FFA_SUCCESS_64) {
+ panic("FFA_SECONDARY_EP_REGISTER_64 failed");
+ }
}
void plat_psci_cpu_suspend(uint32_t power_state)
@@ -35,6 +47,11 @@ void plat_psci_cpu_suspend(uint32_t power_state)
void plat_psci_cpu_resume(struct cpu *c, ipaddr_t entry_point)
{
- (void)c;
- (void)entry_point;
+ if (cpu_on(c, entry_point, 0UL)) {
+ /*
+ * This is the boot time PSCI cold reset path (svc_cpu_on_finish
+ * handler relayed by SPMD) on secondary cores.
+ */
+ dlog_verbose("%s: cpu mpidr 0x%x ON\n", __func__, c->id);
+ }
}
diff --git a/src/cpu.c b/src/cpu.c
index 11eb0a371..42c24289f 100644
--- a/src/cpu.c
+++ b/src/cpu.c
@@ -10,6 +10,8 @@
#include <stdalign.h>
+#include "hf/arch/cache.h"
+
#include "hf/api.h"
#include "hf/check.h"
#include "hf/dlog.h"
@@ -70,7 +72,7 @@ struct cpu cpus[MAX_CPUS] = {
},
};
-static uint32_t cpu_count = 1;
+uint32_t cpu_count = 1;
void cpu_module_init(const cpu_id_t *cpu_ids, size_t count)
{
@@ -111,6 +113,15 @@ void cpu_module_init(const cpu_id_t *cpu_ids, size_t count)
dlog_warning("Boot CPU's ID not found in config.\n");
cpus[0].id = boot_cpu_id;
}
+
+ /*
+ * Clean the cache for the cpus array such that secondary cores
+ * hitting the entry point can read the cpus array consistently
+ * with MMU off (hence data cache off).
+ */
+ arch_cache_clean_range(va_from_ptr(cpus), sizeof(cpus));
+
+ arch_cache_clean_range(va_from_ptr(&cpu_count), sizeof(cpu_count));
}
size_t cpu_index(struct cpu *c)