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

[Xen-devel] [PATCH] x86-64/mmcfg: relax base address restriction



Following what Linux did quite a while ago, don't generally disallow
MMCFG base addresses to live above the 4Gb boundary: New systems are
assumed to be fine, and SGI ones are, too.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>

--- a/xen/arch/x86/dmi_scan.c
+++ b/xen/arch/x86/dmi_scan.c
@@ -520,6 +520,76 @@ fail:              d++;
        return count;
 }
 
+/**
+ *     dmi_get_date - parse a DMI date
+ *     @field: data index (see enum dmi_field)
+ *     @yearp: optional out parameter for the year
+ *     @monthp: optional out parameter for the month
+ *     @dayp: optional out parameter for the day
+ *
+ *     The date field is assumed to be in the form resembling
+ *     [mm[/dd]]/yy[yy] and the result is stored in the out
+ *     parameters any or all of which can be omitted.
+ *
+ *     If the field doesn't exist, all out parameters are set to zero
+ *     and false is returned.  Otherwise, true is returned with any
+ *     invalid part of date set to zero.
+ *
+ *     On return, year, month and day are guaranteed to be in the
+ *     range of [0,9999], [0,12] and [0,31] respectively.
+ */
+bool_t __init dmi_get_date(int field, int *yearp, int *monthp, int *dayp)
+{
+       int year = 0, month = 0, day = 0;
+       bool_t exists;
+       const char *s, *e, *y;
+
+       s = field < DMI_STRING_MAX ? dmi_ident[field] : NULL;
+       exists = !!s;
+       if (!exists)
+               goto out;
+
+       /*
+        * Determine year first.  We assume the date string resembles
+        * mm/dd/yy[yy] but the original code extracted only the year
+        * from the end.  Keep the behavior in the spirit of no
+        * surprises.
+        */
+       y = strrchr(s, '/');
+       if (!y)
+               goto out;
+
+       y++;
+       year = simple_strtoul(y, &e, 10);
+       if (y != e && year < 100) {     /* 2-digit year */
+               year += 1900;
+               if (year < 1996)        /* no dates < spec 1.0 */
+                       year += 100;
+       }
+       if (year > 9999)                /* year should fit in %04d */
+               year = 0;
+
+       /* parse the mm and dd */
+       month = simple_strtoul(s, &e, 10);
+       if (s == e || *e != '/' || !month || month > 12) {
+               month = 0;
+               goto out;
+       }
+
+       s = e + 1;
+       day = simple_strtoul(s, &e, 10);
+       if (s == y || s == e || *e != '/' || day > 31)
+               day = 0;
+out:
+       if (yearp)
+               *yearp = year;
+       if (monthp)
+               *monthp = month;
+       if (dayp)
+               *dayp = day;
+       return exists;
+}
+
 void __init dmi_end_boot(void)
 {
     unsigned int i;
--- a/xen/arch/x86/x86_64/acpi_mmcfg.c
+++ b/xen/arch/x86/x86_64/acpi_mmcfg.c
@@ -48,6 +48,30 @@
 struct acpi_mcfg_allocation *pci_mmcfg_config;
 int pci_mmcfg_config_num;
 
+static int __init acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg,
+                                        struct acpi_mcfg_allocation *cfg)
+{
+    int year;
+
+    if (cfg->address < 0xFFFFFFFF)
+        return 0;
+
+    if (!strcmp(mcfg->header.oem_id, "SGI") ||
+        !strcmp(mcfg->header.oem_id, "SGI2"))
+        return 0;
+
+    if (mcfg->header.revision >= 1 &&
+        dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) &&
+        year >= 2010)
+            return 0;
+
+    printk(KERN_ERR "MCFG region for %04x:%02x-%02x at %#"PRIx64
+                    " (above 4GB) ignored\n",
+           cfg->pci_segment, cfg->start_bus_number, cfg->end_bus_number,
+           cfg->address);
+    return -EINVAL;
+}
+
 int __init acpi_parse_mcfg(struct acpi_table_header *header)
 {
     struct acpi_table_mcfg *mcfg;
@@ -82,9 +106,7 @@ int __init acpi_parse_mcfg(struct acpi_t
            pci_mmcfg_config_num * sizeof(*pci_mmcfg_config));
 
     for (i = 0; i < pci_mmcfg_config_num; ++i) {
-        if (pci_mmcfg_config[i].address > 0xFFFFFFFF) {
-            printk(KERN_ERR PREFIX
-                   "MMCONFIG not in low 4GB of memory\n");
+        if (acpi_mcfg_check_entry(mcfg, &pci_mmcfg_config[i])) {
             xfree(pci_mmcfg_config);
             pci_mmcfg_config_num = 0;
             return -ENODEV;
--- a/xen/include/xen/dmi.h
+++ b/xen/include/xen/dmi.h
@@ -36,6 +36,7 @@ extern int dmi_check_system(struct dmi_s
 extern void dmi_scan_machine(void);
 extern int dmi_get_table(u32 *base, u32 *len);
 extern void dmi_efi_get_table(void *);
+bool_t dmi_get_date(int field, int *yearp, int *monthp, int *dayp);
 extern void dmi_end_boot(void);
 
 #endif /* __DMI_H__ */


Attachment: x86_64-mmcfg-64bit.patch
Description: Text document

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

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