summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2012-09-21 13:58:03 -0400
committerAvi Kivity <avi@redhat.com>2012-09-23 07:50:15 -0400
commit7a84428af7ca6a847f058c9ff244a18a2664fd1b (patch)
treee6c573c701736a75d618b670d66e98398b62769f
parent1e08ec4a130e2745d96df169e67c58df98a07311 (diff)
KVM: Add resampling irqfds for level triggered interrupts
To emulate level triggered interrupts, add a resample option to KVM_IRQFD. When specified, a new resamplefd is provided that notifies the user when the irqchip has been resampled by the VM. This may, for instance, indicate an EOI. Also in this mode, posting of an interrupt through an irqfd only asserts the interrupt. On resampling, the interrupt is automatically de-asserted prior to user notification. This enables level triggered interrupts to be posted and re-enabled from vfio with no userspace intervention. All resampling irqfds can make use of a single irq source ID, so we reserve a new one for this interface. Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--Documentation/virtual/kvm/api.txt13
-rw-r--r--arch/x86/kvm/x86.c4
-rw-r--r--include/linux/kvm.h12
-rw-r--r--include/linux/kvm_host.h5
-rw-r--r--virt/kvm/eventfd.c150
-rw-r--r--virt/kvm/irq_comm.c6
6 files changed, 184 insertions, 6 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 36befa775fdb..f6ec3a92e621 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1950,6 +1950,19 @@ the guest using the specified gsi pin. The irqfd is removed using
1950the KVM_IRQFD_FLAG_DEASSIGN flag, specifying both kvm_irqfd.fd 1950the KVM_IRQFD_FLAG_DEASSIGN flag, specifying both kvm_irqfd.fd
1951and kvm_irqfd.gsi. 1951and kvm_irqfd.gsi.
1952 1952
1953With KVM_CAP_IRQFD_RESAMPLE, KVM_IRQFD supports a de-assert and notify
1954mechanism allowing emulation of level-triggered, irqfd-based
1955interrupts. When KVM_IRQFD_FLAG_RESAMPLE is set the user must pass an
1956additional eventfd in the kvm_irqfd.resamplefd field. When operating
1957in resample mode, posting of an interrupt through kvm_irq.fd asserts
1958the specified gsi in the irqchip. When the irqchip is resampled, such
1959as from an EOI, the gsi is de-asserted and the user is notifed via
1960kvm_irqfd.resamplefd. It is the user's responsibility to re-queue
1961the interrupt if the device making use of it still requires service.
1962Note that closing the resamplefd is not sufficient to disable the
1963irqfd. The KVM_IRQFD_FLAG_RESAMPLE is only necessary on assignment
1964and need not be specified with KVM_IRQFD_FLAG_DEASSIGN.
1965
19534.76 KVM_PPC_ALLOCATE_HTAB 19664.76 KVM_PPC_ALLOCATE_HTAB
1954 1967
1955Capability: KVM_CAP_PPC_ALLOC_HTAB 1968Capability: KVM_CAP_PPC_ALLOC_HTAB
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index fc2a0a132e4b..7d44204c6041 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2176,6 +2176,7 @@ int kvm_dev_ioctl_check_extension(long ext)
2176 case KVM_CAP_PCI_2_3: 2176 case KVM_CAP_PCI_2_3:
2177 case KVM_CAP_KVMCLOCK_CTRL: 2177 case KVM_CAP_KVMCLOCK_CTRL:
2178 case KVM_CAP_READONLY_MEM: 2178 case KVM_CAP_READONLY_MEM:
2179 case KVM_CAP_IRQFD_RESAMPLE:
2179 r = 1; 2180 r = 1;
2180 break; 2181 break;
2181 case KVM_CAP_COALESCED_MMIO: 2182 case KVM_CAP_COALESCED_MMIO:
@@ -6268,6 +6269,9 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
6268 6269
6269 /* Reserve bit 0 of irq_sources_bitmap for userspace irq source */ 6270 /* Reserve bit 0 of irq_sources_bitmap for userspace irq source */
6270 set_bit(KVM_USERSPACE_IRQ_SOURCE_ID, &kvm->arch.irq_sources_bitmap); 6271 set_bit(KVM_USERSPACE_IRQ_SOURCE_ID, &kvm->arch.irq_sources_bitmap);
6272 /* Reserve bit 1 of irq_sources_bitmap for irqfd-resampler */
6273 set_bit(KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID,
6274 &kvm->arch.irq_sources_bitmap);
6271 6275
6272 raw_spin_lock_init(&kvm->arch.tsc_write_lock); 6276 raw_spin_lock_init(&kvm->arch.tsc_write_lock);
6273 mutex_init(&kvm->arch.apic_map_lock); 6277 mutex_init(&kvm->arch.apic_map_lock);
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index d808694673f9..0a6d6ba44c85 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -625,6 +625,7 @@ struct kvm_ppc_smmu_info {
625#ifdef __KVM_HAVE_READONLY_MEM 625#ifdef __KVM_HAVE_READONLY_MEM
626#define KVM_CAP_READONLY_MEM 81 626#define KVM_CAP_READONLY_MEM 81
627#endif 627#endif
628#define KVM_CAP_IRQFD_RESAMPLE 82
628 629
629#ifdef KVM_CAP_IRQ_ROUTING 630#ifdef KVM_CAP_IRQ_ROUTING
630 631
@@ -690,12 +691,21 @@ struct kvm_xen_hvm_config {
690#endif 691#endif
691 692
692#define KVM_IRQFD_FLAG_DEASSIGN (1 << 0) 693#define KVM_IRQFD_FLAG_DEASSIGN (1 << 0)
694/*
695 * Available with KVM_CAP_IRQFD_RESAMPLE
696 *
697 * KVM_IRQFD_FLAG_RESAMPLE indicates resamplefd is valid and specifies
698 * the irqfd to operate in resampling mode for level triggered interrupt
699 * emlation. See Documentation/virtual/kvm/api.txt.
700 */
701#define KVM_IRQFD_FLAG_RESAMPLE (1 << 1)
693 702
694struct kvm_irqfd { 703struct kvm_irqfd {
695 __u32 fd; 704 __u32 fd;
696 __u32 gsi; 705 __u32 gsi;
697 __u32 flags; 706 __u32 flags;
698 __u8 pad[20]; 707 __u32 resamplefd;
708 __u8 pad[16];
699}; 709};
700 710
701struct kvm_clock_data { 711struct kvm_clock_data {
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 80bfc880921e..2850656e2e96 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -119,7 +119,8 @@ static inline bool is_error_page(struct page *page)
119#define KVM_REQ_PMU 16 119#define KVM_REQ_PMU 16
120#define KVM_REQ_PMI 17 120#define KVM_REQ_PMI 17
121 121
122#define KVM_USERSPACE_IRQ_SOURCE_ID 0 122#define KVM_USERSPACE_IRQ_SOURCE_ID 0
123#define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID 1
123 124
124struct kvm; 125struct kvm;
125struct kvm_vcpu; 126struct kvm_vcpu;
@@ -343,6 +344,8 @@ struct kvm {
343 struct { 344 struct {
344 spinlock_t lock; 345 spinlock_t lock;
345 struct list_head items; 346 struct list_head items;
347 struct list_head resampler_list;
348 struct mutex resampler_lock;
346 } irqfds; 349 } irqfds;
347 struct list_head ioeventfds; 350 struct list_head ioeventfds;
348#endif 351#endif
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index 7d7e2aaffece..356965c9d107 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -43,6 +43,31 @@
43 * -------------------------------------------------------------------- 43 * --------------------------------------------------------------------
44 */ 44 */
45 45
46/*
47 * Resampling irqfds are a special variety of irqfds used to emulate
48 * level triggered interrupts. The interrupt is asserted on eventfd
49 * trigger. On acknowledgement through the irq ack notifier, the
50 * interrupt is de-asserted and userspace is notified through the
51 * resamplefd. All resamplers on the same gsi are de-asserted
52 * together, so we don't need to track the state of each individual
53 * user. We can also therefore share the same irq source ID.
54 */
55struct _irqfd_resampler {
56 struct kvm *kvm;
57 /*
58 * List of resampling struct _irqfd objects sharing this gsi.
59 * RCU list modified under kvm->irqfds.resampler_lock
60 */
61 struct list_head list;
62 struct kvm_irq_ack_notifier notifier;
63 /*
64 * Entry in list of kvm->irqfd.resampler_list. Use for sharing
65 * resamplers among irqfds on the same gsi.
66 * Accessed and modified under kvm->irqfds.resampler_lock
67 */
68 struct list_head link;
69};
70
46struct _irqfd { 71struct _irqfd {
47 /* Used for MSI fast-path */ 72 /* Used for MSI fast-path */
48 struct kvm *kvm; 73 struct kvm *kvm;
@@ -52,6 +77,12 @@ struct _irqfd {
52 /* Used for level IRQ fast-path */ 77 /* Used for level IRQ fast-path */
53 int gsi; 78 int gsi;
54 struct work_struct inject; 79 struct work_struct inject;
80 /* The resampler used by this irqfd (resampler-only) */
81 struct _irqfd_resampler *resampler;
82 /* Eventfd notified on resample (resampler-only) */
83 struct eventfd_ctx *resamplefd;
84 /* Entry in list of irqfds for a resampler (resampler-only) */
85 struct list_head resampler_link;
55 /* Used for setup/shutdown */ 86 /* Used for setup/shutdown */
56 struct eventfd_ctx *eventfd; 87 struct eventfd_ctx *eventfd;
57 struct list_head list; 88 struct list_head list;
@@ -67,8 +98,58 @@ irqfd_inject(struct work_struct *work)
67 struct _irqfd *irqfd = container_of(work, struct _irqfd, inject); 98 struct _irqfd *irqfd = container_of(work, struct _irqfd, inject);
68 struct kvm *kvm = irqfd->kvm; 99 struct kvm *kvm = irqfd->kvm;
69 100
70 kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi, 1); 101 if (!irqfd->resampler) {
71 kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi, 0); 102 kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi, 1);
103 kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi, 0);
104 } else
105 kvm_set_irq(kvm, KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID,
106 irqfd->gsi, 1);
107}
108
109/*
110 * Since resampler irqfds share an IRQ source ID, we de-assert once
111 * then notify all of the resampler irqfds using this GSI. We can't
112 * do multiple de-asserts or we risk racing with incoming re-asserts.
113 */
114static void
115irqfd_resampler_ack(struct kvm_irq_ack_notifier *kian)
116{
117 struct _irqfd_resampler *resampler;
118 struct _irqfd *irqfd;
119
120 resampler = container_of(kian, struct _irqfd_resampler, notifier);
121
122 kvm_set_irq(resampler->kvm, KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID,
123 resampler->notifier.gsi, 0);
124
125 rcu_read_lock();
126
127 list_for_each_entry_rcu(irqfd, &resampler->list, resampler_link)
128 eventfd_signal(irqfd->resamplefd, 1);
129
130 rcu_read_unlock();
131}
132
133static void
134irqfd_resampler_shutdown(struct _irqfd *irqfd)
135{
136 struct _irqfd_resampler *resampler = irqfd->resampler;
137 struct kvm *kvm = resampler->kvm;
138
139 mutex_lock(&kvm->irqfds.resampler_lock);
140
141 list_del_rcu(&irqfd->resampler_link);
142 synchronize_rcu();
143
144 if (list_empty(&resampler->list)) {
145 list_del(&resampler->link);
146 kvm_unregister_irq_ack_notifier(kvm, &resampler->notifier);
147 kvm_set_irq(kvm, KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID,
148 resampler->notifier.gsi, 0);
149 kfree(resampler);
150 }
151
152 mutex_unlock(&kvm->irqfds.resampler_lock);
72} 153}
73 154
74/* 155/*
@@ -92,6 +173,11 @@ irqfd_shutdown(struct work_struct *work)
92 */ 173 */
93 flush_work_sync(&irqfd->inject); 174 flush_work_sync(&irqfd->inject);
94 175
176 if (irqfd->resampler) {
177 irqfd_resampler_shutdown(irqfd);
178 eventfd_ctx_put(irqfd->resamplefd);
179 }
180
95 /* 181 /*
96 * It is now safe to release the object's resources 182 * It is now safe to release the object's resources
97 */ 183 */
@@ -203,7 +289,7 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
203 struct kvm_irq_routing_table *irq_rt; 289 struct kvm_irq_routing_table *irq_rt;
204 struct _irqfd *irqfd, *tmp; 290 struct _irqfd *irqfd, *tmp;
205 struct file *file = NULL; 291 struct file *file = NULL;
206 struct eventfd_ctx *eventfd = NULL; 292 struct eventfd_ctx *eventfd = NULL, *resamplefd = NULL;
207 int ret; 293 int ret;
208 unsigned int events; 294 unsigned int events;
209 295
@@ -231,6 +317,54 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
231 317
232 irqfd->eventfd = eventfd; 318 irqfd->eventfd = eventfd;
233 319
320 if (args->flags & KVM_IRQFD_FLAG_RESAMPLE) {
321 struct _irqfd_resampler *resampler;
322
323 resamplefd = eventfd_ctx_fdget(args->resamplefd);
324 if (IS_ERR(resamplefd)) {
325 ret = PTR_ERR(resamplefd);
326 goto fail;
327 }
328
329 irqfd->resamplefd = resamplefd;
330 INIT_LIST_HEAD(&irqfd->resampler_link);
331
332 mutex_lock(&kvm->irqfds.resampler_lock);
333
334 list_for_each_entry(resampler,
335 &kvm->irqfds.resampler_list, list) {
336 if (resampler->notifier.gsi == irqfd->gsi) {
337 irqfd->resampler = resampler;
338 break;
339 }
340 }
341
342 if (!irqfd->resampler) {
343 resampler = kzalloc(sizeof(*resampler), GFP_KERNEL);
344 if (!resampler) {
345 ret = -ENOMEM;
346 mutex_unlock(&kvm->irqfds.resampler_lock);
347 goto fail;
348 }
349
350 resampler->kvm = kvm;
351 INIT_LIST_HEAD(&resampler->list);
352 resampler->notifier.gsi = irqfd->gsi;
353 resampler->notifier.irq_acked = irqfd_resampler_ack;
354 INIT_LIST_HEAD(&resampler->link);
355
356 list_add(&resampler->link, &kvm->irqfds.resampler_list);
357 kvm_register_irq_ack_notifier(kvm,
358 &resampler->notifier);
359 irqfd->resampler = resampler;
360 }
361
362 list_add_rcu(&irqfd->resampler_link, &irqfd->resampler->list);
363 synchronize_rcu();
364
365 mutex_unlock(&kvm->irqfds.resampler_lock);
366 }
367
234 /* 368 /*
235 * Install our own custom wake-up handling so we are notified via 369 * Install our own custom wake-up handling so we are notified via
236 * a callback whenever someone signals the underlying eventfd 370 * a callback whenever someone signals the underlying eventfd
@@ -276,6 +410,12 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
276 return 0; 410 return 0;
277 411
278fail: 412fail:
413 if (irqfd->resampler)
414 irqfd_resampler_shutdown(irqfd);
415
416 if (resamplefd && !IS_ERR(resamplefd))
417 eventfd_ctx_put(resamplefd);
418
279 if (eventfd && !IS_ERR(eventfd)) 419 if (eventfd && !IS_ERR(eventfd))
280 eventfd_ctx_put(eventfd); 420 eventfd_ctx_put(eventfd);
281 421
@@ -291,6 +431,8 @@ kvm_eventfd_init(struct kvm *kvm)
291{ 431{
292 spin_lock_init(&kvm->irqfds.lock); 432 spin_lock_init(&kvm->irqfds.lock);
293 INIT_LIST_HEAD(&kvm->irqfds.items); 433 INIT_LIST_HEAD(&kvm->irqfds.items);
434 INIT_LIST_HEAD(&kvm->irqfds.resampler_list);
435 mutex_init(&kvm->irqfds.resampler_lock);
294 INIT_LIST_HEAD(&kvm->ioeventfds); 436 INIT_LIST_HEAD(&kvm->ioeventfds);
295} 437}
296 438
@@ -340,7 +482,7 @@ kvm_irqfd_deassign(struct kvm *kvm, struct kvm_irqfd *args)
340int 482int
341kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args) 483kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args)
342{ 484{
343 if (args->flags & ~KVM_IRQFD_FLAG_DEASSIGN) 485 if (args->flags & ~(KVM_IRQFD_FLAG_DEASSIGN | KVM_IRQFD_FLAG_RESAMPLE))
344 return -EINVAL; 486 return -EINVAL;
345 487
346 if (args->flags & KVM_IRQFD_FLAG_DEASSIGN) 488 if (args->flags & KVM_IRQFD_FLAG_DEASSIGN)
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index 3ca89c451d6b..2eb58af7ee99 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -228,6 +228,9 @@ int kvm_request_irq_source_id(struct kvm *kvm)
228 } 228 }
229 229
230 ASSERT(irq_source_id != KVM_USERSPACE_IRQ_SOURCE_ID); 230 ASSERT(irq_source_id != KVM_USERSPACE_IRQ_SOURCE_ID);
231#ifdef CONFIG_X86
232 ASSERT(irq_source_id != KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID);
233#endif
231 set_bit(irq_source_id, bitmap); 234 set_bit(irq_source_id, bitmap);
232unlock: 235unlock:
233 mutex_unlock(&kvm->irq_lock); 236 mutex_unlock(&kvm->irq_lock);
@@ -238,6 +241,9 @@ unlock:
238void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id) 241void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id)
239{ 242{
240 ASSERT(irq_source_id != KVM_USERSPACE_IRQ_SOURCE_ID); 243 ASSERT(irq_source_id != KVM_USERSPACE_IRQ_SOURCE_ID);
244#ifdef CONFIG_X86
245 ASSERT(irq_source_id != KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID);
246#endif
241 247
242 mutex_lock(&kvm->irq_lock); 248 mutex_lock(&kvm->irq_lock);
243 if (irq_source_id < 0 || 249 if (irq_source_id < 0 ||