| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) 2001 PPC64 Team, IBM Corp | 
|  | 3 | * | 
|  | 4 | * This struct defines the way the registers are stored on the | 
|  | 5 | * kernel stack during a system call or other kernel entry. | 
|  | 6 | * | 
|  | 7 | * this should only contain volatile regs | 
|  | 8 | * since we can keep non-volatile in the thread_struct | 
|  | 9 | * should set this up when only volatiles are saved | 
|  | 10 | * by intr code. | 
|  | 11 | * | 
|  | 12 | * Since this is going on the stack, *CARE MUST BE TAKEN* to insure | 
|  | 13 | * that the overall structure is a multiple of 16 bytes in length. | 
|  | 14 | * | 
|  | 15 | * Note that the offsets of the fields in this struct correspond with | 
| Stephen Rothwell | da80d46 | 2005-11-03 15:14:36 +1100 | [diff] [blame] | 16 | * the PT_* values below.  This simplifies arch/powerpc/kernel/ptrace.c. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 17 | * | 
|  | 18 | * This program is free software; you can redistribute it and/or | 
|  | 19 | * modify it under the terms of the GNU General Public License | 
|  | 20 | * as published by the Free Software Foundation; either version | 
|  | 21 | * 2 of the License, or (at your option) any later version. | 
|  | 22 | */ | 
| David Howells | c3617f7 | 2012-10-09 09:47:26 +0100 | [diff] [blame] | 23 | #ifndef _ASM_POWERPC_PTRACE_H | 
|  | 24 | #define _ASM_POWERPC_PTRACE_H | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 25 |  | 
| David Howells | c3617f7 | 2012-10-09 09:47:26 +0100 | [diff] [blame] | 26 | #include <uapi/asm/ptrace.h> | 
| Dave Kleikamp | 3162d92 | 2010-02-08 11:51:05 +0000 | [diff] [blame] | 27 |  | 
| Anton Blanchard | a098722 | 2005-09-10 16:01:08 +1000 | [diff] [blame] | 28 |  | 
| Stephen Rothwell | da80d46 | 2005-11-03 15:14:36 +1100 | [diff] [blame] | 29 | #ifdef __powerpc64__ | 
| Anton Blanchard | a098722 | 2005-09-10 16:01:08 +1000 | [diff] [blame] | 30 |  | 
|  | 31 | #define STACK_FRAME_OVERHEAD	112	/* size of minimum stack frame */ | 
| Benjamin Herrenschmidt | ec2b36b | 2008-04-17 14:34:59 +1000 | [diff] [blame] | 32 | #define STACK_FRAME_LR_SAVE	2	/* Location of LR in stack frame */ | 
|  | 33 | #define STACK_FRAME_REGS_MARKER	ASM_CONST(0x7265677368657265) | 
|  | 34 | #define STACK_INT_FRAME_SIZE	(sizeof(struct pt_regs) + \ | 
|  | 35 | STACK_FRAME_OVERHEAD + 288) | 
|  | 36 | #define STACK_FRAME_MARKER	12 | 
| Anton Blanchard | a098722 | 2005-09-10 16:01:08 +1000 | [diff] [blame] | 37 |  | 
|  | 38 | /* Size of dummy stack frame allocated when calling signal handler. */ | 
|  | 39 | #define __SIGNAL_FRAMESIZE	128 | 
|  | 40 | #define __SIGNAL_FRAMESIZE32	64 | 
|  | 41 |  | 
| Stephen Rothwell | da80d46 | 2005-11-03 15:14:36 +1100 | [diff] [blame] | 42 | #else /* __powerpc64__ */ | 
|  | 43 |  | 
|  | 44 | #define STACK_FRAME_OVERHEAD	16	/* size of minimum stack frame */ | 
| Benjamin Herrenschmidt | ec2b36b | 2008-04-17 14:34:59 +1000 | [diff] [blame] | 45 | #define STACK_FRAME_LR_SAVE	1	/* Location of LR in stack frame */ | 
|  | 46 | #define STACK_FRAME_REGS_MARKER	ASM_CONST(0x72656773) | 
|  | 47 | #define STACK_INT_FRAME_SIZE	(sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD) | 
|  | 48 | #define STACK_FRAME_MARKER	2 | 
| Stephen Rothwell | da80d46 | 2005-11-03 15:14:36 +1100 | [diff] [blame] | 49 |  | 
|  | 50 | /* Size of stack frame allocated when calling signal handler. */ | 
|  | 51 | #define __SIGNAL_FRAMESIZE	64 | 
|  | 52 |  | 
|  | 53 | #endif /* __powerpc64__ */ | 
|  | 54 |  | 
|  | 55 | #ifndef __ASSEMBLY__ | 
|  | 56 |  | 
| Srikar Dronamraju | e628942 | 2012-02-08 04:53:13 +0000 | [diff] [blame] | 57 | #define GET_IP(regs)		((regs)->nip) | 
|  | 58 | #define GET_USP(regs)		((regs)->gpr[1]) | 
|  | 59 | #define GET_FP(regs)		(0) | 
|  | 60 | #define SET_FP(regs, val) | 
|  | 61 |  | 
|  | 62 | #ifdef CONFIG_SMP | 
|  | 63 | extern unsigned long profile_pc(struct pt_regs *regs); | 
|  | 64 | #define profile_pc profile_pc | 
|  | 65 | #endif | 
|  | 66 |  | 
|  | 67 | #include <asm-generic/ptrace.h> | 
|  | 68 |  | 
| Mahesh Salgaonkar | 359e428 | 2010-04-07 18:10:20 +1000 | [diff] [blame] | 69 | #define kernel_stack_pointer(regs) ((regs)->gpr[1]) | 
| Eric Paris | d7e7528 | 2012-01-03 14:23:06 -0500 | [diff] [blame] | 70 | static inline int is_syscall_success(struct pt_regs *regs) | 
|  | 71 | { | 
|  | 72 | return !(regs->ccr & 0x10000000); | 
|  | 73 | } | 
|  | 74 |  | 
|  | 75 | static inline long regs_return_value(struct pt_regs *regs) | 
|  | 76 | { | 
|  | 77 | if (is_syscall_success(regs)) | 
|  | 78 | return regs->gpr[3]; | 
|  | 79 | else | 
|  | 80 | return -regs->gpr[3]; | 
|  | 81 | } | 
| Ananth N Mavinakayanahalli | b3f827c | 2006-10-02 02:17:31 -0700 | [diff] [blame] | 82 |  | 
| Stephen Rothwell | da80d46 | 2005-11-03 15:14:36 +1100 | [diff] [blame] | 83 | #ifdef __powerpc64__ | 
|  | 84 | #define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1) | 
|  | 85 | #else | 
|  | 86 | #define user_mode(regs) (((regs)->msr & MSR_PR) != 0) | 
|  | 87 | #endif | 
|  | 88 |  | 
|  | 89 | #define force_successful_syscall_return()   \ | 
|  | 90 | do { \ | 
| David Woodhouse | 401d1f0 | 2005-11-15 18:52:18 +0000 | [diff] [blame] | 91 | set_thread_flag(TIF_NOERROR); \ | 
| Stephen Rothwell | da80d46 | 2005-11-03 15:14:36 +1100 | [diff] [blame] | 92 | } while(0) | 
|  | 93 |  | 
| Benjamin Herrenschmidt | 865418d | 2007-06-04 15:15:44 +1000 | [diff] [blame] | 94 | struct task_struct; | 
|  | 95 | extern unsigned long ptrace_get_reg(struct task_struct *task, int regno); | 
|  | 96 | extern int ptrace_put_reg(struct task_struct *task, int regno, | 
|  | 97 | unsigned long data); | 
|  | 98 |  | 
| Al Viro | be6abfa | 2012-08-31 15:48:05 -0400 | [diff] [blame] | 99 | #define current_pt_regs() \ | 
|  | 100 | ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1) | 
| Stephen Rothwell | da80d46 | 2005-11-03 15:14:36 +1100 | [diff] [blame] | 101 | /* | 
|  | 102 | * We use the least-significant bit of the trap field to indicate | 
|  | 103 | * whether we have saved the full set of registers, or only a | 
|  | 104 | * partial set.  A 1 there means the partial set. | 
|  | 105 | * On 4xx we use the next bit to indicate whether the exception | 
|  | 106 | * is a critical exception (1 means it is). | 
|  | 107 | */ | 
|  | 108 | #define FULL_REGS(regs)		(((regs)->trap & 1) == 0) | 
|  | 109 | #ifndef __powerpc64__ | 
| Benjamin Herrenschmidt | 47c0bd1 | 2007-12-21 15:39:21 +1100 | [diff] [blame] | 110 | #define IS_CRITICAL_EXC(regs)	(((regs)->trap & 2) != 0) | 
|  | 111 | #define IS_MCHECK_EXC(regs)	(((regs)->trap & 4) != 0) | 
| Kumar Gala | 663276b | 2008-04-30 20:44:53 +1000 | [diff] [blame] | 112 | #define IS_DEBUG_EXC(regs)	(((regs)->trap & 8) != 0) | 
| Stephen Rothwell | da80d46 | 2005-11-03 15:14:36 +1100 | [diff] [blame] | 113 | #endif /* ! __powerpc64__ */ | 
|  | 114 | #define TRAP(regs)		((regs)->trap & ~0xF) | 
|  | 115 | #ifdef __powerpc64__ | 
| Mike Wolf | a71f5d5 | 2011-03-21 11:14:53 +1100 | [diff] [blame] | 116 | #define NV_REG_POISON		0xdeadbeefdeadbeefUL | 
| Stephen Rothwell | da80d46 | 2005-11-03 15:14:36 +1100 | [diff] [blame] | 117 | #define CHECK_FULL_REGS(regs)	BUG_ON(regs->trap & 1) | 
|  | 118 | #else | 
| Mike Wolf | a71f5d5 | 2011-03-21 11:14:53 +1100 | [diff] [blame] | 119 | #define NV_REG_POISON		0xdeadbeef | 
| Stephen Rothwell | da80d46 | 2005-11-03 15:14:36 +1100 | [diff] [blame] | 120 | #define CHECK_FULL_REGS(regs)						      \ | 
|  | 121 | do {									      \ | 
|  | 122 | if ((regs)->trap & 1)						      \ | 
| Harvey Harrison | 653c031 | 2008-10-20 16:00:08 -0700 | [diff] [blame] | 123 | printk(KERN_CRIT "%s: partial register set\n", __func__); \ | 
| Stephen Rothwell | da80d46 | 2005-11-03 15:14:36 +1100 | [diff] [blame] | 124 | } while (0) | 
|  | 125 | #endif /* __powerpc64__ */ | 
|  | 126 |  | 
| Roland McGrath | 2a84b0d | 2008-01-30 13:30:51 +0100 | [diff] [blame] | 127 | #define arch_has_single_step()	(1) | 
| Roland McGrath | ec097c8 | 2009-05-28 21:26:38 +0000 | [diff] [blame] | 128 | #define arch_has_block_step()	(!cpu_has_feature(CPU_FTR_601)) | 
| Oleg Nesterov | 25baa35 | 2009-12-15 16:47:18 -0800 | [diff] [blame] | 129 | #define ARCH_HAS_USER_SINGLE_STEP_INFO | 
|  | 130 |  | 
| Mahesh Salgaonkar | 359e428 | 2010-04-07 18:10:20 +1000 | [diff] [blame] | 131 | /* | 
|  | 132 | * kprobe-based event tracer support | 
|  | 133 | */ | 
|  | 134 |  | 
|  | 135 | #include <linux/stddef.h> | 
|  | 136 | #include <linux/thread_info.h> | 
|  | 137 | extern int regs_query_register_offset(const char *name); | 
|  | 138 | extern const char *regs_query_register_name(unsigned int offset); | 
|  | 139 | #define MAX_REG_OFFSET (offsetof(struct pt_regs, dsisr)) | 
|  | 140 |  | 
|  | 141 | /** | 
|  | 142 | * regs_get_register() - get register value from its offset | 
|  | 143 | * @regs:	   pt_regs from which register value is gotten | 
|  | 144 | * @offset:    offset number of the register. | 
|  | 145 | * | 
|  | 146 | * regs_get_register returns the value of a register whose offset from @regs. | 
|  | 147 | * The @offset is the offset of the register in struct pt_regs. | 
|  | 148 | * If @offset is bigger than MAX_REG_OFFSET, this returns 0. | 
|  | 149 | */ | 
|  | 150 | static inline unsigned long regs_get_register(struct pt_regs *regs, | 
|  | 151 | unsigned int offset) | 
|  | 152 | { | 
|  | 153 | if (unlikely(offset > MAX_REG_OFFSET)) | 
|  | 154 | return 0; | 
|  | 155 | return *(unsigned long *)((unsigned long)regs + offset); | 
|  | 156 | } | 
|  | 157 |  | 
|  | 158 | /** | 
|  | 159 | * regs_within_kernel_stack() - check the address in the stack | 
|  | 160 | * @regs:      pt_regs which contains kernel stack pointer. | 
|  | 161 | * @addr:      address which is checked. | 
|  | 162 | * | 
|  | 163 | * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). | 
|  | 164 | * If @addr is within the kernel stack, it returns true. If not, returns false. | 
|  | 165 | */ | 
|  | 166 |  | 
|  | 167 | static inline bool regs_within_kernel_stack(struct pt_regs *regs, | 
|  | 168 | unsigned long addr) | 
|  | 169 | { | 
|  | 170 | return ((addr & ~(THREAD_SIZE - 1))  == | 
|  | 171 | (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))); | 
|  | 172 | } | 
|  | 173 |  | 
|  | 174 | /** | 
|  | 175 | * regs_get_kernel_stack_nth() - get Nth entry of the stack | 
|  | 176 | * @regs:	pt_regs which contains kernel stack pointer. | 
|  | 177 | * @n:		stack entry number. | 
|  | 178 | * | 
|  | 179 | * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which | 
|  | 180 | * is specified by @regs. If the @n th entry is NOT in the kernel stack, | 
|  | 181 | * this returns 0. | 
|  | 182 | */ | 
|  | 183 | static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, | 
|  | 184 | unsigned int n) | 
|  | 185 | { | 
|  | 186 | unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); | 
|  | 187 | addr += n; | 
|  | 188 | if (regs_within_kernel_stack(regs, (unsigned long)addr)) | 
|  | 189 | return *addr; | 
|  | 190 | else | 
|  | 191 | return 0; | 
|  | 192 | } | 
|  | 193 |  | 
| Stephen Rothwell | da80d46 | 2005-11-03 15:14:36 +1100 | [diff] [blame] | 194 | #endif /* __ASSEMBLY__ */ | 
|  | 195 |  | 
| Stephen Rothwell | da80d46 | 2005-11-03 15:14:36 +1100 | [diff] [blame] | 196 | #ifndef __powerpc64__ | 
| Stephen Rothwell | da80d46 | 2005-11-03 15:14:36 +1100 | [diff] [blame] | 197 | #else /* __powerpc64__ */ | 
| Anton Blanchard | a098722 | 2005-09-10 16:01:08 +1000 | [diff] [blame] | 198 | #define PT_FPSCR32 (PT_FPR0 + 2*32 + 1)	/* each FP reg occupies 2 32-bit userspace slots */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 199 | #define PT_VR0_32 164	/* each Vector reg occupies 4 slots in 32-bit */ | 
|  | 200 | #define PT_VSCR_32 (PT_VR0 + 32*4 + 3) | 
|  | 201 | #define PT_VRSAVE_32 (PT_VR0 + 33*4) | 
| Michael Neuling | ce48b21 | 2008-06-25 14:07:18 +1000 | [diff] [blame] | 202 | #define PT_VSR0_32 300 	/* each VSR reg occupies 4 slots in 32-bit */ | 
| Stephen Rothwell | da80d46 | 2005-11-03 15:14:36 +1100 | [diff] [blame] | 203 | #endif /* __powerpc64__ */ | 
| Stephen Rothwell | da80d46 | 2005-11-03 15:14:36 +1100 | [diff] [blame] | 204 | #endif /* _ASM_POWERPC_PTRACE_H */ |