int vmap_page_range (unsigned long from, unsigned long size, unsigned long vaddr) { int error = 0; pgd_t * dir; unsigned long beg = from; unsigned long end = from + size; vaddr -= from; dir = pgd_offset(current->mm, from); flush_cache_range(current->mm, beg, end); while (from < end) { pmd_t *pmd = pmd_alloc(dir, from); error = -ENOMEM; if (!pmd) break; error = vmap_pmd_range(pmd, from, end - from, vaddr + from); if (error) break; from = (from + PGDIR_SIZE) & PGDIR_MASK; dir++; } flush_tlb_range(current->mm, beg, end); return error; }
static int vmap_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end, pgprot_t prot, struct page **pages, int *nr) { pud_t *pud; unsigned long next; pud = pud_alloc(&init_mm, pgd, addr); if (!pud) return -ENOMEM; do { next = pud_addr_end(addr, end); if (vmap_pmd_range(pud, addr, next, prot, pages, nr)) return -ENOMEM; } while (pud++, addr = next, addr != end); return 0; }