- 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@novell.com> --- 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@lists.xensource.com http://lists.xensource.com/xen-devel