x86: don't use large pages to map the first 2/4MB of memory
authorAndi Kleen <andi@firstfloor.org>
Wed, 12 Mar 2008 02:53:30 +0000 (03:53 +0100)
committerIngo Molnar <mingo@elte.hu>
Thu, 17 Apr 2008 15:41:30 +0000 (17:41 +0200)
Intel recommends to not use large pages for the first 1MB
of the physical memory because there are fixed size MTRRs there
which cause splitups in the TLBs.

On AMD doing so is also a good idea.

The implementation is a little different between 32bit and 64bit.
On 32bit I just taught the initial page table set up about this
because it was very simple to do. This also has the advantage
that the risk of a prefetch ever seeing the page even
if it only exists for a short time is minimized.

On 64bit that is not quite possible, so use set_memory_4k() a little
later (in check_bugs) instead.

Signed-off-by: Andi Kleen <ak@suse.de>
Acked-by: andreas.herrmann3@amd.com
Cc: mingo@elte.hu
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/kernel/bugs_64.c
arch/x86/mm/init_32.c

index 60207e999a04431479c41916e6a5c244770e14ed..9a3ed0649d4e98c4459f13d90fbf1988df2195ce 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/bugs.h>
 #include <asm/processor.h>
 #include <asm/mtrr.h>
+#include <asm/cacheflush.h>
 
 void __init check_bugs(void)
 {
@@ -18,4 +19,15 @@ void __init check_bugs(void)
        print_cpu_info(&boot_cpu_data);
 #endif
        alternative_instructions();
+
+       /*
+        * Make sure the first 2MB area is not mapped by huge pages
+        * There are typically fixed size MTRRs in there and overlapping
+        * MTRRs into large pages causes slow downs.
+        *
+        * Right now we don't do that with gbpages because there seems
+        * very little benefit for that case.
+        */
+       if (!direct_gbpages)
+               set_memory_4k((unsigned long)__va(0), 1);
 }
index fc3ace2e88f105e5ba2464d85ab12cc48e782e6f..1500dc8d63e4676586470d458722b71cad63ace1 100644 (file)
@@ -181,8 +181,13 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
                        /*
                         * Map with big pages if possible, otherwise
                         * create normal page tables:
+                        *
+                        * Don't use a large page for the first 2/4MB of memory
+                        * because there are often fixed size MTRRs in there
+                        * and overlapping MTRRs into large pages can cause
+                        * slowdowns.
                         */
-                       if (cpu_has_pse) {
+                       if (cpu_has_pse && !(pgd_idx == 0 && pmd_idx == 0)) {
                                unsigned int addr2;
                                pgprot_t prot = PAGE_KERNEL_LARGE;