This patch adds software breakpoint support for ppc. Patch
allows to insert and remove sw breakpoints using Qemu
gdbserver on ppc.

Patch use "abs" instruction as sw breakpoint instruction.
This instruction with primary opcode 31 and extended opcode 360
has been dropped from PowerISA (in v2.01) and will generate an
Emulation assistance interrupt in hypervisor when executed.
KVM also has to be updated with this to make use of sw breakpoint.

Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 target-ppc/kvm.c | 38 +++++++++++++++++++++++++++++++++++---
 1 file changed, 35 insertions(+), 3 deletions(-)

diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 9974b10..fa4b4ec 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1201,6 +1201,17 @@ static int kvmppc_handle_dcr_write(CPUPPCState *env, 
uint32_t dcrn, uint32_t dat
     return 0;
 }
 
+static int kvmppc_handle_debug(CPUState *cs, struct kvm_debug_exit_arch 
*arch_info)
+{
+       int ret = -1;
+
+       if (kvm_find_sw_breakpoint(cs, arch_info->address)) { 
+               ret = EXCP_DEBUG;
+       }
+
+       return ret;
+}
+
 int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
 {
     PowerPCCPU *cpu = POWERPC_CPU(cs);
@@ -1240,7 +1251,10 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run 
*run)
         watchdog_perform_action();
         ret = 0;
         break;
-
+    case KVM_EXIT_DEBUG:
+        DPRINTF("handle debug exit pc = 0x%lx\n", run->debug.arch.address);
+        ret = kvmppc_handle_debug(cs, &run->debug.arch);
+        break;
     default:
         fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
         ret = -1;
@@ -1901,14 +1915,29 @@ void kvm_arch_init_irq_routing(KVMState *s)
 {
 }
 
+static const uint8_t dbg_int[] = { 0x7c, 0x00, 0x02, 0xd0};
 int kvm_arch_insert_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *bp)
 {
-    return -EINVAL;
+       if( cpu_memory_rw_debug(cpu, bp->pc, (uint8_t *)&bp->saved_insn, 
sizeof(dbg_int), 0) ||
+           cpu_memory_rw_debug(cpu, bp->pc, (uint8_t *)dbg_int, 
sizeof(dbg_int), 1) ){
+               return -EINVAL;
+       }
+       return 0;
 }
 
 int kvm_arch_remove_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *bp)
 {
-    return -EINVAL;
+       uint8_t tmp[4];
+
+       if (cpu_memory_rw_debug(cpu, bp->pc, tmp, sizeof(dbg_int), 0)) {
+               return -EINVAL;
+       } else if (memcmp(tmp, dbg_int, sizeof(dbg_int))) {
+               return -EINVAL;
+       } else if (cpu_memory_rw_debug(cpu, bp->pc, (uint8_t *)&bp->saved_insn, 
sizeof(dbg_int), 1)) {
+               return -EINVAL;
+       }
+
+       return 0;
 }
 
 int kvm_arch_insert_hw_breakpoint(target_ulong addr, target_ulong len, int 
type)
@@ -1927,6 +1956,9 @@ void kvm_arch_remove_all_hw_breakpoints(void)
 
 void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg)
 {
+       if (kvm_sw_breakpoints_active(cpu)) {
+               dbg->control |= KVM_GUESTDBG_USE_SW_BP;
+       }
 }
 
 struct kvm_get_htab_buf {
-- 
1.8.3.1


Reply via email to