1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12
13#include <autoconf.h>
14
15#include <stdio.h>
16#include <stdlib.h>
17#include <assert.h>
18#include <inttypes.h>
19#include <string.h>
20
21#include <sel4/sel4.h>
22#include <sel4debug/debug.h>
23#include <simple-default/simple-default.h>
24
25#include <vspace/page.h>
26#include <vka/kobject_t.h>
27
28void *simple_default_get_frame_info(void *data, void *paddr, int size_bits, seL4_CPtr *frame_cap, seL4_Word *offset)
29{
30    unsigned int i;
31    seL4_BootInfo *bi = (seL4_BootInfo *) data;
32    assert(bi && paddr && offset && frame_cap);
33
34    for (i = 0; i < bi->untyped.end - bi->untyped.start; i++) {
35        if (bi->untypedList[i].paddr <= (seL4_Word)paddr &&
36            bi->untypedList[i].paddr + BIT(bi->untypedList[i].sizeBits) >= (seL4_Word)paddr + BIT(size_bits)) {
37            *frame_cap = bi->untyped.start + i;
38            *offset = (seL4_Word)paddr - bi->untypedList[i].paddr;
39            break;
40        }
41    }
42    return NULL;
43}
44seL4_Error simple_default_get_frame_cap(void *data, void *paddr, int size_bits, cspacepath_t *path)
45{
46    unsigned int i;
47    seL4_BootInfo *bi = (seL4_BootInfo *) data;
48    assert(bi && paddr);
49
50    for (i = 0; i < bi->untyped.end - bi->untyped.start; i++) {
51        if (bi->untypedList[i].paddr == (seL4_Word)paddr &&
52            bi->untypedList[i].sizeBits >= size_bits) {
53            return seL4_Untyped_Retype(bi->untyped.start + i, kobject_get_type(KOBJECT_FRAME, size_bits),
54                                       size_bits, path->root, path->dest, path->destDepth, path->offset, 1);
55        }
56    }
57    return seL4_FailedLookup;
58}
59
60void *simple_default_get_frame_mapping(void *data, void *paddr, int size_bits)
61{
62    return NULL;
63}
64
65seL4_Error simple_default_set_ASID(void *data, seL4_CPtr vspace)
66{
67    return seL4_ARCH_ASIDPool_Assign(seL4_CapInitThreadASIDPool, vspace);
68}
69
70int simple_default_cap_count(void *data)
71{
72    assert(data);
73
74    seL4_BootInfo *bi = data;
75
76    return (bi->sharedFrames.end - bi->sharedFrames.start)
77           + (bi->userImageFrames.end - bi->userImageFrames.start)
78           + (bi->userImagePaging.end - bi->userImagePaging.start)
79           + (bi->untyped.end - bi->untyped.start)
80           + SIMPLE_NUM_INIT_CAPS; //Include all the init caps
81}
82
83seL4_CPtr simple_default_nth_cap(void *data, int n)
84{
85    assert(data);
86
87    seL4_BootInfo *bi = data;
88    size_t shared_frame_range = bi->sharedFrames.end - bi->sharedFrames.start + SIMPLE_NUM_INIT_CAPS;
89    size_t user_img_frame_range = bi->userImageFrames.end - bi->userImageFrames.start + shared_frame_range;
90    size_t user_img_paging_range = bi->userImagePaging.end - bi->userImagePaging.start + user_img_frame_range;
91    size_t untyped_range = bi->untyped.end - bi->untyped.start + user_img_paging_range;
92
93    seL4_CPtr true_return = seL4_CapNull;
94
95    if (n < SIMPLE_NUM_INIT_CAPS) {
96        /* skip seL4_CapNull */
97        true_return = (seL4_CPtr) n + 1;
98#if !(defined(CONFIG_ARCH_IA32) || defined(CONFIG_ARCH_X86_64))
99        /* skip seL4_CapIOPortControl on non-x86 */
100        if (true_return >= seL4_CapIOPortControl) {
101            true_return++;
102        }
103#endif
104#ifndef CONFIG_IOMMU
105        /* skip seL4_CapIOSpace if IOMMU isn't supported on x86 */
106        if (true_return >= seL4_CapIOSpace) {
107            true_return++;
108        }
109#endif
110    } else if (n < shared_frame_range) {
111        return bi->sharedFrames.start + (n - SIMPLE_NUM_INIT_CAPS);
112    } else if (n < user_img_frame_range) {
113        return bi->userImageFrames.start + (n - shared_frame_range);
114    } else if (n < user_img_paging_range) {
115        return bi->userImagePaging.start + (n - user_img_frame_range);
116    } else if (n < untyped_range) {
117        return bi->untyped.start + (n - user_img_paging_range);
118    }
119
120    return true_return;
121}
122
123seL4_CPtr simple_default_init_cap(void *data, seL4_CPtr cap_pos)
124{
125    return cap_pos;
126}
127
128uint8_t simple_default_cnode_size(void *data)
129{
130    assert(data);
131
132    return ((seL4_BootInfo *)data)->initThreadCNodeSizeBits;
133}
134
135int simple_default_untyped_count(void *data)
136{
137    assert(data);
138
139    return ((seL4_BootInfo *)data)->untyped.end - ((seL4_BootInfo *)data)->untyped.start;
140}
141
142seL4_CPtr simple_default_nth_untyped(void *data, int n, size_t *size_bits, uintptr_t *paddr, bool *device)
143{
144    assert(data);
145
146    seL4_BootInfo *bi = data;
147
148    if (n < (bi->untyped.end - bi->untyped.start)) {
149        if (paddr != NULL) {
150            *paddr = bi->untypedList[n].paddr;
151        }
152        if (size_bits != NULL) {
153            *size_bits = bi->untypedList[n].sizeBits;
154        }
155        if (device != NULL) {
156            *device = (bool)bi->untypedList[n].isDevice;
157        }
158        return bi->untyped.start + (n);
159    }
160
161    return seL4_CapNull;
162}
163
164int simple_default_userimage_count(void *data)
165{
166    assert(data);
167
168    return ((seL4_BootInfo *)data)->userImageFrames.end - ((seL4_BootInfo *)data)->userImageFrames.start;
169}
170
171seL4_CPtr simple_default_nth_userimage(void *data, int n)
172{
173    assert(data);
174
175    seL4_BootInfo *bi = data;
176
177    if (n < (bi->userImageFrames.end - bi->userImageFrames.start)) {
178        return bi->userImageFrames.start + (n);
179    }
180
181    return seL4_CapNull;
182}
183
184int simple_default_core_count(void *data)
185{
186    assert(data);
187
188    return ((seL4_BootInfo *)data)->numNodes;
189}
190
191void simple_default_print(void *data)
192{
193    if (data == NULL) {
194        ZF_LOGE("Data is null!");
195    }
196
197    debug_print_bootinfo(data);
198}
199
200seL4_CPtr simple_default_sched_control(void *data, int core)
201{
202    assert(core < simple_default_core_count(data));
203#if CONFIG_KERNEL_MCS
204    return ((seL4_BootInfo *) data)->schedcontrol.start + core;
205#else
206    ZF_LOGW("not implemented");
207    return seL4_CapNull;
208#endif
209}
210
211ssize_t simple_default_get_extended_bootinfo_size(void *data, seL4_Word type)
212{
213    if (data == NULL) {
214        ZF_LOGE("Data is null!");
215        return -1;
216    }
217    seL4_BootInfo *bi = data;
218
219    /* start of the extended bootinfo is defined to be 4K from the start of regular bootinfo */
220    uintptr_t cur = (uintptr_t)bi + PAGE_SIZE_4K;
221    uintptr_t end = cur + bi->extraLen;
222    while (cur < end) {
223        seL4_BootInfoHeader *header = (seL4_BootInfoHeader *)cur;
224        if (header->id == type) {
225            return header->len;
226        }
227        cur += header->len;
228    }
229    return -1;
230}
231
232ssize_t simple_default_get_extended_bootinfo(void *data, seL4_Word type, void *dest, ssize_t max_len)
233{
234    assert(data);
235    seL4_BootInfo *bi = data;
236
237    if (max_len < 0) {
238        ZF_LOGE("Unexpected negative size");
239        return -1;
240    }
241    /* start of the extended bootinfo is defined to be 4K from the start of regular bootinfo */
242    uintptr_t cur = (uintptr_t)bi + PAGE_SIZE_4K;
243    uintptr_t end = cur + bi->extraLen;
244    while (cur < end) {
245        seL4_BootInfoHeader *header = (seL4_BootInfoHeader *)cur;
246        if (header->id == type) {
247            ssize_t copy_len = MIN(header->len, max_len);
248            memcpy(dest, (void *)cur, copy_len);
249            return copy_len;
250        }
251        cur += header->len;
252    }
253    return -1;
254}
255
256void simple_default_init_bootinfo(simple_t *simple, seL4_BootInfo *bi)
257{
258    assert(simple);
259    assert(bi);
260
261    simple->data = bi;
262    simple->frame_info = &simple_default_get_frame_info;
263    simple->frame_cap = &simple_default_get_frame_cap;
264    simple->frame_mapping = &simple_default_get_frame_mapping;
265    simple->ASID_assign = &simple_default_set_ASID;
266    simple->cap_count = &simple_default_cap_count;
267    simple->nth_cap = &simple_default_nth_cap;
268    simple->init_cap = &simple_default_init_cap;
269    simple->cnode_size = &simple_default_cnode_size;
270    simple->untyped_count = &simple_default_untyped_count;
271    simple->nth_untyped = &simple_default_nth_untyped;
272    simple->userimage_count = &simple_default_userimage_count;
273    simple->core_count = &simple_default_core_count;
274    simple->nth_userimage = &simple_default_nth_userimage;
275    simple->print = &simple_default_print;
276    simple->sched_ctrl = &simple_default_sched_control;
277    simple->extended_bootinfo_len = &simple_default_get_extended_bootinfo_size;
278    simple->extended_bootinfo = &simple_default_get_extended_bootinfo;
279    simple_default_init_arch_simple(&simple->arch_simple, NULL);
280}
281