[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v8 4/4] iommu: add rmrr Xen command line option for extra rmrrs
. snip.. > diff --git a/xen/drivers/passthrough/vtd/dmar.c > b/xen/drivers/passthrough/vtd/dmar.c > index a8e1e5d..fa659a9 100644 > --- a/xen/drivers/passthrough/vtd/dmar.c > +++ b/xen/drivers/passthrough/vtd/dmar.c > @@ -42,6 +42,8 @@ > #define MIN_SCOPE_LEN (sizeof(struct acpi_dmar_device_scope) + \ > sizeof(struct acpi_dmar_pci_path)) > > +#define PRI_RMRR(s,e) "[%lx-%lx]" > + > LIST_HEAD_READ_MOSTLY(acpi_drhd_units); > LIST_HEAD_READ_MOSTLY(acpi_rmrr_units); > static LIST_HEAD_READ_MOSTLY(acpi_atsr_units); > @@ -425,7 +427,7 @@ static int __init acpi_parse_dev_scope( > default: > if ( iommu_verbose ) > printk(XENLOG_WARNING VTDPREFIX "Unknown scope type %#x\n", > - acpi_scope->entry_type); > + acpi_scope->entry_type); Stray change? It should be in a seperate patch I think? > start += acpi_scope->length; > continue; > } > @@ -479,8 +481,7 @@ acpi_parse_one_drhd(struct acpi_dmar_header *header) > INIT_LIST_HEAD(&dmaru->ioapic_list); > INIT_LIST_HEAD(&dmaru->hpet_list); > if ( iommu_verbose ) > - dprintk(VTDPREFIX, " dmaru->address = %"PRIx64"\n", > - dmaru->address); > + dprintk(VTDPREFIX, " dmaru->address = %"PRIx64"\n", dmaru->address); Ditto. > > ret = iommu_alloc(dmaru); > if ( ret ) > @@ -541,8 +542,8 @@ acpi_parse_one_drhd(struct acpi_dmar_header *header) > if ( !pci_device_detect(drhd->segment, b, d, f) ) > { > dprintk(XENLOG_WARNING VTDPREFIX, > - " Non-existent device (%04x:%02x:%02x.%u) is > reported" > - " in this DRHD's scope!\n", drhd->segment, b, d, f); > + " Non-existent device (%04x:%02x:%02x.%u) is > reported in this DRHD's scope!\n", > + drhd->segment, b, d, f); As well - an seperate cleanup patch. > invalid_cnt++; > } > } > @@ -553,8 +554,8 @@ acpi_parse_one_drhd(struct acpi_dmar_header *header) > invalid_cnt == dmaru->scope.devices_cnt ) > { > dprintk(XENLOG_WARNING VTDPREFIX, > - " Workaround BIOS bug: ignore the DRHD due to all " > - "devices under its scope are not PCI discoverable!\n"); > + " Workaround BIOS bug: ignore the DRHD due to all " > + "devices under its scope are not PCI > discoverable!\n"); This one too. > > scope_devices_free(&dmaru->scope); > iommu_free(dmaru); > @@ -563,10 +564,10 @@ acpi_parse_one_drhd(struct acpi_dmar_header *header) > else > { > dprintk(XENLOG_WARNING VTDPREFIX, > - " The DRHD is invalid due to there are devices under " > - "its scope are not PCI discoverable! Pls try option " > - "iommu=force or iommu=workaround_bios_bug if you " > - "really want VT-d\n"); > + " The DRHD is invalid due to there are devices > under " > + "its scope are not PCI discoverable! Pls try option " > + "iommu=force or iommu=workaround_bios_bug if you " > + "really want VT-d\n"); And that as well. > ret = -EINVAL; > } > } > @@ -604,8 +605,7 @@ static int register_one_rmrr(struct acpi_rmrr_unit *rmrru) > if ( pci_device_detect(rmrru->segment, b, d, f) == 0 ) > { > dprintk(XENLOG_WARNING VTDPREFIX, > - " Non-existent device (%04x:%02x:%02x.%u) is reported" > - " in RMRR (%"PRIx64", %"PRIx64")'s scope!\n", > + " Non-existent device (%04x:%02x:%02x.%u) is reported in > RMRR "PRI_RMRR(s,e)"'s scope!\n", > rmrru->segment, b, d, f, > rmrru->base_address, rmrru->end_address); > ignore = 1; > @@ -620,16 +620,16 @@ static int register_one_rmrr(struct acpi_rmrr_unit > *rmrru) > if ( ignore ) > { > dprintk(XENLOG_WARNING VTDPREFIX, > - " Ignore the RMRR (%"PRIx64", %"PRIx64") due to " > + " Ignore the RMRR "PRI_RMRR(s,e)" due to " > "devices under its scope are not PCI discoverable!\n", > - rmrru->base_address, rmrru->end_address); > + rmrru->base_address, rmrru->end_address); > scope_devices_free(&rmrru->scope); > xfree(rmrru); > } > else if ( rmrru->base_address > rmrru->end_address ) > { > dprintk(XENLOG_WARNING VTDPREFIX, > - " The RMRR (%"PRIx64", %"PRIx64") is incorrect!\n", > + " The RMRR "PRI_RMRR(s,e)" is incorrect!\n", > rmrru->base_address, rmrru->end_address); > scope_devices_free(&rmrru->scope); > xfree(rmrru); > @@ -639,7 +639,7 @@ static int register_one_rmrr(struct acpi_rmrr_unit *rmrru) > { > if ( iommu_verbose ) > dprintk(VTDPREFIX, > - " RMRR region: base_addr %"PRIx64" end_address > %"PRIx64"\n", > + " RMRR region: "PRI_RMRR(s,e)"\n", > rmrru->base_address, rmrru->end_address); > acpi_register_rmrr_unit(rmrru); > } > @@ -664,7 +664,7 @@ acpi_parse_one_rmrr(struct acpi_dmar_header *header) > if ( base_addr <= rmrru->end_address && rmrru->base_address <= > end_addr ) > { > printk(XENLOG_ERR VTDPREFIX > - "Overlapping RMRRs [%"PRIx64",%"PRIx64"] and > [%"PRIx64",%"PRIx64"]\n", > + "Overlapping RMRRs "PRI_RMRR(s,e)" and "PRI_RMRR(s,e)"\n", > rmrru->base_address, rmrru->end_address, > base_addr, end_addr); > return -EEXIST; > @@ -678,8 +678,7 @@ acpi_parse_one_rmrr(struct acpi_dmar_header *header) > (!page_is_ram_type(paddr_to_pfn(end_addr), RAM_TYPE_RESERVED)) ) > { > dprintk(XENLOG_WARNING VTDPREFIX, > - " RMRR address range not in reserved memory " > - "base = %"PRIx64" end = %"PRIx64"; " > + " RMRR address range "PRI_RMRR(s,e)" not in reserved > memory; " > "iommu_inclusive_mapping=1 parameter may be needed.\n", > base_addr, end_addr); > } > @@ -779,8 +778,7 @@ acpi_parse_one_rhsa(struct acpi_dmar_header *header) > list_add_tail(&rhsau->list, &acpi_rhsa_units); > if ( iommu_verbose ) > dprintk(VTDPREFIX, > - " rhsau->address: %"PRIx64 > - " rhsau->proximity_domain: %"PRIx32"\n", > + " rhsau->address: %"PRIx64" rhsau->proximity_domain: > %"PRIx32"\n", All of those should go in a seperate cleanup patch please. > rhsau->address, rhsau->proximity_domain); > > return ret; > @@ -869,6 +867,140 @@ out: > return ret; > } > > +#define MAX_EXTRA_RMRR_PAGES 16 > +#define MAX_EXTRA_RMRR 10 > + > +/* RMRR units derived from command line rmrr option */ Missing full stop. > +#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 */ Macro? Ah I think you meant the: #define PRI_RMRR(s,e) "[%lx-%lx]" which is defined somewhere at the top of the file with your patch. Please move it here. Also, missing full stop at the end of the line. > + > +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; > + > + 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; > + 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)); > + break; You break out of the for loop (list_for_each_entry) - did .. > + } > + } ... you also want to continue with the next rmrr? Right now the code will continue on with this 'i'. > + > + > + pfn = extra_rmrr_units[i].base_pfn; > + do > + { > + if ( !mfn_valid(pfn) || (pfn >> (paddr_bits - PAGE_SHIFT)) ) > + { > + if ( iommu_verbose ) Why the 'iommu_verbose' ? Why not just print it out as all the other errors are printed? > + printk(XENLOG_ERR VTDPREFIX > + "Invalid mfn 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 mfn 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) */ > @@ -878,6 +1010,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)) ) > @@ -888,7 +1021,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) > @@ -919,3 +1055,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 == ',' && > + 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); Otherwise looks fine! > -- > 2.1.3 > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |