aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kvm')
-rw-r--r--arch/powerpc/kvm/emulate.c14
-rw-r--r--arch/powerpc/kvm/powerpc.c29
2 files changed, 43 insertions, 0 deletions
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index cb72a65f4ecc..11789dd33a13 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -62,6 +62,8 @@
62#define OP_STBU 39 62#define OP_STBU 39
63#define OP_LHZ 40 63#define OP_LHZ 40
64#define OP_LHZU 41 64#define OP_LHZU 41
65#define OP_LHA 42
66#define OP_LHAU 43
65#define OP_STH 44 67#define OP_STH 44
66#define OP_STHU 45 68#define OP_STHU 45
67 69
@@ -450,6 +452,18 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
450 kvmppc_set_gpr(vcpu, ra, vcpu->arch.paddr_accessed); 452 kvmppc_set_gpr(vcpu, ra, vcpu->arch.paddr_accessed);
451 break; 453 break;
452 454
455 case OP_LHA:
456 rt = get_rt(inst);
457 emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
458 break;
459
460 case OP_LHAU:
461 ra = get_ra(inst);
462 rt = get_rt(inst);
463 emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
464 kvmppc_set_gpr(vcpu, ra, vcpu->arch.paddr_accessed);
465 break;
466
453 case OP_STH: 467 case OP_STH:
454 rs = get_rs(inst); 468 rs = get_rs(inst);
455 emulated = kvmppc_handle_store(run, vcpu, 469 emulated = kvmppc_handle_store(run, vcpu,
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index b7858b1e15ec..1266ed02b471 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{