proc_t *proc_create(void) { proc_t *proc = malloc(sizeof(*proc)); if (!proc) return 0; proc->pml4_table = pmm_alloc(); if (!proc->pml4_table) { free(proc); return 0; } if (!vmm_init_pml4(proc->pml4_table)) { pmm_free(proc->pml4_table); free(proc); return 0; } proc->vmm_lock = SPIN_UNLOCKED; if (!seg_init(&proc->segments)) { pmm_free(proc->pml4_table); free(proc); return 0; } proc->state = PROC_RUNNING; list_init(&proc->thread_list); return proc; }
void init_pmm(struct info_multiboot* mb_info) { struct mmap_multiboot* memory_map = mb_info->mbs_mmap_addr; struct mmap_multiboot* memory_map_end = (void*) ((uint32_t) mb_info->mbs_mmap_addr + mb_info->mbs_mmap_length); while(memory_map < memory_map_end) { if(memory_map->type == 1) { uint32_t address = memory_map->base; uint32_t end_address = address + memory_map->length; while(address < end_address) { pmm_free((void*) address); address += 0x1000; } } memory_map++; } uint32_t address = (uint32_t) &kernel_start; while(address < (uint32_t) &kernel_end) { pmm_mark_used((void*) address); address += 0x1000; } }
void pmm_init(struct multiboot_info* mb_info) { struct multiboot_mmap* mmap = mb_info->mbs_mmap_addr; struct multiboot_mmap* mmap_end = (void*) ((uintptr_t) mb_info->mbs_mmap_addr + mb_info->mbs_mmap_length); /* at begin all is reserved */ memset(bitmap, 0, sizeof(bitmap)); /* * the BIOS-memory-map deklares free memory */ while (mmap < mmap_end) { if (mmap->type == 1) { /* it's free, so set the bit */ uintptr_t addr = mmap->base; uintptr_t end_addr = addr + mmap->length; while (addr < end_addr) { pmm_free((void*) addr); addr += 0x1000; } } mmap++; } /* IMPORTANT: mark kernel space as alloc'd */ uintptr_t addr = (uintptr_t) &kernel_start; while (addr < (uintptr_t) &kernel_end) { pmm_mark_used((void*) addr); addr += 0x1000; } /* * lets mark the multiboot struct and the module list too. * Let's say both stay under 4k TODO make real solutiion */ struct multiboot_module* modules = mb_info->mbs_mods_addr; pmm_mark_used(mb_info); pmm_mark_used(modules); /* naturally the modules themself are used too */ int i; for (i = 0; i < mb_info->mbs_mods_count; i++) { addr = modules[i].mod_start; while (addr < modules[i].mod_end) { pmm_mark_used((void*) addr); addr += 0x1000; } } }
void vm_unmap(int n,size_t vp){ vp=GET_PAGE(vp); if(vp<VM_KERNEL)return 0; size_t i1=vp/0x8000000000; vp-=i1*0x8000000000; size_t i2=vp/0x40000000; vp-=i2*0x40000000; size_t i3=vp/0x200000; vp-=i3*0x200000; size_t i4=vp/0x1000; int i; if(vi[n].pagetable!=NULL){ u64 *p1=(u64*)GET_PAGE(vi[n].pagetable[i1]); if(p1!=NULL){ u64 *p2=(u64*)GET_PAGE(p1[i2]); if(p2!=NULL){ u64 *p3=(u64*)GET_PAGE(p2[i3]); if(p3!=NULL){ p3[i4]=NULL; for(i=0;i<4096/8;i++){ if(GET_PAGE(p3[i])!=NULL){ invlpaging(); return; } } p2[i3]=NULL; pmm_free(p3); for(i=0;i<4096/8;i++){ if(GET_PAGE(p2[i])!=NULL){ invlpaging(); return; } } p1[i2]=NULL; invlpaging(); pmm_free(p2); } } } } }
void init_pmm(void* mbd){ multiboot_info_t* mb_info = (multiboot_info_t*)mbd; multiboot_mmap_entry_t* mmap = (multiboot_mmap_entry_t*)mb_info->mmap_addr; multiboot_mmap_entry_t* mmap_end = (void*) ((unsigned int*) mb_info->mmap_addr + mb_info->mmap_length); /* Per Default ist erst einmal alles reserviert */ memset(bitmap, 0, sizeof(bitmap)); /* * Nur, was die BIOS-Memory-Map als frei bezeichnet, wird wieder als frei * markiert */ while (mmap < mmap_end) { if (mmap->type == 1) { /* Der Speicherbereich ist frei, entsprechend markieren */ unsigned int addr = mmap->addr; unsigned int end_addr = (unsigned char*)addr + mmap->len; while (addr < end_addr) { pmm_free((void*) addr); addr += 0x1000; } } mmap++; } extern const void kernel_start; extern const void kernel_end; unsigned int addr = (unsigned int) &kernel_start; while (addr < (unsigned int*) &kernel_end) { pmm_mark_used((void*) addr); addr += 0x1000; } addr = (unsigned int)0x00; unsigned int addr_end = (unsigned int)0x800000; while (addr < addr_end) { pmm_mark_used((void*) addr); addr += 0x1000; } }
void proc_destroy(proc_t *proc) { // TODO: destroy threads within the process and make sure they aren't queued /* lock interrupts so we can temporarily switch address spaces */ intr_lock(); /* record the old pml4 table and switch to the new one */ uintptr_t old_pml4_table = cr3_read(); cr3_write(proc->pml4_table); /* destroy the user memory segments */ seg_destroy(); /* switch back to the old address space and unlock interrupts */ cr3_write(old_pml4_table); intr_unlock(); // TODO: if cpu->proc == proc, change it to 0? /* free the pml4 table and process struct */ pmm_free(proc->pml4_table); free(proc); }