Re: [RFC Patch 2/6] Introduce PPC64 specific Hardware Breakpointinterfaces

2009-05-21 Thread K.Prasad
On Mon, May 18, 2009 at 12:30:41PM -0400, Alan Stern wrote:
 On Mon, 18 May 2009, K.Prasad wrote:
 
  +int __kprobes hw_breakpoint_handler(struct die_args *args)
  +{
  +   int rc = NOTIFY_STOP;
  +   struct hw_breakpoint *bp;
  +   struct pt_regs *regs = args-regs;
  +   unsigned long dar;
  +   int cpu, stepped, is_kernel;
  +
  +   /* Disable breakpoints during exception handling */
  +   set_dabr(0);
  +
  +   dar = regs-dar  (~HW_BREAKPOINT_ALIGN);
  +   is_kernel = (dar = TASK_SIZE) ? 1 : 0;
 
 is_kernel_addr() ?
 

Ok.
   
   Shouldn't this test hbp_kernel_pos instead?
   
  
  Testing hbp_kernel_pos should be sufficient for PPC64 with just one
  breakpoint register. However the above code is more extensible to other
  PowerPC implementations which have more than one breakpoint register.
 
 Then maybe you don't want to test this at all.  Just compare the dar 
 value with each of the breakpoint addresses.  That's more like what the 
 x86 code does.
 
 Alan Stern


Comparing the DAR register value with each breakpoint address is
required to determine if the exception is the cause of a breakpoint hit
and I've added the code to hw_breakpoint_handler(). With this check in
place, I find that using hbp_kernel_pos to determine kernel/user space
origin is much easier (as you suggested) and the code is modified
accordingly.

Please find the changes in the new patchset being sent.

Thanks,
K.Prasad

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [RFC Patch 2/6] Introduce PPC64 specific Hardware Breakpointinterfaces

2009-05-18 Thread Alan Stern
On Mon, 18 May 2009, K.Prasad wrote:

 +int __kprobes hw_breakpoint_handler(struct die_args *args)
 +{
 + int rc = NOTIFY_STOP;
 + struct hw_breakpoint *bp;
 + struct pt_regs *regs = args-regs;
 + unsigned long dar;
 + int cpu, stepped, is_kernel;
 +
 + /* Disable breakpoints during exception handling */
 + set_dabr(0);
 +
 + dar = regs-dar  (~HW_BREAKPOINT_ALIGN);
 + is_kernel = (dar = TASK_SIZE) ? 1 : 0;

is_kernel_addr() ?

   
   Ok.
  
  Shouldn't this test hbp_kernel_pos instead?
  
 
 Testing hbp_kernel_pos should be sufficient for PPC64 with just one
 breakpoint register. However the above code is more extensible to other
 PowerPC implementations which have more than one breakpoint register.

Then maybe you don't want to test this at all.  Just compare the dar 
value with each of the breakpoint addresses.  That's more like what the 
x86 code does.

Alan Stern

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [RFC Patch 2/6] Introduce PPC64 specific Hardware Breakpointinterfaces

2009-05-14 Thread K.Prasad
On Fri, May 15, 2009 at 12:50:11AM +1000, Michael Ellerman wrote:
 On Thu, 2009-05-14 at 19:14 +0530, K.Prasad wrote:
  plain text document attachment (ppc64_arch_hwbkpt_implementation_02)
  Introduce PPC64 implementation for the generic hardware breakpoint 
  interfaces
  defined in kernel/hw_breakpoint.c. Enable the HAVE_HW_BREAKPOINT flag and 
  the
  Makefile.
 
 Hi, some comments inline ...
 


Thanks for reviewing the code.
 
  Index: linux-2.6-tip.hbkpt/arch/powerpc/kernel/hw_breakpoint.c
  ===
  --- /dev/null
  +++ linux-2.6-tip.hbkpt/arch/powerpc/kernel/hw_breakpoint.c
  @@ -0,0 +1,281 @@
  +/*
  + * This program is free software; you can redistribute it and/or modify
  + * it under the terms of the GNU General Public License as published by
  + * the Free Software Foundation; either version 2 of the License, or
  + * (at your option) any later version.
  + *
  + * This program is distributed in the hope that it will be useful,
  + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  + * GNU General Public License for more details.
  + *
  + * You should have received a copy of the GNU General Public License
  + * along with this program; if not, write to the Free Software
  + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 
  USA.
  + *
  + * Copyright (C) 2009 IBM Corporation
  + */
 
 Don't use (C), either use a proper ©, or just skip it. I don't know
 why :)
 

Ok.

  +/*
  + * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,
  + * using the CPU's debug registers.
  + */
 
 This comment would normally go at the top of the file.
 

Ok.

  +
  +#include linux/notifier.h
  +#include linux/kallsyms.h
  +#include linux/kprobes.h
  +#include linux/percpu.h
  +#include linux/kernel.h
  +#include linux/module.h
  +#include linux/sched.h
  +#include linux/init.h
  +#include linux/smp.h
  +
  +#include asm/hw_breakpoint.h
  +#include asm/processor.h
  +#include asm/sstep.h
  +
  +/* Store the kernel-space breakpoint address value */
  +static unsigned long kdabr;
  +
  +/*
  + * Temporarily stores address for DABR before it is written by the
  + * single-step handler routine
  + */
  +static DEFINE_PER_CPU(unsigned long, dabr_data);
 
 How does this relate to the existing current_dabr per-cpu variable?
 

The present infrastructure assumes that kernel-space (through xmon and
KGDB) and user-space requests happen at mutually exclusive times.

current_dabr in arch/powerpc/kernel/process.c stores the value of DABR
as requested by the current process and helps initiate a set_dabr() call
if the new incoming process's DABR value is different (when neither of
them use DABR, the values are 0, hence no set_dabr() call).

The per-cpu 'dabr_data' seen above is used to store the value of DABR
temporarily between a HW Breakpoint exception handler
hw_breakpoint_handler() (where the breakpoint exception might be
temporarily disabled if emulate_step() failed) and a single-step
exception handler single_step_dabr_instruction() in which the DABR value
is restored from per-cpu 'dabr_data'.

This is required because PowerPC triggers DABR match exception before
execution of the causative instruction (such as load/store) and if the
DABR value remains enabled, the system will enter into an infinite loop.

  +void arch_update_kernel_hw_breakpoint(void *unused)
  +{
  +   struct hw_breakpoint *bp;
  +
  +   /* Check if there is nothing to update */
  +   if (hbp_kernel_pos == HBP_NUM)
  +   return;
 
 Should that be hbp_kernel_pos = HBP_NUM, you're checking array bounds
 right?
 

In short, no. If hbp_kernel_pos  HBP_NUM it is only indicative of erroneous
code and not a condition that the system could enter.

To explain 'hbp_kernel_pos' further, it is that variable which points to
the last numbered debug register occupied by the kernel (which is more
meaningful on a processor having more than one debug register). 

In the above code, in arch_update_kernel_hw_breakpoint()
hbp_kernel_pos == HBP_NUM condition would be satisfied when
invoked from load_debug_registers() at initialisation time (kernel
requests are serviced starting from highest numbered register).

Having said that, I find that I've missed invoking
load_debug_registers() [a part of kernel/hw_breakpoint.c] in
start_secondary(). Thanks for raising this question which helped me
identify the missing invocation, I will add the same.

  +   bp = hbp_kernel[hbp_kernel_pos];
  +   if (bp == NULL)
  +   kdabr = 0;
  +   else
  +   kdabr = bp-info.address | bp-info.type | DABR_TRANSLATION;
  +   set_dabr(kdabr);
  +}
  +
  +/*
  + * Install the thread breakpoints in their debug registers.
  + */
  +void arch_install_thread_hw_breakpoint(struct task_struct *tsk)
  +{
  +   set_dabr(tsk-thread.dabr);
 
 Can we avoid setting this value if it's not necessary? It might 

Re: [RFC Patch 2/6] Introduce PPC64 specific Hardware Breakpointinterfaces

2009-05-14 Thread Alan Stern
On Fri, 15 May 2009, K.Prasad wrote:

 I see that you're referring to this code in __switch_to() :
 if (unlikely(__get_cpu_var(current_dabr) != new-thread.dabr))
 set_dabr(new-thread.dabr);
 
 arch_install_thread_hw_breakpoint()--switch_to_thread_hw_breakpoint()
 --__switch_to() implementation is also similar.
 
 In __switch_to(),
 if (unlikely(test_tsk_thread_flag(new, TIF_DEBUG)))
 switch_to_thread_hw_breakpoint(new);
 
 happens only when TIF_DEBUG flag is set. This flag is cleared when the
 process unregisters any breakpoints it had requested earlier. So, the
 set_dabr() call is avoided for processes not using the debug register.

In the x86 code, shouldn't arch_update_user_hw_breakpoint set or clear
TIF_DEBUG, depending on whether or not there are any user breakpoints
remaining?

   +int __kprobes hw_breakpoint_handler(struct die_args *args)
   +{
   + int rc = NOTIFY_STOP;
   + struct hw_breakpoint *bp;
   + struct pt_regs *regs = args-regs;
   + unsigned long dar;
   + int cpu, stepped, is_kernel;
   +
   + /* Disable breakpoints during exception handling */
   + set_dabr(0);
   +
   + dar = regs-dar  (~HW_BREAKPOINT_ALIGN);
   + is_kernel = (dar = TASK_SIZE) ? 1 : 0;
  
  is_kernel_addr() ?
  
 
 Ok.

Shouldn't this test hbp_kernel_pos instead?

   + if (is_kernel)
   + bp = hbp_kernel[0];
   + else {
   + bp = current-thread.hbp[0];
   + /* Lazy debug register switching */
   + if (!bp)
   + return rc;

Shouldn't this test be moved outside the if statement, as in the x86 
code?

Alan Stern

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev