Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 217619
b: refs/heads/master
c: 233325b
h: refs/heads/master
i:
  217617: a2bb882
  217615: 2954566
v: v3
  • Loading branch information
Chris Metcalf committed Oct 15, 2010
1 parent 2e62598 commit d5a76fc
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a78c942df64ef4cf495fd4d8715e48501bd7f8a4
refs/heads/master: 233325b94999d4bb8df227bb39904a57509e4995
4 changes: 4 additions & 0 deletions trunk/arch/tile/include/asm/traps.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,8 @@ void do_hardwall_trap(struct pt_regs *, int fault_num);
void do_breakpoint(struct pt_regs *, int fault_num);


#ifdef __tilegx__
void gx_singlestep_handle(struct pt_regs *, int fault_num);
#endif

#endif /* _ASM_TILE_SYSCALLS_H */
7 changes: 6 additions & 1 deletion trunk/arch/tile/kernel/intvec_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -1472,7 +1472,12 @@ handle_ill:
lw r26, r24
sw r28, r26

/* Clear TIF_SINGLESTEP */
/*
* Clear TIF_SINGLESTEP to prevent recursion if we execute an ill.
* The normal non-arch flow redundantly clears TIF_SINGLESTEP, but we
* need to clear it here and can't really impose on all other arches.
* So what's another write between friends?
*/
GET_THREAD_INFO(r0)

addi r1, r0, THREAD_INFO_FLAGS_OFFSET
Expand Down
73 changes: 72 additions & 1 deletion trunk/arch/tile/kernel/single_step.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* Derived from iLib's single-stepping code.
*/

#ifndef __tilegx__ /* No support for single-step yet. */
#ifndef __tilegx__ /* Hardware support for single step unavailable. */

/* These functions are only used on the TILE platform */
#include <linux/slab.h>
Expand Down Expand Up @@ -660,4 +660,75 @@ void single_step_once(struct pt_regs *regs)
regs->pc += 8;
}

#else
#include <linux/smp.h>
#include <linux/ptrace.h>
#include <arch/spr_def.h>

static DEFINE_PER_CPU(unsigned long, ss_saved_pc);


/*
* Called directly on the occasion of an interrupt.
*
* If the process doesn't have single step set, then we use this as an
* opportunity to turn single step off.
*
* It has been mentioned that we could conditionally turn off single stepping
* on each entry into the kernel and rely on single_step_once to turn it
* on for the processes that matter (as we already do), but this
* implementation is somewhat more efficient in that we muck with registers
* once on a bum interrupt rather than on every entry into the kernel.
*
* If SINGLE_STEP_CONTROL_K has CANCELED set, then an interrupt occurred,
* so we have to run through this process again before we can say that an
* instruction has executed.
*
* swint will set CANCELED, but it's a legitimate instruction. Fortunately
* it changes the PC. If it hasn't changed, then we know that the interrupt
* wasn't generated by swint and we'll need to run this process again before
* we can say an instruction has executed.
*
* If either CANCELED == 0 or the PC's changed, we send out SIGTRAPs and get
* on with our lives.
*/

void gx_singlestep_handle(struct pt_regs *regs, int fault_num)
{
unsigned long *ss_pc = &__get_cpu_var(ss_saved_pc);
struct thread_info *info = (void *)current_thread_info();
int is_single_step = test_ti_thread_flag(info, TIF_SINGLESTEP);
unsigned long control = __insn_mfspr(SPR_SINGLE_STEP_CONTROL_K);

if (is_single_step == 0) {
__insn_mtspr(SPR_SINGLE_STEP_EN_K_K, 0);

} else if ((*ss_pc != regs->pc) ||
(!(control & SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK))) {

ptrace_notify(SIGTRAP);
control |= SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK;
control |= SPR_SINGLE_STEP_CONTROL_1__INHIBIT_MASK;
__insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control);
}
}


/*
* Called from need_singlestep. Set up the control registers and the enable
* register, then return back.
*/

void single_step_once(struct pt_regs *regs)
{
unsigned long *ss_pc = &__get_cpu_var(ss_saved_pc);
unsigned long control = __insn_mfspr(SPR_SINGLE_STEP_CONTROL_K);

*ss_pc = regs->pc;
control |= SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK;
control |= SPR_SINGLE_STEP_CONTROL_1__INHIBIT_MASK;
__insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control);
__insn_mtspr(SPR_SINGLE_STEP_EN_K_K, 1 << USER_PL);
}

#endif /* !__tilegx__ */
2 changes: 1 addition & 1 deletion trunk/arch/tile/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
address = regs->pc;
break;
case INT_UNALIGN_DATA:
#ifndef __tilegx__ /* FIXME: GX: no single-step yet */
#ifndef __tilegx__ /* Emulated support for single step debugging */
if (unaligned_fixup >= 0) {
struct single_step_state *state =
current_thread_info()->step_state;
Expand Down

0 comments on commit d5a76fc

Please sign in to comment.