diff options
author | Avi Kivity <avi@redhat.com> | 2012-07-26 11:01:50 -0400 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2012-07-31 23:21:06 -0400 |
commit | e9d90d472da97e1b1560bffb89578ba082c88a69 (patch) | |
tree | a44f4b5d0d74f88b6dc886a6ee024ae7dd25a5c5 | |
parent | 4a4541a40e1fe145c72c4b959fac524a5600d9fb (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/Makefile | 2 | ||||
-rw-r--r-- | arch/x86/kvm/i8254.c | 8 | ||||
-rw-r--r-- | arch/x86/kvm/i8254.h | 18 | ||||
-rw-r--r-- | arch/x86/kvm/kvm_timer.h | 18 | ||||
-rw-r--r-- | arch/x86/kvm/lapic.c | 30 | ||||
-rw-r--r-- | arch/x86/kvm/lapic.h | 17 | ||||
-rw-r--r-- | arch/x86/kvm/timer.c | 47 |
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) | |||
12 | kvm-$(CONFIG_KVM_ASYNC_PF) += $(addprefix ../../../virt/kvm/, async_pf.o) | 12 | kvm-$(CONFIG_KVM_ASYNC_PF) += $(addprefix ../../../virt/kvm/, async_pf.o) |
13 | 13 | ||
14 | kvm-y += x86.o mmu.o emulate.o i8259.o irq.o lapic.o \ | 14 | kvm-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 |
16 | kvm-intel-y += vmx.o | 16 | kvm-intel-y += vmx.o |
17 | kvm-amd-y += svm.o | 17 | kvm-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 | ||
275 | static bool kpit_is_periodic(struct kvm_timer *ktimer) | 275 | static 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 | ||
282 | static struct kvm_timer_ops kpit_ops = { | 282 | static 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 | ||
323 | static enum hrtimer_restart pit_timer_fn(struct hrtimer *data) | 323 | static 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) | |||
340 | static void create_pit_timer(struct kvm *kvm, u32 val, int is_period) | 340 | static 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 | ||
24 | struct 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 | |||
36 | struct kvm_pit_timer_ops { | ||
37 | bool (*is_periodic)(struct kvm_pit_timer *); | ||
38 | }; | ||
39 | |||
24 | struct kvm_kpit_state { | 40 | struct 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 | |||
2 | struct 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 | |||
14 | struct kvm_timer_ops { | ||
15 | bool (*is_periodic)(struct kvm_timer *); | ||
16 | }; | ||
17 | |||
18 | enum 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 | ||
1265 | static 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 | |||
1265 | int kvm_create_lapic(struct kvm_vcpu *vcpu) | 1293 | int 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 | ||
8 | struct 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 | |||
20 | struct kvm_timer_ops { | ||
21 | bool (*is_periodic)(struct kvm_timer *); | ||
22 | }; | ||
23 | |||
9 | struct kvm_lapic { | 24 | struct 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 | |||
21 | enum 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 | } | ||