Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 336004
b: refs/heads/master
c: 1022623
h: refs/heads/master
v: v3
  • Loading branch information
Robert Richter authored and H. Peter Anvin committed Nov 21, 2012
1 parent 88257da commit c303a87
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 12 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c1ddb482044ca6bfe3de6d45ef17383f3d719ed7
refs/heads/master: 1022623842cb72ee4d0dbf02f6937f38c92c3f41
15 changes: 4 additions & 11 deletions trunk/arch/x86/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,21 +205,14 @@ static inline bool user_64bit_mode(struct pt_regs *regs)
}
#endif

/*
* X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode
* 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'.
*
* This is valid only for kernel mode traps.
*/
static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
{
#ifdef CONFIG_X86_32
return (unsigned long)(&regs->sp);
extern unsigned long kernel_stack_pointer(struct pt_regs *regs);
#else
static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
{
return regs->sp;
#endif
}
#endif

#define GET_IP(regs) ((regs)->ip)
#define GET_FP(regs) ((regs)->bp)
Expand Down
28 changes: 28 additions & 0 deletions trunk/arch/x86/kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,34 @@ static inline bool invalid_selector(u16 value)

#define FLAG_MASK FLAG_MASK_32

/*
* X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode
* 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'.
*
* Now, if the stack is empty, '&regs->sp' is out of range. In this
* case we try to take the previous stack. To always return a non-null
* stack pointer we fall back to regs as stack if no previous stack
* exists.
*
* This is valid only for kernel mode traps.
*/
unsigned long kernel_stack_pointer(struct pt_regs *regs)
{
unsigned long context = (unsigned long)regs & ~(THREAD_SIZE - 1);
unsigned long sp = (unsigned long)&regs->sp;
struct thread_info *tinfo;

if (context == (sp & ~(THREAD_SIZE - 1)))
return sp;

tinfo = (struct thread_info *)context;
if (tinfo->previous_esp)
return tinfo->previous_esp;

return (unsigned long)regs;
}

static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno)
{
BUILD_BUG_ON(offsetof(struct pt_regs, bx) != 0);
Expand Down

0 comments on commit c303a87

Please sign in to comment.