xen/22475-x2apic-cleanup.patch

481 lines
14 KiB
Diff
Raw Normal View History

# HG changeset patch
# User Keir Fraser <keir@xen.org>
# Date 1291922374 0
# Node ID d9fc83a64a82624e24876250dd88b2cd9528d266
# Parent 49d2aa5cee4ecc2411d8d638e4ee32c10e9b2761
x86: x2apic: Large cleanup
References: bnc#656369, bnc#658704
Signed-off-by: Keir Fraser <keir@xen.org>
--- a/xen/arch/x86/apic.c
+++ b/xen/arch/x86/apic.c
@@ -67,12 +67,12 @@ static int enable_local_apic __initdata
*/
int apic_verbosity;
+static int opt_x2apic = 1;
+boolean_param("x2apic", opt_x2apic);
+
int x2apic_enabled __read_mostly = 0;
int directed_eoi_enabled __read_mostly = 0;
-/* x2APIC is enabled in BIOS */
-static int x2apic_preenabled;
-
/*
* The following vectors are part of the Linux architecture, there
* is no hardware IRQ pin equivalent for them, they are triggered
@@ -944,30 +944,24 @@ no_apic:
return -1;
}
-void check_x2apic_preenabled(void)
+void x2apic_setup(void)
{
+ struct IO_APIC_route_entry **ioapic_entries = NULL;
u32 lo, hi;
- if ( !x2apic_is_available() )
- return;
-
- rdmsr(MSR_IA32_APICBASE, lo, hi);
- if ( lo & MSR_IA32_APICBASE_EXTD )
+ if ( smp_processor_id() != 0 )
{
- printk("x2APIC mode is already enabled by BIOS.\n");
- x2apic_preenabled = 1;
- x2apic_enabled = 1;
+ if ( x2apic_enabled )
+ __enable_x2apic();
+ return;
}
-}
-static void enable_bsp_x2apic(void)
-{
- struct IO_APIC_route_entry **ioapic_entries = NULL;
- const struct genapic *x2apic_genapic = NULL;
-
- ASSERT(smp_processor_id() == 0);
+ if ( !cpu_has_x2apic )
+ return;
- if ( x2apic_preenabled )
+ /* Check whether x2apic mode was already enabled by the BIOS. */
+ rdmsr(MSR_IA32_APICBASE, lo, hi);
+ if ( lo & MSR_IA32_APICBASE_EXTD )
{
/*
* Interrupt remapping should be also enabled by BIOS when
@@ -977,39 +971,33 @@ static void enable_bsp_x2apic(void)
if ( !intremap_enabled() )
panic("Interrupt remapping is not enabled by BIOS while "
"x2APIC is already enabled by BIOS!\n");
+
+ printk("x2APIC mode is already enabled by BIOS.\n");
+ x2apic_enabled = 1;
}
- x2apic_genapic = apic_x2apic_probe();
- if ( x2apic_genapic )
- genapic = x2apic_genapic;
- else
+ if ( !opt_x2apic )
{
- if ( x2apic_cmdline_disable() )
+ if ( !x2apic_enabled )
{
- if ( x2apic_preenabled )
- {
- /* Ignore x2apic=0, and set default x2apic mode */
- genapic = &apic_x2apic_cluster;
- printk("x2APIC: already enabled by BIOS, ignore x2apic=0.\n");
- }
- else
- {
- printk("Not enable x2APIC due to x2apic=0 is set.\n");
- return;
- }
+ printk("Not enabling x2APIC: disabled by cmdline.\n");
+ return;
}
- else
+ printk("x2APIC: Already enabled by BIOS: Ignoring cmdline disable.\n");
+ }
+
+ if ( !iommu_supports_eim() )
+ {
+ if ( !x2apic_enabled )
{
- if ( x2apic_preenabled )
- panic("x2APIC: already enabled by BIOS, but "
- "iommu_supports_eim failed!\n");
- printk("Not enabling x2APIC: depends oniommu_supports_eim\n");
+ printk("Not enabling x2APIC: depends on iommu_supports_eim.\n");
return;
}
+ panic("x2APIC: already enabled by BIOS, but "
+ "iommu_supports_eim failed!\n");
}
- ioapic_entries = alloc_ioapic_entries();
- if ( !ioapic_entries )
+ if ( (ioapic_entries = alloc_ioapic_entries()) == NULL )
{
printk("Allocate ioapic_entries failed\n");
goto out;
@@ -1031,13 +1019,13 @@ static void enable_bsp_x2apic(void)
goto restore_out;
}
- x2apic_enabled = 1;
+ genapic = apic_x2apic_probe();
printk("Switched to APIC driver %s.\n", genapic->name);
- if ( !x2apic_preenabled )
+ if ( !x2apic_enabled )
{
+ x2apic_enabled = 1;
__enable_x2apic();
- printk("x2APIC mode enabled.\n");
}
restore_out:
@@ -1049,24 +1037,6 @@ out:
free_ioapic_entries(ioapic_entries);
}
-static void enable_ap_x2apic(void)
-{
- ASSERT(smp_processor_id() != 0);
-
- /* APs only enable x2apic when BSP did so. */
- BUG_ON(!x2apic_enabled);
-
- __enable_x2apic();
-}
-
-void enable_x2apic(void)
-{
- if ( smp_processor_id() == 0 )
- enable_bsp_x2apic();
- else
- enable_ap_x2apic();
-}
-
void __init init_apic_mappings(void)
{
unsigned long apic_phys;
--- a/xen/arch/x86/cpu/common.c
+++ b/xen/arch/x86/cpu/common.c
@@ -250,8 +250,8 @@ static void __init early_cpu_detect(void
c->x86 = 4;
if (c->cpuid_level >= 0x00000001) {
- u32 junk, tfms, cap0, misc;
- cpuid(0x00000001, &tfms, &misc, &junk, &cap0);
+ u32 cap4, tfms, cap0, misc;
+ cpuid(0x00000001, &tfms, &misc, &cap4, &cap0);
c->x86 = (tfms >> 8) & 15;
c->x86_model = (tfms >> 4) & 15;
if (c->x86 == 0xf)
@@ -260,9 +260,12 @@ static void __init early_cpu_detect(void
c->x86_model += ((tfms >> 16) & 0xF) << 4;
c->x86_mask = tfms & 15;
cap0 &= ~cleared_caps[0];
+ cap4 &= ~cleared_caps[4];
if (cap0 & (1<<19))
c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8;
- c->x86_capability[0] = cap0; /* Added for Xen bootstrap */
+ /* Leaf 0x1 capabilities filled in early for Xen. */
+ c->x86_capability[0] = cap0;
+ c->x86_capability[4] = cap4;
}
}
--- a/xen/arch/x86/genapic/x2apic.c
+++ b/xen/arch/x86/genapic/x2apic.c
@@ -23,89 +23,44 @@
#include <xen/smp.h>
#include <asm/mach-default/mach_mpparse.h>
-static int x2apic = 1;
-boolean_param("x2apic", x2apic);
-
-static int x2apic_phys; /* By default we use logical cluster mode. */
+static int x2apic_phys; /* By default we use logical cluster mode. */
boolean_param("x2apic_phys", x2apic_phys);
-int x2apic_cmdline_disable(void)
-{
- return (x2apic == 0);
-}
-
-static int probe_x2apic_phys(void)
+static void init_apic_ldr_x2apic_phys(void)
{
- return x2apic && x2apic_phys && x2apic_is_available() &&
- iommu_supports_eim();
}
-static int probe_x2apic_cluster(void)
-{
- return x2apic && !x2apic_phys && x2apic_is_available() &&
- iommu_supports_eim();
-}
-
-const struct genapic apic_x2apic_phys = {
- APIC_INIT("x2apic_phys", probe_x2apic_phys),
- GENAPIC_X2APIC_PHYS
-};
-
-const struct genapic apic_x2apic_cluster = {
- APIC_INIT("x2apic_cluster", probe_x2apic_cluster),
- GENAPIC_X2APIC_CLUSTER
-};
-
-const struct genapic *apic_x2apic_probe(void)
-{
- if ( !x2apic || !x2apic_is_available() )
- return NULL;
-
- if ( !iommu_supports_eim() )
- return NULL;
-
- if ( x2apic_phys )
- return &apic_x2apic_phys;
- else
- return &apic_x2apic_cluster;
-}
-
-void init_apic_ldr_x2apic_phys(void)
-{
- return;
-}
-
-void init_apic_ldr_x2apic_cluster(void)
+static void init_apic_ldr_x2apic_cluster(void)
{
int cpu = smp_processor_id();
cpu_2_logical_apicid[cpu] = apic_read(APIC_LDR);
}
-void clustered_apic_check_x2apic(void)
+
+static void clustered_apic_check_x2apic(void)
{
- return;
}
-cpumask_t target_cpus_x2apic(void)
+static cpumask_t target_cpus_x2apic(void)
{
return cpu_online_map;
}
-cpumask_t vector_allocation_domain_x2apic(int cpu)
+static cpumask_t vector_allocation_domain_x2apic(int cpu)
{
return cpumask_of_cpu(cpu);
}
-unsigned int cpu_mask_to_apicid_x2apic_phys(cpumask_t cpumask)
+static unsigned int cpu_mask_to_apicid_x2apic_phys(cpumask_t cpumask)
{
return cpu_physical_id(first_cpu(cpumask));
}
-unsigned int cpu_mask_to_apicid_x2apic_cluster(cpumask_t cpumask)
+static unsigned int cpu_mask_to_apicid_x2apic_cluster(cpumask_t cpumask)
{
return cpu_2_logical_apicid[first_cpu(cpumask)];
}
-void send_IPI_mask_x2apic_phys(const cpumask_t *cpumask, int vector)
+static void send_IPI_mask_x2apic_phys(const cpumask_t *cpumask, int vector)
{
unsigned int cpu, cfg;
unsigned long flags;
@@ -132,7 +87,7 @@ void send_IPI_mask_x2apic_phys(const cpu
local_irq_restore(flags);
}
-void send_IPI_mask_x2apic_cluster(const cpumask_t *cpumask, int vector)
+static void send_IPI_mask_x2apic_cluster(const cpumask_t *cpumask, int vector)
{
unsigned int cpu, cfg;
unsigned long flags;
@@ -148,3 +103,34 @@ void send_IPI_mask_x2apic_cluster(const
local_irq_restore(flags);
}
+
+static const struct genapic apic_x2apic_phys = {
+ APIC_INIT("x2apic_phys", NULL),
+ .int_delivery_mode = dest_Fixed,
+ .int_dest_mode = 0 /* physical delivery */,
+ .init_apic_ldr = init_apic_ldr_x2apic_phys,
+ .clustered_apic_check = clustered_apic_check_x2apic,
+ .target_cpus = target_cpus_x2apic,
+ .vector_allocation_domain = vector_allocation_domain_x2apic,
+ .cpu_mask_to_apicid = cpu_mask_to_apicid_x2apic_phys,
+ .send_IPI_mask = send_IPI_mask_x2apic_phys,
+ .send_IPI_self = send_IPI_self_x2apic
+};
+
+static const struct genapic apic_x2apic_cluster = {
+ APIC_INIT("x2apic_cluster", NULL),
+ .int_delivery_mode = dest_LowestPrio,
+ .int_dest_mode = 1 /* logical delivery */,
+ .init_apic_ldr = init_apic_ldr_x2apic_cluster,
+ .clustered_apic_check = clustered_apic_check_x2apic,
+ .target_cpus = target_cpus_x2apic,
+ .vector_allocation_domain = vector_allocation_domain_x2apic,
+ .cpu_mask_to_apicid = cpu_mask_to_apicid_x2apic_cluster,
+ .send_IPI_mask = send_IPI_mask_x2apic_cluster,
+ .send_IPI_self = send_IPI_self_x2apic
+};
+
+const struct genapic *apic_x2apic_probe(void)
+{
+ return x2apic_phys ? &apic_x2apic_phys : &apic_x2apic_cluster;
+}
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -1006,9 +1006,6 @@ void __init __start_xen(unsigned long mb
tboot_probe();
- /* Check if x2APIC is already enabled in BIOS */
- check_x2apic_preenabled();
-
/* Unmap the first page of CPU0's stack. */
memguard_guard_stack(cpu0_stack);
@@ -1039,8 +1036,7 @@ void __init __start_xen(unsigned long mb
init_apic_mappings();
- if ( x2apic_is_available() )
- enable_x2apic();
+ x2apic_setup();
percpu_free_unused_areas();
--- a/xen/arch/x86/smpboot.c
+++ b/xen/arch/x86/smpboot.c
@@ -325,8 +325,7 @@ void __devinit smp_callin(void)
*/
wait_for_init_deassert(&init_deasserted);
- if ( x2apic_enabled )
- enable_x2apic();
+ x2apic_setup();
/*
* (This works even if the APIC is not enabled.)
--- a/xen/drivers/passthrough/vtd/intremap.c
+++ b/xen/drivers/passthrough/vtd/intremap.c
@@ -129,15 +129,10 @@ int iommu_supports_eim(void)
struct acpi_drhd_unit *drhd;
int apic;
- if ( !iommu_enabled || !iommu_qinval || !iommu_intremap )
+ if ( !iommu_enabled || !iommu_qinval || !iommu_intremap ||
+ list_empty(&acpi_drhd_units) )
return 0;
- if ( list_empty(&acpi_drhd_units) )
- {
- dprintk(XENLOG_WARNING VTDPREFIX, "VT-d is not supported\n");
- return 0;
- }
-
/* We MUST have a DRHD unit for each IOAPIC. */
for ( apic = 0; apic < nr_ioapics; apic++ )
if ( !ioapic_to_drhd(IO_APIC_ID(apic)) )
--- a/xen/include/asm-x86/apic.h
+++ b/xen/include/asm-x86/apic.h
@@ -25,21 +25,8 @@ extern int apic_verbosity;
extern int x2apic_enabled;
extern int directed_eoi_enabled;
-extern void check_x2apic_preenabled(void);
-extern int x2apic_cmdline_disable(void);
-extern void enable_x2apic(void);
-
-static __inline int x2apic_is_available(void)
-{
- unsigned int op = 1, eax, ecx;
-
- asm ( "cpuid"
- : "=a" (eax), "=c" (ecx)
- : "0" (op)
- : "bx", "dx" );
-
- return (ecx & (1U << 21));
-}
+void x2apic_setup(void);
+const struct genapic *apic_x2apic_probe(void);
/*
* Define the default level of output to be very little
--- a/xen/include/asm-x86/genapic.h
+++ b/xen/include/asm-x86/genapic.h
@@ -49,8 +49,6 @@ struct genapic {
APICFUNC(acpi_madt_oem_check)
extern const struct genapic *genapic;
-extern const struct genapic apic_x2apic_phys;
-extern const struct genapic apic_x2apic_cluster;
void init_apic_ldr_flat(void);
void clustered_apic_check_flat(void);
@@ -70,39 +68,6 @@ cpumask_t vector_allocation_domain_flat(
.send_IPI_mask = send_IPI_mask_flat, \
.send_IPI_self = send_IPI_self_flat
-const struct genapic *apic_x2apic_probe(void);
-void init_apic_ldr_x2apic_phys(void);
-void init_apic_ldr_x2apic_cluster(void);
-void clustered_apic_check_x2apic(void);
-cpumask_t target_cpus_x2apic(void);
-unsigned int cpu_mask_to_apicid_x2apic_phys(cpumask_t cpumask);
-unsigned int cpu_mask_to_apicid_x2apic_cluster(cpumask_t cpumask);
-void send_IPI_mask_x2apic_phys(const cpumask_t *mask, int vector);
-void send_IPI_mask_x2apic_cluster(const cpumask_t *mask, int vector);
-void send_IPI_self_x2apic(int vector);
-cpumask_t vector_allocation_domain_x2apic(int cpu);
-#define GENAPIC_X2APIC_PHYS \
- .int_delivery_mode = dest_Fixed, \
- .int_dest_mode = 0 /* physical delivery */, \
- .init_apic_ldr = init_apic_ldr_x2apic_phys, \
- .clustered_apic_check = clustered_apic_check_x2apic, \
- .target_cpus = target_cpus_x2apic, \
- .vector_allocation_domain = vector_allocation_domain_x2apic, \
- .cpu_mask_to_apicid = cpu_mask_to_apicid_x2apic_phys, \
- .send_IPI_mask = send_IPI_mask_x2apic_phys, \
- .send_IPI_self = send_IPI_self_x2apic
-
-#define GENAPIC_X2APIC_CLUSTER \
- .int_delivery_mode = dest_LowestPrio, \
- .int_dest_mode = 1 /* logical delivery */, \
- .init_apic_ldr = init_apic_ldr_x2apic_cluster, \
- .clustered_apic_check = clustered_apic_check_x2apic, \
- .target_cpus = target_cpus_x2apic, \
- .vector_allocation_domain = vector_allocation_domain_x2apic, \
- .cpu_mask_to_apicid = cpu_mask_to_apicid_x2apic_cluster, \
- .send_IPI_mask = send_IPI_mask_x2apic_cluster, \
- .send_IPI_self = send_IPI_self_x2apic
-
void init_apic_ldr_phys(void);
void clustered_apic_check_phys(void);
cpumask_t target_cpus_phys(void);
@@ -121,4 +86,6 @@ cpumask_t vector_allocation_domain_phys(
.send_IPI_mask = send_IPI_mask_phys, \
.send_IPI_self = send_IPI_self_phys
+void send_IPI_self_x2apic(int vector);
+
#endif