1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
21965aae3SH. Peter Anvin #ifndef _ASM_X86_PTRACE_H
31965aae3SH. Peter Anvin #define _ASM_X86_PTRACE_H
4bb898558SAl Viro
5bb898558SAl Viro #include <asm/segment.h>
6b1cf540fSMasami Hiramatsu #include <asm/page_types.h>
7af170c50SDavid Howells #include <uapi/asm/ptrace.h>
8bb898558SAl Viro
9bb898558SAl Viro #ifndef __ASSEMBLY__
10bb898558SAl Viro #ifdef __i386__
11bb898558SAl Viro
12bb898558SAl Viro struct pt_regs {
13385eca8fSAndy Lutomirski /*
14385eca8fSAndy Lutomirski * NB: 32-bit x86 CPUs are inconsistent as what happens in the
15385eca8fSAndy Lutomirski * following cases (where %seg represents a segment register):
16385eca8fSAndy Lutomirski *
17385eca8fSAndy Lutomirski * - pushl %seg: some do a 16-bit write and leave the high
18385eca8fSAndy Lutomirski * bits alone
19385eca8fSAndy Lutomirski * - movl %seg, [mem]: some do a 16-bit write despite the movl
20385eca8fSAndy Lutomirski * - IDT entry: some (e.g. 486) will leave the high bits of CS
21385eca8fSAndy Lutomirski * and (if applicable) SS undefined.
22385eca8fSAndy Lutomirski *
23385eca8fSAndy Lutomirski * Fortunately, x86-32 doesn't read the high bits on POP or IRET,
24385eca8fSAndy Lutomirski * so we can just treat all of the segment registers as 16-bit
25385eca8fSAndy Lutomirski * values.
26385eca8fSAndy Lutomirski */
27bb898558SAl Viro unsigned long bx;
28bb898558SAl Viro unsigned long cx;
29bb898558SAl Viro unsigned long dx;
30bb898558SAl Viro unsigned long si;
31bb898558SAl Viro unsigned long di;
32bb898558SAl Viro unsigned long bp;
33bb898558SAl Viro unsigned long ax;
34385eca8fSAndy Lutomirski unsigned short ds;
35385eca8fSAndy Lutomirski unsigned short __dsh;
36385eca8fSAndy Lutomirski unsigned short es;
37385eca8fSAndy Lutomirski unsigned short __esh;
38385eca8fSAndy Lutomirski unsigned short fs;
39385eca8fSAndy Lutomirski unsigned short __fsh;
403fb0fdb3SAndy Lutomirski /*
413fb0fdb3SAndy Lutomirski * On interrupt, gs and __gsh store the vector number. They never
423fb0fdb3SAndy Lutomirski * store gs any more.
433fb0fdb3SAndy Lutomirski */
44385eca8fSAndy Lutomirski unsigned short gs;
45385eca8fSAndy Lutomirski unsigned short __gsh;
4681fd9c18SJann Horn /* On interrupt, this is the error code. */
47bb898558SAl Viro unsigned long orig_ax;
48bb898558SAl Viro unsigned long ip;
49385eca8fSAndy Lutomirski unsigned short cs;
50385eca8fSAndy Lutomirski unsigned short __csh;
51bb898558SAl Viro unsigned long flags;
52bb898558SAl Viro unsigned long sp;
53385eca8fSAndy Lutomirski unsigned short ss;
54385eca8fSAndy Lutomirski unsigned short __ssh;
55bb898558SAl Viro };
56bb898558SAl Viro
57bb898558SAl Viro #else /* __i386__ */
58bb898558SAl Viro
59*9c268be3SXin Li struct fred_cs {
60*9c268be3SXin Li /* CS selector */
61*9c268be3SXin Li u64 cs : 16,
62*9c268be3SXin Li /* Stack level at event time */
63*9c268be3SXin Li sl : 2,
64*9c268be3SXin Li /* IBT in WAIT_FOR_ENDBRANCH state */
65*9c268be3SXin Li wfe : 1,
66*9c268be3SXin Li : 45;
67*9c268be3SXin Li };
68*9c268be3SXin Li
69*9c268be3SXin Li struct fred_ss {
70*9c268be3SXin Li /* SS selector */
71*9c268be3SXin Li u64 ss : 16,
72*9c268be3SXin Li /* STI state */
73*9c268be3SXin Li sti : 1,
74*9c268be3SXin Li /* Set if syscall, sysenter or INT n */
75*9c268be3SXin Li swevent : 1,
76*9c268be3SXin Li /* Event is NMI type */
77*9c268be3SXin Li nmi : 1,
78*9c268be3SXin Li : 13,
79*9c268be3SXin Li /* Event vector */
80*9c268be3SXin Li vector : 8,
81*9c268be3SXin Li : 8,
82*9c268be3SXin Li /* Event type */
83*9c268be3SXin Li type : 4,
84*9c268be3SXin Li : 4,
85*9c268be3SXin Li /* Event was incident to enclave execution */
86*9c268be3SXin Li enclave : 1,
87*9c268be3SXin Li /* CPU was in long mode */
88*9c268be3SXin Li lm : 1,
89*9c268be3SXin Li /*
90*9c268be3SXin Li * Nested exception during FRED delivery, not set
91*9c268be3SXin Li * for #DF.
92*9c268be3SXin Li */
93*9c268be3SXin Li nested : 1,
94*9c268be3SXin Li : 1,
95*9c268be3SXin Li /*
96*9c268be3SXin Li * The length of the instruction causing the event.
97*9c268be3SXin Li * Only set for INTO, INT1, INT3, INT n, SYSCALL
98*9c268be3SXin Li * and SYSENTER. 0 otherwise.
99*9c268be3SXin Li */
100*9c268be3SXin Li insnlen : 4;
101*9c268be3SXin Li };
102*9c268be3SXin Li
103bb898558SAl Viro struct pt_regs {
104e90e147cSDenys Vlasenko /*
105498bdedcSXin Li * C ABI says these regs are callee-preserved. They aren't saved on
106498bdedcSXin Li * kernel entry unless syscall needs a complete, fully filled
107498bdedcSXin Li * "struct pt_regs".
108e90e147cSDenys Vlasenko */
109bb898558SAl Viro unsigned long r15;
110bb898558SAl Viro unsigned long r14;
111bb898558SAl Viro unsigned long r13;
112bb898558SAl Viro unsigned long r12;
113bb898558SAl Viro unsigned long bp;
114bb898558SAl Viro unsigned long bx;
115498bdedcSXin Li
116e90e147cSDenys Vlasenko /* These regs are callee-clobbered. Always saved on kernel entry. */
117bb898558SAl Viro unsigned long r11;
118bb898558SAl Viro unsigned long r10;
119bb898558SAl Viro unsigned long r9;
120bb898558SAl Viro unsigned long r8;
121bb898558SAl Viro unsigned long ax;
122bb898558SAl Viro unsigned long cx;
123bb898558SAl Viro unsigned long dx;
124bb898558SAl Viro unsigned long si;
125bb898558SAl Viro unsigned long di;
126498bdedcSXin Li
127e90e147cSDenys Vlasenko /*
128498bdedcSXin Li * orig_ax is used on entry for:
129498bdedcSXin Li * - the syscall number (syscall, sysenter, int80)
130498bdedcSXin Li * - error_code stored by the CPU on traps and exceptions
131498bdedcSXin Li * - the interrupt number for device interrupts
132*9c268be3SXin Li *
133*9c268be3SXin Li * A FRED stack frame starts here:
134*9c268be3SXin Li * 1) It _always_ includes an error code;
135*9c268be3SXin Li *
136*9c268be3SXin Li * 2) The return frame for ERET[US] starts here, but
137*9c268be3SXin Li * the content of orig_ax is ignored.
138e90e147cSDenys Vlasenko */
139bb898558SAl Viro unsigned long orig_ax;
140498bdedcSXin Li
141498bdedcSXin Li /* The IRETQ return frame starts here */
142bb898558SAl Viro unsigned long ip;
143498bdedcSXin Li
144498bdedcSXin Li union {
145498bdedcSXin Li /* CS selector */
146498bdedcSXin Li u16 cs;
147*9c268be3SXin Li /* The extended 64-bit data slot containing CS */
148*9c268be3SXin Li u64 csx;
149*9c268be3SXin Li /* The FRED CS extension */
150*9c268be3SXin Li struct fred_cs fred_cs;
151498bdedcSXin Li };
152498bdedcSXin Li
153bb898558SAl Viro unsigned long flags;
154bb898558SAl Viro unsigned long sp;
155498bdedcSXin Li
156498bdedcSXin Li union {
157498bdedcSXin Li /* SS selector */
158498bdedcSXin Li u16 ss;
159*9c268be3SXin Li /* The extended 64-bit data slot containing SS */
160*9c268be3SXin Li u64 ssx;
161*9c268be3SXin Li /* The FRED SS extension */
162*9c268be3SXin Li struct fred_ss fred_ss;
163498bdedcSXin Li };
164498bdedcSXin Li
165498bdedcSXin Li /*
166*9c268be3SXin Li * Top of stack on IDT systems, while FRED systems have extra fields
167*9c268be3SXin Li * defined above for storing exception related information, e.g. CR2 or
168*9c268be3SXin Li * DR6.
169498bdedcSXin Li */
170bb898558SAl Viro };
171bb898558SAl Viro
172bb898558SAl Viro #endif /* !__i386__ */
173bb898558SAl Viro
174318f5a2aSAndy Lutomirski #ifdef CONFIG_PARAVIRT
175318f5a2aSAndy Lutomirski #include <asm/paravirt_types.h>
176318f5a2aSAndy Lutomirski #endif
177bb898558SAl Viro
17878a81d88SJoerg Roedel #include <asm/proto.h>
17978a81d88SJoerg Roedel
180bb898558SAl Viro struct cpuinfo_x86;
181bb898558SAl Viro struct task_struct;
182bb898558SAl Viro
183bb898558SAl Viro extern unsigned long profile_pc(struct pt_regs *regs);
184bb898558SAl Viro
185bb898558SAl Viro extern unsigned long
186bb898558SAl Viro convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs);
18728d42ea1SEric W. Biederman extern void send_sigtrap(struct pt_regs *regs, int error_code, int si_code);
188bb898558SAl Viro
189e0ffbaabSAndy Lutomirski
regs_return_value(struct pt_regs * regs)190bb898558SAl Viro static inline unsigned long regs_return_value(struct pt_regs *regs)
191bb898558SAl Viro {
192bb898558SAl Viro return regs->ax;
193bb898558SAl Viro }
194bb898558SAl Viro
regs_set_return_value(struct pt_regs * regs,unsigned long rc)1959802d865SJosef Bacik static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
1969802d865SJosef Bacik {
1979802d865SJosef Bacik regs->ax = rc;
1989802d865SJosef Bacik }
1999802d865SJosef Bacik
200bb898558SAl Viro /*
201efa70451SAndy Lutomirski * user_mode(regs) determines whether a register set came from user
202efa70451SAndy Lutomirski * mode. On x86_32, this is true if V8086 mode was enabled OR if the
203efa70451SAndy Lutomirski * register set was from protected mode with RPL-3 CS value. This
204efa70451SAndy Lutomirski * tricky test checks that with one comparison.
205efa70451SAndy Lutomirski *
206efa70451SAndy Lutomirski * On x86_64, vm86 mode is mercifully nonexistent, and we don't need
207efa70451SAndy Lutomirski * the extra check.
208bb898558SAl Viro */
user_mode(struct pt_regs * regs)2094979fb53SThomas Gleixner static __always_inline int user_mode(struct pt_regs *regs)
210bb898558SAl Viro {
211bb898558SAl Viro #ifdef CONFIG_X86_32
2127ba554b5SJan Beulich return ((regs->cs & SEGMENT_RPL_MASK) | (regs->flags & X86_VM_MASK)) >= USER_RPL;
213bb898558SAl Viro #else
214bb898558SAl Viro return !!(regs->cs & 3);
215bb898558SAl Viro #endif
216bb898558SAl Viro }
217bb898558SAl Viro
v8086_mode(struct pt_regs * regs)218b008893bSBorislav Petkov static __always_inline int v8086_mode(struct pt_regs *regs)
219bb898558SAl Viro {
220bb898558SAl Viro #ifdef CONFIG_X86_32
221bb898558SAl Viro return (regs->flags & X86_VM_MASK);
222bb898558SAl Viro #else
223bb898558SAl Viro return 0; /* No V86 mode support in long mode */
224bb898558SAl Viro #endif
225bb898558SAl Viro }
226bb898558SAl Viro
user_64bit_mode(struct pt_regs * regs)227318f5a2aSAndy Lutomirski static inline bool user_64bit_mode(struct pt_regs *regs)
228318f5a2aSAndy Lutomirski {
229e27c310aSRicardo Neri #ifdef CONFIG_X86_64
23040181646SJuergen Gross #ifndef CONFIG_PARAVIRT_XXL
231318f5a2aSAndy Lutomirski /*
232318f5a2aSAndy Lutomirski * On non-paravirt systems, this is the only long mode CPL 3
233318f5a2aSAndy Lutomirski * selector. We do not allow long mode selectors in the LDT.
234318f5a2aSAndy Lutomirski */
235318f5a2aSAndy Lutomirski return regs->cs == __USER_CS;
236318f5a2aSAndy Lutomirski #else
237318f5a2aSAndy Lutomirski /* Headers are too twisted for this to go in paravirt.h. */
238318f5a2aSAndy Lutomirski return regs->cs == __USER_CS || regs->cs == pv_info.extra_user_64bit_cs;
239318f5a2aSAndy Lutomirski #endif
240e27c310aSRicardo Neri #else /* !CONFIG_X86_64 */
241e27c310aSRicardo Neri return false;
242e27c310aSRicardo Neri #endif
243318f5a2aSAndy Lutomirski }
2449b064fc3SAl Viro
2457be44127SJann Horn /*
2467be44127SJann Horn * Determine whether the register set came from any context that is running in
2477be44127SJann Horn * 64-bit mode.
2487be44127SJann Horn */
any_64bit_mode(struct pt_regs * regs)2497be44127SJann Horn static inline bool any_64bit_mode(struct pt_regs *regs)
2507be44127SJann Horn {
2517be44127SJann Horn #ifdef CONFIG_X86_64
2527be44127SJann Horn return !user_mode(regs) || user_64bit_mode(regs);
2537be44127SJann Horn #else
2547be44127SJann Horn return false;
2557be44127SJann Horn #endif
2567be44127SJann Horn }
2577be44127SJann Horn
258e27c310aSRicardo Neri #ifdef CONFIG_X86_64
259263042e4SDenys Vlasenko #define current_user_stack_pointer() current_pt_regs()->sp
260263042e4SDenys Vlasenko #define compat_user_stack_pointer() current_pt_regs()->sp
26178a81d88SJoerg Roedel
ip_within_syscall_gap(struct pt_regs * regs)262c6b01dacSPeter Zijlstra static __always_inline bool ip_within_syscall_gap(struct pt_regs *regs)
26378a81d88SJoerg Roedel {
26478a81d88SJoerg Roedel bool ret = (regs->ip >= (unsigned long)entry_SYSCALL_64 &&
26578a81d88SJoerg Roedel regs->ip < (unsigned long)entry_SYSCALL_64_safe_stack);
26678a81d88SJoerg Roedel
26747f33de4SLai Jiangshan ret = ret || (regs->ip >= (unsigned long)entry_SYSRETQ_unsafe_stack &&
26847f33de4SLai Jiangshan regs->ip < (unsigned long)entry_SYSRETQ_end);
26978a81d88SJoerg Roedel #ifdef CONFIG_IA32_EMULATION
27078a81d88SJoerg Roedel ret = ret || (regs->ip >= (unsigned long)entry_SYSCALL_compat &&
27178a81d88SJoerg Roedel regs->ip < (unsigned long)entry_SYSCALL_compat_safe_stack);
27247f33de4SLai Jiangshan ret = ret || (regs->ip >= (unsigned long)entry_SYSRETL_compat_unsafe_stack &&
27347f33de4SLai Jiangshan regs->ip < (unsigned long)entry_SYSRETL_compat_end);
27478a81d88SJoerg Roedel #endif
27578a81d88SJoerg Roedel
27678a81d88SJoerg Roedel return ret;
27778a81d88SJoerg Roedel }
278318f5a2aSAndy Lutomirski #endif
279318f5a2aSAndy Lutomirski
kernel_stack_pointer(struct pt_regs * regs)2807b6c6c77SMasami Hiramatsu static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
281bb898558SAl Viro {
282bb898558SAl Viro return regs->sp;
283bb898558SAl Viro }
284bb898558SAl Viro
instruction_pointer(struct pt_regs * regs)28579f2562cSChristoph Hellwig static inline unsigned long instruction_pointer(struct pt_regs *regs)
28679f2562cSChristoph Hellwig {
28779f2562cSChristoph Hellwig return regs->ip;
28879f2562cSChristoph Hellwig }
289bb898558SAl Viro
instruction_pointer_set(struct pt_regs * regs,unsigned long val)29079f2562cSChristoph Hellwig static inline void instruction_pointer_set(struct pt_regs *regs,
29179f2562cSChristoph Hellwig unsigned long val)
29279f2562cSChristoph Hellwig {
29379f2562cSChristoph Hellwig regs->ip = val;
29479f2562cSChristoph Hellwig }
29579f2562cSChristoph Hellwig
frame_pointer(struct pt_regs * regs)29679f2562cSChristoph Hellwig static inline unsigned long frame_pointer(struct pt_regs *regs)
29779f2562cSChristoph Hellwig {
29879f2562cSChristoph Hellwig return regs->bp;
29979f2562cSChristoph Hellwig }
30079f2562cSChristoph Hellwig
user_stack_pointer(struct pt_regs * regs)30179f2562cSChristoph Hellwig static inline unsigned long user_stack_pointer(struct pt_regs *regs)
30279f2562cSChristoph Hellwig {
30379f2562cSChristoph Hellwig return regs->sp;
30479f2562cSChristoph Hellwig }
30579f2562cSChristoph Hellwig
user_stack_pointer_set(struct pt_regs * regs,unsigned long val)30679f2562cSChristoph Hellwig static inline void user_stack_pointer_set(struct pt_regs *regs,
30779f2562cSChristoph Hellwig unsigned long val)
30879f2562cSChristoph Hellwig {
30979f2562cSChristoph Hellwig regs->sp = val;
31079f2562cSChristoph Hellwig }
311bb898558SAl Viro
regs_irqs_disabled(struct pt_regs * regs)3120bf019eaSThomas Gleixner static __always_inline bool regs_irqs_disabled(struct pt_regs *regs)
3130bf019eaSThomas Gleixner {
3140bf019eaSThomas Gleixner return !(regs->flags & X86_EFLAGS_IF);
3150bf019eaSThomas Gleixner }
3160bf019eaSThomas Gleixner
317b1cf540fSMasami Hiramatsu /* Query offset/name of register from its name/offset */
318b1cf540fSMasami Hiramatsu extern int regs_query_register_offset(const char *name);
319b1cf540fSMasami Hiramatsu extern const char *regs_query_register_name(unsigned int offset);
320b1cf540fSMasami Hiramatsu #define MAX_REG_OFFSET (offsetof(struct pt_regs, ss))
321b1cf540fSMasami Hiramatsu
322b1cf540fSMasami Hiramatsu /**
323b1cf540fSMasami Hiramatsu * regs_get_register() - get register value from its offset
324b1cf540fSMasami Hiramatsu * @regs: pt_regs from which register value is gotten.
325b1cf540fSMasami Hiramatsu * @offset: offset number of the register.
326b1cf540fSMasami Hiramatsu *
327e859cf86SMasami Hiramatsu * regs_get_register returns the value of a register. The @offset is the
328e859cf86SMasami Hiramatsu * offset of the register in struct pt_regs address which specified by @regs.
329b1cf540fSMasami Hiramatsu * If @offset is bigger than MAX_REG_OFFSET, this returns 0.
330b1cf540fSMasami Hiramatsu */
regs_get_register(struct pt_regs * regs,unsigned int offset)331b1cf540fSMasami Hiramatsu static inline unsigned long regs_get_register(struct pt_regs *regs,
332b1cf540fSMasami Hiramatsu unsigned int offset)
333b1cf540fSMasami Hiramatsu {
334b1cf540fSMasami Hiramatsu if (unlikely(offset > MAX_REG_OFFSET))
335b1cf540fSMasami Hiramatsu return 0;
3366c8d8b3cSSteven Rostedt #ifdef CONFIG_X86_32
337603e492eSAndy Lutomirski /* The selector fields are 16-bit. */
338603e492eSAndy Lutomirski if (offset == offsetof(struct pt_regs, cs) ||
339603e492eSAndy Lutomirski offset == offsetof(struct pt_regs, ss) ||
340603e492eSAndy Lutomirski offset == offsetof(struct pt_regs, ds) ||
341603e492eSAndy Lutomirski offset == offsetof(struct pt_regs, es) ||
342603e492eSAndy Lutomirski offset == offsetof(struct pt_regs, fs) ||
343603e492eSAndy Lutomirski offset == offsetof(struct pt_regs, gs)) {
344603e492eSAndy Lutomirski return *(u16 *)((unsigned long)regs + offset);
345603e492eSAndy Lutomirski
346603e492eSAndy Lutomirski }
3476c8d8b3cSSteven Rostedt #endif
348b1cf540fSMasami Hiramatsu return *(unsigned long *)((unsigned long)regs + offset);
349b1cf540fSMasami Hiramatsu }
350b1cf540fSMasami Hiramatsu
351b1cf540fSMasami Hiramatsu /**
352b1cf540fSMasami Hiramatsu * regs_within_kernel_stack() - check the address in the stack
353b1cf540fSMasami Hiramatsu * @regs: pt_regs which contains kernel stack pointer.
354b1cf540fSMasami Hiramatsu * @addr: address which is checked.
355b1cf540fSMasami Hiramatsu *
356e859cf86SMasami Hiramatsu * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
357b1cf540fSMasami Hiramatsu * If @addr is within the kernel stack, it returns true. If not, returns false.
358b1cf540fSMasami Hiramatsu */
regs_within_kernel_stack(struct pt_regs * regs,unsigned long addr)359b1cf540fSMasami Hiramatsu static inline int regs_within_kernel_stack(struct pt_regs *regs,
360b1cf540fSMasami Hiramatsu unsigned long addr)
361b1cf540fSMasami Hiramatsu {
3623c88c692SPeter Zijlstra return ((addr & ~(THREAD_SIZE - 1)) == (regs->sp & ~(THREAD_SIZE - 1)));
363b1cf540fSMasami Hiramatsu }
364b1cf540fSMasami Hiramatsu
365b1cf540fSMasami Hiramatsu /**
366c2712b85SSteven Rostedt (VMware) * regs_get_kernel_stack_nth_addr() - get the address of the Nth entry on stack
367c2712b85SSteven Rostedt (VMware) * @regs: pt_regs which contains kernel stack pointer.
368c2712b85SSteven Rostedt (VMware) * @n: stack entry number.
369c2712b85SSteven Rostedt (VMware) *
370c2712b85SSteven Rostedt (VMware) * regs_get_kernel_stack_nth() returns the address of the @n th entry of the
371c2712b85SSteven Rostedt (VMware) * kernel stack which is specified by @regs. If the @n th entry is NOT in
372c2712b85SSteven Rostedt (VMware) * the kernel stack, this returns NULL.
373c2712b85SSteven Rostedt (VMware) */
regs_get_kernel_stack_nth_addr(struct pt_regs * regs,unsigned int n)374c2712b85SSteven Rostedt (VMware) static inline unsigned long *regs_get_kernel_stack_nth_addr(struct pt_regs *regs, unsigned int n)
375c2712b85SSteven Rostedt (VMware) {
3763c88c692SPeter Zijlstra unsigned long *addr = (unsigned long *)regs->sp;
377c2712b85SSteven Rostedt (VMware)
378c2712b85SSteven Rostedt (VMware) addr += n;
379c2712b85SSteven Rostedt (VMware) if (regs_within_kernel_stack(regs, (unsigned long)addr))
380c2712b85SSteven Rostedt (VMware) return addr;
381c2712b85SSteven Rostedt (VMware) else
382c2712b85SSteven Rostedt (VMware) return NULL;
383c2712b85SSteven Rostedt (VMware) }
384c2712b85SSteven Rostedt (VMware)
385c2712b85SSteven Rostedt (VMware) /* To avoid include hell, we can't include uaccess.h */
386fe557319SChristoph Hellwig extern long copy_from_kernel_nofault(void *dst, const void *src, size_t size);
387c2712b85SSteven Rostedt (VMware)
388c2712b85SSteven Rostedt (VMware) /**
389b1cf540fSMasami Hiramatsu * regs_get_kernel_stack_nth() - get Nth entry of the stack
390b1cf540fSMasami Hiramatsu * @regs: pt_regs which contains kernel stack pointer.
391b1cf540fSMasami Hiramatsu * @n: stack entry number.
392b1cf540fSMasami Hiramatsu *
393b1cf540fSMasami Hiramatsu * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
394c2712b85SSteven Rostedt (VMware) * is specified by @regs. If the @n th entry is NOT in the kernel stack
395b1cf540fSMasami Hiramatsu * this returns 0.
396b1cf540fSMasami Hiramatsu */
regs_get_kernel_stack_nth(struct pt_regs * regs,unsigned int n)397b1cf540fSMasami Hiramatsu static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
398b1cf540fSMasami Hiramatsu unsigned int n)
399b1cf540fSMasami Hiramatsu {
400c2712b85SSteven Rostedt (VMware) unsigned long *addr;
401c2712b85SSteven Rostedt (VMware) unsigned long val;
402c2712b85SSteven Rostedt (VMware) long ret;
403c2712b85SSteven Rostedt (VMware)
404c2712b85SSteven Rostedt (VMware) addr = regs_get_kernel_stack_nth_addr(regs, n);
405c2712b85SSteven Rostedt (VMware) if (addr) {
406fe557319SChristoph Hellwig ret = copy_from_kernel_nofault(&val, addr, sizeof(val));
407c2712b85SSteven Rostedt (VMware) if (!ret)
408c2712b85SSteven Rostedt (VMware) return val;
409c2712b85SSteven Rostedt (VMware) }
410b1cf540fSMasami Hiramatsu return 0;
411b1cf540fSMasami Hiramatsu }
412b1cf540fSMasami Hiramatsu
4133c88ee19SMasami Hiramatsu /**
4143c88ee19SMasami Hiramatsu * regs_get_kernel_argument() - get Nth function argument in kernel
4153c88ee19SMasami Hiramatsu * @regs: pt_regs of that context
4163c88ee19SMasami Hiramatsu * @n: function argument number (start from 0)
4173c88ee19SMasami Hiramatsu *
4183c88ee19SMasami Hiramatsu * regs_get_argument() returns @n th argument of the function call.
4193c88ee19SMasami Hiramatsu * Note that this chooses most probably assignment, in some case
4203c88ee19SMasami Hiramatsu * it can be incorrect.
4213c88ee19SMasami Hiramatsu * This is expected to be called from kprobes or ftrace with regs
4223c88ee19SMasami Hiramatsu * where the top of stack is the return address.
4233c88ee19SMasami Hiramatsu */
regs_get_kernel_argument(struct pt_regs * regs,unsigned int n)4243c88ee19SMasami Hiramatsu static inline unsigned long regs_get_kernel_argument(struct pt_regs *regs,
4253c88ee19SMasami Hiramatsu unsigned int n)
4263c88ee19SMasami Hiramatsu {
4273c88ee19SMasami Hiramatsu static const unsigned int argument_offs[] = {
4283c88ee19SMasami Hiramatsu #ifdef __i386__
4293c88ee19SMasami Hiramatsu offsetof(struct pt_regs, ax),
4303c88ee19SMasami Hiramatsu offsetof(struct pt_regs, dx),
4312356bb4bSVamshi K Sthambamkadi offsetof(struct pt_regs, cx),
4323c88ee19SMasami Hiramatsu #define NR_REG_ARGUMENTS 3
4333c88ee19SMasami Hiramatsu #else
4343c88ee19SMasami Hiramatsu offsetof(struct pt_regs, di),
4353c88ee19SMasami Hiramatsu offsetof(struct pt_regs, si),
4363c88ee19SMasami Hiramatsu offsetof(struct pt_regs, dx),
4373c88ee19SMasami Hiramatsu offsetof(struct pt_regs, cx),
4383c88ee19SMasami Hiramatsu offsetof(struct pt_regs, r8),
4393c88ee19SMasami Hiramatsu offsetof(struct pt_regs, r9),
4403c88ee19SMasami Hiramatsu #define NR_REG_ARGUMENTS 6
4413c88ee19SMasami Hiramatsu #endif
4423c88ee19SMasami Hiramatsu };
4433c88ee19SMasami Hiramatsu
4443c88ee19SMasami Hiramatsu if (n >= NR_REG_ARGUMENTS) {
4453c88ee19SMasami Hiramatsu n -= NR_REG_ARGUMENTS - 1;
4463c88ee19SMasami Hiramatsu return regs_get_kernel_stack_nth(regs, n);
4473c88ee19SMasami Hiramatsu } else
4483c88ee19SMasami Hiramatsu return regs_get_register(regs, argument_offs[n]);
4493c88ee19SMasami Hiramatsu }
4503c88ee19SMasami Hiramatsu
451bb898558SAl Viro #define arch_has_single_step() (1)
452bb898558SAl Viro #ifdef CONFIG_X86_DEBUGCTLMSR
453bb898558SAl Viro #define arch_has_block_step() (1)
454bb898558SAl Viro #else
455bb898558SAl Viro #define arch_has_block_step() (boot_cpu_data.x86 >= 6)
456bb898558SAl Viro #endif
457bb898558SAl Viro
458efc463adSEric W. Biederman #define ARCH_HAS_USER_SINGLE_STEP_REPORT
4597f38551fSOleg Nesterov
460bb898558SAl Viro struct user_desc;
461bb898558SAl Viro extern int do_get_thread_area(struct task_struct *p, int idx,
462bb898558SAl Viro struct user_desc __user *info);
463bb898558SAl Viro extern int do_set_thread_area(struct task_struct *p, int idx,
464bb898558SAl Viro struct user_desc __user *info, int can_allocate);
465bb898558SAl Viro
4662fff071dSThomas Gleixner #ifdef CONFIG_X86_64
4672fff071dSThomas Gleixner # define do_set_thread_area_64(p, s, t) do_arch_prctl_64(p, s, t)
4682fff071dSThomas Gleixner #else
4692fff071dSThomas Gleixner # define do_set_thread_area_64(p, s, t) (0)
4702fff071dSThomas Gleixner #endif
4712fff071dSThomas Gleixner
472bb898558SAl Viro #endif /* !__ASSEMBLY__ */
4731965aae3SH. Peter Anvin #endif /* _ASM_X86_PTRACE_H */
474