1
0
mirror of https://git.yoctoproject.org/meta-arm synced 2026-05-07 04:58:57 +00:00

arm-bsp/tc0: Add hafnium support

Enables hafnium support for tc0.
Adds pending patches for SEL1 SP support.

Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: If5c12b7e7b7a301ae9a48a88223be3e51f38d3aa
Signed-off-by: Jon Mason <jon.mason@arm.com>
This commit is contained in:
Arunachalam Ganapathy
2021-01-12 15:20:42 +00:00
committed by Jon Mason
parent 9e00b6b884
commit 9fdf9297ac
5 changed files with 501 additions and 0 deletions
@@ -0,0 +1,324 @@
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
From cb329ce33874abd8b69988c3dc63fd323a3413be Mon Sep 17 00:00:00 2001
From: Max Shvetsov <maksims.svecovs@arm.com>
Date: Thu, 27 Aug 2020 12:37:57 +0100
Subject: [PATCH 1/4] FF-A: Register secondary core entry point at SPMC init.
When the primary physical core boots the SPMC registers its secondary physical
core entry points to the SPMD. All Secure Partition are then initialized on
their primary Execution Contexts. A Secure Partition calls PSCI_CPU_ON from its
first EC (trapped to the SPMC) passing entry point addresses of secondary ECs.
ECs are turned "on" in their SPMC internal states, although they do not run yet
(the service call does not reach the EL3 PSCI layer). Later, when the NWd
(Hypervisor or OS Kernel) boots, it calls PSCI_CPU_ON for waking up physical
cores down to EL3. 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 Hafnium vcpu_main.
Change-Id: I2bd42ea54e1a7feebff20e878345ec196ff352e9
Signed-off-by: Max Shvetsov <maksims.svecovs@arm.com>
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
---
inc/hf/arch/init.h | 7 ++
src/arch/aarch64/hypervisor/psci_handler.c | 131 +++++++++++++++++---
src/arch/aarch64/inc/hf/arch/spmd_helpers.h | 15 +++
src/cpu.c | 7 ++
src/init.c | 2 +
5 files changed, 143 insertions(+), 19 deletions(-)
create mode 100644 src/arch/aarch64/inc/hf/arch/spmd_helpers.h
diff --git a/inc/hf/arch/init.h b/inc/hf/arch/init.h
index 5205e4e..ef0e48f 100644
--- a/inc/hf/arch/init.h
+++ b/inc/hf/arch/init.h
@@ -8,6 +8,8 @@
#pragma once
+#include "hf/boot_params.h"
+
/**
* Performs arch specific boot time initialization.
*
@@ -15,3 +17,8 @@
* possible.
*/
void arch_one_time_init(void);
+
+/**
+ * Sets up secondary cores.
+ */
+void arch_psci_secondary_core_init(const struct boot_params *params);
diff --git a/src/arch/aarch64/hypervisor/psci_handler.c b/src/arch/aarch64/hypervisor/psci_handler.c
index f89a00b..bdcc1d3 100644
--- a/src/arch/aarch64/hypervisor/psci_handler.c
+++ b/src/arch/aarch64/hypervisor/psci_handler.c
@@ -11,9 +11,11 @@
#include <stdint.h>
#include "hf/arch/plat/psci.h"
+#include "hf/arch/spmd_helpers.h"
#include "hf/arch/types.h"
#include "hf/api.h"
+#include "hf/boot_params.h"
#include "hf/cpu.h"
#include "hf/dlog.h"
#include "hf/ffa.h"
@@ -24,9 +26,32 @@
#include "smc.h"
static uint32_t el3_psci_version;
+static ffa_vm_id_t physical_ffa_id;
void cpu_entry(struct cpu *c);
+#if SECURE_WORLD == 1
+
+static void set_ffa_id(void)
+{
+ struct ffa_value res =
+ smc_ffa_call((struct ffa_value){.func = FFA_ID_GET_32});
+
+ if (res.func != FFA_SUCCESS_32) {
+ dlog_error("%s Failed to get it's own FF-A ID.\n", __func__);
+ physical_ffa_id = HF_INVALID_VM_ID;
+ return;
+ }
+ physical_ffa_id = res.arg2 & 0xFFFF;
+}
+
+#endif
+
+ffa_vm_id_t get_ffa_id(void)
+{
+ return physical_ffa_id;
+}
+
/* Performs arch specific boot time initialisation. */
void arch_one_time_init(void)
{
@@ -53,9 +78,79 @@ void arch_one_time_init(void)
}
#else
el3_psci_version = PSCI_VERSION_1_1;
+
+ set_ffa_id();
#endif
}
+/**
+ * Register secondary physical core entry points to the SPMD.
+ */
+void arch_psci_secondary_core_init(const struct boot_params *params)
+{
+#if SECURE_WORLD == 1
+ struct ffa_value res;
+
+ for (uint32_t count = 0; count < params->cpu_count; count++) {
+ uint32_t id = params->cpu_ids[count];
+ struct cpu *cpu = cpu_find(id);
+ const ffa_vm_id_t ffa_id = get_ffa_id();
+
+ res = smc_ffa_call((struct ffa_value){
+ .func = FFA_MSG_SEND_DIRECT_REQ_32,
+ .arg1 = (ffa_id << 16) | SPMD_ID,
+ .arg3 = SPMD_DIRECT_MSG_SET_ENTRY_POINT,
+ .arg4 = params->cpu_ids[count],
+ .arg5 = (uintreg_t)&cpu_entry,
+ .arg6 = (uintreg_t)cpu});
+
+ if (res.func != FFA_SUCCESS_32) {
+ dlog_warning(
+ "%s Failed to initialize secondary core ID: "
+ "%u\n",
+ __func__, id);
+ }
+
+ dlog_verbose("SPMD EP register returned %#x\n", res.func);
+ }
+#endif
+}
+
+/**
+ * Convert a PSCI CPU / affinity ID for a secondary VM to the corresponding vCPU
+ * index.
+ */
+ffa_vcpu_index_t vcpu_id_to_index(cpu_id_t vcpu_id)
+{
+ /* For now we use indices as IDs for the purposes of PSCI. */
+ return vcpu_id;
+}
+
+#if SECURE_WORLD == 1
+/**
+ * Use vcpu_on only as a way to initialize entry point without
+ * an intent to power up vcpu.
+ */
+static uintreg_t ffa_register_entrypoint(cpu_id_t id, struct vm *vm,
+ uintreg_t entrypoint, uintreg_t param)
+{
+ ffa_vcpu_index_t target_vcpu_index = vcpu_id_to_index(id);
+
+ if (target_vcpu_index >= vm->vcpu_count) {
+ return PSCI_ERROR_INVALID_PARAMETERS;
+ }
+
+ struct vcpu *target_vcpu = vm_get_vcpu(vm, target_vcpu_index);
+ struct vcpu_locked locked_target_vcpu = vcpu_lock(target_vcpu);
+
+ vcpu_on(locked_target_vcpu, ipa_init(entrypoint), param);
+
+ vcpu_unlock(&locked_target_vcpu);
+
+ return PSCI_RETURN_SUCCESS;
+}
+#endif
+
/**
* Handles PSCI requests received via HVC or SMC instructions from the primary
* VM.
@@ -180,7 +275,8 @@ bool psci_primary_vm_handler(struct vcpu *vcpu, uint32_t func, uintreg_t arg0,
panic("CPU off failed");
break;
- case PSCI_CPU_ON:
+ case PSCI_CPU_ON: {
+#if SECURE_WORLD == 0
c = cpu_find(arg0);
if (!c) {
*ret = PSCI_ERROR_INVALID_PARAMETERS;
@@ -208,7 +304,12 @@ bool psci_primary_vm_handler(struct vcpu *vcpu, uint32_t func, uintreg_t arg0,
if (*ret != PSCI_RETURN_SUCCESS) {
cpu_off(c);
}
+#else
+ *ret = ffa_register_entrypoint((cpu_id_t)arg0, vcpu->vm, arg1,
+ arg2);
+#endif
break;
+ }
case PSCI_MIGRATE:
case PSCI_MIGRATE_INFO_TYPE:
@@ -234,16 +335,6 @@ bool psci_primary_vm_handler(struct vcpu *vcpu, uint32_t func, uintreg_t arg0,
return true;
}
-/**
- * Convert a PSCI CPU / affinity ID for a secondary VM to the corresponding vCPU
- * index.
- */
-ffa_vcpu_index_t vcpu_id_to_index(cpu_id_t vcpu_id)
-{
- /* For now we use indices as IDs for the purposes of PSCI. */
- return vcpu_id;
-}
-
/**
* Handles PSCI requests received via HVC or SMC instructions from a secondary
* VM.
@@ -337,22 +428,23 @@ bool psci_secondary_vm_handler(struct vcpu *vcpu, uint32_t func, uintreg_t arg0,
case PSCI_CPU_ON: {
/* Parameter names as per PSCI specification. */
cpu_id_t target_cpu = arg0;
- ipaddr_t entry_point_address = ipa_init(arg1);
uint64_t context_id = arg2;
- ffa_vcpu_index_t target_vcpu_index =
- vcpu_id_to_index(target_cpu);
struct vm *vm = vcpu->vm;
- struct vcpu *target_vcpu;
+#if SECURE_WORLD == 1
+ *ret = ffa_register_entrypoint((cpu_id_t)target_cpu, vm, arg1,
+ context_id);
+#else
+ ffa_vcpu_index_t target_vcpu_index =
+ vcpu_id_to_index(target_cpu);
if (target_vcpu_index >= vm->vcpu_count) {
*ret = PSCI_ERROR_INVALID_PARAMETERS;
break;
}
+ struct vcpu *target_vcpu = vm_get_vcpu(vm, target_vcpu_index);
- target_vcpu = vm_get_vcpu(vm, target_vcpu_index);
-
- if (vcpu_secondary_reset_and_start(
- target_vcpu, entry_point_address, context_id)) {
+ if (vcpu_secondary_reset_and_start(target_vcpu, ipa_init(arg1),
+ context_id)) {
/*
* Tell the scheduler that it can start running the new
* vCPU now.
@@ -362,6 +454,7 @@ bool psci_secondary_vm_handler(struct vcpu *vcpu, uint32_t func, uintreg_t arg0,
} else {
*ret = PSCI_ERROR_ALREADY_ON;
}
+#endif
break;
}
diff --git a/src/arch/aarch64/inc/hf/arch/spmd_helpers.h b/src/arch/aarch64/inc/hf/arch/spmd_helpers.h
new file mode 100644
index 0000000..6e11c36
--- /dev/null
+++ b/src/arch/aarch64/inc/hf/arch/spmd_helpers.h
@@ -0,0 +1,15 @@
+/*
+ * 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.
+ */
+
+#define SPMD_ID 0xFFFF
+#define SPMD_DIRECT_MSG_SET_ENTRY_POINT 1
+
+/**
+ * Get SPMC ID stored in the manifest.
+ */
+ffa_vm_id_t get_ffa_id(void);
diff --git a/src/cpu.c b/src/cpu.c
index 0a3fc6f..42a17fa 100644
--- a/src/cpu.c
+++ b/src/cpu.c
@@ -138,6 +138,8 @@ bool cpu_on(struct cpu *c, ipaddr_t entry, uintreg_t arg)
c->is_on = true;
sl_unlock(&c->lock);
+#if SECURE_WORLD == 0
+
if (!prev) {
struct vm *vm = vm_find(HF_PRIMARY_VM_ID);
struct vcpu *vcpu = vm_get_vcpu(vm, cpu_index(c));
@@ -148,6 +150,11 @@ bool cpu_on(struct cpu *c, ipaddr_t entry, uintreg_t arg)
vcpu_unlock(&vcpu_locked);
}
+#else
+ (void)entry;
+ (void)arg;
+#endif
+
return prev;
}
diff --git a/src/init.c b/src/init.c
index a5b48ab..0121213 100644
--- a/src/init.c
+++ b/src/init.c
@@ -146,6 +146,8 @@ void one_time_init(void)
cpu_module_init(params.cpu_ids, params.cpu_count);
+ arch_psci_secondary_core_init(&params);
+
/* Load all VMs. */
update.reserved_ranges_count = 0;
if (!load_vms(mm_stage1_locked, &manifest, &cpio, &params, &update,
--
2.26.2
@@ -0,0 +1,65 @@
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
From 8422e2a5d6b2094f9f451a2d818a593cba29af84 Mon Sep 17 00:00:00 2001
From: Max Shvetsov <maksims.svecovs@arm.com>
Date: Thu, 27 Aug 2020 12:39:50 +0100
Subject: [PATCH 2/4] FF-A: Cold boot and wake up from suspend.
WIP: Currently there is zero entry-point passed with no arguments, This
will be reworked once a proper way to pass this information will be
defined.
Change-Id: Ic6050af16d4081ca31729744995fbb999b170e11
Signed-off-by: Max Shvetsov <maksims.svecovs@arm.com>
---
src/main.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/src/main.c b/src/main.c
index 5f30aac..7b7264f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -7,6 +7,7 @@
*/
#include "hf/cpu.h"
+#include "hf/dlog.h"
#include "hf/vm.h"
/**
@@ -16,9 +17,31 @@
struct vcpu *cpu_main(struct cpu *c)
{
struct vcpu *vcpu;
+
#if SECURE_WORLD == 1
struct vm *first_boot = vm_get_first_boot();
+ if (c->is_on == false) {
+ /*
+ * This is the PSCI warm reset path (svc_cpu_on_finish
+ * handler relayed by SPMD). Notice currenty the "first_boot"
+ * VM is resumed on any CPU on event.
+ */
+ (void)cpu_on(c, ipa_init(0UL), 0UL);
+ dlog_verbose("%s: cpu mpidr 0x%x on\n", __func__, c->id);
+ }
+
+ /*
+ * If `vm_get_first_boot` returns a valid vm, the first partition to
+ * execute is in accordance to the boot-order field of the partition's
+ * manifest.
+ * Else, no partition has been configured with the "boot-order" field
+ * in its manifest, and primary vm should be booted.
+ */
+ if (!first_boot) {
+ first_boot = vm_find(HF_PRIMARY_VM_ID);
+ }
+
vcpu = vm_get_vcpu(first_boot, cpu_index(c));
#else
vcpu = vm_get_vcpu(vm_find(HF_PRIMARY_VM_ID), cpu_index(c));
--
2.26.2
@@ -0,0 +1,87 @@
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
From 66d7628fea54dd7a25d25a13eb4f732c0a3428d0 Mon Sep 17 00:00:00 2001
From: Max Shvetsov <maksims.svecovs@arm.com>
Date: Fri, 18 Sep 2020 13:52:20 +0100
Subject: [PATCH 3/4] FF-A: Respond to PSCI_CPU_OFF from SPMD.
At run-time when a PSCI call is made from NWd, the corresponding SPMD PM
hooks gets called and is eventually routed to the SPMC. This change
implements a generic "SPMD handler" processing PM events that may be
conveyed from SPMD to SPMC such as core suspend, core off.
Change-Id: Id288e26d9fbb8328acc71f5cf68c39e095a0e3da
Signed-off-by: Max Shvetsov <maksims.svecovs@arm.com>
---
src/arch/aarch64/hypervisor/handler.c | 40 ++++++++++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index c10f77e..95d6a18 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -13,6 +13,7 @@
#include "hf/arch/mmu.h"
#include "hf/arch/other_world.h"
#include "hf/arch/plat/smc.h"
+#include "hf/arch/spmd_helpers.h"
#include "hf/api.h"
#include "hf/check.h"
@@ -478,6 +479,41 @@ static bool ffa_handler(struct ffa_value *args, struct vcpu *current,
#if SECURE_WORLD == 1
+/**
+ * Returns true if the message is sent directly from SPMD to SPMC.
+ */
+static bool is_spmd_message(const uint64_t arg)
+{
+ return (((arg & 0xFFFF) == get_ffa_id()) &&
+ (((arg >> 16) & 0xFFFF) == SPMD_ID));
+}
+
+/**
+ * Handle special direct messages from SPMD to SPMC. For now related to power
+ * management only.
+ */
+static bool spmd_handler(struct ffa_value *ret)
+{
+ if (!is_spmd_message(ret->arg1)) {
+ return false;
+ }
+
+ dlog_verbose("%s Handling direct PSCI calls from SPMD\n", __func__);
+
+ switch (ret->arg3) {
+ case PSCI_CPU_OFF:
+ ret->func = FFA_MSG_SEND_DIRECT_RESP_32;
+ ret->arg1 = (get_ffa_id() << 16) | SPMD_ID;
+ ret->arg2 = 0U;
+ break;
+ default:
+ dlog_verbose("Following message not handled %#x\n", ret->arg3);
+ return false;
+ }
+
+ return true;
+}
+
/**
* Called to switch to the other world and handle FF-A calls from it. Returns
* when it is ready to run a secure partition again.
@@ -510,7 +546,9 @@ static void other_world_switch_loop(struct vcpu *other_world_vcpu,
* the result of the call back to EL3 unless the API handler
* sets *next to something different.
*/
- if (!ffa_handler(&other_world_args, other_world_vcpu, next)) {
+
+ if (!spmd_handler(&other_world_args) &&
+ !ffa_handler(&other_world_args, other_world_vcpu, next)) {
other_world_args.func = SMCCC_ERROR_UNKNOWN;
}
}
--
2.26.2
@@ -0,0 +1,19 @@
# TC0 specific configuration
# Intermediate SHA with 2.4 baseline version
SRCREV = "ee68c5494dea5c5a59aa02af46b35ab3d949672e"
PV = "2.4+git${SRCPV}"
FILESEXTRAPATHS_prepend_tc0 := "${THISDIR}/files/tc0:"
SRC_URI_append = " \
file://0001-FF-A-Register-secondary-core-entry-point-at-SPMC-ini.patch \
file://0002-FF-A-Cold-boot-and-wake-up-from-suspend.patch \
file://0003-FF-A-Respond-to-PSCI_CPU_OFF-from-SPMD.patch \
"
COMPATIBLE_MACHINE = "tc0"
HAFNIUM_PROJECT = "reference"
HAFNIUM_PLATFORM = "secure_tc0"
HAFNIUM_INSTALL_TARGET = "hafnium"
@@ -0,0 +1,6 @@
# Machine specific configurations
MACHINE_HAFNIUM_REQUIRE ?= ""
MACHINE_HAFNIUM_REQUIRE_tc0 = "hafnium-tc0.inc"
require ${MACHINE_HAFNIUM_REQUIRE}