aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/powerpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kvm/powerpc.c')
-rw-r--r--arch/powerpc/kvm/powerpc.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index b7858b1e15e..1266ed02b47 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -301,6 +301,22 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,
301 } 301 }
302 } 302 }
303 303
304 if (vcpu->arch.mmio_sign_extend) {
305 switch (run->mmio.len) {
306#ifdef CONFIG_PPC64
307 case 4:
308 gpr = (s64)(s32)gpr;
309 break;
310#endif
311 case 2:
312 gpr = (s64)(s16)gpr;
313 break;
314 case 1:
315 gpr = (s64)(s8)gpr;
316 break;
317 }
318 }
319
304 kvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, gpr); 320 kvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, gpr);
305 321
306 switch (vcpu->arch.io_gpr & KVM_REG_EXT_MASK) { 322 switch (vcpu->arch.io_gpr & KVM_REG_EXT_MASK) {
@@ -338,10 +354,23 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
338 vcpu->arch.mmio_is_bigendian = is_bigendian; 354 vcpu->arch.mmio_is_bigendian = is_bigendian;
339 vcpu->mmio_needed = 1; 355 vcpu->mmio_needed = 1;
340 vcpu->mmio_is_write = 0; 356 vcpu->mmio_is_write = 0;
357 vcpu->arch.mmio_sign_extend = 0;
341 358
342 return EMULATE_DO_MMIO; 359 return EMULATE_DO_MMIO;
343} 360}
344 361
362/* Same as above, but sign extends */
363int kvmppc_handle_loads(struct kvm_run *run, struct kvm_vcpu *vcpu,
364 unsigned int rt, unsigned int bytes, int is_bigendian)
365{
366 int r;
367
368 r = kvmppc_handle_load(run, vcpu, rt, bytes, is_bigendian);
369 vcpu->arch.mmio_sign_extend = 1;
370
371 return r;
372}
373
345int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, 374int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
346 u64 val, unsigned int bytes, int is_bigendian) 375 u64 val, unsigned int bytes, int is_bigendian)
347{ 376{