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
#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>
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.
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);
}
}
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();
--- /dev/null
+/******************************************************************************
+ * 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);
+}
#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)
{
}
/* 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 *)
/* 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 */
{
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) ||
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;
}
exec_in:
if ( !guest_io_okay(port, op_bytes, v, regs) )
goto fail;
- switch ( op_bytes )
+ if ( admin_io_okay(port, op_bytes, v, regs) )
{
- 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);
- }
- 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);
+ io_emul(regs);
+ }
+ else
+ {
+ if ( op_bytes == 4 )
+ regs->eax = 0;
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;
exec_out:
if ( !guest_io_okay(port, op_bytes, v, regs) )
goto fail;
- switch ( op_bytes )
+ if ( admin_io_okay(port, op_bytes, v, regs) )
{
- 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;
+ 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;
#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(
{
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));
}
}
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);
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;
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(
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);
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);
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);
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;
#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;
* 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;
{
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) )
+++ /dev/null
-#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
#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;
/ 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++;
}
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 )
{
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
while ( --depth > 0 )
{
- bus = read_pci_config_byte(
+ bus = pci_conf_read8(
bus, path->dev, path->fn, PCI_SECONDARY_BUS);
path++;
}
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 )
{
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
#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"
#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"
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;
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;
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);
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);
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);
{
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) )
#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"
#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"
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);
}
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) )
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;
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 );
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;
}
/* I/O-port admin-specified access capabilities. */
struct rangeset *ioport_caps;
+ uint32_t pci_cf8;
struct hvm_domain hvm_domain;
--- /dev/null
+/******************************************************************************
+ * 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__ */