x86/apic changes for v4.9
Linus,
Please pull the latest x86-apic-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-apic-for-linus
# HEAD: eb6296dec19f304199ae389e6863ecc1fc74b7c7 x86/apic: Fix silent & fatal merge conflict in __generic_processor_info()
The main changes are:
- Persistent CPU/node numbering across CPU hotplug/unplug events. This is a pretty involved series of changes that first fetches all the information during bootup and then uses it for the various hotplug/unplug methods. (Gu Zheng, Dou Liyang)
- IO-APIC hot-add/remove fixes and enhancements. (Rui Wang)
- ... various fixes, cleanups and enhancements.
Thanks,
Ingo
------------------>
Baoquan He (3):
x86/mm/numa: Open code function early_get_boot_cpu_id() x86/apic, ACPI: Remove the repeated lapic address override entry parsing x86/apic, ACPI: Fix incorrect assignment when handling apic/x2apic entries
Denys Vlasenko (1):
x86/apic: Get rid of apic_version[] array
Dou Liyang (2):
acpi: Provide mechanism to validate processors in the ACPI tables
acpi: Validate processor id when mapping the processor
Gu Zheng (4):
x86/acpi: Enable acpi to register all possible cpus at boot time x86/acpi: Introduce persistent storage for cpuid <-> apicid mapping x86/acpi: Enable MADT APIs to return disabled apicids x86/acpi: Set persistent cpuid <-> nodeid mapping when booting
Rui Wang (6):
x86/ioapic: Change prototype of acpi_ioapic_add() x86/ioapic: Support hot-removal of IOAPICs present during boot x86/ioapic: Fix setup_res() failing to get resource x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd x86/ioapic: Fix IOAPIC failing to request resource x86/ioapic: Ignore root bridges without a companion ACPI device
Tang Chen (1):
x86/numa: Online memory-less nodes at boot time
Thomas Gleixner (2):
acpi: Fix broken error check in map_processor()
x86/apic: Fix silent & fatal merge conflict in __generic_processor_info()
Wanpeng Li (1):
x86/apic: Order irq_enter/exit() calls correctly vs. ack_APIC_irq()
Wei Jiangang (2):
x86/smpboot: Check APIC ID before setting up default routing x86/apic: Update comment about disabling processor focus
arch/ia64/kernel/acpi.c | 2 +- arch/x86/include/asm/apic.h | 5 +- arch/x86/include/asm/mpspec.h | 3 +- arch/x86/kernel/acpi/boot.c | 33 +++------- arch/x86/kernel/apic/apic.c | 97 +++++++++++++++++++++++------ arch/x86/kernel/apic/io_apic.c | 4 +- arch/x86/kernel/apic/probe_32.c | 2 +- arch/x86/kernel/mpparse.c | 3 + arch/x86/kernel/setup.c | 3 +- arch/x86/kernel/smpboot.c | 13 ++-- arch/x86/mm/amdtopology.c | 22 ++----- arch/x86/mm/numa.c | 27 ++++---- drivers/acpi/acpi_processor.c | 104 ++++++++++++++++++++++++++++++- drivers/acpi/bus.c | 1 + drivers/acpi/internal.h | 2 - drivers/acpi/ioapic.c | 46 ++++++++------ drivers/acpi/pci_root.c | 12 +++- drivers/acpi/processor_core.c | 133 +++++++++++++++++++++++++++++++++------- drivers/pci/setup-bus.c | 8 ++- include/linux/acpi.h | 12 ++++ 20 files changed, 393 insertions(+), 139 deletions(-)
arch/ia64/kernel/acpi.c +1 -1
@@ -796,7 +796,7 @@ int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)* ACPI based hotplug CPU support */ #ifdef CONFIG_ACPI_HOTPLUG_CPU -static int acpi_map_cpu2node (acpi_handle handle,int cpu,int physid) +int acpi_map_cpu2node (acpi_handle handle,int cpu,int physid) {#ifdef CONFIG_ACPI_NUMA /*
arch/x86/include/asm/apic.h +2 -3
@@ -650,8 +650,8 @@ static inline void entering_ack_irq(void)static inline void ipi_entering_ack_irq (void ) { -ack_APIC_irq ();irq_enter (); +ack_APIC_irq (); }static inline void exiting_irq (void )
@@ -661,9 +661,8 @@ static inline void exiting_irq(void)static inline void exiting_ack_irq (void ) { -irq_exit (); -/* Ack only at the end to avoid potential reentry */ ack_APIC_irq (); +irq_exit (); }extern void ioapic_zap_locks (void );
arch/x86/include/asm/mpspec.h +2 -1
@@ -6,7 +6,6 @@#include <asm/x86_init.h> #include <asm/apicdef.h> -extern int apic_version[];extern int pic_mode;#ifdef CONFIG_X86_32
@@ -40,6 +39,7 @@ extern int mp_bus_id_to_type[MAX_MP_BUSSES]; extern DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);extern unsigned int boot_cpu_physical_apicid; +extern u8 boot_cpu_apic_version;extern unsigned long mp_lapic_addr;#ifdef CONFIG_X86_LOCAL_APIC
@@ -86,6 +86,7 @@ static inline void early_reserve_e820_mpc_new(void) { }#endif int generic_processor_info (int apicid,int version); +int __generic_processor_info (int apicid,int version,bool enabled);#define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_LOCAL_APIC)
arch/x86/kernel/acpi/boot.c +8 -25
@@ -176,15 +176,10 @@ static int acpi_register_lapic(int id, u32 acpiid, u8 enabled)return -EINVAL ; } -if (!enabled) { - ++disabled_cpus; -return -EINVAL ; - } -if (boot_cpu_physical_apicid !=-1U ) - ver = apic_version[boot_cpu_physical_apicid]; + ver = boot_cpu_apic_version; - cpu =generic_processor_info (id, ver); + cpu =__generic_processor_info (id, ver, enabled);if (cpu >=0 )early_per_cpu (x86_cpu_to_acpiid, cpu) = acpiid;
@@ -282,6 +277,8 @@ acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header,if (BAD_MADT_ENTRY (lapic_addr_ovr, end))return -EINVAL ; +acpi_table_print_madt_entry (header); + acpi_lapic_addr = lapic_addr_ovr->address;return 0 ;
@@ -705,7 +702,7 @@ static void __init acpi_set_irq_model_ioapic(void)#ifdef CONFIG_ACPI_HOTPLUG_CPU #include <acpi/processor.h> -static void acpi_map_cpu2node (acpi_handle handle,int cpu,int physid) +int acpi_map_cpu2node (acpi_handle handle,int cpu,int physid) {#ifdef CONFIG_ACPI_NUMA int nid;
@@ -716,6 +713,7 @@ static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) numa_set_node(cpu, nid); }#endif +return 0 ; }int acpi_map_cpu (acpi_handle handle,phys_cpuid_t physid,int *pcpu)
@@ -998,21 +996,6 @@ static int __init acpi_parse_madt_lapic_entries(void)if (!boot_cpu_has (X86_FEATURE_APIC ))return -ENODEV ; -/* -* Note that the LAPIC address is obtained from the MADT (32-bit value) -* and (optionally) overridden by a LAPIC_ADDR_OVR entry (64-bit value). -*/ - - count =acpi_table_parse_madt (ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE , - acpi_parse_lapic_addr_ovr,0 ); -if (count <0 ) { - printk(KERN_ERR PREFIX - "Error parsing LAPIC address override entry\n"); -return count; - } - -register_lapic_address (acpi_lapic_addr); - count =acpi_table_parse_madt (ACPI_MADT_TYPE_LOCAL_SAPIC , acpi_parse_sapic,MAX_LOCAL_APIC );
@@ -1031,8 +1014,8 @@ static int __init acpi_parse_madt_lapic_entries(void)return ret; } - x2count = madt_proc[0 ].count; - count = madt_proc[1 ].count; + count = madt_proc[0 ].count; + x2count = madt_proc[1 ].count; }if (!count && !x2count) { printk(KERN_ERR PREFIX "No LAPIC entries present\n");
arch/x86/kernel/apic/apic.c +78 -19
171 lines not on this page · raw message
arch/x86/kernel/apic/io_apic.c +2 -2
@@ -1593,7 +1593,7 @@ void __init setup_ioapic_ids_from_mpc(void)* no meaning without the serial APIC bus. */ if (!(boot_cpu_data.x86_vendor ==X86_VENDOR_INTEL ) - ||APIC_XAPIC (apic_version[boot_cpu_physical_apicid])) + ||APIC_XAPIC (boot_cpu_apic_version))return ;setup_ioapic_ids_from_mpc_nocheck (); }
@@ -2423,7 +2423,7 @@ static int io_apic_get_unique_id(int ioapic, int apic_id)static u8 io_apic_unique_id (int idx,u8 id) {if ((boot_cpu_data.x86_vendor ==X86_VENDOR_INTEL ) && - !APIC_XAPIC (apic_version[boot_cpu_physical_apicid])) + !APIC_XAPIC (boot_cpu_apic_version))return io_apic_get_unique_id (idx, id);else return id;
arch/x86/kernel/apic/probe_32.c +1 -1
@@ -152,7 +152,7 @@ early_param("apic", parse_apic);void __init default_setup_apic_routing (void ) { -int version = apic_version[boot_cpu_physical_apicid]; +int version = boot_cpu_apic_version;if (num_possible_cpus () >8 ) {switch (boot_cpu_data.x86_vendor) {
arch/x86/kernel/mpparse.c +3 -0
@@ -499,6 +499,9 @@ void __init default_get_smp_config(unsigned int early) {struct mpf_intel *mpf = mpf_found; +if (!smp_found_config) +return ; +if (!mpf)return ;
arch/x86/kernel/setup.c +1 -2
@@ -1221,8 +1221,7 @@ void __init setup_arch(char **cmdline_p)/* * get boot-time SMP configuration: */ -if (smp_found_config) -get_smp_config (); +get_smp_config ();prefill_possible_map ();
arch/x86/kernel/smpboot.c +6 -7
@@ -690,7 +690,7 @@ wakeup_secondary_cpu_via_nmi(int apicid, unsigned long start_eip)* Give the other CPU some time to accept the IPI. */ udelay (200 ); -if (APIC_INTEGRATED (apic_version[boot_cpu_physical_apicid])) { +if (APIC_INTEGRATED (boot_cpu_apic_version)) { maxlvt =lapic_get_maxlvt ();if (maxlvt >3 )/* Due to the Pentium erratum 3AP. */ apic_write (APIC_ESR ,0 );
@@ -717,7 +717,7 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)/* * Be paranoid about clearing APIC errors. */ -if (APIC_INTEGRATED (apic_version[phys_apicid])) { +if (APIC_INTEGRATED (boot_cpu_apic_version)) {if (maxlvt >3 )/* Due to the Pentium erratum 3AP. */ apic_write (APIC_ESR ,0 );apic_read (APIC_ESR );
@@ -756,7 +756,7 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)* Determine this based on the APIC version. * If we don't have an integrated APIC, don't send the STARTUP IPIs. */ -if (APIC_INTEGRATED (apic_version[phys_apicid])) +if (APIC_INTEGRATED (boot_cpu_apic_version)) num_starts =2 ;else num_starts =0 ;
@@ -994,7 +994,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)/* * Be paranoid about clearing APIC errors. */ -if (APIC_INTEGRATED (apic_version[boot_cpu_physical_apicid])) { +if (APIC_INTEGRATED (boot_cpu_apic_version)) {apic_write (APIC_ESR ,0 );apic_read (APIC_ESR ); }
@@ -1249,7 +1249,7 @@ static int __init smp_sanity_check(unsigned max_cpus)/* * If we couldn't find a local APIC, then get out of here now! */ -if (APIC_INTEGRATED (apic_version[boot_cpu_physical_apicid]) && +if (APIC_INTEGRATED (boot_cpu_apic_version) && !boot_cpu_has (X86_FEATURE_APIC )) {if (!disable_apic) { pr_err("BIOS bug, local APIC #%d not detected!...\n",
@@ -1323,14 +1323,13 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)break ; } -default_setup_apic_routing (); -if (read_apic_id () != boot_cpu_physical_apicid) {panic ("Boot APIC ID in local APIC unexpected (%d vs %d)" ,read_apic_id (), boot_cpu_physical_apicid);/* Or can we switch back to PIC here? */ } +default_setup_apic_routing (); cpu0_logical_apicid =apic_bsp_setup (false);pr_info ("CPU%d: " ,0 );
arch/x86/mm/amdtopology.c +5 -17
@@ -52,21 +52,6 @@ static __init int find_northbridge(void)return -ENOENT ; } -static __init void early_get_boot_cpu_id (void ) -{ -/* -* need to get the APIC ID of the BSP so can use that to -* create apicid_to_node in amd_scan_nodes() -*/ -#ifdef CONFIG_X86_MPPARSE -/* -* get boot-time SMP configuration: -*/ -if (smp_found_config) -early_get_smp_config (); -#endif -} -int __init amd_numa_init (void ) {u64 start =PFN_PHYS (0 );
@@ -180,8 +165,11 @@ int __init amd_numa_init(void) cores =1 << bits; apicid_base =0 ; -/* get the APIC ID of the BSP early for systems with apicid lifting */ -early_get_boot_cpu_id (); +/* +* get boot-time SMP configuration: +*/ +early_get_smp_config (); +if (boot_cpu_physical_apicid >0 ) {pr_info ("BSP APIC ID: %02x\n" , boot_cpu_physical_apicid); apicid_base = boot_cpu_physical_apicid;
arch/x86/mm/numa.c +13 -14
@@ -722,22 +722,19 @@ void __init x86_numa_init(void)numa_init (dummy_numa_init); } -static __init int find_near_online_node (int node) +static void __init init_memory_less_node (int nid) { -int n, val; -int min_val =INT_MAX ; -int best_node =-1 ; +unsigned long zones_size[MAX_NR_ZONES ] = {0 }; +unsigned long zholes_size[MAX_NR_ZONES ] = {0 }; -for_each_online_node (n) { - val =node_distance (node, n); +/* Allocate and initialize node data. Memory-less node is now online.*/ +alloc_node_data (nid); +free_area_init_node (nid, zones_size,0 , zholes_size); -if (val < min_val) { - min_val = val; - best_node = n; - } - } - -return best_node; +/* +* All zonelists will be built later in start_kernel() after per cpu +* areas are initialized. +*/ }/*
@@ -766,8 +763,10 @@ void __init init_cpu_to_node(void)if (node ==NUMA_NO_NODE )continue ; +if (!node_online (node)) - node =find_near_online_node (node); +init_memory_less_node (node); +numa_set_node (cpu, node); } }
drivers/acpi/acpi_processor.c +103 -1
125 lines not on this page · raw message
drivers/acpi/bus.c +1 -0
@@ -1193,6 +1193,7 @@ static int __init acpi_init(void)acpi_wakeup_device_init ();acpi_debugger_init ();acpi_setup_sb_notify_handler (); +acpi_set_processor_mapping ();return 0 ; }
drivers/acpi/internal.h +0 -2
@@ -40,10 +40,8 @@ int acpi_sysfs_init(void);void acpi_container_init (void );void acpi_memory_hotplug_init (void );#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC -int acpi_ioapic_add (struct acpi_pci_root *root);int acpi_ioapic_remove (struct acpi_pci_root *root);#else -static inline int acpi_ioapic_add (struct acpi_pci_root *root) {return 0 ; }static inline int acpi_ioapic_remove (struct acpi_pci_root *root) {return 0 ; }#endif #ifdef CONFIG_ACPI_DOCK
drivers/acpi/ioapic.c +26 -20
99 lines not on this page · raw message
drivers/acpi/pci_root.c +11 -1
@@ -614,7 +614,17 @@ static int acpi_pci_root_add(struct acpi_device *device,if (hotadd) {pcibios_resource_survey_bus (root->bus);pci_assign_unassigned_root_bus_resources (root->bus); -acpi_ioapic_add (root); +/* +* This is only called for the hotadd case. For the boot-time +* case, we need to wait until after PCI initialization in +* order to deal with IOAPICs mapped in on a PCI BAR. +* +* This is currently x86-specific, because acpi_ioapic_add() +* is an empty function without CONFIG_ACPI_HOTPLUG_IOAPIC. +* And CONFIG_ACPI_HOTPLUG_IOAPIC depends on CONFIG_X86_IO_APIC +* (see drivers/acpi/Kconfig). +*/ +acpi_ioapic_add (root->device->handle); }pci_lock_rescan_remove ();
drivers/acpi/processor_core.c +111 -22
232 lines not on this page · raw message
drivers/pci/setup-bus.c +7 -1
@@ -25,6 +25,7 @@#include <linux/ioport.h> #include <linux/cache.h> #include <linux/slab.h> +#include <linux/acpi.h> #include "pci.h" unsigned int pci_flags;
@@ -1852,8 +1853,13 @@ void __init pci_assign_unassigned_resources(void) {struct pci_bus *root_bus; -list_for_each_entry (root_bus, &pci_root_buses, node) +list_for_each_entry (root_bus, &pci_root_buses, node) {pci_assign_unassigned_root_bus_resources (root_bus); + +/* Make sure the root bridge has a companion ACPI device: */ +if (ACPI_HANDLE (root_bus->bridge)) +acpi_ioapic_add (ACPI_HANDLE (root_bus->bridge)); + } }void pci_assign_unassigned_bridge_resources (struct pci_dev *bridge)
include/linux/acpi.h +12 -0
@@ -267,12 +267,18 @@ static inline bool invalid_phys_cpuid(phys_cpuid_t phys_id)return phys_id ==PHYS_CPUID_INVALID ; } +/* Validate the processor object's proc_id */ +bool acpi_processor_validate_proc_id (int proc_id); +#ifdef CONFIG_ACPI_HOTPLUG_CPU /* Arch dependent functions for cpu hotplug support */ int acpi_map_cpu (acpi_handle handle,phys_cpuid_t physid,int *pcpu);int acpi_unmap_cpu (int cpu); +int acpi_map_cpu2node (acpi_handle handle,int cpu,int physid);#endif /* CONFIG_ACPI_HOTPLUG_CPU */ +void acpi_set_processor_mapping (void ); +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC int acpi_get_ioapic_id (acpi_handle handle,u32 gsi_base,u64 *phys_addr);#endif
@@ -751,6 +757,12 @@ static inline int acpi_reconfig_notifier_unregister(struct notifier_block *nb)#endif /* !CONFIG_ACPI */ +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +int acpi_ioapic_add (acpi_handle root); +#else +static inline int acpi_ioapic_add (acpi_handle root) {return 0 ; } +#endif +#ifdef CONFIG_ACPI void acpi_os_set_prepare_sleep (int (*func)(u8 sleep_state,u32 pm1a_ctrl,u32 pm1b_ctrl));