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)
187
187
#endif
188
188
}
189
189
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
- {
199
190
#ifdef CONFIG_X86_32
200
- return ( unsigned long )( & regs -> sp );
191
+ extern unsigned long kernel_stack_pointer ( struct pt_regs * regs );
201
192
#else
193
+ static inline unsigned long kernel_stack_pointer (struct pt_regs * regs )
194
+ {
202
195
return regs -> sp ;
203
- #endif
204
196
}
197
+ #endif
205
198
206
199
#define GET_IP (regs ) ((regs)->ip)
207
200
#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)
164
164
165
165
#define FLAG_MASK FLAG_MASK_32
166
166
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
+
167
195
static unsigned long * pt_regs_access (struct pt_regs * regs , unsigned long regno )
168
196
{
169
197
BUILD_BUG_ON (offsetof(struct pt_regs , bx ) != 0 );
You can’t perform that action at this time.
0 commit comments