arch/s390/kernel/ptrace.c

Source file repositories/reference/linux-study-clean/arch/s390/kernel/ptrace.c

File Facts

System
Linux kernel
Corpus path
arch/s390/kernel/ptrace.c
Extension
.c
Size
27628 bytes
Lines
1022
Domain
Architecture Layer
Bucket
arch/s390
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.

Dependency Surface

Detected Declarations

Annotated Snippet

if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) {
			if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND_TEND)
				cr2_new.tdc = 1;
			else
				cr2_new.tdc = 2;
		}
	}
	/* Take care of enable/disable of guarded storage. */
	if (cpu_has_gs()) {
		cr2_new.gse = 0;
		if (task->thread.gs_cb)
			cr2_new.gse = 1;
	}
	/* Load control register 0/2 iff changed */
	cr0_changed = cr0_new.val != cr0_old.val;
	cr2_changed = cr2_new.val != cr2_old.val;
	if (cr0_changed)
		local_ctl_load(0, &cr0_new.reg);
	if (cr2_changed)
		local_ctl_load(2, &cr2_new.reg);
	/* Copy user specified PER registers */
	new.control.val = thread->per_user.control;
	new.start.val = thread->per_user.start;
	new.end.val = thread->per_user.end;

	/* merge TIF_SINGLE_STEP into user specified PER registers. */
	if (test_tsk_thread_flag(task, TIF_SINGLE_STEP) ||
	    test_tsk_thread_flag(task, TIF_UPROBE_SINGLESTEP)) {
		if (test_tsk_thread_flag(task, TIF_BLOCK_STEP))
			new.control.val |= PER_EVENT_BRANCH;
		else
			new.control.val |= PER_EVENT_IFETCH;
		new.control.val |= PER_CONTROL_SUSPENSION;
		new.control.val |= PER_EVENT_TRANSACTION_END;
		if (test_tsk_thread_flag(task, TIF_UPROBE_SINGLESTEP))
			new.control.val |= PER_EVENT_IFETCH;
		new.start.val = 0;
		new.end.val = -1UL;
	}

	/* Take care of the PER enablement bit in the PSW. */
	if (!(new.control.val & PER_EVENT_MASK)) {
		regs->psw.mask &= ~PSW_MASK_PER;
		return;
	}
	regs->psw.mask |= PSW_MASK_PER;
	__local_ctl_store(9, 11, old.regs);
	if (memcmp(&new, &old, sizeof(struct per_regs)) != 0)
		__local_ctl_load(9, 11, new.regs);
}

void user_enable_single_step(struct task_struct *task)
{
	clear_tsk_thread_flag(task, TIF_BLOCK_STEP);
	set_tsk_thread_flag(task, TIF_SINGLE_STEP);
}

void user_disable_single_step(struct task_struct *task)
{
	clear_tsk_thread_flag(task, TIF_BLOCK_STEP);
	clear_tsk_thread_flag(task, TIF_SINGLE_STEP);
}

void user_enable_block_step(struct task_struct *task)
{
	set_tsk_thread_flag(task, TIF_SINGLE_STEP);
	set_tsk_thread_flag(task, TIF_BLOCK_STEP);
}

/*
 * Called by kernel/ptrace.c when detaching..
 *
 * Clear all debugging related fields.
 */
void ptrace_disable(struct task_struct *task)
{
	memset(&task->thread.per_user, 0, sizeof(task->thread.per_user));
	memset(&task->thread.per_event, 0, sizeof(task->thread.per_event));
	clear_tsk_thread_flag(task, TIF_SINGLE_STEP);
	clear_tsk_thread_flag(task, TIF_PER_TRAP);
	task->thread.per_flags = 0;
}

#define __ADDR_MASK 7

static inline unsigned long __peek_user_per(struct task_struct *child,
					    addr_t addr)
{
	if (addr == offsetof(struct per_struct_kernel, cr9))
		/* Control bits of the active per set. */

Annotation

Implementation Notes