[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2 2/2] iommu: add rmrr Xen command line option for misc rmrrs
From: Elena Ufimtseva <elena.ufimtseva@xxxxxxxxxx> 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>=sbdf1[,sbdf2[,...]]#start<-end>=sbdf1[,sbdf2[,...]] Signed-off-by: Elena Ufimtseva <elena.ufimtseva@xxxxxxxxxx> --- docs/misc/xen-command-line.markdown | 8 +++ xen/drivers/passthrough/vtd/dmar.c | 114 ++++++++++++++++++++++++++++++++++++ xen/drivers/passthrough/vtd/dmar.h | 11 ++++ 3 files changed, 133 insertions(+) diff --git a/docs/misc/xen-command-line.markdown b/docs/misc/xen-command-line.markdown index 1dda1f0..92aefdb 100644 --- a/docs/misc/xen-command-line.markdown +++ b/docs/misc/xen-command-line.markdown @@ -1170,6 +1170,14 @@ 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>=sbdf1[,sbdf2[,...]]#start<-end>=sbdf1[,sbdf2[,...]] + +Define RMRRs 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 end and start +are specified. + ### ro-hpet > `= <boolean>` diff --git a/xen/drivers/passthrough/vtd/dmar.c b/xen/drivers/passthrough/vtd/dmar.c index 979fac1..e8e043b 100644 --- a/xen/drivers/passthrough/vtd/dmar.c +++ b/xen/drivers/passthrough/vtd/dmar.c @@ -49,6 +49,7 @@ static LIST_HEAD_READ_MOSTLY(acpi_rhsa_units); static struct acpi_table_header *__read_mostly dmar_table; static int __read_mostly dmar_flags; static u64 __read_mostly igd_drhd_address; +static void __init add_misc_rmrr(void); static void __init dmar_scope_add_buses(struct dmar_scope *scope, u16 sec_bus, u16 sub_bus) @@ -868,6 +869,7 @@ int __init acpi_dmar_init(void) PAGE_HYPERVISOR); dmar_table = __va(dmar_addr); } + add_misc_rmrr(); return parse_dmar_table(acpi_parse_dmar); } @@ -900,3 +902,115 @@ 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 apci_rmrr_unit list to mapped + * as RMRRs parsed from ACPI. + * Format rmrr=start<-end>=sbdf1[,sbdf2[,...]]#start<-end>=sbdf1[,sbdf2[,...]] + * end address can be ommited and one page will be used + * for mapping with start pfn. + */ + +#define MAX_MISC_RMRR 10 +__initdata LIST_HEAD(misc_rmrr_units); +__initdata unsigned int nr_rmrr = 0; +struct __initdata misc_rmrr_unit rmrru[MAX_MISC_RMRR]; + +static void __init parse_rmrr_param(const char *str) +{ + unsigned int seg, bus, dev, func; + const char *s = str, *cur, *stmp; + unsigned int i = 0, rmrrs = 0; + u64 start, end; + + do { + start = simple_strtoull(cur = s, &s, 0); + if ( cur == s ) + break; + + if ( *s == '-' ) + { + end = simple_strtoull(cur = s + 1, &s, 0); + if ( cur == s ) + break; + } + else + end = start; + if ( end >= start && rmrrs < MAX_MISC_RMRR ) + { + rmrru[i].base_address = start << PAGE_SHIFT; + rmrru[i].end_address = (end + 1) << PAGE_SHIFT; + rmrru[i].dev_count = 0; + } + else + { + printk(XENLOG_WARNING "Bad rmrr: start > end, %"PRIx64" > %"PRIx64"\n", + start, end); + break; + } + + if ( *s != '=' ) + continue; + + do { + if ( rmrru[i].dev_count >= MAX_MISC_RMRR_DEV ) + break; + if ( *s == '#' ) + break; + seg = bus = dev = func = 0; + stmp = parse_pci(s + 1, &seg, &bus, &dev, &func); + if ( !stmp ) + break; + rmrru[i].devices[rmrru[i].dev_count++] = PCI_BDF(bus, dev, func); + rmrru[i].segment = seg; + s = stmp; + } while ( *s == ',' ); + + if ( rmrru[i].dev_count ) { + list_add(&rmrru[i].list, &misc_rmrr_units); + i++; + } + rmrrs++; + + } while ( *s++ == '#' ); + + nr_rmrr = i; +} +custom_param("rmrr", parse_rmrr_param); + +static void __init add_misc_rmrr(void) +{ + struct acpi_rmrr_unit *rmrrn; + struct misc_rmrr_unit *rmrru, *r; + + list_for_each_entry_safe( rmrru, r, &misc_rmrr_units, list ) + { + rmrrn = xzalloc(struct acpi_rmrr_unit); + if ( !rmrrn ) + goto del; + + rmrrn->scope.devices = xzalloc(typeof(*rmrrn->scope.devices)); + if ( !rmrrn->scope.devices ) + { + xfree(rmrrn); + goto del; + } + rmrrn->segment = rmrru->segment; + rmrrn->base_address = rmrru->base_address; + rmrrn->end_address = rmrru->end_address; + + for (int dev = 0; dev < rmrru->dev_count; dev++) + rmrrn->scope.devices[dev] = rmrru->devices[dev]; + + rmrrn->scope.devices_cnt = rmrru->dev_count; + + if ( register_one_rmrr(rmrrn) ) + { + xfree(rmrrn->scope.devices); + xfree(rmrrn); + } + del: + list_del(&rmrru->list); + } +} diff --git a/xen/drivers/passthrough/vtd/dmar.h b/xen/drivers/passthrough/vtd/dmar.h index af1feef..99a20ed 100644 --- a/xen/drivers/passthrough/vtd/dmar.h +++ b/xen/drivers/passthrough/vtd/dmar.h @@ -132,4 +132,15 @@ void disable_pmr(struct iommu *iommu); int is_usb_device(u16 seg, u8 bus, u8 devfn); int is_igd_drhd(struct acpi_drhd_unit *drhd); +/*RMRR units derived from command line rmrr option */ +#define MAX_MISC_RMRR_DEV 20 +struct misc_rmrr_unit { + struct list_head list; + u64 base_address; + u64 end_address; + u16 segment; + u16 devices[MAX_MISC_RMRR_DEV]; + u16 dev_count; +}; + #endif /* _DMAR_H_ */ -- 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 |