|
From: | BALATON Zoltan |
Subject: | Re: [PATCH 2/2] via-ide: Also emulate non 100% native mode |
Date: | Fri, 6 Mar 2020 23:59:47 +0100 (CET) |
User-agent: | Alpine 2.22 (BSF 395 2020-01-19) |
On Fri, 6 Mar 2020, Mark Cave-Ayland wrote:
On 06/03/2020 19:38, BALATON Zoltan wrote:On Fri, 6 Mar 2020, Mark Cave-Ayland wrote:On 06/03/2020 12:06, BALATON Zoltan wrote:On Fri, 6 Mar 2020, Mark Cave-Ayland wrote:On 05/03/2020 23:35, BALATON Zoltan wrote:On real hardware this may be true but in QEMU how would it otherwise raise the correct interrupt line the guest expects? This probably does not matter for pegasos2 but I think is needed for 100% native mode used with the fulong2e so it gets the IRQ it expects.That's easy - remember that both the PCI and IRQ interrupts are separate pins on the chip, so all that needs to be done is expose the legacy IRQ via qdev and use that to wire it up to your interrupt controller.This "chip" is part of an integrated southbridge/superio/everything chip the also includes the two PICs and how they are internally connected is not known so we would be guessing here anyway. I don't see a need to make it more complicated than it is now by modeling internal pins but how would I wire up gpio to the i8259 model and where should I connect the PCI irq?For now I would say not to worry about the PCI IRQ: the reason for discussing this before was because we believed that if the controller was in native mode it must be using the IRQ in PCI_INTERRUPT_LINE. But from yesterday's read of the specification we know that PCI_INTERRUPT_LINE is never used by the device itself, and so given that the existing via-ide device doesn't currently attempt to use the PCI IRQ in via_ide_set_irq() then we should be good. If someone had a machine somewhere that did use the PCI IRQ then it would need investigation, but since there isn't then I don't see any need to do this now.Okay so this is interesting: I've been switching between the VT8231 and the VT82C686B datasheets, and there is a difference here. You are correct in what you say above in that the 8231 docs specify that this is set to 1, but on the 686B this is clearly not the case.The 82C686B says this reg can be 0 or 1, where 0 is legacy interrupt routing and 1 is native mode. Given that we only model native mode of the chip it does not make sense to set it to anything else than 1 and setting it to 0 confuses MorphOS and Linux on pegasos2 while setting it to 1 works with everything I've tried both on pegasos2 and fulong2e even if that may not completely match how it's implemented in hardware.What is rather unusual here is that both the 8231 and 686B have exactly the same device and vendor ids, so I'm not sure how you'd distinguish between them?Guests distinguish by looking at the parent device (function 0) which is the chip this IDE device is part of (on function 1).Okay thanks, that's useful to know. I've done a quick grep of the source tree and AFAICT the only IDE controller that tries to use the PCI_INTERRUPT_LINE register is via-ide, which means this should be fairly easy. In short: 1) Add qemu_irq legacy_irqs[2] into PCIIDEState (You could argue that it should belong in a separate VIAIDEState, however quite a few of the BMDMA controllers in QEMU don't have their own device state and just use PCIIDEState. And whilst via-ide is the only one that currently needs support for legacy IRQs, I think it's good to put it there in case other controllers need it in future) 2) Add via_ide_initfn() to hw/ide/via.c and add qdev_init_gpio_out_named() with a name of "legacy-irq" to itI don't like this. This adds two via-ide specific data to to common PCI IDE code where it does not belong and subclassing it just for this also seems to be more changes than really needed. Reusing the existing CMD646 field and generalising it to allow implementation specific feature flags seems much less intrusive and not less clean than your proposal.It's not VIA-specific though: the ISA legacy and PCI buses have different electrical characteristics and so by definition their signals must be driven by separate physical pins. Have a look at the CMD646 datasheet for example, and you will see that separate pins exist for legacy and PCI native IRQs.
For CMD646 we only use PCI interrupt which is in PCIDevice. Its legacy mode and thus those pins are not modelled so not needed now. For via-ide we only use ISA interrupts because even if we don't model legacy mode, boards expect ISA interrupts also in native mode maybe because this controller is not a separate PCI device only found embedded in southbridge/superio chips where they connect to the also embedded ISA PICs so even in native mode it should raise one of the ISA IRQs. My patch accesses ISA irqs with isa_get_irq() so no gpios and legacy irqs in PCIIDEState is neeeded and I don't see the need to introduce this complexity here. Also newer PCI ATA and SATA controllers such as sii3112 do not have a legacy mode so I'd keep things related to that out of common PCI IDE code and model it instead in the controllers that have this as this does not seem to belong to PCI IDE.
3) Inline via_ide_init() into hw/mips/mips_fulong2e.c, changing pci_create_simple() to pci_create() because the device shouldn't be realised immediately 4) In vt82c686b_southbridge_init use qdev_connect_gpio_out_named() to connect legacy_irq[0] to 8259 IRQ 14 and legacy_irq[1] to 8259 IRQ 15, and then realise the deviceHow do I connect gpios to 8259 interrupts? That seems to be internal state of 8259 that I'm not sure how to access cleanly from code instantiating it. Is this better than my patch? It seems it achieves the same via-ide specific behaviour just in a more complicated way and would still need the feature bit to know when to use legacy_irq[1].We know from the PCI specification that the existing code for via-ide is incorrect, and given that none of the other IDE controllers in QEMU use PCI_INTERRUPT_LINE in this way then both of these strongly suggest that current via-ide implementation is wrong. Rather than add a hack on top of a hack then the simplest solution is to physically wire the IRQ pin using qdev at the board level, as is done on real hardware.
But it's not done that way on real hardware and via-ide is not a PCI device but all this is internal to the VT8231 chip, the PICs, via-ide and a lot of other things which are modelled in QEMU by reusing existing components but I think we don't want to model the internal of the chip down to the smallest detail. In via-ide's case the PCI_INTERRUPT_LINE is probably not used by the IDE controller function but is used by some other function of the southbridge chip that implements interrupt controller but we don't have a separate model of that in QEMU so we can just emulate this function within via-ide which I think is OK as this IDE controller is part of these southbridges and not used anywhere else. This partly mixes IDE controller function and interrupt controller function but probably OK until we want to model this southbridge in more detail which could be done in later clean up patches. The piix model seems to do the same embedding a 8259 which even less belongs to an IDE controller and acceses irqs array directly.
Looking at the code it seems that i8259_init() returns the PIC IRQ array so it should just be a case of returning the nth entry and using that with qdev_init_gpio_out_named().5) Remove the PCI_INTERRUPT_LINE logic from via_ide_set_irq() and instead just do qemu_set_irq() on legacy_irq[0] (in theory I guess it should be legacy_irq[n] but it seems that both drives on MIPS and Pegasos both use IRQ 14).According to the 8231 datasheet in legacy mode (and on pegasos2's half-native mode) the interrupts should be 14 and 15 so legacy_irq[n] with your way but in 100% native mode (used on the fulong2e) it should be the one set in PCI_INTERRUPT_LINE. The 686B datasheet does not detail this but I believe it works the same. Since we currently fixed the native mode interrupt to 14 to work around pegasos2 firmware and QEMU PCI reset interactions using legacy_irq[0] might work but is not correct, the current way using PCI_INTERRUPT_LINE is better modelling what hardware does in my opinion.This is not correct though: please re-read my previous email which quotes from the PCI specification itself that defines PCI_INTERRUPT_LINE has *no effect* upon the device itself, and is merely advisory to the OS. Possibly the MIPS BIOS could be placing a value other than 14 there, but if it does then that suggests the board IRQs are physically wired differently which again should be handled at board level by qdev.
Correct or not or follows the spec or not this is how it works on real hardware and to get guests running we need to emulate this. Again, this controller is embedded in the 868B and 8231 southbridge chips so they may not completely confirm to PCI spec but their own datasheets. We can argue in how much detail do we want to model the internals of these chips (which we don't know for sure) but I think this patch is good enough for now and could be refined later or we likely won't be able to finish this before the freeze.
Another way to look at it is that this patch gets some guests running and does not break anything as far as I know so is there anything in it that's unacceptable now and needs to be changed for it to be merged? Unless you can propose a way to achieve the same in a simpler way now I think we could go with this and you can submit follow up patches to clean it up as you like later.
Regards, BALATON Zoltan
[Prev in Thread] | Current Thread | [Next in Thread] |