Commit b6d3abda6892e9ce4aa08bd9f5d83fee29efec71

Authored by edgar_igl
1 parent cbdbb771

First try at supporting ordinary signals for CRIS linux-user guests.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3999 c046a42c-6fe2-441c-8c8c-71466251a162
linux-user/main.c
... ... @@ -1673,6 +1673,9 @@ void cpu_loop (CPUState *env)
1673 1673 queue_signal(info.si_signo, &info);
1674 1674 }
1675 1675 break;
  1676 + case EXCP_INTERRUPT:
  1677 + /* just indicate that signals should be handled asap */
  1678 + break;
1676 1679 case EXCP_BREAK:
1677 1680 ret = do_syscall(env,
1678 1681 env->regs[9],
... ...
linux-user/signal.c
... ... @@ -2706,6 +2706,178 @@ badframe:
2706 2706 force_sig(TARGET_SIGSEGV);
2707 2707 return 0;
2708 2708 }
  2709 +#elif defined(TARGET_CRIS)
  2710 +
  2711 +struct target_sigcontext {
  2712 + struct target_pt_regs regs; /* needs to be first */
  2713 + uint32_t oldmask;
  2714 + uint32_t usp; /* usp before stacking this gunk on it */
  2715 +};
  2716 +
  2717 +/* Signal frames. */
  2718 +struct target_signal_frame {
  2719 + struct target_sigcontext sc;
  2720 + uint32_t extramask[TARGET_NSIG_WORDS - 1];
  2721 + uint8_t retcode[8]; /* Trampoline code. */
  2722 +};
  2723 +
  2724 +struct rt_signal_frame {
  2725 + struct siginfo *pinfo;
  2726 + void *puc;
  2727 + struct siginfo info;
  2728 + struct ucontext uc;
  2729 + uint8_t retcode[8]; /* Trampoline code. */
  2730 +};
  2731 +
  2732 +static void setup_sigcontext(struct target_sigcontext *sc, CPUState *env)
  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;
  2754 +}
  2755 +static void restore_sigcontext(struct target_sigcontext *sc, CPUState *env)
  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;
  2778 + /* Align the stack downwards to 4. */
  2779 + sp = (uint8_t *) (env->regs[R_SP] & ~3);
  2780 + return (void *)(sp - framesize);
  2781 +}
  2782 +
  2783 +static void setup_frame(int sig, struct emulated_sigaction *ka,
  2784 + target_sigset_t *set, CPUState *env)
  2785 +{
  2786 + struct target_signal_frame *frame;
  2787 + int err = 0;
  2788 + int i;
  2789 + uint32_t old_usp;
  2790 +
  2791 + old_usp = env->regs[R_SP];
  2792 +
  2793 + frame = get_sigframe(env, sizeof *frame);
  2794 + if (!lock_user_struct(VERIFY_WRITE, frame, (abi_ulong)frame, 1))
  2795 + goto badframe;
  2796 +
  2797 + /*
  2798 + * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
  2799 + * use this trampoline anymore but it sets it up for GDB.
  2800 + * In QEMU, using the trampoline simplifies things a bit so we use it.
  2801 + *
  2802 + * This is movu.w __NR_sigreturn, r9; break 13;
  2803 + */
  2804 + err |= __put_user(0x9c5f, frame->retcode+0);
  2805 + err |= __put_user(TARGET_NR_sigreturn,
  2806 + frame->retcode+2);
  2807 + err |= __put_user(0xe93d, frame->retcode+4);
  2808 +
  2809 + /* Save the mask. */
  2810 + err |= __put_user(set->sig[0], &frame->sc.oldmask);
  2811 + if (err)
  2812 + goto badframe;
  2813 +
  2814 + for(i = 1; i < TARGET_NSIG_WORDS; i++) {
  2815 + if (__put_user(set->sig[i], &frame->extramask[i - 1]))
  2816 + goto badframe;
  2817 + }
  2818 +
  2819 + setup_sigcontext(&frame->sc, env);
  2820 +
  2821 + /* Move the stack and setup the arguments for the handler. */
  2822 + env->regs[R_SP] = (uint32_t) frame;
  2823 + env->regs[10] = sig;
  2824 + env->pc = (unsigned long) ka->sa._sa_handler;
  2825 + /* Link SRP so the guest returns through the trampoline. */
  2826 + env->pregs[PR_SRP] = (uint32_t) &frame->retcode[0];
  2827 +
  2828 + unlock_user_struct(frame, (abi_ulong)frame, 0);
  2829 + return;
  2830 + badframe:
  2831 + unlock_user_struct(frame, (abi_ulong)frame, 0);
  2832 + force_sig(TARGET_SIGSEGV);
  2833 +}
  2834 +
  2835 +static void setup_rt_frame(int sig, struct emulated_sigaction *ka,
  2836 + target_siginfo_t *info,
  2837 + target_sigset_t *set, CPUState *env)
  2838 +{
  2839 + fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
  2840 +}
  2841 +
  2842 +long do_sigreturn(CPUState *env)
  2843 +{
  2844 + struct target_signal_frame *frame;
  2845 + target_sigset_t target_set;
  2846 + sigset_t set;
  2847 + int i;
  2848 +
  2849 + frame = (void *) env->regs[R_SP];
  2850 + /* Make sure the guest isn't playing games. */
  2851 + if (!lock_user_struct(VERIFY_READ, frame, (abi_ulong)frame, 1))
  2852 + goto badframe;
  2853 +
  2854 + /* Restore blocked signals */
  2855 + if (__get_user(target_set.sig[0], &frame->sc.oldmask))
  2856 + goto badframe;
  2857 + for(i = 1; i < TARGET_NSIG_WORDS; i++) {
  2858 + if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
  2859 + goto badframe;
  2860 + }
  2861 + target_to_host_sigset_internal(&set, &target_set);
  2862 + sigprocmask(SIG_SETMASK, &set, NULL);
  2863 +
  2864 + 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;
  2868 +
  2869 + unlock_user_struct(frame, (abi_ulong)frame, 0);
  2870 + return env->regs[10];
  2871 + badframe:
  2872 + unlock_user_struct(frame, (abi_ulong)frame, 0);
  2873 + force_sig(TARGET_SIGSEGV);
  2874 +}
  2875 +
  2876 +long do_rt_sigreturn(CPUState *env)
  2877 +{
  2878 + fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
  2879 + return -TARGET_ENOSYS;
  2880 +}
2709 2881  
2710 2882 #else
2711 2883  
... ...