[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] Re: [PATCH 04/26] pci: add accessor function to get irq lev
From: |
Michael S. Tsirkin |
Subject: |
[Qemu-devel] Re: [PATCH 04/26] pci: add accessor function to get irq levels |
Date: |
Thu, 17 Mar 2011 10:19:14 +0200 |
User-agent: |
Mutt/1.5.21 (2010-09-15) |
On Thu, Mar 17, 2011 at 03:05:00PM +0900, Isaku Yamahata wrote:
> On Thu, Mar 17, 2011 at 07:29:09AM +0200, Michael S. Tsirkin wrote:
> > On Wed, Mar 16, 2011 at 06:29:15PM +0900, Isaku Yamahata wrote:
> > > Introduce accessor function to know INTx levels.
> > > It will be used later by q35.
> > > Although piix_pci tracks the intx line levels, it can be eliminated
> > > by this helper function.
> >
> > At least for piix, the right thing to IMO is to have bit per
> > IRQ, then the for loop can be replaced with a single !!. There's a TODO
> > there which this will fix. I think we can reuse pci device irq_state
> > for this: need to check. Haven't looked at q35 yet - applies there as
> > well?
>
> Yes, such bitmap optimization is possible.
> But this accessor function is still necessary,
OK, I'm convinced. It makes sense off data path,
much easier than try to unswizzle and swizzle back
to the new values.
> please see the following. (I didn't do any test yet. Just to show the idea)
> If you like it, I'll post it as separate patch.
Yes. BTW as long as we touch it, we might want some symbolic
name for constants 0x60, 16, and use PCI_NUM_PINS instead of 4.
Some more suggestions below.
Also, save/restore needs to be updated.
> diff --git a/hw/piix_pci.c b/hw/piix_pci.c
> index 151353c..82b7daf 100644
> --- a/hw/piix_pci.c
> +++ b/hw/piix_pci.c
> @@ -40,6 +40,7 @@ typedef PCIHostState I440FXState;
>
> typedef struct PIIX3State {
> PCIDevice dev;
> + unsigned long irq_level[16];
That's 1024 bits. We really only need 4*16 = 64 bits.
Also pic_levels might be a better name.
So just
uint64_t pic_levels;
Maybe stick a check there:
#if PCI_NUM_PINS * PIIX_NUM_PIC_IRQS > 64
#error unable to encode pic state in 64 bit in pic_levels
#endif
Also, need to clear on init?
> int32_t dummy_for_save_load_compat[4];
> qemu_irq *pic;
> } PIIX3State;
> @@ -200,25 +201,51 @@ PCIBus *i440fx_init(int *piix3_devfn, qemu_irq *pic,
> ram_addr_t ram_size)
> }
>
> /* PIIX3 PCI to ISA bridge */
> -
> static void piix3_set_irq(void *opaque, int irq_num, int level)
> {
> int i, pic_irq, pic_level;
> PIIX3State *piix3 = opaque;
>
> - /* now we change the pic irq level according to the piix irq mappings */
> - /* XXX: optimize */
> pic_irq = piix3->dev.config[0x60 + irq_num];
> - if (pic_irq < 16) {
> - /* The pic level is the logical OR of all the PCI irqs mapped
> - to it */
> - pic_level = 0;
> - for (i = 0; i < 4; i++) {
> - if (pic_irq == piix3->dev.config[0x60 + i]) {
> - pic_level |= pci_bus_get_irq_level(piix3->dev.bus, i);
> - }
> + if (pic_irq >= 16) {
> + return;
> + }
> +
> + /* The pic level is the logical OR of all the PCI irqs mapped to it */
> + if (level) {
> + set_bit(&piix3->irq_level[pic_irq], irq_num);
> + } else {
> + clear_bit(&piix3->irq_level[pic_irq], irq_num);
> + }
We can do this without a branch too I think (assuming uint64_t suggested
above):
mask = 0x1ull << (pic_irq * 16 + irq_num);
piix3->pic_levels &= ~mask;
piix3->pic_levels |= mask;
> + qemu_set_irq(piix3->pic[pic_irq], !!piix3->irq_level[pic_irq]);
> +}
> +
> +/* irq routing is changed. so rebuild bitmap */
> +static void piix3_update_irq_levels(PIIX3State *piix3)
> +{
> + int i;
> + for (i = 0; i < 16; i++) {
> + piix3->irq_level[i] = 0;
> + }
memset(piix3->irq_level, 0, sizeof piix3->irq_level);
> + for (i = 0; i < 4; i++) {
> + int pic_irq = piix3->dev.config[0x60 + irq_num];
> + if (pic_irq >= 16) {
> + continue;
> + }
> + if (pci_bus_get_irq_level(piix3->dev.bus, i)) {
> + set_bit(&piix3->irq_level[pic_irq], i);
> }
> - qemu_set_irq(piix3->pic[pic_irq], pic_level);
Hmm, don't we need to set the levels in guest appropriately?
There's also some duplication here.
Can't we just do
for (i = 0; i < 4; i++) {
piix3_set_irq(piix3, i, pci_bus_get_irq_level(piix3->dev.bus,
i));
}
?
> + }
> +}
> +
> +static void piix3_write_config(PCIDevice *dev,
> + uint32_t address, uint32_t val, int len)
> +{
> + PIIX3State *piix3 = DO_UPCAST(PIIX3State, dev, dev);
> +
> + pci_default_write_config(dev, address, val, len);
> + if (ranges_overlap(address, len, 0x60, 4)) {
> + piix3_update_irq_levels(piix3);
> }
> }
>
> @@ -318,6 +345,7 @@ static PCIDeviceInfo i440fx_info[] = {
> .qdev.no_user = 1,
> .no_hotplug = 1,
> .init = piix3_initfn,
> + .config_write = piix3_write_config,
> },{
> /* end of list */
> }
>
> --
> yamahata
- [Qemu-devel] [PATCH 24/26] acpi, acpi_piix: factor out GPE logic, (continued)
- [Qemu-devel] [PATCH 24/26] acpi, acpi_piix: factor out GPE logic, Isaku Yamahata, 2011/03/16
- [Qemu-devel] [PATCH 09/26] dec_pci: simplify dec_pci.c by using pci_p2pbr, Isaku Yamahata, 2011/03/16
- [Qemu-devel] [PATCH 22/26] acpi, acpi_piix: factor out PM1a EVT logic, Isaku Yamahata, 2011/03/16
- [Qemu-devel] [PATCH 08/26] apb_pci: simplify apb_pci.c by using pci_p2pbr, Isaku Yamahata, 2011/03/16
- [Qemu-devel] [PATCH 04/26] pci: add accessor function to get irq levels, Isaku Yamahata, 2011/03/16
- [Qemu-devel] [PATCH 23/26] acpi, acpi_piix: factor out PM1_CNT logic, Isaku Yamahata, 2011/03/16
- [Qemu-devel] [PATCH 15/26] smbus_eeprom: consolidate smbus eeprom creation, Isaku Yamahata, 2011/03/16
- [Qemu-devel] [PATCH 07/26] pci/p2pbr: generic pci p2p bridge, Isaku Yamahata, 2011/03/16
[Qemu-devel] [PATCH 19/26] pc/piix_pci: factor out smram/pam logic, Isaku Yamahata, 2011/03/16
[Qemu-devel] [PATCH 12/26] usb/uhci: generalize initialization, Isaku Yamahata, 2011/03/16