Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x2apic: fix reserved APIC register accesses in print_local_APIC()

APIC_ARBPRI is a reserved register for XAPIC and beyond.
APIC_RRR is a reserved register except for 82489DX, APIC for Pentium processors.
APIC_EOI is a write only register.
APIC_DFR is reserved in x2apic mode.

Access to these registers in x2apic will result in #GP fault. Fix these
apic register accesses.

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: Maciej W. Rozycki <macro@linux-mips.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

authored by

Yinghai Lu and committed by
Ingo Molnar
a11b5abe c59d85a7

+32 -9
+18 -9
arch/x86/kernel/io_apic.c
··· 1751 1751 printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK); 1752 1752 1753 1753 if (APIC_INTEGRATED(ver)) { /* !82489DX */ 1754 - v = apic_read(APIC_ARBPRI); 1755 - printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v, 1756 - v & APIC_ARBPRI_MASK); 1754 + if (!APIC_XAPIC(ver)) { 1755 + v = apic_read(APIC_ARBPRI); 1756 + printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v, 1757 + v & APIC_ARBPRI_MASK); 1758 + } 1757 1759 v = apic_read(APIC_PROCPRI); 1758 1760 printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v); 1759 1761 } 1760 1762 1761 - v = apic_read(APIC_EOI); 1762 - printk(KERN_DEBUG "... APIC EOI: %08x\n", v); 1763 - v = apic_read(APIC_RRR); 1764 - printk(KERN_DEBUG "... APIC RRR: %08x\n", v); 1763 + /* 1764 + * Remote read supported only in the 82489DX and local APIC for 1765 + * Pentium processors. 1766 + */ 1767 + if (!APIC_INTEGRATED(ver) || maxlvt == 3) { 1768 + v = apic_read(APIC_RRR); 1769 + printk(KERN_DEBUG "... APIC RRR: %08x\n", v); 1770 + } 1771 + 1765 1772 v = apic_read(APIC_LDR); 1766 1773 printk(KERN_DEBUG "... APIC LDR: %08x\n", v); 1767 - v = apic_read(APIC_DFR); 1768 - printk(KERN_DEBUG "... APIC DFR: %08x\n", v); 1774 + if (!x2apic_enabled()) { 1775 + v = apic_read(APIC_DFR); 1776 + printk(KERN_DEBUG "... APIC DFR: %08x\n", v); 1777 + } 1769 1778 v = apic_read(APIC_SPIV); 1770 1779 printk(KERN_DEBUG "... APIC SPIV: %08x\n", v); 1771 1780
+14
include/asm-x86/apic.h
··· 98 98 extern void enable_x2apic(void); 99 99 extern void enable_IR_x2apic(void); 100 100 extern void x2apic_icr_write(u32 low, u32 id); 101 + static inline int x2apic_enabled(void) 102 + { 103 + int msr, msr2; 104 + 105 + if (!cpu_has_x2apic) 106 + return 0; 107 + 108 + rdmsr(MSR_IA32_APICBASE, msr, msr2); 109 + if (msr & X2APIC_ENABLE) 110 + return 1; 111 + return 0; 112 + } 113 + #else 114 + #define x2apic_enabled() 0 101 115 #endif 102 116 103 117 struct apic_ops {