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/runtime_svc.h>
10 #include <smccc_helpers.h>
11
12 #include <sbsa_platform.h>
13
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 /*
20 * We do not use SMCCC_ARCH_SOC_ID here because qemu_sbsa is virtual platform
21 * which uses SoC present in QEMU. And they can change on their own while we
22 * need version of whole 'virtual hardware platform'.
23 */
24 #define SIP_SVC_VERSION SIP_FUNCTION_ID(1)
25 #define SIP_SVC_GET_GIC SIP_FUNCTION_ID(100)
26 #define SIP_SVC_GET_GIC_ITS SIP_FUNCTION_ID(101)
27 #define SIP_SVC_GET_CPU_COUNT SIP_FUNCTION_ID(200)
28 #define SIP_SVC_GET_CPU_NODE SIP_FUNCTION_ID(201)
29 #define SIP_SVC_GET_CPU_TOPOLOGY SIP_FUNCTION_ID(202)
30 #define SIP_SVC_GET_MEMORY_NODE_COUNT SIP_FUNCTION_ID(300)
31 #define SIP_SVC_GET_MEMORY_NODE SIP_FUNCTION_ID(301)
32
33 uintptr_t sbsa_get_gicd(void);
34 uintptr_t sbsa_get_gicr(void);
35
36 /*
37 * This function is responsible for handling all SiP calls from the NS world
38 */
sbsa_sip_smc_handler(uint32_t smc_fid,u_register_t x1,u_register_t x2,u_register_t x3,u_register_t x4,void * cookie,void * handle,u_register_t flags)39 uintptr_t sbsa_sip_smc_handler(uint32_t smc_fid,
40 u_register_t x1,
41 u_register_t x2,
42 u_register_t x3,
43 u_register_t x4,
44 void *cookie,
45 void *handle,
46 u_register_t flags)
47 {
48 uint32_t ns;
49 uint64_t index;
50
51 /* Determine which security state this SMC originated from */
52 ns = is_caller_non_secure(flags);
53 if (!ns) {
54 ERROR("%s: wrong world SMC (0x%x)\n", __func__, smc_fid);
55 SMC_RET1(handle, SMC_UNK);
56 }
57
58 switch (smc_fid) {
59 case SIP_SVC_VERSION:
60 INFO("Platform version requested\n");
61 SMC_RET3(handle, NULL, sbsa_platform_version_major(),
62 sbsa_platform_version_minor());
63
64 case SIP_SVC_GET_GIC:
65 SMC_RET3(handle, NULL, sbsa_get_gicd(), sbsa_get_gicr());
66
67 case SIP_SVC_GET_GIC_ITS:
68 SMC_RET2(handle, NULL, sbsa_platform_gic_its_addr());
69
70 case SIP_SVC_GET_CPU_COUNT:
71 SMC_RET2(handle, NULL, sbsa_platform_num_cpus());
72
73 case SIP_SVC_GET_CPU_NODE:
74 index = x1;
75 if (index < PLATFORM_CORE_COUNT) {
76 struct platform_cpu_data data;
77
78 data = sbsa_platform_cpu_node(index);
79
80 SMC_RET3(handle, NULL, data.nodeid, data.mpidr);
81 } else {
82 SMC_RET1(handle, SMC_ARCH_CALL_INVAL_PARAM);
83 }
84
85 case SIP_SVC_GET_CPU_TOPOLOGY: {
86 struct platform_cpu_topology topology;
87
88 topology = sbsa_platform_cpu_topology();
89
90 if (topology.cores > 0) {
91 SMC_RET5(handle, NULL, topology.sockets,
92 topology.clusters, topology.cores,
93 topology.threads);
94 } else {
95 /* we do not know topology so we report SMC as unknown */
96 SMC_RET1(handle, SMC_UNK);
97 }
98 }
99
100 case SIP_SVC_GET_MEMORY_NODE_COUNT:
101 SMC_RET2(handle, NULL, sbsa_platform_num_memnodes());
102
103 case SIP_SVC_GET_MEMORY_NODE:
104 index = x1;
105 if (index < PLAT_MAX_MEM_NODES) {
106 struct platform_memory_data data;
107
108 data = sbsa_platform_memory_node(index);
109
110 SMC_RET4(handle, NULL, data.nodeid,
111 data.addr_base, data.addr_size);
112 } else {
113 SMC_RET1(handle, SMC_ARCH_CALL_INVAL_PARAM);
114 }
115
116 default:
117 ERROR("%s: unhandled SMC (0x%x) (function id: %d)\n", __func__, smc_fid,
118 smc_fid - SIP_FUNCTION);
119 SMC_RET1(handle, SMC_UNK);
120 }
121 }
122
sbsa_sip_smc_setup(void)123 int sbsa_sip_smc_setup(void)
124 {
125 return 0;
126 }
127
128 /* Define a runtime service descriptor for fast SMC calls */
129 DECLARE_RT_SVC(
130 sbsa_sip_svc,
131 OEN_SIP_START,
132 OEN_SIP_END,
133 SMC_TYPE_FAST,
134 sbsa_sip_smc_setup,
135 sbsa_sip_smc_handler
136 );
137