diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-11-10 21:58:34 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-11-10 21:58:34 +0100 |
commit | 2b1768f39aebfcccdc5b948eb4962918a5a64581 (patch) | |
tree | f92c98ef10cf1ded4985050589413946aa8f0e6c /arch/sparc/kernel/process_64.c | |
parent | affd9a8dbc22beadae1186aa060685d6f6a06792 (diff) | |
parent | 226f7cea949303a3e1911999a9a2c71b0a708e73 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
Pull sparc fixes from David Miller:
"Several build/bug fixes for sparc, including:
1) Configuring a mix of static vs. modular sparc64 crypto modules
didn't work, remove an ill-conceived attempt to only have to build
the device match table for these drivers once to fix the problem.
Reported by Meelis Roos.
2) Make the montgomery multiple/square and mpmul instructions actually
usable in 32-bit tasks. Essentially this involves providing 32-bit
userspace with a way to use a 64-bit stack when it needs to.
3) Our sparc64 atomic backoffs don't yield cpu strands properly on
Niagara chips. Use pause instruction when available to achieve
this, otherwise use a benign instruction we know blocks the strand
for some time.
4) Wire up kcmp
5) Fix the build of various drivers by removing the unnecessary
blocking of OF_GPIO when SPARC.
6) Fix unintended regression wherein of_address_to_resource stopped
being provided. Fix from Andreas Larsson.
7) Fix NULL dereference in leon_handle_ext_irq(), also from Andreas
Larsson."
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc:
sparc64: Fix build with mix of modular vs. non-modular crypto drivers.
sparc: Support atomic64_dec_if_positive properly.
of/address: sparc: Declare of_address_to_resource() as an extern function for sparc again
sparc32, leon: Check for existent irq_map entry in leon_handle_ext_irq
sparc: Add sparc support for platform_get_irq()
sparc: Allow OF_GPIO on sparc.
qlogicpti: Fix build warning.
sparc: Wire up sys_kcmp.
sparc64: Improvde documentation and readability of atomic backoff code.
sparc64: Use pause instruction when available.
sparc64: Fix cpu strand yielding.
sparc64: Make montmul/montsqr/mpmul usable in 32-bit threads.
Diffstat (limited to 'arch/sparc/kernel/process_64.c')
-rw-r--r-- | arch/sparc/kernel/process_64.c | 42 |
1 files changed, 23 insertions, 19 deletions
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index d778248ef3f8..c6e0c2910043 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -452,13 +452,16 @@ void flush_thread(void) /* It's a bit more tricky when 64-bit tasks are involved... */ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp) { + bool stack_64bit = test_thread_64bit_stack(psp); unsigned long fp, distance, rval; - if (!(test_thread_flag(TIF_32BIT))) { + if (stack_64bit) { csp += STACK_BIAS; psp += STACK_BIAS; __get_user(fp, &(((struct reg_window __user *)psp)->ins[6])); fp += STACK_BIAS; + if (test_thread_flag(TIF_32BIT)) + fp &= 0xffffffff; } else __get_user(fp, &(((struct reg_window32 __user *)psp)->ins[6])); @@ -472,7 +475,7 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp) rval = (csp - distance); if (copy_in_user((void __user *) rval, (void __user *) psp, distance)) rval = 0; - else if (test_thread_flag(TIF_32BIT)) { + else if (!stack_64bit) { if (put_user(((u32)csp), &(((struct reg_window32 __user *)rval)->ins[6]))) rval = 0; @@ -507,18 +510,18 @@ void synchronize_user_stack(void) flush_user_windows(); if ((window = get_thread_wsaved()) != 0) { - int winsize = sizeof(struct reg_window); - int bias = 0; - - if (test_thread_flag(TIF_32BIT)) - winsize = sizeof(struct reg_window32); - else - bias = STACK_BIAS; - window -= 1; do { - unsigned long sp = (t->rwbuf_stkptrs[window] + bias); struct reg_window *rwin = &t->reg_window[window]; + int winsize = sizeof(struct reg_window); + unsigned long sp; + + sp = t->rwbuf_stkptrs[window]; + + if (test_thread_64bit_stack(sp)) + sp += STACK_BIAS; + else + winsize = sizeof(struct reg_window32); if (!copy_to_user((char __user *)sp, rwin, winsize)) { shift_window_buffer(window, get_thread_wsaved() - 1, t); @@ -544,13 +547,6 @@ void fault_in_user_windows(void) { struct thread_info *t = current_thread_info(); unsigned long window; - int winsize = sizeof(struct reg_window); - int bias = 0; - - if (test_thread_flag(TIF_32BIT)) - winsize = sizeof(struct reg_window32); - else - bias = STACK_BIAS; flush_user_windows(); window = get_thread_wsaved(); @@ -558,8 +554,16 @@ void fault_in_user_windows(void) if (likely(window != 0)) { window -= 1; do { - unsigned long sp = (t->rwbuf_stkptrs[window] + bias); struct reg_window *rwin = &t->reg_window[window]; + int winsize = sizeof(struct reg_window); + unsigned long sp; + + sp = t->rwbuf_stkptrs[window]; + + if (test_thread_64bit_stack(sp)) + sp += STACK_BIAS; + else + winsize = sizeof(struct reg_window32); if (unlikely(sp & 0x7UL)) stack_unaligned(sp); |