Beispiel #1
0
void map_page(uint32_t *page_dir, uint32_t virt_page_num, uint32_t phy_page_num,
        bool global, bool user, bool read_write)
{
    uint16_t pd_idx = PD_IDX(virt_page_num),
             pt_idx = PT_IDX(virt_page_num);
    uint32_t *page_table;

    if(!(page_dir[pd_idx] & 0x1)) {
        uint32_t pt_page_num = alloc_phy_page(0, 1023);
        map_kernel_page(pt_page_num, pt_page_num, true, false, true);
        memset((void *)(pt_page_num << 12), 0, 4096);
        page_dir[pd_idx] = make_pde(pt_page_num, user, read_write);
    }

    page_table = (uint32_t *)(page_dir[pd_idx] & 0xfffff000);
    page_table[pt_idx] = make_pte(phy_page_num, global, user, read_write);
    ++phy_mem_rc[phy_page_num];
    __asm__ volatile(
        ".intel_syntax noprefix;"
        "mov eax, cr3;"
        "mov cr3, eax;"
        ".att_syntax;"
        :::"eax"
    );
}
Beispiel #2
0
pte_t *mmap_lookup(pml4e_t *pml4, uint64_t va, bool create)
{
	struct page *page4pdp = NULL, *page4pd = NULL, *page4pt = NULL;
	pdpe_t pml4e = pml4[PML4_IDX(va)];

	if ((pml4e & PML4E_P) != 0)
		goto pml4e_found;
	if (create == false)
		return NULL;

	// Prepare new page directory pointer
	if ((page4pdp = page_alloc()) == NULL)
		return NULL;
	memset(page2kva(page4pdp), 0, PAGE_SIZE);
	page4pdp->ref = 1;

	// Insert new pdp into PML4
	pml4e = pml4[PML4_IDX(va)] = page2pa(page4pdp) | PML4E_P | PML4E_W | PML4E_U;

pml4e_found:
	assert((pml4e & PML4E_P) != 0);

	pdpe_t *pdp = VADDR(PML4E_ADDR(pml4e));
	pdpe_t pdpe = pdp[PDP_IDX(va)];

	if ((pdpe & PDPE_P) != 0)
		goto pdpe_found;
	if (create == false)
		return NULL;

	// Prepare new page directory
	if ((page4pd = page_alloc()) == NULL)
		return NULL;
	memset(page2kva(page4pd), 0, PAGE_SIZE);
	page4pd->ref = 1;

	// Insert new page directory into page directory pointer table
	pdpe = pdp[PDP_IDX(va)] = page2pa(page4pd) | PDPE_P | PDPE_W | PDPE_U;

pdpe_found:
	assert((pdpe & PDPE_P) != 0);

	pde_t *pd = VADDR(PDPE_ADDR(pdpe));
	pde_t pde = pd[PD_IDX(va)];

	if ((pde & PDE_P) != 0)
		goto pde_found;
	if (create == false)
		return NULL;

	// Prepare new page table
	if ((page4pt = page_alloc()) == NULL)
		return NULL;
	memset(page2kva(page4pt), 0, PAGE_SIZE);
	page4pt->ref = 1;

	// Insert new page table into page directory
	pde = pd[PD_IDX(va)] = page2pa(page4pt) | PDE_P | PTE_W | PDE_U;

pde_found:
	assert((pde & PDE_P) != 0);

	pte_t *pt = VADDR(PDE_ADDR(pde));

	return &pt[PT_IDX(va)];
}
Beispiel #3
0
/*
 * Allocate a number of pages from the OS
 */
static void *
map_pages(size_t pages)
{
	struct pdinfo	*pi, *spi;
	struct pginfo	**pd;
	u_long		idx, pidx, lidx;
	caddr_t		result, tail;
	u_long		index, lindex;
	void 		*pdregion = NULL;
	size_t		dirs, cnt;

	pages <<= malloc_pageshift;
	result = MMAP(pages + malloc_guard);
	if (result == MAP_FAILED) {
#ifdef MALLOC_EXTRA_SANITY
		wrtwarning("(ES): map_pages fails");
#endif /* MALLOC_EXTRA_SANITY */
		errno = ENOMEM;
		return (NULL);
	}
	index = ptr2index(result);
	tail = result + pages + malloc_guard;
	lindex = ptr2index(tail) - 1;
	if (malloc_guard)
		mprotect(result + pages, malloc_guard, PROT_NONE);

	pidx = PI_IDX(index);
	lidx = PI_IDX(lindex);

	if (tail > malloc_brk) {
		malloc_brk = tail;
		last_index = lindex;
	}

	dirs = lidx - pidx;

	/* Insert directory pages, if needed. */
	if (pdir_lookup(index, &pi) != 0)
		dirs++;
	if (dirs > 0) {
		pdregion = MMAP(malloc_pagesize * dirs);
		if (pdregion == MAP_FAILED) {
			munmap(result, tail - result);
#ifdef MALLOC_EXTRA_SANITY
		wrtwarning("(ES): map_pages fails");
#endif
			errno = ENOMEM;
			return (NULL);
		}
	}
	cnt = 0;
	for (idx = pidx, spi = pi; idx <= lidx; idx++) {
		if (pi == NULL || PD_IDX(pi->dirnum) != idx) {
			pd = (struct pginfo **)((char *)pdregion +
			    cnt * malloc_pagesize);
			cnt++;
			memset(pd, 0, malloc_pagesize);
			pi = (struct pdinfo *) ((caddr_t) pd + pdi_off);
			pi->base = pd;
			pi->prev = spi;
			pi->next = spi->next;
			pi->dirnum = idx * (malloc_pagesize /
			    sizeof(struct pginfo *));

			if (spi->next != NULL)
				spi->next->prev = pi;
			spi->next = pi;
		}
		if (idx > pidx && idx < lidx) {
			pi->dirnum += pdi_mod;
		} else if (idx == pidx) {
			if (pidx == lidx) {
				pi->dirnum += (u_long)(tail - result) >>
				    malloc_pageshift;
			} else {
				pi->dirnum += pdi_mod - PI_OFF(index);
			}
		} else {
Beispiel #4
0
void
malloc_dump(int fd)
{
	char		buf[1024];
	struct pginfo	**pd;
	struct pgfree	*pf;
	struct pdinfo	*pi;
	u_long		j;

	pd = page_dir;
	pi = (struct pdinfo *) ((caddr_t) pd + pdi_off);

	/* print out all the pages */
	for (j = 0; j <= last_index;) {
		snprintf(buf, sizeof buf, "%08lx %5lu ", j << malloc_pageshift, j);
		write(fd, buf, strlen(buf));
		if (pd[PI_OFF(j)] == MALLOC_NOT_MINE) {
			for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_NOT_MINE;) {
				if (!PI_OFF(++j)) {
					if ((pi = pi->next) == NULL ||
					    PD_IDX(pi->dirnum) != PI_IDX(j))
						break;
					pd = pi->base;
					j += pdi_mod;
				}
			}
			j--;
			snprintf(buf, sizeof buf, ".. %5lu not mine\n", j);
			write(fd, buf, strlen(buf));
		} else if (pd[PI_OFF(j)] == MALLOC_FREE) {
			for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FREE;) {
				if (!PI_OFF(++j)) {
					if ((pi = pi->next) == NULL ||
					    PD_IDX(pi->dirnum) != PI_IDX(j))
						break;
					pd = pi->base;
					j += pdi_mod;
				}
			}
			j--;
			snprintf(buf, sizeof buf, ".. %5lu free\n", j);
			write(fd, buf, strlen(buf));
		} else if (pd[PI_OFF(j)] == MALLOC_FIRST) {
			for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FOLLOW;) {
				if (!PI_OFF(++j)) {
					if ((pi = pi->next) == NULL ||
					    PD_IDX(pi->dirnum) != PI_IDX(j))
						break;
					pd = pi->base;
					j += pdi_mod;
				}
			}
			j--;
			snprintf(buf, sizeof buf, ".. %5lu in use\n", j);
			write(fd, buf, strlen(buf));
		} else if (pd[PI_OFF(j)] < MALLOC_MAGIC) {
			snprintf(buf, sizeof buf, "(%p)\n", pd[PI_OFF(j)]);
			write(fd, buf, strlen(buf));
		} else {
			snprintf(buf, sizeof buf, "%p %d (of %d) x %d @ %p --> %p\n",
			    pd[PI_OFF(j)], pd[PI_OFF(j)]->free,
			    pd[PI_OFF(j)]->total, pd[PI_OFF(j)]->size,
			    pd[PI_OFF(j)]->page, pd[PI_OFF(j)]->next);
			write(fd, buf, strlen(buf));
		}
		if (!PI_OFF(++j)) {
			if ((pi = pi->next) == NULL)
				break;
			pd = pi->base;
			j += (1 + PD_IDX(pi->dirnum) - PI_IDX(j)) * pdi_mod;
		}
	}

	for (pf = free_list.next; pf; pf = pf->next) {
		snprintf(buf, sizeof buf, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
		    pf, pf->page, (char *)pf->page + pf->size,
		    pf->size, pf->prev, pf->next);
		write(fd, buf, strlen(buf));
		if (pf == pf->next) {
			snprintf(buf, sizeof buf, "Free_list loops\n");
			write(fd, buf, strlen(buf));
			break;
		}
	}

	/* print out various info */
	snprintf(buf, sizeof buf, "Minsize\t%lu\n", malloc_minsize);
	write(fd, buf, strlen(buf));
	snprintf(buf, sizeof buf, "Maxsize\t%lu\n", malloc_maxsize);
	write(fd, buf, strlen(buf));
	snprintf(buf, sizeof buf, "Pagesize\t%lu\n", malloc_pagesize);
	write(fd, buf, strlen(buf));
	snprintf(buf, sizeof buf, "Pageshift\t%u\n", malloc_pageshift);
	write(fd, buf, strlen(buf));
	snprintf(buf, sizeof buf, "In use\t%lu\n", (u_long) malloc_used);
	write(fd, buf, strlen(buf));
	snprintf(buf, sizeof buf, "Guarded\t%lu\n", (u_long) malloc_guarded);
	write(fd, buf, strlen(buf));
}
Beispiel #5
0
/*
 * Function for page directory lookup.
 */
static int
pdir_lookup(u_long index, struct pdinfo ** pdi)
{
	struct pdinfo	*spi;
	u_long		pidx = PI_IDX(index);

	if (last_dir != NULL && PD_IDX(last_dir->dirnum) == pidx)
		*pdi = last_dir;
	else if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) == pidx)
		*pdi = prev_dir;
	else if (last_dir != NULL && prev_dir != NULL) {
		if ((PD_IDX(last_dir->dirnum) > pidx) ?
		    (PD_IDX(last_dir->dirnum) - pidx) :
		    (pidx - PD_IDX(last_dir->dirnum))
		    < (PD_IDX(prev_dir->dirnum) > pidx) ?
		    (PD_IDX(prev_dir->dirnum) - pidx) :
		    (pidx - PD_IDX(prev_dir->dirnum)))
			*pdi = last_dir;
		else
			*pdi = prev_dir;

		if (PD_IDX((*pdi)->dirnum) > pidx) {
			for (spi = (*pdi)->prev;
			    spi != NULL && PD_IDX(spi->dirnum) > pidx;
			    spi = spi->prev)
				*pdi = spi;
			if (spi != NULL)
				*pdi = spi;
		} else
			for (spi = (*pdi)->next;
			    spi != NULL && PD_IDX(spi->dirnum) <= pidx;
			    spi = spi->next)
				*pdi = spi;
	} else {
		*pdi = (struct pdinfo *) ((caddr_t) page_dir + pdi_off);
		for (spi = *pdi;
		    spi != NULL && PD_IDX(spi->dirnum) <= pidx;
		    spi = spi->next)
			*pdi = spi;
	}

	return ((PD_IDX((*pdi)->dirnum) == pidx) ? 0 :
	    (PD_IDX((*pdi)->dirnum) > pidx) ? 1 : -1);
}