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.c114
1 files changed, 23 insertions, 91 deletions
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
index d8af889366a4..856010f9ebc9 100644
--- a/arch/sh/kernel/process_32.c
+++ b/arch/sh/kernel/process_32.c
@@ -25,17 +25,15 @@
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>
31#include <asm/system.h> 32#include <asm/system.h>
32#include <asm/ubc.h>
33#include <asm/fpu.h> 33#include <asm/fpu.h>
34#include <asm/syscalls.h> 34#include <asm/syscalls.h>
35#include <asm/watchdog.h> 35#include <asm/watchdog.h>
36 36
37int ubc_usercnt = 0;
38
39#ifdef CONFIG_32BIT 37#ifdef CONFIG_32BIT
40static void watchdog_trigger_immediate(void) 38static void watchdog_trigger_immediate(void)
41{ 39{
@@ -147,21 +145,34 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
147} 145}
148EXPORT_SYMBOL(kernel_thread); 146EXPORT_SYMBOL(kernel_thread);
149 147
148void start_thread(struct pt_regs *regs, unsigned long new_pc,
149 unsigned long new_sp)
150{
151 set_fs(USER_DS);
152
153 regs->pr = 0;
154 regs->sr = SR_FD;
155 regs->pc = new_pc;
156 regs->regs[15] = new_sp;
157
158 free_thread_xstate(current);
159}
160EXPORT_SYMBOL(start_thread);
161
150/* 162/*
151 * Free current thread data structures etc.. 163 * Free current thread data structures etc..
152 */ 164 */
153void exit_thread(void) 165void exit_thread(void)
154{ 166{
155 if (current->thread.ubc_pc) {
156 current->thread.ubc_pc = 0;
157 ubc_usercnt -= 1;
158 }
159} 167}
160 168
161void flush_thread(void) 169void flush_thread(void)
162{ 170{
163#if defined(CONFIG_SH_FPU)
164 struct task_struct *tsk = current; 171 struct task_struct *tsk = current;
172
173 flush_ptrace_hw_breakpoint(tsk);
174
175#if defined(CONFIG_SH_FPU)
165 /* Forget lazy FPU state */ 176 /* Forget lazy FPU state */
166 clear_fpu(tsk, task_pt_regs(tsk)); 177 clear_fpu(tsk, task_pt_regs(tsk));
167 clear_used_math(); 178 clear_used_math();
@@ -209,11 +220,10 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
209{ 220{
210 struct thread_info *ti = task_thread_info(p); 221 struct thread_info *ti = task_thread_info(p);
211 struct pt_regs *childregs; 222 struct pt_regs *childregs;
223
212#if defined(CONFIG_SH_DSP) 224#if defined(CONFIG_SH_DSP)
213 struct task_struct *tsk = current; 225 struct task_struct *tsk = current;
214#endif
215 226
216#if defined(CONFIG_SH_DSP)
217 if (is_dsp_enabled(tsk)) { 227 if (is_dsp_enabled(tsk)) {
218 /* We can use the __save_dsp or just copy the struct: 228 /* We can use the __save_dsp or just copy the struct:
219 * __save_dsp(p); 229 * __save_dsp(p);
@@ -244,53 +254,11 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
244 p->thread.sp = (unsigned long) childregs; 254 p->thread.sp = (unsigned long) childregs;
245 p->thread.pc = (unsigned long) ret_from_fork; 255 p->thread.pc = (unsigned long) ret_from_fork;
246 256
247 p->thread.ubc_pc = 0; 257 memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
248 258
249 return 0; 259 return 0;
250} 260}
251 261
252/* Tracing by user break controller. */
253static void ubc_set_tracing(int asid, unsigned long pc)
254{
255#if defined(CONFIG_CPU_SH4A)
256 unsigned long val;
257
258 val = (UBC_CBR_ID_INST | UBC_CBR_RW_READ | UBC_CBR_CE);
259 val |= (UBC_CBR_AIE | UBC_CBR_AIV_SET(asid));
260
261 ctrl_outl(val, UBC_CBR0);
262 ctrl_outl(pc, UBC_CAR0);
263 ctrl_outl(0x0, UBC_CAMR0);
264 ctrl_outl(0x0, UBC_CBCR);
265
266 val = (UBC_CRR_RES | UBC_CRR_PCB | UBC_CRR_BIE);
267 ctrl_outl(val, UBC_CRR0);
268
269 /* Read UBC register that we wrote last, for checking update */
270 val = ctrl_inl(UBC_CRR0);
271
272#else /* CONFIG_CPU_SH4A */
273 ctrl_outl(pc, UBC_BARA);
274
275#ifdef CONFIG_MMU
276 ctrl_outb(asid, UBC_BASRA);
277#endif
278
279 ctrl_outl(0, UBC_BAMRA);
280
281 if (current_cpu_data.type == CPU_SH7729 ||
282 current_cpu_data.type == CPU_SH7710 ||
283 current_cpu_data.type == CPU_SH7712 ||
284 current_cpu_data.type == CPU_SH7203){
285 ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
286 ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR);
287 } else {
288 ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA);
289 ctrl_outw(BRCR_PCBA, UBC_BRCR);
290 }
291#endif /* CONFIG_CPU_SH4A */
292}
293
294/* 262/*
295 * switch_to(x,y) should switch tasks from x to y. 263 * switch_to(x,y) should switch tasks from x to y.
296 * 264 *
@@ -304,7 +272,7 @@ __switch_to(struct task_struct *prev, struct task_struct *next)
304 272
305 /* we're going to use this soon, after a few expensive things */ 273 /* we're going to use this soon, after a few expensive things */
306 if (next->fpu_counter > 5) 274 if (next->fpu_counter > 5)
307 prefetch(&next_t->fpu.hard); 275 prefetch(next_t->xstate);
308 276
309#ifdef CONFIG_MMU 277#ifdef CONFIG_MMU
310 /* 278 /*
@@ -316,32 +284,13 @@ __switch_to(struct task_struct *prev, struct task_struct *next)
316 : "r" (task_thread_info(next))); 284 : "r" (task_thread_info(next)));
317#endif 285#endif
318 286
319 /* If no tasks are using the UBC, we're done */
320 if (ubc_usercnt == 0)
321 /* If no tasks are using the UBC, we're done */;
322 else if (next->thread.ubc_pc && next->mm) {
323 int asid = 0;
324#ifdef CONFIG_MMU
325 asid |= cpu_asid(smp_processor_id(), next->mm);
326#endif
327 ubc_set_tracing(asid, next->thread.ubc_pc);
328 } else {
329#if defined(CONFIG_CPU_SH4A)
330 ctrl_outl(UBC_CBR_INIT, UBC_CBR0);
331 ctrl_outl(UBC_CRR_INIT, UBC_CRR0);
332#else
333 ctrl_outw(0, UBC_BBRA);
334 ctrl_outw(0, UBC_BBRB);
335#endif
336 }
337
338 /* 287 /*
339 * If the task has used fpu the last 5 timeslices, just do a full 288 * If the task has used fpu the last 5 timeslices, just do a full
340 * restore of the math state immediately to avoid the trap; the 289 * restore of the math state immediately to avoid the trap; the
341 * chances of needing FPU soon are obviously high now 290 * chances of needing FPU soon are obviously high now
342 */ 291 */
343 if (next->fpu_counter > 5) 292 if (next->fpu_counter > 5)
344 fpu_state_restore(task_pt_regs(next)); 293 __fpu_state_restore();
345 294
346 return prev; 295 return prev;
347} 296}
@@ -434,20 +383,3 @@ unsigned long get_wchan(struct task_struct *p)
434 383
435 return pc; 384 return pc;
436} 385}
437
438asmlinkage void break_point_trap(void)
439{
440 /* Clear tracing. */
441#if defined(CONFIG_CPU_SH4A)
442 ctrl_outl(UBC_CBR_INIT, UBC_CBR0);
443 ctrl_outl(UBC_CRR_INIT, UBC_CRR0);
444#else
445 ctrl_outw(0, UBC_BBRA);
446 ctrl_outw(0, UBC_BBRB);
447 ctrl_outl(0, UBC_BRCR);
448#endif
449 current->thread.ubc_pc = 0;
450 ubc_usercnt -= 1;
451
452 force_sig(SIGTRAP, current);
453}