Update invalidation table's count of in-flight Device-TLB invalidation
request and assign the address of global polling parameter per domain in
the Status Address of each invalidation wait descriptor, when submit
Device-TLB invalidation requests.

Signed-off-by: Quan Xu <quan...@intel.com>
---
 xen/drivers/passthrough/vtd/iommu.h  |  2 ++
 xen/drivers/passthrough/vtd/qinval.c | 24 ++++++++++++++++++++----
 xen/include/xen/hvm/iommu.h          | 23 +++++++++++++++++++++++
 3 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/xen/drivers/passthrough/vtd/iommu.h 
b/xen/drivers/passthrough/vtd/iommu.h
index 52d328f..f2ee56d 100644
--- a/xen/drivers/passthrough/vtd/iommu.h
+++ b/xen/drivers/passthrough/vtd/iommu.h
@@ -453,6 +453,8 @@ struct qinval_entry {
 /* Queue invalidation head/tail shift */
 #define QINVAL_INDEX_SHIFT 4
 
+#define QINVAL_INVALID_DEVICE_ID  ((u16)~0)
+
 #define qinval_present(v) ((v).lo & 1)
 #define qinval_fault_disable(v) (((v).lo >> 1) & 1)
 
diff --git a/xen/drivers/passthrough/vtd/qinval.c 
b/xen/drivers/passthrough/vtd/qinval.c
index b81b0bd..abe6e9c 100644
--- a/xen/drivers/passthrough/vtd/qinval.c
+++ b/xen/drivers/passthrough/vtd/qinval.c
@@ -130,8 +130,9 @@ static void queue_invalidate_iotlb(struct iommu *iommu,
     spin_unlock_irqrestore(&iommu->register_lock, flags);
 }
 
+/* device_id parmeter is invalid when iflag is not set. */
 static int queue_invalidate_wait(struct iommu *iommu,
-    u8 iflag, u8 sw, u8 fn)
+    u8 iflag, u8 sw, u8 fn, u16 device_id)
 {
     s_time_t start_time;
     volatile u32 poll_slot = QINVAL_STAT_INIT;
@@ -139,6 +140,7 @@ static int queue_invalidate_wait(struct iommu *iommu,
     unsigned long flags;
     u64 entry_base;
     struct qinval_entry *qinval_entry, *qinval_entries;
+    struct domain *d;
 
     spin_lock_irqsave(&iommu->register_lock, flags);
     index = qinval_next_index(iommu);
@@ -152,9 +154,22 @@ static int queue_invalidate_wait(struct iommu *iommu,
     qinval_entry->q.inv_wait_dsc.lo.sw = sw;
     qinval_entry->q.inv_wait_dsc.lo.fn = fn;
     qinval_entry->q.inv_wait_dsc.lo.res_1 = 0;
-    qinval_entry->q.inv_wait_dsc.lo.sdata = QINVAL_STAT_DONE;
     qinval_entry->q.inv_wait_dsc.hi.res_1 = 0;
-    qinval_entry->q.inv_wait_dsc.hi.saddr = virt_to_maddr(&poll_slot) >> 2;
+
+    if ( iflag )
+    {
+        d = rcu_lock_domain_by_id(iommu->domid_map[device_id]);
+        if ( d == NULL )
+            return -ENODATA;
+
+        qinval_entry->q.inv_wait_dsc.lo.sdata = ++ qi_table_data(d);
+        qinval_entry->q.inv_wait_dsc.hi.saddr = virt_to_maddr(
+                                                &qi_table_pollslot(d)) >> 2;
+        rcu_unlock_domain(d);
+    } else {
+        qinval_entry->q.inv_wait_dsc.lo.sdata = QINVAL_STAT_DONE;
+        qinval_entry->q.inv_wait_dsc.hi.saddr = virt_to_maddr(&poll_slot) >> 2;
+    }
 
     unmap_vtd_domain_page(qinval_entries);
     qinval_update_qtail(iommu, index);
@@ -185,7 +200,8 @@ static int invalidate_sync(struct iommu *iommu)
     struct qi_ctrl *qi_ctrl = iommu_qi_ctrl(iommu);
 
     if ( qi_ctrl->qinval_maddr )
-        return queue_invalidate_wait(iommu, 0, 1, 1);
+        return queue_invalidate_wait(iommu, 0, 1, 1,
+                                     QINVAL_INVALID_DEVICE_ID);
     return 0;
 }
 
diff --git a/xen/include/xen/hvm/iommu.h b/xen/include/xen/hvm/iommu.h
index 106e08f..28e7fc3 100644
--- a/xen/include/xen/hvm/iommu.h
+++ b/xen/include/xen/hvm/iommu.h
@@ -23,6 +23,21 @@
 #include <xen/list.h>
 #include <asm/hvm/iommu.h>
 
+/*
+ * Status Address and Data: Status address and data is used by hardware to 
perform
+ * wait descriptor completion status write when the Status Write(SW) field is 
Set.
+ *
+ * Track the Device-TLB invalidation status in an invalidation table. Update
+ * invalidation table's count of in-flight Device-TLB invalidation request and
+ * assign the address of global polling parameter per domain in the Status 
Address
+ * of each invalidation wait descriptor, when submit Device-TLB invalidation
+ * requests.
+ */
+struct qi_talbe {
+    u64 qi_table_poll_slot;
+    u32 qi_table_status_data;
+};
+
 struct hvm_iommu {
     struct arch_hvm_iommu arch;
 
@@ -34,6 +49,9 @@ struct hvm_iommu {
     struct list_head dt_devices;
 #endif
 
+    /* IOMMU Queued Invalidation(QI) */
+    struct qi_talbe talbe;
+
     /* Features supported by the IOMMU */
     DECLARE_BITMAP(features, IOMMU_FEAT_count);
 };
@@ -41,4 +59,9 @@ struct hvm_iommu {
 #define iommu_set_feature(d, f)   set_bit((f), domain_hvm_iommu(d)->features)
 #define iommu_clear_feature(d, f) clear_bit((f), domain_hvm_iommu(d)->features)
 
+#define qi_table_data(d) \
+    (d->arch.hvm_domain.hvm_iommu.talbe.qi_table_status_data)
+#define qi_table_pollslot(d) \
+    (d->arch.hvm_domain.hvm_iommu.talbe.qi_table_poll_slot)
+
 #endif /* __XEN_HVM_IOMMU_H__ */
-- 
1.8.3.2


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

Reply via email to