[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




 


Rackspace

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