arm-trusted-firmware/plat/arm/common/plat_arm_sip_svc.c
J-Alves 6873088c2c 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
2024-02-06 10:56:26 +00:00

131 lines
3.1 KiB
C

/*
* 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>
#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,
u_register_t x3,
u_register_t x4,
void *cookie,
void *handle,
u_register_t flags)
{
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);
}
VERBOSE("SiP Call- Set interrupt pending %d\n", (uint32_t)x1);
plat_ic_set_interrupt_pending(x1);
SMC_RET1(handle, SMC_OK);
break; /* Not reached */
#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);
#else
WARN("Unimplemented ARM SiP Service Call: 0x%x\n", smc_fid);
SMC_RET1(handle, SMC_UNK);
#endif
}