diff --git a/include/lib/psci/psci.h b/include/lib/psci/psci.h index 0ed39c9..0b44ab2 100644 --- a/include/lib/psci/psci.h +++ b/include/lib/psci/psci.h @@ -65,6 +65,9 @@ #define PSCI_STAT_RESIDENCY_AARCH64 U(0xc4000010) #define PSCI_STAT_COUNT_AARCH32 U(0x84000011) #define PSCI_STAT_COUNT_AARCH64 U(0xc4000011) +#define PSCI_MEM_PROTECT U(0x84000013) +#define PSCI_MEM_CHK_RANGE_AARCH32 U(0x84000014) +#define PSCI_MEM_CHK_RANGE_AARCH64 U(0xc4000014) /* Macro to help build the psci capabilities bitfield */ #define define_psci_cap(x) (U(1) << (x & U(0x1f))) @@ -288,6 +291,9 @@ unsigned int power_state, psci_power_state_t *output_state); int (*get_node_hw_state)(u_register_t mpidr, unsigned int power_level); + int (*mem_protect_chk)(uintptr_t base, u_register_t length); + int (*read_mem_protect)(int *val); + int (*write_mem_protect)(int val); } plat_psci_ops_t; /******************************************************************************* diff --git a/lib/psci/psci_lib.mk b/lib/psci/psci_lib.mk index 29080db..1d4aac4 100644 --- a/lib/psci/psci_lib.mk +++ b/lib/psci/psci_lib.mk @@ -17,6 +17,7 @@ lib/psci/psci_main.c \ lib/psci/psci_setup.c \ lib/psci/psci_system_off.c \ + lib/psci/psci_mem_protect.c \ lib/psci/${ARCH}/psci_helpers.S ifeq (${ARCH}, aarch64) diff --git a/lib/psci/psci_main.c b/lib/psci/psci_main.c index 257479a..a5d707e 100644 --- a/lib/psci/psci_main.c +++ b/lib/psci/psci_main.c @@ -408,6 +408,11 @@ case PSCI_STAT_COUNT_AARCH32: return psci_stat_count(x1, x2); #endif + case PSCI_MEM_PROTECT: + return psci_mem_protect(x1); + + case PSCI_MEM_CHK_RANGE_AARCH32: + return psci_mem_chk_range(x1, x2); default: break; @@ -445,6 +450,10 @@ return psci_stat_count(x1, x2); #endif + case PSCI_MEM_CHK_RANGE_AARCH64: + return psci_mem_chk_range(x1, x2); + + default: break; } diff --git a/lib/psci/psci_mem_protect.c b/lib/psci/psci_mem_protect.c new file mode 100644 index 0000000..fca84e9 --- /dev/null +++ b/lib/psci/psci_mem_protect.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "psci_private.h" + +int psci_mem_protect(unsigned int enable) +{ + int val; + + assert(psci_plat_pm_ops->read_mem_protect); + assert(psci_plat_pm_ops->write_mem_protect); + + if (psci_plat_pm_ops->read_mem_protect(&val) < 0) + return PSCI_E_NOT_SUPPORTED; + if (psci_plat_pm_ops->write_mem_protect(enable) < 0) + return PSCI_E_NOT_SUPPORTED; + + return val != 0; +} + +int psci_mem_chk_range(uintptr_t base, u_register_t length) +{ + int ret; + + assert(psci_plat_pm_ops->mem_protect_chk); + + if (length == 0 || check_uptr_overflow(base, length-1)) + return PSCI_E_DENIED; + + ret = psci_plat_pm_ops->mem_protect_chk(base, length); + return (ret < 0) ? PSCI_E_DENIED : PSCI_E_SUCCESS; +} diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h index da6a20f..facfacb 100644 --- a/lib/psci/psci_private.h +++ b/lib/psci/psci_private.h @@ -269,4 +269,8 @@ u_register_t psci_stat_count(u_register_t target_cpu, unsigned int power_state); +/* Private exported functions from psci_mem_protect.c */ +int psci_mem_protect(unsigned int enable); +int psci_mem_chk_range(uintptr_t base, u_register_t length); + #endif /* __PSCI_PRIVATE_H__ */ diff --git a/lib/psci/psci_setup.c b/lib/psci/psci_setup.c index f70e34d..5ef49ac 100644 --- a/lib/psci/psci_setup.c +++ b/lib/psci/psci_setup.c @@ -243,6 +243,11 @@ psci_caps |= define_psci_cap(PSCI_SYSTEM_RESET); if (psci_plat_pm_ops->get_node_hw_state) psci_caps |= define_psci_cap(PSCI_NODE_HW_STATE_AARCH64); + if (psci_plat_pm_ops->read_mem_protect && + psci_plat_pm_ops->write_mem_protect) + psci_caps |= define_psci_cap(PSCI_MEM_PROTECT); + if (psci_plat_pm_ops->mem_protect_chk) + psci_caps |= define_psci_cap(PSCI_MEM_CHK_RANGE_AARCH64); #if ENABLE_PSCI_STAT psci_caps |= define_psci_cap(PSCI_STAT_RESIDENCY_AARCH64);