diff options
author | Yinghai Lu <yhlu.kernel@gmail.com> | 2008-07-10 20:38:26 -0700 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-11 10:24:04 +0200 |
commit | f361a450bf1ad14e2b003217dbf3958638631265 (patch) | |
tree | 10c1e4dcc0047f6c37387cada6a0bceba088d2d2 /arch/x86/kernel | |
parent | f302a5bbe5eb95f3d4227d5bd0e9b92b1b125f4f (diff) |
x86: introduce max_low_pfn_mapped for 64-bit
when more than 4g memory is installed, don't map the big hole below 4g.
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Cc: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/amd_64.c | 10 | ||||
-rw-r--r-- | arch/x86/kernel/e820.c | 23 | ||||
-rw-r--r-- | arch/x86/kernel/efi.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/setup.c | 22 |
5 files changed, 47 insertions, 12 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index a31a579a47ca..9c981c4a3644 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -130,7 +130,7 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size) if (!phys || !size) return NULL; - if (phys+size <= (max_pfn_mapped << PAGE_SHIFT)) + if (phys+size <= (max_low_pfn_mapped << PAGE_SHIFT)) return __va(phys); offset = phys & (PAGE_SIZE - 1); diff --git a/arch/x86/kernel/cpu/amd_64.c b/arch/x86/kernel/cpu/amd_64.c index 958526d6a74a..bd182b7616ee 100644 --- a/arch/x86/kernel/cpu/amd_64.c +++ b/arch/x86/kernel/cpu/amd_64.c @@ -199,10 +199,14 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) * Don't do it for gbpages because there seems very little * benefit in doing so. */ - if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg) && - (tseg >> PMD_SHIFT) < - (max_pfn_mapped >> (PMD_SHIFT-PAGE_SHIFT))) + if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg)) { + if ((tseg>>PMD_SHIFT) < + (max_low_pfn_mapped>>(PMD_SHIFT-PAGE_SHIFT)) || + ((tseg>>PMD_SHIFT) < + (max_pfn_mapped>>(PMD_SHIFT-PAGE_SHIFT)) && + (tseg>>PMD_SHIFT) >= (1ULL<<(32 - PMD_SHIFT)))) set_memory_4k((unsigned long)__va(tseg), 1); + } } } diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 3451e0b3f324..9f5002e0b35c 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -1056,7 +1056,7 @@ unsigned long __initdata end_user_pfn = MAX_ARCH_PFN; /* * Find the highest page frame number we have available */ -unsigned long __init e820_end(void) +static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type) { int i; unsigned long last_pfn = 0; @@ -1064,12 +1064,21 @@ unsigned long __init e820_end(void) for (i = 0; i < e820.nr_map; i++) { struct e820entry *ei = &e820.map[i]; + unsigned long start_pfn; unsigned long end_pfn; - if (ei->type != E820_RAM) + if (ei->type != type) continue; + start_pfn = ei->addr >> PAGE_SHIFT; end_pfn = (ei->addr + ei->size) >> PAGE_SHIFT; + + if (start_pfn >= limit_pfn) + continue; + if (end_pfn > limit_pfn) { + last_pfn = limit_pfn; + break; + } if (end_pfn > last_pfn) last_pfn = end_pfn; } @@ -1083,7 +1092,15 @@ unsigned long __init e820_end(void) last_pfn, max_arch_pfn); return last_pfn; } +unsigned long __init e820_end_of_ram_pfn(void) +{ + return e820_end_pfn(MAX_ARCH_PFN, E820_RAM); +} +unsigned long __init e820_end_of_low_ram_pfn(void) +{ + return e820_end_pfn(1UL<<(32 - PAGE_SHIFT), E820_RAM); +} /* * Finds an active region in the address range from start_pfn to last_pfn and * returns its range in ei_startpfn and ei_endpfn for the e820 entry. @@ -1206,7 +1223,7 @@ static int __init parse_memmap_opt(char *p) * the real mem size before original memory map is * reset. */ - saved_max_pfn = e820_end(); + saved_max_pfn = e820_end_of_ram_pfn(); #endif e820.nr_map = 0; userdef = 1; diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c index 94382faeadb6..06cc8d4254b1 100644 --- a/arch/x86/kernel/efi.c +++ b/arch/x86/kernel/efi.c @@ -473,7 +473,7 @@ void __init efi_enter_virtual_mode(void) size = md->num_pages << EFI_PAGE_SHIFT; end = md->phys_addr + size; - if (PFN_UP(end) <= max_pfn_mapped) + if (PFN_UP(end) <= max_low_pfn_mapped) va = __va(md->phys_addr); else va = efi_ioremap(md->phys_addr, size); diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index a7c3471ea17c..86fc2d624270 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -713,14 +713,14 @@ void __init setup_arch(char **cmdline_p) * partially used pages are not usable - thus * we are rounding upwards: */ - max_pfn = e820_end(); + max_pfn = e820_end_of_ram_pfn(); /* preallocate 4k for mptable mpc */ early_reserve_e820_mpc_new(); /* update e820 for memory not covered by WB MTRRs */ mtrr_bp_init(); if (mtrr_trim_uncached_memory(max_pfn)) - max_pfn = e820_end(); + max_pfn = e820_end_of_ram_pfn(); #ifdef CONFIG_X86_32 /* max_low_pfn get updated here */ @@ -732,12 +732,26 @@ void __init setup_arch(char **cmdline_p) /* How many end-of-memory variables you have, grandma! */ /* need this before calling reserve_initrd */ - max_low_pfn = max_pfn; + if (max_pfn > (1UL<<(32 - PAGE_SHIFT))) + max_low_pfn = e820_end_of_low_ram_pfn(); + else + max_low_pfn = max_pfn; + high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1; #endif /* max_pfn_mapped is updated here */ - max_pfn_mapped = init_memory_mapping(0, (max_low_pfn << PAGE_SHIFT)); + max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT); + max_pfn_mapped = max_low_pfn_mapped; + +#ifdef CONFIG_X86_64 + if (max_pfn > max_low_pfn) { + max_pfn_mapped = init_memory_mapping(1UL<<32, + max_pfn<<PAGE_SHIFT); + /* can we preseve max_low_pfn ?*/ + max_low_pfn = max_pfn; + } +#endif /* * NOTE: On x86-32, only from this point on, fixmaps are ready for use. |