ptrace.h 4.2 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2
 *  arch/arm/include/asm/ptrace.h
L
Linus Torvalds 已提交
3 4 5 6 7 8 9 10 11 12
 *
 *  Copyright (C) 1996-2003 Russell King
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#ifndef __ASM_ARM_PTRACE_H
#define __ASM_ARM_PTRACE_H

13
#include <uapi/asm/ptrace.h>
P
Paul Brook 已提交
14

L
Linus Torvalds 已提交
15
#ifndef __ASSEMBLY__
16 17
#include <linux/types.h>

18 19 20
struct pt_regs {
	unsigned long uregs[18];
};
L
Linus Torvalds 已提交
21

22 23 24
struct svc_pt_regs {
	struct pt_regs regs;
	u32 dacr;
25
	u32 addr_limit;
26 27
};

28 29
#define to_svc_pt_regs(r) container_of(r, struct svc_pt_regs, regs)

L
Linus Torvalds 已提交
30 31 32 33 34 35 36 37 38 39
#define user_mode(regs)	\
	(((regs)->ARM_cpsr & 0xf) == 0)

#ifdef CONFIG_ARM_THUMB
#define thumb_mode(regs) \
	(((regs)->ARM_cpsr & PSR_T_BIT))
#else
#define thumb_mode(regs) (0)
#endif

40
#ifndef CONFIG_CPU_V7M
41
#define isa_mode(regs) \
42 43 44 45 46
	((((regs)->ARM_cpsr & PSR_J_BIT) >> (__ffs(PSR_J_BIT) - 1)) | \
	 (((regs)->ARM_cpsr & PSR_T_BIT) >> (__ffs(PSR_T_BIT))))
#else
#define isa_mode(regs) 1 /* Thumb */
#endif
47

L
Linus Torvalds 已提交
48 49 50 51 52 53 54 55 56 57 58 59 60 61
#define processor_mode(regs) \
	((regs)->ARM_cpsr & MODE_MASK)

#define interrupts_enabled(regs) \
	(!((regs)->ARM_cpsr & PSR_I_BIT))

#define fast_interrupts_enabled(regs) \
	(!((regs)->ARM_cpsr & PSR_F_BIT))

/* Are the current registers suitable for user mode?
 * (used to maintain security in signal handlers)
 */
static inline int valid_user_regs(struct pt_regs *regs)
{
62
#ifndef CONFIG_CPU_V7M
63 64 65 66 67 68 69 70 71 72 73 74
	unsigned long mode = regs->ARM_cpsr & MODE_MASK;

	/*
	 * Always clear the F (FIQ) and A (delayed abort) bits
	 */
	regs->ARM_cpsr &= ~(PSR_F_BIT | PSR_A_BIT);

	if ((regs->ARM_cpsr & PSR_I_BIT) == 0) {
		if (mode == USR_MODE)
			return 1;
		if (elf_hwcap & HWCAP_26BIT && mode == USR26_MODE)
			return 1;
75
	}
L
Linus Torvalds 已提交
76 77 78 79

	/*
	 * Force CPSR to something logical...
	 */
80
	regs->ARM_cpsr &= PSR_f | PSR_s | PSR_x | PSR_T_BIT | MODE32_BIT;
81 82
	if (!(elf_hwcap & HWCAP_26BIT))
		regs->ARM_cpsr |= USR_MODE;
L
Linus Torvalds 已提交
83 84

	return 0;
85 86 87
#else /* ifndef CONFIG_CPU_V7M */
	return 1;
#endif
L
Linus Torvalds 已提交
88 89
}

90 91 92 93 94
static inline long regs_return_value(struct pt_regs *regs)
{
	return regs->ARM_r0;
}

R
Russell King 已提交
95
#define instruction_pointer(regs)	(regs)->ARM_pc
L
Linus Torvalds 已提交
96

97 98 99 100 101 102
#ifdef CONFIG_THUMB2_KERNEL
#define frame_pointer(regs) (regs)->ARM_r7
#else
#define frame_pointer(regs) (regs)->ARM_fp
#endif

D
David A. Long 已提交
103 104 105 106 107 108
static inline void instruction_pointer_set(struct pt_regs *regs,
					   unsigned long val)
{
	instruction_pointer(regs) = val;
}

L
Linus Torvalds 已提交
109 110 111 112 113 114
#ifdef CONFIG_SMP
extern unsigned long profile_pc(struct pt_regs *regs);
#else
#define profile_pc(regs) instruction_pointer(regs)
#endif

R
Russell King 已提交
115
#define predicate(x)		((x) & 0xf0000000)
L
Linus Torvalds 已提交
116
#define PREDICATE_ALWAYS	0xe0000000
117

118 119 120 121 122 123 124 125
/*
 * True if instr is a 32-bit thumb instruction. This works if instr
 * is the first or only half-word of a thumb instruction. It also works
 * when instr holds all 32-bits of a wide thumb instruction if stored
 * in the form (first_half<<16)|(second_half)
 */
#define is_wide_instruction(instr)	((unsigned)(instr) >= 0xe800)

126 127 128
/*
 * kprobe-based event tracer support
 */
129
#include <linux/compiler.h>
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
#define MAX_REG_OFFSET (offsetof(struct pt_regs, ARM_ORIG_r0))

extern int regs_query_register_offset(const char *name);
extern const char *regs_query_register_name(unsigned int offset);
extern bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr);
extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
					       unsigned int n);

/**
 * regs_get_register() - get register value from its offset
 * @regs:	   pt_regs from which register value is gotten
 * @offset:    offset number of the register.
 *
 * regs_get_register returns the value of a register whose offset from @regs.
 * The @offset is the offset of the register in struct pt_regs.
 * If @offset is bigger than MAX_REG_OFFSET, this returns 0.
 */
static inline unsigned long regs_get_register(struct pt_regs *regs,
					      unsigned int offset)
{
	if (unlikely(offset > MAX_REG_OFFSET))
		return 0;
	return *(unsigned long *)((unsigned long)regs + offset);
}

/* Valid only for Kernel mode traps. */
static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
{
	return regs->ARM_sp;
}

161 162 163 164 165
static inline unsigned long user_stack_pointer(struct pt_regs *regs)
{
	return regs->ARM_sp;
}

166 167
#define current_pt_regs(void) ({ (struct pt_regs *)			\
		((current_stack_pointer | (THREAD_SIZE - 1)) - 7) - 1;	\
A
Al Viro 已提交
168 169
})

L
Linus Torvalds 已提交
170 171
#endif /* __ASSEMBLY__ */
#endif