feat(fvp): added calls to unprotect/protect memory
Added SiP calls to FVP platform to protect/unprotect a
memory range.
These leverage rme features to change the PAS of a given
memory range from non-secure to secure.
The mentioned call is leveraged by the SPMC in the memory
sharing flow, when memory is shared from the normal world
onto the secure world.
More details in the SPM related patches.
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
Signed-off-by: J-Alves <joao.alves@arm.com>
Change-Id: Iaf15d8603a549d247ffb1fc14c16bfb94d0e178a
diff --git a/include/lib/smccc.h b/include/lib/smccc.h
index 8fd6093..c493105 100644
--- a/include/lib/smccc.h
+++ b/include/lib/smccc.h
@@ -111,6 +111,8 @@
#define SMC_OK ULL(0)
#define SMC_UNK -1
#define SMC_PREEMPTED -2 /* Not defined by the SMCCC */
+#define SMC_DENIED -3 /* Not defined by the SMCCC */
+#define SMC_INVALID_PARAM -4 /* Not defined by the SMCCC */
/* Return codes for Arm Architecture Service SMC calls */
#define SMC_ARCH_CALL_SUCCESS 0
diff --git a/include/plat/arm/common/arm_sip_svc.h b/include/plat/arm/common/arm_sip_svc.h
index 266092e..a6fd42b 100644
--- a/include/plat/arm/common/arm_sip_svc.h
+++ b/include/plat/arm/common/arm_sip_svc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2019,2021-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2019,2021-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -42,6 +42,16 @@
#define ARM_SIP_SET_INTERRUPT_PENDING U(0x82000100)
#endif
+/**
+ * Arm SiP Service Call for the SPM to leverage RME to protect a give memory range.
+ * Protected memory range is one whose PAS was made secure.
+ * Unprotect relates to reverting a protect operation.
+ */
+#if SPMD_SPM_AT_SEL2 && ENABLE_RME
+#define PLAT_PROTECT_MEM_SMC64 0xC2000101
+#define PLAT_UNPROTECT_MEM_SMC64 0xC2000102
+#endif
+
/* SiP handler specific to each Arm platform. */
uintptr_t plat_arm_sip_handler(uint32_t smc_fid,
u_register_t x1,
diff --git a/plat/arm/common/plat_arm_sip_svc.c b/plat/arm/common/plat_arm_sip_svc.c
index b1dab16..d496d2e 100644
--- a/plat/arm/common/plat_arm_sip_svc.c
+++ b/plat/arm/common/plat_arm_sip_svc.c
@@ -1,10 +1,11 @@
/*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
+#include <errno.h>
#include <common/debug.h>
#include <common/runtime_svc.h>
@@ -12,10 +13,73 @@
#include <plat/arm/common/arm_sip_svc.h>
#include <plat/common/platform.h>
+#if ENABLE_RME && SPMD_SPM_AT_SEL2
+#include <lib/gpt_rme/gpt_rme.h>
+#endif
+
#if ENABLE_SPMD_LP
#include <services/el3_spmd_logical_sp.h>
#endif
+#if (ENABLE_RME == 1) && (defined(SPD_spmd) && SPMD_SPM_AT_SEL2 == 1)
+static uint64_t plat_protect_memory(bool protect,
+ bool secure_origin,
+ const uint64_t base,
+ const size_t size,
+ void *handle)
+{
+ uint64_t ret = SMC_INVALID_PARAM;
+ uint64_t last_updated = 0;
+
+ if (!secure_origin) {
+ SMC_RET1(handle, SMC_UNK);
+ /* Shall not be reached. */
+ }
+
+ if ((base % PAGE_SIZE_4KB) != 0U &&
+ (size % PAGE_SIZE_4KB) != 0U) {
+ VERBOSE("Base address must be aligned to 4k.\n");
+ SMC_RET1(handle, SMC_INVALID_PARAM);
+ /* Shall not be reached. */
+ }
+
+ if ((ULONG_MAX - base) < size) {
+ VERBOSE("Base + Size results in overflow.\n");
+ SMC_RET1(handle, SMC_INVALID_PARAM);
+ /* Shall not be reached. */
+ }
+
+ for (uint64_t it = base; it < (base + size); it += PAGE_SIZE_4KB) {
+ /*
+ * If protect is true, add memory to secure PAS.
+ * Else unprotect it, making part of non-secure PAS.
+ */
+ ret = protect
+ ? gpt_delegate_pas(it, PAGE_SIZE_4KB,
+ SMC_FROM_SECURE)
+ : gpt_undelegate_pas(it, PAGE_SIZE_4KB,
+ SMC_FROM_SECURE);
+
+ switch (ret) {
+ case 0:
+ last_updated = it;
+ break;
+ case -EINVAL:
+ SMC_RET2(handle, SMC_INVALID_PARAM, last_updated);
+ break; /* Shall not be reached. */
+ case -EPERM:
+ SMC_RET2(handle, SMC_DENIED, last_updated);
+ break; /* Shall not be reached. */
+ default:
+ ERROR("Unexpected return\n");
+ panic();
+ }
+ }
+
+ SMC_RET1(handle, SMC_OK);
+}
+#endif /* ENABLE_RME && SPMD_SPM_AT_SEL2 */
+
uintptr_t plat_arm_sip_handler(uint32_t smc_fid,
u_register_t x1,
u_register_t x2,
@@ -25,13 +89,14 @@
void *handle,
u_register_t flags)
{
-#if PLAT_TEST_SPM
bool secure_origin;
/* Determine which security state this SMC originated from */
secure_origin = is_caller_secure(flags);
+ (void) secure_origin;
switch (smc_fid) {
+#if PLAT_TEST_SPM
case ARM_SIP_SET_INTERRUPT_PENDING:
if (!secure_origin) {
SMC_RET1(handle, SMC_UNK);
@@ -42,10 +107,19 @@
SMC_RET1(handle, SMC_OK);
break; /* Not reached */
- default:
+#endif
+
+#if (ENABLE_RME == 1) && (defined(SPD_spmd) && SPMD_SPM_AT_SEL2 == 1)
+ case PLAT_PROTECT_MEM_SMC64:
+ INFO("Sip Call - Protect memory\n");
+ return plat_protect_memory(true, secure_origin, x1, x2, handle);
break;
- }
+ case PLAT_UNPROTECT_MEM_SMC64:
+ INFO("Sip Call - Unprotect memory\n");
+ return plat_protect_memory(false, secure_origin, x1, x2, handle);
+ break;
#endif
+ }
#if ENABLE_SPMD_LP
return plat_spmd_logical_sp_smc_handler(smc_fid, x1, x2, x3, x4,
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index 5d19868..e200b80 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -844,7 +844,7 @@
unsigned int linear_id = plat_my_core_pos();
spmd_spm_core_context_t *ctx = spmd_get_context();
bool secure_origin;
- int32_t ret;
+ int ret;
uint32_t input_version;
/* Determine which security state this SMC originated from */