Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 apic updates from Ingo Molnar: "The main changes in this cycle were: - introduce optimized single IPI sending methods on modern APICs (Linus Torvalds, Thomas Gleixner) - kexec/crash APIC handling fixes and enhancements (Hidehiro Kawai) - extend lapic vector saving/restoring to the CMCI (MCE) vector as well (Juergen Gross) - various fixes and enhancements (Jake Oshins, Len Brown)" * 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (23 commits) x86/irq: Export functions to allow MSI domains in modules Documentation: Document kernel.panic_on_io_nmi sysctl x86/nmi: Save regs in crash dump on external NMI x86/apic: Introduce apic_extnmi command line parameter kexec: Fix race between panic() and crash_kexec() panic, x86: Allow CPUs to save registers even if looping in NMI context panic, x86: Fix re-entrance problem due to panic on NMI x86/apic: Fix the saving and restoring of lapic vectors during suspend/resume x86/smpboot: Re-enable init_udelay=0 by default on modern CPUs x86/smp: Remove single IPI wrapper x86/apic: Use default send single IPI wrapper x86/apic: Provide default send single IPI wrapper x86/apic: Implement single IPI for apic_noop x86/apic: Wire up single IPI for apic_numachip x86/apic: Wire up single IPI for x2apic_uv x86/apic: Implement single IPI for x2apic_phys x86/apic: Wire up single IPI for bigsmp_apic x86/apic: Remove pointless indirections from bigsmp_apic x86/apic: Wire up single IPI for apic_physflat x86/apic: Remove pointless indirections from apic_physflat ...
This commit is contained in:
@@ -81,6 +81,12 @@ physid_mask_t phys_cpu_present_map;
|
||||
*/
|
||||
static unsigned int disabled_cpu_apicid __read_mostly = BAD_APICID;
|
||||
|
||||
/*
|
||||
* This variable controls which CPUs receive external NMIs. By default,
|
||||
* external NMIs are delivered only to the BSP.
|
||||
*/
|
||||
static int apic_extnmi = APIC_EXTNMI_BSP;
|
||||
|
||||
/*
|
||||
* Map cpu index to physical APIC ID
|
||||
*/
|
||||
@@ -1161,6 +1167,8 @@ void __init init_bsp_APIC(void)
|
||||
value = APIC_DM_NMI;
|
||||
if (!lapic_is_integrated()) /* 82489DX */
|
||||
value |= APIC_LVT_LEVEL_TRIGGER;
|
||||
if (apic_extnmi == APIC_EXTNMI_NONE)
|
||||
value |= APIC_LVT_MASKED;
|
||||
apic_write(APIC_LVT1, value);
|
||||
}
|
||||
|
||||
@@ -1378,9 +1386,11 @@ void setup_local_APIC(void)
|
||||
apic_write(APIC_LVT0, value);
|
||||
|
||||
/*
|
||||
* only the BP should see the LINT1 NMI signal, obviously.
|
||||
* Only the BSP sees the LINT1 NMI signal by default. This can be
|
||||
* modified by apic_extnmi= boot option.
|
||||
*/
|
||||
if (!cpu)
|
||||
if ((!cpu && apic_extnmi != APIC_EXTNMI_NONE) ||
|
||||
apic_extnmi == APIC_EXTNMI_ALL)
|
||||
value = APIC_DM_NMI;
|
||||
else
|
||||
value = APIC_DM_NMI | APIC_LVT_MASKED;
|
||||
@@ -2270,6 +2280,7 @@ static struct {
|
||||
unsigned int apic_tmict;
|
||||
unsigned int apic_tdcr;
|
||||
unsigned int apic_thmr;
|
||||
unsigned int apic_cmci;
|
||||
} apic_pm_state;
|
||||
|
||||
static int lapic_suspend(void)
|
||||
@@ -2299,6 +2310,10 @@ static int lapic_suspend(void)
|
||||
if (maxlvt >= 5)
|
||||
apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
|
||||
#endif
|
||||
#ifdef CONFIG_X86_MCE_INTEL
|
||||
if (maxlvt >= 6)
|
||||
apic_pm_state.apic_cmci = apic_read(APIC_LVTCMCI);
|
||||
#endif
|
||||
|
||||
local_irq_save(flags);
|
||||
disable_local_APIC();
|
||||
@@ -2355,9 +2370,13 @@ static void lapic_resume(void)
|
||||
apic_write(APIC_SPIV, apic_pm_state.apic_spiv);
|
||||
apic_write(APIC_LVT0, apic_pm_state.apic_lvt0);
|
||||
apic_write(APIC_LVT1, apic_pm_state.apic_lvt1);
|
||||
#if defined(CONFIG_X86_MCE_INTEL)
|
||||
#ifdef CONFIG_X86_THERMAL_VECTOR
|
||||
if (maxlvt >= 5)
|
||||
apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);
|
||||
#endif
|
||||
#ifdef CONFIG_X86_MCE_INTEL
|
||||
if (maxlvt >= 6)
|
||||
apic_write(APIC_LVTCMCI, apic_pm_state.apic_cmci);
|
||||
#endif
|
||||
if (maxlvt >= 4)
|
||||
apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
|
||||
@@ -2548,3 +2567,23 @@ static int __init apic_set_disabled_cpu_apicid(char *arg)
|
||||
return 0;
|
||||
}
|
||||
early_param("disable_cpu_apicid", apic_set_disabled_cpu_apicid);
|
||||
|
||||
static int __init apic_set_extnmi(char *arg)
|
||||
{
|
||||
if (!arg)
|
||||
return -EINVAL;
|
||||
|
||||
if (!strncmp("all", arg, 3))
|
||||
apic_extnmi = APIC_EXTNMI_ALL;
|
||||
else if (!strncmp("none", arg, 4))
|
||||
apic_extnmi = APIC_EXTNMI_NONE;
|
||||
else if (!strncmp("bsp", arg, 3))
|
||||
apic_extnmi = APIC_EXTNMI_BSP;
|
||||
else {
|
||||
pr_warn("Unknown external NMI delivery mode `%s' ignored\n", arg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_param("apic_extnmi", apic_set_extnmi);
|
||||
|
@@ -185,6 +185,7 @@ static struct apic apic_flat = {
|
||||
|
||||
.cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and,
|
||||
|
||||
.send_IPI = default_send_IPI_single,
|
||||
.send_IPI_mask = flat_send_IPI_mask,
|
||||
.send_IPI_mask_allbutself = flat_send_IPI_mask_allbutself,
|
||||
.send_IPI_allbutself = flat_send_IPI_allbutself,
|
||||
@@ -230,17 +231,6 @@ static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void physflat_send_IPI_mask(const struct cpumask *cpumask, int vector)
|
||||
{
|
||||
default_send_IPI_mask_sequence_phys(cpumask, vector);
|
||||
}
|
||||
|
||||
static void physflat_send_IPI_mask_allbutself(const struct cpumask *cpumask,
|
||||
int vector)
|
||||
{
|
||||
default_send_IPI_mask_allbutself_phys(cpumask, vector);
|
||||
}
|
||||
|
||||
static void physflat_send_IPI_allbutself(int vector)
|
||||
{
|
||||
default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector);
|
||||
@@ -248,7 +238,7 @@ static void physflat_send_IPI_allbutself(int vector)
|
||||
|
||||
static void physflat_send_IPI_all(int vector)
|
||||
{
|
||||
physflat_send_IPI_mask(cpu_online_mask, vector);
|
||||
default_send_IPI_mask_sequence_phys(cpu_online_mask, vector);
|
||||
}
|
||||
|
||||
static int physflat_probe(void)
|
||||
@@ -292,8 +282,9 @@ static struct apic apic_physflat = {
|
||||
|
||||
.cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and,
|
||||
|
||||
.send_IPI_mask = physflat_send_IPI_mask,
|
||||
.send_IPI_mask_allbutself = physflat_send_IPI_mask_allbutself,
|
||||
.send_IPI = default_send_IPI_single_phys,
|
||||
.send_IPI_mask = default_send_IPI_mask_sequence_phys,
|
||||
.send_IPI_mask_allbutself = default_send_IPI_mask_allbutself_phys,
|
||||
.send_IPI_allbutself = physflat_send_IPI_allbutself,
|
||||
.send_IPI_all = physflat_send_IPI_all,
|
||||
.send_IPI_self = apic_send_IPI_self,
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include <asm/e820.h>
|
||||
|
||||
static void noop_init_apic_ldr(void) { }
|
||||
static void noop_send_IPI(int cpu, int vector) { }
|
||||
static void noop_send_IPI_mask(const struct cpumask *cpumask, int vector) { }
|
||||
static void noop_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector) { }
|
||||
static void noop_send_IPI_allbutself(int vector) { }
|
||||
@@ -144,6 +145,7 @@ struct apic apic_noop = {
|
||||
|
||||
.cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and,
|
||||
|
||||
.send_IPI = noop_send_IPI,
|
||||
.send_IPI_mask = noop_send_IPI_mask,
|
||||
.send_IPI_mask_allbutself = noop_send_IPI_mask_allbutself,
|
||||
.send_IPI_allbutself = noop_send_IPI_allbutself,
|
||||
|
@@ -273,6 +273,7 @@ static const struct apic apic_numachip1 __refconst = {
|
||||
|
||||
.cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and,
|
||||
|
||||
.send_IPI = numachip_send_IPI_one,
|
||||
.send_IPI_mask = numachip_send_IPI_mask,
|
||||
.send_IPI_mask_allbutself = numachip_send_IPI_mask_allbutself,
|
||||
.send_IPI_allbutself = numachip_send_IPI_allbutself,
|
||||
@@ -324,6 +325,7 @@ static const struct apic apic_numachip2 __refconst = {
|
||||
|
||||
.cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and,
|
||||
|
||||
.send_IPI = numachip_send_IPI_one,
|
||||
.send_IPI_mask = numachip_send_IPI_mask,
|
||||
.send_IPI_mask_allbutself = numachip_send_IPI_mask_allbutself,
|
||||
.send_IPI_allbutself = numachip_send_IPI_allbutself,
|
||||
|
@@ -96,11 +96,6 @@ static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb)
|
||||
return cpuid_apic >> index_msb;
|
||||
}
|
||||
|
||||
static inline void bigsmp_send_IPI_mask(const struct cpumask *mask, int vector)
|
||||
{
|
||||
default_send_IPI_mask_sequence_phys(mask, vector);
|
||||
}
|
||||
|
||||
static void bigsmp_send_IPI_allbutself(int vector)
|
||||
{
|
||||
default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector);
|
||||
@@ -108,7 +103,7 @@ static void bigsmp_send_IPI_allbutself(int vector)
|
||||
|
||||
static void bigsmp_send_IPI_all(int vector)
|
||||
{
|
||||
bigsmp_send_IPI_mask(cpu_online_mask, vector);
|
||||
default_send_IPI_mask_sequence_phys(cpu_online_mask, vector);
|
||||
}
|
||||
|
||||
static int dmi_bigsmp; /* can be set by dmi scanners */
|
||||
@@ -180,7 +175,8 @@ static struct apic apic_bigsmp = {
|
||||
|
||||
.cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and,
|
||||
|
||||
.send_IPI_mask = bigsmp_send_IPI_mask,
|
||||
.send_IPI = default_send_IPI_single_phys,
|
||||
.send_IPI_mask = default_send_IPI_mask_sequence_phys,
|
||||
.send_IPI_mask_allbutself = NULL,
|
||||
.send_IPI_allbutself = bigsmp_send_IPI_allbutself,
|
||||
.send_IPI_all = bigsmp_send_IPI_all,
|
||||
|
@@ -18,6 +18,16 @@
|
||||
#include <asm/proto.h>
|
||||
#include <asm/ipi.h>
|
||||
|
||||
void default_send_IPI_single_phys(int cpu, int vector)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
__default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, cpu),
|
||||
vector, APIC_DEST_PHYSICAL);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, int vector)
|
||||
{
|
||||
unsigned long query_cpu;
|
||||
@@ -55,6 +65,14 @@ void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask,
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function for APICs which insist on cpumasks
|
||||
*/
|
||||
void default_send_IPI_single(int cpu, int vector)
|
||||
{
|
||||
apic->send_IPI_mask(cpumask_of(cpu), vector);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
|
||||
void default_send_IPI_mask_sequence_logical(const struct cpumask *mask,
|
||||
|
@@ -96,8 +96,8 @@ static irq_hw_number_t pci_msi_get_hwirq(struct msi_domain_info *info,
|
||||
return arg->msi_hwirq;
|
||||
}
|
||||
|
||||
static int pci_msi_prepare(struct irq_domain *domain, struct device *dev,
|
||||
int nvec, msi_alloc_info_t *arg)
|
||||
int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec,
|
||||
msi_alloc_info_t *arg)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct msi_desc *desc = first_pci_msi_entry(pdev);
|
||||
@@ -113,11 +113,13 @@ static int pci_msi_prepare(struct irq_domain *domain, struct device *dev,
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_msi_prepare);
|
||||
|
||||
static void pci_msi_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc)
|
||||
void pci_msi_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc)
|
||||
{
|
||||
arg->msi_hwirq = pci_msi_domain_calc_hwirq(arg->msi_dev, desc);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_msi_set_desc);
|
||||
|
||||
static struct msi_domain_ops pci_msi_domain_ops = {
|
||||
.get_hwirq = pci_msi_get_hwirq,
|
||||
|
@@ -105,6 +105,7 @@ static struct apic apic_default = {
|
||||
|
||||
.cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and,
|
||||
|
||||
.send_IPI = default_send_IPI_single,
|
||||
.send_IPI_mask = default_send_IPI_mask_logical,
|
||||
.send_IPI_mask_allbutself = default_send_IPI_mask_allbutself_logical,
|
||||
.send_IPI_allbutself = default_send_IPI_allbutself,
|
||||
|
@@ -29,6 +29,7 @@ struct apic_chip_data {
|
||||
};
|
||||
|
||||
struct irq_domain *x86_vector_domain;
|
||||
EXPORT_SYMBOL_GPL(x86_vector_domain);
|
||||
static DEFINE_RAW_SPINLOCK(vector_lock);
|
||||
static cpumask_var_t vector_cpumask;
|
||||
static struct irq_chip lapic_controller;
|
||||
@@ -66,6 +67,7 @@ struct irq_cfg *irqd_cfg(struct irq_data *irq_data)
|
||||
|
||||
return data ? &data->cfg : NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(irqd_cfg);
|
||||
|
||||
struct irq_cfg *irq_cfg(unsigned int irq)
|
||||
{
|
||||
|
@@ -23,6 +23,14 @@ static inline u32 x2apic_cluster(int cpu)
|
||||
return per_cpu(x86_cpu_to_logical_apicid, cpu) >> 16;
|
||||
}
|
||||
|
||||
static void x2apic_send_IPI(int cpu, int vector)
|
||||
{
|
||||
u32 dest = per_cpu(x86_cpu_to_logical_apicid, cpu);
|
||||
|
||||
x2apic_wrmsr_fence();
|
||||
__x2apic_send_IPI_dest(dest, vector, APIC_DEST_LOGICAL);
|
||||
}
|
||||
|
||||
static void
|
||||
__x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest)
|
||||
{
|
||||
@@ -266,6 +274,7 @@ static struct apic apic_x2apic_cluster = {
|
||||
|
||||
.cpu_mask_to_apicid_and = x2apic_cpu_mask_to_apicid_and,
|
||||
|
||||
.send_IPI = x2apic_send_IPI,
|
||||
.send_IPI_mask = x2apic_send_IPI_mask,
|
||||
.send_IPI_mask_allbutself = x2apic_send_IPI_mask_allbutself,
|
||||
.send_IPI_allbutself = x2apic_send_IPI_allbutself,
|
||||
|
@@ -36,6 +36,14 @@ static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
return x2apic_enabled() && (x2apic_phys || x2apic_fadt_phys());
|
||||
}
|
||||
|
||||
static void x2apic_send_IPI(int cpu, int vector)
|
||||
{
|
||||
u32 dest = per_cpu(x86_cpu_to_apicid, cpu);
|
||||
|
||||
x2apic_wrmsr_fence();
|
||||
__x2apic_send_IPI_dest(dest, vector, APIC_DEST_PHYSICAL);
|
||||
}
|
||||
|
||||
static void
|
||||
__x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest)
|
||||
{
|
||||
@@ -122,6 +130,7 @@ static struct apic apic_x2apic_phys = {
|
||||
|
||||
.cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and,
|
||||
|
||||
.send_IPI = x2apic_send_IPI,
|
||||
.send_IPI_mask = x2apic_send_IPI_mask,
|
||||
.send_IPI_mask_allbutself = x2apic_send_IPI_mask_allbutself,
|
||||
.send_IPI_allbutself = x2apic_send_IPI_allbutself,
|
||||
|
@@ -406,6 +406,7 @@ static struct apic __refdata apic_x2apic_uv_x = {
|
||||
|
||||
.cpu_mask_to_apicid_and = uv_cpu_mask_to_apicid_and,
|
||||
|
||||
.send_IPI = uv_send_IPI_one,
|
||||
.send_IPI_mask = uv_send_IPI_mask,
|
||||
.send_IPI_mask_allbutself = uv_send_IPI_mask_allbutself,
|
||||
.send_IPI_allbutself = uv_send_IPI_allbutself,
|
||||
|
Reference in New Issue
Block a user