From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754397AbZBRMJU (ORCPT ); Wed, 18 Feb 2009 07:09:20 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753537AbZBRMGz (ORCPT ); Wed, 18 Feb 2009 07:06:55 -0500 Received: from mx2.redhat.com ([66.187.237.31]:47933 "EHLO mx2.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754248AbZBRMGx (ORCPT ); Wed, 18 Feb 2009 07:06:53 -0500 Date: Wed, 18 Feb 2009 14:00:51 +0200 From: Gleb Natapov To: linux-kernel@vger.kernel.org Cc: yinghai@kernel.org, mingo@elte.hu Subject: [PATCH] decouple x2apic from irq remapping Message-ID: <20090218120051.GF26845@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi, Currently x2apic is used only if interrupt remapping can be enabled, but if all apic ids are smaller then 255 there is no reason to enable interrupt remapping at all. Although there is not real HW that has x2apic but does not have IR the decoupling is useful since we want to emulate x2apic interface in KVM (it is more vitalization friendly), but we don't want to emulate IR just for that. According to Intel docs BIOS should pass control to OS in x2apic mode if there are apics with id > 255 and in xapic otherwise, so the proposed patch requires IR configuration only if BIOS switched apic to x2apic mode. The patch is against tip:x86/apic. Signed-off-by: Gleb Natapov diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index af494ba..2f048f8 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -1293,10 +1293,33 @@ void enable_x2apic(void) } } -void __init enable_IR_x2apic(void) +static int __init enable_IR(void) { -#ifdef CONFIG_INTR_REMAP int ret; + + ret = dmar_table_init(); + if (ret) { + pr_info("dmar_table_init() failed with %d:\n", ret); + return ret; + } + + ret = save_mask_IO_APIC_setup(); + if (ret) { + pr_info("Saving IO-APIC state failed: %d\n", ret); + return ret; + } + + ret = enable_intr_remapping(1); + if (ret) + return ret; + + reinit_intr_remapped_IO_APIC(x2apic_preenabled); + + return 0; +} + +void __init enable_IR_x2apic(void) +{ unsigned long flags; if (!cpu_has_x2apic) @@ -1317,72 +1340,33 @@ void __init enable_IR_x2apic(void) return; } - ret = dmar_table_init(); - if (ret) { - pr_info("dmar_table_init() failed with %d:\n", ret); - - if (x2apic_preenabled) - panic("x2apic enabled by bios. But IR enabling failed"); - else - pr_info("Not enabling x2apic,Intr-remapping\n"); - return; - } - local_irq_save(flags); mask_8259A(); - ret = save_mask_IO_APIC_setup(); - if (ret) { - pr_info("Saving IO-APIC state failed: %d\n", ret); - goto end; - } - - ret = enable_intr_remapping(1); - - if (ret && x2apic_preenabled) { + if (x2apic_preenabled) { +#ifdef CONFIG_INTR_REMAP + if (enable_IR()) { + local_irq_restore(flags); + panic("x2apic enabled by bios. But IR enabling failed"); + } +#else local_irq_restore(flags); - panic("x2apic enabled by bios. But IR enabling failed"); + panic("x2apic enabled prior OS handover," + " enable CONFIG_INTR_REMAP"); +#endif + pr_info("Enabled interrupt remapping for x2apic\n"); } - if (ret) - goto end_restore; - if (!x2apic) { x2apic = 1; enable_x2apic(); } -end_restore: - if (ret) - /* - * IR enabling failed - */ - restore_IO_APIC_setup(); - else - reinit_intr_remapped_IO_APIC(x2apic_preenabled); - -end: unmask_8259A(); local_irq_restore(flags); - if (!ret) { - if (!x2apic_preenabled) - pr_info("Enabled x2apic and interrupt-remapping\n"); - else - pr_info("Enabled Interrupt-remapping\n"); - } else - pr_err("Failed to enable Interrupt-remapping and x2apic\n"); -#else - if (!cpu_has_x2apic) - return; - - if (x2apic_preenabled) - panic("x2apic enabled prior OS handover," - " enable CONFIG_INTR_REMAP"); - - pr_info("Enable CONFIG_INTR_REMAP for enabling intr-remapping " - " and x2apic\n"); -#endif + if (!x2apic_preenabled) + pr_info("Enabled x2apic\n"); return; } diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index ef78863..0fd3bed 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -49,13 +49,6 @@ static struct genapic *apic_probe[] __initdata = { */ void __init default_setup_apic_routing(void) { -#ifdef CONFIG_X86_X2APIC - if (apic == &apic_x2apic_phys || apic == &apic_x2apic_cluster) { - if (!intr_remapping_enabled) - apic = &apic_flat; - } -#endif - if (apic == &apic_flat) { if (max_physical_apicid >= 8) apic = &apic_physflat; diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index dd6e8d6..b1d4e4e 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -24,7 +24,10 @@ static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) static const struct cpumask *x2apic_target_cpus(void) { - return cpumask_of(0); + if (intr_remapping_enabled) + return cpumask_of(0); + else + return cpu_online_mask; } /* @@ -116,37 +119,46 @@ static int x2apic_apic_id_registered(void) static unsigned int x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask) { - /* - * We're using fixed IRQ delivery, can only return one logical APIC ID. - * May as well be the first. - */ - int cpu = cpumask_first(cpumask); - - if ((unsigned)cpu < nr_cpu_ids) - return per_cpu(x86_cpu_to_logical_apicid, cpu); - else - return BAD_APICID; + if (intr_remapping_enabled) { + /* + * We're using fixed IRQ delivery, can only return one + * logical APIC ID. May as well be the first. + */ + int cpu = cpumask_first(cpumask); + + if ((unsigned)cpu < nr_cpu_ids) + return per_cpu(x86_cpu_to_logical_apicid, cpu); + else + return BAD_APICID; + } else + return cpumask_bits(cpumask)[0] & APIC_ALL_CPUS; } static unsigned int x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, const struct cpumask *andmask) { - int cpu; + if (intr_remapping_enabled) { + int cpu; - /* - * We're using fixed IRQ delivery, can only return one logical APIC ID. - * May as well be the first. - */ - for_each_cpu_and(cpu, cpumask, andmask) { - if (cpumask_test_cpu(cpu, cpu_online_mask)) - break; - } + /* + * We're using fixed IRQ delivery, can only return one + * logical APIC ID. May as well be the first. + */ + for_each_cpu_and(cpu, cpumask, andmask) { + if (cpumask_test_cpu(cpu, cpu_online_mask)) + break; + } - if (cpu < nr_cpu_ids) - return per_cpu(x86_cpu_to_logical_apicid, cpu); + if (cpu < nr_cpu_ids) + return per_cpu(x86_cpu_to_logical_apicid, cpu); - return BAD_APICID; + return BAD_APICID; + } else { + unsigned long mask1 = cpumask_bits(cpumask)[0] & APIC_ALL_CPUS; + unsigned long mask2 = cpumask_bits(andmask)[0] & APIC_ALL_CPUS; + return mask1 & mask2; + } } static unsigned int x2apic_cluster_phys_get_apic_id(unsigned long x) -- Gleb.