aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm
diff options
context:
space:
mode:
authorEddie Dong <eddie.dong@intel.com>2007-07-06 05:20:49 -0400
committerAvi Kivity <avi@qumranet.com>2007-10-13 04:18:24 -0400
commit85f455f7ddbed403b34b4d54b1eaf0e14126a126 (patch)
tree1dba7aa8fee3c8f756e12049c496dee5baae752c /drivers/kvm
parent152d3f2f246ce3c2a0cf2fc6c2214663cd99aa83 (diff)
KVM: Add support for in-kernel PIC emulation
Signed-off-by: Yaozu (Eddie) Dong <eddie.dong@intel.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm')
-rw-r--r--drivers/kvm/Makefile2
-rw-r--r--drivers/kvm/i8259.c442
-rw-r--r--drivers/kvm/irq.c61
-rw-r--r--drivers/kvm/irq.h64
-rw-r--r--drivers/kvm/kvm.h11
-rw-r--r--drivers/kvm/kvm_main.c46
-rw-r--r--drivers/kvm/svm.c69
-rw-r--r--drivers/kvm/vmx.c80
8 files changed, 751 insertions, 24 deletions
diff --git a/drivers/kvm/Makefile b/drivers/kvm/Makefile
index c0a789fa9d65..952dff38eb6c 100644
--- a/drivers/kvm/Makefile
+++ b/drivers/kvm/Makefile
@@ -2,7 +2,7 @@
2# Makefile for Kernel-based Virtual Machine module 2# Makefile for Kernel-based Virtual Machine module
3# 3#
4 4
5kvm-objs := kvm_main.o mmu.o x86_emulate.o 5kvm-objs := kvm_main.o mmu.o x86_emulate.o i8259.o irq.o
6obj-$(CONFIG_KVM) += kvm.o 6obj-$(CONFIG_KVM) += kvm.o
7kvm-intel-objs = vmx.o 7kvm-intel-objs = vmx.o
8obj-$(CONFIG_KVM_INTEL) += kvm-intel.o 8obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
diff --git a/drivers/kvm/i8259.c b/drivers/kvm/i8259.c
new file mode 100644
index 000000000000..40ad10462238
--- /dev/null
+++ b/drivers/kvm/i8259.c
@@ -0,0 +1,442 @@
1/*
2 * 8259 interrupt controller emulation
3 *
4 * Copyright (c) 2003-2004 Fabrice Bellard
5 * Copyright (c) 2007 Intel Corporation
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 * Authors:
25 * Yaozu (Eddie) Dong <Eddie.dong@intel.com>
26 * Port from Qemu.
27 */
28#include <linux/mm.h>
29#include "irq.h"
30
31/*
32 * set irq level. If an edge is detected, then the IRR is set to 1
33 */
34static inline void pic_set_irq1(struct kvm_kpic_state *s, int irq, int level)
35{
36 int mask;
37 mask = 1 << irq;
38 if (s->elcr & mask) /* level triggered */
39 if (level) {
40 s->irr |= mask;
41 s->last_irr |= mask;
42 } else {
43 s->irr &= ~mask;
44 s->last_irr &= ~mask;
45 }
46 else /* edge triggered */
47 if (level) {
48 if ((s->last_irr & mask) == 0)
49 s->irr |= mask;
50 s->last_irr |= mask;
51 } else
52 s->last_irr &= ~mask;
53}
54
55/*
56 * return the highest priority found in mask (highest = smallest
57 * number). Return 8 if no irq
58 */
59static inline int get_priority(struct kvm_kpic_state *s, int mask)
60{
61 int priority;
62 if (mask == 0)
63 return 8;
64 priority = 0;
65 while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0)
66 priority++;
67 return priority;
68}
69
70/*
71 * return the pic wanted interrupt. return -1 if none
72 */
73static int pic_get_irq(struct kvm_kpic_state *s)
74{
75 int mask, cur_priority, priority;
76
77 mask = s->irr & ~s->imr;
78 priority = get_priority(s, mask);
79 if (priority == 8)
80 return -1;
81 /*
82 * compute current priority. If special fully nested mode on the
83 * master, the IRQ coming from the slave is not taken into account
84 * for the priority computation.
85 */
86 mask = s->isr;
87 if (s->special_fully_nested_mode && s == &s->pics_state->pics[0])
88 mask &= ~(1 << 2);
89 cur_priority = get_priority(s, mask);
90 if (priority < cur_priority)
91 /*
92 * higher priority found: an irq should be generated
93 */
94 return (priority + s->priority_add) & 7;
95 else
96 return -1;
97}
98
99/*
100 * raise irq to CPU if necessary. must be called every time the active
101 * irq may change
102 */
103static void pic_update_irq(struct kvm_pic *s)
104{
105 int irq2, irq;
106
107 irq2 = pic_get_irq(&s->pics[1]);
108 if (irq2 >= 0) {
109 /*
110 * if irq request by slave pic, signal master PIC
111 */
112 pic_set_irq1(&s->pics[0], 2, 1);
113 pic_set_irq1(&s->pics[0], 2, 0);
114 }
115 irq = pic_get_irq(&s->pics[0]);
116 if (irq >= 0)
117 s->irq_request(s->irq_request_opaque, 1);
118 else
119 s->irq_request(s->irq_request_opaque, 0);
120}
121
122void kvm_pic_set_irq(void *opaque, int irq, int level)
123{
124 struct kvm_pic *s = opaque;
125
126 pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
127 pic_update_irq(s);
128}
129
130/*
131 * acknowledge interrupt 'irq'
132 */
133static inline void pic_intack(struct kvm_kpic_state *s, int irq)
134{
135 if (s->auto_eoi) {
136 if (s->rotate_on_auto_eoi)
137 s->priority_add = (irq + 1) & 7;
138 } else
139 s->isr |= (1 << irq);
140 /*
141 * We don't clear a level sensitive interrupt here
142 */
143 if (!(s->elcr & (1 << irq)))
144 s->irr &= ~(1 << irq);
145}
146
147int kvm_pic_read_irq(struct kvm_pic *s)
148{
149 int irq, irq2, intno;
150
151 irq = pic_get_irq(&s->pics[0]);
152 if (irq >= 0) {
153 pic_intack(&s->pics[0], irq);
154 if (irq == 2) {
155 irq2 = pic_get_irq(&s->pics[1]);
156 if (irq2 >= 0)
157 pic_intack(&s->pics[1], irq2);
158 else
159 /*
160 * spurious IRQ on slave controller
161 */
162 irq2 = 7;
163 intno = s->pics[1].irq_base + irq2;
164 irq = irq2 + 8;
165 } else
166 intno = s->pics[0].irq_base + irq;
167 } else {
168 /*
169 * spurious IRQ on host controller
170 */
171 irq = 7;
172 intno = s->pics[0].irq_base + irq;
173 }
174 pic_update_irq(s);
175
176 return intno;
177}
178
179static void pic_reset(void *opaque)
180{
181 struct kvm_kpic_state *s = opaque;
182
183 s->last_irr = 0;
184 s->irr = 0;
185 s->imr = 0;
186 s->isr = 0;
187 s->priority_add = 0;
188 s->irq_base = 0;
189 s->read_reg_select = 0;
190 s->poll = 0;
191 s->special_mask = 0;
192 s->init_state = 0;
193 s->auto_eoi = 0;
194 s->rotate_on_auto_eoi = 0;
195 s->special_fully_nested_mode = 0;
196 s->init4 = 0;
197}
198
199static void pic_ioport_write(void *opaque, u32 addr, u32 val)
200{
201 struct kvm_kpic_state *s = opaque;
202 int priority, cmd, irq;
203
204 addr &= 1;
205 if (addr == 0) {
206 if (val & 0x10) {
207 pic_reset(s); /* init */
208 /*
209 * deassert a pending interrupt
210 */
211 s->pics_state->irq_request(s->pics_state->
212 irq_request_opaque, 0);
213 s->init_state = 1;
214 s->init4 = val & 1;
215 if (val & 0x02)
216 printk(KERN_ERR "single mode not supported");
217 if (val & 0x08)
218 printk(KERN_ERR
219 "level sensitive irq not supported");
220 } else if (val & 0x08) {
221 if (val & 0x04)
222 s->poll = 1;
223 if (val & 0x02)
224 s->read_reg_select = val & 1;
225 if (val & 0x40)
226 s->special_mask = (val >> 5) & 1;
227 } else {
228 cmd = val >> 5;
229 switch (cmd) {
230 case 0:
231 case 4:
232 s->rotate_on_auto_eoi = cmd >> 2;
233 break;
234 case 1: /* end of interrupt */
235 case 5:
236 priority = get_priority(s, s->isr);
237 if (priority != 8) {
238 irq = (priority + s->priority_add) & 7;
239 s->isr &= ~(1 << irq);
240 if (cmd == 5)
241 s->priority_add = (irq + 1) & 7;
242 pic_update_irq(s->pics_state);
243 }
244 break;
245 case 3:
246 irq = val & 7;
247 s->isr &= ~(1 << irq);
248 pic_update_irq(s->pics_state);
249 break;
250 case 6:
251 s->priority_add = (val + 1) & 7;
252 pic_update_irq(s->pics_state);
253 break;
254 case 7:
255 irq = val & 7;
256 s->isr &= ~(1 << irq);
257 s->priority_add = (irq + 1) & 7;
258 pic_update_irq(s->pics_state);
259 break;
260 default:
261 break; /* no operation */
262 }
263 }
264 } else
265 switch (s->init_state) {
266 case 0: /* normal mode */
267 s->imr = val;
268 pic_update_irq(s->pics_state);
269 break;
270 case 1:
271 s->irq_base = val & 0xf8;
272 s->init_state = 2;
273 break;
274 case 2:
275 if (s->init4)
276 s->init_state = 3;
277 else
278 s->init_state = 0;
279 break;
280 case 3:
281 s->special_fully_nested_mode = (val >> 4) & 1;
282 s->auto_eoi = (val >> 1) & 1;
283 s->init_state = 0;
284 break;
285 }
286}
287
288static u32 pic_poll_read(struct kvm_kpic_state *s, u32 addr1)
289{
290 int ret;
291
292 ret = pic_get_irq(s);
293 if (ret >= 0) {
294 if (addr1 >> 7) {
295 s->pics_state->pics[0].isr &= ~(1 << 2);
296 s->pics_state->pics[0].irr &= ~(1 << 2);
297 }
298 s->irr &= ~(1 << ret);
299 s->isr &= ~(1 << ret);
300 if (addr1 >> 7 || ret != 2)
301 pic_update_irq(s->pics_state);
302 } else {
303 ret = 0x07;
304 pic_update_irq(s->pics_state);
305 }
306
307 return ret;
308}
309
310static u32 pic_ioport_read(void *opaque, u32 addr1)
311{
312 struct kvm_kpic_state *s = opaque;
313 unsigned int addr;
314 int ret;
315
316 addr = addr1;
317 addr &= 1;
318 if (s->poll) {
319 ret = pic_poll_read(s, addr1);
320 s->poll = 0;
321 } else
322 if (addr == 0)
323 if (s->read_reg_select)
324 ret = s->isr;
325 else
326 ret = s->irr;
327 else
328 ret = s->imr;
329 return ret;
330}
331
332static void elcr_ioport_write(void *opaque, u32 addr, u32 val)
333{
334 struct kvm_kpic_state *s = opaque;
335 s->elcr = val & s->elcr_mask;
336}
337
338static u32 elcr_ioport_read(void *opaque, u32 addr1)
339{
340 struct kvm_kpic_state *s = opaque;
341 return s->elcr;
342}
343
344static int picdev_in_range(struct kvm_io_device *this, gpa_t addr)
345{
346 switch (addr) {
347 case 0x20:
348 case 0x21:
349 case 0xa0:
350 case 0xa1:
351 case 0x4d0:
352 case 0x4d1:
353 return 1;
354 default:
355 return 0;
356 }
357}
358
359static void picdev_write(struct kvm_io_device *this,
360 gpa_t addr, int len, const void *val)
361{
362 struct kvm_pic *s = this->private;
363 unsigned char data = *(unsigned char *)val;
364
365 if (len != 1) {
366 if (printk_ratelimit())
367 printk(KERN_ERR "PIC: non byte write\n");
368 return;
369 }
370 switch (addr) {
371 case 0x20:
372 case 0x21:
373 case 0xa0:
374 case 0xa1:
375 pic_ioport_write(&s->pics[addr >> 7], addr, data);
376 break;
377 case 0x4d0:
378 case 0x4d1:
379 elcr_ioport_write(&s->pics[addr & 1], addr, data);
380 break;
381 }
382}
383
384static void picdev_read(struct kvm_io_device *this,
385 gpa_t addr, int len, void *val)
386{
387 struct kvm_pic *s = this->private;
388 unsigned char data = 0;
389
390 if (len != 1) {
391 if (printk_ratelimit())
392 printk(KERN_ERR "PIC: non byte read\n");
393 return;
394 }
395 switch (addr) {
396 case 0x20:
397 case 0x21:
398 case 0xa0:
399 case 0xa1:
400 data = pic_ioport_read(&s->pics[addr >> 7], addr);
401 break;
402 case 0x4d0:
403 case 0x4d1:
404 data = elcr_ioport_read(&s->pics[addr & 1], addr);
405 break;
406 }
407 *(unsigned char *)val = data;
408}
409
410/*
411 * callback when PIC0 irq status changed
412 */
413static void pic_irq_request(void *opaque, int level)
414{
415 struct kvm *kvm = opaque;
416
417 pic_irqchip(kvm)->output = level;
418}
419
420struct kvm_pic *kvm_create_pic(struct kvm *kvm)
421{
422 struct kvm_pic *s;
423 s = kzalloc(sizeof(struct kvm_pic), GFP_KERNEL);
424 if (!s)
425 return NULL;
426 s->pics[0].elcr_mask = 0xf8;
427 s->pics[1].elcr_mask = 0xde;
428 s->irq_request = pic_irq_request;
429 s->irq_request_opaque = kvm;
430 s->pics[0].pics_state = s;
431 s->pics[1].pics_state = s;
432
433 /*
434 * Initialize PIO device
435 */
436 s->dev.read = picdev_read;
437 s->dev.write = picdev_write;
438 s->dev.in_range = picdev_in_range;
439 s->dev.private = s;
440 kvm_io_bus_register_dev(&kvm->pio_bus, &s->dev);
441 return s;
442}
diff --git a/drivers/kvm/irq.c b/drivers/kvm/irq.c
new file mode 100644
index 000000000000..b08005ca7050
--- /dev/null
+++ b/drivers/kvm/irq.c
@@ -0,0 +1,61 @@
1/*
2 * irq.c: API for in kernel interrupt controller
3 * Copyright (c) 2007, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
17 * Authors:
18 * Yaozu (Eddie) Dong <Eddie.dong@intel.com>
19 *
20 */
21
22#include <linux/module.h>
23
24#include "kvm.h"
25#include "irq.h"
26
27/*
28 * check if there is pending interrupt without
29 * intack.
30 */
31int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
32{
33 struct kvm_pic *s = pic_irqchip(v->kvm);
34
35 if (s->output) /* PIC */
36 return 1;
37 /*
38 * TODO: APIC
39 */
40 return 0;
41}
42EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt);
43
44/*
45 * Read pending interrupt vector and intack.
46 */
47int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
48{
49 struct kvm_pic *s = pic_irqchip(v->kvm);
50 int vector;
51
52 s->output = 0;
53 vector = kvm_pic_read_irq(s);
54 if (vector != -1)
55 return vector;
56 /*
57 * TODO: APIC
58 */
59 return -1;
60}
61EXPORT_SYMBOL_GPL(kvm_cpu_get_interrupt);
diff --git a/drivers/kvm/irq.h b/drivers/kvm/irq.h
new file mode 100644
index 000000000000..bdb2fc34804b
--- /dev/null
+++ b/drivers/kvm/irq.h
@@ -0,0 +1,64 @@
1/*
2 * irq.h: in kernel interrupt controller related definitions
3 * Copyright (c) 2007, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
17 * Authors:
18 * Yaozu (Eddie) Dong <Eddie.dong@intel.com>
19 *
20 */
21
22#ifndef __IRQ_H
23#define __IRQ_H
24
25#include "kvm.h"
26
27typedef void irq_request_func(void *opaque, int level);
28
29struct kvm_pic;
30struct kvm_kpic_state {
31 u8 last_irr; /* edge detection */
32 u8 irr; /* interrupt request register */
33 u8 imr; /* interrupt mask register */
34 u8 isr; /* interrupt service register */
35 u8 priority_add; /* highest irq priority */
36 u8 irq_base;
37 u8 read_reg_select;
38 u8 poll;
39 u8 special_mask;
40 u8 init_state;
41 u8 auto_eoi;
42 u8 rotate_on_auto_eoi;
43 u8 special_fully_nested_mode;
44 u8 init4; /* true if 4 byte init */
45 u8 elcr; /* PIIX edge/trigger selection */
46 u8 elcr_mask;
47 struct kvm_pic *pics_state;
48};
49
50struct kvm_pic {
51 struct kvm_kpic_state pics[2]; /* 0 is master pic, 1 is slave pic */
52 irq_request_func *irq_request;
53 void *irq_request_opaque;
54 int output; /* intr from master PIC */
55 struct kvm_io_device dev;
56};
57
58struct kvm_pic *kvm_create_pic(struct kvm *kvm);
59void kvm_pic_set_irq(void *opaque, int irq, int level);
60int kvm_pic_read_irq(struct kvm_pic *s);
61int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
62int kvm_cpu_has_interrupt(struct kvm_vcpu *v);
63
64#endif
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index a42a6f314a85..d71712ddebee 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -408,8 +408,19 @@ struct kvm {
408 struct file *filp; 408 struct file *filp;
409 struct kvm_io_bus mmio_bus; 409 struct kvm_io_bus mmio_bus;
410 struct kvm_io_bus pio_bus; 410 struct kvm_io_bus pio_bus;
411 struct kvm_pic *vpic;
411}; 412};
412 413
414static inline struct kvm_pic *pic_irqchip(struct kvm *kvm)
415{
416 return kvm->vpic;
417}
418
419static inline int irqchip_in_kernel(struct kvm *kvm)
420{
421 return pic_irqchip(kvm) != 0;
422}
423
413struct descriptor_table { 424struct descriptor_table {
414 u16 limit; 425 u16 limit;
415 unsigned long base; 426 unsigned long base;
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index d154487b7729..09a04bc9541d 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -18,6 +18,7 @@
18#include "kvm.h" 18#include "kvm.h"
19#include "x86_emulate.h" 19#include "x86_emulate.h"
20#include "segment_descriptor.h" 20#include "segment_descriptor.h"
21#include "irq.h"
21 22
22#include <linux/kvm.h> 23#include <linux/kvm.h>
23#include <linux/module.h> 24#include <linux/module.h>
@@ -378,6 +379,7 @@ static void kvm_destroy_vm(struct kvm *kvm)
378 spin_unlock(&kvm_lock); 379 spin_unlock(&kvm_lock);
379 kvm_io_bus_destroy(&kvm->pio_bus); 380 kvm_io_bus_destroy(&kvm->pio_bus);
380 kvm_io_bus_destroy(&kvm->mmio_bus); 381 kvm_io_bus_destroy(&kvm->mmio_bus);
382 kfree(kvm->vpic);
381 kvm_free_vcpus(kvm); 383 kvm_free_vcpus(kvm);
382 kvm_free_physmem(kvm); 384 kvm_free_physmem(kvm);
383 kfree(kvm); 385 kfree(kvm);
@@ -1258,7 +1260,8 @@ EXPORT_SYMBOL_GPL(emulate_instruction);
1258 1260
1259int kvm_emulate_halt(struct kvm_vcpu *vcpu) 1261int kvm_emulate_halt(struct kvm_vcpu *vcpu)
1260{ 1262{
1261 if (vcpu->irq_summary) 1263 if (vcpu->irq_summary ||
1264 (irqchip_in_kernel(vcpu->kvm) && kvm_cpu_has_interrupt(vcpu)))
1262 return 1; 1265 return 1;
1263 1266
1264 vcpu->run->exit_reason = KVM_EXIT_HLT; 1267 vcpu->run->exit_reason = KVM_EXIT_HLT;
@@ -2715,6 +2718,30 @@ static long kvm_vm_ioctl(struct file *filp,
2715 goto out; 2718 goto out;
2716 break; 2719 break;
2717 } 2720 }
2721 case KVM_CREATE_IRQCHIP:
2722 r = -ENOMEM;
2723 kvm->vpic = kvm_create_pic(kvm);
2724 if (kvm->vpic)
2725 r = 0;
2726 else
2727 goto out;
2728 break;
2729 case KVM_IRQ_LINE: {
2730 struct kvm_irq_level irq_event;
2731
2732 r = -EFAULT;
2733 if (copy_from_user(&irq_event, argp, sizeof irq_event))
2734 goto out;
2735 if (irqchip_in_kernel(kvm)) {
2736 if (irq_event.irq < 16)
2737 kvm_pic_set_irq(pic_irqchip(kvm),
2738 irq_event.irq,
2739 irq_event.level);
2740 /* TODO: IOAPIC */
2741 r = 0;
2742 }
2743 break;
2744 }
2718 default: 2745 default:
2719 ; 2746 ;
2720 } 2747 }
@@ -2825,12 +2852,19 @@ static long kvm_dev_ioctl(struct file *filp,
2825 r = 0; 2852 r = 0;
2826 break; 2853 break;
2827 } 2854 }
2828 case KVM_CHECK_EXTENSION: 2855 case KVM_CHECK_EXTENSION: {
2829 /* 2856 int ext = (long)argp;
2830 * No extensions defined at present. 2857
2831 */ 2858 switch (ext) {
2832 r = 0; 2859 case KVM_CAP_IRQCHIP:
2860 r = 1;
2861 break;
2862 default:
2863 r = 0;
2864 break;
2865 }
2833 break; 2866 break;
2867 }
2834 case KVM_GET_VCPU_MMAP_SIZE: 2868 case KVM_GET_VCPU_MMAP_SIZE:
2835 r = -EINVAL; 2869 r = -EINVAL;
2836 if (arg) 2870 if (arg)
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index cc674bfd31d9..2237a594a8ef 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -16,6 +16,7 @@
16 16
17#include "kvm_svm.h" 17#include "kvm_svm.h"
18#include "x86_emulate.h" 18#include "x86_emulate.h"
19#include "irq.h"
19 20
20#include <linux/module.h> 21#include <linux/module.h>
21#include <linux/kernel.h> 22#include <linux/kernel.h>
@@ -921,7 +922,8 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
921 enum emulation_result er; 922 enum emulation_result er;
922 int r; 923 int r;
923 924
924 if (is_external_interrupt(exit_int_info)) 925 if (!irqchip_in_kernel(kvm) &&
926 is_external_interrupt(exit_int_info))
925 push_irq(&svm->vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK); 927 push_irq(&svm->vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK);
926 928
927 mutex_lock(&kvm->lock); 929 mutex_lock(&kvm->lock);
@@ -1185,6 +1187,8 @@ static int msr_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
1185static int interrupt_window_interception(struct vcpu_svm *svm, 1187static int interrupt_window_interception(struct vcpu_svm *svm,
1186 struct kvm_run *kvm_run) 1188 struct kvm_run *kvm_run)
1187{ 1189{
1190 svm->vmcb->control.intercept &= ~(1ULL << INTERCEPT_VINTR);
1191 svm->vmcb->control.int_ctl &= ~V_IRQ_MASK;
1188 /* 1192 /*
1189 * If the user space waits to inject interrupts, exit as soon as 1193 * If the user space waits to inject interrupts, exit as soon as
1190 * possible 1194 * possible
@@ -1289,22 +1293,56 @@ static void pre_svm_run(struct vcpu_svm *svm)
1289} 1293}
1290 1294
1291 1295
1292static inline void inject_irq(struct vcpu_svm *svm) 1296static inline void svm_inject_irq(struct vcpu_svm *svm, int irq)
1293{ 1297{
1294 struct vmcb_control_area *control; 1298 struct vmcb_control_area *control;
1295 1299
1296 control = &svm->vmcb->control; 1300 control = &svm->vmcb->control;
1297 control->int_vector = pop_irq(&svm->vcpu); 1301 control->int_vector = irq;
1298 control->int_ctl &= ~V_INTR_PRIO_MASK; 1302 control->int_ctl &= ~V_INTR_PRIO_MASK;
1299 control->int_ctl |= V_IRQ_MASK | 1303 control->int_ctl |= V_IRQ_MASK |
1300 ((/*control->int_vector >> 4*/ 0xf) << V_INTR_PRIO_SHIFT); 1304 ((/*control->int_vector >> 4*/ 0xf) << V_INTR_PRIO_SHIFT);
1301} 1305}
1302 1306
1303static void reput_irq(struct vcpu_svm *svm) 1307static void svm_intr_assist(struct vcpu_svm *svm)
1304{ 1308{
1309 struct vmcb *vmcb = svm->vmcb;
1310 int intr_vector = -1;
1311
1312 if ((vmcb->control.exit_int_info & SVM_EVTINJ_VALID) &&
1313 ((vmcb->control.exit_int_info & SVM_EVTINJ_TYPE_MASK) == 0)) {
1314 intr_vector = vmcb->control.exit_int_info &
1315 SVM_EVTINJ_VEC_MASK;
1316 vmcb->control.exit_int_info = 0;
1317 svm_inject_irq(svm, intr_vector);
1318 return;
1319 }
1320
1321 if (vmcb->control.int_ctl & V_IRQ_MASK)
1322 return;
1323
1324 if (!kvm_cpu_has_interrupt(&svm->vcpu))
1325 return;
1326
1327 if (!(vmcb->save.rflags & X86_EFLAGS_IF) ||
1328 (vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) ||
1329 (vmcb->control.event_inj & SVM_EVTINJ_VALID)) {
1330 /* unable to deliver irq, set pending irq */
1331 vmcb->control.intercept |= (1ULL << INTERCEPT_VINTR);
1332 svm_inject_irq(svm, 0x0);
1333 return;
1334 }
1335 /* Okay, we can deliver the interrupt: grab it and update PIC state. */
1336 intr_vector = kvm_cpu_get_interrupt(&svm->vcpu);
1337 svm_inject_irq(svm, intr_vector);
1338}
1339
1340static void kvm_reput_irq(struct vcpu_svm *svm)
1341{
1342 struct kvm_vcpu *vcpu = &svm->vcpu;
1305 struct vmcb_control_area *control = &svm->vmcb->control; 1343 struct vmcb_control_area *control = &svm->vmcb->control;
1306 1344
1307 if (control->int_ctl & V_IRQ_MASK) { 1345 if ((control->int_ctl & V_IRQ_MASK) && !irqchip_in_kernel(vcpu->kvm)) {
1308 control->int_ctl &= ~V_IRQ_MASK; 1346 control->int_ctl &= ~V_IRQ_MASK;
1309 push_irq(&svm->vcpu, control->int_vector); 1347 push_irq(&svm->vcpu, control->int_vector);
1310 } 1348 }
@@ -1313,6 +1351,19 @@ static void reput_irq(struct vcpu_svm *svm)
1313 !(control->int_state & SVM_INTERRUPT_SHADOW_MASK); 1351 !(control->int_state & SVM_INTERRUPT_SHADOW_MASK);
1314} 1352}
1315 1353
1354static void svm_do_inject_vector(struct vcpu_svm *svm)
1355{
1356 struct kvm_vcpu *vcpu = &svm->vcpu;
1357 int word_index = __ffs(vcpu->irq_summary);
1358 int bit_index = __ffs(vcpu->irq_pending[word_index]);
1359 int irq = word_index * BITS_PER_LONG + bit_index;
1360
1361 clear_bit(bit_index, &vcpu->irq_pending[word_index]);
1362 if (!vcpu->irq_pending[word_index])
1363 clear_bit(word_index, &vcpu->irq_summary);
1364 svm_inject_irq(svm, irq);
1365}
1366
1316static void do_interrupt_requests(struct vcpu_svm *svm, 1367static void do_interrupt_requests(struct vcpu_svm *svm,
1317 struct kvm_run *kvm_run) 1368 struct kvm_run *kvm_run)
1318{ 1369{
@@ -1326,7 +1377,7 @@ static void do_interrupt_requests(struct vcpu_svm *svm,
1326 /* 1377 /*
1327 * If interrupts enabled, and not blocked by sti or mov ss. Good. 1378 * If interrupts enabled, and not blocked by sti or mov ss. Good.
1328 */ 1379 */
1329 inject_irq(svm); 1380 svm_do_inject_vector(svm);
1330 1381
1331 /* 1382 /*
1332 * Interrupts blocked. Wait for unblock. 1383 * Interrupts blocked. Wait for unblock.
@@ -1408,7 +1459,9 @@ again:
1408 return -EINTR; 1459 return -EINTR;
1409 } 1460 }
1410 1461
1411 if (!vcpu->mmio_read_completed) 1462 if (irqchip_in_kernel(vcpu->kvm))
1463 svm_intr_assist(svm);
1464 else if (!vcpu->mmio_read_completed)
1412 do_interrupt_requests(svm, kvm_run); 1465 do_interrupt_requests(svm, kvm_run);
1413 1466
1414 vcpu->guest_mode = 1; 1467 vcpu->guest_mode = 1;
@@ -1576,7 +1629,7 @@ again:
1576 1629
1577 stgi(); 1630 stgi();
1578 1631
1579 reput_irq(svm); 1632 kvm_reput_irq(svm);
1580 1633
1581 svm->next_rip = 0; 1634 svm->next_rip = 0;
1582 1635
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index d63e82e5dbf8..f1e80a95b69d 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -17,6 +17,7 @@
17 17
18#include "kvm.h" 18#include "kvm.h"
19#include "x86_emulate.h" 19#include "x86_emulate.h"
20#include "irq.h"
20#include "vmx.h" 21#include "vmx.h"
21#include "segment_descriptor.h" 22#include "segment_descriptor.h"
22 23
@@ -1582,6 +1583,16 @@ static void inject_rmode_irq(struct kvm_vcpu *vcpu, int irq)
1582 vmcs_writel(GUEST_RSP, (vmcs_readl(GUEST_RSP) & ~0xffff) | (sp - 6)); 1583 vmcs_writel(GUEST_RSP, (vmcs_readl(GUEST_RSP) & ~0xffff) | (sp - 6));
1583} 1584}
1584 1585
1586static void vmx_inject_irq(struct kvm_vcpu *vcpu, int irq)
1587{
1588 if (vcpu->rmode.active) {
1589 inject_rmode_irq(vcpu, irq);
1590 return;
1591 }
1592 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
1593 irq | INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
1594}
1595
1585static void kvm_do_inject_irq(struct kvm_vcpu *vcpu) 1596static void kvm_do_inject_irq(struct kvm_vcpu *vcpu)
1586{ 1597{
1587 int word_index = __ffs(vcpu->irq_summary); 1598 int word_index = __ffs(vcpu->irq_summary);
@@ -1591,13 +1602,7 @@ static void kvm_do_inject_irq(struct kvm_vcpu *vcpu)
1591 clear_bit(bit_index, &vcpu->irq_pending[word_index]); 1602 clear_bit(bit_index, &vcpu->irq_pending[word_index]);
1592 if (!vcpu->irq_pending[word_index]) 1603 if (!vcpu->irq_pending[word_index])
1593 clear_bit(word_index, &vcpu->irq_summary); 1604 clear_bit(word_index, &vcpu->irq_summary);
1594 1605 vmx_inject_irq(vcpu, irq);
1595 if (vcpu->rmode.active) {
1596 inject_rmode_irq(vcpu, irq);
1597 return;
1598 }
1599 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
1600 irq | INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
1601} 1606}
1602 1607
1603 1608
@@ -1681,7 +1686,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1681 "intr info 0x%x\n", __FUNCTION__, vect_info, intr_info); 1686 "intr info 0x%x\n", __FUNCTION__, vect_info, intr_info);
1682 } 1687 }
1683 1688
1684 if (is_external_interrupt(vect_info)) { 1689 if (!irqchip_in_kernel(vcpu->kvm) && is_external_interrupt(vect_info)) {
1685 int irq = vect_info & VECTORING_INFO_VECTOR_MASK; 1690 int irq = vect_info & VECTORING_INFO_VECTOR_MASK;
1686 set_bit(irq, vcpu->irq_pending); 1691 set_bit(irq, vcpu->irq_pending);
1687 set_bit(irq / BITS_PER_LONG, &vcpu->irq_summary); 1692 set_bit(irq / BITS_PER_LONG, &vcpu->irq_summary);
@@ -1961,6 +1966,12 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu,
1961static int handle_interrupt_window(struct kvm_vcpu *vcpu, 1966static int handle_interrupt_window(struct kvm_vcpu *vcpu,
1962 struct kvm_run *kvm_run) 1967 struct kvm_run *kvm_run)
1963{ 1968{
1969 u32 cpu_based_vm_exec_control;
1970
1971 /* clear pending irq */
1972 cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
1973 cpu_based_vm_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
1974 vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
1964 /* 1975 /*
1965 * If the user space waits to inject interrupts, exit as soon as 1976 * If the user space waits to inject interrupts, exit as soon as
1966 * possible 1977 * possible
@@ -2052,6 +2063,55 @@ static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
2052{ 2063{
2053} 2064}
2054 2065
2066static void enable_irq_window(struct kvm_vcpu *vcpu)
2067{
2068 u32 cpu_based_vm_exec_control;
2069
2070 cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
2071 cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING;
2072 vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
2073}
2074
2075static void vmx_intr_assist(struct kvm_vcpu *vcpu)
2076{
2077 u32 idtv_info_field, intr_info_field;
2078 int has_ext_irq, interrupt_window_open;
2079
2080 has_ext_irq = kvm_cpu_has_interrupt(vcpu);
2081 intr_info_field = vmcs_read32(VM_ENTRY_INTR_INFO_FIELD);
2082 idtv_info_field = vmcs_read32(IDT_VECTORING_INFO_FIELD);
2083 if (intr_info_field & INTR_INFO_VALID_MASK) {
2084 if (idtv_info_field & INTR_INFO_VALID_MASK) {
2085 /* TODO: fault when IDT_Vectoring */
2086 printk(KERN_ERR "Fault when IDT_Vectoring\n");
2087 }
2088 if (has_ext_irq)
2089 enable_irq_window(vcpu);
2090 return;
2091 }
2092 if (unlikely(idtv_info_field & INTR_INFO_VALID_MASK)) {
2093 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field);
2094 vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
2095 vmcs_read32(VM_EXIT_INSTRUCTION_LEN));
2096
2097 if (unlikely(idtv_info_field & INTR_INFO_DELIEVER_CODE_MASK))
2098 vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE,
2099 vmcs_read32(IDT_VECTORING_ERROR_CODE));
2100 if (unlikely(has_ext_irq))
2101 enable_irq_window(vcpu);
2102 return;
2103 }
2104 if (!has_ext_irq)
2105 return;
2106 interrupt_window_open =
2107 ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
2108 (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0);
2109 if (interrupt_window_open)
2110 vmx_inject_irq(vcpu, kvm_cpu_get_interrupt(vcpu));
2111 else
2112 enable_irq_window(vcpu);
2113}
2114
2055static int vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 2115static int vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
2056{ 2116{
2057 struct vcpu_vmx *vmx = to_vmx(vcpu); 2117 struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -2088,7 +2148,9 @@ again:
2088 goto out; 2148 goto out;
2089 } 2149 }
2090 2150
2091 if (!vcpu->mmio_read_completed) 2151 if (irqchip_in_kernel(vcpu->kvm))
2152 vmx_intr_assist(vcpu);
2153 else if (!vcpu->mmio_read_completed)
2092 do_interrupt_requests(vcpu, kvm_run); 2154 do_interrupt_requests(vcpu, kvm_run);
2093 2155
2094 vcpu->guest_mode = 1; 2156 vcpu->guest_mode = 1;