Skip to content

Commit 1c9f852

Browse files
committed
KVM: Extract generic irqchip logic into irqchip.c
The current irq_comm.c file contains pieces of code that are generic across different irqchip implementations, as well as code that is fully IOAPIC specific. Split the generic bits out into irqchip.c. Signed-off-by: Alexander Graf <agraf@suse.de> Acked-by: Michael S. Tsirkin <mst@redhat.com>
1 parent aa8d594 commit 1c9f852

File tree

4 files changed

+163
-121
lines changed

4 files changed

+163
-121
lines changed

arch/x86/kvm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ CFLAGS_vmx.o := -I.
77

88
kvm-y += $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \
99
coalesced_mmio.o irq_comm.o eventfd.o \
10-
assigned-dev.o)
10+
assigned-dev.o irqchip.o)
1111
kvm-$(CONFIG_IOMMU_API) += $(addprefix ../../../virt/kvm/, iommu.o)
1212
kvm-$(CONFIG_KVM_ASYNC_PF) += $(addprefix ../../../virt/kvm/, async_pf.o)
1313

include/trace/events/kvm.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ TRACE_EVENT(kvm_userspace_exit,
3737
__entry->errno < 0 ? -__entry->errno : __entry->reason)
3838
);
3939

40-
#if defined(__KVM_HAVE_IRQ_LINE)
40+
#if defined(CONFIG_HAVE_KVM_IRQCHIP)
4141
TRACE_EVENT(kvm_set_irq,
4242
TP_PROTO(unsigned int gsi, int level, int irq_source_id),
4343
TP_ARGS(gsi, level, irq_source_id),
@@ -122,6 +122,10 @@ TRACE_EVENT(kvm_msi_set_irq,
122122
{KVM_IRQCHIP_PIC_SLAVE, "PIC slave"}, \
123123
{KVM_IRQCHIP_IOAPIC, "IOAPIC"}
124124

125+
#endif /* defined(__KVM_HAVE_IOAPIC) */
126+
127+
#if defined(CONFIG_HAVE_KVM_IRQCHIP)
128+
125129
TRACE_EVENT(kvm_ack_irq,
126130
TP_PROTO(unsigned int irqchip, unsigned int pin),
127131
TP_ARGS(irqchip, pin),
@@ -136,14 +140,18 @@ TRACE_EVENT(kvm_ack_irq,
136140
__entry->pin = pin;
137141
),
138142

143+
#ifdef kvm_irqchips
139144
TP_printk("irqchip %s pin %u",
140145
__print_symbolic(__entry->irqchip, kvm_irqchips),
141146
__entry->pin)
147+
#else
148+
TP_printk("irqchip %d pin %u", __entry->irqchip, __entry->pin)
149+
#endif
142150
);
143151

152+
#endif /* defined(CONFIG_HAVE_KVM_IRQCHIP) */
144153

145154

146-
#endif /* defined(__KVM_HAVE_IOAPIC) */
147155

148156
#define KVM_TRACE_MMIO_READ_UNSATISFIED 0
149157
#define KVM_TRACE_MMIO_READ 1

virt/kvm/irq_comm.c

Lines changed: 0 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -151,59 +151,6 @@ static int kvm_set_msi_inatomic(struct kvm_kernel_irq_routing_entry *e,
151151
return -EWOULDBLOCK;
152152
}
153153

154-
int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi)
155-
{
156-
struct kvm_kernel_irq_routing_entry route;
157-
158-
if (!irqchip_in_kernel(kvm) || msi->flags != 0)
159-
return -EINVAL;
160-
161-
route.msi.address_lo = msi->address_lo;
162-
route.msi.address_hi = msi->address_hi;
163-
route.msi.data = msi->data;
164-
165-
return kvm_set_msi(&route, kvm, KVM_USERSPACE_IRQ_SOURCE_ID, 1, false);
166-
}
167-
168-
/*
169-
* Return value:
170-
* < 0 Interrupt was ignored (masked or not delivered for other reasons)
171-
* = 0 Interrupt was coalesced (previous irq is still pending)
172-
* > 0 Number of CPUs interrupt was delivered to
173-
*/
174-
int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
175-
bool line_status)
176-
{
177-
struct kvm_kernel_irq_routing_entry *e, irq_set[KVM_NR_IRQCHIPS];
178-
int ret = -1, i = 0;
179-
struct kvm_irq_routing_table *irq_rt;
180-
181-
trace_kvm_set_irq(irq, level, irq_source_id);
182-
183-
/* Not possible to detect if the guest uses the PIC or the
184-
* IOAPIC. So set the bit in both. The guest will ignore
185-
* writes to the unused one.
186-
*/
187-
rcu_read_lock();
188-
irq_rt = rcu_dereference(kvm->irq_routing);
189-
if (irq < irq_rt->nr_rt_entries)
190-
hlist_for_each_entry(e, &irq_rt->map[irq], link)
191-
irq_set[i++] = *e;
192-
rcu_read_unlock();
193-
194-
while(i--) {
195-
int r;
196-
r = irq_set[i].set(&irq_set[i], kvm, irq_source_id, level,
197-
line_status);
198-
if (r < 0)
199-
continue;
200-
201-
ret = r + ((ret < 0) ? 0 : ret);
202-
}
203-
204-
return ret;
205-
}
206-
207154
/*
208155
* Deliver an IRQ in an atomic context if we can, or return a failure,
209156
* user can retry in a process context.
@@ -241,63 +188,6 @@ int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level)
241188
return ret;
242189
}
243190

244-
bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin)
245-
{
246-
struct kvm_irq_ack_notifier *kian;
247-
int gsi;
248-
249-
rcu_read_lock();
250-
gsi = rcu_dereference(kvm->irq_routing)->chip[irqchip][pin];
251-
if (gsi != -1)
252-
hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list,
253-
link)
254-
if (kian->gsi == gsi) {
255-
rcu_read_unlock();
256-
return true;
257-
}
258-
259-
rcu_read_unlock();
260-
261-
return false;
262-
}
263-
EXPORT_SYMBOL_GPL(kvm_irq_has_notifier);
264-
265-
void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin)
266-
{
267-
struct kvm_irq_ack_notifier *kian;
268-
int gsi;
269-
270-
trace_kvm_ack_irq(irqchip, pin);
271-
272-
rcu_read_lock();
273-
gsi = rcu_dereference(kvm->irq_routing)->chip[irqchip][pin];
274-
if (gsi != -1)
275-
hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list,
276-
link)
277-
if (kian->gsi == gsi)
278-
kian->irq_acked(kian);
279-
rcu_read_unlock();
280-
}
281-
282-
void kvm_register_irq_ack_notifier(struct kvm *kvm,
283-
struct kvm_irq_ack_notifier *kian)
284-
{
285-
mutex_lock(&kvm->irq_lock);
286-
hlist_add_head_rcu(&kian->link, &kvm->irq_ack_notifier_list);
287-
mutex_unlock(&kvm->irq_lock);
288-
kvm_vcpu_request_scan_ioapic(kvm);
289-
}
290-
291-
void kvm_unregister_irq_ack_notifier(struct kvm *kvm,
292-
struct kvm_irq_ack_notifier *kian)
293-
{
294-
mutex_lock(&kvm->irq_lock);
295-
hlist_del_init_rcu(&kian->link);
296-
mutex_unlock(&kvm->irq_lock);
297-
synchronize_rcu();
298-
kvm_vcpu_request_scan_ioapic(kvm);
299-
}
300-
301191
int kvm_request_irq_source_id(struct kvm *kvm)
302192
{
303193
unsigned long *bitmap = &kvm->arch.irq_sources_bitmap;
@@ -381,13 +271,6 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin,
381271
rcu_read_unlock();
382272
}
383273

384-
void kvm_free_irq_routing(struct kvm *kvm)
385-
{
386-
/* Called only during vm destruction. Nobody can use the pointer
387-
at this stage */
388-
kfree(kvm->irq_routing);
389-
}
390-
391274
static int setup_routing_entry(struct kvm_irq_routing_table *rt,
392275
struct kvm_kernel_irq_routing_entry *e,
393276
const struct kvm_irq_routing_entry *ue)
@@ -451,7 +334,6 @@ static int setup_routing_entry(struct kvm_irq_routing_table *rt,
451334
return r;
452335
}
453336

454-
455337
int kvm_set_irq_routing(struct kvm *kvm,
456338
const struct kvm_irq_routing_entry *ue,
457339
unsigned nr,

virt/kvm/irqchip.c

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/*
2+
* irqchip.c: Common API for in kernel interrupt controllers
3+
* Copyright (c) 2007, Intel Corporation.
4+
* Copyright 2010 Red Hat, Inc. and/or its affiliates.
5+
* Copyright (c) 2013, Alexander Graf <agraf@suse.de>
6+
*
7+
* This program is free software; you can redistribute it and/or modify it
8+
* under the terms and conditions of the GNU General Public License,
9+
* version 2, as published by the Free Software Foundation.
10+
*
11+
* This program is distributed in the hope it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14+
* more details.
15+
*
16+
* You should have received a copy of the GNU General Public License along with
17+
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
18+
* Place - Suite 330, Boston, MA 02111-1307 USA.
19+
*
20+
* This file is derived from virt/kvm/irq_comm.c.
21+
*
22+
* Authors:
23+
* Yaozu (Eddie) Dong <Eddie.dong@intel.com>
24+
* Alexander Graf <agraf@suse.de>
25+
*/
26+
27+
#include <linux/kvm_host.h>
28+
#include <linux/slab.h>
29+
#include <linux/export.h>
30+
#include <trace/events/kvm.h>
31+
#include "irq.h"
32+
33+
bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin)
34+
{
35+
struct kvm_irq_ack_notifier *kian;
36+
int gsi;
37+
38+
rcu_read_lock();
39+
gsi = rcu_dereference(kvm->irq_routing)->chip[irqchip][pin];
40+
if (gsi != -1)
41+
hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list,
42+
link)
43+
if (kian->gsi == gsi) {
44+
rcu_read_unlock();
45+
return true;
46+
}
47+
48+
rcu_read_unlock();
49+
50+
return false;
51+
}
52+
EXPORT_SYMBOL_GPL(kvm_irq_has_notifier);
53+
54+
void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin)
55+
{
56+
struct kvm_irq_ack_notifier *kian;
57+
int gsi;
58+
59+
trace_kvm_ack_irq(irqchip, pin);
60+
61+
rcu_read_lock();
62+
gsi = rcu_dereference(kvm->irq_routing)->chip[irqchip][pin];
63+
if (gsi != -1)
64+
hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list,
65+
link)
66+
if (kian->gsi == gsi)
67+
kian->irq_acked(kian);
68+
rcu_read_unlock();
69+
}
70+
71+
void kvm_register_irq_ack_notifier(struct kvm *kvm,
72+
struct kvm_irq_ack_notifier *kian)
73+
{
74+
mutex_lock(&kvm->irq_lock);
75+
hlist_add_head_rcu(&kian->link, &kvm->irq_ack_notifier_list);
76+
mutex_unlock(&kvm->irq_lock);
77+
#ifdef __KVM_HAVE_IOAPIC
78+
kvm_vcpu_request_scan_ioapic(kvm);
79+
#endif
80+
}
81+
82+
void kvm_unregister_irq_ack_notifier(struct kvm *kvm,
83+
struct kvm_irq_ack_notifier *kian)
84+
{
85+
mutex_lock(&kvm->irq_lock);
86+
hlist_del_init_rcu(&kian->link);
87+
mutex_unlock(&kvm->irq_lock);
88+
synchronize_rcu();
89+
#ifdef __KVM_HAVE_IOAPIC
90+
kvm_vcpu_request_scan_ioapic(kvm);
91+
#endif
92+
}
93+
94+
int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi)
95+
{
96+
struct kvm_kernel_irq_routing_entry route;
97+
98+
if (!irqchip_in_kernel(kvm) || msi->flags != 0)
99+
return -EINVAL;
100+
101+
route.msi.address_lo = msi->address_lo;
102+
route.msi.address_hi = msi->address_hi;
103+
route.msi.data = msi->data;
104+
105+
return kvm_set_msi(&route, kvm, KVM_USERSPACE_IRQ_SOURCE_ID, 1, false);
106+
}
107+
108+
/*
109+
* Return value:
110+
* < 0 Interrupt was ignored (masked or not delivered for other reasons)
111+
* = 0 Interrupt was coalesced (previous irq is still pending)
112+
* > 0 Number of CPUs interrupt was delivered to
113+
*/
114+
int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
115+
bool line_status)
116+
{
117+
struct kvm_kernel_irq_routing_entry *e, irq_set[KVM_NR_IRQCHIPS];
118+
int ret = -1, i = 0;
119+
struct kvm_irq_routing_table *irq_rt;
120+
121+
trace_kvm_set_irq(irq, level, irq_source_id);
122+
123+
/* Not possible to detect if the guest uses the PIC or the
124+
* IOAPIC. So set the bit in both. The guest will ignore
125+
* writes to the unused one.
126+
*/
127+
rcu_read_lock();
128+
irq_rt = rcu_dereference(kvm->irq_routing);
129+
if (irq < irq_rt->nr_rt_entries)
130+
hlist_for_each_entry(e, &irq_rt->map[irq], link)
131+
irq_set[i++] = *e;
132+
rcu_read_unlock();
133+
134+
while(i--) {
135+
int r;
136+
r = irq_set[i].set(&irq_set[i], kvm, irq_source_id, level,
137+
line_status);
138+
if (r < 0)
139+
continue;
140+
141+
ret = r + ((ret < 0) ? 0 : ret);
142+
}
143+
144+
return ret;
145+
}
146+
147+
void kvm_free_irq_routing(struct kvm *kvm)
148+
{
149+
/* Called only during vm destruction. Nobody can use the pointer
150+
at this stage */
151+
kfree(kvm->irq_routing);
152+
}

0 commit comments

Comments
 (0)