2008-10-22 22:26:29 -07:00
# ifndef _ASM_X86_PTRACE_H
# define _ASM_X86_PTRACE_H
2007-10-23 22:37:24 +02:00
# include <linux/compiler.h> /* For __user */
# include <asm/ptrace-abi.h>
2008-05-28 09:46:19 +02:00
# include <asm/processor-flags.h>
2007-10-23 22:37:24 +02:00
2008-05-28 09:46:19 +02:00
# ifdef __KERNEL__
# include <asm/segment.h>
2009-08-13 16:34:44 -04:00
# include <asm/page_types.h>
2008-05-28 09:46:19 +02:00
# endif
2008-01-30 13:31:09 +01:00
2007-10-23 22:37:24 +02:00
# ifndef __ASSEMBLY__
# ifdef __i386__
/* this struct defines the way the registers are stored on the
stack during a system call . */
2008-01-30 13:30:56 +01:00
# ifndef __KERNEL__
2007-10-23 22:37:24 +02:00
struct pt_regs {
long ebx ;
long ecx ;
long edx ;
long esi ;
long edi ;
long ebp ;
long eax ;
int xds ;
int xes ;
int xfs ;
2009-02-09 22:17:40 +09:00
int xgs ;
2007-10-23 22:37:24 +02:00
long orig_eax ;
long eip ;
int xcs ;
long eflags ;
long esp ;
int xss ;
} ;
2008-01-30 13:30:56 +01:00
# else /* __KERNEL__ */
struct pt_regs {
2008-02-08 12:09:56 -08:00
unsigned long bx ;
unsigned long cx ;
unsigned long dx ;
unsigned long si ;
unsigned long di ;
unsigned long bp ;
2008-02-08 12:09:57 -08:00
unsigned long ax ;
2008-02-08 12:09:56 -08:00
unsigned long ds ;
unsigned long es ;
unsigned long fs ;
2009-02-09 22:17:40 +09:00
unsigned long gs ;
2008-02-08 12:09:57 -08:00
unsigned long orig_ax ;
2008-02-08 12:09:56 -08:00
unsigned long ip ;
unsigned long cs ;
unsigned long flags ;
unsigned long sp ;
unsigned long ss ;
2008-01-30 13:30:56 +01:00
} ;
2007-10-23 22:37:24 +02:00
# endif /* __KERNEL__ */
# else /* __i386__ */
2008-01-30 13:30:56 +01:00
# ifndef __KERNEL__
2007-10-23 22:37:24 +02:00
struct pt_regs {
unsigned long r15 ;
unsigned long r14 ;
unsigned long r13 ;
unsigned long r12 ;
unsigned long rbp ;
unsigned long rbx ;
2011-03-17 16:24:16 -03:00
/* arguments: non interrupts/non tracing syscalls only save up to here*/
2007-10-23 22:37:24 +02:00
unsigned long r11 ;
unsigned long r10 ;
unsigned long r9 ;
unsigned long r8 ;
unsigned long rax ;
unsigned long rcx ;
unsigned long rdx ;
unsigned long rsi ;
unsigned long rdi ;
unsigned long orig_rax ;
/* end of arguments */
/* cpu exception frame or undefined */
unsigned long rip ;
unsigned long cs ;
unsigned long eflags ;
unsigned long rsp ;
unsigned long ss ;
/* top of stack page */
} ;
2008-01-30 13:30:56 +01:00
# else /* __KERNEL__ */
struct pt_regs {
unsigned long r15 ;
unsigned long r14 ;
unsigned long r13 ;
unsigned long r12 ;
unsigned long bp ;
unsigned long bx ;
2011-03-17 16:24:16 -03:00
/* arguments: non interrupts/non tracing syscalls only save up to here*/
2008-01-30 13:30:56 +01:00
unsigned long r11 ;
unsigned long r10 ;
unsigned long r9 ;
unsigned long r8 ;
unsigned long ax ;
unsigned long cx ;
unsigned long dx ;
unsigned long si ;
unsigned long di ;
unsigned long orig_ax ;
/* end of arguments */
/* cpu exception frame or undefined */
unsigned long ip ;
unsigned long cs ;
unsigned long flags ;
unsigned long sp ;
unsigned long ss ;
/* top of stack page */
} ;
2007-10-23 22:37:24 +02:00
2008-01-30 13:33:16 +01:00
# endif /* __KERNEL__ */
# endif /* !__i386__ */
2007-10-23 22:37:24 +02:00
2008-04-08 11:01:58 +02:00
2008-01-30 13:33:16 +01:00
# ifdef __KERNEL__
2008-04-08 11:01:58 +02:00
# include <linux/init.h>
2011-08-03 09:31:53 -04:00
# ifdef CONFIG_PARAVIRT
# include <asm/paravirt_types.h>
# endif
2007-10-23 22:37:24 +02:00
2008-04-08 11:01:58 +02:00
struct cpuinfo_x86 ;
2007-10-23 22:37:24 +02:00
struct task_struct ;
2008-01-30 13:33:16 +01:00
extern unsigned long profile_pc ( struct pt_regs * regs ) ;
2011-05-26 16:25:43 -07:00
# define profile_pc profile_pc
2008-01-30 13:33:16 +01:00
2007-10-23 22:37:24 +02:00
extern unsigned long
2008-01-30 13:33:12 +01:00
convert_ip_to_linear ( struct task_struct * child , struct pt_regs * regs ) ;
2008-03-23 01:03:17 -07:00
extern void send_sigtrap ( struct task_struct * tsk , struct pt_regs * regs ,
2008-09-23 15:23:52 +05:30
int error_code , int si_code ) ;
2008-09-05 16:27:11 -07:00
void signal_fault ( struct pt_regs * regs , void __user * frame , char * where ) ;
2008-07-21 22:35:38 +05:30
extern long syscall_trace_enter ( struct pt_regs * ) ;
extern void syscall_trace_leave ( struct pt_regs * ) ;
2008-02-08 12:09:57 -08:00
static inline unsigned long regs_return_value ( struct pt_regs * regs )
{
return regs - > ax ;
}
2008-01-30 13:30:46 +01:00
2008-01-30 13:33:16 +01:00
/*
* user_mode_vm ( regs ) determines whether a register set came from user mode .
* This is true if V8086 mode was enabled OR if the register set was from
* protected mode with RPL - 3 CS value . This tricky test checks that with
* one comparison . Many places in the kernel can bypass this full check
* if they have already ruled out V8086 mode , so user_mode ( regs ) can be used .
*/
static inline int user_mode ( struct pt_regs * regs )
{
# ifdef CONFIG_X86_32
return ( regs - > cs & SEGMENT_RPL_MASK ) = = USER_RPL ;
# else
return ! ! ( regs - > cs & 3 ) ;
# endif
}
static inline int user_mode_vm ( struct pt_regs * regs )
{
# ifdef CONFIG_X86_32
2008-03-28 17:56:57 +03:00
return ( ( regs - > cs & SEGMENT_RPL_MASK ) | ( regs - > flags & X86_VM_MASK ) ) > =
2008-03-23 01:03:17 -07:00
USER_RPL ;
2008-01-30 13:33:16 +01:00
# else
return user_mode ( regs ) ;
# endif
}
static inline int v8086_mode ( struct pt_regs * regs )
{
# ifdef CONFIG_X86_32
2008-03-28 17:56:57 +03:00
return ( regs - > flags & X86_VM_MASK ) ;
2008-01-30 13:33:16 +01:00
# else
return 0 ; /* No V86 mode support in long mode */
# endif
}
2011-08-03 09:31:53 -04:00
# ifdef CONFIG_X86_64
static inline bool user_64bit_mode ( struct pt_regs * regs )
{
# ifndef CONFIG_PARAVIRT
/*
* On non - paravirt systems , this is the only long mode CPL 3
* selector . We do not allow long mode selectors in the LDT .
*/
return regs - > cs = = __USER_CS ;
# else
/* Headers are too twisted for this to go in paravirt.h. */
return regs - > cs = = __USER_CS | | regs - > cs = = pv_info . extra_user_64bit_cs ;
# endif
}
# endif
2008-01-30 13:33:16 +01:00
/*
* X86_32 CPUs don ' t save ss and esp if the CPU is already in kernel mode
2009-05-11 17:03:00 -04:00
* when it traps . The previous stack will be directly underneath the saved
* registers , and ' sp / ss ' won ' t even have been saved . Thus the ' & regs - > sp ' .
2008-01-30 13:33:16 +01:00
*
* This is valid only for kernel mode traps .
*/
2009-05-11 17:03:00 -04:00
static inline unsigned long kernel_stack_pointer ( struct pt_regs * regs )
2008-01-30 13:33:16 +01:00
{
# ifdef CONFIG_X86_32
2009-05-11 17:03:00 -04:00
return ( unsigned long ) ( & regs - > sp ) ;
2008-01-30 13:33:16 +01:00
# else
return regs - > sp ;
# endif
}
2011-05-26 16:25:43 -07:00
# define GET_IP(regs) ((regs)->ip)
# define GET_FP(regs) ((regs)->bp)
# define GET_USP(regs) ((regs)->sp)
2008-01-30 13:33:16 +01:00
2011-05-26 16:25:43 -07:00
# include <asm-generic/ptrace.h>
2008-04-18 17:08:44 -07:00
2009-08-13 16:34:44 -04:00
/* Query offset/name of register from its name/offset */
extern int regs_query_register_offset ( const char * name ) ;
extern const char * regs_query_register_name ( unsigned int offset ) ;
# define MAX_REG_OFFSET (offsetof(struct pt_regs, ss))
/**
* regs_get_register ( ) - get register value from its offset
* @ regs : pt_regs from which register value is gotten .
* @ offset : offset number of the register .
*
2009-11-30 19:02:22 -05:00
* regs_get_register returns the value of a register . The @ offset is the
* offset of the register in struct pt_regs address which specified by @ regs .
2009-08-13 16:34:44 -04:00
* 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 ) ;
}
/**
* regs_within_kernel_stack ( ) - check the address in the stack
* @ regs : pt_regs which contains kernel stack pointer .
* @ addr : address which is checked .
*
2009-11-30 19:02:22 -05:00
* regs_within_kernel_stack ( ) checks @ addr is within the kernel stack page ( s ) .
2009-08-13 16:34:44 -04:00
* If @ addr is within the kernel stack , it returns true . If not , returns false .
*/
static inline int regs_within_kernel_stack ( struct pt_regs * regs ,
unsigned long addr )
{
return ( ( addr & ~ ( THREAD_SIZE - 1 ) ) = =
( kernel_stack_pointer ( regs ) & ~ ( THREAD_SIZE - 1 ) ) ) ;
}
/**
* regs_get_kernel_stack_nth ( ) - get Nth entry of the stack
* @ regs : pt_regs which contains kernel stack pointer .
* @ n : stack entry number .
*
* regs_get_kernel_stack_nth ( ) returns @ n th entry of the kernel stack which
2009-11-30 19:02:22 -05:00
* is specified by @ regs . If the @ n th entry is NOT in the kernel stack ,
2009-08-13 16:34:44 -04:00
* this returns 0.
*/
static inline unsigned long regs_get_kernel_stack_nth ( struct pt_regs * regs ,
unsigned int n )
{
unsigned long * addr = ( unsigned long * ) kernel_stack_pointer ( regs ) ;
addr + = n ;
if ( regs_within_kernel_stack ( regs , ( unsigned long ) addr ) )
return * addr ;
else
return 0 ;
}
2008-01-30 13:30:48 +01:00
# define arch_has_single_step() (1)
2008-01-30 13:30:54 +01:00
# ifdef CONFIG_X86_DEBUGCTLMSR
# define arch_has_block_step() (1)
# else
# define arch_has_block_step() (boot_cpu_data.x86 >= 6)
# endif
2009-12-15 16:47:20 -08:00
# define ARCH_HAS_USER_SINGLE_STEP_INFO
2008-01-30 13:30:46 +01:00
struct user_desc ;
extern int do_get_thread_area ( struct task_struct * p , int idx ,
struct user_desc __user * info ) ;
extern int do_set_thread_area ( struct task_struct * p , int idx ,
struct user_desc __user * info , int can_allocate ) ;
# endif /* __KERNEL__ */
2007-10-23 22:37:24 +02:00
# endif /* !__ASSEMBLY__ */
2008-10-22 22:26:29 -07:00
# endif /* _ASM_X86_PTRACE_H */