mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
x86/msi: passthrough all MSI-X vector ctrl writes to device model
QEMU needs to know whether clearing maskbit of a vector is really clearing, or was already cleared before. Currently Xen sends only clearing that bit to the device model, but not setting it, so QEMU cannot detect it. Because of that, QEMU is working this around by checking via /dev/mem, but that isn't the proper approach. Give all necessary information to QEMU by passing all ctrl writes, including masking a vector. Advertise the new behavior via XENVER_get_features, so QEMU can know it doesn't need to access /dev/mem anymore. While this commit doesn't move the whole maskbit handling to QEMU (as discussed on xen-devel as one of the possibilities), it is a necessary first step anyway. Including telling QEMU it will get all the required information to do so. The actual implementation would need to include: - a hypercall for QEMU to control just maskbit (without (re)binding the interrupt again - a method for QEMU to tell Xen it will actually do the work Those are not part of this series. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> Acked-by: Roger Pau Monné <roger.pau@citrix.com>
This commit is contained in:
1 parent
be5b08dd6e
commit
64b21662b1
3 files changed
+23
-5
No files matched your search
+14
-5
@@ -283,8 +283,8 @@ static int msixtbl_write(struct vcpu *v, unsigned long address,
|
||||
unsigned long flags;
|
||||
struct irq_desc *desc;
|
||||
|
||||
if ( (len != 4 && len != 8) || (address & (len - 1)) )
|
||||
return r;
|
||||
if ( !IS_ALIGNED(address, len) )
|
||||
return X86EMUL_OKAY;
|
||||
|
||||
rcu_read_lock(&msixtbl_rcu_lock);
|
||||
|
||||
@@ -345,8 +345,7 @@ static int msixtbl_write(struct vcpu *v, unsigned long address,
|
||||
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
if ( len == 4 )
|
||||
r = X86EMUL_OKAY;
|
||||
r = X86EMUL_OKAY;
|
||||
|
||||
out:
|
||||
rcu_read_unlock(&msixtbl_rcu_lock);
|
||||
@@ -357,7 +356,17 @@ static int cf_check _msixtbl_write(
|
||||
const struct hvm_io_handler *handler, uint64_t address, uint32_t len,
|
||||
uint64_t val)
|
||||
{
|
||||
return msixtbl_write(current, address, len, val);
|
||||
/* Ignore invalid length or unaligned writes. */
|
||||
if ( (len != 4 && len != 8) || !IS_ALIGNED(address, len) )
|
||||
return X86EMUL_OKAY;
|
||||
|
||||
/*
|
||||
* This function returns X86EMUL_UNHANDLEABLE even if write is properly
|
||||
* handled, to propagate it to the device model (so it can keep its
|
||||
* internal state in sync).
|
||||
*/
|
||||
msixtbl_write(current, address, len, val);
|
||||
return X86EMUL_UNHANDLEABLE;
|
||||
}
|
||||
|
||||
static bool cf_check msixtbl_range(
|
||||
|
||||
@@ -637,6 +637,7 @@ long do_xen_version(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
|
||||
fi.submap |= (1U << XENFEAT_hvm_safe_pvclock) |
|
||||
(1U << XENFEAT_hvm_callback_vector) |
|
||||
(has_pirq(d) ? (1U << XENFEAT_hvm_pirqs) : 0);
|
||||
fi.submap |= (1U << XENFEAT_dm_msix_all_writes);
|
||||
#endif
|
||||
if ( !paging_mode_translate(d) || is_domain_direct_mapped(d) )
|
||||
fi.submap |= (1U << XENFEAT_direct_mapped);
|
||||
|
||||
@@ -120,6 +120,14 @@
|
||||
#define XENFEAT_runstate_phys_area 18
|
||||
#define XENFEAT_vcpu_time_phys_area 19
|
||||
|
||||
/*
|
||||
* If set, Xen will passthrough all MSI-X vector ctrl writes to device model,
|
||||
* not only those unmasking an entry. This allows device model to properly keep
|
||||
* track of the MSI-X table without having to read it from the device behind
|
||||
* Xen's backs. This information is relevant only for device models.
|
||||
*/
|
||||
#define XENFEAT_dm_msix_all_writes 20
|
||||
|
||||
#define XENFEAT_NR_SUBMAPS 1
|
||||
|
||||
#endif /* __XEN_PUBLIC_FEATURES_H__ */
|
||||
|
||||