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#include <rumprun/init_data.h>
13#include <simple/simple.h>
14#include <utils/util.h>
15#include <sel4/helpers.h>
16#include <allocman/utspace/utspace.h>
17#include <rumprun/custom_simple.h>
18
19static int simple_default_cap_count(void *data)
20{
21    assert(data);
22
23    init_data_t * init_data = data;
24
25    return   init_data->free_slots.start;
26}
27
28
29static seL4_CPtr simple_default_init_cap(void *data, seL4_CPtr cap_pos)
30{
31    seL4_CPtr cap = sel4utils_process_init_cap(data, cap_pos);
32    if (cap == seL4_CapNull && cap_pos != seL4_CapNull) {
33        init_data_t *init_data = data;
34
35        switch (cap_pos) {
36        case seL4_CapIRQControl: /* global IRQ controller cap */
37            cap = init_data->irq_control;
38            break;
39        case seL4_CapIOPortControl:
40        /* IO port cap (null cap if not supported)
41           This cap won't be a control cap, but we use the same slot index */
42            cap = init_data->io_port;
43            break;
44        case seL4_CapIOSpace: /* global IO space cap (null cap if no IOMMU support) */
45#ifdef CONFIG_IOMMU
46            cap = init_data->io_space;
47#else
48            ZF_LOGE("This shouldn't be currently supported");
49#endif
50        default:
51            break;
52        }
53    }
54    return cap;
55}
56
57static seL4_CPtr simple_default_sched_control(void *data, int core)
58{
59    ZF_LOGF_IF(data == NULL, "data is NULL");
60    ZF_LOGF_IF(core != 0, "Only supports core of 0");
61
62    return ((init_data_t *)data)->sched_control;
63}
64
65static uint8_t simple_default_cnode_size(void *data)
66{
67    assert(data);
68
69    return ((init_data_t *)data)->cspace_size_bits;
70}
71
72static int simple_default_untyped_count(void *data)
73{
74    assert(data);
75
76    return ((init_data_t *)data)->untypeds.end - ((init_data_t *)data)->untypeds.start;
77}
78
79static seL4_CPtr simple_default_nth_untyped(void *data, int n, size_t *size_bits, uintptr_t *paddr, bool *device)
80{
81    assert(data && size_bits && paddr);
82
83    init_data_t *init_data = data;
84
85    if (n < (init_data->untypeds.end - init_data->untypeds.start)) {
86        if (paddr != NULL) {
87            *paddr = init_data->untyped_list[n].paddr;
88        }
89        if (size_bits != NULL) {
90            *size_bits = init_data->untyped_list[n].size_bits;
91        }
92        if (device != NULL) {
93            uint8_t custom_device = init_data->untyped_list[n].is_device;
94            *device = custom_device == ALLOCMAN_UT_KERNEL ? 0 : 1;
95        }
96        return init_data->untypeds.start + (n);
97    }
98
99    return seL4_CapNull;
100}
101
102
103static seL4_CPtr simple_default_nth_cap(void *data, int n)
104{
105    return n;
106}
107
108int custom_simple_vspace_bootstrap_frames(custom_simple_t *custom_simple, vspace_t *vspace, sel4utils_alloc_data_t *alloc_data,
109                                          vka_t *vka)
110{
111    if (custom_simple->camkes) {
112        void *existing_frames_camkes[] = {
113            NULL
114        };
115        return sel4utils_bootstrap_vspace(vspace, alloc_data, simple_get_pd(custom_simple->simple), vka,
116                                          NULL, NULL, existing_frames_camkes);
117
118    }
119    init_data_t *init_data = custom_simple->simple->data;
120    void *existing_frames[init_data->stack_pages + RR_NUMIO + 4];
121    existing_frames[0] = (void *) init_data;
122    existing_frames[1] = ((char *) init_data) + PAGE_SIZE_4K;
123    existing_frames[2] = seL4_GetIPCBuffer();
124    ZF_LOGF_IF(init_data->stack_pages == 0, "No stack");
125    for (int i = 0; i < RR_NUMIO; i++) {
126        existing_frames[i+3] = init_data->stdio[i];
127    }
128
129    int frames_index = 3 + RR_NUMIO;
130    for (int i = 0; i < init_data->stack_pages; i++, frames_index++) {
131        existing_frames[frames_index] = init_data->stack + (i * PAGE_SIZE_4K);
132    }
133    existing_frames[frames_index] = NULL;
134    return sel4utils_bootstrap_vspace(vspace, alloc_data, simple_get_pd(custom_simple->simple), vka,
135                                      NULL, NULL, existing_frames);
136
137}
138
139int custom_get_priority(custom_simple_t *custom_simple)
140{
141    return custom_simple->priority;
142}
143
144const char *custom_get_cmdline(custom_simple_t *custom_simple)
145{
146    return custom_simple->cmdline;
147
148}
149
150
151static init_data_t *
152receive_init_data(seL4_CPtr endpoint)
153{
154    /* wait for a message */
155    seL4_Word badge;
156    seL4_Wait(endpoint, &badge);
157
158    init_data_t *init_data = (init_data_t *) seL4_GetMR(0);
159    ZF_LOGF_IF(init_data->free_slots.start == 0, "Bad init data");
160    ZF_LOGF_IF(init_data->free_slots.end == 0, "Bad init data");
161
162    return init_data;
163}
164
165int custom_get_num_regions(custom_simple_t *custom_simple)
166{
167    if (custom_simple->camkes) {
168        return 0;
169    }
170    init_data_t *init_data = custom_simple->simple->data;
171    int j = 0;
172    for (int i = 0; i < (init_data->untypeds.end - init_data->untypeds.start); i++) {
173        uint8_t custom_device = init_data->untyped_list[i].is_device;
174        if (custom_device == ALLOCMAN_UT_DEV_MEM) {
175            j++;
176        }
177
178    }
179    return j;
180
181}
182
183int custom_get_region_list(custom_simple_t *custom_simple, int num_regions, pmem_region_t *regions)
184{
185    if (custom_simple->camkes) {
186        return 0;
187    }
188    init_data_t *init_data = custom_simple->simple->data;
189    int j = 0;
190    for (int i = 0; i < (init_data->untypeds.end - init_data->untypeds.start); i++) {
191        uint8_t custom_device = init_data->untyped_list[i].is_device;
192        if (custom_device == ALLOCMAN_UT_DEV_MEM) {
193            pmem_region_t region = {
194                .type = PMEM_TYPE_RAM,
195                .base_addr = init_data->untyped_list[i].paddr,
196                .length = BIT(init_data->untyped_list[i].size_bits),
197            };
198            regions[j] = region;
199            j++;
200            if (j == num_regions) {
201                return j;
202            }
203        }
204
205    }
206    return j;
207}
208
209static int simple_default_core_count(void *data) {
210    ZF_LOGF_IF(data == NULL, "Data is NULL");
211    /* Currently only support one core */
212    return 1;
213}
214
215void simple_init_rumprun(custom_simple_t *custom_simple, seL4_CPtr endpoint)
216{
217    init_data_t *init_data = receive_init_data(endpoint);
218    ZF_LOGF_IF(init_data == NULL, "Failed to allocate init data");
219
220    simple_t *simple = custom_simple->simple;
221    custom_simple->camkes = false;
222    custom_simple->cmdline = init_data->cmdline;
223    custom_simple->priority = init_data->priority;
224    custom_simple->rumprun_memory_size = init_data->rumprun_memory_size;
225    custom_simple->timer_config.timer_ntfn = init_data->timer_signal;
226    custom_simple->timer_config.timer = TIMER_LTIMER;
227    custom_simple->timer_config.tsc_freq = init_data->tsc_freq;
228    custom_simple->serial_config.serial = SERIAL_SERVER;
229    custom_simple->rpc_ep = init_data->rpc_ep;
230    custom_simple->serial_config.ep = init_data->serial_ep;
231    for (int i = 0; i < 3; i++) {
232        custom_simple->stdio_buf[i] = init_data->stdio[i];
233        custom_simple->stdio_ep[i] = init_data->stdio_eps[i];
234    }
235    custom_simple->get_char_handler = NULL;
236    simple->data = init_data;
237    simple->cap_count = &simple_default_cap_count;
238    simple->init_cap = &simple_default_init_cap;
239    simple->cnode_size = &simple_default_cnode_size;
240    simple->untyped_count = &simple_default_untyped_count;
241    simple->nth_untyped = &simple_default_nth_untyped;
242    simple->nth_cap = &simple_default_nth_cap;
243    simple->sched_ctrl = &simple_default_sched_control;
244    simple->core_count = &simple_default_core_count;
245    arch_init_simple(simple);
246}
247