# 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
|