xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH v10 5/5] iommu: add rmrr Xen command line option for extra rmrrs
@ 2015-07-16 16:00 Elena Ufimtseva
  0 siblings, 0 replies; 8+ messages in thread
From: Elena Ufimtseva @ 2015-07-16 16:00 UTC (permalink / raw)
  To: JBeulich; +Cc: yang.z.zhang, boris.ostrovsky, tim, kevin.tian, xen-devel


----- JBeulich@suse.com wrote:

> >>> On 15.07.15 at 18:15, <elena.ufimtseva@oracle.com> wrote:
> 
> > ----- JBeulich@suse.com wrote:
> > 
> >> >>> On 15.07.15 at 17:27, <elena.ufimtseva@oracle.com> wrote:
> >> > On Wed, Jul 15, 2015 at 08:25:06AM +0100, Jan Beulich wrote:
> >> >> >>> On 14.07.15 at 12:43, <JBeulich@suse.com> wrote:
> >> >> >>>> On 13.07.15 at 20:18, <elena.ufimtseva@oracle.com> wrote:
> >> >> >> +/* Macro for RMRR inclusive range formatting. */
> >> >> >> +#define PRI_RMRR(s,e) "[%lx-%lx]"
> >> >> > 
> >> >> > Just PRI_RMRR (i.e. no parens or parameters) please. And I'm
> >> still
> >> >> > missing a macro to pair the respective arguments - as said
> >> before,
> >> >> > as single format specifier should be accompanied by a single
> >> >> > argument (as visible to the reader at the use sites).
> >> >> 
> >> >> Answering your IRC question here:
> >> >> 
> >> >> #define ERU_FMT "[%lx-%lx]"
> >> >> #define ERU_ARG(eru) eru.base_pfn, eru.end_pfn
> >> >> 
> >> >> (with the acronym "eru" open for improvement).
> >> > 
> >> > Great! Thanks Jan.
> >> > Can ERU be RMRRU? 
> >> 
> >> ERMRRU maybe - I'd like the "extra" to somehow be expressed in
> >> the name.
> > 
> > Does this imply that it can be used for formatting ACPI RMRRs? 
> > Or with some modification perharps?
> 
> If you wanted that (which would be fine with me if it works as
> outlined), then dropping the E or any other remnants of "extra"
> would of course be fine. But I doubt that'll be immediately possible
> considering that RMRRs have their addresses tracked, while for
> extra RMRRs you track MFNs (i.e. you'd first need to convert
> one of them).

Thanks Jan, I will think what is better.

> 
> Jan

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v10 5/5] iommu: add rmrr Xen command line option for extra rmrrs
  2015-07-15 16:15 Elena Ufimtseva
@ 2015-07-16  8:02 ` Jan Beulich
  0 siblings, 0 replies; 8+ messages in thread
From: Jan Beulich @ 2015-07-16  8:02 UTC (permalink / raw)
  To: Elena Ufimtseva; +Cc: yang.z.zhang, kevin.tian, tim, boris.ostrovsky, xen-devel

>>> On 15.07.15 at 18:15, <elena.ufimtseva@oracle.com> wrote:

> ----- JBeulich@suse.com wrote:
> 
>> >>> On 15.07.15 at 17:27, <elena.ufimtseva@oracle.com> wrote:
>> > On Wed, Jul 15, 2015 at 08:25:06AM +0100, Jan Beulich wrote:
>> >> >>> On 14.07.15 at 12:43, <JBeulich@suse.com> wrote:
>> >> >>>> On 13.07.15 at 20:18, <elena.ufimtseva@oracle.com> wrote:
>> >> >> +/* Macro for RMRR inclusive range formatting. */
>> >> >> +#define PRI_RMRR(s,e) "[%lx-%lx]"
>> >> > 
>> >> > Just PRI_RMRR (i.e. no parens or parameters) please. And I'm
>> still
>> >> > missing a macro to pair the respective arguments - as said
>> before,
>> >> > as single format specifier should be accompanied by a single
>> >> > argument (as visible to the reader at the use sites).
>> >> 
>> >> Answering your IRC question here:
>> >> 
>> >> #define ERU_FMT "[%lx-%lx]"
>> >> #define ERU_ARG(eru) eru.base_pfn, eru.end_pfn
>> >> 
>> >> (with the acronym "eru" open for improvement).
>> > 
>> > Great! Thanks Jan.
>> > Can ERU be RMRRU? 
>> 
>> ERMRRU maybe - I'd like the "extra" to somehow be expressed in
>> the name.
> 
> Does this imply that it can be used for formatting ACPI RMRRs? 
> Or with some modification perharps?

If you wanted that (which would be fine with me if it works as
outlined), then dropping the E or any other remnants of "extra"
would of course be fine. But I doubt that'll be immediately possible
considering that RMRRs have their addresses tracked, while for
extra RMRRs you track MFNs (i.e. you'd first need to convert
one of them).

Jan

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v10 5/5] iommu: add rmrr Xen command line option for extra rmrrs
@ 2015-07-15 16:15 Elena Ufimtseva
  2015-07-16  8:02 ` Jan Beulich
  0 siblings, 1 reply; 8+ messages in thread
From: Elena Ufimtseva @ 2015-07-15 16:15 UTC (permalink / raw)
  To: JBeulich; +Cc: yang.z.zhang, boris.ostrovsky, tim, kevin.tian, xen-devel


----- JBeulich@suse.com wrote:

> >>> On 15.07.15 at 17:27, <elena.ufimtseva@oracle.com> wrote:
> > On Wed, Jul 15, 2015 at 08:25:06AM +0100, Jan Beulich wrote:
> >> >>> On 14.07.15 at 12:43, <JBeulich@suse.com> wrote:
> >> >>>> On 13.07.15 at 20:18, <elena.ufimtseva@oracle.com> wrote:
> >> >> +/* Macro for RMRR inclusive range formatting. */
> >> >> +#define PRI_RMRR(s,e) "[%lx-%lx]"
> >> > 
> >> > Just PRI_RMRR (i.e. no parens or parameters) please. And I'm
> still
> >> > missing a macro to pair the respective arguments - as said
> before,
> >> > as single format specifier should be accompanied by a single
> >> > argument (as visible to the reader at the use sites).
> >> 
> >> Answering your IRC question here:
> >> 
> >> #define ERU_FMT "[%lx-%lx]"
> >> #define ERU_ARG(eru) eru.base_pfn, eru.end_pfn
> >> 
> >> (with the acronym "eru" open for improvement).
> > 
> > Great! Thanks Jan.
> > Can ERU be RMRRU? 
> 
> ERMRRU maybe - I'd like the "extra" to somehow be expressed in
> the name.

Does this imply that it can be used for formatting ACPI RMRRs? 
Or with some modification perharps?
> 
> Jan

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v10 5/5] iommu: add rmrr Xen command line option for extra rmrrs
  2015-07-15 15:27       ` Elena Ufimtseva
@ 2015-07-15 16:08         ` Jan Beulich
  0 siblings, 0 replies; 8+ messages in thread
From: Jan Beulich @ 2015-07-15 16:08 UTC (permalink / raw)
  To: Elena Ufimtseva; +Cc: yang.z.zhang, kevin.tian, tim, boris.ostrovsky, xen-devel

>>> On 15.07.15 at 17:27, <elena.ufimtseva@oracle.com> wrote:
> On Wed, Jul 15, 2015 at 08:25:06AM +0100, Jan Beulich wrote:
>> >>> On 14.07.15 at 12:43, <JBeulich@suse.com> wrote:
>> >>>> On 13.07.15 at 20:18, <elena.ufimtseva@oracle.com> wrote:
>> >> +/* Macro for RMRR inclusive range formatting. */
>> >> +#define PRI_RMRR(s,e) "[%lx-%lx]"
>> > 
>> > Just PRI_RMRR (i.e. no parens or parameters) please. And I'm still
>> > missing a macro to pair the respective arguments - as said before,
>> > as single format specifier should be accompanied by a single
>> > argument (as visible to the reader at the use sites).
>> 
>> Answering your IRC question here:
>> 
>> #define ERU_FMT "[%lx-%lx]"
>> #define ERU_ARG(eru) eru.base_pfn, eru.end_pfn
>> 
>> (with the acronym "eru" open for improvement).
> 
> Great! Thanks Jan.
> Can ERU be RMRRU? 

ERMRRU maybe - I'd like the "extra" to somehow be expressed in
the name.

Jan

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v10 5/5] iommu: add rmrr Xen command line option for extra rmrrs
  2015-07-15  7:25     ` Jan Beulich
@ 2015-07-15 15:27       ` Elena Ufimtseva
  2015-07-15 16:08         ` Jan Beulich
  0 siblings, 1 reply; 8+ messages in thread
From: Elena Ufimtseva @ 2015-07-15 15:27 UTC (permalink / raw)
  To: Jan Beulich; +Cc: yang.z.zhang, kevin.tian, tim, boris.ostrovsky, xen-devel

On Wed, Jul 15, 2015 at 08:25:06AM +0100, Jan Beulich wrote:
> >>> On 14.07.15 at 12:43, <JBeulich@suse.com> wrote:
> >>>> On 13.07.15 at 20:18, <elena.ufimtseva@oracle.com> wrote:
> >> +/* Macro for RMRR inclusive range formatting. */
> >> +#define PRI_RMRR(s,e) "[%lx-%lx]"
> > 
> > Just PRI_RMRR (i.e. no parens or parameters) please. And I'm still
> > missing a macro to pair the respective arguments - as said before,
> > as single format specifier should be accompanied by a single
> > argument (as visible to the reader at the use sites).
> 
> Answering your IRC question here:
> 
> #define ERU_FMT "[%lx-%lx]"
> #define ERU_ARG(eru) eru.base_pfn, eru.end_pfn
> 
> (with the acronym "eru" open for improvement).

Great! Thanks Jan.
Can ERU be RMRRU? 

> 
> Jan
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v10 5/5] iommu: add rmrr Xen command line option for extra rmrrs
  2015-07-14 10:43   ` Jan Beulich
@ 2015-07-15  7:25     ` Jan Beulich
  2015-07-15 15:27       ` Elena Ufimtseva
  0 siblings, 1 reply; 8+ messages in thread
From: Jan Beulich @ 2015-07-15  7:25 UTC (permalink / raw)
  To: elena.ufimtseva; +Cc: yang.z.zhang, kevin.tian, tim, boris.ostrovsky, xen-devel

>>> On 14.07.15 at 12:43, <JBeulich@suse.com> wrote:
>>>> On 13.07.15 at 20:18, <elena.ufimtseva@oracle.com> wrote:
>> +/* Macro for RMRR inclusive range formatting. */
>> +#define PRI_RMRR(s,e) "[%lx-%lx]"
> 
> Just PRI_RMRR (i.e. no parens or parameters) please. And I'm still
> missing a macro to pair the respective arguments - as said before,
> as single format specifier should be accompanied by a single
> argument (as visible to the reader at the use sites).

Answering your IRC question here:

#define ERU_FMT "[%lx-%lx]"
#define ERU_ARG(eru) eru.base_pfn, eru.end_pfn

(with the acronym "eru" open for improvement).

Jan

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v10 5/5] iommu: add rmrr Xen command line option for extra rmrrs
  2015-07-13 18:18 ` [PATCH v10 5/5] iommu: add rmrr Xen command line option for extra rmrrs elena.ufimtseva
@ 2015-07-14 10:43   ` Jan Beulich
  2015-07-15  7:25     ` Jan Beulich
  0 siblings, 1 reply; 8+ messages in thread
From: Jan Beulich @ 2015-07-14 10:43 UTC (permalink / raw)
  To: elena.ufimtseva; +Cc: kevin.tian, tim, xen-devel, yang.z.zhang, boris.ostrovsky

>>> On 13.07.15 at 20:18, <elena.ufimtseva@oracle.com> wrote:
> --- a/xen/drivers/passthrough/vtd/dmar.c
> +++ b/xen/drivers/passthrough/vtd/dmar.c
> @@ -867,6 +867,145 @@ out:
>      return ret;
>  }
>  
> +#define MAX_EXTRA_RMRR_PAGES 16
> +#define MAX_EXTRA_RMRR 10
> +
> +/* RMRR units derived from command line rmrr option. */
> +#define MAX_EXTRA_RMRR_DEV 20
> +struct extra_rmrr_unit {
> +    struct list_head list;
> +    unsigned long base_pfn, end_pfn;
> +    unsigned int dev_count;
> +    u32    sbdf[MAX_EXTRA_RMRR_DEV];

unless you want to align _all_ fields' names, there should be just a
single space between type and name.

> +};
> +static __initdata unsigned int nr_rmrr;
> +static struct __initdata extra_rmrr_unit extra_rmrr_units[MAX_EXTRA_RMRR];
> +
> +/* Macro for RMRR inclusive range formatting. */
> +#define PRI_RMRR(s,e) "[%lx-%lx]"

Just PRI_RMRR (i.e. no parens or parameters) please. And I'm still
missing a macro to pair the respective arguments - as said before,
as single format specifier should be accompanied by a single
argument (as visible to the reader at the use sites).

> +static void __init add_extra_rmrr(void)
> +{
> +    struct acpi_rmrr_unit *acpi_rmrr;
> +    struct acpi_rmrr_unit *rmrru;
> +    unsigned int dev, seg, i, j;
> +    unsigned long pfn;
> +    bool_t overlap;
> +
> +    for ( i = 0; i < nr_rmrr; i++ )
> +    {
> +        if ( extra_rmrr_units[i].base_pfn > extra_rmrr_units[i].end_pfn )
> +        {
> +            printk(XENLOG_ERR VTDPREFIX
> +                   "Invalid RMRR Range "PRI_RMRR(s,e)"\n",
> +                   extra_rmrr_units[i].base_pfn, extra_rmrr_units[i].end_pfn);
> +            continue;
> +        }
> +
> +        if ( extra_rmrr_units[i].end_pfn - extra_rmrr_units[i].base_pfn >=
> +             MAX_EXTRA_RMRR_PAGES )
> +        {
> +            printk(XENLOG_ERR VTDPREFIX
> +                   "RMRR range "PRI_RMRR(s,e)" exceeds "__stringify(MAX_EXTRA_RMRR_PAGES)" pages\n",
> +                   extra_rmrr_units[i].base_pfn, extra_rmrr_units[i].end_pfn);
> +            continue;
> +        }
> +
> +        for ( j = 0; j < nr_rmrr; j++ )
> +        {
> +            if ( i != j &&
> +                 extra_rmrr_units[i].base_pfn <= extra_rmrr_units[j].end_pfn &&
> +                 extra_rmrr_units[j].base_pfn <= extra_rmrr_units[i].end_pfn )
> +            {
> +                printk(XENLOG_ERR VTDPREFIX
> +                      "Overlapping RMRRs "PRI_RMRR(s,e)" and "PRI_RMRR(s,e)"\n",

No "extra" here ...

> +                      extra_rmrr_units[i].base_pfn, extra_rmrr_units[i].end_pfn,
> +                      extra_rmrr_units[j].base_pfn, extra_rmrr_units[j].end_pfn);
> +                break;
> +            }
> +        }
> +        /* Broke out of the overlap loop check, continue with next rmrr. */
> +        if ( j < nr_rmrr )
> +            continue;
> +        overlap = 0;
> +        list_for_each_entry(rmrru, &acpi_rmrr_units, list)
> +        {
> +            if ( pfn_to_paddr(extra_rmrr_units[i].base_pfn <= rmrru->end_address) &&
> +                 rmrru->base_address <= pfn_to_paddr(extra_rmrr_units[i].end_pfn) )
> +            {
> +                printk(XENLOG_ERR VTDPREFIX
> +                       "Overlapping extra RMRRs "PRI_RMRR(s,e)" and ACPI RMRRs "PRI_RMRR(s,e)"\n",

... but here? This may end up being confusing... Also s/RMRRs/RMRR/g
here please.

Also note the misplaced closing parenthesis on the first line of the
enclosing if().

> +                       extra_rmrr_units[i].base_pfn,
> +                       extra_rmrr_units[i].end_pfn,
> +                       paddr_to_pfn(rmrru->base_address),
> +                       paddr_to_pfn(rmrru->end_address));
> +                overlap = 1;
> +                break;
> +            }
> +        }
> +        /* Continue to next RMRR is this one overlaps with one from ACPI. */
> +        if ( overlap )
> +            continue;
> +
> +        pfn = extra_rmrr_units[i].base_pfn;
> +        do
> +        {
> +            if ( !mfn_valid(pfn) || (pfn >> (paddr_bits - PAGE_SHIFT)) )
> +            {
> +                printk(XENLOG_ERR VTDPREFIX
> +                       "Invalid pfn in RMRR range "PRI_RMRR(s,e)"\n",
> +                       extra_rmrr_units[i].base_pfn, extra_rmrr_units[i].end_pfn);
> +                break;
> +            }
> +        } while ( pfn++ <= extra_rmrr_units[i].end_pfn );

Off by one afaict.

> +static void __init parse_rmrr_param(const char *str)
> +{
> +    const char *s = str, *cur, *stmp;
> +    unsigned int seg, bus, dev, func;
> +    unsigned long start, end;
> +
> +    do {
> +        start = simple_strtoul(cur = s, &s, 0);
> +        if ( cur == s )
> +            break;
> +
> +        if ( *s == '-' )
> +        {
> +            end = simple_strtoul(cur = s + 1, &s, 0);
> +            if ( cur == s )
> +                break;
> +        }
> +        else
> +            end = start;
> +
> +        extra_rmrr_units[nr_rmrr].base_pfn = start;
> +        extra_rmrr_units[nr_rmrr].end_pfn = end;
> +        extra_rmrr_units[nr_rmrr].dev_count = 0;
> +
> +        if ( *s != '=' )
> +            continue;
> +
> +        do {
> +            bool_t default_segment = 0;
> +
> +            if ( *s == ';' )
> +                break;
> +            stmp = __parse_pci(s + 1, &seg, &bus, &dev, &func, &default_segment);
> +            if ( !stmp )
> +                break;
> +
> +            /* Not specified segment will be replaced with one from first device. */
> +            if ( extra_rmrr_units[nr_rmrr].dev_count && default_segment )
> +                seg = PCI_SEG(extra_rmrr_units[nr_rmrr].sbdf[0]);
> +
> +            /* Keep sbdf's even if they differ and later report an error. */
> +            extra_rmrr_units[nr_rmrr].sbdf[extra_rmrr_units[nr_rmrr].dev_count] = PCI_SBDF(seg, bus, dev, func);

Long line.

> +            extra_rmrr_units[nr_rmrr].dev_count++;
> +            s = stmp;
> +        } while ( (*s == ',' || *s ) &&
> +                  extra_rmrr_units[nr_rmrr].dev_count < MAX_EXTRA_RMRR_DEV );

This condition is _still_ bogus: If *s == ',' then obviously also *s, i.e.
the former condition is redundant with the latter. But then I don't
think you really mean just *s here, i.e. I'd rather see the latter part
dropped.

Jan

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v10 5/5] iommu: add rmrr Xen command line option for extra rmrrs
  2015-07-13 18:17 [PATCH v10 0/5] iommu: add rmrr Xen command line option elena.ufimtseva
@ 2015-07-13 18:18 ` elena.ufimtseva
  2015-07-14 10:43   ` Jan Beulich
  0 siblings, 1 reply; 8+ messages in thread
From: elena.ufimtseva @ 2015-07-13 18:18 UTC (permalink / raw)
  To: xen-devel
  Cc: Elena Ufimtseva, kevin.tian, tim, jbeulich, yang.z.zhang,
	boris.ostrovsky

From: Elena Ufimtseva <elena.ufimtseva@oracle.com>

On some platforms RMRR regions may be not specified
in ACPI and thus will not be mapped 1:1 in dom0. This
causes IO Page Faults and prevents dom0 from booting
in PVH mode.
New Xen command line option rmrr allows to specify
such devices and memory regions. These regions are added
to the list of RMRR defined in ACPI if the device
is present in system. As a result, additional RMRRs will
be mapped 1:1 in dom0 with correct permissions.

Mentioned above problems were discovered during PVH work with
ThinkCentre M and Dell 5600T. No official documentation
was found so far in regards to what devices and why cause this.
Experiments show that ThinkCentre M USB devices with enabled
debug port generate DMA read transactions to the regions of
memory marked reserved in host e820 map.
For Dell 5600T the device and faulting addresses are not found yet.

For detailed history of the discussion please check following threads:
http://lists.Xen.org/archives/html/xen-devel/2015-02/msg01724.html
http://lists.Xen.org/archives/html/xen-devel/2015-01/msg02513.html

Format for rmrr Xen command line option:
rmrr=start<-end>=[s1]bdf1[,[s1]bdf2[,...]];start<-end>=[s2]bdf1[,[s2]bdf2[,...]]
If grub2 used and multiple ranges are specified, ';' should be
quoted/escaped, refer to grub2 manual for more information.

Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
 docs/misc/xen-command-line.markdown |  13 +++
 xen/drivers/passthrough/vtd/dmar.c  | 209 +++++++++++++++++++++++++++++++++++-
 2 files changed, 221 insertions(+), 1 deletion(-)

diff --git a/docs/misc/xen-command-line.markdown b/docs/misc/xen-command-line.markdown
index aa684c0..f307f3d 100644
--- a/docs/misc/xen-command-line.markdown
+++ b/docs/misc/xen-command-line.markdown
@@ -1197,6 +1197,19 @@ Specify the host reboot method.
 'efi' instructs Xen to reboot using the EFI reboot call (in EFI mode by
  default it will use that method first).
 
+### rmrr
+> '= start<-end>=[s1]bdf1[,[s1]bdf2[,...]];start<-end>=[s2]bdf1[,[s2]bdf2[,...]]
+
+Define RMRR units that are missing from ACPI table along with device they
+belong to and use them for 1:1 mapping. End addresses can be omitted and one
+page will be mapped. The ranges are inclusive when start and end are specified.
+If segment of the first device is not specified, segment zero will be used.
+If other segments are not specified, first device segment will be used.
+If a segment is specified for other than the first device and it does not match
+the one specified for the first one, an error will be reported.
+Note: grub2 requires to escape or use quotations if special characters are used,
+namely ';', refer to the grub2 documentation if multiple ranges are specified.
+
 ### ro-hpet
 > `= <boolean>`
 
diff --git a/xen/drivers/passthrough/vtd/dmar.c b/xen/drivers/passthrough/vtd/dmar.c
index 93f10fd..61e8f28 100644
--- a/xen/drivers/passthrough/vtd/dmar.c
+++ b/xen/drivers/passthrough/vtd/dmar.c
@@ -867,6 +867,145 @@ out:
     return ret;
 }
 
+#define MAX_EXTRA_RMRR_PAGES 16
+#define MAX_EXTRA_RMRR 10
+
+/* RMRR units derived from command line rmrr option. */
+#define MAX_EXTRA_RMRR_DEV 20
+struct extra_rmrr_unit {
+    struct list_head list;
+    unsigned long base_pfn, end_pfn;
+    unsigned int dev_count;
+    u32    sbdf[MAX_EXTRA_RMRR_DEV];
+};
+static __initdata unsigned int nr_rmrr;
+static struct __initdata extra_rmrr_unit extra_rmrr_units[MAX_EXTRA_RMRR];
+
+/* Macro for RMRR inclusive range formatting. */
+#define PRI_RMRR(s,e) "[%lx-%lx]"
+
+static void __init add_extra_rmrr(void)
+{
+    struct acpi_rmrr_unit *acpi_rmrr;
+    struct acpi_rmrr_unit *rmrru;
+    unsigned int dev, seg, i, j;
+    unsigned long pfn;
+    bool_t overlap;
+
+    for ( i = 0; i < nr_rmrr; i++ )
+    {
+        if ( extra_rmrr_units[i].base_pfn > extra_rmrr_units[i].end_pfn )
+        {
+            printk(XENLOG_ERR VTDPREFIX
+                   "Invalid RMRR Range "PRI_RMRR(s,e)"\n",
+                   extra_rmrr_units[i].base_pfn, extra_rmrr_units[i].end_pfn);
+            continue;
+        }
+
+        if ( extra_rmrr_units[i].end_pfn - extra_rmrr_units[i].base_pfn >=
+             MAX_EXTRA_RMRR_PAGES )
+        {
+            printk(XENLOG_ERR VTDPREFIX
+                   "RMRR range "PRI_RMRR(s,e)" exceeds "__stringify(MAX_EXTRA_RMRR_PAGES)" pages\n",
+                   extra_rmrr_units[i].base_pfn, extra_rmrr_units[i].end_pfn);
+            continue;
+        }
+
+        for ( j = 0; j < nr_rmrr; j++ )
+        {
+            if ( i != j &&
+                 extra_rmrr_units[i].base_pfn <= extra_rmrr_units[j].end_pfn &&
+                 extra_rmrr_units[j].base_pfn <= extra_rmrr_units[i].end_pfn )
+            {
+                printk(XENLOG_ERR VTDPREFIX
+                      "Overlapping RMRRs "PRI_RMRR(s,e)" and "PRI_RMRR(s,e)"\n",
+                      extra_rmrr_units[i].base_pfn, extra_rmrr_units[i].end_pfn,
+                      extra_rmrr_units[j].base_pfn, extra_rmrr_units[j].end_pfn);
+                break;
+            }
+        }
+        /* Broke out of the overlap loop check, continue with next rmrr. */
+        if ( j < nr_rmrr )
+            continue;
+        overlap = 0;
+        list_for_each_entry(rmrru, &acpi_rmrr_units, list)
+        {
+            if ( pfn_to_paddr(extra_rmrr_units[i].base_pfn <= rmrru->end_address) &&
+                 rmrru->base_address <= pfn_to_paddr(extra_rmrr_units[i].end_pfn) )
+            {
+                printk(XENLOG_ERR VTDPREFIX
+                       "Overlapping extra RMRRs "PRI_RMRR(s,e)" and ACPI RMRRs "PRI_RMRR(s,e)"\n",
+                       extra_rmrr_units[i].base_pfn,
+                       extra_rmrr_units[i].end_pfn,
+                       paddr_to_pfn(rmrru->base_address),
+                       paddr_to_pfn(rmrru->end_address));
+                overlap = 1;
+                break;
+            }
+        }
+        /* Continue to next RMRR is this one overlaps with one from ACPI. */
+        if ( overlap )
+            continue;
+
+        pfn = extra_rmrr_units[i].base_pfn;
+        do
+        {
+            if ( !mfn_valid(pfn) || (pfn >> (paddr_bits - PAGE_SHIFT)) )
+            {
+                printk(XENLOG_ERR VTDPREFIX
+                       "Invalid pfn in RMRR range "PRI_RMRR(s,e)"\n",
+                       extra_rmrr_units[i].base_pfn, extra_rmrr_units[i].end_pfn);
+                break;
+            }
+        } while ( pfn++ <= extra_rmrr_units[i].end_pfn );
+        /* The range had invalid pfn as the loop was broken out before reaching end_pfn. */
+        if ( pfn <= extra_rmrr_units[i].end_pfn )
+            continue;
+
+        acpi_rmrr = xzalloc(struct acpi_rmrr_unit);
+        if ( !acpi_rmrr )
+            return;
+
+        acpi_rmrr->scope.devices = xmalloc_array(u16,
+                                                 extra_rmrr_units[i].dev_count);
+        if ( !acpi_rmrr->scope.devices )
+        {
+            xfree(acpi_rmrr);
+            return;
+        }
+
+        seg = 0;
+        for ( dev = 0; dev < extra_rmrr_units[i].dev_count; dev++ )
+        {
+            acpi_rmrr->scope.devices[dev] = extra_rmrr_units[i].sbdf[dev];
+            seg = seg | PCI_SEG(extra_rmrr_units[i].sbdf[dev]);
+        }
+        if ( seg != PCI_SEG(extra_rmrr_units[i].sbdf[0]) )
+        {
+            printk(XENLOG_ERR VTDPREFIX
+                   "Segments are not equal for RMRR range "PRI_RMRR(s,e)"\n",
+                   extra_rmrr_units[i].base_pfn, extra_rmrr_units[i].end_pfn);
+            scope_devices_free(&acpi_rmrr->scope);
+            xfree(acpi_rmrr);
+            continue;
+        }
+
+        acpi_rmrr->segment = seg;
+        acpi_rmrr->base_address = pfn_to_paddr(extra_rmrr_units[i].base_pfn);
+        acpi_rmrr->end_address = pfn_to_paddr(extra_rmrr_units[i].end_pfn + 1);
+        acpi_rmrr->scope.devices_cnt = extra_rmrr_units[i].dev_count;
+
+        if ( register_one_rmrr(acpi_rmrr) )
+        {
+            printk(XENLOG_ERR VTDPREFIX
+                   "Could not register RMMR range "PRI_RMRR(s,e)"\n",
+                   extra_rmrr_units[i].base_pfn, extra_rmrr_units[i].end_pfn);
+            scope_devices_free(&acpi_rmrr->scope);
+            xfree(acpi_rmrr);
+        }
+    }
+}
+
 #include <asm/tboot.h>
 /* ACPI tables may not be DMA protected by tboot, so use DMAR copy */
 /* SINIT saved in SinitMleData in TXT heap (which is DMA protected) */
@@ -876,6 +1015,7 @@ int __init acpi_dmar_init(void)
 {
     acpi_physical_address dmar_addr;
     acpi_native_uint dmar_len;
+    int ret;
 
     if ( ACPI_SUCCESS(acpi_get_table_phys(ACPI_SIG_DMAR, 0,
                                           &dmar_addr, &dmar_len)) )
@@ -886,7 +1026,10 @@ int __init acpi_dmar_init(void)
         dmar_table = __va(dmar_addr);
     }
 
-    return parse_dmar_table(acpi_parse_dmar);
+    ret = parse_dmar_table(acpi_parse_dmar);
+    add_extra_rmrr();
+
+    return ret;
 }
 
 void acpi_dmar_reinstate(void)
@@ -917,3 +1060,67 @@ int platform_supports_x2apic(void)
     unsigned int mask = ACPI_DMAR_INTR_REMAP | ACPI_DMAR_X2APIC_OPT_OUT;
     return cpu_has_x2apic && ((dmar_flags & mask) == ACPI_DMAR_INTR_REMAP);
 }
+
+/*
+ * Parse rmrr Xen command line options and add parsed device and region into
+ * acpi_rmrr_unit list to mapped as RMRRs parsed from ACPI.
+ * Format:
+ * rmrr=start<-end>=[s1]bdf1[,[s1]bdf2[,...]];start<-end>=[s2]bdf1[,[s2]bdf2[,...]]
+ * If the segment of the first device is not specified, segment zero will be used.
+ * If other segments are not specified, first device segment will be used.
+ * If a segment is specified for other than the first device and it does not match
+ * the one specified for the first one, an error will be reported.
+ */
+static void __init parse_rmrr_param(const char *str)
+{
+    const char *s = str, *cur, *stmp;
+    unsigned int seg, bus, dev, func;
+    unsigned long start, end;
+
+    do {
+        start = simple_strtoul(cur = s, &s, 0);
+        if ( cur == s )
+            break;
+
+        if ( *s == '-' )
+        {
+            end = simple_strtoul(cur = s + 1, &s, 0);
+            if ( cur == s )
+                break;
+        }
+        else
+            end = start;
+
+        extra_rmrr_units[nr_rmrr].base_pfn = start;
+        extra_rmrr_units[nr_rmrr].end_pfn = end;
+        extra_rmrr_units[nr_rmrr].dev_count = 0;
+
+        if ( *s != '=' )
+            continue;
+
+        do {
+            bool_t default_segment = 0;
+
+            if ( *s == ';' )
+                break;
+            stmp = __parse_pci(s + 1, &seg, &bus, &dev, &func, &default_segment);
+            if ( !stmp )
+                break;
+
+            /* Not specified segment will be replaced with one from first device. */
+            if ( extra_rmrr_units[nr_rmrr].dev_count && default_segment )
+                seg = PCI_SEG(extra_rmrr_units[nr_rmrr].sbdf[0]);
+
+            /* Keep sbdf's even if they differ and later report an error. */
+            extra_rmrr_units[nr_rmrr].sbdf[extra_rmrr_units[nr_rmrr].dev_count] = PCI_SBDF(seg, bus, dev, func);
+            extra_rmrr_units[nr_rmrr].dev_count++;
+            s = stmp;
+        } while ( (*s == ',' || *s ) &&
+                  extra_rmrr_units[nr_rmrr].dev_count < MAX_EXTRA_RMRR_DEV );
+
+        if ( extra_rmrr_units[nr_rmrr].dev_count )
+            nr_rmrr++;
+
+    } while ( *s++ == ';' && nr_rmrr < MAX_EXTRA_RMRR );
+}
+custom_param("rmrr", parse_rmrr_param);
-- 
2.1.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2015-07-16 16:00 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-16 16:00 [PATCH v10 5/5] iommu: add rmrr Xen command line option for extra rmrrs Elena Ufimtseva
  -- strict thread matches above, loose matches on Subject: below --
2015-07-15 16:15 Elena Ufimtseva
2015-07-16  8:02 ` Jan Beulich
2015-07-13 18:17 [PATCH v10 0/5] iommu: add rmrr Xen command line option elena.ufimtseva
2015-07-13 18:18 ` [PATCH v10 5/5] iommu: add rmrr Xen command line option for extra rmrrs elena.ufimtseva
2015-07-14 10:43   ` Jan Beulich
2015-07-15  7:25     ` Jan Beulich
2015-07-15 15:27       ` Elena Ufimtseva
2015-07-15 16:08         ` Jan Beulich

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).