Skip to content

Commit

Permalink
ARCv2: save ABI registers across signal handling
Browse files Browse the repository at this point in the history
commit 96f1b00 upstream.

ARCv2 has some configuration dependent registers (r30, r58, r59) which
could be targetted by the compiler. To keep the ABI stable, these were
unconditionally part of the glibc ABI
(sysdeps/unix/sysv/linux/arc/sys/ucontext.h:mcontext_t) however we
missed populating them (by saving/restoring them across signal
handling).

This patch fixes the issue by
 - adding arcv2 ABI regs to kernel struct sigcontext
 - populating them during signal handling

Change to struct sigcontext might seem like a glibc ABI change (although
it primarily uses ucontext_t:mcontext_t) but the fact is
 - it has only been extended (existing fields are not touched)
 - the old sigcontext was ABI incomplete to begin with anyways

Fixes: foss-for-synopsys-dwc-arc-processors/linux#53
Cc: <stable@vger.kernel.org>
Tested-by: kernel test robot <lkp@intel.com>
Reported-by: Vladimir Isaev <isaev@synopsys.com>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
vineetgarc authored and gregkh committed Jun 23, 2021
1 parent b516dae commit f6bcb1a
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 0 deletions.
1 change: 1 addition & 0 deletions arch/arc/include/uapi/asm/sigcontext.h
Expand Up @@ -18,6 +18,7 @@
*/
struct sigcontext {
struct user_regs_struct regs;
struct user_regs_arcv2 v2abi;
};

#endif /* _ASM_ARC_SIGCONTEXT_H */
43 changes: 43 additions & 0 deletions arch/arc/kernel/signal.c
Expand Up @@ -61,6 +61,41 @@ struct rt_sigframe {
unsigned int sigret_magic;
};

static int save_arcv2_regs(struct sigcontext *mctx, struct pt_regs *regs)
{
int err = 0;
#ifndef CONFIG_ISA_ARCOMPACT
struct user_regs_arcv2 v2abi;

v2abi.r30 = regs->r30;
#ifdef CONFIG_ARC_HAS_ACCL_REGS
v2abi.r58 = regs->r58;
v2abi.r59 = regs->r59;
#else
v2abi.r58 = v2abi.r59 = 0;
#endif
err = __copy_to_user(&mctx->v2abi, &v2abi, sizeof(v2abi));
#endif
return err;
}

static int restore_arcv2_regs(struct sigcontext *mctx, struct pt_regs *regs)
{
int err = 0;
#ifndef CONFIG_ISA_ARCOMPACT
struct user_regs_arcv2 v2abi;

err = __copy_from_user(&v2abi, &mctx->v2abi, sizeof(v2abi));

regs->r30 = v2abi.r30;
#ifdef CONFIG_ARC_HAS_ACCL_REGS
regs->r58 = v2abi.r58;
regs->r59 = v2abi.r59;
#endif
#endif
return err;
}

static int
stash_usr_regs(struct rt_sigframe __user *sf, struct pt_regs *regs,
sigset_t *set)
Expand Down Expand Up @@ -94,6 +129,10 @@ stash_usr_regs(struct rt_sigframe __user *sf, struct pt_regs *regs,

err = __copy_to_user(&(sf->uc.uc_mcontext.regs.scratch), &uregs.scratch,
sizeof(sf->uc.uc_mcontext.regs.scratch));

if (is_isa_arcv2())
err |= save_arcv2_regs(&(sf->uc.uc_mcontext), regs);

err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(sigset_t));

return err ? -EFAULT : 0;
Expand All @@ -109,6 +148,10 @@ static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf)
err |= __copy_from_user(&uregs.scratch,
&(sf->uc.uc_mcontext.regs.scratch),
sizeof(sf->uc.uc_mcontext.regs.scratch));

if (is_isa_arcv2())
err |= restore_arcv2_regs(&(sf->uc.uc_mcontext), regs);

if (err)
return -EFAULT;

Expand Down

0 comments on commit f6bcb1a

Please sign in to comment.