void load_segment_into_vspace_cb_continue(int pid ,seL4_CPtr reply_cap ,load_segment_args *args ,int err ) { if (TMP_DEBUG) printf("load_segment_into_vspace_cb_continue\n"); // Get the arguments we use if (err) { eprintf("Error caught in load_segment_into_vspace_cb_continue\n"); args->cb(pid, reply_cap, args->cb_args, err); free(args); return; } int index = args->index; seL4_Word vaddr = args->vaddr; unsigned long pos = args->pos; unsigned long file_size = args->file_size; unsigned long dst = args->dst; char *src = args->src; // Calculate nuber of bytes left to right int nbytes = PAGESIZE - (dst & PAGEMASK); // Might not be copying to start of page, so add offset from user ptr vaddr = vaddr + (dst & OFST_MASK); if (pos < file_size){ memcpy((void*)vaddr, (void*)src, MIN(nbytes, file_size - args->pos)); } seL4_ARM_Page_Unify_Instruction(frametable[index].mapping_cap, 0, PAGESIZE); args->pos += nbytes; args->dst += nbytes; args->src += nbytes; load_segment_into_vspace(pid, reply_cap, args, err); if (TMP_DEBUG) printf("load_segment_into_vspace_cb_continue end\n"); }
static void _sos_VMFaultHandler_reply(void* token, int err){ dprintf(3, "sos_vmf_reply called\n"); VMF_cont_t *cont= (VMF_cont_t*)token; if(err){ dprintf(3, "sos_vmf received an err\n"); } if (!is_proc_alive(cont->pid)) { cspace_free_slot(cur_cspace, cont->reply_cap); free(cont); return; } /* Flush the i-cache. Ideally, this should only be done when faulting on text segment */ //if (cont->is_code) { if (!err) { seL4_Word vpage = PAGE_ALIGN(cont->vaddr); int x = PT_L1_INDEX(vpage); int y = PT_L2_INDEX(vpage); seL4_Word kvaddr = (cont->as->as_pd_regs[x][y] & PTE_KVADDR_MASK); seL4_CPtr kframe_cap; err = frame_get_cap(kvaddr, &kframe_cap); //assert(!err); // This kvaddr is ready to use, there should be no error seL4_ARM_Page_Unify_Instruction(kframe_cap, 0, PAGESIZE); } //} /* If there is an err here, it is not the process's fault * It is either the kernel running out of memory or swapping doesn't work */ seL4_MessageInfo_t reply = seL4_MessageInfo_new(0, 0, 0, 0); seL4_Send(cont->reply_cap, reply); cspace_free_slot(cur_cspace, cont->reply_cap); free(cont); set_cur_proc(PROC_NULL); }
// Callback for SOS page directory setup void pd_init_cb(int pid, seL4_CPtr reply_cap, frame_alloc_args *args, int err) { if (SOS_DEBUG) printf("pd_init_cb\n"); // Get the return values from the frame_alloc call vm_init_args *vm_args = (vm_init_args *) args->cb_args; int index = args->index; seL4_Word vaddr = args->vaddr; if (index == FRAMETABLE_ERR || err) { eprintf("Error caught in pd_init_cb\n"); vm_args->cb(pid, reply_cap, vm_args->cb_args, -1); free(args); free(vm_args); return; } // Set up args for callback vm_args->curr_page = 0; // Free args from frame_alloc cal free(args); // Set the page directory to the newly allocated page proc_table[pid]->page_directory = (seL4_Word**) vaddr; memset((void *)vaddr, 0, PAGE_SIZE); if (frametable[index].mapping_cap) { seL4_ARM_Page_Unify_Instruction(frametable[index].mapping_cap, 0, PAGESIZE); } if (TMP_DEBUG) printf("pd addr %p\n", proc_table[pid]->page_directory[0]); // Make sure the page directory isn't swapped out printf("Setting index %p to don't swap\n", (void *) index); frametable[index].frame_status |= FRAME_DONT_SWAP; // Continue initialisation pd_caps_init(pid, reply_cap, vm_args); if (SOS_DEBUG) printf("pd_init_cb ended\n"); }
static int test_large_page_flush_operation(env_t env) { int num_frame_types = ARRAY_SIZE(frame_types); seL4_CPtr frames[num_frame_types]; int error; vka_t *vka = &env->vka; bool pt_mapped = false; /* Grab some free vspace big enough to hold all the tests. */ seL4_Word vstart; reservation_t reserve = vspace_reserve_range(&env->vspace, 2 * (1 << 25), seL4_AllRights, 1, (void **) &vstart); test_assert(reserve.res != 0); vstart = ALIGN_UP(vstart, (1 << 25)); /* Create us some frames to play with. */ for (int i = 0; i < num_frame_types; i++) { frames[i] = vka_alloc_frame_leaky(vka, CTZ(frame_types[i].size)); assert(frames[i]); } /* Also create a pagetable to map the pages into. */ seL4_CPtr pt = vka_alloc_page_table_leaky(vka); /* Map the pages in. */ for (int i = 0; i < num_frame_types; i++) { if (frame_types[i].need_pt && !pt_mapped) { /* Map the pagetable in. */ error = seL4_ARCH_PageTable_Map(pt, env->page_directory, vstart + frame_types[i].vaddr_offset, seL4_ARCH_Default_VMAttributes); test_assert(error == 0); pt_mapped = true; } error = seL4_ARCH_Page_Map(frames[i], env->page_directory, vstart + frame_types[i].vaddr_offset, seL4_AllRights, seL4_ARCH_Default_VMAttributes); test_assert(error == 0); } /* See if we can invoke page flush on each of them */ for (int i = 0; i < num_frame_types; i++) { error = seL4_ARM_Page_Invalidate_Data(frames[i], 0, frame_types[i].size); test_assert(error == 0); error = seL4_ARM_Page_Clean_Data(frames[i], 0, frame_types[i].size); test_assert(error == 0); error = seL4_ARM_Page_CleanInvalidate_Data(frames[i], 0, frame_types[i].size); test_assert(error == 0); error = seL4_ARM_Page_Unify_Instruction(frames[i], 0, frame_types[i].size); test_assert(error == 0); error = seL4_ARM_PageDirectory_Invalidate_Data(env->page_directory, vstart + frame_types[i].vaddr_offset, vstart + frame_types[i].vaddr_offset + frame_types[i].size); test_assert(error == 0); error = seL4_ARM_PageDirectory_Clean_Data(env->page_directory, vstart + frame_types[i].vaddr_offset, vstart + frame_types[i].vaddr_offset + frame_types[i].size); test_assert(error == 0); error = seL4_ARM_PageDirectory_CleanInvalidate_Data(env->page_directory, vstart + frame_types[i].vaddr_offset, vstart + frame_types[i].vaddr_offset + frame_types[i].size); test_assert(error == 0); error = seL4_ARM_PageDirectory_Unify_Instruction(env->page_directory, vstart + frame_types[i].vaddr_offset, vstart + frame_types[i].vaddr_offset + frame_types[i].size); test_assert(error == 0); } return sel4test_get_result(); }
int map_if_valid(seL4_Word vaddr, int pid, callback_ptr cb, void* args, seL4_CPtr reply_cap) { if (SOS_DEBUG) printf("map_if_valid: %p, pid = %d\n", (void * ) vaddr, pid); int dir_index = PT_TOP(vaddr); int page_index = PT_BOTTOM(vaddr); printf("pd addr = %p\n", proc_table[pid]->page_directory); if (proc_table[pid]->page_directory == NULL) { //assert(0); //cb(pid, reply_cap, args, -1); eprintf("Error caught in map_if_valid\n"); return -1; } if (proc_table[pid]->page_directory[dir_index] != NULL) { int index = proc_table[pid]->page_directory[dir_index][page_index]; if (index & SWAPPED) { if (SOS_DEBUG) printf("page was swapped\n"); read_swap_args *swap_args = malloc(sizeof(read_swap_args)); if (swap_args == NULL) { eprintf("Error caught in map_if_valid\n"); return -1; } swap_args->cb = cb; swap_args->cb_args = args; swap_args->vaddr = vaddr; swap_args->pid = pid = pid; swap_args->reply_cap = reply_cap; read_from_swap_slot(pid, reply_cap, swap_args); return 0; } else if (index != 0 && frametable[index].vaddr == vaddr && frametable[index].frame_status & FRAME_SWAP_MARKED) { // Was temporarily unmapped by clock algo, just map back in if (SOS_DEBUG) printf("unmapped by clock, map back in\n"); seL4_CPtr cap = cspace_copy_cap(cur_cspace ,cur_cspace ,frametable[index].frame_cap ,seL4_AllRights ); int err = map_page_user(cap, proc_table[pid]->vroot, vaddr, seL4_AllRights, seL4_ARM_Default_VMAttributes, proc_table[pid]); if (err) { eprintf("Error caught in map_if_valid\n"); return -1; } frametable[index].frame_status &= ~FRAME_SWAP_MARKED; seL4_ARM_Page_Unify_Instruction(cap, 0, PAGESIZE); frametable[index].mapping_cap = cap; if (cb != NULL) { cb(pid, reply_cap, args, 0); return 0; } } else if (index != 0) { if (SOS_DEBUG) printf("page should be mapped in\n"); if (cb != NULL) { cb(pid, reply_cap, args, 0); return 0; } } } return map_new_frame(vaddr, pid, cb, args, reply_cap); }
void sos_map_page_cb(int pid, seL4_CPtr reply_cap, void *args, int err) { // Get arguments we need sos_map_page_args *map_args = (sos_map_page_args *) args; int index = map_args->ft_index; if (err || index == FRAMETABLE_ERR) { eprintf("Error caught in sos_map_page_cb\n"); map_args->cb(pid, reply_cap, map_args->cb_args, -1); free(args); return; } addr_space *as = proc_table[pid]; seL4_ARM_PageDirectory pd = as->vroot; seL4_Word vaddr = map_args->vaddr; if (SOS_DEBUG) printf("sos_map_page_cb at %p\n", (void *) map_args->vaddr); seL4_Word dir_index = PT_TOP(vaddr); seL4_Word page_index = PT_BOTTOM(vaddr); assert(as->page_directory[dir_index] != NULL); if (SOS_DEBUG) printf("dir_index %d, page_index %d\n", dir_index, page_index); if ((as->page_directory[dir_index][page_index] & SWAPPED) == SWAPPED) { printf("Page was swapped out from under us: %p, pid: %d, value %p\n", (void *) vaddr, pid, (void *) as->page_directory[dir_index][page_index]); assert(0); } else { as->page_directory[dir_index][page_index] = index; // Map into the given process page directory // if (!frametable[index].mapping_cap) { seL4_CPtr cap = cspace_copy_cap(cur_cspace ,cur_cspace ,frametable[index].frame_cap ,seL4_AllRights ); err = map_page_user(cap, pd, vaddr, seL4_AllRights, seL4_ARM_Default_VMAttributes, as); if (err) { eprintf("Error caught in sos_map_page_cb\n"); map_args->cb(pid, reply_cap, map_args->cb_args, -1); free(args); return; } seL4_ARM_Page_Unify_Instruction(cap, 0, PAGESIZE); frametable[index].mapping_cap = cap; if (SOS_DEBUG) printf("setting mapping cap: %d\n", cap); frametable[map_args->ft_index].vaddr = map_args->vaddr; } } seL4_ARM_Page_Unify_Instruction(frametable[index].mapping_cap, 0, PAGESIZE); if (map_args->cb != NULL) { map_args->cb(pid, reply_cap, map_args->cb_args, 0); free(map_args); } if (SOS_DEBUG) printf("sos_map_page_cb ended\n"); }