Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=093af8d7f0ba3c6be1485973508584ef081e9f93
Commit:     093af8d7f0ba3c6be1485973508584ef081e9f93
Parent:     11201e603d28a1cb7a4bb1d65f39e61629c97a28
Author:     Yinghai Lu <[EMAIL PROTECTED]>
AuthorDate: Wed Jan 30 13:33:32 2008 +0100
Committer:  Ingo Molnar <[EMAIL PROTECTED]>
CommitDate: Wed Jan 30 13:33:32 2008 +0100

    x86_32: trim memory by updating e820
    
    when MTRRs are not covering the whole e820 table, we need to trim the
    RAM and need to update e820.
    
    reuse some code on 64-bit as well.
    
    here need to add early_get_cap and use it in early_cpu_detect, and move
    mtrr_bp_init early.
    
    The code successfully trimmed the memory map on Justin's system:
    
    from:
    
     [    0.000000]  BIOS-e820: 0000000100000000 - 000000022c000000 (usable)
    
    to:
    
     [    0.000000]   modified: 0000000100000000 - 0000000228000000 (usable)
     [    0.000000]   modified: 0000000228000000 - 000000022c000000 (reserved)
    
    According to Justin it makes quite a difference:
    
    |  When I boot the box without any trimming it acts like a 286 or 386,
    |  takes about 10 minutes to boot (using raptor disks).
    
    Signed-off-by: Yinghai Lu <[EMAIL PROTECTED]>
    Tested-by: Justin Piszcz <[EMAIL PROTECTED]>
    Signed-off-by: Ingo Molnar <[EMAIL PROTECTED]>
    Signed-off-by: Thomas Gleixner <[EMAIL PROTECTED]>
---
 Documentation/kernel-parameters.txt |    2 +-
 arch/x86/kernel/cpu/common.c        |   30 +++++++++++++++++++++++++++++-
 arch/x86/kernel/cpu/mtrr/main.c     |   22 ++++++++++++++--------
 arch/x86/kernel/e820_32.c           |   11 +++++++++++
 arch/x86/kernel/setup_32.c          |    6 ++++++
 include/asm-x86/e820_32.h           |    3 +++
 6 files changed, 64 insertions(+), 10 deletions(-)

diff --git a/Documentation/kernel-parameters.txt 
b/Documentation/kernel-parameters.txt
index 50d564d..fe3031d 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -583,7 +583,7 @@ and is between 256 and 4096 characters. It is defined in 
the file
                        See drivers/char/README.epca and
                        Documentation/digiepca.txt.
 
-       disable_mtrr_trim [X86-64, Intel only]
+       disable_mtrr_trim [X86, Intel and AMD only]
                        By default the kernel will trim any uncacheable
                        memory out of your available memory pool based on
                        MTRR settings.  This parameter disables that behavior,
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 56cc341..bba850b 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -278,6 +278,33 @@ void __init cpu_detect(struct cpuinfo_x86 *c)
                        c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8;
        }
 }
+static void __cpuinit early_get_cap(struct cpuinfo_x86 *c)
+{
+       u32 tfms, xlvl;
+       int ebx;
+
+       memset(&c->x86_capability, 0, sizeof c->x86_capability);
+       if (have_cpuid_p()) {
+               /* Intel-defined flags: level 0x00000001 */
+               if (c->cpuid_level >= 0x00000001) {
+                       u32 capability, excap;
+                       cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
+                       c->x86_capability[0] = capability;
+                       c->x86_capability[4] = excap;
+               }
+
+               /* AMD-defined flags: level 0x80000001 */
+               xlvl = cpuid_eax(0x80000000);
+               if ((xlvl & 0xffff0000) == 0x80000000) {
+                       if (xlvl >= 0x80000001) {
+                               c->x86_capability[1] = cpuid_edx(0x80000001);
+                               c->x86_capability[6] = cpuid_ecx(0x80000001);
+                       }
+               }
+
+       }
+
+}
 
 /* Do minimum CPU detection early.
    Fields really needed: vendor, cpuid_level, family, model, mask, cache 
alignment.
@@ -306,6 +333,8 @@ static void __init early_cpu_detect(void)
                early_init_intel(c);
                break;
        }
+
+       early_get_cap(c);
 }
 
 static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
@@ -485,7 +514,6 @@ void __init identify_boot_cpu(void)
        identify_cpu(&boot_cpu_data);
        sysenter_setup();
        enable_sep_cpu();
-       mtrr_bp_init();
 }
 
 void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
index ccd36ed..ac4b633 100644
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -624,7 +624,6 @@ static struct sysdev_driver mtrr_sysdev_driver = {
        .resume         = mtrr_restore,
 };
 
-#ifdef CONFIG_X86_64
 static int disable_mtrr_trim;
 
 static int __init disable_mtrr_trim_setup(char *str)
@@ -643,13 +642,10 @@ early_param("disable_mtrr_trim", disable_mtrr_trim_setup);
 #define Tom2Enabled (1U << 21)
 #define Tom2ForceMemTypeWB (1U << 22)
 
-static __init int amd_special_default_mtrr(unsigned long end_pfn)
+static __init int amd_special_default_mtrr(void)
 {
        u32 l, h;
 
-       /* Doesn't apply to memory < 4GB */
-       if (end_pfn <= (0xffffffff >> PAGE_SHIFT))
-               return 0;
        if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
                return 0;
        if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11)
@@ -687,9 +683,14 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn)
         * Make sure we only trim uncachable memory on machines that
         * support the Intel MTRR architecture:
         */
+       if (!is_cpu(INTEL) || disable_mtrr_trim)
+               return 0;
        rdmsr(MTRRdefType_MSR, def, dummy);
        def &= 0xff;
-       if (!is_cpu(INTEL) || disable_mtrr_trim || def != MTRR_TYPE_UNCACHABLE)
+       if (def != MTRR_TYPE_UNCACHABLE)
+               return 0;
+
+       if (amd_special_default_mtrr())
                return 0;
 
        /* Find highest cached pfn */
@@ -703,8 +704,14 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn)
                        highest_addr = base + size;
        }
 
-       if (amd_special_default_mtrr(end_pfn))
+       /* kvm/qemu doesn't have mtrr set right, don't trim them all */
+       if (!highest_addr) {
+               printk(KERN_WARNING "***************\n");
+               printk(KERN_WARNING "**** WARNING: likely strange cpu\n");
+               printk(KERN_WARNING "**** MTRRs all blank, cpu in qemu?\n");
+               printk(KERN_WARNING "***************\n");
                return 0;
+       }
 
        if ((highest_addr >> PAGE_SHIFT) < end_pfn) {
                printk(KERN_WARNING "***************\n");
@@ -726,7 +733,6 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn)
 
        return 0;
 }
-#endif
 
 /**
  * mtrr_bp_init - initialize mtrrs on the boot CPU
diff --git a/arch/x86/kernel/e820_32.c b/arch/x86/kernel/e820_32.c
index 931934a..4e16ef4 100644
--- a/arch/x86/kernel/e820_32.c
+++ b/arch/x86/kernel/e820_32.c
@@ -749,3 +749,14 @@ static int __init parse_memmap(char *arg)
        return 0;
 }
 early_param("memmap", parse_memmap);
+void __init update_e820(void)
+{
+       u8 nr_map;
+
+       nr_map = e820.nr_map;
+       if (sanitize_e820_map(e820.map, &nr_map))
+               return;
+       e820.nr_map = nr_map;
+       printk(KERN_INFO "modified physical RAM map:\n");
+       print_memory_map("modified");
+}
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
index 26a56f7..83ba3ca 100644
--- a/arch/x86/kernel/setup_32.c
+++ b/arch/x86/kernel/setup_32.c
@@ -48,6 +48,7 @@
 
 #include <video/edid.h>
 
+#include <asm/mtrr.h>
 #include <asm/apic.h>
 #include <asm/e820.h>
 #include <asm/mpspec.h>
@@ -758,6 +759,11 @@ void __init setup_arch(char **cmdline_p)
 
        max_low_pfn = setup_memory();
 
+       /* update e820 for memory not covered by WB MTRRs */
+       mtrr_bp_init();
+       if (mtrr_trim_uncached_memory(max_pfn))
+               max_low_pfn = setup_memory();
+
 #ifdef CONFIG_VMI
        /*
         * Must be after max_low_pfn is determined, and before kernel
diff --git a/include/asm-x86/e820_32.h b/include/asm-x86/e820_32.h
index e2faf5f..f1da7eb 100644
--- a/include/asm-x86/e820_32.h
+++ b/include/asm-x86/e820_32.h
@@ -19,12 +19,15 @@
 #ifndef __ASSEMBLY__
 
 extern struct e820map e820;
+extern void update_e820(void);
 
 extern int e820_all_mapped(unsigned long start, unsigned long end,
                           unsigned type);
 extern int e820_any_mapped(u64 start, u64 end, unsigned type);
 extern void find_max_pfn(void);
 extern void register_bootmem_low_pages(unsigned long max_low_pfn);
+extern void add_memory_region(unsigned long long start,
+                             unsigned long long size, int type);
 extern void e820_register_memory(void);
 extern void limit_regions(unsigned long long size);
 extern void print_memory_map(char *who);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to