- fix the mapping range (end_bus_number is inclusive)
- fix the mapping base address (shifting segment by 22 was set for
overlapping mappings; assuming the goal was to reduce the virtual
space used when less than 256 busses are present on all segments,
adding logic to determine the smallest possible shift value)
- fix PCI_MCFG_VIRT_END, and actually use it to avoid creating mappings
outside the designated range
- fix address calculations (segment numbers must be converted to long
to avoid truncation)
- add a way (command line option) to suppress the use of mmconfig as
well as to actually use the AMD Fam10 special code
- correct __init annotations
- use xmalloc()/xmalloc_array() in favor of xmalloc_bytes()
- eliminate dead code and data
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
--- 2009-08-18.orig/xen/arch/x86/x86_64/acpi_mmcfg.c 2009-09-04
14:23:19.000000000 +0200
+++ 2009-08-18/xen/arch/x86/x86_64/acpi_mmcfg.c 2009-09-04 12:38:10.000000000
+0200
@@ -48,13 +48,10 @@
struct acpi_mcfg_allocation *pci_mmcfg_config;
int pci_mmcfg_config_num;
-static int acpi_mcfg_64bit_base_addr __initdata = FALSE;
-
-int acpi_parse_mcfg(struct acpi_table_header *header)
+int __init acpi_parse_mcfg(struct acpi_table_header *header)
{
struct acpi_table_mcfg *mcfg;
unsigned long i;
- int config_size;
if (!header)
return -EINVAL;
@@ -73,19 +70,19 @@ int acpi_parse_mcfg(struct acpi_table_he
return -ENODEV;
}
- config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config);
- pci_mmcfg_config = xmalloc_bytes(config_size);
+ pci_mmcfg_config = xmalloc_array(struct acpi_mcfg_allocation,
+ pci_mmcfg_config_num);
if (!pci_mmcfg_config) {
printk(KERN_WARNING PREFIX
"No memory for MCFG config tables\n");
return -ENOMEM;
}
- memcpy(pci_mmcfg_config, &mcfg[1], config_size);
+ memcpy(pci_mmcfg_config, &mcfg[1],
+ pci_mmcfg_config_num * sizeof(*pci_mmcfg_config));
for (i = 0; i < pci_mmcfg_config_num; ++i) {
- if ((pci_mmcfg_config[i].address > 0xFFFFFFFF) &&
- !acpi_mcfg_64bit_base_addr) {
+ if (pci_mmcfg_config[i].address > 0xFFFFFFFF) {
printk(KERN_ERR PREFIX
"MMCONFIG not in low 4GB of memory\n");
xfree(pci_mmcfg_config);
--- 2009-08-18.orig/xen/arch/x86/x86_64/mmconfig.h 2009-09-04
12:32:49.000000000 +0200
+++ 2009-08-18/xen/arch/x86/x86_64/mmconfig.h 2009-09-04 12:38:10.000000000
+0200
@@ -81,7 +81,7 @@ static inline void mmio_config_writel(vo
extern int pci_mmcfg_config_num;
extern struct acpi_mcfg_allocation *pci_mmcfg_config;
-/* fucntion prototypes */
-int __init acpi_parse_mcfg(struct acpi_table_header *header);
-int __init pci_mmcfg_arch_init(void);
-void __init pci_mmcfg_arch_free(void);
+/* function prototypes */
+int acpi_parse_mcfg(struct acpi_table_header *header);
+int pci_mmcfg_arch_init(void);
+void pci_mmcfg_arch_free(void);
--- 2009-08-18.orig/xen/arch/x86/x86_64/mmconfig-shared.c 2009-09-04
12:30:42.000000000 +0200
+++ 2009-08-18/xen/arch/x86/x86_64/mmconfig-shared.c 2009-09-04
13:35:07.000000000 +0200
@@ -24,7 +24,27 @@
#include "mmconfig.h"
static int __initdata known_bridge;
-unsigned int pci_probe = PCI_PROBE_CONF1 | PCI_PROBE_MMCONF;
+static unsigned int pci_probe = PCI_PROBE_CONF1 | PCI_PROBE_MMCONF;
+
+static void __init parse_mmcfg(char *s)
+{
+ char *ss;
+
+ do {
+ ss = strchr(s, ',');
+ if ( ss )
+ *ss = '\0';
+
+ if ( !strcmp(s, "off") || !strcmp(s, "no") || !strcmp(s, "false") ||
+ !strcmp(s, "0") || !strcmp(s, "disable") )
+ pci_probe &= ~PCI_PROBE_MMCONF;
+ else if ( !strcmp(s, "amd_fam10") || !strcmp(s, "amd-fam10") )
+ pci_probe |= PCI_CHECK_ENABLE_AMD_MMCONF;
+
+ s = ss + 1;
+ } while ( ss );
+}
+custom_param("mmcfg", parse_mmcfg);
static const char __init *pci_mmcfg_e7520(void)
{
@@ -36,7 +56,7 @@ static const char __init *pci_mmcfg_e752
pci_mmcfg_config_num = 0;
else {
pci_mmcfg_config_num = 1;
- pci_mmcfg_config = xmalloc_bytes(sizeof(pci_mmcfg_config[0]));
+ pci_mmcfg_config = xmalloc(struct acpi_mcfg_allocation);
if (!pci_mmcfg_config)
return NULL;
memset(pci_mmcfg_config, 0, sizeof(pci_mmcfg_config[0]));
@@ -90,7 +110,7 @@ static const char __init *pci_mmcfg_inte
pci_mmcfg_config_num = 0;
if (pci_mmcfg_config_num) {
- pci_mmcfg_config = xmalloc_bytes(sizeof(pci_mmcfg_config[0]));
+ pci_mmcfg_config = xmalloc(struct acpi_mcfg_allocation);
if (!pci_mmcfg_config)
return NULL;
memset(pci_mmcfg_config, 0, sizeof(pci_mmcfg_config[0]));
@@ -143,13 +163,13 @@ static const char __init *pci_mmcfg_amd_
}
pci_mmcfg_config_num = (1 << segnbits);
- pci_mmcfg_config = xmalloc_bytes(sizeof(pci_mmcfg_config[0]) *
+ pci_mmcfg_config = xmalloc_array(struct acpi_mcfg_allocation,
pci_mmcfg_config_num);
if (!pci_mmcfg_config)
return NULL;
for (i = 0; i < (1 << segnbits); i++) {
- pci_mmcfg_config[i].address = base + (1<<28) * i;
+ pci_mmcfg_config[i].address = base + ((unsigned long)i << 28);
pci_mmcfg_config[i].pci_segment = i;
pci_mmcfg_config[i].start_bus_number = 0;
pci_mmcfg_config[i].end_bus_number = (1 << busnbits) - 1;
@@ -334,7 +354,7 @@ static int __init is_mmconf_reserved(
return valid;
}
-static void __init pci_mmcfg_reject_broken(int early)
+static void __init pci_mmcfg_reject_broken(void)
{
typeof(pci_mmcfg_config[0]) *cfg;
int i;
@@ -347,7 +367,6 @@ static void __init pci_mmcfg_reject_brok
cfg = &pci_mmcfg_config[0];
for (i = 0; i < pci_mmcfg_config_num; i++) {
- int valid = 0;
u64 addr, size;
cfg = &pci_mmcfg_config[i];
@@ -362,17 +381,7 @@ static void __init pci_mmcfg_reject_brok
(unsigned int)cfg->start_bus_number,
(unsigned int)cfg->end_bus_number);
- if (valid)
- continue;
-
- if (!early)
- printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %lx is not"
- " reserved in ACPI motherboard resources\n",
- cfg->address);
-
- valid = is_mmconf_reserved(e820_all_mapped, addr, size, i, cfg, 1);
-
- if (!valid)
+ if (!is_mmconf_reserved(e820_all_mapped, addr, size, i, cfg, 1))
goto reject;
}
@@ -386,28 +395,26 @@ reject:
pci_mmcfg_config_num = 0;
}
-void __init __pci_mmcfg_init(int early)
+void __init acpi_mmcfg_init(void)
{
/* MMCONFIG disabled */
if ((pci_probe & PCI_PROBE_MMCONF) == 0)
return;
/* MMCONFIG already enabled */
- if (!early && !(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
+ if (!(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
return;
/* for late to exit */
if (known_bridge)
return;
- if (early) {
- if (pci_mmcfg_check_hostbridge())
- known_bridge = 1;
- }
+ if (pci_mmcfg_check_hostbridge())
+ known_bridge = 1;
if (!known_bridge) {
acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
- pci_mmcfg_reject_broken(early);
+ pci_mmcfg_reject_broken();
}
if ((pci_mmcfg_config_num == 0) ||
@@ -420,11 +427,6 @@ void __init __pci_mmcfg_init(int early)
}
}
-void acpi_mmcfg_init(void)
-{
- __pci_mmcfg_init(1);
-}
-
/**
* pci_find_ext_capability - Find an extended capability
* @dev: PCI device to query
--- 2009-08-18.orig/xen/arch/x86/x86_64/mmconfig_64.c 2009-09-04
14:23:19.000000000 +0200
+++ 2009-08-18/xen/arch/x86/x86_64/mmconfig_64.c 2009-09-04
14:30:10.000000000 +0200
@@ -21,6 +21,7 @@ struct mmcfg_virt {
char __iomem *virt;
};
static struct mmcfg_virt *pci_mmcfg_virt;
+static int __initdata mmcfg_pci_segment_shift;
static char __iomem *get_virt(unsigned int seg, unsigned bus)
{
@@ -109,27 +110,26 @@ int pci_mmcfg_write(unsigned int seg, un
static void __iomem * __init mcfg_ioremap(struct acpi_mcfg_allocation *cfg)
{
- void __iomem *addr;
- unsigned long virt;
- unsigned long mfn;
- unsigned long size, nr_mfn;
-
- virt = PCI_MCFG_VIRT_START + (cfg->pci_segment * (1 << 22)) +
- (cfg->start_bus_number * (1 << 20));
- mfn = cfg->address >> PAGE_SHIFT;
- size = (cfg->end_bus_number - cfg->start_bus_number) << 20;
- nr_mfn = size >> PAGE_SHIFT;
+ unsigned long virt, size;
- map_pages_to_xen(virt, mfn, nr_mfn, PAGE_HYPERVISOR_NOCACHE);
- addr = (void __iomem *) virt;
+ virt = PCI_MCFG_VIRT_START +
+ ((unsigned long)cfg->pci_segment << mmcfg_pci_segment_shift) +
+ (cfg->start_bus_number << 20);
+ size = (cfg->end_bus_number - cfg->start_bus_number + 1) << 20;
+ if (virt + size < virt || virt + size > PCI_MCFG_VIRT_END)
+ return NULL;
+
+ map_pages_to_xen(virt, cfg->address >> PAGE_SHIFT,
+ size >> PAGE_SHIFT, PAGE_HYPERVISOR_NOCACHE);
- return addr;
+ return (void __iomem *) virt;
}
int __init pci_mmcfg_arch_init(void)
{
int i;
- pci_mmcfg_virt = xmalloc_bytes(sizeof(*pci_mmcfg_virt) *
pci_mmcfg_config_num);
+
+ pci_mmcfg_virt = xmalloc_array(struct mmcfg_virt, pci_mmcfg_config_num);
if (pci_mmcfg_virt == NULL) {
printk(KERN_ERR "PCI: Can not allocate memory for mmconfig
structures\n");
return 0;
@@ -138,6 +138,11 @@ int __init pci_mmcfg_arch_init(void)
for (i = 0; i < pci_mmcfg_config_num; ++i) {
pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
+ while (pci_mmcfg_config[i].end_bus_number >> mmcfg_pci_segment_shift)
+ ++mmcfg_pci_segment_shift;
+ }
+ mmcfg_pci_segment_shift += 20;
+ for (i = 0; i < pci_mmcfg_config_num; ++i) {
pci_mmcfg_virt[i].virt = mcfg_ioremap(&pci_mmcfg_config[i]);
if (!pci_mmcfg_virt[i].virt) {
printk(KERN_ERR "PCI: Cannot map mmconfig aperture for "
--- 2009-08-18.orig/xen/include/asm-x86/config.h 2009-09-04
14:01:23.000000000 +0200
+++ 2009-08-18/xen/include/asm-x86/config.h 2009-09-04 14:15:36.000000000
+0200
@@ -194,7 +194,7 @@ extern unsigned int video_mode, video_fl
* - since PML4 slot has 39 bits, we limit segments to 2048 (11-bits)
*/
#define PCI_MCFG_VIRT_START (PML4_ADDR(257))
-#define PCI_MCFG_VIRT_END (RDWR_MPT_VIRT_START + PML4_ENTRY_BYTES)
+#define PCI_MCFG_VIRT_END (PCI_MCFG_VIRT_START + PML4_ENTRY_BYTES)
/* Slot 258: linear page table (guest table). */
#define LINEAR_PT_VIRT_START (PML4_ADDR(258))
#define LINEAR_PT_VIRT_END (LINEAR_PT_VIRT_START + PML4_ENTRY_BYTES)
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|