Commit 43fff2384e7027f1c870520dbb111e0b2df8b4bb

Authored by bellard
1 parent 1b21b62a

ARM signal support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@318 c046a42c-6fe2-441c-8c8c-71466251a162
linux-user/main.c
... ... @@ -246,8 +246,6 @@ void cpu_loop(CPUX86State *env)
246 246  
247 247 #ifdef TARGET_ARM
248 248  
249   -#define ARM_SYSCALL_BASE 0x900000
250   -
251 249 void cpu_loop(CPUARMState *env)
252 250 {
253 251 int trapnr;
... ... @@ -285,6 +283,9 @@ void cpu_loop(CPUARMState *env)
285 283 }
286 284 }
287 285 break;
  286 + case EXCP_INTERRUPT:
  287 + /* just indicate that signals should be handled asap */
  288 + break;
288 289 default:
289 290 error:
290 291 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
... ...
linux-user/signal.c
... ... @@ -364,6 +364,80 @@ int do_sigaction(int sig, const struct target_sigaction *act,
364 364 return 0;
365 365 }
366 366  
  367 +#define __put_user(x,ptr)\
  368 +({\
  369 + int size = sizeof(*ptr);\
  370 + switch(size) {\
  371 + case 1:\
  372 + stb(ptr, (typeof(*ptr))(x));\
  373 + break;\
  374 + case 2:\
  375 + stw(ptr, (typeof(*ptr))(x));\
  376 + break;\
  377 + case 4:\
  378 + stl(ptr, (typeof(*ptr))(x));\
  379 + break;\
  380 + case 8:\
  381 + stq(ptr, (typeof(*ptr))(x));\
  382 + break;\
  383 + default:\
  384 + abort();\
  385 + }\
  386 + 0;\
  387 +})
  388 +
  389 +#define __get_user(x, ptr) \
  390 +({\
  391 + int size = sizeof(*ptr);\
  392 + switch(size) {\
  393 + case 1:\
  394 + x = (typeof(*ptr))ldub(ptr);\
  395 + break;\
  396 + case 2:\
  397 + x = (typeof(*ptr))lduw(ptr);\
  398 + break;\
  399 + case 4:\
  400 + x = (typeof(*ptr))ldl(ptr);\
  401 + break;\
  402 + case 8:\
  403 + x = (typeof(*ptr))ldq(ptr);\
  404 + break;\
  405 + default:\
  406 + abort();\
  407 + }\
  408 + 0;\
  409 +})
  410 +
  411 +
  412 +#define __copy_to_user(dst, src, size)\
  413 +({\
  414 + memcpy(dst, src, size);\
  415 + 0;\
  416 +})
  417 +
  418 +#define __copy_from_user(dst, src, size)\
  419 +({\
  420 + memcpy(dst, src, size);\
  421 + 0;\
  422 +})
  423 +
  424 +#define __clear_user(dst, size)\
  425 +({\
  426 + memset(dst, 0, size);\
  427 + 0;\
  428 +})
  429 +
  430 +#ifndef offsetof
  431 +#define offsetof(type, field) ((size_t) &((type *)0)->field)
  432 +#endif
  433 +
  434 +static inline int copy_siginfo_to_user(target_siginfo_t *tinfo,
  435 + const target_siginfo_t *info)
  436 +{
  437 + tswap_siginfo(tinfo, info);
  438 + return 0;
  439 +}
  440 +
367 441 #ifdef TARGET_I386
368 442  
369 443 /* from the Linux kernel */
... ... @@ -472,44 +546,6 @@ struct rt_sigframe
472 546 * Set up a signal frame.
473 547 */
474 548  
475   -#define __put_user(x,ptr)\
476   -({\
477   - int size = sizeof(*ptr);\
478   - switch(size) {\
479   - case 1:\
480   - stb(ptr, (typeof(*ptr))(x));\
481   - break;\
482   - case 2:\
483   - stw(ptr, (typeof(*ptr))(x));\
484   - break;\
485   - case 4:\
486   - stl(ptr, (typeof(*ptr))(x));\
487   - break;\
488   - case 8:\
489   - stq(ptr, (typeof(*ptr))(x));\
490   - break;\
491   - default:\
492   - abort();\
493   - }\
494   - 0;\
495   -})
496   -
497   -#define get_user(val, ptr) (typeof(*ptr))(*(ptr))
498   -
499   -
500   -#define __copy_to_user(dst, src, size)\
501   -({\
502   - memcpy(dst, src, size);\
503   - 0;\
504   -})
505   -
506   -static inline int copy_siginfo_to_user(target_siginfo_t *tinfo,
507   - const target_siginfo_t *info)
508   -{
509   - tswap_siginfo(tinfo, info);
510   - return 0;
511   -}
512   -
513 549 /* XXX: save x87 state */
514 550 static int
515 551 setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate,
... ... @@ -825,6 +861,377 @@ badframe:
825 861 return 0;
826 862 }
827 863  
  864 +#elif defined(TARGET_ARM)
  865 +
  866 +struct target_sigcontext {
  867 + target_ulong trap_no;
  868 + target_ulong error_code;
  869 + target_ulong oldmask;
  870 + target_ulong arm_r0;
  871 + target_ulong arm_r1;
  872 + target_ulong arm_r2;
  873 + target_ulong arm_r3;
  874 + target_ulong arm_r4;
  875 + target_ulong arm_r5;
  876 + target_ulong arm_r6;
  877 + target_ulong arm_r7;
  878 + target_ulong arm_r8;
  879 + target_ulong arm_r9;
  880 + target_ulong arm_r10;
  881 + target_ulong arm_fp;
  882 + target_ulong arm_ip;
  883 + target_ulong arm_sp;
  884 + target_ulong arm_lr;
  885 + target_ulong arm_pc;
  886 + target_ulong arm_cpsr;
  887 + target_ulong fault_address;
  888 +};
  889 +
  890 +typedef struct target_sigaltstack {
  891 + target_ulong ss_sp;
  892 + int ss_flags;
  893 + target_ulong ss_size;
  894 +} target_stack_t;
  895 +
  896 +struct target_ucontext {
  897 + target_ulong uc_flags;
  898 + target_ulong uc_link;
  899 + target_stack_t uc_stack;
  900 + struct target_sigcontext uc_mcontext;
  901 + target_sigset_t uc_sigmask; /* mask last for extensibility */
  902 +};
  903 +
  904 +struct sigframe
  905 +{
  906 + struct target_sigcontext sc;
  907 + target_ulong extramask[TARGET_NSIG_WORDS-1];
  908 + target_ulong retcode;
  909 +};
  910 +
  911 +struct rt_sigframe
  912 +{
  913 + struct target_siginfo *pinfo;
  914 + void *puc;
  915 + struct target_siginfo info;
  916 + struct target_ucontext uc;
  917 + target_ulong retcode;
  918 +};
  919 +
  920 +#define TARGET_CONFIG_CPU_32 1
  921 +
  922 +/*
  923 + * For ARM syscalls, we encode the syscall number into the instruction.
  924 + */
  925 +#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
  926 +#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
  927 +
  928 +/*
  929 + * For Thumb syscalls, we pass the syscall number via r7. We therefore
  930 + * need two 16-bit instructions.
  931 + */
  932 +#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
  933 +#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
  934 +
  935 +static const target_ulong retcodes[4] = {
  936 + SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
  937 + SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
  938 +};
  939 +
  940 +
  941 +#define __put_user_error(x,p,e) __put_user(x, p)
  942 +#define __get_user_error(x,p,e) __get_user(x, p)
  943 +
  944 +static inline int valid_user_regs(CPUState *regs)
  945 +{
  946 + return 1;
  947 +}
  948 +
  949 +static int
  950 +setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
  951 + CPUState *env, unsigned long mask)
  952 +{
  953 + int err = 0;
  954 +
  955 + __put_user_error(env->regs[0], &sc->arm_r0, err);
  956 + __put_user_error(env->regs[1], &sc->arm_r1, err);
  957 + __put_user_error(env->regs[2], &sc->arm_r2, err);
  958 + __put_user_error(env->regs[3], &sc->arm_r3, err);
  959 + __put_user_error(env->regs[4], &sc->arm_r4, err);
  960 + __put_user_error(env->regs[5], &sc->arm_r5, err);
  961 + __put_user_error(env->regs[6], &sc->arm_r6, err);
  962 + __put_user_error(env->regs[7], &sc->arm_r7, err);
  963 + __put_user_error(env->regs[8], &sc->arm_r8, err);
  964 + __put_user_error(env->regs[9], &sc->arm_r9, err);
  965 + __put_user_error(env->regs[10], &sc->arm_r10, err);
  966 + __put_user_error(env->regs[11], &sc->arm_fp, err);
  967 + __put_user_error(env->regs[12], &sc->arm_ip, err);
  968 + __put_user_error(env->regs[13], &sc->arm_sp, err);
  969 + __put_user_error(env->regs[14], &sc->arm_lr, err);
  970 + __put_user_error(env->regs[15], &sc->arm_pc, err);
  971 +#ifdef TARGET_CONFIG_CPU_32
  972 + __put_user_error(env->cpsr, &sc->arm_cpsr, err);
  973 +#endif
  974 +
  975 + __put_user_error(/* current->thread.trap_no */ 0, &sc->trap_no, err);
  976 + __put_user_error(/* current->thread.error_code */ 0, &sc->error_code, err);
  977 + __put_user_error(/* current->thread.address */ 0, &sc->fault_address, err);
  978 + __put_user_error(mask, &sc->oldmask, err);
  979 +
  980 + return err;
  981 +}
  982 +
  983 +static inline void *
  984 +get_sigframe(struct emulated_sigaction *ka, CPUState *regs, int framesize)
  985 +{
  986 + unsigned long sp = regs->regs[13];
  987 +
  988 +#if 0
  989 + /*
  990 + * This is the X/Open sanctioned signal stack switching.
  991 + */
  992 + if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
  993 + sp = current->sas_ss_sp + current->sas_ss_size;
  994 +#endif
  995 + /*
  996 + * ATPCS B01 mandates 8-byte alignment
  997 + */
  998 + return (void *)((sp - framesize) & ~7);
  999 +}
  1000 +
  1001 +static int
  1002 +setup_return(CPUState *env, struct emulated_sigaction *ka,
  1003 + target_ulong *rc, void *frame, int usig)
  1004 +{
  1005 + target_ulong handler = (target_ulong)ka->sa._sa_handler;
  1006 + target_ulong retcode;
  1007 + int thumb = 0;
  1008 +#if defined(TARGET_CONFIG_CPU_32)
  1009 + target_ulong cpsr = env->cpsr;
  1010 +
  1011 +#if 0
  1012 + /*
  1013 + * Maybe we need to deliver a 32-bit signal to a 26-bit task.
  1014 + */
  1015 + if (ka->sa.sa_flags & SA_THIRTYTWO)
  1016 + cpsr = (cpsr & ~MODE_MASK) | USR_MODE;
  1017 +
  1018 +#ifdef CONFIG_ARM_THUMB
  1019 + if (elf_hwcap & HWCAP_THUMB) {
  1020 + /*
  1021 + * The LSB of the handler determines if we're going to
  1022 + * be using THUMB or ARM mode for this signal handler.
  1023 + */
  1024 + thumb = handler & 1;
  1025 +
  1026 + if (thumb)
  1027 + cpsr |= T_BIT;
  1028 + else
  1029 + cpsr &= ~T_BIT;
  1030 + }
  1031 +#endif
  1032 +#endif
  1033 +#endif /* TARGET_CONFIG_CPU_32 */
  1034 +
  1035 + if (ka->sa.sa_flags & TARGET_SA_RESTORER) {
  1036 + retcode = (target_ulong)ka->sa.sa_restorer;
  1037 + } else {
  1038 + unsigned int idx = thumb;
  1039 +
  1040 + if (ka->sa.sa_flags & TARGET_SA_SIGINFO)
  1041 + idx += 2;
  1042 +
  1043 + if (__put_user(retcodes[idx], rc))
  1044 + return 1;
  1045 +#if 0
  1046 + flush_icache_range((target_ulong)rc,
  1047 + (target_ulong)(rc + 1));
  1048 +#endif
  1049 + retcode = ((target_ulong)rc) + thumb;
  1050 + }
  1051 +
  1052 + env->regs[0] = usig;
  1053 + env->regs[13] = (target_ulong)frame;
  1054 + env->regs[14] = retcode;
  1055 + env->regs[15] = handler & (thumb ? ~1 : ~3);
  1056 +
  1057 +#ifdef TARGET_CONFIG_CPU_32
  1058 + env->cpsr = cpsr;
  1059 +#endif
  1060 +
  1061 + return 0;
  1062 +}
  1063 +
  1064 +static void setup_frame(int usig, struct emulated_sigaction *ka,
  1065 + target_sigset_t *set, CPUState *regs)
  1066 +{
  1067 + struct sigframe *frame = get_sigframe(ka, regs, sizeof(*frame));
  1068 + int err = 0;
  1069 +
  1070 + err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]);
  1071 +
  1072 + if (TARGET_NSIG_WORDS > 1) {
  1073 + err |= __copy_to_user(frame->extramask, &set->sig[1],
  1074 + sizeof(frame->extramask));
  1075 + }
  1076 +
  1077 + if (err == 0)
  1078 + err = setup_return(regs, ka, &frame->retcode, frame, usig);
  1079 + // return err;
  1080 +}
  1081 +
  1082 +static void setup_rt_frame(int usig, struct emulated_sigaction *ka,
  1083 + target_siginfo_t *info,
  1084 + target_sigset_t *set, CPUState *env)
  1085 +{
  1086 + struct rt_sigframe *frame = get_sigframe(ka, env, sizeof(*frame));
  1087 + int err = 0;
  1088 +
  1089 +#if 0
  1090 + if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
  1091 + return 1;
  1092 +#endif
  1093 + __put_user_error(&frame->info, (target_ulong *)&frame->pinfo, err);
  1094 + __put_user_error(&frame->uc, (target_ulong *)&frame->puc, err);
  1095 + err |= copy_siginfo_to_user(&frame->info, info);
  1096 +
  1097 + /* Clear all the bits of the ucontext we don't use. */
  1098 + err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
  1099 +
  1100 + err |= setup_sigcontext(&frame->uc.uc_mcontext, /*&frame->fpstate,*/
  1101 + env, set->sig[0]);
  1102 + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
  1103 +
  1104 + if (err == 0)
  1105 + err = setup_return(env, ka, &frame->retcode, frame, usig);
  1106 +
  1107 + if (err == 0) {
  1108 + /*
  1109 + * For realtime signals we must also set the second and third
  1110 + * arguments for the signal handler.
  1111 + * -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06
  1112 + */
  1113 + env->regs[1] = (target_ulong)frame->pinfo;
  1114 + env->regs[2] = (target_ulong)frame->puc;
  1115 + }
  1116 +
  1117 + // return err;
  1118 +}
  1119 +
  1120 +static int
  1121 +restore_sigcontext(CPUState *env, struct target_sigcontext *sc)
  1122 +{
  1123 + int err = 0;
  1124 +
  1125 + __get_user_error(env->regs[0], &sc->arm_r0, err);
  1126 + __get_user_error(env->regs[1], &sc->arm_r1, err);
  1127 + __get_user_error(env->regs[2], &sc->arm_r2, err);
  1128 + __get_user_error(env->regs[3], &sc->arm_r3, err);
  1129 + __get_user_error(env->regs[4], &sc->arm_r4, err);
  1130 + __get_user_error(env->regs[5], &sc->arm_r5, err);
  1131 + __get_user_error(env->regs[6], &sc->arm_r6, err);
  1132 + __get_user_error(env->regs[7], &sc->arm_r7, err);
  1133 + __get_user_error(env->regs[8], &sc->arm_r8, err);
  1134 + __get_user_error(env->regs[9], &sc->arm_r9, err);
  1135 + __get_user_error(env->regs[10], &sc->arm_r10, err);
  1136 + __get_user_error(env->regs[11], &sc->arm_fp, err);
  1137 + __get_user_error(env->regs[12], &sc->arm_ip, err);
  1138 + __get_user_error(env->regs[13], &sc->arm_sp, err);
  1139 + __get_user_error(env->regs[14], &sc->arm_lr, err);
  1140 + __get_user_error(env->regs[15], &sc->arm_pc, err);
  1141 +#ifdef TARGET_CONFIG_CPU_32
  1142 + __get_user_error(env->cpsr, &sc->arm_cpsr, err);
  1143 +#endif
  1144 +
  1145 + err |= !valid_user_regs(env);
  1146 +
  1147 + return err;
  1148 +}
  1149 +
  1150 +long do_sigreturn(CPUState *env)
  1151 +{
  1152 + struct sigframe *frame;
  1153 + target_sigset_t set;
  1154 + sigset_t host_set;
  1155 +
  1156 + /*
  1157 + * Since we stacked the signal on a 64-bit boundary,
  1158 + * then 'sp' should be word aligned here. If it's
  1159 + * not, then the user is trying to mess with us.
  1160 + */
  1161 + if (env->regs[13] & 7)
  1162 + goto badframe;
  1163 +
  1164 + frame = (struct sigframe *)env->regs[13];
  1165 +
  1166 +#if 0
  1167 + if (verify_area(VERIFY_READ, frame, sizeof (*frame)))
  1168 + goto badframe;
  1169 +#endif
  1170 + if (__get_user(set.sig[0], &frame->sc.oldmask)
  1171 + || (TARGET_NSIG_WORDS > 1
  1172 + && __copy_from_user(&set.sig[1], &frame->extramask,
  1173 + sizeof(frame->extramask))))
  1174 + goto badframe;
  1175 +
  1176 + target_to_host_sigset(&host_set, &set);
  1177 + sigprocmask(SIG_SETMASK, &host_set, NULL);
  1178 +
  1179 + if (restore_sigcontext(env, &frame->sc))
  1180 + goto badframe;
  1181 +
  1182 +#if 0
  1183 + /* Send SIGTRAP if we're single-stepping */
  1184 + if (ptrace_cancel_bpt(current))
  1185 + send_sig(SIGTRAP, current, 1);
  1186 +#endif
  1187 + return env->regs[0];
  1188 +
  1189 +badframe:
  1190 + force_sig(SIGSEGV /* , current */);
  1191 + return 0;
  1192 +}
  1193 +
  1194 +long do_rt_sigreturn(CPUState *env)
  1195 +{
  1196 + struct rt_sigframe *frame;
  1197 + target_sigset_t set;
  1198 + sigset_t host_set;
  1199 +
  1200 + /*
  1201 + * Since we stacked the signal on a 64-bit boundary,
  1202 + * then 'sp' should be word aligned here. If it's
  1203 + * not, then the user is trying to mess with us.
  1204 + */
  1205 + if (env->regs[13] & 7)
  1206 + goto badframe;
  1207 +
  1208 + frame = (struct rt_sigframe *)env->regs[13];
  1209 +
  1210 +#if 0
  1211 + if (verify_area(VERIFY_READ, frame, sizeof (*frame)))
  1212 + goto badframe;
  1213 +#endif
  1214 + if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
  1215 + goto badframe;
  1216 +
  1217 + target_to_host_sigset(&host_set, &set);
  1218 + sigprocmask(SIG_SETMASK, &host_set, NULL);
  1219 +
  1220 + if (restore_sigcontext(env, &frame->uc.uc_mcontext))
  1221 + goto badframe;
  1222 +
  1223 +#if 0
  1224 + /* Send SIGTRAP if we're single-stepping */
  1225 + if (ptrace_cancel_bpt(current))
  1226 + send_sig(SIGTRAP, current, 1);
  1227 +#endif
  1228 + return env->regs[0];
  1229 +
  1230 +badframe:
  1231 + force_sig(SIGSEGV /* , current */);
  1232 + return 0;
  1233 +}
  1234 +
828 1235 #else
829 1236  
830 1237 static void setup_frame(int sig, struct emulated_sigaction *ka,
... ...
syscall-arm.h
... ... @@ -25,3 +25,4 @@ struct target_pt_regs {
25 25 #define ARM_r0 uregs[0]
26 26 #define ARM_ORIG_r0 uregs[17]
27 27  
  28 +#define ARM_SYSCALL_BASE 0x900000
... ...