diff options
Diffstat (limited to '0050-cmdline-document-and-enforce-extra_guest_irqs-upper-.patch')
-rw-r--r-- | 0050-cmdline-document-and-enforce-extra_guest_irqs-upper-.patch | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/0050-cmdline-document-and-enforce-extra_guest_irqs-upper-.patch b/0050-cmdline-document-and-enforce-extra_guest_irqs-upper-.patch new file mode 100644 index 0000000..f7f61e8 --- /dev/null +++ b/0050-cmdline-document-and-enforce-extra_guest_irqs-upper-.patch @@ -0,0 +1,156 @@ +From 30c695ddaf067cbe7a98037474e7910109238807 Mon Sep 17 00:00:00 2001 +From: Jan Beulich <jbeulich@suse.com> +Date: Thu, 4 Jul 2024 14:14:16 +0200 +Subject: [PATCH 50/56] cmdline: document and enforce "extra_guest_irqs" upper + bounds +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +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> + +amend 'cmdline: document and enforce "extra_guest_irqs" upper bounds' + +Address late review comments for what is now commit 17f6d398f765: +- bound max_irqs right away against nr_irqs +- introduce a #define for a constant used twice + +Requested-by: Roger Pau Monné <roger.pau@citrix.com> +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> +master commit: 17f6d398f76597f8009ec0530842fb8705ece7ba +master date: 2024-07-02 12:00:27 +0200 +master commit: 1f56accba33ffea0abf7d1c6384710823d10cbd6 +master date: 2024-07-03 14:03:27 +0200 +--- + docs/misc/xen-command-line.pandoc | 3 ++- + xen/arch/x86/io_apic.c | 17 ++++++++++------- + xen/common/domain.c | 24 ++++++++++++++++++++++-- + xen/include/xen/irq.h | 3 ++- + 4 files changed, 36 insertions(+), 11 deletions(-) + +diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc +index 10a09bbf23..d857bd0f89 100644 +--- a/docs/misc/xen-command-line.pandoc ++++ b/docs/misc/xen-command-line.pandoc +@@ -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. + +diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c +index c5342789e8..f7591fd091 100644 +--- a/xen/arch/x86/io_apic.c ++++ b/xen/arch/x86/io_apic.c +@@ -2664,18 +2664,21 @@ 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()); ++ /* Bounding by the domain pirq EOI bitmap capacity. */ ++ const unsigned int max_irqs = min_t(unsigned int, nr_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, max_irqs); + +- printk("Dom%d has maximum %u PIRQs\n", domid, n); ++ printk("%pd has maximum %u PIRQs\n", d, n); + + return n; + } +diff --git a/xen/common/domain.c b/xen/common/domain.c +index 003f4ab125..62832a5860 100644 +--- a/xen/common/domain.c ++++ b/xen/common/domain.c +@@ -351,7 +351,8 @@ static int late_hwdom_init(struct domain *d) + } + + static unsigned int __read_mostly extra_hwdom_irqs; +-static unsigned int __read_mostly extra_domU_irqs = 32; ++#define DEFAULT_EXTRA_DOMU_IRQS 32U ++static unsigned int __read_mostly extra_domU_irqs = DEFAULT_EXTRA_DOMU_IRQS; + + static int __init cf_check parse_extra_guest_irqs(const char *s) + { +@@ -688,7 +689,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); +@@ -812,6 +813,25 @@ 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(DEFAULT_EXTRA_DOMU_IRQS, 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 +diff --git a/xen/include/xen/irq.h b/xen/include/xen/irq.h +index 5dcd2d8f0c..bef170bcb6 100644 +--- a/xen/include/xen/irq.h ++++ b/xen/include/xen/irq.h +@@ -196,8 +196,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 +-- +2.45.2 + |