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

RE: [PATCH v7 08/11] IOMMU/VT-d: wire common device reserved memory API


  • To: "Marczykowski, Marek" <marmarek@xxxxxxxxxxxxxxxxxxxxxx>, "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: "Tian, Kevin" <kevin.tian@xxxxxxxxx>
  • Date: Fri, 23 Sep 2022 07:21:04 +0000
  • Accept-language: en-US
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=intel.com; dmarc=pass action=none header.from=intel.com; dkim=pass header.d=intel.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=Bj80AYRRNEOWdMv2f+ZnFW1gv/B54IFr4mvLYGnfNNo=; b=epLPZvFYAJ4b2oufY9PkwYrXl/7+1/xwdq1x8BEq5Jc6Lxn6U39dl6+v4GEfI1ln7y1pVRrZECm2dMIpxjXK5UD4HAbChgwGvpV7CfcwZQVUT01560EOQ7wyYiH3ykxOBooHKPi3PBfgVxKBq3Sys8U95FC5ICktoYAC3Ed+wkwcg/k/TtwdtaV6UG3IOclExHVX3cd/i+XXpgrk99H4IP88F5i25Tle9IjXFMcav4kvyOjJR6/CapBM7DaY6Jgm2ADpc76nFnBJfGdPXw+ffQNeXoSnkpDO/YIR2xSwlzKiPvyjw53siEn/U8WsOywTnlcJbhlQp16TdYeBiWFhIA==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=KwKHoO2Mlt3yCb5nVvkb6F+PsfT+rQtXotXDEnKa3AbTQhTrB3tZbQC0Ntc8kVz03q0PZ8HkLI9qFfR+Em/bq/KavKPoOjeRS5/UO1OF6XZLkZiqYss6/eRyhOyYfFF1o18hnbdeZxfo2Vwtc2BNX3xPqpQp/7FfV3m2d3QmRW/1JSQO0RiFtt/eOeSHdRinv9AzsCSTlK9wJRJ8ucRKfwwXN5uTrdqTDaaO6U/7tZq8RIjZGZK1Z3TmTkRoE7LA4VEcNq29QWay/7vwKsPUzL+O8RfPiRclT71U6YASTeBE7j7rfbJJ+YBpM4S9vW2rVFLUhrGp/qpv+uZiAlEV1g==
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=intel.com;
  • Cc: "Marczykowski, Marek" <marmarek@xxxxxxxxxxxxxxxxxxxxxx>
  • Delivery-date: Fri, 23 Sep 2022 07:21:43 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
  • Thread-index: AQHYykB/Pv1Ek/NIGEWzHFZweNfBzq3so7bg
  • Thread-topic: [PATCH v7 08/11] IOMMU/VT-d: wire common device reserved memory API

> From: Marek Marczykowski-Górecki
> Sent: Saturday, September 17, 2022 10:51 AM
> 
> Re-use rmrr= parameter handling code to handle common device reserved
> memory.
> 
> Signed-off-by: Marek Marczykowski-Górecki
> <marmarek@xxxxxxxxxxxxxxxxxxxxxx>
> ---
> Changes in v3:
> - make MAX_USER_RMRR_PAGES applicable only to user-configured RMRR
> ---
>  xen/drivers/passthrough/vtd/dmar.c | 201 +++++++++++++++++-------------
>  1 file changed, 119 insertions(+), 82 deletions(-)
> 
> diff --git a/xen/drivers/passthrough/vtd/dmar.c
> b/xen/drivers/passthrough/vtd/dmar.c
> index 367304c8739c..3df5f6b69719 100644
> --- a/xen/drivers/passthrough/vtd/dmar.c
> +++ b/xen/drivers/passthrough/vtd/dmar.c
> @@ -861,111 +861,139 @@ static struct user_rmrr __initdata
> user_rmrrs[MAX_USER_RMRR];
> 
>  /* Macro for RMRR inclusive range formatting. */
>  #define ERMRRU_FMT "[%lx-%lx]"
> -#define ERMRRU_ARG(eru) eru.base_pfn, eru.end_pfn
> +#define ERMRRU_ARG base_pfn, end_pfn
> +
> +static int __init add_one_user_rmrr(unsigned long base_pfn,
> +                                    unsigned long end_pfn,
> +                                    unsigned int dev_count,
> +                                    uint32_t *sbdf);

Just move the function here then no need of a declaration.

> 
>  static int __init add_user_rmrr(void)
>  {
> +    unsigned int i;
> +    int ret;
> +
> +    for ( i = 0; i < nr_rmrr; i++ )
> +    {
> +        ret = add_one_user_rmrr(user_rmrrs[i].base_pfn,
> +                                user_rmrrs[i].end_pfn,
> +                                user_rmrrs[i].dev_count,
> +                                user_rmrrs[i].sbdf);
> +        if ( ret < 0 )
> +            return ret;
> +    }
> +    return 0;
> +}
> +
> +/* Returns 1 on success, 0 when ignoring and < 0 on error. */

I'm not sure the point of 'ignoring'. If user specifies a wrong RMRR
range (overlap, mfn invalid, etc.) just return an error similar to
-ENOMEM. Ignoring a user-specified range implies that something
would potentially get broken hence better fail it early.

> +static int __init add_one_user_rmrr(unsigned long base_pfn,
> +                                    unsigned long end_pfn,
> +                                    unsigned int dev_count,
> +                                    uint32_t *sbdf)
> +{
>      struct acpi_rmrr_unit *rmrr, *rmrru;
> -    unsigned int idx, seg, i;
> -    unsigned long base, end;
> +    unsigned int idx, seg;
> +    unsigned long base_iter;
>      bool overlap;
> 
> -    for ( i = 0; i < nr_rmrr; i++ )
> +    if ( iommu_verbose )
> +        printk(XENLOG_DEBUG VTDPREFIX
> +               "Adding RMRR for %d device ([0]: %#x) range "ERMRRU_FMT"\n",
> +               dev_count, sbdf[0], ERMRRU_ARG);
> +
> +    if ( base_pfn > end_pfn )
>      {
> -        base = user_rmrrs[i].base_pfn;
> -        end = user_rmrrs[i].end_pfn;
> +        printk(XENLOG_ERR VTDPREFIX
> +               "Invalid RMRR Range "ERMRRU_FMT"\n",
> +               ERMRRU_ARG);
> +        return 0;
> +    }
> 
> -        if ( base > end )
> +    overlap = false;
> +    list_for_each_entry(rmrru, &acpi_rmrr_units, list)
> +    {
> +        if ( pfn_to_paddr(base_pfn) <= rmrru->end_address &&
> +             rmrru->base_address <= pfn_to_paddr(end_pfn) )
>          {
>              printk(XENLOG_ERR VTDPREFIX
> -                   "Invalid RMRR Range "ERMRRU_FMT"\n",
> -                   ERMRRU_ARG(user_rmrrs[i]));
> -            continue;
> +                   "Overlapping RMRRs: "ERMRRU_FMT" and [%lx-%lx]\n",
> +                   ERMRRU_ARG,
> +                   paddr_to_pfn(rmrru->base_address),
> +                   paddr_to_pfn(rmrru->end_address));
> +            overlap = true;
> +            break;
>          }
> +    }
> +    /* Don't add overlapping RMRR. */
> +    if ( overlap )
> +        return 0;
> 
> -        if ( (end - base) >= MAX_USER_RMRR_PAGES )
> +    base_iter = base_pfn;
> +    do
> +    {
> +        if ( !mfn_valid(_mfn(base_iter)) )
>          {
>              printk(XENLOG_ERR VTDPREFIX
> -                   "RMRR range "ERMRRU_FMT" exceeds "\
> -                   __stringify(MAX_USER_RMRR_PAGES)" pages\n",
> -                   ERMRRU_ARG(user_rmrrs[i]));
> -            continue;
> +                   "Invalid pfn in RMRR range "ERMRRU_FMT"\n",
> +                   ERMRRU_ARG);
> +            break;
>          }
> +    } while ( base_iter++ < end_pfn );
> 
> -        overlap = false;
> -        list_for_each_entry(rmrru, &acpi_rmrr_units, list)
> -        {
> -            if ( pfn_to_paddr(base) <= rmrru->end_address &&
> -                 rmrru->base_address <= pfn_to_paddr(end) )
> -            {
> -                printk(XENLOG_ERR VTDPREFIX
> -                       "Overlapping RMRRs: "ERMRRU_FMT" and [%lx-%lx]\n",
> -                       ERMRRU_ARG(user_rmrrs[i]),
> -                       paddr_to_pfn(rmrru->base_address),
> -                       paddr_to_pfn(rmrru->end_address));
> -                overlap = true;
> -                break;
> -            }
> -        }
> -        /* Don't add overlapping RMRR. */
> -        if ( overlap )
> -            continue;
> +    /* Invalid pfn in range as the loop ended before end_pfn was reached. */
> +    if ( base_iter <= end_pfn )
> +        return 0;
> 
> -        do
> -        {
> -            if ( !mfn_valid(_mfn(base)) )
> -            {
> -                printk(XENLOG_ERR VTDPREFIX
> -                       "Invalid pfn in RMRR range "ERMRRU_FMT"\n",
> -                       ERMRRU_ARG(user_rmrrs[i]));
> -                break;
> -            }
> -        } while ( base++ < end );
> +    rmrr = xzalloc(struct acpi_rmrr_unit);
> +    if ( !rmrr )
> +        return -ENOMEM;
> 
> -        /* Invalid pfn in range as the loop ended before end_pfn was reached.
> */
> -        if ( base <= end )
> -            continue;
> +    rmrr->scope.devices = xmalloc_array(u16, dev_count);
> +    if ( !rmrr->scope.devices )
> +    {
> +        xfree(rmrr);
> +        return -ENOMEM;
> +    }
> 
> -        rmrr = xzalloc(struct acpi_rmrr_unit);
> -        if ( !rmrr )
> -            return -ENOMEM;
> +    seg = 0;
> +    for ( idx = 0; idx < dev_count; idx++ )
> +    {
> +        rmrr->scope.devices[idx] = sbdf[idx];
> +        seg |= PCI_SEG(sbdf[idx]);
> +    }
> +    if ( seg != PCI_SEG(sbdf[0]) )
> +    {
> +        printk(XENLOG_ERR VTDPREFIX
> +               "Segments are not equal for RMRR range "ERMRRU_FMT"\n",
> +               ERMRRU_ARG);
> +        scope_devices_free(&rmrr->scope);
> +        xfree(rmrr);
> +        return 0;
> +    }
> 
> -        rmrr->scope.devices = xmalloc_array(u16, user_rmrrs[i].dev_count);
> -        if ( !rmrr->scope.devices )
> -        {
> -            xfree(rmrr);
> -            return -ENOMEM;
> -        }
> +    rmrr->segment = seg;
> +    rmrr->base_address = pfn_to_paddr(base_pfn);
> +    /* Align the end_address to the end of the page */
> +    rmrr->end_address = pfn_to_paddr(end_pfn) | ~PAGE_MASK;
> +    rmrr->scope.devices_cnt = dev_count;
> 
> -        seg = 0;
> -        for ( idx = 0; idx < user_rmrrs[i].dev_count; idx++ )
> -        {
> -            rmrr->scope.devices[idx] = user_rmrrs[i].sbdf[idx];
> -            seg |= PCI_SEG(user_rmrrs[i].sbdf[idx]);
> -        }
> -        if ( seg != PCI_SEG(user_rmrrs[i].sbdf[0]) )
> -        {
> -            printk(XENLOG_ERR VTDPREFIX
> -                   "Segments are not equal for RMRR range "ERMRRU_FMT"\n",
> -                   ERMRRU_ARG(user_rmrrs[i]));
> -            scope_devices_free(&rmrr->scope);
> -            xfree(rmrr);
> -            continue;
> -        }
> +    if ( register_one_rmrr(rmrr) )
> +        printk(XENLOG_ERR VTDPREFIX
> +               "Could not register RMMR range "ERMRRU_FMT"\n",
> +               ERMRRU_ARG);
> 
> -        rmrr->segment = seg;
> -        rmrr->base_address = pfn_to_paddr(user_rmrrs[i].base_pfn);
> -        /* Align the end_address to the end of the page */
> -        rmrr->end_address = pfn_to_paddr(user_rmrrs[i].end_pfn) |
> ~PAGE_MASK;
> -        rmrr->scope.devices_cnt = user_rmrrs[i].dev_count;
> +    return 1;
> +}
> 
> -        if ( register_one_rmrr(rmrr) )
> -            printk(XENLOG_ERR VTDPREFIX
> -                   "Could not register RMMR range "ERMRRU_FMT"\n",
> -                   ERMRRU_ARG(user_rmrrs[i]));
> -    }
> +static int __init cf_check add_one_extra_rmrr(xen_pfn_t start, xen_ulong_t
> nr, u32 id, void *ctxt)
> +{
> +    u32 sbdf_array[] = { id };
> +    return add_one_user_rmrr(start, start+nr, 1, sbdf_array);
> +}
> 
> -    return 0;
> +static int __init add_extra_rmrr(void)
> +{
> +    return iommu_get_extra_reserved_device_memory(add_one_extra_rmrr,
> NULL);
>  }
> 
>  #include <asm/tboot.h>
> @@ -1010,7 +1038,7 @@ int __init acpi_dmar_init(void)
>      {
>          iommu_init_ops = &intel_iommu_init_ops;
> 
> -        return add_user_rmrr();
> +        return add_user_rmrr() || add_extra_rmrr();
>      }
> 
>      return ret;
> @@ -1108,6 +1136,15 @@ static int __init cf_check parse_rmrr_param(const
> char *str)
>          else
>              end = start;
> 
> +        if ( (end - start) >= MAX_USER_RMRR_PAGES )
> +        {
> +            printk(XENLOG_ERR VTDPREFIX
> +                    "RMRR range "ERMRRU_FMT" exceeds "\
> +                    __stringify(MAX_USER_RMRR_PAGES)" pages\n",
> +                    start, end);
> +            return -E2BIG;
> +        }
> +

why moving this error check out of add_one_user_rmrr()? I didn't
get why it's special from other checks there, e.g. having base>end...

>          user_rmrrs[nr_rmrr].base_pfn = start;
>          user_rmrrs[nr_rmrr].end_pfn = end;
> 
> --
> git-series 0.9.1


 


Rackspace

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