diff options
Diffstat (limited to 'arch/x86/kernel/apic/apic.c')
| -rw-r--r-- | arch/x86/kernel/apic/apic.c | 29 | 
1 files changed, 25 insertions, 4 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 098ec84b8c0..c3be10f5773 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -98,6 +98,29 @@ early_param("lapic", parse_lapic);  /* Local APIC was disabled by the BIOS and enabled by the kernel */  static int enabled_via_apicbase; +/* + * Handle interrupt mode configuration register (IMCR). + * This register controls whether the interrupt signals + * that reach the BSP come from the master PIC or from the + * local APIC. Before entering Symmetric I/O Mode, either + * the BIOS or the operating system must switch out of + * PIC Mode by changing the IMCR. + */ +static inline imcr_pic_to_apic(void) +{ +	/* select IMCR register */ +	outb(0x70, 0x22); +	/* NMI and 8259 INTR go through APIC */ +	outb(0x01, 0x23); +} + +static inline imcr_apic_to_pic(void) +{ +	/* select IMCR register */ +	outb(0x70, 0x22); +	/* NMI and 8259 INTR go directly to BSP */ +	outb(0x00, 0x23); +}  #endif  #ifdef CONFIG_X86_64 @@ -1727,8 +1750,7 @@ void __init connect_bsp_APIC(void)  		 */  		apic_printk(APIC_VERBOSE, "leaving PIC mode, "  				"enabling APIC mode.\n"); -		outb(0x70, 0x22); -		outb(0x01, 0x23); +		imcr_pic_to_apic();  	}  #endif  	if (apic->enable_apic_mode) @@ -1756,8 +1778,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)  		 */  		apic_printk(APIC_VERBOSE, "disabling APIC mode, "  				"entering PIC mode.\n"); -		outb(0x70, 0x22); -		outb(0x00, 0x23); +		imcr_apic_to_pic();  		return;  	}  #endif  | 
