arch/sparc/kernel/uprobes.c

Source file repositories/reference/linux-study-clean/arch/sparc/kernel/uprobes.c

File Facts

System
Linux kernel
Corpus path
arch/sparc/kernel/uprobes.c
Extension
.c
Size
8676 bytes
Lines
321
Domain
Architecture Layer
Bucket
arch/sparc
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 (rd <= 15) {
			slot = &regs->u_regs[rd];
		} else {
			unsigned long fp = regs->u_regs[UREG_FP];
			/* Hard case, it goes onto the stack. */
			flushw_all();

			rd -= 16;
			if (test_thread_64bit_stack(fp)) {
				unsigned long __user *uslot =
			(unsigned long __user *) (fp + STACK_BIAS) + rd;
				rc = __put_user(real_pc, uslot);
			} else {
				unsigned int __user *uslot = (unsigned int
						__user *) fp + rd;
				rc = __put_user((u32) real_pc, uslot);
			}
		}
	}
	if (slot != NULL)
		*slot = real_pc;
	return rc;
}

/* Single-stepping can be avoided for certain instructions: NOPs and
 * instructions that can be emulated.  This function determines
 * whether the instruction where the uprobe is installed falls in one
 * of these cases and emulates it.
 *
 * This function returns true if the single-stepping can be skipped,
 * false otherwise.
 */
bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
{
	/* We currently only emulate NOP instructions.
	 */

	if (auprobe->ixol == (1 << 24)) {
		regs->tnpc += 4;
		regs->tpc += 4;
		return true;
	}

	return false;
}

/* Prepare to execute out of line.  At this point
 * current->utask->xol_vaddr points to an allocated XOL slot properly
 * initialized with the original instruction and the single-stepping
 * trap instruction.
 *
 * This function returns 0 on success, any other number on error.
 */
int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
{
	struct uprobe_task *utask = current->utask;
	struct arch_uprobe_task *autask = &current->utask->autask;

	/* Save the current program counters so they can be restored
	 * later.
	 */
	autask->saved_tpc = regs->tpc;
	autask->saved_tnpc = regs->tnpc;

	/* Adjust PC and NPC so the first instruction in the XOL slot
	 * will be executed by the user task.
	 */
	instruction_pointer_set(regs, utask->xol_vaddr);

	return 0;
}

/* Prepare to resume execution after the single-step.  Called after
 * single-stepping. To avoid the SMP problems that can occur when we
 * temporarily put back the original opcode to single-step, we
 * single-stepped a copy of the instruction.
 *
 * This function returns 0 on success, any other number on error.
 */
int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
{
	struct uprobe_task *utask = current->utask;
	struct arch_uprobe_task *autask = &utask->autask;
	u32 insn = auprobe->ixol;
	int rc = 0;

	if (utask->state == UTASK_SSTEP_ACK) {
		regs->tnpc = relbranch_fixup(insn, utask, regs);
		regs->tpc = autask->saved_tnpc;
		rc =  retpc_fixup(regs, insn, (unsigned long) utask->vaddr);

Annotation

Implementation Notes