Merge changes from topic "ja/spm_rme" into integration
* changes:
docs: change FVP argument in RME configuration
feat(fvp): added calls to unprotect/protect memory
diff --git a/docs/components/realm-management-extension.rst b/docs/components/realm-management-extension.rst
index f228e6b..39186b4 100644
--- a/docs/components/realm-management-extension.rst
+++ b/docs/components/realm-management-extension.rst
@@ -237,7 +237,7 @@
-C bp.ve_sysregs.exit_on_shutdown=1 \
-C cache_state_modelled=1 \
-C bp.dram_size=4 \
- -C bp.secure_memory=1 \
+ -C bp.secure_memory=0 \
-C pci.pci_smmuv3.mmu.SMMU_ROOT_IDR0=3 \
-C pci.pci_smmuv3.mmu.SMMU_ROOT_IIDR=0x43B \
-C pci.pci_smmuv3.mmu.root_register_page_offset=0x20000 \
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 */