void do_rt_sigreturn(struct pt_regs *regs) { struct rt_signal_frame *sf; unsigned long tpc, tnpc, tstate; __siginfo_fpu_t *fpu_save; sigset_t set; stack_t st; int err; synchronize_user_stack (); sf = (struct rt_signal_frame *) (regs->u_regs [UREG_FP] + STACK_BIAS); /* 1. Make sure we are not getting garbage from the user */ if (((unsigned long) sf) & 3) goto segv; err = get_user(tpc, &sf->regs.tpc); err |= __get_user(tnpc, &sf->regs.tnpc); if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) { tpc &= 0xffffffff; tnpc &= 0xffffffff; } err |= ((tpc | tnpc) & 3); /* 2. Restore the state */ err |= __get_user(regs->y, &sf->regs.y); err |= __get_user(tstate, &sf->regs.tstate); err |= copy_from_user(regs->u_regs, sf->regs.u_regs, sizeof(regs->u_regs)); /* User can only change condition codes in %tstate. */ regs->tstate &= ~(TSTATE_ICC); regs->tstate |= (tstate & TSTATE_ICC); err |= __get_user(fpu_save, &sf->fpu_save); if (fpu_save) err |= restore_fpu_state(regs, &sf->fpu_state); err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); err |= __copy_from_user(&st, &sf->stack, sizeof(stack_t)); if (err) goto segv; regs->tpc = tpc; regs->tnpc = tnpc; /* It is more difficult to avoid calling this function than to call it and ignore errors. */ do_sigaltstack(&st, NULL, (unsigned long)sf); sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sigmask_lock); current->blocked = set; recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); return; segv: send_sig(SIGSEGV, current, 1); }
void fpu_handler(void) { task_t* task = per_core(current_task); uint32_t core_id = CORE_ID; task->flags |= TASK_FPU_USED; if (!(task->flags & TASK_FPU_INIT)) { // use the FPU at the first time => Initialize FPU fpu_init(&task->fpu); task->flags |= TASK_FPU_INIT; } if (readyqueues[core_id].fpu_owner == task->id) return; spinlock_irqsave_lock(&readyqueues[core_id].lock); // did another already use the the FPU? => save FPU state if (readyqueues[core_id].fpu_owner) { save_fpu_state(&(task_table[readyqueues[core_id].fpu_owner].fpu)); task_table[readyqueues[core_id].fpu_owner].flags &= ~TASK_FPU_USED; } readyqueues[core_id].fpu_owner = task->id; spinlock_irqsave_unlock(&readyqueues[core_id].lock); restore_fpu_state(&task->fpu); }
void do_rt_sigreturn(struct pt_regs *regs) { struct rt_signal_frame __user *sf; unsigned long tpc, tnpc, tstate; __siginfo_fpu_t __user *fpu_save; sigset_t set; int err; /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; synchronize_user_stack (); sf = (struct rt_signal_frame __user *) (regs->u_regs [UREG_FP] + STACK_BIAS); /* 1. Make sure we are not getting garbage from the user */ if (((unsigned long) sf) & 3) goto segv; err = get_user(tpc, &sf->regs.tpc); err |= __get_user(tnpc, &sf->regs.tnpc); if (test_thread_flag(TIF_32BIT)) { tpc &= 0xffffffff; tnpc &= 0xffffffff; } err |= ((tpc | tnpc) & 3); /* 2. Restore the state */ err |= __get_user(regs->y, &sf->regs.y); err |= __get_user(tstate, &sf->regs.tstate); err |= copy_from_user(regs->u_regs, sf->regs.u_regs, sizeof(regs->u_regs)); /* User can only change condition codes and %asi in %tstate. */ regs->tstate &= ~(TSTATE_ASI | TSTATE_ICC | TSTATE_XCC); regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC)); err |= __get_user(fpu_save, &sf->fpu_save); if (fpu_save) err |= restore_fpu_state(regs, &sf->fpu_state); err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf); if (err) goto segv; regs->tpc = tpc; regs->tnpc = tnpc; sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); return; segv: force_sig(SIGSEGV, current); }
asmlinkage void do_rt_sigreturn(struct pt_regs *regs) { struct rt_signal_frame __user *sf; unsigned int psr, pc, npc; __siginfo_fpu_t __user *fpu_save; __siginfo_rwin_t __user *rwin_save; sigset_t set; int err; synchronize_user_stack(); sf = (struct rt_signal_frame __user *) regs->u_regs[UREG_FP]; if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) || (((unsigned long) sf) & 0x03)) goto segv; err = __get_user(pc, &sf->regs.pc); err |= __get_user(npc, &sf->regs.npc); err |= ((pc | npc) & 0x03); err |= __get_user(regs->y, &sf->regs.y); err |= __get_user(psr, &sf->regs.psr); err |= __copy_from_user(®s->u_regs[UREG_G1], &sf->regs.u_regs[UREG_G1], 15 * sizeof(u32)); regs->psr = (regs->psr & ~PSR_ICC) | (psr & PSR_ICC); /* Prevent syscall restart. */ pt_regs_clear_syscall(regs); err |= __get_user(fpu_save, &sf->fpu_save); if (!err && fpu_save) err |= restore_fpu_state(regs, fpu_save); err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); err |= restore_altstack(&sf->stack); if (err) goto segv; regs->pc = pc; regs->npc = npc; err |= __get_user(rwin_save, &sf->rwin_save); if (!err && rwin_save) { if (restore_rwin_state(rwin_save)) goto segv; } set_current_blocked(&set); return; segv: force_sig(SIGSEGV, current); }
static long restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) { int err = 0; /* sc_pt_regs is structured the same as the start of pt_regs */ err |= __copy_from_user(regs, &sc->sc_pt_regs, sizeof(struct pt_regs)); /* Restore the floating-point state. */ err |= restore_fpu_state(sc); return err; }
asmlinkage void do_sigreturn(struct pt_regs *regs) { struct signal_frame __user *sf; unsigned long up_psr, pc, npc; sigset_t set; __siginfo_fpu_t __user *fpu_save; __siginfo_rwin_t __user *rwin_save; int err; /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; synchronize_user_stack(); sf = (struct signal_frame __user *) regs->u_regs[UREG_FP]; /* 1. Make sure we are not getting garbage from the user */ if (!access_ok(VERIFY_READ, sf, sizeof(*sf))) goto segv_and_exit; if (((unsigned long) sf) & 3) goto segv_and_exit; err = __get_user(pc, &sf->info.si_regs.pc); err |= __get_user(npc, &sf->info.si_regs.npc); if ((pc | npc) & 3) goto segv_and_exit; /* 2. Restore the state */ up_psr = regs->psr; err |= __copy_from_user(regs, &sf->info.si_regs, sizeof(struct pt_regs)); /* User can only change condition codes and FPU enabling in %psr. */ regs->psr = (up_psr & ~(PSR_ICC | PSR_EF)) | (regs->psr & (PSR_ICC | PSR_EF)); /* Prevent syscall restart. */ pt_regs_clear_syscall(regs); err |= __get_user(fpu_save, &sf->fpu_save); if (fpu_save) err |= restore_fpu_state(regs, fpu_save); err |= __get_user(rwin_save, &sf->rwin_save); if (rwin_save) err |= restore_rwin_state(rwin_save); /* This is pretty much atomic, no amount locking would prevent * the races which exist anyways. */ err |= __get_user(set.sig[0], &sf->info.si_mask); err |= __copy_from_user(&set.sig[1], &sf->extramask, (_NSIG_WORDS-1) * sizeof(unsigned int)); if (err) goto segv_and_exit; sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); return; segv_and_exit: force_sig(SIGSEGV, current); }
asmlinkage void do_rt_sigreturn(struct pt_regs *regs) { struct rt_signal_frame __user *sf; unsigned int psr, pc, npc; __siginfo_fpu_t __user *fpu_save; __siginfo_rwin_t __user *rwin_save; mm_segment_t old_fs; sigset_t set; stack_t st; int err; synchronize_user_stack(); sf = (struct rt_signal_frame __user *) regs->u_regs[UREG_FP]; if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) || (((unsigned long) sf) & 0x03)) goto segv; err = __get_user(pc, &sf->regs.pc); err |= __get_user(npc, &sf->regs.npc); err |= ((pc | npc) & 0x03); err |= __get_user(regs->y, &sf->regs.y); err |= __get_user(psr, &sf->regs.psr); err |= __copy_from_user(®s->u_regs[UREG_G1], &sf->regs.u_regs[UREG_G1], 15 * sizeof(u32)); regs->psr = (regs->psr & ~PSR_ICC) | (psr & PSR_ICC); /* Prevent syscall restart. */ pt_regs_clear_syscall(regs); err |= __get_user(fpu_save, &sf->fpu_save); if (!err && fpu_save) err |= restore_fpu_state(regs, fpu_save); err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); err |= __copy_from_user(&st, &sf->stack, sizeof(stack_t)); if (err) goto segv; regs->pc = pc; regs->npc = npc; /* It is more difficult to avoid calling this function than to * call it and ignore errors. */ old_fs = get_fs(); set_fs(KERNEL_DS); do_sigaltstack((const stack_t __user *) &st, NULL, (unsigned long)sf); set_fs(old_fs); err |= __get_user(rwin_save, &sf->rwin_save); if (!err && rwin_save) { if (restore_rwin_state(rwin_save)) goto segv; } sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); return; segv: force_sig(SIGSEGV, current); }
void sigtrap_handler(HANDLER_ARGS) { unsigned int trap; os_context_t* os_context = (os_context_t *) context; #if 0 fprintf(stderr, "x86sigtrap: %8x %x\n", SC_PC(os_os_context), *(unsigned char *) (SC_PC(os_context) - 1)); fprintf(stderr, "sigtrap(%d %d %x)\n", signal, CODE(code), os_context); #endif if (single_stepping && (signal == SIGTRAP)) { #if 0 fprintf(stderr, "* Single step trap %p\n", single_stepping); #endif #ifdef SC_EFLAGS /* Disable single-stepping */ SC_EFLAGS(os_context) ^= 0x100; #else /* Un-install single step helper instructions. */ *(single_stepping - 3) = single_step_save1; *(single_stepping - 2) = single_step_save2; *(single_stepping - 1) = single_step_save3; DPRINTF(0, (stderr, "Uninstalling helper instructions\n")); #endif /* * Re-install the breakpoint if possible. */ if ((int) SC_PC(os_context) == (int) single_stepping + 1) fprintf(stderr, "* Breakpoint not re-install\n"); else { char *ptr = (char *) single_stepping; ptr[0] = BREAKPOINT_INST; /* x86 INT3 */ ptr[1] = trap_Breakpoint; } single_stepping = NULL; return; } /* This is just for info in case monitor wants to print an approx */ current_control_stack_pointer = (unsigned long *) SC_SP(os_context); RESTORE_FPU(os_context); /* * On entry %eip points just after the INT3 byte and aims at the * 'kind' value (eg trap_Cerror). For error-trap and Cerror-trap a * number of bytes will follow, the first is the length of the byte * arguments to follow. */ trap = *(unsigned char *) SC_PC(os_context); switch (trap) { case trap_PendingInterrupt: DPRINTF(0, (stderr, "<trap Pending Interrupt.>\n")); arch_skip_instruction(os_context); interrupt_handle_pending(os_context); break; case trap_Halt: { FPU_STATE(fpu_state); save_fpu_state(fpu_state); fake_foreign_function_call(os_context); lose("%%primitive halt called; the party is over.\n"); undo_fake_foreign_function_call(os_context); restore_fpu_state(fpu_state); arch_skip_instruction(os_context); break; } case trap_Error: case trap_Cerror: DPRINTF(0, (stderr, "<trap Error %x>\n", CODE(code))); interrupt_internal_error(signal, code, os_context, CODE(code) == trap_Cerror); break; case trap_Breakpoint: #if 0 fprintf(stderr, "*C break\n"); #endif SC_PC(os_context) -= 1; handle_breakpoint(signal, CODE(code), os_context); #if 0 fprintf(stderr, "*C break return\n"); #endif break; case trap_FunctionEndBreakpoint: SC_PC(os_context) -= 1; SC_PC(os_context) = (int) handle_function_end_breakpoint(signal, CODE(code), os_context); break; #ifdef trap_DynamicSpaceOverflowWarning case trap_DynamicSpaceOverflowWarning: interrupt_handle_space_overflow(SymbolFunction (DYNAMIC_SPACE_OVERFLOW_WARNING_HIT), os_context); break; #endif #ifdef trap_DynamicSpaceOverflowError case trap_DynamicSpaceOverflowError: interrupt_handle_space_overflow(SymbolFunction (DYNAMIC_SPACE_OVERFLOW_ERROR_HIT), os_context); break; #endif default: DPRINTF(0, (stderr, "[C--trap default %d %d %p]\n", signal, CODE(code), os_context)); interrupt_handle_now(signal, code, os_context); break; } }
void do_rt_sigreturn(struct pt_regs *regs) { unsigned long tpc, tnpc, tstate, ufp; struct rt_signal_frame __user *sf; __siginfo_fpu_t __user *fpu_save; __siginfo_rwin_t __user *rwin_save; sigset_t set; int err; /* Always make any pending restarted system calls return -EINTR */ current->restart_block.fn = do_no_restart_syscall; synchronize_user_stack (); sf = (struct rt_signal_frame __user *) (regs->u_regs [UREG_FP] + STACK_BIAS); /* 1. Make sure we are not getting garbage from the user */ if (invalid_frame_pointer(sf)) goto segv; if (get_user(ufp, &sf->regs.u_regs[UREG_FP])) goto segv; if ((ufp + STACK_BIAS) & 0x7) goto segv; err = __get_user(tpc, &sf->regs.tpc); err |= __get_user(tnpc, &sf->regs.tnpc); if (test_thread_flag(TIF_32BIT)) { tpc &= 0xffffffff; tnpc &= 0xffffffff; } err |= ((tpc | tnpc) & 3); /* 2. Restore the state */ err |= __get_user(regs->y, &sf->regs.y); err |= __get_user(tstate, &sf->regs.tstate); err |= copy_from_user(regs->u_regs, sf->regs.u_regs, sizeof(regs->u_regs)); /* User can only change condition codes and %asi in %tstate. */ regs->tstate &= ~(TSTATE_ASI | TSTATE_ICC | TSTATE_XCC); regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC)); err |= __get_user(fpu_save, &sf->fpu_save); if (!err && fpu_save) err |= restore_fpu_state(regs, fpu_save); err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); err |= restore_altstack(&sf->stack); if (err) goto segv; err |= __get_user(rwin_save, &sf->rwin_save); if (!err && rwin_save) { if (restore_rwin_state(rwin_save)) goto segv; } regs->tpc = tpc; regs->tnpc = tnpc; /* Prevent syscall restart. */ pt_regs_clear_syscall(regs); set_current_blocked(&set); return; segv: force_sig(SIGSEGV, current); }
void do_rt_sigreturn(struct pt_regs *regs) { struct rt_signal_frame __user *sf; unsigned long tpc, tnpc, tstate; __siginfo_fpu_t __user *fpu_save; __siginfo_rwin_t __user *rwin_save; sigset_t set; int err; current_thread_info()->restart_block.fn = do_no_restart_syscall; synchronize_user_stack (); sf = (struct rt_signal_frame __user *) (regs->u_regs [UREG_FP] + STACK_BIAS); if (((unsigned long) sf) & 3) goto segv; err = get_user(tpc, &sf->regs.tpc); err |= __get_user(tnpc, &sf->regs.tnpc); if (test_thread_flag(TIF_32BIT)) { tpc &= 0xffffffff; tnpc &= 0xffffffff; } err |= ((tpc | tnpc) & 3); err |= __get_user(regs->y, &sf->regs.y); err |= __get_user(tstate, &sf->regs.tstate); err |= copy_from_user(regs->u_regs, sf->regs.u_regs, sizeof(regs->u_regs)); regs->tstate &= ~(TSTATE_ASI | TSTATE_ICC | TSTATE_XCC); regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC)); err |= __get_user(fpu_save, &sf->fpu_save); if (!err && fpu_save) err |= restore_fpu_state(regs, fpu_save); err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf); if (err) goto segv; err |= __get_user(rwin_save, &sf->rwin_save); if (!err && rwin_save) { if (restore_rwin_state(rwin_save)) goto segv; } regs->tpc = tpc; regs->tnpc = tnpc; pt_regs_clear_syscall(regs); sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); return; segv: force_sig(SIGSEGV, current); }