* [PATCH 1/3] arm64: Provide read/write fault information in compat signal handlers
2014-04-06 22:19 [PATCH 0/3] arm64: Provide ESR_EL1 information to user signal handlers Catalin Marinas
@ 2014-04-06 22:19 ` Catalin Marinas
2014-04-07 9:39 ` Michal Simek
2014-04-06 22:19 ` [PATCH 2/3] arm64: Remove the aux_context structure Catalin Marinas
2014-04-06 22:19 ` [PATCH 3/3] arm64: Expose ESR_EL1 information to user when SIGSEGV/SIGBUS Catalin Marinas
2 siblings, 1 reply; 6+ messages in thread
From: Catalin Marinas @ 2014-04-06 22:19 UTC (permalink / raw)
To: linux-arm-kernel
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>
---
arch/arm64/include/asm/processor.h | 1 +
arch/arm64/kernel/signal32.c | 4 +++-
arch/arm64/kernel/traps.c | 7 +++++--
arch/arm64/mm/fault.c | 3 ++-
4 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 45b20cd6cbca..34de2a8f7d93 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -79,6 +79,7 @@ struct thread_struct {
unsigned long tp_value;
struct fpsimd_state fpsimd_state;
unsigned long fault_address; /* fault info */
+ unsigned long fault_code; /* ESR_EL1 value */
struct debug_info debug; /* debugging */
};
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index b3fc9f5ec6d3..e4f0c0b0ca3a 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -500,7 +500,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);
+ /* compat tasks expect bit 11 as WnR status bit */
+ __put_user_error((current->thread.fault_code & (1 << 6)) << 5,
+ &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);
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 7ffadddb645d..c43cfa9b8304 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -251,10 +251,13 @@ void die(const char *str, struct pt_regs *regs, int err)
void arm64_notify_die(const char *str, struct pt_regs *regs,
struct siginfo *info, int err)
{
- if (user_mode(regs))
+ if (user_mode(regs)) {
+ current->thread.fault_address = 0;
+ current->thread.fault_code = err;
force_sig_info(info->si_signo, info, current);
- else
+ } else {
die(str, regs, err);
+ }
}
asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index c23751b06120..625985f6531b 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -123,6 +123,7 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
}
tsk->thread.fault_address = addr;
+ tsk->thread.fault_code = esr;
si.si_signo = sig;
si.si_errno = 0;
si.si_code = code;
@@ -525,7 +526,7 @@ asmlinkage int __exception do_debug_exception(unsigned long addr,
info.si_errno = 0;
info.si_code = inf->code;
info.si_addr = (void __user *)addr;
- arm64_notify_die("", regs, &info, esr);
+ arm64_notify_die("", regs, &info, 0);
return 0;
}
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 1/3] arm64: Provide read/write fault information in compat signal handlers
2014-04-06 22:19 ` [PATCH 1/3] arm64: Provide read/write fault information in compat " Catalin Marinas
@ 2014-04-07 9:39 ` Michal Simek
2014-04-07 11:41 ` Catalin Marinas
0 siblings, 1 reply; 6+ messages in thread
From: Michal Simek @ 2014-04-07 9:39 UTC (permalink / raw)
To: linux-arm-kernel
On 04/07/2014 12:19 AM, Catalin Marinas wrote:
> 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>
> ---
> arch/arm64/include/asm/processor.h | 1 +
> arch/arm64/kernel/signal32.c | 4 +++-
> arch/arm64/kernel/traps.c | 7 +++++--
> arch/arm64/mm/fault.c | 3 ++-
> 4 files changed, 11 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
> index 45b20cd6cbca..34de2a8f7d93 100644
> --- a/arch/arm64/include/asm/processor.h
> +++ b/arch/arm64/include/asm/processor.h
> @@ -79,6 +79,7 @@ struct thread_struct {
> unsigned long tp_value;
> struct fpsimd_state fpsimd_state;
> unsigned long fault_address; /* fault info */
> + unsigned long fault_code; /* ESR_EL1 value */
> struct debug_info debug; /* debugging */
> };
>
> diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
> index b3fc9f5ec6d3..e4f0c0b0ca3a 100644
> --- a/arch/arm64/kernel/signal32.c
> +++ b/arch/arm64/kernel/signal32.c
> @@ -500,7 +500,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);
> + /* compat tasks expect bit 11 as WnR status bit */
> + __put_user_error((current->thread.fault_code & (1 << 6)) << 5,
Isn't it better to use macros for these magic values?
Thanks,
Michal
--
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Microblaze cpu - http://www.monstr.eu/fdt/
Maintainer of Linux kernel - Xilinx Zynq ARM architecture
Microblaze U-BOOT custodian and responsible for u-boot arm zynq platform
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 263 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140407/7499cd9b/attachment.sig>
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/3] arm64: Provide read/write fault information in compat signal handlers
2014-04-07 9:39 ` Michal Simek
@ 2014-04-07 11:41 ` Catalin Marinas
0 siblings, 0 replies; 6+ messages in thread
From: Catalin Marinas @ 2014-04-07 11:41 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Apr 07, 2014 at 10:39:20AM +0100, Michal Simek wrote:
> On 04/07/2014 12:19 AM, Catalin Marinas wrote:
> > --- a/arch/arm64/kernel/signal32.c
> > +++ b/arch/arm64/kernel/signal32.c
> > @@ -500,7 +500,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);
> > + /* compat tasks expect bit 11 as WnR status bit */
> > + __put_user_error((current->thread.fault_code & (1 << 6)) << 5,
>
> Isn't it better to use macros for these magic values?
I was too lazy ;). I'll add some macros.
--
Catalin
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/3] arm64: Remove the aux_context structure
2014-04-06 22:19 [PATCH 0/3] arm64: Provide ESR_EL1 information to user signal handlers Catalin Marinas
2014-04-06 22:19 ` [PATCH 1/3] arm64: Provide read/write fault information in compat " Catalin Marinas
@ 2014-04-06 22:19 ` Catalin Marinas
2014-04-06 22:19 ` [PATCH 3/3] arm64: Expose ESR_EL1 information to user when SIGSEGV/SIGBUS Catalin Marinas
2 siblings, 0 replies; 6+ messages in thread
From: Catalin Marinas @ 2014-04-06 22:19 UTC (permalink / raw)
To: linux-arm-kernel
This patch removes the aux_context structure (and the containing file)
to allow the placement of the _aarch64_ctx end magic based on the
context stored on the signal stack.
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
arch/arm64/include/asm/sigcontext.h | 31 -------------------------------
arch/arm64/kernel/signal.c | 27 +++++++++++++++++----------
2 files changed, 17 insertions(+), 41 deletions(-)
delete mode 100644 arch/arm64/include/asm/sigcontext.h
diff --git a/arch/arm64/include/asm/sigcontext.h b/arch/arm64/include/asm/sigcontext.h
deleted file mode 100644
index dca1094acc74..000000000000
--- a/arch/arm64/include/asm/sigcontext.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2012 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef __ASM_SIGCONTEXT_H
-#define __ASM_SIGCONTEXT_H
-
-#include <uapi/asm/sigcontext.h>
-
-/*
- * Auxiliary context saved in the sigcontext.__reserved array. Not exported to
- * user space as it will change with the addition of new context. User space
- * should check the magic/size information.
- */
-struct aux_context {
- struct fpsimd_context fpsimd;
- /* additional context to be added before "end" */
- struct _aarch64_ctx end;
-};
-#endif
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 890a591f75dd..7ff2eee96c6b 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -100,8 +100,7 @@ static int restore_sigframe(struct pt_regs *regs,
{
sigset_t set;
int i, err;
- struct aux_context __user *aux =
- (struct aux_context __user *)sf->uc.uc_mcontext.__reserved;
+ void *aux = sf->uc.uc_mcontext.__reserved;
err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
if (err == 0)
@@ -121,8 +120,11 @@ static int restore_sigframe(struct pt_regs *regs,
err |= !valid_user_regs(®s->user_regs);
- if (err == 0)
- err |= restore_fpsimd_context(&aux->fpsimd);
+ if (err == 0) {
+ struct fpsimd_context *fpsimd_ctx =
+ container_of(aux, struct fpsimd_context, head);
+ err |= restore_fpsimd_context(fpsimd_ctx);
+ }
return err;
}
@@ -167,8 +169,8 @@ static int setup_sigframe(struct rt_sigframe __user *sf,
struct pt_regs *regs, sigset_t *set)
{
int i, err = 0;
- struct aux_context __user *aux =
- (struct aux_context __user *)sf->uc.uc_mcontext.__reserved;
+ void *aux = sf->uc.uc_mcontext.__reserved;
+ struct _aarch64_ctx *end;
/* set up the stack frame for unwinding */
__put_user_error(regs->regs[29], &sf->fp, err);
@@ -185,12 +187,17 @@ static int setup_sigframe(struct rt_sigframe __user *sf,
err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
- if (err == 0)
- err |= preserve_fpsimd_context(&aux->fpsimd);
+ if (err == 0) {
+ struct fpsimd_context *fpsimd_ctx =
+ container_of(aux, struct fpsimd_context, head);
+ err |= preserve_fpsimd_context(fpsimd_ctx);
+ aux += sizeof(*fpsimd_ctx);
+ }
/* set the "end" magic */
- __put_user_error(0, &aux->end.magic, err);
- __put_user_error(0, &aux->end.size, err);
+ end = aux;
+ __put_user_error(0, &end->magic, err);
+ __put_user_error(0, &end->size, err);
return err;
}
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/3] arm64: Expose ESR_EL1 information to user when SIGSEGV/SIGBUS
2014-04-06 22:19 [PATCH 0/3] arm64: Provide ESR_EL1 information to user signal handlers Catalin Marinas
2014-04-06 22:19 ` [PATCH 1/3] arm64: Provide read/write fault information in compat " Catalin Marinas
2014-04-06 22:19 ` [PATCH 2/3] arm64: Remove the aux_context structure Catalin Marinas
@ 2014-04-06 22:19 ` Catalin Marinas
2 siblings, 0 replies; 6+ messages in thread
From: Catalin Marinas @ 2014-04-06 22:19 UTC (permalink / raw)
To: linux-arm-kernel
This information is useful for instruction emulators to detect
read/write and access size without having to decode the faulting
instruction. The current patch exports it via sigcontext (struct
esr_context) and is only valid for SIGSEGV and SIGBUS.
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
arch/arm64/include/uapi/asm/sigcontext.h | 7 +++++++
arch/arm64/kernel/signal.c | 10 ++++++++++
2 files changed, 17 insertions(+)
diff --git a/arch/arm64/include/uapi/asm/sigcontext.h b/arch/arm64/include/uapi/asm/sigcontext.h
index 690ad51cc901..b72cf405b3fe 100644
--- a/arch/arm64/include/uapi/asm/sigcontext.h
+++ b/arch/arm64/include/uapi/asm/sigcontext.h
@@ -53,5 +53,12 @@ struct fpsimd_context {
__uint128_t vregs[32];
};
+/* ESR_EL1 context */
+#define ESR_MAGIC 0x45535201
+
+struct esr_context {
+ struct _aarch64_ctx head;
+ u64 esr;
+};
#endif /* _UAPI__ASM_SIGCONTEXT_H */
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 7ff2eee96c6b..dc2ab1b0ac0d 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -194,6 +194,16 @@ static int setup_sigframe(struct rt_sigframe __user *sf,
aux += sizeof(*fpsimd_ctx);
}
+ /* fault information, if valid */
+ if (current->thread.fault_code) {
+ struct esr_context *esr_ctx =
+ container_of(aux, struct esr_context, head);
+ __put_user_error(ESR_MAGIC, &esr_ctx->head.magic, err);
+ __put_user_error(sizeof(*esr_ctx), &esr_ctx->head.size, err);
+ __put_user_error(current->thread.fault_code, &esr_ctx->esr, err);
+ aux += sizeof(*esr_ctx);
+ }
+
/* set the "end" magic */
end = aux;
__put_user_error(0, &end->magic, err);
^ permalink raw reply related [flat|nested] 6+ messages in thread