aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMarcelo Tosatti <mtosatti@redhat.com>2009-02-23 08:57:41 -0500
committerAvi Kivity <avi@redhat.com>2009-06-10 04:48:25 -0400
commitd3c7b77d1a6e7a0a27035a7ba723a3455317883e (patch)
tree65053ca8122dda5772c48ce70c9d99e8127f8cdd /arch
parentfd66842370e32f3bbe429677280a326c07e508c1 (diff)
KVM: unify part of generic timer handling
Hide the internals of vcpu awakening / injection from the in-kernel emulated timers. This makes future changes in this logic easier and decreases the distance to more generic timer handling. Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kvm/Makefile2
-rw-r--r--arch/x86/kvm/i8254.c57
-rw-r--r--arch/x86/kvm/i8254.h11
-rw-r--r--arch/x86/kvm/kvm_timer.h18
-rw-r--r--arch/x86/kvm/lapic.c94
-rw-r--r--arch/x86/kvm/lapic.h9
-rw-r--r--arch/x86/kvm/timer.c46
7 files changed, 129 insertions, 108 deletions
diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
index d3ec292f00f..b43c4efafe8 100644
--- a/arch/x86/kvm/Makefile
+++ b/arch/x86/kvm/Makefile
@@ -14,7 +14,7 @@ endif
14EXTRA_CFLAGS += -Ivirt/kvm -Iarch/x86/kvm 14EXTRA_CFLAGS += -Ivirt/kvm -Iarch/x86/kvm
15 15
16kvm-objs := $(common-objs) x86.o mmu.o x86_emulate.o i8259.o irq.o lapic.o \ 16kvm-objs := $(common-objs) x86.o mmu.o x86_emulate.o i8259.o irq.o lapic.o \
17 i8254.o 17 i8254.o timer.o
18obj-$(CONFIG_KVM) += kvm.o 18obj-$(CONFIG_KVM) += kvm.o
19kvm-intel-objs = vmx.o 19kvm-intel-objs = vmx.o
20obj-$(CONFIG_KVM_INTEL) += kvm-intel.o 20obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index 09ae841ff46..4e2e3f26dbf 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -219,25 +219,6 @@ static void pit_latch_status(struct kvm *kvm, int channel)
219 } 219 }
220} 220}
221 221
222static int __pit_timer_fn(struct kvm_kpit_state *ps)
223{
224 struct kvm_vcpu *vcpu0 = ps->pit->kvm->vcpus[0];
225 struct kvm_kpit_timer *pt = &ps->pit_timer;
226
227 if (!atomic_inc_and_test(&pt->pending))
228 set_bit(KVM_REQ_PENDING_TIMER, &vcpu0->requests);
229
230 if (!pt->reinject)
231 atomic_set(&pt->pending, 1);
232
233 if (vcpu0 && waitqueue_active(&vcpu0->wq))
234 wake_up_interruptible(&vcpu0->wq);
235
236 hrtimer_add_expires_ns(&pt->timer, pt->period);
237
238 return (pt->period == 0 ? 0 : 1);
239}
240
241int pit_has_pending_timer(struct kvm_vcpu *vcpu) 222int pit_has_pending_timer(struct kvm_vcpu *vcpu)
242{ 223{
243 struct kvm_pit *pit = vcpu->kvm->arch.vpit; 224 struct kvm_pit *pit = vcpu->kvm->arch.vpit;
@@ -258,21 +239,6 @@ static void kvm_pit_ack_irq(struct kvm_irq_ack_notifier *kian)
258 spin_unlock(&ps->inject_lock); 239 spin_unlock(&ps->inject_lock);
259} 240}
260 241
261static enum hrtimer_restart pit_timer_fn(struct hrtimer *data)
262{
263 struct kvm_kpit_state *ps;
264 int restart_timer = 0;
265
266 ps = container_of(data, struct kvm_kpit_state, pit_timer.timer);
267
268 restart_timer = __pit_timer_fn(ps);
269
270 if (restart_timer)
271 return HRTIMER_RESTART;
272 else
273 return HRTIMER_NORESTART;
274}
275
276void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu) 242void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu)
277{ 243{
278 struct kvm_pit *pit = vcpu->kvm->arch.vpit; 244 struct kvm_pit *pit = vcpu->kvm->arch.vpit;
@@ -286,15 +252,26 @@ void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu)
286 hrtimer_start_expires(timer, HRTIMER_MODE_ABS); 252 hrtimer_start_expires(timer, HRTIMER_MODE_ABS);
287} 253}
288 254
289static void destroy_pit_timer(struct kvm_kpit_timer *pt) 255static void destroy_pit_timer(struct kvm_timer *pt)
290{ 256{
291 pr_debug("pit: execute del timer!\n"); 257 pr_debug("pit: execute del timer!\n");
292 hrtimer_cancel(&pt->timer); 258 hrtimer_cancel(&pt->timer);
293} 259}
294 260
261static bool kpit_is_periodic(struct kvm_timer *ktimer)
262{
263 struct kvm_kpit_state *ps = container_of(ktimer, struct kvm_kpit_state,
264 pit_timer);
265 return ps->is_periodic;
266}
267
268struct kvm_timer_ops kpit_ops = {
269 .is_periodic = kpit_is_periodic,
270};
271
295static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period) 272static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period)
296{ 273{
297 struct kvm_kpit_timer *pt = &ps->pit_timer; 274 struct kvm_timer *pt = &ps->pit_timer;
298 s64 interval; 275 s64 interval;
299 276
300 interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ); 277 interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ);
@@ -304,7 +281,13 @@ static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period)
304 /* TODO The new value only affected after the retriggered */ 281 /* TODO The new value only affected after the retriggered */
305 hrtimer_cancel(&pt->timer); 282 hrtimer_cancel(&pt->timer);
306 pt->period = (is_period == 0) ? 0 : interval; 283 pt->period = (is_period == 0) ? 0 : interval;
307 pt->timer.function = pit_timer_fn; 284 ps->is_periodic = is_period;
285
286 pt->timer.function = kvm_timer_fn;
287 pt->t_ops = &kpit_ops;
288 pt->kvm = ps->pit->kvm;
289 pt->vcpu_id = 0;
290
308 atomic_set(&pt->pending, 0); 291 atomic_set(&pt->pending, 0);
309 ps->irq_ack = 1; 292 ps->irq_ack = 1;
310 293
diff --git a/arch/x86/kvm/i8254.h b/arch/x86/kvm/i8254.h
index 521accf3bae..bbd863ff60b 100644
--- a/arch/x86/kvm/i8254.h
+++ b/arch/x86/kvm/i8254.h
@@ -3,14 +3,6 @@
3 3
4#include "iodev.h" 4#include "iodev.h"
5 5
6struct kvm_kpit_timer {
7 struct hrtimer timer;
8 int irq;
9 s64 period; /* unit: ns */
10 atomic_t pending;
11 bool reinject;
12};
13
14struct kvm_kpit_channel_state { 6struct kvm_kpit_channel_state {
15 u32 count; /* can be 65536 */ 7 u32 count; /* can be 65536 */
16 u16 latched_count; 8 u16 latched_count;
@@ -29,7 +21,8 @@ struct kvm_kpit_channel_state {
29 21
30struct kvm_kpit_state { 22struct kvm_kpit_state {
31 struct kvm_kpit_channel_state channels[3]; 23 struct kvm_kpit_channel_state channels[3];
32 struct kvm_kpit_timer pit_timer; 24 struct kvm_timer pit_timer;
25 bool is_periodic;
33 u32 speaker_data_on; 26 u32 speaker_data_on;
34 struct mutex lock; 27 struct mutex lock;
35 struct kvm_pit *pit; 28 struct kvm_pit *pit;
diff --git a/arch/x86/kvm/kvm_timer.h b/arch/x86/kvm/kvm_timer.h
new file mode 100644
index 00000000000..26bd6ba74e1
--- /dev/null
+++ b/arch/x86/kvm/kvm_timer.h
@@ -0,0 +1,18 @@
1
2struct kvm_timer {
3 struct hrtimer timer;
4 s64 period; /* unit: ns */
5 atomic_t pending; /* accumulated triggered timers */
6 bool reinject;
7 struct kvm_timer_ops *t_ops;
8 struct kvm *kvm;
9 int vcpu_id;
10};
11
12struct kvm_timer_ops {
13 bool (*is_periodic)(struct kvm_timer *);
14};
15
16
17enum hrtimer_restart kvm_timer_fn(struct hrtimer *data);
18
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index afc59b2e7e0..27ca43e4e44 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -528,12 +528,13 @@ static u32 apic_get_tmcct(struct kvm_lapic *apic)
528 if (apic_get_reg(apic, APIC_TMICT) == 0) 528 if (apic_get_reg(apic, APIC_TMICT) == 0)
529 return 0; 529 return 0;
530 530
531 remaining = hrtimer_expires_remaining(&apic->timer.dev); 531 remaining = hrtimer_expires_remaining(&apic->lapic_timer.timer);
532 if (ktime_to_ns(remaining) < 0) 532 if (ktime_to_ns(remaining) < 0)
533 remaining = ktime_set(0, 0); 533 remaining = ktime_set(0, 0);
534 534
535 ns = mod_64(ktime_to_ns(remaining), apic->timer.period); 535 ns = mod_64(ktime_to_ns(remaining), apic->lapic_timer.period);
536 tmcct = div64_u64(ns, (APIC_BUS_CYCLE_NS * apic->timer.divide_count)); 536 tmcct = div64_u64(ns,
537 (APIC_BUS_CYCLE_NS * apic->divide_count));
537 538
538 return tmcct; 539 return tmcct;
539} 540}
@@ -620,25 +621,25 @@ static void update_divide_count(struct kvm_lapic *apic)
620 tdcr = apic_get_reg(apic, APIC_TDCR); 621 tdcr = apic_get_reg(apic, APIC_TDCR);
621 tmp1 = tdcr & 0xf; 622 tmp1 = tdcr & 0xf;
622 tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1; 623 tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1;
623 apic->timer.divide_count = 0x1 << (tmp2 & 0x7); 624 apic->divide_count = 0x1 << (tmp2 & 0x7);
624 625
625 apic_debug("timer divide count is 0x%x\n", 626 apic_debug("timer divide count is 0x%x\n",
626 apic->timer.divide_count); 627 apic->lapic_timer.divide_count);
627} 628}
628 629
629static void start_apic_timer(struct kvm_lapic *apic) 630static void start_apic_timer(struct kvm_lapic *apic)
630{ 631{
631 ktime_t now = apic->timer.dev.base->get_time(); 632 ktime_t now = apic->lapic_timer.timer.base->get_time();
632 633
633 apic->timer.period = apic_get_reg(apic, APIC_TMICT) * 634 apic->lapic_timer.period = apic_get_reg(apic, APIC_TMICT) *
634 APIC_BUS_CYCLE_NS * apic->timer.divide_count; 635 APIC_BUS_CYCLE_NS * apic->divide_count;
635 atomic_set(&apic->timer.pending, 0); 636 atomic_set(&apic->lapic_timer.pending, 0);
636 637
637 if (!apic->timer.period) 638 if (!apic->lapic_timer.period)
638 return; 639 return;
639 640
640 hrtimer_start(&apic->timer.dev, 641 hrtimer_start(&apic->lapic_timer.timer,
641 ktime_add_ns(now, apic->timer.period), 642 ktime_add_ns(now, apic->lapic_timer.period),
642 HRTIMER_MODE_ABS); 643 HRTIMER_MODE_ABS);
643 644
644 apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016" 645 apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
@@ -647,9 +648,9 @@ static void start_apic_timer(struct kvm_lapic *apic)
647 "expire @ 0x%016" PRIx64 ".\n", __func__, 648 "expire @ 0x%016" PRIx64 ".\n", __func__,
648 APIC_BUS_CYCLE_NS, ktime_to_ns(now), 649 APIC_BUS_CYCLE_NS, ktime_to_ns(now),
649 apic_get_reg(apic, APIC_TMICT), 650 apic_get_reg(apic, APIC_TMICT),
650 apic->timer.period, 651 apic->lapic_timer.period,
651 ktime_to_ns(ktime_add_ns(now, 652 ktime_to_ns(ktime_add_ns(now,
652 apic->timer.period))); 653 apic->lapic_timer.period)));
653} 654}
654 655
655static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val) 656static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
@@ -731,7 +732,7 @@ static void apic_mmio_write(struct kvm_io_device *this,
731 apic_set_reg(apic, APIC_LVTT + 0x10 * i, 732 apic_set_reg(apic, APIC_LVTT + 0x10 * i,
732 lvt_val | APIC_LVT_MASKED); 733 lvt_val | APIC_LVT_MASKED);
733 } 734 }
734 atomic_set(&apic->timer.pending, 0); 735 atomic_set(&apic->lapic_timer.pending, 0);
735 736
736 } 737 }
737 break; 738 break;
@@ -763,7 +764,7 @@ static void apic_mmio_write(struct kvm_io_device *this,
763 break; 764 break;
764 765
765 case APIC_TMICT: 766 case APIC_TMICT:
766 hrtimer_cancel(&apic->timer.dev); 767 hrtimer_cancel(&apic->lapic_timer.timer);
767 apic_set_reg(apic, APIC_TMICT, val); 768 apic_set_reg(apic, APIC_TMICT, val);
768 start_apic_timer(apic); 769 start_apic_timer(apic);
769 return; 770 return;
@@ -803,7 +804,7 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu)
803 if (!vcpu->arch.apic) 804 if (!vcpu->arch.apic)
804 return; 805 return;
805 806
806 hrtimer_cancel(&vcpu->arch.apic->timer.dev); 807 hrtimer_cancel(&vcpu->arch.apic->lapic_timer.timer);
807 808
808 if (vcpu->arch.apic->regs_page) 809 if (vcpu->arch.apic->regs_page)
809 __free_page(vcpu->arch.apic->regs_page); 810 __free_page(vcpu->arch.apic->regs_page);
@@ -881,7 +882,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
881 ASSERT(apic != NULL); 882 ASSERT(apic != NULL);
882 883
883 /* Stop the timer in case it's a reset to an active apic */ 884 /* Stop the timer in case it's a reset to an active apic */
884 hrtimer_cancel(&apic->timer.dev); 885 hrtimer_cancel(&apic->lapic_timer.timer);
885 886
886 apic_set_reg(apic, APIC_ID, vcpu->vcpu_id << 24); 887 apic_set_reg(apic, APIC_ID, vcpu->vcpu_id << 24);
887 apic_set_reg(apic, APIC_LVR, APIC_VERSION); 888 apic_set_reg(apic, APIC_LVR, APIC_VERSION);
@@ -906,7 +907,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
906 apic_set_reg(apic, APIC_TMR + 0x10 * i, 0); 907 apic_set_reg(apic, APIC_TMR + 0x10 * i, 0);
907 } 908 }
908 update_divide_count(apic); 909 update_divide_count(apic);
909 atomic_set(&apic->timer.pending, 0); 910 atomic_set(&apic->lapic_timer.pending, 0);
910 if (vcpu->vcpu_id == 0) 911 if (vcpu->vcpu_id == 0)
911 vcpu->arch.apic_base |= MSR_IA32_APICBASE_BSP; 912 vcpu->arch.apic_base |= MSR_IA32_APICBASE_BSP;
912 apic_update_ppr(apic); 913 apic_update_ppr(apic);
@@ -937,22 +938,11 @@ EXPORT_SYMBOL_GPL(kvm_lapic_enabled);
937 *---------------------------------------------------------------------- 938 *----------------------------------------------------------------------
938 */ 939 */
939 940
940/* TODO: make sure __apic_timer_fn runs in current pCPU */ 941static bool lapic_is_periodic(struct kvm_timer *ktimer)
941static int __apic_timer_fn(struct kvm_lapic *apic)
942{ 942{
943 int result = 0; 943 struct kvm_lapic *apic = container_of(ktimer, struct kvm_lapic,
944 wait_queue_head_t *q = &apic->vcpu->wq; 944 lapic_timer);
945 945 return apic_lvtt_period(apic);
946 if(!atomic_inc_and_test(&apic->timer.pending))
947 set_bit(KVM_REQ_PENDING_TIMER, &apic->vcpu->requests);
948 if (waitqueue_active(q))
949 wake_up_interruptible(q);
950
951 if (apic_lvtt_period(apic)) {
952 result = 1;
953 hrtimer_add_expires_ns(&apic->timer.dev, apic->timer.period);
954 }
955 return result;
956} 946}
957 947
958int apic_has_pending_timer(struct kvm_vcpu *vcpu) 948int apic_has_pending_timer(struct kvm_vcpu *vcpu)
@@ -960,7 +950,7 @@ int apic_has_pending_timer(struct kvm_vcpu *vcpu)
960 struct kvm_lapic *lapic = vcpu->arch.apic; 950 struct kvm_lapic *lapic = vcpu->arch.apic;
961 951
962 if (lapic && apic_enabled(lapic) && apic_lvt_enabled(lapic, APIC_LVTT)) 952 if (lapic && apic_enabled(lapic) && apic_lvt_enabled(lapic, APIC_LVTT))
963 return atomic_read(&lapic->timer.pending); 953 return atomic_read(&lapic->lapic_timer.pending);
964 954
965 return 0; 955 return 0;
966} 956}
@@ -987,20 +977,9 @@ void kvm_apic_nmi_wd_deliver(struct kvm_vcpu *vcpu)
987 kvm_apic_local_deliver(apic, APIC_LVT0); 977 kvm_apic_local_deliver(apic, APIC_LVT0);
988} 978}
989 979
990static enum hrtimer_restart apic_timer_fn(struct hrtimer *data) 980struct kvm_timer_ops lapic_timer_ops = {
991{ 981 .is_periodic = lapic_is_periodic,
992 struct kvm_lapic *apic; 982};
993 int restart_timer = 0;
994
995 apic = container_of(data, struct kvm_lapic, timer.dev);
996
997 restart_timer = __apic_timer_fn(apic);
998
999 if (restart_timer)
1000 return HRTIMER_RESTART;
1001 else
1002 return HRTIMER_NORESTART;
1003}
1004 983
1005int kvm_create_lapic(struct kvm_vcpu *vcpu) 984int kvm_create_lapic(struct kvm_vcpu *vcpu)
1006{ 985{
@@ -1025,8 +1004,13 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu)
1025 memset(apic->regs, 0, PAGE_SIZE); 1004 memset(apic->regs, 0, PAGE_SIZE);
1026 apic->vcpu = vcpu; 1005 apic->vcpu = vcpu;
1027 1006
1028 hrtimer_init(&apic->timer.dev, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); 1007 hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC,
1029 apic->timer.dev.function = apic_timer_fn; 1008 HRTIMER_MODE_ABS);
1009 apic->lapic_timer.timer.function = kvm_timer_fn;
1010 apic->lapic_timer.t_ops = &lapic_timer_ops;
1011 apic->lapic_timer.kvm = vcpu->kvm;
1012 apic->lapic_timer.vcpu_id = vcpu->vcpu_id;
1013
1030 apic->base_address = APIC_DEFAULT_PHYS_BASE; 1014 apic->base_address = APIC_DEFAULT_PHYS_BASE;
1031 vcpu->arch.apic_base = APIC_DEFAULT_PHYS_BASE; 1015 vcpu->arch.apic_base = APIC_DEFAULT_PHYS_BASE;
1032 1016
@@ -1079,9 +1063,9 @@ void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu)
1079{ 1063{
1080 struct kvm_lapic *apic = vcpu->arch.apic; 1064 struct kvm_lapic *apic = vcpu->arch.apic;
1081 1065
1082 if (apic && atomic_read(&apic->timer.pending) > 0) { 1066 if (apic && atomic_read(&apic->lapic_timer.pending) > 0) {
1083 if (kvm_apic_local_deliver(apic, APIC_LVTT)) 1067 if (kvm_apic_local_deliver(apic, APIC_LVTT))
1084 atomic_dec(&apic->timer.pending); 1068 atomic_dec(&apic->lapic_timer.pending);
1085 } 1069 }
1086} 1070}
1087 1071
@@ -1107,7 +1091,7 @@ void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu)
1107 MSR_IA32_APICBASE_BASE; 1091 MSR_IA32_APICBASE_BASE;
1108 apic_set_reg(apic, APIC_LVR, APIC_VERSION); 1092 apic_set_reg(apic, APIC_LVR, APIC_VERSION);
1109 apic_update_ppr(apic); 1093 apic_update_ppr(apic);
1110 hrtimer_cancel(&apic->timer.dev); 1094 hrtimer_cancel(&apic->lapic_timer.timer);
1111 update_divide_count(apic); 1095 update_divide_count(apic);
1112 start_apic_timer(apic); 1096 start_apic_timer(apic);
1113} 1097}
@@ -1120,7 +1104,7 @@ void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu)
1120 if (!apic) 1104 if (!apic)
1121 return; 1105 return;
1122 1106
1123 timer = &apic->timer.dev; 1107 timer = &apic->lapic_timer.timer;
1124 if (hrtimer_cancel(timer)) 1108 if (hrtimer_cancel(timer))
1125 hrtimer_start_expires(timer, HRTIMER_MODE_ABS); 1109 hrtimer_start_expires(timer, HRTIMER_MODE_ABS);
1126} 1110}
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 45ab6ee7120..2fc0d3c1b19 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -2,18 +2,15 @@
2#define __KVM_X86_LAPIC_H 2#define __KVM_X86_LAPIC_H
3 3
4#include "iodev.h" 4#include "iodev.h"
5#include "kvm_timer.h"
5 6
6#include <linux/kvm_host.h> 7#include <linux/kvm_host.h>
7 8
8struct kvm_lapic { 9struct kvm_lapic {
9 unsigned long base_address; 10 unsigned long base_address;
10 struct kvm_io_device dev; 11 struct kvm_io_device dev;
11 struct { 12 struct kvm_timer lapic_timer;
12 atomic_t pending; 13 u32 divide_count;
13 s64 period; /* unit: ns */
14 u32 divide_count;
15 struct hrtimer dev;
16 } timer;
17 struct kvm_vcpu *vcpu; 14 struct kvm_vcpu *vcpu;
18 struct page *regs_page; 15 struct page *regs_page;
19 void *regs; 16 void *regs;
diff --git a/arch/x86/kvm/timer.c b/arch/x86/kvm/timer.c
new file mode 100644
index 00000000000..86dbac072d0
--- /dev/null
+++ b/arch/x86/kvm/timer.c
@@ -0,0 +1,46 @@
1#include <linux/kvm_host.h>
2#include <linux/kvm.h>
3#include <linux/hrtimer.h>
4#include <asm/atomic.h>
5#include "kvm_timer.h"
6
7static int __kvm_timer_fn(struct kvm_vcpu *vcpu, struct kvm_timer *ktimer)
8{
9 int restart_timer = 0;
10 wait_queue_head_t *q = &vcpu->wq;
11
12 /* FIXME: this code should not know anything about vcpus */
13 if (!atomic_inc_and_test(&ktimer->pending))
14 set_bit(KVM_REQ_PENDING_TIMER, &vcpu->requests);
15
16 if (!ktimer->reinject)
17 atomic_set(&ktimer->pending, 1);
18
19 if (waitqueue_active(q))
20 wake_up_interruptible(q);
21
22 if (ktimer->t_ops->is_periodic(ktimer)) {
23 hrtimer_add_expires_ns(&ktimer->timer, ktimer->period);
24 restart_timer = 1;
25 }
26
27 return restart_timer;
28}
29
30enum hrtimer_restart kvm_timer_fn(struct hrtimer *data)
31{
32 int restart_timer;
33 struct kvm_vcpu *vcpu;
34 struct kvm_timer *ktimer = container_of(data, struct kvm_timer, timer);
35
36 vcpu = ktimer->kvm->vcpus[ktimer->vcpu_id];
37 if (!vcpu)
38 return HRTIMER_NORESTART;
39
40 restart_timer = __kvm_timer_fn(vcpu, ktimer);
41 if (restart_timer)
42 return HRTIMER_RESTART;
43 else
44 return HRTIMER_NORESTART;
45}
46