diff options
-rw-r--r-- | arch/x86/mm/pageattr.c | 39 |
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 | */ | ||
675 | static 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 | |||
669 | static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr, | 708 | static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr, |
670 | int primary) | 709 | int primary) |
671 | { | 710 | { |