On 24/12/2020 08:11, BALATON Zoltan via wrote:
On Wed, 23 Dec 2020, Guenter Roeck wrote:
On Thu, Dec 24, 2020 at 02:34:07AM +0100, BALATON Zoltan wrote:
[ ... ]
If we need legacy mode then we may be able to emulate that by setting BARs
to legacy ports ignoring what values are written to them if legacy mode
config is set (which may be what the real chip does) and we already have
IRQs hard wired to legacy values so that would give us legacy and
half-native mode which is enough for both fuloong2e and pegasos2 but I'm not
sure how can we fix BARs in QEMU because that's also handled by generic PCI
code which I also don't want to break.
The code below works for booting Linux while at the same time not affecting
any other emulation. I don't claim it to be a perfect fix, and overloading
the existing property is a bit hackish, but it does work.
Yes, maybe combining it with my original patch 1 to change secondary to flags to make
it a bit cleaner would work for me. Then we would either only emulate legacy or
half-native mode which is sufficient for these two machines we have. If Mark or
others do not object it this time, I can update my patch and resubmit with this one
to fix this issue, otherwise let's wait what idea do they have because I hate to
spend time with something only to be discarded again. I think we don't need more
complete emulation of this chip than this for now but if somebody wants to attempt
that I don't mind as long as it does not break pegasos2.
I had a play with your patches this afternoon, and spent some time performing some
experiments and also reading various PCI bus master specifications and datasheets:
this helped me understand a lot more about the theory of IRQ routing and compatible
vs. legacy mode.
From reading all the documentation (including the VIA and other datasheets) I cannot
find any reference to a half-native mode which makes me think something else is wrong
here. At the simplest level it could simply be that the VIA doesn't tri-state its
legacy IRQ lines whilst the device is in native mode (the SI controller has an option
for this), or it could indicate there is a PCI IRQ routing problem somewhere else
that hasn't been picked up yet.
All of the datasheets suggest that legacy vs. native mode is selected by setting the
correct bits in PCI_CLASS_PROG, and Linux reads this byte and configures itself to
use legacy or native mode accordingly. Since the current default for the VIA is 0x8a
then it should default to legacy mode, but we're immediately hitting some issues
here: I've summarised my notes below for those interested.
1) PCI bus reset loses the default BAR addresses
The first problem we find is that the initialisation of the PCI bus erases the
default BAR addresses: that's to say lines 133-137 in hw/ide/via.c will in effect do
nothing:
133 pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, 0x000001f0);
134 pci_set_long(pci_conf + PCI_BASE_ADDRESS_1, 0x000003f4);
135 pci_set_long(pci_conf + PCI_BASE_ADDRESS_2, 0x00000170);
136 pci_set_long(pci_conf + PCI_BASE_ADDRESS_3, 0x00000374);
137 pci_set_long(pci_conf + PCI_BASE_ADDRESS_4, 0x0000cc01); /* BMIBA:
20-23h */
The lifecycle of the VIA IDE device goes like this: init() -> realize() -> reset()
but then the PCI bus reset in pci_do_device_reset() immediately wipes the BAR
addresses. This is why the legacy IDE ports currently don't appear at startup. Note I
do see that other devices do try this e.g. gt64120_pci_realize() so it's an easy
mistake to make.
2) -kernel doesn't initialise the VIA device
If you take a look at the PMON source it is possible to see that the firmware
explicitly sets the PCI_CLASS_PROG to compatibility mode and disables the native PCI
interrupt
(https://github.com/loongson-community/pmon-2ef/blob/master/sys/dev/pci/vt82c686.c#L82).
Since Linux reads this byte on startup then this is why the kernel switches to
compatibility mode by default. However the point here is that booting a kernel
directly without firmware means the VIA IDE device isn't initialised as it would be
in real life, and that's why there are attempts to pre-configure the device
accordingly in via_ide_realize()/via_ide_reset().
3) QEMU doesn't (easily) enable a BAR to be disabled
The ideal situation would be for QEMU's VIA IDE device to check PCI_CLASS_PROG and
configure itself dynamically: with PCI_CLASS_PROG set for legacy mode by default, the
device can disable its BARs until they are explicitly enabled.
According to the PCI bus master specification the recommended behaviour for a device
in compatible mode is to ignore all writes to the BARs, and for all BAR reads to
return 0. This fits nicely with Guenter's finding that the BMDMA BAR should not
return a value in order for Linux to boot correctly in legacy mode.
Unfortunately there is no existing functionality for this in QEMU which means you
would have to do this manually by overriding the PCI config read/write functions.
This is trickier than it sounds because the reads/writes don't necessarily have to be
aligned to the BAR addresses in configuration space.
In summary whilst I'm not keen on the series in its current form, it seems the best
solution for now. I've got a few comments on the latest version of the series which I
will send along shortly.
ATB,
Mark.