All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Gabriel L. Somlo" <gsomlo@gmail.com>
To: Laszlo Ersek <lersek@redhat.com>
Cc: edk2-devel@lists.sourceforge.net, agraf@suse.de,
	qemu-devel@nongnu.org, Gerd Hoffmann <kraxel@redhat.com>,
	reza.jelveh@tuhh.de, Paolo Bonzini <pbonzini@redhat.com>
Subject: Re: [Qemu-devel] OVMF, Q35 and USB keyboard/mouse
Date: Mon, 15 Sep 2014 15:23:34 -0400	[thread overview]
Message-ID: <20140915192333.GR1825@ERROL.INI.CMU.EDU> (raw)
In-Reply-To: <5417299C.7020107@redhat.com>

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

  reply	other threads:[~2014-09-15 19:23 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-09 22:00 [Qemu-devel] OVMF, Q35 and USB keyboard/mouse Gabriel L. Somlo
2014-09-10  0:40 ` Laszlo Ersek
2014-09-10  6:31 ` Gerd Hoffmann
2014-09-10  7:59   ` Laszlo Ersek
2014-09-10 14:06     ` Gabriel L. Somlo
2014-09-10 23:08       ` [Qemu-devel] [edk2] " Paolo Bonzini
2014-09-11 15:42         ` [Qemu-devel] " Gabriel L. Somlo
2014-09-11 15:49           ` Paolo Bonzini
2014-09-11 16:35             ` Gabriel L. Somlo
2014-09-11 16:40               ` Paolo Bonzini
2014-09-11 17:11                 ` Gabriel L. Somlo
2014-09-11 17:15                   ` [Qemu-devel] [edk2] " Paolo Bonzini
2014-09-11 20:16                 ` [Qemu-devel] " Gabriel L. Somlo
2014-09-11 20:46                   ` Laszlo Ersek
2014-09-11 21:34                     ` Alexander Graf
2014-09-11 23:21                       ` Gabriel L. Somlo
2014-09-12  9:17                         ` BALATON Zoltan
2014-09-12 17:58                           ` Gabriel L. Somlo
2014-09-12  6:46                   ` Gerd Hoffmann
2014-09-12 18:18                     ` Gabriel L. Somlo
2014-09-12 18:26                       ` Paolo Bonzini
2014-09-12 19:59                         ` Gabriel L. Somlo
2014-09-13  5:06                           ` Laszlo Ersek
2014-09-15 14:50                           ` Gabriel L. Somlo
2014-09-15 15:01                             ` Laszlo Ersek
2014-09-15 15:07                               ` Gabriel L. Somlo
2014-09-15 18:02                                 ` Laszlo Ersek
2014-09-15 19:23                                   ` Gabriel L. Somlo [this message]
2014-09-15 19:56                                     ` BALATON Zoltan
2014-09-16  8:15                                     ` Gerd Hoffmann
2014-09-21 20:00                                       ` Gabriel L. Somlo
2014-09-21 22:10                                   ` Gabriel L. Somlo
2014-09-21 22:43                                     ` Laszlo Ersek
2014-09-22 16:44                                       ` [Qemu-devel] [edk2] " Paolo Bonzini
2014-09-22 16:59                                         ` Gabriel L. Somlo
2014-09-22 20:40                                         ` Laszlo Ersek
2014-09-24 22:03                                           ` Gabriel L. Somlo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140915192333.GR1825@ERROL.INI.CMU.EDU \
    --to=gsomlo@gmail.com \
    --cc=agraf@suse.de \
    --cc=edk2-devel@lists.sourceforge.net \
    --cc=kraxel@redhat.com \
    --cc=lersek@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=reza.jelveh@tuhh.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.