aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>2008-11-24 21:21:37 -0500
committerIngo Molnar <mingo@elte.hu>2008-11-25 23:11:51 -0500
commit2601657d223d82053d4e1fe1063091401e6b860a (patch)
tree04302bbebc28b0fc63a9e488dfcaeefff62a814f
parent2456d738ef051f85170bf018faef63f83fa84eb5 (diff)
x86: signal: move {setup|restore}_sigcontext()
Impact: cleanup Move {setup|restore}_sigcontext() declaration onto head of file. Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/kernel/signal_32.c271
-rw-r--r--arch/x86/kernel/signal_64.c148
2 files changed, 210 insertions, 209 deletions
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c
index f7dd6c44c042..b3f30d2a2178 100644
--- a/arch/x86/kernel/signal_32.c
+++ b/arch/x86/kernel/signal_32.c
@@ -70,6 +70,142 @@ static const struct {
70 0 70 0
71}; 71};
72 72
73#define COPY(x) { \
74 err |= __get_user(regs->x, &sc->x); \
75}
76
77#define COPY_SEG(seg) { \
78 unsigned short tmp; \
79 err |= __get_user(tmp, &sc->seg); \
80 regs->seg = tmp; \
81}
82
83#define COPY_SEG_CPL3(seg) { \
84 unsigned short tmp; \
85 err |= __get_user(tmp, &sc->seg); \
86 regs->seg = tmp | 3; \
87}
88
89#define GET_SEG(seg) { \
90 unsigned short tmp; \
91 err |= __get_user(tmp, &sc->seg); \
92 loadsegment(seg, tmp); \
93}
94
95static int
96restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
97 unsigned long *pax)
98{
99 void __user *buf;
100 unsigned int tmpflags;
101 unsigned int err = 0;
102
103 /* Always make any pending restarted system calls return -EINTR */
104 current_thread_info()->restart_block.fn = do_no_restart_syscall;
105
106#ifdef CONFIG_X86_32
107 GET_SEG(gs);
108 COPY_SEG(fs);
109 COPY_SEG(es);
110 COPY_SEG(ds);
111#endif /* CONFIG_X86_32 */
112
113 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
114 COPY(dx); COPY(cx); COPY(ip);
115
116#ifdef CONFIG_X86_64
117 COPY(r8);
118 COPY(r9);
119 COPY(r10);
120 COPY(r11);
121 COPY(r12);
122 COPY(r13);
123 COPY(r14);
124 COPY(r15);
125#endif /* CONFIG_X86_64 */
126
127#ifdef CONFIG_X86_32
128 COPY_SEG_CPL3(cs);
129 COPY_SEG_CPL3(ss);
130#else /* !CONFIG_X86_32 */
131 /* Kernel saves and restores only the CS segment register on signals,
132 * which is the bare minimum needed to allow mixed 32/64-bit code.
133 * App's signal handler can save/restore other segments if needed. */
134 COPY_SEG_CPL3(cs);
135#endif /* CONFIG_X86_32 */
136
137 err |= __get_user(tmpflags, &sc->flags);
138 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
139 regs->orig_ax = -1; /* disable syscall checks */
140
141 err |= __get_user(buf, &sc->fpstate);
142 err |= restore_i387_xstate(buf);
143
144 err |= __get_user(*pax, &sc->ax);
145 return err;
146}
147
148static int
149setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
150 struct pt_regs *regs, unsigned long mask)
151{
152 int err = 0;
153
154#ifdef CONFIG_X86_32
155 {
156 unsigned int tmp;
157
158 savesegment(gs, tmp);
159 err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
160 }
161 err |= __put_user(regs->fs, (unsigned int __user *)&sc->fs);
162 err |= __put_user(regs->es, (unsigned int __user *)&sc->es);
163 err |= __put_user(regs->ds, (unsigned int __user *)&sc->ds);
164#endif /* CONFIG_X86_32 */
165
166 err |= __put_user(regs->di, &sc->di);
167 err |= __put_user(regs->si, &sc->si);
168 err |= __put_user(regs->bp, &sc->bp);
169 err |= __put_user(regs->sp, &sc->sp);
170 err |= __put_user(regs->bx, &sc->bx);
171 err |= __put_user(regs->dx, &sc->dx);
172 err |= __put_user(regs->cx, &sc->cx);
173 err |= __put_user(regs->ax, &sc->ax);
174#ifdef CONFIG_X86_64
175 err |= __put_user(regs->r8, &sc->r8);
176 err |= __put_user(regs->r9, &sc->r9);
177 err |= __put_user(regs->r10, &sc->r10);
178 err |= __put_user(regs->r11, &sc->r11);
179 err |= __put_user(regs->r12, &sc->r12);
180 err |= __put_user(regs->r13, &sc->r13);
181 err |= __put_user(regs->r14, &sc->r14);
182 err |= __put_user(regs->r15, &sc->r15);
183#endif /* CONFIG_X86_64 */
184
185 err |= __put_user(current->thread.trap_no, &sc->trapno);
186 err |= __put_user(current->thread.error_code, &sc->err);
187 err |= __put_user(regs->ip, &sc->ip);
188#ifdef CONFIG_X86_32
189 err |= __put_user(regs->cs, (unsigned int __user *)&sc->cs);
190 err |= __put_user(regs->flags, &sc->flags);
191 err |= __put_user(regs->sp, &sc->sp_at_signal);
192 err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss);
193#else /* !CONFIG_X86_32 */
194 err |= __put_user(regs->flags, &sc->flags);
195 err |= __put_user(regs->cs, &sc->cs);
196 err |= __put_user(0, &sc->gs);
197 err |= __put_user(0, &sc->fs);
198#endif /* CONFIG_X86_32 */
199
200 err |= __put_user(fpstate, &sc->fpstate);
201
202 /* non-iBCS2 extensions.. */
203 err |= __put_user(mask, &sc->oldmask);
204 err |= __put_user(current->thread.cr2, &sc->cr2);
205
206 return err;
207}
208
73/* 209/*
74 * Atomically swap in the new signal mask, and wait for a signal. 210 * Atomically swap in the new signal mask, and wait for a signal.
75 */ 211 */
@@ -147,84 +283,9 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
147} 283}
148#endif /* CONFIG_X86_32 */ 284#endif /* CONFIG_X86_32 */
149 285
150#define COPY(x) { \
151 err |= __get_user(regs->x, &sc->x); \
152}
153
154#define COPY_SEG(seg) { \
155 unsigned short tmp; \
156 err |= __get_user(tmp, &sc->seg); \
157 regs->seg = tmp; \
158}
159
160#define COPY_SEG_CPL3(seg) { \
161 unsigned short tmp; \
162 err |= __get_user(tmp, &sc->seg); \
163 regs->seg = tmp | 3; \
164}
165
166#define GET_SEG(seg) { \
167 unsigned short tmp; \
168 err |= __get_user(tmp, &sc->seg); \
169 loadsegment(seg, tmp); \
170}
171
172/* 286/*
173 * Do a signal return; undo the signal stack. 287 * Do a signal return; undo the signal stack.
174 */ 288 */
175static int
176restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
177 unsigned long *pax)
178{
179 void __user *buf;
180 unsigned int tmpflags;
181 unsigned int err = 0;
182
183 /* Always make any pending restarted system calls return -EINTR */
184 current_thread_info()->restart_block.fn = do_no_restart_syscall;
185
186#ifdef CONFIG_X86_32
187 GET_SEG(gs);
188 COPY_SEG(fs);
189 COPY_SEG(es);
190 COPY_SEG(ds);
191#endif /* CONFIG_X86_32 */
192
193 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
194 COPY(dx); COPY(cx); COPY(ip);
195
196#ifdef CONFIG_X86_64
197 COPY(r8);
198 COPY(r9);
199 COPY(r10);
200 COPY(r11);
201 COPY(r12);
202 COPY(r13);
203 COPY(r14);
204 COPY(r15);
205#endif /* CONFIG_X86_64 */
206
207#ifdef CONFIG_X86_32
208 COPY_SEG_CPL3(cs);
209 COPY_SEG_CPL3(ss);
210#else /* !CONFIG_X86_32 */
211 /* Kernel saves and restores only the CS segment register on signals,
212 * which is the bare minimum needed to allow mixed 32/64-bit code.
213 * App's signal handler can save/restore other segments if needed. */
214 COPY_SEG_CPL3(cs);
215#endif /* CONFIG_X86_32 */
216
217 err |= __get_user(tmpflags, &sc->flags);
218 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
219 regs->orig_ax = -1; /* disable syscall checks */
220
221 err |= __get_user(buf, &sc->fpstate);
222 err |= restore_i387_xstate(buf);
223
224 err |= __get_user(*pax, &sc->ax);
225 return err;
226}
227
228asmlinkage unsigned long sys_sigreturn(unsigned long __unused) 289asmlinkage unsigned long sys_sigreturn(unsigned long __unused)
229{ 290{
230 struct sigframe __user *frame; 291 struct sigframe __user *frame;
@@ -316,66 +377,6 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
316/* 377/*
317 * Set up a signal frame. 378 * Set up a signal frame.
318 */ 379 */
319static int
320setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
321 struct pt_regs *regs, unsigned long mask)
322{
323 int err = 0;
324
325#ifdef CONFIG_X86_32
326 {
327 unsigned int tmp;
328
329 savesegment(gs, tmp);
330 err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
331 }
332 err |= __put_user(regs->fs, (unsigned int __user *)&sc->fs);
333 err |= __put_user(regs->es, (unsigned int __user *)&sc->es);
334 err |= __put_user(regs->ds, (unsigned int __user *)&sc->ds);
335#endif /* CONFIG_X86_32 */
336
337 err |= __put_user(regs->di, &sc->di);
338 err |= __put_user(regs->si, &sc->si);
339 err |= __put_user(regs->bp, &sc->bp);
340 err |= __put_user(regs->sp, &sc->sp);
341 err |= __put_user(regs->bx, &sc->bx);
342 err |= __put_user(regs->dx, &sc->dx);
343 err |= __put_user(regs->cx, &sc->cx);
344 err |= __put_user(regs->ax, &sc->ax);
345#ifdef CONFIG_X86_64
346 err |= __put_user(regs->r8, &sc->r8);
347 err |= __put_user(regs->r9, &sc->r9);
348 err |= __put_user(regs->r10, &sc->r10);
349 err |= __put_user(regs->r11, &sc->r11);
350 err |= __put_user(regs->r12, &sc->r12);
351 err |= __put_user(regs->r13, &sc->r13);
352 err |= __put_user(regs->r14, &sc->r14);
353 err |= __put_user(regs->r15, &sc->r15);
354#endif /* CONFIG_X86_64 */
355
356 err |= __put_user(current->thread.trap_no, &sc->trapno);
357 err |= __put_user(current->thread.error_code, &sc->err);
358 err |= __put_user(regs->ip, &sc->ip);
359#ifdef CONFIG_X86_32
360 err |= __put_user(regs->cs, (unsigned int __user *)&sc->cs);
361 err |= __put_user(regs->flags, &sc->flags);
362 err |= __put_user(regs->sp, &sc->sp_at_signal);
363 err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss);
364#else /* !CONFIG_X86_32 */
365 err |= __put_user(regs->flags, &sc->flags);
366 err |= __put_user(regs->cs, &sc->cs);
367 err |= __put_user(0, &sc->gs);
368 err |= __put_user(0, &sc->fs);
369#endif /* CONFIG_X86_32 */
370
371 err |= __put_user(fpstate, &sc->fpstate);
372
373 /* non-iBCS2 extensions.. */
374 err |= __put_user(mask, &sc->oldmask);
375 err |= __put_user(current->thread.cr2, &sc->cr2);
376
377 return err;
378}
379 380
380/* 381/*
381 * Determine which stack to use.. 382 * Determine which stack to use..
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
index 32718f5e4f61..771c8fcc8b0d 100644
--- a/arch/x86/kernel/signal_64.c
+++ b/arch/x86/kernel/signal_64.c
@@ -50,28 +50,6 @@
50# define FIX_EFLAGS __FIX_EFLAGS 50# define FIX_EFLAGS __FIX_EFLAGS
51#endif 51#endif
52 52
53#ifdef CONFIG_X86_32
54asmlinkage int sys_sigaltstack(unsigned long bx)
55{
56 /*
57 * This is needed to make gcc realize it doesn't own the
58 * "struct pt_regs"
59 */
60 struct pt_regs *regs = (struct pt_regs *)&bx;
61 const stack_t __user *uss = (const stack_t __user *)bx;
62 stack_t __user *uoss = (stack_t __user *)regs->cx;
63
64 return do_sigaltstack(uss, uoss, regs->sp);
65}
66#else /* !CONFIG_X86_32 */
67asmlinkage long
68sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
69 struct pt_regs *regs)
70{
71 return do_sigaltstack(uss, uoss, regs->sp);
72}
73#endif /* CONFIG_X86_32 */
74
75#define COPY(x) { \ 53#define COPY(x) { \
76 err |= __get_user(regs->x, &sc->x); \ 54 err |= __get_user(regs->x, &sc->x); \
77} 55}
@@ -82,9 +60,6 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
82 regs->seg = tmp | 3; \ 60 regs->seg = tmp | 3; \
83} 61}
84 62
85/*
86 * Do a signal return; undo the signal stack.
87 */
88static int 63static int
89restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, 64restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
90 unsigned long *pax) 65 unsigned long *pax)
@@ -138,54 +113,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
138 return err; 113 return err;
139} 114}
140 115
141static long do_rt_sigreturn(struct pt_regs *regs)
142{
143 struct rt_sigframe __user *frame;
144 unsigned long ax;
145 sigset_t set;
146
147 frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long));
148 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
149 goto badframe;
150 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
151 goto badframe;
152
153 sigdelsetmask(&set, ~_BLOCKABLE);
154 spin_lock_irq(&current->sighand->siglock);
155 current->blocked = set;
156 recalc_sigpending();
157 spin_unlock_irq(&current->sighand->siglock);
158
159 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
160 goto badframe;
161
162 if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
163 goto badframe;
164
165 return ax;
166
167badframe:
168 signal_fault(regs, frame, "rt_sigreturn");
169 return 0;
170}
171
172#ifdef CONFIG_X86_32
173asmlinkage int sys_rt_sigreturn(unsigned long __unused)
174{
175 struct pt_regs *regs = (struct pt_regs *)&__unused;
176
177 return do_rt_sigreturn(regs);
178}
179#else /* !CONFIG_X86_32 */
180asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
181{
182 return do_rt_sigreturn(regs);
183}
184#endif /* CONFIG_X86_32 */
185
186/*
187 * Set up a signal frame.
188 */
189static int 116static int
190setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate, 117setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
191 struct pt_regs *regs, unsigned long mask) 118 struct pt_regs *regs, unsigned long mask)
@@ -247,10 +174,83 @@ setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
247 return err; 174 return err;
248} 175}
249 176
177#ifdef CONFIG_X86_32
178asmlinkage int sys_sigaltstack(unsigned long bx)
179{
180 /*
181 * This is needed to make gcc realize it doesn't own the
182 * "struct pt_regs"
183 */
184 struct pt_regs *regs = (struct pt_regs *)&bx;
185 const stack_t __user *uss = (const stack_t __user *)bx;
186 stack_t __user *uoss = (stack_t __user *)regs->cx;
187
188 return do_sigaltstack(uss, uoss, regs->sp);
189}
190#else /* !CONFIG_X86_32 */
191asmlinkage long
192sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
193 struct pt_regs *regs)
194{
195 return do_sigaltstack(uss, uoss, regs->sp);
196}
197#endif /* CONFIG_X86_32 */
198
250/* 199/*
251 * Determine which stack to use.. 200 * Do a signal return; undo the signal stack.
201 */
202static long do_rt_sigreturn(struct pt_regs *regs)
203{
204 struct rt_sigframe __user *frame;
205 unsigned long ax;
206 sigset_t set;
207
208 frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long));
209 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
210 goto badframe;
211 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
212 goto badframe;
213
214 sigdelsetmask(&set, ~_BLOCKABLE);
215 spin_lock_irq(&current->sighand->siglock);
216 current->blocked = set;
217 recalc_sigpending();
218 spin_unlock_irq(&current->sighand->siglock);
219
220 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
221 goto badframe;
222
223 if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
224 goto badframe;
225
226 return ax;
227
228badframe:
229 signal_fault(regs, frame, "rt_sigreturn");
230 return 0;
231}
232
233#ifdef CONFIG_X86_32
234asmlinkage int sys_rt_sigreturn(unsigned long __unused)
235{
236 struct pt_regs *regs = (struct pt_regs *)&__unused;
237
238 return do_rt_sigreturn(regs);
239}
240#else /* !CONFIG_X86_32 */
241asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
242{
243 return do_rt_sigreturn(regs);
244}
245#endif /* CONFIG_X86_32 */
246
247/*
248 * Set up a signal frame.
252 */ 249 */
253 250
251/*
252 * Determine which stack to use..
253 */
254static void __user * 254static void __user *
255get_stack(struct k_sigaction *ka, unsigned long sp, unsigned long size) 255get_stack(struct k_sigaction *ka, unsigned long sp, unsigned long size)
256{ 256{