Commit 9664d92872de669dbf87bdc376f3d993a6aa859a
1 parent
ccd4a219
CRIS signals:
* Save $mof across signals. * Cleaned up frame accesses. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4012 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
58 additions
and
57 deletions
linux-user/signal.c
@@ -2731,67 +2731,68 @@ struct rt_signal_frame { | @@ -2731,67 +2731,68 @@ struct rt_signal_frame { | ||
2731 | 2731 | ||
2732 | static void setup_sigcontext(struct target_sigcontext *sc, CPUState *env) | 2732 | static void setup_sigcontext(struct target_sigcontext *sc, CPUState *env) |
2733 | { | 2733 | { |
2734 | - sc->regs.r0 = env->regs[0]; | ||
2735 | - sc->regs.r1 = env->regs[1]; | ||
2736 | - sc->regs.r2 = env->regs[2]; | ||
2737 | - sc->regs.r3 = env->regs[3]; | ||
2738 | - sc->regs.r4 = env->regs[4]; | ||
2739 | - sc->regs.r5 = env->regs[5]; | ||
2740 | - sc->regs.r6 = env->regs[6]; | ||
2741 | - sc->regs.r7 = env->regs[7]; | ||
2742 | - sc->regs.r8 = env->regs[8]; | ||
2743 | - sc->regs.r9 = env->regs[9]; | ||
2744 | - sc->regs.r10 = env->regs[10]; | ||
2745 | - sc->regs.r11 = env->regs[11]; | ||
2746 | - sc->regs.r12 = env->regs[12]; | ||
2747 | - sc->regs.r13 = env->regs[13]; | ||
2748 | - sc->usp = env->regs[14]; | ||
2749 | - sc->regs.acr = env->regs[15]; | ||
2750 | - sc->regs.srp = env->pregs[PR_SRP]; | ||
2751 | - sc->regs.erp = env->pc; | ||
2752 | - | ||
2753 | - env->pregs[PR_ERP] = env->pc; | 2734 | + __put_user(env->regs[0], &sc->regs.r0); |
2735 | + __put_user(env->regs[1], &sc->regs.r1); | ||
2736 | + __put_user(env->regs[2], &sc->regs.r2); | ||
2737 | + __put_user(env->regs[3], &sc->regs.r3); | ||
2738 | + __put_user(env->regs[4], &sc->regs.r4); | ||
2739 | + __put_user(env->regs[5], &sc->regs.r5); | ||
2740 | + __put_user(env->regs[6], &sc->regs.r6); | ||
2741 | + __put_user(env->regs[7], &sc->regs.r7); | ||
2742 | + __put_user(env->regs[8], &sc->regs.r8); | ||
2743 | + __put_user(env->regs[9], &sc->regs.r9); | ||
2744 | + __put_user(env->regs[10], &sc->regs.r10); | ||
2745 | + __put_user(env->regs[11], &sc->regs.r11); | ||
2746 | + __put_user(env->regs[12], &sc->regs.r12); | ||
2747 | + __put_user(env->regs[13], &sc->regs.r13); | ||
2748 | + __put_user(env->regs[14], &sc->usp); | ||
2749 | + __put_user(env->regs[15], &sc->regs.acr); | ||
2750 | + __put_user(env->pregs[PR_MOF], &sc->regs.mof); | ||
2751 | + __put_user(env->pregs[PR_SRP], &sc->regs.srp); | ||
2752 | + __put_user(env->pc, &sc->regs.erp); | ||
2754 | } | 2753 | } |
2754 | + | ||
2755 | static void restore_sigcontext(struct target_sigcontext *sc, CPUState *env) | 2755 | static void restore_sigcontext(struct target_sigcontext *sc, CPUState *env) |
2756 | { | 2756 | { |
2757 | - env->regs[0] = sc->regs.r0; | ||
2758 | - env->regs[1] = sc->regs.r1; | ||
2759 | - env->regs[2] = sc->regs.r2; | ||
2760 | - env->regs[3] = sc->regs.r3; | ||
2761 | - env->regs[4] = sc->regs.r4; | ||
2762 | - env->regs[5] = sc->regs.r5; | ||
2763 | - env->regs[6] = sc->regs.r6; | ||
2764 | - env->regs[7] = sc->regs.r7; | ||
2765 | - env->regs[8] = sc->regs.r8; | ||
2766 | - env->regs[9] = sc->regs.r9; | ||
2767 | - env->regs[10] = sc->regs.r10; | ||
2768 | - env->regs[11] = sc->regs.r11; | ||
2769 | - env->regs[12] = sc->regs.r12; | ||
2770 | - env->regs[13] = sc->regs.r13; | ||
2771 | - env->regs[14] = sc->usp; | ||
2772 | - env->regs[15] = sc->regs.acr; | ||
2773 | -} | ||
2774 | - | ||
2775 | -static struct target_signal_frame *get_sigframe(CPUState *env, int framesize) | ||
2776 | -{ | ||
2777 | - uint8_t *sp; | 2757 | + __get_user(env->regs[0], &sc->regs.r0); |
2758 | + __get_user(env->regs[1], &sc->regs.r1); | ||
2759 | + __get_user(env->regs[2], &sc->regs.r2); | ||
2760 | + __get_user(env->regs[3], &sc->regs.r3); | ||
2761 | + __get_user(env->regs[4], &sc->regs.r4); | ||
2762 | + __get_user(env->regs[5], &sc->regs.r5); | ||
2763 | + __get_user(env->regs[6], &sc->regs.r6); | ||
2764 | + __get_user(env->regs[7], &sc->regs.r7); | ||
2765 | + __get_user(env->regs[8], &sc->regs.r8); | ||
2766 | + __get_user(env->regs[9], &sc->regs.r9); | ||
2767 | + __get_user(env->regs[10], &sc->regs.r10); | ||
2768 | + __get_user(env->regs[11], &sc->regs.r11); | ||
2769 | + __get_user(env->regs[12], &sc->regs.r12); | ||
2770 | + __get_user(env->regs[13], &sc->regs.r13); | ||
2771 | + __get_user(env->regs[14], &sc->usp); | ||
2772 | + __get_user(env->regs[15], &sc->regs.acr); | ||
2773 | + __get_user(env->pregs[PR_MOF], &sc->regs.mof); | ||
2774 | + __get_user(env->pregs[PR_SRP], &sc->regs.srp); | ||
2775 | + __get_user(env->pc, &sc->regs.erp); | ||
2776 | +} | ||
2777 | + | ||
2778 | +static abi_ulong get_sigframe(CPUState *env, int framesize) | ||
2779 | +{ | ||
2780 | + abi_ulong sp; | ||
2778 | /* Align the stack downwards to 4. */ | 2781 | /* Align the stack downwards to 4. */ |
2779 | - sp = (uint8_t *) (env->regs[R_SP] & ~3); | ||
2780 | - return (void *)(sp - framesize); | 2782 | + sp = (env->regs[R_SP] & ~3); |
2783 | + return sp - framesize; | ||
2781 | } | 2784 | } |
2782 | 2785 | ||
2783 | static void setup_frame(int sig, struct emulated_sigaction *ka, | 2786 | static void setup_frame(int sig, struct emulated_sigaction *ka, |
2784 | target_sigset_t *set, CPUState *env) | 2787 | target_sigset_t *set, CPUState *env) |
2785 | { | 2788 | { |
2786 | struct target_signal_frame *frame; | 2789 | struct target_signal_frame *frame; |
2790 | + abi_ulong frame_addr; | ||
2787 | int err = 0; | 2791 | int err = 0; |
2788 | int i; | 2792 | int i; |
2789 | - uint32_t old_usp; | ||
2790 | - | ||
2791 | - old_usp = env->regs[R_SP]; | ||
2792 | 2793 | ||
2793 | - frame = get_sigframe(env, sizeof *frame); | ||
2794 | - if (!lock_user_struct(VERIFY_WRITE, frame, (abi_ulong)frame, 1)) | 2794 | + frame_addr = get_sigframe(env, sizeof *frame); |
2795 | + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) | ||
2795 | goto badframe; | 2796 | goto badframe; |
2796 | 2797 | ||
2797 | /* | 2798 | /* |
@@ -2825,10 +2826,10 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | @@ -2825,10 +2826,10 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | ||
2825 | /* Link SRP so the guest returns through the trampoline. */ | 2826 | /* Link SRP so the guest returns through the trampoline. */ |
2826 | env->pregs[PR_SRP] = (uint32_t) &frame->retcode[0]; | 2827 | env->pregs[PR_SRP] = (uint32_t) &frame->retcode[0]; |
2827 | 2828 | ||
2828 | - unlock_user_struct(frame, (abi_ulong)frame, 0); | 2829 | + unlock_user_struct(frame, frame_addr, 1); |
2829 | return; | 2830 | return; |
2830 | badframe: | 2831 | badframe: |
2831 | - unlock_user_struct(frame, (abi_ulong)frame, 0); | 2832 | + unlock_user_struct(frame, frame_addr, 1); |
2832 | force_sig(TARGET_SIGSEGV); | 2833 | force_sig(TARGET_SIGSEGV); |
2833 | } | 2834 | } |
2834 | 2835 | ||
@@ -2842,13 +2843,14 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | @@ -2842,13 +2843,14 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | ||
2842 | long do_sigreturn(CPUState *env) | 2843 | long do_sigreturn(CPUState *env) |
2843 | { | 2844 | { |
2844 | struct target_signal_frame *frame; | 2845 | struct target_signal_frame *frame; |
2846 | + abi_ulong frame_addr; | ||
2845 | target_sigset_t target_set; | 2847 | target_sigset_t target_set; |
2846 | sigset_t set; | 2848 | sigset_t set; |
2847 | int i; | 2849 | int i; |
2848 | 2850 | ||
2849 | - frame = (void *) env->regs[R_SP]; | 2851 | + frame_addr = env->regs[R_SP]; |
2850 | /* Make sure the guest isn't playing games. */ | 2852 | /* Make sure the guest isn't playing games. */ |
2851 | - if (!lock_user_struct(VERIFY_READ, frame, (abi_ulong)frame, 1)) | 2853 | + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) |
2852 | goto badframe; | 2854 | goto badframe; |
2853 | 2855 | ||
2854 | /* Restore blocked signals */ | 2856 | /* Restore blocked signals */ |
@@ -2862,14 +2864,13 @@ long do_sigreturn(CPUState *env) | @@ -2862,14 +2864,13 @@ long do_sigreturn(CPUState *env) | ||
2862 | sigprocmask(SIG_SETMASK, &set, NULL); | 2864 | sigprocmask(SIG_SETMASK, &set, NULL); |
2863 | 2865 | ||
2864 | restore_sigcontext(&frame->sc, env); | 2866 | restore_sigcontext(&frame->sc, env); |
2865 | - /* Compensate -2 for the syscall return path advancing brk. */ | ||
2866 | - env->pc = frame->sc.regs.erp - 2; | ||
2867 | - env->pregs[PR_SRP] = frame->sc.regs.srp; | 2867 | + /* Compensate for the syscall return path advancing brk. */ |
2868 | + env->pc -= 2; | ||
2868 | 2869 | ||
2869 | - unlock_user_struct(frame, (abi_ulong)frame, 0); | 2870 | + unlock_user_struct(frame, frame_addr, 0); |
2870 | return env->regs[10]; | 2871 | return env->regs[10]; |
2871 | badframe: | 2872 | badframe: |
2872 | - unlock_user_struct(frame, (abi_ulong)frame, 0); | 2873 | + unlock_user_struct(frame, frame_addr, 0); |
2873 | force_sig(TARGET_SIGSEGV); | 2874 | force_sig(TARGET_SIGSEGV); |
2874 | } | 2875 | } |
2875 | 2876 |