1 /* 2 * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <arch.h> 8 #include <arch_helpers.h> 9 #include <assert.h> 10 #include <errno.h> 11 #include <lib/xlat_tables/xlat_tables_v2.h> 12 #include <platform_def.h> 13 #include <plat/common/platform.h> 14 #include <services/spm_mm_partition.h> 15 #include <services/spm_mm_svc.h> 16 17 #include "spm_mm_private.h" 18 #include "spm_mm_shim_private.h" 19 20 /* Place translation tables by default along with the ones used by BL31. */ 21 #ifndef PLAT_SP_IMAGE_XLAT_SECTION_NAME 22 #define PLAT_SP_IMAGE_XLAT_SECTION_NAME ".xlat_table" 23 #endif 24 #ifndef PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME 25 #define PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME ".bss" 26 #endif 27 28 /* Allocate and initialise the translation context for the secure partitions. */ 29 REGISTER_XLAT_CONTEXT2(sp, 30 PLAT_SP_IMAGE_MMAP_REGIONS, 31 PLAT_SP_IMAGE_MAX_XLAT_TABLES, 32 PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE, 33 EL1_EL0_REGIME, PLAT_SP_IMAGE_XLAT_SECTION_NAME, 34 PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME); 35 36 /* Lock used for SP_MEMORY_ATTRIBUTES_GET and SP_MEMORY_ATTRIBUTES_SET */ 37 static spinlock_t mem_attr_smc_lock; 38 39 /* Get handle of Secure Partition translation context */ 40 xlat_ctx_t *spm_get_sp_xlat_context(void) 41 { 42 return &sp_xlat_ctx; 43 }; 44 45 /* 46 * Attributes are encoded using a different format in the SMC interface than in 47 * the Trusted Firmware, where the mmap_attr_t enum type is used. This function 48 * converts an attributes value from the SMC format to the mmap_attr_t format by 49 * setting MT_RW/MT_RO, MT_USER/MT_PRIVILEGED and MT_EXECUTE/MT_EXECUTE_NEVER. 50 * The other fields are left as 0 because they are ignored by the function 51 * xlat_change_mem_attributes_ctx(). 52 */ 53 static unsigned int smc_attr_to_mmap_attr(unsigned int attributes) 54 { 55 unsigned int tf_attr = 0U; 56 57 unsigned int access = (attributes & MM_SP_MEMORY_ATTRIBUTES_ACCESS_MASK) 58 >> MM_SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT; 59 60 if (access == MM_SP_MEMORY_ATTRIBUTES_ACCESS_RW) { 61 tf_attr |= MT_RW | MT_USER; 62 } else if (access == MM_SP_MEMORY_ATTRIBUTES_ACCESS_RO) { 63 tf_attr |= MT_RO | MT_USER; 64 } else { 65 /* Other values are reserved. */ 66 assert(access == MM_SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS); 67 /* The only requirement is that there's no access from EL0 */ 68 tf_attr |= MT_RO | MT_PRIVILEGED; 69 } 70 71 if ((attributes & MM_SP_MEMORY_ATTRIBUTES_NON_EXEC) == 0) { 72 tf_attr |= MT_EXECUTE; 73 } else { 74 tf_attr |= MT_EXECUTE_NEVER; 75 } 76 77 return tf_attr; 78 } 79 80 /* 81 * This function converts attributes from the Trusted Firmware format into the 82 * SMC interface format. 83 */ 84 static unsigned int smc_mmap_to_smc_attr(unsigned int attr) 85 { 86 unsigned int smc_attr = 0U; 87 88 unsigned int data_access; 89 90 if ((attr & MT_USER) == 0) { 91 /* No access from EL0. */ 92 data_access = MM_SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS; 93 } else { 94 if ((attr & MT_RW) != 0) { 95 assert(MT_TYPE(attr) != MT_DEVICE); 96 data_access = MM_SP_MEMORY_ATTRIBUTES_ACCESS_RW; 97 } else { 98 data_access = MM_SP_MEMORY_ATTRIBUTES_ACCESS_RO; 99 } 100 } 101 102 smc_attr |= (data_access & MM_SP_MEMORY_ATTRIBUTES_ACCESS_MASK) 103 << MM_SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT; 104 105 if ((attr & MT_EXECUTE_NEVER) != 0U) { 106 smc_attr |= MM_SP_MEMORY_ATTRIBUTES_NON_EXEC; 107 } 108 109 return smc_attr; 110 } 111 112 int32_t spm_memory_attributes_get_smc_handler(sp_context_t *sp_ctx, 113 uintptr_t base_va) 114 { 115 uint32_t attributes; 116 117 spin_lock(&mem_attr_smc_lock); 118 119 int rc = xlat_get_mem_attributes_ctx(sp_ctx->xlat_ctx_handle, 120 base_va, &attributes); 121 122 spin_unlock(&mem_attr_smc_lock); 123 124 /* Convert error codes of xlat_get_mem_attributes_ctx() into SPM. */ 125 assert((rc == 0) || (rc == -EINVAL)); 126 127 if (rc == 0) { 128 return (int32_t) smc_mmap_to_smc_attr(attributes); 129 } else { 130 return SPM_MM_INVALID_PARAMETER; 131 } 132 } 133 134 int spm_memory_attributes_set_smc_handler(sp_context_t *sp_ctx, 135 u_register_t page_address, 136 u_register_t pages_count, 137 u_register_t smc_attributes) 138 { 139 uintptr_t base_va = (uintptr_t) page_address; 140 size_t size = (size_t) (pages_count * PAGE_SIZE); 141 uint32_t attributes = (uint32_t) smc_attributes; 142 143 INFO(" Start address : 0x%lx\n", base_va); 144 INFO(" Number of pages: %i (%zi bytes)\n", (int) pages_count, size); 145 INFO(" Attributes : 0x%x\n", attributes); 146 147 spin_lock(&mem_attr_smc_lock); 148 149 int ret = xlat_change_mem_attributes_ctx(sp_ctx->xlat_ctx_handle, 150 base_va, size, 151 smc_attr_to_mmap_attr(attributes)); 152 153 spin_unlock(&mem_attr_smc_lock); 154 155 /* Convert error codes of xlat_change_mem_attributes_ctx() into SPM. */ 156 assert((ret == 0) || (ret == -EINVAL)); 157 158 return (ret == 0) ? SPM_MM_SUCCESS : SPM_MM_INVALID_PARAMETER; 159 } 160