[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Enable pci mmcfg and ATS for x86_64
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1243939774 -3600 # Node ID 42fe00c6f8b4e7f5c7c13ab8928d8dae24f19a72 # Parent 4294a04b24bc55ffc18215d85a9eda517935b816 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@xxxxxxxxx> --- xen/arch/x86/acpi/boot.c | 2 xen/arch/x86/e820.c | 34 ++ xen/arch/x86/pci.c | 49 ---- xen/arch/x86/traps.c | 2 xen/arch/x86/x86_32/Makefile | 1 xen/arch/x86/x86_32/pci.c | 70 ++++++ xen/arch/x86/x86_64/Makefile | 4 xen/arch/x86/x86_64/acpi_mmcfg.c | 98 ++++++++ xen/arch/x86/x86_64/mmconfig-shared.c | 382 +++++++++++++++++++++++++++++++++ xen/arch/x86/x86_64/mmconfig.h | 85 +++++++ xen/arch/x86/x86_64/mmconfig_64.c | 180 +++++++++++++++ xen/arch/x86/x86_64/pci.c | 109 +++++++++ xen/drivers/passthrough/vtd/extern.h | 6 xen/drivers/passthrough/vtd/ia64/ats.c | 8 xen/drivers/passthrough/vtd/iommu.c | 2 xen/drivers/passthrough/vtd/qinval.c | 2 xen/drivers/passthrough/vtd/x86/ats.c | 8 xen/include/asm-x86/acpi.h | 3 xen/include/asm-x86/config.h | 8 xen/include/asm-x86/e820.h | 1 xen/include/asm-x86/msr-index.h | 2 xen/include/xen/pci.h | 5 22 files changed, 988 insertions(+), 73 deletions(-) diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/acpi/boot.c --- a/xen/arch/x86/acpi/boot.c Mon Jun 01 18:37:27 2009 +0100 +++ b/xen/arch/x86/acpi/boot.c Tue Jun 02 11:49:34 2009 +0100 @@ -937,6 +937,8 @@ int __init acpi_boot_init(void) acpi_dmar_init(); + acpi_mmcfg_init(); + return 0; } diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/e820.c --- a/xen/arch/x86/e820.c Mon Jun 01 18:37:27 2009 +0100 +++ b/xen/arch/x86/e820.c Tue Jun 02 11:49:34 2009 +0100 @@ -24,6 +24,40 @@ boolean_param("e820-verbose", e820_verbo boolean_param("e820-verbose", e820_verbose); struct e820map e820; + +/* + * This function checks if the entire range <start,end> is mapped with type. + * + * Note: this function only works correct if the e820 table is sorted and + * not-overlapping, which is the case + */ +int __init e820_all_mapped(u64 start, u64 end, unsigned type) +{ + int i; + + for (i = 0; i < e820.nr_map; i++) { + struct e820entry *ei = &e820.map[i]; + + if (type && ei->type != type) + continue; + /* is the region (part) in overlap with the current region ?*/ + if (ei->addr >= end || ei->addr + ei->size <= start) + continue; + + /* if the region is at the beginning of <start,end> we move + * start to the end of the region since it's ok until there + */ + if (ei->addr <= start) + start = ei->addr + ei->size; + /* + * if start is now at or beyond end, we're done, full + * coverage + */ + if (start >= end) + return 1; + } + return 0; +} static void __init add_memory_region(unsigned long long start, unsigned long long size, int type) diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/pci.c --- a/xen/arch/x86/pci.c Mon Jun 01 18:37:27 2009 +0100 +++ b/xen/arch/x86/pci.c Tue Jun 02 11:49:34 2009 +0100 @@ -6,9 +6,6 @@ #include <xen/spinlock.h> #include <asm/io.h> - -#define PCI_CONF_ADDRESS(bus, dev, func, reg) \ - (0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg & ~3)) static DEFINE_SPINLOCK(pci_config_lock); @@ -69,49 +66,3 @@ void pci_conf_write(uint32_t cf8, uint8_ spin_unlock_irqrestore(&pci_config_lock, flags); } - -uint8_t pci_conf_read8( - unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg) -{ - BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255)); - return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1); -} - -uint16_t pci_conf_read16( - unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg) -{ - BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255)); - return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2); -} - -uint32_t pci_conf_read32( - unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg) -{ - BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255)); - return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4); -} - -void pci_conf_write8( - unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg, - uint8_t data) -{ - BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255)); - pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1, data); -} - -void pci_conf_write16( - unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg, - uint16_t data) -{ - BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255)); - pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2, data); -} - -void pci_conf_write32( - unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg, - uint32_t data) -{ - BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255)); - pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4, data); -} - diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Mon Jun 01 18:37:27 2009 +0100 +++ b/xen/arch/x86/traps.c Tue Jun 02 11:49:34 2009 +0100 @@ -2186,7 +2186,7 @@ static int emulate_privileged_op(struct break; if ( (rdmsr_safe(MSR_FAM10H_MMIO_CONF_BASE, l, h) != 0) || (((((u64)h << 32) | l) ^ res) & - ~((1 << FAM10H_MMIO_CONF_ENABLE_BIT) | + ~( FAM10H_MMIO_CONF_ENABLE | (FAM10H_MMIO_CONF_BUSRANGE_MASK << FAM10H_MMIO_CONF_BUSRANGE_SHIFT) | ((u64)FAM10H_MMIO_CONF_BASE_MASK << diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/x86_32/Makefile --- a/xen/arch/x86/x86_32/Makefile Mon Jun 01 18:37:27 2009 +0100 +++ b/xen/arch/x86/x86_32/Makefile Tue Jun 02 11:49:34 2009 +0100 @@ -5,6 +5,7 @@ obj-y += seg_fixup.o obj-y += seg_fixup.o obj-y += traps.o obj-y += machine_kexec.o +obj-y += pci.o obj-$(crash_debug) += gdbstub.o diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/x86_32/pci.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/x86/x86_32/pci.c Tue Jun 02 11:49:34 2009 +0100 @@ -0,0 +1,70 @@ +/****************************************************************************** + * pci.c + * + * Architecture-dependent PCI access functions. + */ + +#include <xen/spinlock.h> +#include <xen/pci.h> +#include <asm/io.h> + +#define PCI_CONF_ADDRESS(bus, dev, func, reg) \ + (0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg & ~3)) + +uint32_t pci_conf_read(uint32_t cf8, uint8_t offset, uint8_t bytes); +void pci_conf_write(uint32_t cf8, uint8_t offset, uint8_t bytes, uint32_t data); + +uint8_t pci_conf_read8( + unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg) +{ + BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255)); + return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1); +} + +uint16_t pci_conf_read16( + unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg) +{ + BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255)); + return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2); +} + +uint32_t pci_conf_read32( + unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg) +{ + BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255)); + return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4); +} + +void pci_conf_write8( + unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg, + uint8_t data) +{ + BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255)); + pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1, data); +} + +void pci_conf_write16( + unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg, + uint16_t data) +{ + BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255)); + pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2, data); +} + +void pci_conf_write32( + unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg, + uint32_t data) +{ + BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255)); + pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4, data); +} + +int pci_find_ext_capability(int seg, int bus, int devfn, int cap) +{ + return 0; +} + +void acpi_mmcfg_init(void) +{ + return; +} diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/x86_64/Makefile --- a/xen/arch/x86/x86_64/Makefile Mon Jun 01 18:37:27 2009 +0100 +++ b/xen/arch/x86/x86_64/Makefile Tue Jun 02 11:49:34 2009 +0100 @@ -5,6 +5,10 @@ obj-y += mm.o obj-y += mm.o obj-y += traps.o obj-y += machine_kexec.o +obj-y += pci.o +obj-y += acpi_mmcfg.o +obj-y += mmconfig_64.o +obj-y += mmconfig-shared.o obj-$(crash_debug) += gdbstub.o obj-$(CONFIG_COMPAT) += compat.o diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/x86_64/acpi_mmcfg.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/x86/x86_64/acpi_mmcfg.c Tue Jun 02 11:49:34 2009 +0100 @@ -0,0 +1,98 @@ +/* + * acpi_mmconfig.c - Architecture-Specific Low-Level ACPI Boot Support + * + * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@xxxxxxxxx> + * Copyright (C) 2001 Jun Nakajima <jun.nakajima@xxxxxxxxx> + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * copied from Linux + */ + +#include <xen/config.h> +#include <xen/errno.h> +#include <xen/init.h> +#include <xen/acpi.h> +#include <xen/irq.h> +#include <xen/dmi.h> +#include <asm/fixmap.h> +#include <asm/page.h> +#include <asm/apic.h> +#include <asm/io_apic.h> +#include <asm/apic.h> +#include <asm/io.h> +#include <asm/mpspec.h> +#include <asm/processor.h> +#include <mach_apic.h> +#include <mach_mpparse.h> + +#include "mmconfig.h" + +/* The physical address of the MMCONFIG aperture. Set from ACPI tables. */ +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) +{ + struct acpi_table_mcfg *mcfg; + unsigned long i; + int config_size; + + if (!header) + return -EINVAL; + + mcfg = (struct acpi_table_mcfg *)header; + + /* how many config structures do we have */ + pci_mmcfg_config_num = 0; + i = header->length - sizeof(struct acpi_table_mcfg); + while (i >= sizeof(struct acpi_mcfg_allocation)) { + ++pci_mmcfg_config_num; + i -= sizeof(struct acpi_mcfg_allocation); + }; + if (pci_mmcfg_config_num == 0) { + printk(KERN_ERR PREFIX "MMCONFIG has no entries\n"); + return -ENODEV; + } + + config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config); + pci_mmcfg_config = xmalloc_bytes(config_size); + 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); + + for (i = 0; i < pci_mmcfg_config_num; ++i) { + if ((pci_mmcfg_config[i].address > 0xFFFFFFFF) && + !acpi_mcfg_64bit_base_addr) { + printk(KERN_ERR PREFIX + "MMCONFIG not in low 4GB of memory\n"); + xfree(pci_mmcfg_config); + pci_mmcfg_config_num = 0; + return -ENODEV; + } + } + + return 0; +} diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/x86_64/mmconfig-shared.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/x86/x86_64/mmconfig-shared.c Tue Jun 02 11:49:34 2009 +0100 @@ -0,0 +1,382 @@ +/* + * mmconfig-shared.c - Low-level direct PCI config space access via + * MMCONFIG - common code between i386 and x86-64. + * + * This code does: + * - known chipset handling + * - ACPI decoding and validation + * + * Per-architecture code takes care of the mappings and accesses + * themselves. + * + * Author: Allen Kay <allen.m.kay@xxxxxxxxx> - adapted to xen from Linux + */ + +#include <xen/mm.h> +#include <xen/acpi.h> +#include <xen/xmalloc.h> +#include <xen/pci.h> +#include <xen/pci_regs.h> +#include <asm/e820.h> +#include <asm/msr.h> +#include <asm/msr-index.h> + +#include "mmconfig.h" + +static int __initdata known_bridge; +unsigned int pci_probe = PCI_PROBE_CONF1 | PCI_PROBE_MMCONF; + +static const char __init *pci_mmcfg_e7520(void) +{ + u32 win; + win = pci_conf_read16(0, 0, 0, 0xce); + + win = win & 0xf000; + if(win == 0x0000 || win == 0xf000) + pci_mmcfg_config_num = 0; + else { + pci_mmcfg_config_num = 1; + pci_mmcfg_config = xmalloc_bytes(sizeof(pci_mmcfg_config[0])); + if (!pci_mmcfg_config) + return NULL; + memset(pci_mmcfg_config, 0, sizeof(pci_mmcfg_config[0])); + pci_mmcfg_config[0].address = win << 16; + pci_mmcfg_config[0].pci_segment = 0; + pci_mmcfg_config[0].start_bus_number = 0; + pci_mmcfg_config[0].end_bus_number = 255; + } + + return "Intel Corporation E7520 Memory Controller Hub"; +} + +static const char __init *pci_mmcfg_intel_945(void) +{ + u32 pciexbar, mask = 0, len = 0; + + pci_mmcfg_config_num = 1; + + pciexbar = pci_conf_read32(0, 0, 0, 0x48); + + /* Enable bit */ + if (!(pciexbar & 1)) + pci_mmcfg_config_num = 0; + + /* Size bits */ + switch ((pciexbar >> 1) & 3) { + case 0: + mask = 0xf0000000U; + len = 0x10000000U; + break; + case 1: + mask = 0xf8000000U; + len = 0x08000000U; + break; + case 2: + mask = 0xfc000000U; + len = 0x04000000U; + break; + default: + pci_mmcfg_config_num = 0; + } + + /* Errata #2, things break when not aligned on a 256Mb boundary */ + /* Can only happen in 64M/128M mode */ + + if ((pciexbar & mask) & 0x0fffffffU) + pci_mmcfg_config_num = 0; + + /* Don't hit the APIC registers and their friends */ + if ((pciexbar & mask) >= 0xf0000000U) + pci_mmcfg_config_num = 0; + + if (pci_mmcfg_config_num) { + pci_mmcfg_config = xmalloc_bytes(sizeof(pci_mmcfg_config[0])); + if (!pci_mmcfg_config) + return NULL; + memset(pci_mmcfg_config, 0, sizeof(pci_mmcfg_config[0])); + pci_mmcfg_config[0].address = pciexbar & mask; + pci_mmcfg_config[0].pci_segment = 0; + pci_mmcfg_config[0].start_bus_number = 0; + pci_mmcfg_config[0].end_bus_number = (len >> 20) - 1; + } + + return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub"; +} + +static const char __init *pci_mmcfg_amd_fam10h(void) +{ + u32 low, high, address; + u64 base, msr; + int i; + unsigned segnbits = 0, busnbits; + + if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF)) + return NULL; + + address = MSR_FAM10H_MMIO_CONF_BASE; + if (rdmsr_safe(address, low, high)) + return NULL; + + msr = high; + msr <<= 32; + msr |= low; + + /* mmconfig is not enable */ + if (!(msr & FAM10H_MMIO_CONF_ENABLE)) + return NULL; + + base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT); + + busnbits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) & + FAM10H_MMIO_CONF_BUSRANGE_MASK; + + /* + * only handle bus 0 ? + * need to skip it + */ + if (!busnbits) + return NULL; + + if (busnbits > 8) { + segnbits = busnbits - 8; + busnbits = 8; + } + + pci_mmcfg_config_num = (1 << segnbits); + pci_mmcfg_config = xmalloc_bytes(sizeof(pci_mmcfg_config[0]) * + 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].pci_segment = i; + pci_mmcfg_config[i].start_bus_number = 0; + pci_mmcfg_config[i].end_bus_number = (1 << busnbits) - 1; + } + + return "AMD Family 10h NB"; +} + +struct pci_mmcfg_hostbridge_probe { + u32 bus; + u32 devfn; + u32 vendor; + u32 device; + const char *(*probe)(void); +}; + +static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = { + { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 }, + { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 }, + { 0, PCI_DEVFN(0x18, 0), PCI_VENDOR_ID_AMD, + 0x1200, pci_mmcfg_amd_fam10h }, + { 0xff, PCI_DEVFN(0, 0), PCI_VENDOR_ID_AMD, + 0x1200, pci_mmcfg_amd_fam10h }, +}; + +static int __init pci_mmcfg_check_hostbridge(void) +{ + u32 l; + u32 bus, devfn; + u16 vendor, device; + int i; + const char *name; + + pci_mmcfg_config_num = 0; + pci_mmcfg_config = NULL; + name = NULL; + + for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) { + bus = pci_mmcfg_probes[i].bus; + devfn = pci_mmcfg_probes[i].devfn; + l = pci_conf_read32(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), 0); + vendor = l & 0xffff; + device = (l >> 16) & 0xffff; + + if (pci_mmcfg_probes[i].vendor == vendor && + pci_mmcfg_probes[i].device == device) + name = pci_mmcfg_probes[i].probe(); + } + + if (name) { + printk(KERN_INFO "PCI: Found %s %s MMCONFIG support.\n", + name, pci_mmcfg_config_num ? "with" : "without"); + } + + return name != NULL; +} + +typedef int (*check_reserved_t)(u64 start, u64 end, unsigned type); + +static int __init is_mmconf_reserved( + check_reserved_t is_reserved, + u64 addr, u64 size, int i, + typeof(pci_mmcfg_config[0]) *cfg, int with_e820) +{ + u64 old_size = size; + int valid = 0; + + while (!is_reserved(addr, addr + size - 1, E820_RESERVED)) { + size >>= 1; + if (size < (16UL<<20)) + break; + } + + if (size >= (16UL<<20) || size == old_size) { + printk(KERN_NOTICE + "PCI: MCFG area at %lx reserved in %s\n", + addr, with_e820?"E820":"ACPI motherboard resources"); + valid = 1; + + if (old_size != size) { + /* update end_bus_number */ + cfg->end_bus_number = cfg->start_bus_number + ((size>>20) - 1); + printk(KERN_NOTICE "PCI: updated MCFG configuration %d: base %lx " + "segment %hu buses %u - %u\n", + i, (unsigned long)cfg->address, cfg->pci_segment, + (unsigned int)cfg->start_bus_number, + (unsigned int)cfg->end_bus_number); + } + } + + return valid; +} + +static void __init pci_mmcfg_reject_broken(int early) +{ + typeof(pci_mmcfg_config[0]) *cfg; + int i; + + if ((pci_mmcfg_config_num == 0) || + (pci_mmcfg_config == NULL) || + (pci_mmcfg_config[0].address == 0)) + return; + + 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]; + addr = cfg->start_bus_number; + addr <<= 20; + addr += cfg->address; + size = cfg->end_bus_number + 1 - cfg->start_bus_number; + size <<= 20; + printk(KERN_NOTICE "PCI: MCFG configuration %d: base %lx " + "segment %hu buses %u - %u\n", + i, (unsigned long)cfg->address, cfg->pci_segment, + (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) + goto reject; + } + + return; + +reject: + printk(KERN_INFO "PCI: Not using MMCONFIG.\n"); + pci_mmcfg_arch_free(); + xfree(pci_mmcfg_config); + pci_mmcfg_config = NULL; + pci_mmcfg_config_num = 0; +} + +void __init __pci_mmcfg_init(int early) +{ + /* MMCONFIG disabled */ + if ((pci_probe & PCI_PROBE_MMCONF) == 0) + return; + + /* MMCONFIG already enabled */ + if (!early && !(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 (!known_bridge) { + acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg); + pci_mmcfg_reject_broken(early); + } + + if ((pci_mmcfg_config_num == 0) || + (pci_mmcfg_config == NULL) || + (pci_mmcfg_config[0].address == 0)) + return; + + if (pci_mmcfg_arch_init()) { + pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; + } +} + +void acpi_mmcfg_init(void) +{ + __pci_mmcfg_init(1); +} + +/** + * pci_find_ext_capability - Find an extended capability + * @dev: PCI device to query + * @cap: capability code + * + * Returns the address of the requested extended capability structure + * within the device's PCI configuration space or 0 if the device does + * not support it. Possible values for @cap: + * + * %PCI_EXT_CAP_ID_ERR Advanced Error Reporting + * %PCI_EXT_CAP_ID_VC Virtual Channel + * %PCI_EXT_CAP_ID_DSN Device Serial Number + * %PCI_EXT_CAP_ID_PWR Power Budgeting + */ +int pci_find_ext_capability(int seg, int bus, int devfn, int cap) +{ + u32 header; + int ttl = 480; /* 3840 bytes, minimum 8 bytes per capability */ + int pos = 0x100; + + header = pci_conf_read32(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos); + + /* + * If we have no capabilities, this is indicated by cap ID, + * cap version and next pointer all being 0. + */ + if ( (header == 0) || (header == -1) ) + { + dprintk(XENLOG_INFO VTDPREFIX, + "next cap:%x:%x.%x: no extended config\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + return 0; + } + + while ( ttl-- > 0 ) { + if ( PCI_EXT_CAP_ID(header) == cap ) + return pos; + pos = PCI_EXT_CAP_NEXT(header); + if ( pos < 0x100 ) + break; + header = pci_conf_read32(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos); + } + return 0; +} diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/x86_64/mmconfig.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/x86/x86_64/mmconfig.h Tue Jun 02 11:49:34 2009 +0100 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Author: Allen Kay <allen.m.kay@xxxxxxxxx> - adapted from linux + */ + +#define PCI_VENDOR_ID_INTEL 0x8086 +#define PCI_DEVICE_ID_INTEL_E7520_MCH 0x3590 +#define PCI_DEVICE_ID_INTEL_82945G_HB 0x2770 + +/* ioport ends */ +#define PCI_PROBE_BIOS 0x0001 +#define PCI_PROBE_CONF1 0x0002 +#define PCI_PROBE_CONF2 0x0004 +#define PCI_PROBE_MMCONF 0x0008 +#define PCI_PROBE_MASK 0x000f +#define PCI_PROBE_NOEARLY 0x0010 + +#define PCI_VENDOR_ID_AMD 0x1022 +#define PCI_CHECK_ENABLE_AMD_MMCONF 0x20000 + +/* + * AMD Fam10h CPUs are buggy, and cannot access MMIO config space + * on their northbrige except through the * %eax register. As such, you MUST + * NOT use normal IOMEM accesses, you need to only use the magic mmio-config + * accessor functions. + * In fact just use pci_config_*, nothing else please. + */ +static inline unsigned char mmio_config_readb(void __iomem *pos) +{ + u8 val; + asm volatile("movb (%1),%%al" : "=a" (val) : "r" (pos)); + return val; +} + +static inline unsigned short mmio_config_readw(void __iomem *pos) +{ + u16 val; + asm volatile("movw (%1),%%ax" : "=a" (val) : "r" (pos)); + return val; +} + +static inline unsigned int mmio_config_readl(void __iomem *pos) +{ + u32 val; + asm volatile("movl (%1),%%eax" : "=a" (val) : "r" (pos)); + return val; +} + +static inline void mmio_config_writeb(void __iomem *pos, u8 val) +{ + asm volatile("movb %%al,(%1)" :: "a" (val), "r" (pos) : "memory"); +} + +static inline void mmio_config_writew(void __iomem *pos, u16 val) +{ + asm volatile("movw %%ax,(%1)" :: "a" (val), "r" (pos) : "memory"); +} + +static inline void mmio_config_writel(void __iomem *pos, u32 val) +{ + asm volatile("movl %%eax,(%1)" :: "a" (val), "r" (pos) : "memory"); +} + +/* external variable defines */ +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); diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/x86_64/mmconfig_64.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/x86/x86_64/mmconfig_64.c Tue Jun 02 11:49:34 2009 +0100 @@ -0,0 +1,180 @@ +/* + * mmconfig.c - Low-level direct PCI config space access via MMCONFIG + * + * This is an 64bit optimized version that always keeps the full mmconfig + * space mapped. This allows lockless config space operation. + * + * copied from Linux + */ + +#include <xen/mm.h> +#include <xen/acpi.h> +#include <xen/xmalloc.h> +#include <xen/pci.h> +#include <xen/pci_regs.h> + +#include "mmconfig.h" + +/* Static virtual mapping of the MMCONFIG aperture */ +struct mmcfg_virt { + struct acpi_mcfg_allocation *cfg; + char __iomem *virt; +}; +static struct mmcfg_virt *pci_mmcfg_virt; + +static char __iomem *get_virt(unsigned int seg, unsigned bus) +{ + struct acpi_mcfg_allocation *cfg; + int cfg_num; + + for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) { + cfg = pci_mmcfg_virt[cfg_num].cfg; + if (cfg->pci_segment == seg && + (cfg->start_bus_number <= bus) && + (cfg->end_bus_number >= bus)) + return pci_mmcfg_virt[cfg_num].virt; + } + + /* Fall back to type 0 */ + return NULL; +} + +static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) +{ + char __iomem *addr; + + addr = get_virt(seg, bus); + if (!addr) + return NULL; + return addr + ((bus << 20) | (devfn << 12)); +} + +int pci_mmcfg_read(unsigned int seg, unsigned int bus, + unsigned int devfn, int reg, int len, u32 *value) +{ + char __iomem *addr; + + /* Why do we have this when nobody checks it. How about a BUG()!? -AK */ + if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) { +err: *value = -1; + return -EINVAL; + } + + addr = pci_dev_base(seg, bus, devfn); + if (!addr) + goto err; + + switch (len) { + case 1: + *value = mmio_config_readb(addr + reg); + break; + case 2: + *value = mmio_config_readw(addr + reg); + break; + case 4: + *value = mmio_config_readl(addr + reg); + break; + } + + return 0; +} + +int pci_mmcfg_write(unsigned int seg, unsigned int bus, + unsigned int devfn, int reg, int len, u32 value) +{ + char __iomem *addr; + + /* Why do we have this when nobody checks it. How about a BUG()!? -AK */ + if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) + return -EINVAL; + + addr = pci_dev_base(seg, bus, devfn); + if (!addr) + return -EINVAL; + + switch (len) { + case 1: + mmio_config_writeb(addr + reg, value); + break; + case 2: + mmio_config_writew(addr + reg, value); + break; + case 4: + mmio_config_writel(addr + reg, value); + break; + } + + return 0; +} + +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; + + printk("amk_mcfg_ioremap: PCI_MCFG_VIRT_START %lx\n", (u64)PCI_MCFG_VIRT_START); + printk("amk_mcfg_ioremap: start_bus %x end_bus %x\n", + cfg->start_bus_number, cfg->end_bus_number); + + 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; + + printk("amk_mcfg_ioremap: virt %lx mfn = %lx size %lx\n", virt, mfn, size); + + map_pages_to_xen(virt, mfn, nr_mfn, PAGE_HYPERVISOR_NOCACHE); + addr = (void __iomem *) virt; + + printk("amk_mcfg_ioremap: PCI_MCFG_VIRT_START %lx\n", + (u64)PCI_MCFG_VIRT_START); + printk("amk_mcfg_ioremap: virt %lx size %lx\n", virt, size); + + return addr; +} + +int __init pci_mmcfg_arch_init(void) +{ + int i; + pci_mmcfg_virt = xmalloc_bytes(sizeof(*pci_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; + } + memset(pci_mmcfg_virt, 0, sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num); + + for (i = 0; i < pci_mmcfg_config_num; ++i) { + pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[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 " + "segment %d\n", + pci_mmcfg_config[i].pci_segment); + pci_mmcfg_arch_free(); + return 0; + } + } + return 1; +} + +void __init pci_mmcfg_arch_free(void) +{ + int i; + + if (pci_mmcfg_virt == NULL) + return; + + for (i = 0; i < pci_mmcfg_config_num; ++i) { + if (pci_mmcfg_virt[i].virt) { + iounmap(pci_mmcfg_virt[i].virt); + pci_mmcfg_virt[i].virt = NULL; + pci_mmcfg_virt[i].cfg = NULL; + } + } + + xfree(pci_mmcfg_virt); + pci_mmcfg_virt = NULL; +} diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/x86_64/pci.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/x86/x86_64/pci.c Tue Jun 02 11:49:34 2009 +0100 @@ -0,0 +1,109 @@ +/****************************************************************************** + * pci.c + * + * Architecture-dependent PCI access functions. + */ + +#include <xen/spinlock.h> +#include <xen/pci.h> +#include <asm/io.h> + +#define PCI_CONF_ADDRESS(bus, dev, func, reg) \ + (0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg & ~3)) + +int pci_mmcfg_read(unsigned int seg, unsigned int bus, + unsigned int devfn, int reg, int len, u32 *value); +int pci_mmcfg_write(unsigned int seg, unsigned int bus, + unsigned int devfn, int reg, int len, u32 value); +uint32_t pci_conf_read(uint32_t cf8, uint8_t offset, uint8_t bytes); +void pci_conf_write(uint32_t cf8, uint8_t offset, uint8_t bytes, uint32_t data); + +uint8_t pci_conf_read8( + unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg) +{ + u32 value; + + if ( reg > 255 ) + { + pci_mmcfg_read(0, bus, PCI_DEVFN(dev, func), reg, 1, &value); + return value; + } + else + { + BUG_ON((bus > 255) || (dev > 31) || (func > 7)); + return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1); + } +} + +uint16_t pci_conf_read16( + unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg) +{ + u32 value; + + if ( reg > 255 ) + { + pci_mmcfg_read(0, bus, PCI_DEVFN(dev, func), reg, 2, &value); + return value; + } + else + { + BUG_ON((bus > 255) || (dev > 31) || (func > 7)); + return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2); + } +} + +uint32_t pci_conf_read32( + unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg) +{ + u32 value; + + if ( reg > 255 ) + { + pci_mmcfg_read(0, bus, PCI_DEVFN(dev, func), reg, 4, &value); + return value; + } + else + { + BUG_ON((bus > 255) || (dev > 31) || (func > 7)); + return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4); + } +} + +void pci_conf_write8( + unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg, + uint8_t data) +{ + if ( reg > 255 ) + pci_mmcfg_write(0, bus, PCI_DEVFN(dev, func), reg, 1, data); + else + { + BUG_ON((bus > 255) || (dev > 31) || (func > 7)); + pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1, data); + } +} + +void pci_conf_write16( + unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg, + uint16_t data) +{ + if ( reg > 255 ) + pci_mmcfg_write(0, bus, PCI_DEVFN(dev, func), reg, 2, data); + else + { + BUG_ON((bus > 255) || (dev > 31) || (func > 7)); + pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2, data); + } +} + +void pci_conf_write32( + unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg, + uint32_t data) +{ + if ( reg > 255 ) + pci_mmcfg_write(0, bus, PCI_DEVFN(dev, func), reg, 4, data); + else + { + BUG_ON((bus > 255) || (dev > 31) || (func > 7)); + pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4, data); + } +} diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/drivers/passthrough/vtd/extern.h --- a/xen/drivers/passthrough/vtd/extern.h Mon Jun 01 18:37:27 2009 +0100 +++ b/xen/drivers/passthrough/vtd/extern.h Tue Jun 02 11:49:34 2009 +0100 @@ -48,8 +48,14 @@ struct iommu * ioapic_to_iommu(unsigned struct iommu * ioapic_to_iommu(unsigned int apic_id); struct acpi_drhd_unit * ioapic_to_drhd(unsigned int apic_id); void clear_fault_bits(struct iommu *iommu); +int ats_device(int seg, int bus, int devfn); +int enable_ats_device(int seg, int bus, int devfn); +int disable_ats_device(int seg, int bus, int devfn); +int invalidate_ats_tcs(struct iommu *iommu); int qinval_device_iotlb(struct iommu *iommu, u32 max_invs_pend, u16 sid, u16 size, u64 addr); +int dev_invalidate_iotlb(struct iommu *iommu, u16 did, + u64 addr, unsigned int size_order, u64 type); struct acpi_drhd_unit * find_ats_dev_drhd(struct iommu *iommu); #endif // _VTD_EXTERN_H_ diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/drivers/passthrough/vtd/ia64/ats.c --- a/xen/drivers/passthrough/vtd/ia64/ats.c Mon Jun 01 18:37:27 2009 +0100 +++ b/xen/drivers/passthrough/vtd/ia64/ats.c Tue Jun 02 11:49:34 2009 +0100 @@ -35,14 +35,6 @@ struct acpi_drhd_unit * find_ats_dev_drh return NULL; } -/* - * BUGBUG: return 0 until pcimmcfg is checked in. - */ -int pci_find_ext_capability(int seg, int bus, int devfn, int cap) -{ - return 0; -} - int ats_device(int seg, int bus, int devfn) { return 0; diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/drivers/passthrough/vtd/iommu.c --- a/xen/drivers/passthrough/vtd/iommu.c Mon Jun 01 18:37:27 2009 +0100 +++ b/xen/drivers/passthrough/vtd/iommu.c Tue Jun 02 11:49:34 2009 +0100 @@ -1663,10 +1663,8 @@ static void setup_dom0_devices(struct do pdev->domain = d; list_add(&pdev->domain_list, &d->arch.pdev_list); domain_context_mapping(d, pdev->bus, pdev->devfn); -#if defined(NOT_YET) if ( ats_device(0, pdev->bus, pdev->devfn) ) enable_ats_device(0, pdev->bus, pdev->devfn); -#endif } } } diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/drivers/passthrough/vtd/qinval.c --- a/xen/drivers/passthrough/vtd/qinval.c Mon Jun 01 18:37:27 2009 +0100 +++ b/xen/drivers/passthrough/vtd/qinval.c Tue Jun 02 11:49:34 2009 +0100 @@ -409,10 +409,8 @@ static int flush_iotlb_qi( ret = queue_invalidate_iotlb(iommu, (type >> DMA_TLB_FLUSH_GRANU_OFFSET), dr, dw, did, (u8)size_order, 0, addr); -#if defined(NOT_YET) if ( flush_dev_iotlb ) ret |= dev_invalidate_iotlb(iommu, did, addr, size_order, type); -#endif ret |= invalidate_sync(iommu); } return ret; diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/drivers/passthrough/vtd/x86/ats.c --- a/xen/drivers/passthrough/vtd/x86/ats.c Mon Jun 01 18:37:27 2009 +0100 +++ b/xen/drivers/passthrough/vtd/x86/ats.c Tue Jun 02 11:49:34 2009 +0100 @@ -79,14 +79,6 @@ struct acpi_drhd_unit * find_ats_dev_drh return drhd; } return NULL; -} - -/* - * BUGBUG: return 0 until pcimmcfg is checked in. - */ -int pci_find_ext_capability(int seg, int bus, int devfn, int cap) -{ - return 0; } int ats_device(int seg, int bus, int devfn) diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/include/asm-x86/acpi.h --- a/xen/include/asm-x86/acpi.h Mon Jun 01 18:37:27 2009 +0100 +++ b/xen/include/asm-x86/acpi.h Tue Jun 02 11:49:34 2009 +0100 @@ -164,7 +164,8 @@ extern u8 x86_acpiid_to_apicid[]; extern u8 x86_acpiid_to_apicid[]; #define MAX_LOCAL_APIC 256 -extern int acpi_dmar_init(void); +int acpi_dmar_init(void); +void acpi_mmcfg_init(void); /* Incremented whenever we transition through S3. Value is 1 during boot. */ extern uint32_t system_reset_counter; diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/include/asm-x86/config.h --- a/xen/include/asm-x86/config.h Mon Jun 01 18:37:27 2009 +0100 +++ b/xen/include/asm-x86/config.h Tue Jun 02 11:49:34 2009 +0100 @@ -135,7 +135,7 @@ extern unsigned int video_mode, video_fl * 0xffff804000000000 - 0xffff807fffffffff [256GB, 2^38 bytes, PML4:256] * Reserved for future shared info with the guest OS (GUEST ACCESSIBLE). * 0xffff808000000000 - 0xffff80ffffffffff [512GB, 2^39 bytes, PML4:257] - * Reserved for future use. + * ioremap for PCI mmconfig space * 0xffff810000000000 - 0xffff817fffffffff [512GB, 2^39 bytes, PML4:258] * Guest linear page table. * 0xffff818000000000 - 0xffff81ffffffffff [512GB, 2^39 bytes, PML4:259] @@ -188,6 +188,12 @@ extern unsigned int video_mode, video_fl /* Slot 256: read-only guest-accessible machine-to-phys translation table. */ #define RO_MPT_VIRT_START (PML4_ADDR(256)) #define RO_MPT_VIRT_END (RO_MPT_VIRT_START + PML4_ENTRY_BYTES/2) +/* Slot 257: ioremap for PCI mmconfig space for 2048 segments (512GB) + * - full 16-bit segment support needs 44 bits + * - 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) /* 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) diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/include/asm-x86/e820.h --- a/xen/include/asm-x86/e820.h Mon Jun 01 18:37:27 2009 +0100 +++ b/xen/include/asm-x86/e820.h Tue Jun 02 11:49:34 2009 +0100 @@ -23,6 +23,7 @@ struct e820map { struct e820entry map[E820MAX]; }; +extern int e820_all_mapped(u64 start, u64 end, unsigned type); extern int reserve_e820_ram(struct e820map *e820, uint64_t s, uint64_t e); extern int e820_change_range_type( struct e820map *e820, uint64_t s, uint64_t e, diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/include/asm-x86/msr-index.h --- a/xen/include/asm-x86/msr-index.h Mon Jun 01 18:37:27 2009 +0100 +++ b/xen/include/asm-x86/msr-index.h Tue Jun 02 11:49:34 2009 +0100 @@ -231,7 +231,7 @@ /* Other AMD Fam10h MSRs */ #define MSR_FAM10H_MMIO_CONF_BASE 0xc0010058 -#define FAM10H_MMIO_CONF_ENABLE_BIT 0 +#define FAM10H_MMIO_CONF_ENABLE (1<<0) #define FAM10H_MMIO_CONF_BUSRANGE_MASK 0xf #define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2 #define FAM10H_MMIO_CONF_BASE_MASK 0xfffffff diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/include/xen/pci.h --- a/xen/include/xen/pci.h Mon Jun 01 18:37:27 2009 +0100 +++ b/xen/include/xen/pci.h Tue Jun 02 11:49:34 2009 +0100 @@ -93,8 +93,13 @@ void pci_conf_write32( void pci_conf_write32( unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg, uint32_t data); +int pci_mmcfg_read(unsigned int seg, unsigned int bus, + unsigned int devfn, int reg, int len, u32 *value); +int pci_mmcfg_write(unsigned int seg, unsigned int bus, + unsigned int devfn, int reg, int len, u32 value); int pci_find_cap_offset(u8 bus, u8 dev, u8 func, u8 cap); int pci_find_next_cap(u8 bus, unsigned int devfn, u8 pos, int cap); +int pci_find_ext_capability(int seg, int bus, int devfn, int cap); int msixtbl_pt_register(struct domain *d, int pirq, uint64_t gtable); void msixtbl_pt_unregister(struct domain *d, int pirq); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |