enum ia_css_err ia_css_frame_allocate_with_buffer_size( struct ia_css_frame **frame, const unsigned int buffer_size_bytes, const bool contiguous) { /* AM: Body coppied from frame_allocate_with_data(). */ enum ia_css_err err; struct ia_css_frame *me = frame_create(0, 0, IA_CSS_FRAME_FORMAT_NUM,/* Not valid format yet */ 0, 0, contiguous, false); if (me == NULL) return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; /* Get the data size */ me->data_bytes = buffer_size_bytes; err = frame_allocate_buffer_data(me); if (err != IA_CSS_SUCCESS) { sh_css_free(me); return err; } *frame = me; return err; }
static struct resizor * resizor_create(struct display *display) { struct resizor *resizor; resizor = malloc(sizeof *resizor); if (resizor == NULL) return resizor; memset(resizor, 0, sizeof *resizor); resizor->window = window_create(display); resizor->widget = frame_create(resizor->window, resizor); window_set_title(resizor->window, "Wayland Resizor"); resizor->display = display; window_set_key_handler(resizor->window, key_handler); window_set_user_data(resizor->window, resizor); widget_set_redraw_handler(resizor->widget, redraw_handler); window_set_keyboard_focus_handler(resizor->window, keyboard_focus_handler); widget_set_button_handler(resizor->widget, button_handler); resizor->height.previous = 400; resizor->height.current = 400; resizor->height.target = 400; resizor->width.previous = 400; resizor->width.current = 400; resizor->width.target = 400; widget_schedule_resize(resizor->widget, 400, 400); return resizor; }
static enum ia_css_err frame_allocate_with_data(struct ia_css_frame **frame, unsigned int width, unsigned int height, enum ia_css_frame_format format, unsigned int padded_width, unsigned int raw_bit_depth, bool contiguous) { enum ia_css_err err; struct ia_css_frame *me = frame_create(width, height, format, padded_width, raw_bit_depth, contiguous, true); if (me == NULL) return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; err = ia_css_frame_init_planes(me); if (err == IA_CSS_SUCCESS) err = frame_allocate_buffer_data(me); if (err != IA_CSS_SUCCESS) { sh_css_free(me); return err; } *frame = me; return err; }
static struct clickdot * clickdot_create(struct display *display) { struct clickdot *clickdot; clickdot = xzalloc(sizeof *clickdot); clickdot->window = window_create(display); clickdot->widget = frame_create(clickdot->window, clickdot); window_set_title(clickdot->window, "Wayland ClickDot"); clickdot->display = display; clickdot->buffer = NULL; window_set_key_handler(clickdot->window, key_handler); window_set_user_data(clickdot->window, clickdot); window_set_keyboard_focus_handler(clickdot->window, keyboard_focus_handler); widget_set_redraw_handler(clickdot->widget, redraw_handler); widget_set_button_handler(clickdot->widget, button_handler); widget_set_motion_handler(clickdot->widget, motion_handler); widget_set_resize_handler(clickdot->widget, resize_handler); widget_set_leave_handler(clickdot->widget, leave_handler); widget_schedule_resize(clickdot->widget, 500, 400); clickdot->dot.x = 250; clickdot->dot.y = 200; clickdot->line.x = -1; clickdot->line.y = -1; clickdot->line.old_x = -1; clickdot->line.old_y = -1; clickdot->reset = 0; return clickdot; }
int main(int argc, char *argv[]) { struct editor editor; editor.display = display_create(argc, argv); if (editor.display == NULL) { fprintf(stderr, "failed to create display: %m\n"); return -1; } wl_display_add_global_listener(display_get_display(editor.display), global_handler, &editor); editor.window = window_create(editor.display); editor.widget = frame_create(editor.window, &editor); editor.entry = text_entry_create(&editor, "Entry"); editor.editor = text_entry_create(&editor, "Editor"); window_set_title(editor.window, "Text Editor"); widget_set_redraw_handler(editor.widget, redraw_handler); widget_set_resize_handler(editor.widget, resize_handler); widget_set_button_handler(editor.widget, button_handler); window_schedule_resize(editor.window, 500, 400); display_run(editor.display); text_entry_destroy(editor.entry); text_entry_destroy(editor.editor); return 0; }
static struct view * view_create(struct display *display, uint32_t key, const char *filename, int fullscreen, int *view_counter) { struct view *view; gchar *basename; gchar *title; GFile *file = NULL; GError *error = NULL; view = malloc(sizeof *view); if (view == NULL) return view; memset(view, 0, sizeof *view); file = g_file_new_for_commandline_arg(filename); basename = g_file_get_basename(file); if(!basename) { title = g_strdup("Wayland View"); } else { title = g_strdup_printf("Wayland View - %s", basename); g_free(basename); } view->document = poppler_document_new_from_file(g_file_get_uri(file), NULL, &error); if(error) { title = g_strdup("File not found"); } view->window = window_create(display); view->widget = frame_create(view->window, view); window_set_title(view->window, title); g_free(title); view->display = display; window_set_user_data(view->window, view); window_set_key_handler(view->window, key_handler); window_set_keyboard_focus_handler(view->window, keyboard_focus_handler); window_set_fullscreen_handler(view->window, fullscreen_handler); window_set_close_handler(view->window, close_handler); widget_set_button_handler(view->widget, button_handler); widget_set_resize_handler(view->widget, resize_handler); widget_set_redraw_handler(view->widget, redraw_handler); view->page = 0; view->fullscreen = fullscreen; window_set_fullscreen(view->window, view->fullscreen); window_schedule_resize(view->window, 500, 400); view->view_counter = view_counter; *view_counter += 1; return view; }
// FIXME: error handling (not asserts) needed in this function static void mem_allocate_handler(struct mem_binding *b, uint8_t bits, genpaddr_t minbase, genpaddr_t maxlimit) { struct capref *cap = malloc(sizeof(struct capref)); errval_t err, ret; trace_event(TRACE_SUBSYS_MEMSERV, TRACE_EVENT_MEMSERV_ALLOC, bits); /* refill slot allocator if needed */ err = slot_prealloc_refill(mm_ram.slot_alloc_inst); assert(err_is_ok(err)); /* refill slab allocator if needed */ while (slab_freecount(&mm_ram.slabs) <= MINSPARENODES) { struct capref frame; err = msa.a.alloc(&msa.a, &frame); assert(err_is_ok(err)); err = frame_create(frame, BASE_PAGE_SIZE * 8, NULL); assert(err_is_ok(err)); void *buf; err = vspace_map_one_frame(&buf, BASE_PAGE_SIZE * 8, frame, NULL, NULL); if (err_is_fail(err)) { DEBUG_ERR(err, "vspace_map_one_frame failed"); assert(buf); } slab_grow(&mm_ram.slabs, buf, BASE_PAGE_SIZE * 8); } ret = mymm_alloc(cap, bits, minbase, maxlimit); if (err_is_ok(ret)) { mem_avail -= 1UL << bits; } else { // DEBUG_ERR(ret, "allocation of %d bits in % " PRIxGENPADDR "-%" PRIxGENPADDR " failed", // bits, minbase, maxlimit); *cap = NULL_CAP; } /* Reply */ err = b->tx_vtbl.allocate_response(b, MKCONT(allocate_response_done, cap), ret, *cap); if (err_is_fail(err)) { if (err_no(err) == FLOUNDER_ERR_TX_BUSY) { struct pending_reply *r = malloc(sizeof(struct pending_reply)); assert(r != NULL); r->b = b; r->err = ret; r->cap = cap; err = b->register_send(b, get_default_waitset(), MKCONT(retry_reply,r)); assert(err_is_ok(err)); } else { DEBUG_ERR(err, "failed to reply to memory request"); allocate_response_done(cap); } } }
static struct image * image_create(struct display *display, const char *filename, int *image_counter) { struct image *image; char *b, *copy, title[512];; image = malloc(sizeof *image); if (image == NULL) return image; memset(image, 0, sizeof *image); copy = strdup(filename); b = basename(copy); snprintf(title, sizeof title, "Wayland Image - %s", b); free(copy); image->filename = strdup(filename); image->image = load_cairo_surface(filename); if (!image->image) { fprintf(stderr, "could not find the image %s!\n", b); free(image); return NULL; } image->window = window_create(display); image->widget = frame_create(image->window, image); window_set_title(image->window, title); image->display = display; image->image_counter = image_counter; *image_counter += 1; image->initialized = false; window_set_user_data(image->window, image); widget_set_redraw_handler(image->widget, redraw_handler); widget_set_resize_handler(image->widget, resize_handler); window_set_keyboard_focus_handler(image->window, keyboard_focus_handler); window_set_fullscreen_handler(image->window, fullscreen_handler); window_set_close_handler(image->window, close_handler); widget_set_enter_handler(image->widget, enter_handler); widget_set_motion_handler(image->widget, motion_handler); widget_set_button_handler(image->widget, button_handler); widget_set_axis_handler(image->widget, axis_handler); window_set_key_handler(image->window, key_handler); widget_schedule_resize(image->widget, 500, 400); return image; }
int test_01() { FILE* log = stdout; int frame_size = 10; int data_size = (int)1e6; int* data_in = (int*)calloc(data_size, sizeof(int)); int* data_out = NULL; int times = 100; int i = 0; transmitter_t transmitter = transmitter_create(log, frame_size, data_in, data_size); receiver_t receiver = receiver_create(log, frame_size, data_size); transmitter->start(transmitter); receiver->start(receiver); L_Loop: frame_t frame_in = transmitter->transmit_frame(transmitter); if (frame_in == NULL) goto L_Stop; frame_display(frame_in); /* channel emulation */ frame_t frame_out = frame_create(frame_size); frame_out = frame_cpy(frame_out, frame_in); frame_display(frame_out); receiver->receive_frame(receiver, frame_out, frame_in); goto L_Loop; L_Stop: transmitter->stop(transmitter); receiver->stop(receiver); data_out = receiver_get_received_data(receiver); if (cmp_data(data_in, data_out, data_size)) printf("test: OK\n"); else printf("test: FAIL\n"); //print_data(data_in, data_size); //print_data(data_out, data_size); free(data_in); receiver_destroy(receiver); transmitter_destroy(transmitter); return 0; }
errval_t memserv_alloc(struct capref *ret, uint8_t bits, genpaddr_t minbase, genpaddr_t maxlimit) { errval_t err; assert(bits >= MINSIZEBITS); /* refill slot allocator if needed */ err = slot_prealloc_refill(mm_ram.slot_alloc_inst); assert(err_is_ok(err)); /* refill slab allocator if needed */ size_t freecount = slab_freecount(&mm_ram.slabs); while (!refilling && (freecount <= MINSPARENODES)) { refilling = true; struct capref frame; err = msa.a.alloc(&msa.a, &frame); assert(err_is_ok(err)); size_t retsize; err = frame_create(frame, BASE_PAGE_SIZE * 8, &retsize); assert(err_is_ok(err)); assert(retsize % BASE_PAGE_SIZE == 0); assert(retsize >= BASE_PAGE_SIZE); void *buf; err = paging_map_frame(get_current_paging_state(), &buf, retsize, frame, NULL, NULL); if (err_is_fail(err)) { DEBUG_ERR(err, "paging_map_frame failed"); assert(buf); } slab_grow(&mm_ram.slabs, buf, retsize); freecount = slab_freecount(&mm_ram.slabs); } if (freecount > MINSPARENODES) { refilling = false; } if(maxlimit == 0) { err = mm_alloc(&mm_ram, bits, ret, NULL); } else { err = mm_alloc_range(&mm_ram, bits, minbase, maxlimit, ret, NULL); } if (err_is_fail(err)) { debug_printf("in mem_serv:mymm_alloc(bits=%"PRIu8", minbase=%"PRIxGENPADDR ", maxlimit=%"PRIxGENPADDR")\n", bits, minbase, maxlimit); DEBUG_ERR(err, "mem_serv:mymm_alloc"); } return err; }
/* create various resources like shrapnells */ void client_game_create() { frame_create(); shrapnells_init(); shine_load(); init_angles(); /* background */ bkgnd = stk_surface_create( SDL_SWSURFACE, stk_display->w, stk_display->h ); SDL_SetColorKey( bkgnd, 0, 0 ); stk_surface_fill( bkgnd, 0,0,-1,-1, 0x0 ); }
static struct ModeInfo * create_wscreensaver_instance(struct wscreensaver *screensaver, struct wl_output *output, int width, int height) { static int instance; struct ModeInfo *mi; struct rectangle drawarea; mi = calloc(1, sizeof *mi); if (!mi) return NULL; if (demo_mode) mi->window = window_create(screensaver->display); else mi->window = window_create_custom(screensaver->display); if (!mi->window) { fprintf(stderr, "%s: creating a window failed.\n", progname); free(mi); return NULL; } window_set_title(mi->window, progname); if (screensaver->interface && !demo_mode) { mi->widget = window_add_widget(mi->window, mi); screensaver_set_surface(screensaver->interface, window_get_wl_surface(mi->window), output); } else { mi->widget = frame_create(mi->window, mi); } widget_set_redraw_handler(mi->widget, redraw_handler); mi->priv = screensaver; mi->eglctx = EGL_NO_CONTEXT; mi->instance_number = instance++; /* XXX */ widget_get_allocation(mi->widget, &drawarea); mi->width = drawarea.width; mi->height = drawarea.height; screensaver->plugin->init(mi); window_schedule_resize(mi->window, width, height); return mi; }
static struct demoapp * demoapp_create(struct display *display) { struct demoapp *app; app = calloc(1, sizeof *app); if (!app) return NULL; app->egl = egl_state_create(display_get_display(display)); app->display = display; display_set_user_data(app->display, app); app->window = window_create(app->display); app->widget = frame_create(app->window, app); window_set_title(app->window, "Wayland Sub-surface Demo"); window_set_key_handler(app->window, key_handler); window_set_user_data(app->window, app); window_set_keyboard_focus_handler(app->window, keyboard_focus_handler); widget_set_redraw_handler(app->widget, redraw_handler); widget_set_resize_handler(app->widget, resize_handler); app->subsurface = window_add_subsurface(app->window, app, int_to_mode(option_red_mode)); widget_set_redraw_handler(app->subsurface, sub_redraw_handler); widget_set_resize_handler(app->subsurface, sub_resize_handler); if (app->egl && !option_no_triangle) app->triangle = triangle_create(app->window, app->egl); /* minimum size */ widget_schedule_resize(app->widget, 100, 100); /* initial size */ widget_schedule_resize(app->widget, 400, 300); app->animate = 1; return app; }
enum ia_css_err ia_css_frame_create_from_info(struct ia_css_frame **frame, const struct ia_css_frame_info *info) { enum ia_css_err err = IA_CSS_SUCCESS; struct ia_css_frame *me; ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_frame_create_from_info() enter:\n"); if (frame == NULL || info == NULL) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_frame_create_from_info() leave:" " invalid arguments\n"); return IA_CSS_ERR_INVALID_ARGUMENTS; } me = frame_create(info->res.width, info->res.height, info->format, info->padded_width, info->raw_bit_depth, false, false); if (me == NULL) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_frame_create_from_info() leave:" " frame create failed\n"); return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; } err = ia_css_frame_init_planes(me); if (err == IA_CSS_SUCCESS) *frame = me; else sh_css_free(me); ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_frame_create_from_info() leave:\n"); return err; }
int main(int argc, char *argv[]) { struct editor editor; memset(&editor, 0, sizeof editor); editor.display = display_create(argc, argv); if (editor.display == NULL) { fprintf(stderr, "failed to create display: %m\n"); return -1; } display_set_user_data(editor.display, &editor); display_set_global_handler(editor.display, global_handler); editor.window = window_create(editor.display); editor.widget = frame_create(editor.window, &editor); editor.entry = text_entry_create(&editor, "Entry"); editor.editor = text_entry_create(&editor, "Editor"); window_set_title(editor.window, "Text Editor"); window_set_key_handler(editor.window, key_handler); window_set_user_data(editor.window, &editor); widget_set_redraw_handler(editor.widget, redraw_handler); widget_set_resize_handler(editor.widget, resize_handler); widget_set_button_handler(editor.widget, editor_button_handler); window_schedule_resize(editor.window, 500, 400); display_run(editor.display); text_entry_destroy(editor.entry); text_entry_destroy(editor.editor); return 0; }
/** * \brief Create mappings * * \param state The object metadata * \param frame An empty slot to place the frame capability in * \param req_size The required amount by the application * \param retbuf Pointer to return the mapped buffer * \param retsize The actual size returned * * This function will returns a special error code if frame_create * fails due to the constrains to the memory server (amount of memory * or region of memory). This is to facilitate retrying with different * constraints. */ errval_t vspace_mmu_aware_map(struct vspace_mmu_aware *state, size_t req_size, void **retbuf, size_t *retsize) { errval_t err; struct capref frame; // Calculate how much still to map in size_t origsize = req_size; assert(state->mapoffset >= state->offset); if(state->mapoffset - state->offset > req_size) { req_size = 0; } else { req_size -= state->mapoffset - state->offset; } size_t alloc_size = ROUND_UP(req_size, BASE_PAGE_SIZE); size_t ret_size = 0; if (req_size > 0) { #if __x86_64__ if ((state->vregion.flags & VREGION_FLAGS_HUGE) && (state->mapoffset & HUGE_PAGE_MASK) == 0) { // this is an opportunity to switch to 1G pages if requested. // we know that we can use large pages without jumping through hoops // if state->vregion.flags has VREGION_FLAGS_HUGE set and // mapoffset is aligned to at least HUGE_PAGE_SIZE. alloc_size = ROUND_UP(req_size, HUGE_PAGE_SIZE); // goto allocation directly so we can avoid nasty code interaction // between #if __x86_64__ and the size checks, we want to be able // to use 2M pages on x86_64 also. -SG, 2015-04-30. goto allocate; } #endif if ((state->vregion.flags & VREGION_FLAGS_LARGE) && (state->mapoffset & LARGE_PAGE_MASK) == 0) { // this is an opportunity to switch to 2M pages if requested. // we know that we can use large pages without jumping through hoops // if state->vregion.flags has VREGION_FLAGS_LARGE set and // mapoffset is aligned to at least LARGE_PAGE_SIZE. alloc_size = ROUND_UP(req_size, LARGE_PAGE_SIZE); } // Create frame of appropriate size allocate: err = state->slot_alloc->alloc(state->slot_alloc, &frame); if (err_is_fail(err)) { return err_push(err, LIB_ERR_SLOT_ALLOC_NO_SPACE); } err = frame_create(frame, alloc_size, &ret_size); if (err_is_fail(err)) { if (err_no(err) == LIB_ERR_RAM_ALLOC_MS_CONSTRAINTS) { // we can only get 4k frames for now; retry with 4k if (alloc_size > BASE_PAGE_SIZE && req_size <= BASE_PAGE_SIZE) { alloc_size = BASE_PAGE_SIZE; goto allocate; } return err_push(err, LIB_ERR_FRAME_CREATE_MS_CONSTRAINTS); } return err_push(err, LIB_ERR_FRAME_CREATE); } assert(ret_size >= req_size); origsize += ret_size - req_size; req_size = ret_size; if (state->consumed + req_size > state->size) { err = cap_delete(frame); if (err_is_fail(err)) { debug_err(__FILE__, __func__, __LINE__, err, "cap_delete failed"); } state->slot_alloc->free(state->slot_alloc, frame); return LIB_ERR_VSPACE_MMU_AWARE_NO_SPACE; } // Map it in err = state->memobj.m.f.fill(&state->memobj.m, state->mapoffset, frame, req_size); if (err_is_fail(err)) { return err_push(err, LIB_ERR_MEMOBJ_FILL); } err = state->memobj.m.f.pagefault(&state->memobj.m, &state->vregion, state->mapoffset, 0); if (err_is_fail(err)) { return err_push(err, LIB_ERR_MEMOBJ_PAGEFAULT_HANDLER); } } // Return buffer genvaddr_t gvaddr = vregion_get_base_addr(&state->vregion) + state->offset; *retbuf = (void*)vspace_genvaddr_to_lvaddr(gvaddr); *retsize = origsize; state->mapoffset += req_size; state->offset += origsize; state->consumed += origsize; return SYS_ERR_OK; }
static errval_t elf_allocate(void *state, genvaddr_t base, size_t size, uint32_t flags, void **retbase) { errval_t err; struct spawninfo *si = state; // Increase size by space wasted on first page due to page-alignment size_t base_offset = BASE_PAGE_OFFSET(base); size += base_offset; base -= base_offset; // Page-align size = ROUND_UP(size, BASE_PAGE_SIZE); cslot_t vspace_slot = si->elfload_slot; // Allocate the frames size_t sz = 0; for (lpaddr_t offset = 0; offset < size; offset += sz) { sz = 1UL << log2floor(size - offset); struct capref frame = { .cnode = si->segcn, .slot = si->elfload_slot++, }; err = frame_create(frame, sz, NULL); if (err_is_fail(err)) { return err_push(err, LIB_ERR_FRAME_CREATE); } } cslot_t spawn_vspace_slot = si->elfload_slot; cslot_t new_slot_count = si->elfload_slot - vspace_slot; // create copies of the frame capabilities for spawn vspace for (int copy_idx = 0; copy_idx < new_slot_count; copy_idx++) { struct capref frame = { .cnode = si->segcn, .slot = vspace_slot + copy_idx, }; struct capref spawn_frame = { .cnode = si->segcn, .slot = si->elfload_slot++, }; err = cap_copy(spawn_frame, frame); if (err_is_fail(err)) { // TODO: make debug printf printf("cap_copy failed for src_slot = %"PRIuCSLOT", dest_slot = %"PRIuCSLOT"\n", frame.slot, spawn_frame.slot); return err_push(err, LIB_ERR_CAP_COPY); } } /* Map into my vspace */ struct memobj *memobj = malloc(sizeof(struct memobj_anon)); if (!memobj) { return LIB_ERR_MALLOC_FAIL; } struct vregion *vregion = malloc(sizeof(struct vregion)); if (!vregion) { return LIB_ERR_MALLOC_FAIL; } // Create the objects err = memobj_create_anon((struct memobj_anon*)memobj, size, 0); if (err_is_fail(err)) { return err_push(err, LIB_ERR_MEMOBJ_CREATE_ANON); } err = vregion_map(vregion, get_current_vspace(), memobj, 0, size, VREGION_FLAGS_READ_WRITE); if (err_is_fail(err)) { return err_push(err, LIB_ERR_VSPACE_MAP); } for (lvaddr_t offset = 0; offset < size; offset += sz) { sz = 1UL << log2floor(size - offset); struct capref frame = { .cnode = si->segcn, .slot = vspace_slot++, }; genvaddr_t genvaddr = vspace_lvaddr_to_genvaddr(offset); err = memobj->f.fill(memobj, genvaddr, frame, sz); if (err_is_fail(err)) { return err_push(err, LIB_ERR_MEMOBJ_FILL); } err = memobj->f.pagefault(memobj, vregion, offset, 0); if (err_is_fail(err)) { DEBUG_ERR(err, "lib_err_memobj_pagefault_handler"); return err_push(err, LIB_ERR_MEMOBJ_PAGEFAULT_HANDLER); } } /* Map into spawn vspace */ struct memobj *spawn_memobj = NULL; struct vregion *spawn_vregion = NULL; err = spawn_vspace_map_anon_fixed_attr(si, base, size, &spawn_vregion, &spawn_memobj, elf_to_vregion_flags(flags)); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_VSPACE_MAP); } for (lvaddr_t offset = 0; offset < size; offset += sz) { sz = 1UL << log2floor(size - offset); struct capref frame = { .cnode = si->segcn, .slot = spawn_vspace_slot++, }; genvaddr_t genvaddr = vspace_lvaddr_to_genvaddr(offset); err = memobj->f.fill(spawn_memobj, genvaddr, frame, sz); if (err_is_fail(err)) { return err_push(err, LIB_ERR_MEMOBJ_FILL); } err = spawn_memobj->f.pagefault(spawn_memobj, spawn_vregion, offset, 0); if (err_is_fail(err)) { DEBUG_ERR(err, "lib_err_memobj_pagefault_handler"); return err_push(err, LIB_ERR_MEMOBJ_PAGEFAULT_HANDLER); } } genvaddr_t genvaddr = vregion_get_base_addr(vregion) + base_offset; *retbase = (void*)vspace_genvaddr_to_lvaddr(genvaddr); return SYS_ERR_OK; } /** * \brief Load the elf image */ errval_t spawn_arch_load(struct spawninfo *si, lvaddr_t binary, size_t binary_size, genvaddr_t *entry, void** arch_info) { errval_t err; // Reset the elfloader_slot si->elfload_slot = 0; struct capref cnode_cap = { .cnode = si->rootcn, .slot = ROOTCN_SLOT_SEGCN, }; err = cnode_create_raw(cnode_cap, &si->segcn, DEFAULT_CNODE_SLOTS, NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_SEGCN); } // TLS is NYI si->tls_init_base = 0; si->tls_init_len = si->tls_total_len = 0; // Load the binary err = elf_load(EM_HOST, elf_allocate, si, binary, binary_size, entry); if (err_is_fail(err)) { return err; } struct Elf32_Shdr* got_shdr = elf32_find_section_header_name(binary, binary_size, ".got"); if (got_shdr) { *arch_info = (void*)got_shdr->sh_addr; } else { return SPAWN_ERR_LOAD; } return SYS_ERR_OK; } void spawn_arch_set_registers(void *arch_load_info, dispatcher_handle_t handle, arch_registers_state_t *enabled_area, arch_registers_state_t *disabled_area) { assert(arch_load_info != NULL); uintptr_t got_base = (uintptr_t)arch_load_info; struct dispatcher_shared_arm* disp_arm = get_dispatcher_shared_arm(handle); disp_arm->got_base = got_base; enabled_area->regs[REG_OFFSET(PIC_REGISTER)] = got_base; disabled_area->regs[REG_OFFSET(PIC_REGISTER)] = got_base; #ifndef __ARM_ARCH_7M__ //armv7-m does not support these flags enabled_area->named.cpsr = CPSR_F_MASK | ARM_MODE_USR; disabled_area->named.cpsr = CPSR_F_MASK | ARM_MODE_USR; #endif }
static errval_t elf_allocate(void *state, genvaddr_t base, size_t size, uint32_t flags, void **retbase) { errval_t err; lvaddr_t vaddr; size_t used_size; struct spawninfo *si = state; // Increase size by space wasted on first page due to page-alignment size_t base_offset = BASE_PAGE_OFFSET(base); size += base_offset; base -= base_offset; // Page-align size = ROUND_UP(size, BASE_PAGE_SIZE); cslot_t vspace_slot = si->elfload_slot; // Step 1: Allocate the frames size_t sz = 0; for (lpaddr_t offset = 0; offset < size; offset += sz) { sz = 1UL << log2floor(size - offset); struct capref frame = { .cnode = si->segcn, .slot = si->elfload_slot++, }; err = frame_create(frame, sz, NULL); if (err_is_fail(err)) { return err_push(err, LIB_ERR_FRAME_CREATE); } } cslot_t spawn_vspace_slot = si->elfload_slot; cslot_t new_slot_count = si->elfload_slot - vspace_slot; // Step 2: create copies of the frame capabilities for child vspace for (int copy_idx = 0; copy_idx < new_slot_count; copy_idx++) { struct capref frame = { .cnode = si->segcn, .slot = vspace_slot + copy_idx, }; struct capref spawn_frame = { .cnode = si->segcn, .slot = si->elfload_slot++, }; err = cap_copy(spawn_frame, frame); if (err_is_fail(err)) { debug_printf("cap_copy failed for src_slot = %"PRIuCSLOT ", dest_slot = %"PRIuCSLOT"\n", frame.slot, spawn_frame.slot); return err_push(err, LIB_ERR_CAP_COPY); } } // Step 3: map into own vspace // Get virtual address range to hold the module void *vaddr_range; err = paging_alloc(get_current_paging_state(), &vaddr_range, size); if (err_is_fail(err)) { debug_printf("elf_allocate: paging_alloc failed\n"); return (err); } // map allocated physical memory in virutal memory of parent process vaddr = (lvaddr_t)vaddr_range; used_size = size; while (used_size > 0) { struct capref frame = { .cnode = si->segcn, .slot = vspace_slot++, }; // find out the size of the frame struct frame_identity id; err = invoke_frame_identify(frame, &id); assert(err_is_ok(err)); size_t slot_size = (1UL << id.bits); // map frame to provide physical memory backing err = paging_map_fixed_attr(get_current_paging_state(), vaddr, frame, slot_size, VREGION_FLAGS_READ_WRITE); if (err_is_fail(err)) { debug_printf("elf_allocate: paging_map_fixed_attr failed\n"); return err; } used_size -= slot_size; vaddr += slot_size; } // end while: // Step 3: map into new process struct paging_state *cp = si->vspace; // map allocated physical memory in virutal memory of child process vaddr = (lvaddr_t)base; used_size = size; while (used_size > 0) { struct capref frame = { .cnode = si->segcn, .slot = spawn_vspace_slot++, }; // find out the size of the frame struct frame_identity id; err = invoke_frame_identify(frame, &id); assert(err_is_ok(err)); size_t slot_size = (1UL << id.bits); // map frame to provide physical memory backing err = paging_map_fixed_attr(cp, vaddr, frame, slot_size, elf_to_vregion_flags(flags)); if (err_is_fail(err)) { debug_printf("elf_allocate: paging_map_fixed_attr failed\n"); return err; } used_size -= slot_size; vaddr += slot_size; } // end while: *retbase = (void*) vaddr_range + base_offset; return SYS_ERR_OK; } // end function: elf_allocate /** * \brief Load the elf image */ errval_t spawn_arch_load(struct spawninfo *si, lvaddr_t binary, size_t binary_size, genvaddr_t *entry, void** arch_info) { errval_t err; // Reset the elfloader_slot si->elfload_slot = 0; struct capref cnode_cap = { .cnode = si->rootcn, .slot = ROOTCN_SLOT_SEGCN, }; err = cnode_create_raw(cnode_cap, &si->segcn, DEFAULT_CNODE_SLOTS, NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_SEGCN); } // TLS is NYI si->tls_init_base = 0; si->tls_init_len = si->tls_total_len = 0; //debug_printf("spawn_arch_load: about to load elf %p\n", elf_allocate); // Load the binary err = elf_load(EM_HOST, elf_allocate, si, binary, binary_size, entry); if (err_is_fail(err)) { return err; } //debug_printf("hello here\n"); struct Elf32_Shdr* got_shdr = elf32_find_section_header_name(binary, binary_size, ".got"); if (got_shdr) { *arch_info = (void*)got_shdr->sh_addr; } else { return SPAWN_ERR_LOAD; } return SYS_ERR_OK; } void spawn_arch_set_registers(void *arch_load_info, dispatcher_handle_t handle, arch_registers_state_t *enabled_area, arch_registers_state_t *disabled_area) { assert(arch_load_info != NULL); uintptr_t got_base = (uintptr_t)arch_load_info; struct dispatcher_shared_arm* disp_arm = get_dispatcher_shared_arm(handle); disp_arm->got_base = got_base; enabled_area->regs[REG_OFFSET(PIC_REGISTER)] = got_base; enabled_area->named.cpsr = CPSR_F_MASK | ARM_MODE_USR; disabled_area->regs[REG_OFFSET(PIC_REGISTER)] = got_base; disabled_area->named.cpsr = CPSR_F_MASK | ARM_MODE_USR; }
int main( int argc, char *argv[] ){ int ret = 0; signed char option; int i = 0; int lastopt = 0; bool interactive = false; bool load_libs = true; bool set_a_gc_profile = false; unsigned new_gc_profile = 0; stack_frame_t *global_frame; if ( argc < 2 ){ // By default, go into an REPL interactive = true; } else { // otherwise parse options lastopt = 1; for ( i = 1; i < argc && argv[i][0] == '-'; i++ ){ option = argv[i][1]; switch ( option ){ case 'i': interactive = true; break; case 'h': print_help( ); exit( 0 ); break; case 'L': load_libs = false; break; case 'g': { char *profile = argv[++i]; set_a_gc_profile = true; if ( strcmp( profile, "fast" ) == 0 ){ new_gc_profile = GC_PROFILE_FAST; } else if ( strcmp( profile, "balanced" ) == 0 ){ new_gc_profile = GC_PROFILE_BALANCED; } else if ( strcmp( profile, "lowmem" ) == 0 ){ new_gc_profile = GC_PROFILE_LOWMEM; } else { printf( "Unknown garbage collector profile \"%s\", " "using \"balanced\" instead...\n", profile ); new_gc_profile = GC_PROFILE_BALANCED; } } case 'v': break; default: print_help( ); exit( 1 ); break; } /* This keeps track of where the argument after the current argument is, in order to find the filenames after option parsing is done. */ lastopt = i + 1; } } // print some info about the interpreter going into a REPL if ( interactive ){ printf( "%s\n", GOJIRA_BUILD_NAME ); } // Initialize the global interpreter state global_frame = frame_create( NULL, NULL, MAKE_ENV ); init_global_frame( global_frame ); if ( set_a_gc_profile ){ gc_set_profile( get_current_gc( global_frame ), new_gc_profile ); } // Load the 'base' library for needed primatives if ( load_libs ){ evaluate_file( global_frame, BASE_LIB ); } make_argument_var( global_frame, lastopt, argc, argv ); if ( lastopt ){ evaluate_file( global_frame, argv[lastopt] ); } // Go into the REPL if the interpreter flag is set if ( interactive ){ read_eval_print( global_frame ); } // Clean up the global frame, and free all tokens left in the token cache gc_collect( get_current_gc( global_frame )); destroy_token_cache( ); return ret; }
void _DbgNewFrame(int l, const char* name) { // Create a new frame and add it as an element on the frames' list frames=linked_list_element_push_front(frames, frame_create(l, name)); }
/** * \brief Setup arguments and environment * * \param argv Command-line arguments, NULL-terminated * \param envp Environment, NULL-terminated */ static errval_t spawn_setup_env(struct spawninfo *si, char *const argv[], char *const envp[]) { errval_t err; // Create frame (actually multiple pages) for arguments si->argspg.cnode = si->taskcn; si->argspg.slot = TASKCN_SLOT_ARGSPAGE; struct capref spawn_argspg = { .cnode = si->taskcn, .slot = TASKCN_SLOT_ARGSPAGE2, }; err = frame_create(si->argspg, ARGS_SIZE, NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_ARGSPG); } err = cap_copy(spawn_argspg, si->argspg); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_ARGSPG); } /* Map in args frame */ genvaddr_t spawn_args_base; err = spawn_vspace_map_one_frame(si, &spawn_args_base, spawn_argspg, ARGS_SIZE); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_MAP_ARGSPG_TO_NEW); } void *argspg; err = vspace_map_one_frame(&argspg, ARGS_SIZE, si->argspg, NULL, NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_MAP_ARGSPG_TO_SELF); } /* Layout of arguments page: * struct spawn_domain_params; // contains pointers to other fields * char buf[]; // NUL-terminated strings for arguments and environment * vspace layout data follows the string data */ struct spawn_domain_params *params = argspg; char *buf = (char *)(params + 1); size_t buflen = ARGS_SIZE - (buf - (char *)argspg); /* Copy command-line arguments */ int i; size_t len; for (i = 0; argv[i] != NULL; i++) { len = strlen(argv[i]) + 1; if (len > buflen) { return SPAWN_ERR_ARGSPG_OVERFLOW; } strcpy(buf, argv[i]); params->argv[i] = buf - (char *)argspg + (char *)(lvaddr_t)spawn_args_base; buf += len; buflen -= len; } assert(i <= MAX_CMDLINE_ARGS); int argc = i; params->argv[i] = NULL; /* Copy environment strings */ for (i = 0; envp[i] != NULL; i++) { len = strlen(envp[i]) + 1; if (len > buflen) { return SPAWN_ERR_ARGSPG_OVERFLOW; } strcpy(buf, envp[i]); params->envp[i] = buf - (char *)argspg + (char *)(lvaddr_t)spawn_args_base; buf += len; buflen -= len; } assert(i <= MAX_ENVIRON_VARS); params->envp[i] = NULL; /* Serialise vspace data */ // XXX: align buf to next word char *vspace_buf = (char *)ROUND_UP((lvaddr_t)buf, sizeof(uintptr_t)); buflen -= vspace_buf - buf; // FIXME: currently just the pmap is serialised err = si->vspace->pmap->f.serialise(si->vspace->pmap, vspace_buf, buflen); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_SERIALISE_VSPACE); } /* Setup environment pointer and vspace pointer */ params->argc = argc; params->vspace_buf = (char *)vspace_buf - (char *)argspg + (char *)(lvaddr_t)spawn_args_base; params->vspace_buf_len = buflen; // Setup TLS data params->tls_init_base = (void *)vspace_genvaddr_to_lvaddr(si->tls_init_base); params->tls_init_len = si->tls_init_len; params->tls_total_len = si->tls_total_len; arch_registers_state_t *enabled_area = dispatcher_get_enabled_save_area(si->handle); registers_set_param(enabled_area, (uintptr_t)spawn_args_base); return SYS_ERR_OK; } /** * Copies caps from inheritcnode into destination cnode, * ignores caps that to not exist. * * \param inheritcn Source cnode * \param inherit_slot Source cnode slot * \param destcn Target cnode * \param destcn_slot Target cnode slot * * \retval SYS_ERR_OK Copy to target was successful or source cap * did not exist. * \retval SPAWN_ERR_COPY_INHERITCN_CAP Error in cap_copy */ static errval_t spawn_setup_inherited_cap(struct cnoderef inheritcn, capaddr_t inherit_slot, struct cnoderef destcn, capaddr_t destcn_slot) { errval_t err; struct capref src; src.cnode = inheritcn; src.slot = inherit_slot;; // Create frame (actually multiple pages) for fds struct capref dest; dest.cnode = destcn; dest.slot = destcn_slot; err = cap_copy(dest, src); if (err_no(err) == SYS_ERR_SOURCE_CAP_LOOKUP) { // there was no fdcap to inherit, continue return SYS_ERR_OK; } else if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_COPY_INHERITCN_CAP); } return SYS_ERR_OK; }
/** * \brief Setup the dispatcher frame */ static errval_t spawn_setup_dispatcher(struct spawninfo *si, coreid_t core_id, const char *name, genvaddr_t entry, void* arch_info) { errval_t err; /* Create dispatcher frame (in taskcn) */ si->dispframe.cnode = si->taskcn; si->dispframe.slot = TASKCN_SLOT_DISPFRAME; struct capref spawn_dispframe = { .cnode = si->taskcn, .slot = TASKCN_SLOT_DISPFRAME2, }; err = frame_create(si->dispframe, (1 << DISPATCHER_FRAME_BITS), NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_DISPATCHER_FRAME); } err = cap_copy(spawn_dispframe, si->dispframe); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_DISPATCHER_FRAME); } /* Map in dispatcher frame */ dispatcher_handle_t handle; err = vspace_map_one_frame((void**)&handle, 1ul << DISPATCHER_FRAME_BITS, si->dispframe, NULL, NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_MAP_DISPATCHER_TO_SELF); } genvaddr_t spawn_dispatcher_base; err = spawn_vspace_map_one_frame(si, &spawn_dispatcher_base, spawn_dispframe, 1UL << DISPATCHER_FRAME_BITS); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_MAP_DISPATCHER_TO_NEW); } /* Set initial state */ // XXX: Confusion address translation about l/gen/addr in entry struct dispatcher_shared_generic *disp = get_dispatcher_shared_generic(handle); struct dispatcher_generic *disp_gen = get_dispatcher_generic(handle); arch_registers_state_t *enabled_area = dispatcher_get_enabled_save_area(handle); arch_registers_state_t *disabled_area = dispatcher_get_disabled_save_area(handle); /* Place core_id */ disp_gen->core_id = core_id; /* place eh information */ disp_gen->eh_frame = si->eh_frame; disp_gen->eh_frame_size = si->eh_frame_size; disp_gen->eh_frame_hdr = si->eh_frame_hdr; disp_gen->eh_frame_hdr_size = si->eh_frame_hdr_size; /* Setup dispatcher and make it runnable */ disp->udisp = spawn_dispatcher_base; disp->disabled = 1; disp->fpu_trap = 1; #ifdef __k1om__ disp->xeon_phi_id = disp_xeon_phi_id(); #endif // Copy the name for debugging const char *copy_name = strrchr(name, '/'); if (copy_name == NULL) { copy_name = name; } else { copy_name++; } strncpy(disp->name, copy_name, DISP_NAME_LEN); spawn_arch_set_registers(arch_info, handle, enabled_area, disabled_area); registers_set_entry(disabled_area, entry); si->handle = handle; return SYS_ERR_OK; } errval_t spawn_map_bootinfo(struct spawninfo *si, genvaddr_t *retvaddr) { errval_t err; struct capref src = { .cnode = cnode_task, .slot = TASKCN_SLOT_BOOTINFO }; struct capref dest = { .cnode = si->taskcn, .slot = TASKCN_SLOT_BOOTINFO }; err = cap_copy(dest, src); if (err_is_fail(err)) { return err_push(err, LIB_ERR_CAP_COPY); } err = spawn_vspace_map_one_frame(si, retvaddr, dest, BOOTINFO_SIZE); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_MAP_BOOTINFO); } return SYS_ERR_OK; } /** * \brief Retrive the commandline args of #name * * The arguments are malloced into a new space so need to be freed after use */ errval_t spawn_get_cmdline_args(struct mem_region *module, char **retargs) { assert(module != NULL && retargs != NULL); /* Get the cmdline args */ const char *args = getopt_module(module); /* Allocate space */ *retargs = malloc(sizeof(char) * strlen(args)); if (!retargs) { return LIB_ERR_MALLOC_FAIL; } /* Copy args */ strcpy(*retargs, args); return SYS_ERR_OK; }
int main(int argc, char *argv[]) { struct editor editor; int i; uint32_t click_to_show = 0; const char *preferred_language = NULL; for (i = 1; i < argc; i++) { if (strcmp("--click-to-show", argv[i]) == 0) click_to_show = 1; else if (strcmp("--preferred-language", argv[i]) == 0) { if (i + 1 < argc) { preferred_language = argv[i + 1]; i++; } } } memset(&editor, 0, sizeof editor); #ifdef HAVE_PANGO g_type_init(); #endif editor.display = display_create(&argc, argv); if (editor.display == NULL) { fprintf(stderr, "failed to create display: %m\n"); return -1; } display_set_user_data(editor.display, &editor); display_set_global_handler(editor.display, global_handler); editor.window = window_create(editor.display); editor.widget = frame_create(editor.window, &editor); editor.entry = text_entry_create(&editor, "Entry"); editor.entry->click_to_show = click_to_show; if (preferred_language) editor.entry->preferred_language = strdup(preferred_language); editor.editor = text_entry_create(&editor, "Numeric"); editor.editor->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER; editor.editor->click_to_show = click_to_show; window_set_title(editor.window, "Text Editor"); window_set_key_handler(editor.window, key_handler); window_set_user_data(editor.window, &editor); widget_set_redraw_handler(editor.widget, redraw_handler); widget_set_resize_handler(editor.widget, resize_handler); widget_set_button_handler(editor.widget, editor_button_handler); window_schedule_resize(editor.window, 500, 400); display_run(editor.display); text_entry_destroy(editor.entry); text_entry_destroy(editor.editor); return 0; }
static struct gears * gears_create(struct display *display) { const int width = 450, height = 500; struct gears *gears; int i; gears = malloc(sizeof *gears); memset(gears, 0, sizeof *gears); gears->d = display; gears->window = window_create(display); gears->widget = frame_create(gears->window, gears); window_set_title(gears->window, "Wayland Gears"); gears->display = display_get_egl_display(gears->d); if (gears->display == NULL) die("failed to create egl display\n"); eglBindAPI(EGL_OPENGL_API); gears->config = display_get_argb_egl_config(gears->d); gears->context = eglCreateContext(gears->display, gears->config, EGL_NO_CONTEXT, NULL); if (gears->context == NULL) die("failed to create context\n"); if (!eglMakeCurrent(gears->display, NULL, NULL, gears->context)) die("failed to make context current\n"); for (i = 0; i < 3; i++) { gears->gear_list[i] = glGenLists(1); glNewList(gears->gear_list[i], GL_COMPILE); make_gear(&gear_templates[i]); glEndList(); } glEnable(GL_NORMALIZE); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 200.0); glMatrixMode(GL_MODELVIEW); glLightfv(GL_LIGHT0, GL_POSITION, light_pos); glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); glClearColor(0, 0, 0, 0.92); window_set_user_data(gears->window, gears); widget_set_resize_handler(gears->widget, resize_handler); widget_set_redraw_handler(gears->widget, redraw_handler); window_set_keyboard_focus_handler(gears->window, keyboard_focus_handler); window_schedule_resize(gears->window, width, height); return gears; }
static errval_t elf_allocate(void *state, genvaddr_t base, size_t size, uint32_t flags, void **retbase) { errval_t err; struct spawninfo *si = state; // Increase size by space wasted on first page due to page-alignment size_t base_offset = BASE_PAGE_OFFSET(base); size += base_offset; base -= base_offset; // Page-align size = ROUND_UP(size, BASE_PAGE_SIZE); cslot_t vspace_slot = si->elfload_slot; // Allocate the frames size_t sz = 0; for (lpaddr_t offset = 0; offset < size; offset += sz) { sz = 1UL << log2floor(size - offset); struct capref frame = { .cnode = si->segcn, .slot = si->elfload_slot++, }; err = frame_create(frame, sz, NULL); if (err_is_fail(err)) { return err_push(err, LIB_ERR_FRAME_CREATE); } } cslot_t spawn_vspace_slot = si->elfload_slot; cslot_t new_slot_count = si->elfload_slot - vspace_slot; // create copies of the frame capabilities for spawn vspace for (int copy_idx = 0; copy_idx < new_slot_count; copy_idx++) { struct capref frame = { .cnode = si->segcn, .slot = vspace_slot + copy_idx, }; struct capref spawn_frame = { .cnode = si->segcn, .slot = si->elfload_slot++, }; err = cap_copy(spawn_frame, frame); if (err_is_fail(err)) { // TODO: make debug printf printf("cap_copy failed for src_slot = %"PRIuCSLOT", dest_slot = %"PRIuCSLOT"\n", frame.slot, spawn_frame.slot); return err_push(err, LIB_ERR_CAP_COPY); } } /* Map into my vspace */ struct memobj *memobj = malloc(sizeof(struct memobj_anon)); if (!memobj) { return LIB_ERR_MALLOC_FAIL; } struct vregion *vregion = malloc(sizeof(struct vregion)); if (!vregion) { return LIB_ERR_MALLOC_FAIL; } // Create the objects err = memobj_create_anon((struct memobj_anon*)memobj, size, 0); if (err_is_fail(err)) { return err_push(err, LIB_ERR_MEMOBJ_CREATE_ANON); } err = vregion_map(vregion, get_current_vspace(), memobj, 0, size, VREGION_FLAGS_READ_WRITE); if (err_is_fail(err)) { return err_push(err, LIB_ERR_VSPACE_MAP); } for (lvaddr_t offset = 0; offset < size; offset += sz) { sz = 1UL << log2floor(size - offset); struct capref frame = { .cnode = si->segcn, .slot = vspace_slot++, }; genvaddr_t genvaddr = vspace_lvaddr_to_genvaddr(offset); err = memobj->f.fill(memobj, genvaddr, frame, sz); if (err_is_fail(err)) { return err_push(err, LIB_ERR_MEMOBJ_FILL); } err = memobj->f.pagefault(memobj, vregion, offset, 0); if (err_is_fail(err)) { DEBUG_ERR(err, "lib_err_memobj_pagefault_handler"); return err_push(err, LIB_ERR_MEMOBJ_PAGEFAULT_HANDLER); } } /* Map into spawn vspace */ struct memobj *spawn_memobj = NULL; struct vregion *spawn_vregion = NULL; err = spawn_vspace_map_anon_fixed_attr(si, base, size, &spawn_vregion, &spawn_memobj, elf_to_vregion_flags(flags)); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_VSPACE_MAP); } for (lvaddr_t offset = 0; offset < size; offset += sz) { sz = 1UL << log2floor(size - offset); struct capref spawn_frame = { .cnode = si->segcn, .slot = spawn_vspace_slot++, }; genvaddr_t genvaddr = vspace_lvaddr_to_genvaddr(offset); err = memobj->f.fill(spawn_memobj, genvaddr, spawn_frame, sz); if (err_is_fail(err)) { return err_push(err, LIB_ERR_MEMOBJ_FILL); } err = spawn_memobj->f.pagefault(spawn_memobj, spawn_vregion, offset, 0); if (err_is_fail(err)) { DEBUG_ERR(err, "lib_err_memobj_pagefault_handler"); return err_push(err, LIB_ERR_MEMOBJ_PAGEFAULT_HANDLER); } } si->vregion[si->vregions] = vregion; si->base[si->vregions++] = base; genvaddr_t genvaddr = vregion_get_base_addr(vregion) + base_offset; *retbase = (void*)vspace_genvaddr_to_lvaddr(genvaddr); return SYS_ERR_OK; } /** * \brief Load the elf image */ errval_t spawn_arch_load(struct spawninfo *si, lvaddr_t binary, size_t binary_size, genvaddr_t *entry, void** arch_load_info) { errval_t err; // Reset the elfloader_slot si->elfload_slot = 0; si->vregions = 0; struct capref cnode_cap = { .cnode = si->rootcn, .slot = ROOTCN_SLOT_SEGCN, }; // XXX: this code assumes that elf_load never needs more than 32 slots for // text frame capabilities. err = cnode_create_raw(cnode_cap, &si->segcn, DEFAULT_CNODE_SLOTS, NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_SEGCN); } // Load the binary si->tls_init_base = 0; si->tls_init_len = si->tls_total_len = 0; err = elf_load_tls(EM_HOST, elf_allocate, si, binary, binary_size, entry, &si->tls_init_base, &si->tls_init_len, &si->tls_total_len); if (err_is_fail(err)) { return err; } return SYS_ERR_OK; } void spawn_arch_set_registers(void *arch_load_info, dispatcher_handle_t handle, arch_registers_state_t *enabled_area, arch_registers_state_t *disabled_area) { #if defined(__x86_64__) /* XXX: 1st argument to _start is the dispatcher pointer * see lib/crt/arch/x86_64/crt0.s */ disabled_area->rdi = get_dispatcher_shared_generic(handle)->udisp; #elif defined(__i386__) /* XXX: 1st argument to _start is the dispatcher pointer * see lib/crt/arch/x86_32/crt0.s */ disabled_area->edi = get_dispatcher_shared_generic(handle)->udisp; #endif }