File tree Expand file tree Collapse file tree 2 files changed +32
-11
lines changed Expand file tree Collapse file tree 2 files changed +32
-11
lines changed Original file line number Diff line number Diff line change @@ -205,21 +205,14 @@ static inline bool user_64bit_mode(struct pt_regs *regs)
205205}
206206#endif
207207
208- /*
209- * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode
210- * when it traps. The previous stack will be directly underneath the saved
211- * registers, and 'sp/ss' won't even have been saved. Thus the '®s->sp'.
212- *
213- * This is valid only for kernel mode traps.
214- */
215- static inline unsigned long kernel_stack_pointer (struct pt_regs * regs )
216- {
217208#ifdef CONFIG_X86_32
218- return ( unsigned long )( & regs -> sp );
209+ extern unsigned long kernel_stack_pointer ( struct pt_regs * regs );
219210#else
211+ static inline unsigned long kernel_stack_pointer (struct pt_regs * regs )
212+ {
220213 return regs -> sp ;
221- #endif
222214}
215+ #endif
223216
224217#define GET_IP (regs ) ((regs)->ip)
225218#define GET_FP (regs ) ((regs)->bp)
Original file line number Diff line number Diff line change @@ -166,6 +166,34 @@ static inline bool invalid_selector(u16 value)
166166
167167#define FLAG_MASK FLAG_MASK_32
168168
169+ /*
170+ * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode
171+ * when it traps. The previous stack will be directly underneath the saved
172+ * registers, and 'sp/ss' won't even have been saved. Thus the '®s->sp'.
173+ *
174+ * Now, if the stack is empty, '®s->sp' is out of range. In this
175+ * case we try to take the previous stack. To always return a non-null
176+ * stack pointer we fall back to regs as stack if no previous stack
177+ * exists.
178+ *
179+ * This is valid only for kernel mode traps.
180+ */
181+ unsigned long kernel_stack_pointer (struct pt_regs * regs )
182+ {
183+ unsigned long context = (unsigned long )regs & ~(THREAD_SIZE - 1 );
184+ unsigned long sp = (unsigned long )& regs -> sp ;
185+ struct thread_info * tinfo ;
186+
187+ if (context == (sp & ~(THREAD_SIZE - 1 )))
188+ return sp ;
189+
190+ tinfo = (struct thread_info * )context ;
191+ if (tinfo -> previous_esp )
192+ return tinfo -> previous_esp ;
193+
194+ return (unsigned long )regs ;
195+ }
196+
169197static unsigned long * pt_regs_access (struct pt_regs * regs , unsigned long regno )
170198{
171199 BUILD_BUG_ON (offsetof(struct pt_regs , bx ) != 0 );
You can’t perform that action at this time.
0 commit comments