aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/emulate.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kvm/emulate.c')
-rw-r--r--arch/powerpc/kvm/emulate.c61
1 files changed, 32 insertions, 29 deletions
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index 141dce3c6810..968f40101883 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -13,6 +13,7 @@
13 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 13 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
14 * 14 *
15 * Copyright IBM Corp. 2007 15 * Copyright IBM Corp. 2007
16 * Copyright 2011 Freescale Semiconductor, Inc.
16 * 17 *
17 * Authors: Hollis Blanchard <hollisb@us.ibm.com> 18 * Authors: Hollis Blanchard <hollisb@us.ibm.com>
18 */ 19 */
@@ -69,54 +70,55 @@
69#define OP_STH 44 70#define OP_STH 44
70#define OP_STHU 45 71#define OP_STHU 45
71 72
72#ifdef CONFIG_PPC_BOOK3S
73static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu)
74{
75 return 1;
76}
77#else
78static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu)
79{
80 return vcpu->arch.tcr & TCR_DIE;
81}
82#endif
83
84void kvmppc_emulate_dec(struct kvm_vcpu *vcpu) 73void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
85{ 74{
86 unsigned long dec_nsec; 75 unsigned long dec_nsec;
76 unsigned long long dec_time;
87 77
88 pr_debug("mtDEC: %x\n", vcpu->arch.dec); 78 pr_debug("mtDEC: %x\n", vcpu->arch.dec);
79 hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
80
89#ifdef CONFIG_PPC_BOOK3S 81#ifdef CONFIG_PPC_BOOK3S
90 /* mtdec lowers the interrupt line when positive. */ 82 /* mtdec lowers the interrupt line when positive. */
91 kvmppc_core_dequeue_dec(vcpu); 83 kvmppc_core_dequeue_dec(vcpu);
92 84
93 /* POWER4+ triggers a dec interrupt if the value is < 0 */ 85 /* POWER4+ triggers a dec interrupt if the value is < 0 */
94 if (vcpu->arch.dec & 0x80000000) { 86 if (vcpu->arch.dec & 0x80000000) {
95 hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
96 kvmppc_core_queue_dec(vcpu); 87 kvmppc_core_queue_dec(vcpu);
97 return; 88 return;
98 } 89 }
99#endif 90#endif
100 if (kvmppc_dec_enabled(vcpu)) { 91
101 /* The decrementer ticks at the same rate as the timebase, so 92#ifdef CONFIG_BOOKE
102 * that's how we convert the guest DEC value to the number of 93 /* On BOOKE, DEC = 0 is as good as decrementer not enabled */
103 * host ticks. */ 94 if (vcpu->arch.dec == 0)
104 95 return;
105 hrtimer_try_to_cancel(&vcpu->arch.dec_timer); 96#endif
106 dec_nsec = vcpu->arch.dec; 97
107 dec_nsec *= 1000; 98 /*
108 dec_nsec /= tb_ticks_per_usec; 99 * The decrementer ticks at the same rate as the timebase, so
109 hrtimer_start(&vcpu->arch.dec_timer, ktime_set(0, dec_nsec), 100 * that's how we convert the guest DEC value to the number of
110 HRTIMER_MODE_REL); 101 * host ticks.
111 vcpu->arch.dec_jiffies = get_tb(); 102 */
112 } else { 103
113 hrtimer_try_to_cancel(&vcpu->arch.dec_timer); 104 dec_time = vcpu->arch.dec;
114 } 105 dec_time *= 1000;
106 do_div(dec_time, tb_ticks_per_usec);
107 dec_nsec = do_div(dec_time, NSEC_PER_SEC);
108 hrtimer_start(&vcpu->arch.dec_timer,
109 ktime_set(dec_time, dec_nsec), HRTIMER_MODE_REL);
110 vcpu->arch.dec_jiffies = get_tb();
115} 111}
116 112
117u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb) 113u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb)
118{ 114{
119 u64 jd = tb - vcpu->arch.dec_jiffies; 115 u64 jd = tb - vcpu->arch.dec_jiffies;
116
117#ifdef CONFIG_BOOKE
118 if (vcpu->arch.dec < jd)
119 return 0;
120#endif
121
120 return vcpu->arch.dec - jd; 122 return vcpu->arch.dec - jd;
121} 123}
122 124
@@ -159,7 +161,8 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
159 case OP_TRAP_64: 161 case OP_TRAP_64:
160 kvmppc_core_queue_program(vcpu, SRR1_PROGTRAP); 162 kvmppc_core_queue_program(vcpu, SRR1_PROGTRAP);
161#else 163#else
162 kvmppc_core_queue_program(vcpu, vcpu->arch.esr | ESR_PTR); 164 kvmppc_core_queue_program(vcpu,
165 vcpu->arch.shared->esr | ESR_PTR);
163#endif 166#endif
164 advance = 0; 167 advance = 0;
165 break; 168 break;