diff options
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) | |||
| 452 | /* It's a bit more tricky when 64-bit tasks are involved... */ | 452 | /* It's a bit more tricky when 64-bit tasks are involved... */ |
| 453 | static unsigned long clone_stackframe(unsigned long csp, unsigned long psp) | 453 | static unsigned long clone_stackframe(unsigned long csp, unsigned long psp) |
| 454 | { | 454 | { |
| 455 | bool stack_64bit = test_thread_64bit_stack(psp); | ||
| 455 | unsigned long fp, distance, rval; | 456 | unsigned long fp, distance, rval; |
| 456 | 457 | ||
| 457 | if (!(test_thread_flag(TIF_32BIT))) { | 458 | if (stack_64bit) { |
| 458 | csp += STACK_BIAS; | 459 | csp += STACK_BIAS; |
| 459 | psp += STACK_BIAS; | 460 | psp += STACK_BIAS; |
| 460 | __get_user(fp, &(((struct reg_window __user *)psp)->ins[6])); | 461 | __get_user(fp, &(((struct reg_window __user *)psp)->ins[6])); |
| 461 | fp += STACK_BIAS; | 462 | fp += STACK_BIAS; |
| 463 | if (test_thread_flag(TIF_32BIT)) | ||
| 464 | fp &= 0xffffffff; | ||
| 462 | } else | 465 | } else |
| 463 | __get_user(fp, &(((struct reg_window32 __user *)psp)->ins[6])); | 466 | __get_user(fp, &(((struct reg_window32 __user *)psp)->ins[6])); |
| 464 | 467 | ||
| @@ -472,7 +475,7 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp) | |||
| 472 | rval = (csp - distance); | 475 | rval = (csp - distance); |
| 473 | if (copy_in_user((void __user *) rval, (void __user *) psp, distance)) | 476 | if (copy_in_user((void __user *) rval, (void __user *) psp, distance)) |
| 474 | rval = 0; | 477 | rval = 0; |
| 475 | else if (test_thread_flag(TIF_32BIT)) { | 478 | else if (!stack_64bit) { |
| 476 | if (put_user(((u32)csp), | 479 | if (put_user(((u32)csp), |
| 477 | &(((struct reg_window32 __user *)rval)->ins[6]))) | 480 | &(((struct reg_window32 __user *)rval)->ins[6]))) |
| 478 | rval = 0; | 481 | rval = 0; |
| @@ -507,18 +510,18 @@ void synchronize_user_stack(void) | |||
| 507 | 510 | ||
| 508 | flush_user_windows(); | 511 | flush_user_windows(); |
| 509 | if ((window = get_thread_wsaved()) != 0) { | 512 | if ((window = get_thread_wsaved()) != 0) { |
| 510 | int winsize = sizeof(struct reg_window); | ||
| 511 | int bias = 0; | ||
| 512 | |||
| 513 | if (test_thread_flag(TIF_32BIT)) | ||
| 514 | winsize = sizeof(struct reg_window32); | ||
| 515 | else | ||
| 516 | bias = STACK_BIAS; | ||
| 517 | |||
| 518 | window -= 1; | 513 | window -= 1; |
| 519 | do { | 514 | do { |
| 520 | unsigned long sp = (t->rwbuf_stkptrs[window] + bias); | ||
| 521 | struct reg_window *rwin = &t->reg_window[window]; | 515 | struct reg_window *rwin = &t->reg_window[window]; |
| 516 | int winsize = sizeof(struct reg_window); | ||
| 517 | unsigned long sp; | ||
| 518 | |||
| 519 | sp = t->rwbuf_stkptrs[window]; | ||
| 520 | |||
| 521 | if (test_thread_64bit_stack(sp)) | ||
| 522 | sp += STACK_BIAS; | ||
| 523 | else | ||
| 524 | winsize = sizeof(struct reg_window32); | ||
| 522 | 525 | ||
| 523 | if (!copy_to_user((char __user *)sp, rwin, winsize)) { | 526 | if (!copy_to_user((char __user *)sp, rwin, winsize)) { |
| 524 | shift_window_buffer(window, get_thread_wsaved() - 1, t); | 527 | shift_window_buffer(window, get_thread_wsaved() - 1, t); |
| @@ -544,13 +547,6 @@ void fault_in_user_windows(void) | |||
| 544 | { | 547 | { |
| 545 | struct thread_info *t = current_thread_info(); | 548 | struct thread_info *t = current_thread_info(); |
| 546 | unsigned long window; | 549 | unsigned long window; |
| 547 | int winsize = sizeof(struct reg_window); | ||
| 548 | int bias = 0; | ||
| 549 | |||
| 550 | if (test_thread_flag(TIF_32BIT)) | ||
| 551 | winsize = sizeof(struct reg_window32); | ||
| 552 | else | ||
| 553 | bias = STACK_BIAS; | ||
| 554 | 550 | ||
| 555 | flush_user_windows(); | 551 | flush_user_windows(); |
| 556 | window = get_thread_wsaved(); | 552 | window = get_thread_wsaved(); |
| @@ -558,8 +554,16 @@ void fault_in_user_windows(void) | |||
| 558 | if (likely(window != 0)) { | 554 | if (likely(window != 0)) { |
| 559 | window -= 1; | 555 | window -= 1; |
| 560 | do { | 556 | do { |
| 561 | unsigned long sp = (t->rwbuf_stkptrs[window] + bias); | ||
| 562 | struct reg_window *rwin = &t->reg_window[window]; | 557 | struct reg_window *rwin = &t->reg_window[window]; |
| 558 | int winsize = sizeof(struct reg_window); | ||
| 559 | unsigned long sp; | ||
| 560 | |||
| 561 | sp = t->rwbuf_stkptrs[window]; | ||
| 562 | |||
| 563 | if (test_thread_64bit_stack(sp)) | ||
| 564 | sp += STACK_BIAS; | ||
| 565 | else | ||
| 566 | winsize = sizeof(struct reg_window32); | ||
| 563 | 567 | ||
| 564 | if (unlikely(sp & 0x7UL)) | 568 | if (unlikely(sp & 0x7UL)) |
| 565 | stack_unaligned(sp); | 569 | stack_unaligned(sp); |
