Skip to content

Commit

Permalink
[ARM] 3664/1: crunch: add signal frame save/restore
Browse files Browse the repository at this point in the history
Patch from Lennert Buytenhek

This patch makes the kernel save Crunch state in userland signal frames,
so that any userland signal handler can safely use the Crunch coprocessor
without corrupting the Crunch state of the code it preempted.

Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Lennert Buytenhek authored and Russell King committed Jun 28, 2006
1 parent 562ca1e commit 3bec6de
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 0 deletions.
39 changes: 39 additions & 0 deletions arch/arm/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,37 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
return ret;
}

#ifdef CONFIG_CRUNCH
static int preserve_crunch_context(struct crunch_sigframe *frame)
{
char kbuf[sizeof(*frame) + 8];
struct crunch_sigframe *kframe;

/* the crunch context must be 64 bit aligned */
kframe = (struct crunch_sigframe *)((unsigned long)(kbuf + 8) & ~7);
kframe->magic = CRUNCH_MAGIC;
kframe->size = CRUNCH_STORAGE_SIZE;
crunch_task_copy(current_thread_info(), &kframe->storage);
return __copy_to_user(frame, kframe, sizeof(*frame));
}

static int restore_crunch_context(struct crunch_sigframe *frame)
{
char kbuf[sizeof(*frame) + 8];
struct crunch_sigframe *kframe;

/* the crunch context must be 64 bit aligned */
kframe = (struct crunch_sigframe *)((unsigned long)(kbuf + 8) & ~7);
if (__copy_from_user(kframe, frame, sizeof(*frame)))
return -1;
if (kframe->magic != CRUNCH_MAGIC ||
kframe->size != CRUNCH_STORAGE_SIZE)
return -1;
crunch_task_restore(current_thread_info(), &kframe->storage);
return 0;
}
#endif

#ifdef CONFIG_IWMMXT

static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame)
Expand Down Expand Up @@ -214,6 +245,10 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
err |= !valid_user_regs(regs);

aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
#ifdef CONFIG_CRUNCH
if (err == 0)
err |= restore_crunch_context(&aux->crunch);
#endif
#ifdef CONFIG_IWMMXT
if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
err |= restore_iwmmxt_context(&aux->iwmmxt);
Expand Down Expand Up @@ -333,6 +368,10 @@ setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));

aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
#ifdef CONFIG_CRUNCH
if (err == 0)
err |= preserve_crunch_context(&aux->crunch);
#endif
#ifdef CONFIG_IWMMXT
if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
err |= preserve_iwmmxt_context(&aux->iwmmxt);
Expand Down
14 changes: 14 additions & 0 deletions include/asm-arm/ucontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ struct ucontext {
* bytes, to prevent unpredictable padding in the signal frame.
*/

#ifdef CONFIG_CRUNCH
#define CRUNCH_MAGIC 0x5065cf03
#define CRUNCH_STORAGE_SIZE (CRUNCH_SIZE + 8)

struct crunch_sigframe {
unsigned long magic;
unsigned long size;
struct crunch_state storage;
} __attribute__((__aligned__(8)));
#endif

#ifdef CONFIG_IWMMXT
/* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */
#define IWMMXT_MAGIC 0x12ef842a
Expand Down Expand Up @@ -74,6 +85,9 @@ struct vfp_sigframe
* one of these.
*/
struct aux_sigframe {
#ifdef CONFIG_CRUNCH
struct crunch_sigframe crunch;
#endif
#ifdef CONFIG_IWMMXT
struct iwmmxt_sigframe iwmmxt;
#endif
Expand Down

0 comments on commit 3bec6de

Please sign in to comment.