Commit 1022623 1 parent c1ddb48 commit 1022623 Copy full SHA for 1022623
File tree 2 files changed +32
-11
lines changed
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)
205
205
}
206
206
#endif
207
207
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
- {
217
208
#ifdef CONFIG_X86_32
218
- return ( unsigned long )( & regs -> sp );
209
+ extern unsigned long kernel_stack_pointer ( struct pt_regs * regs );
219
210
#else
211
+ static inline unsigned long kernel_stack_pointer (struct pt_regs * regs )
212
+ {
220
213
return regs -> sp ;
221
- #endif
222
214
}
215
+ #endif
223
216
224
217
#define GET_IP (regs ) ((regs)->ip)
225
218
#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)
166
166
167
167
#define FLAG_MASK FLAG_MASK_32
168
168
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
+
169
197
static unsigned long * pt_regs_access (struct pt_regs * regs , unsigned long regno )
170
198
{
171
199
BUILD_BUG_ON (offsetof(struct pt_regs , bx ) != 0 );
You can’t perform that action at this time.
0 commit comments