aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@siemens.com>2012-03-29 15:14:12 -0400
committerAvi Kivity <avi@redhat.com>2012-04-24 08:59:47 -0400
commit07975ad3b30579ca27d880491ad992326b930c63 (patch)
treefea166a02c387949a09a948a51781074bdc9ed68
parent1f15d10984c854e077da5aa1a23f901496b49773 (diff)
KVM: Introduce direct MSI message injection for in-kernel irqchips
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. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--Documentation/virtual/kvm/api.txt21
-rw-r--r--arch/x86/kvm/Kconfig1
-rw-r--r--include/linux/kvm.h11
-rw-r--r--include/linux/kvm_host.h2
-rw-r--r--virt/kvm/Kconfig3
-rw-r--r--virt/kvm/irq_comm.c14
-rw-r--r--virt/kvm/kvm_main.c14
7 files changed, 66 insertions, 0 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 81ff39f6248d..a1552210b16d 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1689,6 +1689,27 @@ where the guest will clear the flag: when the soft lockup watchdog timer resets
1689itself or when a soft lockup is detected. This ioctl can be called any time 1689itself or when a soft lockup is detected. This ioctl can be called any time
1690after pausing the vcpu, but before it is resumed. 1690after pausing the vcpu, but before it is resumed.
1691 1691
16924.71 KVM_SIGNAL_MSI
1693
1694Capability: KVM_CAP_SIGNAL_MSI
1695Architectures: x86
1696Type: vm ioctl
1697Parameters: struct kvm_msi (in)
1698Returns: >0 on delivery, 0 if guest blocked the MSI, and -1 on error
1699
1700Directly inject a MSI message. Only valid with in-kernel irqchip that handles
1701MSI messages.
1702
1703struct kvm_msi {
1704 __u32 address_lo;
1705 __u32 address_hi;
1706 __u32 data;
1707 __u32 flags;
1708 __u8 pad[16];
1709};
1710
1711No flags are defined so far. The corresponding field must be 0.
1712
16925. The kvm_run structure 17135. The kvm_run structure
1693 1714
1694Application code obtains a pointer to the kvm_run structure by 1715Application code obtains a pointer to the kvm_run structure by
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index 1a7fe868f375..a28f338843ea 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -36,6 +36,7 @@ config KVM
36 select TASKSTATS 36 select TASKSTATS
37 select TASK_DELAY_ACCT 37 select TASK_DELAY_ACCT
38 select PERF_EVENTS 38 select PERF_EVENTS
39 select HAVE_KVM_MSI
39 ---help--- 40 ---help---
40 Support hosting fully virtualized guest machines using hardware 41 Support hosting fully virtualized guest machines using hardware
41 virtualization extensions. You will need a fairly recent 42 virtualization extensions. You will need a fairly recent
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 7a9dd4b3dede..225b452e1d1d 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -590,6 +590,7 @@ struct kvm_ppc_pvinfo {
590#define KVM_CAP_SYNC_REGS 74 590#define KVM_CAP_SYNC_REGS 74
591#define KVM_CAP_PCI_2_3 75 591#define KVM_CAP_PCI_2_3 75
592#define KVM_CAP_KVMCLOCK_CTRL 76 592#define KVM_CAP_KVMCLOCK_CTRL 76
593#define KVM_CAP_SIGNAL_MSI 77
593 594
594#ifdef KVM_CAP_IRQ_ROUTING 595#ifdef KVM_CAP_IRQ_ROUTING
595 596
@@ -715,6 +716,14 @@ struct kvm_one_reg {
715 __u64 addr; 716 __u64 addr;
716}; 717};
717 718
719struct kvm_msi {
720 __u32 address_lo;
721 __u32 address_hi;
722 __u32 data;
723 __u32 flags;
724 __u8 pad[16];
725};
726
718/* 727/*
719 * ioctls for VM fds 728 * ioctls for VM fds
720 */ 729 */
@@ -789,6 +798,8 @@ struct kvm_s390_ucas_mapping {
789/* Available with KVM_CAP_PCI_2_3 */ 798/* Available with KVM_CAP_PCI_2_3 */
790#define KVM_ASSIGN_SET_INTX_MASK _IOW(KVMIO, 0xa4, \ 799#define KVM_ASSIGN_SET_INTX_MASK _IOW(KVMIO, 0xa4, \
791 struct kvm_assigned_pci_dev) 800 struct kvm_assigned_pci_dev)
801/* Available with KVM_CAP_SIGNAL_MSI */
802#define KVM_SIGNAL_MSI _IOW(KVMIO, 0xa5, struct kvm_msi)
792 803
793/* 804/*
794 * ioctls for vcpu fds 805 * ioctls for vcpu fds
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 186ffab0b9f0..6f343307d72b 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -802,6 +802,8 @@ int kvm_set_irq_routing(struct kvm *kvm,
802 unsigned flags); 802 unsigned flags);
803void kvm_free_irq_routing(struct kvm *kvm); 803void kvm_free_irq_routing(struct kvm *kvm);
804 804
805int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi);
806
805#else 807#else
806 808
807static inline void kvm_free_irq_routing(struct kvm *kvm) {} 809static inline void kvm_free_irq_routing(struct kvm *kvm) {}
diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
index f63ccb0a5982..28694f4a9139 100644
--- a/virt/kvm/Kconfig
+++ b/virt/kvm/Kconfig
@@ -18,3 +18,6 @@ config KVM_MMIO
18 18
19config KVM_ASYNC_PF 19config KVM_ASYNC_PF
20 bool 20 bool
21
22config HAVE_KVM_MSI
23 bool
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index 9f614b4e365f..a6a0365475ed 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -138,6 +138,20 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
138 return kvm_irq_delivery_to_apic(kvm, NULL, &irq); 138 return kvm_irq_delivery_to_apic(kvm, NULL, &irq);
139} 139}
140 140
141int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi)
142{
143 struct kvm_kernel_irq_routing_entry route;
144
145 if (!irqchip_in_kernel(kvm) || msi->flags != 0)
146 return -EINVAL;
147
148 route.msi.address_lo = msi->address_lo;
149 route.msi.address_hi = msi->address_hi;
150 route.msi.data = msi->data;
151
152 return kvm_set_msi(&route, kvm, KVM_USERSPACE_IRQ_SOURCE_ID, 1);
153}
154
141/* 155/*
142 * Return value: 156 * Return value:
143 * < 0 Interrupt was ignored (masked or not delivered for other reasons) 157 * < 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 9eb7936e491d..1847c762d8d9 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2060,6 +2060,17 @@ static long kvm_vm_ioctl(struct file *filp,
2060 mutex_unlock(&kvm->lock); 2060 mutex_unlock(&kvm->lock);
2061 break; 2061 break;
2062#endif 2062#endif
2063#ifdef CONFIG_HAVE_KVM_MSI
2064 case KVM_SIGNAL_MSI: {
2065 struct kvm_msi msi;
2066
2067 r = -EFAULT;
2068 if (copy_from_user(&msi, argp, sizeof msi))
2069 goto out;
2070 r = kvm_send_userspace_msi(kvm, &msi);
2071 break;
2072 }
2073#endif
2063 default: 2074 default:
2064 r = kvm_arch_vm_ioctl(filp, ioctl, arg); 2075 r = kvm_arch_vm_ioctl(filp, ioctl, arg);
2065 if (r == -ENOTTY) 2076 if (r == -ENOTTY)
@@ -2188,6 +2199,9 @@ static long kvm_dev_ioctl_check_extension_generic(long arg)
2188 case KVM_CAP_SET_BOOT_CPU_ID: 2199 case KVM_CAP_SET_BOOT_CPU_ID:
2189#endif 2200#endif
2190 case KVM_CAP_INTERNAL_ERROR_DATA: 2201 case KVM_CAP_INTERNAL_ERROR_DATA:
2202#ifdef CONFIG_HAVE_KVM_MSI
2203 case KVM_CAP_SIGNAL_MSI:
2204#endif
2191 return 1; 2205 return 1;
2192#ifdef CONFIG_HAVE_KVM_IRQCHIP 2206#ifdef CONFIG_HAVE_KVM_IRQCHIP
2193 case KVM_CAP_IRQ_ROUTING: 2207 case KVM_CAP_IRQ_ROUTING: