void *MemoryPool::get_page(size_t bytes) { if(bytes > max_alloc) { char_t *result = allocate_page(bytes); assert(result); pages.push_back(result); return result; } pages.push_back(current_page); char_t *result = allocate_page(); assert(result); current_page = result; current = result + bytes; max = result + max_alloc; return result; }
void kmain(struct multiboot_info *mbt) { vga_init(); gdt_install(); idt_install(); isr_install(); irq_install(); syscalls_install(); puts_c(__kernel_name " kernel v" __kernel_version_str "\n\n", COLOR_LIGHT_BLUE, COLOR_DEFAULT_BG); uint64_t mem; get_multiboot_info(mbt, &mem); extern uint32_t _kernel_memory_end[]; kprintf("End of kernel's memory: 0x%x\n", (uint64_t) (uint32_t) _kernel_memory_end); kprintf("Memory:\n%l B\n%l KB\n%l MB\n%l GB\n", mem, mem / 1024, mem / 1024 / 1024, mem / 1024 / 1024 / 1024); init_paging(); map_page(0xFD7FF000, 0x60000, 3); int *p = (int *) 0xFD7FF000; *p = 12; kprintf("*(0x%x) = %i\n", (uint64_t) (uint32_t) p, *p); map_page(0x10000000, 0x60000, 3); int *p2 = (int *) 0x10000000; kprintf("*(0x%x) = %i\n", (uint64_t) (uint32_t) p2, *p2); print_next_available_page(); uint32_t ap = allocate_page(203); map_page(ap, 0x60000, 3); int *p3 = (int *) ap; kprintf("*(0x%x) = %i\n", (uint64_t) ap, *p3); print_next_available_page(); ap = allocate_page(203); kprintf("ap = 0x%x\n", (uint32_t) ap); struct kthread thread; create_kthread(thread_test, &thread); start_kthread(&thread); kprintf("Returned from thread.\n"); _asm_print_test(); return; }
static int test_offer_write(int argc, char *argv[]) { DOMAIN_ID domid; unsigned delay; GRANT_REF gref; void *buffer; UNREFERENCED_PARAMETER(argc); domid = wrap_DOMAIN_ID(atoi(argv[0])); delay = atoi(argv[1]); buffer = allocate_page(); memset(buffer, 0, PAGE_SIZE); printf("buffer at %p\n", buffer); if (!xenops_grant_readwrite(xenops, domid, buffer, &gref)) xs_win_err(1, &xs_render_error_stderr, "performing grant operation"); printf("grant with reference %d\n", xen_GRANT_REF(gref)); if (delay == 0) { while (1) Sleep(INFINITE); } else { Sleep(delay * 1000); if (!xenops_ungrant(xenops, gref)) xs_win_err(1, &xs_render_error_stderr, "revoking grant after %d seconds", delay); } dump_page(buffer); return 0; }
uint64_t *vmap_pde(int pdpe_off,uint64_t* pdpe) { uint64_t pde = allocate_page(); pdpe[pdpe_off] = pde | 7; uint64_t *a = (uint64_t *) (VADDR + pde); return a; }
uint64_t *vmap_pte( int pde_off,uint64_t* pde) { uint64_t pte = allocate_page(); pde[pde_off] = pte | 7; uint64_t *a = (uint64_t *) (VADDR + pte); return a; }
uint64_t *vmap_pdpe( int pml4e_off,uint64_t* vir_pml4e) { uint64_t pdpe = allocate_page(); vir_pml4e[pml4e_off] = pdpe | 7; uint64_t *a = (uint64_t *) (VADDR + pdpe); return a; }
btree_t btree_alloc(const struct btree_def *def) { btree_t bt; if (def->branches < 2 || (def->branches & 1)) { fprintf(stderr, "btree: invalid branch count: %d\n", def->branches); return NULL; } bt = malloc(sizeof(*bt)); if (!bt) { fprintf(stderr, "btree: couldn't allocate tree: %s\n", strerror(errno)); return NULL; } memset(bt, 0, sizeof(*bt)); bt->def = def; bt->slot[0] = -1; bt->root = allocate_page(bt, 0); if (!bt->root) { fprintf(stderr, "btree: couldn't allocate root node: %s\n", strerror(errno)); free(bt); return NULL; } return bt; }
stack::stack() { m_curr_page = 0; m_curr_ptr = 0; m_curr_end_ptr = 0; m_free_pages = 0; allocate_page(0); SASSERT(empty()); }
region::region() { m_curr_page = nullptr; m_curr_ptr = nullptr; m_curr_end_ptr = nullptr; m_free_pages = nullptr; m_mark = nullptr; allocate_page(); }
MemoryPool::MemoryPool() { current = current_page = allocate_page(); assert(current_page); max = current + max_alloc; }
static void allocate_stack(uint64_t stack_top) { int i; for (i = 0; i < INITIAL_STACK_PAGES; i++) allocate_page(stack_top - (i * PAGE_SIZE)); /* XXX unmap page at bottom of stack to protect from overrun */ }
static int test_offer_dup_exit(int argc, char *argv[]) { DOMAIN_ID domid; GRANT_REF gref; void *buffer; STARTUPINFO startInfo; PROCESS_INFORMATION processInfo; HANDLE xenopsHandle; HANDLE xenopsTargetHandle; UNREFERENCED_PARAMETER(argc); domid = wrap_DOMAIN_ID(atoi(argv[0])); buffer = allocate_page(); printf("buffer at %p\n", buffer); if (!xenops_grant_readonly(xenops, domid, buffer, &gref)) xs_win_err(1, &xs_render_error_stderr, "performing grant operation"); printf("grant with reference %d\n", xen_GRANT_REF(gref)); memset(&startInfo, 0, sizeof(startInfo)); startInfo.cb = sizeof(startInfo); if (!CreateProcessA("xenops_test.exe", "xenops_test.exe /offer_dup_child", NULL, NULL, FALSE, 0, NULL, NULL, &startInfo, &processInfo)) xs_win_err(1, &xs_render_error_stderr, "starting child process"); CloseHandle(processInfo.hThread); xenopsHandle = *((HANDLE *)xenops); printf("xenops handle %p\n", xenopsHandle); if (!DuplicateHandle(GetCurrentProcess(), xenopsHandle, processInfo.hProcess, &xenopsTargetHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) xs_win_err(1, &xs_render_error_stderr, "transfering handle"); printf("Duplicated to %p\n", xenopsTargetHandle); Sleep(1000); printf("Parent exiting.\n"); return 0; }
// Randomly choose a set of input values. The set will consist of the specified number of non-pointers and pointers. The // non-pointer values are chosen randomly, but limited to a certain range. The pointers are chosen randomly to be null or // non-null and the non-null values each have one page allocated via simulated mmap() (i.e., the non-null values themselves // are not actually random). InputValues choose_inputs(size_t nintegers, size_t npointers) { static unsigned integer_modulus = 256; // arbitrary; static unsigned nonnull_denom = 3; // probability of a non-null pointer is 1/N CloneDetection::InputValues inputs; for (size_t i=0; i<nintegers; ++i) inputs.add_integer(rand() % integer_modulus); for (size_t i=0; i<npointers; ++i) inputs.add_pointer(rand()%nonnull_denom ? 0 : allocate_page()); return inputs; }
inline void stack::store_mark(void * ptr, bool external) { SASSERT(m_curr_ptr < m_curr_end_ptr || m_curr_ptr == m_curr_end_ptr); // mem is aligned if (m_curr_ptr + sizeof(size_t) > m_curr_end_ptr) { SASSERT(m_curr_ptr == m_curr_end_ptr); // doesn't fit in the current page allocate_page(ptr2mark(ptr, external)); } else { store_mark(ptr2mark(ptr, external)); } }
void sighandler(int signo) { signal_number = signo; if(signo == SIGUSR1) { allocate_page(); } else if(signo == SIGUSR2) { dump_pt(); } else if(signo == SIGINT) { cleanup(); exit(EXIT_SUCCESS); } }
/* * Allocate a memory page and return its physical address. * * Parameters: * - uiFlags = Flags for page allocation. * - tag = Tag to give the newly-allocated page. * - subtag = Subtag to give the newly-allocated page. * - ppaNewPage = Pointer to location that will receive the physical address of the new page. * * Returns: * Standard HRESULT success/failure indication. */ HRESULT MmAllocatePage(UINT32 uiFlags, UINT32 tag, UINT32 subtag, PPHYSADDR ppaNewPage) { register UINT32 ndxPage; /* index of page to be allocated */ if (!ppaNewPage) return E_POINTER; ndxPage = allocate_page(uiFlags); if (ndxPage == INVALID_PAGE) return E_OUTOFMEMORY; g_pMasterPageDB[ndxPage].d.tag = tag; g_pMasterPageDB[ndxPage].d.subtag = subtag; *ppaNewPage = mmPageIndex2PA(ndxPage); return S_OK; }
void sighandler(int signo) { signal_number = signo; switch(signo) { case SIGUSR1: allocate_page(); break; case SIGUSR2: dump_pt(); break; case SIGINT: cleanup(); exit(EXIT_SUCCESS); default: break;// nop } }
int setupt_proc_vm(ProcStruct* NewProc) { PageStruct* pa=allocate_page(); if(!pa) return 0; NewProc->pml4e=(uint64_t*)KADDR(pageToPhysicalAddress(pa)); //printf("userpml4=%p",NewProc->pml4e); NewProc->cr3 = (physaddr_t*)PADDR(NewProc->pml4e); /* CHANGE THIS LATER. SET extries at indexes less than UTOP to 0 */ NewProc->pml4e[PML4(PHYSBASE)]=boot_pml4e[PML4(PHYSBASE)]; NewProc->pml4e[PML4(VIDEO_START)]=boot_pml4e[PML4(VIDEO_START)]; return 1; }
/* for malloc */ void *sbrk(intptr_t increment) { uint64_t ret; int i; if ( increment == 0 ) return (void *)heap_top; assert(increment >= PAGE_SIZE); assert((increment % PAGE_SIZE) == 0); for ( i = 0; i < increment; i += PAGE_SIZE ) allocate_page(heap_top + i); ret = heap_top; heap_top += increment; return (void *)ret; }
int _start(char *boot_args, char *monitor) { unsigned int bootdir_pages; memset(&ka, 0, sizeof(ka)); init_nextmon(monitor); dprintf("\nNewOS stage2: args '%s', monitor %p\n", boot_args, monitor); probe_memory(&ka); dprintf("tc 0x%x\n", get_tc()); dprintf("urp 0x%x\n", get_urp()); dprintf("srp 0x%x\n", get_srp()); // calculate how big the bootdir is { int entry; bootdir_pages = 0; for (entry = 0; entry < BOOTDIR_MAX_ENTRIES; entry++) { if (bootdir[entry].be_type == BE_TYPE_NONE) break; bootdir_pages += bootdir[entry].be_size; } ka.bootdir_addr.start = (unsigned long)bootdir; ka.bootdir_addr.size = bootdir_pages * PAGE_SIZE; dprintf("bootdir: start %p, size 0x%x\n", (char *)ka.bootdir_addr.start, ka.bootdir_addr.size); } // begin to set up the physical page allocation range data structures ka.num_phys_alloc_ranges = 1; ka.phys_alloc_range[0].start = ka.bootdir_addr.start; ka.phys_alloc_range[0].size = ka.bootdir_addr.size; // allocate a stack for the kernel when we jump into it ka.cpu_kstack[0].start = allocate_page(&ka); ka.cpu_kstack[0].size = PAGE_SIZE; ka.num_cpus = 1; return 0; }
int allocate_proc_area(ProcStruct* p, void* va, uint64_t size) { char* start = (char*)ROUNDDOWN((uint64_t)va, PGSIZE); char* end = (char*)ROUNDUP((char*)va+size, PGSIZE); uint64_t* newpage=0; PageStruct* pa; for(char* i=start; i<end; i+=PGSIZE) { pa = allocate_page(); pa->ref_count++; if(!pa) return -1; newpage = pageToPhysicalAddress(pa); //printf("Mapping..%p to %p",i,newpage); map_vm_pm(p->pml4e, (uint64_t)i,(uint64_t)newpage,PGSIZE,PTE_P |PTE_U|PTE_W); } return (uint64_t)newpage; }
static int test_offer_const(int argc, char *argv[]) { DOMAIN_ID domid; unsigned delay; GRANT_REF gref; void *buffer; unsigned x; UNREFERENCED_PARAMETER(argc); domid = wrap_DOMAIN_ID(atoi(argv[0])); delay = atoi(argv[1]); buffer = allocate_page(); memset(buffer, 0x73, PAGE_SIZE); printf("buffer at %p\n", buffer); if (!xenops_grant_readonly(xenops, domid, buffer, &gref)) xs_win_err(1, &xs_render_error_stderr, "performing grant operation"); printf("grant with reference %d\n", xen_GRANT_REF(gref)); if (delay == 0) { while (1) Sleep(INFINITE); } else { Sleep(delay * 1000); if (!xenops_ungrant(xenops, gref)) xs_win_err(1, &xs_render_error_stderr, "revoking grant after %d seconds", delay); xenops_close(xenops); for (x = 0; x < PAGE_SIZE; x++) { if ( ((unsigned char *)buffer)[x] != 0x73 ) xs_errx(1, &xs_render_error_stderr, "granted page was corrupted: %x changed to %x at %x\n", 0x73, ((unsigned char *)buffer)[x], x); } return 0; } }
/*! \brief Implements POSIX fork(). * * \returns -1 if child, or the child's PID if parent */ int fork (isr_regs * regs) { context_t * new_context, *t; memory_region_t *newr; new_context = (context_t*)allocate_from_slab(context_slab); if (context_list == 0) { context_list = new_context; } else { for (t = context_list; t->next != 0; t = t->next); /*Get to end*/ t->next = new_context; } new_context->next = 0; new_context->pid = next_avail_pid; ++next_avail_pid; memcpy ((void *) &new_context->registers, (void *) regs, sizeof (isr_regs)); new_context->registers.edx = 0; new_context->space = create_address_space (); for (newr = new_context->space->first->next; newr->next != new_context->space->stack; newr = newr->next); newr->next = new_context->space->stack->next; deallocate_from_slab (regions_slab, new_context->space->stack); new_context->status = PROCESS_STATUS_RUNNING; memory_region_t * mr = cur_process->space->first->next; unsigned long addr; while (mr->type != MR_TYPE_SENTINEL) { switch (mr->type) { case MR_TYPE_ANON: case MR_TYPE_CORE: case MR_TYPE_LIBRARY: newr = create_region (new_context->space, mr->virtual_address, mr->length, mr->type, mr->attributes, mr->parameter); map_user_region_to_physical(newr, 0); for (addr = newr->virtual_address; addr < newr->virtual_address + newr->length * PAGE_SIZE; addr += PAGE_SIZE) { void * a = (void * )map_user_virtual_to_kernel (new_context, addr); memcpy (a, (void *) addr, PAGE_SIZE); free_kernel_virtual_page ((unsigned long)a); } break; case MR_TYPE_STACK: newr = create_region (new_context->space, mr->virtual_address, mr->length, mr->type, mr->attributes, mr->parameter); for (addr = newr->virtual_address; addr < newr->virtual_address + newr->length * PAGE_SIZE; addr += PAGE_SIZE) { if (user_address_to_physical (cur_process->space, addr) != 0) { map_user_address (new_context->space->virt_cr3, addr, allocate_page (0) * PAGE_SIZE, 0); void * a = (void * )map_user_virtual_to_kernel (new_context, addr); memcpy (a, (void *) addr, PAGE_SIZE); } } new_context->space->stack = newr; break; case MR_TYPE_IPC: newr = clone_region (new_context->space, mr, 0); kfifo_clone_fifo (newr->parameter, new_context->pid); break; default: break; } kfifo_update_senders (cur_process->pid, new_context->pid); mr = mr->next; } return new_context->pid; }
ssize_t CachingDataSource::read_at(off_t offset, void *data, size_t size) { Mutex::Autolock autoLock(mLock); size_t total = 0; while (size > 0) { Page *page = mFirst; while (page != NULL) { if (page->mOffset >= 0 && offset >= page->mOffset && offset < page->mOffset + (off_t)page->mLength) { break; } page = page->mNext; } if (page == NULL) { page = allocate_page(); page->mOffset = offset - offset % mPageSize; ssize_t n = mSource->read_at(page->mOffset, page->mData, mPageSize); if (n < 0) { page->mLength = 0; } else { page->mLength = (size_t)n; } mFirst->mPrev = page; page->mNext = mFirst; page->mPrev = NULL; mFirst = page; if (n < 0) { return n; } if (offset >= page->mOffset + (off_t)page->mLength) { break; } } else { // Move "page" to the front in LRU order. if (page->mNext != NULL) { page->mNext->mPrev = page->mPrev; } else { mLast = page->mPrev; } if (page->mPrev != NULL) { page->mPrev->mNext = page->mNext; } else { mFirst = page->mNext; } mFirst->mPrev = page; page->mNext = mFirst; page->mPrev = NULL; mFirst = page; } size_t copy = page->mLength - (offset - page->mOffset); if (copy > size) { copy = size; } memcpy(data,(const char *)page->mData + (offset - page->mOffset), copy); total += copy; if (page->mLength < mPageSize) { // This was the final page. There is no more data beyond it. break; } offset += copy; size -= copy; data = (char *)data + copy; } return total; }
uint16_t map_vm_pm(pml4e_t* pml4e, uint64_t va,uint64_t pa,uint64_t size, uint16_t perm) { uint64_t* pdpe,*pde,*pte; //extract the upper 9 bits of VA to get the index into pml4e. for(uint64_t i=0; i<size; i+=PGSIZE) { if((pml4e[PML4(va+i)] & (uint64_t)PTE_P) == 0) { pdpe = pageToPhysicalAddress(allocate_page()); //printf("ret=%p",pdpe); if(physicalAddressToPage(pdpe)) { physicalAddressToPage(pdpe)->ref_count++; pml4e[PML4(va+i)] = (((uint64_t) pdpe) & (~0xFFF))|(perm|PTE_P); } else { printf("Failed in PML4E:%x",pdpe); return -1; } } pdpe = (uint64_t*) (KADDR(pml4e[PML4(va+i)]) & (~0xFFF)); // printf("pdpe retu=%p",pdpe); if((pdpe[PDPE(va+i)] & (uint64_t)PTE_P) == 0) { pde = pageToPhysicalAddress(allocate_page()); // printf("ret=%p",pde); // printf("pde retu=%p",pde); if(pde) { physicalAddressToPage(pde)->ref_count++; pdpe[PDPE(va+i)] = ( (uint64_t)pde & (~0xFFF))|(perm|PTE_P); } else { printf("Failed in PDPE:%x",pde); return -1; } } pde = (uint64_t*)(KADDR(pdpe[PDPE(va+i)]) & ~0xFFF); if((pde[PDX(va+i)] & (uint64_t)PTE_P) == 0) { pte = pageToPhysicalAddress(allocate_page()); // printf("ret=%p",pte); if(pte) { physicalAddressToPage(pte)->ref_count++; pde[PDX(va+i)] =((uint64_t)pte & (~0xFFF))|(perm|PTE_P); } else { printf("Failed in PDE:%x",pte); return -1; } } pte = (uint64_t*)(KADDR(pde[PDX(va+i)]) & ~0xFFF); pte[PTX(va+i)] = ((pa+i) & (~0xFFF))|(perm|PTE_P);; //printf("MAPPED"); tlb_invalidate(pml4e,(void*)va+i); }//for loop end //printf("Mapped Region:%p-%p to %p-%p\n",ROUNDDOWN(va,PGSIZE),ROUNDDOWN(va+size,PGSIZE), ROUNDDOWN(pa,PGSIZE),ROUNDDOWN(pa+size,PGSIZE)); return 0; }
/* Allocate a single block, first allocating an hbin (page) at the end * of the current file if necessary. NB. To keep the implementation * simple and more likely to be correct, we do not reuse existing free * blocks. * * seg_len is the size of the block (this INCLUDES the block header). * The header of the block is initialized to -seg_len (negative to * indicate used). id[2] is the block ID (type), eg. "nk" for nk- * record. The block bitmap is updated to show this block as valid. * The rest of the contents of the block will be zero. * * **NB** Because allocate_block may reallocate the memory, all * pointers into the memory become potentially invalid. I really * love writing in C, can't you tell? * * Returns: * > 0 : offset of new block * 0 : error (errno set) */ static size_t allocate_block (hive_h *h, size_t seg_len, const char id[2]) { CHECK_WRITABLE (0); if (seg_len < 4) { /* The caller probably forgot to include the header. Note that * value lists have no ID field, so seg_len == 4 would be possible * for them, albeit unusual. */ SET_ERRNO (ERANGE, "refusing too small allocation (%zu)", seg_len); return 0; } /* Refuse really large allocations. */ if (seg_len > HIVEX_MAX_ALLOCATION) { SET_ERRNO (ERANGE, "refusing too large allocation (%zu)", seg_len); return 0; } /* Round up allocation to multiple of 8 bytes. All blocks must be * on an 8 byte boundary. */ seg_len = (seg_len + 7) & ~7; /* Allocate a new page if necessary. */ if (h->endblocks == 0 || h->endblocks + seg_len > h->endpages) { size_t newendblocks = allocate_page (h, seg_len); if (newendblocks == 0) return 0; h->endblocks = newendblocks; } size_t offset = h->endblocks; DEBUG (2, "new block at 0x%zx, size %zu", offset, seg_len); struct ntreg_hbin_block *blockhdr = (struct ntreg_hbin_block *) ((char *) h->addr + offset); memset (blockhdr, 0, seg_len); blockhdr->seg_len = htole32 (- (int32_t) seg_len); if (id[0] && id[1] && seg_len >= sizeof (struct ntreg_hbin_block)) { blockhdr->id[0] = id[0]; blockhdr->id[1] = id[1]; } BITMAP_SET (h->bitmap, offset); h->endblocks += seg_len; /* If there is space after the last block in the last page, then we * have to put a dummy free block header here to mark the rest of * the page as free. */ ssize_t rem = h->endpages - h->endblocks; if (rem > 0) { DEBUG (2, "marking remainder of page free" " starting at 0x%zx, size %zd", h->endblocks, rem); assert (rem >= 4); blockhdr = (struct ntreg_hbin_block *) ((char *) h->addr + h->endblocks); blockhdr->seg_len = htole32 ((int32_t) rem); } return offset; }
int btree_put(btree_t bt, const void *key, const void *data) { const struct btree_def *def = bt->def; struct btree_page *new_root = NULL; struct btree_page *path_new[MAX_HEIGHT] = {0}; struct btree_page *path_old[MAX_HEIGHT] = {0}; int slot_old[MAX_HEIGHT] = {0}; int h; check_btree(bt); /* Special case: cursor overwrite */ if (!key) { if (bt->slot[0] < 0) { fprintf(stderr, "btree: put at invalid cursor\n"); return -1; } memcpy(PAGE_DATA(bt->path[0], bt->slot[0]), data, def->data_size); return 1; } /* Find a path down the tree that leads to the page which should * contain this datum (though the page might be too big to hold it). */ if (trace_path(bt, key, path_old, slot_old)) { /* Special case: overwrite existing item */ memcpy(PAGE_DATA(path_old[0], slot_old[0]), data, def->data_size); return 1; } /* Trace from the leaf up. If the leaf is at its maximum size, it will * need to split, and cause a pointer to be added in the parent page * of the same node (which may in turn cause it to split). */ for (h = 0; h <= bt->root->height; h++) { if (path_old[h]->num_children < def->branches) break; path_new[h] = allocate_page(bt, h); if (!path_new[h]) goto fail; } /* If the split reaches the top (i.e. the root splits), then we need * to allocate a new root node. */ if (h > bt->root->height) { if (h >= MAX_HEIGHT) { fprintf(stderr, "btree: maximum height exceeded\n"); goto fail; } new_root = allocate_page(bt, h); if (!new_root) goto fail; } /* Trace up to one page above the split. At each page that needs * splitting, copy the top half of keys into the new page. Also, * insert a key into one of the pages at all pages from the leaf * to the page above the top of the split. */ for (h = 0; h <= bt->root->height; h++) { int s = slot_old[h] + 1; struct btree_page *p = path_old[h]; /* If there's a split at this level, copy the top half of * the keys from the old page to the new one. Check to see * if the position we were going to insert into is in the * old page or the new one. */ if (path_new[h]) { split_page(path_old[h], path_new[h]); if (s > p->num_children) { s -= p->num_children; p = path_new[h]; } } /* Insert the key in the appropriate page */ if (h) insert_ptr(p, s, PAGE_KEY(path_new[h - 1], 0), path_new[h - 1]); else insert_data(p, s, key, data); /* If there was no split at this level, there's nothing to * insert higher up, and we're all done. */ if (!path_new[h]) return 0; } /* If we made it this far, the split reached the top of the tree, and * we need to grow it using the extra page we allocated. */ assert (new_root); if (bt->slot[0] >= 0) { /* Fix up the cursor, if active */ bt->slot[new_root->height] = bt->path[bt->root->height] == new_root ? 1 : 0; bt->path[new_root->height] = new_root; } memcpy(PAGE_KEY(new_root, 0), def->zero, def->key_size); *PAGE_PTR(new_root, 0) = path_old[h - 1]; memcpy(PAGE_KEY(new_root, 1), PAGE_KEY(path_new[h - 1], 0), def->key_size); *PAGE_PTR(new_root, 1) = path_new[h - 1]; new_root->num_children = 2; bt->root = new_root; return 0; fail: for (h = 0; h <= bt->root->height; h++) if (path_new[h]) free(path_new[h]); return -1; }
ProcStruct* allocate_process(unsigned char parentid) { ProcStruct* NewProc=NULL; if((NewProc = getnewprocess())==NULL) return NULL; //printf("New Proc Created"); if(setupt_proc_vm(NewProc)==0) return NULL; // printf("Proc vm set"); NewProc->proc_id = (unsigned char)(NewProc-procs)+1; NewProc->parent_id = parentid; kmemset((void*)&NewProc->tf, 0, sizeof(NewProc->tf)); NewProc->tf.tf_ds =(uint16_t)(U_DS|RPL3); NewProc->tf.tf_es =(uint16_t)(U_DS|RPL3); NewProc->tf.tf_ss = (uint16_t)(U_DS|RPL3); NewProc->tf.tf_rsp = USERSTACKTOP; NewProc->tf.tf_cs = (uint16_t)(U_CS|RPL3); NewProc->tf.tf_eflags = 0x200;//9th bit=IF flag NewProc->status = RUNNABLE; NewProc->waitingfor = -1; NewProc->num_child=0; ((ProcStruct*)(procs+parentid-1))->num_child++; maxcount=proccount++; PageStruct *pa=allocate_page(); NewProc->mm=(mm_struct*)KADDR(pageToPhysicalAddress(pa)); kmemset((void *)(NewProc->mm), 0, sizeof(mm_struct)); //printf("Before copying the fd table to child\n"); //while(1); kstrcpy(NewProc->cwd,"/"); //set the cwd of a new process to root dir. if(parentid==0) { //printf("IN if\n"); NewProc->fd_table[0] = 0; NewProc->fd_table[1] = 1; NewProc->fd_table[2] = 2; for(int x=3;x<50;x++){ NewProc->fd_table[x] = -1; } } else{ //printf("In else\n"); NewProc->fd_table[0] = curproc->fd_table[0]; NewProc->fd_table[1] = curproc->fd_table[1]; NewProc->fd_table[2] = curproc->fd_table[2]; //while(1); for(int i=3;i<50;i++) { // printf("Inside while loop\n"); //while(1); NewProc->fd_table[i] = curproc->fd_table[i]; if(NewProc->fd_table[i]!=-1) { file_table[NewProc->fd_table[i]].ref_count++; } } } //while(1); //printf("After copying the fd table to child\n"); return NewProc; }
Status DB::add_file_entry(const char* fname, PageId start_page_num) { #ifdef DEBUG cout << "Adding a file entry: " << fname << " : " << start_page_num << endl; #endif // Is the info kosher? if ( strlen(fname) >= MAX_NAME ) return MINIBASE_FIRST_ERROR( DBMGR, FILE_NAME_TOO_LONG ); if ((start_page_num < 0) || (start_page_num >= (int) num_pages) ) return MINIBASE_FIRST_ERROR( DBMGR, BAD_PAGE_NO ); // Does the file already exist? PageId tmp; if ( get_file_entry(fname,tmp) == OK ) return MINIBASE_FIRST_ERROR( DBMGR, DUPLICATE_ENTRY ); char *pg = 0; Status status; directory_page* dp = 0; bool found = false; unsigned free_slot = 0; PageId hpid, nexthpid = 0; do { hpid = nexthpid; // Pin the header page. status = MINIBASE_BM->pinPage( hpid, (Page*&)pg ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); // This complication is because the first page has a different // structure from that of subsequent pages. dp = (hpid == 0)? &((first_page*)pg)->dir : (directory_page*)pg; nexthpid = dp->next_page; unsigned entry = 0; while ( (entry < dp->num_entries) && (dp->entries[entry].pagenum != INVALID_PAGE)) ++entry; if ( entry < dp->num_entries ) { free_slot = entry; found = true; } else if ( nexthpid != INVALID_PAGE ) { // We only unpin if we're going to continue looping. status = MINIBASE_BM->unpinPage( hpid ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); } } while ( nexthpid != INVALID_PAGE && !found ); // Have to add a new header page if possible. if ( !found ) { status = allocate_page( nexthpid ); if ( status != OK ) { MINIBASE_BM->unpinPage( hpid ); return status; } // Set the next-page pointer on the previous directory page. dp->next_page = nexthpid; status = MINIBASE_BM->unpinPage( hpid, true /*dirty*/ ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); // Pin the newly-allocated directory page. hpid = nexthpid; status = MINIBASE_BM->pinPage( hpid, (Page*&)pg, true /*empty*/ ); if ( status != OK ) return MINIBASE_CHAIN_ERROR( DBMGR, status ); dp = (directory_page*)pg; init_dir_page( dp, sizeof(directory_page) ); free_slot = 0; } // At this point, "hpid" has the page id of the header page with the free // slot; "pg" points to the pinned page; "dp" has the directory_page // pointer; "free_slot" is the entry number in the directory where we're // going to put the new file entry. dp->entries[free_slot].pagenum = start_page_num; strcpy( dp->entries[free_slot].fname, fname ); status = MINIBASE_BM->unpinPage( hpid, true /*dirty*/ ); if ( status != OK ) status = MINIBASE_CHAIN_ERROR( DBMGR, status ); return status; }
int load_exe(task_struct *task, void *exe_start) { mm_struct *mm = task->mm; /* ELF header */ elfHeader *ehdr = (elfHeader *)exe_start; /* program header */ progHeader *phdr = (progHeader *)((uint64_t)ehdr + ehdr->e_phoff); int count = 0; /* new task entry point */ task->rip = ehdr->e_entry; task->mm->mmap = NULL; for(; count < ehdr->e_phnum; count++) { /* loadable section */ if(phdr->p_type == 1) { vma_struct *vma = (vma_struct *)kmalloc(); if(mm->mmap == NULL) { mm->mmap = vma; } else { mm->current->next = vma; } mm->current = vma; vma->mm = mm; vma->start = phdr->p_vaddr; vma->end = phdr->p_vaddr + phdr->p_memsz; /* copy the exe contents to the binary's virtual address */ uint64_t size = (((vma->end/0x1000)*0x1000 + 0x1000)-((vma->start/0x1000)*0x1000)); uint64_t itr = size/0x1000; uint64_t start = (phdr->p_vaddr/0x1000)*0x1000; while(itr) { uint64_t page = (uint64_t)allocate_page(); map_process(start, page); itr--; start += 0x1000; } vma->flags = phdr->p_flags; vma->file = NULL; vma->next = NULL; vma->type = NOTYPE; if((phdr->p_flags == (PERM_R | PERM_X)) || (phdr->p_flags == (PERM_R | PERM_W))){ task->mm->start_code = phdr->p_vaddr; task->mm->end_code = phdr->p_vaddr + phdr->p_memsz; vma->file = (struct file *)kmalloc(); vma->file->start = (uint64_t)ehdr; vma->file->pgoff = phdr->p_offset; vma->file->size = phdr->p_filesz; memcpy((void*)vma->start, (void*)((uint64_t)ehdr + phdr->p_offset), phdr->p_filesz); if(phdr->p_flags == (PERM_R | PERM_X)) { vma->file->bss_size = 0; vma->type = TEXT; } else { vma->file->bss_size = phdr->p_memsz - phdr->p_filesz; vma->type = DATA; } } } phdr++; } /* Allocate HEAP */ vma_struct *vma_heap = (vma_struct *)kmalloc(); if(mm->mmap == NULL) mm->mmap = vma_heap; else mm->current->next = vma_heap; mm->current = vma_heap; vma_heap->mm = mm; // if(!mm->end_data) // return 1; vma_heap->start = HEAP_START; mm->brk = HEAP_START; vma_heap->end = HEAP_START + PAGE_SIZE; vma_heap->flags = (PERM_R | PERM_W); vma_heap->type = HEAP; vma_heap->file = NULL; vma_heap->next = NULL; get_phy_addr(HEAP_START); /* Allocate STACK */ vma_struct *vma_stack = (vma_struct *)kmalloc(); if(mm->mmap == NULL) { mm->mmap = vma_stack; } else { mm->current->next = vma_stack; } mm->current = vma_stack; uint64_t *stack = (uint64_t *)get_phy_addr(USER_STACK_TOP); vma_stack->start = (uint64_t)stack + PAGE_SIZE; vma_stack->end = (uint64_t)stack; vma_stack->flags = (PERM_R | PERM_W); vma_stack->type = STACK; vma_stack->file = NULL; vma_stack->next = NULL; task->rsp = (uint64_t)((uint64_t)stack + 4096 - 16); return 0; }