Commit 7c7fcf762e405eb040ee10d22d656a791f616122

Authored by David Howells
1 parent a5e03ca2fd

MN10300: Save frame pointer in thread_info struct rather than global var

Save the current exception frame pointer in the thread_info struct rather than
in a global variable as the latter makes SMP tricky, especially when preemption
is also enabled.

This also replaces __frame with current_frame() and rearranges header file
inclusions to make it all compile.

Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Akira Takeuchi <takeuchi.akr@jp.panasonic.com>

Showing 15 changed files with 76 additions and 146 deletions Side-by-side Diff

arch/mn10300/include/asm/frame.inc
... ... @@ -18,9 +18,7 @@
18 18 #ifndef __ASM_OFFSETS_H__
19 19 #include <asm/asm-offsets.h>
20 20 #endif
21   -#ifdef CONFIG_SMP
22   -#include <proc/smp-regs.h>
23   -#endif
  21 +#include <asm/thread_info.h>
24 22  
25 23 #define pi break
26 24  
27 25  
28 26  
... ... @@ -40,28 +38,16 @@
40 38 movm [d2,d3,a2,a3,exreg0,exreg1,exother],(sp)
41 39 mov sp,fp # FRAME pointer in A3
42 40 add -12,sp # allow for calls to be made
43   -#ifdef CONFIG_SMP
44   -#ifdef CONFIG_PREEMPT /* FIXME */
45   - mov epsw,d2
46   - and ~EPSW_IE,epsw
47   -#endif
48   - mov (CPUID),a0
49   - add a0,a0
50   - add a0,a0
51   - mov (___frame,a0),a1
52   - mov a1,(REG_NEXT,fp)
53   - mov fp,(___frame,a0)
54   -#ifdef CONFIG_PREEMPT /* FIXME */
55   - mov d2,epsw
56   -#endif
57   -#else /* CONFIG_SMP */
58   - mov (__frame),a1
59   - mov a1,(REG_NEXT,fp)
60   - mov fp,(__frame)
61   -#endif /* CONFIG_SMP */
62 41  
63   - and ~EPSW_FE,epsw # disable the FPU inside the kernel
  42 + # push the exception frame onto the front of the list
  43 + GET_THREAD_INFO a1
  44 + mov (TI_frame,a1),a0
  45 + mov a0,(REG_NEXT,fp)
  46 + mov fp,(TI_frame,a1)
64 47  
  48 + # disable the FPU inside the kernel
  49 + and ~EPSW_FE,epsw
  50 +
65 51 # we may be holding current in E2
66 52 #ifdef CONFIG_MN10300_CURRENT_IN_E2
67 53 mov (__current),e2
68 54  
... ... @@ -76,27 +62,11 @@
76 62 .macro RESTORE_ALL
77 63 # peel back the stack to the calling frame
78 64 # - this permits execve() to discard extra frames due to kernel syscalls
79   -#ifdef CONFIG_SMP
80   -#ifdef CONFIG_PREEMPT /* FIXME */
81   - mov epsw,d2
82   - and ~EPSW_IE,epsw
83   -#endif
84   - mov (CPUID),a0
85   - add a0,a0
86   - add a0,a0
87   - mov (___frame,a0),fp
  65 + GET_THREAD_INFO a0
  66 + mov (TI_frame,a0),fp
88 67 mov fp,sp
89   - mov (REG_NEXT,fp),d0 # userspace has regs->next == 0
90   - mov d0,(___frame,a0)
91   -#ifdef CONFIG_PREEMPT /* FIXME */
92   - mov d2,epsw
93   -#endif
94   -#else /* CONFIG_SMP */
95   - mov (__frame),fp
96   - mov fp,sp
97   - mov (REG_NEXT,fp),d0 # userspace has regs->next == 0
98   - mov d0,(__frame)
99   -#endif /* CONFIG_SMP */
  68 + mov (REG_NEXT,fp),d0
  69 + mov d0,(TI_frame,a0) # userspace has regs->next == 0
100 70  
101 71 #ifndef CONFIG_MN10300_USING_JTAG
102 72 mov (REG_EPSW,fp),d0
arch/mn10300/include/asm/irq_regs.h
... ... @@ -18,7 +18,11 @@
18 18 #define ARCH_HAS_OWN_IRQ_REGS
19 19  
20 20 #ifndef __ASSEMBLY__
21   -#define get_irq_regs() (__frame)
  21 +static inline __attribute__((const))
  22 +struct pt_regs *get_irq_regs(void)
  23 +{
  24 + return current_frame();
  25 +}
22 26 #endif
23 27  
24 28 #endif /* _ASM_IRQ_REGS_H */
arch/mn10300/include/asm/pgalloc.h
... ... @@ -11,7 +11,6 @@
11 11 #ifndef _ASM_PGALLOC_H
12 12 #define _ASM_PGALLOC_H
13 13  
14   -#include <asm/processor.h>
15 14 #include <asm/page.h>
16 15 #include <linux/threads.h>
17 16 #include <linux/mm.h> /* for struct page */
arch/mn10300/include/asm/processor.h
... ... @@ -13,10 +13,13 @@
13 13 #ifndef _ASM_PROCESSOR_H
14 14 #define _ASM_PROCESSOR_H
15 15  
  16 +#include <linux/threads.h>
  17 +#include <linux/thread_info.h>
16 18 #include <asm/page.h>
17 19 #include <asm/ptrace.h>
18 20 #include <asm/cpu-regs.h>
19   -#include <linux/threads.h>
  21 +#include <asm/uaccess.h>
  22 +#include <asm/current.h>
20 23  
21 24 /* Forward declaration, a strange C thing */
22 25 struct task_struct;
... ... @@ -83,10 +86,6 @@
83 86 */
84 87 #define TASK_UNMAPPED_BASE 0x30000000
85 88  
86   -typedef struct {
87   - unsigned long seg;
88   -} mm_segment_t;
89   -
90 89 struct fpu_state_struct {
91 90 unsigned long fs[32]; /* fpu registers */
92 91 unsigned long fpcr; /* fpu control register */
... ... @@ -99,7 +98,6 @@
99 98 unsigned long a3; /* kernel FP */
100 99 unsigned long wchan;
101 100 unsigned long usp;
102   - struct pt_regs *frame;
103 101 unsigned long fpu_flags;
104 102 #define THREAD_USING_FPU 0x00000001 /* T if this task is using the FPU */
105 103 #define THREAD_HAS_FPU 0x00000002 /* T if this task owns the FPU right now */
... ... @@ -113,7 +111,6 @@
113 111 .sp = 0, \
114 112 .a3 = 0, \
115 113 .wchan = 0, \
116   - .frame = NULL, \
117 114 }
118 115  
119 116 #define INIT_MMAP \
... ... @@ -125,27 +122,20 @@
125 122 * - need to discard the frame stacked by the kernel thread invoking the execve
126 123 * syscall (see RESTORE_ALL macro)
127 124 */
128   -#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT) /* FIXME */
129   -#define start_thread(regs, new_pc, new_sp) do { \
130   - int cpu; \
131   - preempt_disable(); \
132   - cpu = CPUID; \
133   - set_fs(USER_DS); \
134   - ___frame[cpu] = current->thread.uregs; \
135   - ___frame[cpu]->epsw = EPSW_nSL | EPSW_IE | EPSW_IM;\
136   - ___frame[cpu]->pc = new_pc; \
137   - ___frame[cpu]->sp = new_sp; \
138   - preempt_enable(); \
139   -} while (0)
140   -#else /* CONFIG_SMP && CONFIG_PREEMPT */
141   -#define start_thread(regs, new_pc, new_sp) do { \
142   - set_fs(USER_DS); \
143   - __frame = current->thread.uregs; \
144   - __frame->epsw = EPSW_nSL | EPSW_IE | EPSW_IM; \
145   - __frame->pc = new_pc; \
146   - __frame->sp = new_sp; \
147   -} while (0)
148   -#endif /* CONFIG_SMP && CONFIG_PREEMPT */
  125 +static inline void start_thread(struct pt_regs *regs,
  126 + unsigned long new_pc, unsigned long new_sp)
  127 +{
  128 + struct thread_info *ti = current_thread_info();
  129 + struct pt_regs *frame0;
  130 + set_fs(USER_DS);
  131 +
  132 + frame0 = thread_info_to_uregs(ti);
  133 + frame0->epsw = EPSW_nSL | EPSW_IE | EPSW_IM;
  134 + frame0->pc = new_pc;
  135 + frame0->sp = new_sp;
  136 + ti->frame = frame0;
  137 +}
  138 +
149 139  
150 140 /* Free all resources held by a thread. */
151 141 extern void release_thread(struct task_struct *);
arch/mn10300/include/asm/ptrace.h
... ... @@ -86,12 +86,6 @@
86 86  
87 87 #ifdef __KERNEL__
88 88  
89   -#ifdef CONFIG_SMP
90   -extern struct pt_regs *___frame[]; /* current frame pointer */
91   -#else
92   -extern struct pt_regs *__frame; /* current frame pointer */
93   -#endif
94   -
95 89 #define user_mode(regs) (((regs)->epsw & EPSW_nSL) == EPSW_nSL)
96 90 #define instruction_pointer(regs) ((regs)->pc)
97 91 #define user_stack_pointer(regs) ((regs)->sp)
arch/mn10300/include/asm/smp.h
... ... @@ -93,19 +93,6 @@
93 93 extern void __cpu_die(unsigned int cpu);
94 94 #endif /* CONFIG_HOTPLUG_CPU */
95 95  
96   -#ifdef CONFIG_PREEMPT /* FIXME */
97   -#define __frame \
98   - ({ \
99   - struct pt_regs *f; \
100   - preempt_disable(); \
101   - f = ___frame[CPUID]; \
102   - preempt_enable(); \
103   - f; \
104   - })
105   -#else
106   -#define __frame ___frame[CPUID]
107   -#endif
108   -
109 96 #endif /* __ASSEMBLY__ */
110 97 #else /* CONFIG_SMP */
111 98 #ifndef __ASSEMBLY__
arch/mn10300/include/asm/thread_info.h
... ... @@ -16,10 +16,6 @@
16 16  
17 17 #include <asm/page.h>
18 18  
19   -#ifndef __ASSEMBLY__
20   -#include <asm/processor.h>
21   -#endif
22   -
23 19 #define PREEMPT_ACTIVE 0x10000000
24 20  
25 21 #ifdef CONFIG_4KSTACKS
26 22  
... ... @@ -38,10 +34,14 @@
38 34 * must also be changed
39 35 */
40 36 #ifndef __ASSEMBLY__
  37 +typedef struct {
  38 + unsigned long seg;
  39 +} mm_segment_t;
41 40  
42 41 struct thread_info {
43 42 struct task_struct *task; /* main task structure */
44 43 struct exec_domain *exec_domain; /* execution domain */
  44 + struct pt_regs *frame; /* current exception frame */
45 45 unsigned long flags; /* low level flags */
46 46 __u32 cpu; /* current CPU */
47 47 __s32 preempt_count; /* 0 => preemptable, <0 => BUG */
... ... @@ -55,6 +55,10 @@
55 55 __u8 supervisor_stack[0];
56 56 };
57 57  
  58 +#define thread_info_to_uregs(ti) \
  59 + ((struct pt_regs *) \
  60 + ((unsigned long)ti + THREAD_SIZE - sizeof(struct pt_regs)))
  61 +
58 62 #else /* !__ASSEMBLY__ */
59 63  
60 64 #ifndef __ASM_OFFSETS_H__
... ... @@ -100,6 +104,12 @@
100 104 : "i" (~(THREAD_SIZE - 1))
101 105 : "cc");
102 106 return ti;
  107 +}
  108 +
  109 +static inline __attribute__((const))
  110 +struct pt_regs *current_frame(void)
  111 +{
  112 + return current_thread_info()->frame;
103 113 }
104 114  
105 115 /* how to get the current stack pointer from C */
arch/mn10300/include/asm/uaccess.h
... ... @@ -14,9 +14,8 @@
14 14 /*
15 15 * User space memory access functions
16 16 */
17   -#include <linux/sched.h>
  17 +#include <linux/thread_info.h>
18 18 #include <asm/page.h>
19   -#include <asm/pgtable.h>
20 19 #include <asm/errno.h>
21 20  
22 21 #define VERIFY_READ 0
... ... @@ -29,7 +28,6 @@
29 28 *
30 29 * For historical reasons, these macros are grossly misnamed.
31 30 */
32   -
33 31 #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
34 32  
35 33 #define KERNEL_XDS MAKE_MM_SEG(0xBFFFFFFF)
arch/mn10300/kernel/asm-offsets.c
... ... @@ -23,6 +23,7 @@
23 23  
24 24 OFFSET(TI_task, thread_info, task);
25 25 OFFSET(TI_exec_domain, thread_info, exec_domain);
  26 + OFFSET(TI_frame, thread_info, frame);
26 27 OFFSET(TI_flags, thread_info, flags);
27 28 OFFSET(TI_cpu, thread_info, cpu);
28 29 OFFSET(TI_preempt_count, thread_info, preempt_count);
... ... @@ -66,7 +67,6 @@
66 67 OFFSET(THREAD_SP, thread_struct, sp);
67 68 OFFSET(THREAD_A3, thread_struct, a3);
68 69 OFFSET(THREAD_USP, thread_struct, usp);
69   - OFFSET(THREAD_FRAME, thread_struct, frame);
70 70 #ifdef CONFIG_FPU
71 71 OFFSET(THREAD_FPU_FLAGS, thread_struct, fpu_flags);
72 72 OFFSET(THREAD_FPU_STATE, thread_struct, fpu_state);
arch/mn10300/kernel/mn10300-watchdog.c
... ... @@ -122,7 +122,7 @@
122 122 static void watchdog_dump_register(void *dummy)
123 123 {
124 124 printk(KERN_ERR "--- Register Dump (CPU%d) ---\n", CPUID);
125   - show_registers(__frame);
  125 + show_registers(current_frame());
126 126 }
127 127 #endif
128 128  
arch/mn10300/kernel/process.c
... ... @@ -228,6 +228,7 @@
228 228 unsigned long c_usp, unsigned long ustk_size,
229 229 struct task_struct *p, struct pt_regs *kregs)
230 230 {
  231 + struct thread_info *ti = task_thread_info(p);
231 232 struct pt_regs *c_uregs, *c_kregs, *uregs;
232 233 unsigned long c_ksp;
233 234  
... ... @@ -248,7 +249,7 @@
248 249  
249 250 /* the new TLS pointer is passed in as arg #5 to sys_clone() */
250 251 if (clone_flags & CLONE_SETTLS)
251   - c_uregs->e2 = __frame->d3;
  252 + c_uregs->e2 = current_frame()->d3;
252 253  
253 254 /* set up the return kernel frame if called from kernel_thread() */
254 255 c_kregs = c_uregs;
... ... @@ -266,7 +267,7 @@
266 267 }
267 268  
268 269 /* set up things up so the scheduler can start the new task */
269   - p->thread.frame = c_kregs;
  270 + ti->frame = c_kregs;
270 271 p->thread.a3 = (unsigned long) c_kregs;
271 272 p->thread.sp = c_ksp;
272 273 p->thread.pc = (unsigned long) ret_from_fork;
273 274  
274 275  
275 276  
... ... @@ -278,25 +279,26 @@
278 279  
279 280 /*
280 281 * clone a process
281   - * - tlsptr is retrieved by copy_thread() from __frame->d3
  282 + * - tlsptr is retrieved by copy_thread() from current_frame()->d3
282 283 */
283 284 asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
284 285 int __user *parent_tidptr, int __user *child_tidptr,
285 286 int __user *tlsptr)
286 287 {
287   - return do_fork(clone_flags, newsp ?: __frame->sp, __frame, 0,
288   - parent_tidptr, child_tidptr);
  288 + return do_fork(clone_flags, newsp ?: current_frame()->sp,
  289 + current_frame(), 0, parent_tidptr, child_tidptr);
289 290 }
290 291  
291 292 asmlinkage long sys_fork(void)
292 293 {
293   - return do_fork(SIGCHLD, __frame->sp, __frame, 0, NULL, NULL);
  294 + return do_fork(SIGCHLD, current_frame()->sp,
  295 + current_frame(), 0, NULL, NULL);
294 296 }
295 297  
296 298 asmlinkage long sys_vfork(void)
297 299 {
298   - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, __frame->sp, __frame,
299   - 0, NULL, NULL);
  300 + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, current_frame()->sp,
  301 + current_frame(), 0, NULL, NULL);
300 302 }
301 303  
302 304 asmlinkage long sys_execve(const char __user *name,
... ... @@ -310,7 +312,7 @@
310 312 error = PTR_ERR(filename);
311 313 if (IS_ERR(filename))
312 314 return error;
313   - error = do_execve(filename, argv, envp, __frame);
  315 + error = do_execve(filename, argv, envp, current_frame());
314 316 putname(filename);
315 317 return error;
316 318 }
arch/mn10300/kernel/signal.c
... ... @@ -91,7 +91,7 @@
91 91 */
92 92 asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t *uoss)
93 93 {
94   - return do_sigaltstack(uss, uoss, __frame->sp);
  94 + return do_sigaltstack(uss, uoss, current_frame()->sp);
95 95 }
96 96  
97 97 /*
98 98  
... ... @@ -156,10 +156,11 @@
156 156 */
157 157 asmlinkage long sys_sigreturn(void)
158 158 {
159   - struct sigframe __user *frame = (struct sigframe __user *) __frame->sp;
  159 + struct sigframe __user *frame;
160 160 sigset_t set;
161 161 long d0;
162 162  
  163 + frame = (struct sigframe __user *) current_frame()->sp;
163 164 if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
164 165 goto badframe;
165 166 if (__get_user(set.sig[0], &frame->sc.oldmask))
... ... @@ -176,7 +177,7 @@
176 177 recalc_sigpending();
177 178 spin_unlock_irq(&current->sighand->siglock);
178 179  
179   - if (restore_sigcontext(__frame, &frame->sc, &d0))
  180 + if (restore_sigcontext(current_frame(), &frame->sc, &d0))
180 181 goto badframe;
181 182  
182 183 return d0;
183 184  
184 185  
... ... @@ -191,11 +192,11 @@
191 192 */
192 193 asmlinkage long sys_rt_sigreturn(void)
193 194 {
194   - struct rt_sigframe __user *frame =
195   - (struct rt_sigframe __user *) __frame->sp;
  195 + struct rt_sigframe __user *frame;
196 196 sigset_t set;
197   - unsigned long d0;
  197 + long d0;
198 198  
  199 + frame = (struct rt_sigframe __user *) current_frame()->sp;
199 200 if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
200 201 goto badframe;
201 202 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
202 203  
... ... @@ -207,10 +208,11 @@
207 208 recalc_sigpending();
208 209 spin_unlock_irq(&current->sighand->siglock);
209 210  
210   - if (restore_sigcontext(__frame, &frame->uc.uc_mcontext, &d0))
  211 + if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0))
211 212 goto badframe;
212 213  
213   - if (do_sigaltstack(&frame->uc.uc_stack, NULL, __frame->sp) == -EFAULT)
  214 + if (do_sigaltstack(&frame->uc.uc_stack, NULL, current_frame()->sp) ==
  215 + -EFAULT)
214 216 goto badframe;
215 217  
216 218 return d0;
... ... @@ -572,7 +574,7 @@
572 574  
573 575 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
574 576 clear_thread_flag(TIF_NOTIFY_RESUME);
575   - tracehook_notify_resume(__frame);
  577 + tracehook_notify_resume(current_frame());
576 578 if (current->replacement_session_keyring)
577 579 key_replace_session_keyring();
578 580 }
arch/mn10300/kernel/switch_to.S
... ... @@ -38,15 +38,6 @@
38 38 mov d1,a1
39 39  
40 40 # save prev context
41   -#ifdef CONFIG_SMP
42   - mov (CPUID),a2
43   - add a2,a2
44   - add a2,a2
45   - mov (___frame,a2),d0
46   -#else /* CONFIG_SMP */
47   - mov (__frame),d0
48   -#endif /* CONFIG_SMP */
49   - mov d0,(THREAD_FRAME,a0)
50 41 mov __switch_back,d0
51 42 mov d0,(THREAD_PC,a0)
52 43 mov sp,a2
... ... @@ -68,15 +59,6 @@
68 59 mov a2,e2
69 60 #endif
70 61  
71   - mov (THREAD_FRAME,a1),a2
72   -#ifdef CONFIG_SMP
73   - mov (CPUID),a0
74   - add a0,a0
75   - add a0,a0
76   - mov a2,(___frame,a0)
77   -#else /* CONFIG_SMP */
78   - mov a2,(__frame)
79   -#endif /* CONFIG_SMP */
80 62 mov (THREAD_PC,a1),a2
81 63 mov d2,d0 # for ret_from_fork
82 64 mov d0,a0 # for __switch_to
arch/mn10300/kernel/traps.c
... ... @@ -45,14 +45,6 @@
45 45 #error "INTERRUPT_VECTOR_BASE not aligned to 16MiB boundary!"
46 46 #endif
47 47  
48   -#ifdef CONFIG_SMP
49   -struct pt_regs *___frame[NR_CPUS]; /* current frame pointer */
50   -EXPORT_SYMBOL(___frame);
51   -#else /* CONFIG_SMP */
52   -struct pt_regs *__frame; /* current frame pointer */
53   -EXPORT_SYMBOL(__frame);
54   -#endif /* CONFIG_SMP */
55   -
56 48 int kstack_depth_to_print = 24;
57 49  
58 50 spinlock_t die_lock = __SPIN_LOCK_UNLOCKED(die_lock);
1 1 /*
2 2 * Access kernel memory without faulting.
3 3 */
4   -#include <linux/uaccess.h>
5 4 #include <linux/module.h>
6 5 #include <linux/mm.h>
  6 +#include <linux/uaccess.h>
7 7  
8 8 /**
9 9 * probe_kernel_read(): safely attempt to read from a location