qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] Re: [PATCH V6 17/32] pci: 64bit bar support.


From: Michael S. Tsirkin
Subject: [Qemu-devel] Re: [PATCH V6 17/32] pci: 64bit bar support.
Date: Sun, 1 Nov 2009 18:07:30 +0200
User-agent: Mutt/1.5.19 (2009-01-05)

On Fri, Oct 30, 2009 at 09:21:11PM +0900, Isaku Yamahata wrote:
> implemented pci 64bit bar support.
> The tricky bit is pci_update_mapping().
> An OS is allowed to set the BAR such that OS can't address the area
> pointed by BAR. It doesn't make sense, though.

It might make sense. 32 bit guest can address more than 4G of
physical RAM, e.g. using PAE.
Since I think qemu can not support this if target phys address is 32
bit, we should declare lack of support for 64 bit addressing on these
platforms, by forcing BAR into 32 bit mode, rather than silently failing
to map it.

> In that case, don't map the BAR.
> 
> Signed-off-by: Isaku Yamahata <address@hidden>
> ---
>  hw/pci.c |   35 ++++++++++++++++++++++++++++++-----
>  hw/pci.h |    1 +
>  2 files changed, 31 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index b462bd6..7da3db9 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -484,8 +484,14 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
>          wmask |= PCI_ROM_ADDRESS_ENABLE;
>      }
>      pci_set_long(pci_dev->config + addr, type);
> -    pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
> -    pci_set_long(pci_dev->cmask + addr, 0xffffffff);
> +    if (!(r->type & PCI_BASE_ADDRESS_SPACE_IO) &&
> +        r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
> +        pci_set_quad(pci_dev->wmask + addr, wmask);
> +        pci_set_quad(pci_dev->cmask + addr, ~0ULL);
> +    } else {
> +        pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
> +        pci_set_long(pci_dev->cmask + addr, 0xffffffff);
> +    }
>  }
>  
>  static void pci_update_mappings(PCIDevice *d)
> @@ -513,7 +519,11 @@ static void pci_update_mappings(PCIDevice *d)
>                  }
>              } else {
>                  if (cmd & PCI_COMMAND_MEMORY) {
> -                    new_addr = pci_get_long(d->config + pci_bar(d, i));
> +                    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;
> @@ -531,7 +541,15 @@ static void pci_update_mappings(PCIDevice *d)
>                           * Without this, PC ide doesn't work well.
>                           * TODO: remove this work around.
>                           */
> -                        last_addr >= UINT32_MAX) {
> +                        (!(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 {
> @@ -773,8 +791,15 @@ static void pci_info_device(PCIDevice *d)
>                                 " [0x%04"FMT_PCIBUS"].\n",
>                                 r->addr, r->addr + r->size - 1);
>              } else {
> -                monitor_printf(mon, "32 bit memory at 0x%08"FMT_PCIBUS
> +                const char *type = r->type & PCI_BASE_ADDRESS_MEM_TYPE_64 ?
> +                    "64 bit" : "32 bit";
> +                const char *prefetch =
> +                    r->type & PCI_BASE_ADDRESS_MEM_PREFETCH ?
> +                    " prefetchable" : "";
> +
> +                monitor_printf(mon, "%s%s memory at 0x%08"FMT_PCIBUS
>                                 " [0x%08"FMT_PCIBUS"].\n",
> +                               type, prefetch,
>                                 r->addr, r->addr + r->size - 1);
>              }
>          }
> diff --git a/hw/pci.h b/hw/pci.h
> index 305c030..e83faf5 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -114,6 +114,7 @@ typedef struct PCIIORegion {
>  #define PCI_BASE_ADDRESS_0   0x10    /* 32 bits */
>  #define  PCI_BASE_ADDRESS_SPACE_IO   0x01
>  #define  PCI_BASE_ADDRESS_SPACE_MEMORY       0x00
> +#define  PCI_BASE_ADDRESS_MEM_TYPE_64        0x04    /* 64 bit address */
>  #define  PCI_BASE_ADDRESS_MEM_PREFETCH       0x08    /* prefetchable? */
>  #define PCI_PRIMARY_BUS              0x18    /* Primary bus number */
>  #define PCI_SECONDARY_BUS    0x19    /* Secondary bus number */
> -- 
> 1.6.0.2
> 
> 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]