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