// SPDX-License-Identifier: GPL-2.0-or-later /* * Common signal handling code for both 32 and 64 bits * * Copyright (c) 2007 Benjamin Herrenschmidt, IBM Corporation * Extracted from signal_32.c and signal_64.c
*/
/* save FPR copy to local buffer then write to the thread_struct */ for (i = 0; i < (ELF_NFPREG - 1) ; i++)
buf[i] = task->thread.TS_FPR(i);
buf[i] = task->thread.fp_state.fpscr; return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double));
}
/* save FPR copy to local buffer then write to the thread_struct */ for (i = 0; i < ELF_NVSRHALFREG; i++)
buf[i] = task->thread.fp_state.fpr[i][TS_VSRLOWOFFSET]; return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double));
}
/* save FPR copy to local buffer then write to the thread_struct */ for (i = 0; i < (ELF_NFPREG - 1) ; i++)
buf[i] = task->thread.TS_CKFPR(i);
buf[i] = task->thread.ckfp_state.fpscr; return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double));
}
/* save FPR copy to local buffer then write to the thread_struct */ for (i = 0; i < ELF_NVSRHALFREG; i++)
buf[i] = task->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET]; return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double));
}
/* Default to using normal stack */ if (is_32)
oldsp = sp & 0x0ffffffffUL; else
oldsp = sp;
oldsp = sigsp(oldsp, ksig);
newsp = (oldsp - frame_size) & ~0xFUL;
return (void __user *)newsp;
}
staticvoid check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
{ unsignedlong ret = regs->gpr[3]; int restart = 1;
/* syscall ? */ if (!trap_is_syscall(regs)) return;
if (trap_norestart(regs)) return;
/* error signalled ? */ if (trap_is_scv(regs)) { /* 32-bit compat mode sign extend? */ if (!IS_ERR_VALUE(ret)) return;
ret = -ret;
} elseif (!(regs->ccr & 0x10000000)) { return;
}
switch (ret) { case ERESTART_RESTARTBLOCK: case ERESTARTNOHAND: /* ERESTARTNOHAND means that the syscall should only be * restarted if there was no handler for the signal, and since * we only get here if there is a handler, we dont restart.
*/
restart = !has_handler; break; case ERESTARTSYS: /* ERESTARTSYS means to restart the syscall if there is no * handler or the handler was registered with SA_RESTART
*/
restart = !has_handler || (ka->sa.sa_flags & SA_RESTART) != 0; break; case ERESTARTNOINTR: /* ERESTARTNOINTR means that the syscall should be * called again after the signal handler returns.
*/ break; default: return;
} if (restart) { if (ret == ERESTART_RESTARTBLOCK)
regs->gpr[0] = __NR_restart_syscall; else
regs->gpr[3] = regs->orig_gpr3;
regs_add_return_ip(regs, -4);
regs->result = 0;
} else { if (trap_is_scv(regs)) {
regs->result = -EINTR;
regs->gpr[3] = -EINTR;
} else {
regs->result = -EINTR;
regs->gpr[3] = EINTR;
regs->ccr |= 0x10000000;
}
}
}
/* Is there any syscall restart business here ? */
check_syscall_restart(tsk->thread.regs, &ksig.ka, ksig.sig > 0);
if (ksig.sig <= 0) { /* No signal to deliver -- put the saved sigmask back */
restore_saved_sigmask();
set_trap_norestart(tsk->thread.regs); return; /* no signals delivered */
}
/* * Reenable the DABR before delivering the signal to * user space. The DABR will have been cleared if it * triggered inside the kernel.
*/ if (!IS_ENABLED(CONFIG_PPC_ADV_DEBUG_REGS)) { int i;
for (i = 0; i < nr_wp_slots(); i++) { if (tsk->thread.hw_brk[i].address && tsk->thread.hw_brk[i].type)
__set_breakpoint(i, &tsk->thread.hw_brk[i]);
}
}
/* Re-enable the breakpoints for the signal stack */
thread_change_pc(tsk, tsk->thread.regs);
rseq_signal_deliver(&ksig, tsk->thread.regs);
if (is_32bit_task()) { if (ksig.ka.sa.sa_flags & SA_SIGINFO)
ret = handle_rt_signal32(&ksig, oldset, tsk); else
ret = handle_signal32(&ksig, oldset, tsk);
} else {
ret = handle_rt_signal64(&ksig, oldset, tsk);
}
if (thread_info_flags & _TIF_NOTIFY_RESUME)
resume_user_mode_work(regs);
}
staticunsignedlong get_tm_stackpointer(struct task_struct *tsk)
{ /* When in an active transaction that takes a signal, we need to be * careful with the stack. It's possible that the stack has moved back * up after the tbegin. The obvious case here is when the tbegin is * called inside a function that returns before a tend. In this case, * the stack is part of the checkpointed transactional memory state. * If we write over this non transactionally or in suspend, we are in * trouble because if we get a tm abort, the program counter and stack * pointer will be back at the tbegin but our in memory stack won't be * valid anymore. * * To avoid this, when taking a signal in an active transaction, we * need to use the stack pointer from the checkpointed state, rather * than the speculated state. This ensures that the signal context * (written tm suspended) will be written below the stack required for * the rollback. The transaction is aborted because of the treclaim, * so any memory written between the tbegin and the signal will be * rolled back anyway. * * For signals taken in non-TM or suspended mode, we use the * normal/non-checkpointed stack pointer.
*/ struct pt_regs *regs = tsk->thread.regs; unsignedlong ret = regs->gpr[1];
if (MSR_TM_ACTIVE(regs->msr)) {
preempt_disable();
tm_reclaim_current(TM_CAUSE_SIGNAL); if (MSR_TM_TRANSACTIONAL(regs->msr))
ret = tsk->thread.ckpt_regs.gpr[1];
/* * If we treclaim, we must clear the current thread's TM bits * before re-enabling preemption. Otherwise we might be * preempted and have the live MSR[TS] changed behind our back * (tm_recheckpoint_new_task() would recheckpoint). Besides, we * enter the signal handler in non-transactional state.
*/
regs_set_return_msr(regs, regs->msr & ~MSR_TS_MASK);
preempt_enable();
} #endif return ret;
}
staticconstchar fm32[] = KERN_INFO "%s[%d]: bad frame in %s: %p nip %08lx lr %08lx\n"; staticconstchar fm64[] = KERN_INFO "%s[%d]: bad frame in %s: %p nip %016lx lr %016lx\n";
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.