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