sbsa_sip_svc.c 11 KB

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