/* * We need our own copy of the higher levels of the page tables * because we want to avoid inserting EFI region mappings (EFI_VA_END * to EFI_VA_START) into the standard kernel page tables. Everything * else can be shared, see efi_sync_low_kernel_mappings(). */ int __init efi_alloc_page_tables(void) { pgd_t *pgd; pud_t *pud; gfp_t gfp_mask; if (efi_enabled(EFI_OLD_MEMMAP)) return 0; gfp_mask = GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO; efi_pgd = (pgd_t *)__get_free_page(gfp_mask); if (!efi_pgd) return -ENOMEM; pgd = efi_pgd + pgd_index(EFI_VA_END); pud = pud_alloc_one(NULL, 0); if (!pud) { free_page((unsigned long)efi_pgd); return -ENOMEM; } pgd_populate(NULL, pgd, pud); return 0; }
static int __create_hyp_mappings(pgd_t *pgdp, unsigned long start, unsigned long end, unsigned long pfn, pgprot_t prot) { pgd_t *pgd; pud_t *pud; unsigned long addr, next; int err = 0; mutex_lock(&kvm_hyp_pgd_mutex); addr = start & PAGE_MASK; end = PAGE_ALIGN(end); do { pgd = pgdp + pgd_index(addr); if (pgd_none(*pgd)) { pud = pud_alloc_one(NULL, addr); if (!pud) { kvm_err("Cannot allocate Hyp pud\n"); err = -ENOMEM; goto out; } pgd_populate(NULL, pgd, pud); get_page(virt_to_page(pgd)); kvm_flush_dcache_to_poc(pgd, sizeof(*pgd)); } next = pgd_addr_end(addr, end); err = create_hyp_pud_mappings(pgd, addr, next, pfn, prot); if (err) goto out; pfn += (next - addr) >> PAGE_SHIFT; } while (addr = next, addr != end); out: mutex_unlock(&kvm_hyp_pgd_mutex); return err; }