Annotation of sys/arch/arm/arm/sig_machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: sig_machdep.c,v 1.2 2004/02/16 15:40:00 miod Exp $ */
! 2: /* $NetBSD: sig_machdep.c,v 1.22 2003/10/08 00:28:41 thorpej Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1994-1998 Mark Brinicombe.
! 6: * Copyright (c) 1994 Brini.
! 7: * All rights reserved.
! 8: *
! 9: * This code is derived from software written for Brini by Mark Brinicombe
! 10: *
! 11: * Redistribution and use in source and binary forms, with or without
! 12: * modification, are permitted provided that the following conditions
! 13: * are met:
! 14: * 1. Redistributions of source code must retain the above copyright
! 15: * notice, this list of conditions and the following disclaimer.
! 16: * 2. Redistributions in binary form must reproduce the above copyright
! 17: * notice, this list of conditions and the following disclaimer in the
! 18: * documentation and/or other materials provided with the distribution.
! 19: * 3. All advertising materials mentioning features or use of this software
! 20: * must display the following acknowledgement:
! 21: * This product includes software developed by Mark Brinicombe
! 22: * for the NetBSD Project.
! 23: * 4. The name of the company nor the name of the author may be used to
! 24: * endorse or promote products derived from this software without specific
! 25: * prior written permission.
! 26: *
! 27: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
! 28: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
! 29: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 30: * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
! 31: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 32: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 33: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 34: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 35: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 36: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 37: * SUCH DAMAGE.
! 38: *
! 39: * Machine dependant functions for kernel setup
! 40: *
! 41: * Created : 17/09/94
! 42: */
! 43:
! 44: #include <sys/param.h>
! 45:
! 46: #include <sys/mount.h> /* XXX only needed by syscallargs.h */
! 47: #include <sys/proc.h>
! 48: #include <sys/signal.h>
! 49: #include <sys/signalvar.h>
! 50: #include <sys/syscallargs.h>
! 51: #include <sys/systm.h>
! 52: #include <sys/user.h>
! 53:
! 54: #include <arm/armreg.h>
! 55:
! 56: #include <machine/cpu.h>
! 57: #include <machine/frame.h>
! 58: #include <machine/pcb.h>
! 59: #ifndef acorn26
! 60: #include <arm/cpufunc.h>
! 61: #endif
! 62:
! 63: static __inline struct trapframe *
! 64: process_frame(struct proc *p)
! 65: {
! 66:
! 67: return p->p_addr->u_pcb.pcb_tf;
! 68: }
! 69:
! 70: void *getframe(struct proc *p, int sig, int *onstack);
! 71:
! 72:
! 73: /*
! 74: * Send an interrupt to process.
! 75: *
! 76: * Stack is set up to allow sigcode stored
! 77: * in u. to call routine, followed by kcall
! 78: * to sigreturn routine below. After sigreturn
! 79: * resets the signal mask, the stack, and the
! 80: * frame pointer, it returns to the user specified pc.
! 81: */
! 82: void
! 83: sendsig(sig_t catcher, int sig, int returnmask, u_long code, int type,
! 84: union sigval val)
! 85: {
! 86: struct proc *p = curproc;
! 87: struct trapframe *tf;
! 88: struct sigframe *fp, frame;
! 89: struct sigacts *psp = p->p_sigacts;
! 90: int oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
! 91: int onstack = 0;
! 92:
! 93: tf = process_frame(p);
! 94:
! 95: /* Do we need to jump onto the signal stack? */
! 96:
! 97: /* Allocate space for the signal handler context. */
! 98: if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
! 99: (psp->ps_sigonstack & sigmask(sig))) {
! 100: onstack = 1;
! 101: fp = (struct sigframe *)((caddr_t)psp->ps_sigstk.ss_sp +
! 102: psp->ps_sigstk.ss_size);
! 103: } else
! 104: fp = (struct sigframe *)tf->tf_usr_sp;
! 105: /* make room on the stack */
! 106: fp--;
! 107:
! 108: /* make the stack aligned */
! 109: fp = (void *)STACKALIGN(fp);
! 110:
! 111: /* Build stack frame for signal trampoline. */
! 112: frame.sf_signum = sig;
! 113: frame.sf_sip = NULL;
! 114: frame.sf_scp = &fp->sf_sc;
! 115: frame.sf_handler = catcher;
! 116:
! 117: /* Save register context. */
! 118: frame.sf_sc.sc_r0 = tf->tf_r0;
! 119: frame.sf_sc.sc_r1 = tf->tf_r1;
! 120: frame.sf_sc.sc_r2 = tf->tf_r2;
! 121: frame.sf_sc.sc_r3 = tf->tf_r3;
! 122: frame.sf_sc.sc_r4 = tf->tf_r4;
! 123: frame.sf_sc.sc_r5 = tf->tf_r5;
! 124: frame.sf_sc.sc_r6 = tf->tf_r6;
! 125: frame.sf_sc.sc_r7 = tf->tf_r7;
! 126: frame.sf_sc.sc_r8 = tf->tf_r8;
! 127: frame.sf_sc.sc_r9 = tf->tf_r9;
! 128: frame.sf_sc.sc_r10 = tf->tf_r10;
! 129: frame.sf_sc.sc_r11 = tf->tf_r11;
! 130: frame.sf_sc.sc_r12 = tf->tf_r12;
! 131: frame.sf_sc.sc_usr_sp = tf->tf_usr_sp;
! 132: frame.sf_sc.sc_usr_lr = tf->tf_usr_lr;
! 133: frame.sf_sc.sc_svc_lr = tf->tf_svc_lr;
! 134: frame.sf_sc.sc_pc = tf->tf_pc;
! 135: frame.sf_sc.sc_spsr = tf->tf_spsr;
! 136:
! 137: /* Save signal stack. */
! 138: frame.sf_sc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
! 139:
! 140: /* Save signal mask. */
! 141: frame.sf_sc.sc_mask = returnmask;
! 142:
! 143: if (psp->ps_siginfo & sigmask(sig)) {
! 144: frame.sf_sip = &fp->sf_si;
! 145: initsiginfo(&frame.sf_si, sig, code, type, val);
! 146: }
! 147:
! 148: if (copyout(&frame, fp, sizeof(frame)) != 0) {
! 149: /*
! 150: * Process has trashed its stack; give it an illegal
! 151: * instruction to halt it in its tracks.
! 152: */
! 153: sigexit(p, SIGILL);
! 154: /* NOTREACHED */
! 155: }
! 156:
! 157: /*
! 158: * Build context to run handler in. We invoke the handler
! 159: * directly, only returning via the trampoline. Note the
! 160: * trampoline version numbers are coordinated with machine-
! 161: * dependent code in libc.
! 162: */
! 163:
! 164: /*
! 165: * this was all in the switch below, seemed daft to duplicate it, if
! 166: * we do a new trampoline version it might change then
! 167: */
! 168: tf->tf_r0 = sig;
! 169: tf->tf_r1 = (int)frame.sf_sip;
! 170: tf->tf_r2 = (int)frame.sf_scp;
! 171: tf->tf_pc = (int)frame.sf_handler;
! 172: tf->tf_usr_sp = (int)fp;
! 173:
! 174: tf->tf_usr_lr = (int)p->p_sigcode;
! 175: /* XXX This should not be needed. */
! 176: cpu_icache_sync_all();
! 177:
! 178: /* Remember that we're now on the signal stack. */
! 179: if (onstack)
! 180: psp->ps_sigstk.ss_flags |= SS_ONSTACK;
! 181: }
! 182:
! 183: #if 0
! 184: void *
! 185: getframe(struct proc *p, int sig, int *onstack)
! 186: {
! 187: struct sigctx *ctx = &p->p_sigctx;
! 188: struct trapframe *tf = process_frame(l);
! 189:
! 190: /* Do we need to jump onto the signal stack? */
! 191: *onstack = (ctx->ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0
! 192: && (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
! 193: if (*onstack)
! 194: return (char *)ctx->ps_sigstk.ss_sp + ctx->ps_sigstk.ss_size;
! 195: return (void *)tf->tf_usr_sp;
! 196: }
! 197: #endif
! 198:
! 199:
! 200: /*
! 201: * System call to cleanup state after a signal
! 202: * has been taken. Reset signal mask and
! 203: * stack state from context left by sendsig (above).
! 204: * Return to previous pc and psl as specified by
! 205: * context left by sendsig. Check carefully to
! 206: * make sure that the user has not modified the
! 207: * psr to gain improper privileges or to cause
! 208: * a machine fault.
! 209: */
! 210:
! 211: int
! 212: sys_sigreturn(struct proc *p, void *v, register_t *retval)
! 213: {
! 214: struct sys_sigreturn_args /* {
! 215: syscallarg(struct sigcontext *) sigcntxp;
! 216: } */ *uap = v;
! 217: struct sigcontext *scp, context;
! 218: struct trapframe *tf;
! 219: struct sigacts *psp = p->p_sigacts;
! 220:
! 221: /*
! 222: * we do a rather scary test in userland
! 223: */
! 224: if (v == NULL)
! 225: return (EFAULT);
! 226:
! 227: /*
! 228: * The trampoline code hands us the context.
! 229: * It is unsafe to keep track of it ourselves, in the event that a
! 230: * program jumps out of a signal handler.
! 231: */
! 232: scp = SCARG(uap, sigcntxp);
! 233: if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0)
! 234: return (EFAULT);
! 235:
! 236: /*
! 237: * Make sure the processor mode has not been tampered with and
! 238: * interrupts have not been disabled.
! 239: */
! 240: #ifdef __PROG32
! 241: if ((context.sc_spsr & PSR_MODE) != PSR_USR32_MODE ||
! 242: (context.sc_spsr & (I32_bit | F32_bit)) != 0)
! 243: return (EINVAL);
! 244: #else /* __PROG26 */
! 245: if ((context.sc_pc & R15_MODE) != R15_MODE_USR ||
! 246: (context.sc_pc & (R15_IRQ_DISABLE | R15_FIQ_DISABLE)) != 0)
! 247: return EINVAL;
! 248: #endif
! 249:
! 250: /* Restore register context. */
! 251: tf = process_frame(p);
! 252: tf->tf_r0 = context.sc_r0;
! 253: tf->tf_r1 = context.sc_r1;
! 254: tf->tf_r2 = context.sc_r2;
! 255: tf->tf_r3 = context.sc_r3;
! 256: tf->tf_r4 = context.sc_r4;
! 257: tf->tf_r5 = context.sc_r5;
! 258: tf->tf_r6 = context.sc_r6;
! 259: tf->tf_r7 = context.sc_r7;
! 260: tf->tf_r8 = context.sc_r8;
! 261: tf->tf_r9 = context.sc_r9;
! 262: tf->tf_r10 = context.sc_r10;
! 263: tf->tf_r11 = context.sc_r11;
! 264: tf->tf_r12 = context.sc_r12;
! 265: tf->tf_usr_sp = context.sc_usr_sp;
! 266: tf->tf_usr_lr = context.sc_usr_lr;
! 267: tf->tf_svc_lr = context.sc_svc_lr;
! 268: tf->tf_pc = context.sc_pc;
! 269: tf->tf_spsr = context.sc_spsr;
! 270:
! 271: /* Restore signal stack. */
! 272: if (context.sc_onstack & SS_ONSTACK)
! 273: psp->ps_sigstk.ss_flags |= SS_ONSTACK;
! 274: else
! 275: psp->ps_sigstk.ss_flags &= ~SS_ONSTACK;
! 276:
! 277: /* Restore signal mask. */
! 278: #if 0
! 279: (void) sigprocmask1(p, SIG_SETMASK, &context.sc_mask, 0);
! 280: #else
! 281: p->p_sigmask = context.sc_mask & ~sigcantmask;
! 282: #endif
! 283:
! 284: return (EJUSTRETURN);
! 285: }
! 286:
! 287: #if 0
! 288: void
! 289: cpu_getmcontext(p, mcp, flags)
! 290: struct proc *p;
! 291: mcontext_t *mcp;
! 292: unsigned int *flags;
! 293: {
! 294: struct trapframe *tf = process_frame(p);
! 295: __greg_t *gr = mcp->__gregs;
! 296: __greg_t ras_pc;
! 297:
! 298: /* Save General Register context. */
! 299: gr[_REG_R0] = tf->tf_r0;
! 300: gr[_REG_R1] = tf->tf_r1;
! 301: gr[_REG_R2] = tf->tf_r2;
! 302: gr[_REG_R3] = tf->tf_r3;
! 303: gr[_REG_R4] = tf->tf_r4;
! 304: gr[_REG_R5] = tf->tf_r5;
! 305: gr[_REG_R6] = tf->tf_r6;
! 306: gr[_REG_R7] = tf->tf_r7;
! 307: gr[_REG_R8] = tf->tf_r8;
! 308: gr[_REG_R9] = tf->tf_r9;
! 309: gr[_REG_R10] = tf->tf_r10;
! 310: gr[_REG_R11] = tf->tf_r11;
! 311: gr[_REG_R12] = tf->tf_r12;
! 312: gr[_REG_SP] = tf->tf_usr_sp;
! 313: gr[_REG_LR] = tf->tf_usr_lr;
! 314: gr[_REG_PC] = tf->tf_pc;
! 315: gr[_REG_CPSR] = tf->tf_spsr;
! 316:
! 317: if ((ras_pc = (__greg_t)ras_lookup(l->l_proc,
! 318: (caddr_t) gr[_REG_PC])) != -1)
! 319: gr[_REG_PC] = ras_pc;
! 320:
! 321: *flags |= _UC_CPU;
! 322:
! 323: #ifdef ARMFPE
! 324: /* Save Floating Point Register context. */
! 325: arm_fpe_getcontext(p, (struct fpreg *)(void *)&mcp->fpregs);
! 326: *flags |= _UC_FPU;
! 327: #endif
! 328: }
! 329:
! 330: int
! 331: cpu_setmcontext(p, mcp, flags)
! 332: struct proc *p;
! 333: const mcontext_t *mcp;
! 334: unsigned int flags;
! 335: {
! 336: struct trapframe *tf = process_frame(l);
! 337: __greg_t *gr = mcp->__gregs;
! 338:
! 339: if ((flags & _UC_CPU) != 0) {
! 340: /* Restore General Register context. */
! 341: /* Make sure the processor mode has not been tampered with. */
! 342: #ifdef PROG32
! 343: if ((gr[_REG_CPSR] & PSR_MODE) != PSR_USR32_MODE ||
! 344: (gr[_REG_CPSR] & (I32_bit | F32_bit)) != 0)
! 345: return (EINVAL);
! 346: #else /* PROG26 */
! 347: if ((gr[_REG_PC] & R15_MODE) != R15_MODE_USR ||
! 348: (gr[_REG_PC] & (R15_IRQ_DISABLE | R15_FIQ_DISABLE)) != 0)
! 349: return (EINVAL);
! 350: #endif
! 351:
! 352: tf->tf_r0 = gr[_REG_R0];
! 353: tf->tf_r1 = gr[_REG_R1];
! 354: tf->tf_r2 = gr[_REG_R2];
! 355: tf->tf_r3 = gr[_REG_R3];
! 356: tf->tf_r4 = gr[_REG_R4];
! 357: tf->tf_r5 = gr[_REG_R5];
! 358: tf->tf_r6 = gr[_REG_R6];
! 359: tf->tf_r7 = gr[_REG_R7];
! 360: tf->tf_r8 = gr[_REG_R8];
! 361: tf->tf_r9 = gr[_REG_R9];
! 362: tf->tf_r10 = gr[_REG_R10];
! 363: tf->tf_r11 = gr[_REG_R11];
! 364: tf->tf_r12 = gr[_REG_R12];
! 365: tf->tf_usr_sp = gr[_REG_SP];
! 366: tf->tf_usr_lr = gr[_REG_LR];
! 367: tf->tf_pc = gr[_REG_PC];
! 368: tf->tf_spsr = gr[_REG_CPSR];
! 369: }
! 370:
! 371: #ifdef ARMFPE
! 372: if ((flags & _UC_FPU) != 0) {
! 373: /* Restore Floating Point Register context. */
! 374: arm_fpe_setcontext(p, (struct fpreg *)(void *)&mcp->__fpregs);
! 375: }
! 376: #endif
! 377: if (flags & _UC_SETSTACK)
! 378: l->l_proc->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
! 379: if (flags & _UC_CLRSTACK)
! 380: l->l_proc->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK;
! 381:
! 382: return (0);
! 383: }
! 384: #endif
CVSweb