xref: /rk3399_ARM-atf/common/runtime_svc.c (revision 57de50322768ced4ba8d0cf5295e5cb8f01a382b)
1 /*
2  * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <errno.h>
9 #include <string.h>
10 
11 #include <common/debug.h>
12 #include <common/runtime_svc.h>
13 
14 /*******************************************************************************
15  * The 'rt_svc_descs' array holds the runtime service descriptors exported by
16  * services by placing them in the 'rt_svc_descs' linker section.
17  * The 'rt_svc_descs_indices' array holds the index of a descriptor in the
18  * 'rt_svc_descs' array. When an SMC arrives, the OEN[29:24] bits and the call
19  * type[31] bit in the function id are combined to get an index into the
20  * 'rt_svc_descs_indices' array. This gives the index of the descriptor in the
21  * 'rt_svc_descs' array which contains the SMC handler.
22  ******************************************************************************/
23 uint8_t rt_svc_descs_indices[MAX_RT_SVCS];
24 
25 #define RT_SVC_DECS_NUM		((RT_SVC_DESCS_END - RT_SVC_DESCS_START)\
26 					/ sizeof(rt_svc_desc_t))
27 
28 static bool get_handler_for_smc_fid(uint32_t smc_fid, rt_svc_handle_t *handler)
29 {
30 	unsigned int index;
31 	unsigned int idx;
32 	const rt_svc_desc_t *rt_svc_descs;
33 
34 	idx = get_unique_oen_from_smc_fid(smc_fid);
35 	assert(idx < MAX_RT_SVCS);
36 	index = rt_svc_descs_indices[idx];
37 
38 	if (index >= RT_SVC_DECS_NUM)
39 		return false;
40 
41 	rt_svc_descs = (rt_svc_desc_t *) RT_SVC_DESCS_START;
42 	assert(handler != NULL);
43 	*handler = rt_svc_descs[index].handle;
44 	assert(*handler != NULL);
45 
46 	return true;
47 }
48 
49 /*******************************************************************************
50  * Function to invoke the registered `handle` corresponding to the smc_fid in
51  * AArch32 mode.
52  ******************************************************************************/
53 uintptr_t handle_runtime_svc(uint32_t smc_fid,
54 			     void *cookie,
55 			     void *handle,
56 			     unsigned int flags)
57 {
58 	u_register_t x1, x2, x3, x4;
59 	rt_svc_handle_t handler;
60 
61 	assert(handle != NULL);
62 
63 	if (!get_handler_for_smc_fid(smc_fid, &handler)) {
64 		SMC_RET1(handle, SMC_UNK);
65 	}
66 
67 	get_smc_params_from_ctx(handle, x1, x2, x3, x4);
68 
69 	return handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
70 }
71 
72 /*******************************************************************************
73  * Simple routine to sanity check a runtime service descriptor before using it
74  ******************************************************************************/
75 static int32_t validate_rt_svc_desc(const rt_svc_desc_t *desc)
76 {
77 	if (desc == NULL) {
78 		return -EINVAL;
79 	}
80 	if (desc->start_oen > desc->end_oen) {
81 		return -EINVAL;
82 	}
83 	if (desc->end_oen >= OEN_LIMIT) {
84 		return -EINVAL;
85 	}
86 	if ((desc->call_type != SMC_TYPE_FAST) &&
87 	    (desc->call_type != SMC_TYPE_YIELD)) {
88 		return -EINVAL;
89 	}
90 	/* A runtime service having no init or handle function doesn't make sense */
91 	if ((desc->init == NULL) && (desc->handle == NULL)) {
92 		return -EINVAL;
93 	}
94 	return 0;
95 }
96 
97 /*******************************************************************************
98  * This function calls the initialisation routine in the descriptor exported by
99  * a runtime service. Once a descriptor has been validated, its start & end
100  * owning entity numbers and the call type are combined to form a unique oen.
101  * The unique oen is used as an index into the 'rt_svc_descs_indices' array.
102  * The index of the runtime service descriptor is stored at this index.
103  ******************************************************************************/
104 void __init runtime_svc_init(void)
105 {
106 	int rc = 0;
107 	uint8_t index, start_idx, end_idx;
108 	rt_svc_desc_t *rt_svc_descs;
109 
110 	/* Assert the number of descriptors detected are less than maximum indices */
111 	assert((RT_SVC_DESCS_END >= RT_SVC_DESCS_START) &&
112 			(RT_SVC_DECS_NUM < MAX_RT_SVCS));
113 
114 	/* If no runtime services are implemented then simply bail out */
115 	if (RT_SVC_DECS_NUM == 0U) {
116 		return;
117 	}
118 	/* Initialise internal variables to invalid state */
119 	(void)memset(rt_svc_descs_indices, -1, sizeof(rt_svc_descs_indices));
120 
121 	rt_svc_descs = (rt_svc_desc_t *) RT_SVC_DESCS_START;
122 	for (index = 0U; index < RT_SVC_DECS_NUM; index++) {
123 		rt_svc_desc_t *service = &rt_svc_descs[index];
124 
125 		/*
126 		 * An invalid descriptor is an error condition since it is
127 		 * difficult to predict the system behaviour in the absence
128 		 * of this service.
129 		 */
130 		rc = validate_rt_svc_desc(service);
131 		if (rc != 0) {
132 			ERROR("Invalid runtime service descriptor %p\n",
133 				(void *) service);
134 			panic();
135 		}
136 
137 		/*
138 		 * The runtime service may have separate rt_svc_desc_t
139 		 * for its fast smc and yielding smc. Since the service itself
140 		 * need to be initialized only once, only one of them will have
141 		 * an initialisation routine defined. Call the initialisation
142 		 * routine for this runtime service, if it is defined.
143 		 */
144 		if (service->init != NULL) {
145 			rc = service->init();
146 			if (rc != 0) {
147 				ERROR("Error initializing runtime service %s\n",
148 						service->name);
149 				continue;
150 			}
151 		}
152 
153 		/*
154 		 * Fill the indices corresponding to the start and end
155 		 * owning entity numbers with the index of the
156 		 * descriptor which will handle the SMCs for this owning
157 		 * entity range.
158 		 */
159 		start_idx = (uint8_t)get_unique_oen(service->start_oen,
160 						    service->call_type);
161 		end_idx = (uint8_t)get_unique_oen(service->end_oen,
162 						  service->call_type);
163 		assert(start_idx <= end_idx);
164 		assert(end_idx < MAX_RT_SVCS);
165 		for (; start_idx <= end_idx; start_idx++) {
166 			rt_svc_descs_indices[start_idx] = index;
167 		}
168 	}
169 }
170