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

[xen staging] x86/IRQ: make max number of guests for a shared IRQ configurable



commit e373bc1bdc593564e15d11a7a50f74968907ee5f
Author:     Igor Druzhinin <igor.druzhinin@xxxxxxxxxx>
AuthorDate: Mon Dec 7 14:49:30 2020 +0100
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Mon Dec 7 14:49:30 2020 +0100

    x86/IRQ: make max number of guests for a shared IRQ configurable
    
    ... and increase the default to 16.
    
    Current limit of 7 is too restrictive for modern systems where one GSI
    could be shared by potentially many PCI INTx sources where each of them
    corresponds to a device passed through to its own guest. Some systems do not
    apply due dilligence in swizzling INTx links in case e.g. INTA is declared 
as
    interrupt pin for the majority of PCI devices behind a single router,
    resulting in overuse of a GSI.
    
    Introduce a new command line option to configure that limit and dynamically
    allocate an array of the necessary size. Set the default size now to 16 
which
    is higher than 7 but could later be increased even more if necessary.
    
    Signed-off-by: Igor Druzhinin <igor.druzhinin@xxxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
---
 docs/misc/xen-command-line.pandoc | 10 ++++++++++
 xen/arch/x86/irq.c                | 26 +++++++++++++++++++-------
 2 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/docs/misc/xen-command-line.pandoc 
b/docs/misc/xen-command-line.pandoc
index b4a0d60c11..53e676b30f 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -1641,6 +1641,16 @@ This option is ignored in **pv-shim** mode.
 ### nr_irqs (x86)
 > `= <integer>`
 
+### irq-max-guests (x86)
+> `= <integer>`
+
+> Default: `16`
+
+Maximum number of guests any individual IRQ could be shared between,
+i.e. a limit on the number of guests it is possible to start each having
+assigned a device sharing a common interrupt line.  Accepts values between
+1 and 255.
+
 ### numa (x86)
 > `= on | off | fake=<integer> | noacpi`
 
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
index 3387c1b5c3..1a60160916 100644
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -42,6 +42,10 @@ integer_param("nr_irqs", nr_irqs);
 int __read_mostly opt_irq_vector_map = OPT_IRQ_VECTOR_MAP_DEFAULT;
 custom_param("irq_vector_map", parse_irq_vector_map_param);
 
+/* Max number of guests IRQ could be shared with */
+static unsigned char __read_mostly irq_max_guests;
+integer_param("irq-max-guests", irq_max_guests);
+
 vmask_t global_used_vector_map;
 
 struct irq_desc __read_mostly *irq_desc = NULL;
@@ -435,6 +439,9 @@ int __init init_irq_data(void)
     for ( ; irq < nr_irqs; irq++ )
         irq_to_desc(irq)->irq = irq;
 
+    if ( !irq_max_guests )
+        irq_max_guests = 16;
+
 #ifdef CONFIG_PV
     /* Never allocate the hypercall vector or Linux/BSD fast-trap vector. */
     set_bit(LEGACY_SYSCALL_VECTOR, used_vectors);
@@ -1028,7 +1035,6 @@ int __init setup_irq(unsigned int irq, unsigned int 
irqflags,
  * HANDLING OF GUEST-BOUND PHYSICAL IRQS
  */
 
-#define IRQ_MAX_GUESTS 7
 typedef struct {
     u8 nr_guests;
     u8 in_flight;
@@ -1039,7 +1045,7 @@ typedef struct {
 #define ACKTYPE_EOI    2     /* EOI on the CPU that was interrupted  */
     cpumask_var_t cpu_eoi_map; /* CPUs that need to EOI this interrupt */
     struct timer eoi_timer;
-    struct domain *guest[IRQ_MAX_GUESTS];
+    struct domain *guest[];
 } irq_guest_action_t;
 
 static irq_guest_action_t *guest_action(const struct irq_desc *desc)
@@ -1553,7 +1559,8 @@ int pirq_guest_bind(struct vcpu *v, struct pirq *pirq, 
int will_share)
         if ( newaction == NULL )
         {
             spin_unlock_irq(&desc->lock);
-            if ( (newaction = xmalloc(irq_guest_action_t)) != NULL &&
+            if ( (newaction = xmalloc_flex_struct(irq_guest_action_t, guest,
+                                                  irq_max_guests)) != NULL &&
                  zalloc_cpumask_var(&newaction->cpu_eoi_map) )
                 goto retry;
             xfree(newaction);
@@ -1622,11 +1629,12 @@ int pirq_guest_bind(struct vcpu *v, struct pirq *pirq, 
int will_share)
         goto retry;
     }
 
-    if ( action->nr_guests == IRQ_MAX_GUESTS )
+    if ( action->nr_guests == irq_max_guests )
     {
-        printk(XENLOG_G_INFO "Cannot bind IRQ%d to dom%d. "
-               "Already at max share.\n",
-               pirq->pirq, v->domain->domain_id);
+        printk(XENLOG_G_INFO
+               "Cannot bind IRQ%d to %pd: already at max share %u"
+               " (increase with irq-max-guests= option)\n",
+               pirq->pirq, v->domain, irq_max_guests);
         rc = -EBUSY;
         goto unlock_out;
     }
@@ -2510,6 +2518,10 @@ static void dump_irqs(unsigned char key)
 
 static int __init setup_dump_irqs(void)
 {
+    /* In lieu of being able to live in init_irq_data(). */
+    BUILD_BUG_ON(sizeof(irq_max_guests) >
+                 sizeof_field(irq_guest_action_t, nr_guests));
+
     register_keyhandler('i', dump_irqs, "dump interrupt bindings", 1);
     return 0;
 }
--
generated by git-patchbot for /home/xen/git/xen.git#staging



 


Rackspace

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