aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYinghai Lu <yhlu.kernel@gmail.com>2008-07-10 23:38:26 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-11 04:24:04 -0400
commitf361a450bf1ad14e2b003217dbf3958638631265 (patch)
tree10c1e4dcc0047f6c37387cada6a0bceba088d2d2
parentf302a5bbe5eb95f3d4227d5bd0e9b92b1b125f4f (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>
-rw-r--r--arch/x86/kernel/acpi/boot.c2
-rw-r--r--arch/x86/kernel/cpu/amd_64.c10
-rw-r--r--arch/x86/kernel/e820.c23
-rw-r--r--arch/x86/kernel/efi.c2
-rw-r--r--arch/x86/kernel/setup.c22
-rw-r--r--arch/x86/mm/init_32.c1
-rw-r--r--arch/x86/mm/init_64.c1
-rw-r--r--arch/x86/mm/pageattr.c19
-rw-r--r--arch/x86/mm/pat.c3
-rw-r--r--arch/x86/pci/i386.c4
-rw-r--r--include/asm-x86/e820.h3
-rw-r--r--include/asm-x86/page.h1
12 files changed, 74 insertions, 17 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)
130 if (!phys || !size) 130 if (!phys || !size)
131 return NULL; 131 return NULL;
132 132
133 if (phys+size <= (max_pfn_mapped << PAGE_SHIFT)) 133 if (phys+size <= (max_low_pfn_mapped << PAGE_SHIFT))
134 return __va(phys); 134 return __va(phys);
135 135
136 offset = phys & (PAGE_SIZE - 1); 136 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)
199 * Don't do it for gbpages because there seems very little 199 * Don't do it for gbpages because there seems very little
200 * benefit in doing so. 200 * benefit in doing so.
201 */ 201 */
202 if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg) && 202 if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg)) {
203 (tseg >> PMD_SHIFT) < 203 if ((tseg>>PMD_SHIFT) <
204 (max_pfn_mapped >> (PMD_SHIFT-PAGE_SHIFT))) 204 (max_low_pfn_mapped>>(PMD_SHIFT-PAGE_SHIFT)) ||
205 ((tseg>>PMD_SHIFT) <
206 (max_pfn_mapped>>(PMD_SHIFT-PAGE_SHIFT)) &&
207 (tseg>>PMD_SHIFT) >= (1ULL<<(32 - PMD_SHIFT))))
205 set_memory_4k((unsigned long)__va(tseg), 1); 208 set_memory_4k((unsigned long)__va(tseg), 1);
209 }
206 } 210 }
207} 211}
208 212
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;
1056/* 1056/*
1057 * Find the highest page frame number we have available 1057 * Find the highest page frame number we have available
1058 */ 1058 */
1059unsigned long __init e820_end(void) 1059static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type)
1060{ 1060{
1061 int i; 1061 int i;
1062 unsigned long last_pfn = 0; 1062 unsigned long last_pfn = 0;
@@ -1064,12 +1064,21 @@ unsigned long __init e820_end(void)
1064 1064
1065 for (i = 0; i < e820.nr_map; i++) { 1065 for (i = 0; i < e820.nr_map; i++) {
1066 struct e820entry *ei = &e820.map[i]; 1066 struct e820entry *ei = &e820.map[i];
1067 unsigned long start_pfn;
1067 unsigned long end_pfn; 1068 unsigned long end_pfn;
1068 1069
1069 if (ei->type != E820_RAM) 1070 if (ei->type != type)
1070 continue; 1071 continue;
1071 1072
1073 start_pfn = ei->addr >> PAGE_SHIFT;
1072 end_pfn = (ei->addr + ei->size) >> PAGE_SHIFT; 1074 end_pfn = (ei->addr + ei->size) >> PAGE_SHIFT;
1075
1076 if (start_pfn >= limit_pfn)
1077 continue;
1078 if (end_pfn > limit_pfn) {
1079 last_pfn = limit_pfn;
1080 break;
1081 }
1073 if (end_pfn > last_pfn) 1082 if (end_pfn > last_pfn)
1074 last_pfn = end_pfn; 1083 last_pfn = end_pfn;
1075 } 1084 }
@@ -1083,7 +1092,15 @@ unsigned long __init e820_end(void)
1083 last_pfn, max_arch_pfn); 1092 last_pfn, max_arch_pfn);
1084 return last_pfn; 1093 return last_pfn;
1085} 1094}
1095unsigned long __init e820_end_of_ram_pfn(void)
1096{
1097 return e820_end_pfn(MAX_ARCH_PFN, E820_RAM);
1098}
1086 1099
1100unsigned long __init e820_end_of_low_ram_pfn(void)
1101{
1102 return e820_end_pfn(1UL<<(32 - PAGE_SHIFT), E820_RAM);
1103}
1087/* 1104/*
1088 * Finds an active region in the address range from start_pfn to last_pfn and 1105 * Finds an active region in the address range from start_pfn to last_pfn and
1089 * returns its range in ei_startpfn and ei_endpfn for the e820 entry. 1106 * 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)
1206 * the real mem size before original memory map is 1223 * the real mem size before original memory map is
1207 * reset. 1224 * reset.
1208 */ 1225 */
1209 saved_max_pfn = e820_end(); 1226 saved_max_pfn = e820_end_of_ram_pfn();
1210#endif 1227#endif
1211 e820.nr_map = 0; 1228 e820.nr_map = 0;
1212 userdef = 1; 1229 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)
473 size = md->num_pages << EFI_PAGE_SHIFT; 473 size = md->num_pages << EFI_PAGE_SHIFT;
474 end = md->phys_addr + size; 474 end = md->phys_addr + size;
475 475
476 if (PFN_UP(end) <= max_pfn_mapped) 476 if (PFN_UP(end) <= max_low_pfn_mapped)
477 va = __va(md->phys_addr); 477 va = __va(md->phys_addr);
478 else 478 else
479 va = efi_ioremap(md->phys_addr, size); 479 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)
713 * partially used pages are not usable - thus 713 * partially used pages are not usable - thus
714 * we are rounding upwards: 714 * we are rounding upwards:
715 */ 715 */
716 max_pfn = e820_end(); 716 max_pfn = e820_end_of_ram_pfn();
717 717
718 /* preallocate 4k for mptable mpc */ 718 /* preallocate 4k for mptable mpc */
719 early_reserve_e820_mpc_new(); 719 early_reserve_e820_mpc_new();
720 /* update e820 for memory not covered by WB MTRRs */ 720 /* update e820 for memory not covered by WB MTRRs */
721 mtrr_bp_init(); 721 mtrr_bp_init();
722 if (mtrr_trim_uncached_memory(max_pfn)) 722 if (mtrr_trim_uncached_memory(max_pfn))
723 max_pfn = e820_end(); 723 max_pfn = e820_end_of_ram_pfn();
724 724
725#ifdef CONFIG_X86_32 725#ifdef CONFIG_X86_32
726 /* max_low_pfn get updated here */ 726 /* max_low_pfn get updated here */
@@ -732,12 +732,26 @@ void __init setup_arch(char **cmdline_p)
732 732
733 /* How many end-of-memory variables you have, grandma! */ 733 /* How many end-of-memory variables you have, grandma! */
734 /* need this before calling reserve_initrd */ 734 /* need this before calling reserve_initrd */
735 max_low_pfn = max_pfn; 735 if (max_pfn > (1UL<<(32 - PAGE_SHIFT)))
736 max_low_pfn = e820_end_of_low_ram_pfn();
737 else
738 max_low_pfn = max_pfn;
739
736 high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1; 740 high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
737#endif 741#endif
738 742
739 /* max_pfn_mapped is updated here */ 743 /* max_pfn_mapped is updated here */
740 max_pfn_mapped = init_memory_mapping(0, (max_low_pfn << PAGE_SHIFT)); 744 max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT);
745 max_pfn_mapped = max_low_pfn_mapped;
746
747#ifdef CONFIG_X86_64
748 if (max_pfn > max_low_pfn) {
749 max_pfn_mapped = init_memory_mapping(1UL<<32,
750 max_pfn<<PAGE_SHIFT);
751 /* can we preseve max_low_pfn ?*/
752 max_low_pfn = max_pfn;
753 }
754#endif
741 755
742 /* 756 /*
743 * NOTE: On x86-32, only from this point on, fixmaps are ready for use. 757 * NOTE: On x86-32, only from this point on, fixmaps are ready for use.
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index b5a0fd5f4c5f..029e8cffca9e 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -50,6 +50,7 @@
50 50
51unsigned int __VMALLOC_RESERVE = 128 << 20; 51unsigned int __VMALLOC_RESERVE = 128 << 20;
52 52
53unsigned long max_low_pfn_mapped;
53unsigned long max_pfn_mapped; 54unsigned long max_pfn_mapped;
54 55
55DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); 56DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 48548ef7ddf8..122bcef222fc 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -53,6 +53,7 @@
53 * The direct mapping extends to max_pfn_mapped, so that we can directly access 53 * The direct mapping extends to max_pfn_mapped, so that we can directly access
54 * apertures, ACPI and other tables without having to play with fixmaps. 54 * apertures, ACPI and other tables without having to play with fixmaps.
55 */ 55 */
56unsigned long max_low_pfn_mapped;
56unsigned long max_pfn_mapped; 57unsigned long max_pfn_mapped;
57 58
58static unsigned long dma_reserve __initdata; 59static unsigned long dma_reserve __initdata;
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index afd40054d157..0389cb8f6b1a 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -536,8 +536,14 @@ static int split_large_page(pte_t *kpte, unsigned long address)
536 set_pte(&pbase[i], pfn_pte(pfn, ref_prot)); 536 set_pte(&pbase[i], pfn_pte(pfn, ref_prot));
537 537
538 if (address >= (unsigned long)__va(0) && 538 if (address >= (unsigned long)__va(0) &&
539 address < (unsigned long)__va(max_low_pfn_mapped << PAGE_SHIFT))
540 split_page_count(level);
541
542#ifdef CONFIG_X86_64
543 if (address >= (unsigned long)__va(1UL<<32) &&
539 address < (unsigned long)__va(max_pfn_mapped << PAGE_SHIFT)) 544 address < (unsigned long)__va(max_pfn_mapped << PAGE_SHIFT))
540 split_page_count(level); 545 split_page_count(level);
546#endif
541 547
542 /* 548 /*
543 * Install the new, split up pagetable. Important details here: 549 * Install the new, split up pagetable. Important details here:
@@ -655,12 +661,21 @@ static int cpa_process_alias(struct cpa_data *cpa)
655 if (cpa->pfn > max_pfn_mapped) 661 if (cpa->pfn > max_pfn_mapped)
656 return 0; 662 return 0;
657 663
664#ifdef CONFIG_X86_64
665 if (cpa->pfn > max_low_pfn_mapped && cpa->pfn < (1UL<<(32-PAGE_SHIFT)))
666 return 0;
667#endif
658 /* 668 /*
659 * No need to redo, when the primary call touched the direct 669 * No need to redo, when the primary call touched the direct
660 * mapping already: 670 * mapping already:
661 */ 671 */
662 if (!within(cpa->vaddr, PAGE_OFFSET, 672 if (!(within(cpa->vaddr, PAGE_OFFSET,
663 PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT))) { 673 PAGE_OFFSET + (max_low_pfn_mapped << PAGE_SHIFT))
674#ifdef CONFIG_X86_64
675 || within(cpa->vaddr, PAGE_OFFSET + (1UL<<32),
676 PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT))
677#endif
678 )) {
664 679
665 alias_cpa = *cpa; 680 alias_cpa = *cpa;
666 alias_cpa.vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT); 681 alias_cpa.vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT);
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index a885a1019b8a..749766c3c5cd 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -449,7 +449,8 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
449 if (retval < 0) 449 if (retval < 0)
450 return 0; 450 return 0;
451 451
452 if (pfn <= max_pfn_mapped && 452 if (((pfn <= max_low_pfn_mapped) ||
453 (pfn >= (1UL<<(32 - PAGE_SHIFT)) && pfn <= max_pfn_mapped)) &&
453 ioremap_change_attr((unsigned long)__va(offset), size, flags) < 0) { 454 ioremap_change_attr((unsigned long)__va(offset), size, flags) < 0) {
454 free_memtype(offset, offset + size); 455 free_memtype(offset, offset + size);
455 printk(KERN_INFO 456 printk(KERN_INFO
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 6ccd7a108cd4..5281e343dd9f 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -334,7 +334,9 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
334 flags = new_flags; 334 flags = new_flags;
335 } 335 }
336 336
337 if (vma->vm_pgoff <= max_pfn_mapped && 337 if (((vma->vm_pgoff <= max_low_pfn_mapped) ||
338 (vma->vm_pgoff >= (1UL<<(32 - PAGE_SHIFT)) &&
339 vma->vm_pgoff <= max_pfn_mapped)) &&
338 ioremap_change_attr((unsigned long)__va(addr), len, flags)) { 340 ioremap_change_attr((unsigned long)__va(addr), len, flags)) {
339 free_memtype(addr, addr + len); 341 free_memtype(addr, addr + len);
340 return -EINVAL; 342 return -EINVAL;
diff --git a/include/asm-x86/e820.h b/include/asm-x86/e820.h
index 78c03d7bf441..33e793e991d0 100644
--- a/include/asm-x86/e820.h
+++ b/include/asm-x86/e820.h
@@ -99,7 +99,8 @@ extern void free_early(u64 start, u64 end);
99extern void early_res_to_bootmem(u64 start, u64 end); 99extern void early_res_to_bootmem(u64 start, u64 end);
100extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align); 100extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align);
101 101
102extern unsigned long e820_end(void); 102extern unsigned long e820_end_of_ram_pfn(void);
103extern unsigned long e820_end_of_low_ram_pfn(void);
103extern int e820_find_active_region(const struct e820entry *ei, 104extern int e820_find_active_region(const struct e820entry *ei,
104 unsigned long start_pfn, 105 unsigned long start_pfn,
105 unsigned long last_pfn, 106 unsigned long last_pfn,
diff --git a/include/asm-x86/page.h b/include/asm-x86/page.h
index b52ed85f32f5..28d7b4533b1a 100644
--- a/include/asm-x86/page.h
+++ b/include/asm-x86/page.h
@@ -61,6 +61,7 @@ extern void map_devmem(unsigned long pfn, unsigned long size,
61extern void unmap_devmem(unsigned long pfn, unsigned long size, 61extern void unmap_devmem(unsigned long pfn, unsigned long size,
62 pgprot_t vma_prot); 62 pgprot_t vma_prot);
63 63
64extern unsigned long max_low_pfn_mapped;
64extern unsigned long max_pfn_mapped; 65extern unsigned long max_pfn_mapped;
65 66
66struct page; 67struct page;