VMSI: This patch
simulates the MSIx table read operation
 
Signed-off-by:
Liu Yuan <yuan.b.liu@xxxxxxxxx>
Signed-off-by:
Eddie Dong <eddie.dong@xxxxxxxxx>
 
diff -r
114f860872fb xen/arch/x86/hvm/vmsi.c
---
a/xen/arch/x86/hvm/vmsi.c
+++
b/xen/arch/x86/hvm/vmsi.c
@@ -158,7 +158,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,6 +208,7
@@ static int msixtbl_read(
    
unsigned long offset;
    
struct msixtbl_entry *entry;
    
void *virt;
+   
int nr_entry, index;
    
int r = X86EMUL_UNHANDLEABLE;
 
    
rcu_read_lock();
@@ -212,14
+216,22 @@ static int msixtbl_read(
    
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;
+
+   
offset = address & (PCI_MSIX_ENTRY_SIZE - 1);
+   
entry = msixtbl_find_entry(v, address);
+   
if ( offset != PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET){
+       
nr_entry = (address - entry->gtable) / PCI_MSIX_ENTRY_SIZE;
+       
index = offset / sizeof(uint32_t);
+       
if (nr_entry < MAX_MSIX_ACC_ENTRIES) {
+           
*pval = entry->gentries[nr_entry].msi_ad[index];
+           
readl(virt); /* Linux kernel needs this to flush the write */
+           
r = X86EMUL_OKAY;
+       
}
+       
goto out;
+   
}
 
    
*pval = readl(virt);
    
r = X86EMUL_OKAY;
@@ -235,7 +247,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();
@@ -249,6 +261,10
@@ 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;
    
}