arch/powerpc/kernel/ptrace/ptrace-tm.c

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

File Facts

System
Linux kernel
Corpus path
arch/powerpc/kernel/ptrace/ptrace-tm.c
Extension
.c
Size
20624 bytes
Lines
789
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.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-or-later

#include <linux/regset.h>

#include <asm/switch_to.h>
#include <asm/tm.h>
#include <asm/asm-prototypes.h>

#include "ptrace-decl.h"

void flush_tmregs_to_thread(struct task_struct *tsk)
{
	/*
	 * If task is not current, it will have been flushed already to
	 * its thread_struct during __switch_to().
	 *
	 * A reclaim flushes ALL the state or if not in TM save TM SPRs
	 * in the appropriate thread structures from live.
	 */

	if (!cpu_has_feature(CPU_FTR_TM) || tsk != current)
		return;

	if (MSR_TM_SUSPENDED(mfmsr())) {
		tm_reclaim_current(TM_CAUSE_SIGNAL);
	} else {
		tm_enable();
		tm_save_sprs(&tsk->thread);
	}
}

static unsigned long get_user_ckpt_msr(struct task_struct *task)
{
	return task->thread.ckpt_regs.msr | task->thread.fpexc_mode;
}

static int set_user_ckpt_msr(struct task_struct *task, unsigned long msr)
{
	task->thread.ckpt_regs.msr &= ~MSR_DEBUGCHANGE;
	task->thread.ckpt_regs.msr |= msr & MSR_DEBUGCHANGE;
	return 0;
}

static int set_user_ckpt_trap(struct task_struct *task, unsigned long trap)
{
	set_trap(&task->thread.ckpt_regs, trap);
	return 0;
}

/**
 * tm_cgpr_active - get active number of registers in CGPR
 * @target:	The target task.
 * @regset:	The user regset structure.
 *
 * This function checks for the active number of available
 * regisers in transaction checkpointed GPR category.
 */
int tm_cgpr_active(struct task_struct *target, const struct user_regset *regset)
{
	if (!cpu_has_feature(CPU_FTR_TM))
		return -ENODEV;

	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
		return 0;

	return regset->n;
}

/**
 * tm_cgpr_get - get CGPR registers
 * @target:	The target task.
 * @regset:	The user regset structure.
 * @to:		Destination of copy.
 *
 * This function gets transaction checkpointed GPR registers.
 *
 * When the transaction is active, 'ckpt_regs' holds all the checkpointed
 * GPR register values for the current transaction to fall back on if it
 * aborts in between. This function gets those checkpointed GPR registers.
 * The userspace interface buffer layout is as follows.
 *
 * struct data {
 *	struct pt_regs ckpt_regs;
 * };
 */
int tm_cgpr_get(struct task_struct *target, const struct user_regset *regset,
		struct membuf to)
{
	struct membuf to_msr = membuf_at(&to, offsetof(struct pt_regs, msr));
#ifdef CONFIG_PPC64

Annotation

Implementation Notes