ce69a78450
KVM would like to provide x2APIC interface to a guest without emulating interrupt remapping device. The reason KVM prefers guest to use x2APIC is that x2APIC interface is better virtualizable and provides better performance than mmio xAPIC interface: - msr exits are faster than mmio (no page table walk, emulation) - no need to read back ICR to look at the busy bit - one 64 bit ICR write instead of two 32 bit writes - shared code with the Hyper-V paravirt interface Included patch changes x2APIC enabling logic to enable it even if IR initialization failed, but kernel runs under KVM and no apic id is greater than 255 (if there is one spec requires BIOS to move to x2apic mode before starting an OS). -v2: fix build -v3: fix bug causing compiler warning Signed-off-by: Gleb Natapov <gleb@redhat.com> Acked-by: Suresh Siddha <suresh.b.siddha@intel.com> Cc: Sheng Yang <sheng@linux.intel.com> Cc: "avi@redhat.com" <avi@redhat.com> LKML-Reference: <20090720122417.GR5638@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
101 lines
2.2 KiB
C
101 lines
2.2 KiB
C
/*
|
|
* Copyright 2004 James Cleverdon, IBM.
|
|
* Subject to the GNU Public License, v.2
|
|
*
|
|
* Generic APIC sub-arch probe layer.
|
|
*
|
|
* Hacked for x86-64 by James Cleverdon from i386 architecture code by
|
|
* Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
|
|
* James Cleverdon.
|
|
*/
|
|
#include <linux/threads.h>
|
|
#include <linux/cpumask.h>
|
|
#include <linux/string.h>
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/ctype.h>
|
|
#include <linux/init.h>
|
|
#include <linux/hardirq.h>
|
|
#include <linux/dmar.h>
|
|
|
|
#include <asm/smp.h>
|
|
#include <asm/apic.h>
|
|
#include <asm/ipi.h>
|
|
#include <asm/setup.h>
|
|
|
|
extern struct apic apic_flat;
|
|
extern struct apic apic_physflat;
|
|
extern struct apic apic_x2xpic_uv_x;
|
|
extern struct apic apic_x2apic_phys;
|
|
extern struct apic apic_x2apic_cluster;
|
|
|
|
struct apic __read_mostly *apic = &apic_flat;
|
|
EXPORT_SYMBOL_GPL(apic);
|
|
|
|
static struct apic *apic_probe[] __initdata = {
|
|
#ifdef CONFIG_X86_UV
|
|
&apic_x2apic_uv_x,
|
|
#endif
|
|
#ifdef CONFIG_X86_X2APIC
|
|
&apic_x2apic_phys,
|
|
&apic_x2apic_cluster,
|
|
#endif
|
|
&apic_physflat,
|
|
NULL,
|
|
};
|
|
|
|
/*
|
|
* Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
|
|
*/
|
|
void __init default_setup_apic_routing(void)
|
|
{
|
|
#ifdef CONFIG_X86_X2APIC
|
|
if (x2apic_mode
|
|
#ifdef CONFIG_X86_UV
|
|
&& apic != &apic_x2apic_uv_x
|
|
#endif
|
|
) {
|
|
if (x2apic_phys)
|
|
apic = &apic_x2apic_phys;
|
|
else
|
|
apic = &apic_x2apic_cluster;
|
|
printk(KERN_INFO "Setting APIC routing to %s\n", apic->name);
|
|
}
|
|
#endif
|
|
|
|
if (apic == &apic_flat) {
|
|
if (max_physical_apicid >= 8)
|
|
apic = &apic_physflat;
|
|
printk(KERN_INFO "Setting APIC routing to %s\n", apic->name);
|
|
}
|
|
|
|
/*
|
|
* Now that apic routing model is selected, configure the
|
|
* fault handling for intr remapping.
|
|
*/
|
|
if (intr_remapping_enabled)
|
|
enable_drhd_fault_handling();
|
|
}
|
|
|
|
/* Same for both flat and physical. */
|
|
|
|
void apic_send_IPI_self(int vector)
|
|
{
|
|
__default_send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
|
|
}
|
|
|
|
int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; apic_probe[i]; ++i) {
|
|
if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) {
|
|
apic = apic_probe[i];
|
|
printk(KERN_INFO "Setting APIC routing to %s.\n",
|
|
apic->name);
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|