Skip to content

Commit

Permalink
Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/tip/tip

Pull x86 apic updates from Ingo Molnar:
 "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"

* 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (22 commits)
  x86/apic: Fix silent & fatal merge conflict in __generic_processor_info()
  acpi: Fix broken error check in map_processor()
  acpi: Validate processor id when mapping the processor
  acpi: Provide mechanism to validate processors in the ACPI tables
  x86/acpi: Set persistent cpuid <-> nodeid mapping when booting
  x86/acpi: Enable MADT APIs to return disabled apicids
  x86/acpi: Introduce persistent storage for cpuid <-> apicid mapping
  x86/acpi: Enable acpi to register all possible cpus at boot time
  x86/numa: Online memory-less nodes at boot time
  x86/apic: Get rid of apic_version[] array
  x86/apic: Order irq_enter/exit() calls correctly vs. ack_APIC_irq()
  x86/ioapic: Ignore root bridges without a companion ACPI device
  x86/apic: Update comment about disabling processor focus
  x86/smpboot: Check APIC ID before setting up default routing
  x86/ioapic: Fix IOAPIC failing to request resource
  x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd
  x86/ioapic: Fix setup_res() failing to get resource
  x86/ioapic: Support hot-removal of IOAPICs present during boot
  x86/ioapic: Change prototype of acpi_ioapic_add()
  x86/apic, ACPI: Fix incorrect assignment when handling apic/x2apic entries
  ...
  • Loading branch information
Linus Torvalds committed Oct 3, 2016
2 parents af79ad2 + eb6296d commit 110a9e4
Show file tree
Hide file tree
Showing 20 changed files with 391 additions and 137 deletions.
2 changes: 1 addition & 1 deletion arch/ia64/kernel/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
/*
Expand Down
5 changes: 2 additions & 3 deletions arch/x86/include/asm/apic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion arch/x86/include/asm/mpspec.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand Down
29 changes: 6 additions & 23 deletions arch/x86/kernel/acpi/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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);

Expand Down
97 changes: 78 additions & 19 deletions arch/x86/kernel/apic/apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ unsigned disabled_cpus;
unsigned int boot_cpu_physical_apicid = -1U;
EXPORT_SYMBOL_GPL(boot_cpu_physical_apicid);

u8 boot_cpu_apic_version;

/*
* The highest APIC ID seen during enumeration.
*/
Expand Down Expand Up @@ -1374,7 +1376,6 @@ void setup_local_APIC(void)
* Actually disabling the focus CPU check just makes the hang less
* frequent as it makes the interrupt distributon model be more
* like LRU than MRU (the short-term load is more even across CPUs).
* See also the comment in end_level_ioapic_irq(). --macro
*/

/*
Expand Down Expand Up @@ -1816,8 +1817,7 @@ void __init init_apic_mappings(void)
* since smp_sanity_check is prepared for such a case
* and disable smp mode
*/
apic_version[new_apicid] =
GET_APIC_VERSION(apic_read(APIC_LVR));
boot_cpu_apic_version = GET_APIC_VERSION(apic_read(APIC_LVR));
}
}

Expand All @@ -1828,17 +1828,14 @@ void __init register_lapic_address(unsigned long address)
if (!x2apic_mode) {
set_fixmap_nocache(FIX_APIC_BASE, address);
apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
APIC_BASE, mp_lapic_addr);
APIC_BASE, address);
}
if (boot_cpu_physical_apicid == -1U) {
boot_cpu_physical_apicid = read_apic_id();
apic_version[boot_cpu_physical_apicid] =
GET_APIC_VERSION(apic_read(APIC_LVR));
boot_cpu_apic_version = GET_APIC_VERSION(apic_read(APIC_LVR));
}
}

int apic_version[MAX_LOCAL_APIC];

/*
* Local APIC interrupts
*/
Expand Down Expand Up @@ -2027,7 +2024,53 @@ void disconnect_bsp_APIC(int virt_wire_setup)
apic_write(APIC_LVT1, value);
}

int generic_processor_info(int apicid, int version)
/*
* The number of allocated logical CPU IDs. Since logical CPU IDs are allocated
* contiguously, it equals to current allocated max logical CPU ID plus 1.
* All allocated CPU ID should be in [0, nr_logical_cpuidi), so the maximum of
* nr_logical_cpuids is nr_cpu_ids.
*
* NOTE: Reserve 0 for BSP.
*/
static int nr_logical_cpuids = 1;

/*
* Used to store mapping between logical CPU IDs and APIC IDs.
*/
static int cpuid_to_apicid[] = {
[0 ... NR_CPUS - 1] = -1,
};

/*
* Should use this API to allocate logical CPU IDs to keep nr_logical_cpuids
* and cpuid_to_apicid[] synchronized.
*/
static int allocate_logical_cpuid(int apicid)
{
int i;

/*
* cpuid <-> apicid mapping is persistent, so when a cpu is up,
* check if the kernel has allocated a cpuid for it.
*/
for (i = 0; i < nr_logical_cpuids; i++) {
if (cpuid_to_apicid[i] == apicid)
return i;
}

/* Allocate a new cpuid. */
if (nr_logical_cpuids >= nr_cpu_ids) {
WARN_ONCE(1, "Only %d processors supported."
"Processor %d/0x%x and the rest are ignored.\n",
nr_cpu_ids - 1, nr_logical_cpuids, apicid);
return -1;
}

cpuid_to_apicid[nr_logical_cpuids] = apicid;
return nr_logical_cpuids++;
}

int __generic_processor_info(int apicid, int version, bool enabled)
{
int cpu, max = nr_cpu_ids;
bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid,
Expand Down Expand Up @@ -2102,8 +2145,16 @@ int generic_processor_info(int apicid, int version)
* for BSP.
*/
cpu = 0;
} else
cpu = cpumask_next_zero(-1, cpu_present_mask);

/* Logical cpuid 0 is reserved for BSP. */
cpuid_to_apicid[0] = apicid;
} else {
cpu = allocate_logical_cpuid(apicid);
if (cpu < 0) {
disabled_cpus++;
return -EINVAL;
}
}

/*
* This can happen on physical hotplug. The sanity check at boot time
Expand All @@ -2120,8 +2171,6 @@ int generic_processor_info(int apicid, int version)
return -ENOSPC;
}

num_processors++;

/*
* Validate version
*/
Expand All @@ -2130,14 +2179,12 @@ int generic_processor_info(int apicid, int version)
cpu, apicid);
version = 0x10;
}
apic_version[apicid] = version;

if (version != apic_version[boot_cpu_physical_apicid]) {
if (version != boot_cpu_apic_version) {
pr_warning("BIOS bug: APIC version mismatch, boot CPU: %x, CPU %d: version %x\n",
apic_version[boot_cpu_physical_apicid], cpu, version);
boot_cpu_apic_version, cpu, version);
}

physid_set(apicid, phys_cpu_present_map);
if (apicid > max_physical_apicid)
max_physical_apicid = apicid;

Expand All @@ -2150,11 +2197,23 @@ int generic_processor_info(int apicid, int version)
apic->x86_32_early_logical_apicid(cpu);
#endif
set_cpu_possible(cpu, true);
set_cpu_present(cpu, true);

if (enabled) {
num_processors++;
physid_set(apicid, phys_cpu_present_map);
set_cpu_present(cpu, true);
} else {
disabled_cpus++;
}

return cpu;
}

int generic_processor_info(int apicid, int version)
{
return __generic_processor_info(apicid, version, true);
}

int hard_smp_processor_id(void)
{
return read_apic_id();
Expand Down Expand Up @@ -2277,7 +2336,7 @@ int __init APIC_init_uniprocessor(void)
* Complain if the BIOS pretends there is one.
*/
if (!boot_cpu_has(X86_FEATURE_APIC) &&
APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
APIC_INTEGRATED(boot_cpu_apic_version)) {
pr_err("BIOS bug, local APIC 0x%x not detected!...\n",
boot_cpu_physical_apicid);
return -1;
Expand Down
4 changes: 2 additions & 2 deletions arch/x86/kernel/apic/io_apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/apic/probe_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
3 changes: 3 additions & 0 deletions arch/x86/kernel/mpparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
3 changes: 1 addition & 2 deletions arch/x86/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -1219,8 +1219,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();

Expand Down
Loading

0 comments on commit 110a9e4

Please sign in to comment.