Message ID | 20140915150754.GO1825@ERROL.INI.CMU.EDU |
---|---|
State | New |
Headers | show |
On 09/15/14 17:07, Gabriel L. Somlo wrote: > On Mon, Sep 15, 2014 at 05:01:21PM +0200, Laszlo Ersek wrote: >>> diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c >>> index 289ca3b..bb230f1 100644 >>> --- a/hw/usb/hcd-ehci-pci.c >>> +++ b/hw/usb/hcd-ehci-pci.c >>> @@ -208,8 +208,8 @@ struct ehci_companions { >>> }; >>> >>> static const struct ehci_companions ich9_1d[] = { >>> - { .name = "ich9-usb-uhci1", .func = 0, .port = 0 }, >>> - { .name = "ich9-usb-uhci2", .func = 1, .port = 2 }, >>> + { .name = "ich9-usb-uhci3", .func = 0, .port = 0 }, >>> + { .name = "ich9-usb-uhci3", .func = 1, .port = 2 }, >>> { .name = "ich9-usb-uhci3", .func = 2, .port = 4 }, >>> }; >>> >>> >>> they *all* get detected and work great on ovmf+osx. Slow kbd+mouse >>> get routed automatically to one of them, and work fine. The only >>> differences I can see between them (in hw/usb/hcd-uhci.c) is >>> the name string and "irq_pin" field. Not sure yet if that's likely >>> to point to an explanation... >> >> It is actually extremely relevant, the irq_pin field. I'm not exactly >> sure how just yet, but it is. Maybe check the interrupt routing in OSX >> somehow? Do you have a dmesg-like log in OSX, with a PRT dump from the >> DSDT, and messages about interrupt routing setup? Do you have in OSX >> anything that corresponds to /proc/interrupts under Linux? > > Actually, even more exciting: > > diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c > index 3b3ebcd..d61656e 100644 > --- a/hw/usb/hcd-uhci.c > +++ b/hw/usb/hcd-uhci.c > @@ -1335,21 +1335,21 @@ static UHCIInfo uhci_info[] = { > .vendor_id = PCI_VENDOR_ID_INTEL, > .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI1, > .revision = 0x03, > - .irq_pin = 0, > + .irq_pin = 1, > .unplug = false, > },{ > .name = "ich9-usb-uhci2", /* 00:1d.1 */ > .vendor_id = PCI_VENDOR_ID_INTEL, > .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI2, > .revision = 0x03, > - .irq_pin = 1, > + .irq_pin = 2, > .unplug = false, > },{ > .name = "ich9-usb-uhci3", /* 00:1d.2 */ > .vendor_id = PCI_VENDOR_ID_INTEL, > .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI3, > .revision = 0x03, > - .irq_pin = 2, > + .irq_pin = 3, > .unplug = false, > },{ > .name = "ich9-usb-uhci4", /* 00:1a.0 */ > > Turns out, anything with an irq_pin <= 1 won't show up when osx is > booted on q35 with ovmf (but osx + q35 works if booted via Chameleon). > > DSDT looks identical across the ovmf vs. chameleon divide. Now I'm curious. What's this chameleon thing? (Yes, I did find the homepage. Apparently the lead developer is a fellow Hungarian. A small world.) I'm surprised how you can get the same DSDT under both OVMF and chameleon. Assuming you run a recent OVMF on a recent QEMU, the DSDT exposed to the guest will originate from QEMU. This is confirmed by your q35.log that you sent me in private (due to its size) previously: InstallQemuLinkedTables: "etc/acpi/tables" offset 0x0000000000000000: Signature="FACS" Length=0x00000040 InstallQemuLinkedTables: "etc/acpi/tables" offset 0x0000000000000040: Signature="DSDT" Length=0x00001CE5 InstallQemuLinkedTables: "etc/acpi/tables" offset 0x0000000000001D25: Signature="FACP" Length=0x00000074 InstallQemuLinkedTables: "etc/acpi/tables" offset 0x0000000000001D99: Signature="SSDT" Length=0x00000687 InstallQemuLinkedTables: "etc/acpi/tables" offset 0x0000000000002420: Signature="APIC" Length=0x00000090 InstallQemuLinkedTables: "etc/acpi/tables" offset 0x00000000000024B0: Signature="HPET" Length=0x00000038 InstallQemuLinkedTables: "etc/acpi/tables" offset 0x00000000000024E8: Signature="QEMU" Length=0x0000003C InstallQemuLinkedTables: "etc/acpi/tables" offset 0x0000000000002524: Signature="RSDT" Length=0x00000038 InstallAllQemuLinkedTables: installed 7 tables I've got no clue how you can end up with the exact same DSDT under chameleon, unless it has a client for QEMU's fw_cfg ACPI linker/loader. In fact I think that should be *precisely* the difference here. The PCI interrupt routing table (_PRT) in the DSDT describes a two-level mapping. (I've probably forgotten most of the details, sorry.) First, it maps each PCI (bus, dev, pin) triplet to a PNP0C0F ("PCI interrupt link") device. We usually call these LNKA, LNKB, LNC, LNKD, LNKS on i440fx; there are more on q35. Then, each LNKx specifies a set of possible legacy interrupts that the link can be programmed for / assigned to. At runtime, the OS programs each of the interrupt links to one of its allowed legacy interrupts, and then all the pins (across buses and functions) that are connected to that interrupt link will trigger that interrupt. The OS usually tries to come up with a mapping (from LNKx to IRQ) so that interrupt sharing is minimized. Here's an example from my i440fx Fedora 20 VM. (1) The dmesg says first ACPI: PCI Interrupt Link [LNKA] (IRQs 5 10 *11) ACPI: PCI Interrupt Link [LNKB] (IRQs 5 10 *11) ACPI: PCI Interrupt Link [LNKC] (IRQs 5 *10 11) ACPI: PCI Interrupt Link [LNKD] (IRQs 5 *10 11) ACPI: PCI Interrupt Link [LNKS] (IRQs *9) This displays what IRQs the _PRT in the DSDT allows for each of the LNKx links, and the asterisks show (IIRC) what elements of those sets are selected (programmed) when Linux inherits the hardware. (2) Later it logs ACPI: PCI Interrupt Link [LNKC] enabled at IRQ 10 ACPI: PCI Interrupt Link [LNKD] enabled at IRQ 11 ACPI: PCI Interrupt Link [LNKA] enabled at IRQ 11 ACPI: PCI Interrupt Link [LNKB] enabled at IRQ 10 Let's call this mapping LNK_IRQ(). (3) Then look for the uchi controllers: uhci_hcd 0000:00:07.0: irq 10, io base 0x0000c0c0 uhci_hcd 0000:00:07.1: irq 11, io base 0x0000c0a0 uhci_hcd 0000:00:07.2: irq 11, io base 0x0000c080 And /proc/interrupts is consistent with that: CPU0 CPU1 10: 6 25 IO-APIC-fasteoi ehci_hcd:usb1, uhci_hcd:usb2 11: 0 0 IO-APIC-fasteoi uhci_hcd:usb3, uhci_hcd:usb4, virtio2 These last two blocks are *results*. Again, this is the result of composing two functions: device_interrupt = LNK_IRQ(PRT(bus, dev, pin)) PRT() comes from the DSDT, and maps (bus, dev, pin) to a link, while LNK_IRQ() comes from the OS (the actual link -> IRQ assignment), and is restricted to the possibilities offered in the DSDT. The PRT that QEMU generates follows a rotating pattern (it is not restricted by physical circuits). As you go from one PCI device to the next, the same LNKA - LNKD links are distributed over the device's pins, but the sequence is shifted by one. The idea is that most PCI devices use only their first pin (INTA), and placing such devices "beside" each other should nicely iterate over all links, evenly. Thus far I didn't speak about functions of the same PCI device. I didn't do that because I'm uneducated (even more than in the above :)). The basic idea is that different functions of the device will use different pins. Most devices are single-function, hence they usually stick with INTA. If you've got a multifunction device, then the functions will use separate pins. For example, if I dump and decompile the DSDT in the guest, for bus 0 device 7, I get, from the PRT: Package (0x04) { 0x0007FFFF, Zero, LNKC, Zero }, <-- pin 0 / INTA Package (0x04) { 0x0007FFFF, One, LNKD, Zero }, <-- pin 1 / INTB Package (0x04) { 0x0007FFFF, 0x02, LNKA, Zero }, <-- pin 2 / INTC Package (0x04) { 0x0007FFFF, 0x03, LNKB, Zero }, <-- pin 3 / INTD Let's put it all together, for a QEMU command line with -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x7 -device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x7.0x1 -device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,addr=0x7.0x2 dev & func, pin, set interrupt link IRQ programmed set on qemu in qemu for dev & pin, by Linux for cmdline source set in DSDT link ----------- -------- -------------- -------------- 07.0 0 LNKC 10 07.1 1 LNKD 11 07.2 2 LNKA 11 The first two columns are input parameters (from the command line and from the source code). The third colum is the result of evaluating PRT() on the input params. The fourth column is the result of evaluating Linux's LNK_IRQ() function on the third column. (Note that all of the above is for i440fx, not q35, but the method is similar.) Ultimately, I think that the difference between OVMF and chameleon is the following: when booting OSX with chameleon, QEMU's rotating _PRT is not exposed to OSX, because chameleon doesn't know how to download and interpret the necessary fw_cfg blobs. (What _PRT OSX decides to use then, I can't imagine.) But when you boot OSX with OVMF, then QEMU's _PRT is exposed to OSX, and OSX, seeing the PCI bus/device/func addresses of the UHCI controllers, *and* seeing their respective PINs, *and* seeing their respective LNKx links (from the DSDT), maps the function to some interrupt that kills the device. This is consistent with your results (if you change the PINs in the source code, things work). It would be interesting to see what happens if you shuffle the PCI addresses of the UHCI controllers. ... Hm. You did mention in the thread starter that chameleon runs on top of SeaBIOS. SeaBIOS does have an ACPI linker/loader client, which would explain why you see the same DSDT. The only thing that could differ between the two cases is the LNK_IRQ() assignment then (ie. how OSX chooses to map PCI interrupt links to IRQs), and I don't know why that would be different. A /proc/interrupts table would be useful, again. (Sorry about all the crazy errors I must have said above about PCI, ACPI etc etc etc. Even if it turns out to be incorrect to some degree, if it helps others help you, then it wasn't in vain.) Laszlo > I'm going > to take some time to do a more thorough search of any and all logging > I can find on OS X, and also try to find wherever in ovmf the guest > device irq pin comes into play where uhci is concerned. > > I am basically just poking at it with a stick right now, but maybe > something will start making sense soon :) > > Thanks again, > --Gabriel >
On Mon, Sep 15, 2014 at 08:02:04PM +0200, Laszlo Ersek wrote: > >> It is actually extremely relevant, the irq_pin field. I'm not exactly > >> sure how just yet, but it is. Maybe check the interrupt routing in OSX > >> somehow? Do you have a dmesg-like log in OSX, with a PRT dump from the > >> DSDT, and messages about interrupt routing setup? Do you have in OSX > >> anything that corresponds to /proc/interrupts under Linux? > > > > Actually, even more exciting: > > > > diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c > > index 3b3ebcd..d61656e 100644 > > --- a/hw/usb/hcd-uhci.c > > +++ b/hw/usb/hcd-uhci.c > > @@ -1335,21 +1335,21 @@ static UHCIInfo uhci_info[] = { > > .vendor_id = PCI_VENDOR_ID_INTEL, > > .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI1, > > .revision = 0x03, > > - .irq_pin = 0, > > + .irq_pin = 1, > > .unplug = false, > > },{ > > .name = "ich9-usb-uhci2", /* 00:1d.1 */ > > .vendor_id = PCI_VENDOR_ID_INTEL, > > .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI2, > > .revision = 0x03, > > - .irq_pin = 1, > > + .irq_pin = 2, > > .unplug = false, > > },{ > > .name = "ich9-usb-uhci3", /* 00:1d.2 */ > > .vendor_id = PCI_VENDOR_ID_INTEL, > > .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI3, > > .revision = 0x03, > > - .irq_pin = 2, > > + .irq_pin = 3, > > .unplug = false, > > },{ > > .name = "ich9-usb-uhci4", /* 00:1a.0 */ > > > > Turns out, anything with an irq_pin <= 1 won't show up when osx is > > booted on q35 with ovmf (but osx + q35 works if booted via Chameleon). OK, so I forgot to articulate that with the above patch, I'm seeing *both* uhci2 and uhci3, but not uhci1. Basically, if uhciX has an irq_pin less than 2, it won't show up in OSX if booted with ovmf. We're no longer looking at PIIX, this is q35 with ovmf or without. > > > > DSDT looks identical across the ovmf vs. chameleon divide. > > Now I'm curious. What's this chameleon thing? (Yes, I did find the > homepage. Apparently the lead developer is a fellow Hungarian. A small > world.) I'm surprised how you can get the same DSDT under both OVMF and > chameleon. Assuming you run a recent OVMF on a recent QEMU, the DSDT > exposed to the guest will originate from QEMU. This is confirmed by your > q35.log that you sent me in private (due to its size) previously: > ... > > I've got no clue how you can end up with the exact same DSDT under > chameleon, unless it has a client for QEMU's fw_cfg ACPI linker/loader. Chameleon is a multistage bootloader which can be started by a PC-BIOS based machine, and which can then load OSX's /mach_kernel file from the root directory of the main HFS+ partition (as opposed to loading and running /System/Library/CoreServices/boot.efi, which is how an EFI compatible BIOS would do it natively. With qemu, I'm "side-loading" Chameleon's stage-2 loader. I.e., I won't bother loading all the stages via the bios from the hard drive. Instead, I add "-kernel chameleon_stage2_loader" to the qemu command line, which bypasses all earlier stages. While Chameleon *can* override the DSDT of its underlying machine by accessing a .plist config file dropped into the root of the OS X file system (i.e., that's how it's done on a hackintosh), in my case I don't need to do that, as QEMU already provides a perfectly adequate DSDT, so Chameleon just leaves it alone and proceeds to boot the mach kernel. I downloaded a DSDT ripper for the Mac (DSDTEditor_Mac.zip) I found via from some forum or another (insanelymac.com or osx86project.org or tonymacx86.com, don't remember precisely anymore) and dumped the DSDT from inside OSX after having booted it with Chameleon-on-top-of-SeaBIOS on one hand, or OVMF on the other. They look identical. It's just that when using ovmf, the uhci irq_pin less-than-two invisibility thing kicks in for some weird reason I'm still looking for :) > In fact I think that should be *precisely* the difference here. The PCI > interrupt routing table (_PRT) in the DSDT describes a two-level > mapping. (I've probably forgotten most of the details, sorry.) First, it > maps each PCI (bus, dev, pin) triplet to a PNP0C0F ("PCI interrupt > link") device. We usually call these LNKA, LNKB, LNC, LNKD, LNKS on > i440fx; there are more on q35. Then, each LNKx specifies a set of > possible legacy interrupts that the link can be programmed for / > assigned to. At runtime, the OS programs each of the interrupt links to > one of its allowed legacy interrupts, and then all the pins (across > buses and functions) that are connected to that interrupt link will > trigger that interrupt. The OS usually tries to come up with a mapping > (from LNKx to IRQ) so that interrupt sharing is minimized. > > Here's an example from my i440fx Fedora 20 VM. > > (1) The dmesg says first > > ACPI: PCI Interrupt Link [LNKA] (IRQs 5 10 *11) > ACPI: PCI Interrupt Link [LNKB] (IRQs 5 10 *11) > ACPI: PCI Interrupt Link [LNKC] (IRQs 5 *10 11) > ACPI: PCI Interrupt Link [LNKD] (IRQs 5 *10 11) > ACPI: PCI Interrupt Link [LNKS] (IRQs *9) > > This displays what IRQs the _PRT in the DSDT allows for each of the LNKx > links, and the asterisks show (IIRC) what elements of those sets are > selected (programmed) when Linux inherits the hardware. > > (2) Later it logs > > ACPI: PCI Interrupt Link [LNKC] enabled at IRQ 10 > ACPI: PCI Interrupt Link [LNKD] enabled at IRQ 11 > ACPI: PCI Interrupt Link [LNKA] enabled at IRQ 11 > ACPI: PCI Interrupt Link [LNKB] enabled at IRQ 10 > > Let's call this mapping LNK_IRQ(). > > (3) Then look for the uchi controllers: > > uhci_hcd 0000:00:07.0: irq 10, io base 0x0000c0c0 > uhci_hcd 0000:00:07.1: irq 11, io base 0x0000c0a0 > uhci_hcd 0000:00:07.2: irq 11, io base 0x0000c080 > > And /proc/interrupts is consistent with that: > > CPU0 CPU1 > 10: 6 25 IO-APIC-fasteoi ehci_hcd:usb1, uhci_hcd:usb2 > 11: 0 0 IO-APIC-fasteoi uhci_hcd:usb3, uhci_hcd:usb4, virtio2 > > These last two blocks are *results*. > > Again, this is the result of composing two functions: > > device_interrupt = LNK_IRQ(PRT(bus, dev, pin)) > > PRT() comes from the DSDT, and maps (bus, dev, pin) to a link, while > LNK_IRQ() comes from the OS (the actual link -> IRQ assignment), and is > restricted to the possibilities offered in the DSDT. > > The PRT that QEMU generates follows a rotating pattern (it is not > restricted by physical circuits). As you go from one PCI device to the > next, the same LNKA - LNKD links are distributed over the device's pins, > but the sequence is shifted by one. The idea is that most PCI devices > use only their first pin (INTA), and placing such devices "beside" each > other should nicely iterate over all links, evenly. > > Thus far I didn't speak about functions of the same PCI device. I didn't > do that because I'm uneducated (even more than in the above :)). The > basic idea is that different functions of the device will use different > pins. Most devices are single-function, hence they usually stick with > INTA. If you've got a multifunction device, then the functions will use > separate pins. > > For example, if I dump and decompile the DSDT in the guest, for bus 0 > device 7, I get, from the PRT: > > Package (0x04) { 0x0007FFFF, Zero, LNKC, Zero }, <-- pin 0 / INTA > Package (0x04) { 0x0007FFFF, One, LNKD, Zero }, <-- pin 1 / INTB > Package (0x04) { 0x0007FFFF, 0x02, LNKA, Zero }, <-- pin 2 / INTC > Package (0x04) { 0x0007FFFF, 0x03, LNKB, Zero }, <-- pin 3 / INTD > > Let's put it all together, for a QEMU command line with > > -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x7 > -device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x7.0x1 > -device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,addr=0x7.0x2 > > dev & func, pin, set interrupt link IRQ programmed > set on qemu in qemu for dev & pin, by Linux for > cmdline source set in DSDT link > ----------- -------- -------------- -------------- > 07.0 0 LNKC 10 > 07.1 1 LNKD 11 > 07.2 2 LNKA 11 > > The first two columns are input parameters (from the command line and > from the source code). The third colum is the result of evaluating PRT() > on the input params. The fourth column is the result of evaluating > Linux's LNK_IRQ() function on the third column. > > (Note that all of the above is for i440fx, not q35, but the method is > similar.) Thanks for this crash course, this is really useful stuff to know! > Ultimately, I think that the difference between OVMF and chameleon is > the following: when booting OSX with chameleon, QEMU's rotating _PRT is > not exposed to OSX, because chameleon doesn't know how to download and > interpret the necessary fw_cfg blobs. (What _PRT OSX decides to use > then, I can't imagine.) But when you boot OSX with OVMF, then QEMU's > _PRT is exposed to OSX, and OSX, seeing the PCI bus/device/func > addresses of the UHCI controllers, *and* seeing their respective PINs, > *and* seeing their respective LNKx links (from the DSDT), maps the > function to some interrupt that kills the device. > > This is consistent with your results (if you change the PINs in the > source code, things work). It would be interesting to see what happens > if you shuffle the PCI addresses of the UHCI controllers. > > ... Hm. You did mention in the thread starter that chameleon runs on top > of SeaBIOS. SeaBIOS does have an ACPI linker/loader client, which would > explain why you see the same DSDT. The only thing that could differ > between the two cases is the LNK_IRQ() assignment then (ie. how OSX > chooses to map PCI interrupt links to IRQs), and I don't know why that > would be different. A /proc/interrupts table would be useful, again. > > (Sorry about all the crazy errors I must have said above about PCI, ACPI > etc etc etc. Even if it turns out to be incorrect to some degree, if it > helps others help you, then it wasn't in vain.) Since the DSDT as seen by the guest is identical regardless of whether I boot via ovmf or seabios+chameleon, I assume the results of all these mappings should end up being the same. I'll look for as close an equivalent of "cat /proc/interrupts" on os x as I can find, and try to sanity-check this assumption. Thanks, --Gabriel
On Mon, 15 Sep 2014, Gabriel L. Somlo wrote: > mappings should end up being the same. I'll look for as close an > equivalent of "cat /proc/interrupts" on os x as I can find, and try to > sanity-check this assumption. I think you can find these in the ioreg output. Try ioreg -lfw0 and look for IOInterruptSpecifiers or you can try different IORegistryPlanes with the -p option (I don't have OS X at hand to test). Alternatively there's a GUI tool to get the same info called IORegistryExplorer that used to be part of older XCode versions, not sure where can you get it now. Regards, BALATON Zoltan
Hi, > OK, so I forgot to articulate that with the above patch, I'm seeing > *both* uhci2 and uhci3, but not uhci1. Basically, if uhciX has an > irq_pin less than 2, it won't show up in OSX if booted with ovmf. > We're no longer looking at PIIX, this is q35 with ovmf or without. Can you test what happens with piix4 + usb2? (I suspect you can't as osx will simply not boot then due to the piix4 being much older than the intel port of osx). I think ovmf simply doesn't get the IRQ routing right (doesn't initialize PCI_INTERRUPT_LINE register correctly). It is *not* the same on piix and q35. See piix_pci_slot_get_irq vs. mch_pci_slot_get_irq in seabios source code. I think if you boot linux guests with "noacpi" it will have trouble with usb interrupts too. cheers, Gerd
On Mon, Sep 15, 2014 at 08:02:04PM +0200, Laszlo Ersek wrote: > Here's an example from my i440fx Fedora 20 VM. > > (1) The dmesg says first > > ACPI: PCI Interrupt Link [LNKA] (IRQs 5 10 *11) > ACPI: PCI Interrupt Link [LNKB] (IRQs 5 10 *11) > ACPI: PCI Interrupt Link [LNKC] (IRQs 5 *10 11) > ACPI: PCI Interrupt Link [LNKD] (IRQs 5 *10 11) > ACPI: PCI Interrupt Link [LNKS] (IRQs *9) > > This displays what IRQs the _PRT in the DSDT allows for each of the LNKx > links, and the asterisks show (IIRC) what elements of those sets are > selected (programmed) when Linux inherits the hardware. > > (2) Later it logs > > ACPI: PCI Interrupt Link [LNKC] enabled at IRQ 10 > ACPI: PCI Interrupt Link [LNKD] enabled at IRQ 11 > ACPI: PCI Interrupt Link [LNKA] enabled at IRQ 11 > ACPI: PCI Interrupt Link [LNKB] enabled at IRQ 10 > > Let's call this mapping LNK_IRQ(). > > (3) Then look for the uchi controllers: > > uhci_hcd 0000:00:07.0: irq 10, io base 0x0000c0c0 > uhci_hcd 0000:00:07.1: irq 11, io base 0x0000c0a0 > uhci_hcd 0000:00:07.2: irq 11, io base 0x0000c080 > > And /proc/interrupts is consistent with that: > > CPU0 CPU1 > 10: 6 25 IO-APIC-fasteoi ehci_hcd:usb1, uhci_hcd:usb2 > 11: 0 0 IO-APIC-fasteoi uhci_hcd:usb3, uhci_hcd:usb4, virtio2 > > These last two blocks are *results*. Using F20-live on Q35 with SeaBIOS vs. OVMF, I get: $> grep LNK dmsg*.log dmsg_bios.log: ACPI: PCI Interrupt Link [LNKA] (IRQs 5 *10 11) dmsg_bios.log: ACPI: PCI Interrupt Link [LNKB] (IRQs 5 *10 11) dmsg_bios.log: ACPI: PCI Interrupt Link [LNKC] (IRQs 5 10 *11) dmsg_bios.log: ACPI: PCI Interrupt Link [LNKD] (IRQs 5 10 *11) dmsg_bios.log: ACPI: PCI Interrupt Link [LNKE] (IRQs 5 *10 11) dmsg_bios.log: ACPI: PCI Interrupt Link [LNKF] (IRQs 5 *10 11) dmsg_bios.log: ACPI: PCI Interrupt Link [LNKG] (IRQs 5 10 *11) dmsg_bios.log: ACPI: PCI Interrupt Link [LNKH] (IRQs 5 10 *11) dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKA] (IRQs 5 10 11) *0, disabled. dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKB] (IRQs 5 10 11) *0, disabled. dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKC] (IRQs 5 10 11) *0, disabled. dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKD] (IRQs 5 10 11) *0, disabled. dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKE] (IRQs 5 10 11) *0, disabled. dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKF] (IRQs 5 10 11) *0, disabled. dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKG] (IRQs 5 10 11) *0, disabled. dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKH] (IRQs 5 10 11) *0, disabled. Neither logs any "Link enabled at IRQ X" messages (at least not for LNKX; they both do for GSIX, though). Wonder why it says "disabled" on OVMF... This is the only suspicious (to me) difference between SeaBIOS and OVMF with q35 and fedora. $> grep uhci_hcd dmsg*.log dmsg_bios.log: uhci_hcd: USB Universal Host Controller Interface driver dmsg_bios.log: uhci_hcd 0000:00:1d.0: setting latency timer to 64 dmsg_bios.log: uhci_hcd 0000:00:1d.0: UHCI Host Controller dmsg_bios.log: uhci_hcd 0000:00:1d.0: new USB bus registered, assigned bus # 2 dmsg_bios.log: uhci_hcd 0000:00:1d.0: irq 16, io base 0x0000c080 dmsg_bios.log: usb usb2: Manufacturer: Linux 3.11.10-301.fc20.x86_64 uhci_hcd dmsg_bios.log: uhci_hcd 0000:00:1d.1: setting latency timer to 64 dmsg_bios.log: uhci_hcd 0000:00:1d.1: UHCI Host Controller dmsg_bios.log: uhci_hcd 0000:00:1d.1: new USB bus registered, assigned bus # 3 dmsg_bios.log: uhci_hcd 0000:00:1d.1: irq 17, io base 0x0000c0a0 dmsg_bios.log: usb usb3: Manufacturer: Linux 3.11.10-301.fc20.x86_64 uhci_hcd dmsg_bios.log: uhci_hcd 0000:00:1d.2: setting latency timer to 64 dmsg_bios.log: uhci_hcd 0000:00:1d.2: UHCI Host Controller dmsg_bios.log: uhci_hcd 0000:00:1d.2: new USB bus registered, assigned bus # 4 dmsg_bios.log: uhci_hcd 0000:00:1d.2: irq 18, io base 0x0000c0c0 dmsg_bios.log: usb usb4: Manufacturer: Linux 3.11.10-301.fc20.x86_64 uhci_hcd dmsg_ovmf.log: uhci_hcd: USB Universal Host Controller Interface driver dmsg_ovmf.log: uhci_hcd 0000:00:1d.0: setting latency timer to 64 dmsg_ovmf.log: uhci_hcd 0000:00:1d.0: UHCI Host Controller dmsg_ovmf.log: uhci_hcd 0000:00:1d.0: new USB bus registered, assigned bus # 2 dmsg_ovmf.log: uhci_hcd 0000:00:1d.0: irq 16, io base 0x0000c0e0 dmsg_ovmf.log: usb usb2: Manufacturer: Linux 3.11.10-301.fc20.x86_64 uhci_hcd dmsg_ovmf.log: uhci_hcd 0000:00:1d.1: setting latency timer to 64 dmsg_ovmf.log: uhci_hcd 0000:00:1d.1: UHCI Host Controller dmsg_ovmf.log: uhci_hcd 0000:00:1d.1: new USB bus registered, assigned bus # 3 dmsg_ovmf.log: uhci_hcd 0000:00:1d.1: irq 17, io base 0x0000c0c0 dmsg_ovmf.log: usb usb3: Manufacturer: Linux 3.11.10-301.fc20.x86_64 uhci_hcd dmsg_ovmf.log: uhci_hcd 0000:00:1d.2: setting latency timer to 64 dmsg_ovmf.log: uhci_hcd 0000:00:1d.2: UHCI Host Controller dmsg_ovmf.log: uhci_hcd 0000:00:1d.2: new USB bus registered, assigned bus # 4 dmsg_ovmf.log: uhci_hcd 0000:00:1d.2: irq 18, io base 0x0000c0a0 dmsg_ovmf.log: usb usb4: Manufacturer: Linux 3.11.10-301.fc20.x86_64 uhci_hcd The IO base addresses are the only difference, not sure if this matters: pci io_base_addr device bios ovmf --------------------- 1d.0 c080 c0e0 1d.1 c0a0 c0c0 1d.2 c0c0 c0a0 Finally, the relevant bits from /proc/interrupts: with SeaBIOS: 16: 0 0 0 0 IO-APIC-fasteoi uhci_hcd:usb2, i801_smbus 17: 0 0 0 0 IO-APIC-fasteoi uhci_hcd:usb3 18: 0 0 0 0 IO-APIC-fasteoi uhci_hcd:usb4 19: 55 0 341 0 IO-APIC-fasteoi ehci_hcd:usb1 and with OVMF: 16: 0 0 0 0 IO-APIC-fasteoi uhci_hcd:usb2, i801_smbus 17: 0 0 0 0 IO-APIC-fasteoi uhci_hcd:usb3 18: 0 0 0 0 IO-APIC-fasteoi uhci_hcd:usb4 19: 55 0 131 0 IO-APIC-fasteoi ehci_hcd:usb1 So, basically, no difference. I'm off studying "pci_slot_get_irq" functions in SeaBIOS per Gerd's suggestion, hopefully I can locate the equivalent functionality in OVMF and spot some problem with it I can fix. That might take me a while... :) Thanks, --Gabriel
On 09/22/14 00:10, Gabriel L. Somlo wrote: > dmsg_bios.log: ACPI: PCI Interrupt Link [LNKA] (IRQs 5 *10 11) > dmsg_bios.log: ACPI: PCI Interrupt Link [LNKB] (IRQs 5 *10 11) > dmsg_bios.log: ACPI: PCI Interrupt Link [LNKC] (IRQs 5 10 *11) > dmsg_bios.log: ACPI: PCI Interrupt Link [LNKD] (IRQs 5 10 *11) > dmsg_bios.log: ACPI: PCI Interrupt Link [LNKE] (IRQs 5 *10 11) > dmsg_bios.log: ACPI: PCI Interrupt Link [LNKF] (IRQs 5 *10 11) > dmsg_bios.log: ACPI: PCI Interrupt Link [LNKG] (IRQs 5 10 *11) > dmsg_bios.log: ACPI: PCI Interrupt Link [LNKH] (IRQs 5 10 *11) > > dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKA] (IRQs 5 10 11) *0, disabled. > dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKB] (IRQs 5 10 11) *0, disabled. > dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKC] (IRQs 5 10 11) *0, disabled. > dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKD] (IRQs 5 10 11) *0, disabled. > dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKE] (IRQs 5 10 11) *0, disabled. > dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKF] (IRQs 5 10 11) *0, disabled. > dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKG] (IRQs 5 10 11) *0, disabled. > dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKH] (IRQs 5 10 11) *0, disabled. I mentioned earlier that grepping OvmfPkg for PCI_LIB_ADDRESS would be necessary. See PciInitialization() in "OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c". // // Bus 0, Device 1, Function 0 - PCI to ISA Bridge // PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x3c), 0x00); PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // LNKA routing target PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // LNKB routing target PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // LNKC routing target PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // LNKD routing target This is not appropriate for q35. See "ICH9 PCI to ISA irq remapping" in qemu's "q35-acpi-dsdt.dsl" file, vs. "PIIX PCI to ISA irq remapping" in "acpi-dsdt.dsl". The above was added in 05c89c7f. Thanks Laszlo
Il 22/09/2014 00:43, Laszlo Ersek ha scritto: > // Bus 0, Device 1, Function 0 - PCI to ISA Bridge > // > PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x3c), 0x00); > PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // LNKA routing target > PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // LNKB routing target > PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // LNKC routing target > PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // LNKD routing target > > This is not appropriate for q35. See "ICH9 PCI to ISA irq remapping" in > qemu's "q35-acpi-dsdt.dsl" file, vs. "PIIX PCI to ISA irq remapping" in > "acpi-dsdt.dsl". If I understand the DSDT right, the field is still at 0x60, but the bridge is now at 1f.0. Right? Also, LNKE-LNKH must be set at 0x68. However, these are only used if OS X runs in PIC mode rather than APIC mode (see \_PIC). Why should OS X be running in PIC mode? So fixing the above is right to do, but may not be enough. Paolo
On Mon, Sep 22, 2014 at 06:44:26PM +0200, Paolo Bonzini wrote: > Il 22/09/2014 00:43, Laszlo Ersek ha scritto: > > I mentioned earlier that grepping OvmfPkg for PCI_LIB_ADDRESS would be > > necessary. See PciInitialization() in > > "OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c". I remember that, but back then I hadn't RTFMed enough for it to mean something useful to me. I get it now though, so thanks for the repetition :) > > // > > // Bus 0, Device 1, Function 0 - PCI to ISA Bridge > > // > > PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x3c), 0x00); > > PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // LNKA routing target > > PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // LNKB routing target > > PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // LNKC routing target > > PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // LNKD routing target > > > > This is not appropriate for q35. See "ICH9 PCI to ISA irq remapping" in > > qemu's "q35-acpi-dsdt.dsl" file, vs. "PIIX PCI to ISA irq remapping" in > > "acpi-dsdt.dsl". > > If I understand the DSDT right, the field is still at 0x60, but the > bridge is now at 1f.0. Right? Also, LNKE-LNKH must be set at 0x68. > > However, these are only used if OS X runs in PIC mode rather than APIC > mode (see \_PIC). Why should OS X be running in PIC mode? So fixing > the above is right to do, but may not be enough. I'll take a pass at making these dependent on the host bridge DID (same as with the pmbase/pmtimer) instead of hard coded, then we'll see what else breaks :) Thanks again for
On 09/22/14 18:44, Paolo Bonzini wrote: > Il 22/09/2014 00:43, Laszlo Ersek ha scritto: >> // Bus 0, Device 1, Function 0 - PCI to ISA Bridge >> // >> PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x3c), 0x00); >> PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // LNKA routing target >> PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // LNKB routing target >> PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // LNKC routing target >> PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // LNKD routing target >> >> This is not appropriate for q35. See "ICH9 PCI to ISA irq remapping" in >> qemu's "q35-acpi-dsdt.dsl" file, vs. "PIIX PCI to ISA irq remapping" in >> "acpi-dsdt.dsl". > > If I understand the DSDT right, the field is still at 0x60, but the > bridge is now at 1f.0. Right? Also, LNKE-LNKH must be set at 0x68. > > However, these are only used if OS X runs in PIC mode rather than APIC > mode (see \_PIC). Why should OS X be running in PIC mode? So fixing > the above is right to do, but may not be enough. I agree completely. I mentioned this because of dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKA] (IRQs 5 10 11) *0, disabled. dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKB] (IRQs 5 10 11) *0, disabled. dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKC] (IRQs 5 10 11) *0, disabled. dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKD] (IRQs 5 10 11) *0, disabled. dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKE] (IRQs 5 10 11) *0, disabled. dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKF] (IRQs 5 10 11) *0, disabled. dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKG] (IRQs 5 10 11) *0, disabled. dmsg_ovmf.log: ACPI: PCI Interrupt Link [LNKH] (IRQs 5 10 11) *0, disabled. Thanks, Laszlo
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 3b3ebcd..d61656e 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -1335,21 +1335,21 @@ static UHCIInfo uhci_info[] = { .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI1, .revision = 0x03, - .irq_pin = 0, + .irq_pin = 1, .unplug = false, },{ .name = "ich9-usb-uhci2", /* 00:1d.1 */ .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI2, .revision = 0x03, - .irq_pin = 1, + .irq_pin = 2, .unplug = false, },{ .name = "ich9-usb-uhci3", /* 00:1d.2 */ .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI3, .revision = 0x03, - .irq_pin = 2, + .irq_pin = 3, .unplug = false, },{ .name = "ich9-usb-uhci4", /* 00:1a.0 */