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 @@ -187,21 +187,14 @@ static inline int v8086_mode(struct pt_regs *regs)
187187#endif
188188}
189189
190- /*
191- * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode
192- * when it traps. The previous stack will be directly underneath the saved
193- * registers, and 'sp/ss' won't even have been saved. Thus the '®s->sp'.
194- *
195- * This is valid only for kernel mode traps.
196- */
197- static inline unsigned long kernel_stack_pointer (struct pt_regs * regs )
198- {
199190#ifdef CONFIG_X86_32
200- return ( unsigned long )( & regs -> sp );
191+ extern unsigned long kernel_stack_pointer ( struct pt_regs * regs );
201192#else
193+ static inline unsigned long kernel_stack_pointer (struct pt_regs * regs )
194+ {
202195 return regs -> sp ;
203- #endif
204196}
197+ #endif
205198
206199#define GET_IP (regs ) ((regs)->ip)
207200#define GET_FP (regs ) ((regs)->bp)
Original file line number Diff line number Diff line change @@ -164,6 +164,34 @@ static inline bool invalid_selector(u16 value)
164164
165165#define FLAG_MASK FLAG_MASK_32
166166
167+ /*
168+ * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode
169+ * when it traps. The previous stack will be directly underneath the saved
170+ * registers, and 'sp/ss' won't even have been saved. Thus the '®s->sp'.
171+ *
172+ * Now, if the stack is empty, '®s->sp' is out of range. In this
173+ * case we try to take the previous stack. To always return a non-null
174+ * stack pointer we fall back to regs as stack if no previous stack
175+ * exists.
176+ *
177+ * This is valid only for kernel mode traps.
178+ */
179+ unsigned long kernel_stack_pointer (struct pt_regs * regs )
180+ {
181+ unsigned long context = (unsigned long )regs & ~(THREAD_SIZE - 1 );
182+ unsigned long sp = (unsigned long )& regs -> sp ;
183+ struct thread_info * tinfo ;
184+
185+ if (context == (sp & ~(THREAD_SIZE - 1 )))
186+ return sp ;
187+
188+ tinfo = (struct thread_info * )context ;
189+ if (tinfo -> previous_esp )
190+ return tinfo -> previous_esp ;
191+
192+ return (unsigned long )regs ;
193+ }
194+
167195static unsigned long * pt_regs_access (struct pt_regs * regs , unsigned long regno )
168196{
169197 BUILD_BUG_ON (offsetof(struct pt_regs , bx ) != 0 );
You can’t perform that action at this time.
0 commit comments