* [Qemu-devel] [PATCH 1/6] ARM: linux-user: Correct size of padding in target_ucontext_v2
2010-11-24 15:20 [Qemu-devel] [PATCH 0/6] ARM: linux-user: save/restore fpu regs to signal context Peter Maydell
@ 2010-11-24 15:20 ` Peter Maydell
2010-11-29 19:06 ` Nathan Froyd
2010-11-24 15:20 ` [Qemu-devel] [PATCH 2/6] ARM: Expose vfp_get_fpscr() and vfp_set_fpscr() to C code Peter Maydell
` (4 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Peter Maydell @ 2010-11-24 15:20 UTC (permalink / raw)
To: qemu-devel
The padding in the target_ucontext_v2 is defined by the size of
the target's sigset_t type, not the host's. (This bug only causes
problems when we start using the uc_regspace[] array to expose
VFP registers to userspace signal handlers.)
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
linux-user/signal.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 77683f7..da0ba50 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1108,7 +1108,7 @@ struct target_ucontext_v2 {
target_stack_t tuc_stack;
struct target_sigcontext tuc_mcontext;
target_sigset_t tuc_sigmask; /* mask last for extensibility */
- char __unused[128 - sizeof(sigset_t)];
+ char __unused[128 - sizeof(target_sigset_t)];
abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
};
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 2/6] ARM: Expose vfp_get_fpscr() and vfp_set_fpscr() to C code
2010-11-24 15:20 [Qemu-devel] [PATCH 0/6] ARM: linux-user: save/restore fpu regs to signal context Peter Maydell
2010-11-24 15:20 ` [Qemu-devel] [PATCH 1/6] ARM: linux-user: Correct size of padding in target_ucontext_v2 Peter Maydell
@ 2010-11-24 15:20 ` Peter Maydell
2010-11-29 19:07 ` Nathan Froyd
2010-11-24 15:20 ` [Qemu-devel] [PATCH 3/6] ARM: linux-user: Expose VFP registers to signal handlers Peter Maydell
` (3 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Peter Maydell @ 2010-11-24 15:20 UTC (permalink / raw)
To: qemu-devel
Expose the vfp_get_fpscr() and vfp_set_fpscr() functions to C
code as well as generated code, so we can use them to read and
write the FPSCR when saving and restoring VFP registers across
signal handlers in linux-user mode.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target-arm/cpu.h | 4 ++++
target-arm/helper.c | 10 ++++++++++
2 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index b87c605..0fb3f5c 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -302,6 +302,10 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
}
}
+/* Return the current FPSCR value. */
+uint32_t vfp_get_fpscr(CPUARMState *env);
+void vfp_set_fpscr(CPUARMState *env, uint32_t val);
+
enum arm_cpu_mode {
ARM_CPU_MODE_USR = 0x10,
ARM_CPU_MODE_FIQ = 0x11,
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 996d40d..b8dcdf7 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2245,6 +2245,11 @@ uint32_t HELPER(vfp_get_fpscr)(CPUState *env)
return fpscr;
}
+uint32_t vfp_get_fpscr(CPUState *env)
+{
+ return HELPER(vfp_get_fpscr)(env);
+}
+
/* Convert vfp exception flags to target form. */
static inline int vfp_exceptbits_to_host(int target_bits)
{
@@ -2301,6 +2306,11 @@ void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val)
set_float_exception_flags(i, &env->vfp.fp_status);
}
+void vfp_set_fpscr(CPUState *env, uint32_t val)
+{
+ HELPER(vfp_set_fpscr)(env, val);
+}
+
#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
#define VFP_BINOP(name) \
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 3/6] ARM: linux-user: Expose VFP registers to signal handlers
2010-11-24 15:20 [Qemu-devel] [PATCH 0/6] ARM: linux-user: save/restore fpu regs to signal context Peter Maydell
2010-11-24 15:20 ` [Qemu-devel] [PATCH 1/6] ARM: linux-user: Correct size of padding in target_ucontext_v2 Peter Maydell
2010-11-24 15:20 ` [Qemu-devel] [PATCH 2/6] ARM: Expose vfp_get_fpscr() and vfp_set_fpscr() to C code Peter Maydell
@ 2010-11-24 15:20 ` Peter Maydell
2010-11-29 19:16 ` Nathan Froyd
2010-11-24 15:20 ` [Qemu-devel] [PATCH 4/6] ARM: linux-user: Restore VFP state from ucontext on sigreturn Peter Maydell
` (2 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Peter Maydell @ 2010-11-24 15:20 UTC (permalink / raw)
To: qemu-devel
For ARM linux-user mode signal handlers, fill in the ucontext with
VFP register contents in the same way that the kernel does. We only
do this for v2 format sigframe (2.6.12 and above); this is actually
bug-for-bug compatible with the older kernels, which don't save and
restore VFP registers either.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
linux-user/signal.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 46 insertions(+), 1 deletions(-)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index da0ba50..71cc2cd 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1112,6 +1112,26 @@ struct target_ucontext_v2 {
abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
};
+struct target_user_vfp {
+ uint64_t fpregs[32];
+ abi_ulong fpscr;
+};
+
+struct target_user_vfp_exc {
+ abi_ulong fpexc;
+ abi_ulong fpinst;
+ abi_ulong fpinst2;
+};
+
+struct target_vfp_sigframe {
+ abi_ulong magic;
+ abi_ulong size;
+ struct target_user_vfp ufp;
+ struct target_user_vfp_exc ufp_exc;
+} __attribute__((__aligned__(8)));
+
+#define TARGET_VFP_MAGIC 0x56465001
+
struct sigframe_v1
{
struct target_sigcontext sc;
@@ -1255,11 +1275,29 @@ setup_return(CPUState *env, struct target_sigaction *ka,
return 0;
}
+static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUState *env)
+{
+ int i;
+ struct target_vfp_sigframe *vfpframe;
+ vfpframe = (struct target_vfp_sigframe *)regspace;
+ __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
+ __put_user(sizeof(*vfpframe), &vfpframe->size);
+ for (i = 0; i < 32; i++) {
+ __put_user(env->vfp.regs[i], &vfpframe->ufp.fpregs[i]);
+ }
+ __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
+ __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
+ __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
+ __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
+ return (abi_ulong*)(vfpframe+1);
+}
+
static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
target_sigset_t *set, CPUState *env)
{
struct target_sigaltstack stack;
int i;
+ abi_ulong *regspace;
/* Clear all the bits of the ucontext we don't use. */
memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
@@ -1271,7 +1309,14 @@ static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
memcpy(&uc->tuc_stack, &stack, sizeof(stack));
setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
- /* FIXME: Save coprocessor signal frame. */
+ /* Save coprocessor signal frame. */
+ regspace = uc->tuc_regspace;
+ if (arm_feature(env, ARM_FEATURE_VFP)) {
+ regspace = setup_sigframe_v2_vfp(regspace, env);
+ }
+ /* Write terminating magic word */
+ __put_user(0, regspace);
+
for(i = 0; i < TARGET_NSIG_WORDS; i++) {
__put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
}
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 4/6] ARM: linux-user: Restore VFP state from ucontext on sigreturn
2010-11-24 15:20 [Qemu-devel] [PATCH 0/6] ARM: linux-user: save/restore fpu regs to signal context Peter Maydell
` (2 preceding siblings ...)
2010-11-24 15:20 ` [Qemu-devel] [PATCH 3/6] ARM: linux-user: Expose VFP registers to signal handlers Peter Maydell
@ 2010-11-24 15:20 ` Peter Maydell
2010-11-29 19:17 ` Nathan Froyd
2010-11-29 19:19 ` Nathan Froyd
2010-11-24 15:20 ` [Qemu-devel] [PATCH 5/6] ARM: linux-user: Expose iWMMXT registers to signal handlers Peter Maydell
2010-11-24 15:20 ` [Qemu-devel] [PATCH 6/6] ARM: linux-user: Restore iWMMXT state from ucontext on sigreturn Peter Maydell
5 siblings, 2 replies; 12+ messages in thread
From: Peter Maydell @ 2010-11-24 15:20 UTC (permalink / raw)
To: qemu-devel
Restore the VFP registers from the ucontext on return from a signal
handler in linux-user mode. This means that signal handlers cannot
accidentally corrupt the interrupted code's VFP state, and allows
them to deliberately modify the state via the ucontext structure.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
linux-user/signal.c | 40 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 40 insertions(+), 0 deletions(-)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 71cc2cd..5e8cbeb 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1535,10 +1535,41 @@ badframe:
return 0;
}
+static abi_ulong *restore_sigframe_v2_vfp(CPUState *env, abi_ulong *regspace)
+{
+ int i;
+ abi_ulong magic, sz;
+ uint32_t fpscr, fpexc;
+ struct target_vfp_sigframe *vfpframe;
+ vfpframe = (struct target_vfp_sigframe *)regspace;
+
+ __get_user(magic, &vfpframe->magic);
+ __get_user(sz, &vfpframe->size);
+ if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
+ return 0;
+ }
+ for (i = 0; i < 32; i++) {
+ __get_user(env->vfp.regs[i], &vfpframe->ufp.fpregs[i]);
+ }
+ __get_user(fpscr, &vfpframe->ufp.fpscr);
+ vfp_set_fpscr(env, fpscr);
+ __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
+ /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
+ * and the exception flag is cleared
+ */
+ fpexc |= (1 << 30);
+ fpexc &= ~((1 << 31) | (1 << 28));
+ env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
+ __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
+ __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
+ return (abi_ulong*)(vfpframe + 1);
+}
+
static int do_sigframe_return_v2(CPUState *env, target_ulong frame_addr,
struct target_ucontext_v2 *uc)
{
sigset_t host_set;
+ abi_ulong *regspace;
target_to_host_sigset(&host_set, &uc->tuc_sigmask);
sigprocmask(SIG_SETMASK, &host_set, NULL);
@@ -1546,6 +1577,15 @@ static int do_sigframe_return_v2(CPUState *env, target_ulong frame_addr,
if (restore_sigcontext(env, &uc->tuc_mcontext))
return 1;
+ /* Restore coprocessor signal frame */
+ regspace = uc->tuc_regspace;
+ if (arm_feature(env, ARM_FEATURE_VFP)) {
+ regspace = restore_sigframe_v2_vfp(env, regspace);
+ if (!regspace) {
+ return 1;
+ }
+ }
+
if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
return 1;
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH 4/6] ARM: linux-user: Restore VFP state from ucontext on sigreturn
2010-11-24 15:20 ` [Qemu-devel] [PATCH 4/6] ARM: linux-user: Restore VFP state from ucontext on sigreturn Peter Maydell
@ 2010-11-29 19:17 ` Nathan Froyd
2010-11-29 19:19 ` Nathan Froyd
1 sibling, 0 replies; 12+ messages in thread
From: Nathan Froyd @ 2010-11-29 19:17 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-devel
On Wed, Nov 24, 2010 at 03:20:06PM +0000, Peter Maydell wrote:
> Restore the VFP registers from the ucontext on return from a signal
> handler in linux-user mode. This means that signal handlers cannot
> accidentally corrupt the interrupted code's VFP state, and allows
> them to deliberately modify the state via the ucontext structure.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Nathan Froyd <froydnj@codesourcery.com>
-Nathan
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH 4/6] ARM: linux-user: Restore VFP state from ucontext on sigreturn
2010-11-24 15:20 ` [Qemu-devel] [PATCH 4/6] ARM: linux-user: Restore VFP state from ucontext on sigreturn Peter Maydell
2010-11-29 19:17 ` Nathan Froyd
@ 2010-11-29 19:19 ` Nathan Froyd
1 sibling, 0 replies; 12+ messages in thread
From: Nathan Froyd @ 2010-11-29 19:19 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-devel
On Wed, Nov 24, 2010 at 03:20:06PM +0000, Peter Maydell wrote:
> Restore the VFP registers from the ucontext on return from a signal
> handler in linux-user mode. This means that signal handlers cannot
> accidentally corrupt the interrupted code's VFP state, and allows
> them to deliberately modify the state via the ucontext structure.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Nathan Froyd <froydnj@codesourcery.com>
-Nathan
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 5/6] ARM: linux-user: Expose iWMMXT registers to signal handlers
2010-11-24 15:20 [Qemu-devel] [PATCH 0/6] ARM: linux-user: save/restore fpu regs to signal context Peter Maydell
` (3 preceding siblings ...)
2010-11-24 15:20 ` [Qemu-devel] [PATCH 4/6] ARM: linux-user: Restore VFP state from ucontext on sigreturn Peter Maydell
@ 2010-11-24 15:20 ` Peter Maydell
2010-11-24 15:20 ` [Qemu-devel] [PATCH 6/6] ARM: linux-user: Restore iWMMXT state from ucontext on sigreturn Peter Maydell
5 siblings, 0 replies; 12+ messages in thread
From: Peter Maydell @ 2010-11-24 15:20 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
linux-user/signal.c | 37 +++++++++++++++++++++++++++++++++++++
1 files changed, 37 insertions(+), 0 deletions(-)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 5e8cbeb..3d0233d 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1130,7 +1130,21 @@ struct target_vfp_sigframe {
struct target_user_vfp_exc ufp_exc;
} __attribute__((__aligned__(8)));
+struct target_iwmmxt_sigframe {
+ abi_ulong magic;
+ abi_ulong size;
+ uint64_t regs[16];
+ /* Note that not all the coprocessor control registers are stored here */
+ uint32_t wcssf;
+ uint32_t wcasf;
+ uint32_t wcgr0;
+ uint32_t wcgr1;
+ uint32_t wcgr2;
+ uint32_t wcgr3;
+} __attribute__((__aligned__(8)));
+
#define TARGET_VFP_MAGIC 0x56465001
+#define TARGET_IWMMXT_MAGIC 0x12ef842a
struct sigframe_v1
{
@@ -1292,6 +1306,25 @@ static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUState *env)
return (abi_ulong*)(vfpframe+1);
}
+static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace, CPUState *env)
+{
+ int i;
+ struct target_iwmmxt_sigframe *iwmmxtframe;
+ iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
+ __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
+ __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
+ for (i = 0; i < 16; i++) {
+ __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
+ }
+ __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
+ __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
+ __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
+ __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
+ __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
+ __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
+ return (abi_ulong*)(iwmmxtframe+1);
+}
+
static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
target_sigset_t *set, CPUState *env)
{
@@ -1314,6 +1347,10 @@ static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
if (arm_feature(env, ARM_FEATURE_VFP)) {
regspace = setup_sigframe_v2_vfp(regspace, env);
}
+ if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
+ regspace = setup_sigframe_v2_iwmmxt(regspace, env);
+ }
+
/* Write terminating magic word */
__put_user(0, regspace);
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 6/6] ARM: linux-user: Restore iWMMXT state from ucontext on sigreturn
2010-11-24 15:20 [Qemu-devel] [PATCH 0/6] ARM: linux-user: save/restore fpu regs to signal context Peter Maydell
` (4 preceding siblings ...)
2010-11-24 15:20 ` [Qemu-devel] [PATCH 5/6] ARM: linux-user: Expose iWMMXT registers to signal handlers Peter Maydell
@ 2010-11-24 15:20 ` Peter Maydell
5 siblings, 0 replies; 12+ messages in thread
From: Peter Maydell @ 2010-11-24 15:20 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
linux-user/signal.c | 30 ++++++++++++++++++++++++++++++
1 files changed, 30 insertions(+), 0 deletions(-)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 3d0233d..bd0dbc1 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1602,6 +1602,30 @@ static abi_ulong *restore_sigframe_v2_vfp(CPUState *env, abi_ulong *regspace)
return (abi_ulong*)(vfpframe + 1);
}
+static abi_ulong *restore_sigframe_v2_iwmmxt(CPUState *env, abi_ulong *regspace)
+{
+ int i;
+ abi_ulong magic, sz;
+ struct target_iwmmxt_sigframe *iwmmxtframe;
+ iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
+
+ __get_user(magic, &iwmmxtframe->magic);
+ __get_user(sz, &iwmmxtframe->size);
+ if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
+ return 0;
+ }
+ for (i = 0; i < 16; i++) {
+ __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
+ }
+ __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
+ __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
+ __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
+ __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
+ __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
+ __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
+ return (abi_ulong*)(iwmmxtframe + 1);
+}
+
static int do_sigframe_return_v2(CPUState *env, target_ulong frame_addr,
struct target_ucontext_v2 *uc)
{
@@ -1622,6 +1646,12 @@ static int do_sigframe_return_v2(CPUState *env, target_ulong frame_addr,
return 1;
}
}
+ if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
+ regspace = restore_sigframe_v2_iwmmxt(env, regspace);
+ if (!regspace) {
+ return 1;
+ }
+ }
if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
return 1;
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread