From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57081) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X6cOW-0002nT-SX for qemu-devel@nongnu.org; Mon, 14 Jul 2014 05:18:07 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1X6cOQ-0001Rz-Jp for qemu-devel@nongnu.org; Mon, 14 Jul 2014 05:18:00 -0400 From: Bharat Bhushan Date: Mon, 14 Jul 2014 14:45:38 +0530 Message-ID: <1405329338-10206-5-git-send-email-Bharat.Bhushan@freescale.com> In-Reply-To: <1405329338-10206-1-git-send-email-Bharat.Bhushan@freescale.com> References: <1405329338-10206-1-git-send-email-Bharat.Bhushan@freescale.com> MIME-Version: 1.0 Content-Type: text/plain Subject: [Qemu-devel] [PATCH 3/4 v8] ppc: Add software breakpoint support List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: agraf@suse.de Cc: Bharat Bhushan , maddy@linux.vnet.ibm.com, qemu-ppc@nongnu.org, qemu-devel@nongnu.org This patch allow insert/remove software breakpoint. When QEMU is not able to handle debug exception then we inject program exception to guest because for software breakpoint QEMU uses a ehpriv-1 instruction; So there cannot be any reason that we are in qemu with exit reason KVM_EXIT_DEBUG for guest set debug exception, only possibility is guest executed ehpriv-1 privilege instruction and that's why we are injecting program exception. Signed-off-by: Bharat Bhushan --- v7->v8 - Decrement nip by 4 before calling ppc_cpu_do_interrupt() as pointed by "Madhavan Srinivasan" - Also added missing cpu_sync() target-ppc/kvm.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 79 insertions(+), 14 deletions(-) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index e00a20f..0f2e8e4 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -1275,6 +1275,75 @@ static int kvmppc_handle_dcr_write(CPUPPCState *env, uint32_t dcrn, uint32_t dat return 0; } +int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) +{ + /* Mixed endian case is not handled */ + uint32_t sc = debug_inst_opcode; + + if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, + sizeof(sc), 0) || + cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&sc, sizeof(sc), 1)) { + return -EINVAL; + } + + return 0; +} + +int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) +{ + uint32_t sc; + + if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&sc, sizeof(sc), 0) || + sc != debug_inst_opcode || + cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, + sizeof(sc), 1)) { + return -EINVAL; + } + + return 0; +} + +void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg) +{ + /* Software Breakpoint updates */ + if (kvm_sw_breakpoints_active(cs)) { + dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; + } +} + +static int kvm_handle_debug(PowerPCCPU *cpu, struct kvm_run *run) +{ + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; + struct kvm_debug_exit_arch *arch_info = &run->debug.arch; + int handle = 0; + + if (kvm_find_sw_breakpoint(cs, arch_info->address)) { + handle = 1; + } else { + /* QEMU is not able to handle debug exception, so inject + * program exception to guest; + * Yes program exception NOT debug exception !! + * For software breakpoint QEMU uses a ehpriv-1 instruction; + * So there cannot be any reason that we are here for guest + * set debug exception, only possibility is guest executed a + * privilege instruction and that's why we are injecting + * program exception. + */ + + cpu_synchronize_state(cs); + /* env->nip is PC, so increment this by 4 to use + * ppc_cpu_do_interrupt(), which set srr0 = env->nip - 4. + */ + env->nip += 4; + cs->exception_index = POWERPC_EXCP_PROGRAM; + env->error_code = POWERPC_EXCP_INVAL; + ppc_cpu_do_interrupt(cs); + } + + return handle; +} + int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) { PowerPCCPU *cpu = POWERPC_CPU(cs); @@ -1315,6 +1384,16 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) ret = 0; break; + case KVM_EXIT_DEBUG: + DPRINTF("handle debug exception\n"); + if (kvm_handle_debug(cpu, run)) { + ret = EXCP_DEBUG; + break; + } + /* re-enter, this exception was guest-internal */ + ret = 0; + break; + default: fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason); ret = -1; @@ -2003,16 +2082,6 @@ void kvm_arch_init_irq_routing(KVMState *s) { } -int kvm_arch_insert_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *bp) -{ - return -EINVAL; -} - -int kvm_arch_remove_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *bp) -{ - return -EINVAL; -} - int kvm_arch_insert_hw_breakpoint(target_ulong addr, target_ulong len, int type) { return -EINVAL; @@ -2027,10 +2096,6 @@ void kvm_arch_remove_all_hw_breakpoints(void) { } -void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg) -{ -} - struct kvm_get_htab_buf { struct kvm_get_htab_header header; /* -- 1.9.3