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); |
