aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/process.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-02-04 03:10:01 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-03-20 04:11:36 -0500
commit314ef6859750b6539eac48d78059bb7986f29cb1 (patch)
tree26c7da386349c1cf377225356e1012ae62da6f07 /arch/sparc64/kernel/process.c
parentffe483d55229fadbaf4cc7316d47024a24ecd1a2 (diff)
[SPARC64]: Refine register window trap handling.
When saving and restoing trap state, do the window spill/fill handling inline so that we never trap deeper than 2 trap levels. This is important for chips like Niagara. The window fixup code is massively simplified, and many more improvements are now possible. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/process.c')
-rw-r--r--arch/sparc64/kernel/process.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 26548fc604b6..803eea4dc4ff 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -541,6 +541,18 @@ void synchronize_user_stack(void)
541 } 541 }
542} 542}
543 543
544static void stack_unaligned(unsigned long sp)
545{
546 siginfo_t info;
547
548 info.si_signo = SIGBUS;
549 info.si_errno = 0;
550 info.si_code = BUS_ADRALN;
551 info.si_addr = (void __user *) sp;
552 info.si_trapno = 0;
553 force_sig_info(SIGBUS, &info, current);
554}
555
544void fault_in_user_windows(void) 556void fault_in_user_windows(void)
545{ 557{
546 struct thread_info *t = current_thread_info(); 558 struct thread_info *t = current_thread_info();
@@ -556,13 +568,17 @@ void fault_in_user_windows(void)
556 flush_user_windows(); 568 flush_user_windows();
557 window = get_thread_wsaved(); 569 window = get_thread_wsaved();
558 570
559 if (window != 0) { 571 if (likely(window != 0)) {
560 window -= 1; 572 window -= 1;
561 do { 573 do {
562 unsigned long sp = (t->rwbuf_stkptrs[window] + bias); 574 unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
563 struct reg_window *rwin = &t->reg_window[window]; 575 struct reg_window *rwin = &t->reg_window[window];
564 576
565 if (copy_to_user((char __user *)sp, rwin, winsize)) 577 if (unlikely(sp & 0x7UL))
578 stack_unaligned(sp);
579
580 if (unlikely(copy_to_user((char __user *)sp,
581 rwin, winsize)))
566 goto barf; 582 goto barf;
567 } while (window--); 583 } while (window--);
568 } 584 }