arch/powerpc/kernel/signal.c
Source file repositories/reference/linux-study-clean/arch/powerpc/kernel/signal.c
File Facts
- System
- Linux kernel
- Corpus path
arch/powerpc/kernel/signal.c- Extension
.c- Size
- 9856 bytes
- Lines
- 362
- Domain
- Architecture Layer
- Bucket
- arch/powerpc
- Inferred role
- Architecture Layer: implementation source
- Status
- source implementation candidate
Why This File Exists
CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/entry-common.hlinux/resume_user_mode.hlinux/signal.hlinux/uprobes.hlinux/key.hlinux/context_tracking.hlinux/livepatch.hlinux/syscalls.hasm/hw_breakpoint.hlinux/uaccess.hasm/switch_to.hasm/unistd.hasm/debug.hasm/tm.hsignal.h
Detected Declarations
function Copyrightfunction copy_fpr_from_userfunction copy_vsx_to_userfunction copy_vsx_from_userfunction copy_ckfpr_to_userfunction copy_ckfpr_from_userfunction copy_ckvsx_to_userfunction copy_ckvsx_from_userfunction get_min_sigframe_sizefunction get_min_sigframe_size_compatfunction check_syscall_restartfunction do_signalfunction get_tm_stackpointerfunction signal_faultfunction arch_do_signal_or_restart
Annotated Snippet
if (trap_is_scv(regs)) {
regs->result = -EINTR;
regs->gpr[3] = -EINTR;
} else {
regs->result = -EINTR;
regs->gpr[3] = EINTR;
regs->ccr |= 0x10000000;
}
}
}
static void do_signal(struct task_struct *tsk)
{
sigset_t *oldset = sigmask_to_save();
struct ksignal ksig = { .sig = 0 };
int ret;
BUG_ON(tsk != current);
get_signal(&ksig);
/* 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);
}
set_trap_norestart(tsk->thread.regs);
signal_setup_done(ret, &ksig, test_thread_flag(TIF_SINGLESTEP));
}
static unsigned long 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;
unsigned long ret = regs->gpr[1];
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
Annotation
- Immediate include surface: `linux/entry-common.h`, `linux/resume_user_mode.h`, `linux/signal.h`, `linux/uprobes.h`, `linux/key.h`, `linux/context_tracking.h`, `linux/livepatch.h`, `linux/syscalls.h`.
- Detected declarations: `function Copyright`, `function copy_fpr_from_user`, `function copy_vsx_to_user`, `function copy_vsx_from_user`, `function copy_ckfpr_to_user`, `function copy_ckfpr_from_user`, `function copy_ckvsx_to_user`, `function copy_ckvsx_from_user`, `function get_min_sigframe_size`, `function get_min_sigframe_size_compat`.
- Atlas domain: Architecture Layer / arch/powerpc.
- Implementation status: source implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.