aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2012-07-26 11:01:50 -0400
committerMarcelo Tosatti <mtosatti@redhat.com>2012-07-31 23:21:06 -0400
commite9d90d472da97e1b1560bffb89578ba082c88a69 (patch)
treea44f4b5d0d74f88b6dc886a6ee024ae7dd25a5c5
parent4a4541a40e1fe145c72c4b959fac524a5600d9fb (diff)
KVM: Remove internal timer abstraction
kvm_timer_fn(), the sole inhabitant of timer.c, is only used by lapic.c. Move it there to make it easier to hack on it. struct kvm_timer is a thin wrapper around hrtimer, and only adds obfuscation. Move near its two users (with different names) to prepare for simplification. Signed-off-by: Avi Kivity <avi@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r--arch/x86/kvm/Makefile2
-rw-r--r--arch/x86/kvm/i8254.c8
-rw-r--r--arch/x86/kvm/i8254.h18
-rw-r--r--arch/x86/kvm/kvm_timer.h18
-rw-r--r--arch/x86/kvm/lapic.c30
-rw-r--r--arch/x86/kvm/lapic.h17
-rw-r--r--arch/x86/kvm/timer.c47
7 files changed, 67 insertions, 73 deletions
diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
index 4f579e8dcacf..04d30401c5cb 100644
--- a/arch/x86/kvm/Makefile
+++ b/arch/x86/kvm/Makefile
@@ -12,7 +12,7 @@ kvm-$(CONFIG_IOMMU_API) += $(addprefix ../../../virt/kvm/, iommu.o)
12kvm-$(CONFIG_KVM_ASYNC_PF) += $(addprefix ../../../virt/kvm/, async_pf.o) 12kvm-$(CONFIG_KVM_ASYNC_PF) += $(addprefix ../../../virt/kvm/, async_pf.o)
13 13
14kvm-y += x86.o mmu.o emulate.o i8259.o irq.o lapic.o \ 14kvm-y += x86.o mmu.o emulate.o i8259.o irq.o lapic.o \
15 i8254.o timer.o cpuid.o pmu.o 15 i8254.o cpuid.o pmu.o
16kvm-intel-y += vmx.o 16kvm-intel-y += vmx.o
17kvm-amd-y += svm.o 17kvm-amd-y += svm.o
18 18
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index adba28f88d1a..1d8e75702d95 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -272,14 +272,14 @@ static void destroy_pit_timer(struct kvm_pit *pit)
272 flush_kthread_work(&pit->expired); 272 flush_kthread_work(&pit->expired);
273} 273}
274 274
275static bool kpit_is_periodic(struct kvm_timer *ktimer) 275static bool kpit_is_periodic(struct kvm_pit_timer *ktimer)
276{ 276{
277 struct kvm_kpit_state *ps = container_of(ktimer, struct kvm_kpit_state, 277 struct kvm_kpit_state *ps = container_of(ktimer, struct kvm_kpit_state,
278 pit_timer); 278 pit_timer);
279 return ps->is_periodic; 279 return ps->is_periodic;
280} 280}
281 281
282static struct kvm_timer_ops kpit_ops = { 282static struct kvm_pit_timer_ops kpit_ops = {
283 .is_periodic = kpit_is_periodic, 283 .is_periodic = kpit_is_periodic,
284}; 284};
285 285
@@ -322,7 +322,7 @@ static void pit_do_work(struct kthread_work *work)
322 322
323static enum hrtimer_restart pit_timer_fn(struct hrtimer *data) 323static enum hrtimer_restart pit_timer_fn(struct hrtimer *data)
324{ 324{
325 struct kvm_timer *ktimer = container_of(data, struct kvm_timer, timer); 325 struct kvm_pit_timer *ktimer = container_of(data, struct kvm_pit_timer, timer);
326 struct kvm_pit *pt = ktimer->kvm->arch.vpit; 326 struct kvm_pit *pt = ktimer->kvm->arch.vpit;
327 327
328 if (ktimer->reinject || !atomic_read(&ktimer->pending)) { 328 if (ktimer->reinject || !atomic_read(&ktimer->pending)) {
@@ -340,7 +340,7 @@ static enum hrtimer_restart pit_timer_fn(struct hrtimer *data)
340static void create_pit_timer(struct kvm *kvm, u32 val, int is_period) 340static void create_pit_timer(struct kvm *kvm, u32 val, int is_period)
341{ 341{
342 struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state; 342 struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
343 struct kvm_timer *pt = &ps->pit_timer; 343 struct kvm_pit_timer *pt = &ps->pit_timer;
344 s64 interval; 344 s64 interval;
345 345
346 if (!irqchip_in_kernel(kvm) || ps->flags & KVM_PIT_FLAGS_HPET_LEGACY) 346 if (!irqchip_in_kernel(kvm) || ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)
diff --git a/arch/x86/kvm/i8254.h b/arch/x86/kvm/i8254.h
index fdf40425ea1d..3351816e8b32 100644
--- a/arch/x86/kvm/i8254.h
+++ b/arch/x86/kvm/i8254.h
@@ -21,10 +21,26 @@ struct kvm_kpit_channel_state {
21 ktime_t count_load_time; 21 ktime_t count_load_time;
22}; 22};
23 23
24struct kvm_pit_timer {
25 struct hrtimer timer;
26 s64 period; /* unit: ns */
27 u32 timer_mode_mask;
28 u64 tscdeadline;
29 atomic_t pending; /* accumulated triggered timers */
30 bool reinject;
31 struct kvm_pit_timer_ops *t_ops;
32 struct kvm *kvm;
33 struct kvm_vcpu *vcpu;
34};
35
36struct kvm_pit_timer_ops {
37 bool (*is_periodic)(struct kvm_pit_timer *);
38};
39
24struct kvm_kpit_state { 40struct kvm_kpit_state {
25 struct kvm_kpit_channel_state channels[3]; 41 struct kvm_kpit_channel_state channels[3];
26 u32 flags; 42 u32 flags;
27 struct kvm_timer pit_timer; 43 struct kvm_pit_timer pit_timer;
28 bool is_periodic; 44 bool is_periodic;
29 u32 speaker_data_on; 45 u32 speaker_data_on;
30 struct mutex lock; 46 struct mutex lock;
diff --git a/arch/x86/kvm/kvm_timer.h b/arch/x86/kvm/kvm_timer.h
deleted file mode 100644
index 497dbaa366d4..000000000000
--- a/arch/x86/kvm/kvm_timer.h
+++ /dev/null
@@ -1,18 +0,0 @@
1
2struct kvm_timer {
3 struct hrtimer timer;
4 s64 period; /* unit: ns */
5 u32 timer_mode_mask;
6 u64 tscdeadline;
7 atomic_t pending; /* accumulated triggered timers */
8 bool reinject;
9 struct kvm_timer_ops *t_ops;
10 struct kvm *kvm;
11 struct kvm_vcpu *vcpu;
12};
13
14struct kvm_timer_ops {
15 bool (*is_periodic)(struct kvm_timer *);
16};
17
18enum hrtimer_restart kvm_timer_fn(struct hrtimer *data);
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index ad7fff7ad13c..61ed32cd17c1 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1262,6 +1262,34 @@ static const struct kvm_io_device_ops apic_mmio_ops = {
1262 .write = apic_mmio_write, 1262 .write = apic_mmio_write,
1263}; 1263};
1264 1264
1265static enum hrtimer_restart apic_timer_fn(struct hrtimer *data)
1266{
1267 struct kvm_timer *ktimer = container_of(data, struct kvm_timer, timer);
1268 struct kvm_vcpu *vcpu = ktimer->vcpu;
1269 wait_queue_head_t *q = &vcpu->wq;
1270
1271 /*
1272 * There is a race window between reading and incrementing, but we do
1273 * not care about potentially losing timer events in the !reinject
1274 * case anyway. Note: KVM_REQ_PENDING_TIMER is implicitly checked
1275 * in vcpu_enter_guest.
1276 */
1277 if (ktimer->reinject || !atomic_read(&ktimer->pending)) {
1278 atomic_inc(&ktimer->pending);
1279 /* FIXME: this code should not know anything about vcpus */
1280 kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu);
1281 }
1282
1283 if (waitqueue_active(q))
1284 wake_up_interruptible(q);
1285
1286 if (ktimer->t_ops->is_periodic(ktimer)) {
1287 hrtimer_add_expires_ns(&ktimer->timer, ktimer->period);
1288 return HRTIMER_RESTART;
1289 } else
1290 return HRTIMER_NORESTART;
1291}
1292
1265int kvm_create_lapic(struct kvm_vcpu *vcpu) 1293int kvm_create_lapic(struct kvm_vcpu *vcpu)
1266{ 1294{
1267 struct kvm_lapic *apic; 1295 struct kvm_lapic *apic;
@@ -1285,7 +1313,7 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu)
1285 1313
1286 hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC, 1314 hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC,
1287 HRTIMER_MODE_ABS); 1315 HRTIMER_MODE_ABS);
1288 apic->lapic_timer.timer.function = kvm_timer_fn; 1316 apic->lapic_timer.timer.function = apic_timer_fn;
1289 apic->lapic_timer.t_ops = &lapic_timer_ops; 1317 apic->lapic_timer.t_ops = &lapic_timer_ops;
1290 apic->lapic_timer.kvm = vcpu->kvm; 1318 apic->lapic_timer.kvm = vcpu->kvm;
1291 apic->lapic_timer.vcpu = vcpu; 1319 apic->lapic_timer.vcpu = vcpu;
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 4af5405ae1e2..d7251c92ed42 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -2,10 +2,25 @@
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"
6 5
7#include <linux/kvm_host.h> 6#include <linux/kvm_host.h>
8 7
8struct kvm_timer {
9 struct hrtimer timer;
10 s64 period; /* unit: ns */
11 u32 timer_mode_mask;
12 u64 tscdeadline;
13 atomic_t pending; /* accumulated triggered timers */
14 bool reinject;
15 struct kvm_timer_ops *t_ops;
16 struct kvm *kvm;
17 struct kvm_vcpu *vcpu;
18};
19
20struct kvm_timer_ops {
21 bool (*is_periodic)(struct kvm_timer *);
22};
23
9struct kvm_lapic { 24struct kvm_lapic {
10 unsigned long base_address; 25 unsigned long base_address;
11 struct kvm_io_device dev; 26 struct kvm_io_device dev;
diff --git a/arch/x86/kvm/timer.c b/arch/x86/kvm/timer.c
deleted file mode 100644
index 6b85cc647f34..000000000000
--- a/arch/x86/kvm/timer.c
+++ /dev/null
@@ -1,47 +0,0 @@
1/*
2 * Kernel-based Virtual Machine driver for Linux
3 *
4 * This module enables machines with Intel VT-x extensions to run virtual
5 * machines without emulation or binary translation.
6 *
7 * timer support
8 *
9 * Copyright 2010 Red Hat, Inc. and/or its affiliates.
10 *
11 * This work is licensed under the terms of the GNU GPL, version 2. See
12 * the COPYING file in the top-level directory.
13 */
14
15#include <linux/kvm_host.h>
16#include <linux/kvm.h>
17#include <linux/hrtimer.h>
18#include <linux/atomic.h>
19#include "kvm_timer.h"
20
21enum hrtimer_restart kvm_timer_fn(struct hrtimer *data)
22{
23 struct kvm_timer *ktimer = container_of(data, struct kvm_timer, timer);
24 struct kvm_vcpu *vcpu = ktimer->vcpu;
25 wait_queue_head_t *q = &vcpu->wq;
26
27 /*
28 * There is a race window between reading and incrementing, but we do
29 * not care about potentially losing timer events in the !reinject
30 * case anyway. Note: KVM_REQ_PENDING_TIMER is implicitly checked
31 * in vcpu_enter_guest.
32 */
33 if (ktimer->reinject || !atomic_read(&ktimer->pending)) {
34 atomic_inc(&ktimer->pending);
35 /* FIXME: this code should not know anything about vcpus */
36 kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu);
37 }
38
39 if (waitqueue_active(q))
40 wake_up_interruptible(q);
41
42 if (ktimer->t_ops->is_periodic(ktimer)) {
43 hrtimer_add_expires_ns(&ktimer->timer, ktimer->period);
44 return HRTIMER_RESTART;
45 } else
46 return HRTIMER_NORESTART;
47}