1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2015-2023, Linaro Limited 4 * Copyright (c) 2023, Arm Limited 5 */ 6 7 #include <kernel/boot.h> 8 #include <kernel/dt.h> 9 #include <libfdt.h> 10 #include <mm/core_memprot.h> 11 12 #ifdef CFG_CORE_DYN_SHM 13 static uint64_t get_dt_val_and_advance(const void *data, size_t *offs, 14 uint32_t cell_size) 15 { 16 uint64_t rv = 0; 17 18 if (cell_size == 1) { 19 uint32_t v; 20 21 memcpy(&v, (const uint8_t *)data + *offs, sizeof(v)); 22 *offs += sizeof(v); 23 rv = fdt32_to_cpu(v); 24 } else { 25 uint64_t v; 26 27 memcpy(&v, (const uint8_t *)data + *offs, sizeof(v)); 28 *offs += sizeof(v); 29 rv = fdt64_to_cpu(v); 30 } 31 32 return rv; 33 } 34 35 /* 36 * Find all non-secure memory from DT. Memory marked inaccessible by Secure 37 * World is ignored since it could not be mapped to be used as dynamic shared 38 * memory. 39 */ 40 static int __maybe_unused get_nsec_memory_helper(void *fdt, struct core_mmu_phys_mem *mem) 41 { 42 const uint8_t *prop = NULL; 43 uint64_t a = 0; 44 uint64_t l = 0; 45 size_t prop_offs = 0; 46 size_t prop_len = 0; 47 int elems_total = 0; 48 int addr_size = 0; 49 int len_size = 0; 50 int offs = 0; 51 size_t n = 0; 52 int len = 0; 53 54 addr_size = fdt_address_cells(fdt, 0); 55 if (addr_size < 0) 56 return 0; 57 58 len_size = fdt_size_cells(fdt, 0); 59 if (len_size < 0) 60 return 0; 61 62 while (true) { 63 offs = fdt_node_offset_by_prop_value(fdt, offs, "device_type", 64 "memory", 65 sizeof("memory")); 66 if (offs < 0) 67 break; 68 69 if (fdt_get_status(fdt, offs) != (DT_STATUS_OK_NSEC | 70 DT_STATUS_OK_SEC)) 71 continue; 72 73 prop = fdt_getprop(fdt, offs, "reg", &len); 74 if (!prop) 75 continue; 76 77 prop_len = len; 78 for (n = 0, prop_offs = 0; prop_offs < prop_len; n++) { 79 a = get_dt_val_and_advance(prop, &prop_offs, addr_size); 80 if (prop_offs >= prop_len) { 81 n--; 82 break; 83 } 84 85 l = get_dt_val_and_advance(prop, &prop_offs, len_size); 86 if (mem) { 87 mem->type = MEM_AREA_DDR_OVERALL; 88 mem->addr = a; 89 mem->size = l; 90 mem++; 91 } 92 } 93 94 elems_total += n; 95 } 96 97 return elems_total; 98 } 99 100 #ifdef CFG_DT 101 static struct core_mmu_phys_mem *get_nsec_memory(void *fdt, size_t *nelems) 102 { 103 struct core_mmu_phys_mem *mem = NULL; 104 int elems_total = 0; 105 106 elems_total = get_nsec_memory_helper(fdt, NULL); 107 if (elems_total <= 0) 108 return NULL; 109 110 mem = nex_calloc(elems_total, sizeof(*mem)); 111 if (!mem) 112 panic(); 113 114 elems_total = get_nsec_memory_helper(fdt, mem); 115 assert(elems_total > 0); 116 117 *nelems = elems_total; 118 119 return mem; 120 } 121 #else /*CFG_DT*/ 122 static struct core_mmu_phys_mem *get_nsec_memory(void *fdt __unused, 123 size_t *nelems __unused) 124 { 125 return NULL; 126 } 127 #endif /*!CFG_DT*/ 128 129 void discover_nsec_memory(void) 130 { 131 struct core_mmu_phys_mem *mem; 132 const struct core_mmu_phys_mem *mem_begin = NULL; 133 const struct core_mmu_phys_mem *mem_end = NULL; 134 size_t nelems; 135 void *fdt = get_external_dt(); 136 137 if (fdt) { 138 mem = get_nsec_memory(fdt, &nelems); 139 if (mem) { 140 core_mmu_set_discovered_nsec_ddr(mem, nelems); 141 return; 142 } 143 144 DMSG("No non-secure memory found in FDT"); 145 } 146 147 mem_begin = phys_ddr_overall_begin; 148 mem_end = phys_ddr_overall_end; 149 nelems = mem_end - mem_begin; 150 if (nelems) { 151 /* 152 * Platform cannot use both register_ddr() and the now 153 * deprecated register_dynamic_shm(). 154 */ 155 assert(phys_ddr_overall_compat_begin == 156 phys_ddr_overall_compat_end); 157 } else { 158 mem_begin = phys_ddr_overall_compat_begin; 159 mem_end = phys_ddr_overall_compat_end; 160 nelems = mem_end - mem_begin; 161 if (!nelems) 162 return; 163 DMSG("Warning register_dynamic_shm() is deprecated, " 164 "please use register_ddr() instead"); 165 } 166 167 mem = nex_calloc(nelems, sizeof(*mem)); 168 if (!mem) 169 panic(); 170 171 memcpy(mem, phys_ddr_overall_begin, sizeof(*mem) * nelems); 172 core_mmu_set_discovered_nsec_ddr(mem, nelems); 173 } 174 #else /*CFG_CORE_DYN_SHM*/ 175 void discover_nsec_memory(void) 176 { 177 } 178 #endif /*!CFG_CORE_DYN_SHM*/ 179 180 #ifdef CFG_CORE_RESERVED_SHM 181 int mark_static_shm_as_reserved(struct dt_descriptor *dt) 182 { 183 vaddr_t shm_start; 184 vaddr_t shm_end; 185 186 core_mmu_get_mem_by_type(MEM_AREA_NSEC_SHM, &shm_start, &shm_end); 187 if (shm_start != shm_end) 188 return add_res_mem_dt_node(dt, "optee_shm", 189 virt_to_phys((void *)shm_start), 190 shm_end - shm_start); 191 192 DMSG("No SHM configured"); 193 return -1; 194 } 195 #endif /*CFG_CORE_RESERVED_SHM*/ 196