diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2014-04-07 00:04:12 +0200 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2014-05-09 16:47:47 +0200 |
commit | 9141300a5884b57cea6d32c4e3fd16a337cfc99a (patch) | |
tree | d717d0ae66c7458c922b885c689b9c192b0f4083 /arch/arm64/kernel/signal32.c | |
parent | arm64: Remove boot thread synchronisation for spin-table release method (diff) | |
download | linux-9141300a5884b57cea6d32c4e3fd16a337cfc99a.tar.xz linux-9141300a5884b57cea6d32c4e3fd16a337cfc99a.zip |
arm64: Provide read/write fault information in compat signal handlers
For AArch32, bit 11 (WnR) of the FSR/ESR register is set when the fault
was caused by a write access and applications like Qemu rely on such
information being provided in sigcontext. This patch introduces the
ESR_EL1 tracking for the arm64 kernel faults and sets bit 11 accordingly
in compat sigcontext.
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch/arm64/kernel/signal32.c')
-rw-r--r-- | arch/arm64/kernel/signal32.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c index b3fc9f5ec6d3..050c1c2af777 100644 --- a/arch/arm64/kernel/signal32.c +++ b/arch/arm64/kernel/signal32.c @@ -23,6 +23,7 @@ #include <linux/syscalls.h> #include <linux/ratelimit.h> +#include <asm/esr.h> #include <asm/fpsimd.h> #include <asm/signal32.h> #include <asm/uaccess.h> @@ -81,6 +82,8 @@ struct compat_vfp_sigframe { #define VFP_MAGIC 0x56465001 #define VFP_STORAGE_SIZE sizeof(struct compat_vfp_sigframe) +#define FSR_WRITE_SHIFT (11) + struct compat_aux_sigframe { struct compat_vfp_sigframe vfp; @@ -500,7 +503,9 @@ static int compat_setup_sigframe(struct compat_sigframe __user *sf, __put_user_error(regs->pstate, &sf->uc.uc_mcontext.arm_cpsr, err); __put_user_error((compat_ulong_t)0, &sf->uc.uc_mcontext.trap_no, err); - __put_user_error((compat_ulong_t)0, &sf->uc.uc_mcontext.error_code, err); + /* set the compat FSR WnR */ + __put_user_error(!!(current->thread.fault_code & ESR_EL1_WRITE) << + FSR_WRITE_SHIFT, &sf->uc.uc_mcontext.error_code, err); __put_user_error(current->thread.fault_address, &sf->uc.uc_mcontext.fault_address, err); __put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err); |