mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
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@novell.com>
This commit is contained in:
1 parent
6067ef23ef
commit
94ea0622c5
3 files changed
+96
-3
No files matched your search
@@ -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;
|
||||
|
||||
@@ -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_table_header *header)
|
||||
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;
|
||||
|
||||
@@ -36,6 +36,7 @@ extern int dmi_check_system(struct dmi_system_id *list);
|
||||
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__ */
|
||||