diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/mm/pageattr.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 143fbafc948a..42ca3d8effad 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -281,7 +281,12 @@ static int try_preserve_large_page(pte_t *kpte, unsigned long address, | |||
281 | psize = PMD_PAGE_SIZE; | 281 | psize = PMD_PAGE_SIZE; |
282 | pmask = PMD_PAGE_MASK; | 282 | pmask = PMD_PAGE_MASK; |
283 | break; | 283 | break; |
284 | #ifdef CONFIG_X86_64 | ||
284 | case PG_LEVEL_1G: | 285 | case PG_LEVEL_1G: |
286 | psize = PMD_PAGE_SIZE; | ||
287 | pmask = PMD_PAGE_MASK; | ||
288 | break; | ||
289 | #endif | ||
285 | default: | 290 | default: |
286 | res = -EINVAL; | 291 | res = -EINVAL; |
287 | goto out_unlock; | 292 | goto out_unlock; |
@@ -343,7 +348,7 @@ static int split_large_page(pte_t *kpte, unsigned long address) | |||
343 | { | 348 | { |
344 | pgprot_t ref_prot; | 349 | pgprot_t ref_prot; |
345 | gfp_t gfp_flags = GFP_KERNEL; | 350 | gfp_t gfp_flags = GFP_KERNEL; |
346 | unsigned long flags, addr, pfn; | 351 | unsigned long flags, addr, pfn, pfninc = 1; |
347 | pte_t *pbase, *tmp; | 352 | pte_t *pbase, *tmp; |
348 | struct page *base; | 353 | struct page *base; |
349 | unsigned int i, level; | 354 | unsigned int i, level; |
@@ -372,11 +377,19 @@ static int split_large_page(pte_t *kpte, unsigned long address) | |||
372 | #endif | 377 | #endif |
373 | ref_prot = pte_pgprot(pte_clrhuge(*kpte)); | 378 | ref_prot = pte_pgprot(pte_clrhuge(*kpte)); |
374 | 379 | ||
380 | #ifdef CONFIG_X86_64 | ||
381 | if (level == PG_LEVEL_1G) { | ||
382 | pfninc = PMD_PAGE_SIZE >> PAGE_SHIFT; | ||
383 | pgprot_val(ref_prot) |= _PAGE_PSE; | ||
384 | addr &= PUD_PAGE_MASK; | ||
385 | } | ||
386 | #endif | ||
387 | |||
375 | /* | 388 | /* |
376 | * Get the target pfn from the original entry: | 389 | * Get the target pfn from the original entry: |
377 | */ | 390 | */ |
378 | pfn = pte_pfn(*kpte); | 391 | pfn = pte_pfn(*kpte); |
379 | for (i = 0; i < PTRS_PER_PTE; i++, pfn++) | 392 | for (i = 0; i < PTRS_PER_PTE; i++, pfn += pfninc) |
380 | set_pte(&pbase[i], pfn_pte(pfn, ref_prot)); | 393 | set_pte(&pbase[i], pfn_pte(pfn, ref_prot)); |
381 | 394 | ||
382 | /* | 395 | /* |