|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH 1/4] pc/xen: Xen Q35 support: provide IRQ handling for PCI devices
On Fri, Mar 13, 2026 at 04:47:07PM +0000, Thierry Escande wrote:
> From: Alexey Gerasimenko <x1917x@xxxxxxxxx>
>
> This patch introduces support for ICH9 LPC PCI interrupt routing when
> running under Xen. This intercepts writes to the PIRQA-D routing
> registers and propagates routing changes to the Xen device model via
> xen_set_pci_link_route().
>
> A major difference between i440 and Q35 is the number of PIRQ inputs and
> PIRQ routers (PCI IRQ links in terms of ACPI) available. i440 has 4 PCI
> interrupt links, while Q35 has 8 (PIRQA...PIRQH). Currently Xen has
> support for only 4 PCI links, so we describe only 4 of 8 PCI links in
> ACPI tables. Also, hvmloader disables PIRQ routing for PIRQE..PIRQH by
> writing 80h into corresponding PIRQ[n]_ROUT registers.
>
> All this PCI interrupt routing stuff largely concerns legacy mechanism
> from PIC era. It's hardly worth to extend number of PCI links supported
> as we normally deal with APIC mode and/or MSI interrupts.
>
> The only useful thing to do with PIRQE..PIRQH routing currently is to
> check if guest actually attempts to use it for some reason (despite ACPI
> PCI routing information provided). In this case, a warning is reported.
>
> This has been tested on Linux guests with noapic and pci=nomsi kernel
> parameters set.
>
> Signed-off-by: Alexey Gerasimenko <x1917x@xxxxxxxxx>
> Signed-off-by: Thierry Escande <thierry.escande@xxxxxxxxxx>
> ---
> hw/i386/pc_piix.c | 2 --
> hw/i386/xen/xen-hvm.c | 38 ++++++++++++++++++++++++++++++++++++++
> hw/isa/lpc_ich9.c | 16 +++++++++++++---
> include/hw/xen/xen.h | 5 +++++
> stubs/xen-hw-stub.c | 4 ++++
> 5 files changed, 60 insertions(+), 5 deletions(-)
>
> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
> index 4d71e0d51a..a65e09e46c 100644
> --- a/hw/i386/pc_piix.c
> +++ b/hw/i386/pc_piix.c
> @@ -66,8 +66,6 @@
> #include "hw/i386/acpi-build.h"
> #include "target/i386/cpu.h"
>
> -#define XEN_IOAPIC_NUM_PIRQS 128ULL
> -
> static GlobalProperty pc_piix_compat_defaults[] = {
> { TYPE_RAMFB_DEVICE, "use-legacy-x86-rom", "true" },
> { TYPE_VFIO_PCI_NOHOTPLUG, "use-legacy-x86-rom", "true" },
> diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
> index 67d3e836eb..2dba289e09 100644
> --- a/hw/i386/xen/xen-hvm.c
> +++ b/hw/i386/xen/xen-hvm.c
> @@ -18,6 +18,7 @@
> #include "hw/core/hw-error.h"
> #include "hw/i386/pc.h"
> #include "hw/core/irq.h"
> +#include "hw/southbridge/ich9.h"
> #include "hw/i386/apic-msidef.h"
> #include "hw/xen/xen-x86.h"
> #include "qemu/range.h"
> @@ -87,6 +88,43 @@ int xen_set_pci_link_route(uint8_t link, uint8_t irq)
> return xendevicemodel_set_pci_link_route(xen_dmod, xen_domid, link, irq);
> }
>
> +void xen_ich9_pci_write_config_client(PCIDevice *pci_dev, uint32_t address,
> uint32_t val, int len)
> +{
> + static bool pirqe_f_warned = false;
> + int i;
> +
> + if (ranges_overlap(address, len, ICH9_LPC_PIRQA_ROUT, 4)) {
> + /* handle PIRQA..PIRQD routing */
> + /* Scan for updates to PCI link routes (0x60-0x63). */
> + for (i = 0; i < len; i++) {
> + uint8_t v = (val >> (8 * i)) & 0xff;
> + if (v & 0x80) {
> + v = 0;
> + }
> + v &= 0xf;
> + if (((address + i) >= ICH9_LPC_PIRQA_ROUT) &&
> + ((address + i) <= ICH9_LPC_PIRQD_ROUT)) {
> + xen_set_pci_link_route(address + i - ICH9_LPC_PIRQA_ROUT, v);
> + }
> + }
> + } else if (ranges_overlap(address, len, ICH9_LPC_PIRQE_ROUT, 4)) {
> + while (len--) {
> + if (range_covers_byte(ICH9_LPC_PIRQE_ROUT, 4, address) &&
> + (val & 0x80) == 0) {
> + /* print warning only once */
> + if (!pirqe_f_warned) {
> + pirqe_f_warned = true;
> + warn_report("WARNING: guest domain attempted to use
> PIRQ%c "
> + "routing which is not supported for Xen/Q35
> currently\n",
> + (char)(address - ICH9_LPC_PIRQE_ROUT + 'E'));
> + break;
> + }
> + }
> + address++, val >>= 8;
> + }
> + }
> +}
> +
> int xen_is_pirq_msi(uint32_t msi_data)
> {
> /* If vector is 0, the msi is remapped into a pirq, passed as
> diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
> index 51dc680029..8c627f0734 100644
> --- a/hw/isa/lpc_ich9.c
> +++ b/hw/isa/lpc_ich9.c
> @@ -46,8 +46,10 @@
> #include "hw/acpi/ich9_timer.h"
> #include "hw/pci/pci_bus.h"
> #include "hw/core/qdev-properties.h"
> +#include "hw/xen/xen.h"
> #include "system/runstate.h"
> #include "system/system.h"
> +#include "system/xen.h"
> #include "hw/core/cpu.h"
> #include "hw/nvram/fw_cfg.h"
> #include "qemu/cutils.h"
> @@ -569,6 +571,9 @@ static void ich9_lpc_config_write(PCIDevice *d,
> ICH9LPCState *lpc = ICH9_LPC_DEVICE(d);
> uint32_t rcba_old = pci_get_long(d->config + ICH9_LPC_RCBA);
>
> + if (xen_enabled()){
Coding style violation.
> + xen_ich9_pci_write_config_client(d, addr, val, len);
> + }
> pci_default_write_config(d, addr, val, len);
> if (ranges_overlap(addr, len, ICH9_LPC_PMBASE, 4) ||
> ranges_overlap(addr, len, ICH9_LPC_ACPI_CTRL, 1)) {
> @@ -762,9 +767,14 @@ static void ich9_lpc_realize(PCIDevice *d, Error **errp)
> irq = object_property_get_uint(OBJECT(&lpc->rtc), "irq", &error_fatal);
> isa_connect_gpio_out(ISA_DEVICE(&lpc->rtc), 0, irq);
>
> - pci_bus_irqs(pci_bus, ich9_lpc_set_irq, d, ICH9_LPC_NB_PIRQS);
> - pci_bus_map_irqs(pci_bus, ich9_lpc_map_irq);
> - pci_bus_set_route_irq_fn(pci_bus, ich9_route_intx_pin_to_irq);
> + if (xen_enabled()) {
> + pci_bus_irqs(pci_bus, xen_intx_set_irq, d, XEN_IOAPIC_NUM_PIRQS);
> + pci_bus_map_irqs(pci_bus, xen_pci_slot_get_pirq);
> + } else {
> + pci_bus_irqs(pci_bus, ich9_lpc_set_irq, d, ICH9_LPC_NB_PIRQS);
> + pci_bus_map_irqs(pci_bus, ich9_lpc_map_irq);
> + pci_bus_set_route_irq_fn(pci_bus, ich9_route_intx_pin_to_irq);
> + }
>
> ich9_lpc_pm_init(lpc);
> }
> diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h
> index e94c6e5a31..910289b54d 100644
> --- a/include/hw/xen/xen.h
> +++ b/include/hw/xen/xen.h
> @@ -24,6 +24,8 @@
> #define __XEN_INTERFACE_VERSION__ 0x00040e00
> #endif
>
> +#define XEN_IOAPIC_NUM_PIRQS 128ULL
> +
> /* xen-machine.c */
> enum xen_mode {
> XEN_DISABLED = 0, /* xen support disabled (default) */
> @@ -39,6 +41,9 @@ extern bool xen_is_stubdomain;
> int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num);
> int xen_set_pci_link_route(uint8_t link, uint8_t irq);
> void xen_intx_set_irq(void *opaque, int irq_num, int level);
> +void xen_ich9_pci_write_config_client(PCIDevice *pci_dev,
> + uint32_t address, uint32_t val,
> + int len);
> void xen_hvm_inject_msi(uint64_t addr, uint32_t data);
> int xen_is_pirq_msi(uint32_t msi_data);
>
> diff --git a/stubs/xen-hw-stub.c b/stubs/xen-hw-stub.c
> index 6cf0e9a4c1..a74209d01e 100644
> --- a/stubs/xen-hw-stub.c
> +++ b/stubs/xen-hw-stub.c
> @@ -24,6 +24,10 @@ int xen_set_pci_link_route(uint8_t link, uint8_t irq)
> return -1;
> }
>
> +void xen_ich9_pci_write_config_client(PCIDevice *pci_dev, uint32_t address,
> uint32_t val, int len)
> +{
> +}
> +
> int xen_is_pirq_msi(uint32_t msi_data)
> {
> return 0;
> --
> 2.51.0
>
>
>
> --
> Thierry Escande | Vates XCP-ng Developer
>
> XCP-ng & Xen Orchestra - Vates solutions
>
> web: https://vates.tech
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |