Currently, MSI messages can only be injected to in-kernel irqchips by defining a corresponding IRQ route for each message. This is not only unhandy if the MSI messages are generated "on the fly" by user space, IRQ routes are a limited resource that user space as to manage carefully. By providing a direct injection with, we can both avoid using up limited resources and simplify the necessary steps for user land. The API already provides a channel (flags) to revoke an injected but not yet delivered message which will become important for in-kernel MSI-X vector masking support. Signed-off-by: Jan Kiszka <jan.kiszka@xxxxxxxxxxx> --- Documentation/virtual/kvm/api.txt | 23 +++++++++++++++++++++++ include/linux/kvm.h | 15 +++++++++++++++ virt/kvm/kvm_main.c | 18 ++++++++++++++++++ 3 files changed, 56 insertions(+), 0 deletions(-) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 7945b0b..f4c3de3 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -1383,6 +1383,29 @@ The following flags are defined: If datamatch flag is set, the event will be signaled only if the written value to the registered address is equal to datamatch in struct kvm_ioeventfd. +4.59 KVM_SET_MSI + +Capability: KVM_CAP_SET_MSI +Architectures: x86 ia64 +Type: vm ioctl +Parameters: struct kvm_msi (in) +Returns: 0 on success, -1 on error + +Directly inject a MSI message. Only valid with in-kernel irqchip that handles +MSI messages. + +struct kvm_msi { + __u32 address_lo; + __u32 address_hi; + __u32 data; + __u32 flags; + __u8 pad[16]; +}; + +The following flags are defined: + +#define KVM_MSI_FLAG_RAISE (1 << 0) + 4.62 KVM_CREATE_SPAPR_TCE Capability: KVM_CAP_SPAPR_TCE diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 6884054..83875ed 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -557,6 +557,9 @@ struct kvm_ppc_pvinfo { #define KVM_CAP_PPC_HIOR 67 #define KVM_CAP_PPC_PAPR 68 #define KVM_CAP_S390_GMAP 71 +#ifdef __KVM_HAVE_MSI +#define KVM_CAP_SET_MSI 72 +#endif #ifdef KVM_CAP_IRQ_ROUTING @@ -636,6 +639,16 @@ struct kvm_clock_data { __u32 pad[9]; }; +#define KVM_MSI_FLAG_RAISE (1 << 0) + +struct kvm_msi { + __u32 address_lo; + __u32 address_hi; + __u32 data; + __u32 flags; + __u8 pad[16]; +}; + /* * ioctls for VM fds */ @@ -696,6 +709,8 @@ struct kvm_clock_data { /* Available with KVM_CAP_TSC_CONTROL */ #define KVM_SET_TSC_KHZ _IO(KVMIO, 0xa2) #define KVM_GET_TSC_KHZ _IO(KVMIO, 0xa3) +/* Available with KVM_CAP_SET_MSI */ +#define KVM_SET_MSI _IOW(KVMIO, 0xa4, struct kvm_msi) /* * ioctls for vcpu fds diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index d9cfb78..0e3a947 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2058,6 +2058,24 @@ static long kvm_vm_ioctl(struct file *filp, mutex_unlock(&kvm->lock); break; #endif +#ifdef __KVM_HAVE_MSI + case KVM_SET_MSI: { + struct kvm_kernel_irq_routing_entry route; + struct kvm_msi msi; + + r = -EFAULT; + if (copy_from_user(&msi, argp, sizeof msi)) + goto out; + route.msi.address_lo = msi.address_lo; + route.msi.address_hi = msi.address_hi; + route.msi.data = msi.data; + r = 0; + if (msi.flags & KVM_MSI_FLAG_RAISE) + r = kvm_set_msi(&route, kvm, + KVM_USERSPACE_IRQ_SOURCE_ID, 1); + break; + } +#endif default: r = kvm_arch_vm_ioctl(filp, ioctl, arg); if (r == -ENOTTY) -- 1.7.3.4 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html