ia64/xen-unstable

changeset 19697:42fe00c6f8b4

Enable pci mmcfg and ATS for x86_64

This patch enables PCI MMCONFIG in xen and turns on hooks for ATS.

Signed-off-by: Allen Kay <allen.m.kay@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jun 02 11:49:34 2009 +0100 (2009-06-02)
parents 4294a04b24bc
children f72d26c00002
files xen/arch/x86/acpi/boot.c xen/arch/x86/e820.c xen/arch/x86/pci.c xen/arch/x86/traps.c xen/arch/x86/x86_32/Makefile xen/arch/x86/x86_32/pci.c xen/arch/x86/x86_64/Makefile xen/arch/x86/x86_64/acpi_mmcfg.c xen/arch/x86/x86_64/mmconfig-shared.c xen/arch/x86/x86_64/mmconfig.h xen/arch/x86/x86_64/mmconfig_64.c xen/arch/x86/x86_64/pci.c xen/drivers/passthrough/vtd/extern.h xen/drivers/passthrough/vtd/ia64/ats.c xen/drivers/passthrough/vtd/iommu.c xen/drivers/passthrough/vtd/qinval.c xen/drivers/passthrough/vtd/x86/ats.c xen/include/asm-x86/acpi.h xen/include/asm-x86/config.h xen/include/asm-x86/e820.h xen/include/asm-x86/msr-index.h xen/include/xen/pci.h
line diff
     1.1 --- a/xen/arch/x86/acpi/boot.c	Mon Jun 01 18:37:27 2009 +0100
     1.2 +++ b/xen/arch/x86/acpi/boot.c	Tue Jun 02 11:49:34 2009 +0100
     1.3 @@ -937,6 +937,8 @@ int __init acpi_boot_init(void)
     1.4  
     1.5  	acpi_dmar_init();
     1.6  
     1.7 +	acpi_mmcfg_init();
     1.8 +
     1.9  	return 0;
    1.10  }
    1.11  
     2.1 --- a/xen/arch/x86/e820.c	Mon Jun 01 18:37:27 2009 +0100
     2.2 +++ b/xen/arch/x86/e820.c	Tue Jun 02 11:49:34 2009 +0100
     2.3 @@ -25,6 +25,40 @@ boolean_param("e820-verbose", e820_verbo
     2.4  
     2.5  struct e820map e820;
     2.6  
     2.7 +/*
     2.8 + * This function checks if the entire range <start,end> is mapped with type.
     2.9 + *
    2.10 + * Note: this function only works correct if the e820 table is sorted and
    2.11 + * not-overlapping, which is the case
    2.12 + */
    2.13 +int __init e820_all_mapped(u64 start, u64 end, unsigned type)
    2.14 +{
    2.15 +	int i;
    2.16 +
    2.17 +	for (i = 0; i < e820.nr_map; i++) {
    2.18 +		struct e820entry *ei = &e820.map[i];
    2.19 +
    2.20 +		if (type && ei->type != type)
    2.21 +			continue;
    2.22 +		/* is the region (part) in overlap with the current region ?*/
    2.23 +		if (ei->addr >= end || ei->addr + ei->size <= start)
    2.24 +			continue;
    2.25 +
    2.26 +		/* if the region is at the beginning of <start,end> we move
    2.27 +		 * start to the end of the region since it's ok until there
    2.28 +		 */
    2.29 +		if (ei->addr <= start)
    2.30 +			start = ei->addr + ei->size;
    2.31 +		/*
    2.32 +		 * if start is now at or beyond end, we're done, full
    2.33 +		 * coverage
    2.34 +		 */
    2.35 +		if (start >= end)
    2.36 +			return 1;
    2.37 +	}
    2.38 +	return 0;
    2.39 +}
    2.40 +
    2.41  static void __init add_memory_region(unsigned long long start,
    2.42                                       unsigned long long size, int type)
    2.43  {
     3.1 --- a/xen/arch/x86/pci.c	Mon Jun 01 18:37:27 2009 +0100
     3.2 +++ b/xen/arch/x86/pci.c	Tue Jun 02 11:49:34 2009 +0100
     3.3 @@ -7,9 +7,6 @@
     3.4  #include <xen/spinlock.h>
     3.5  #include <asm/io.h>
     3.6  
     3.7 -#define PCI_CONF_ADDRESS(bus, dev, func, reg) \
     3.8 -    (0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg & ~3))
     3.9 -
    3.10  static DEFINE_SPINLOCK(pci_config_lock);
    3.11  
    3.12  uint32_t pci_conf_read(uint32_t cf8, uint8_t offset, uint8_t bytes)
    3.13 @@ -69,49 +66,3 @@ void pci_conf_write(uint32_t cf8, uint8_
    3.14  
    3.15      spin_unlock_irqrestore(&pci_config_lock, flags);
    3.16  }
    3.17 -
    3.18 -uint8_t pci_conf_read8(
    3.19 -    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
    3.20 -{
    3.21 -    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
    3.22 -    return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1);
    3.23 -}
    3.24 -
    3.25 -uint16_t pci_conf_read16(
    3.26 -    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
    3.27 -{
    3.28 -    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
    3.29 -    return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2);
    3.30 -}
    3.31 -
    3.32 -uint32_t pci_conf_read32(
    3.33 -    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
    3.34 -{
    3.35 -    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
    3.36 -    return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4);
    3.37 -}
    3.38 -
    3.39 -void pci_conf_write8(
    3.40 -    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
    3.41 -    uint8_t data)
    3.42 -{
    3.43 -    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
    3.44 -    pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1, data);
    3.45 -}
    3.46 -
    3.47 -void pci_conf_write16(
    3.48 -    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
    3.49 -    uint16_t data)
    3.50 -{
    3.51 -    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
    3.52 -    pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2, data);
    3.53 -}
    3.54 -
    3.55 -void pci_conf_write32(
    3.56 -    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
    3.57 -    uint32_t data)
    3.58 -{
    3.59 -    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
    3.60 -    pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4, data);
    3.61 -}
    3.62 -
     4.1 --- a/xen/arch/x86/traps.c	Mon Jun 01 18:37:27 2009 +0100
     4.2 +++ b/xen/arch/x86/traps.c	Tue Jun 02 11:49:34 2009 +0100
     4.3 @@ -2186,7 +2186,7 @@ static int emulate_privileged_op(struct 
     4.4                  break;
     4.5              if ( (rdmsr_safe(MSR_FAM10H_MMIO_CONF_BASE, l, h) != 0) ||
     4.6                   (((((u64)h << 32) | l) ^ res) &
     4.7 -                  ~((1 << FAM10H_MMIO_CONF_ENABLE_BIT) |
     4.8 +                  ~( FAM10H_MMIO_CONF_ENABLE |
     4.9                      (FAM10H_MMIO_CONF_BUSRANGE_MASK <<
    4.10                       FAM10H_MMIO_CONF_BUSRANGE_SHIFT) |
    4.11                      ((u64)FAM10H_MMIO_CONF_BASE_MASK <<
     5.1 --- a/xen/arch/x86/x86_32/Makefile	Mon Jun 01 18:37:27 2009 +0100
     5.2 +++ b/xen/arch/x86/x86_32/Makefile	Tue Jun 02 11:49:34 2009 +0100
     5.3 @@ -5,6 +5,7 @@ obj-y += mm.o
     5.4  obj-y += seg_fixup.o
     5.5  obj-y += traps.o
     5.6  obj-y += machine_kexec.o
     5.7 +obj-y += pci.o
     5.8  
     5.9  obj-$(crash_debug) += gdbstub.o
    5.10  
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xen/arch/x86/x86_32/pci.c	Tue Jun 02 11:49:34 2009 +0100
     6.3 @@ -0,0 +1,70 @@
     6.4 +/******************************************************************************
     6.5 + * pci.c
     6.6 + * 
     6.7 + * Architecture-dependent PCI access functions.
     6.8 + */
     6.9 +
    6.10 +#include <xen/spinlock.h>
    6.11 +#include <xen/pci.h>
    6.12 +#include <asm/io.h>
    6.13 +
    6.14 +#define PCI_CONF_ADDRESS(bus, dev, func, reg) \
    6.15 +    (0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg & ~3))
    6.16 +
    6.17 +uint32_t pci_conf_read(uint32_t cf8, uint8_t offset, uint8_t bytes);
    6.18 +void pci_conf_write(uint32_t cf8, uint8_t offset, uint8_t bytes, uint32_t data);
    6.19 +
    6.20 +uint8_t pci_conf_read8(
    6.21 +    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
    6.22 +{
    6.23 +    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
    6.24 +    return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1);
    6.25 +}
    6.26 +
    6.27 +uint16_t pci_conf_read16(
    6.28 +    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
    6.29 +{
    6.30 +    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
    6.31 +    return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2);
    6.32 +}
    6.33 +
    6.34 +uint32_t pci_conf_read32(
    6.35 +    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
    6.36 +{
    6.37 +    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
    6.38 +    return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4);
    6.39 +}
    6.40 +
    6.41 +void pci_conf_write8(
    6.42 +    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
    6.43 +    uint8_t data)
    6.44 +{
    6.45 +    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
    6.46 +    pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1, data);
    6.47 +}
    6.48 +
    6.49 +void pci_conf_write16(
    6.50 +    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
    6.51 +    uint16_t data)
    6.52 +{
    6.53 +    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
    6.54 +    pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2, data);
    6.55 +}
    6.56 +
    6.57 +void pci_conf_write32(
    6.58 +    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
    6.59 +    uint32_t data)
    6.60 +{
    6.61 +    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
    6.62 +    pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4, data);
    6.63 +}
    6.64 +
    6.65 +int pci_find_ext_capability(int seg, int bus, int devfn, int cap)
    6.66 +{
    6.67 +    return 0;
    6.68 +}
    6.69 +
    6.70 +void acpi_mmcfg_init(void)
    6.71 +{
    6.72 +    return;
    6.73 +}
     7.1 --- a/xen/arch/x86/x86_64/Makefile	Mon Jun 01 18:37:27 2009 +0100
     7.2 +++ b/xen/arch/x86/x86_64/Makefile	Tue Jun 02 11:49:34 2009 +0100
     7.3 @@ -5,6 +5,10 @@ obj-y += gpr_switch.o
     7.4  obj-y += mm.o
     7.5  obj-y += traps.o
     7.6  obj-y += machine_kexec.o
     7.7 +obj-y += pci.o
     7.8 +obj-y += acpi_mmcfg.o
     7.9 +obj-y += mmconfig_64.o
    7.10 +obj-y += mmconfig-shared.o
    7.11  
    7.12  obj-$(crash_debug)   += gdbstub.o
    7.13  obj-$(CONFIG_COMPAT) += compat.o
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/xen/arch/x86/x86_64/acpi_mmcfg.c	Tue Jun 02 11:49:34 2009 +0100
     8.3 @@ -0,0 +1,98 @@
     8.4 +/*
     8.5 + *  acpi_mmconfig.c - Architecture-Specific Low-Level ACPI Boot Support
     8.6 + *
     8.7 + *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
     8.8 + *  Copyright (C) 2001 Jun Nakajima <jun.nakajima@intel.com>
     8.9 + *
    8.10 + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    8.11 + *
    8.12 + *  This program is free software; you can redistribute it and/or modify
    8.13 + *  it under the terms of the GNU General Public License as published by
    8.14 + *  the Free Software Foundation; either version 2 of the License, or
    8.15 + *  (at your option) any later version.
    8.16 + *
    8.17 + *  This program is distributed in the hope that it will be useful,
    8.18 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.19 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.20 + *  GNU General Public License for more details.
    8.21 + *
    8.22 + *  You should have received a copy of the GNU General Public License
    8.23 + *  along with this program; if not, write to the Free Software
    8.24 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    8.25 + *
    8.26 + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    8.27 + *
    8.28 + * copied from Linux
    8.29 + */
    8.30 +
    8.31 +#include <xen/config.h>
    8.32 +#include <xen/errno.h>
    8.33 +#include <xen/init.h>
    8.34 +#include <xen/acpi.h>
    8.35 +#include <xen/irq.h>
    8.36 +#include <xen/dmi.h>
    8.37 +#include <asm/fixmap.h>
    8.38 +#include <asm/page.h>
    8.39 +#include <asm/apic.h>
    8.40 +#include <asm/io_apic.h>
    8.41 +#include <asm/apic.h>
    8.42 +#include <asm/io.h>
    8.43 +#include <asm/mpspec.h>
    8.44 +#include <asm/processor.h>
    8.45 +#include <mach_apic.h>
    8.46 +#include <mach_mpparse.h>
    8.47 +
    8.48 +#include "mmconfig.h"
    8.49 +
    8.50 +/* The physical address of the MMCONFIG aperture.  Set from ACPI tables. */
    8.51 +struct acpi_mcfg_allocation *pci_mmcfg_config;
    8.52 +int pci_mmcfg_config_num;
    8.53 +
    8.54 +static int acpi_mcfg_64bit_base_addr __initdata = FALSE;
    8.55 +
    8.56 +int acpi_parse_mcfg(struct acpi_table_header *header)
    8.57 +{
    8.58 +    struct acpi_table_mcfg *mcfg;
    8.59 +    unsigned long i;
    8.60 +    int config_size;
    8.61 +
    8.62 +    if (!header)
    8.63 +        return -EINVAL;
    8.64 +
    8.65 +    mcfg = (struct acpi_table_mcfg *)header;
    8.66 +
    8.67 +    /* how many config structures do we have */
    8.68 +    pci_mmcfg_config_num = 0;
    8.69 +    i = header->length - sizeof(struct acpi_table_mcfg);
    8.70 +    while (i >= sizeof(struct acpi_mcfg_allocation)) {
    8.71 +        ++pci_mmcfg_config_num;
    8.72 +        i -= sizeof(struct acpi_mcfg_allocation);
    8.73 +    };
    8.74 +    if (pci_mmcfg_config_num == 0) {
    8.75 +        printk(KERN_ERR PREFIX "MMCONFIG has no entries\n");
    8.76 +        return -ENODEV;
    8.77 +    }
    8.78 +
    8.79 +    config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config);
    8.80 +    pci_mmcfg_config = xmalloc_bytes(config_size);
    8.81 +    if (!pci_mmcfg_config) {
    8.82 +        printk(KERN_WARNING PREFIX
    8.83 +               "No memory for MCFG config tables\n");
    8.84 +        return -ENOMEM;
    8.85 +    }
    8.86 +
    8.87 +    memcpy(pci_mmcfg_config, &mcfg[1], config_size);
    8.88 +
    8.89 +    for (i = 0; i < pci_mmcfg_config_num; ++i) {
    8.90 +        if ((pci_mmcfg_config[i].address > 0xFFFFFFFF) &&
    8.91 +            !acpi_mcfg_64bit_base_addr) {
    8.92 +            printk(KERN_ERR PREFIX
    8.93 +                   "MMCONFIG not in low 4GB of memory\n");
    8.94 +            xfree(pci_mmcfg_config);
    8.95 +            pci_mmcfg_config_num = 0;
    8.96 +            return -ENODEV;
    8.97 +        }
    8.98 +    }
    8.99 +
   8.100 +    return 0;
   8.101 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xen/arch/x86/x86_64/mmconfig-shared.c	Tue Jun 02 11:49:34 2009 +0100
     9.3 @@ -0,0 +1,382 @@
     9.4 +/*
     9.5 + * mmconfig-shared.c - Low-level direct PCI config space access via
     9.6 + *                     MMCONFIG - common code between i386 and x86-64.
     9.7 + *
     9.8 + * This code does:
     9.9 + * - known chipset handling
    9.10 + * - ACPI decoding and validation
    9.11 + *
    9.12 + * Per-architecture code takes care of the mappings and accesses
    9.13 + * themselves.
    9.14 + *
    9.15 + * Author: Allen Kay <allen.m.kay@intel.com> -  adapted to xen from Linux
    9.16 + */
    9.17 +
    9.18 +#include <xen/mm.h>
    9.19 +#include <xen/acpi.h>
    9.20 +#include <xen/xmalloc.h>
    9.21 +#include <xen/pci.h>
    9.22 +#include <xen/pci_regs.h>
    9.23 +#include <asm/e820.h>
    9.24 +#include <asm/msr.h>
    9.25 +#include <asm/msr-index.h>
    9.26 +
    9.27 +#include "mmconfig.h"
    9.28 +
    9.29 +static int __initdata known_bridge;
    9.30 +unsigned int pci_probe = PCI_PROBE_CONF1 | PCI_PROBE_MMCONF;
    9.31 +
    9.32 +static const char __init *pci_mmcfg_e7520(void)
    9.33 +{
    9.34 +    u32 win;
    9.35 +    win = pci_conf_read16(0, 0, 0, 0xce);
    9.36 +
    9.37 +    win = win & 0xf000;
    9.38 +    if(win == 0x0000 || win == 0xf000)
    9.39 +        pci_mmcfg_config_num = 0;
    9.40 +    else {
    9.41 +        pci_mmcfg_config_num = 1;
    9.42 +        pci_mmcfg_config = xmalloc_bytes(sizeof(pci_mmcfg_config[0]));
    9.43 +        if (!pci_mmcfg_config)
    9.44 +            return NULL;
    9.45 +        memset(pci_mmcfg_config, 0, sizeof(pci_mmcfg_config[0]));
    9.46 +        pci_mmcfg_config[0].address = win << 16;
    9.47 +        pci_mmcfg_config[0].pci_segment = 0;
    9.48 +        pci_mmcfg_config[0].start_bus_number = 0;
    9.49 +        pci_mmcfg_config[0].end_bus_number = 255;
    9.50 +    }
    9.51 +
    9.52 +    return "Intel Corporation E7520 Memory Controller Hub";
    9.53 +}
    9.54 +
    9.55 +static const char __init *pci_mmcfg_intel_945(void)
    9.56 +{
    9.57 +    u32 pciexbar, mask = 0, len = 0;
    9.58 +
    9.59 +    pci_mmcfg_config_num = 1;
    9.60 +
    9.61 +        pciexbar = pci_conf_read32(0, 0, 0, 0x48);
    9.62 +
    9.63 +    /* Enable bit */
    9.64 +    if (!(pciexbar & 1))
    9.65 +        pci_mmcfg_config_num = 0;
    9.66 +
    9.67 +    /* Size bits */
    9.68 +    switch ((pciexbar >> 1) & 3) {
    9.69 +    case 0:
    9.70 +        mask = 0xf0000000U;
    9.71 +        len  = 0x10000000U;
    9.72 +        break;
    9.73 +    case 1:
    9.74 +        mask = 0xf8000000U;
    9.75 +        len  = 0x08000000U;
    9.76 +        break;
    9.77 +    case 2:
    9.78 +        mask = 0xfc000000U;
    9.79 +        len  = 0x04000000U;
    9.80 +        break;
    9.81 +    default:
    9.82 +        pci_mmcfg_config_num = 0;
    9.83 +    }
    9.84 +
    9.85 +    /* Errata #2, things break when not aligned on a 256Mb boundary */
    9.86 +    /* Can only happen in 64M/128M mode */
    9.87 +
    9.88 +    if ((pciexbar & mask) & 0x0fffffffU)
    9.89 +        pci_mmcfg_config_num = 0;
    9.90 +
    9.91 +    /* Don't hit the APIC registers and their friends */
    9.92 +    if ((pciexbar & mask) >= 0xf0000000U)
    9.93 +        pci_mmcfg_config_num = 0;
    9.94 +
    9.95 +    if (pci_mmcfg_config_num) {
    9.96 +        pci_mmcfg_config = xmalloc_bytes(sizeof(pci_mmcfg_config[0]));
    9.97 +        if (!pci_mmcfg_config)
    9.98 +            return NULL;
    9.99 +        memset(pci_mmcfg_config, 0, sizeof(pci_mmcfg_config[0]));
   9.100 +        pci_mmcfg_config[0].address = pciexbar & mask;
   9.101 +        pci_mmcfg_config[0].pci_segment = 0;
   9.102 +        pci_mmcfg_config[0].start_bus_number = 0;
   9.103 +        pci_mmcfg_config[0].end_bus_number = (len >> 20) - 1;
   9.104 +    }
   9.105 +
   9.106 +    return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
   9.107 +}
   9.108 +
   9.109 +static const char __init *pci_mmcfg_amd_fam10h(void)
   9.110 +{
   9.111 +    u32 low, high, address;
   9.112 +    u64 base, msr;
   9.113 +    int i;
   9.114 +    unsigned segnbits = 0, busnbits;
   9.115 +
   9.116 +    if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF))
   9.117 +        return NULL;
   9.118 +
   9.119 +    address = MSR_FAM10H_MMIO_CONF_BASE;
   9.120 +    if (rdmsr_safe(address, low, high))
   9.121 +        return NULL;
   9.122 +
   9.123 +    msr = high;
   9.124 +    msr <<= 32;
   9.125 +    msr |= low;
   9.126 +
   9.127 +    /* mmconfig is not enable */
   9.128 +    if (!(msr & FAM10H_MMIO_CONF_ENABLE))
   9.129 +        return NULL;
   9.130 +
   9.131 +    base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT);
   9.132 +
   9.133 +    busnbits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) &
   9.134 +                FAM10H_MMIO_CONF_BUSRANGE_MASK;
   9.135 +
   9.136 +    /*
   9.137 +     * only handle bus 0 ?
   9.138 +     * need to skip it
   9.139 +     */
   9.140 +    if (!busnbits)
   9.141 +        return NULL;
   9.142 +
   9.143 +    if (busnbits > 8) {
   9.144 +        segnbits = busnbits - 8;
   9.145 +        busnbits = 8;
   9.146 +    }
   9.147 +
   9.148 +    pci_mmcfg_config_num = (1 << segnbits);
   9.149 +    pci_mmcfg_config = xmalloc_bytes(sizeof(pci_mmcfg_config[0]) *
   9.150 +                                     pci_mmcfg_config_num);
   9.151 +    if (!pci_mmcfg_config)
   9.152 +        return NULL;
   9.153 +
   9.154 +    for (i = 0; i < (1 << segnbits); i++) {
   9.155 +        pci_mmcfg_config[i].address = base + (1<<28) * i;
   9.156 +        pci_mmcfg_config[i].pci_segment = i;
   9.157 +        pci_mmcfg_config[i].start_bus_number = 0;
   9.158 +        pci_mmcfg_config[i].end_bus_number = (1 << busnbits) - 1;
   9.159 +    }
   9.160 +
   9.161 +    return "AMD Family 10h NB";
   9.162 +}
   9.163 +
   9.164 +struct pci_mmcfg_hostbridge_probe {
   9.165 +    u32 bus;
   9.166 +    u32 devfn;
   9.167 +    u32 vendor;
   9.168 +    u32 device;
   9.169 +    const char *(*probe)(void);
   9.170 +};
   9.171 +
   9.172 +static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
   9.173 +    { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL,
   9.174 +      PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
   9.175 +    { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL,
   9.176 +      PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
   9.177 +    { 0, PCI_DEVFN(0x18, 0), PCI_VENDOR_ID_AMD,
   9.178 +      0x1200, pci_mmcfg_amd_fam10h },
   9.179 +    { 0xff, PCI_DEVFN(0, 0), PCI_VENDOR_ID_AMD,
   9.180 +      0x1200, pci_mmcfg_amd_fam10h },
   9.181 +};
   9.182 +
   9.183 +static int __init pci_mmcfg_check_hostbridge(void)
   9.184 +{
   9.185 +    u32 l;
   9.186 +    u32 bus, devfn;
   9.187 +    u16 vendor, device;
   9.188 +    int i;
   9.189 +    const char *name;
   9.190 +
   9.191 +    pci_mmcfg_config_num = 0;
   9.192 +    pci_mmcfg_config = NULL;
   9.193 +    name = NULL;
   9.194 +
   9.195 +    for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
   9.196 +        bus =  pci_mmcfg_probes[i].bus;
   9.197 +        devfn = pci_mmcfg_probes[i].devfn;
   9.198 +        l = pci_conf_read32(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), 0);
   9.199 +        vendor = l & 0xffff;
   9.200 +        device = (l >> 16) & 0xffff;
   9.201 +
   9.202 +        if (pci_mmcfg_probes[i].vendor == vendor &&
   9.203 +            pci_mmcfg_probes[i].device == device)
   9.204 +            name = pci_mmcfg_probes[i].probe();
   9.205 +    }
   9.206 +
   9.207 +    if (name) {
   9.208 +        printk(KERN_INFO "PCI: Found %s %s MMCONFIG support.\n",
   9.209 +            name, pci_mmcfg_config_num ? "with" : "without");
   9.210 +    }
   9.211 +
   9.212 +    return name != NULL;
   9.213 +}
   9.214 +
   9.215 +typedef int (*check_reserved_t)(u64 start, u64 end, unsigned type);
   9.216 +
   9.217 +static int __init is_mmconf_reserved(
   9.218 +    check_reserved_t is_reserved,
   9.219 +    u64 addr, u64 size, int i,
   9.220 +    typeof(pci_mmcfg_config[0]) *cfg, int with_e820)
   9.221 +{
   9.222 +    u64 old_size = size;
   9.223 +    int valid = 0;
   9.224 +
   9.225 +    while (!is_reserved(addr, addr + size - 1, E820_RESERVED)) {
   9.226 +        size >>= 1;
   9.227 +        if (size < (16UL<<20))
   9.228 +            break;
   9.229 +    }
   9.230 +
   9.231 +    if (size >= (16UL<<20) || size == old_size) {
   9.232 +        printk(KERN_NOTICE
   9.233 +               "PCI: MCFG area at %lx reserved in %s\n",
   9.234 +                addr, with_e820?"E820":"ACPI motherboard resources");
   9.235 +        valid = 1;
   9.236 +
   9.237 +        if (old_size != size) {
   9.238 +            /* update end_bus_number */
   9.239 +            cfg->end_bus_number = cfg->start_bus_number + ((size>>20) - 1);
   9.240 +            printk(KERN_NOTICE "PCI: updated MCFG configuration %d: base %lx "
   9.241 +                   "segment %hu buses %u - %u\n",
   9.242 +                   i, (unsigned long)cfg->address, cfg->pci_segment,
   9.243 +                   (unsigned int)cfg->start_bus_number,
   9.244 +                   (unsigned int)cfg->end_bus_number);
   9.245 +        }
   9.246 +    }
   9.247 +
   9.248 +    return valid;
   9.249 +}
   9.250 +
   9.251 +static void __init pci_mmcfg_reject_broken(int early)
   9.252 +{
   9.253 +    typeof(pci_mmcfg_config[0]) *cfg;
   9.254 +    int i;
   9.255 +
   9.256 +    if ((pci_mmcfg_config_num == 0) ||
   9.257 +        (pci_mmcfg_config == NULL) ||
   9.258 +        (pci_mmcfg_config[0].address == 0))
   9.259 +        return;
   9.260 +
   9.261 +    cfg = &pci_mmcfg_config[0];
   9.262 +
   9.263 +    for (i = 0; i < pci_mmcfg_config_num; i++) {
   9.264 +        int valid = 0;
   9.265 +        u64 addr, size;
   9.266 +
   9.267 +        cfg = &pci_mmcfg_config[i];
   9.268 +        addr = cfg->start_bus_number;
   9.269 +        addr <<= 20;
   9.270 +        addr += cfg->address;
   9.271 +        size = cfg->end_bus_number + 1 - cfg->start_bus_number;
   9.272 +        size <<= 20;
   9.273 +        printk(KERN_NOTICE "PCI: MCFG configuration %d: base %lx "
   9.274 +               "segment %hu buses %u - %u\n",
   9.275 +               i, (unsigned long)cfg->address, cfg->pci_segment,
   9.276 +               (unsigned int)cfg->start_bus_number,
   9.277 +               (unsigned int)cfg->end_bus_number);
   9.278 +
   9.279 +        if (valid)
   9.280 +            continue;
   9.281 +
   9.282 +        if (!early)
   9.283 +            printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %lx is not"
   9.284 +                   " reserved in ACPI motherboard resources\n",
   9.285 +                   cfg->address);
   9.286 +
   9.287 +        valid = is_mmconf_reserved(e820_all_mapped, addr, size, i, cfg, 1);
   9.288 +
   9.289 +        if (!valid)
   9.290 +            goto reject;
   9.291 +    }
   9.292 +
   9.293 +    return;
   9.294 +
   9.295 +reject:
   9.296 +    printk(KERN_INFO "PCI: Not using MMCONFIG.\n");
   9.297 +    pci_mmcfg_arch_free();
   9.298 +    xfree(pci_mmcfg_config);
   9.299 +    pci_mmcfg_config = NULL;
   9.300 +    pci_mmcfg_config_num = 0;
   9.301 +}
   9.302 +
   9.303 +void __init __pci_mmcfg_init(int early)
   9.304 +{
   9.305 +    /* MMCONFIG disabled */
   9.306 +    if ((pci_probe & PCI_PROBE_MMCONF) == 0)
   9.307 +        return;
   9.308 +
   9.309 +    /* MMCONFIG already enabled */
   9.310 +    if (!early && !(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
   9.311 +        return;
   9.312 +
   9.313 +    /* for late to exit */
   9.314 +    if (known_bridge)
   9.315 +        return;
   9.316 +
   9.317 +    if (early) {
   9.318 +        if (pci_mmcfg_check_hostbridge())
   9.319 +            known_bridge = 1;
   9.320 +    }
   9.321 +
   9.322 +    if (!known_bridge) {
   9.323 +        acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
   9.324 +        pci_mmcfg_reject_broken(early);
   9.325 +    }
   9.326 +
   9.327 +    if ((pci_mmcfg_config_num == 0) ||
   9.328 +        (pci_mmcfg_config == NULL) ||
   9.329 +        (pci_mmcfg_config[0].address == 0))
   9.330 +        return;
   9.331 +
   9.332 +    if (pci_mmcfg_arch_init()) {
   9.333 +        pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
   9.334 +    }
   9.335 +}
   9.336 +
   9.337 +void acpi_mmcfg_init(void)
   9.338 +{
   9.339 +    __pci_mmcfg_init(1);
   9.340 +}
   9.341 +
   9.342 +/**
   9.343 + * pci_find_ext_capability - Find an extended capability
   9.344 + * @dev: PCI device to query
   9.345 + * @cap: capability code
   9.346 + *
   9.347 + * Returns the address of the requested extended capability structure
   9.348 + * within the device's PCI configuration space or 0 if the device does
   9.349 + * not support it.  Possible values for @cap:
   9.350 + *
   9.351 + *  %PCI_EXT_CAP_ID_ERR         Advanced Error Reporting
   9.352 + *  %PCI_EXT_CAP_ID_VC          Virtual Channel
   9.353 + *  %PCI_EXT_CAP_ID_DSN         Device Serial Number
   9.354 + *  %PCI_EXT_CAP_ID_PWR         Power Budgeting
   9.355 + */
   9.356 +int pci_find_ext_capability(int seg, int bus, int devfn, int cap)
   9.357 +{
   9.358 +    u32 header;
   9.359 +    int ttl = 480; /* 3840 bytes, minimum 8 bytes per capability */
   9.360 +    int pos = 0x100;
   9.361 +
   9.362 +    header = pci_conf_read32(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos);
   9.363 +
   9.364 +    /*
   9.365 +     * If we have no capabilities, this is indicated by cap ID,
   9.366 +     * cap version and next pointer all being 0.
   9.367 +     */
   9.368 +    if ( (header == 0) || (header == -1) )
   9.369 +    {
   9.370 +        dprintk(XENLOG_INFO VTDPREFIX,
   9.371 +                "next cap:%x:%x.%x:  no extended config\n",
   9.372 +                bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
   9.373 +        return 0;
   9.374 +    }
   9.375 +
   9.376 +    while ( ttl-- > 0 ) {
   9.377 +        if ( PCI_EXT_CAP_ID(header) == cap )
   9.378 +            return pos;
   9.379 +        pos = PCI_EXT_CAP_NEXT(header);
   9.380 +        if ( pos < 0x100 )
   9.381 +            break;
   9.382 +        header = pci_conf_read32(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos);
   9.383 +    }
   9.384 +    return 0;
   9.385 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/xen/arch/x86/x86_64/mmconfig.h	Tue Jun 02 11:49:34 2009 +0100
    10.3 @@ -0,0 +1,85 @@
    10.4 +/*
    10.5 + * Copyright (c) 2006, Intel Corporation.
    10.6 + *
    10.7 + * This program is free software; you can redistribute it and/or modify it
    10.8 + * under the terms and conditions of the GNU General Public License,
    10.9 + * version 2, as published by the Free Software Foundation.
   10.10 + *
   10.11 + * This program is distributed in the hope it will be useful, but WITHOUT
   10.12 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   10.13 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   10.14 + * more details.
   10.15 + *
   10.16 + * You should have received a copy of the GNU General Public License along with
   10.17 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
   10.18 + * Place - Suite 330, Boston, MA 02111-1307 USA.
   10.19 + *
   10.20 + * Author: Allen Kay <allen.m.kay@intel.com> - adapted from linux
   10.21 + */
   10.22 +
   10.23 +#define PCI_VENDOR_ID_INTEL        0x8086
   10.24 +#define PCI_DEVICE_ID_INTEL_E7520_MCH    0x3590
   10.25 +#define PCI_DEVICE_ID_INTEL_82945G_HB    0x2770
   10.26 +
   10.27 +/* ioport ends */
   10.28 +#define PCI_PROBE_BIOS        0x0001
   10.29 +#define PCI_PROBE_CONF1        0x0002
   10.30 +#define PCI_PROBE_CONF2        0x0004
   10.31 +#define PCI_PROBE_MMCONF    0x0008
   10.32 +#define PCI_PROBE_MASK        0x000f
   10.33 +#define PCI_PROBE_NOEARLY    0x0010
   10.34 +
   10.35 +#define PCI_VENDOR_ID_AMD             0x1022
   10.36 +#define PCI_CHECK_ENABLE_AMD_MMCONF     0x20000
   10.37 +
   10.38 +/*
   10.39 + * AMD Fam10h CPUs are buggy, and cannot access MMIO config space
   10.40 + * on their northbrige except through the * %eax register. As such, you MUST
   10.41 + * NOT use normal IOMEM accesses, you need to only use the magic mmio-config
   10.42 + * accessor functions.
   10.43 + * In fact just use pci_config_*, nothing else please.
   10.44 + */
   10.45 +static inline unsigned char mmio_config_readb(void __iomem *pos)
   10.46 +{
   10.47 +    u8 val;
   10.48 +    asm volatile("movb (%1),%%al" : "=a" (val) : "r" (pos));
   10.49 +    return val;
   10.50 +}
   10.51 +
   10.52 +static inline unsigned short mmio_config_readw(void __iomem *pos)
   10.53 +{
   10.54 +    u16 val;
   10.55 +    asm volatile("movw (%1),%%ax" : "=a" (val) : "r" (pos));
   10.56 +    return val;
   10.57 +}
   10.58 +
   10.59 +static inline unsigned int mmio_config_readl(void __iomem *pos)
   10.60 +{
   10.61 +    u32 val;
   10.62 +    asm volatile("movl (%1),%%eax" : "=a" (val) : "r" (pos));
   10.63 +    return val;
   10.64 +}
   10.65 +
   10.66 +static inline void mmio_config_writeb(void __iomem *pos, u8 val)
   10.67 +{
   10.68 +    asm volatile("movb %%al,(%1)" :: "a" (val), "r" (pos) : "memory");
   10.69 +}
   10.70 +
   10.71 +static inline void mmio_config_writew(void __iomem *pos, u16 val)
   10.72 +{
   10.73 +    asm volatile("movw %%ax,(%1)" :: "a" (val), "r" (pos) : "memory");
   10.74 +}
   10.75 +
   10.76 +static inline void mmio_config_writel(void __iomem *pos, u32 val)
   10.77 +{
   10.78 +    asm volatile("movl %%eax,(%1)" :: "a" (val), "r" (pos) : "memory");
   10.79 +}
   10.80 +
   10.81 +/* external variable defines */
   10.82 +extern int pci_mmcfg_config_num;
   10.83 +extern struct acpi_mcfg_allocation *pci_mmcfg_config;
   10.84 +
   10.85 +/* fucntion prototypes */
   10.86 +int __init acpi_parse_mcfg(struct acpi_table_header *header);
   10.87 +int __init pci_mmcfg_arch_init(void);
   10.88 +void __init pci_mmcfg_arch_free(void);
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/xen/arch/x86/x86_64/mmconfig_64.c	Tue Jun 02 11:49:34 2009 +0100
    11.3 @@ -0,0 +1,180 @@
    11.4 +/*
    11.5 + * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
    11.6 + *
    11.7 + * This is an 64bit optimized version that always keeps the full mmconfig
    11.8 + * space mapped. This allows lockless config space operation.
    11.9 + *
   11.10 + * copied from Linux
   11.11 + */
   11.12 +
   11.13 +#include <xen/mm.h>
   11.14 +#include <xen/acpi.h>
   11.15 +#include <xen/xmalloc.h>
   11.16 +#include <xen/pci.h>
   11.17 +#include <xen/pci_regs.h>
   11.18 +
   11.19 +#include "mmconfig.h"
   11.20 +
   11.21 +/* Static virtual mapping of the MMCONFIG aperture */
   11.22 +struct mmcfg_virt {
   11.23 +    struct acpi_mcfg_allocation *cfg;
   11.24 +    char __iomem *virt;
   11.25 +};
   11.26 +static struct mmcfg_virt *pci_mmcfg_virt;
   11.27 +
   11.28 +static char __iomem *get_virt(unsigned int seg, unsigned bus)
   11.29 +{
   11.30 +    struct acpi_mcfg_allocation *cfg;
   11.31 +    int cfg_num;
   11.32 +
   11.33 +    for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) {
   11.34 +        cfg = pci_mmcfg_virt[cfg_num].cfg;
   11.35 +        if (cfg->pci_segment == seg &&
   11.36 +            (cfg->start_bus_number <= bus) &&
   11.37 +            (cfg->end_bus_number >= bus))
   11.38 +            return pci_mmcfg_virt[cfg_num].virt;
   11.39 +    }
   11.40 +
   11.41 +    /* Fall back to type 0 */
   11.42 +    return NULL;
   11.43 +}
   11.44 +
   11.45 +static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
   11.46 +{
   11.47 +    char __iomem *addr;
   11.48 +
   11.49 +    addr = get_virt(seg, bus);
   11.50 +    if (!addr)
   11.51 +        return NULL;
   11.52 +     return addr + ((bus << 20) | (devfn << 12));
   11.53 +}
   11.54 +
   11.55 +int pci_mmcfg_read(unsigned int seg, unsigned int bus,
   11.56 +              unsigned int devfn, int reg, int len, u32 *value)
   11.57 +{
   11.58 +    char __iomem *addr;
   11.59 +
   11.60 +    /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
   11.61 +    if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
   11.62 +err:        *value = -1;
   11.63 +        return -EINVAL;
   11.64 +    }
   11.65 +
   11.66 +    addr = pci_dev_base(seg, bus, devfn);
   11.67 +    if (!addr)
   11.68 +        goto err;
   11.69 +
   11.70 +    switch (len) {
   11.71 +    case 1:
   11.72 +        *value = mmio_config_readb(addr + reg);
   11.73 +        break;
   11.74 +    case 2:
   11.75 +        *value = mmio_config_readw(addr + reg);
   11.76 +        break;
   11.77 +    case 4:
   11.78 +        *value = mmio_config_readl(addr + reg);
   11.79 +        break;
   11.80 +    }
   11.81 +
   11.82 +    return 0;
   11.83 +}
   11.84 +
   11.85 +int pci_mmcfg_write(unsigned int seg, unsigned int bus,
   11.86 +               unsigned int devfn, int reg, int len, u32 value)
   11.87 +{
   11.88 +    char __iomem *addr;
   11.89 +
   11.90 +    /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
   11.91 +    if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))
   11.92 +        return -EINVAL;
   11.93 +
   11.94 +    addr = pci_dev_base(seg, bus, devfn);
   11.95 +    if (!addr)
   11.96 +        return -EINVAL;
   11.97 +
   11.98 +    switch (len) {
   11.99 +    case 1:
  11.100 +        mmio_config_writeb(addr + reg, value);
  11.101 +        break;
  11.102 +    case 2:
  11.103 +        mmio_config_writew(addr + reg, value);
  11.104 +        break;
  11.105 +    case 4:
  11.106 +        mmio_config_writel(addr + reg, value);
  11.107 +        break;
  11.108 +    }
  11.109 +
  11.110 +    return 0;
  11.111 +}
  11.112 +
  11.113 +static void __iomem * __init mcfg_ioremap(struct acpi_mcfg_allocation *cfg)
  11.114 +{
  11.115 +    void __iomem *addr;
  11.116 +    unsigned long virt;
  11.117 +    unsigned long mfn;
  11.118 +    unsigned long size, nr_mfn;
  11.119 +
  11.120 +    printk("amk_mcfg_ioremap: PCI_MCFG_VIRT_START %lx\n", (u64)PCI_MCFG_VIRT_START); 
  11.121 +    printk("amk_mcfg_ioremap: start_bus %x end_bus %x\n",
  11.122 +               cfg->start_bus_number, cfg->end_bus_number);
  11.123 +
  11.124 +    virt = PCI_MCFG_VIRT_START + (cfg->pci_segment * (1 << 22)) +
  11.125 +               (cfg->start_bus_number * (1 << 20));
  11.126 +    mfn = cfg->address >> PAGE_SHIFT;
  11.127 +        size = (cfg->end_bus_number - cfg->start_bus_number) << 20;
  11.128 +        nr_mfn = size >> PAGE_SHIFT;
  11.129 +
  11.130 +    printk("amk_mcfg_ioremap: virt %lx mfn = %lx size %lx\n", virt, mfn, size);
  11.131 +
  11.132 +    map_pages_to_xen(virt, mfn, nr_mfn, PAGE_HYPERVISOR_NOCACHE);
  11.133 +    addr = (void __iomem *) virt;
  11.134 +
  11.135 +    printk("amk_mcfg_ioremap: PCI_MCFG_VIRT_START %lx\n",
  11.136 +        (u64)PCI_MCFG_VIRT_START); 
  11.137 +    printk("amk_mcfg_ioremap: virt  %lx size %lx\n", virt, size);
  11.138 +
  11.139 +    return addr;
  11.140 +}
  11.141 +
  11.142 +int __init pci_mmcfg_arch_init(void)
  11.143 +{
  11.144 +    int i;
  11.145 +    pci_mmcfg_virt = xmalloc_bytes(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num);
  11.146 +    if (pci_mmcfg_virt == NULL) {
  11.147 +        printk(KERN_ERR "PCI: Can not allocate memory for mmconfig structures\n");
  11.148 +        return 0;
  11.149 +    }
  11.150 +    memset(pci_mmcfg_virt, 0, sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num);
  11.151 +
  11.152 +    for (i = 0; i < pci_mmcfg_config_num; ++i) {
  11.153 +        pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
  11.154 +        pci_mmcfg_virt[i].virt = mcfg_ioremap(&pci_mmcfg_config[i]);
  11.155 +        if (!pci_mmcfg_virt[i].virt) {
  11.156 +            printk(KERN_ERR "PCI: Cannot map mmconfig aperture for "
  11.157 +                    "segment %d\n",
  11.158 +                pci_mmcfg_config[i].pci_segment);
  11.159 +            pci_mmcfg_arch_free();
  11.160 +            return 0;
  11.161 +        }
  11.162 +    }
  11.163 +    return 1;
  11.164 +}
  11.165 +
  11.166 +void __init pci_mmcfg_arch_free(void)
  11.167 +{
  11.168 +    int i;
  11.169 +
  11.170 +    if (pci_mmcfg_virt == NULL)
  11.171 +        return;
  11.172 +
  11.173 +    for (i = 0; i < pci_mmcfg_config_num; ++i) {
  11.174 +        if (pci_mmcfg_virt[i].virt) {
  11.175 +            iounmap(pci_mmcfg_virt[i].virt);
  11.176 +            pci_mmcfg_virt[i].virt = NULL;
  11.177 +            pci_mmcfg_virt[i].cfg = NULL;
  11.178 +        }
  11.179 +    }
  11.180 +
  11.181 +    xfree(pci_mmcfg_virt);
  11.182 +    pci_mmcfg_virt = NULL;
  11.183 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/xen/arch/x86/x86_64/pci.c	Tue Jun 02 11:49:34 2009 +0100
    12.3 @@ -0,0 +1,109 @@
    12.4 +/******************************************************************************
    12.5 + * pci.c
    12.6 + * 
    12.7 + * Architecture-dependent PCI access functions.
    12.8 + */
    12.9 +
   12.10 +#include <xen/spinlock.h>
   12.11 +#include <xen/pci.h>
   12.12 +#include <asm/io.h>
   12.13 +
   12.14 +#define PCI_CONF_ADDRESS(bus, dev, func, reg) \
   12.15 +    (0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg & ~3))
   12.16 +
   12.17 +int pci_mmcfg_read(unsigned int seg, unsigned int bus,
   12.18 +                   unsigned int devfn, int reg, int len, u32 *value);
   12.19 +int pci_mmcfg_write(unsigned int seg, unsigned int bus,
   12.20 +                    unsigned int devfn, int reg, int len, u32 value);
   12.21 +uint32_t pci_conf_read(uint32_t cf8, uint8_t offset, uint8_t bytes);
   12.22 +void pci_conf_write(uint32_t cf8, uint8_t offset, uint8_t bytes, uint32_t data);
   12.23 +
   12.24 +uint8_t pci_conf_read8(
   12.25 +    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
   12.26 +{
   12.27 +    u32 value;
   12.28 +
   12.29 +    if ( reg > 255 )
   12.30 +    {
   12.31 +        pci_mmcfg_read(0, bus, PCI_DEVFN(dev, func), reg, 1, &value);
   12.32 +        return value;
   12.33 +    }
   12.34 +    else
   12.35 +    {
   12.36 +        BUG_ON((bus > 255) || (dev > 31) || (func > 7));
   12.37 +        return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1);
   12.38 +    }
   12.39 +}
   12.40 +
   12.41 +uint16_t pci_conf_read16(
   12.42 +    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
   12.43 +{
   12.44 +    u32 value;
   12.45 +
   12.46 +    if ( reg > 255 )
   12.47 +    {
   12.48 +        pci_mmcfg_read(0, bus, PCI_DEVFN(dev, func), reg, 2, &value);
   12.49 +        return value;
   12.50 +    }
   12.51 +    else
   12.52 +    {
   12.53 +        BUG_ON((bus > 255) || (dev > 31) || (func > 7));
   12.54 +        return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2);
   12.55 +    }
   12.56 +}
   12.57 +
   12.58 +uint32_t pci_conf_read32(
   12.59 +    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
   12.60 +{
   12.61 +    u32 value;
   12.62 +
   12.63 +    if ( reg > 255 )
   12.64 +    {
   12.65 +        pci_mmcfg_read(0, bus, PCI_DEVFN(dev, func), reg, 4, &value);
   12.66 +        return value;
   12.67 +    }
   12.68 +    else
   12.69 +    {
   12.70 +        BUG_ON((bus > 255) || (dev > 31) || (func > 7));
   12.71 +        return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4);
   12.72 +    }
   12.73 +}
   12.74 +
   12.75 +void pci_conf_write8(
   12.76 +    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
   12.77 +    uint8_t data)
   12.78 +{
   12.79 +    if ( reg > 255 )
   12.80 +        pci_mmcfg_write(0, bus, PCI_DEVFN(dev, func), reg, 1, data);
   12.81 +    else
   12.82 +    {
   12.83 +        BUG_ON((bus > 255) || (dev > 31) || (func > 7));
   12.84 +        pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1, data);
   12.85 +    }
   12.86 +}
   12.87 +
   12.88 +void pci_conf_write16(
   12.89 +    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
   12.90 +    uint16_t data)
   12.91 +{
   12.92 +    if ( reg > 255 )
   12.93 +        pci_mmcfg_write(0, bus, PCI_DEVFN(dev, func), reg, 2, data);
   12.94 +    else
   12.95 +    {
   12.96 +        BUG_ON((bus > 255) || (dev > 31) || (func > 7));
   12.97 +        pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2, data);
   12.98 +    }
   12.99 +}
  12.100 +
  12.101 +void pci_conf_write32(
  12.102 +    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
  12.103 +    uint32_t data)
  12.104 +{
  12.105 +    if ( reg > 255 )
  12.106 +        pci_mmcfg_write(0, bus, PCI_DEVFN(dev, func), reg, 4, data);
  12.107 +    else
  12.108 +    {
  12.109 +        BUG_ON((bus > 255) || (dev > 31) || (func > 7));
  12.110 +        pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4, data);
  12.111 +    }
  12.112 +}
    13.1 --- a/xen/drivers/passthrough/vtd/extern.h	Mon Jun 01 18:37:27 2009 +0100
    13.2 +++ b/xen/drivers/passthrough/vtd/extern.h	Tue Jun 02 11:49:34 2009 +0100
    13.3 @@ -48,8 +48,14 @@ int iommu_flush_iec_index(struct iommu *
    13.4  struct iommu * ioapic_to_iommu(unsigned int apic_id);
    13.5  struct acpi_drhd_unit * ioapic_to_drhd(unsigned int apic_id);
    13.6  void clear_fault_bits(struct iommu *iommu);
    13.7 +int ats_device(int seg, int bus, int devfn);
    13.8 +int enable_ats_device(int seg, int bus, int devfn);
    13.9 +int disable_ats_device(int seg, int bus, int devfn);
   13.10 +int invalidate_ats_tcs(struct iommu *iommu);
   13.11  int qinval_device_iotlb(struct iommu *iommu,
   13.12                          u32 max_invs_pend, u16 sid, u16 size, u64 addr);
   13.13 +int dev_invalidate_iotlb(struct iommu *iommu, u16 did,
   13.14 +                         u64 addr, unsigned int size_order, u64 type);
   13.15  struct acpi_drhd_unit * find_ats_dev_drhd(struct iommu *iommu);
   13.16  
   13.17  #endif // _VTD_EXTERN_H_
    14.1 --- a/xen/drivers/passthrough/vtd/ia64/ats.c	Mon Jun 01 18:37:27 2009 +0100
    14.2 +++ b/xen/drivers/passthrough/vtd/ia64/ats.c	Tue Jun 02 11:49:34 2009 +0100
    14.3 @@ -35,14 +35,6 @@ struct acpi_drhd_unit * find_ats_dev_drh
    14.4      return NULL;
    14.5  }
    14.6  
    14.7 -/*
    14.8 - * BUGBUG: return 0 until pcimmcfg is checked in.
    14.9 - */
   14.10 -int pci_find_ext_capability(int seg, int bus, int devfn, int cap)
   14.11 -{
   14.12 -    return 0;
   14.13 -}
   14.14 -
   14.15  int ats_device(int seg, int bus, int devfn)
   14.16  {
   14.17      return 0;
    15.1 --- a/xen/drivers/passthrough/vtd/iommu.c	Mon Jun 01 18:37:27 2009 +0100
    15.2 +++ b/xen/drivers/passthrough/vtd/iommu.c	Tue Jun 02 11:49:34 2009 +0100
    15.3 @@ -1663,10 +1663,8 @@ static void setup_dom0_devices(struct do
    15.4                  pdev->domain = d;
    15.5                  list_add(&pdev->domain_list, &d->arch.pdev_list);
    15.6                  domain_context_mapping(d, pdev->bus, pdev->devfn);
    15.7 -#if defined(NOT_YET)
    15.8                  if ( ats_device(0, pdev->bus, pdev->devfn) )
    15.9                      enable_ats_device(0, pdev->bus, pdev->devfn);
   15.10 -#endif
   15.11              }
   15.12          }
   15.13      }
    16.1 --- a/xen/drivers/passthrough/vtd/qinval.c	Mon Jun 01 18:37:27 2009 +0100
    16.2 +++ b/xen/drivers/passthrough/vtd/qinval.c	Tue Jun 02 11:49:34 2009 +0100
    16.3 @@ -409,10 +409,8 @@ static int flush_iotlb_qi(
    16.4          ret = queue_invalidate_iotlb(iommu,
    16.5                    (type >> DMA_TLB_FLUSH_GRANU_OFFSET), dr,
    16.6                    dw, did, (u8)size_order, 0, addr);
    16.7 -#if defined(NOT_YET)
    16.8          if ( flush_dev_iotlb )
    16.9              ret |= dev_invalidate_iotlb(iommu, did, addr, size_order, type);
   16.10 -#endif
   16.11          ret |= invalidate_sync(iommu);
   16.12      }
   16.13      return ret;
    17.1 --- a/xen/drivers/passthrough/vtd/x86/ats.c	Mon Jun 01 18:37:27 2009 +0100
    17.2 +++ b/xen/drivers/passthrough/vtd/x86/ats.c	Tue Jun 02 11:49:34 2009 +0100
    17.3 @@ -81,14 +81,6 @@ struct acpi_drhd_unit * find_ats_dev_drh
    17.4      return NULL;
    17.5  }
    17.6  
    17.7 -/*
    17.8 - * BUGBUG: return 0 until pcimmcfg is checked in.
    17.9 - */
   17.10 -int pci_find_ext_capability(int seg, int bus, int devfn, int cap)
   17.11 -{
   17.12 -    return 0;
   17.13 -}
   17.14 -
   17.15  int ats_device(int seg, int bus, int devfn)
   17.16  {
   17.17      struct acpi_drhd_unit *drhd, *ats_drhd, *new_drhd;
    18.1 --- a/xen/include/asm-x86/acpi.h	Mon Jun 01 18:37:27 2009 +0100
    18.2 +++ b/xen/include/asm-x86/acpi.h	Tue Jun 02 11:49:34 2009 +0100
    18.3 @@ -164,7 +164,8 @@ struct acpi_sleep_info {
    18.4  extern u8 x86_acpiid_to_apicid[];
    18.5  #define MAX_LOCAL_APIC 256
    18.6  
    18.7 -extern int acpi_dmar_init(void);
    18.8 +int acpi_dmar_init(void);
    18.9 +void acpi_mmcfg_init(void);
   18.10  
   18.11  /* Incremented whenever we transition through S3. Value is 1 during boot. */
   18.12  extern uint32_t system_reset_counter;
    19.1 --- a/xen/include/asm-x86/config.h	Mon Jun 01 18:37:27 2009 +0100
    19.2 +++ b/xen/include/asm-x86/config.h	Tue Jun 02 11:49:34 2009 +0100
    19.3 @@ -135,7 +135,7 @@ extern unsigned int video_mode, video_fl
    19.4   *  0xffff804000000000 - 0xffff807fffffffff [256GB, 2^38 bytes, PML4:256]
    19.5   *    Reserved for future shared info with the guest OS (GUEST ACCESSIBLE).
    19.6   *  0xffff808000000000 - 0xffff80ffffffffff [512GB, 2^39 bytes, PML4:257]
    19.7 - *    Reserved for future use.
    19.8 + *    ioremap for PCI mmconfig space
    19.9   *  0xffff810000000000 - 0xffff817fffffffff [512GB, 2^39 bytes, PML4:258]
   19.10   *    Guest linear page table.
   19.11   *  0xffff818000000000 - 0xffff81ffffffffff [512GB, 2^39 bytes, PML4:259]
   19.12 @@ -188,6 +188,12 @@ extern unsigned int video_mode, video_fl
   19.13  /* Slot 256: read-only guest-accessible machine-to-phys translation table. */
   19.14  #define RO_MPT_VIRT_START       (PML4_ADDR(256))
   19.15  #define RO_MPT_VIRT_END         (RO_MPT_VIRT_START + PML4_ENTRY_BYTES/2)
   19.16 +/* Slot 257: ioremap for PCI mmconfig space for 2048 segments (512GB)
   19.17 + *     - full 16-bit segment support needs 44 bits
   19.18 + *     - since PML4 slot has 39 bits, we limit segments to 2048 (11-bits)
   19.19 + */
   19.20 +#define PCI_MCFG_VIRT_START     (PML4_ADDR(257))
   19.21 +#define PCI_MCFG_VIRT_END       (RDWR_MPT_VIRT_START + PML4_ENTRY_BYTES)
   19.22  /* Slot 258: linear page table (guest table). */
   19.23  #define LINEAR_PT_VIRT_START    (PML4_ADDR(258))
   19.24  #define LINEAR_PT_VIRT_END      (LINEAR_PT_VIRT_START + PML4_ENTRY_BYTES)
    20.1 --- a/xen/include/asm-x86/e820.h	Mon Jun 01 18:37:27 2009 +0100
    20.2 +++ b/xen/include/asm-x86/e820.h	Tue Jun 02 11:49:34 2009 +0100
    20.3 @@ -23,6 +23,7 @@ struct e820map {
    20.4      struct e820entry map[E820MAX];
    20.5  };
    20.6  
    20.7 +extern int e820_all_mapped(u64 start, u64 end, unsigned type);
    20.8  extern int reserve_e820_ram(struct e820map *e820, uint64_t s, uint64_t e);
    20.9  extern int e820_change_range_type(
   20.10      struct e820map *e820, uint64_t s, uint64_t e,
    21.1 --- a/xen/include/asm-x86/msr-index.h	Mon Jun 01 18:37:27 2009 +0100
    21.2 +++ b/xen/include/asm-x86/msr-index.h	Tue Jun 02 11:49:34 2009 +0100
    21.3 @@ -231,7 +231,7 @@
    21.4  
    21.5  /* Other AMD Fam10h MSRs */
    21.6  #define MSR_FAM10H_MMIO_CONF_BASE	0xc0010058
    21.7 -#define FAM10H_MMIO_CONF_ENABLE_BIT	0
    21.8 +#define FAM10H_MMIO_CONF_ENABLE         (1<<0)
    21.9  #define FAM10H_MMIO_CONF_BUSRANGE_MASK	0xf
   21.10  #define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2
   21.11  #define FAM10H_MMIO_CONF_BASE_MASK	0xfffffff
    22.1 --- a/xen/include/xen/pci.h	Mon Jun 01 18:37:27 2009 +0100
    22.2 +++ b/xen/include/xen/pci.h	Tue Jun 02 11:49:34 2009 +0100
    22.3 @@ -93,8 +93,13 @@ void pci_conf_write16(
    22.4  void pci_conf_write32(
    22.5      unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
    22.6      uint32_t data);
    22.7 +int pci_mmcfg_read(unsigned int seg, unsigned int bus,
    22.8 +                   unsigned int devfn, int reg, int len, u32 *value);
    22.9 +int pci_mmcfg_write(unsigned int seg, unsigned int bus,
   22.10 +                    unsigned int devfn, int reg, int len, u32 value);
   22.11  int pci_find_cap_offset(u8 bus, u8 dev, u8 func, u8 cap);
   22.12  int pci_find_next_cap(u8 bus, unsigned int devfn, u8 pos, int cap);
   22.13 +int pci_find_ext_capability(int seg, int bus, int devfn, int cap);
   22.14  
   22.15  int msixtbl_pt_register(struct domain *d, int pirq, uint64_t gtable);
   22.16  void msixtbl_pt_unregister(struct domain *d, int pirq);