diff mbox

qemu/target-ppc: software breakpoint support

Message ID 1402780107-28864-1-git-send-email-maddy@linux.vnet.ibm.com
State New
Headers show

Commit Message

maddy June 14, 2014, 9:08 p.m. UTC
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 <maddy@linux.vnet.ibm.com>
---
 target-ppc/kvm.c | 38 +++++++++++++++++++++++++++++++++++---
 1 file changed, 35 insertions(+), 3 deletions(-)

Comments

Bharat Bhushan June 16, 2014, 9:52 a.m. UTC | #1
> -----Original Message-----
> From: qemu-ppc-bounces+bharat.bhushan=freescale.com@nongnu.org [mailto:qemu-ppc-
> bounces+bharat.bhushan=freescale.com@nongnu.org] On Behalf Of Madhavan
> Srinivasan
> Sent: Sunday, June 15, 2014 2:38 AM
> To: agraf@suse.de; paulus@samba.org
> Cc: Madhavan Srinivasan; qemu-ppc@nongnu.org; qemu-devel@nongnu.org
> Subject: [Qemu-ppc] [PATCH] qemu/target-ppc: software breakpoint support
> 
> 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.

There are already a patch "ppc debug: Add debug stub support" in review which implements software breakpoint
In addition this patch also implements h/w breakpoints/watchpoints for BOOKE. But I actually do not know how h/w breakpoints works on BOOK3S and you can help me figuring out what can be shared between booke and book3s.

> 
> Signed-off-by: Madhavan Srinivasan <maddy@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};

This should not be hardcoded but we should get this from KVM. Please refer to patch "ppc debug: Add debug stub support" to know how to get debug instruction.

Thanks
-Bharat

>  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
>
maddy June 17, 2014, 8:08 a.m. UTC | #2
On Monday 16 June 2014 03:22 PM, Bharat.Bhushan@freescale.com wrote:
> 
> 
>> -----Original Message-----
>> From: qemu-ppc-bounces+bharat.bhushan=freescale.com@nongnu.org [mailto:qemu-ppc-
>> bounces+bharat.bhushan=freescale.com@nongnu.org] On Behalf Of Madhavan
>> Srinivasan
>> Sent: Sunday, June 15, 2014 2:38 AM
>> To: agraf@suse.de; paulus@samba.org
>> Cc: Madhavan Srinivasan; qemu-ppc@nongnu.org; qemu-devel@nongnu.org
>> Subject: [Qemu-ppc] [PATCH] qemu/target-ppc: software breakpoint support
>>
>> 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.
> 
> There are already a patch "ppc debug: Add debug stub support" in review which implements software breakpoint

My bad. Should have checked for it. Will look at the patchset posted.

> In addition this patch also implements h/w breakpoints/watchpoints for BOOKE. But I actually do not know how h/w breakpoints works on BOOK3S and you can help me figuring out what can be shared between booke and book3s.
> 
Sure will update you on this soon.

>>
>> Signed-off-by: Madhavan Srinivasan <maddy@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};
> 
> This should not be hardcoded but we should get this from KVM. Please refer to patch "ppc debug: Add debug stub support" to know how to get debug instruction.
> 
Sure Will do

> Thanks
> -Bharat
> 

Thanks for review.
Regards
Maddy

>>  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
>>
>
diff mbox

Patch

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 {