[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86: Emulate accesses to PCI window registers cf8/cfc to synchronise
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1207916395 -3600 # Node ID 80ba1b4270321baa58b0e8064fb472f2c2462b8d # Parent 082d3886fded0ba361eafff82cda651acffc53cd x86: Emulate accesses to PCI window registers cf8/cfc to synchronise with accesses by teh hypervisor itself. All users of cf8/cfc go through new access functions which take the appropriate spinlock. Based on a patch by Haitao Shan <haitao.shan@xxxxxxxxx> Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> --- xen/drivers/passthrough/pci-direct.h | 48 ----- xen/arch/x86/Makefile | 1 xen/arch/x86/cpu/amd.c | 18 - xen/arch/x86/domain_build.c | 2 xen/arch/x86/pci.c | 118 ++++++++++++ xen/arch/x86/traps.c | 259 +++++++++++++++++----------- xen/drivers/passthrough/amd/iommu_detect.c | 37 +--- xen/drivers/passthrough/amd/iommu_init.c | 2 xen/drivers/passthrough/amd/pci_amd_iommu.c | 6 xen/drivers/passthrough/vtd/dmar.c | 18 - xen/drivers/passthrough/vtd/intremap.c | 2 xen/drivers/passthrough/vtd/iommu.c | 28 +-- xen/drivers/passthrough/vtd/qinval.c | 2 xen/drivers/passthrough/vtd/utils.c | 32 +-- xen/include/asm-x86/domain.h | 1 xen/include/xen/pci.h | 29 +++ 16 files changed, 374 insertions(+), 229 deletions(-) diff -r 082d3886fded -r 80ba1b427032 xen/arch/x86/Makefile --- a/xen/arch/x86/Makefile Fri Apr 11 09:14:03 2008 +0100 +++ b/xen/arch/x86/Makefile Fri Apr 11 13:19:55 2008 +0100 @@ -31,6 +31,7 @@ obj-y += mpparse.o obj-y += mpparse.o obj-y += nmi.o obj-y += numa.o +obj-y += pci.o obj-y += physdev.o obj-y += rwlock.o obj-y += setup.o diff -r 082d3886fded -r 80ba1b427032 xen/arch/x86/cpu/amd.c --- a/xen/arch/x86/cpu/amd.c Fri Apr 11 09:14:03 2008 +0100 +++ b/xen/arch/x86/cpu/amd.c Fri Apr 11 13:19:55 2008 +0100 @@ -3,6 +3,7 @@ #include <xen/bitops.h> #include <xen/mm.h> #include <xen/smp.h> +#include <xen/pci.h> #include <asm/io.h> #include <asm/msr.h> #include <asm/processor.h> @@ -66,19 +67,6 @@ static int c1_ramping_may_cause_clock_dr return 1; } -/* PCI access functions. Should be safe to use 0xcf8/0xcfc port accesses here. */ -static u8 pci_read_byte(u32 bus, u32 dev, u32 fn, u32 reg) -{ - outl((1U<<31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3), 0xcf8); - return inb(0xcfc + (reg & 3)); -} - -static void pci_write_byte(u32 bus, u32 dev, u32 fn, u32 reg, u8 val) -{ - outl((1U<<31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3), 0xcf8); - outb(val, 0xcfc + (reg & 3)); -} - /* * Disable C1-Clock ramping if enabled in PMM7.CpuLowPwrEnh on 8th-generation * cores only. Assume BIOS has setup all Northbridges equivalently. @@ -90,12 +78,12 @@ static void disable_c1_ramping(void) for (node=0; node < NR_CPUS; node++) { /* PMM7: bus=0, dev=0x18+node, function=0x3, register=0x87. */ - pmm7 = pci_read_byte(0, 0x18+node, 0x3, 0x87); + pmm7 = pci_conf_read8(0, 0x18+node, 0x3, 0x87); /* Invalid read means we've updated every Northbridge. */ if (pmm7 == 0xFF) break; pmm7 &= 0xFC; /* clear pmm7[1:0] */ - pci_write_byte(0, 0x18+node, 0x3, 0x87, pmm7); + pci_conf_write8(0, 0x18+node, 0x3, 0x87, pmm7); printk ("AMD: Disabling C1 Clock Ramping Node #%x\n", node); } } diff -r 082d3886fded -r 80ba1b427032 xen/arch/x86/domain_build.c --- a/xen/arch/x86/domain_build.c Fri Apr 11 09:14:03 2008 +0100 +++ b/xen/arch/x86/domain_build.c Fri Apr 11 13:19:55 2008 +0100 @@ -957,6 +957,8 @@ int __init construct_dom0( rc |= ioports_deny_access(dom0, 0x40, 0x43); /* PIT Channel 2 / PC Speaker Control. */ rc |= ioports_deny_access(dom0, 0x61, 0x61); + /* PCI configuration spaces. */ + rc |= ioports_deny_access(dom0, 0xcf8, 0xcff); /* Command-line I/O ranges. */ process_dom0_ioports_disable(); diff -r 082d3886fded -r 80ba1b427032 xen/arch/x86/pci.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/x86/pci.c Fri Apr 11 13:19:55 2008 +0100 @@ -0,0 +1,118 @@ +/****************************************************************************** + * pci.c + * + * PCI access functions. + */ + +#include <xen/config.h> +#include <xen/pci.h> +#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); + +uint32_t pci_conf_read(uint32_t cf8, uint8_t offset, uint8_t bytes) +{ + unsigned long flags; + uint32_t value; + + BUG_ON((offset + bytes) > 4); + + spin_lock_irqsave(&pci_config_lock, flags); + + outl(cf8, 0xcf8); + + switch ( bytes ) + { + case 1: + value = inb(0xcfc + offset); + break; + case 2: + value = inw(0xcfc + offset); + break; + case 4: + value = inl(0xcfc + offset); + break; + default: + value = 0; + BUG(); + } + + spin_unlock_irqrestore(&pci_config_lock, flags); + + return value; +} + +void pci_conf_write(uint32_t cf8, uint8_t offset, uint8_t bytes, uint32_t data) +{ + unsigned long flags; + + BUG_ON((offset + bytes) > 4); + + spin_lock_irqsave(&pci_config_lock, flags); + + outl(cf8, 0xcf8); + + switch ( bytes ) + { + case 1: + outb((uint8_t)data, 0xcfc + offset); + break; + case 2: + outw((uint16_t)data, 0xcfc + offset); + break; + case 4: + outl(data, 0xcfc + offset); + break; + } + + 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 082d3886fded -r 80ba1b427032 xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Fri Apr 11 09:14:03 2008 +0100 +++ b/xen/arch/x86/traps.c Fri Apr 11 13:19:55 2008 +0100 @@ -1353,7 +1353,7 @@ static int read_gate_descriptor(unsigned #endif /* Has the guest requested sufficient permission for this I/O access? */ -static inline int guest_io_okay( +static int guest_io_okay( unsigned int port, unsigned int bytes, struct vcpu *v, struct cpu_user_regs *regs) { @@ -1395,19 +1395,130 @@ static inline int guest_io_okay( } /* Has the administrator granted sufficient permission for this I/O access? */ -static inline int admin_io_okay( +static int admin_io_okay( unsigned int port, unsigned int bytes, struct vcpu *v, struct cpu_user_regs *regs) { return ioports_access_permitted(v->domain, port, port + bytes - 1); } -#define guest_inb_okay(_p, _d, _r) admin_io_okay(_p, 1, _d, _r) -#define guest_inw_okay(_p, _d, _r) admin_io_okay(_p, 2, _d, _r) -#define guest_inl_okay(_p, _d, _r) admin_io_okay(_p, 4, _d, _r) -#define guest_outb_okay(_p, _d, _r) admin_io_okay(_p, 1, _d, _r) -#define guest_outw_okay(_p, _d, _r) admin_io_okay(_p, 2, _d, _r) -#define guest_outl_okay(_p, _d, _r) admin_io_okay(_p, 4, _d, _r) +static uint32_t guest_io_read( + unsigned int port, unsigned int bytes, + struct vcpu *v, struct cpu_user_regs *regs) +{ + extern uint32_t pci_conf_read( + uint32_t cf8, uint8_t offset, uint8_t bytes); + + uint32_t data = 0; + unsigned int shift = 0; + + if ( admin_io_okay(port, bytes, v, regs) ) + { + switch ( bytes ) + { + case 1: return inb(port); + case 2: return inw(port); + case 4: return inl(port); + } + } + + while ( bytes != 0 ) + { + unsigned int size = 1; + uint32_t sub_data = 0xff; + + if ( (port == 0x42) || (port == 0x43) || (port == 0x61) ) + { + sub_data = pv_pit_handler(port, 0, 0); + } + else if ( (port & 0xfffc) == 0xcf8 ) + { + size = min(bytes, 4 - (port & 3)); + sub_data = v->domain->arch.pci_cf8 >> ((port & 3) * 8); + } + else if ( ((port & 0xfffc) == 0xcfc) && IS_PRIV(v->domain) ) + { + size = min(bytes, 4 - (port & 3)); + if ( size == 3 ) + size = 2; + sub_data = pci_conf_read(v->domain->arch.pci_cf8, port & 3, size); + } + + if ( size == 4 ) + return sub_data; + + data |= (sub_data & ((1u << (size * 8)) - 1)) << shift; + shift += size * 8; + port += size; + bytes -= size; + } + + return data; +} + +static void guest_io_write( + unsigned int port, unsigned int bytes, uint32_t data, + struct vcpu *v, struct cpu_user_regs *regs) +{ + extern void pci_conf_write( + uint32_t cf8, uint8_t offset, uint8_t bytes, uint32_t data); + + if ( admin_io_okay(port, bytes, v, regs) ) + { + switch ( bytes ) { + case 1: + outb((uint8_t)data, port); + if ( pv_post_outb_hook ) + pv_post_outb_hook(port, (uint8_t)data); + break; + case 2: + outw((uint16_t)data, port); + break; + case 4: + outl(data, port); + break; + } + return; + } + + while ( bytes != 0 ) + { + unsigned int size = 1; + + if ( (port == 0x42) || (port == 0x43) || (port == 0x61) ) + { + pv_pit_handler(port, (uint8_t)data, 1); + } + else if ( (port & 0xfffc) == 0xcf8 ) + { + size = min(bytes, 4 - (port & 3)); + if ( size == 4 ) + { + v->domain->arch.pci_cf8 = data; + } + else + { + uint32_t mask = ((1u << (size * 8)) - 1) << ((port & 3) * 8); + v->domain->arch.pci_cf8 &= ~mask; + v->domain->arch.pci_cf8 |= (data << ((port & 3) * 8)) & mask; + } + } + else if ( ((port & 0xfffc) == 0xcfc) && IS_PRIV(v->domain) ) + { + size = min(bytes, 4 - (port & 3)); + if ( size == 3 ) + size = 2; + pci_conf_write(v->domain->arch.pci_cf8, port & 3, size, data); + } + + if ( size == 4 ) + return; + + port += size; + bytes -= size; + data >>= size * 8; + } +} /* I/O emulation support. Helper routines for, and type of, the stack stub.*/ void host_to_guest_gpr_switch(struct cpu_user_regs *) @@ -1526,7 +1637,7 @@ static int emulate_privileged_op(struct /* REX prefix. */ if ( rex & 8 ) /* REX.W */ - op_bytes = 4; /* emulating only opcodes not supporting 64-bit operands */ + op_bytes = 4; /* emulate only opcodes not supporting 64-bit operands */ modrm_reg = (rex & 4) << 1; /* REX.R */ /* REX.X does not need to be decoded. */ modrm_rm = (rex & 1) << 3; /* REX.B */ @@ -1555,7 +1666,8 @@ static int emulate_privileged_op(struct { if ( !read_descriptor(data_sel, v, regs, &data_base, &data_limit, &ar, - _SEGMENT_WR|_SEGMENT_S|_SEGMENT_DPL|_SEGMENT_P) ) + _SEGMENT_WR|_SEGMENT_S|_SEGMENT_DPL| + _SEGMENT_P) ) goto fail; if ( !(ar & _SEGMENT_S) || !(ar & _SEGMENT_P) || @@ -1602,69 +1714,39 @@ static int emulate_privileged_op(struct case 0x6c: /* INSB */ op_bytes = 1; case 0x6d: /* INSW/INSL */ - if ( data_limit < op_bytes - 1 || - rd_ad(edi) > data_limit - (op_bytes - 1) || + if ( (data_limit < (op_bytes - 1)) || + (rd_ad(edi) > (data_limit - (op_bytes - 1))) || !guest_io_okay(port, op_bytes, v, regs) ) goto fail; - switch ( op_bytes ) - { - case 1: - /* emulate PIT counter 2 */ - data = (u8)(guest_inb_okay(port, v, regs) ? inb(port) : - ((port == 0x42 || port == 0x43 || port == 0x61) ? - pv_pit_handler(port, 0, 0) : ~0)); - break; - case 2: - data = (u16)(guest_inw_okay(port, v, regs) ? inw(port) : ~0); - break; - case 4: - data = (u32)(guest_inl_okay(port, v, regs) ? inl(port) : ~0); - break; - } - if ( (rc = copy_to_user((void *)data_base + rd_ad(edi), &data, op_bytes)) != 0 ) + data = guest_io_read(port, op_bytes, v, regs); + if ( (rc = copy_to_user((void *)data_base + rd_ad(edi), + &data, op_bytes)) != 0 ) { propagate_page_fault(data_base + rd_ad(edi) + op_bytes - rc, PFEC_write_access); return EXCRET_fault_fixed; } - wr_ad(edi, regs->edi + (int)((regs->eflags & EF_DF) ? -op_bytes : op_bytes)); + wr_ad(edi, regs->edi + (int)((regs->eflags & EF_DF) + ? -op_bytes : op_bytes)); break; case 0x6e: /* OUTSB */ op_bytes = 1; case 0x6f: /* OUTSW/OUTSL */ - if ( data_limit < op_bytes - 1 || - rd_ad(esi) > data_limit - (op_bytes - 1) || - !guest_io_okay(port, op_bytes, v, regs) ) + if ( (data_limit < (op_bytes - 1)) || + (rd_ad(esi) > (data_limit - (op_bytes - 1))) || + !guest_io_okay(port, op_bytes, v, regs) ) goto fail; - rc = copy_from_user(&data, (void *)data_base + rd_ad(esi), op_bytes); - if ( rc != 0 ) + if ( (rc = copy_from_user(&data, (void *)data_base + rd_ad(esi), + op_bytes)) != 0 ) { - propagate_page_fault(data_base + rd_ad(esi) + op_bytes - rc, 0); + propagate_page_fault(data_base + rd_ad(esi) + + op_bytes - rc, 0); return EXCRET_fault_fixed; } - switch ( op_bytes ) - { - case 1: - if ( guest_outb_okay(port, v, regs) ) - { - outb((u8)data, port); - if ( pv_post_outb_hook ) - pv_post_outb_hook(port, data); - } - else if ( port == 0x42 || port == 0x43 || port == 0x61 ) - pv_pit_handler(port, data, 1); - break; - case 2: - if ( guest_outw_okay(port, v, regs) ) - outw((u16)data, port); - break; - case 4: - if ( guest_outl_okay(port, v, regs) ) - outl((u32)data, port); - break; - } - wr_ad(esi, regs->esi + (int)((regs->eflags & EF_DF) ? -op_bytes : op_bytes)); + guest_io_write(port, op_bytes, data, v, regs); + wr_ad(esi, regs->esi + (int)((regs->eflags & EF_DF) + ? -op_bytes : op_bytes)); break; } @@ -1728,31 +1810,17 @@ static int emulate_privileged_op(struct exec_in: if ( !guest_io_okay(port, op_bytes, v, regs) ) goto fail; - switch ( op_bytes ) - { - case 1: - if ( guest_inb_okay(port, v, regs) ) - io_emul(regs); - else if ( port == 0x42 || port == 0x43 || port == 0x61 ) - { - regs->eax &= ~0xffUL; - regs->eax |= pv_pit_handler(port, 0, 0); - } + if ( admin_io_okay(port, op_bytes, v, regs) ) + { + io_emul(regs); + } + else + { + if ( op_bytes == 4 ) + regs->eax = 0; else - regs->eax |= (u8)~0; - break; - case 2: - if ( guest_inw_okay(port, v, regs) ) - io_emul(regs); - else - regs->eax |= (u16)~0; - break; - case 4: - if ( guest_inl_okay(port, v, regs) ) - io_emul(regs); - else - regs->eax = (u32)~0; - break; + regs->eax &= ~((1u << (op_bytes * 8)) - 1); + regs->eax |= guest_io_read(port, op_bytes, v, regs); } bpmatch = check_guest_io_breakpoint(v, port, op_bytes); goto done; @@ -1771,26 +1839,15 @@ static int emulate_privileged_op(struct exec_out: if ( !guest_io_okay(port, op_bytes, v, regs) ) goto fail; - switch ( op_bytes ) - { - case 1: - if ( guest_outb_okay(port, v, regs) ) - { - io_emul(regs); - if ( pv_post_outb_hook ) - pv_post_outb_hook(port, regs->eax); - } - else if ( port == 0x42 || port == 0x43 || port == 0x61 ) - pv_pit_handler(port, regs->eax, 1); - break; - case 2: - if ( guest_outw_okay(port, v, regs) ) - io_emul(regs); - break; - case 4: - if ( guest_outl_okay(port, v, regs) ) - io_emul(regs); - break; + if ( admin_io_okay(port, op_bytes, v, regs) ) + { + io_emul(regs); + if ( (op_bytes == 1) && pv_post_outb_hook ) + pv_post_outb_hook(port, regs->eax); + } + else + { + guest_io_write(port, op_bytes, regs->eax, v, regs); } bpmatch = check_guest_io_breakpoint(v, port, op_bytes); goto done; diff -r 082d3886fded -r 80ba1b427032 xen/drivers/passthrough/amd/iommu_detect.c --- a/xen/drivers/passthrough/amd/iommu_detect.c Fri Apr 11 09:14:03 2008 +0100 +++ b/xen/drivers/passthrough/amd/iommu_detect.c Fri Apr 11 13:19:55 2008 +0100 @@ -21,9 +21,9 @@ #include <xen/config.h> #include <xen/errno.h> #include <xen/iommu.h> +#include <xen/pci.h> #include <asm/amd-iommu.h> #include <asm/hvm/svm/amd-iommu-proto.h> -#include "../pci-direct.h" #include "../pci_regs.h" static int __init valid_bridge_bus_config( @@ -31,9 +31,9 @@ static int __init valid_bridge_bus_confi { int pri_bus; - pri_bus = read_pci_config_byte(bus, dev, func, PCI_PRIMARY_BUS); - *sec_bus = read_pci_config_byte(bus, dev, func, PCI_SECONDARY_BUS); - *sub_bus = read_pci_config_byte(bus, dev, func, PCI_SUBORDINATE_BUS); + pri_bus = pci_conf_read8(bus, dev, func, PCI_PRIMARY_BUS); + *sec_bus = pci_conf_read8(bus, dev, func, PCI_SECONDARY_BUS); + *sub_bus = pci_conf_read8(bus, dev, func, PCI_SUBORDINATE_BUS); return ((pri_bus == bus) && (*sec_bus > bus) && (*sub_bus >= *sec_bus)); } @@ -59,12 +59,11 @@ int __init get_iommu_last_downstream_bus } func = PCI_FUNC(devfn); - if ( !VALID_PCI_VENDOR_ID( - read_pci_config_16(bus, dev, func, PCI_VENDOR_ID)) ) + if ( !VALID_PCI_VENDOR_ID(pci_conf_read16(bus, dev, func, + PCI_VENDOR_ID)) ) continue; - hdr_type = read_pci_config_byte(bus, dev, func, - PCI_HEADER_TYPE); + hdr_type = pci_conf_read8(bus, dev, func, PCI_HEADER_TYPE); if ( func == 0 ) multi_func = IS_PCI_MULTI_FUNCTION(hdr_type); @@ -92,9 +91,9 @@ int __init get_iommu_capabilities(u8 bus u32 cap_header, cap_range, misc_info; u64 mmio_bar; - mmio_bar = (u64)read_pci_config( + mmio_bar = (u64)pci_conf_read32( bus, dev, func, cap_ptr + PCI_CAP_MMIO_BAR_HIGH_OFFSET) << 32; - mmio_bar |= read_pci_config(bus, dev, func, + mmio_bar |= pci_conf_read32(bus, dev, func, cap_ptr + PCI_CAP_MMIO_BAR_LOW_OFFSET); iommu->mmio_base_phys = mmio_bar & (u64)~0x3FFF; @@ -108,7 +107,7 @@ int __init get_iommu_capabilities(u8 bus iommu->bdf = (bus << 8) | PCI_DEVFN(dev, func); iommu->cap_offset = cap_ptr; - cap_header = read_pci_config(bus, dev, func, cap_ptr); + cap_header = pci_conf_read32(bus, dev, func, cap_ptr); iommu->revision = get_field_from_reg_u32( cap_header, PCI_CAP_REV_MASK, PCI_CAP_REV_SHIFT); iommu->iotlb_support = get_field_from_reg_u32( @@ -118,7 +117,7 @@ int __init get_iommu_capabilities(u8 bus iommu->pte_not_present_cached = get_field_from_reg_u32( cap_header, PCI_CAP_NP_CACHE_MASK, PCI_CAP_NP_CACHE_SHIFT); - cap_range = read_pci_config(bus, dev, func, + cap_range = pci_conf_read32(bus, dev, func, cap_ptr + PCI_CAP_RANGE_OFFSET); iommu->unit_id = get_field_from_reg_u32( cap_range, PCI_CAP_UNIT_ID_MASK, PCI_CAP_UNIT_ID_SHIFT); @@ -129,7 +128,7 @@ int __init get_iommu_capabilities(u8 bus iommu->last_devfn = get_field_from_reg_u32( cap_range, PCI_CAP_LAST_DEVICE_MASK, PCI_CAP_LAST_DEVICE_SHIFT); - misc_info = read_pci_config(bus, dev, func, + misc_info = pci_conf_read32(bus, dev, func, cap_ptr + PCI_MISC_INFO_OFFSET); iommu->msi_number = get_field_from_reg_u32( misc_info, PCI_CAP_MSI_NUMBER_MASK, PCI_CAP_MSI_NUMBER_SHIFT); @@ -146,14 +145,13 @@ static int __init scan_caps_for_iommu( int count, error = 0; count = 0; - cap_ptr = read_pci_config_byte(bus, dev, func, - PCI_CAPABILITY_LIST); + cap_ptr = pci_conf_read8(bus, dev, func, PCI_CAPABILITY_LIST); while ( (cap_ptr >= PCI_MIN_CAP_OFFSET) && (count < PCI_MAX_CAP_BLOCKS) && !error ) { cap_ptr &= PCI_CAP_PTR_MASK; - cap_header = read_pci_config(bus, dev, func, cap_ptr); + cap_header = pci_conf_read32(bus, dev, func, cap_ptr); cap_id = get_field_from_reg_u32( cap_header, PCI_CAP_ID_MASK, PCI_CAP_ID_SHIFT); @@ -182,12 +180,11 @@ static int __init scan_functions_for_iom func = 0; count = 1; - while ( VALID_PCI_VENDOR_ID(read_pci_config_16(bus, dev, func, - PCI_VENDOR_ID)) && + while ( VALID_PCI_VENDOR_ID(pci_conf_read16(bus, dev, func, + PCI_VENDOR_ID)) && !error && (func < count) ) { - hdr_type = read_pci_config_byte(bus, dev, func, - PCI_HEADER_TYPE); + hdr_type = pci_conf_read8(bus, dev, func, PCI_HEADER_TYPE); if ( func == 0 && IS_PCI_MULTI_FUNCTION(hdr_type) ) count = PCI_MAX_FUNC_COUNT; diff -r 082d3886fded -r 80ba1b427032 xen/drivers/passthrough/amd/iommu_init.c --- a/xen/drivers/passthrough/amd/iommu_init.c Fri Apr 11 09:14:03 2008 +0100 +++ b/xen/drivers/passthrough/amd/iommu_init.c Fri Apr 11 13:19:55 2008 +0100 @@ -20,10 +20,10 @@ #include <xen/config.h> #include <xen/errno.h> +#include <xen/pci.h> #include <asm/amd-iommu.h> #include <asm/hvm/svm/amd-iommu-proto.h> #include <asm-x86/fixmap.h> -#include "../pci-direct.h" #include "../pci_regs.h" extern int nr_amd_iommus; diff -r 082d3886fded -r 80ba1b427032 xen/drivers/passthrough/amd/pci_amd_iommu.c --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c Fri Apr 11 09:14:03 2008 +0100 +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c Fri Apr 11 13:19:55 2008 +0100 @@ -18,12 +18,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <xen/sched.h> +#include <xen/pci.h> #include <asm/amd-iommu.h> #include <asm/hvm/svm/amd-iommu-proto.h> #include <asm/hvm/svm/amd-iommu-acpi.h> -#include <xen/sched.h> #include <asm/mm.h> -#include "../pci-direct.h" #include "../pci_regs.h" struct list_head amd_iommu_head; @@ -316,7 +316,7 @@ void __init amd_iommu_setup_dom0_devices { for ( func = 0; func < 8; func++ ) { - l = read_pci_config(bus, dev, func, PCI_VENDOR_ID); + l = pci_conf_read32(bus, dev, func, PCI_VENDOR_ID); /* some broken boards return 0 or ~0 if a slot is empty: */ if ( (l == 0xffffffff) || (l == 0x00000000) || (l == 0x0000ffff) || (l == 0xffff0000) ) diff -r 082d3886fded -r 80ba1b427032 xen/drivers/passthrough/pci-direct.h --- a/xen/drivers/passthrough/pci-direct.h Fri Apr 11 09:14:03 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -#ifndef ASM_PCI_DIRECT_H -#define ASM_PCI_DIRECT_H 1 - -#include <xen/types.h> -#include <asm/io.h> - -/* Direct PCI access. This is used for PCI accesses in early boot before - the PCI subsystem works. */ - -#define PDprintk(x...) - -static inline u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset) -{ - u32 v; - outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); - v = inl(0xcfc); - if (v != 0xffffffff) - PDprintk("%x reading 4 from %x: %x\n", slot, offset, v); - return v; -} - -static inline u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset) -{ - u8 v; - outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); - v = inb(0xcfc + (offset&3)); - PDprintk("%x reading 1 from %x: %x\n", slot, offset, v); - return v; -} - -static inline u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset) -{ - u16 v; - outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); - v = inw(0xcfc + (offset&2)); - PDprintk("%x reading 2 from %x: %x\n", slot, offset, v); - return v; -} - -static inline void write_pci_config( - u8 bus, u8 slot, u8 func, u8 offset, u32 val) -{ - PDprintk("%x writing to %x: %x\n", slot, offset, val); - outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); - outl(val, 0xcfc); -} - -#endif diff -r 082d3886fded -r 80ba1b427032 xen/drivers/passthrough/vtd/dmar.c --- a/xen/drivers/passthrough/vtd/dmar.c Fri Apr 11 09:14:03 2008 +0100 +++ b/xen/drivers/passthrough/vtd/dmar.c Fri Apr 11 13:19:55 2008 +0100 @@ -25,9 +25,9 @@ #include <xen/acpi.h> #include <xen/mm.h> #include <xen/xmalloc.h> +#include <xen/pci.h> #include <asm/string.h> #include "dmar.h" -#include "../pci-direct.h" #include "../pci_regs.h" int vtd_enabled; @@ -233,7 +233,7 @@ static int scope_device_count(void *star / sizeof(struct acpi_pci_path); while ( --depth > 0 ) { - bus = read_pci_config_byte( + bus = pci_conf_read8( bus, path->dev, path->fn, PCI_SECONDARY_BUS); path++; } @@ -250,9 +250,9 @@ static int scope_device_count(void *star dprintk(XENLOG_INFO VTDPREFIX, "found bridge: bdf = %x:%x:%x\n", bus, path->dev, path->fn); - sec_bus = read_pci_config_byte( + sec_bus = pci_conf_read8( bus, path->dev, path->fn, PCI_SECONDARY_BUS); - sub_bus = read_pci_config_byte( + sub_bus = pci_conf_read8( bus, path->dev, path->fn, PCI_SUBORDINATE_BUS); while ( sec_bus <= sub_bus ) @@ -261,7 +261,7 @@ static int scope_device_count(void *star { for ( func = 0; func < 8; func++ ) { - l = read_pci_config( + l = pci_conf_read32( sec_bus, dev, func, PCI_VENDOR_ID); /* some broken boards return 0 or @@ -355,7 +355,7 @@ static int __init acpi_parse_dev_scope( while ( --depth > 0 ) { - bus = read_pci_config_byte( + bus = pci_conf_read8( bus, path->dev, path->fn, PCI_SECONDARY_BUS); path++; } @@ -374,9 +374,9 @@ static int __init acpi_parse_dev_scope( dprintk(XENLOG_INFO VTDPREFIX, "found bridge: bus = %x dev = %x func = %x\n", bus, path->dev, path->fn); - sec_bus = read_pci_config_byte( + sec_bus = pci_conf_read8( bus, path->dev, path->fn, PCI_SECONDARY_BUS); - sub_bus = read_pci_config_byte( + sub_bus = pci_conf_read8( bus, path->dev, path->fn, PCI_SUBORDINATE_BUS); while ( sec_bus <= sub_bus ) @@ -385,7 +385,7 @@ static int __init acpi_parse_dev_scope( { for ( func = 0; func < 8; func++ ) { - l = read_pci_config( + l = pci_conf_read32( sec_bus, dev, func, PCI_VENDOR_ID); /* some broken boards return 0 or diff -r 082d3886fded -r 80ba1b427032 xen/drivers/passthrough/vtd/intremap.c --- a/xen/drivers/passthrough/vtd/intremap.c Fri Apr 11 09:14:03 2008 +0100 +++ b/xen/drivers/passthrough/vtd/intremap.c Fri Apr 11 13:19:55 2008 +0100 @@ -22,10 +22,10 @@ #include <xen/sched.h> #include <xen/iommu.h> #include <xen/time.h> +#include <xen/pci.h> #include "iommu.h" #include "dmar.h" #include "vtd.h" -#include "../pci-direct.h" #include "../pci_regs.h" #include "msi.h" #include "extern.h" diff -r 082d3886fded -r 80ba1b427032 xen/drivers/passthrough/vtd/iommu.c --- a/xen/drivers/passthrough/vtd/iommu.c Fri Apr 11 09:14:03 2008 +0100 +++ b/xen/drivers/passthrough/vtd/iommu.c Fri Apr 11 13:19:55 2008 +0100 @@ -23,13 +23,13 @@ #include <xen/sched.h> #include <xen/xmalloc.h> #include <xen/domain_page.h> -#include <asm/paging.h> #include <xen/iommu.h> #include <xen/numa.h> #include <xen/time.h> +#include <xen/pci.h> +#include <asm/paging.h> #include "iommu.h" #include "dmar.h" -#include "../pci-direct.h" #include "../pci_regs.h" #include "msi.h" #include "extern.h" @@ -1228,13 +1228,13 @@ static int __pci_find_next_cap(u8 bus, u while ( ttl-- ) { - pos = read_pci_config_byte(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos); + pos = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos); if ( pos < 0x40 ) break; pos &= ~3; - id = read_pci_config_byte(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), - pos + PCI_CAP_LIST_ID); + id = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), + pos + PCI_CAP_LIST_ID); if ( id == 0xff ) break; @@ -1258,13 +1258,13 @@ int pdev_type(struct pci_dev *dev) u16 class_device; u16 status; - class_device = read_pci_config_16(dev->bus, PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn), PCI_CLASS_DEVICE); + class_device = pci_conf_read16(dev->bus, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), PCI_CLASS_DEVICE); if ( class_device == PCI_CLASS_BRIDGE_PCI ) return DEV_TYPE_PCI_BRIDGE; - status = read_pci_config_16(dev->bus, PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn), PCI_STATUS); + status = pci_conf_read16(dev->bus, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), PCI_STATUS); if ( !(status & PCI_STATUS_CAP_LIST) ) return DEV_TYPE_PCI; @@ -1292,7 +1292,7 @@ static int domain_context_mapping( switch ( type ) { case DEV_TYPE_PCI_BRIDGE: - sec_bus = read_pci_config_byte( + sec_bus = pci_conf_read8( pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), PCI_SECONDARY_BUS); @@ -1302,7 +1302,7 @@ static int domain_context_mapping( bus2bridge[sec_bus].devfn = pdev->devfn; } - sub_bus = read_pci_config_byte( + sub_bus = pci_conf_read8( pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), PCI_SUBORDINATE_BUS); @@ -1425,10 +1425,10 @@ static int domain_context_unmap( switch ( type ) { case DEV_TYPE_PCI_BRIDGE: - sec_bus = read_pci_config_byte( + sec_bus = pci_conf_read8( pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), PCI_SECONDARY_BUS); - sub_bus = read_pci_config_byte( + sub_bus = pci_conf_read8( pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), PCI_SUBORDINATE_BUS); @@ -1781,7 +1781,7 @@ void __init setup_dom0_devices(void) { for ( func = 0; func < 8; func++ ) { - l = read_pci_config(bus, dev, func, PCI_VENDOR_ID); + l = pci_conf_read32(bus, dev, func, PCI_VENDOR_ID); /* some broken boards return 0 or ~0 if a slot is empty: */ if ( (l == 0xffffffff) || (l == 0x00000000) || (l == 0x0000ffff) || (l == 0xffff0000) ) diff -r 082d3886fded -r 80ba1b427032 xen/drivers/passthrough/vtd/qinval.c --- a/xen/drivers/passthrough/vtd/qinval.c Fri Apr 11 09:14:03 2008 +0100 +++ b/xen/drivers/passthrough/vtd/qinval.c Fri Apr 11 13:19:55 2008 +0100 @@ -22,10 +22,10 @@ #include <xen/sched.h> #include <xen/iommu.h> #include <xen/time.h> +#include <xen/pci.h> #include "iommu.h" #include "dmar.h" #include "vtd.h" -#include "../pci-direct.h" #include "../pci_regs.h" #include "msi.h" #include "extern.h" diff -r 082d3886fded -r 80ba1b427032 xen/drivers/passthrough/vtd/utils.c --- a/xen/drivers/passthrough/vtd/utils.c Fri Apr 11 09:14:03 2008 +0100 +++ b/xen/drivers/passthrough/vtd/utils.c Fri Apr 11 13:19:55 2008 +0100 @@ -21,9 +21,9 @@ #include <xen/delay.h> #include <xen/iommu.h> #include <xen/time.h> +#include <xen/pci.h> #include "iommu.h" #include "dmar.h" -#include "../pci-direct.h" #include "../pci_regs.h" #include "msi.h" #include "vtd.h" @@ -37,7 +37,7 @@ int is_usb_device(struct pci_dev *pdev) u8 bus = pdev->bus; u8 dev = PCI_SLOT(pdev->devfn); u8 func = PCI_FUNC(pdev->devfn); - u16 class = read_pci_config_16(bus, dev, func, PCI_CLASS_DEVICE); + u16 class = pci_conf_read16(bus, dev, func, PCI_CLASS_DEVICE); return (class == 0xc03); } @@ -46,9 +46,9 @@ int vtd_hw_check(void) u16 vendor, device; u8 revision, stepping; - vendor = read_pci_config_16(0, 0, 0, PCI_VENDOR_ID); - device = read_pci_config_16(0, 0, 0, PCI_DEVICE_ID); - revision = read_pci_config_byte(0, 0, 0, PCI_REVISION_ID); + vendor = pci_conf_read16(0, 0, 0, PCI_VENDOR_ID); + device = pci_conf_read16(0, 0, 0, PCI_DEVICE_ID); + revision = pci_conf_read8(0, 0, 0, PCI_REVISION_ID); stepping = revision & 0xf; if ( (vendor == INTEL) && (device == SEABURG) ) @@ -103,18 +103,18 @@ static u8 find_cap_offset(u8 bus, u8 dev u8 pos = PCI_CAPABILITY_LIST; u16 status; - status = read_pci_config_16(bus, dev, func, PCI_STATUS); + status = pci_conf_read16(bus, dev, func, PCI_STATUS); if ( (status & PCI_STATUS_CAP_LIST) == 0 ) return 0; while ( max_cap-- ) { - pos = read_pci_config_byte(bus, dev, func, pos); + pos = pci_conf_read8(bus, dev, func, pos); if ( pos < 0x40 ) break; pos &= ~3; - id = read_pci_config_byte(bus, dev, func, pos + PCI_CAP_LIST_ID); + id = pci_conf_read8(bus, dev, func, pos + PCI_CAP_LIST_ID); if ( id == 0xff ) break; @@ -143,13 +143,13 @@ void pdev_flr(u8 bus, u8 devfn) pos = find_cap_offset(bus, dev, func, PCI_CAP_ID_EXP); if ( pos != 0 ) { - dev_cap = read_pci_config(bus, dev, func, pos + PCI_EXP_DEVCAP); + dev_cap = pci_conf_read32(bus, dev, func, pos + PCI_EXP_DEVCAP); if ( dev_cap & PCI_EXP_DEVCAP_FLR ) { - write_pci_config(bus, dev, func, + pci_conf_write32(bus, dev, func, pos + PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_FLR); do { - dev_status = read_pci_config(bus, dev, func, + dev_status = pci_conf_read32(bus, dev, func, pos + PCI_EXP_DEVSTA); } while ( dev_status & PCI_EXP_DEVSTA_TRPND ); @@ -169,23 +169,23 @@ void pdev_flr(u8 bus, u8 devfn) int i; u32 config[PCI_CONFIG_DWORD_SIZE]; for ( i = 0; i < PCI_CONFIG_DWORD_SIZE; i++ ) - config[i] = read_pci_config(bus, dev, func, i*4); + config[i] = pci_conf_read32(bus, dev, func, i*4); /* Enter D3hot without soft reset */ - pm_ctl = read_pci_config(bus, dev, func, pos + PCI_PM_CTRL); + pm_ctl = pci_conf_read32(bus, dev, func, pos + PCI_PM_CTRL); pm_ctl |= PCI_PM_CTRL_NO_SOFT_RESET; pm_ctl &= ~PCI_PM_CTRL_STATE_MASK; pm_ctl |= PCI_D3hot; - write_pci_config(bus, dev, func, pos + PCI_PM_CTRL, pm_ctl); + pci_conf_write32(bus, dev, func, pos + PCI_PM_CTRL, pm_ctl); mdelay(10); /* From D3hot to D0 */ - write_pci_config(bus, dev, func, pos + PCI_PM_CTRL, 0); + pci_conf_write32(bus, dev, func, pos + PCI_PM_CTRL, 0); mdelay(10); /* Write saved configurations to device */ for ( i = 0; i < PCI_CONFIG_DWORD_SIZE; i++ ) - write_pci_config(bus, dev, func, i*4, config[i]); + pci_conf_write32(bus, dev, func, i*4, config[i]); flr = 1; } diff -r 082d3886fded -r 80ba1b427032 xen/include/asm-x86/domain.h --- a/xen/include/asm-x86/domain.h Fri Apr 11 09:14:03 2008 +0100 +++ b/xen/include/asm-x86/domain.h Fri Apr 11 13:19:55 2008 +0100 @@ -209,6 +209,7 @@ struct arch_domain /* I/O-port admin-specified access capabilities. */ struct rangeset *ioport_caps; + uint32_t pci_cf8; struct hvm_domain hvm_domain; diff -r 082d3886fded -r 80ba1b427032 xen/include/xen/pci.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/include/xen/pci.h Fri Apr 11 13:19:55 2008 +0100 @@ -0,0 +1,29 @@ +/****************************************************************************** + * pci.h + * + * PCI access functions. + */ + +#ifndef __XEN_PCI_H__ +#define __XEN_PCI_H__ + +#include <xen/config.h> +#include <xen/types.h> + +uint8_t pci_conf_read8( + unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg); +uint16_t pci_conf_read16( + unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg); +uint32_t pci_conf_read32( + unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg); +void pci_conf_write8( + unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg, + uint8_t data); +void pci_conf_write16( + unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg, + uint16_t data); +void pci_conf_write32( + unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg, + uint32_t data); + +#endif /* __XEN_PCI_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |