|
|
240766 |
From 48addb5b5b3b4712744e2ba9c3205b981f898118 Mon Sep 17 00:00:00 2001
|
|
|
240766 |
From: Laszlo Ersek <lersek@redhat.com>
|
|
|
240766 |
Date: Thu, 24 Apr 2014 10:57:23 +0200
|
|
|
240766 |
Subject: [PATCH 11/12] uhci: UNfix irq routing for RHEL-6 machtypes (RHEL only)
|
|
|
240766 |
|
|
|
240766 |
RH-Author: Laszlo Ersek <lersek@redhat.com>
|
|
|
240766 |
Message-id: <1398337043-4967-1-git-send-email-lersek@redhat.com>
|
|
|
240766 |
Patchwork-id: 58540
|
|
|
240766 |
O-Subject: [RHEL-7.0 0day qemu-kvm PATCH] uhci: UNfix irq routing for RHEL-6 machtypes (RHEL only)
|
|
|
240766 |
Bugzilla: 1085701
|
|
|
240766 |
RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
240766 |
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
|
|
|
240766 |
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
240766 |
|
|
|
240766 |
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1085701
|
|
|
240766 |
Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=7368968
|
|
|
240766 |
|
|
|
240766 |
Tested by myself and QE.
|
|
|
240766 |
|
|
|
240766 |
(Note that the bulk of the work related to this issue happened in bug
|
|
|
240766 |
1027565 comments 64 to 74, because QE was experiencing it with the other
|
|
|
240766 |
(original) issue reported in bug 1027565. Only later did I realize that
|
|
|
240766 |
bug 1085701 already existed for this specific problem.)
|
|
|
240766 |
|
|
|
240766 |
Refer to the following upstream commit, present in v1.2.0 and RHEL-7:
|
|
|
240766 |
|
|
|
240766 |
commit 973002c11460efd3c17fe61a76711a103e30e1f9
|
|
|
240766 |
Author: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
240766 |
Date: Fri May 25 12:53:47 2012 +0200
|
|
|
240766 |
|
|
|
240766 |
uhci: fix irq routing
|
|
|
240766 |
|
|
|
240766 |
The multifunction ich9 ehci controller with uhci companions uses a
|
|
|
240766 |
different interrupt pin for each function. The three uhci devices
|
|
|
240766 |
get pins A, B and C, whereas ehci uses pin D. This way the guest
|
|
|
240766 |
can assign different IRQ lines to each controller.
|
|
|
240766 |
|
|
|
240766 |
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
240766 |
|
|
|
240766 |
This is a performance optimization so that IRQ sharing can be avoided in
|
|
|
240766 |
the guest.
|
|
|
240766 |
|
|
|
240766 |
Contrarily, the RHEL-6 emulator exclusively assigns pin D to each of the
|
|
|
240766 |
three devices (see "hw/usb-uhci.c" there):
|
|
|
240766 |
- usb_uhci_ich9_1_initfn()
|
|
|
240766 |
- usb_uhci_ich9_2_initfn()
|
|
|
240766 |
- usb_uhci_ich9_3_initfn()
|
|
|
240766 |
|
|
|
240766 |
These init functions call usb_uhci_common_initfn(), which in turn assigns:
|
|
|
240766 |
|
|
|
240766 |
pci_conf[0x3d] = 4; // interrupt pin 3
|
|
|
240766 |
|
|
|
240766 |
This mismatch breaks migration for rhel6.x.0 machine types from the
|
|
|
240766 |
RHEL-6.5 emulator to the RHEL-7.0 one.
|
|
|
240766 |
|
|
|
240766 |
For example, considering the uhci1 controller, the guest kernel, started
|
|
|
240766 |
on the RHEL-6.5 source host, will see pin D advertised, and (according to
|
|
|
240766 |
the PCI interrupt routing table provided by SeaBIOS) will route it to IRQ
|
|
|
240766 |
11:
|
|
|
240766 |
|
|
|
240766 |
dmesg:
|
|
|
240766 |
|
|
|
240766 |
uhci_hcd 0000:00:11.0: PCI INT D -> Link[LNKD] -> GSI 11 (level, high)
|
|
|
240766 |
-> IRQ 11
|
|
|
240766 |
|
|
|
240766 |
/proc/interrupts:
|
|
|
240766 |
|
|
|
240766 |
10: ... IO-APIC-fasteoi virtio0
|
|
|
240766 |
11: ... IO-APIC-fasteoi uhci_hcd:usb1
|
|
|
240766 |
|
|
|
240766 |
When the same guest kernel, using the same rhel6.5.0 machine type, is
|
|
|
240766 |
started fresh on the RHEL-7.0 target host, pin A is advertised instead
|
|
|
240766 |
(and routed to a different IRQ, based on the same table from SeaBIOS):
|
|
|
240766 |
|
|
|
240766 |
dmesg:
|
|
|
240766 |
|
|
|
240766 |
uhci_hcd 0000:00:11.0: PCI INT A -> Link[LNKA] -> GSI 10 (level, high)
|
|
|
240766 |
-> IRQ 10
|
|
|
240766 |
|
|
|
240766 |
/proc/interrupts:
|
|
|
240766 |
|
|
|
240766 |
10: ... IO-APIC-fasteoi uhci_hcd:usb1, virtio0
|
|
|
240766 |
|
|
|
240766 |
This is no problem as long as we don't migrate.
|
|
|
240766 |
|
|
|
240766 |
When we migrate the rhel6.x.0 machtype guest from the RHEL-6.5 host to the
|
|
|
240766 |
RHEL-7.0 host, the guest kernel (having booted on the source host) will
|
|
|
240766 |
expect the interrupts for the UHCI device on pin D / IRQ 11. However, the
|
|
|
240766 |
target host will inject the interrupts on pin A / IRQ 10. No handler in
|
|
|
240766 |
the guest kernel will claim such IRQ 10 instances (examples are: HDA or
|
|
|
240766 |
virtio-balloon), hence IRQ 10 will be disabled.
|
|
|
240766 |
|
|
|
240766 |
We can fix this in at least two ways:
|
|
|
240766 |
(1) Drop the persistent "UHCIState.irq_pin" field, and simply use the pin
|
|
|
240766 |
identifier that is stored in (already migrated) PCI config space (at
|
|
|
240766 |
offset 0x3d).
|
|
|
240766 |
(2) Introduce yet another RHEL-6 compatibility knob that selects pin D for
|
|
|
240766 |
all three ICH9-UHCI controllers.
|
|
|
240766 |
|
|
|
240766 |
Since PCI config space could be write-accessible to the guest, plus it
|
|
|
240766 |
could originate from an untrusted migration source as well, and we'd use
|
|
|
240766 |
the setting as a subscript into the s->dev.irq[] array in
|
|
|
240766 |
uhci_update_irq(), it seems safer to go with (2).
|
|
|
240766 |
|
|
|
240766 |
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
240766 |
---
|
|
|
240766 |
include/hw/usb.h | 4 ++++
|
|
|
240766 |
hw/i386/pc_piix.c | 1 +
|
|
|
240766 |
hw/usb/hcd-uhci.c | 13 ++++++++++++-
|
|
|
240766 |
3 files changed, 17 insertions(+), 1 deletion(-)
|
|
|
240766 |
|
|
|
240766 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
240766 |
---
|
|
|
240766 |
hw/i386/pc_piix.c | 1 +
|
|
|
240766 |
hw/usb/hcd-uhci.c | 13 ++++++++++++-
|
|
|
240766 |
include/hw/usb.h | 4 ++++
|
|
|
240766 |
3 files changed, 17 insertions(+), 1 deletions(-)
|
|
|
240766 |
|
|
|
240766 |
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
|
|
|
240766 |
index fea98b6..67d51da 100644
|
|
|
240766 |
--- a/hw/i386/pc_piix.c
|
|
|
240766 |
+++ b/hw/i386/pc_piix.c
|
|
|
240766 |
@@ -955,6 +955,7 @@ static void pc_compat_rhel650(QEMUMachineInitArgs *args)
|
|
|
240766 |
has_acpi_build = false;
|
|
|
240766 |
gigabyte_align = false;
|
|
|
240766 |
shadow_bios_after_incoming = true;
|
|
|
240766 |
+ ich9_uhci123_irqpin_override = true;
|
|
|
240766 |
}
|
|
|
240766 |
|
|
|
240766 |
static void pc_init_rhel650(QEMUMachineInitArgs *args)
|
|
|
240766 |
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
|
|
|
240766 |
index 4fc3410..3380107 100644
|
|
|
240766 |
--- a/hw/usb/hcd-uhci.c
|
|
|
240766 |
+++ b/hw/usb/hcd-uhci.c
|
|
|
240766 |
@@ -187,6 +187,8 @@ typedef struct UHCI_QH {
|
|
|
240766 |
uint32_t el_link;
|
|
|
240766 |
} UHCI_QH;
|
|
|
240766 |
|
|
|
240766 |
+bool ich9_uhci123_irqpin_override;
|
|
|
240766 |
+
|
|
|
240766 |
static void uhci_async_cancel(UHCIAsync *async);
|
|
|
240766 |
static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td);
|
|
|
240766 |
|
|
|
240766 |
@@ -1232,7 +1234,16 @@ static int usb_uhci_common_initfn(PCIDevice *dev)
|
|
|
240766 |
/* TODO: reset value should be 0. */
|
|
|
240766 |
pci_conf[USB_SBRN] = USB_RELEASE_1; // release number
|
|
|
240766 |
|
|
|
240766 |
- s->irq_pin = u->info.irq_pin;
|
|
|
240766 |
+ if (ich9_uhci123_irqpin_override &&
|
|
|
240766 |
+ u->info.vendor_id == PCI_VENDOR_ID_INTEL &&
|
|
|
240766 |
+ (u->info.device_id == PCI_DEVICE_ID_INTEL_82801I_UHCI1 ||
|
|
|
240766 |
+ u->info.device_id == PCI_DEVICE_ID_INTEL_82801I_UHCI2 ||
|
|
|
240766 |
+ u->info.device_id == PCI_DEVICE_ID_INTEL_82801I_UHCI3)) {
|
|
|
240766 |
+ fprintf(stderr, "RHEL-6 compat: %s: irq_pin = 3\n", u->info.name);
|
|
|
240766 |
+ s->irq_pin = 3;
|
|
|
240766 |
+ } else {
|
|
|
240766 |
+ s->irq_pin = u->info.irq_pin;
|
|
|
240766 |
+ }
|
|
|
240766 |
pci_config_set_interrupt_pin(pci_conf, s->irq_pin + 1);
|
|
|
240766 |
|
|
|
240766 |
if (s->masterbus) {
|
|
|
240766 |
diff --git a/include/hw/usb.h b/include/hw/usb.h
|
|
|
240766 |
index b111be0..5668701 100644
|
|
|
240766 |
--- a/include/hw/usb.h
|
|
|
240766 |
+++ b/include/hw/usb.h
|
|
|
240766 |
@@ -578,4 +578,8 @@ int usb_get_quirks(uint16_t vendor_id, uint16_t product_id,
|
|
|
240766 |
uint8_t interface_class, uint8_t interface_subclass,
|
|
|
240766 |
uint8_t interface_protocol);
|
|
|
240766 |
|
|
|
240766 |
+
|
|
|
240766 |
+/* hcd-uhci.c -- RHEL-6 machine type compatibility */
|
|
|
240766 |
+extern bool ich9_uhci123_irqpin_override;
|
|
|
240766 |
+
|
|
|
240766 |
#endif
|
|
|
240766 |
--
|
|
|
240766 |
1.7.1
|
|
|
240766 |
|