aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2009-10-30 01:47:16 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-11-05 00:49:57 -0500
commit513579e3a391a3874c478a8493080822069976e8 (patch)
tree329af02fc9790cbfcdda3c7162a734fd34111801 /arch/powerpc/kvm
parent9a7a9b09fee8487003df012d9af4b227b3661e4d (diff)
Add desktop PowerPC specific emulation
Little opcodes behave differently on desktop and embedded PowerPC cores. In order to reflect those differences, let's add some #ifdef code to emulate.c. We could probably also handle them in the core specific emulation files, but I would prefer to reuse as much code as possible. Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kvm')
-rw-r--r--arch/powerpc/kvm/emulate.c49
1 files changed, 39 insertions, 10 deletions
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index 50d411d946eb..1ec5e07b81eb 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -32,6 +32,7 @@
32#include "trace.h" 32#include "trace.h"
33 33
34#define OP_TRAP 3 34#define OP_TRAP 3
35#define OP_TRAP_64 2
35 36
36#define OP_31_XOP_LWZX 23 37#define OP_31_XOP_LWZX 23
37#define OP_31_XOP_LBZX 87 38#define OP_31_XOP_LBZX 87
@@ -64,16 +65,36 @@
64#define OP_STH 44 65#define OP_STH 44
65#define OP_STHU 45 66#define OP_STHU 45
66 67
68#ifdef CONFIG_PPC64
69static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu)
70{
71 return 1;
72}
73#else
74static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu)
75{
76 return vcpu->arch.tcr & TCR_DIE;
77}
78#endif
79
67void kvmppc_emulate_dec(struct kvm_vcpu *vcpu) 80void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
68{ 81{
69 unsigned long nr_jiffies; 82 unsigned long nr_jiffies;
70 83
71 if (vcpu->arch.tcr & TCR_DIE) { 84#ifdef CONFIG_PPC64
85 /* POWER4+ triggers a dec interrupt if the value is < 0 */
86 if (vcpu->arch.dec & 0x80000000) {
87 del_timer(&vcpu->arch.dec_timer);
88 kvmppc_core_queue_dec(vcpu);
89 return;
90 }
91#endif
92 if (kvmppc_dec_enabled(vcpu)) {
72 /* The decrementer ticks at the same rate as the timebase, so 93 /* The decrementer ticks at the same rate as the timebase, so
73 * that's how we convert the guest DEC value to the number of 94 * that's how we convert the guest DEC value to the number of
74 * host ticks. */ 95 * host ticks. */
75 96
76 vcpu->arch.dec_jiffies = mftb(); 97 vcpu->arch.dec_jiffies = get_tb();
77 nr_jiffies = vcpu->arch.dec / tb_ticks_per_jiffy; 98 nr_jiffies = vcpu->arch.dec / tb_ticks_per_jiffy;
78 mod_timer(&vcpu->arch.dec_timer, 99 mod_timer(&vcpu->arch.dec_timer,
79 get_jiffies_64() + nr_jiffies); 100 get_jiffies_64() + nr_jiffies);
@@ -113,9 +134,15 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
113 /* this default type might be overwritten by subcategories */ 134 /* this default type might be overwritten by subcategories */
114 kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS); 135 kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
115 136
137 pr_debug(KERN_INFO "Emulating opcode %d / %d\n", get_op(inst), get_xop(inst));
138
116 switch (get_op(inst)) { 139 switch (get_op(inst)) {
117 case OP_TRAP: 140 case OP_TRAP:
141#ifdef CONFIG_PPC64
142 case OP_TRAP_64:
143#else
118 vcpu->arch.esr |= ESR_PTR; 144 vcpu->arch.esr |= ESR_PTR;
145#endif
119 kvmppc_core_queue_program(vcpu); 146 kvmppc_core_queue_program(vcpu);
120 advance = 0; 147 advance = 0;
121 break; 148 break;
@@ -190,17 +217,19 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
190 case SPRN_SRR1: 217 case SPRN_SRR1:
191 vcpu->arch.gpr[rt] = vcpu->arch.srr1; break; 218 vcpu->arch.gpr[rt] = vcpu->arch.srr1; break;
192 case SPRN_PVR: 219 case SPRN_PVR:
193 vcpu->arch.gpr[rt] = mfspr(SPRN_PVR); break; 220 vcpu->arch.gpr[rt] = vcpu->arch.pvr; break;
194 case SPRN_PIR: 221 case SPRN_PIR:
195 vcpu->arch.gpr[rt] = mfspr(SPRN_PIR); break; 222 vcpu->arch.gpr[rt] = vcpu->vcpu_id; break;
223 case SPRN_MSSSR0:
224 vcpu->arch.gpr[rt] = 0; break;
196 225
197 /* Note: mftb and TBRL/TBWL are user-accessible, so 226 /* Note: mftb and TBRL/TBWL are user-accessible, so
198 * the guest can always access the real TB anyways. 227 * the guest can always access the real TB anyways.
199 * In fact, we probably will never see these traps. */ 228 * In fact, we probably will never see these traps. */
200 case SPRN_TBWL: 229 case SPRN_TBWL:
201 vcpu->arch.gpr[rt] = mftbl(); break; 230 vcpu->arch.gpr[rt] = get_tb() >> 32; break;
202 case SPRN_TBWU: 231 case SPRN_TBWU:
203 vcpu->arch.gpr[rt] = mftbu(); break; 232 vcpu->arch.gpr[rt] = get_tb(); break;
204 233
205 case SPRN_SPRG0: 234 case SPRN_SPRG0:
206 vcpu->arch.gpr[rt] = vcpu->arch.sprg0; break; 235 vcpu->arch.gpr[rt] = vcpu->arch.sprg0; break;
@@ -215,11 +244,9 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
215 244
216 case SPRN_DEC: 245 case SPRN_DEC:
217 { 246 {
218 u64 jd = mftb() - vcpu->arch.dec_jiffies; 247 u64 jd = get_tb() - vcpu->arch.dec_jiffies;
219 vcpu->arch.gpr[rt] = vcpu->arch.dec - jd; 248 vcpu->arch.gpr[rt] = vcpu->arch.dec - jd;
220#ifdef DEBUG_EMUL 249 pr_debug(KERN_INFO "mfDEC: %x - %llx = %lx\n", vcpu->arch.dec, jd, vcpu->arch.gpr[rt]);
221 printk(KERN_INFO "mfDEC: %x - %llx = %lx\n", vcpu->arch.dec, jd, vcpu->arch.gpr[rt]);
222#endif
223 break; 250 break;
224 } 251 }
225 default: 252 default:
@@ -271,6 +298,8 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
271 case SPRN_TBWL: break; 298 case SPRN_TBWL: break;
272 case SPRN_TBWU: break; 299 case SPRN_TBWU: break;
273 300
301 case SPRN_MSSSR0: break;
302
274 case SPRN_DEC: 303 case SPRN_DEC:
275 vcpu->arch.dec = vcpu->arch.gpr[rs]; 304 vcpu->arch.dec = vcpu->arch.gpr[rs];
276 kvmppc_emulate_dec(vcpu); 305 kvmppc_emulate_dec(vcpu);