summaryrefslogtreecommitdiffstats
path: root/arch/tile
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2011-02-28 13:08:32 -0500
committerChris Metcalf <cmetcalf@tilera.com>2011-03-01 16:19:58 -0500
commit04f7a3f12e10032ee3d44df1a509dbf5b2001fce (patch)
tree2e9281f10f1dffc9fc6b470e823b02bb720ecc4c /arch/tile
parent2cb82400719e085a3c226cf7cce8950208f09a06 (diff)
arch/tile: bug fix: exec'ed task thought it was still single-stepping
To handle single-step, tile mmap's a page of memory in the process space for each thread and uses it to construct a version of the instruction that we want to single step. If the process exec's, though, we lose that mapping, and the kernel needs to be aware that it will need to recreate it if the exec'ed process than tries to single-step as well. Also correct some int32_t to s32 for better kernel style. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Diffstat (limited to 'arch/tile')
-rw-r--r--arch/tile/include/asm/ptrace.h3
-rw-r--r--arch/tile/kernel/process.c4
-rw-r--r--arch/tile/kernel/single_step.c21
3 files changed, 26 insertions, 2 deletions
diff --git a/arch/tile/include/asm/ptrace.h b/arch/tile/include/asm/ptrace.h
index ac6d343129d..6be2246e015 100644
--- a/arch/tile/include/asm/ptrace.h
+++ b/arch/tile/include/asm/ptrace.h
@@ -141,6 +141,9 @@ struct single_step_state {
/* Single-step the instruction at regs->pc */
extern void single_step_once(struct pt_regs *regs);
+/* Clean up after execve(). */
+extern void single_step_execve(void);
+
struct task_struct;
extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c
index e90eb53173b..5db8b5b63ce 100644
--- a/arch/tile/kernel/process.c
+++ b/arch/tile/kernel/process.c
@@ -574,6 +574,8 @@ SYSCALL_DEFINE4(execve, const char __user *, path,
goto out;
error = do_execve(filename, argv, envp, regs);
putname(filename);
+ if (error == 0)
+ single_step_execve();
out:
return error;
}
@@ -593,6 +595,8 @@ long compat_sys_execve(const char __user *path,
goto out;
error = compat_do_execve(filename, argv, envp, regs);
putname(filename);
+ if (error == 0)
+ single_step_execve();
out:
return error;
}
diff --git a/arch/tile/kernel/single_step.c b/arch/tile/kernel/single_step.c
index 1eb3b39e36c..84a729e06ec 100644
--- a/arch/tile/kernel/single_step.c
+++ b/arch/tile/kernel/single_step.c
@@ -56,7 +56,7 @@ enum mem_op {
MEMOP_STORE_POSTINCR
};
-static inline tile_bundle_bits set_BrOff_X1(tile_bundle_bits n, int32_t offset)
+static inline tile_bundle_bits set_BrOff_X1(tile_bundle_bits n, s32 offset)
{
tile_bundle_bits result;
@@ -254,6 +254,18 @@ P("\n");
return bundle;
}
+/*
+ * Called after execve() has started the new image. This allows us
+ * to reset the info state. Note that the the mmap'ed memory, if there
+ * was any, has already been unmapped by the exec.
+ */
+void single_step_execve(void)
+{
+ struct thread_info *ti = current_thread_info();
+ kfree(ti->step_state);
+ ti->step_state = NULL;
+}
+
/**
* single_step_once() - entry point when single stepping has been triggered.
* @regs: The machine register state
@@ -373,7 +385,7 @@ void single_step_once(struct pt_regs *regs)
/* branches */
case BRANCH_OPCODE_X1:
{
- int32_t offset = signExtend17(get_BrOff_X1(bundle));
+ s32 offset = signExtend17(get_BrOff_X1(bundle));
/*
* For branches, we use a rewriting trick to let the
@@ -731,4 +743,9 @@ void single_step_once(struct pt_regs *regs)
__insn_mtspr(SPR_SINGLE_STEP_EN_K_K, 1 << USER_PL);
}
+void single_step_execve(void)
+{
+ /* Nothing */
+}
+
#endif /* !__tilegx__ */