# HG changeset patch # User Keir Fraser # Date 1291922374 0 # Node ID d9fc83a64a82624e24876250dd88b2cd9528d266 # Parent 49d2aa5cee4ecc2411d8d638e4ee32c10e9b2761 x86: x2apic: Large cleanup References: bnc#656369, bnc#658704 Signed-off-by: Keir Fraser --- 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 #include -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