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 | 2731 | |
2732 | 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 | 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 | 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 | 2786 | static void setup_frame(int sig, struct emulated_sigaction *ka, |
2784 | 2787 | target_sigset_t *set, CPUState *env) |
2785 | 2788 | { |
2786 | 2789 | struct target_signal_frame *frame; |
2790 | + abi_ulong frame_addr; | |
2787 | 2791 | int err = 0; |
2788 | 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 | 2796 | goto badframe; |
2796 | 2797 | |
2797 | 2798 | /* |
... | ... | @@ -2825,10 +2826,10 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
2825 | 2826 | /* Link SRP so the guest returns through the trampoline. */ |
2826 | 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 | 2830 | return; |
2830 | 2831 | badframe: |
2831 | - unlock_user_struct(frame, (abi_ulong)frame, 0); | |
2832 | + unlock_user_struct(frame, frame_addr, 1); | |
2832 | 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 | 2843 | long do_sigreturn(CPUState *env) |
2843 | 2844 | { |
2844 | 2845 | struct target_signal_frame *frame; |
2846 | + abi_ulong frame_addr; | |
2845 | 2847 | target_sigset_t target_set; |
2846 | 2848 | sigset_t set; |
2847 | 2849 | int i; |
2848 | 2850 | |
2849 | - frame = (void *) env->regs[R_SP]; | |
2851 | + frame_addr = env->regs[R_SP]; | |
2850 | 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 | 2854 | goto badframe; |
2853 | 2855 | |
2854 | 2856 | /* Restore blocked signals */ |
... | ... | @@ -2862,14 +2864,13 @@ long do_sigreturn(CPUState *env) |
2862 | 2864 | sigprocmask(SIG_SETMASK, &set, NULL); |
2863 | 2865 | |
2864 | 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 | 2871 | return env->regs[10]; |
2871 | 2872 | badframe: |
2872 | - unlock_user_struct(frame, (abi_ulong)frame, 0); | |
2873 | + unlock_user_struct(frame, frame_addr, 0); | |
2873 | 2874 | force_sig(TARGET_SIGSEGV); |
2874 | 2875 | } |
2875 | 2876 | ... | ... |