Esempio n. 1
0
static int pt_populate_pml2(pte_t *pml2, virt_t from, virt_t to, pte_t flags)
{
	virt_t vaddr = from;

	for (int i = pml2_i(from); vaddr != to; ++i) {
		const virt_t bytes =
			MINU(PML1_SIZE - (vaddr & PML1_MASK), to - vaddr);
		const pfn_t pages = bytes >> PAGE_BITS;

		if (!pte_present(pml2[i]) && !pte_large(flags)) {
			struct page *pt = alloc_page_table(flags);

			if (!pt) {
				pt_release_pml2(pml2, from, vaddr);
				return -ENOMEM;
			}

			pt->u.refcount += pages;
			pml2[i] = page_paddr(pt) | flags;
		} else if (pte_present(pml2[i]) && !pte_large(pml2[i])) {
			const pfn_t pfn = pte_phys(pml2[i]) >> PAGE_BITS;
			struct page *pt = pfn2page(pfn);

			pt->u.refcount += pages;
		}
		vaddr += bytes;
	}

	return 0;
}
Esempio n. 2
0
struct pt_iter *pt_iter_next(struct pt_iter *iter)
{
	int level = iter->level;
	int idx = iter->idx[level];

	while (idx == PT_SIZE - 1 && level != PT_MAX_LEVEL)
		idx = iter->idx[++level];

	if (idx == PT_SIZE - 1)
		return 0;

	pte_t pte = iter->pt[level][++idx];

	iter->idx[level] = idx;

	while (pte_present(pte) && level != 0 && !pte_large(pte)) {
		const phys_t paddr = pte_phys(pte);
		pte_t *pt = va(paddr);

		iter->idx[--level] = 0;
		iter->pt[level] = pt;
		pte = pt[0];
	}
	iter->level = level;

	while (level != 0) {
		iter->pt[--level] = 0;
		iter->idx[level] = 0;
	}
	iter->addr = pt_iter_addr(iter);

	return iter;
}
Esempio n. 3
0
struct pt_iter *pt_iter_set(struct pt_iter *iter, pte_t *pml4, virt_t addr)
{
	memset(iter, 0, sizeof(*iter));

	if (!pml4)
		return iter;

	int level = PT_MAX_LEVEL;
	int idx = pml4_i(addr);
	pte_t pte = pml4[idx];

	iter->pt[level] = pml4;
	iter->idx[level] = idx;

	while (pte_present(pte) && level != 0 && !pte_large(pte)) {
		const phys_t paddr = pte_phys(pte);
		pte_t *pt = va(paddr);

		idx = pt_index(addr, level--);
		pte = pt[idx];

		iter->idx[level] = idx;
		iter->pt[level] = pt;
	}

	iter->addr = pt_iter_addr(iter);
	iter->level = level;

	return iter;
}
Esempio n. 4
0
bool pt_iter_large(const struct pt_iter *iter)
{
	const int level = iter->level;
	const int index = iter->idx[level];

	return pte_large(iter->pt[level][index]);
}
Esempio n. 5
0
phys_t get_phys_adr(virt_t vad) {
    phys_t pad;
    pte_t *pml4e = pml4 + pml4_i(vad);
    pte_t *pdpte = ((pte_t *) va(pte_phys(*pml4e) << 12)) + pml3_i(vad);
    pte_t *pde = ((pte_t *) va(pte_phys(*pdpte) << 12)) + pml2_i(vad);
    if (pte_large(*pde)) {
        pad = ((*pde & (~((1 << 21) - 1)))) | (vad & ((1 << 21) - 1));
        return pad;
    }

    pte_t *pte = ((pte_t *) va(pte_phys(*pde) << 12)) + pml1_i(vad);
    pad = ((*pte & (~((1 << 12) - 1)))) | (vad & ((1 << 12) - 1));;
    return pad;
}
Esempio n. 6
0
static void pt_release_pml2(pte_t *pml2, virt_t from, virt_t to)
{
	virt_t vaddr = from;

	for (int i = pml2_i(from); vaddr != to; ++i) {
		const pte_t pte = pml2[i];
		const virt_t bytes =
			MINU(PML1_SIZE - (vaddr & PML1_MASK), to - vaddr);	
		const pfn_t pages = bytes >> PAGE_BITS;

		if (pte_present(pte) && !pte_large(pte)) {
			const pfn_t pfn = pte_phys(pte) >> PAGE_BITS;
			struct page *pt = pfn2page(pfn);

			pt->u.refcount -= pages;

			if (pt->u.refcount == 0) {
				pml2[i] = 0;
				free_page_table(pt);
			}
		}
		vaddr += bytes;	
	}
}