aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2009-11-02 07:02:31 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-11-05 00:51:05 -0500
commit544c6761bb05a1dd19a39cb9bed096273f9bdb36 (patch)
tree66fde2d24a61c3be4712ac2701263aca04f26ebb
parentc8240bd6f0b4b1b21ffd36dd44114d05c7afe0c0 (diff)
Use hrtimers for the decrementer
Following S390's good example we should use hrtimers for the decrementer too! This patch converts the timer from the old mechanism to hrtimers. Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/include/asm/kvm_host.h6
-rw-r--r--arch/powerpc/kvm/emulate.c18
-rw-r--r--arch/powerpc/kvm/powerpc.c20
3 files changed, 33 insertions, 11 deletions
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 2cff5fe0cbe6..1201f62d0d73 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -21,7 +21,8 @@
21#define __POWERPC_KVM_HOST_H__ 21#define __POWERPC_KVM_HOST_H__
22 22
23#include <linux/mutex.h> 23#include <linux/mutex.h>
24#include <linux/timer.h> 24#include <linux/hrtimer.h>
25#include <linux/interrupt.h>
25#include <linux/types.h> 26#include <linux/types.h>
26#include <linux/kvm_types.h> 27#include <linux/kvm_types.h>
27#include <asm/kvm_asm.h> 28#include <asm/kvm_asm.h>
@@ -250,7 +251,8 @@ struct kvm_vcpu_arch {
250 251
251 u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */ 252 u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */
252 253
253 struct timer_list dec_timer; 254 struct hrtimer dec_timer;
255 struct tasklet_struct tasklet;
254 u64 dec_jiffies; 256 u64 dec_jiffies;
255 unsigned long pending_exceptions; 257 unsigned long pending_exceptions;
256 258
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index 1ec5e07b81eb..4a9ac6640fad 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -18,7 +18,7 @@
18 */ 18 */
19 19
20#include <linux/jiffies.h> 20#include <linux/jiffies.h>
21#include <linux/timer.h> 21#include <linux/hrtimer.h>
22#include <linux/types.h> 22#include <linux/types.h>
23#include <linux/string.h> 23#include <linux/string.h>
24#include <linux/kvm_host.h> 24#include <linux/kvm_host.h>
@@ -79,12 +79,13 @@ static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu)
79 79
80void kvmppc_emulate_dec(struct kvm_vcpu *vcpu) 80void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
81{ 81{
82 unsigned long nr_jiffies; 82 unsigned long dec_nsec;
83 83
84 pr_debug("mtDEC: %x\n", vcpu->arch.dec);
84#ifdef CONFIG_PPC64 85#ifdef CONFIG_PPC64
85 /* POWER4+ triggers a dec interrupt if the value is < 0 */ 86 /* POWER4+ triggers a dec interrupt if the value is < 0 */
86 if (vcpu->arch.dec & 0x80000000) { 87 if (vcpu->arch.dec & 0x80000000) {
87 del_timer(&vcpu->arch.dec_timer); 88 hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
88 kvmppc_core_queue_dec(vcpu); 89 kvmppc_core_queue_dec(vcpu);
89 return; 90 return;
90 } 91 }
@@ -94,12 +95,15 @@ void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
94 * that's how we convert the guest DEC value to the number of 95 * that's how we convert the guest DEC value to the number of
95 * host ticks. */ 96 * host ticks. */
96 97
98 hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
99 dec_nsec = vcpu->arch.dec;
100 dec_nsec *= 1000;
101 dec_nsec /= tb_ticks_per_usec;
102 hrtimer_start(&vcpu->arch.dec_timer, ktime_set(0, dec_nsec),
103 HRTIMER_MODE_REL);
97 vcpu->arch.dec_jiffies = get_tb(); 104 vcpu->arch.dec_jiffies = get_tb();
98 nr_jiffies = vcpu->arch.dec / tb_ticks_per_jiffy;
99 mod_timer(&vcpu->arch.dec_timer,
100 get_jiffies_64() + nr_jiffies);
101 } else { 105 } else {
102 del_timer(&vcpu->arch.dec_timer); 106 hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
103 } 107 }
104} 108}
105 109
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index a06ecc3401fd..692c3709011e 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -23,6 +23,7 @@
23#include <linux/kvm_host.h> 23#include <linux/kvm_host.h>
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/vmalloc.h> 25#include <linux/vmalloc.h>
26#include <linux/hrtimer.h>
26#include <linux/fs.h> 27#include <linux/fs.h>
27#include <asm/cputable.h> 28#include <asm/cputable.h>
28#include <asm/uaccess.h> 29#include <asm/uaccess.h>
@@ -208,10 +209,25 @@ static void kvmppc_decrementer_func(unsigned long data)
208 } 209 }
209} 210}
210 211
212/*
213 * low level hrtimer wake routine. Because this runs in hardirq context
214 * we schedule a tasklet to do the real work.
215 */
216enum hrtimer_restart kvmppc_decrementer_wakeup(struct hrtimer *timer)
217{
218 struct kvm_vcpu *vcpu;
219
220 vcpu = container_of(timer, struct kvm_vcpu, arch.dec_timer);
221 tasklet_schedule(&vcpu->arch.tasklet);
222
223 return HRTIMER_NORESTART;
224}
225
211int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) 226int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
212{ 227{
213 setup_timer(&vcpu->arch.dec_timer, kvmppc_decrementer_func, 228 hrtimer_init(&vcpu->arch.dec_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
214 (unsigned long)vcpu); 229 tasklet_init(&vcpu->arch.tasklet, kvmppc_decrementer_func, (ulong)vcpu);
230 vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup;
215 231
216 return 0; 232 return 0;
217} 233}