diff options
author | Eric Auger <eric.auger@linaro.org> | 2015-09-18 10:29:42 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2015-10-01 09:06:44 -0400 |
commit | 166c9775f1f8b8f00ad1db0fa5c8fc74059d965d (patch) | |
tree | 06d78f0f45d69b861ecc3be064469bcee19c2b21 /virt | |
parent | 37d9fe4783ffcaddcc4afe67626691e62c5ab30e (diff) |
KVM: create kvm_irqfd.h
Move _irqfd_resampler and _irqfd struct declarations in a new
public header: kvm_irqfd.h. They are respectively renamed into
kvm_kernel_irqfd_resampler and kvm_kernel_irqfd. Those datatypes
will be used by architecture specific code, in the context of
IRQ bypass manager integration.
Signed-off-by: Eric Auger <eric.auger@linaro.org>
Signed-off-by: Feng Wu <feng.wu@intel.com>
Reviewed-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'virt')
-rw-r--r-- | virt/kvm/eventfd.c | 95 |
1 files changed, 23 insertions, 72 deletions
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c index ac89299b8699..413f5a6b61ba 100644 --- a/virt/kvm/eventfd.c +++ b/virt/kvm/eventfd.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include <linux/kvm_host.h> | 24 | #include <linux/kvm_host.h> |
25 | #include <linux/kvm.h> | 25 | #include <linux/kvm.h> |
26 | #include <linux/kvm_irqfd.h> | ||
26 | #include <linux/workqueue.h> | 27 | #include <linux/workqueue.h> |
27 | #include <linux/syscalls.h> | 28 | #include <linux/syscalls.h> |
28 | #include <linux/wait.h> | 29 | #include <linux/wait.h> |
@@ -39,68 +40,14 @@ | |||
39 | #include <kvm/iodev.h> | 40 | #include <kvm/iodev.h> |
40 | 41 | ||
41 | #ifdef CONFIG_HAVE_KVM_IRQFD | 42 | #ifdef CONFIG_HAVE_KVM_IRQFD |
42 | /* | ||
43 | * -------------------------------------------------------------------- | ||
44 | * irqfd: Allows an fd to be used to inject an interrupt to the guest | ||
45 | * | ||
46 | * Credit goes to Avi Kivity for the original idea. | ||
47 | * -------------------------------------------------------------------- | ||
48 | */ | ||
49 | |||
50 | /* | ||
51 | * Resampling irqfds are a special variety of irqfds used to emulate | ||
52 | * level triggered interrupts. The interrupt is asserted on eventfd | ||
53 | * trigger. On acknowledgement through the irq ack notifier, the | ||
54 | * interrupt is de-asserted and userspace is notified through the | ||
55 | * resamplefd. All resamplers on the same gsi are de-asserted | ||
56 | * together, so we don't need to track the state of each individual | ||
57 | * user. We can also therefore share the same irq source ID. | ||
58 | */ | ||
59 | struct _irqfd_resampler { | ||
60 | struct kvm *kvm; | ||
61 | /* | ||
62 | * List of resampling struct _irqfd objects sharing this gsi. | ||
63 | * RCU list modified under kvm->irqfds.resampler_lock | ||
64 | */ | ||
65 | struct list_head list; | ||
66 | struct kvm_irq_ack_notifier notifier; | ||
67 | /* | ||
68 | * Entry in list of kvm->irqfd.resampler_list. Use for sharing | ||
69 | * resamplers among irqfds on the same gsi. | ||
70 | * Accessed and modified under kvm->irqfds.resampler_lock | ||
71 | */ | ||
72 | struct list_head link; | ||
73 | }; | ||
74 | |||
75 | struct _irqfd { | ||
76 | /* Used for MSI fast-path */ | ||
77 | struct kvm *kvm; | ||
78 | wait_queue_t wait; | ||
79 | /* Update side is protected by irqfds.lock */ | ||
80 | struct kvm_kernel_irq_routing_entry irq_entry; | ||
81 | seqcount_t irq_entry_sc; | ||
82 | /* Used for level IRQ fast-path */ | ||
83 | int gsi; | ||
84 | struct work_struct inject; | ||
85 | /* The resampler used by this irqfd (resampler-only) */ | ||
86 | struct _irqfd_resampler *resampler; | ||
87 | /* Eventfd notified on resample (resampler-only) */ | ||
88 | struct eventfd_ctx *resamplefd; | ||
89 | /* Entry in list of irqfds for a resampler (resampler-only) */ | ||
90 | struct list_head resampler_link; | ||
91 | /* Used for setup/shutdown */ | ||
92 | struct eventfd_ctx *eventfd; | ||
93 | struct list_head list; | ||
94 | poll_table pt; | ||
95 | struct work_struct shutdown; | ||
96 | }; | ||
97 | 43 | ||
98 | static struct workqueue_struct *irqfd_cleanup_wq; | 44 | static struct workqueue_struct *irqfd_cleanup_wq; |
99 | 45 | ||
100 | static void | 46 | static void |
101 | irqfd_inject(struct work_struct *work) | 47 | irqfd_inject(struct work_struct *work) |
102 | { | 48 | { |
103 | struct _irqfd *irqfd = container_of(work, struct _irqfd, inject); | 49 | struct kvm_kernel_irqfd *irqfd = |
50 | container_of(work, struct kvm_kernel_irqfd, inject); | ||
104 | struct kvm *kvm = irqfd->kvm; | 51 | struct kvm *kvm = irqfd->kvm; |
105 | 52 | ||
106 | if (!irqfd->resampler) { | 53 | if (!irqfd->resampler) { |
@@ -121,12 +68,13 @@ irqfd_inject(struct work_struct *work) | |||
121 | static void | 68 | static void |
122 | irqfd_resampler_ack(struct kvm_irq_ack_notifier *kian) | 69 | irqfd_resampler_ack(struct kvm_irq_ack_notifier *kian) |
123 | { | 70 | { |
124 | struct _irqfd_resampler *resampler; | 71 | struct kvm_kernel_irqfd_resampler *resampler; |
125 | struct kvm *kvm; | 72 | struct kvm *kvm; |
126 | struct _irqfd *irqfd; | 73 | struct kvm_kernel_irqfd *irqfd; |
127 | int idx; | 74 | int idx; |
128 | 75 | ||
129 | resampler = container_of(kian, struct _irqfd_resampler, notifier); | 76 | resampler = container_of(kian, |
77 | struct kvm_kernel_irqfd_resampler, notifier); | ||
130 | kvm = resampler->kvm; | 78 | kvm = resampler->kvm; |
131 | 79 | ||
132 | kvm_set_irq(kvm, KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID, | 80 | kvm_set_irq(kvm, KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID, |
@@ -141,9 +89,9 @@ irqfd_resampler_ack(struct kvm_irq_ack_notifier *kian) | |||
141 | } | 89 | } |
142 | 90 | ||
143 | static void | 91 | static void |
144 | irqfd_resampler_shutdown(struct _irqfd *irqfd) | 92 | irqfd_resampler_shutdown(struct kvm_kernel_irqfd *irqfd) |
145 | { | 93 | { |
146 | struct _irqfd_resampler *resampler = irqfd->resampler; | 94 | struct kvm_kernel_irqfd_resampler *resampler = irqfd->resampler; |
147 | struct kvm *kvm = resampler->kvm; | 95 | struct kvm *kvm = resampler->kvm; |
148 | 96 | ||
149 | mutex_lock(&kvm->irqfds.resampler_lock); | 97 | mutex_lock(&kvm->irqfds.resampler_lock); |
@@ -168,7 +116,8 @@ irqfd_resampler_shutdown(struct _irqfd *irqfd) | |||
168 | static void | 116 | static void |
169 | irqfd_shutdown(struct work_struct *work) | 117 | irqfd_shutdown(struct work_struct *work) |
170 | { | 118 | { |
171 | struct _irqfd *irqfd = container_of(work, struct _irqfd, shutdown); | 119 | struct kvm_kernel_irqfd *irqfd = |
120 | container_of(work, struct kvm_kernel_irqfd, shutdown); | ||
172 | u64 cnt; | 121 | u64 cnt; |
173 | 122 | ||
174 | /* | 123 | /* |
@@ -198,7 +147,7 @@ irqfd_shutdown(struct work_struct *work) | |||
198 | 147 | ||
199 | /* assumes kvm->irqfds.lock is held */ | 148 | /* assumes kvm->irqfds.lock is held */ |
200 | static bool | 149 | static bool |
201 | irqfd_is_active(struct _irqfd *irqfd) | 150 | irqfd_is_active(struct kvm_kernel_irqfd *irqfd) |
202 | { | 151 | { |
203 | return list_empty(&irqfd->list) ? false : true; | 152 | return list_empty(&irqfd->list) ? false : true; |
204 | } | 153 | } |
@@ -209,7 +158,7 @@ irqfd_is_active(struct _irqfd *irqfd) | |||
209 | * assumes kvm->irqfds.lock is held | 158 | * assumes kvm->irqfds.lock is held |
210 | */ | 159 | */ |
211 | static void | 160 | static void |
212 | irqfd_deactivate(struct _irqfd *irqfd) | 161 | irqfd_deactivate(struct kvm_kernel_irqfd *irqfd) |
213 | { | 162 | { |
214 | BUG_ON(!irqfd_is_active(irqfd)); | 163 | BUG_ON(!irqfd_is_active(irqfd)); |
215 | 164 | ||
@@ -224,7 +173,8 @@ irqfd_deactivate(struct _irqfd *irqfd) | |||
224 | static int | 173 | static int |
225 | irqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key) | 174 | irqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key) |
226 | { | 175 | { |
227 | struct _irqfd *irqfd = container_of(wait, struct _irqfd, wait); | 176 | struct kvm_kernel_irqfd *irqfd = |
177 | container_of(wait, struct kvm_kernel_irqfd, wait); | ||
228 | unsigned long flags = (unsigned long)key; | 178 | unsigned long flags = (unsigned long)key; |
229 | struct kvm_kernel_irq_routing_entry irq; | 179 | struct kvm_kernel_irq_routing_entry irq; |
230 | struct kvm *kvm = irqfd->kvm; | 180 | struct kvm *kvm = irqfd->kvm; |
@@ -274,12 +224,13 @@ static void | |||
274 | irqfd_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh, | 224 | irqfd_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh, |
275 | poll_table *pt) | 225 | poll_table *pt) |
276 | { | 226 | { |
277 | struct _irqfd *irqfd = container_of(pt, struct _irqfd, pt); | 227 | struct kvm_kernel_irqfd *irqfd = |
228 | container_of(pt, struct kvm_kernel_irqfd, pt); | ||
278 | add_wait_queue(wqh, &irqfd->wait); | 229 | add_wait_queue(wqh, &irqfd->wait); |
279 | } | 230 | } |
280 | 231 | ||
281 | /* Must be called under irqfds.lock */ | 232 | /* Must be called under irqfds.lock */ |
282 | static void irqfd_update(struct kvm *kvm, struct _irqfd *irqfd) | 233 | static void irqfd_update(struct kvm *kvm, struct kvm_kernel_irqfd *irqfd) |
283 | { | 234 | { |
284 | struct kvm_kernel_irq_routing_entry *e; | 235 | struct kvm_kernel_irq_routing_entry *e; |
285 | struct kvm_kernel_irq_routing_entry entries[KVM_NR_IRQCHIPS]; | 236 | struct kvm_kernel_irq_routing_entry entries[KVM_NR_IRQCHIPS]; |
@@ -304,7 +255,7 @@ static void irqfd_update(struct kvm *kvm, struct _irqfd *irqfd) | |||
304 | static int | 255 | static int |
305 | kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args) | 256 | kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args) |
306 | { | 257 | { |
307 | struct _irqfd *irqfd, *tmp; | 258 | struct kvm_kernel_irqfd *irqfd, *tmp; |
308 | struct fd f; | 259 | struct fd f; |
309 | struct eventfd_ctx *eventfd = NULL, *resamplefd = NULL; | 260 | struct eventfd_ctx *eventfd = NULL, *resamplefd = NULL; |
310 | int ret; | 261 | int ret; |
@@ -340,7 +291,7 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args) | |||
340 | irqfd->eventfd = eventfd; | 291 | irqfd->eventfd = eventfd; |
341 | 292 | ||
342 | if (args->flags & KVM_IRQFD_FLAG_RESAMPLE) { | 293 | if (args->flags & KVM_IRQFD_FLAG_RESAMPLE) { |
343 | struct _irqfd_resampler *resampler; | 294 | struct kvm_kernel_irqfd_resampler *resampler; |
344 | 295 | ||
345 | resamplefd = eventfd_ctx_fdget(args->resamplefd); | 296 | resamplefd = eventfd_ctx_fdget(args->resamplefd); |
346 | if (IS_ERR(resamplefd)) { | 297 | if (IS_ERR(resamplefd)) { |
@@ -525,7 +476,7 @@ kvm_eventfd_init(struct kvm *kvm) | |||
525 | static int | 476 | static int |
526 | kvm_irqfd_deassign(struct kvm *kvm, struct kvm_irqfd *args) | 477 | kvm_irqfd_deassign(struct kvm *kvm, struct kvm_irqfd *args) |
527 | { | 478 | { |
528 | struct _irqfd *irqfd, *tmp; | 479 | struct kvm_kernel_irqfd *irqfd, *tmp; |
529 | struct eventfd_ctx *eventfd; | 480 | struct eventfd_ctx *eventfd; |
530 | 481 | ||
531 | eventfd = eventfd_ctx_fdget(args->fd); | 482 | eventfd = eventfd_ctx_fdget(args->fd); |
@@ -581,7 +532,7 @@ kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args) | |||
581 | void | 532 | void |
582 | kvm_irqfd_release(struct kvm *kvm) | 533 | kvm_irqfd_release(struct kvm *kvm) |
583 | { | 534 | { |
584 | struct _irqfd *irqfd, *tmp; | 535 | struct kvm_kernel_irqfd *irqfd, *tmp; |
585 | 536 | ||
586 | spin_lock_irq(&kvm->irqfds.lock); | 537 | spin_lock_irq(&kvm->irqfds.lock); |
587 | 538 | ||
@@ -604,7 +555,7 @@ kvm_irqfd_release(struct kvm *kvm) | |||
604 | */ | 555 | */ |
605 | void kvm_irq_routing_update(struct kvm *kvm) | 556 | void kvm_irq_routing_update(struct kvm *kvm) |
606 | { | 557 | { |
607 | struct _irqfd *irqfd; | 558 | struct kvm_kernel_irqfd *irqfd; |
608 | 559 | ||
609 | spin_lock_irq(&kvm->irqfds.lock); | 560 | spin_lock_irq(&kvm->irqfds.lock); |
610 | 561 | ||