diff options
author | Alexander Graf <agraf@suse.de> | 2009-10-30 01:47:16 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-11-05 00:49:57 -0500 |
commit | 513579e3a391a3874c478a8493080822069976e8 (patch) | |
tree | 329af02fc9790cbfcdda3c7162a734fd34111801 /arch/powerpc/kvm | |
parent | 9a7a9b09fee8487003df012d9af4b227b3661e4d (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.c | 49 |
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 | ||
69 | static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu) | ||
70 | { | ||
71 | return 1; | ||
72 | } | ||
73 | #else | ||
74 | static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu) | ||
75 | { | ||
76 | return vcpu->arch.tcr & TCR_DIE; | ||
77 | } | ||
78 | #endif | ||
79 | |||
67 | void kvmppc_emulate_dec(struct kvm_vcpu *vcpu) | 80 | void 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); |