aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/process_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/process_32.c')
-rw-r--r--arch/sh/kernel/process_32.c94
1 files changed, 6 insertions, 88 deletions
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
index 0673c4746be3..4a2c866f9773 100644
--- a/arch/sh/kernel/process_32.c
+++ b/arch/sh/kernel/process_32.c
@@ -25,6 +25,7 @@
25#include <linux/fs.h> 25#include <linux/fs.h>
26#include <linux/ftrace.h> 26#include <linux/ftrace.h>
27#include <linux/preempt.h> 27#include <linux/preempt.h>
28#include <linux/hw_breakpoint.h>
28#include <asm/uaccess.h> 29#include <asm/uaccess.h>
29#include <asm/mmu_context.h> 30#include <asm/mmu_context.h>
30#include <asm/pgalloc.h> 31#include <asm/pgalloc.h>
@@ -34,8 +35,6 @@
34#include <asm/syscalls.h> 35#include <asm/syscalls.h>
35#include <asm/watchdog.h> 36#include <asm/watchdog.h>
36 37
37int ubc_usercnt = 0;
38
39#ifdef CONFIG_32BIT 38#ifdef CONFIG_32BIT
40static void watchdog_trigger_immediate(void) 39static void watchdog_trigger_immediate(void)
41{ 40{
@@ -148,16 +147,15 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
148 */ 147 */
149void exit_thread(void) 148void exit_thread(void)
150{ 149{
151 if (current->thread.ubc_pc) {
152 current->thread.ubc_pc = 0;
153 ubc_usercnt -= 1;
154 }
155} 150}
156 151
157void flush_thread(void) 152void flush_thread(void)
158{ 153{
159#if defined(CONFIG_SH_FPU)
160 struct task_struct *tsk = current; 154 struct task_struct *tsk = current;
155
156 flush_ptrace_hw_breakpoint(tsk);
157
158#if defined(CONFIG_SH_FPU)
161 /* Forget lazy FPU state */ 159 /* Forget lazy FPU state */
162 clear_fpu(tsk, task_pt_regs(tsk)); 160 clear_fpu(tsk, task_pt_regs(tsk));
163 clear_used_math(); 161 clear_used_math();
@@ -195,9 +193,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
195{ 193{
196 struct thread_info *ti = task_thread_info(p); 194 struct thread_info *ti = task_thread_info(p);
197 struct pt_regs *childregs; 195 struct pt_regs *childregs;
198#if defined(CONFIG_SH_FPU) || defined(CONFIG_SH_DSP)
199 struct task_struct *tsk = current; 196 struct task_struct *tsk = current;
200#endif
201 197
202#if defined(CONFIG_SH_FPU) 198#if defined(CONFIG_SH_FPU)
203 unlazy_fpu(tsk, regs); 199 unlazy_fpu(tsk, regs);
@@ -234,53 +230,11 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
234 p->thread.sp = (unsigned long) childregs; 230 p->thread.sp = (unsigned long) childregs;
235 p->thread.pc = (unsigned long) ret_from_fork; 231 p->thread.pc = (unsigned long) ret_from_fork;
236 232
237 p->thread.ubc_pc = 0; 233 memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
238 234
239 return 0; 235 return 0;
240} 236}
241 237
242/* Tracing by user break controller. */
243static void ubc_set_tracing(int asid, unsigned long pc)
244{
245#if defined(CONFIG_CPU_SH4A)
246 unsigned long val;
247
248 val = (UBC_CBR_ID_INST | UBC_CBR_RW_READ | UBC_CBR_CE);
249 val |= (UBC_CBR_AIE | UBC_CBR_AIV_SET(asid));
250
251 ctrl_outl(val, UBC_CBR0);
252 ctrl_outl(pc, UBC_CAR0);
253 ctrl_outl(0x0, UBC_CAMR0);
254 ctrl_outl(0x0, UBC_CBCR);
255
256 val = (UBC_CRR_RES | UBC_CRR_PCB | UBC_CRR_BIE);
257 ctrl_outl(val, UBC_CRR0);
258
259 /* Read UBC register that we wrote last, for checking update */
260 val = ctrl_inl(UBC_CRR0);
261
262#else /* CONFIG_CPU_SH4A */
263 ctrl_outl(pc, UBC_BARA);
264
265#ifdef CONFIG_MMU
266 ctrl_outb(asid, UBC_BASRA);
267#endif
268
269 ctrl_outl(0, UBC_BAMRA);
270
271 if (current_cpu_data.type == CPU_SH7729 ||
272 current_cpu_data.type == CPU_SH7710 ||
273 current_cpu_data.type == CPU_SH7712 ||
274 current_cpu_data.type == CPU_SH7203){
275 ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
276 ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR);
277 } else {
278 ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA);
279 ctrl_outw(BRCR_PCBA, UBC_BRCR);
280 }
281#endif /* CONFIG_CPU_SH4A */
282}
283
284/* 238/*
285 * switch_to(x,y) should switch tasks from x to y. 239 * switch_to(x,y) should switch tasks from x to y.
286 * 240 *
@@ -302,25 +256,6 @@ __switch_to(struct task_struct *prev, struct task_struct *next)
302 : "r" (task_thread_info(next))); 256 : "r" (task_thread_info(next)));
303#endif 257#endif
304 258
305 /* If no tasks are using the UBC, we're done */
306 if (ubc_usercnt == 0)
307 /* If no tasks are using the UBC, we're done */;
308 else if (next->thread.ubc_pc && next->mm) {
309 int asid = 0;
310#ifdef CONFIG_MMU
311 asid |= cpu_asid(smp_processor_id(), next->mm);
312#endif
313 ubc_set_tracing(asid, next->thread.ubc_pc);
314 } else {
315#if defined(CONFIG_CPU_SH4A)
316 ctrl_outl(UBC_CBR_INIT, UBC_CBR0);
317 ctrl_outl(UBC_CRR_INIT, UBC_CRR0);
318#else
319 ctrl_outw(0, UBC_BBRA);
320 ctrl_outw(0, UBC_BBRB);
321#endif
322 }
323
324 return prev; 259 return prev;
325} 260}
326 261
@@ -412,20 +347,3 @@ unsigned long get_wchan(struct task_struct *p)
412 347
413 return pc; 348 return pc;
414} 349}
415
416asmlinkage void break_point_trap(void)
417{
418 /* Clear tracing. */
419#if defined(CONFIG_CPU_SH4A)
420 ctrl_outl(UBC_CBR_INIT, UBC_CBR0);
421 ctrl_outl(UBC_CRR_INIT, UBC_CRR0);
422#else
423 ctrl_outw(0, UBC_BBRA);
424 ctrl_outw(0, UBC_BBRB);
425 ctrl_outl(0, UBC_BRCR);
426#endif
427 current->thread.ubc_pc = 0;
428 ubc_usercnt -= 1;
429
430 force_sig(SIGTRAP, current);
431}