aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2008-02-04 10:48:09 -0500
committerIngo Molnar <mingo@elte.hu>2008-02-04 10:48:09 -0500
commitf07333fd149eb6826da26a89c3aff90324f270b0 (patch)
tree139557a0a7469e52dc8407c72dd70a011dee3884
parentb5360222273cb3e57a119c18eef42f59da4da87b (diff)
x86: implement gbpages support in change_page_attr()
Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/x86/mm/pageattr.c17
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 /*