static kstatus_t retain_helper(struct _physicalMemoryManager* self, unsigned nbr_page, IPhysicalPage* out_pages, BOOL try_to_search_in_free_page_list) { for (unsigned i = 0; i < nbr_page; i++) { IPhysicalPage page_to_give = 0x0; /* First try to get from free list */ if (try_to_search_in_free_page_list) page_to_give = SINGLY_LINKED_LIST_FIRST_VALUE(self->_freePageList); if (page_to_give) /* There is a free page available */ { SINGLY_LINKED_LIST_POP(self->_freePageList); /* Remove from free page list */ } else /* Free page list is empty */ { /* Move the kernel extended memory top address */ ASSERT(self->_extendedMemoryTop > self->_usedExtendedMemoryTop, "Extended memory full"); page_to_give = physical_page_alloc(); /* Alloc a new physical page object */ page_to_give->initWithPhysicalAddress(page_to_give, self->_usedExtendedMemoryTop); /* Associate top address with page */ self->_usedExtendedMemoryTop += PAGESIZE; } ASSERT(page_to_give != 0x0, "page_to_give is null"); /* Insert in caller output */ out_pages[i] = page_to_give; } return KS_SUCCESS; }
// copyseg(p, ph, src) // Load an ELF segment at virtual address `ph->p_va` in process `p`. Copies // `[src, src + ph->p_filesz)` to `dst`, then clears // `[ph->p_va + ph->p_filesz, ph->p_va + ph->p_memsz)` to 0. // Calls `physical_page_alloc` to allocate pages and `virtual_memory_map` // to map them in `p->p_pagetable`. Returns 0 on success and -1 on failure. static int copyseg(proc* p, const elf_program* ph, const uint8_t* src) { uintptr_t va = (uintptr_t) ph->p_va; uintptr_t end_file = va + ph->p_filesz, end_mem = va + ph->p_memsz; va &= ~(PAGESIZE - 1); // round to page boundary // allocate memory for (uintptr_t page_va = va; page_va < end_mem; page_va += PAGESIZE) { if (physical_page_alloc(page_va, p->p_pid) < 0) return -1; virtual_memory_map(p->p_pagetable, page_va, page_va, PAGESIZE, PTE_P|PTE_W|PTE_U); } // ensure new memory mappings are active lcr3((uintptr_t) p->p_pagetable); memcpy((uint8_t*) va, src, end_file - va); memset((uint8_t*) end_file, 0, end_mem - end_file); return 0; }