feat(spm): update MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 interface
Update MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 interface
correspondant to FF-A v1.3 memory management protocol's
FFA_MEM_PERM_GET interface [0].
This adds one input/output parameter with page_count
to set search range and get the range having same permssion from
base_va.
This change is backward compatible.
Links: https://developer.arm.com/documentation/den0140/latest/
Change-Id: Ib1b19dd433ad018f0c39af3a9ac8dda41358fb02
Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
diff --git a/docs/components/secure-partition-manager-mm.rst b/docs/components/secure-partition-manager-mm.rst
index d9b2b1b..589a362 100644
--- a/docs/components/secure-partition-manager-mm.rst
+++ b/docs/components/secure-partition-manager-mm.rst
@@ -652,6 +652,13 @@
There are no alignment restrictions on the Base Address. The permission
attributes of the translation granule it lies in are returned.
+ - **uint32** Input Page Count
+
+ This parameter is the number of translation granule size pages from
+ *Base Address* whose permission should be returned.
+ This is calculated as *Input Page count + 1*.
+ (i.e. If Input Page Count is 0, then it is calculated as 1).
+
- Return parameters
- **int32** - Memory Attributes/Return Code
@@ -687,6 +694,16 @@
See `Error Codes`_ for integer values that are associated with each return
code.
+ - **uint32** - Output Page Count
+
+ On success, the number of translation granule size pages from
+ the *Base address* whose permissions match those returned in the
+ *Memory Attributes* output parameter.
+ This is calculated as *Output Page count + 1*.
+ (i.e. If Output Page Count is 0, It is calculated as 1).
+
+ On failure, It must be zero:
+
- Usage
This function is used to request the permission attributes for S-EL0 on a
diff --git a/services/std_svc/spm/spm_mm/spm_mm_main.c b/services/std_svc/spm/spm_mm/spm_mm_main.c
index 60b34d2..c204987 100644
--- a/services/std_svc/spm/spm_mm/spm_mm_main.c
+++ b/services/std_svc/spm/spm_mm/spm_mm_main.c
@@ -312,6 +312,9 @@
uint64_t flags)
{
unsigned int ns;
+ int32_t ret;
+ uint32_t attr;
+ uint32_t page_count;
/* Determine which security state this SMC originated from */
ns = is_caller_non_secure(flags);
@@ -340,9 +343,17 @@
WARN("MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n");
SMC_RET1(handle, SPM_MM_NOT_SUPPORTED);
}
- SMC_RET1(handle,
- spm_memory_attributes_get_smc_handler(
- &sp_ctx, x1));
+
+ /* x2 = page_count - 1 */
+ page_count = x2 + 1;
+
+ ret = spm_memory_attributes_get_smc_handler(
+ &sp_ctx, x1, &page_count, &attr);
+ if (ret != SPM_MM_SUCCESS) {
+ SMC_RET1(handle, ret);
+ } else {
+ SMC_RET2(handle, attr, --page_count);
+ }
case MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64:
INFO("Received MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n");
diff --git a/services/std_svc/spm/spm_mm/spm_mm_private.h b/services/std_svc/spm/spm_mm/spm_mm_private.h
index 3a52a3e..473d84d 100644
--- a/services/std_svc/spm/spm_mm/spm_mm_private.h
+++ b/services/std_svc/spm/spm_mm/spm_mm_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -56,7 +56,9 @@
void spm_sp_setup(sp_context_t *sp_ctx);
int32_t spm_memory_attributes_get_smc_handler(sp_context_t *sp_ctx,
- uintptr_t base_va);
+ uintptr_t base_va,
+ uint32_t *page_count,
+ uint32_t *attr);
int spm_memory_attributes_set_smc_handler(sp_context_t *sp_ctx,
u_register_t page_address,
u_register_t pages_count,
diff --git a/services/std_svc/spm/spm_mm/spm_mm_xlat.c b/services/std_svc/spm/spm_mm/spm_mm_xlat.c
index 3e13e90..32eda3a 100644
--- a/services/std_svc/spm/spm_mm/spm_mm_xlat.c
+++ b/services/std_svc/spm/spm_mm/spm_mm_xlat.c
@@ -88,22 +88,61 @@
}
int32_t spm_memory_attributes_get_smc_handler(sp_context_t *sp_ctx,
- uintptr_t base_va)
+ uintptr_t base_va,
+ uint32_t *page_count,
+ uint32_t *attr)
{
- uint32_t attributes;
+ uint32_t cur_attr;
+ uint32_t table_level;
+ uint32_t count;
+ int rc;
+
+ assert((page_count != NULL) && (*page_count > 0));
+ assert(attr != NULL);
+
+ base_va &= ~(PAGE_SIZE_MASK);
spin_lock(&mem_attr_smc_lock);
- int rc = xlat_get_mem_attributes_ctx(sp_ctx->xlat_ctx_handle,
- base_va, &attributes, NULL);
+ rc = xlat_get_mem_attributes_ctx(sp_ctx->xlat_ctx_handle,
+ base_va, attr, &table_level);
+ if (rc != 0) {
+ goto err_out;
+ }
+ /*
+ * Caculate how many pages in this block entry from base_va including
+ * its page.
+ */
+ count = ((XLAT_BLOCK_SIZE(table_level) -
+ (base_va & XLAT_BLOCK_MASK(table_level))) >> PAGE_SIZE_SHIFT);
+ base_va += XLAT_BLOCK_SIZE(table_level);
+
+ while ((count < *page_count) && (base_va != 0x00)) {
+ rc = xlat_get_mem_attributes_ctx(sp_ctx->xlat_ctx_handle,
+ base_va, &cur_attr, &table_level);
+ if (rc != 0) {
+ goto err_out;
+ }
+
+ if (*attr != cur_attr) {
+ *page_count = count;
+ break;
+ }
+
+ base_va += XLAT_BLOCK_SIZE(table_level);
+ count += (XLAT_BLOCK_SIZE(table_level) >> PAGE_SIZE_SHIFT);
+ }
+
+ *attr = smc_mmap_to_smc_attr(*attr);
+
+err_out:
spin_unlock(&mem_attr_smc_lock);
-
/* Convert error codes of xlat_get_mem_attributes_ctx() into SPM. */
assert((rc == 0) || (rc == -EINVAL));
if (rc == 0) {
- return (int32_t) smc_mmap_to_smc_attr(attributes);
+ return SPM_MM_SUCCESS;
} else {
return SPM_MM_INVALID_PARAMETER;
}