diff options
author | Daniel Jacobowitz <drow@false.org> | 2006-06-24 18:46:21 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-06-24 18:46:21 -0400 |
commit | 85fe068123aa11d3477ce88c7d365e233b1f2e10 (patch) | |
tree | 2b4d4a255737dc3b2bc031e0853902637250e125 /arch/arm | |
parent | ca195cfec9fff622a61b1b72534e73360747f735 (diff) |
[ARM] 3648/1: Update struct ucontext layout for coprocessor registers
Patch from Daniel Jacobowitz
In order for userspace to find saved coprocessor registers, move them from
struct rt_sigframe into struct ucontext. Also allow space for glibc's
sigset_t, so that userspace and kernelspace can use the same ucontext
layout. Define the magic numbers for iWMMXt in the header file for easier
reference. Include the size of the coprocessor data in the magic numbers.
Also define magic numbers and layout for VFP, not yet saved.
Signed-off-by: Daniel Jacobowitz <dan@codesourcery.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/kernel/signal.c | 42 |
1 files changed, 11 insertions, 31 deletions
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index c0ba8afee42f..e5802bfda31d 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c | |||
@@ -134,17 +134,6 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, | |||
134 | 134 | ||
135 | #ifdef CONFIG_IWMMXT | 135 | #ifdef CONFIG_IWMMXT |
136 | 136 | ||
137 | /* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */ | ||
138 | #define IWMMXT_STORAGE_SIZE (0x98 + 8) | ||
139 | #define IWMMXT_MAGIC0 0x12ef842a | ||
140 | #define IWMMXT_MAGIC1 0x1c07ca71 | ||
141 | |||
142 | struct iwmmxt_sigframe { | ||
143 | unsigned long magic0; | ||
144 | unsigned long magic1; | ||
145 | unsigned long storage[0x98/4]; | ||
146 | }; | ||
147 | |||
148 | static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame) | 137 | static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame) |
149 | { | 138 | { |
150 | char kbuf[sizeof(*frame) + 8]; | 139 | char kbuf[sizeof(*frame) + 8]; |
@@ -152,8 +141,8 @@ static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame) | |||
152 | 141 | ||
153 | /* the iWMMXt context must be 64 bit aligned */ | 142 | /* the iWMMXt context must be 64 bit aligned */ |
154 | kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7); | 143 | kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7); |
155 | kframe->magic0 = IWMMXT_MAGIC0; | 144 | kframe->magic = IWMMXT_MAGIC; |
156 | kframe->magic1 = IWMMXT_MAGIC1; | 145 | kframe->size = IWMMXT_STORAGE_SIZE; |
157 | iwmmxt_task_copy(current_thread_info(), &kframe->storage); | 146 | iwmmxt_task_copy(current_thread_info(), &kframe->storage); |
158 | return __copy_to_user(frame, kframe, sizeof(*frame)); | 147 | return __copy_to_user(frame, kframe, sizeof(*frame)); |
159 | } | 148 | } |
@@ -167,8 +156,8 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame) | |||
167 | kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7); | 156 | kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7); |
168 | if (__copy_from_user(kframe, frame, sizeof(*frame))) | 157 | if (__copy_from_user(kframe, frame, sizeof(*frame))) |
169 | return -1; | 158 | return -1; |
170 | if (kframe->magic0 != IWMMXT_MAGIC0 || | 159 | if (kframe->magic != IWMMXT_MAGIC || |
171 | kframe->magic1 != IWMMXT_MAGIC1) | 160 | kframe->size != IWMMXT_STORAGE_SIZE) |
172 | return -1; | 161 | return -1; |
173 | iwmmxt_task_restore(current_thread_info(), &kframe->storage); | 162 | iwmmxt_task_restore(current_thread_info(), &kframe->storage); |
174 | return 0; | 163 | return 0; |
@@ -177,25 +166,11 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame) | |||
177 | #endif | 166 | #endif |
178 | 167 | ||
179 | /* | 168 | /* |
180 | * Auxiliary signal frame. This saves stuff like FP state. | ||
181 | * The layout of this structure is not part of the user ABI. | ||
182 | */ | ||
183 | struct aux_sigframe { | ||
184 | #ifdef CONFIG_IWMMXT | ||
185 | struct iwmmxt_sigframe iwmmxt; | ||
186 | #endif | ||
187 | #ifdef CONFIG_VFP | ||
188 | union vfp_state vfp; | ||
189 | #endif | ||
190 | }; | ||
191 | |||
192 | /* | ||
193 | * Do a signal return; undo the signal stack. These are aligned to 64-bit. | 169 | * Do a signal return; undo the signal stack. These are aligned to 64-bit. |
194 | */ | 170 | */ |
195 | struct sigframe { | 171 | struct sigframe { |
196 | struct ucontext uc; | 172 | struct ucontext uc; |
197 | unsigned long retcode[2]; | 173 | unsigned long retcode[2]; |
198 | struct aux_sigframe aux __attribute__((aligned(8))); | ||
199 | }; | 174 | }; |
200 | 175 | ||
201 | struct rt_sigframe { | 176 | struct rt_sigframe { |
@@ -205,6 +180,7 @@ struct rt_sigframe { | |||
205 | 180 | ||
206 | static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf) | 181 | static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf) |
207 | { | 182 | { |
183 | struct aux_sigframe __user *aux; | ||
208 | sigset_t set; | 184 | sigset_t set; |
209 | int err; | 185 | int err; |
210 | 186 | ||
@@ -237,9 +213,10 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf) | |||
237 | 213 | ||
238 | err |= !valid_user_regs(regs); | 214 | err |= !valid_user_regs(regs); |
239 | 215 | ||
216 | aux = (struct aux_sigframe __user *) sf->uc.uc_regspace; | ||
240 | #ifdef CONFIG_IWMMXT | 217 | #ifdef CONFIG_IWMMXT |
241 | if (err == 0 && test_thread_flag(TIF_USING_IWMMXT)) | 218 | if (err == 0 && test_thread_flag(TIF_USING_IWMMXT)) |
242 | err |= restore_iwmmxt_context(&sf->aux.iwmmxt); | 219 | err |= restore_iwmmxt_context(&aux->iwmmxt); |
243 | #endif | 220 | #endif |
244 | #ifdef CONFIG_VFP | 221 | #ifdef CONFIG_VFP |
245 | // if (err == 0) | 222 | // if (err == 0) |
@@ -327,6 +304,7 @@ badframe: | |||
327 | static int | 304 | static int |
328 | setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set) | 305 | setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set) |
329 | { | 306 | { |
307 | struct aux_sigframe __user *aux; | ||
330 | int err = 0; | 308 | int err = 0; |
331 | 309 | ||
332 | __put_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err); | 310 | __put_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err); |
@@ -354,14 +332,16 @@ setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set) | |||
354 | 332 | ||
355 | err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set)); | 333 | err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set)); |
356 | 334 | ||
335 | aux = (struct aux_sigframe __user *) sf->uc.uc_regspace; | ||
357 | #ifdef CONFIG_IWMMXT | 336 | #ifdef CONFIG_IWMMXT |
358 | if (err == 0 && test_thread_flag(TIF_USING_IWMMXT)) | 337 | if (err == 0 && test_thread_flag(TIF_USING_IWMMXT)) |
359 | err |= preserve_iwmmxt_context(&sf->aux.iwmmxt); | 338 | err |= preserve_iwmmxt_context(&aux->iwmmxt); |
360 | #endif | 339 | #endif |
361 | #ifdef CONFIG_VFP | 340 | #ifdef CONFIG_VFP |
362 | // if (err == 0) | 341 | // if (err == 0) |
363 | // err |= vfp_save_state(&sf->aux.vfp); | 342 | // err |= vfp_save_state(&sf->aux.vfp); |
364 | #endif | 343 | #endif |
344 | __put_user_error(0, &aux->end_magic, err); | ||
365 | 345 | ||
366 | return err; | 346 | return err; |
367 | } | 347 | } |