"p2p/net/mock/interface.go" did not exist on "536c183b3775768bc1489d292eac24b3cd2ecb9c"
runtime_svc.c 5.12 KB
Newer Older
1
/*
2
 * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
3
 *
dp-arm's avatar
dp-arm committed
4
 * SPDX-License-Identifier: BSD-3-Clause
5
6
 */

7
#include <assert.h>
8
#include <debug.h>
9
#include <errno.h>
10
#include <runtime_svc.h>
11
#include <string.h>
12
13

/*******************************************************************************
Achin Gupta's avatar
Achin Gupta committed
14
15
16
17
18
19
20
 * The 'rt_svc_descs' array holds the runtime service descriptors exported by
 * services by placing them in the 'rt_svc_descs' linker section.
 * The 'rt_svc_descs_indices' array holds the index of a descriptor in the
 * 'rt_svc_descs' array. When an SMC arrives, the OEN[29:24] bits and the call
 * type[31] bit in the function id are combined to get an index into the
 * 'rt_svc_descs_indices' array. This gives the index of the descriptor in the
 * 'rt_svc_descs' array which contains the SMC handler.
21
 ******************************************************************************/
22
23
#define RT_SVC_DESCS_START	((uintptr_t) (&__RT_SVC_DESCS_START__))
#define RT_SVC_DESCS_END	((uintptr_t) (&__RT_SVC_DESCS_END__))
Achin Gupta's avatar
Achin Gupta committed
24
uint8_t rt_svc_descs_indices[MAX_RT_SVCS];
25
static rt_svc_desc_t *rt_svc_descs;
Achin Gupta's avatar
Achin Gupta committed
26

27
28
29
#define RT_SVC_DECS_NUM		((RT_SVC_DESCS_END - RT_SVC_DESCS_START)\
					/ sizeof(rt_svc_desc_t))

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/*******************************************************************************
 * Function to invoke the registered `handle` corresponding to the smc_fid.
 ******************************************************************************/
uintptr_t handle_runtime_svc(uint32_t smc_fid,
			     void *cookie,
			     void *handle,
			     unsigned int flags)
{
	u_register_t x1, x2, x3, x4;
	int index, idx;
	const rt_svc_desc_t *rt_svc_descs;

	assert(handle);
	idx = get_unique_oen_from_smc_fid(smc_fid);
	assert(idx >= 0 && idx < MAX_RT_SVCS);

	index = rt_svc_descs_indices[idx];
	if (index < 0 || index >= RT_SVC_DECS_NUM)
		SMC_RET1(handle, SMC_UNK);

	rt_svc_descs = (rt_svc_desc_t *) RT_SVC_DESCS_START;

	get_smc_params_from_ctx(handle, x1, x2, x3, x4);

	return rt_svc_descs[index].handle(smc_fid, x1, x2, x3, x4, cookie,
						handle, flags);
}

Achin Gupta's avatar
Achin Gupta committed
58
59
60
/*******************************************************************************
 * Simple routine to sanity check a runtime service descriptor before using it
 ******************************************************************************/
61
static int32_t validate_rt_svc_desc(const rt_svc_desc_t *desc)
Achin Gupta's avatar
Achin Gupta committed
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
{
	if (desc == NULL)
		return -EINVAL;

	if (desc->start_oen > desc->end_oen)
		return -EINVAL;

	if (desc->end_oen >= OEN_LIMIT)
		return -EINVAL;

	if (desc->call_type != SMC_TYPE_FAST && desc->call_type != SMC_TYPE_STD)
		return -EINVAL;

	/* A runtime service having no init or handle function doesn't make sense */
	if (desc->init == NULL && desc->handle == NULL)
		return -EINVAL;

	return 0;
}

/*******************************************************************************
 * This function calls the initialisation routine in the descriptor exported by
 * a runtime service. Once a descriptor has been validated, its start & end
 * owning entity numbers and the call type are combined to form a unique oen.
 * The unique oen is used as an index into the 'rt_svc_descs_indices' array.
 * The index of the runtime service descriptor is stored at this index.
 ******************************************************************************/
89
void runtime_svc_init(void)
90
{
91
92
93
	int rc = 0, index, start_idx, end_idx;

	/* Assert the number of descriptors detected are less than maximum indices */
94
95
	assert((RT_SVC_DESCS_END >= RT_SVC_DESCS_START) &&
			(RT_SVC_DECS_NUM < MAX_RT_SVCS));
Achin Gupta's avatar
Achin Gupta committed
96
97

	/* If no runtime services are implemented then simply bail out */
98
	if (RT_SVC_DECS_NUM == 0)
Achin Gupta's avatar
Achin Gupta committed
99
100
101
102
103
		return;

	/* Initialise internal variables to invalid state */
	memset(rt_svc_descs_indices, -1, sizeof(rt_svc_descs_indices));

104
	rt_svc_descs = (rt_svc_desc_t *) RT_SVC_DESCS_START;
105
	for (index = 0; index < RT_SVC_DECS_NUM; index++) {
106
		rt_svc_desc_t *service = &rt_svc_descs[index];
Achin Gupta's avatar
Achin Gupta committed
107
108
109
110
111
112

		/*
		 * An invalid descriptor is an error condition since it is
		 * difficult to predict the system behaviour in the absence
		 * of this service.
		 */
113
		rc = validate_rt_svc_desc(service);
Achin Gupta's avatar
Achin Gupta committed
114
		if (rc) {
115
116
			ERROR("Invalid runtime service descriptor %p\n",
				(void *) service);
117
			panic();
Achin Gupta's avatar
Achin Gupta committed
118
119
		}

120
		/*
121
		 * The runtime service may have separate rt_svc_desc_t
122
123
124
125
126
		 * for its fast smc and standard smc. Since the service itself
		 * need to be initialized only once, only one of them will have
		 * an initialisation routine defined. Call the initialisation
		 * routine for this runtime service, if it is defined.
		 */
127
128
		if (service->init) {
			rc = service->init();
129
130
			if (rc) {
				ERROR("Error initializing runtime service %s\n",
131
						service->name);
132
133
				continue;
			}
Achin Gupta's avatar
Achin Gupta committed
134
		}
135
136
137
138
139
140
141
142

		/*
		 * Fill the indices corresponding to the start and end
		 * owning entity numbers with the index of the
		 * descriptor which will handle the SMCs for this owning
		 * entity range.
		 */
		start_idx = get_unique_oen(rt_svc_descs[index].start_oen,
143
				service->call_type);
144
		assert(start_idx < MAX_RT_SVCS);
145
		end_idx = get_unique_oen(rt_svc_descs[index].end_oen,
146
				service->call_type);
147
		assert(end_idx < MAX_RT_SVCS);
148
149
		for (; start_idx <= end_idx; start_idx++)
			rt_svc_descs_indices[start_idx] = index;
Achin Gupta's avatar
Achin Gupta committed
150
	}
151
}