[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen staging] x86/IRQ: re-use legacy vector ranges on APs



commit 3fba06ba9f8bbf80b601e9760ae47f4bf96097a0
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Fri Dec 27 09:54:59 2019 +0100
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Fri Dec 27 09:54:59 2019 +0100

    x86/IRQ: re-use legacy vector ranges on APs
    
    The legacy vectors have been actively used on CPU 0 only. CPUs not
    sharing vector space with CPU 0 can easily re-use them, slightly
    increasing the relatively scarce resource of total vectors available in
    the system. As a result the legacy vector range simply becomes a
    sub-range of the dynamic one, with an extra check performed in
    _assign_irq_vector() (we can't rely on the
    "per_cpu(vector_irq, new_cpu)[vector] >= 0" check in the subsequent
    loop, as we need to also exclude vectors of disabled legacy IRQs).
    
    Suggested-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Acked-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
 xen/arch/x86/io_apic.c                         |  5 ++---
 xen/arch/x86/irq.c                             | 30 ++++++++++++++++++++------
 xen/include/asm-x86/apicdef.h                  |  3 +++
 xen/include/asm-x86/mach-default/irq_vectors.h | 15 ++++++++-----
 4 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c
index 9913dfde1f..6093648197 100644
--- a/xen/arch/x86/io_apic.c
+++ b/xen/arch/x86/io_apic.c
@@ -2389,8 +2389,7 @@ int ioapic_guest_write(unsigned long physbase, unsigned 
int reg, u32 val)
     }
 
     if ( desc->arch.vector <= 0 || desc->arch.vector > LAST_DYNAMIC_VECTOR ||
-         (desc->arch.vector >= FIRST_LEGACY_VECTOR &&
-          desc->arch.vector <= LAST_LEGACY_VECTOR) )
+         desc->handler->enable == enable_8259A_irq )
     {
         int vector = desc->arch.vector;
 
@@ -2617,7 +2616,7 @@ void __init init_ioapic_mappings(void)
 
     if ( nr_irqs == 0 )
         nr_irqs = cpu_has_apic ?
-                  max(16U + num_present_cpus() * NR_DYNAMIC_VECTORS,
+                  max(0U + num_present_cpus() * NR_DYNAMIC_VECTORS,
                       8 * nr_irqs_gsi) :
                   nr_irqs_gsi;
     else if ( nr_irqs < 16 )
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
index ae02cf1712..e48e323fd7 100644
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -361,17 +361,25 @@ void destroy_irq(unsigned int irq)
 int irq_to_vector(int irq)
 {
     int vector = IRQ_VECTOR_UNASSIGNED;
+    const struct irq_desc *desc;
 
     BUG_ON(irq >= nr_irqs || irq < 0);
+    desc = irq_to_desc(irq);
 
     if (IO_APIC_IRQ(irq))
     {
-        vector = irq_to_desc(irq)->arch.vector;
-        if (vector >= FIRST_LEGACY_VECTOR && vector <= LAST_LEGACY_VECTOR)
+        vector = desc->arch.vector;
+        /*
+         * Both parts of the condition are needed here during early boot, as
+         * at that time IRQ0 in particular may still have the 8259A chip set,
+         * but has already got its special IRQ0_VECTOR.
+         */
+        if ( desc->handler->enable == enable_8259A_irq &&
+             vector >= FIRST_LEGACY_VECTOR && vector <= LAST_LEGACY_VECTOR )
             vector = 0;
     }
     else if (MSI_IRQ(irq))
-        vector = irq_to_desc(irq)->arch.vector;
+        vector = desc->arch.vector;
     else
         vector = LEGACY_VECTOR(irq);
 
@@ -568,6 +576,10 @@ next:
             && test_bit(vector, irq_used_vectors) )
             goto next;
 
+        if ( cpumask_test_cpu(0, vec_mask) &&
+             vector >= FIRST_LEGACY_VECTOR && vector <= LAST_LEGACY_VECTOR )
+            goto next;
+
         for_each_cpu(new_cpu, vec_mask)
             if (per_cpu(vector_irq, new_cpu)[vector] >= 0)
                 goto next;
@@ -713,6 +725,10 @@ void irq_move_cleanup_interrupt(struct cpu_user_regs *regs)
 {
     unsigned vector, me;
 
+    /* This interrupt should not nest inside others. */
+    BUILD_BUG_ON(APIC_PRIO_CLASS(IRQ_MOVE_CLEANUP_VECTOR) !=
+                 APIC_PRIO_CLASS(FIRST_DYNAMIC_VECTOR));
+
     ack_APIC_irq();
 
     me = smp_processor_id();
@@ -730,14 +746,15 @@ void irq_move_cleanup_interrupt(struct cpu_user_regs 
*regs)
         if ((int)irq < 0)
             continue;
 
-        if ( vector >= FIRST_LEGACY_VECTOR && vector <= LAST_LEGACY_VECTOR )
-            continue;
-
         desc = irq_to_desc(irq);
         if (!desc)
             continue;
 
         spin_lock(&desc->lock);
+
+        if (desc->handler->enable == enable_8259A_irq)
+            goto unlock;
+
         if (!desc->arch.move_cleanup_count)
             goto unlock;
 
@@ -1894,6 +1911,7 @@ void do_IRQ(struct cpu_user_regs *regs)
                 kind = "";
             if ( !(vector >= FIRST_LEGACY_VECTOR &&
                    vector <= LAST_LEGACY_VECTOR &&
+                   !smp_processor_id() &&
                    bogus_8259A_irq(vector - FIRST_LEGACY_VECTOR)) )
             {
                 printk("CPU%u: No irq handler for vector %02x (IRQ %d%s)\n",
diff --git a/xen/include/asm-x86/apicdef.h b/xen/include/asm-x86/apicdef.h
index d00850699e..0633da9fe1 100644
--- a/xen/include/asm-x86/apicdef.h
+++ b/xen/include/asm-x86/apicdef.h
@@ -119,6 +119,9 @@
 /* Only available in x2APIC mode */
 #define                APIC_SELF_IPI   0x3F0
 
+/* Applicable to vectors, TPR, and PPR. */
+#define                APIC_PRIO_CLASS(v)      ((v) & 0xF0)
+
 #define APIC_BASE __fix_to_virt(FIX_APIC_BASE)
 
 /* It's only used in x2APIC mode of an x2APIC unit. */
diff --git a/xen/include/asm-x86/mach-default/irq_vectors.h 
b/xen/include/asm-x86/mach-default/irq_vectors.h
index 6824a9e301..ba77d790ed 100644
--- a/xen/include/asm-x86/mach-default/irq_vectors.h
+++ b/xen/include/asm-x86/mach-default/irq_vectors.h
@@ -19,22 +19,27 @@
 #define IRQ0_VECTOR             0xf0
 
 /* Legacy PIC uses vectors 0x20-0x2f. */
-#define FIRST_LEGACY_VECTOR     0x20
+#define FIRST_LEGACY_VECTOR     FIRST_DYNAMIC_VECTOR
 #define LAST_LEGACY_VECTOR      (FIRST_LEGACY_VECTOR + 0xf)
 
 #define HYPERCALL_VECTOR       0x82
 #define LEGACY_SYSCALL_VECTOR   0x80
 
-/* Dynamically-allocated vectors available to any driver. */
-#define FIRST_DYNAMIC_VECTOR    (LAST_LEGACY_VECTOR + 1)
+/*
+ * Dynamically-allocated vectors available to any driver. Note that the
+ * legacy vector range is a sub-range of this one, re-used on CPUs not
+ * sharing vectors with CPU 0.
+ */
+#define FIRST_DYNAMIC_VECTOR    0x20
 #define LAST_DYNAMIC_VECTOR     0xef
 #define NR_DYNAMIC_VECTORS     (LAST_DYNAMIC_VECTOR - FIRST_DYNAMIC_VECTOR + 1)
 
-#define IRQ_MOVE_CLEANUP_VECTOR FIRST_DYNAMIC_VECTOR
+/* There's no IRQ2 at the PIC. */
+#define IRQ_MOVE_CLEANUP_VECTOR (FIRST_LEGACY_VECTOR + 2)
 
 #define NR_VECTORS 256
 
-#define FIRST_IRQ_VECTOR        FIRST_LEGACY_VECTOR
+#define FIRST_IRQ_VECTOR        FIRST_DYNAMIC_VECTOR
 #define LAST_IRQ_VECTOR         LAST_HIPRIORITY_VECTOR
 
 #endif /* _ASM_IRQ_VECTORS_H */
--
generated by git-patchbot for /home/xen/git/xen.git#staging

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.