diff options
author | Jan Kiszka <jan.kiszka@siemens.com> | 2012-03-29 15:14:12 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2012-04-24 08:59:47 -0400 |
commit | 07975ad3b30579ca27d880491ad992326b930c63 (patch) | |
tree | fea166a02c387949a09a948a51781074bdc9ed68 | |
parent | 1f15d10984c854e077da5aa1a23f901496b49773 (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.txt | 21 | ||||
-rw-r--r-- | arch/x86/kvm/Kconfig | 1 | ||||
-rw-r--r-- | include/linux/kvm.h | 11 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 2 | ||||
-rw-r--r-- | virt/kvm/Kconfig | 3 | ||||
-rw-r--r-- | virt/kvm/irq_comm.c | 14 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 14 |
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 | |||
1689 | itself or when a soft lockup is detected. This ioctl can be called any time | 1689 | itself or when a soft lockup is detected. This ioctl can be called any time |
1690 | after pausing the vcpu, but before it is resumed. | 1690 | after pausing the vcpu, but before it is resumed. |
1691 | 1691 | ||
1692 | 4.71 KVM_SIGNAL_MSI | ||
1693 | |||
1694 | Capability: KVM_CAP_SIGNAL_MSI | ||
1695 | Architectures: x86 | ||
1696 | Type: vm ioctl | ||
1697 | Parameters: struct kvm_msi (in) | ||
1698 | Returns: >0 on delivery, 0 if guest blocked the MSI, and -1 on error | ||
1699 | |||
1700 | Directly inject a MSI message. Only valid with in-kernel irqchip that handles | ||
1701 | MSI messages. | ||
1702 | |||
1703 | struct kvm_msi { | ||
1704 | __u32 address_lo; | ||
1705 | __u32 address_hi; | ||
1706 | __u32 data; | ||
1707 | __u32 flags; | ||
1708 | __u8 pad[16]; | ||
1709 | }; | ||
1710 | |||
1711 | No flags are defined so far. The corresponding field must be 0. | ||
1712 | |||
1692 | 5. The kvm_run structure | 1713 | 5. The kvm_run structure |
1693 | 1714 | ||
1694 | Application code obtains a pointer to the kvm_run structure by | 1715 | Application 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 | ||
719 | struct 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); |
803 | void kvm_free_irq_routing(struct kvm *kvm); | 803 | void kvm_free_irq_routing(struct kvm *kvm); |
804 | 804 | ||
805 | int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi); | ||
806 | |||
805 | #else | 807 | #else |
806 | 808 | ||
807 | static inline void kvm_free_irq_routing(struct kvm *kvm) {} | 809 | static 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 | ||
19 | config KVM_ASYNC_PF | 19 | config KVM_ASYNC_PF |
20 | bool | 20 | bool |
21 | |||
22 | config 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 | ||
141 | int 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: |