Rebased the patch and
simplified some logic.
Regards,
Yuan
----
VMSI: This patch
simulate the MSIx table read operation
Signed-off-by:
Liu Yuan <yuan.b.liu@xxxxxxxxx>
Signed-off-by:
Eddie Dong <eddie.dong@xxxxxxxxx>
diff -r
ef5f25de00da xen/arch/x86/hvm/vmsi.c
---
a/xen/arch/x86/hvm/vmsi.c Mon Aug 02 17:19:06 2010 +0100
+++
b/xen/arch/x86/hvm/vmsi.c Wed Aug 04 16:04:49 2010 +0800
@@ -158,7 +158,10
@@
unsigned long gtable; /* gpa of msix table
*/
unsigned long table_len;
unsigned long table_flags[MAX_MSIX_TABLE_ENTRIES / BITS_PER_LONG + 1];
-
+#define
MAX_MSIX_ACC_ENTRIES 3
+
struct {
+
uint32_t msi_ad[3]; /* Shadow of address low, high and data
*/
+
} gentries[MAX_MSIX_ACC_ENTRIES];
struct rcu_head rcu;
};
@@ -202,9 +205,10
@@
struct vcpu *v, unsigned long address,
unsigned long len, unsigned long *pval)
{
-
unsigned long offset;
+
unsigned long offset, val;
struct msixtbl_entry *entry;
void *virt;
+
int nr_entry, index;
int r = X86EMUL_UNHANDLEABLE;
rcu_read_lock();
@@ -212,16
+216,27 @@
if ( len != 4 )
goto out;
-
offset = address & (PCI_MSIX_ENTRY_SIZE - 1);
-
if ( offset != PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET)
-
goto out;
-
entry = msixtbl_find_entry(v, address);
virt = msixtbl_addr_to_virt(entry, address);
if ( !virt )
goto out;
-
*pval = readl(virt);
+
nr_entry = (address - entry->gtable) / PCI_MSIX_ENTRY_SIZE;
+
offset = address & (PCI_MSIX_ENTRY_SIZE - 1);
+
if (nr_entry >= MAX_MSIX_ACC_ENTRIES &&
+
offset != PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET)
+
goto out;
+
+
val = readl(virt);
+
if ( offset != PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET){
+
index = offset / sizeof(uint32_t);
+
*pval = entry->gentries[nr_entry].msi_ad[index];
+
}
+
else
+
{
+
*pval = val;
+
}
+
r = X86EMUL_OKAY;
out:
@@ -235,7 +250,7
@@
unsigned long offset;
struct msixtbl_entry *entry;
void *virt;
-
int nr_entry;
+
int nr_entry, index;
int r = X86EMUL_UNHANDLEABLE;
rcu_read_lock();
@@ -249,6 +264,10
@@
offset = address & (PCI_MSIX_ENTRY_SIZE - 1);
if ( offset != PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET)
{
+
if (nr_entry < MAX_MSIX_ACC_ENTRIES) {
+
index = offset / sizeof(uint32_t);
+
entry->gentries[nr_entry].msi_ad[index] = val;
+
}
set_bit(nr_entry, &entry->table_flags);
goto out;
}