From 6873088c2cd6983025b6777d4c3bde912eade571 Mon Sep 17 00:00:00 2001 From: J-Alves Date: Wed, 4 Oct 2023 17:16:45 +0100 Subject: [PATCH] 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 Signed-off-by: J-Alves Change-Id: Iaf15d8603a549d247ffb1fc14c16bfb94d0e178a --- include/lib/smccc.h | 2 + include/plat/arm/common/arm_sip_svc.h | 12 +++- plat/arm/common/plat_arm_sip_svc.c | 84 +++++++++++++++++++++++++-- services/std_svc/spmd/spmd_main.c | 2 +- 4 files changed, 93 insertions(+), 7 deletions(-) diff --git a/include/lib/smccc.h b/include/lib/smccc.h index 8fd609314..c4931058d 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 266092e30..a6fd42bac 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 b1dab165b..d496d2e11 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 +#include #include #include @@ -12,10 +13,73 @@ #include #include +#if ENABLE_RME && SPMD_SPM_AT_SEL2 +#include +#endif + #if ENABLE_SPMD_LP #include #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 @@ uintptr_t plat_arm_sip_handler(uint32_t smc_fid, 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,11 +107,20 @@ uintptr_t plat_arm_sip_handler(uint32_t smc_fid, SMC_RET1(handle, SMC_OK); break; /* Not reached */ - default: - break; - } #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, cookie, handle, flags); diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c index 5d19868a2..e200b80ef 100644 --- a/services/std_svc/spmd/spmd_main.c +++ b/services/std_svc/spmd/spmd_main.c @@ -844,7 +844,7 @@ uint64_t spmd_smc_handler(uint32_t smc_fid, 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 */