aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMadhavan Srinivasan <maddy@linux.vnet.ibm.com>2014-09-09 13:07:36 -0400
committerAlexander Graf <agraf@suse.de>2014-09-22 04:11:36 -0400
commit033aaa14af0251285226a7dafc11c24a13959bca (patch)
tree8d71dd7d94ff7e9ae42a53d1b90514f182880613
parenta59c1d9e609c4bbad9ec3b238221ecf3b9ca091b (diff)
powerpc/kvm: common sw breakpoint instr across ppc
This patch extends the use of illegal instruction as software breakpoint instruction across the ppc platform. Patch extends booke program interrupt code to support software breakpoint. Signed-off-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com> [agraf: Fix bookehv] Signed-off-by: Alexander Graf <agraf@suse.de>
-rw-r--r--arch/powerpc/include/asm/kvm_booke.h2
-rw-r--r--arch/powerpc/kvm/booke.c19
-rw-r--r--arch/powerpc/kvm/bookehv_interrupts.S4
3 files changed, 20 insertions, 5 deletions
diff --git a/arch/powerpc/include/asm/kvm_booke.h b/arch/powerpc/include/asm/kvm_booke.h
index 630134d17f5d..3286f0d6a86c 100644
--- a/arch/powerpc/include/asm/kvm_booke.h
+++ b/arch/powerpc/include/asm/kvm_booke.h
@@ -33,8 +33,6 @@
33#define EHPRIV_OC_SHIFT 11 33#define EHPRIV_OC_SHIFT 11
34/* "ehpriv 1" : ehpriv with OC = 1 is used for debug emulation */ 34/* "ehpriv 1" : ehpriv with OC = 1 is used for debug emulation */
35#define EHPRIV_OC_DEBUG 1 35#define EHPRIV_OC_DEBUG 1
36#define KVMPPC_INST_EHPRIV_DEBUG (KVMPPC_INST_EHPRIV | \
37 (EHPRIV_OC_DEBUG << EHPRIV_OC_SHIFT))
38 36
39static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val) 37static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
40{ 38{
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 97ec5b7fce9c..ed5b0dd58726 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -994,6 +994,11 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
994 case BOOKE_INTERRUPT_HV_PRIV: 994 case BOOKE_INTERRUPT_HV_PRIV:
995 emulated = kvmppc_get_last_inst(vcpu, false, &last_inst); 995 emulated = kvmppc_get_last_inst(vcpu, false, &last_inst);
996 break; 996 break;
997 case BOOKE_INTERRUPT_PROGRAM:
998 /* SW breakpoints arrive as illegal instructions on HV */
999 if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
1000 emulated = kvmppc_get_last_inst(vcpu, false, &last_inst);
1001 break;
997 default: 1002 default:
998 break; 1003 break;
999 } 1004 }
@@ -1071,6 +1076,18 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
1071 break; 1076 break;
1072 1077
1073 case BOOKE_INTERRUPT_PROGRAM: 1078 case BOOKE_INTERRUPT_PROGRAM:
1079 if ((vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) &&
1080 (last_inst == KVMPPC_INST_SW_BREAKPOINT)) {
1081 /*
1082 * We are here because of an SW breakpoint instr,
1083 * so lets return to host to handle.
1084 */
1085 r = kvmppc_handle_debug(run, vcpu);
1086 run->exit_reason = KVM_EXIT_DEBUG;
1087 kvmppc_account_exit(vcpu, DEBUG_EXITS);
1088 break;
1089 }
1090
1074 if (vcpu->arch.shared->msr & (MSR_PR | MSR_GS)) { 1091 if (vcpu->arch.shared->msr & (MSR_PR | MSR_GS)) {
1075 /* 1092 /*
1076 * Program traps generated by user-level software must 1093 * Program traps generated by user-level software must
@@ -1647,7 +1664,7 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id,
1647 *val = get_reg_val(id, vcpu->arch.tsr); 1664 *val = get_reg_val(id, vcpu->arch.tsr);
1648 break; 1665 break;
1649 case KVM_REG_PPC_DEBUG_INST: 1666 case KVM_REG_PPC_DEBUG_INST:
1650 *val = get_reg_val(id, KVMPPC_INST_EHPRIV_DEBUG); 1667 *val = get_reg_val(id, KVMPPC_INST_SW_BREAKPOINT);
1651 break; 1668 break;
1652 case KVM_REG_PPC_VRSAVE: 1669 case KVM_REG_PPC_VRSAVE:
1653 *val = get_reg_val(id, vcpu->arch.vrsave); 1670 *val = get_reg_val(id, vcpu->arch.vrsave);
diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S
index c8e4da55cb43..81bd8a07aa51 100644
--- a/arch/powerpc/kvm/bookehv_interrupts.S
+++ b/arch/powerpc/kvm/bookehv_interrupts.S
@@ -238,7 +238,7 @@ kvm_handler BOOKE_INTERRUPT_EXTERNAL, EX_PARAMS(GEN), \
238kvm_handler BOOKE_INTERRUPT_ALIGNMENT, EX_PARAMS(GEN), \ 238kvm_handler BOOKE_INTERRUPT_ALIGNMENT, EX_PARAMS(GEN), \
239 SPRN_SRR0, SPRN_SRR1,(NEED_DEAR | NEED_ESR) 239 SPRN_SRR0, SPRN_SRR1,(NEED_DEAR | NEED_ESR)
240kvm_handler BOOKE_INTERRUPT_PROGRAM, EX_PARAMS(GEN), \ 240kvm_handler BOOKE_INTERRUPT_PROGRAM, EX_PARAMS(GEN), \
241 SPRN_SRR0, SPRN_SRR1,NEED_ESR 241 SPRN_SRR0, SPRN_SRR1, (NEED_ESR | NEED_EMU)
242kvm_handler BOOKE_INTERRUPT_FP_UNAVAIL, EX_PARAMS(GEN), \ 242kvm_handler BOOKE_INTERRUPT_FP_UNAVAIL, EX_PARAMS(GEN), \
243 SPRN_SRR0, SPRN_SRR1, 0 243 SPRN_SRR0, SPRN_SRR1, 0
244kvm_handler BOOKE_INTERRUPT_AP_UNAVAIL, EX_PARAMS(GEN), \ 244kvm_handler BOOKE_INTERRUPT_AP_UNAVAIL, EX_PARAMS(GEN), \
@@ -348,7 +348,7 @@ kvm_handler BOOKE_INTERRUPT_INST_STORAGE, SPRN_SRR0, SPRN_SRR1, NEED_ESR
348kvm_handler BOOKE_INTERRUPT_EXTERNAL, SPRN_SRR0, SPRN_SRR1, 0 348kvm_handler BOOKE_INTERRUPT_EXTERNAL, SPRN_SRR0, SPRN_SRR1, 0
349kvm_handler BOOKE_INTERRUPT_ALIGNMENT, \ 349kvm_handler BOOKE_INTERRUPT_ALIGNMENT, \
350 SPRN_SRR0, SPRN_SRR1, (NEED_DEAR | NEED_ESR) 350 SPRN_SRR0, SPRN_SRR1, (NEED_DEAR | NEED_ESR)
351kvm_handler BOOKE_INTERRUPT_PROGRAM, SPRN_SRR0, SPRN_SRR1, NEED_ESR 351kvm_handler BOOKE_INTERRUPT_PROGRAM, SPRN_SRR0, SPRN_SRR1, (NEED_ESR | NEED_EMU)
352kvm_handler BOOKE_INTERRUPT_FP_UNAVAIL, SPRN_SRR0, SPRN_SRR1, 0 352kvm_handler BOOKE_INTERRUPT_FP_UNAVAIL, SPRN_SRR0, SPRN_SRR1, 0
353kvm_handler BOOKE_INTERRUPT_SYSCALL, SPRN_SRR0, SPRN_SRR1, 0 353kvm_handler BOOKE_INTERRUPT_SYSCALL, SPRN_SRR0, SPRN_SRR1, 0
354kvm_handler BOOKE_INTERRUPT_AP_UNAVAIL, SPRN_SRR0, SPRN_SRR1, 0 354kvm_handler BOOKE_INTERRUPT_AP_UNAVAIL, SPRN_SRR0, SPRN_SRR1, 0