/
object.h
328 lines (283 loc) · 9.96 KB
/
object.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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
58
59
60
61
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
/*
* Copyright 2017, Data61
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
* ABN 41 687 119 230.
*
* This software may be distributed and modified according to the terms of
* the BSD 2-Clause license. Note that NO WARRANTY is provided.
* See "LICENSE_BSD2.txt" for details.
*
* @TAG(DATA61_BSD)
*/
#ifndef __VKA_OBJECT_H__
#define __VKA_OBJECT_H__
#include <assert.h>
#include <errno.h>
#include <vka/vka.h>
#include <vka/kobject_t.h>
#include <stdio.h>
#include <string.h>
#include <utils/util.h>
/*
* A wrapper to hold all the allocation information for an 'object'
* An object here is just combination of cptr and untyped allocation
* The type and size of the allocation is also stored to make free
* more convenient.
*/
typedef struct vka_object {
seL4_CPtr cptr;
seL4_Word ut;
seL4_Word type;
seL4_Word size_bits;
} vka_object_t;
/*
* Generic object allocator used by functions below, can also be used directly
*/
static inline int
vka_alloc_object_at_maybe_dev(vka_t *vka, seL4_Word type, seL4_Word size_bits, uintptr_t paddr,
bool can_use_dev, vka_object_t *result)
{
int error = vka_cspace_alloc(vka, &result->cptr);
if (unlikely(error)) {
result->cptr = 0;
ZF_LOGE("Failed to allocate cslot: error %d\n", error);
goto error;
}
cspacepath_t path;
vka_cspace_make_path(vka, result->cptr, &path);
if (paddr == VKA_NO_PADDR) {
error = vka_utspace_alloc_maybe_device(vka, &path, type, size_bits, can_use_dev, &result->ut);
if (unlikely(error)) {
ZF_LOGE("Failed to allocate object of size %lu, error %d\n",
BIT(size_bits), error);
goto error;
}
} else {
error = vka_utspace_alloc_at(vka, &path, type, size_bits, paddr, &result->ut);
if (unlikely(error)) {
ZF_LOGE("Failed to allocate object of size %lu at paddr %p, error %d\n",
BIT(size_bits), (void*)paddr, error);
goto error;
}
}
result->type = type;
result->size_bits = size_bits;
return 0;
error:
if (result->cptr) {
vka_cspace_free(vka, result->cptr);
}
/* don't return garbage to the caller */
memset(result, 0, sizeof(*result));
return error;
}
static inline int
vka_alloc_object_at(vka_t *vka, seL4_Word type, seL4_Word size_bits, uintptr_t paddr,
vka_object_t *result)
{
return vka_alloc_object_at_maybe_dev(vka, type, size_bits, paddr, false, result);
}
static inline int
vka_alloc_object(vka_t *vka, seL4_Word type, seL4_Word size_bits, vka_object_t *result)
{
return vka_alloc_object_at(vka, type, size_bits, VKA_NO_PADDR, result);
}
/* convenient wrapper that throws away the vka_object_t and just returns the cptr -
* note you cannot use this if you intend to free the object */
static inline seL4_CPtr vka_alloc_object_leaky(vka_t *vka, seL4_Word type, seL4_Word size_bits) WARN_UNUSED_RESULT;
static inline seL4_CPtr
vka_alloc_object_leaky(vka_t *vka, seL4_Word type, seL4_Word size_bits)
{
vka_object_t result = {.cptr = 0, .ut = 0, .type = 0, size_bits = 0};
return vka_alloc_object(vka, type, size_bits, &result) == -1 ? 0 : result.cptr;
}
static inline void
vka_free_object(vka_t *vka, vka_object_t *object)
{
cspacepath_t path;
vka_cspace_make_path(vka, object->cptr, &path);
if (path.capPtr == 0) {
ZF_LOGE("Failed to create cspace path to object");
return;
}
/* ignore any errors */
seL4_CNode_Delete(path.root, path.capPtr, path.capDepth);
vka_cspace_free(vka, object->cptr);
vka_utspace_free(vka, object->type, object->size_bits, object->ut);
}
static inline uintptr_t
vka_object_paddr(vka_t *vka, vka_object_t *object)
{
return vka_utspace_paddr(vka, object->ut, object->type, object->size_bits);
}
/* Convenience wrappers for allocating objects */
static inline int vka_alloc_untyped(vka_t *vka, uint32_t size_bits, vka_object_t *result)
{
return vka_alloc_object(vka, seL4_UntypedObject, size_bits, result);
}
static inline int vka_alloc_untyped_at(vka_t *vka, uint32_t size_bits, uintptr_t paddr,
vka_object_t *result)
{
return vka_alloc_object_at(vka, seL4_UntypedObject, size_bits, paddr, result);
}
static inline int vka_alloc_tcb(vka_t *vka, vka_object_t *result)
{
return vka_alloc_object(vka, seL4_TCBObject, seL4_TCBBits, result);
}
static inline int vka_alloc_sched_context(UNUSED vka_t *vka, UNUSED vka_object_t *result)
{
#ifdef CONFIG_KERNEL_RT
return vka_alloc_object(vka, seL4_SchedContextObject, seL4_MinSchedContextBits, result);
#else
ZF_LOGW("Allocating sched context on non RT kernel");
return ENOSYS;
#endif
}
static inline int vka_alloc_sched_context_size(UNUSED vka_t *vka, UNUSED vka_object_t *result, UNUSED uint32_t size_bits)
{
#ifdef CONFIG_KERNEL_RT
if (size_bits < seL4_MinSchedContextBits) {
ZF_LOGE("Invalid size bits for sc");
return -1;
}
return vka_alloc_object(vka, seL4_SchedContextObject, size_bits, result);
#else
ZF_LOGW("Allocating sched context on non RT kernel");
return ENOSYS;
#endif
}
static inline int vka_alloc_endpoint(vka_t *vka, vka_object_t *result)
{
return vka_alloc_object(vka, seL4_EndpointObject, seL4_EndpointBits, result);
}
static inline int vka_alloc_notification(vka_t *vka, vka_object_t *result)
{
return vka_alloc_object(vka, seL4_NotificationObject, seL4_NotificationBits, result);
}
/* @deprecated use vka_alloc_notification */
static inline int DEPRECATED("Use vka_alloc_notification")
vka_alloc_async_endpoint(vka_t *vka, vka_object_t *result)
{
return vka_alloc_notification(vka, result);
}
static inline int vka_alloc_reply(UNUSED vka_t *vka, UNUSED vka_object_t *result)
{
#ifdef CONFIG_KERNEL_RT
return vka_alloc_object(vka, seL4_ReplyObject, seL4_ReplyBits, result);
#else
ZF_LOGW("Allocating reply on non RT kernel");
return ENOSYS;
#endif
}
static inline int vka_alloc_cnode_object(vka_t *vka, uint32_t slot_bits, vka_object_t *result)
{
return vka_alloc_object(vka, seL4_CapTableObject, slot_bits, result);
}
/* For arch specific allocations we call upon kobject to avoid code duplication */
static inline int vka_alloc_frame(vka_t *vka, uint32_t size_bits, vka_object_t *result)
{
return vka_alloc_object(vka, kobject_get_type(KOBJECT_FRAME, size_bits), size_bits, result);
}
/* For arch specific allocations we call upon kobject to avoid code duplication */
static inline int vka_alloc_frame_maybe_device(vka_t *vka, uint32_t size_bits, bool can_use_dev, vka_object_t *result)
{
return vka_alloc_object_at_maybe_dev(vka, kobject_get_type(KOBJECT_FRAME, size_bits),
size_bits, VKA_NO_PADDR, can_use_dev, result);
}
static inline int vka_alloc_frame_at(vka_t *vka, uint32_t size_bits, uintptr_t paddr,
vka_object_t *result)
{
return vka_alloc_object_at(vka, kobject_get_type(KOBJECT_FRAME, size_bits), size_bits,
paddr, result);
}
static inline int vka_alloc_page_directory(vka_t *vka, vka_object_t *result)
{
return vka_alloc_object(vka, kobject_get_type(KOBJECT_PAGE_DIRECTORY, 0), seL4_PageDirBits, result);
}
static inline int vka_alloc_page_table(vka_t *vka, vka_object_t *result)
{
return vka_alloc_object(vka, kobject_get_type(KOBJECT_PAGE_TABLE, 0), seL4_PageTableBits, result);
}
#ifdef CONFIG_CACHE_COLORING
static inline int vka_alloc_kernel_image(vka_t *vka, vka_object_t *result)
{
return vka_alloc_object(vka, kobject_get_type(KOBJECT_KERNEL_IMAGE, 0), seL4_KernelImageBits, result);
}
#endif
/* Implement a kobject interface */
static inline int vka_alloc_kobject(vka_t *vka, kobject_t type, seL4_Word size_bits,
vka_object_t *result)
{
return vka_alloc_object(vka, kobject_get_type(type, size_bits), size_bits, result);
}
/* leaky versions of the object allocation functions - throws away the kobject_t */
#define LEAKY(name) \
static inline seL4_CPtr vka_alloc_##name##_leaky(vka_t *vka) WARN_UNUSED_RESULT; \
static inline seL4_CPtr vka_alloc_##name##_leaky(vka_t *vka) \
{\
vka_object_t object;\
if (vka_alloc_##name(vka, &object) != 0) {\
return 0;\
}\
return object.cptr;\
}
LEAKY(tcb)
LEAKY(endpoint)
LEAKY(notification)
LEAKY(page_directory)
LEAKY(page_table)
LEAKY(sched_context)
LEAKY(reply)
static inline DEPRECATED("use vka_alloc_notification_leaky") seL4_CPtr
vka_alloc_async_endpoint_leaky(vka_t *vka)
{
return vka_alloc_notification_leaky(vka);
}
#define LEAKY_SIZE_BITS(name) \
static inline seL4_CPtr vka_alloc_##name##_leaky(vka_t *vka, uint32_t size_bits) WARN_UNUSED_RESULT; \
static inline seL4_CPtr vka_alloc_##name##_leaky(vka_t *vka, uint32_t size_bits) \
{\
vka_object_t object;\
if (vka_alloc_##name(vka, size_bits, &object) != 0) {\
return 0;\
}\
return object.cptr;\
}
LEAKY_SIZE_BITS(untyped)
LEAKY_SIZE_BITS(frame)
LEAKY_SIZE_BITS(cnode_object)
#include <vka/arch/object.h>
/*
* Get the size (in bits) of the untyped memory required to create an object of
* the given size.
*/
static inline unsigned long
vka_get_object_size(seL4_Word objectType, seL4_Word objectSize)
{
switch (objectType) {
/* Generic objects. */
case seL4_UntypedObject:
return objectSize;
case seL4_TCBObject:
return seL4_TCBBits;
#ifdef CONFIG_KERNEL_RT
case seL4_SchedContextObject:
return objectSize > seL4_MinSchedContextBits ? objectSize : seL4_MinSchedContextBits;
case seL4_ReplyObject:
return seL4_ReplyBits;
#endif
case seL4_EndpointObject:
return seL4_EndpointBits;
case seL4_NotificationObject:
return seL4_NotificationBits;
case seL4_CapTableObject:
return (seL4_SlotBits + objectSize);
#ifdef CONFIG_CACHE_COLORING
case seL4_KernelImageObject:
return seL4_KernelImageBits;
#endif
default:
return vka_arch_get_object_size(objectType);
}
}
#endif /* __VKA_OBJECT_H__ */