# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1280917300 -3600
# Node ID 39448a99227b61abb463c91e7e7c93763ddb3dce
# Parent 4566d523b10a1016643f4823a6c2de2068973627
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>
---
xen/arch/x86/hvm/vmsi.c | 38 +++++++++++++++++++++++++++++---------
1 files changed, 29 insertions(+), 9 deletions(-)
diff -r 4566d523b10a -r 39448a99227b xen/arch/x86/hvm/vmsi.c
--- a/xen/arch/x86/hvm/vmsi.c Wed Aug 04 11:21:08 2010 +0100
+++ b/xen/arch/x86/hvm/vmsi.c Wed Aug 04 11:21:40 2010 +0100
@@ -159,7 +159,10 @@ struct msixtbl_entry
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;
};
@@ -205,18 +208,15 @@ static int msixtbl_read(
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(&msixtbl_rcu_lock);
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);
@@ -224,9 +224,24 @@ static int msixtbl_read(
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:
rcu_read_unlock(&msixtbl_rcu_lock);
return r;
@@ -238,7 +253,7 @@ static int msixtbl_write(struct vcpu *v,
unsigned long offset;
struct msixtbl_entry *entry;
void *virt;
- int nr_entry;
+ int nr_entry, index;
int r = X86EMUL_UNHANDLEABLE;
rcu_read_lock(&msixtbl_rcu_lock);
@@ -252,6 +267,11 @@ static int msixtbl_write(struct vcpu *v,
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;
}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|