162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Based on arch/arm/include/asm/ptrace.h
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 1996-2003 Russell King
662306a36Sopenharmony_ci * Copyright (C) 2012 ARM Ltd.
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci#ifndef __ASM_PTRACE_H
962306a36Sopenharmony_ci#define __ASM_PTRACE_H
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <asm/cpufeature.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <uapi/asm/ptrace.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci/* Current Exception Level values, as contained in CurrentEL */
1662306a36Sopenharmony_ci#define CurrentEL_EL1		(1 << 2)
1762306a36Sopenharmony_ci#define CurrentEL_EL2		(2 << 2)
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#define INIT_PSTATE_EL1 \
2062306a36Sopenharmony_ci	(PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | PSR_MODE_EL1h)
2162306a36Sopenharmony_ci#define INIT_PSTATE_EL2 \
2262306a36Sopenharmony_ci	(PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | PSR_MODE_EL2h)
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci/*
2562306a36Sopenharmony_ci * PMR values used to mask/unmask interrupts.
2662306a36Sopenharmony_ci *
2762306a36Sopenharmony_ci * GIC priority masking works as follows: if an IRQ's priority is a higher value
2862306a36Sopenharmony_ci * than the value held in PMR, that IRQ is masked. Lowering the value of PMR
2962306a36Sopenharmony_ci * means masking more IRQs (or at least that the same IRQs remain masked).
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci * To mask interrupts, we clear the most significant bit of PMR.
3262306a36Sopenharmony_ci *
3362306a36Sopenharmony_ci * Some code sections either automatically switch back to PSR.I or explicitly
3462306a36Sopenharmony_ci * require to not use priority masking. If bit GIC_PRIO_PSR_I_SET is included
3562306a36Sopenharmony_ci * in the priority mask, it indicates that PSR.I should be set and
3662306a36Sopenharmony_ci * interrupt disabling temporarily does not rely on IRQ priorities.
3762306a36Sopenharmony_ci */
3862306a36Sopenharmony_ci#define GIC_PRIO_IRQON			0xe0
3962306a36Sopenharmony_ci#define __GIC_PRIO_IRQOFF		(GIC_PRIO_IRQON & ~0x80)
4062306a36Sopenharmony_ci#define __GIC_PRIO_IRQOFF_NS		0xa0
4162306a36Sopenharmony_ci#define GIC_PRIO_PSR_I_SET		(1 << 4)
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci#define GIC_PRIO_IRQOFF							\
4462306a36Sopenharmony_ci	({								\
4562306a36Sopenharmony_ci		extern struct static_key_false gic_nonsecure_priorities;\
4662306a36Sopenharmony_ci		u8 __prio = __GIC_PRIO_IRQOFF;				\
4762306a36Sopenharmony_ci									\
4862306a36Sopenharmony_ci		if (static_branch_unlikely(&gic_nonsecure_priorities))	\
4962306a36Sopenharmony_ci			__prio = __GIC_PRIO_IRQOFF_NS;			\
5062306a36Sopenharmony_ci									\
5162306a36Sopenharmony_ci		__prio;							\
5262306a36Sopenharmony_ci	})
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci/* Additional SPSR bits not exposed in the UABI */
5562306a36Sopenharmony_ci#define PSR_MODE_THREAD_BIT	(1 << 0)
5662306a36Sopenharmony_ci#define PSR_IL_BIT		(1 << 20)
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci/* AArch32-specific ptrace requests */
5962306a36Sopenharmony_ci#define COMPAT_PTRACE_GETREGS		12
6062306a36Sopenharmony_ci#define COMPAT_PTRACE_SETREGS		13
6162306a36Sopenharmony_ci#define COMPAT_PTRACE_GET_THREAD_AREA	22
6262306a36Sopenharmony_ci#define COMPAT_PTRACE_SET_SYSCALL	23
6362306a36Sopenharmony_ci#define COMPAT_PTRACE_GETVFPREGS	27
6462306a36Sopenharmony_ci#define COMPAT_PTRACE_SETVFPREGS	28
6562306a36Sopenharmony_ci#define COMPAT_PTRACE_GETHBPREGS	29
6662306a36Sopenharmony_ci#define COMPAT_PTRACE_SETHBPREGS	30
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/* SPSR_ELx bits for exceptions taken from AArch32 */
6962306a36Sopenharmony_ci#define PSR_AA32_MODE_MASK	0x0000001f
7062306a36Sopenharmony_ci#define PSR_AA32_MODE_USR	0x00000010
7162306a36Sopenharmony_ci#define PSR_AA32_MODE_FIQ	0x00000011
7262306a36Sopenharmony_ci#define PSR_AA32_MODE_IRQ	0x00000012
7362306a36Sopenharmony_ci#define PSR_AA32_MODE_SVC	0x00000013
7462306a36Sopenharmony_ci#define PSR_AA32_MODE_ABT	0x00000017
7562306a36Sopenharmony_ci#define PSR_AA32_MODE_HYP	0x0000001a
7662306a36Sopenharmony_ci#define PSR_AA32_MODE_UND	0x0000001b
7762306a36Sopenharmony_ci#define PSR_AA32_MODE_SYS	0x0000001f
7862306a36Sopenharmony_ci#define PSR_AA32_T_BIT		0x00000020
7962306a36Sopenharmony_ci#define PSR_AA32_F_BIT		0x00000040
8062306a36Sopenharmony_ci#define PSR_AA32_I_BIT		0x00000080
8162306a36Sopenharmony_ci#define PSR_AA32_A_BIT		0x00000100
8262306a36Sopenharmony_ci#define PSR_AA32_E_BIT		0x00000200
8362306a36Sopenharmony_ci#define PSR_AA32_PAN_BIT	0x00400000
8462306a36Sopenharmony_ci#define PSR_AA32_SSBS_BIT	0x00800000
8562306a36Sopenharmony_ci#define PSR_AA32_DIT_BIT	0x01000000
8662306a36Sopenharmony_ci#define PSR_AA32_Q_BIT		0x08000000
8762306a36Sopenharmony_ci#define PSR_AA32_V_BIT		0x10000000
8862306a36Sopenharmony_ci#define PSR_AA32_C_BIT		0x20000000
8962306a36Sopenharmony_ci#define PSR_AA32_Z_BIT		0x40000000
9062306a36Sopenharmony_ci#define PSR_AA32_N_BIT		0x80000000
9162306a36Sopenharmony_ci#define PSR_AA32_IT_MASK	0x0600fc00	/* If-Then execution state mask */
9262306a36Sopenharmony_ci#define PSR_AA32_GE_MASK	0x000f0000
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci#ifdef CONFIG_CPU_BIG_ENDIAN
9562306a36Sopenharmony_ci#define PSR_AA32_ENDSTATE	PSR_AA32_E_BIT
9662306a36Sopenharmony_ci#else
9762306a36Sopenharmony_ci#define PSR_AA32_ENDSTATE	0
9862306a36Sopenharmony_ci#endif
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci/* AArch32 CPSR bits, as seen in AArch32 */
10162306a36Sopenharmony_ci#define COMPAT_PSR_DIT_BIT	0x00200000
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci/*
10462306a36Sopenharmony_ci * These are 'magic' values for PTRACE_PEEKUSR that return info about where a
10562306a36Sopenharmony_ci * process is located in memory.
10662306a36Sopenharmony_ci */
10762306a36Sopenharmony_ci#define COMPAT_PT_TEXT_ADDR		0x10000
10862306a36Sopenharmony_ci#define COMPAT_PT_DATA_ADDR		0x10004
10962306a36Sopenharmony_ci#define COMPAT_PT_TEXT_END_ADDR		0x10008
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci/*
11262306a36Sopenharmony_ci * If pt_regs.syscallno == NO_SYSCALL, then the thread is not executing
11362306a36Sopenharmony_ci * a syscall -- i.e., its most recent entry into the kernel from
11462306a36Sopenharmony_ci * userspace was not via SVC, or otherwise a tracer cancelled the syscall.
11562306a36Sopenharmony_ci *
11662306a36Sopenharmony_ci * This must have the value -1, for ABI compatibility with ptrace etc.
11762306a36Sopenharmony_ci */
11862306a36Sopenharmony_ci#define NO_SYSCALL (-1)
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci#ifndef __ASSEMBLY__
12162306a36Sopenharmony_ci#include <linux/bug.h>
12262306a36Sopenharmony_ci#include <linux/types.h>
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci/* sizeof(struct user) for AArch32 */
12562306a36Sopenharmony_ci#define COMPAT_USER_SZ	296
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci/* Architecturally defined mapping between AArch32 and AArch64 registers */
12862306a36Sopenharmony_ci#define compat_usr(x)	regs[(x)]
12962306a36Sopenharmony_ci#define compat_fp	regs[11]
13062306a36Sopenharmony_ci#define compat_sp	regs[13]
13162306a36Sopenharmony_ci#define compat_lr	regs[14]
13262306a36Sopenharmony_ci#define compat_sp_hyp	regs[15]
13362306a36Sopenharmony_ci#define compat_lr_irq	regs[16]
13462306a36Sopenharmony_ci#define compat_sp_irq	regs[17]
13562306a36Sopenharmony_ci#define compat_lr_svc	regs[18]
13662306a36Sopenharmony_ci#define compat_sp_svc	regs[19]
13762306a36Sopenharmony_ci#define compat_lr_abt	regs[20]
13862306a36Sopenharmony_ci#define compat_sp_abt	regs[21]
13962306a36Sopenharmony_ci#define compat_lr_und	regs[22]
14062306a36Sopenharmony_ci#define compat_sp_und	regs[23]
14162306a36Sopenharmony_ci#define compat_r8_fiq	regs[24]
14262306a36Sopenharmony_ci#define compat_r9_fiq	regs[25]
14362306a36Sopenharmony_ci#define compat_r10_fiq	regs[26]
14462306a36Sopenharmony_ci#define compat_r11_fiq	regs[27]
14562306a36Sopenharmony_ci#define compat_r12_fiq	regs[28]
14662306a36Sopenharmony_ci#define compat_sp_fiq	regs[29]
14762306a36Sopenharmony_ci#define compat_lr_fiq	regs[30]
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cistatic inline unsigned long compat_psr_to_pstate(const unsigned long psr)
15062306a36Sopenharmony_ci{
15162306a36Sopenharmony_ci	unsigned long pstate;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	pstate = psr & ~COMPAT_PSR_DIT_BIT;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	if (psr & COMPAT_PSR_DIT_BIT)
15662306a36Sopenharmony_ci		pstate |= PSR_AA32_DIT_BIT;
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	return pstate;
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic inline unsigned long pstate_to_compat_psr(const unsigned long pstate)
16262306a36Sopenharmony_ci{
16362306a36Sopenharmony_ci	unsigned long psr;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	psr = pstate & ~PSR_AA32_DIT_BIT;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	if (pstate & PSR_AA32_DIT_BIT)
16862306a36Sopenharmony_ci		psr |= COMPAT_PSR_DIT_BIT;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	return psr;
17162306a36Sopenharmony_ci}
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci/*
17462306a36Sopenharmony_ci * This struct defines the way the registers are stored on the stack during an
17562306a36Sopenharmony_ci * exception. Note that sizeof(struct pt_regs) has to be a multiple of 16 (for
17662306a36Sopenharmony_ci * stack alignment). struct user_pt_regs must form a prefix of struct pt_regs.
17762306a36Sopenharmony_ci */
17862306a36Sopenharmony_cistruct pt_regs {
17962306a36Sopenharmony_ci	union {
18062306a36Sopenharmony_ci		struct user_pt_regs user_regs;
18162306a36Sopenharmony_ci		struct {
18262306a36Sopenharmony_ci			u64 regs[31];
18362306a36Sopenharmony_ci			u64 sp;
18462306a36Sopenharmony_ci			u64 pc;
18562306a36Sopenharmony_ci			u64 pstate;
18662306a36Sopenharmony_ci		};
18762306a36Sopenharmony_ci	};
18862306a36Sopenharmony_ci	u64 orig_x0;
18962306a36Sopenharmony_ci#ifdef __AARCH64EB__
19062306a36Sopenharmony_ci	u32 unused2;
19162306a36Sopenharmony_ci	s32 syscallno;
19262306a36Sopenharmony_ci#else
19362306a36Sopenharmony_ci	s32 syscallno;
19462306a36Sopenharmony_ci	u32 unused2;
19562306a36Sopenharmony_ci#endif
19662306a36Sopenharmony_ci	u64 sdei_ttbr1;
19762306a36Sopenharmony_ci	/* Only valid when ARM64_HAS_GIC_PRIO_MASKING is enabled. */
19862306a36Sopenharmony_ci	u64 pmr_save;
19962306a36Sopenharmony_ci	u64 stackframe[2];
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	/* Only valid for some EL1 exceptions. */
20262306a36Sopenharmony_ci	u64 lockdep_hardirqs;
20362306a36Sopenharmony_ci	u64 exit_rcu;
20462306a36Sopenharmony_ci};
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistatic inline bool in_syscall(struct pt_regs const *regs)
20762306a36Sopenharmony_ci{
20862306a36Sopenharmony_ci	return regs->syscallno != NO_SYSCALL;
20962306a36Sopenharmony_ci}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_cistatic inline void forget_syscall(struct pt_regs *regs)
21262306a36Sopenharmony_ci{
21362306a36Sopenharmony_ci	regs->syscallno = NO_SYSCALL;
21462306a36Sopenharmony_ci}
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci#define MAX_REG_OFFSET offsetof(struct pt_regs, pstate)
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci#define arch_has_single_step()	(1)
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci#ifdef CONFIG_COMPAT
22162306a36Sopenharmony_ci#define compat_thumb_mode(regs) \
22262306a36Sopenharmony_ci	(((regs)->pstate & PSR_AA32_T_BIT))
22362306a36Sopenharmony_ci#else
22462306a36Sopenharmony_ci#define compat_thumb_mode(regs) (0)
22562306a36Sopenharmony_ci#endif
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci#define user_mode(regs)	\
22862306a36Sopenharmony_ci	(((regs)->pstate & PSR_MODE_MASK) == PSR_MODE_EL0t)
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci#define compat_user_mode(regs)	\
23162306a36Sopenharmony_ci	(((regs)->pstate & (PSR_MODE32_BIT | PSR_MODE_MASK)) == \
23262306a36Sopenharmony_ci	 (PSR_MODE32_BIT | PSR_MODE_EL0t))
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci#define processor_mode(regs) \
23562306a36Sopenharmony_ci	((regs)->pstate & PSR_MODE_MASK)
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci#define irqs_priority_unmasked(regs)					\
23862306a36Sopenharmony_ci	(system_uses_irq_prio_masking() ?				\
23962306a36Sopenharmony_ci		(regs)->pmr_save == GIC_PRIO_IRQON :			\
24062306a36Sopenharmony_ci		true)
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci#define interrupts_enabled(regs)			\
24362306a36Sopenharmony_ci	(!((regs)->pstate & PSR_I_BIT) && irqs_priority_unmasked(regs))
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci#define fast_interrupts_enabled(regs) \
24662306a36Sopenharmony_ci	(!((regs)->pstate & PSR_F_BIT))
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_cistatic inline unsigned long user_stack_pointer(struct pt_regs *regs)
24962306a36Sopenharmony_ci{
25062306a36Sopenharmony_ci	if (compat_user_mode(regs))
25162306a36Sopenharmony_ci		return regs->compat_sp;
25262306a36Sopenharmony_ci	return regs->sp;
25362306a36Sopenharmony_ci}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ciextern int regs_query_register_offset(const char *name);
25662306a36Sopenharmony_ciextern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
25762306a36Sopenharmony_ci					       unsigned int n);
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci/**
26062306a36Sopenharmony_ci * regs_get_register() - get register value from its offset
26162306a36Sopenharmony_ci * @regs:	pt_regs from which register value is gotten
26262306a36Sopenharmony_ci * @offset:	offset of the register.
26362306a36Sopenharmony_ci *
26462306a36Sopenharmony_ci * regs_get_register returns the value of a register whose offset from @regs.
26562306a36Sopenharmony_ci * The @offset is the offset of the register in struct pt_regs.
26662306a36Sopenharmony_ci * If @offset is bigger than MAX_REG_OFFSET, this returns 0.
26762306a36Sopenharmony_ci */
26862306a36Sopenharmony_cistatic inline u64 regs_get_register(struct pt_regs *regs, unsigned int offset)
26962306a36Sopenharmony_ci{
27062306a36Sopenharmony_ci	u64 val = 0;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	WARN_ON(offset & 7);
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	offset >>= 3;
27562306a36Sopenharmony_ci	switch (offset) {
27662306a36Sopenharmony_ci	case 0 ... 30:
27762306a36Sopenharmony_ci		val = regs->regs[offset];
27862306a36Sopenharmony_ci		break;
27962306a36Sopenharmony_ci	case offsetof(struct pt_regs, sp) >> 3:
28062306a36Sopenharmony_ci		val = regs->sp;
28162306a36Sopenharmony_ci		break;
28262306a36Sopenharmony_ci	case offsetof(struct pt_regs, pc) >> 3:
28362306a36Sopenharmony_ci		val = regs->pc;
28462306a36Sopenharmony_ci		break;
28562306a36Sopenharmony_ci	case offsetof(struct pt_regs, pstate) >> 3:
28662306a36Sopenharmony_ci		val = regs->pstate;
28762306a36Sopenharmony_ci		break;
28862306a36Sopenharmony_ci	default:
28962306a36Sopenharmony_ci		val = 0;
29062306a36Sopenharmony_ci	}
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	return val;
29362306a36Sopenharmony_ci}
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci/*
29662306a36Sopenharmony_ci * Read a register given an architectural register index r.
29762306a36Sopenharmony_ci * This handles the common case where 31 means XZR, not SP.
29862306a36Sopenharmony_ci */
29962306a36Sopenharmony_cistatic inline unsigned long pt_regs_read_reg(const struct pt_regs *regs, int r)
30062306a36Sopenharmony_ci{
30162306a36Sopenharmony_ci	return (r == 31) ? 0 : regs->regs[r];
30262306a36Sopenharmony_ci}
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci/*
30562306a36Sopenharmony_ci * Write a register given an architectural register index r.
30662306a36Sopenharmony_ci * This handles the common case where 31 means XZR, not SP.
30762306a36Sopenharmony_ci */
30862306a36Sopenharmony_cistatic inline void pt_regs_write_reg(struct pt_regs *regs, int r,
30962306a36Sopenharmony_ci				     unsigned long val)
31062306a36Sopenharmony_ci{
31162306a36Sopenharmony_ci	if (r != 31)
31262306a36Sopenharmony_ci		regs->regs[r] = val;
31362306a36Sopenharmony_ci}
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci/* Valid only for Kernel mode traps. */
31662306a36Sopenharmony_cistatic inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
31762306a36Sopenharmony_ci{
31862306a36Sopenharmony_ci	return regs->sp;
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_cistatic inline unsigned long regs_return_value(struct pt_regs *regs)
32262306a36Sopenharmony_ci{
32362306a36Sopenharmony_ci	unsigned long val = regs->regs[0];
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	/*
32662306a36Sopenharmony_ci	 * Audit currently uses regs_return_value() instead of
32762306a36Sopenharmony_ci	 * syscall_get_return_value(). Apply the same sign-extension here until
32862306a36Sopenharmony_ci	 * audit is updated to use syscall_get_return_value().
32962306a36Sopenharmony_ci	 */
33062306a36Sopenharmony_ci	if (compat_user_mode(regs))
33162306a36Sopenharmony_ci		val = sign_extend64(val, 31);
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	return val;
33462306a36Sopenharmony_ci}
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_cistatic inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
33762306a36Sopenharmony_ci{
33862306a36Sopenharmony_ci	regs->regs[0] = rc;
33962306a36Sopenharmony_ci}
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci/**
34262306a36Sopenharmony_ci * regs_get_kernel_argument() - get Nth function argument in kernel
34362306a36Sopenharmony_ci * @regs:	pt_regs of that context
34462306a36Sopenharmony_ci * @n:		function argument number (start from 0)
34562306a36Sopenharmony_ci *
34662306a36Sopenharmony_ci * regs_get_argument() returns @n th argument of the function call.
34762306a36Sopenharmony_ci *
34862306a36Sopenharmony_ci * Note that this chooses the most likely register mapping. In very rare
34962306a36Sopenharmony_ci * cases this may not return correct data, for example, if one of the
35062306a36Sopenharmony_ci * function parameters is 16 bytes or bigger. In such cases, we cannot
35162306a36Sopenharmony_ci * get access the parameter correctly and the register assignment of
35262306a36Sopenharmony_ci * subsequent parameters will be shifted.
35362306a36Sopenharmony_ci */
35462306a36Sopenharmony_cistatic inline unsigned long regs_get_kernel_argument(struct pt_regs *regs,
35562306a36Sopenharmony_ci						     unsigned int n)
35662306a36Sopenharmony_ci{
35762306a36Sopenharmony_ci#define NR_REG_ARGUMENTS 8
35862306a36Sopenharmony_ci	if (n < NR_REG_ARGUMENTS)
35962306a36Sopenharmony_ci		return pt_regs_read_reg(regs, n);
36062306a36Sopenharmony_ci	return 0;
36162306a36Sopenharmony_ci}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci/* We must avoid circular header include via sched.h */
36462306a36Sopenharmony_cistruct task_struct;
36562306a36Sopenharmony_ciint valid_user_regs(struct user_pt_regs *regs, struct task_struct *task);
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_cistatic inline unsigned long instruction_pointer(struct pt_regs *regs)
36862306a36Sopenharmony_ci{
36962306a36Sopenharmony_ci	return regs->pc;
37062306a36Sopenharmony_ci}
37162306a36Sopenharmony_cistatic inline void instruction_pointer_set(struct pt_regs *regs,
37262306a36Sopenharmony_ci		unsigned long val)
37362306a36Sopenharmony_ci{
37462306a36Sopenharmony_ci	regs->pc = val;
37562306a36Sopenharmony_ci}
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_cistatic inline unsigned long frame_pointer(struct pt_regs *regs)
37862306a36Sopenharmony_ci{
37962306a36Sopenharmony_ci	return regs->regs[29];
38062306a36Sopenharmony_ci}
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci#define procedure_link_pointer(regs)	((regs)->regs[30])
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_cistatic inline void procedure_link_pointer_set(struct pt_regs *regs,
38562306a36Sopenharmony_ci					   unsigned long val)
38662306a36Sopenharmony_ci{
38762306a36Sopenharmony_ci	procedure_link_pointer(regs) = val;
38862306a36Sopenharmony_ci}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ciextern unsigned long profile_pc(struct pt_regs *regs);
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci#endif /* __ASSEMBLY__ */
39362306a36Sopenharmony_ci#endif
394