|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 1/4] pc/xen: Xen Q35 support: provide IRQ handling for PCI devices
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()){
+ 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 |