desc = msixtbl_addr_to_desc(msixtbl_find_entry(v, addr), addr);
rcu_read_unlock(&msixtbl_rcu_lock);
- return !!desc;
+ if ( desc )
+ return 1;
+
+ if ( (addr & (PCI_MSIX_ENTRY_SIZE - 1)) ==
+ PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET )
+ {
+ const ioreq_t *r = &v->arch.hvm_vcpu.hvm_io.io_req;
+
+ ASSERT(r->type == IOREQ_TYPE_COPY);
+ if ( r->dir == IOREQ_WRITE && r->size == 4 && !r->data_is_ptr
+ && !(r->data & PCI_MSIX_VECTOR_BITMASK) )
+ v->arch.hvm_vcpu.hvm_io.msix_snoop_address = addr;
+ }
+
+ return 0;
}
static const struct hvm_mmio_ops msixtbl_mmio_ops = {
return r;
}
- if ( !irq_desc->msi_desc )
- goto out;
-
msi_desc = irq_desc->msi_desc;
if ( !msi_desc )
goto out;
out:
spin_unlock_irq(&irq_desc->lock);
xfree(new_entry);
+
+ if ( !r )
+ {
+ struct vcpu *v;
+
+ for_each_vcpu ( d, v )
+ {
+ if ( v->arch.hvm_vcpu.hvm_io.msix_snoop_address ==
+ (gtable + msi_desc->msi_attrib.entry_nr *
+ PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET) )
+ v->arch.hvm_vcpu.hvm_io.msix_unmask_address =
+ v->arch.hvm_vcpu.hvm_io.msix_snoop_address;
+ }
+ }
+
return r;
}
if ( !irq_desc )
return;
- if ( !irq_desc->msi_desc )
- goto out;
-
msi_desc = irq_desc->msi_desc;
if ( !msi_desc )
goto out;
{
unsigned long ctrl_address = v->arch.hvm_vcpu.hvm_io.msix_unmask_address;
+ v->arch.hvm_vcpu.hvm_io.msix_snoop_address = 0;
+
if ( !ctrl_address )
return;