aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-11-26 11:08:45 +0000
committerKeir Fraser <keir.fraser@citrix.com>2008-11-26 11:08:45 +0000
commit26943a1d9403630485085a36a5b246f56e22312f (patch)
tree92fad19e92c158d767c1669567f631be607a5407
parent2853fea7b065a2a0b649beeb901f8fb394299f2a (diff)
downloadxen-26943a1d9403630485085a36a5b246f56e22312f.tar.gz
xen-26943a1d9403630485085a36a5b246f56e22312f.tar.bz2
xen-26943a1d9403630485085a36a5b246f56e22312f.zip
vtd: cleanups
- potential issues in vtd_page_fault() handler - wrong print messages - existing ATS code in dmar.c. Signed-off-by: Allen Kay <allen.m.kay@intel.com>
-rw-r--r--xen/drivers/passthrough/vtd/dmar.c26
-rw-r--r--xen/drivers/passthrough/vtd/dmar.h1
-rw-r--r--xen/drivers/passthrough/vtd/iommu.c20
-rw-r--r--xen/drivers/passthrough/vtd/iommu.h4
-rw-r--r--xen/drivers/passthrough/vtd/qinval.c11
5 files changed, 44 insertions, 18 deletions
diff --git a/xen/drivers/passthrough/vtd/dmar.c b/xen/drivers/passthrough/vtd/dmar.c
index 93531c65a2..358b178880 100644
--- a/xen/drivers/passthrough/vtd/dmar.c
+++ b/xen/drivers/passthrough/vtd/dmar.c
@@ -172,6 +172,28 @@ struct acpi_drhd_unit * acpi_find_matched_drhd_unit(u8 bus, u8 devfn)
return found ? found : include_all;
}
+struct acpi_atsr_unit * acpi_find_matched_atsr_unit(u8 bus, u8 devfn)
+{
+ struct acpi_atsr_unit *atsr;
+ struct acpi_atsr_unit *found = NULL, *include_all = NULL;
+ int i;
+
+ list_for_each_entry ( atsr, &acpi_atsr_units, list )
+ {
+ for (i = 0; i < atsr->scope.devices_cnt; i++)
+ if ( atsr->scope.devices[i] == PCI_BDF2(bus, devfn) )
+ return atsr;
+
+ if ( test_bit(bus, atsr->scope.buses) )
+ found = atsr;
+
+ if ( atsr->all_ports )
+ include_all = atsr;
+ }
+
+ return found ? found : include_all;
+}
+
/*
* Count number of devices in device scope. Do not include PCI sub
* hierarchies.
@@ -242,7 +264,6 @@ static int __init acpi_parse_dev_scope(void *start, void *end,
switch ( acpi_scope->dev_type )
{
case ACPI_DEV_P2PBRIDGE:
- {
sec_bus = pci_conf_read8(
bus, path->dev, path->fn, PCI_SECONDARY_BUS);
sub_bus = pci_conf_read8(
@@ -253,7 +274,6 @@ static int __init acpi_parse_dev_scope(void *start, void *end,
dmar_scope_add_buses(scope, sec_bus, sub_bus);
break;
- }
case ACPI_DEV_MSI_HPET:
dprintk(XENLOG_INFO VTDPREFIX, "found MSI HPET: bdf = %x:%x.%x\n",
@@ -268,7 +288,6 @@ static int __init acpi_parse_dev_scope(void *start, void *end,
break;
case ACPI_DEV_IOAPIC:
- {
dprintk(XENLOG_INFO VTDPREFIX, "found IOAPIC: bdf = %x:%x.%x\n",
bus, path->dev, path->fn);
@@ -288,7 +307,6 @@ static int __init acpi_parse_dev_scope(void *start, void *end,
scope->devices[didx++] = PCI_BDF(bus, path->dev, path->fn);
break;
}
- }
start += acpi_scope->length;
}
diff --git a/xen/drivers/passthrough/vtd/dmar.h b/xen/drivers/passthrough/vtd/dmar.h
index bcbb88bf34..c2132e2a0f 100644
--- a/xen/drivers/passthrough/vtd/dmar.h
+++ b/xen/drivers/passthrough/vtd/dmar.h
@@ -80,6 +80,7 @@ struct acpi_atsr_unit {
idx < rmrr->scope.devices_cnt; idx++)
struct acpi_drhd_unit * acpi_find_matched_drhd_unit(u8 bus, u8 devfn);
+struct acpi_atsr_unit * acpi_find_matched_atsr_unit(u8 bus, u8 devfn);
void dmar_scope_add_buses(struct dmar_scope *scope, u16 sec, u16 sub);
void dmar_scope_remove_buses(struct dmar_scope *scope, u16 sec, u16 sub);
diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c
index 2a3310fadf..80bab920b5 100644
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -714,22 +714,22 @@ static void iommu_fault_status(u32 fault_status)
if ( fault_status & DMA_FSTS_PFO )
dprintk(XENLOG_ERR VTDPREFIX,
"iommu_fault_status: Fault Overflow\n");
- else if ( fault_status & DMA_FSTS_PPF )
+ if ( fault_status & DMA_FSTS_PPF )
dprintk(XENLOG_ERR VTDPREFIX,
"iommu_fault_status: Primary Pending Fault\n");
- else if ( fault_status & DMA_FSTS_AFO )
+ if ( fault_status & DMA_FSTS_AFO )
dprintk(XENLOG_ERR VTDPREFIX,
"iommu_fault_status: Advanced Fault Overflow\n");
- else if ( fault_status & DMA_FSTS_APF )
+ if ( fault_status & DMA_FSTS_APF )
dprintk(XENLOG_ERR VTDPREFIX,
"iommu_fault_status: Advanced Pending Fault\n");
- else if ( fault_status & DMA_FSTS_IQE )
+ if ( fault_status & DMA_FSTS_IQE )
dprintk(XENLOG_ERR VTDPREFIX,
"iommu_fault_status: Invalidation Queue Error\n");
- else if ( fault_status & DMA_FSTS_ICE )
+ if ( fault_status & DMA_FSTS_ICE )
dprintk(XENLOG_ERR VTDPREFIX,
"iommu_fault_status: Invalidation Completion Error\n");
- else if ( fault_status & DMA_FSTS_ITE )
+ if ( fault_status & DMA_FSTS_ITE )
dprintk(XENLOG_ERR VTDPREFIX,
"iommu_fault_status: Invalidation Time-out Error\n");
}
@@ -754,10 +754,11 @@ static void iommu_page_fault(int vector, void *dev_id,
/* FIXME: ignore advanced fault log */
if ( !(fault_status & DMA_FSTS_PPF) )
- return;
+ goto clear_overflow;
+
fault_index = dma_fsts_fault_record_index(fault_status);
reg = cap_fault_reg_offset(iommu->cap);
- for ( ; ; )
+ while (1)
{
u8 fault_reason;
u16 source_id;
@@ -797,8 +798,9 @@ static void iommu_page_fault(int vector, void *dev_id,
if ( fault_index > cap_num_fault_regs(iommu->cap) )
fault_index = 0;
}
-
+clear_overflow:
/* clear primary fault overflow */
+ fault_status = readl(iommu->reg + DMAR_FSTS_REG);
if ( fault_status & DMA_FSTS_PFO )
{
spin_lock_irqsave(&iommu->register_lock, flags);
diff --git a/xen/drivers/passthrough/vtd/iommu.h b/xen/drivers/passthrough/vtd/iommu.h
index dd17a6b642..c03d20fe17 100644
--- a/xen/drivers/passthrough/vtd/iommu.h
+++ b/xen/drivers/passthrough/vtd/iommu.h
@@ -310,6 +310,10 @@ struct iremap_entry {
struct qinval_entry {
union {
struct {
+ u64 lo;
+ u64 hi;
+ }val;
+ struct {
struct {
u64 type : 4,
granu : 2,
diff --git a/xen/drivers/passthrough/vtd/qinval.c b/xen/drivers/passthrough/vtd/qinval.c
index 048089350d..47707de44c 100644
--- a/xen/drivers/passthrough/vtd/qinval.c
+++ b/xen/drivers/passthrough/vtd/qinval.c
@@ -34,13 +34,13 @@ static void print_qi_regs(struct iommu *iommu)
u64 val;
val = dmar_readq(iommu->reg, DMAR_IQA_REG);
- printk("DMAR_IAQ_REG = %"PRIx64"\n", val);
+ printk("DMAR_IQA_REG = %"PRIx64"\n", val);
val = dmar_readq(iommu->reg, DMAR_IQH_REG);
- printk("DMAR_IAH_REG = %"PRIx64"\n", val);
+ printk("DMAR_IQH_REG = %"PRIx64"\n", val);
val = dmar_readq(iommu->reg, DMAR_IQT_REG);
- printk("DMAR_IAT_REG = %"PRIx64"\n", val);
+ printk("DMAR_IQT_REG = %"PRIx64"\n", val);
}
static int qinval_next_index(struct iommu *iommu)
@@ -252,14 +252,15 @@ static int gen_dev_iotlb_inv_dsc(struct iommu *iommu, int index,
qinval_entry->q.dev_iotlb_inv_dsc.lo.res_3 = 0;
qinval_entry->q.dev_iotlb_inv_dsc.hi.size = size;
- qinval_entry->q.dev_iotlb_inv_dsc.hi.addr = addr;
+ qinval_entry->q.dev_iotlb_inv_dsc.hi.res_1 = 0;
+ qinval_entry->q.dev_iotlb_inv_dsc.hi.addr = addr >> PAGE_SHIFT_4K;
unmap_vtd_domain_page(qinval_entries);
spin_unlock_irqrestore(&qi_ctrl->qinval_lock, flags);
return 0;
}
-int queue_invalidate_device_iotlb(struct iommu *iommu,
+int qinval_device_iotlb(struct iommu *iommu,
u32 max_invs_pend, u16 sid, u16 size, u64 addr)
{
int ret = -1;