mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-06 14:05:39 +00:00
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: "Continued fallout of the conversion of the x86 IRQ code to the hierarchical irqdomain framework: more cleanups, simplifications, memory allocation behavior enhancements, mainly in the interrupt remapping and APIC code" * 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (44 commits) x86, init: Fix UP boot regression on x86_64 iommu/amd: Fix irq remapping detection logic x86/acpi: Make acpi_[un]register_gsi_ioapic() depend on CONFIG_X86_LOCAL_APIC x86: Consolidate boot cpu timer setup x86/apic: Reuse apic_bsp_setup() for UP APIC setup x86/smpboot: Sanitize uniprocessor init x86/smpboot: Move apic init code to apic.c init: Get rid of x86isms x86/apic: Move apic_init_uniprocessor code x86/smpboot: Cleanup ioapic handling x86/apic: Sanitize ioapic handling x86/ioapic: Add proper checks to setp/enable_IO_APIC() x86/ioapic: Provide stub functions for IOAPIC%3Dn x86/smpboot: Move smpboot inlines to code x86/x2apic: Use state information for disable x86/x2apic: Split enable and setup function x86/x2apic: Disable x2apic from nox2apic setup x86/x2apic: Add proper state tracking x86/x2apic: Clarify remapping mode for x2apic enablement x86/x2apic: Move code in conditional region ...
This commit is contained in:
commit
9d43bade34
@ -856,6 +856,10 @@ config SCHED_MC
|
|||||||
|
|
||||||
source "kernel/Kconfig.preempt"
|
source "kernel/Kconfig.preempt"
|
||||||
|
|
||||||
|
config UP_LATE_INIT
|
||||||
|
def_bool y
|
||||||
|
depends on !SMP && X86_LOCAL_APIC
|
||||||
|
|
||||||
config X86_UP_APIC
|
config X86_UP_APIC
|
||||||
bool "Local APIC support on uniprocessors"
|
bool "Local APIC support on uniprocessors"
|
||||||
depends on X86_32 && !SMP && !X86_32_NON_STANDARD
|
depends on X86_32 && !SMP && !X86_32_NON_STANDARD
|
||||||
|
@ -106,7 +106,14 @@ extern u32 native_safe_apic_wait_icr_idle(void);
|
|||||||
extern void native_apic_icr_write(u32 low, u32 id);
|
extern void native_apic_icr_write(u32 low, u32 id);
|
||||||
extern u64 native_apic_icr_read(void);
|
extern u64 native_apic_icr_read(void);
|
||||||
|
|
||||||
extern int x2apic_mode;
|
static inline bool apic_is_x2apic_enabled(void)
|
||||||
|
{
|
||||||
|
u64 msr;
|
||||||
|
|
||||||
|
if (rdmsrl_safe(MSR_IA32_APICBASE, &msr))
|
||||||
|
return false;
|
||||||
|
return msr & X2APIC_ENABLE;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_X86_X2APIC
|
#ifdef CONFIG_X86_X2APIC
|
||||||
/*
|
/*
|
||||||
@ -169,48 +176,23 @@ static inline u64 native_x2apic_icr_read(void)
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern int x2apic_mode;
|
||||||
extern int x2apic_phys;
|
extern int x2apic_phys;
|
||||||
extern int x2apic_preenabled;
|
extern void __init check_x2apic(void);
|
||||||
extern void check_x2apic(void);
|
extern void x2apic_setup(void);
|
||||||
extern void enable_x2apic(void);
|
|
||||||
static inline int x2apic_enabled(void)
|
static inline int x2apic_enabled(void)
|
||||||
{
|
{
|
||||||
u64 msr;
|
return cpu_has_x2apic && apic_is_x2apic_enabled();
|
||||||
|
|
||||||
if (!cpu_has_x2apic)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
rdmsrl(MSR_IA32_APICBASE, msr);
|
|
||||||
if (msr & X2APIC_ENABLE)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define x2apic_supported() (cpu_has_x2apic)
|
#define x2apic_supported() (cpu_has_x2apic)
|
||||||
static inline void x2apic_force_phys(void)
|
|
||||||
{
|
|
||||||
x2apic_phys = 1;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
static inline void disable_x2apic(void)
|
static inline void check_x2apic(void) { }
|
||||||
{
|
static inline void x2apic_setup(void) { }
|
||||||
}
|
static inline int x2apic_enabled(void) { return 0; }
|
||||||
static inline void check_x2apic(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
static inline void enable_x2apic(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
static inline int x2apic_enabled(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static inline void x2apic_force_phys(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#define x2apic_preenabled 0
|
#define x2apic_mode (0)
|
||||||
#define x2apic_supported() 0
|
#define x2apic_supported() (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void enable_IR_x2apic(void);
|
extern void enable_IR_x2apic(void);
|
||||||
@ -219,7 +201,6 @@ extern int get_physical_broadcast(void);
|
|||||||
|
|
||||||
extern int lapic_get_maxlvt(void);
|
extern int lapic_get_maxlvt(void);
|
||||||
extern void clear_local_APIC(void);
|
extern void clear_local_APIC(void);
|
||||||
extern void connect_bsp_APIC(void);
|
|
||||||
extern void disconnect_bsp_APIC(int virt_wire_setup);
|
extern void disconnect_bsp_APIC(int virt_wire_setup);
|
||||||
extern void disable_local_APIC(void);
|
extern void disable_local_APIC(void);
|
||||||
extern void lapic_shutdown(void);
|
extern void lapic_shutdown(void);
|
||||||
@ -227,8 +208,6 @@ extern int verify_local_APIC(void);
|
|||||||
extern void sync_Arb_IDs(void);
|
extern void sync_Arb_IDs(void);
|
||||||
extern void init_bsp_APIC(void);
|
extern void init_bsp_APIC(void);
|
||||||
extern void setup_local_APIC(void);
|
extern void setup_local_APIC(void);
|
||||||
extern void end_local_APIC_setup(void);
|
|
||||||
extern void bsp_end_local_APIC_setup(void);
|
|
||||||
extern void init_apic_mappings(void);
|
extern void init_apic_mappings(void);
|
||||||
void register_lapic_address(unsigned long address);
|
void register_lapic_address(unsigned long address);
|
||||||
extern void setup_boot_APIC_clock(void);
|
extern void setup_boot_APIC_clock(void);
|
||||||
@ -236,6 +215,9 @@ extern void setup_secondary_APIC_clock(void);
|
|||||||
extern int APIC_init_uniprocessor(void);
|
extern int APIC_init_uniprocessor(void);
|
||||||
extern int apic_force_enable(unsigned long addr);
|
extern int apic_force_enable(unsigned long addr);
|
||||||
|
|
||||||
|
extern int apic_bsp_setup(bool upmode);
|
||||||
|
extern void apic_ap_setup(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On 32bit this is mach-xxx local
|
* On 32bit this is mach-xxx local
|
||||||
*/
|
*/
|
||||||
|
@ -279,6 +279,11 @@ static inline void disable_ioapic_support(void) { }
|
|||||||
#define native_ioapic_set_affinity NULL
|
#define native_ioapic_set_affinity NULL
|
||||||
#define native_setup_ioapic_entry NULL
|
#define native_setup_ioapic_entry NULL
|
||||||
#define native_eoi_ioapic_pin NULL
|
#define native_eoi_ioapic_pin NULL
|
||||||
|
|
||||||
|
static inline void setup_IO_APIC(void) { }
|
||||||
|
static inline void enable_IO_APIC(void) { }
|
||||||
|
static inline void setup_ioapic_dest(void) { }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _ASM_X86_IO_APIC_H */
|
#endif /* _ASM_X86_IO_APIC_H */
|
||||||
|
@ -33,8 +33,6 @@ struct irq_cfg;
|
|||||||
|
|
||||||
#ifdef CONFIG_IRQ_REMAP
|
#ifdef CONFIG_IRQ_REMAP
|
||||||
|
|
||||||
extern void setup_irq_remapping_ops(void);
|
|
||||||
extern int irq_remapping_supported(void);
|
|
||||||
extern void set_irq_remapping_broken(void);
|
extern void set_irq_remapping_broken(void);
|
||||||
extern int irq_remapping_prepare(void);
|
extern int irq_remapping_prepare(void);
|
||||||
extern int irq_remapping_enable(void);
|
extern int irq_remapping_enable(void);
|
||||||
@ -60,8 +58,6 @@ void irq_remap_modify_chip_defaults(struct irq_chip *chip);
|
|||||||
|
|
||||||
#else /* CONFIG_IRQ_REMAP */
|
#else /* CONFIG_IRQ_REMAP */
|
||||||
|
|
||||||
static inline void setup_irq_remapping_ops(void) { }
|
|
||||||
static inline int irq_remapping_supported(void) { return 0; }
|
|
||||||
static inline void set_irq_remapping_broken(void) { }
|
static inline void set_irq_remapping_broken(void) { }
|
||||||
static inline int irq_remapping_prepare(void) { return -ENODEV; }
|
static inline int irq_remapping_prepare(void) { return -ENODEV; }
|
||||||
static inline int irq_remapping_enable(void) { return -ENODEV; }
|
static inline int irq_remapping_enable(void) { return -ENODEV; }
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
/* two abstractions specific to kernel/smpboot.c, mainly to cater to visws
|
|
||||||
* which needs to alter them. */
|
|
||||||
|
|
||||||
static inline void smpboot_clear_io_apic_irqs(void)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_X86_IO_APIC
|
|
||||||
io_apic_irqs = 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&rtc_lock, flags);
|
|
||||||
CMOS_WRITE(0xa, 0xf);
|
|
||||||
spin_unlock_irqrestore(&rtc_lock, flags);
|
|
||||||
local_flush_tlb();
|
|
||||||
pr_debug("1.\n");
|
|
||||||
*((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) =
|
|
||||||
start_eip >> 4;
|
|
||||||
pr_debug("2.\n");
|
|
||||||
*((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) =
|
|
||||||
start_eip & 0xf;
|
|
||||||
pr_debug("3.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void smpboot_restore_warm_reset_vector(void)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Install writable page 0 entry to set BIOS data area.
|
|
||||||
*/
|
|
||||||
local_flush_tlb();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Paranoid: Set warm reset code and vector here back
|
|
||||||
* to default values.
|
|
||||||
*/
|
|
||||||
spin_lock_irqsave(&rtc_lock, flags);
|
|
||||||
CMOS_WRITE(0, 0xf);
|
|
||||||
spin_unlock_irqrestore(&rtc_lock, flags);
|
|
||||||
|
|
||||||
*((volatile u32 *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void __init smpboot_setup_io_apic(void)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_X86_IO_APIC
|
|
||||||
/*
|
|
||||||
* Here we can be sure that there is an IO-APIC in the system. Let's
|
|
||||||
* go and set it up:
|
|
||||||
*/
|
|
||||||
if (!skip_ioapic_setup && nr_ioapics)
|
|
||||||
setup_IO_APIC();
|
|
||||||
else {
|
|
||||||
nr_ioapics = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void smpboot_clear_io_apic(void)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_X86_IO_APIC
|
|
||||||
nr_ioapics = 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
@ -653,6 +653,7 @@ static int acpi_register_gsi_pic(struct device *dev, u32 gsi,
|
|||||||
return gsi;
|
return gsi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
|
static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
|
||||||
int trigger, int polarity)
|
int trigger, int polarity)
|
||||||
{
|
{
|
||||||
@ -675,6 +676,7 @@ static void acpi_unregister_gsi_ioapic(u32 gsi)
|
|||||||
mutex_unlock(&acpi_ioapic_lock);
|
mutex_unlock(&acpi_ioapic_lock);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int (*__acpi_register_gsi)(struct device *dev, u32 gsi,
|
int (*__acpi_register_gsi)(struct device *dev, u32 gsi,
|
||||||
int trigger, int polarity) = acpi_register_gsi_pic;
|
int trigger, int polarity) = acpi_register_gsi_pic;
|
||||||
|
@ -134,9 +134,6 @@ static inline void imcr_apic_to_pic(void)
|
|||||||
*/
|
*/
|
||||||
static int force_enable_local_apic __initdata;
|
static int force_enable_local_apic __initdata;
|
||||||
|
|
||||||
/* Control whether x2APIC mode is enabled or not */
|
|
||||||
static bool nox2apic __initdata;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* APIC command line parameters
|
* APIC command line parameters
|
||||||
*/
|
*/
|
||||||
@ -161,33 +158,6 @@ static __init int setup_apicpmtimer(char *s)
|
|||||||
__setup("apicpmtimer", setup_apicpmtimer);
|
__setup("apicpmtimer", setup_apicpmtimer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int x2apic_mode;
|
|
||||||
#ifdef CONFIG_X86_X2APIC
|
|
||||||
/* x2apic enabled before OS handover */
|
|
||||||
int x2apic_preenabled;
|
|
||||||
static int x2apic_disabled;
|
|
||||||
static int __init setup_nox2apic(char *str)
|
|
||||||
{
|
|
||||||
if (x2apic_enabled()) {
|
|
||||||
int apicid = native_apic_msr_read(APIC_ID);
|
|
||||||
|
|
||||||
if (apicid >= 255) {
|
|
||||||
pr_warning("Apicid: %08x, cannot enforce nox2apic\n",
|
|
||||||
apicid);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_warning("x2apic already enabled. will disable it\n");
|
|
||||||
} else
|
|
||||||
setup_clear_cpu_cap(X86_FEATURE_X2APIC);
|
|
||||||
|
|
||||||
nox2apic = true;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
early_param("nox2apic", setup_nox2apic);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unsigned long mp_lapic_addr;
|
unsigned long mp_lapic_addr;
|
||||||
int disable_apic;
|
int disable_apic;
|
||||||
/* Disable local APIC timer from the kernel commandline or via dmi quirk */
|
/* Disable local APIC timer from the kernel commandline or via dmi quirk */
|
||||||
@ -1475,7 +1445,7 @@ void setup_local_APIC(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void end_local_APIC_setup(void)
|
static void end_local_APIC_setup(void)
|
||||||
{
|
{
|
||||||
lapic_setup_esr();
|
lapic_setup_esr();
|
||||||
|
|
||||||
@ -1492,116 +1462,184 @@ void end_local_APIC_setup(void)
|
|||||||
apic_pm_activate();
|
apic_pm_activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init bsp_end_local_APIC_setup(void)
|
/*
|
||||||
|
* APIC setup function for application processors. Called from smpboot.c
|
||||||
|
*/
|
||||||
|
void apic_ap_setup(void)
|
||||||
{
|
{
|
||||||
|
setup_local_APIC();
|
||||||
end_local_APIC_setup();
|
end_local_APIC_setup();
|
||||||
|
|
||||||
/*
|
|
||||||
* Now that local APIC setup is completed for BP, configure the fault
|
|
||||||
* handling for interrupt remapping.
|
|
||||||
*/
|
|
||||||
irq_remap_enable_fault_handling();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_X86_X2APIC
|
#ifdef CONFIG_X86_X2APIC
|
||||||
/*
|
int x2apic_mode;
|
||||||
* Need to disable xapic and x2apic at the same time and then enable xapic mode
|
|
||||||
*/
|
|
||||||
static inline void __disable_x2apic(u64 msr)
|
|
||||||
{
|
|
||||||
wrmsrl(MSR_IA32_APICBASE,
|
|
||||||
msr & ~(X2APIC_ENABLE | XAPIC_ENABLE));
|
|
||||||
wrmsrl(MSR_IA32_APICBASE, msr & ~X2APIC_ENABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static __init void disable_x2apic(void)
|
enum {
|
||||||
|
X2APIC_OFF,
|
||||||
|
X2APIC_ON,
|
||||||
|
X2APIC_DISABLED,
|
||||||
|
};
|
||||||
|
static int x2apic_state;
|
||||||
|
|
||||||
|
static inline void __x2apic_disable(void)
|
||||||
{
|
{
|
||||||
u64 msr;
|
u64 msr;
|
||||||
|
|
||||||
if (!cpu_has_x2apic)
|
if (cpu_has_apic)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
rdmsrl(MSR_IA32_APICBASE, msr);
|
rdmsrl(MSR_IA32_APICBASE, msr);
|
||||||
if (msr & X2APIC_ENABLE) {
|
if (!(msr & X2APIC_ENABLE))
|
||||||
u32 x2apic_id = read_apic_id();
|
return;
|
||||||
|
/* Disable xapic and x2apic first and then reenable xapic mode */
|
||||||
if (x2apic_id >= 255)
|
wrmsrl(MSR_IA32_APICBASE, msr & ~(X2APIC_ENABLE | XAPIC_ENABLE));
|
||||||
panic("Cannot disable x2apic, id: %08x\n", x2apic_id);
|
wrmsrl(MSR_IA32_APICBASE, msr & ~X2APIC_ENABLE);
|
||||||
|
printk_once(KERN_INFO "x2apic disabled\n");
|
||||||
pr_info("Disabling x2apic\n");
|
|
||||||
__disable_x2apic(msr);
|
|
||||||
|
|
||||||
if (nox2apic) {
|
|
||||||
clear_cpu_cap(&cpu_data(0), X86_FEATURE_X2APIC);
|
|
||||||
setup_clear_cpu_cap(X86_FEATURE_X2APIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
x2apic_disabled = 1;
|
|
||||||
x2apic_mode = 0;
|
|
||||||
|
|
||||||
register_lapic_address(mp_lapic_addr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_x2apic(void)
|
static inline void __x2apic_enable(void)
|
||||||
|
{
|
||||||
|
u64 msr;
|
||||||
|
|
||||||
|
rdmsrl(MSR_IA32_APICBASE, msr);
|
||||||
|
if (msr & X2APIC_ENABLE)
|
||||||
|
return;
|
||||||
|
wrmsrl(MSR_IA32_APICBASE, msr | X2APIC_ENABLE);
|
||||||
|
printk_once(KERN_INFO "x2apic enabled\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init setup_nox2apic(char *str)
|
||||||
{
|
{
|
||||||
if (x2apic_enabled()) {
|
if (x2apic_enabled()) {
|
||||||
pr_info("x2apic enabled by BIOS, switching to x2apic ops\n");
|
int apicid = native_apic_msr_read(APIC_ID);
|
||||||
x2apic_preenabled = x2apic_mode = 1;
|
|
||||||
|
if (apicid >= 255) {
|
||||||
|
pr_warning("Apicid: %08x, cannot enforce nox2apic\n",
|
||||||
|
apicid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pr_warning("x2apic already enabled.\n");
|
||||||
|
__x2apic_disable();
|
||||||
}
|
}
|
||||||
|
setup_clear_cpu_cap(X86_FEATURE_X2APIC);
|
||||||
|
x2apic_state = X2APIC_DISABLED;
|
||||||
|
x2apic_mode = 0;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
early_param("nox2apic", setup_nox2apic);
|
||||||
|
|
||||||
void enable_x2apic(void)
|
/* Called from cpu_init() to enable x2apic on (secondary) cpus */
|
||||||
|
void x2apic_setup(void)
|
||||||
{
|
{
|
||||||
u64 msr;
|
/*
|
||||||
|
* If x2apic is not in ON state, disable it if already enabled
|
||||||
rdmsrl(MSR_IA32_APICBASE, msr);
|
* from BIOS.
|
||||||
if (x2apic_disabled) {
|
*/
|
||||||
__disable_x2apic(msr);
|
if (x2apic_state != X2APIC_ON) {
|
||||||
|
__x2apic_disable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
__x2apic_enable();
|
||||||
|
}
|
||||||
|
|
||||||
if (!x2apic_mode)
|
static __init void x2apic_disable(void)
|
||||||
|
{
|
||||||
|
u32 x2apic_id;
|
||||||
|
|
||||||
|
if (x2apic_state != X2APIC_ON)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
x2apic_id = read_apic_id();
|
||||||
|
if (x2apic_id >= 255)
|
||||||
|
panic("Cannot disable x2apic, id: %08x\n", x2apic_id);
|
||||||
|
|
||||||
|
__x2apic_disable();
|
||||||
|
register_lapic_address(mp_lapic_addr);
|
||||||
|
out:
|
||||||
|
x2apic_state = X2APIC_DISABLED;
|
||||||
|
x2apic_mode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __init void x2apic_enable(void)
|
||||||
|
{
|
||||||
|
if (x2apic_state != X2APIC_OFF)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!(msr & X2APIC_ENABLE)) {
|
x2apic_mode = 1;
|
||||||
printk_once(KERN_INFO "Enabling x2apic\n");
|
x2apic_state = X2APIC_ON;
|
||||||
wrmsrl(MSR_IA32_APICBASE, msr | X2APIC_ENABLE);
|
__x2apic_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
static __init void try_to_enable_x2apic(int remap_mode)
|
||||||
|
{
|
||||||
|
if (x2apic_state == X2APIC_DISABLED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (remap_mode != IRQ_REMAP_X2APIC_MODE) {
|
||||||
|
/* IR is required if there is APIC ID > 255 even when running
|
||||||
|
* under KVM
|
||||||
|
*/
|
||||||
|
if (max_physical_apicid > 255 ||
|
||||||
|
(IS_ENABLED(CONFIG_HYPERVISOR_GUEST) &&
|
||||||
|
!hypervisor_x2apic_available())) {
|
||||||
|
pr_info("x2apic: IRQ remapping doesn't support X2APIC mode\n");
|
||||||
|
x2apic_disable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* without IR all CPUs can be addressed by IOAPIC/MSI
|
||||||
|
* only in physical mode
|
||||||
|
*/
|
||||||
|
x2apic_phys = 1;
|
||||||
|
}
|
||||||
|
x2apic_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init check_x2apic(void)
|
||||||
|
{
|
||||||
|
if (x2apic_enabled()) {
|
||||||
|
pr_info("x2apic: enabled by BIOS, switching to x2apic ops\n");
|
||||||
|
x2apic_mode = 1;
|
||||||
|
x2apic_state = X2APIC_ON;
|
||||||
|
} else if (!cpu_has_x2apic) {
|
||||||
|
x2apic_state = X2APIC_DISABLED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_X86_X2APIC */
|
#else /* CONFIG_X86_X2APIC */
|
||||||
|
static int __init validate_x2apic(void)
|
||||||
int __init enable_IR(void)
|
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_IRQ_REMAP
|
if (!apic_is_x2apic_enabled())
|
||||||
if (!irq_remapping_supported()) {
|
return 0;
|
||||||
pr_debug("intr-remapping not supported\n");
|
/*
|
||||||
|
* Checkme: Can we simply turn off x2apic here instead of panic?
|
||||||
|
*/
|
||||||
|
panic("BIOS has enabled x2apic but kernel doesn't support x2apic, please disable x2apic in BIOS.\n");
|
||||||
|
}
|
||||||
|
early_initcall(validate_x2apic);
|
||||||
|
|
||||||
|
static inline void try_to_enable_x2apic(int remap_mode) { }
|
||||||
|
static inline void __x2apic_enable(void) { }
|
||||||
|
#endif /* !CONFIG_X86_X2APIC */
|
||||||
|
|
||||||
|
static int __init try_to_enable_IR(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_X86_IO_APIC
|
||||||
|
if (!x2apic_enabled() && skip_ioapic_setup) {
|
||||||
|
pr_info("Not enabling interrupt remapping due to skipped IO-APIC setup\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!x2apic_preenabled && skip_ioapic_setup) {
|
|
||||||
pr_info("Skipped enabling intr-remap because of skipping "
|
|
||||||
"io-apic setup\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return irq_remapping_enable();
|
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
return irq_remapping_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init enable_IR_x2apic(void)
|
void __init enable_IR_x2apic(void)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret, x2apic_enabled = 0;
|
int ret, ir_stat;
|
||||||
int hardware_init_ret;
|
|
||||||
|
|
||||||
/* Make sure irq_remap_ops are initialized */
|
ir_stat = irq_remapping_prepare();
|
||||||
setup_irq_remapping_ops();
|
if (ir_stat < 0 && !x2apic_supported())
|
||||||
|
|
||||||
hardware_init_ret = irq_remapping_prepare();
|
|
||||||
if (hardware_init_ret && !x2apic_supported())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ret = save_ioapic_entries();
|
ret = save_ioapic_entries();
|
||||||
@ -1614,49 +1652,13 @@ void __init enable_IR_x2apic(void)
|
|||||||
legacy_pic->mask_all();
|
legacy_pic->mask_all();
|
||||||
mask_ioapic_entries();
|
mask_ioapic_entries();
|
||||||
|
|
||||||
if (x2apic_preenabled && nox2apic)
|
/* If irq_remapping_prepare() succeded, try to enable it */
|
||||||
disable_x2apic();
|
if (ir_stat >= 0)
|
||||||
|
ir_stat = try_to_enable_IR();
|
||||||
|
/* ir_stat contains the remap mode or an error code */
|
||||||
|
try_to_enable_x2apic(ir_stat);
|
||||||
|
|
||||||
if (hardware_init_ret)
|
if (ir_stat < 0)
|
||||||
ret = -1;
|
|
||||||
else
|
|
||||||
ret = enable_IR();
|
|
||||||
|
|
||||||
if (!x2apic_supported())
|
|
||||||
goto skip_x2apic;
|
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
/* IR is required if there is APIC ID > 255 even when running
|
|
||||||
* under KVM
|
|
||||||
*/
|
|
||||||
if (max_physical_apicid > 255 ||
|
|
||||||
!hypervisor_x2apic_available()) {
|
|
||||||
if (x2apic_preenabled)
|
|
||||||
disable_x2apic();
|
|
||||||
goto skip_x2apic;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* without IR all CPUs can be addressed by IOAPIC/MSI
|
|
||||||
* only in physical mode
|
|
||||||
*/
|
|
||||||
x2apic_force_phys();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret == IRQ_REMAP_XAPIC_MODE) {
|
|
||||||
pr_info("x2apic not enabled, IRQ remapping is in xapic mode\n");
|
|
||||||
goto skip_x2apic;
|
|
||||||
}
|
|
||||||
|
|
||||||
x2apic_enabled = 1;
|
|
||||||
|
|
||||||
if (x2apic_supported() && !x2apic_mode) {
|
|
||||||
x2apic_mode = 1;
|
|
||||||
enable_x2apic();
|
|
||||||
pr_info("Enabled x2apic\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
skip_x2apic:
|
|
||||||
if (ret < 0) /* IR enabling failed */
|
|
||||||
restore_ioapic_entries();
|
restore_ioapic_entries();
|
||||||
legacy_pic->restore_mask();
|
legacy_pic->restore_mask();
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
@ -1847,82 +1849,8 @@ void __init register_lapic_address(unsigned long address)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* This initializes the IO-APIC and APIC hardware if this is
|
|
||||||
* a UP kernel.
|
|
||||||
*/
|
|
||||||
int apic_version[MAX_LOCAL_APIC];
|
int apic_version[MAX_LOCAL_APIC];
|
||||||
|
|
||||||
int __init APIC_init_uniprocessor(void)
|
|
||||||
{
|
|
||||||
if (disable_apic) {
|
|
||||||
pr_info("Apic disabled\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#ifdef CONFIG_X86_64
|
|
||||||
if (!cpu_has_apic) {
|
|
||||||
disable_apic = 1;
|
|
||||||
pr_info("Apic disabled by BIOS\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (!smp_found_config && !cpu_has_apic)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Complain if the BIOS pretends there is one.
|
|
||||||
*/
|
|
||||||
if (!cpu_has_apic &&
|
|
||||||
APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
|
|
||||||
pr_err("BIOS bug, local APIC 0x%x not detected!...\n",
|
|
||||||
boot_cpu_physical_apicid);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
default_setup_apic_routing();
|
|
||||||
|
|
||||||
verify_local_APIC();
|
|
||||||
connect_bsp_APIC();
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
|
||||||
apic_write(APIC_ID, SET_APIC_ID(boot_cpu_physical_apicid));
|
|
||||||
#else
|
|
||||||
/*
|
|
||||||
* Hack: In case of kdump, after a crash, kernel might be booting
|
|
||||||
* on a cpu with non-zero lapic id. But boot_cpu_physical_apicid
|
|
||||||
* might be zero if read from MP tables. Get it from LAPIC.
|
|
||||||
*/
|
|
||||||
# ifdef CONFIG_CRASH_DUMP
|
|
||||||
boot_cpu_physical_apicid = read_apic_id();
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map);
|
|
||||||
setup_local_APIC();
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86_IO_APIC
|
|
||||||
/*
|
|
||||||
* Now enable IO-APICs, actually call clear_IO_APIC
|
|
||||||
* We need clear_IO_APIC before enabling error vector
|
|
||||||
*/
|
|
||||||
if (!skip_ioapic_setup && nr_ioapics)
|
|
||||||
enable_IO_APIC();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bsp_end_local_APIC_setup();
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86_IO_APIC
|
|
||||||
if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
|
|
||||||
setup_IO_APIC();
|
|
||||||
else {
|
|
||||||
nr_ioapics = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
x86_init.timers.setup_percpu_clockev();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local APIC interrupts
|
* Local APIC interrupts
|
||||||
*/
|
*/
|
||||||
@ -2027,7 +1955,7 @@ __visible void smp_trace_error_interrupt(struct pt_regs *regs)
|
|||||||
/**
|
/**
|
||||||
* connect_bsp_APIC - attach the APIC to the interrupt system
|
* connect_bsp_APIC - attach the APIC to the interrupt system
|
||||||
*/
|
*/
|
||||||
void __init connect_bsp_APIC(void)
|
static void __init connect_bsp_APIC(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
if (pic_mode) {
|
if (pic_mode) {
|
||||||
@ -2274,6 +2202,100 @@ void __init apic_set_eoi_write(void (*eoi_write)(u32 reg, u32 v))
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __init apic_bsp_up_setup(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
apic_write(APIC_ID, SET_APIC_ID(boot_cpu_physical_apicid));
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* Hack: In case of kdump, after a crash, kernel might be booting
|
||||||
|
* on a cpu with non-zero lapic id. But boot_cpu_physical_apicid
|
||||||
|
* might be zero if read from MP tables. Get it from LAPIC.
|
||||||
|
*/
|
||||||
|
# ifdef CONFIG_CRASH_DUMP
|
||||||
|
boot_cpu_physical_apicid = read_apic_id();
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* apic_bsp_setup - Setup function for local apic and io-apic
|
||||||
|
* @upmode: Force UP mode (for APIC_init_uniprocessor)
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* apic_id of BSP APIC
|
||||||
|
*/
|
||||||
|
int __init apic_bsp_setup(bool upmode)
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
|
||||||
|
connect_bsp_APIC();
|
||||||
|
if (upmode)
|
||||||
|
apic_bsp_up_setup();
|
||||||
|
setup_local_APIC();
|
||||||
|
|
||||||
|
if (x2apic_mode)
|
||||||
|
id = apic_read(APIC_LDR);
|
||||||
|
else
|
||||||
|
id = GET_APIC_LOGICAL_ID(apic_read(APIC_LDR));
|
||||||
|
|
||||||
|
enable_IO_APIC();
|
||||||
|
end_local_APIC_setup();
|
||||||
|
irq_remap_enable_fault_handling();
|
||||||
|
setup_IO_APIC();
|
||||||
|
/* Setup local timer */
|
||||||
|
x86_init.timers.setup_percpu_clockev();
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This initializes the IO-APIC and APIC hardware if this is
|
||||||
|
* a UP kernel.
|
||||||
|
*/
|
||||||
|
int __init APIC_init_uniprocessor(void)
|
||||||
|
{
|
||||||
|
if (disable_apic) {
|
||||||
|
pr_info("Apic disabled\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
if (!cpu_has_apic) {
|
||||||
|
disable_apic = 1;
|
||||||
|
pr_info("Apic disabled by BIOS\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (!smp_found_config && !cpu_has_apic)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Complain if the BIOS pretends there is one.
|
||||||
|
*/
|
||||||
|
if (!cpu_has_apic &&
|
||||||
|
APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
|
||||||
|
pr_err("BIOS bug, local APIC 0x%x not detected!...\n",
|
||||||
|
boot_cpu_physical_apicid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!smp_found_config)
|
||||||
|
disable_ioapic_support();
|
||||||
|
|
||||||
|
default_setup_apic_routing();
|
||||||
|
verify_local_APIC();
|
||||||
|
apic_bsp_setup(true);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_UP_LATE_INIT
|
||||||
|
void __init up_late_init(void)
|
||||||
|
{
|
||||||
|
APIC_init_uniprocessor();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Power management
|
* Power management
|
||||||
*/
|
*/
|
||||||
@ -2359,9 +2381,9 @@ static void lapic_resume(void)
|
|||||||
mask_ioapic_entries();
|
mask_ioapic_entries();
|
||||||
legacy_pic->mask_all();
|
legacy_pic->mask_all();
|
||||||
|
|
||||||
if (x2apic_mode)
|
if (x2apic_mode) {
|
||||||
enable_x2apic();
|
__x2apic_enable();
|
||||||
else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Make sure the APICBASE points to the right address
|
* Make sure the APICBASE points to the right address
|
||||||
*
|
*
|
||||||
|
@ -1507,7 +1507,10 @@ void __init enable_IO_APIC(void)
|
|||||||
int i8259_apic, i8259_pin;
|
int i8259_apic, i8259_pin;
|
||||||
int apic, pin;
|
int apic, pin;
|
||||||
|
|
||||||
if (!nr_legacy_irqs())
|
if (skip_ioapic_setup)
|
||||||
|
nr_ioapics = 0;
|
||||||
|
|
||||||
|
if (!nr_legacy_irqs() || !nr_ioapics)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for_each_ioapic_pin(apic, pin) {
|
for_each_ioapic_pin(apic, pin) {
|
||||||
@ -2295,7 +2298,7 @@ static inline void __init check_timer(void)
|
|||||||
}
|
}
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n");
|
apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n");
|
||||||
if (x2apic_preenabled)
|
if (apic_is_x2apic_enabled())
|
||||||
apic_printk(APIC_QUIET, KERN_INFO
|
apic_printk(APIC_QUIET, KERN_INFO
|
||||||
"Perhaps problem with the pre-enabled x2apic mode\n"
|
"Perhaps problem with the pre-enabled x2apic mode\n"
|
||||||
"Try booting with x2apic and interrupt-remapping disabled in the bios.\n");
|
"Try booting with x2apic and interrupt-remapping disabled in the bios.\n");
|
||||||
@ -2373,9 +2376,9 @@ void __init setup_IO_APIC(void)
|
|||||||
{
|
{
|
||||||
int ioapic;
|
int ioapic;
|
||||||
|
|
||||||
/*
|
if (skip_ioapic_setup || !nr_ioapics)
|
||||||
* calling enable_IO_APIC() is moved to setup_local_APIC for BP
|
return;
|
||||||
*/
|
|
||||||
io_apic_irqs = nr_legacy_irqs() ? ~PIC_IRQS : ~0UL;
|
io_apic_irqs = nr_legacy_irqs() ? ~PIC_IRQS : ~0UL;
|
||||||
|
|
||||||
apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
|
apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
|
||||||
|
@ -1332,7 +1332,7 @@ void cpu_init(void)
|
|||||||
barrier();
|
barrier();
|
||||||
|
|
||||||
x86_configure_nx();
|
x86_configure_nx();
|
||||||
enable_x2apic();
|
x2apic_setup();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set up and load the per-CPU TSS
|
* set up and load the per-CPU TSS
|
||||||
|
@ -73,7 +73,6 @@
|
|||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
#include <asm/uv/uv.h>
|
#include <asm/uv/uv.h>
|
||||||
#include <linux/mc146818rtc.h>
|
#include <linux/mc146818rtc.h>
|
||||||
#include <asm/smpboot_hooks.h>
|
|
||||||
#include <asm/i8259.h>
|
#include <asm/i8259.h>
|
||||||
#include <asm/realmode.h>
|
#include <asm/realmode.h>
|
||||||
#include <asm/misc.h>
|
#include <asm/misc.h>
|
||||||
@ -104,6 +103,43 @@ EXPORT_PER_CPU_SYMBOL(cpu_info);
|
|||||||
|
|
||||||
atomic_t init_deasserted;
|
atomic_t init_deasserted;
|
||||||
|
|
||||||
|
static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&rtc_lock, flags);
|
||||||
|
CMOS_WRITE(0xa, 0xf);
|
||||||
|
spin_unlock_irqrestore(&rtc_lock, flags);
|
||||||
|
local_flush_tlb();
|
||||||
|
pr_debug("1.\n");
|
||||||
|
*((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) =
|
||||||
|
start_eip >> 4;
|
||||||
|
pr_debug("2.\n");
|
||||||
|
*((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) =
|
||||||
|
start_eip & 0xf;
|
||||||
|
pr_debug("3.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void smpboot_restore_warm_reset_vector(void)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Install writable page 0 entry to set BIOS data area.
|
||||||
|
*/
|
||||||
|
local_flush_tlb();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Paranoid: Set warm reset code and vector here back
|
||||||
|
* to default values.
|
||||||
|
*/
|
||||||
|
spin_lock_irqsave(&rtc_lock, flags);
|
||||||
|
CMOS_WRITE(0, 0xf);
|
||||||
|
spin_unlock_irqrestore(&rtc_lock, flags);
|
||||||
|
|
||||||
|
*((volatile u32 *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Report back to the Boot Processor during boot time or to the caller processor
|
* Report back to the Boot Processor during boot time or to the caller processor
|
||||||
* during CPU online.
|
* during CPU online.
|
||||||
@ -136,8 +172,7 @@ static void smp_callin(void)
|
|||||||
* CPU, first the APIC. (this is probably redundant on most
|
* CPU, first the APIC. (this is probably redundant on most
|
||||||
* boards)
|
* boards)
|
||||||
*/
|
*/
|
||||||
setup_local_APIC();
|
apic_ap_setup();
|
||||||
end_local_APIC_setup();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Need to setup vector mappings before we enable interrupts.
|
* Need to setup vector mappings before we enable interrupts.
|
||||||
@ -955,9 +990,12 @@ void arch_disable_smp_support(void)
|
|||||||
*/
|
*/
|
||||||
static __init void disable_smp(void)
|
static __init void disable_smp(void)
|
||||||
{
|
{
|
||||||
|
pr_info("SMP disabled\n");
|
||||||
|
|
||||||
|
disable_ioapic_support();
|
||||||
|
|
||||||
init_cpu_present(cpumask_of(0));
|
init_cpu_present(cpumask_of(0));
|
||||||
init_cpu_possible(cpumask_of(0));
|
init_cpu_possible(cpumask_of(0));
|
||||||
smpboot_clear_io_apic_irqs();
|
|
||||||
|
|
||||||
if (smp_found_config)
|
if (smp_found_config)
|
||||||
physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map);
|
physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map);
|
||||||
@ -967,6 +1005,13 @@ static __init void disable_smp(void)
|
|||||||
cpumask_set_cpu(0, cpu_core_mask(0));
|
cpumask_set_cpu(0, cpu_core_mask(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SMP_OK,
|
||||||
|
SMP_NO_CONFIG,
|
||||||
|
SMP_NO_APIC,
|
||||||
|
SMP_FORCE_UP,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Various sanity checks.
|
* Various sanity checks.
|
||||||
*/
|
*/
|
||||||
@ -1014,10 +1059,7 @@ static int __init smp_sanity_check(unsigned max_cpus)
|
|||||||
if (!smp_found_config && !acpi_lapic) {
|
if (!smp_found_config && !acpi_lapic) {
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
pr_notice("SMP motherboard not detected\n");
|
pr_notice("SMP motherboard not detected\n");
|
||||||
disable_smp();
|
return SMP_NO_CONFIG;
|
||||||
if (APIC_init_uniprocessor())
|
|
||||||
pr_notice("Local APIC not detected. Using dummy APIC emulation.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1041,9 +1083,7 @@ static int __init smp_sanity_check(unsigned max_cpus)
|
|||||||
boot_cpu_physical_apicid);
|
boot_cpu_physical_apicid);
|
||||||
pr_err("... forcing use of dummy APIC emulation (tell your hw vendor)\n");
|
pr_err("... forcing use of dummy APIC emulation (tell your hw vendor)\n");
|
||||||
}
|
}
|
||||||
smpboot_clear_io_apic();
|
return SMP_NO_APIC;
|
||||||
disable_ioapic_support();
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
verify_local_APIC();
|
verify_local_APIC();
|
||||||
@ -1053,15 +1093,10 @@ static int __init smp_sanity_check(unsigned max_cpus)
|
|||||||
*/
|
*/
|
||||||
if (!max_cpus) {
|
if (!max_cpus) {
|
||||||
pr_info("SMP mode deactivated\n");
|
pr_info("SMP mode deactivated\n");
|
||||||
smpboot_clear_io_apic();
|
return SMP_FORCE_UP;
|
||||||
|
|
||||||
connect_bsp_APIC();
|
|
||||||
setup_local_APIC();
|
|
||||||
bsp_end_local_APIC_setup();
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return SMP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init smp_cpu_index_default(void)
|
static void __init smp_cpu_index_default(void)
|
||||||
@ -1101,10 +1136,21 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
|
|||||||
}
|
}
|
||||||
set_cpu_sibling_map(0);
|
set_cpu_sibling_map(0);
|
||||||
|
|
||||||
if (smp_sanity_check(max_cpus) < 0) {
|
switch (smp_sanity_check(max_cpus)) {
|
||||||
pr_info("SMP disabled\n");
|
case SMP_NO_CONFIG:
|
||||||
|
disable_smp();
|
||||||
|
if (APIC_init_uniprocessor())
|
||||||
|
pr_notice("Local APIC not detected. Using dummy APIC emulation.\n");
|
||||||
|
return;
|
||||||
|
case SMP_NO_APIC:
|
||||||
disable_smp();
|
disable_smp();
|
||||||
return;
|
return;
|
||||||
|
case SMP_FORCE_UP:
|
||||||
|
disable_smp();
|
||||||
|
apic_bsp_setup(false);
|
||||||
|
return;
|
||||||
|
case SMP_OK:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default_setup_apic_routing();
|
default_setup_apic_routing();
|
||||||
@ -1115,33 +1161,10 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
|
|||||||
/* Or can we switch back to PIC here? */
|
/* Or can we switch back to PIC here? */
|
||||||
}
|
}
|
||||||
|
|
||||||
connect_bsp_APIC();
|
cpu0_logical_apicid = apic_bsp_setup(false);
|
||||||
|
|
||||||
/*
|
|
||||||
* Switch from PIC to APIC mode.
|
|
||||||
*/
|
|
||||||
setup_local_APIC();
|
|
||||||
|
|
||||||
if (x2apic_mode)
|
|
||||||
cpu0_logical_apicid = apic_read(APIC_LDR);
|
|
||||||
else
|
|
||||||
cpu0_logical_apicid = GET_APIC_LOGICAL_ID(apic_read(APIC_LDR));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Enable IO APIC before setting up error vector
|
|
||||||
*/
|
|
||||||
if (!skip_ioapic_setup && nr_ioapics)
|
|
||||||
enable_IO_APIC();
|
|
||||||
|
|
||||||
bsp_end_local_APIC_setup();
|
|
||||||
smpboot_setup_io_apic();
|
|
||||||
/*
|
|
||||||
* Set up local APIC timer on boot CPU.
|
|
||||||
*/
|
|
||||||
|
|
||||||
pr_info("CPU%d: ", 0);
|
pr_info("CPU%d: ", 0);
|
||||||
print_cpu_info(&cpu_data(0));
|
print_cpu_info(&cpu_data(0));
|
||||||
x86_init.timers.setup_percpu_clockev();
|
|
||||||
|
|
||||||
if (is_uv_system())
|
if (is_uv_system())
|
||||||
uv_system_init();
|
uv_system_init();
|
||||||
@ -1177,9 +1200,7 @@ void __init native_smp_cpus_done(unsigned int max_cpus)
|
|||||||
|
|
||||||
nmi_selftest();
|
nmi_selftest();
|
||||||
impress_friends();
|
impress_friends();
|
||||||
#ifdef CONFIG_X86_IO_APIC
|
|
||||||
setup_ioapic_dest();
|
setup_ioapic_dest();
|
||||||
#endif
|
|
||||||
mtrr_aps_init();
|
mtrr_aps_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4284,7 +4284,6 @@ static int alloc_hpet_msi(unsigned int irq, unsigned int id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct irq_remap_ops amd_iommu_irq_ops = {
|
struct irq_remap_ops amd_iommu_irq_ops = {
|
||||||
.supported = amd_iommu_supported,
|
|
||||||
.prepare = amd_iommu_prepare,
|
.prepare = amd_iommu_prepare,
|
||||||
.enable = amd_iommu_enable,
|
.enable = amd_iommu_enable,
|
||||||
.disable = amd_iommu_disable,
|
.disable = amd_iommu_disable,
|
||||||
|
@ -2014,9 +2014,6 @@ static bool detect_ivrs(void)
|
|||||||
/* Make sure ACS will be enabled during PCI probe */
|
/* Make sure ACS will be enabled during PCI probe */
|
||||||
pci_request_acs();
|
pci_request_acs();
|
||||||
|
|
||||||
if (!disable_irq_remap)
|
|
||||||
amd_iommu_irq_remap = true;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2123,12 +2120,14 @@ static int __init iommu_go_to_state(enum iommu_init_state state)
|
|||||||
#ifdef CONFIG_IRQ_REMAP
|
#ifdef CONFIG_IRQ_REMAP
|
||||||
int __init amd_iommu_prepare(void)
|
int __init amd_iommu_prepare(void)
|
||||||
{
|
{
|
||||||
return iommu_go_to_state(IOMMU_ACPI_FINISHED);
|
int ret;
|
||||||
}
|
|
||||||
|
|
||||||
int __init amd_iommu_supported(void)
|
amd_iommu_irq_remap = true;
|
||||||
{
|
|
||||||
return amd_iommu_irq_remap ? 1 : 0;
|
ret = iommu_go_to_state(IOMMU_ACPI_FINISHED);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
return amd_iommu_irq_remap ? 0 : -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __init amd_iommu_enable(void)
|
int __init amd_iommu_enable(void)
|
||||||
|
@ -33,7 +33,6 @@ extern void amd_iommu_init_notifier(void);
|
|||||||
extern void amd_iommu_init_api(void);
|
extern void amd_iommu_init_api(void);
|
||||||
|
|
||||||
/* Needed for interrupt remapping */
|
/* Needed for interrupt remapping */
|
||||||
extern int amd_iommu_supported(void);
|
|
||||||
extern int amd_iommu_prepare(void);
|
extern int amd_iommu_prepare(void);
|
||||||
extern int amd_iommu_enable(void);
|
extern int amd_iommu_enable(void);
|
||||||
extern void amd_iommu_disable(void);
|
extern void amd_iommu_disable(void);
|
||||||
|
@ -32,8 +32,9 @@ struct hpet_scope {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0)
|
#define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0)
|
||||||
#define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8)
|
#define IRTE_DEST(dest) ((eim_mode) ? dest : dest << 8)
|
||||||
|
|
||||||
|
static int __read_mostly eim_mode;
|
||||||
static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
|
static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
|
||||||
static struct hpet_scope ir_hpet[MAX_HPET_TBS];
|
static struct hpet_scope ir_hpet[MAX_HPET_TBS];
|
||||||
|
|
||||||
@ -481,11 +482,11 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu)
|
|||||||
if (iommu->ir_table)
|
if (iommu->ir_table)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ir_table = kzalloc(sizeof(struct ir_table), GFP_ATOMIC);
|
ir_table = kzalloc(sizeof(struct ir_table), GFP_KERNEL);
|
||||||
if (!ir_table)
|
if (!ir_table)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
pages = alloc_pages_node(iommu->node, GFP_ATOMIC | __GFP_ZERO,
|
pages = alloc_pages_node(iommu->node, GFP_KERNEL | __GFP_ZERO,
|
||||||
INTR_REMAP_PAGE_ORDER);
|
INTR_REMAP_PAGE_ORDER);
|
||||||
|
|
||||||
if (!pages) {
|
if (!pages) {
|
||||||
@ -566,13 +567,27 @@ static int __init dmar_x2apic_optout(void)
|
|||||||
return dmar->flags & DMAR_X2APIC_OPT_OUT;
|
return dmar->flags & DMAR_X2APIC_OPT_OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init intel_irq_remapping_supported(void)
|
static void __init intel_cleanup_irq_remapping(void)
|
||||||
|
{
|
||||||
|
struct dmar_drhd_unit *drhd;
|
||||||
|
struct intel_iommu *iommu;
|
||||||
|
|
||||||
|
for_each_iommu(iommu, drhd) {
|
||||||
|
if (ecap_ir_support(iommu->ecap)) {
|
||||||
|
iommu_disable_irq_remapping(iommu);
|
||||||
|
intel_teardown_irq_remapping(iommu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x2apic_supported())
|
||||||
|
pr_warn("Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init intel_prepare_irq_remapping(void)
|
||||||
{
|
{
|
||||||
struct dmar_drhd_unit *drhd;
|
struct dmar_drhd_unit *drhd;
|
||||||
struct intel_iommu *iommu;
|
struct intel_iommu *iommu;
|
||||||
|
|
||||||
if (disable_irq_remap)
|
|
||||||
return 0;
|
|
||||||
if (irq_remap_broken) {
|
if (irq_remap_broken) {
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"This system BIOS has enabled interrupt remapping\n"
|
"This system BIOS has enabled interrupt remapping\n"
|
||||||
@ -581,38 +596,45 @@ static int __init intel_irq_remapping_supported(void)
|
|||||||
"interrupt remapping is being disabled. Please\n"
|
"interrupt remapping is being disabled. Please\n"
|
||||||
"contact your BIOS vendor for an update\n");
|
"contact your BIOS vendor for an update\n");
|
||||||
add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
|
add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
|
||||||
disable_irq_remap = 1;
|
return -ENODEV;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dmar_ir_support())
|
if (dmar_table_init() < 0)
|
||||||
return 0;
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (!dmar_ir_support())
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (parse_ioapics_under_ir() != 1) {
|
||||||
|
printk(KERN_INFO "Not enabling interrupt remapping\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* First make sure all IOMMUs support IRQ remapping */
|
||||||
for_each_iommu(iommu, drhd)
|
for_each_iommu(iommu, drhd)
|
||||||
if (!ecap_ir_support(iommu->ecap))
|
if (!ecap_ir_support(iommu->ecap))
|
||||||
return 0;
|
goto error;
|
||||||
|
|
||||||
return 1;
|
/* Do the allocations early */
|
||||||
|
for_each_iommu(iommu, drhd)
|
||||||
|
if (intel_setup_irq_remapping(iommu))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
intel_cleanup_irq_remapping();
|
||||||
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init intel_enable_irq_remapping(void)
|
static int __init intel_enable_irq_remapping(void)
|
||||||
{
|
{
|
||||||
struct dmar_drhd_unit *drhd;
|
struct dmar_drhd_unit *drhd;
|
||||||
struct intel_iommu *iommu;
|
struct intel_iommu *iommu;
|
||||||
bool x2apic_present;
|
|
||||||
int setup = 0;
|
int setup = 0;
|
||||||
int eim = 0;
|
int eim = 0;
|
||||||
|
|
||||||
x2apic_present = x2apic_supported();
|
if (x2apic_supported()) {
|
||||||
|
|
||||||
if (parse_ioapics_under_ir() != 1) {
|
|
||||||
printk(KERN_INFO "Not enable interrupt remapping\n");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x2apic_present) {
|
|
||||||
pr_info("Queued invalidation will be enabled to support x2apic and Intr-remapping.\n");
|
|
||||||
|
|
||||||
eim = !dmar_x2apic_optout();
|
eim = !dmar_x2apic_optout();
|
||||||
if (!eim)
|
if (!eim)
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
@ -646,16 +668,15 @@ static int __init intel_enable_irq_remapping(void)
|
|||||||
/*
|
/*
|
||||||
* check for the Interrupt-remapping support
|
* check for the Interrupt-remapping support
|
||||||
*/
|
*/
|
||||||
for_each_iommu(iommu, drhd) {
|
for_each_iommu(iommu, drhd)
|
||||||
if (!ecap_ir_support(iommu->ecap))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (eim && !ecap_eim_support(iommu->ecap)) {
|
if (eim && !ecap_eim_support(iommu->ecap)) {
|
||||||
printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, "
|
printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, "
|
||||||
" ecap %Lx\n", drhd->reg_base_addr, iommu->ecap);
|
" ecap %Lx\n", drhd->reg_base_addr, iommu->ecap);
|
||||||
goto error;
|
eim = 0;
|
||||||
}
|
}
|
||||||
}
|
eim_mode = eim;
|
||||||
|
if (eim)
|
||||||
|
pr_info("Queued invalidation will be enabled to support x2apic and Intr-remapping.\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enable queued invalidation for all the DRHD's.
|
* Enable queued invalidation for all the DRHD's.
|
||||||
@ -675,12 +696,6 @@ static int __init intel_enable_irq_remapping(void)
|
|||||||
* Setup Interrupt-remapping for all the DRHD's now.
|
* Setup Interrupt-remapping for all the DRHD's now.
|
||||||
*/
|
*/
|
||||||
for_each_iommu(iommu, drhd) {
|
for_each_iommu(iommu, drhd) {
|
||||||
if (!ecap_ir_support(iommu->ecap))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (intel_setup_irq_remapping(iommu))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
iommu_set_irq_remapping(iommu, eim);
|
iommu_set_irq_remapping(iommu, eim);
|
||||||
setup = 1;
|
setup = 1;
|
||||||
}
|
}
|
||||||
@ -702,15 +717,7 @@ static int __init intel_enable_irq_remapping(void)
|
|||||||
return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE;
|
return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
for_each_iommu(iommu, drhd)
|
intel_cleanup_irq_remapping();
|
||||||
if (ecap_ir_support(iommu->ecap)) {
|
|
||||||
iommu_disable_irq_remapping(iommu);
|
|
||||||
intel_teardown_irq_remapping(iommu);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x2apic_present)
|
|
||||||
pr_warn("Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n");
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1199,8 +1206,7 @@ static int intel_alloc_hpet_msi(unsigned int irq, unsigned int id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct irq_remap_ops intel_irq_remap_ops = {
|
struct irq_remap_ops intel_irq_remap_ops = {
|
||||||
.supported = intel_irq_remapping_supported,
|
.prepare = intel_prepare_irq_remapping,
|
||||||
.prepare = dmar_table_init,
|
|
||||||
.enable = intel_enable_irq_remapping,
|
.enable = intel_enable_irq_remapping,
|
||||||
.disable = disable_irq_remapping,
|
.disable = disable_irq_remapping,
|
||||||
.reenable = reenable_irq_remapping,
|
.reenable = reenable_irq_remapping,
|
||||||
|
@ -17,12 +17,11 @@
|
|||||||
#include "irq_remapping.h"
|
#include "irq_remapping.h"
|
||||||
|
|
||||||
int irq_remapping_enabled;
|
int irq_remapping_enabled;
|
||||||
|
|
||||||
int disable_irq_remap;
|
|
||||||
int irq_remap_broken;
|
int irq_remap_broken;
|
||||||
int disable_sourceid_checking;
|
int disable_sourceid_checking;
|
||||||
int no_x2apic_optout;
|
int no_x2apic_optout;
|
||||||
|
|
||||||
|
static int disable_irq_remap;
|
||||||
static struct irq_remap_ops *remap_ops;
|
static struct irq_remap_ops *remap_ops;
|
||||||
|
|
||||||
static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec);
|
static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec);
|
||||||
@ -194,45 +193,32 @@ static __init int setup_irqremap(char *str)
|
|||||||
}
|
}
|
||||||
early_param("intremap", setup_irqremap);
|
early_param("intremap", setup_irqremap);
|
||||||
|
|
||||||
void __init setup_irq_remapping_ops(void)
|
|
||||||
{
|
|
||||||
remap_ops = &intel_irq_remap_ops;
|
|
||||||
|
|
||||||
#ifdef CONFIG_AMD_IOMMU
|
|
||||||
if (amd_iommu_irq_ops.prepare() == 0)
|
|
||||||
remap_ops = &amd_iommu_irq_ops;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_irq_remapping_broken(void)
|
void set_irq_remapping_broken(void)
|
||||||
{
|
{
|
||||||
irq_remap_broken = 1;
|
irq_remap_broken = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int irq_remapping_supported(void)
|
|
||||||
{
|
|
||||||
if (disable_irq_remap)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!remap_ops || !remap_ops->supported)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return remap_ops->supported();
|
|
||||||
}
|
|
||||||
|
|
||||||
int __init irq_remapping_prepare(void)
|
int __init irq_remapping_prepare(void)
|
||||||
{
|
{
|
||||||
if (!remap_ops || !remap_ops->prepare)
|
if (disable_irq_remap)
|
||||||
return -ENODEV;
|
return -ENOSYS;
|
||||||
|
|
||||||
return remap_ops->prepare();
|
if (intel_irq_remap_ops.prepare() == 0)
|
||||||
|
remap_ops = &intel_irq_remap_ops;
|
||||||
|
else if (IS_ENABLED(CONFIG_AMD_IOMMU) &&
|
||||||
|
amd_iommu_irq_ops.prepare() == 0)
|
||||||
|
remap_ops = &amd_iommu_irq_ops;
|
||||||
|
else
|
||||||
|
return -ENOSYS;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __init irq_remapping_enable(void)
|
int __init irq_remapping_enable(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!remap_ops || !remap_ops->enable)
|
if (!remap_ops->enable)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
ret = remap_ops->enable();
|
ret = remap_ops->enable();
|
||||||
@ -245,22 +231,16 @@ int __init irq_remapping_enable(void)
|
|||||||
|
|
||||||
void irq_remapping_disable(void)
|
void irq_remapping_disable(void)
|
||||||
{
|
{
|
||||||
if (!irq_remapping_enabled ||
|
if (irq_remapping_enabled && remap_ops->disable)
|
||||||
!remap_ops ||
|
remap_ops->disable();
|
||||||
!remap_ops->disable)
|
|
||||||
return;
|
|
||||||
|
|
||||||
remap_ops->disable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int irq_remapping_reenable(int mode)
|
int irq_remapping_reenable(int mode)
|
||||||
{
|
{
|
||||||
if (!irq_remapping_enabled ||
|
if (irq_remapping_enabled && remap_ops->reenable)
|
||||||
!remap_ops ||
|
return remap_ops->reenable(mode);
|
||||||
!remap_ops->reenable)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return remap_ops->reenable(mode);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __init irq_remap_enable_fault_handling(void)
|
int __init irq_remap_enable_fault_handling(void)
|
||||||
@ -268,7 +248,7 @@ int __init irq_remap_enable_fault_handling(void)
|
|||||||
if (!irq_remapping_enabled)
|
if (!irq_remapping_enabled)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!remap_ops || !remap_ops->enable_faulting)
|
if (!remap_ops->enable_faulting)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
return remap_ops->enable_faulting();
|
return remap_ops->enable_faulting();
|
||||||
@ -279,7 +259,7 @@ int setup_ioapic_remapped_entry(int irq,
|
|||||||
unsigned int destination, int vector,
|
unsigned int destination, int vector,
|
||||||
struct io_apic_irq_attr *attr)
|
struct io_apic_irq_attr *attr)
|
||||||
{
|
{
|
||||||
if (!remap_ops || !remap_ops->setup_ioapic_entry)
|
if (!remap_ops->setup_ioapic_entry)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
return remap_ops->setup_ioapic_entry(irq, entry, destination,
|
return remap_ops->setup_ioapic_entry(irq, entry, destination,
|
||||||
@ -289,8 +269,7 @@ int setup_ioapic_remapped_entry(int irq,
|
|||||||
static int set_remapped_irq_affinity(struct irq_data *data,
|
static int set_remapped_irq_affinity(struct irq_data *data,
|
||||||
const struct cpumask *mask, bool force)
|
const struct cpumask *mask, bool force)
|
||||||
{
|
{
|
||||||
if (!config_enabled(CONFIG_SMP) || !remap_ops ||
|
if (!config_enabled(CONFIG_SMP) || !remap_ops->set_affinity)
|
||||||
!remap_ops->set_affinity)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return remap_ops->set_affinity(data, mask, force);
|
return remap_ops->set_affinity(data, mask, force);
|
||||||
@ -300,10 +279,7 @@ void free_remapped_irq(int irq)
|
|||||||
{
|
{
|
||||||
struct irq_cfg *cfg = irq_cfg(irq);
|
struct irq_cfg *cfg = irq_cfg(irq);
|
||||||
|
|
||||||
if (!remap_ops || !remap_ops->free_irq)
|
if (irq_remapped(cfg) && remap_ops->free_irq)
|
||||||
return;
|
|
||||||
|
|
||||||
if (irq_remapped(cfg))
|
|
||||||
remap_ops->free_irq(irq);
|
remap_ops->free_irq(irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,13 +291,13 @@ void compose_remapped_msi_msg(struct pci_dev *pdev,
|
|||||||
|
|
||||||
if (!irq_remapped(cfg))
|
if (!irq_remapped(cfg))
|
||||||
native_compose_msi_msg(pdev, irq, dest, msg, hpet_id);
|
native_compose_msi_msg(pdev, irq, dest, msg, hpet_id);
|
||||||
else if (remap_ops && remap_ops->compose_msi_msg)
|
else if (remap_ops->compose_msi_msg)
|
||||||
remap_ops->compose_msi_msg(pdev, irq, dest, msg, hpet_id);
|
remap_ops->compose_msi_msg(pdev, irq, dest, msg, hpet_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec)
|
static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec)
|
||||||
{
|
{
|
||||||
if (!remap_ops || !remap_ops->msi_alloc_irq)
|
if (!remap_ops->msi_alloc_irq)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
return remap_ops->msi_alloc_irq(pdev, irq, nvec);
|
return remap_ops->msi_alloc_irq(pdev, irq, nvec);
|
||||||
@ -330,7 +306,7 @@ static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec)
|
|||||||
static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq,
|
static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq,
|
||||||
int index, int sub_handle)
|
int index, int sub_handle)
|
||||||
{
|
{
|
||||||
if (!remap_ops || !remap_ops->msi_setup_irq)
|
if (!remap_ops->msi_setup_irq)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
return remap_ops->msi_setup_irq(pdev, irq, index, sub_handle);
|
return remap_ops->msi_setup_irq(pdev, irq, index, sub_handle);
|
||||||
@ -340,7 +316,7 @@ int setup_hpet_msi_remapped(unsigned int irq, unsigned int id)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!remap_ops || !remap_ops->alloc_hpet_msi)
|
if (!remap_ops->alloc_hpet_msi)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
ret = remap_ops->alloc_hpet_msi(irq, id);
|
ret = remap_ops->alloc_hpet_msi(irq, id);
|
||||||
|
@ -31,16 +31,12 @@ struct cpumask;
|
|||||||
struct pci_dev;
|
struct pci_dev;
|
||||||
struct msi_msg;
|
struct msi_msg;
|
||||||
|
|
||||||
extern int disable_irq_remap;
|
|
||||||
extern int irq_remap_broken;
|
extern int irq_remap_broken;
|
||||||
extern int disable_sourceid_checking;
|
extern int disable_sourceid_checking;
|
||||||
extern int no_x2apic_optout;
|
extern int no_x2apic_optout;
|
||||||
extern int irq_remapping_enabled;
|
extern int irq_remapping_enabled;
|
||||||
|
|
||||||
struct irq_remap_ops {
|
struct irq_remap_ops {
|
||||||
/* Check whether Interrupt Remapping is supported */
|
|
||||||
int (*supported)(void);
|
|
||||||
|
|
||||||
/* Initializes hardware and makes it ready for remapping interrupts */
|
/* Initializes hardware and makes it ready for remapping interrupts */
|
||||||
int (*prepare)(void);
|
int (*prepare)(void);
|
||||||
|
|
||||||
@ -89,7 +85,6 @@ extern struct irq_remap_ops amd_iommu_irq_ops;
|
|||||||
#else /* CONFIG_IRQ_REMAP */
|
#else /* CONFIG_IRQ_REMAP */
|
||||||
|
|
||||||
#define irq_remapping_enabled 0
|
#define irq_remapping_enabled 0
|
||||||
#define disable_irq_remap 1
|
|
||||||
#define irq_remap_broken 0
|
#define irq_remap_broken 0
|
||||||
|
|
||||||
#endif /* CONFIG_IRQ_REMAP */
|
#endif /* CONFIG_IRQ_REMAP */
|
||||||
|
@ -151,6 +151,13 @@ smp_call_function_any(const struct cpumask *mask, smp_call_func_t func,
|
|||||||
static inline void kick_all_cpus_sync(void) { }
|
static inline void kick_all_cpus_sync(void) { }
|
||||||
static inline void wake_up_all_idle_cpus(void) { }
|
static inline void wake_up_all_idle_cpus(void) { }
|
||||||
|
|
||||||
|
#ifdef CONFIG_UP_LATE_INIT
|
||||||
|
extern void __init up_late_init(void);
|
||||||
|
static inline void smp_init(void) { up_late_init(); }
|
||||||
|
#else
|
||||||
|
static inline void smp_init(void) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* !SMP */
|
#endif /* !SMP */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
13
init/main.c
13
init/main.c
@ -87,10 +87,6 @@
|
|||||||
#include <asm/sections.h>
|
#include <asm/sections.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
|
|
||||||
#ifdef CONFIG_X86_LOCAL_APIC
|
|
||||||
#include <asm/smp.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int kernel_init(void *);
|
static int kernel_init(void *);
|
||||||
|
|
||||||
extern void init_IRQ(void);
|
extern void init_IRQ(void);
|
||||||
@ -351,15 +347,6 @@ __setup("rdinit=", rdinit_setup);
|
|||||||
|
|
||||||
#ifndef CONFIG_SMP
|
#ifndef CONFIG_SMP
|
||||||
static const unsigned int setup_max_cpus = NR_CPUS;
|
static const unsigned int setup_max_cpus = NR_CPUS;
|
||||||
#ifdef CONFIG_X86_LOCAL_APIC
|
|
||||||
static void __init smp_init(void)
|
|
||||||
{
|
|
||||||
APIC_init_uniprocessor();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define smp_init() do { } while (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline void setup_nr_cpu_ids(void) { }
|
static inline void setup_nr_cpu_ids(void) { }
|
||||||
static inline void smp_prepare_cpus(unsigned int maxcpus) { }
|
static inline void smp_prepare_cpus(unsigned int maxcpus) { }
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user