1/* 2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Copyright (c) 1992 NeXT, Inc. 30 * 31 * HISTORY 32 * 13 May 1992 ? at NeXT 33 * Created. 34 */ 35 36#include <mach/mach_types.h> 37#include <mach/exception.h> 38#include <kern/thread.h> 39#include <sys/systm.h> 40#include <sys/param.h> 41#include <sys/proc_internal.h> 42#include <sys/user.h> 43#include <sys/sysproto.h> 44#include <sys/sysent.h> 45#include <sys/ucontext.h> 46#include <sys/wait.h> 47#include <mach/thread_act.h> /* for thread_abort_safely */ 48#include <mach/thread_status.h> 49#include <mach/arm/thread_state.h> 50#include <mach/arm/thread_status.h> 51#include <arm/machine_routines.h> 52#include <machine/pal_routines.h> 53#include <sys/kdebug.h> 54#include <sys/sdt.h> 55 56#define C_32_STK_ALIGN 16 57#define C_32_PARAMSAVE_LEN 32 58#define C_32_LINKAGE_LEN 48 59 60#define TRUNC_DOWN32(a,c) ((((uint32_t)a)-(c)) & ((uint32_t)(-(c)))) 61 62/* 63 * The stack layout possibilities (info style); This needs to mach with signal trampoline code 64 * 65 * Traditional: 1 66 * 32bit context 30 67 */ 68#define UC_TRAD 1 69#define UC_FLAVOR 30 70 71 /* The following are valid mcontext sizes */ 72#define UC_FLAVOR_SIZE ((ARM_THREAD_STATE_COUNT + ARM_EXCEPTION_STATE_COUNT + ARM_VFP_STATE_COUNT) * sizeof(int)) 73 74/* 75 * Send an interrupt to process. 76 * 77 * Stack is set up to allow sigcode stored 78 * in u. to call routine, followed by chmk 79 * to sigreturn routine below. After sigreturn 80 * resets the signal mask, the stack, the frame 81 * pointer, and the argument pointer, it returns 82 * to the user specified pc, psl. 83 */ 84 85void sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused uint32_t code) 86{ 87 user_addr_t ua_sp; 88 user_addr_t ua_sip; 89 user_addr_t trampact; 90 user_addr_t ua_uctxp; 91 user_addr_t ua_mctxp; 92 user_siginfo_t sinfo32; 93 94 struct uthread *ut; 95 struct mcontext mctx32; 96 struct user_ucontext32 uctx32; 97 struct sigacts *ps = p->p_sigacts; 98 99 void *state; 100 arm_thread_state_t *tstate32; 101 mach_msg_type_number_t state_count; 102 103 int stack_size = 0; 104 int infostyle = UC_TRAD; 105 int oonstack, flavor, error; 106 107 proc_unlock(p); 108 109 thread_t thread = current_thread(); 110 ut = get_bsdthread_info(thread); 111 112 /* 113 * Set up thread state info. 114 */ 115 flavor = ARM_THREAD_STATE; 116 state = (void *)&mctx32.ss; 117 state_count = ARM_THREAD_STATE_COUNT; 118 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS) 119 goto bad; 120 121 flavor = ARM_EXCEPTION_STATE; 122 state = (void *)&mctx32.es; 123 state_count = ARM_EXCEPTION_STATE_COUNT; 124 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS) 125 goto bad; 126 127 flavor = ARM_VFP_STATE; 128 state = (void *)&mctx32.fs; 129 state_count = ARM_VFP_STATE_COUNT; 130 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS) 131 goto bad; 132 133 tstate32 = &mctx32.ss; 134 135 /* 136 * Set the signal style. 137 */ 138 if (p->p_sigacts->ps_siginfo & sigmask(sig)) 139 infostyle = UC_FLAVOR; 140 141 /* 142 * Get the signal disposition. 143 */ 144 trampact = ps->ps_trampact[sig]; 145 146 /* 147 * Figure out where our new stack lives. 148 */ 149 oonstack = ut->uu_sigstk.ss_flags & SA_ONSTACK; 150 if ((ut->uu_flag & UT_ALTSTACK) && !oonstack && (ps->ps_sigonstack & sigmask(sig))) { 151 ua_sp = ut->uu_sigstk.ss_sp; 152 ua_sp += ut->uu_sigstk.ss_size; 153 stack_size = ut->uu_sigstk.ss_size; 154 ut->uu_sigstk.ss_flags |= SA_ONSTACK; 155 } else { 156 ua_sp = tstate32->sp; 157 } 158 159 /* 160 * Set up the stack. 161 */ 162 ua_sp -= UC_FLAVOR_SIZE; 163 ua_mctxp = ua_sp; 164 165 ua_sp -= sizeof(struct user_ucontext32); 166 ua_uctxp = ua_sp; 167 168 ua_sp -= sizeof(siginfo_t); 169 ua_sip = ua_sp; 170 171 /* 172 * Align the stack pointer. 173 */ 174 ua_sp = TRUNC_DOWN32(ua_sp, C_32_STK_ALIGN); 175 176 /* 177 * Build the signal context to be used by sigreturn. 178 */ 179 uctx32.uc_onstack = oonstack; 180 uctx32.uc_sigmask = mask; 181 uctx32.uc_stack.ss_sp = ua_sp; 182 uctx32.uc_stack.ss_size = stack_size; 183 184 if (oonstack) 185 uctx32.uc_stack.ss_flags |= SS_ONSTACK; 186 187 uctx32.uc_link = 0; 188 189 uctx32.uc_mcsize = UC_FLAVOR_SIZE; 190 191 uctx32.uc_mcontext = ua_mctxp; 192 193 /* 194 * init siginfo 195 */ 196 bzero((caddr_t)&sinfo32, sizeof(user_siginfo_t)); 197 198 sinfo32.si_signo = sig; 199 sinfo32.pad[0] = tstate32->sp; 200 sinfo32.si_addr = tstate32->lr; 201 202 switch (sig) { 203 case SIGILL: 204 sinfo32.si_code = ILL_NOOP; 205 break; 206 case SIGFPE: 207 sinfo32.si_code = FPE_NOOP; 208 break; 209 case SIGBUS: 210 sinfo32.si_code = BUS_ADRALN; 211 break; 212 case SIGSEGV: 213 sinfo32.si_code = SEGV_ACCERR; 214 break; 215 default: 216 { 217 int status_and_exitcode; 218 219 /* 220 * All other signals need to fill out a minimum set of 221 * information for the siginfo structure passed into 222 * the signal handler, if SA_SIGINFO was specified. 223 * 224 * p->si_status actually contains both the status and 225 * the exit code; we save it off in its own variable 226 * for later breakdown. 227 */ 228 proc_lock(p); 229 sinfo32.si_pid = p->si_pid; 230 p->si_pid = 0; 231 status_and_exitcode = p->si_status; 232 p->si_status = 0; 233 sinfo32.si_uid = p->si_uid; 234 p->si_uid = 0; 235 sinfo32.si_code = p->si_code; 236 p->si_code = 0; 237 proc_unlock(p); 238 if (sinfo32.si_code == CLD_EXITED) { 239 if (WIFEXITED(status_and_exitcode)) 240 sinfo32.si_code = CLD_EXITED; 241 else if (WIFSIGNALED(status_and_exitcode)) { 242 if (WCOREDUMP(status_and_exitcode)) { 243 sinfo32.si_code = CLD_DUMPED; 244 status_and_exitcode = W_EXITCODE(status_and_exitcode, status_and_exitcode); 245 } else { 246 sinfo32.si_code = CLD_KILLED; 247 status_and_exitcode = W_EXITCODE(status_and_exitcode, status_and_exitcode); 248 } 249 } 250 } 251 /* 252 * The recorded status contains the exit code and the 253 * signal information, but the information to be passed 254 * in the siginfo to the handler is supposed to only 255 * contain the status, so we have to shift it out. 256 */ 257 sinfo32.si_status = WEXITSTATUS(status_and_exitcode); 258 break; 259 } 260 } 261 262 /* 263 * Copy out context info. 264 */ 265 if (copyout((caddr_t)&uctx32, ua_uctxp, sizeof(struct user_ucontext32))) 266 goto bad; 267 if (copyout((caddr_t)&sinfo32, ua_sip, sizeof(user_siginfo_t))) 268 goto bad; 269 if (copyout((caddr_t)&mctx32, ua_mctxp, sizeof(struct mcontext))) 270 goto bad; 271 if (copyout((caddr_t)&ua_uctxp, ua_sp, sizeof(user_addr_t))) 272 goto bad; 273 274 /* 275 * Set up regsiters for the trampoline. 276 */ 277 tstate32->r[0] = ua_catcher; 278 tstate32->r[1] = infostyle; 279 tstate32->r[2] = sig; 280 tstate32->r[3] = ua_sip; 281 tstate32->sp = ua_sp; 282 283 if (trampact & 0x01) { 284 tstate32->lr = trampact; 285 tstate32->cpsr = 0x10; /* ARM_FIQ_MODE */ 286 } else { 287 trampact &= ~0x01; 288 tstate32->lr = trampact; 289 tstate32->cpsr = 0x30; /* ARM_THUMB_MODE | ARM_USER_MODE */ 290 } 291 292 /* 293 * Call the trampoline. 294 */ 295 flavor = ARM_THREAD_STATE; 296 state_count = ARM_THREAD_STATE_COUNT; 297 state = (void *)tstate32; 298 if ((error = thread_setstatus(thread, flavor, (thread_state_t)state, state_count)) != KERN_SUCCESS) 299 panic("sendsig: thread_setstatus failed, ret = %08X\n", error); 300 301 proc_lock(p); 302 303 return; 304 305bad: 306 proc_lock(p); 307 SIGACTION(p, SIGILL) = SIG_DFL; 308 sig = sigmask(SIGILL); 309 p->p_sigignore &= ~sig; 310 p->p_sigcatch &= ~sig; 311 ut->uu_sigmask &= ~sig; 312 313 /* 314 * sendsig is called with signal lock held 315 */ 316 proc_unlock(p); 317 psignal_locked(p, SIGILL); 318 proc_lock(p); 319 320 return; 321} 322 323/* 324 * System call to cleanup state after a signal 325 * has been taken. Reset signal mask and 326 * stack state from context left by sendsig (above). 327 * Return to previous pc and psl as specified by 328 * context left by sendsig. Check carefully to 329 * make sure that the user has not modified the 330 * psl to gain improper priviledges or to cause 331 * a machine fault. 332 */ 333 334int sigreturn(struct proc *p, struct sigreturn_args *uap, __unused int *retval) 335{ 336 void *state; 337 int onstack = 0; 338 int error, flavor; 339 thread_t thread; 340 struct uthread *ut; 341 struct mcontext mctx32; 342 struct user_ucontext32 uctx32; 343 mach_msg_type_number_t state_count; 344 345 thread = current_thread(); 346 ut = get_bsdthread_info(thread); 347 348 /* 349 * Retrieve the user context that contains our machine context. 350 */ 351 if ((error = copyin(uap->uctx, (void *)&uctx32, sizeof(struct user_ucontext32)))) 352 return (error); 353 354 /* 355 * Validate that our machine context is the right size. 356 */ 357 if (uctx32.uc_mcsize != UC_FLAVOR_SIZE) 358 return (EINVAL); 359 360 /* 361 * Populate our machine context info that we need to restore. 362 */ 363 if ((error = copyin(uctx32.uc_mcontext, (void *)&mctx32, UC_FLAVOR_SIZE))) 364 return (error); 365 366 /* 367 * Restore the signal mask. 368 */ 369 ut->uu_sigmask = uctx32.uc_sigmask & ~sigcantmask; 370 371 /* 372 * Restore other signal info. 373 */ 374 if ((uctx32.uc_onstack & 0x01)) 375 ut->uu_sigstk.ss_flags |= SA_ONSTACK; 376 else 377 ut->uu_sigstk.ss_flags &= ~SA_ONSTACK; 378 379 if (ut->uu_siglist & ~ut->uu_sigmask) 380 signal_setast(thread); 381 382 /* 383 * Restore the states from our machine context. 384 * NOTE: we don't really need to check on infostyle since state restoring 385 * for UC_TRAD and UC_FLAVOR is identical on this architecture. 386 */ 387 flavor = ARM_THREAD_STATE; 388 state = (void *)&mctx32.ss; 389 state_count = ARM_THREAD_STATE_COUNT; 390 if (thread_setstatus(thread, flavor, (thread_state_t)state, state_count) != KERN_SUCCESS) 391 return (EINVAL); 392 393 flavor = ARM_VFP_STATE; 394 state = (void *)&mctx32.fs; 395 state_count = ARM_VFP_STATE_COUNT; 396 if (thread_setstatus(thread, flavor, (thread_state_t)state, state_count) != KERN_SUCCESS) 397 return (EINVAL); 398 399 return (EJUSTRETURN); 400} 401 402/* 403 * machine_exception() performs MD translation 404 * of a mach exception to a unix signal and code. 405 */ 406 407boolean_t machine_exception(int exception, mach_exception_code_t code, __unused mach_exception_subcode_t subcode, int *unix_signal, mach_exception_code_t * unix_code) 408{ 409 410 switch (exception) { 411 case EXC_BAD_ACCESS: 412 /* 413 * Map GP fault to SIGSEGV, otherwise defer to caller 414 */ 415 *unix_signal = SIGSEGV; 416 *unix_code = code; 417 return (FALSE); 418 case EXC_BAD_INSTRUCTION: 419 *unix_signal = SIGILL; 420 *unix_code = code; 421 break; 422 case EXC_ARITHMETIC: 423 *unix_signal = SIGFPE; 424 *unix_code = code; 425 break; 426 case EXC_SOFTWARE: 427 *unix_signal = SIGTRAP; 428 *unix_code = code; 429 break; 430 default: 431 return (FALSE); 432 } 433 434 return (TRUE); 435} 436