diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-02-20 11:44:21 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-02-20 11:48:49 -0500 |
commit | 7a5714e0186030676d79a7b4b9830c8e45c3b0a1 (patch) | |
tree | 7d76720d333893db5b5fa4bb492d69a823ba76db /arch/x86/mm/pageattr.c | |
parent | 609162850db11dfe3b23f43b36888aa8b3ad7685 (diff) |
x86, pat: add large-PAT check to split_large_page()
Impact: future-proof the split_large_page() function
Linus noticed that split_large_page() is not safe wrt. the
PAT bit: it is bit 12 on the 1GB and 2MB page table level
(_PAGE_BIT_PAT_LARGE), and it is bit 7 on the 4K page
table level (_PAGE_BIT_PAT).
Currently it is not a problem because we never set
_PAGE_BIT_PAT_LARGE on any of the large-page mappings - but
should this happen in the future the split_large_page() would
silently lift bit 12 into the lowlevel 4K pte and would start
corrupting the physical page frame offset. Not fun.
So add a debug warning, to make sure if something ever sets
the PAT bit then this function gets updated too.
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/mm/pageattr.c')
-rw-r--r-- | arch/x86/mm/pageattr.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 7be47d1a97e4..8253bc97587e 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -482,6 +482,13 @@ static int split_large_page(pte_t *kpte, unsigned long address) | |||
482 | pbase = (pte_t *)page_address(base); | 482 | pbase = (pte_t *)page_address(base); |
483 | paravirt_alloc_pte(&init_mm, page_to_pfn(base)); | 483 | paravirt_alloc_pte(&init_mm, page_to_pfn(base)); |
484 | ref_prot = pte_pgprot(pte_clrhuge(*kpte)); | 484 | ref_prot = pte_pgprot(pte_clrhuge(*kpte)); |
485 | /* | ||
486 | * If we ever want to utilize the PAT bit, we need to | ||
487 | * update this function to make sure it's converted from | ||
488 | * bit 12 to bit 7 when we cross from the 2MB level to | ||
489 | * the 4K level: | ||
490 | */ | ||
491 | WARN_ON_ONCE(pgprot_val(ref_prot) & _PAGE_PAT_LARGE); | ||
485 | 492 | ||
486 | #ifdef CONFIG_X86_64 | 493 | #ifdef CONFIG_X86_64 |
487 | if (level == PG_LEVEL_1G) { | 494 | if (level == PG_LEVEL_1G) { |