summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/signal_32.c
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2013-09-10 20:20:42 +1000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-10-11 17:26:49 +1100
commitde79f7b9f6f92ec1bd6f61fa1f20de60728a5b5e (patch)
tree452b24060a36bf7c57a3a484c6ff981539259ea2 /arch/powerpc/kernel/signal_32.c
parent8e0a1611cb891e72a9affc4a8ee4795c634896a6 (diff)
downloadlinux-de79f7b9f6f92ec1bd6f61fa1f20de60728a5b5e.tar.gz
linux-de79f7b9f6f92ec1bd6f61fa1f20de60728a5b5e.tar.bz2
linux-de79f7b9f6f92ec1bd6f61fa1f20de60728a5b5e.zip
powerpc: Put FP/VSX and VR state into structures
This creates new 'thread_fp_state' and 'thread_vr_state' structures to store FP/VSX state (including FPSCR) and Altivec/VSX state (including VSCR), and uses them in the thread_struct. In the thread_fp_state, the FPRs and VSRs are represented as u64 rather than double, since we rarely perform floating-point computations on the values, and this will enable the structures to be used in KVM code as well. Similarly FPSCR is now a u64 rather than a structure of two 32-bit values. This takes the offsets out of the macros such as SAVE_32FPRS, REST_32FPRS, etc. This enables the same macros to be used for normal and transactional state, enabling us to delete the transactional versions of the macros. This also removes the unused do_load_up_fpu and do_load_up_altivec, which were in fact buggy since they didn't create large enough stack frames to account for the fact that load_up_fpu and load_up_altivec are not designed to be called from C and assume that their caller's stack frame is an interrupt frame. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/signal_32.c')
-rw-r--r--arch/powerpc/kernel/signal_32.c72
1 files changed, 37 insertions, 35 deletions
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index bebdf1a1a540..ea25e45ea959 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -265,27 +265,27 @@ struct rt_sigframe {
unsigned long copy_fpr_to_user(void __user *to,
struct task_struct *task)
{
- double buf[ELF_NFPREG];
+ u64 buf[ELF_NFPREG];
int i;
/* save FPR copy to local buffer then write to the thread_struct */
for (i = 0; i < (ELF_NFPREG - 1) ; i++)
buf[i] = task->thread.TS_FPR(i);
- memcpy(&buf[i], &task->thread.fpscr, sizeof(double));
+ buf[i] = task->thread.fp_state.fpscr;
return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double));
}
unsigned long copy_fpr_from_user(struct task_struct *task,
void __user *from)
{
- double buf[ELF_NFPREG];
+ u64 buf[ELF_NFPREG];
int i;
if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double)))
return 1;
for (i = 0; i < (ELF_NFPREG - 1) ; i++)
task->thread.TS_FPR(i) = buf[i];
- memcpy(&task->thread.fpscr, &buf[i], sizeof(double));
+ task->thread.fp_state.fpscr = buf[i];
return 0;
}
@@ -293,25 +293,25 @@ unsigned long copy_fpr_from_user(struct task_struct *task,
unsigned long copy_vsx_to_user(void __user *to,
struct task_struct *task)
{
- double buf[ELF_NVSRHALFREG];
+ u64 buf[ELF_NVSRHALFREG];
int i;
/* save FPR copy to local buffer then write to the thread_struct */
for (i = 0; i < ELF_NVSRHALFREG; i++)
- buf[i] = task->thread.fpr[i][TS_VSRLOWOFFSET];
+ buf[i] = task->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double));
}
unsigned long copy_vsx_from_user(struct task_struct *task,
void __user *from)
{
- double buf[ELF_NVSRHALFREG];
+ u64 buf[ELF_NVSRHALFREG];
int i;
if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double)))
return 1;
for (i = 0; i < ELF_NVSRHALFREG ; i++)
- task->thread.fpr[i][TS_VSRLOWOFFSET] = buf[i];
+ task->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
return 0;
}
@@ -319,27 +319,27 @@ unsigned long copy_vsx_from_user(struct task_struct *task,
unsigned long copy_transact_fpr_to_user(void __user *to,
struct task_struct *task)
{
- double buf[ELF_NFPREG];
+ u64 buf[ELF_NFPREG];
int i;
/* save FPR copy to local buffer then write to the thread_struct */
for (i = 0; i < (ELF_NFPREG - 1) ; i++)
buf[i] = task->thread.TS_TRANS_FPR(i);
- memcpy(&buf[i], &task->thread.transact_fpscr, sizeof(double));
+ buf[i] = task->thread.transact_fp.fpscr;
return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double));
}
unsigned long copy_transact_fpr_from_user(struct task_struct *task,
void __user *from)
{
- double buf[ELF_NFPREG];
+ u64 buf[ELF_NFPREG];
int i;
if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double)))
return 1;
for (i = 0; i < (ELF_NFPREG - 1) ; i++)
task->thread.TS_TRANS_FPR(i) = buf[i];
- memcpy(&task->thread.transact_fpscr, &buf[i], sizeof(double));
+ task->thread.transact_fp.fpscr = buf[i];
return 0;
}
@@ -347,25 +347,25 @@ unsigned long copy_transact_fpr_from_user(struct task_struct *task,
unsigned long copy_transact_vsx_to_user(void __user *to,
struct task_struct *task)
{
- double buf[ELF_NVSRHALFREG];
+ u64 buf[ELF_NVSRHALFREG];
int i;
/* save FPR copy to local buffer then write to the thread_struct */
for (i = 0; i < ELF_NVSRHALFREG; i++)
- buf[i] = task->thread.transact_fpr[i][TS_VSRLOWOFFSET];
+ buf[i] = task->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET];
return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double));
}
unsigned long copy_transact_vsx_from_user(struct task_struct *task,
void __user *from)
{
- double buf[ELF_NVSRHALFREG];
+ u64 buf[ELF_NVSRHALFREG];
int i;
if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double)))
return 1;
for (i = 0; i < ELF_NVSRHALFREG ; i++)
- task->thread.transact_fpr[i][TS_VSRLOWOFFSET] = buf[i];
+ task->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET] = buf[i];
return 0;
}
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
@@ -373,14 +373,14 @@ unsigned long copy_transact_vsx_from_user(struct task_struct *task,
inline unsigned long copy_fpr_to_user(void __user *to,
struct task_struct *task)
{
- return __copy_to_user(to, task->thread.fpr,
+ return __copy_to_user(to, task->thread.fp_state.fpr,
ELF_NFPREG * sizeof(double));
}
inline unsigned long copy_fpr_from_user(struct task_struct *task,
void __user *from)
{
- return __copy_from_user(task->thread.fpr, from,
+ return __copy_from_user(task->thread.fp_state.fpr, from,
ELF_NFPREG * sizeof(double));
}
@@ -388,14 +388,14 @@ inline unsigned long copy_fpr_from_user(struct task_struct *task,
inline unsigned long copy_transact_fpr_to_user(void __user *to,
struct task_struct *task)
{
- return __copy_to_user(to, task->thread.transact_fpr,
+ return __copy_to_user(to, task->thread.transact_fp.fpr,
ELF_NFPREG * sizeof(double));
}
inline unsigned long copy_transact_fpr_from_user(struct task_struct *task,
void __user *from)
{
- return __copy_from_user(task->thread.transact_fpr, from,
+ return __copy_from_user(task->thread.transact_fp.fpr, from,
ELF_NFPREG * sizeof(double));
}
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
@@ -423,7 +423,7 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
/* save altivec registers */
if (current->thread.used_vr) {
flush_altivec_to_thread(current);
- if (__copy_to_user(&frame->mc_vregs, current->thread.vr,
+ if (__copy_to_user(&frame->mc_vregs, &current->thread.vr_state,
ELF_NVRREG * sizeof(vector128)))
return 1;
/* set MSR_VEC in the saved MSR value to indicate that
@@ -534,17 +534,17 @@ static int save_tm_user_regs(struct pt_regs *regs,
/* save altivec registers */
if (current->thread.used_vr) {
flush_altivec_to_thread(current);
- if (__copy_to_user(&frame->mc_vregs, current->thread.vr,
+ if (__copy_to_user(&frame->mc_vregs, &current->thread.vr_state,
ELF_NVRREG * sizeof(vector128)))
return 1;
if (msr & MSR_VEC) {
if (__copy_to_user(&tm_frame->mc_vregs,
- current->thread.transact_vr,
+ &current->thread.transact_vr,
ELF_NVRREG * sizeof(vector128)))
return 1;
} else {
if (__copy_to_user(&tm_frame->mc_vregs,
- current->thread.vr,
+ &current->thread.vr_state,
ELF_NVRREG * sizeof(vector128)))
return 1;
}
@@ -692,11 +692,12 @@ static long restore_user_regs(struct pt_regs *regs,
regs->msr &= ~MSR_VEC;
if (msr & MSR_VEC) {
/* restore altivec registers from the stack */
- if (__copy_from_user(current->thread.vr, &sr->mc_vregs,
+ if (__copy_from_user(&current->thread.vr_state, &sr->mc_vregs,
sizeof(sr->mc_vregs)))
return 1;
} else if (current->thread.used_vr)
- memset(current->thread.vr, 0, ELF_NVRREG * sizeof(vector128));
+ memset(&current->thread.vr_state, 0,
+ ELF_NVRREG * sizeof(vector128));
/* Always get VRSAVE back */
if (__get_user(current->thread.vrsave, (u32 __user *)&sr->mc_vregs[32]))
@@ -722,7 +723,7 @@ static long restore_user_regs(struct pt_regs *regs,
return 1;
} else if (current->thread.used_vsr)
for (i = 0; i < 32 ; i++)
- current->thread.fpr[i][TS_VSRLOWOFFSET] = 0;
+ current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0;
#endif /* CONFIG_VSX */
/*
* force the process to reload the FP registers from
@@ -798,15 +799,16 @@ static long restore_tm_user_regs(struct pt_regs *regs,
regs->msr &= ~MSR_VEC;
if (msr & MSR_VEC) {
/* restore altivec registers from the stack */
- if (__copy_from_user(current->thread.vr, &sr->mc_vregs,
+ if (__copy_from_user(&current->thread.vr_state, &sr->mc_vregs,
sizeof(sr->mc_vregs)) ||
- __copy_from_user(current->thread.transact_vr,
+ __copy_from_user(&current->thread.transact_vr,
&tm_sr->mc_vregs,
sizeof(sr->mc_vregs)))
return 1;
} else if (current->thread.used_vr) {
- memset(current->thread.vr, 0, ELF_NVRREG * sizeof(vector128));
- memset(current->thread.transact_vr, 0,
+ memset(&current->thread.vr_state, 0,
+ ELF_NVRREG * sizeof(vector128));
+ memset(&current->thread.transact_vr, 0,
ELF_NVRREG * sizeof(vector128));
}
@@ -838,8 +840,8 @@ static long restore_tm_user_regs(struct pt_regs *regs,
return 1;
} else if (current->thread.used_vsr)
for (i = 0; i < 32 ; i++) {
- current->thread.fpr[i][TS_VSRLOWOFFSET] = 0;
- current->thread.transact_fpr[i][TS_VSRLOWOFFSET] = 0;
+ current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0;
+ current->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET] = 0;
}
#endif /* CONFIG_VSX */
@@ -1030,7 +1032,7 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
if (__put_user(0, &rt_sf->uc.uc_link))
goto badframe;
- current->thread.fpscr.val = 0; /* turn off all fp exceptions */
+ current->thread.fp_state.fpscr = 0; /* turn off all fp exceptions */
/* create a stack frame for the caller of the handler */
newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16);
@@ -1462,7 +1464,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
regs->link = tramp;
- current->thread.fpscr.val = 0; /* turn off all fp exceptions */
+ current->thread.fp_state.fpscr = 0; /* turn off all fp exceptions */
/* create a stack frame for the caller of the handler */
newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;