[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] RE: [PATCH v8 1/2] IOMMU/VT-d: wire common device reserved memory API
Hi Marek, > -----Original Message----- > From: Marek Marczykowski-Górecki <marmarek@xxxxxxxxxxxxxxxxxxxxxx> > Subject: Re: [PATCH v8 1/2] IOMMU/VT-d: wire common device reserved > memory API > > On Thu, Sep 29, 2022 at 03:33:12PM +0200, Marek Marczykowski-Górecki > wrote: > > Re-use rmrr= parameter handling code to handle common device reserved > > memory. > > > > Move MAX_USER_RMRR_PAGES limit enforcement to apply only to > > user-configured ranges, but not those from internal callers. > > > > Signed-off-by: Marek Marczykowski-Górecki > <marmarek@xxxxxxxxxxxxxxxxxxxxxx> > > Reviewed-by: Kevin Tian <kevin.tian@xxxxxxxxx> > > Henry, can this be included in 4.17? The AMD counterpart went in > earlier, but due to late review on Intel part, this one didn't. Thanks for the information. I agree this is a valid reason, but to be safe I would like to hear opinions from the x86 maintainers (added in CC). Andrew/Jan/Roger: May I have your feedback about this? Thanks! Kind regards, Henry > > > --- > > Changes in v8: > > - move add_one_user_rmrr() function earlier > > - extend commit message > > Changes in v3: > > - make MAX_USER_RMRR_PAGES applicable only to user-configured RMRR > > --- > > xen/drivers/passthrough/vtd/dmar.c | 196 +++++++++++++++++------------- > > 1 file changed, 114 insertions(+), 82 deletions(-) > > > > diff --git a/xen/drivers/passthrough/vtd/dmar.c > b/xen/drivers/passthrough/vtd/dmar.c > > index 367304c8739c..78c8bad1515a 100644 > > --- a/xen/drivers/passthrough/vtd/dmar.c > > +++ b/xen/drivers/passthrough/vtd/dmar.c > > @@ -861,113 +861,136 @@ 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_user_rmrr(void) > > +/* Returns 1 on success, 0 when ignoring and < 0 on error. */ > > +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 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; > > } > > > > +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); > > +} > > + > > +static int __init add_extra_rmrr(void) > > +{ > > + return > iommu_get_extra_reserved_device_memory(add_one_extra_rmrr, NULL); > > +} > > + > > #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) */ > > @@ -1010,7 +1033,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 +1131,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; > > + } > > + > > user_rmrrs[nr_rmrr].base_pfn = start; > > user_rmrrs[nr_rmrr].end_pfn = end; > > > > -- > > git-series 0.9.1 > > > > -- > Best Regards, > Marek Marczykowski-Górecki > Invisible Things Lab
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |