diff options
author | Andi Kleen <ak@suse.de> | 2008-02-04 16:48:09 +0100 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-02-04 16:48:09 +0100 |
commit | f07333fd149eb6826da26a89c3aff90324f270b0 (patch) | |
tree | 139557a0a7469e52dc8407c72dd70a011dee3884 /arch/x86 | |
parent | b5360222273cb3e57a119c18eef42f59da4da87b (diff) | |
download | op-kernel-dev-f07333fd149eb6826da26a89c3aff90324f270b0.zip op-kernel-dev-f07333fd149eb6826da26a89c3aff90324f270b0.tar.gz |
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>
Diffstat (limited to 'arch/x86')
-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 143fbaf..42ca3d8 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, psize = PMD_PAGE_SIZE; pmask = PMD_PAGE_MASK; break; +#ifdef CONFIG_X86_64 case PG_LEVEL_1G: + psize = PMD_PAGE_SIZE; + pmask = PMD_PAGE_MASK; + break; +#endif default: res = -EINVAL; goto out_unlock; @@ -343,7 +348,7 @@ static int split_large_page(pte_t *kpte, unsigned long address) { pgprot_t ref_prot; gfp_t gfp_flags = GFP_KERNEL; - unsigned long flags, addr, pfn; + unsigned long flags, addr, pfn, pfninc = 1; pte_t *pbase, *tmp; struct page *base; unsigned int i, level; @@ -372,11 +377,19 @@ static int split_large_page(pte_t *kpte, unsigned long address) #endif ref_prot = pte_pgprot(pte_clrhuge(*kpte)); +#ifdef CONFIG_X86_64 + if (level == PG_LEVEL_1G) { + pfninc = PMD_PAGE_SIZE >> PAGE_SHIFT; + pgprot_val(ref_prot) |= _PAGE_PSE; + addr &= PUD_PAGE_MASK; + } +#endif + /* * Get the target pfn from the original entry: */ pfn = pte_pfn(*kpte); - for (i = 0; i < PTRS_PER_PTE; i++, pfn++) + for (i = 0; i < PTRS_PER_PTE; i++, pfn += pfninc) set_pte(&pbase[i], pfn_pte(pfn, ref_prot)); /* |