All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jan Kiszka <jan.kiszka@siemens.com>
To: Avi Kivity <avi@redhat.com>, Marcelo Tosatti <mtosatti@redhat.com>
Cc: kvm <kvm@vger.kernel.org>, "Michael S. Tsirkin" <mst@redhat.com>,
	Eric Northup <digitaleric@google.com>
Subject: [PATCH] KVM: Introduce generic interrupt injection for in-kernel irqchips
Date: Tue, 10 Apr 2012 20:30:13 +0200	[thread overview]
Message-ID: <4F847C35.9070105@siemens.com> (raw)
In-Reply-To: <4F7B24EA.2070300@redhat.com>

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 has to manage
carefully.

By providing a direct injection path, we can both avoid using up limited
resources and simplify the necessary steps for user land. This path is
provide in a way that allows for use with other interrupt sources as
well. Besides MSIs also external interrupt lines can be manipulated
through this interface, obsoleting KVM_IRQ_LINE_STATUS.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

This picks up Avi's first suggestion as I still think it is the better
option to provide a direct MSI injection channel.

 Documentation/virtual/kvm/api.txt |   46 +++++++++++++++++++++++++++++++++++++
 include/linux/kvm.h               |   26 +++++++++++++++++++++
 include/linux/kvm_host.h          |    2 +
 virt/kvm/irq_comm.c               |   29 +++++++++++++++++++++++
 virt/kvm/kvm_main.c               |   20 ++++++++++++++++
 5 files changed, 123 insertions(+), 0 deletions(-)

diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 81ff39f..c70be58 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1482,6 +1482,52 @@ See KVM_ASSIGN_DEV_IRQ for the data structure.  The target device is specified
 by assigned_dev_id.  In the flags field, only KVM_DEV_ASSIGN_MASK_INTX is
 evaluated.
 
+4.61 KVM_GENERAL_IRQ
+
+Capability: KVM_CAP_GENERAL_IRQ
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_general_irq (in/out)
+Returns: 0 on success, <0 on error
+
+Inject an interrupt event to the guest. Only valid if in-kernel irqchip is
+enabled.
+
+struct kvm_general_irq {
+	__u32 type;
+	__u32 op;
+	__s32 status;
+	__u32 pad;
+	union {
+		__u32 line;
+		struct {
+			__u32 address_lo;
+			__u32 address_hi;
+			__u32 data;
+		} msi;
+		__u8 pad[32];
+	} u;
+};
+
+Support IRQ types are:
+
+#define KVM_IRQTYPE_EXTERNAL_LINE	0
+#define KVM_IRQTYPE_MSI			1
+
+Available operations are:
+
+#define KVM_IRQOP_LOWER			0
+#define KVM_IRQOP_RAISE			1
+#define KVM_IRQOP_TRIGGER		2
+
+The level of an external interrupt line can either be raised or lowered, a
+MSI can only be triggered.
+
+If 0 is returned from the IOCTL, the status field was updated as well to
+reflect the injection result. It will be >0 on interrupt delivery, 0 if the
+interrupt was coalesced with an already pending one, and <0 if the guest
+blocked the delivery or some delivery error occurred.
+
 4.62 KVM_CREATE_SPAPR_TCE
 
 Capability: KVM_CAP_SPAPR_TCE
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 7a9dd4b..cb3afaf 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -590,6 +590,7 @@ struct kvm_ppc_pvinfo {
 #define KVM_CAP_SYNC_REGS 74
 #define KVM_CAP_PCI_2_3 75
 #define KVM_CAP_KVMCLOCK_CTRL 76
+#define KVM_CAP_GENERAL_IRQ 77
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -715,6 +716,29 @@ struct kvm_one_reg {
 	__u64 addr;
 };
 
+#define KVM_IRQTYPE_EXTERNAL_LINE	0
+#define KVM_IRQTYPE_MSI			1
+
+#define KVM_IRQOP_LOWER			0
+#define KVM_IRQOP_RAISE			1
+#define KVM_IRQOP_TRIGGER		2
+
+struct kvm_general_irq {
+	__u32 type;
+	__u32 op;
+	__s32 status;
+	__u32 pad;
+	union {
+		__u32 line;
+		struct {
+			__u32 address_lo;
+			__u32 address_hi;
+			__u32 data;
+		} msi;
+		__u8 pad[32];
+	} u;
+};
+
 /*
  * ioctls for VM fds
  */
@@ -789,6 +813,8 @@ struct kvm_s390_ucas_mapping {
 /* Available with KVM_CAP_PCI_2_3 */
 #define KVM_ASSIGN_SET_INTX_MASK  _IOW(KVMIO,  0xa4, \
 				       struct kvm_assigned_pci_dev)
+/* Available with KVM_CAP_GENERAL_IRQ */
+#define KVM_GENERAL_IRQ           _IOWR(KVMIO,  0xa5, struct kvm_general_irq)
 
 /*
  * ioctls for vcpu fds
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 49c2f2f..31d3b44 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -773,6 +773,8 @@ int kvm_set_irq_routing(struct kvm *kvm,
 			unsigned flags);
 void kvm_free_irq_routing(struct kvm *kvm);
 
+int kvm_general_irq(struct kvm *kvm, struct kvm_general_irq *irq);
+
 #else
 
 static inline void kvm_free_irq_routing(struct kvm *kvm) {}
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index 9f614b4..e487d3f 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -138,6 +138,35 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
 	return kvm_irq_delivery_to_apic(kvm, NULL, &irq);
 }
 
+int kvm_general_irq(struct kvm *kvm, struct kvm_general_irq *irq)
+{
+	struct kvm_kernel_irq_routing_entry route;
+
+	if (!irqchip_in_kernel(kvm))
+		return -EINVAL;
+
+	switch (irq->type) {
+	case KVM_IRQTYPE_EXTERNAL_LINE:
+		if (irq->op > KVM_IRQOP_RAISE)
+			return -EINVAL;
+		irq->status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
+					  irq->u.line, irq->op);
+		break;
+	case KVM_IRQTYPE_MSI:
+		if (irq->op != KVM_IRQOP_TRIGGER)
+			return -EINVAL;
+		route.msi.address_lo = irq->u.msi.address_lo;
+		route.msi.address_hi = irq->u.msi.address_hi;
+		route.msi.data = irq->u.msi.data;
+		irq->status = kvm_set_msi(&route, kvm,
+					  KVM_USERSPACE_IRQ_SOURCE_ID, 1);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
 /*
  * Return value:
  *  < 0   Interrupt was ignored (masked or not delivered for other reasons)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 6bd34a6..95dffec 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2059,6 +2059,23 @@ static long kvm_vm_ioctl(struct file *filp,
 		mutex_unlock(&kvm->lock);
 		break;
 #endif
+#ifdef CONFIG_HAVE_KVM_IRQCHIP
+	case KVM_GENERAL_IRQ: {
+		struct kvm_general_irq irq;
+
+		r = -EFAULT;
+		if (copy_from_user(&irq, argp, sizeof(irq)))
+			goto out;
+		r = kvm_general_irq(kvm, &irq);
+		if (r < 0)
+			goto out;
+		if (copy_to_user(argp +
+				 offsetof(struct kvm_general_irq, status),
+				 &irq.status, sizeof(irq.status)))
+			r = -EFAULT;
+		break;
+	}
+#endif
 	default:
 		r = kvm_arch_vm_ioctl(filp, ioctl, arg);
 		if (r == -ENOTTY)
@@ -2187,6 +2204,9 @@ static long kvm_dev_ioctl_check_extension_generic(long arg)
 	case KVM_CAP_SET_BOOT_CPU_ID:
 #endif
 	case KVM_CAP_INTERNAL_ERROR_DATA:
+#ifdef CONFIG_HAVE_KVM_IRQCHIP
+	case KVM_CAP_GENERAL_IRQ:
+#endif
 		return 1;
 #ifdef CONFIG_HAVE_KVM_IRQCHIP
 	case KVM_CAP_IRQ_ROUTING:
-- 
1.7.3.4

  parent reply	other threads:[~2012-04-10 18:30 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-28 17:47 [PATCH v2] KVM: Introduce direct MSI message injection for in-kernel irqchips Jan Kiszka
2012-03-28 17:52 ` Jan Kiszka
2012-03-28 19:58 ` Eric Northup
2012-03-28 20:21   ` Jan Kiszka
2012-03-29 15:39 ` Michael S. Tsirkin
2012-03-29 15:43   ` Jan Kiszka
2012-03-29 16:15 ` [PATCH v3] " Jan Kiszka
2012-03-29 16:46   ` Michael S. Tsirkin
2012-03-29 16:50     ` Jan Kiszka
2012-03-29 18:25   ` Jan Kiszka
2012-03-29 19:14   ` [PATCH v4] " Jan Kiszka
2012-03-29 19:41     ` Michael S. Tsirkin
2012-03-30  7:45       ` Jan Kiszka
2012-03-30 12:45         ` Michael S. Tsirkin
2012-04-03 16:27     ` Avi Kivity
2012-04-03 16:47       ` Jan Kiszka
2012-04-03 16:54         ` Avi Kivity
2012-04-03 17:24           ` Jan Kiszka
2012-04-04  8:47             ` Avi Kivity
2012-04-04  8:38         ` Michael S. Tsirkin
2012-04-04  8:44           ` Avi Kivity
2012-04-04  8:53             ` Michael S. Tsirkin
2012-04-04  9:22               ` Jan Kiszka
2012-04-04  9:36                 ` Avi Kivity
2012-04-04  9:38                   ` Jan Kiszka
2012-04-04  9:55                     ` Avi Kivity
2012-04-04 10:48                       ` Jan Kiszka
2012-04-04 11:50                         ` Avi Kivity
2012-04-04 12:01                           ` Jan Kiszka
2012-04-10 18:30       ` Jan Kiszka [this message]
2012-04-23 14:44         ` [PATCH] KVM: Introduce generic interrupt " Jan Kiszka
2012-04-23 15:17           ` Avi Kivity
2012-04-23 15:32         ` Avi Kivity
2012-04-23 15:55           ` Jan Kiszka
2012-04-24 11:54             ` Avi Kivity
2012-04-24 11:57     ` [PATCH v4] KVM: Introduce direct MSI message " Avi Kivity
2012-04-24 12:07       ` Jan Kiszka
2012-04-24 12:59         ` Avi Kivity
2012-04-24 13:24           ` Jan Kiszka
2012-04-11 22:10   ` [PATCH v3] " Marcelo Tosatti
2012-04-12  9:28     ` Jan Kiszka
2012-04-12 22:38       ` Marcelo Tosatti
2012-04-13 13:45         ` Jan Kiszka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4F847C35.9070105@siemens.com \
    --to=jan.kiszka@siemens.com \
    --cc=avi@redhat.com \
    --cc=digitaleric@google.com \
    --cc=kvm@vger.kernel.org \
    --cc=mst@redhat.com \
    --cc=mtosatti@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.