]> xenbits.xensource.com Git - xen.git/commitdiff
cmdline: document and enforce "extra_guest_irqs" upper bounds
authorJan Beulich <jbeulich@suse.com>
Tue, 2 Jul 2024 10:00:27 +0000 (12:00 +0200)
committerJan Beulich <jbeulich@suse.com>
Tue, 2 Jul 2024 10:00:27 +0000 (12:00 +0200)
PHYSDEVOP_pirq_eoi_gmfn_v<N> accepting just a single GFN implies that no
more than 32k pIRQ-s can be used by a domain on x86. Document this upper
bound.

To also enforce the limit, (ab)use both arch_hwdom_irqs() (changing its
parameter type) and setup_system_domains(). This is primarily to avoid
exposing the two static variables or introducing yet further arch hooks.

While touching arch_hwdom_irqs() also mark it hwdom-init.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Roger Pau Monné <roger.pau@citrix.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
docs/misc/xen-command-line.pandoc
xen/arch/x86/io_apic.c
xen/common/domain.c
xen/include/xen/irq.h

index 1dea7431fab6b98fafdaca912d243549348c2c8d..cd9a7164f4b09dc1096aedc36029ffbc986baad6 100644 (file)
@@ -1175,7 +1175,8 @@ common for all domUs, while the optional second number (preceded by a comma)
 is for dom0.  Changing the setting for domU has no impact on dom0 and vice
 versa.  For example to change dom0 without changing domU, use
 `extra_guest_irqs=,512`.  The default value for Dom0 and an eventual separate
-hardware domain is architecture dependent.
+hardware domain is architecture dependent.  The upper limit for both values on
+x86 is such that the resulting total number of IRQs can't be higher than 32768.
 Note that specifying zero as domU value means zero, while for dom0 it means
 to use the default.
 
index d73108558e09424e8cc3c1051b53b4c24016edb4..adcc9b2ff34d2140843e685896efb4e85b2d347d 100644 (file)
@@ -2660,18 +2660,20 @@ void __init ioapic_init(void)
            nr_irqs_gsi, nr_irqs - nr_irqs_gsi);
 }
 
-unsigned int arch_hwdom_irqs(domid_t domid)
+unsigned int __hwdom_init arch_hwdom_irqs(const struct domain *d)
 {
     unsigned int n = fls(num_present_cpus());
+    /* Bounded by the domain pirq EOI bitmap gfn. */
+    const unsigned int max_irqs = PAGE_SIZE * BITS_PER_BYTE;
 
-    if ( !domid )
-        n = min(n, dom0_max_vcpus());
-    n = min(nr_irqs_gsi + n * NR_DYNAMIC_VECTORS, nr_irqs);
+    if ( is_system_domain(d) )
+        return max_irqs;
 
-    /* Bounded by the domain pirq eoi bitmap gfn. */
-    n = min_t(unsigned int, n, PAGE_SIZE * BITS_PER_BYTE);
+    if ( !d->domain_id )
+        n = min(n, dom0_max_vcpus());
+    n = min(nr_irqs_gsi + n * NR_DYNAMIC_VECTORS, min(nr_irqs, max_irqs));
 
-    printk("Dom%d has maximum %u PIRQs\n", domid, n);
+    printk("%pd has maximum %u PIRQs\n", d, n);
 
     return n;
 }
index 67cadb7c3f4fbfd57a63edfa4f83fa802d634f77..23a73d953ca60217410dcc9ab9514dba4bf9ba2e 100644 (file)
@@ -695,7 +695,7 @@ struct domain *domain_create(domid_t domid,
             d->nr_pirqs = nr_static_irqs + extra_domU_irqs;
         else
             d->nr_pirqs = extra_hwdom_irqs ? nr_static_irqs + extra_hwdom_irqs
-                                           : arch_hwdom_irqs(domid);
+                                           : arch_hwdom_irqs(d);
         d->nr_pirqs = min(d->nr_pirqs, nr_irqs);
 
         radix_tree_init(&d->pirq_tree);
@@ -829,6 +829,24 @@ void __init setup_system_domains(void)
     if ( IS_ERR(dom_xen) )
         panic("Failed to create d[XEN]: %ld\n", PTR_ERR(dom_xen));
 
+#ifdef CONFIG_HAS_PIRQ
+    /* Bound-check values passed via "extra_guest_irqs=". */
+    {
+        unsigned int n = max(arch_hwdom_irqs(dom_xen), nr_static_irqs);
+
+        if ( extra_hwdom_irqs > n - nr_static_irqs )
+        {
+            extra_hwdom_irqs = n - nr_static_irqs;
+            printk(XENLOG_WARNING "hwdom IRQs bounded to %u\n", n);
+        }
+        if ( extra_domU_irqs > max(32U, n - nr_static_irqs) )
+        {
+            extra_domU_irqs = n - nr_static_irqs;
+            printk(XENLOG_WARNING "domU IRQs bounded to %u\n", n);
+        }
+    }
+#endif
+
     /*
      * Initialise our DOMID_IO domain.
      * This domain owns I/O pages that are within the range of the page_info
index ee45d19af82440b561f7b09169411116641946e5..95034c0d6bb5f0aa7d5bb572aca59872508a438a 100644 (file)
@@ -202,8 +202,9 @@ extern struct irq_desc *pirq_spin_lock_irq_desc(
 
 unsigned int set_desc_affinity(struct irq_desc *desc, const cpumask_t *mask);
 
+/* When passed a system domain, this returns the maximum permissible value. */
 #ifndef arch_hwdom_irqs
-unsigned int arch_hwdom_irqs(domid_t domid);
+unsigned int arch_hwdom_irqs(const struct domain *d);
 #endif
 
 #ifndef arch_evtchn_bind_pirq