aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/kvm_book3s.h2
-rw-r--r--arch/powerpc/kvm/book3s.c10
-rw-r--r--arch/powerpc/kvm/book3s_64_emulate.c75
3 files changed, 87 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index b47b2f516eff..bea76371dbe1 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -131,6 +131,8 @@ extern void kvmppc_rmcall(ulong srr0, ulong srr1);
131extern void kvmppc_load_up_fpu(void); 131extern void kvmppc_load_up_fpu(void);
132extern void kvmppc_load_up_altivec(void); 132extern void kvmppc_load_up_altivec(void);
133extern void kvmppc_load_up_vsx(void); 133extern void kvmppc_load_up_vsx(void);
134extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst);
135extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst);
134 136
135static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu) 137static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
136{ 138{
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index c058f1a5c095..de12202fe1c6 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -906,6 +906,16 @@ program_interrupt:
906 } 906 }
907 break; 907 break;
908 } 908 }
909 case BOOK3S_INTERRUPT_ALIGNMENT:
910 if (kvmppc_read_inst(vcpu) == EMULATE_DONE) {
911 to_book3s(vcpu)->dsisr = kvmppc_alignment_dsisr(vcpu,
912 vcpu->arch.last_inst);
913 vcpu->arch.dear = kvmppc_alignment_dar(vcpu,
914 vcpu->arch.last_inst);
915 kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
916 }
917 r = RESUME_GUEST;
918 break;
909 case BOOK3S_INTERRUPT_MACHINE_CHECK: 919 case BOOK3S_INTERRUPT_MACHINE_CHECK:
910 case BOOK3S_INTERRUPT_TRACE: 920 case BOOK3S_INTERRUPT_TRACE:
911 kvmppc_book3s_queue_irqprio(vcpu, exit_nr); 921 kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
diff --git a/arch/powerpc/kvm/book3s_64_emulate.c b/arch/powerpc/kvm/book3s_64_emulate.c
index 39d5003e01f0..1e5cf8d594ea 100644
--- a/arch/powerpc/kvm/book3s_64_emulate.c
+++ b/arch/powerpc/kvm/book3s_64_emulate.c
@@ -44,6 +44,11 @@
44/* DCBZ is actually 1014, but we patch it to 1010 so we get a trap */ 44/* DCBZ is actually 1014, but we patch it to 1010 so we get a trap */
45#define OP_31_XOP_DCBZ 1010 45#define OP_31_XOP_DCBZ 1010
46 46
47#define OP_LFS 48
48#define OP_LFD 50
49#define OP_STFS 52
50#define OP_STFD 54
51
47#define SPRN_GQR0 912 52#define SPRN_GQR0 912
48#define SPRN_GQR1 913 53#define SPRN_GQR1 913
49#define SPRN_GQR2 914 54#define SPRN_GQR2 914
@@ -474,3 +479,73 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
474 return emulated; 479 return emulated;
475} 480}
476 481
482u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst)
483{
484 u32 dsisr = 0;
485
486 /*
487 * This is what the spec says about DSISR bits (not mentioned = 0):
488 *
489 * 12:13 [DS] Set to bits 30:31
490 * 15:16 [X] Set to bits 29:30
491 * 17 [X] Set to bit 25
492 * [D/DS] Set to bit 5
493 * 18:21 [X] Set to bits 21:24
494 * [D/DS] Set to bits 1:4
495 * 22:26 Set to bits 6:10 (RT/RS/FRT/FRS)
496 * 27:31 Set to bits 11:15 (RA)
497 */
498
499 switch (get_op(inst)) {
500 /* D-form */
501 case OP_LFS:
502 case OP_LFD:
503 case OP_STFD:
504 case OP_STFS:
505 dsisr |= (inst >> 12) & 0x4000; /* bit 17 */
506 dsisr |= (inst >> 17) & 0x3c00; /* bits 18:21 */
507 break;
508 /* X-form */
509 case 31:
510 dsisr |= (inst << 14) & 0x18000; /* bits 15:16 */
511 dsisr |= (inst << 8) & 0x04000; /* bit 17 */
512 dsisr |= (inst << 3) & 0x03c00; /* bits 18:21 */
513 break;
514 default:
515 printk(KERN_INFO "KVM: Unaligned instruction 0x%x\n", inst);
516 break;
517 }
518
519 dsisr |= (inst >> 16) & 0x03ff; /* bits 22:31 */
520
521 return dsisr;
522}
523
524ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst)
525{
526 ulong dar = 0;
527 ulong ra;
528
529 switch (get_op(inst)) {
530 case OP_LFS:
531 case OP_LFD:
532 case OP_STFD:
533 case OP_STFS:
534 ra = get_ra(inst);
535 if (ra)
536 dar = kvmppc_get_gpr(vcpu, ra);
537 dar += (s32)((s16)inst);
538 break;
539 case 31:
540 ra = get_ra(inst);
541 if (ra)
542 dar = kvmppc_get_gpr(vcpu, ra);
543 dar += kvmppc_get_gpr(vcpu, get_rb(inst));
544 break;
545 default:
546 printk(KERN_INFO "KVM: Unaligned instruction 0x%x\n", inst);
547 break;
548 }
549
550 return dar;
551}