aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/mm/pageattr.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index c53de62a1170..4b47ae0602e1 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -666,6 +666,45 @@ static int split_large_page(pte_t *kpte, unsigned long address)
666 return 0; 666 return 0;
667} 667}
668 668
669#define populate_pud(cpa, addr, pgd, pgprot) (-1)
670
671/*
672 * Restrictions for kernel page table do not necessarily apply when mapping in
673 * an alternate PGD.
674 */
675static int populate_pgd(struct cpa_data *cpa, unsigned long addr)
676{
677 pgprot_t pgprot = __pgprot(_KERNPG_TABLE);
678 bool allocd_pgd = false;
679 pgd_t *pgd_entry;
680 pud_t *pud = NULL; /* shut up gcc */
681 int ret;
682
683 pgd_entry = cpa->pgd + pgd_index(addr);
684
685 /*
686 * Allocate a PUD page and hand it down for mapping.
687 */
688 if (pgd_none(*pgd_entry)) {
689 pud = (pud_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK);
690 if (!pud)
691 return -1;
692
693 set_pgd(pgd_entry, __pgd(__pa(pud) | _KERNPG_TABLE));
694 allocd_pgd = true;
695 }
696
697 pgprot_val(pgprot) &= ~pgprot_val(cpa->mask_clr);
698 pgprot_val(pgprot) |= pgprot_val(cpa->mask_set);
699
700 ret = populate_pud(cpa, addr, pgd_entry, pgprot);
701 if (ret < 0)
702 return ret;
703
704 cpa->numpages = ret;
705 return 0;
706}
707
669static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr, 708static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr,
670 int primary) 709 int primary)
671{ 710{