]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
x86/apic: Use physical mode for external interrupts even for x2apic_cluster
authorDavid Woodhouse <dwmw@amazon.co.uk>
Wed, 7 Oct 2020 08:01:49 +0000 (09:01 +0100)
committerDavid Woodhouse <dwmw@amazon.co.uk>
Wed, 7 Oct 2020 10:28:36 +0000 (11:28 +0100)
Linux only ever uses dest_Fixed to target a single CPU with external
IOAPIC/MSI interrupts; there's never any benefit to using logical mode
for those.

In logical mode, the destination APIC ID gratuitously requires more
bits, making it less likely to fit into an IOAPIC/MSI destination ID
field which may be limited to 8 bits without interrupt remapping.

Linux has cases which force x2apic_phys mode just to work around this
limitation of external interrupts, when it could perfectly happily be
using cluster mode for IPI communication as long as the *external*
interrupts use physical mode.

There is a corner case where this bimodality doesn't work — when interrupt
remapping is enabled, but there are devices which fall outside the scope
of any remapping unit. Such devices would fall into the scope of the
non-remapped MSI domain, limited to 8 bits of destination ID.

As an alternative to this patch, it might be theoretically possible to
make IOMMU drivers attempt to detect that case in advance, and manually
set x2apic_phys if it is possible that an unremapped device could ever
be hotplugged.

For completeness, the other alternative I see is restricting the non-IR
domains to those *logical* APIC IDs which fit in 8 bits. It's just that
there are very few of those. About 8, in fact.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
arch/x86/kernel/apic/x2apic_cluster.c

index b0889c48a2ac5e02e2ff64c53b1b1f8e25cef7eb..0f8cf9dcc45901f49edfe4a8be9483b2c5856089 100644 (file)
@@ -185,7 +185,7 @@ static struct apic apic_x2apic_cluster __ro_after_init = {
        .apic_id_registered             = x2apic_apic_id_registered,
 
        .irq_delivery_mode              = dest_Fixed,
-       .irq_dest_mode                  = 1, /* logical */
+       .irq_dest_mode                  = 0, /* physical */
 
        .disable_esr                    = 0,
        .dest_logical                   = APIC_DEST_LOGICAL,
@@ -203,7 +203,7 @@ static struct apic apic_x2apic_cluster __ro_after_init = {
        .get_apic_id                    = x2apic_get_apic_id,
        .set_apic_id                    = x2apic_set_apic_id,
 
-       .calc_dest_apicid               = x2apic_calc_apicid,
+       .calc_dest_apicid               = apic_default_calc_apicid,
 
        .send_IPI                       = x2apic_send_IPI,
        .send_IPI_mask                  = x2apic_send_IPI_mask,