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

Re: [PATCH v9 09/16] vpci/header: program p2m with guest BAR view


  • To: Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>
  • From: Roger Pau Monné <roger.pau@xxxxxxxxxx>
  • Date: Thu, 21 Sep 2023 12:34:54 +0200
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=citrix.com; dmarc=pass action=none header.from=citrix.com; dkim=pass header.d=citrix.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=UN/7qGC5S1MpI+QDA5ODcJ6g1SSckQpPQYBpfiLkuaE=; b=WsOXmHmQe7HqkHKHFoqipY+SeOjW26aMpCiaMwOMlEr63IfC1raCd0X4oSrmMWRhPs7OMtE0Uuuherse+YlYbwykqj4tehccemYam4H8bY8Grcnk6y5CGZ8seIv/UMxUuxldPf+qMS32plo78GPMhYE7LQk5RpKn6oPtsjPttTFGJ7Oa4XSPGEh0z7BMOLVSs2i4fSXQsO235ffgH+t1i1vw5L4tFdzROyKTizimHOevKRZXTFpvn5gFdHGWiJXLisrrEPAa3DL0lnTXKG0VZBpka5GRJoyHKAtWzEJ/J+xdKgewFg04RITIMxb6VwqomNcalsid+1Js7u7KU3HNXg==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=UyW6Hw7YqxsQJoddVNBaEQDrBXXyElK8BbiEdR1yNDMPDzX0IKX2oDDAQzxMrFFX006Nv3C4VCHdFOoBvbEsIRd/EnEqOrpNWtcL00ApTrnp5AtWKpDfkySKDGosZRif8y1uxv+4mvCQDVnmavnjIjYCFZ5NAyutFgfSU6kbKm7OaNEHwGvOdIXXJVAt/EJBh8JYWnWFg3gc6Hxun2Hhgd7zcXVIOoKK7ZGlweoLtHe1V4dEnB9SVmtfbEv4C/NgZTxevNc1RVHW+SGuZ7gtvUciZif4K3e7IHTdFZJYO6k/SijiOgYBS8guQVzuE/CLzMyI9EXAvji3gRtA2Nh0uQ==
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=citrix.com;
  • Cc: "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>, Stewart Hildebrand <stewart.hildebrand@xxxxxxx>, Oleksandr Andrushchenko <Oleksandr_Andrushchenko@xxxxxxxx>
  • Delivery-date: Thu, 21 Sep 2023 10:35:19 +0000
  • Ironport-data: A9a23:IfDzoqLEbgO48k4IFE+RCpQlxSXFcZb7ZxGr2PjKsXjdYENS1zUGz zAXDz3SOqqDZWX8edogbo2190lQvZ/dzoJgHQFlqX01Q3x08seUXt7xwmUcnc+xBpaaEB84t ZV2hv3odp1coqr0/0/1WlTZhSAhk/nOHvylULKs1hlZHWdMUD0mhQ9oh9k3i4tphcnRKw6Ws Jb5rta31GWNglaYCUpKrfrYwP9TlK6q4mhA7wZnPaojUGL2zBH5MrpOfcldEFOgKmVkNrbSb /rOyri/4lTY838FYj9yuu+mGqGiaue60Tmm0hK6aYD76vRxjnVaPpIAHOgdcS9qZwChxLid/ jnvWauYEm/FNoWU8AgUvoIx/ytWZcWq85efSZSzXFD6I+QrvBIAzt03ZHzaM7H09c5SAE5lz dpFIQs1dzKmvr+V2raJCbFV05FLwMnDZOvzu1lG5BSAV7MKZM6GRK/Ho9hFwD03m8ZCW+7EY NYUYiZuaxKGZABTPlAQC9Q1m+LAanvXKmUE7g7K4/dmpTGMlWSd05C0WDbRUsaNSshP2F6Ru 0rN/njjAwFcP9uaodaA2iv23bCfxHumAOr+EpWc5+9togOP61UIEUw5D1ef/KKypW+xDoc3x 0s8v3BGQbIJ3HKsSt7xThipukmutxQXW8dTO+Ai4QTLwa3Riy6JC25BQjNfZdgOsM4tWSdsx lKPh8nuBzFkrPuSU3313qyIoCy7IzRTLW4GaSIOVwID7/HqpY11hRXKJv5EFKO2ldTzFSvH6 jaGtjUlh74TgMgI0I225VnCxTmro/D0ohUd4wzWWiep611/bYv8PYiwswGEtLBHMZqTSUSHs D4cgc+C4esSDJaL0iuQXOEKG7Lv7PGAWNHBvWNS81Aa32zF0xaekUp4ulmS+G8B3h44RALU
  • Ironport-hdrordr: A9a23:+CsDEqF/1GUxTlfnpLqELMeALOsnbusQ8zAXPiBKJCC9E/bo8v xG+c5w6faaslkssR0b9+xoW5PwI080l6QU3WB5B97LMDUO0FHCEGgI1/qA/9SPIUzDHu4279 YbT0B9YueAcGSTW6zBkXWF+9VL+qj5zEix792uq0uE1WtRGtldBwESMHf9LmRGADNoKLAeD5 Sm6s9Ot1ObCA8qhpTSPAhiYwDbzee77a7bXQ==
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

On Tue, Aug 29, 2023 at 11:19:44PM +0000, Volodymyr Babchuk wrote:
> From: Oleksandr Andrushchenko <oleksandr_andrushchenko@xxxxxxxx>
> 
> Take into account guest's BAR view and program its p2m accordingly:
> gfn is guest's view of the BAR and mfn is the physical BAR value.
> This way hardware domain sees physical BAR values and guest sees
> emulated ones.
> 
> Hardware domain continues getting the BARs identity mapped, while for
> domUs the BARs are mapped at the requested guest address without
> modifying the BAR address in the device PCI config space.
> 
> Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@xxxxxxxx>
> Signed-off-by: Volodymyr Babchuk <volodymyr_babchuk@xxxxxxxx>
> ---
> Since v9:
> - Extended the commit message
> - Use bar->guest_addr in modify_bars
> - Extended printk error message in map_range
> - Moved map_data initialization so .bar can be initialized during declaration
> Since v5:
> - remove debug print in map_range callback
> - remove "identity" from the debug print
> Since v4:
> - moved start_{gfn|mfn} calculation into map_range
> - pass vpci_bar in the map_data instead of start_{gfn|mfn}
> - s/guest_addr/guest_reg
> Since v3:
> - updated comment (Roger)
> - removed gfn_add(map->start_gfn, rc); which is wrong
> - use v->domain instead of v->vpci.pdev->domain
> - removed odd e.g. in comment
> - s/d%d/%pd in altered code
> - use gdprintk for map/unmap logs
> Since v2:
> - improve readability for data.start_gfn and restructure ?: construct
> Since v1:
>  - s/MSI/MSI-X in comments
> ---
>  xen/drivers/vpci/header.c | 52 ++++++++++++++++++++++++++++-----------
>  1 file changed, 38 insertions(+), 14 deletions(-)
> 
> diff --git a/xen/drivers/vpci/header.c b/xen/drivers/vpci/header.c
> index 3cc6a96849..1e82217200 100644
> --- a/xen/drivers/vpci/header.c
> +++ b/xen/drivers/vpci/header.c
> @@ -33,6 +33,7 @@
>  
>  struct map_data {
>      struct domain *d;
> +    const struct vpci_bar *bar;
>      bool map;
>  };
>  
> @@ -44,6 +45,12 @@ static int cf_check map_range(
>  
>      for ( ; ; )
>      {
> +        /* Start address of the BAR as seen by the guest. */
> +        gfn_t start_gfn = _gfn(PFN_DOWN(is_hardware_domain(map->d)
> +                                        ? map->bar->addr
> +                                        : map->bar->guest_addr));
> +        /* Physical start address of the BAR. */
> +        mfn_t start_mfn = _mfn(PFN_DOWN(map->bar->addr));

Both of those should be declared outside of the loop, as there's no
need to (re)calculate them at each iteration.

Also start_gfn likely wants to be unsigned long?  All the usages of it
in the patch convert it to integer by using gfn_x().

>          unsigned long size = e - s + 1;
>  
>          if ( !iomem_access_permitted(map->d, s, e) )
> @@ -63,6 +70,13 @@ static int cf_check map_range(
>              return rc;
>          }
>  
> +        /*
> +         * Ranges to be mapped don't always start at the BAR start address, 
> as
> +         * there can be holes or partially consumed ranges. Account for the
> +         * offset of the current address from the BAR start.
> +         */
> +        start_mfn = mfn_add(start_mfn, s - gfn_x(start_gfn));

This should then be a local loop variable with a different name.

> +
>          /*
>           * ARM TODOs:
>           * - On ARM whether the memory is prefetchable or not should be 
> passed
> @@ -72,8 +86,8 @@ static int cf_check map_range(
>           * - {un}map_mmio_regions doesn't support preemption.
>           */
>  
> -        rc = map->map ? map_mmio_regions(map->d, _gfn(s), size, _mfn(s))
> -                      : unmap_mmio_regions(map->d, _gfn(s), size, _mfn(s));
> +        rc = map->map ? map_mmio_regions(map->d, _gfn(s), size, start_mfn)
> +                      : unmap_mmio_regions(map->d, _gfn(s), size, start_mfn);
>          if ( rc == 0 )
>          {
>              *c += size;
> @@ -82,8 +96,9 @@ static int cf_check map_range(
>          if ( rc < 0 )
>          {
>              printk(XENLOG_G_WARNING
> -                   "Failed to identity %smap [%lx, %lx] for d%d: %d\n",
> -                   map->map ? "" : "un", s, e, map->d->domain_id, rc);
> +                   "Failed to %smap [%lx (%lx), %lx (%lx)] for %pd: %d\n",

I think we would usually write such mapping messages as:

[start gfn, end gfn] -> [start mfn, end mfn]

So:

"Failed to %smap [%lx, %lx] -> [%lx, %lx] for %pd: %d\n"

> +                   map->map ? "" : "un", s,  mfn_x(start_mfn), e,
> +                   mfn_x(start_mfn) + size, map->d, rc);
>              break;
>          }
>          ASSERT(rc < size);
> @@ -162,10 +177,6 @@ static void modify_decoding(const struct pci_dev *pdev, 
> uint16_t cmd,
>  bool vpci_process_pending(struct vcpu *v)
>  {
>      struct pci_dev *pdev = v->vpci.pdev;
> -    struct map_data data = {
> -        .d = v->domain,
> -        .map = v->vpci.cmd & PCI_COMMAND_MEMORY,
> -    };
>      struct vpci_header *header = NULL;
>      unsigned int i;
>  
> @@ -177,6 +188,11 @@ bool vpci_process_pending(struct vcpu *v)
>      for ( i = 0; i < ARRAY_SIZE(header->bars); i++ )
>      {
>          struct vpci_bar *bar = &header->bars[i];
> +        struct map_data data = {
> +            .d = v->domain,
> +            .map = v->vpci.cmd & PCI_COMMAND_MEMORY,
> +            .bar = bar,
> +        };
>          int rc;
>  
>          if ( rangeset_is_empty(bar->mem) )
> @@ -229,7 +245,6 @@ bool vpci_process_pending(struct vcpu *v)
>  static int __init apply_map(struct domain *d, const struct pci_dev *pdev,
>                              uint16_t cmd)
>  {
> -    struct map_data data = { .d = d, .map = true };
>      struct vpci_header *header = &pdev->vpci->header;
>      int rc = 0;
>      unsigned int i;
> @@ -239,6 +254,7 @@ static int __init apply_map(struct domain *d, const 
> struct pci_dev *pdev,
>      for ( i = 0; i < ARRAY_SIZE(header->bars); i++ )
>      {
>          struct vpci_bar *bar = &header->bars[i];
> +        struct map_data data = { .d = d, .map = true, .bar = bar };
>  
>          if ( rangeset_is_empty(bar->mem) )
>              continue;
> @@ -306,12 +322,18 @@ static int modify_bars(const struct pci_dev *pdev, 
> uint16_t cmd, bool rom_only)
>       * First fill the rangesets with the BAR of this device or with the ROM
>       * BAR only, depending on whether the guest is toggling the memory decode
>       * bit of the command register, or the enable bit of the ROM BAR 
> register.
> +     *
> +     * For non-hardware domain we use guest physical addresses.
>       */
>      for ( i = 0; i < ARRAY_SIZE(header->bars); i++ )
>      {
>          struct vpci_bar *bar = &header->bars[i];
>          unsigned long start = PFN_DOWN(bar->addr);
>          unsigned long end = PFN_DOWN(bar->addr + bar->size - 1);
> +        unsigned long start_guest = 
> PFN_DOWN(is_hardware_domain(pdev->domain) ?
> +                                             bar->addr : bar->guest_addr);
> +        unsigned long end_guest = PFN_DOWN((is_hardware_domain(pdev->domain) 
> ?
> +                                  bar->addr : bar->guest_addr) + bar->size - 
> 1);
>  
>          if ( !bar->mem )
>              continue;
> @@ -331,11 +353,11 @@ static int modify_bars(const struct pci_dev *pdev, 
> uint16_t cmd, bool rom_only)
>              continue;
>          }
>  
> -        rc = rangeset_add_range(bar->mem, start, end);
> +        rc = rangeset_add_range(bar->mem, start_guest, end_guest);
>          if ( rc )
>          {
>              printk(XENLOG_G_WARNING "Failed to add [%lx, %lx]: %d\n",
> -                   start, end, rc);
> +                   start_guest, end_guest, rc);
>              return rc;
>          }
>  
> @@ -352,7 +374,7 @@ static int modify_bars(const struct pci_dev *pdev, 
> uint16_t cmd, bool rom_only)
>              {
>                  gprintk(XENLOG_WARNING,
>                         "%pp: failed to remove overlapping range [%lx, %lx]: 
> %d\n",
> -                        &pdev->sbdf, start, end, rc);
> +                        &pdev->sbdf, start_guest, end_guest, rc);
>                  return rc;
>              }
>          }

I think you are missing a change to adjust vmsix_table_base() to also
return the MSI-X table position in guest address space for domUs, or
else the MSI-X overlapping range checks for domUs are wrong.

Thanks, Roger.



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.