aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-02-15 20:59:33 +0100
committerGreg Kroah-Hartman <gregkh@suse.de>2008-02-25 16:19:02 -0800
commit7a0fd2e6b0190e5dd2bfe71a0b4f10826811418e (patch)
treeb620d2101383f9949f311faba1e3c4fbccf88db0
parentf7e1b66a194e38f9fa41f8144aa34b782fb4f53a (diff)
x86_64: CPA, fix cache attribute inconsistency bug
(no matching git id as the upstream code is rewritten) fix CPA cache attribute bug in v2.6.24. When phys_base is nonzero (when CONFIG_RELOCATABLE=y) then change_page_attr_addr() miscalculates the secondary alias address by -14 MB (depending on the configured offset). The default 64-bit kernels of Fedora and Ubuntu are affected: $ grep RELOCA /boot/config-2.6.23.9-85.fc8 CONFIG_RELOCATABLE=y $ grep RELOC /boot/config-2.6.22-14-generic CONFIG_RELOCATABLE=y and probably on many other distros as well. the bug affects all pages in the first 40 MB of physical RAM that are allocated by some subsystem that does ioremap_nocache() on them: if (__pa(address) < KERNEL_TEXT_SIZE) { Hence we might leave page table entries with inconsistent cache attributes around (pages mapped at both UnCacheable and Write-Back), and we can also set the wrong kernel text pages to UnCacheable. the effects of this bug can be random slowdowns and other misbehavior. If for example AGP allocates its aperture pages into the first 40 MB of physical RAM, then the -14 MB bug might mark random kernel texto pages as uncacheable, slowing down a random portion of the 64-bit kernel until the AGP driver is unloaded. Signed-off-by: Ingo Molnar <mingo@elte.hu> Acked-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--arch/x86/mm/pageattr_64.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/arch/x86/mm/pageattr_64.c b/arch/x86/mm/pageattr_64.c
index c40afbaaf93..f636c1e4d6c 100644
--- a/arch/x86/mm/pageattr_64.c
+++ b/arch/x86/mm/pageattr_64.c
@@ -207,7 +207,7 @@ int change_page_attr_addr(unsigned long address, int numpages, pgprot_t prot)
if (__pa(address) < KERNEL_TEXT_SIZE) {
unsigned long addr2;
pgprot_t prot2;
- addr2 = __START_KERNEL_map + __pa(address);
+ addr2 = __START_KERNEL_map + __pa(address) - phys_base;
/* Make sure the kernel mappings stay executable */
prot2 = pte_pgprot(pte_mkexec(pfn_pte(0, prot)));
err = __change_page_attr(addr2, pfn, prot2,