Skip to content

Commit e179f69

Browse files
kattisrinivasanH. Peter Anvin
authored andcommitted
x86, irq, pic: Probe for legacy PIC and set legacy_pic appropriately
The legacy PIC may or may not be available and we need a mechanism to detect the existence of the legacy PIC that is applicable for all hardware (both physical as well as virtual) currently supported by Linux. On Hyper-V, when our legacy firmware presented to the guests, emulates the legacy PIC while when our EFI based firmware is presented we do not emulate the PIC. To support Hyper-V EFI firmware, we had to set the legacy_pic to the null_legacy_pic since we had to bypass PIC based calibration in the early boot code. While, on the EFI firmware, we know we don't emulate the legacy PIC, we need a generic mechanism to detect the presence of the legacy PIC that is not based on boot time state - this became apparent when we tried to get kexec to work on Hyper-V EFI firmware. This patch implements the proposal put forth by H. Peter Anvin <[email protected]>: Write a known value to the PIC data port and read it back. If the value read is the value written, we do have the PIC, if not there is no PIC and we can safely set the legacy_pic to null_legacy_pic. Since the read from an unconnected I/O port returns 0xff, we will use ~(1 << PIC_CASCADE_IR) (0xfb: mask all lines except the cascade line) to probe for the existence of the PIC. In version V1 of the patch, I had cleaned up the code based on comments from Peter. In version V2 of the patch, I have addressed additional comments from Peter. In version V3 of the patch, I have addressed Jan's comments ([email protected]). In version V4 of the patch, I have addressed additional comments from Peter. Signed-off-by: K. Y. Srinivasan <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Cc: Thomas Gleixner <[email protected]> Signed-off-by: H. Peter Anvin <[email protected]>
1 parent c9eaa44 commit e179f69

File tree

2 files changed

+19
-10
lines changed

2 files changed

+19
-10
lines changed

arch/x86/kernel/cpu/mshyperv.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,15 +132,6 @@ static void __init ms_hyperv_init_platform(void)
132132
lapic_timer_frequency = hv_lapic_frequency;
133133
printk(KERN_INFO "HyperV: LAPIC Timer Frequency: %#x\n",
134134
lapic_timer_frequency);
135-
136-
/*
137-
* On Hyper-V, when we are booting off an EFI firmware stack,
138-
* we do not have many legacy devices including PIC, PIT etc.
139-
*/
140-
if (efi_enabled(EFI_BOOT)) {
141-
printk(KERN_INFO "HyperV: Using null_legacy_pic\n");
142-
legacy_pic = &null_legacy_pic;
143-
}
144135
}
145136
#endif
146137

arch/x86/kernel/i8259.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,13 +299,31 @@ static void unmask_8259A(void)
299299
static void init_8259A(int auto_eoi)
300300
{
301301
unsigned long flags;
302+
unsigned char probe_val = ~(1 << PIC_CASCADE_IR);
303+
unsigned char new_val;
302304

303305
i8259A_auto_eoi = auto_eoi;
304306

305307
raw_spin_lock_irqsave(&i8259A_lock, flags);
306308

307-
outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */
309+
/*
310+
* Check to see if we have a PIC.
311+
* Mask all except the cascade and read
312+
* back the value we just wrote. If we don't
313+
* have a PIC, we will read 0xff as opposed to the
314+
* value we wrote.
315+
*/
308316
outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */
317+
outb(probe_val, PIC_MASTER_IMR);
318+
new_val = inb(PIC_MASTER_IMR);
319+
if (new_val != probe_val) {
320+
printk(KERN_INFO "Using NULL legacy PIC\n");
321+
legacy_pic = &null_legacy_pic;
322+
raw_spin_unlock_irqrestore(&i8259A_lock, flags);
323+
return;
324+
}
325+
326+
outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */
309327

310328
/*
311329
* outb_pic - this has to work on a wide range of PC hardware.

0 commit comments

Comments
 (0)