diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-26 12:35:46 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-26 12:35:46 -0400 |
| commit | 622f202a4cba7acbd843f22fa67c206c15d45034 (patch) | |
| tree | fa272b824e49a48f595f1faceb79368a6bd634c0 | |
| parent | 6a2e52f844ed0002579e9f6d3e6d6286fa3bd76d (diff) | |
| parent | 8b724e2a12d553cad8ad412846511c783a92d25e (diff) | |
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Ingo Molnar:
"This fixes a couple of nasty page table initialization bugs which were
causing kdump regressions. A clean rearchitecturing of the code is in
the works - meanwhile these are reverts that restore the
best-known-working state of the kernel.
There's also EFI fixes and other small fixes."
* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86, mm: Undo incorrect revert in arch/x86/mm/init.c
x86: efi: Turn off efi_enabled after setup on mixed fw/kernel
x86, mm: Find_early_table_space based on ranges that are actually being mapped
x86, mm: Use memblock memory loop instead of e820_RAM
x86, mm: Trim memory in memblock to be page aligned
x86/irq/ioapic: Check for valid irq_cfg pointer in smp_irq_move_cleanup_interrupt
x86/efi: Fix oops caused by incorrect set_memory_uc() usage
x86-64: Fix page table accounting
Revert "x86/mm: Fix the size calculation of mapping tables"
MAINTAINERS: Add EFI git repository location
| -rw-r--r-- | MAINTAINERS | 1 | ||||
| -rw-r--r-- | arch/x86/include/asm/efi.h | 6 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 3 | ||||
| -rw-r--r-- | arch/x86/kernel/e820.c | 3 | ||||
| -rw-r--r-- | arch/x86/kernel/setup.c | 27 | ||||
| -rw-r--r-- | arch/x86/mm/init.c | 58 | ||||
| -rw-r--r-- | arch/x86/mm/init_64.c | 7 | ||||
| -rw-r--r-- | arch/x86/platform/efi/efi.c | 47 | ||||
| -rw-r--r-- | arch/x86/platform/efi/efi_64.c | 7 | ||||
| -rw-r--r-- | include/linux/memblock.h | 1 | ||||
| -rw-r--r-- | mm/memblock.c | 24 |
11 files changed, 126 insertions, 58 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 027ec2bfa135..f39a82dc0260 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -2802,6 +2802,7 @@ F: sound/usb/misc/ua101.c | |||
| 2802 | EXTENSIBLE FIRMWARE INTERFACE (EFI) | 2802 | EXTENSIBLE FIRMWARE INTERFACE (EFI) |
| 2803 | M: Matt Fleming <matt.fleming@intel.com> | 2803 | M: Matt Fleming <matt.fleming@intel.com> |
| 2804 | L: linux-efi@vger.kernel.org | 2804 | L: linux-efi@vger.kernel.org |
| 2805 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git | ||
| 2805 | S: Maintained | 2806 | S: Maintained |
| 2806 | F: Documentation/x86/efi-stub.txt | 2807 | F: Documentation/x86/efi-stub.txt |
| 2807 | F: arch/ia64/kernel/efi.c | 2808 | F: arch/ia64/kernel/efi.c |
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index c9dcc181d4d1..6e8fdf5ad113 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h | |||
| @@ -35,7 +35,7 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...); | |||
| 35 | #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6) \ | 35 | #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6) \ |
| 36 | efi_call_virt(f, a1, a2, a3, a4, a5, a6) | 36 | efi_call_virt(f, a1, a2, a3, a4, a5, a6) |
| 37 | 37 | ||
| 38 | #define efi_ioremap(addr, size, type) ioremap_cache(addr, size) | 38 | #define efi_ioremap(addr, size, type, attr) ioremap_cache(addr, size) |
| 39 | 39 | ||
| 40 | #else /* !CONFIG_X86_32 */ | 40 | #else /* !CONFIG_X86_32 */ |
| 41 | 41 | ||
| @@ -89,7 +89,7 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3, | |||
| 89 | (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6)) | 89 | (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6)) |
| 90 | 90 | ||
| 91 | extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, | 91 | extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, |
| 92 | u32 type); | 92 | u32 type, u64 attribute); |
| 93 | 93 | ||
| 94 | #endif /* CONFIG_X86_32 */ | 94 | #endif /* CONFIG_X86_32 */ |
| 95 | 95 | ||
| @@ -98,6 +98,8 @@ extern void efi_set_executable(efi_memory_desc_t *md, bool executable); | |||
| 98 | extern int efi_memblock_x86_reserve_range(void); | 98 | extern int efi_memblock_x86_reserve_range(void); |
| 99 | extern void efi_call_phys_prelog(void); | 99 | extern void efi_call_phys_prelog(void); |
| 100 | extern void efi_call_phys_epilog(void); | 100 | extern void efi_call_phys_epilog(void); |
| 101 | extern void efi_unmap_memmap(void); | ||
| 102 | extern void efi_memory_uc(u64 addr, unsigned long size); | ||
| 101 | 103 | ||
| 102 | #ifndef CONFIG_EFI | 104 | #ifndef CONFIG_EFI |
| 103 | /* | 105 | /* |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index c265593ec2cd..1817fa911024 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
| @@ -2257,6 +2257,9 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void) | |||
| 2257 | continue; | 2257 | continue; |
| 2258 | 2258 | ||
| 2259 | cfg = irq_cfg(irq); | 2259 | cfg = irq_cfg(irq); |
| 2260 | if (!cfg) | ||
| 2261 | continue; | ||
| 2262 | |||
| 2260 | raw_spin_lock(&desc->lock); | 2263 | raw_spin_lock(&desc->lock); |
| 2261 | 2264 | ||
| 2262 | /* | 2265 | /* |
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index ed858e9e9a74..df06ade26bef 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c | |||
| @@ -1077,6 +1077,9 @@ void __init memblock_x86_fill(void) | |||
| 1077 | memblock_add(ei->addr, ei->size); | 1077 | memblock_add(ei->addr, ei->size); |
| 1078 | } | 1078 | } |
| 1079 | 1079 | ||
| 1080 | /* throw away partial pages */ | ||
| 1081 | memblock_trim_memory(PAGE_SIZE); | ||
| 1082 | |||
| 1080 | memblock_dump_all(); | 1083 | memblock_dump_all(); |
| 1081 | } | 1084 | } |
| 1082 | 1085 | ||
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 468e98dfd44e..ca45696f30fb 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
| @@ -921,18 +921,19 @@ void __init setup_arch(char **cmdline_p) | |||
| 921 | #ifdef CONFIG_X86_64 | 921 | #ifdef CONFIG_X86_64 |
| 922 | if (max_pfn > max_low_pfn) { | 922 | if (max_pfn > max_low_pfn) { |
| 923 | int i; | 923 | int i; |
| 924 | for (i = 0; i < e820.nr_map; i++) { | 924 | unsigned long start, end; |
| 925 | struct e820entry *ei = &e820.map[i]; | 925 | unsigned long start_pfn, end_pfn; |
| 926 | 926 | ||
| 927 | if (ei->addr + ei->size <= 1UL << 32) | 927 | for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, |
| 928 | continue; | 928 | NULL) { |
| 929 | 929 | ||
| 930 | if (ei->type == E820_RESERVED) | 930 | end = PFN_PHYS(end_pfn); |
| 931 | if (end <= (1UL<<32)) | ||
| 931 | continue; | 932 | continue; |
| 932 | 933 | ||
| 934 | start = PFN_PHYS(start_pfn); | ||
| 933 | max_pfn_mapped = init_memory_mapping( | 935 | max_pfn_mapped = init_memory_mapping( |
| 934 | ei->addr < 1UL << 32 ? 1UL << 32 : ei->addr, | 936 | max((1UL<<32), start), end); |
| 935 | ei->addr + ei->size); | ||
| 936 | } | 937 | } |
| 937 | 938 | ||
| 938 | /* can we preseve max_low_pfn ?*/ | 939 | /* can we preseve max_low_pfn ?*/ |
| @@ -1048,6 +1049,18 @@ void __init setup_arch(char **cmdline_p) | |||
| 1048 | arch_init_ideal_nops(); | 1049 | arch_init_ideal_nops(); |
| 1049 | 1050 | ||
| 1050 | register_refined_jiffies(CLOCK_TICK_RATE); | 1051 | register_refined_jiffies(CLOCK_TICK_RATE); |
| 1052 | |||
| 1053 | #ifdef CONFIG_EFI | ||
| 1054 | /* Once setup is done above, disable efi_enabled on mismatched | ||
| 1055 | * firmware/kernel archtectures since there is no support for | ||
| 1056 | * runtime services. | ||
| 1057 | */ | ||
| 1058 | if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) { | ||
| 1059 | pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n"); | ||
| 1060 | efi_unmap_memmap(); | ||
| 1061 | efi_enabled = 0; | ||
| 1062 | } | ||
| 1063 | #endif | ||
| 1051 | } | 1064 | } |
| 1052 | 1065 | ||
| 1053 | #ifdef CONFIG_X86_32 | 1066 | #ifdef CONFIG_X86_32 |
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index ab1f6a93b527..d7aea41563b3 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c | |||
| @@ -35,40 +35,44 @@ struct map_range { | |||
| 35 | unsigned page_size_mask; | 35 | unsigned page_size_mask; |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | static void __init find_early_table_space(struct map_range *mr, unsigned long end, | 38 | /* |
| 39 | int use_pse, int use_gbpages) | 39 | * First calculate space needed for kernel direct mapping page tables to cover |
| 40 | * mr[0].start to mr[nr_range - 1].end, while accounting for possible 2M and 1GB | ||
| 41 | * pages. Then find enough contiguous space for those page tables. | ||
| 42 | */ | ||
| 43 | static void __init find_early_table_space(struct map_range *mr, int nr_range) | ||
| 40 | { | 44 | { |
| 41 | unsigned long puds, pmds, ptes, tables, start = 0, good_end = end; | 45 | int i; |
| 46 | unsigned long puds = 0, pmds = 0, ptes = 0, tables; | ||
| 47 | unsigned long start = 0, good_end; | ||
| 42 | phys_addr_t base; | 48 | phys_addr_t base; |
| 43 | 49 | ||
| 44 | puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; | 50 | for (i = 0; i < nr_range; i++) { |
| 45 | tables = roundup(puds * sizeof(pud_t), PAGE_SIZE); | 51 | unsigned long range, extra; |
| 46 | |||
| 47 | if (use_gbpages) { | ||
| 48 | unsigned long extra; | ||
| 49 | |||
| 50 | extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT); | ||
| 51 | pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT; | ||
| 52 | } else | ||
| 53 | pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; | ||
| 54 | 52 | ||
| 55 | tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE); | 53 | range = mr[i].end - mr[i].start; |
| 54 | puds += (range + PUD_SIZE - 1) >> PUD_SHIFT; | ||
| 56 | 55 | ||
| 57 | if (use_pse) { | 56 | if (mr[i].page_size_mask & (1 << PG_LEVEL_1G)) { |
| 58 | unsigned long extra; | 57 | extra = range - ((range >> PUD_SHIFT) << PUD_SHIFT); |
| 58 | pmds += (extra + PMD_SIZE - 1) >> PMD_SHIFT; | ||
| 59 | } else { | ||
| 60 | pmds += (range + PMD_SIZE - 1) >> PMD_SHIFT; | ||
| 61 | } | ||
| 59 | 62 | ||
| 60 | extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT); | 63 | if (mr[i].page_size_mask & (1 << PG_LEVEL_2M)) { |
| 64 | extra = range - ((range >> PMD_SHIFT) << PMD_SHIFT); | ||
| 61 | #ifdef CONFIG_X86_32 | 65 | #ifdef CONFIG_X86_32 |
| 62 | extra += PMD_SIZE; | 66 | extra += PMD_SIZE; |
| 63 | #endif | 67 | #endif |
| 64 | /* The first 2/4M doesn't use large pages. */ | 68 | ptes += (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; |
| 65 | if (mr->start < PMD_SIZE) | 69 | } else { |
| 66 | extra += mr->end - mr->start; | 70 | ptes += (range + PAGE_SIZE - 1) >> PAGE_SHIFT; |
| 67 | 71 | } | |
| 68 | ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; | 72 | } |
| 69 | } else | ||
| 70 | ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
| 71 | 73 | ||
| 74 | tables = roundup(puds * sizeof(pud_t), PAGE_SIZE); | ||
| 75 | tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE); | ||
| 72 | tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE); | 76 | tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE); |
| 73 | 77 | ||
| 74 | #ifdef CONFIG_X86_32 | 78 | #ifdef CONFIG_X86_32 |
| @@ -86,7 +90,7 @@ static void __init find_early_table_space(struct map_range *mr, unsigned long en | |||
| 86 | pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT); | 90 | pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT); |
| 87 | 91 | ||
| 88 | printk(KERN_DEBUG "kernel direct mapping tables up to %#lx @ [mem %#010lx-%#010lx]\n", | 92 | printk(KERN_DEBUG "kernel direct mapping tables up to %#lx @ [mem %#010lx-%#010lx]\n", |
| 89 | end - 1, pgt_buf_start << PAGE_SHIFT, | 93 | mr[nr_range - 1].end - 1, pgt_buf_start << PAGE_SHIFT, |
| 90 | (pgt_buf_top << PAGE_SHIFT) - 1); | 94 | (pgt_buf_top << PAGE_SHIFT) - 1); |
| 91 | } | 95 | } |
| 92 | 96 | ||
| @@ -267,7 +271,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, | |||
| 267 | * nodes are discovered. | 271 | * nodes are discovered. |
| 268 | */ | 272 | */ |
| 269 | if (!after_bootmem) | 273 | if (!after_bootmem) |
| 270 | find_early_table_space(&mr[0], end, use_pse, use_gbpages); | 274 | find_early_table_space(mr, nr_range); |
| 271 | 275 | ||
| 272 | for (i = 0; i < nr_range; i++) | 276 | for (i = 0; i < nr_range; i++) |
| 273 | ret = kernel_physical_mapping_init(mr[i].start, mr[i].end, | 277 | ret = kernel_physical_mapping_init(mr[i].start, mr[i].end, |
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 2b6b4a3c8beb..3baff255adac 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
| @@ -386,7 +386,8 @@ phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end, | |||
| 386 | * these mappings are more intelligent. | 386 | * these mappings are more intelligent. |
| 387 | */ | 387 | */ |
| 388 | if (pte_val(*pte)) { | 388 | if (pte_val(*pte)) { |
| 389 | pages++; | 389 | if (!after_bootmem) |
| 390 | pages++; | ||
| 390 | continue; | 391 | continue; |
| 391 | } | 392 | } |
| 392 | 393 | ||
| @@ -451,6 +452,8 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, | |||
| 451 | * attributes. | 452 | * attributes. |
| 452 | */ | 453 | */ |
| 453 | if (page_size_mask & (1 << PG_LEVEL_2M)) { | 454 | if (page_size_mask & (1 << PG_LEVEL_2M)) { |
| 455 | if (!after_bootmem) | ||
| 456 | pages++; | ||
| 454 | last_map_addr = next; | 457 | last_map_addr = next; |
| 455 | continue; | 458 | continue; |
| 456 | } | 459 | } |
| @@ -526,6 +529,8 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, | |||
| 526 | * attributes. | 529 | * attributes. |
| 527 | */ | 530 | */ |
| 528 | if (page_size_mask & (1 << PG_LEVEL_1G)) { | 531 | if (page_size_mask & (1 << PG_LEVEL_1G)) { |
| 532 | if (!after_bootmem) | ||
| 533 | pages++; | ||
| 529 | last_map_addr = next; | 534 | last_map_addr = next; |
| 530 | continue; | 535 | continue; |
| 531 | } | 536 | } |
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index aded2a91162a..ad4439145f85 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
| @@ -70,11 +70,15 @@ EXPORT_SYMBOL(efi); | |||
| 70 | struct efi_memory_map memmap; | 70 | struct efi_memory_map memmap; |
| 71 | 71 | ||
| 72 | bool efi_64bit; | 72 | bool efi_64bit; |
| 73 | static bool efi_native; | ||
| 74 | 73 | ||
| 75 | static struct efi efi_phys __initdata; | 74 | static struct efi efi_phys __initdata; |
| 76 | static efi_system_table_t efi_systab __initdata; | 75 | static efi_system_table_t efi_systab __initdata; |
| 77 | 76 | ||
| 77 | static inline bool efi_is_native(void) | ||
| 78 | { | ||
| 79 | return IS_ENABLED(CONFIG_X86_64) == efi_64bit; | ||
| 80 | } | ||
| 81 | |||
| 78 | static int __init setup_noefi(char *arg) | 82 | static int __init setup_noefi(char *arg) |
| 79 | { | 83 | { |
| 80 | efi_enabled = 0; | 84 | efi_enabled = 0; |
| @@ -420,7 +424,7 @@ void __init efi_reserve_boot_services(void) | |||
| 420 | } | 424 | } |
| 421 | } | 425 | } |
| 422 | 426 | ||
| 423 | static void __init efi_unmap_memmap(void) | 427 | void __init efi_unmap_memmap(void) |
| 424 | { | 428 | { |
| 425 | if (memmap.map) { | 429 | if (memmap.map) { |
| 426 | early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); | 430 | early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); |
| @@ -432,7 +436,7 @@ void __init efi_free_boot_services(void) | |||
| 432 | { | 436 | { |
| 433 | void *p; | 437 | void *p; |
| 434 | 438 | ||
| 435 | if (!efi_native) | 439 | if (!efi_is_native()) |
| 436 | return; | 440 | return; |
| 437 | 441 | ||
| 438 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 442 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
| @@ -684,12 +688,10 @@ void __init efi_init(void) | |||
| 684 | return; | 688 | return; |
| 685 | } | 689 | } |
| 686 | efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; | 690 | efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; |
| 687 | efi_native = !efi_64bit; | ||
| 688 | #else | 691 | #else |
| 689 | efi_phys.systab = (efi_system_table_t *) | 692 | efi_phys.systab = (efi_system_table_t *) |
| 690 | (boot_params.efi_info.efi_systab | | 693 | (boot_params.efi_info.efi_systab | |
| 691 | ((__u64)boot_params.efi_info.efi_systab_hi<<32)); | 694 | ((__u64)boot_params.efi_info.efi_systab_hi<<32)); |
| 692 | efi_native = efi_64bit; | ||
| 693 | #endif | 695 | #endif |
| 694 | 696 | ||
| 695 | if (efi_systab_init(efi_phys.systab)) { | 697 | if (efi_systab_init(efi_phys.systab)) { |
| @@ -723,7 +725,7 @@ void __init efi_init(void) | |||
| 723 | * that doesn't match the kernel 32/64-bit mode. | 725 | * that doesn't match the kernel 32/64-bit mode. |
| 724 | */ | 726 | */ |
| 725 | 727 | ||
| 726 | if (!efi_native) | 728 | if (!efi_is_native()) |
| 727 | pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); | 729 | pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); |
| 728 | else if (efi_runtime_init()) { | 730 | else if (efi_runtime_init()) { |
| 729 | efi_enabled = 0; | 731 | efi_enabled = 0; |
| @@ -735,7 +737,7 @@ void __init efi_init(void) | |||
| 735 | return; | 737 | return; |
| 736 | } | 738 | } |
| 737 | #ifdef CONFIG_X86_32 | 739 | #ifdef CONFIG_X86_32 |
| 738 | if (efi_native) { | 740 | if (efi_is_native()) { |
| 739 | x86_platform.get_wallclock = efi_get_time; | 741 | x86_platform.get_wallclock = efi_get_time; |
| 740 | x86_platform.set_wallclock = efi_set_rtc_mmss; | 742 | x86_platform.set_wallclock = efi_set_rtc_mmss; |
| 741 | } | 743 | } |
| @@ -810,6 +812,16 @@ void __iomem *efi_lookup_mapped_addr(u64 phys_addr) | |||
| 810 | return NULL; | 812 | return NULL; |
| 811 | } | 813 | } |
| 812 | 814 | ||
| 815 | void efi_memory_uc(u64 addr, unsigned long size) | ||
| 816 | { | ||
| 817 | unsigned long page_shift = 1UL << EFI_PAGE_SHIFT; | ||
| 818 | u64 npages; | ||
| 819 | |||
| 820 | npages = round_up(size, page_shift) / page_shift; | ||
| 821 | memrange_efi_to_native(&addr, &npages); | ||
| 822 | set_memory_uc(addr, npages); | ||
| 823 | } | ||
| 824 | |||
| 813 | /* | 825 | /* |
| 814 | * This function will switch the EFI runtime services to virtual mode. | 826 | * This function will switch the EFI runtime services to virtual mode. |
| 815 | * Essentially, look through the EFI memmap and map every region that | 827 | * Essentially, look through the EFI memmap and map every region that |
| @@ -823,7 +835,7 @@ void __init efi_enter_virtual_mode(void) | |||
| 823 | efi_memory_desc_t *md, *prev_md = NULL; | 835 | efi_memory_desc_t *md, *prev_md = NULL; |
| 824 | efi_status_t status; | 836 | efi_status_t status; |
| 825 | unsigned long size; | 837 | unsigned long size; |
| 826 | u64 end, systab, addr, npages, end_pfn; | 838 | u64 end, systab, end_pfn; |
| 827 | void *p, *va, *new_memmap = NULL; | 839 | void *p, *va, *new_memmap = NULL; |
| 828 | int count = 0; | 840 | int count = 0; |
| 829 | 841 | ||
| @@ -834,7 +846,7 @@ void __init efi_enter_virtual_mode(void) | |||
| 834 | * non-native EFI | 846 | * non-native EFI |
| 835 | */ | 847 | */ |
| 836 | 848 | ||
| 837 | if (!efi_native) { | 849 | if (!efi_is_native()) { |
| 838 | efi_unmap_memmap(); | 850 | efi_unmap_memmap(); |
| 839 | return; | 851 | return; |
| 840 | } | 852 | } |
| @@ -879,10 +891,14 @@ void __init efi_enter_virtual_mode(void) | |||
| 879 | end_pfn = PFN_UP(end); | 891 | end_pfn = PFN_UP(end); |
| 880 | if (end_pfn <= max_low_pfn_mapped | 892 | if (end_pfn <= max_low_pfn_mapped |
| 881 | || (end_pfn > (1UL << (32 - PAGE_SHIFT)) | 893 | || (end_pfn > (1UL << (32 - PAGE_SHIFT)) |
| 882 | && end_pfn <= max_pfn_mapped)) | 894 | && end_pfn <= max_pfn_mapped)) { |
| 883 | va = __va(md->phys_addr); | 895 | va = __va(md->phys_addr); |
| 884 | else | 896 | |
| 885 | va = efi_ioremap(md->phys_addr, size, md->type); | 897 | if (!(md->attribute & EFI_MEMORY_WB)) |
| 898 | efi_memory_uc((u64)(unsigned long)va, size); | ||
| 899 | } else | ||
| 900 | va = efi_ioremap(md->phys_addr, size, | ||
| 901 | md->type, md->attribute); | ||
| 886 | 902 | ||
| 887 | md->virt_addr = (u64) (unsigned long) va; | 903 | md->virt_addr = (u64) (unsigned long) va; |
| 888 | 904 | ||
| @@ -892,13 +908,6 @@ void __init efi_enter_virtual_mode(void) | |||
| 892 | continue; | 908 | continue; |
| 893 | } | 909 | } |
| 894 | 910 | ||
| 895 | if (!(md->attribute & EFI_MEMORY_WB)) { | ||
| 896 | addr = md->virt_addr; | ||
| 897 | npages = md->num_pages; | ||
| 898 | memrange_efi_to_native(&addr, &npages); | ||
| 899 | set_memory_uc(addr, npages); | ||
| 900 | } | ||
| 901 | |||
| 902 | systab = (u64) (unsigned long) efi_phys.systab; | 911 | systab = (u64) (unsigned long) efi_phys.systab; |
| 903 | if (md->phys_addr <= systab && systab < end) { | 912 | if (md->phys_addr <= systab && systab < end) { |
| 904 | systab += md->virt_addr - md->phys_addr; | 913 | systab += md->virt_addr - md->phys_addr; |
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index ac3aa54e2654..95fd505dfeb6 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c | |||
| @@ -82,7 +82,7 @@ void __init efi_call_phys_epilog(void) | |||
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, | 84 | void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, |
| 85 | u32 type) | 85 | u32 type, u64 attribute) |
| 86 | { | 86 | { |
| 87 | unsigned long last_map_pfn; | 87 | unsigned long last_map_pfn; |
| 88 | 88 | ||
| @@ -92,8 +92,11 @@ void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, | |||
| 92 | last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size); | 92 | last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size); |
| 93 | if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size) { | 93 | if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size) { |
| 94 | unsigned long top = last_map_pfn << PAGE_SHIFT; | 94 | unsigned long top = last_map_pfn << PAGE_SHIFT; |
| 95 | efi_ioremap(top, size - (top - phys_addr), type); | 95 | efi_ioremap(top, size - (top - phys_addr), type, attribute); |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | if (!(attribute & EFI_MEMORY_WB)) | ||
| 99 | efi_memory_uc((u64)(unsigned long)__va(phys_addr), size); | ||
| 100 | |||
| 98 | return (void __iomem *)__va(phys_addr); | 101 | return (void __iomem *)__va(phys_addr); |
| 99 | } | 102 | } |
diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 569d67d4243e..d452ee191066 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h | |||
| @@ -57,6 +57,7 @@ int memblock_add(phys_addr_t base, phys_addr_t size); | |||
| 57 | int memblock_remove(phys_addr_t base, phys_addr_t size); | 57 | int memblock_remove(phys_addr_t base, phys_addr_t size); |
| 58 | int memblock_free(phys_addr_t base, phys_addr_t size); | 58 | int memblock_free(phys_addr_t base, phys_addr_t size); |
| 59 | int memblock_reserve(phys_addr_t base, phys_addr_t size); | 59 | int memblock_reserve(phys_addr_t base, phys_addr_t size); |
| 60 | void memblock_trim_memory(phys_addr_t align); | ||
| 60 | 61 | ||
| 61 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP | 62 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP |
| 62 | void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn, | 63 | void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn, |
diff --git a/mm/memblock.c b/mm/memblock.c index 931eef145af5..625905523c2a 100644 --- a/mm/memblock.c +++ b/mm/memblock.c | |||
| @@ -930,6 +930,30 @@ int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t si | |||
| 930 | return memblock_overlaps_region(&memblock.reserved, base, size) >= 0; | 930 | return memblock_overlaps_region(&memblock.reserved, base, size) >= 0; |
| 931 | } | 931 | } |
| 932 | 932 | ||
| 933 | void __init_memblock memblock_trim_memory(phys_addr_t align) | ||
| 934 | { | ||
| 935 | int i; | ||
| 936 | phys_addr_t start, end, orig_start, orig_end; | ||
| 937 | struct memblock_type *mem = &memblock.memory; | ||
| 938 | |||
| 939 | for (i = 0; i < mem->cnt; i++) { | ||
| 940 | orig_start = mem->regions[i].base; | ||
| 941 | orig_end = mem->regions[i].base + mem->regions[i].size; | ||
| 942 | start = round_up(orig_start, align); | ||
| 943 | end = round_down(orig_end, align); | ||
| 944 | |||
| 945 | if (start == orig_start && end == orig_end) | ||
| 946 | continue; | ||
| 947 | |||
| 948 | if (start < end) { | ||
| 949 | mem->regions[i].base = start; | ||
| 950 | mem->regions[i].size = end - start; | ||
| 951 | } else { | ||
| 952 | memblock_remove_region(mem, i); | ||
| 953 | i--; | ||
| 954 | } | ||
| 955 | } | ||
| 956 | } | ||
| 933 | 957 | ||
| 934 | void __init_memblock memblock_set_current_limit(phys_addr_t limit) | 958 | void __init_memblock memblock_set_current_limit(phys_addr_t limit) |
| 935 | { | 959 | { |
