All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: Isaku Yamahata <yamahata@valinux.co.jp>
Cc: qemu-devel@nongnu.org
Subject: [Qemu-devel] Re: [PATCH 16/20] pci: kill goto in pci_update_mappings()
Date: Thu, 12 Nov 2009 15:13:08 +0200	[thread overview]
Message-ID: <20091112131308.GD11123@redhat.com> (raw)
In-Reply-To: <20091112131207.GF2240%yamahata@valinux.co.jp>

On Thu, Nov 12, 2009 at 10:12:07PM +0900, Isaku Yamahata wrote:
> On Thu, Nov 12, 2009 at 02:06:22PM +0200, Michael S. Tsirkin wrote:
> > On Thu, Nov 12, 2009 at 02:58:44PM +0900, Isaku Yamahata wrote:
> > > This patch kills nasty goto in pci_update_mappings().
> > > 
> > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > > ---
> > >  hw/pci.c |   54 ++++++++++++++++++++++++++++--------------------------
> > >  1 files changed, 28 insertions(+), 26 deletions(-)
> > > 
> > > diff --git a/hw/pci.c b/hw/pci.c
> > > index cae3d53..2eff7fe 100644
> > > --- a/hw/pci.c
> > > +++ b/hw/pci.c
> > > @@ -756,35 +756,37 @@ static void pci_update_mappings(PCIDevice *d)
> > >                      new_addr = pci_get_long(d->config + pci_bar(d, i));
> > >                  }
> > >                  /* the ROM slot has a specific enable bit */
> > > -                if (i == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE))
> > > -                    goto no_mem_map;
> > > -                new_addr = new_addr & ~(r->size - 1);
> > > -                last_addr = new_addr + r->size - 1;
> > > -                /* NOTE: we do not support wrapping */
> > > -                /* XXX: as we cannot support really dynamic
> > > -                   mappings, we handle specific values as invalid
> > > -                   mappings. */
> > > -                if (last_addr <= new_addr || new_addr == 0 ||
> > 
> > By the way, any idea why do we need new_addr == 0
> > and last_addr == PCI_BAR_UNMAPPED?
> 
> As for new_addr == 0, since default BAR value is zero, plural BARs can
> overlap with each other. I think qemu can't handle BAR overlap anyway.

Heh, for that matter, BARs can overlap anyway.
0 just makes it more likely.

> As for last_addr == PCI_BAR_UNMAPPED, it avoid to map
> around 4GB as discussed before. I observed that guest doesn't boot
> without the check. However I didn't track it down further.
> Now it's 64bit though.

Hmm. Would be nice to figure all this out.

> > What would it take to fix these?
> > 
> > > -                    last_addr == PCI_BAR_UNMAPPED ||
> > > -
> > > -                    /* Now pcibus_t is 64bit.
> > > -                     * Check if 32 bit BAR wrap around explicitly.
> > > -                     * Without this, PC ide doesn't work well.
> > > -                     * TODO: remove this work around.
> > > -                     */
> > > -                    (!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) &&
> > > -                     last_addr >= UINT32_MAX) ||
> > > -
> > > -                    /*
> > > -                     * OS is allowed to set BAR beyond its addressable
> > > -                     * bits. For example, 32 bit OS can set 64bit bar
> > > -                     * to >4G. Check it.
> > > -                     */
> > > -                    last_addr >= TARGET_PHYS_ADDR_MAX) {
> > > +                if (i == PCI_ROM_SLOT &&
> > > +                    !(new_addr & PCI_ROM_ADDRESS_ENABLE)) {
> > >                      new_addr = PCI_BAR_UNMAPPED;
> > > +                } else {
> > > +                    new_addr = new_addr & ~(r->size - 1);
> > > +                    last_addr = new_addr + r->size - 1;
> > > +                    /* NOTE: we do not support wrapping */
> > > +                    /* XXX: as we cannot support really dynamic
> > > +                       mappings, we handle specific values as invalid
> > > +                       mappings. */
> > > +                    if (last_addr <= new_addr || new_addr == 0 ||
> > > +                        last_addr == PCI_BAR_UNMAPPED ||
> > > +
> > > +                        /* Now pcibus_t is 64bit.
> > > +                         * Check if 32 bit BAR wrap around explicitly.
> > > +                         * Without this, PC ide doesn't work well.
> > > +                         * TODO: remove this work around.
> > > +                         */
> > > +                        (!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) &&
> > > +                         last_addr >= UINT32_MAX) ||
> > > +
> > > +                        /*
> > > +                         * OS is allowed to set BAR beyond its addressable
> > > +                         * bits. For example, 32 bit OS can set 64bit bar
> > > +                         * to >4G. Check it.
> > > +                         */
> > > +                        last_addr >= TARGET_PHYS_ADDR_MAX) {
> > > +                        new_addr = PCI_BAR_UNMAPPED;
> > > +                    }
> > >                  }
> > >              } else {
> > > -            no_mem_map:
> > >                  new_addr = PCI_BAR_UNMAPPED;
> > >              }
> > >          }
> > 
> > Nesting is too deep in pci_update_mappings already.
> > And this makes it worse. I split out the math into
> > a subfunction, and it looks better IMO:
> > 
> > --->
> > 
> > From: Michael S. Tsirkin <mst@redhat.com>
> > Subject: pci: split up up pci_update mappings
> > 
> > Split bar address math into a separate function.
> > In particular, this gets rid of an ugly forward goto
> > into scope that we have there.
> > 
> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> 
> Makes sense. Much more readable.
> Acked-by: Isaku Yamahata <yamahata@valinux.co.jp>
> 
> 
> > 
> > ---
> > 
> > diff --git a/hw/pci.c b/hw/pci.c
> > index 380d43c..847d31e 100644
> > --- a/hw/pci.c
> > +++ b/hw/pci.c
> > @@ -720,14 +720,77 @@ static void pci_bridge_filter(PCIDevice *d, pcibus_t *addr, pcibus_t *size,
> >      }
> >  }
> >  
> > +static pcibus_t pci_bar_address(PCIDevice *d,
> > +				int reg, uint8_t type, pcibus_t size)
> > +{
> > +    pcibus_t new_addr, last_addr;
> > +    int bar = pci_bar(d, reg);
> > +    uint16_t cmd = pci_get_word(d->config + PCI_COMMAND);
> > +
> > +    if (type & PCI_BASE_ADDRESS_SPACE_IO) {
> > +        if (!(cmd & PCI_COMMAND_IO)) {
> > +            return PCI_BAR_UNMAPPED;
> > +        }
> > +        new_addr = pci_get_long(d->config + bar) & ~(size - 1);
> > +        last_addr = new_addr + size - 1;
> > +        /* NOTE: we have only 64K ioports on PC */
> > +        if (last_addr <= new_addr || new_addr == 0 || last_addr > UINT16_MAX) {
> > +            return PCI_BAR_UNMAPPED;
> > +        }
> > +        return new_addr;
> > +    }
> > +
> > +    if (!(cmd & PCI_COMMAND_MEMORY)) {
> > +        return PCI_BAR_UNMAPPED;
> > +    }
> > +    if (type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
> > +        new_addr = pci_get_quad(d->config + bar);
> > +    } else {
> > +        new_addr = pci_get_long(d->config + bar);
> > +    }
> > +    /* the ROM slot has a specific enable bit */
> > +    if (reg == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE)) {
> > +        return PCI_BAR_UNMAPPED;
> > +    }
> > +    new_addr &= ~(size - 1);
> > +    last_addr = new_addr + size - 1;
> > +    /* NOTE: we do not support wrapping */
> > +    /* XXX: as we cannot support really dynamic
> > +       mappings, we handle specific values as invalid
> > +       mappings. */
> > +    if (last_addr <= new_addr || new_addr == 0 ||
> > +        last_addr == PCI_BAR_UNMAPPED) {
> > +        return PCI_BAR_UNMAPPED;
> > +    }
> > +
> > +    /* Now pcibus_t is 64bit.
> > +     * Check if 32 bit BAR wraps around explicitly.
> > +     * Without this, PC ide doesn't work well.
> > +     * TODO: remove this work around.
> > +     */
> > +    if  (!(type & PCI_BASE_ADDRESS_MEM_TYPE_64) && last_addr >= UINT32_MAX) {
> > +        return PCI_BAR_UNMAPPED;
> > +    }
> > +
> > +    /*
> > +     * OS is allowed to set BAR beyond its addressable
> > +     * bits. For example, 32 bit OS can set 64bit bar
> > +     * to >4G. Check it. TODO: we might need to support
> > +     * it in the future for e.g. PAE.
> > +     */
> > +    if (last_addr >= TARGET_PHYS_ADDR_MAX) {
> > +        return PCI_BAR_UNMAPPED;
> > +    }
> > +
> > +    return new_addr;
> > +}
> > +
> >  static void pci_update_mappings(PCIDevice *d)
> >  {
> >      PCIIORegion *r;
> > -    int cmd, i;
> > -    pcibus_t last_addr, new_addr;
> > -    pcibus_t filtered_size;
> > +    int i;
> > +    pcibus_t new_addr, filtered_size;
> >  
> > -    cmd = pci_get_word(d->config + PCI_COMMAND);
> >      for(i = 0; i < PCI_NUM_REGIONS; i++) {
> >          r = &d->io_regions[i];
> >  
> > @@ -735,59 +798,7 @@ static void pci_update_mappings(PCIDevice *d)
> >          if (!r->size)
> >              continue;
> >  
> > -        if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
> > -            if (cmd & PCI_COMMAND_IO) {
> > -                new_addr = pci_get_long(d->config + pci_bar(d, i));
> > -                new_addr = new_addr & ~(r->size - 1);
> > -                last_addr = new_addr + r->size - 1;
> > -                /* NOTE: we have only 64K ioports on PC */
> > -                if (last_addr <= new_addr || new_addr == 0 ||
> > -                    last_addr >= 0x10000) {
> > -                    new_addr = PCI_BAR_UNMAPPED;
> > -                }
> > -            } else {
> > -                new_addr = PCI_BAR_UNMAPPED;
> > -            }
> > -        } else {
> > -            if (cmd & PCI_COMMAND_MEMORY) {
> > -                if (r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
> > -                    new_addr = pci_get_quad(d->config + pci_bar(d, i));
> > -                } else {
> > -                    new_addr = pci_get_long(d->config + pci_bar(d, i));
> > -                }
> > -                /* the ROM slot has a specific enable bit */
> > -                if (i == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE))
> > -                    goto no_mem_map;
> > -                new_addr = new_addr & ~(r->size - 1);
> > -                last_addr = new_addr + r->size - 1;
> > -                /* NOTE: we do not support wrapping */
> > -                /* XXX: as we cannot support really dynamic
> > -                   mappings, we handle specific values as invalid
> > -                   mappings. */
> > -                if (last_addr <= new_addr || new_addr == 0 ||
> > -                    last_addr == PCI_BAR_UNMAPPED ||
> > -
> > -                    /* Now pcibus_t is 64bit.
> > -                     * Check if 32 bit BAR wrap around explicitly.
> > -                     * Without this, PC ide doesn't work well.
> > -                     * TODO: remove this work around.
> > -                     */
> > -                    (!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) &&
> > -                     last_addr >= UINT32_MAX) ||
> > -
> > -                    /*
> > -                     * OS is allowed to set BAR beyond its addressable
> > -                     * bits. For example, 32 bit OS can set 64bit bar
> > -                     * to >4G. Check it.
> > -                     */
> > -                    last_addr >= TARGET_PHYS_ADDR_MAX) {
> > -                    new_addr = PCI_BAR_UNMAPPED;
> > -                }
> > -            } else {
> > -            no_mem_map:
> > -                new_addr = PCI_BAR_UNMAPPED;
> > -            }
> > -        }
> > +        new_addr = pci_bar_address(d, i, r->type, r->size);
> >  
> >          /* bridge filtering */
> >          filtered_size = r->size;
> > 
> 
> -- 
> yamahata

  reply	other threads:[~2009-11-12 13:15 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-11-12  5:58 [Qemu-devel] [PATCH 00/20] PCI express clean up patches Isaku Yamahata
2009-11-12  5:58 ` [Qemu-devel] [PATCH 01/20] pci: fix pci_info_device() Isaku Yamahata
2009-11-12 10:17   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12  5:58 ` [Qemu-devel] [PATCH 02/20] pci: move pci_data_{read, write}() declaration from pci.h to pci_host.h Isaku Yamahata
2009-11-12 10:18   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12 12:44   ` Michael S. Tsirkin
2009-11-12  5:58 ` [Qemu-devel] [PATCH 03/20] pci: simplify pci_data_read(), pcie_mmcfg_data_read() Isaku Yamahata
2009-11-12 11:01   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12 11:15     ` Michael S. Tsirkin
2009-11-12 12:02       ` Michael S. Tsirkin
2009-11-12 12:14         ` Isaku Yamahata
2009-11-12  5:58 ` [Qemu-devel] [PATCH 04/20] pci: remove pci_addr_to_config() by open code Isaku Yamahata
2009-11-12 11:01   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12  5:58 ` [Qemu-devel] [PATCH 05/20] pci: rename pci_addr_to_dev(), pcie_mmcfg_addr_to_dev() Isaku Yamahata
2009-11-12 11:02   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12  5:58 ` [Qemu-devel] [PATCH 06/20] pci: shorten pci_host_{conf, data}_register_xxx function a bit Isaku Yamahata
2009-11-12 10:19   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12  5:58 ` [Qemu-devel] [PATCH 07/20] pci: remove pci_sub_bus() by open coding Isaku Yamahata
2009-11-12 10:45   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12 13:00     ` Isaku Yamahata
2009-11-12  5:58 ` [Qemu-devel] [PATCH 08/20] pci: s/pci_find_host_bus/pci_find_root_bus/g Isaku Yamahata
2009-11-12 10:45   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12  5:58 ` [Qemu-devel] [PATCH 09/20] pci_host: remove unnecessary & 0xff Isaku Yamahata
2009-11-12 10:32   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12  5:58 ` [Qemu-devel] [PATCH 10/20] pci: kill unnecessary included in pci.c Isaku Yamahata
2009-11-12 10:32   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12  5:58 ` [Qemu-devel] [PATCH 11/20] pci: clean up of pci_init_wmask() Isaku Yamahata
2009-11-12 10:18   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12  5:58 ` [Qemu-devel] [PATCH 12/20] pci: remove some unnecessary comment in pci.h Isaku Yamahata
2009-11-12 10:33   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12  5:58 ` [Qemu-devel] [PATCH 13/20] pci: move typedef, PCIHostState, PCIExpressHost to qemu-common.h Isaku Yamahata
2009-11-12 10:33   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12  5:58 ` [Qemu-devel] [PATCH 14/20] pci: remove unused constants Isaku Yamahata
2009-11-12 10:33   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12  5:58 ` [Qemu-devel] [PATCH 15/20] pci: clean up of pci_update_mappings() Isaku Yamahata
2009-11-12 10:34   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12  5:58 ` [Qemu-devel] [PATCH 16/20] pci: kill goto in pci_update_mappings() Isaku Yamahata
2009-11-12 12:06   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12 13:12     ` Isaku Yamahata
2009-11-12 13:13       ` Michael S. Tsirkin [this message]
2009-11-12 13:29       ` Michael S. Tsirkin
2009-11-12  5:58 ` [Qemu-devel] [PATCH 17/20] pci: remove magic number, 256 in pci.c Isaku Yamahata
2009-11-12 10:34   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12  5:58 ` [Qemu-devel] [PATCH 18/20] pci: fix pci_config_get_io_base() Isaku Yamahata
2009-11-12 10:36   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12  5:58 ` [Qemu-devel] [PATCH 19/20] pci: pci bridge related clean up Isaku Yamahata
2009-11-12 10:47   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12  5:58 ` [Qemu-devel] [PATCH 20/20] pci: remove goto in pci_bridge_filter() Isaku Yamahata
2009-11-12 12:08   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12 13:13     ` Isaku Yamahata
2009-11-12 12:58 ` [Qemu-devel] Re: [PATCH 00/20] PCI express clean up patches Michael S. Tsirkin

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=20091112131308.GD11123@redhat.com \
    --to=mst@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=yamahata@valinux.co.jp \
    /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.