1 /* 2 * Copyright (c) 2023, Linaro Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 9 #include <common/fdt_wrappers.h> 10 #include <common/runtime_svc.h> 11 #include <libfdt.h> 12 #include <smccc_helpers.h> 13 14 #include <sbsa_platform.h> 15 16 /* default platform version is 0.0 */ 17 static int platform_version_major; 18 static int platform_version_minor; 19 20 #define SMC_FASTCALL 0x80000000 21 #define SMC64_FUNCTION (SMC_FASTCALL | 0x40000000) 22 #define SIP_FUNCTION (SMC64_FUNCTION | 0x02000000) 23 #define SIP_FUNCTION_ID(n) (SIP_FUNCTION | (n)) 24 25 /* 26 * We do not use SMCCC_ARCH_SOC_ID here because qemu_sbsa is virtual platform 27 * which uses SoC present in QEMU. And they can change on their own while we 28 * need version of whole 'virtual hardware platform'. 29 */ 30 #define SIP_SVC_VERSION SIP_FUNCTION_ID(1) 31 #define SIP_SVC_GET_GIC SIP_FUNCTION_ID(100) 32 #define SIP_SVC_GET_GIC_ITS SIP_FUNCTION_ID(101) 33 #define SIP_SVC_GET_CPU_COUNT SIP_FUNCTION_ID(200) 34 #define SIP_SVC_GET_CPU_NODE SIP_FUNCTION_ID(201) 35 #define SIP_SVC_GET_CPU_TOPOLOGY SIP_FUNCTION_ID(202) 36 #define SIP_SVC_GET_MEMORY_NODE_COUNT SIP_FUNCTION_ID(300) 37 #define SIP_SVC_GET_MEMORY_NODE SIP_FUNCTION_ID(301) 38 39 static uint64_t gic_its_addr; 40 static struct qemu_platform_info dynamic_platform_info; 41 42 void sbsa_set_gic_bases(const uintptr_t gicd_base, const uintptr_t gicr_base); 43 uintptr_t sbsa_get_gicd(void); 44 uintptr_t sbsa_get_gicr(void); 45 46 /* 47 * QEMU provides us with minimal information about hardware platform using 48 * minimalistic DeviceTree. This is not a Linux DeviceTree. It is not even 49 * a firmware DeviceTree. 50 * 51 * It is information passed from QEMU to describe the information a hardware 52 * platform would have other mechanisms to discover at runtime, that are 53 * affected by the QEMU command line. 54 * 55 * Ultimately this device tree will be replaced by IPC calls to an emulated SCP. 56 * And when we do that, we won't then have to rewrite Normal world firmware to 57 * cope. 58 */ 59 60 static void read_cpu_topology_from_dt(void *dtb) 61 { 62 int node; 63 64 /* 65 * QEMU gives us this DeviceTree node when we config: 66 * -smp 16,sockets=2,clusters=2,cores=2,threads=2 67 * 68 * topology { 69 * threads = <0x02>; 70 * cores = <0x02>; 71 * clusters = <0x02>; 72 * sockets = <0x02>; 73 * }; 74 */ 75 76 node = fdt_path_offset(dtb, "/cpus/topology"); 77 if (node > 0) { 78 dynamic_platform_info.cpu_topo.sockets = 79 fdt_read_uint32_default(dtb, node, "sockets", 0); 80 dynamic_platform_info.cpu_topo.clusters = 81 fdt_read_uint32_default(dtb, node, "clusters", 0); 82 dynamic_platform_info.cpu_topo.cores = 83 fdt_read_uint32_default(dtb, node, "cores", 0); 84 dynamic_platform_info.cpu_topo.threads = 85 fdt_read_uint32_default(dtb, node, "threads", 0); 86 } 87 88 INFO("Cpu topology: sockets: %d, clusters: %d, cores: %d, threads: %d\n", 89 dynamic_platform_info.cpu_topo.sockets, 90 dynamic_platform_info.cpu_topo.clusters, 91 dynamic_platform_info.cpu_topo.cores, 92 dynamic_platform_info.cpu_topo.threads); 93 } 94 95 void read_cpuinfo_from_dt(void *dtb) 96 { 97 int node; 98 int prev; 99 int cpu = 0; 100 uintptr_t mpidr; 101 102 /* 103 * QEMU gives us this DeviceTree node: 104 * numa-node-id entries are only when NUMA config is used 105 * 106 * cpus { 107 * #size-cells = <0x00>; 108 * #address-cells = <0x02>; 109 * 110 * cpu@0 { 111 * numa-node-id = <0x00>; 112 * reg = <0x00 0x00>; 113 * }; 114 * 115 * cpu@1 { 116 * numa-node-id = <0x03>; 117 * reg = <0x00 0x01>; 118 * }; 119 * }; 120 */ 121 node = fdt_path_offset(dtb, "/cpus"); 122 if (node < 0) { 123 ERROR("No information about cpus in DeviceTree.\n"); 124 panic(); 125 } 126 127 /* 128 * QEMU numbers cpus from 0 and there can be /cpus/cpu-map present so we 129 * cannot use fdt_first_subnode() here 130 */ 131 node = fdt_path_offset(dtb, "/cpus/cpu@0"); 132 133 while (node > 0) { 134 if (fdt_getprop(dtb, node, "reg", NULL)) { 135 fdt_get_reg_props_by_index(dtb, node, 0, &mpidr, NULL); 136 } else { 137 ERROR("Incomplete information for cpu %d in DeviceTree.\n", cpu); 138 panic(); 139 } 140 141 dynamic_platform_info.cpu[cpu].mpidr = mpidr; 142 dynamic_platform_info.cpu[cpu].nodeid = 143 fdt_read_uint32_default(dtb, node, "numa-node-id", 0); 144 145 INFO("CPU %d: node-id: %d, mpidr: %ld\n", cpu, 146 dynamic_platform_info.cpu[cpu].nodeid, mpidr); 147 148 cpu++; 149 150 prev = node; 151 node = fdt_next_subnode(dtb, prev); 152 } 153 154 dynamic_platform_info.num_cpus = cpu; 155 INFO("Found %d cpus\n", dynamic_platform_info.num_cpus); 156 157 read_cpu_topology_from_dt(dtb); 158 } 159 160 void read_meminfo_from_dt(void *dtb) 161 { 162 const fdt32_t *prop; 163 const char *type; 164 int prev, node; 165 int len; 166 uint32_t memnode = 0; 167 uint32_t higher_value, lower_value; 168 uint64_t cur_base, cur_size; 169 170 /* 171 * QEMU gives us this DeviceTree node: 172 * 173 * memory@100c0000000 { 174 * numa-node-id = <0x01>; 175 * reg = <0x100 0xc0000000 0x00 0x40000000>; 176 * device_type = "memory"; 177 * }; 178 * 179 * memory@10000000000 { 180 * numa-node-id = <0x00>; 181 * reg = <0x100 0x00 0x00 0xc0000000>; 182 * device_type = "memory"; 183 * } 184 */ 185 186 for (prev = 0;; prev = node) { 187 node = fdt_next_node(dtb, prev, NULL); 188 if (node < 0) { 189 break; 190 } 191 192 type = fdt_getprop(dtb, node, "device_type", &len); 193 if (type && strncmp(type, "memory", len) == 0) { 194 dynamic_platform_info.memory[memnode].nodeid = 195 fdt_read_uint32_default(dtb, node, "numa-node-id", 0); 196 197 /* 198 * Get the 'reg' property of this node and 199 * assume two 8 bytes for base and size. 200 */ 201 prop = fdt_getprop(dtb, node, "reg", &len); 202 if (prop != 0 && len == (2 * sizeof(int64_t))) { 203 higher_value = fdt32_to_cpu(*prop); 204 lower_value = fdt32_to_cpu(*(prop + 1)); 205 cur_base = (uint64_t)(lower_value | ((uint64_t)higher_value) << 32); 206 207 higher_value = fdt32_to_cpu(*(prop + 2)); 208 lower_value = fdt32_to_cpu(*(prop + 3)); 209 cur_size = (uint64_t)(lower_value | ((uint64_t)higher_value) << 32); 210 211 dynamic_platform_info.memory[memnode].addr_base = cur_base; 212 dynamic_platform_info.memory[memnode].addr_size = cur_size; 213 214 INFO("RAM %d: node-id: %d, address: 0x%lx - 0x%lx\n", 215 memnode, 216 dynamic_platform_info.memory[memnode].nodeid, 217 dynamic_platform_info.memory[memnode].addr_base, 218 dynamic_platform_info.memory[memnode].addr_base + 219 dynamic_platform_info.memory[memnode].addr_size - 1); 220 } 221 222 memnode++; 223 } 224 } 225 226 dynamic_platform_info.num_memnodes = memnode; 227 } 228 229 void read_platform_config_from_dt(void *dtb) 230 { 231 int node; 232 const fdt64_t *data; 233 int err; 234 uintptr_t gicd_base; 235 uintptr_t gicr_base; 236 237 /* 238 * QEMU gives us this DeviceTree node: 239 * 240 * intc { 241 * reg = < 0x00 0x40060000 0x00 0x10000 242 * 0x00 0x40080000 0x00 0x4000000>; 243 * its { 244 * reg = <0x00 0x44081000 0x00 0x20000>; 245 * }; 246 * }; 247 */ 248 node = fdt_path_offset(dtb, "/intc"); 249 if (node < 0) { 250 return; 251 } 252 253 data = fdt_getprop(dtb, node, "reg", NULL); 254 if (data == NULL) { 255 return; 256 } 257 258 err = fdt_get_reg_props_by_index(dtb, node, 0, &gicd_base, NULL); 259 if (err < 0) { 260 ERROR("Failed to read GICD reg property of GIC node\n"); 261 return; 262 } 263 INFO("GICD base = 0x%lx\n", gicd_base); 264 265 err = fdt_get_reg_props_by_index(dtb, node, 1, &gicr_base, NULL); 266 if (err < 0) { 267 ERROR("Failed to read GICR reg property of GIC node\n"); 268 return; 269 } 270 INFO("GICR base = 0x%lx\n", gicr_base); 271 272 sbsa_set_gic_bases(gicd_base, gicr_base); 273 274 node = fdt_path_offset(dtb, "/intc/its"); 275 if (node < 0) { 276 return; 277 } 278 279 err = fdt_get_reg_props_by_index(dtb, node, 0, &gic_its_addr, NULL); 280 if (err < 0) { 281 ERROR("Failed to read GICI reg property of GIC node\n"); 282 return; 283 } 284 INFO("GICI base = 0x%lx\n", gic_its_addr); 285 } 286 287 void read_platform_version(void *dtb) 288 { 289 int node; 290 291 node = fdt_path_offset(dtb, "/"); 292 if (node >= 0) { 293 platform_version_major = 294 fdt_read_uint32_default(dtb, node, "machine-version-major", 0); 295 platform_version_minor = 296 fdt_read_uint32_default(dtb, node, "machine-version-minor", 0); 297 } 298 } 299 300 void sbsa_platform_init(void) 301 { 302 /* Read DeviceTree data before MMU is enabled */ 303 304 void *dtb = (void *)(uintptr_t)ARM_PRELOADED_DTB_BASE; 305 int err; 306 307 err = fdt_open_into(dtb, dtb, PLAT_QEMU_DT_MAX_SIZE); 308 if (err < 0) { 309 ERROR("Invalid Device Tree at %p: error %d\n", dtb, err); 310 return; 311 } 312 313 err = fdt_check_header(dtb); 314 if (err < 0) { 315 ERROR("Invalid DTB file passed\n"); 316 return; 317 } 318 319 read_platform_version(dtb); 320 INFO("Platform version: %d.%d\n", platform_version_major, platform_version_minor); 321 322 read_platform_config_from_dt(dtb); 323 read_cpuinfo_from_dt(dtb); 324 read_meminfo_from_dt(dtb); 325 } 326 327 /* 328 * This function is responsible for handling all SiP calls from the NS world 329 */ 330 uintptr_t sbsa_sip_smc_handler(uint32_t smc_fid, 331 u_register_t x1, 332 u_register_t x2, 333 u_register_t x3, 334 u_register_t x4, 335 void *cookie, 336 void *handle, 337 u_register_t flags) 338 { 339 uint32_t ns; 340 uint64_t index; 341 342 /* Determine which security state this SMC originated from */ 343 ns = is_caller_non_secure(flags); 344 if (!ns) { 345 ERROR("%s: wrong world SMC (0x%x)\n", __func__, smc_fid); 346 SMC_RET1(handle, SMC_UNK); 347 } 348 349 switch (smc_fid) { 350 case SIP_SVC_VERSION: 351 INFO("Platform version requested\n"); 352 SMC_RET3(handle, NULL, platform_version_major, platform_version_minor); 353 354 case SIP_SVC_GET_GIC: 355 SMC_RET3(handle, NULL, sbsa_get_gicd(), sbsa_get_gicr()); 356 357 case SIP_SVC_GET_GIC_ITS: 358 SMC_RET2(handle, NULL, gic_its_addr); 359 360 case SIP_SVC_GET_CPU_COUNT: 361 SMC_RET2(handle, NULL, dynamic_platform_info.num_cpus); 362 363 case SIP_SVC_GET_CPU_NODE: 364 index = x1; 365 if (index < PLATFORM_CORE_COUNT) { 366 SMC_RET3(handle, NULL, 367 dynamic_platform_info.cpu[index].nodeid, 368 dynamic_platform_info.cpu[index].mpidr); 369 } else { 370 SMC_RET1(handle, SMC_ARCH_CALL_INVAL_PARAM); 371 } 372 373 case SIP_SVC_GET_CPU_TOPOLOGY: 374 if (dynamic_platform_info.cpu_topo.cores > 0) { 375 SMC_RET5(handle, NULL, 376 dynamic_platform_info.cpu_topo.sockets, 377 dynamic_platform_info.cpu_topo.clusters, 378 dynamic_platform_info.cpu_topo.cores, 379 dynamic_platform_info.cpu_topo.threads); 380 } else { 381 /* we do not know topology so we report SMC as unknown */ 382 SMC_RET1(handle, SMC_UNK); 383 } 384 385 case SIP_SVC_GET_MEMORY_NODE_COUNT: 386 SMC_RET2(handle, NULL, dynamic_platform_info.num_memnodes); 387 388 case SIP_SVC_GET_MEMORY_NODE: 389 index = x1; 390 if (index < PLAT_MAX_MEM_NODES) { 391 SMC_RET4(handle, NULL, 392 dynamic_platform_info.memory[index].nodeid, 393 dynamic_platform_info.memory[index].addr_base, 394 dynamic_platform_info.memory[index].addr_size); 395 } else { 396 SMC_RET1(handle, SMC_ARCH_CALL_INVAL_PARAM); 397 } 398 399 default: 400 ERROR("%s: unhandled SMC (0x%x) (function id: %d)\n", __func__, smc_fid, 401 smc_fid - SIP_FUNCTION); 402 SMC_RET1(handle, SMC_UNK); 403 } 404 } 405 406 int sbsa_sip_smc_setup(void) 407 { 408 return 0; 409 } 410 411 /* Define a runtime service descriptor for fast SMC calls */ 412 DECLARE_RT_SVC( 413 sbsa_sip_svc, 414 OEN_SIP_START, 415 OEN_SIP_END, 416 SMC_TYPE_FAST, 417 sbsa_sip_smc_setup, 418 sbsa_sip_smc_handler 419 ); 420