/* the iWMMXt context must be 64 bit aligned */
kframe = (struct iwmmxt_sigframe *)((unsignedlong)(kbuf + 8) & ~7);
if (test_thread_flag(TIF_USING_IWMMXT)) {
kframe->magic = IWMMXT_MAGIC;
kframe->size = IWMMXT_STORAGE_SIZE;
iwmmxt_task_copy(current_thread_info(), &kframe->storage);
} else { /* * For bug-compatibility with older kernels, some space * has to be reserved for iWMMXt even if it's not used. * Set the magic and size appropriately so that properly * written userspace can skip it reliably:
*/
*kframe = (struct iwmmxt_sigframe) {
.magic = DUMMY_MAGIC,
.size = IWMMXT_STORAGE_SIZE,
};
}
/* the iWMMXt context must be 64 bit aligned */
kframe = (struct iwmmxt_sigframe *)((unsignedlong)(kbuf + 8) & ~7); if (__copy_from_user(kframe, frame, sizeof(*frame))) return -1;
/* * For non-iWMMXt threads: a single iwmmxt_sigframe-sized dummy * block is discarded for compatibility with setup_sigframe() if * present, but we don't mandate its presence. If some other * magic is here, it's not for us:
*/ if (!test_thread_flag(TIF_USING_IWMMXT) &&
kframe->magic != DUMMY_MAGIC) return 0;
if (kframe->size != IWMMXT_STORAGE_SIZE) return -1;
if (test_thread_flag(TIF_USING_IWMMXT)) { if (kframe->magic != IWMMXT_MAGIC) return -1;
aux = (char __user *) sf->uc.uc_regspace; #ifdef CONFIG_IWMMXT if (err == 0)
err |= restore_iwmmxt_context(&aux); #endif #ifdef CONFIG_VFP if (err == 0)
err |= restore_vfp_context(&aux); #endif
return err;
}
asmlinkage int sys_sigreturn(struct pt_regs *regs)
{ struct sigframe __user *frame;
/* Always make any pending restarted system calls return -EINTR */
current->restart_block.fn = do_no_restart_syscall;
/* * Since we stacked the signal on a 64-bit boundary, * then 'sp' should be word aligned here. If it's * not, then the user is trying to mess with us.
*/ if (regs->ARM_sp & 7) goto badframe;
frame = (struct sigframe __user *)regs->ARM_sp;
if (!access_ok(frame, sizeof (*frame))) goto badframe;
if (restore_sigframe(regs, frame)) goto badframe;
return regs->ARM_r0;
badframe:
force_sig(SIGSEGV); return 0;
}
asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
{ struct rt_sigframe __user *frame;
/* Always make any pending restarted system calls return -EINTR */
current->restart_block.fn = do_no_restart_syscall;
/* * Since we stacked the signal on a 64-bit boundary, * then 'sp' should be word aligned here. If it's * not, then the user is trying to mess with us.
*/ if (regs->ARM_sp & 7) goto badframe;
if (fdpic) { unsignedlong __user *fdpic_func_desc =
(unsignedlong __user *)handler; if (__get_user(handler, &fdpic_func_desc[0]) ||
__get_user(handler_fdpic_GOT, &fdpic_func_desc[1])) return 1;
}
cpsr |= PSR_ENDSTATE;
/* * Maybe we need to deliver a 32-bit signal to a 26-bit task.
*/ if (ksig->ka.sa.sa_flags & SA_THIRTYTWO)
cpsr = (cpsr & ~MODE_MASK) | USR_MODE;
#ifdef CONFIG_ARM_THUMB if (elf_hwcap & HWCAP_THUMB) { /* * The LSB of the handler determines if we're going to * be using THUMB or ARM mode for this signal handler.
*/
thumb = handler & 1;
/* * Clear the If-Then Thumb-2 execution state. ARM spec * requires this to be all 000s in ARM mode. Snapdragon * S4/Krait misbehaves on a Thumb=>ARM signal transition * without this. * * We must do this whenever we are running on a Thumb-2 * capable CPU, which includes ARMv6T2. However, we elect * to always do this to simplify the code; this field is * marked UNK/SBZP for older architectures.
*/
cpsr &= ~PSR_IT_MASK;
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
retcode = (unsignedlong)ksig->ka.sa.sa_restorer; if (fdpic) { /* * We need code to load the function descriptor. * That code follows the standard sigreturn code * (6 words), and is made of 3 + 2 words for each * variant. The 4th copied word is the actual FD * address that the assembly code expects.
*/
idx = 6 + thumb * 3; if (ksig->ka.sa.sa_flags & SA_SIGINFO)
idx += 5; if (__put_user(sigreturn_codes[idx], rc ) ||
__put_user(sigreturn_codes[idx+1], rc+1) ||
__put_user(sigreturn_codes[idx+2], rc+2) ||
__put_user(retcode, rc+3)) return 1; goto rc_finish;
}
} else {
idx = thumb << 1; if (ksig->ka.sa.sa_flags & SA_SIGINFO)
idx += 3;
/* * Put the sigreturn code on the stack no matter which return * mechanism we use in order to remain ABI compliant
*/ if (__put_user(sigreturn_codes[idx], rc) ||
__put_user(sigreturn_codes[idx+1], rc+1)) return 1;
/* * 32-bit code can use the signal return page * except when the MPU has protected the vectors * page from PL0
*/
retcode = mm->context.sigpage + signal_return_offset +
(idx << 2) + thumb;
} else #endif
{ /* * Ensure that the instruction cache sees * the return code written onto the stack.
*/
flush_icache_range((unsignedlong)rc,
(unsignedlong)(rc + 3));
if (err == 0) { /* * For realtime signals we must also set the second and third * arguments for the signal handler. * -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06
*/
regs->ARM_r1 = (unsignedlong)&frame->info;
regs->ARM_r2 = (unsignedlong)&frame->sig.uc;
}
/* * Perform fixup for the pre-signal frame.
*/
rseq_signal_deliver(ksig, regs);
/* * Set up the stack frame
*/ if (ksig->ka.sa.sa_flags & SA_SIGINFO)
ret = setup_rt_frame(ksig, oldset, regs); else
ret = setup_frame(ksig, oldset, regs);
/* * Check that the resulting registers are actually sane.
*/
ret |= !valid_user_regs(regs);
signal_setup_done(ret, ksig, 0);
}
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that.
*/ staticint do_signal(struct pt_regs *regs, int syscall)
{ unsignedint retval = 0, continue_addr = 0, restart_addr = 0; struct ksignal ksig; int restart = 0;
/* * If we were from a system call, check for system call restarting...
*/ if (syscall) {
continue_addr = regs->ARM_pc;
restart_addr = continue_addr - (thumb_mode(regs) ? 2 : 4);
retval = regs->ARM_r0;
/* * Prepare for system call restart. We do this here so that a * debugger will see the already changed PSW.
*/ switch (retval) { case -ERESTART_RESTARTBLOCK:
restart -= 2;
fallthrough; case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR:
restart++;
regs->ARM_r0 = regs->ARM_ORIG_r0;
regs->ARM_pc = restart_addr; break;
}
}
/* * Get the signal to deliver. When running under ptrace, at this * point the debugger may change all our registers ...
*/ /* * Depending on the signal settings we may need to revert the * decision to restart the system call. But skip this if a * debugger has chosen to restart at a different PC.
*/ if (get_signal(&ksig)) { /* handler */ if (unlikely(restart) && regs->ARM_pc == restart_addr) { if (retval == -ERESTARTNOHAND ||
retval == -ERESTART_RESTARTBLOCK
|| (retval == -ERESTARTSYS
&& !(ksig.ka.sa.sa_flags & SA_RESTART))) {
regs->ARM_r0 = -EINTR;
regs->ARM_pc = continue_addr;
}
}
handle_signal(&ksig, regs);
} else { /* no handler */
restore_saved_sigmask(); if (unlikely(restart) && regs->ARM_pc == restart_addr) {
regs->ARM_pc = continue_addr; return restart;
}
} return 0;
}
asmlinkage int
do_work_pending(struct pt_regs *regs, unsignedint thread_flags, int syscall)
{ /* * The assembly code enters us with IRQs off, but it hasn't * informed the tracing code of that for efficiency reasons. * Update the trace code with the current status.
*/
trace_hardirqs_off(); do { if (likely(thread_flags & _TIF_NEED_RESCHED)) {
schedule();
} else { if (unlikely(!user_mode(regs))) return 0;
local_irq_enable(); if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) { int restart = do_signal(regs, syscall); if (unlikely(restart)) { /* * Restart without handlers. * Deal with it without leaving * the kernel space.
*/ return restart;
}
syscall = 0;
} elseif (thread_flags & _TIF_UPROBE) {
uprobe_notify_resume(regs);
} else {
resume_user_mode_work(regs);
}
}
local_irq_disable();
thread_flags = read_thread_flags();
} while (thread_flags & _TIF_WORK_MASK); return 0;
}
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.