void physmem_init(void *boot_info) { multiboot_info_t *mb_info = (multiboot_info_t*)boot_info; uint64_t *mem_ptr = (uint64_t*)(uint64_t)mb_info->memory_map_addr; uint64_t Itr = 0, last_address = 0; /* Setup Memory Stuff */ highest_page = 0; memory_size = mb_info->memory_high; memory_size += mb_info->memory_low; total_blocks = (memory_size * 1024) / PAGE_SIZE; used_blocks = total_blocks; bitmap_size = total_blocks / PMM_BLOCKS_PER_BYTE; _mem_bitmap = (uint64_t*)stalloc(bitmap_size); physmem_lock = (spinlock_t*)stalloc(sizeof(spinlock_t)); spinlock_reset(physmem_lock); /* Set all memory as used, and use memory map to set free */ memoryset(_mem_bitmap, 0xF, bitmap_size); /* Physical Page Bitmap */ kprintf("Memory size: %u Kb\n", (uint32_t)memory_size); /* Go through regions */ for(Itr = (uint64_t)mem_ptr; Itr < ((uint64_t)mem_ptr + mb_info->memory_map_length); ) { /* Get next member */ mem_region_t *mem_region = (mem_region_t*)Itr; /* Output */ //kprintf("Memory Region: Address 0x%xL, length 0x%xL, Type %u\n", // mem_region->base_address, mem_region->length, mem_region->Type); /* Is it free? */ if(mem_region->type == MEMTYPE_FREE) physmem_freeregion(mem_region->base_address, mem_region->length); /* Advance by one structure */ Itr += sizeof(mem_region_t); } /* Mark all memory up to the static allocation point as used */ last_address = (physaddr_t)stalloc(1); stalloc_disable(); for(Itr = physmem_allocblock(); Itr < last_address;) Itr = physmem_allocblock(); /* Debug*/ kprintf("New memory allocation starts at 0x%xl\n", Itr); }
void* syscall_memlimit(void* new_end){ uint32_t phys_page; interrupt_status_t intr_status; intr_status = _interrupt_disable(); spinlock_acquire(&process_table_slock); process_control_block_t *curr_proc = process_get_current_process_entry(); // checks if the new_end is NULL if (new_end == NULL){ spinlock_release(&process_table_slock); _interrupt_set_state(intr_status); return (void*)curr_proc->heap_end; } // checks if we are trying to shrink the memory, if so we error // and return NULL if ((uint32_t)new_end < curr_proc->heap_end){ spinlock_release(&process_table_slock); _interrupt_set_state(intr_status); return NULL; } // loop where we alloc the physical and the virtual memoery, we also check // if we have enough physical memory. for (uint32_t i = (curr_proc->heap_end / PAGE_SIZE +1); i <= ((uint32_t)new_end / PAGE_SIZE);i++){ // we allocate some physical memory. phys_page = physmem_allocblock(); //check if we got enough physical memory, if we do not we error if (phys_page == 0){ spinlock_release(&process_table_slock); _interrupt_set_state(intr_status); return NULL; } // maps the virtual memory vm_map(thread_get_current_thread_entry()->pagetable, phys_page, i * PAGE_SIZE, 1); } // if nothing fails we at last set heap_end to new_end curr_proc->heap_end = (uint32_t)new_end; spinlock_release(&process_table_slock); _interrupt_set_state(intr_status); return new_end; }
/* Return non-zero on error. */ int setup_new_process(TID_t thread, const char *executable, const char **argv_src, virtaddr_t *entry_point, virtaddr_t *stack_top) { pagetable_t *pagetable; elf_info_t elf; openfile_t file; uintptr_t phys_page; int i, res; thread_table_t *thread_entry = thread_get_thread_entry(thread); int argc = 1; virtaddr_t argv_begin; virtaddr_t argv_dst; int argv_elem_size; virtaddr_t argv_elem_dst; file = vfs_open((char *)executable); /* Make sure the file existed and was a valid ELF file */ if (file < 0) { return -1; } res = elf_parse_header(&elf, file); if (res < 0) { return -1; } /* Trivial and naive sanity check for entry point: */ if (elf.entry_point < PAGE_SIZE) { return -1; } *entry_point = elf.entry_point; pagetable = vm_create_pagetable(thread); thread_entry->pagetable = pagetable; /* Allocate and map stack */ for(i = 0; i < CONFIG_USERLAND_STACK_SIZE; i++) { phys_page = physmem_allocblock(); KERNEL_ASSERT(phys_page != 0); /* Zero the page */ memoryset((void*)ADDR_PHYS_TO_KERNEL(phys_page), 0, PAGE_SIZE); vm_map(pagetable, phys_page, (USERLAND_STACK_TOP & PAGE_SIZE_MASK) - i*PAGE_SIZE, 1); } /* Allocate and map pages for the segments. We assume that segments begin at page boundary. (The linker script in tests directory creates this kind of segments) */ for(i = 0; i < (int)elf.ro_pages; i++) { int left_to_read = elf.ro_size - i*PAGE_SIZE; phys_page = physmem_allocblock(); KERNEL_ASSERT(phys_page != 0); /* Zero the page */ memoryset((void*)ADDR_PHYS_TO_KERNEL(phys_page), 0, PAGE_SIZE); /* Fill the page from ro segment */ if (left_to_read > 0) { KERNEL_ASSERT(vfs_seek(file, elf.ro_location + i*PAGE_SIZE) == VFS_OK); KERNEL_ASSERT(vfs_read(file, (void*)ADDR_PHYS_TO_KERNEL(phys_page), MIN(PAGE_SIZE, left_to_read)) == (int) MIN(PAGE_SIZE, left_to_read)); } vm_map(pagetable, phys_page, elf.ro_vaddr + i*PAGE_SIZE, 0); } for(i = 0; i < (int)elf.rw_pages; i++) { int left_to_read = elf.rw_size - i*PAGE_SIZE; phys_page = physmem_allocblock(); KERNEL_ASSERT(phys_page != 0); /* Zero the page */ memoryset((void*)ADDR_PHYS_TO_KERNEL(phys_page), 0, PAGE_SIZE); /* Fill the page from rw segment */ if (left_to_read > 0) { KERNEL_ASSERT(vfs_seek(file, elf.rw_location + i*PAGE_SIZE) == VFS_OK); KERNEL_ASSERT(vfs_read(file, (void*)ADDR_PHYS_TO_KERNEL(phys_page), MIN(PAGE_SIZE, left_to_read)) == (int) MIN(PAGE_SIZE, left_to_read)); } vm_map(pagetable, phys_page, elf.rw_vaddr + i*PAGE_SIZE, 1); } /* Set up argc and argv on the stack. */ /* Start by preparing ancillary information for the new process argv. */ if (argv_src != NULL) for (i = 0; argv_src[i] != NULL; i++) { argc++; } argv_begin = USERLAND_STACK_TOP - (argc * sizeof(virtaddr_t)); argv_dst = argv_begin; /* Prepare for copying executable. */ argv_elem_size = strlen(executable) + 1; argv_elem_dst = argv_dst - wordpad(argv_elem_size); /* Copy executable to argv[0] location. */ vm_memwrite(pagetable, argv_elem_size, argv_elem_dst, executable); /* Set argv[i] */ vm_memwrite(pagetable, sizeof(virtaddr_t), argv_dst, &argv_elem_dst); /* Move argv_dst to &argv[1]. */ argv_dst += sizeof(virtaddr_t); if (argv_src != NULL) { for (i = 0; argv_src[i] != NULL; i++) { /* Compute the size of argv[i+1] */ argv_elem_size = strlen(argv_src[i]) + 1; argv_elem_dst -= wordpad(argv_elem_size); /* Write the 'i+1'th element of argv */ vm_memwrite(pagetable, argv_elem_size, argv_elem_dst, argv_src[i]); /* Write argv[i+1] */ vm_memwrite(pagetable, sizeof(virtaddr_t), argv_dst, &argv_elem_dst); /* Move argv_dst to next element of argv. */ argv_dst += sizeof(virtaddr_t); } } /* Write argc to the stack. */ vm_memwrite(pagetable, sizeof(int), argv_elem_dst - sizeof(int), &argc); /* Write argv to the stack. */ vm_memwrite(pagetable, sizeof(virtaddr_t), argv_elem_dst - sizeof(int) - sizeof(virtaddr_t), &argv_begin); /* Stack pointer points at argv. */ *stack_top = argv_elem_dst - sizeof(int) - sizeof(virtaddr_t); return 0; }