x86 fixes
Subsystems (5)
Linus,
Please pull the latest x86-urgent-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-urgent-for-linus
HEAD: 8b724e2a12d553cad8ad412846511c783a92d25e Merge tag 'efi-for-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi into x86/urgent
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.
out-of-topic modifications in x86-urgent-for-linus:
---------------------------------------------------
MAINTAINERS # 78bef24: MAINTAINERS: Add EFI git reposito include/linux/memblock.h # 6ede1fd: x86, mm: Trim memory in memblock mm/memblock.c # 6ede1fd: x86, mm: Trim memory in memblock
Thanks,
Ingo
------------------>
Dave Young (1):
Revert "x86/mm: Fix the size calculation of mapping tables"
Dimitri Sivanich (1):
x86/irq/ioapic: Check for valid irq_cfg pointer in smp_irq_move_cleanup_interrupt
Jacob Shin (1):
x86, mm: Find_early_table_space based on ranges that are actually being mapped
Jan Beulich (1):
x86-64: Fix page table accounting
Matt Fleming (2):
MAINTAINERS: Add EFI git repository location x86/efi: Fix oops caused by incorrect set_memory_uc() usage
Olof Johansson (1):
x86: efi: Turn off efi_enabled after setup on mixed fw/kernel
Yinghai Lu (3):
x86, mm: Trim memory in memblock to be page aligned x86, mm: Use memblock memory loop instead of e820_RAM x86, mm: Undo incorrect revert in arch/x86/mm/init.c
MAINTAINERS | 1 + arch/x86/include/asm/efi.h | 6 +++-- arch/x86/kernel/apic/io_apic.c | 3 +++ arch/x86/kernel/e820.c | 3 +++ arch/x86/kernel/setup.c | 27 +++++++++++++++----- arch/x86/mm/init.c | 58 ++++++++++++++++++++++-------------------- arch/x86/mm/init_64.c | 7 ++++- arch/x86/platform/efi/efi.c | 47 ++++++++++++++++++++-------------- arch/x86/platform/efi/efi_64.c | 7 +++-- include/linux/memblock.h | 1 + mm/memblock.c | 24 +++++++++++++++++ 11 files changed, 126 insertions(+), 58 deletions(-)
MAINTAINERS +1 -0
@@ -2802,6 +2802,7 @@ F: sound/usb/misc/ua101.c EXTENSIBLE FIRMWARE INTERFACE (EFI) M: Matt Fleming <[email protected]> L: [email protected] +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git S: Maintained F: Documentation/x86/efi-stub.txt F: arch/ia64/kernel/efi.c
arch/x86/include/asm/efi.h +4 -2
@@ -35,7 +35,7 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...);#define efi_call_virt6 (f, a1, a2, a3, a4, a5, a6) \ efi_call_virt(f, a1, a2, a3, a4, a5, a6) -#define efi_ioremap (addr, size, type) ioremap_cache(addr, size) +#define efi_ioremap (addr, size, type, attr) ioremap_cache(addr, size)#else /* !CONFIG_X86_32 */
@@ -89,7 +89,7 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3, (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))extern void __iomem *efi_ioremap (unsigned long addr,unsigned long size, -u32 type); +u32 type,u64 attribute);#endif /* CONFIG_X86_32 */
@@ -98,6 +98,8 @@ extern void efi_set_executable(efi_memory_desc_t *md, bool executable);extern int efi_memblock_x86_reserve_range (void );extern void efi_call_phys_prelog (void );extern void efi_call_phys_epilog (void ); +extern void efi_unmap_memmap (void ); +extern void efi_memory_uc (u64 addr,unsigned long size);#ifndef CONFIG_EFI /*
arch/x86/kernel/apic/io_apic.c +3 -0
@@ -2257,6 +2257,9 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)continue ; cfg =irq_cfg (irq); +if (!cfg) +continue ; +raw_spin_lock (&desc->lock);/*
arch/x86/kernel/e820.c +3 -0
@@ -1077,6 +1077,9 @@ void __init memblock_x86_fill(void)memblock_add (ei->addr, ei->size); } +/* throw away partial pages */ +memblock_trim_memory (PAGE_SIZE ); +memblock_dump_all (); }
arch/x86/kernel/setup.c +20 -7
@@ -921,18 +921,19 @@ void __init setup_arch(char **cmdline_p)#ifdef CONFIG_X86_64 if (max_pfn > max_low_pfn) {int i; -for (i =0 ; i < e820.nr_map; i++) { -struct e820entry *ei = &e820.map[i]; +unsigned long start, end; +unsigned long start_pfn, end_pfn; -if (ei->addr + ei->size <=1UL <<32 ) -continue ; +for_each_mem_pfn_range (i,MAX_NUMNODES , &start_pfn, &end_pfn, +NULL ) { -if (ei->type ==E820_RESERVED ) + end =PFN_PHYS (end_pfn); +if (end <= (1UL <<32 ))continue ; + start =PFN_PHYS (start_pfn); max_pfn_mapped =init_memory_mapping ( - ei->addr <1UL <<32 ?1UL <<32 : ei->addr, - ei->addr + ei->size); +max ((1UL <<32 ), start), end); }/* can we preseve max_low_pfn ?*/
@@ -1048,6 +1049,18 @@ void __init setup_arch(char **cmdline_p)arch_init_ideal_nops ();register_refined_jiffies (CLOCK_TICK_RATE ); + +#ifdef CONFIG_EFI +/* Once setup is done above, disable efi_enabled on mismatched +* firmware/kernel archtectures since there is no support for +* runtime services. +*/ +if (efi_enabled &&IS_ENABLED (CONFIG_X86_64 ) != efi_64bit) { +pr_info ("efi: Setup done, disabling due to 32/64-bit mismatch\n" ); +efi_unmap_memmap (); + efi_enabled =0 ; + } +#endif }#ifdef CONFIG_X86_32
arch/x86/mm/init.c +31 -27
85 lines not on this page · raw message
arch/x86/mm/init_64.c +6 -1
@@ -386,7 +386,8 @@ phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end,* these mappings are more intelligent. */ if (pte_val (*pte)) { - pages++; +if (!after_bootmem) + pages++;continue ; }
@@ -451,6 +452,8 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,* attributes. */ if (page_size_mask & (1 <<PG_LEVEL_2M )) { +if (!after_bootmem) + pages++; last_map_addr = next;continue ; }
@@ -526,6 +529,8 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,* attributes. */ if (page_size_mask & (1 <<PG_LEVEL_1G )) { +if (!after_bootmem) + pages++; last_map_addr = next;continue ; }
arch/x86/platform/efi/efi.c +28 -19
122 lines not on this page · raw message
arch/x86/platform/efi/efi_64.c +5 -2
@@ -82,7 +82,7 @@ void __init efi_call_phys_epilog(void) }void __iomem *__init efi_ioremap (unsigned long phys_addr,unsigned long size, -u32 type) +u32 type,u64 attribute) {unsigned long last_map_pfn;
@@ -92,8 +92,11 @@ void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, last_map_pfn =init_memory_mapping (phys_addr, phys_addr + size);if ((last_map_pfn <<PAGE_SHIFT ) < phys_addr + size) {unsigned long top = last_map_pfn <<PAGE_SHIFT ; -efi_ioremap (top, size - (top - phys_addr), type); +efi_ioremap (top, size - (top - phys_addr), type, attribute); } +if (!(attribute &EFI_MEMORY_WB )) +efi_memory_uc ((u64 )(unsigned long )__va (phys_addr), size); +return (void __iomem *)__va (phys_addr); }
include/linux/memblock.h +1 -0
@@ -57,6 +57,7 @@ int memblock_add(phys_addr_t base, phys_addr_t size);int memblock_remove (phys_addr_t base,phys_addr_t size);int memblock_free (phys_addr_t base,phys_addr_t size);int memblock_reserve (phys_addr_t base,phys_addr_t size); +void memblock_trim_memory (phys_addr_t align);#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
mm/memblock.c +24 -0
@@ -930,6 +930,30 @@ int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t sireturn memblock_overlaps_region (&memblock.reserved, base, size) >=0 ; } +void __init_memblock memblock_trim_memory(phys_addr_t align) +{ +int i; +phys_addr_t start, end, orig_start, orig_end; +struct memblock_type *mem = &memblock.memory; + +for (i =0 ; i < mem->cnt; i++) { + orig_start = mem->regions[i].base; + orig_end = mem->regions[i].base + mem->regions[i].size; + start =round_up (orig_start, align); + end =round_down (orig_end, align); + +if (start == orig_start && end == orig_end) +continue ; + +if (start < end) { + mem->regions[i].base = start; + mem->regions[i].size = end - start; + }else { +memblock_remove_region (mem, i); + i--; + } + } +} void __init_memblock memblock_set_current_limit(phys_addr_t limit) {