Merge branches 'sh/xstate', 'sh/hw-breakpoints' and 'sh/stable-updates'
authorPaul Mundt <lethal@linux-sh.org>
Wed, 13 Jan 2010 04:02:55 +0000 (13:02 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Wed, 13 Jan 2010 04:02:55 +0000 (13:02 +0900)
1  2  3  4 
arch/sh/Kconfig
arch/sh/include/asm/processor_32.h
arch/sh/include/asm/system.h
arch/sh/kernel/Makefile
arch/sh/kernel/cpu/init.c
arch/sh/kernel/process_32.c
arch/sh/kernel/ptrace_32.c
arch/sh/kernel/traps_32.c

diff --cc arch/sh/Kconfig
Simple merge
@@@@@ -100,21 -104,21 -101,18 -100,21 +105,18 @@@@@ struct thread_struct 
        unsigned long sp;
        unsigned long pc;
    
-- -    /* Hardware debugging registers */
-- -    unsigned long ubc_pc;
-  -
-  -    /* floating point info */
-  -    union sh_fpu_union fpu;
++ +    /* Save middle states of ptrace breakpoints */
++ +    struct perf_event       *ptrace_bps[HBP_NUM];
    
  -     /* floating point info */
  -     union sh_fpu_union fpu;
  - 
    #ifdef CONFIG_SH_DSP
        /* Dsp status information */
        struct sh_dsp_struct dsp_status;
    #endif
-  -};
  + 
-  -/* Count of active tasks with UBC settings */
-  -extern int ubc_usercnt;
+ ++    /* Extended processor state */
+ ++    union thread_xstate *xstate;
+  +};
    
 -  /* Count of active tasks with UBC settings */
 -  extern int ubc_usercnt;
 -  
    #define INIT_THREAD  {                                              \
        .sp = sizeof(init_stack) + (long) &init_stack,          \
    }
Simple merge
Simple merge
    #include <asm/elf.h>
    #include <asm/io.h>
    #include <asm/smp.h>
-- -#ifdef CONFIG_SUPERH32
-- -#include <asm/ubc.h>
 -  #endif
+  +
+ ++#ifdef CONFIG_SH_FPU
+ ++#define cpu_has_fpu 1
+ ++#else
+ ++#define cpu_has_fpu 0
+ ++#endif
+ ++
+ ++#ifdef CONFIG_SH_DSP
+ ++#define cpu_has_dsp 1
+ ++#else
+ ++#define cpu_has_dsp 0
  + #endif
  + 
    /*
     * Generic wrapper for command line arguments to disable on-chip
     * peripherals (nofpu, nodsp, and so forth).
Simple merge
@@@@@ -63,16 -63,16 -64,59 -63,16 +64,59 @@@@@ static inline int put_stack_long(struc
        return 0;
    }
    
-- -void user_enable_single_step(struct task_struct *child)
++ +void ptrace_triggered(struct perf_event *bp, int nmi,
++ +                  struct perf_sample_data *data, struct pt_regs *regs)
 +  {
-  -    /* Next scheduling will set up UBC */
-  -    if (child->thread.ubc_pc == 0)
-  -            ubc_usercnt += 1;
++ +    struct perf_event_attr attr;
++ +
++ +    /*
++ +     * Disable the breakpoint request here since ptrace has defined a
++ +     * one-shot behaviour for breakpoint exceptions.
++ +     */
++ +    attr = bp->attr;
++ +    attr.disabled = true;
++ +    modify_user_hw_breakpoint(bp, &attr);
++ +}
++ +
++ +static int set_single_step(struct task_struct *tsk, unsigned long addr)
+  +{
 -      /* Next scheduling will set up UBC */
 -      if (child->thread.ubc_pc == 0)
 -              ubc_usercnt += 1;
++ +    struct thread_struct *thread = &tsk->thread;
++ +    struct perf_event *bp;
++ +    struct perf_event_attr attr;
++ +
++ +    bp = thread->ptrace_bps[0];
++ +    if (!bp) {
++ +            hw_breakpoint_init(&attr);
++ +
++ +            attr.bp_addr = addr;
++ +            attr.bp_len = HW_BREAKPOINT_LEN_2;
++ +            attr.bp_type = HW_BREAKPOINT_R;
+  +
 -      child->thread.ubc_pc = get_stack_long(child,
 -                              offsetof(struct pt_regs, pc));
++ +            bp = register_user_hw_breakpoint(&attr, ptrace_triggered, tsk);
++ +            if (IS_ERR(bp))
++ +                    return PTR_ERR(bp);
++ +
++ +            thread->ptrace_bps[0] = bp;
++ +    } else {
++ +            int err;
++ +
++ +            attr = bp->attr;
++ +            attr.bp_addr = addr;
++ +            err = modify_user_hw_breakpoint(bp, &attr);
++ +            if (unlikely(err))
++ +                    return err;
++ +    }
++ +
++ +    return 0;
++ +}
 +  
-  -    child->thread.ubc_pc = get_stack_long(child,
-  -                            offsetof(struct pt_regs, pc));
++ +void user_enable_single_step(struct task_struct *child)
++ +{
++ +    unsigned long pc = get_stack_long(child, offsetof(struct pt_regs, pc));
    
        set_tsk_thread_flag(child, TIF_SINGLESTEP);
++ +
++ +    set_single_step(child, pc);
    }
    
    void user_disable_single_step(struct task_struct *child)
@@@@@ -846,12 -846,12 -956,9 -956,9 +846,12 @@@@@ void __init trap_init(void
    #endif
    
    #ifdef TRAP_UBC
-- -    set_exception_table_vec(TRAP_UBC, break_point_trap);
++ +    set_exception_table_vec(TRAP_UBC, breakpoint_trap_handler);
    #endif
    
  ++    /* Save off the BIOS VBR, if there is one */
  ++    sh_bios_vbr_init();
  ++
        /* Setup VBR for boot cpu */
        per_cpu_trap_init();
    }