mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-04-13 17:55:14 +00:00
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>
This commit is contained in:
parent
8e0a1611cb
commit
de79f7b9f6
17 changed files with 200 additions and 358 deletions
|
@ -98,123 +98,40 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
|
||||||
#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
|
#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
|
||||||
#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
|
#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
|
||||||
|
|
||||||
#define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base)
|
#define SAVE_FPR(n, base) stfd n,8*TS_FPRWIDTH*(n)(base)
|
||||||
#define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base)
|
#define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base)
|
||||||
#define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base)
|
#define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base)
|
||||||
#define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base)
|
#define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base)
|
||||||
#define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base)
|
#define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base)
|
||||||
#define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base)
|
#define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base)
|
||||||
#define REST_FPR(n, base) lfd n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base)
|
#define REST_FPR(n, base) lfd n,8*TS_FPRWIDTH*(n)(base)
|
||||||
#define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base)
|
#define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base)
|
||||||
#define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, base)
|
#define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, base)
|
||||||
#define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, base)
|
#define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, base)
|
||||||
#define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base)
|
#define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base)
|
||||||
#define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base)
|
#define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base)
|
||||||
|
|
||||||
#define SAVE_VR(n,b,base) li b,THREAD_VR0+(16*(n)); stvx n,base,b
|
#define SAVE_VR(n,b,base) li b,16*(n); stvx n,base,b
|
||||||
#define SAVE_2VRS(n,b,base) SAVE_VR(n,b,base); SAVE_VR(n+1,b,base)
|
#define SAVE_2VRS(n,b,base) SAVE_VR(n,b,base); SAVE_VR(n+1,b,base)
|
||||||
#define SAVE_4VRS(n,b,base) SAVE_2VRS(n,b,base); SAVE_2VRS(n+2,b,base)
|
#define SAVE_4VRS(n,b,base) SAVE_2VRS(n,b,base); SAVE_2VRS(n+2,b,base)
|
||||||
#define SAVE_8VRS(n,b,base) SAVE_4VRS(n,b,base); SAVE_4VRS(n+4,b,base)
|
#define SAVE_8VRS(n,b,base) SAVE_4VRS(n,b,base); SAVE_4VRS(n+4,b,base)
|
||||||
#define SAVE_16VRS(n,b,base) SAVE_8VRS(n,b,base); SAVE_8VRS(n+8,b,base)
|
#define SAVE_16VRS(n,b,base) SAVE_8VRS(n,b,base); SAVE_8VRS(n+8,b,base)
|
||||||
#define SAVE_32VRS(n,b,base) SAVE_16VRS(n,b,base); SAVE_16VRS(n+16,b,base)
|
#define SAVE_32VRS(n,b,base) SAVE_16VRS(n,b,base); SAVE_16VRS(n+16,b,base)
|
||||||
#define REST_VR(n,b,base) li b,THREAD_VR0+(16*(n)); lvx n,base,b
|
#define REST_VR(n,b,base) li b,16*(n); lvx n,base,b
|
||||||
#define REST_2VRS(n,b,base) REST_VR(n,b,base); REST_VR(n+1,b,base)
|
#define REST_2VRS(n,b,base) REST_VR(n,b,base); REST_VR(n+1,b,base)
|
||||||
#define REST_4VRS(n,b,base) REST_2VRS(n,b,base); REST_2VRS(n+2,b,base)
|
#define REST_4VRS(n,b,base) REST_2VRS(n,b,base); REST_2VRS(n+2,b,base)
|
||||||
#define REST_8VRS(n,b,base) REST_4VRS(n,b,base); REST_4VRS(n+4,b,base)
|
#define REST_8VRS(n,b,base) REST_4VRS(n,b,base); REST_4VRS(n+4,b,base)
|
||||||
#define REST_16VRS(n,b,base) REST_8VRS(n,b,base); REST_8VRS(n+8,b,base)
|
#define REST_16VRS(n,b,base) REST_8VRS(n,b,base); REST_8VRS(n+8,b,base)
|
||||||
#define REST_32VRS(n,b,base) REST_16VRS(n,b,base); REST_16VRS(n+16,b,base)
|
#define REST_32VRS(n,b,base) REST_16VRS(n,b,base); REST_16VRS(n+16,b,base)
|
||||||
|
|
||||||
/* Save/restore FPRs, VRs and VSRs from their checkpointed backups in
|
|
||||||
* thread_struct:
|
|
||||||
*/
|
|
||||||
#define SAVE_FPR_TRANSACT(n, base) stfd n,THREAD_TRANSACT_FPR0+ \
|
|
||||||
8*TS_FPRWIDTH*(n)(base)
|
|
||||||
#define SAVE_2FPRS_TRANSACT(n, base) SAVE_FPR_TRANSACT(n, base); \
|
|
||||||
SAVE_FPR_TRANSACT(n+1, base)
|
|
||||||
#define SAVE_4FPRS_TRANSACT(n, base) SAVE_2FPRS_TRANSACT(n, base); \
|
|
||||||
SAVE_2FPRS_TRANSACT(n+2, base)
|
|
||||||
#define SAVE_8FPRS_TRANSACT(n, base) SAVE_4FPRS_TRANSACT(n, base); \
|
|
||||||
SAVE_4FPRS_TRANSACT(n+4, base)
|
|
||||||
#define SAVE_16FPRS_TRANSACT(n, base) SAVE_8FPRS_TRANSACT(n, base); \
|
|
||||||
SAVE_8FPRS_TRANSACT(n+8, base)
|
|
||||||
#define SAVE_32FPRS_TRANSACT(n, base) SAVE_16FPRS_TRANSACT(n, base); \
|
|
||||||
SAVE_16FPRS_TRANSACT(n+16, base)
|
|
||||||
|
|
||||||
#define REST_FPR_TRANSACT(n, base) lfd n,THREAD_TRANSACT_FPR0+ \
|
|
||||||
8*TS_FPRWIDTH*(n)(base)
|
|
||||||
#define REST_2FPRS_TRANSACT(n, base) REST_FPR_TRANSACT(n, base); \
|
|
||||||
REST_FPR_TRANSACT(n+1, base)
|
|
||||||
#define REST_4FPRS_TRANSACT(n, base) REST_2FPRS_TRANSACT(n, base); \
|
|
||||||
REST_2FPRS_TRANSACT(n+2, base)
|
|
||||||
#define REST_8FPRS_TRANSACT(n, base) REST_4FPRS_TRANSACT(n, base); \
|
|
||||||
REST_4FPRS_TRANSACT(n+4, base)
|
|
||||||
#define REST_16FPRS_TRANSACT(n, base) REST_8FPRS_TRANSACT(n, base); \
|
|
||||||
REST_8FPRS_TRANSACT(n+8, base)
|
|
||||||
#define REST_32FPRS_TRANSACT(n, base) REST_16FPRS_TRANSACT(n, base); \
|
|
||||||
REST_16FPRS_TRANSACT(n+16, base)
|
|
||||||
|
|
||||||
|
|
||||||
#define SAVE_VR_TRANSACT(n,b,base) li b,THREAD_TRANSACT_VR0+(16*(n)); \
|
|
||||||
stvx n,b,base
|
|
||||||
#define SAVE_2VRS_TRANSACT(n,b,base) SAVE_VR_TRANSACT(n,b,base); \
|
|
||||||
SAVE_VR_TRANSACT(n+1,b,base)
|
|
||||||
#define SAVE_4VRS_TRANSACT(n,b,base) SAVE_2VRS_TRANSACT(n,b,base); \
|
|
||||||
SAVE_2VRS_TRANSACT(n+2,b,base)
|
|
||||||
#define SAVE_8VRS_TRANSACT(n,b,base) SAVE_4VRS_TRANSACT(n,b,base); \
|
|
||||||
SAVE_4VRS_TRANSACT(n+4,b,base)
|
|
||||||
#define SAVE_16VRS_TRANSACT(n,b,base) SAVE_8VRS_TRANSACT(n,b,base); \
|
|
||||||
SAVE_8VRS_TRANSACT(n+8,b,base)
|
|
||||||
#define SAVE_32VRS_TRANSACT(n,b,base) SAVE_16VRS_TRANSACT(n,b,base); \
|
|
||||||
SAVE_16VRS_TRANSACT(n+16,b,base)
|
|
||||||
|
|
||||||
#define REST_VR_TRANSACT(n,b,base) li b,THREAD_TRANSACT_VR0+(16*(n)); \
|
|
||||||
lvx n,b,base
|
|
||||||
#define REST_2VRS_TRANSACT(n,b,base) REST_VR_TRANSACT(n,b,base); \
|
|
||||||
REST_VR_TRANSACT(n+1,b,base)
|
|
||||||
#define REST_4VRS_TRANSACT(n,b,base) REST_2VRS_TRANSACT(n,b,base); \
|
|
||||||
REST_2VRS_TRANSACT(n+2,b,base)
|
|
||||||
#define REST_8VRS_TRANSACT(n,b,base) REST_4VRS_TRANSACT(n,b,base); \
|
|
||||||
REST_4VRS_TRANSACT(n+4,b,base)
|
|
||||||
#define REST_16VRS_TRANSACT(n,b,base) REST_8VRS_TRANSACT(n,b,base); \
|
|
||||||
REST_8VRS_TRANSACT(n+8,b,base)
|
|
||||||
#define REST_32VRS_TRANSACT(n,b,base) REST_16VRS_TRANSACT(n,b,base); \
|
|
||||||
REST_16VRS_TRANSACT(n+16,b,base)
|
|
||||||
|
|
||||||
|
|
||||||
#define SAVE_VSR_TRANSACT(n,b,base) li b,THREAD_TRANSACT_VSR0+(16*(n)); \
|
|
||||||
STXVD2X(n,R##base,R##b)
|
|
||||||
#define SAVE_2VSRS_TRANSACT(n,b,base) SAVE_VSR_TRANSACT(n,b,base); \
|
|
||||||
SAVE_VSR_TRANSACT(n+1,b,base)
|
|
||||||
#define SAVE_4VSRS_TRANSACT(n,b,base) SAVE_2VSRS_TRANSACT(n,b,base); \
|
|
||||||
SAVE_2VSRS_TRANSACT(n+2,b,base)
|
|
||||||
#define SAVE_8VSRS_TRANSACT(n,b,base) SAVE_4VSRS_TRANSACT(n,b,base); \
|
|
||||||
SAVE_4VSRS_TRANSACT(n+4,b,base)
|
|
||||||
#define SAVE_16VSRS_TRANSACT(n,b,base) SAVE_8VSRS_TRANSACT(n,b,base); \
|
|
||||||
SAVE_8VSRS_TRANSACT(n+8,b,base)
|
|
||||||
#define SAVE_32VSRS_TRANSACT(n,b,base) SAVE_16VSRS_TRANSACT(n,b,base); \
|
|
||||||
SAVE_16VSRS_TRANSACT(n+16,b,base)
|
|
||||||
|
|
||||||
#define REST_VSR_TRANSACT(n,b,base) li b,THREAD_TRANSACT_VSR0+(16*(n)); \
|
|
||||||
LXVD2X(n,R##base,R##b)
|
|
||||||
#define REST_2VSRS_TRANSACT(n,b,base) REST_VSR_TRANSACT(n,b,base); \
|
|
||||||
REST_VSR_TRANSACT(n+1,b,base)
|
|
||||||
#define REST_4VSRS_TRANSACT(n,b,base) REST_2VSRS_TRANSACT(n,b,base); \
|
|
||||||
REST_2VSRS_TRANSACT(n+2,b,base)
|
|
||||||
#define REST_8VSRS_TRANSACT(n,b,base) REST_4VSRS_TRANSACT(n,b,base); \
|
|
||||||
REST_4VSRS_TRANSACT(n+4,b,base)
|
|
||||||
#define REST_16VSRS_TRANSACT(n,b,base) REST_8VSRS_TRANSACT(n,b,base); \
|
|
||||||
REST_8VSRS_TRANSACT(n+8,b,base)
|
|
||||||
#define REST_32VSRS_TRANSACT(n,b,base) REST_16VSRS_TRANSACT(n,b,base); \
|
|
||||||
REST_16VSRS_TRANSACT(n+16,b,base)
|
|
||||||
|
|
||||||
/* Save the lower 32 VSRs in the thread VSR region */
|
/* Save the lower 32 VSRs in the thread VSR region */
|
||||||
#define SAVE_VSR(n,b,base) li b,THREAD_VSR0+(16*(n)); STXVD2X(n,R##base,R##b)
|
#define SAVE_VSR(n,b,base) li b,16*(n); STXVD2X(n,R##base,R##b)
|
||||||
#define SAVE_2VSRS(n,b,base) SAVE_VSR(n,b,base); SAVE_VSR(n+1,b,base)
|
#define SAVE_2VSRS(n,b,base) SAVE_VSR(n,b,base); SAVE_VSR(n+1,b,base)
|
||||||
#define SAVE_4VSRS(n,b,base) SAVE_2VSRS(n,b,base); SAVE_2VSRS(n+2,b,base)
|
#define SAVE_4VSRS(n,b,base) SAVE_2VSRS(n,b,base); SAVE_2VSRS(n+2,b,base)
|
||||||
#define SAVE_8VSRS(n,b,base) SAVE_4VSRS(n,b,base); SAVE_4VSRS(n+4,b,base)
|
#define SAVE_8VSRS(n,b,base) SAVE_4VSRS(n,b,base); SAVE_4VSRS(n+4,b,base)
|
||||||
#define SAVE_16VSRS(n,b,base) SAVE_8VSRS(n,b,base); SAVE_8VSRS(n+8,b,base)
|
#define SAVE_16VSRS(n,b,base) SAVE_8VSRS(n,b,base); SAVE_8VSRS(n+8,b,base)
|
||||||
#define SAVE_32VSRS(n,b,base) SAVE_16VSRS(n,b,base); SAVE_16VSRS(n+16,b,base)
|
#define SAVE_32VSRS(n,b,base) SAVE_16VSRS(n,b,base); SAVE_16VSRS(n+16,b,base)
|
||||||
#define REST_VSR(n,b,base) li b,THREAD_VSR0+(16*(n)); LXVD2X(n,R##base,R##b)
|
#define REST_VSR(n,b,base) li b,16*(n); LXVD2X(n,R##base,R##b)
|
||||||
#define REST_2VSRS(n,b,base) REST_VSR(n,b,base); REST_VSR(n+1,b,base)
|
#define REST_2VSRS(n,b,base) REST_VSR(n,b,base); REST_VSR(n+1,b,base)
|
||||||
#define REST_4VSRS(n,b,base) REST_2VSRS(n,b,base); REST_2VSRS(n+2,b,base)
|
#define REST_4VSRS(n,b,base) REST_2VSRS(n,b,base); REST_2VSRS(n+2,b,base)
|
||||||
#define REST_8VSRS(n,b,base) REST_4VSRS(n,b,base); REST_4VSRS(n+4,b,base)
|
#define REST_8VSRS(n,b,base) REST_4VSRS(n,b,base); REST_4VSRS(n+4,b,base)
|
||||||
|
|
|
@ -144,8 +144,20 @@ typedef struct {
|
||||||
|
|
||||||
#define TS_FPROFFSET 0
|
#define TS_FPROFFSET 0
|
||||||
#define TS_VSRLOWOFFSET 1
|
#define TS_VSRLOWOFFSET 1
|
||||||
#define TS_FPR(i) fpr[i][TS_FPROFFSET]
|
#define TS_FPR(i) fp_state.fpr[i][TS_FPROFFSET]
|
||||||
#define TS_TRANS_FPR(i) transact_fpr[i][TS_FPROFFSET]
|
#define TS_TRANS_FPR(i) transact_fp.fpr[i][TS_FPROFFSET]
|
||||||
|
|
||||||
|
/* FP and VSX 0-31 register set */
|
||||||
|
struct thread_fp_state {
|
||||||
|
u64 fpr[32][TS_FPRWIDTH] __attribute__((aligned(16)));
|
||||||
|
u64 fpscr; /* Floating point status */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Complete AltiVec register set including VSCR */
|
||||||
|
struct thread_vr_state {
|
||||||
|
vector128 vr[32] __attribute__((aligned(16)));
|
||||||
|
vector128 vscr __attribute__((aligned(16)));
|
||||||
|
};
|
||||||
|
|
||||||
struct thread_struct {
|
struct thread_struct {
|
||||||
unsigned long ksp; /* Kernel stack pointer */
|
unsigned long ksp; /* Kernel stack pointer */
|
||||||
|
@ -198,13 +210,7 @@ struct thread_struct {
|
||||||
unsigned long dvc2;
|
unsigned long dvc2;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
/* FP and VSX 0-31 register set */
|
struct thread_fp_state fp_state;
|
||||||
double fpr[32][TS_FPRWIDTH] __attribute__((aligned(16)));
|
|
||||||
struct {
|
|
||||||
|
|
||||||
unsigned int pad;
|
|
||||||
unsigned int val; /* Floating point status */
|
|
||||||
} fpscr;
|
|
||||||
int fpexc_mode; /* floating-point exception mode */
|
int fpexc_mode; /* floating-point exception mode */
|
||||||
unsigned int align_ctl; /* alignment handling control */
|
unsigned int align_ctl; /* alignment handling control */
|
||||||
#ifdef CONFIG_PPC64
|
#ifdef CONFIG_PPC64
|
||||||
|
@ -222,10 +228,7 @@ struct thread_struct {
|
||||||
struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */
|
struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */
|
||||||
unsigned long trap_nr; /* last trap # on this thread */
|
unsigned long trap_nr; /* last trap # on this thread */
|
||||||
#ifdef CONFIG_ALTIVEC
|
#ifdef CONFIG_ALTIVEC
|
||||||
/* Complete AltiVec register set */
|
struct thread_vr_state vr_state;
|
||||||
vector128 vr[32] __attribute__((aligned(16)));
|
|
||||||
/* AltiVec status */
|
|
||||||
vector128 vscr __attribute__((aligned(16)));
|
|
||||||
unsigned long vrsave;
|
unsigned long vrsave;
|
||||||
int used_vr; /* set if process has used altivec */
|
int used_vr; /* set if process has used altivec */
|
||||||
#endif /* CONFIG_ALTIVEC */
|
#endif /* CONFIG_ALTIVEC */
|
||||||
|
@ -262,13 +265,8 @@ struct thread_struct {
|
||||||
* transact_fpr[] is the new set of transactional values.
|
* transact_fpr[] is the new set of transactional values.
|
||||||
* VRs work the same way.
|
* VRs work the same way.
|
||||||
*/
|
*/
|
||||||
double transact_fpr[32][TS_FPRWIDTH];
|
struct thread_fp_state transact_fp;
|
||||||
struct {
|
struct thread_vr_state transact_vr;
|
||||||
unsigned int pad;
|
|
||||||
unsigned int val; /* Floating point status */
|
|
||||||
} transact_fpscr;
|
|
||||||
vector128 transact_vr[32] __attribute__((aligned(16)));
|
|
||||||
vector128 transact_vscr __attribute__((aligned(16)));
|
|
||||||
unsigned long transact_vrsave;
|
unsigned long transact_vrsave;
|
||||||
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
|
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
|
||||||
#ifdef CONFIG_KVM_BOOK3S_32_HANDLER
|
#ifdef CONFIG_KVM_BOOK3S_32_HANDLER
|
||||||
|
@ -322,8 +320,6 @@ struct thread_struct {
|
||||||
.ksp = INIT_SP, \
|
.ksp = INIT_SP, \
|
||||||
.regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \
|
.regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \
|
||||||
.fs = KERNEL_DS, \
|
.fs = KERNEL_DS, \
|
||||||
.fpr = {{0}}, \
|
|
||||||
.fpscr = { .val = 0, }, \
|
|
||||||
.fpexc_mode = 0, \
|
.fpexc_mode = 0, \
|
||||||
.ppr = INIT_PPR, \
|
.ppr = INIT_PPR, \
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,7 @@
|
||||||
#define FP_EX_DIVZERO (1 << (31 - 5))
|
#define FP_EX_DIVZERO (1 << (31 - 5))
|
||||||
#define FP_EX_INEXACT (1 << (31 - 6))
|
#define FP_EX_INEXACT (1 << (31 - 6))
|
||||||
|
|
||||||
#define __FPU_FPSCR (current->thread.fpscr.val)
|
#define __FPU_FPSCR (current->thread.fp_state.fpscr)
|
||||||
|
|
||||||
/* We only actually write to the destination register
|
/* We only actually write to the destination register
|
||||||
* if exceptions signalled (if any) will not trap.
|
* if exceptions signalled (if any) will not trap.
|
||||||
|
|
|
@ -660,7 +660,7 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg,
|
||||||
if (reg < 32)
|
if (reg < 32)
|
||||||
ptr = (char *) ¤t->thread.TS_FPR(reg);
|
ptr = (char *) ¤t->thread.TS_FPR(reg);
|
||||||
else
|
else
|
||||||
ptr = (char *) ¤t->thread.vr[reg - 32];
|
ptr = (char *) ¤t->thread.vr_state.vr[reg - 32];
|
||||||
|
|
||||||
lptr = (unsigned long *) ptr;
|
lptr = (unsigned long *) ptr;
|
||||||
|
|
||||||
|
@ -897,7 +897,7 @@ int fix_alignment(struct pt_regs *regs)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
} else if (flags & F) {
|
} else if (flags & F) {
|
||||||
data.dd = current->thread.TS_FPR(reg);
|
data.ll = current->thread.TS_FPR(reg);
|
||||||
if (flags & S) {
|
if (flags & S) {
|
||||||
/* Single-precision FP store requires conversion... */
|
/* Single-precision FP store requires conversion... */
|
||||||
#ifdef CONFIG_PPC_FPU
|
#ifdef CONFIG_PPC_FPU
|
||||||
|
@ -975,7 +975,7 @@ int fix_alignment(struct pt_regs *regs)
|
||||||
if (unlikely(ret))
|
if (unlikely(ret))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
} else if (flags & F)
|
} else if (flags & F)
|
||||||
current->thread.TS_FPR(reg) = data.dd;
|
current->thread.TS_FPR(reg) = data.ll;
|
||||||
else
|
else
|
||||||
regs->gpr[reg] = data.ll;
|
regs->gpr[reg] = data.ll;
|
||||||
|
|
||||||
|
|
|
@ -90,16 +90,15 @@ int main(void)
|
||||||
DEFINE(THREAD_NORMSAVES, offsetof(struct thread_struct, normsave[0]));
|
DEFINE(THREAD_NORMSAVES, offsetof(struct thread_struct, normsave[0]));
|
||||||
#endif
|
#endif
|
||||||
DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
|
DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
|
||||||
DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
|
DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fp_state));
|
||||||
DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr));
|
DEFINE(FPSTATE_FPSCR, offsetof(struct thread_fp_state, fpscr));
|
||||||
#ifdef CONFIG_ALTIVEC
|
#ifdef CONFIG_ALTIVEC
|
||||||
DEFINE(THREAD_VR0, offsetof(struct thread_struct, vr[0]));
|
DEFINE(THREAD_VRSTATE, offsetof(struct thread_struct, vr_state));
|
||||||
DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave));
|
DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave));
|
||||||
DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr));
|
|
||||||
DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr));
|
DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr));
|
||||||
|
DEFINE(VRSTATE_VSCR, offsetof(struct thread_vr_state, vscr));
|
||||||
#endif /* CONFIG_ALTIVEC */
|
#endif /* CONFIG_ALTIVEC */
|
||||||
#ifdef CONFIG_VSX
|
#ifdef CONFIG_VSX
|
||||||
DEFINE(THREAD_VSR0, offsetof(struct thread_struct, fpr));
|
|
||||||
DEFINE(THREAD_USED_VSR, offsetof(struct thread_struct, used_vsr));
|
DEFINE(THREAD_USED_VSR, offsetof(struct thread_struct, used_vsr));
|
||||||
#endif /* CONFIG_VSX */
|
#endif /* CONFIG_VSX */
|
||||||
#ifdef CONFIG_PPC64
|
#ifdef CONFIG_PPC64
|
||||||
|
@ -143,20 +142,12 @@ int main(void)
|
||||||
DEFINE(THREAD_TM_PPR, offsetof(struct thread_struct, tm_ppr));
|
DEFINE(THREAD_TM_PPR, offsetof(struct thread_struct, tm_ppr));
|
||||||
DEFINE(THREAD_TM_DSCR, offsetof(struct thread_struct, tm_dscr));
|
DEFINE(THREAD_TM_DSCR, offsetof(struct thread_struct, tm_dscr));
|
||||||
DEFINE(PT_CKPT_REGS, offsetof(struct thread_struct, ckpt_regs));
|
DEFINE(PT_CKPT_REGS, offsetof(struct thread_struct, ckpt_regs));
|
||||||
DEFINE(THREAD_TRANSACT_VR0, offsetof(struct thread_struct,
|
DEFINE(THREAD_TRANSACT_VRSTATE, offsetof(struct thread_struct,
|
||||||
transact_vr[0]));
|
transact_vr));
|
||||||
DEFINE(THREAD_TRANSACT_VSCR, offsetof(struct thread_struct,
|
|
||||||
transact_vscr));
|
|
||||||
DEFINE(THREAD_TRANSACT_VRSAVE, offsetof(struct thread_struct,
|
DEFINE(THREAD_TRANSACT_VRSAVE, offsetof(struct thread_struct,
|
||||||
transact_vrsave));
|
transact_vrsave));
|
||||||
DEFINE(THREAD_TRANSACT_FPR0, offsetof(struct thread_struct,
|
DEFINE(THREAD_TRANSACT_FPSTATE, offsetof(struct thread_struct,
|
||||||
transact_fpr[0]));
|
transact_fp));
|
||||||
DEFINE(THREAD_TRANSACT_FPSCR, offsetof(struct thread_struct,
|
|
||||||
transact_fpscr));
|
|
||||||
#ifdef CONFIG_VSX
|
|
||||||
DEFINE(THREAD_TRANSACT_VSR0, offsetof(struct thread_struct,
|
|
||||||
transact_fpr[0]));
|
|
||||||
#endif
|
|
||||||
/* Local pt_regs on stack for Transactional Memory funcs. */
|
/* Local pt_regs on stack for Transactional Memory funcs. */
|
||||||
DEFINE(TM_FRAME_SIZE, STACK_FRAME_OVERHEAD +
|
DEFINE(TM_FRAME_SIZE, STACK_FRAME_OVERHEAD +
|
||||||
sizeof(struct pt_regs) + 16);
|
sizeof(struct pt_regs) + 16);
|
||||||
|
|
|
@ -35,15 +35,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX); \
|
||||||
2: REST_32VSRS(n,c,base); \
|
2: REST_32VSRS(n,c,base); \
|
||||||
3:
|
3:
|
||||||
|
|
||||||
#define __REST_32FPVSRS_TRANSACT(n,c,base) \
|
|
||||||
BEGIN_FTR_SECTION \
|
|
||||||
b 2f; \
|
|
||||||
END_FTR_SECTION_IFSET(CPU_FTR_VSX); \
|
|
||||||
REST_32FPRS_TRANSACT(n,base); \
|
|
||||||
b 3f; \
|
|
||||||
2: REST_32VSRS_TRANSACT(n,c,base); \
|
|
||||||
3:
|
|
||||||
|
|
||||||
#define __SAVE_32FPVSRS(n,c,base) \
|
#define __SAVE_32FPVSRS(n,c,base) \
|
||||||
BEGIN_FTR_SECTION \
|
BEGIN_FTR_SECTION \
|
||||||
b 2f; \
|
b 2f; \
|
||||||
|
@ -54,40 +45,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX); \
|
||||||
3:
|
3:
|
||||||
#else
|
#else
|
||||||
#define __REST_32FPVSRS(n,b,base) REST_32FPRS(n, base)
|
#define __REST_32FPVSRS(n,b,base) REST_32FPRS(n, base)
|
||||||
#define __REST_32FPVSRS_TRANSACT(n,b,base) REST_32FPRS(n, base)
|
|
||||||
#define __SAVE_32FPVSRS(n,b,base) SAVE_32FPRS(n, base)
|
#define __SAVE_32FPVSRS(n,b,base) SAVE_32FPRS(n, base)
|
||||||
#endif
|
#endif
|
||||||
#define REST_32FPVSRS(n,c,base) __REST_32FPVSRS(n,__REG_##c,__REG_##base)
|
#define REST_32FPVSRS(n,c,base) __REST_32FPVSRS(n,__REG_##c,__REG_##base)
|
||||||
#define REST_32FPVSRS_TRANSACT(n,c,base) \
|
|
||||||
__REST_32FPVSRS_TRANSACT(n,__REG_##c,__REG_##base)
|
|
||||||
#define SAVE_32FPVSRS(n,c,base) __SAVE_32FPVSRS(n,__REG_##c,__REG_##base)
|
#define SAVE_32FPVSRS(n,c,base) __SAVE_32FPVSRS(n,__REG_##c,__REG_##base)
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||||
/*
|
|
||||||
* Wrapper to call load_up_fpu from C.
|
|
||||||
* void do_load_up_fpu(struct pt_regs *regs);
|
|
||||||
*/
|
|
||||||
_GLOBAL(do_load_up_fpu)
|
|
||||||
mflr r0
|
|
||||||
std r0, 16(r1)
|
|
||||||
stdu r1, -112(r1)
|
|
||||||
|
|
||||||
subi r6, r3, STACK_FRAME_OVERHEAD
|
|
||||||
/* load_up_fpu expects r12=MSR, r13=PACA, and returns
|
|
||||||
* with r12 = new MSR.
|
|
||||||
*/
|
|
||||||
ld r12,_MSR(r6)
|
|
||||||
GET_PACA(r13)
|
|
||||||
|
|
||||||
bl load_up_fpu
|
|
||||||
std r12,_MSR(r6)
|
|
||||||
|
|
||||||
ld r0, 112+16(r1)
|
|
||||||
addi r1, r1, 112
|
|
||||||
mtlr r0
|
|
||||||
blr
|
|
||||||
|
|
||||||
|
|
||||||
/* void do_load_up_transact_fpu(struct thread_struct *thread)
|
/* void do_load_up_transact_fpu(struct thread_struct *thread)
|
||||||
*
|
*
|
||||||
* This is similar to load_up_fpu but for the transactional version of the FP
|
* This is similar to load_up_fpu but for the transactional version of the FP
|
||||||
|
@ -105,9 +68,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
|
||||||
SYNC
|
SYNC
|
||||||
MTMSRD(r5)
|
MTMSRD(r5)
|
||||||
|
|
||||||
lfd fr0,THREAD_TRANSACT_FPSCR(r3)
|
addi r7,r3,THREAD_TRANSACT_FPSTATE
|
||||||
|
lfd fr0,FPSTATE_FPSCR(r7)
|
||||||
MTFSF_L(fr0)
|
MTFSF_L(fr0)
|
||||||
REST_32FPVSRS_TRANSACT(0, R4, R3)
|
REST_32FPVSRS(0, R4, R7)
|
||||||
|
|
||||||
/* FP/VSX off again */
|
/* FP/VSX off again */
|
||||||
MTMSRD(r6)
|
MTMSRD(r6)
|
||||||
|
@ -147,9 +111,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
|
||||||
beq 1f
|
beq 1f
|
||||||
toreal(r4)
|
toreal(r4)
|
||||||
addi r4,r4,THREAD /* want last_task_used_math->thread */
|
addi r4,r4,THREAD /* want last_task_used_math->thread */
|
||||||
SAVE_32FPVSRS(0, R5, R4)
|
addi r8,r4,THREAD_FPSTATE
|
||||||
|
SAVE_32FPVSRS(0, R5, R8)
|
||||||
mffs fr0
|
mffs fr0
|
||||||
stfd fr0,THREAD_FPSCR(r4)
|
stfd fr0,FPSTATE_FPSCR(r8)
|
||||||
PPC_LL r5,PT_REGS(r4)
|
PPC_LL r5,PT_REGS(r4)
|
||||||
toreal(r5)
|
toreal(r5)
|
||||||
PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
|
PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
|
||||||
|
@ -160,7 +125,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
|
||||||
#endif /* CONFIG_SMP */
|
#endif /* CONFIG_SMP */
|
||||||
/* enable use of FP after return */
|
/* enable use of FP after return */
|
||||||
#ifdef CONFIG_PPC32
|
#ifdef CONFIG_PPC32
|
||||||
mfspr r5,SPRN_SPRG_THREAD /* current task's THREAD (phys) */
|
mfspr r5,SPRN_SPRG_THREAD /* current task's THREAD (phys) */
|
||||||
lwz r4,THREAD_FPEXC_MODE(r5)
|
lwz r4,THREAD_FPEXC_MODE(r5)
|
||||||
ori r9,r9,MSR_FP /* enable FP for current */
|
ori r9,r9,MSR_FP /* enable FP for current */
|
||||||
or r9,r9,r4
|
or r9,r9,r4
|
||||||
|
@ -172,9 +137,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
|
||||||
or r12,r12,r4
|
or r12,r12,r4
|
||||||
std r12,_MSR(r1)
|
std r12,_MSR(r1)
|
||||||
#endif
|
#endif
|
||||||
lfd fr0,THREAD_FPSCR(r5)
|
addi r7,r5,THREAD_FPSTATE
|
||||||
|
lfd fr0,FPSTATE_FPSCR(r7)
|
||||||
MTFSF_L(fr0)
|
MTFSF_L(fr0)
|
||||||
REST_32FPVSRS(0, R4, R5)
|
REST_32FPVSRS(0, R4, R7)
|
||||||
#ifndef CONFIG_SMP
|
#ifndef CONFIG_SMP
|
||||||
subi r4,r5,THREAD
|
subi r4,r5,THREAD
|
||||||
fromreal(r4)
|
fromreal(r4)
|
||||||
|
@ -208,9 +174,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
|
||||||
addi r3,r3,THREAD /* want THREAD of task */
|
addi r3,r3,THREAD /* want THREAD of task */
|
||||||
PPC_LL r5,PT_REGS(r3)
|
PPC_LL r5,PT_REGS(r3)
|
||||||
PPC_LCMPI 0,r5,0
|
PPC_LCMPI 0,r5,0
|
||||||
SAVE_32FPVSRS(0, R4 ,R3)
|
addi r6,r3,THREAD_FPSTATE
|
||||||
|
SAVE_32FPVSRS(0, R4, R6)
|
||||||
mffs fr0
|
mffs fr0
|
||||||
stfd fr0,THREAD_FPSCR(r3)
|
stfd fr0,FPSTATE_FPSCR(r6)
|
||||||
beq 1f
|
beq 1f
|
||||||
PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
|
PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
|
||||||
li r3,MSR_FP|MSR_FE0|MSR_FE1
|
li r3,MSR_FP|MSR_FE0|MSR_FE1
|
||||||
|
|
|
@ -1113,12 +1113,10 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
|
||||||
#ifdef CONFIG_VSX
|
#ifdef CONFIG_VSX
|
||||||
current->thread.used_vsr = 0;
|
current->thread.used_vsr = 0;
|
||||||
#endif
|
#endif
|
||||||
memset(current->thread.fpr, 0, sizeof(current->thread.fpr));
|
memset(¤t->thread.fp_state, 0, sizeof(current->thread.fp_state));
|
||||||
current->thread.fpscr.val = 0;
|
|
||||||
#ifdef CONFIG_ALTIVEC
|
#ifdef CONFIG_ALTIVEC
|
||||||
memset(current->thread.vr, 0, sizeof(current->thread.vr));
|
memset(¤t->thread.vr_state, 0, sizeof(current->thread.vr_state));
|
||||||
memset(¤t->thread.vscr, 0, sizeof(current->thread.vscr));
|
current->thread.vr_state.vscr.u[3] = 0x00010000; /* Java mode disabled */
|
||||||
current->thread.vscr.u[3] = 0x00010000; /* Java mode disabled */
|
|
||||||
current->thread.vrsave = 0;
|
current->thread.vrsave = 0;
|
||||||
current->thread.used_vr = 0;
|
current->thread.used_vr = 0;
|
||||||
#endif /* CONFIG_ALTIVEC */
|
#endif /* CONFIG_ALTIVEC */
|
||||||
|
|
|
@ -362,7 +362,7 @@ static int fpr_get(struct task_struct *target, const struct user_regset *regset,
|
||||||
void *kbuf, void __user *ubuf)
|
void *kbuf, void __user *ubuf)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_VSX
|
#ifdef CONFIG_VSX
|
||||||
double buf[33];
|
u64 buf[33];
|
||||||
int i;
|
int i;
|
||||||
#endif
|
#endif
|
||||||
flush_fp_to_thread(target);
|
flush_fp_to_thread(target);
|
||||||
|
@ -371,15 +371,15 @@ static int fpr_get(struct task_struct *target, const struct user_regset *regset,
|
||||||
/* copy to local buffer then write that out */
|
/* copy to local buffer then write that out */
|
||||||
for (i = 0; i < 32 ; i++)
|
for (i = 0; i < 32 ; i++)
|
||||||
buf[i] = target->thread.TS_FPR(i);
|
buf[i] = target->thread.TS_FPR(i);
|
||||||
memcpy(&buf[32], &target->thread.fpscr, sizeof(double));
|
buf[32] = target->thread.fp_state.fpscr;
|
||||||
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
|
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
BUILD_BUG_ON(offsetof(struct thread_struct, fpscr) !=
|
BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
|
||||||
offsetof(struct thread_struct, TS_FPR(32)));
|
offsetof(struct thread_fp_state, fpr[32][0]));
|
||||||
|
|
||||||
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||||
&target->thread.fpr, 0, -1);
|
&target->thread.fp_state, 0, -1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset,
|
||||||
const void *kbuf, const void __user *ubuf)
|
const void *kbuf, const void __user *ubuf)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_VSX
|
#ifdef CONFIG_VSX
|
||||||
double buf[33];
|
u64 buf[33];
|
||||||
int i;
|
int i;
|
||||||
#endif
|
#endif
|
||||||
flush_fp_to_thread(target);
|
flush_fp_to_thread(target);
|
||||||
|
@ -400,14 +400,14 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset,
|
||||||
return i;
|
return i;
|
||||||
for (i = 0; i < 32 ; i++)
|
for (i = 0; i < 32 ; i++)
|
||||||
target->thread.TS_FPR(i) = buf[i];
|
target->thread.TS_FPR(i) = buf[i];
|
||||||
memcpy(&target->thread.fpscr, &buf[32], sizeof(double));
|
target->thread.fp_state.fpscr = buf[32];
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
BUILD_BUG_ON(offsetof(struct thread_struct, fpscr) !=
|
BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
|
||||||
offsetof(struct thread_struct, TS_FPR(32)));
|
offsetof(struct thread_fp_state, fpr[32][0]));
|
||||||
|
|
||||||
return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||||
&target->thread.fpr, 0, -1);
|
&target->thread.fp_state, 0, -1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,11 +440,11 @@ static int vr_get(struct task_struct *target, const struct user_regset *regset,
|
||||||
|
|
||||||
flush_altivec_to_thread(target);
|
flush_altivec_to_thread(target);
|
||||||
|
|
||||||
BUILD_BUG_ON(offsetof(struct thread_struct, vscr) !=
|
BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
|
||||||
offsetof(struct thread_struct, vr[32]));
|
offsetof(struct thread_vr_state, vr[32]));
|
||||||
|
|
||||||
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||||
&target->thread.vr, 0,
|
&target->thread.vr_state, 0,
|
||||||
33 * sizeof(vector128));
|
33 * sizeof(vector128));
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
/*
|
/*
|
||||||
|
@ -471,11 +471,12 @@ static int vr_set(struct task_struct *target, const struct user_regset *regset,
|
||||||
|
|
||||||
flush_altivec_to_thread(target);
|
flush_altivec_to_thread(target);
|
||||||
|
|
||||||
BUILD_BUG_ON(offsetof(struct thread_struct, vscr) !=
|
BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
|
||||||
offsetof(struct thread_struct, vr[32]));
|
offsetof(struct thread_vr_state, vr[32]));
|
||||||
|
|
||||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||||
&target->thread.vr, 0, 33 * sizeof(vector128));
|
&target->thread.vr_state, 0,
|
||||||
|
33 * sizeof(vector128));
|
||||||
if (!ret && count > 0) {
|
if (!ret && count > 0) {
|
||||||
/*
|
/*
|
||||||
* We use only the first word of vrsave.
|
* We use only the first word of vrsave.
|
||||||
|
@ -514,13 +515,13 @@ static int vsr_get(struct task_struct *target, const struct user_regset *regset,
|
||||||
unsigned int pos, unsigned int count,
|
unsigned int pos, unsigned int count,
|
||||||
void *kbuf, void __user *ubuf)
|
void *kbuf, void __user *ubuf)
|
||||||
{
|
{
|
||||||
double buf[32];
|
u64 buf[32];
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
flush_vsx_to_thread(target);
|
flush_vsx_to_thread(target);
|
||||||
|
|
||||||
for (i = 0; i < 32 ; i++)
|
for (i = 0; i < 32 ; i++)
|
||||||
buf[i] = target->thread.fpr[i][TS_VSRLOWOFFSET];
|
buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
|
||||||
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||||
buf, 0, 32 * sizeof(double));
|
buf, 0, 32 * sizeof(double));
|
||||||
|
|
||||||
|
@ -531,7 +532,7 @@ static int vsr_set(struct task_struct *target, const struct user_regset *regset,
|
||||||
unsigned int pos, unsigned int count,
|
unsigned int pos, unsigned int count,
|
||||||
const void *kbuf, const void __user *ubuf)
|
const void *kbuf, const void __user *ubuf)
|
||||||
{
|
{
|
||||||
double buf[32];
|
u64 buf[32];
|
||||||
int ret,i;
|
int ret,i;
|
||||||
|
|
||||||
flush_vsx_to_thread(target);
|
flush_vsx_to_thread(target);
|
||||||
|
@ -539,7 +540,7 @@ static int vsr_set(struct task_struct *target, const struct user_regset *regset,
|
||||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||||
buf, 0, 32 * sizeof(double));
|
buf, 0, 32 * sizeof(double));
|
||||||
for (i = 0; i < 32 ; i++)
|
for (i = 0; i < 32 ; i++)
|
||||||
target->thread.fpr[i][TS_VSRLOWOFFSET] = buf[i];
|
target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
|
||||||
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1554,10 +1555,10 @@ long arch_ptrace(struct task_struct *child, long request,
|
||||||
|
|
||||||
flush_fp_to_thread(child);
|
flush_fp_to_thread(child);
|
||||||
if (fpidx < (PT_FPSCR - PT_FPR0))
|
if (fpidx < (PT_FPSCR - PT_FPR0))
|
||||||
tmp = ((unsigned long *)child->thread.fpr)
|
tmp = ((unsigned long *)child->thread.fp_state.fpr)
|
||||||
[fpidx * TS_FPRWIDTH];
|
[fpidx * TS_FPRWIDTH];
|
||||||
else
|
else
|
||||||
tmp = child->thread.fpscr.val;
|
tmp = child->thread.fp_state.fpscr;
|
||||||
}
|
}
|
||||||
ret = put_user(tmp, datalp);
|
ret = put_user(tmp, datalp);
|
||||||
break;
|
break;
|
||||||
|
@ -1587,10 +1588,10 @@ long arch_ptrace(struct task_struct *child, long request,
|
||||||
|
|
||||||
flush_fp_to_thread(child);
|
flush_fp_to_thread(child);
|
||||||
if (fpidx < (PT_FPSCR - PT_FPR0))
|
if (fpidx < (PT_FPSCR - PT_FPR0))
|
||||||
((unsigned long *)child->thread.fpr)
|
((unsigned long *)child->thread.fp_state.fpr)
|
||||||
[fpidx * TS_FPRWIDTH] = data;
|
[fpidx * TS_FPRWIDTH] = data;
|
||||||
else
|
else
|
||||||
child->thread.fpscr.val = data;
|
child->thread.fp_state.fpscr = data;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -43,7 +43,6 @@
|
||||||
#define FPRNUMBER(i) (((i) - PT_FPR0) >> 1)
|
#define FPRNUMBER(i) (((i) - PT_FPR0) >> 1)
|
||||||
#define FPRHALF(i) (((i) - PT_FPR0) & 1)
|
#define FPRHALF(i) (((i) - PT_FPR0) & 1)
|
||||||
#define FPRINDEX(i) TS_FPRWIDTH * FPRNUMBER(i) * 2 + FPRHALF(i)
|
#define FPRINDEX(i) TS_FPRWIDTH * FPRNUMBER(i) * 2 + FPRHALF(i)
|
||||||
#define FPRINDEX_3264(i) (TS_FPRWIDTH * ((i) - PT_FPR0))
|
|
||||||
|
|
||||||
long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
||||||
compat_ulong_t caddr, compat_ulong_t cdata)
|
compat_ulong_t caddr, compat_ulong_t cdata)
|
||||||
|
@ -105,7 +104,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
||||||
* to be an array of unsigned int (32 bits) - the
|
* to be an array of unsigned int (32 bits) - the
|
||||||
* index passed in is based on this assumption.
|
* index passed in is based on this assumption.
|
||||||
*/
|
*/
|
||||||
tmp = ((unsigned int *)child->thread.fpr)
|
tmp = ((unsigned int *)child->thread.fp_state.fpr)
|
||||||
[FPRINDEX(index)];
|
[FPRINDEX(index)];
|
||||||
}
|
}
|
||||||
ret = put_user((unsigned int)tmp, (u32 __user *)data);
|
ret = put_user((unsigned int)tmp, (u32 __user *)data);
|
||||||
|
@ -147,8 +146,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
||||||
if (numReg >= PT_FPR0) {
|
if (numReg >= PT_FPR0) {
|
||||||
flush_fp_to_thread(child);
|
flush_fp_to_thread(child);
|
||||||
/* get 64 bit FPR */
|
/* get 64 bit FPR */
|
||||||
tmp = ((u64 *)child->thread.fpr)
|
tmp = child->thread.fp_state.fpr[numReg - PT_FPR0][0];
|
||||||
[FPRINDEX_3264(numReg)];
|
|
||||||
} else { /* register within PT_REGS struct */
|
} else { /* register within PT_REGS struct */
|
||||||
unsigned long tmp2;
|
unsigned long tmp2;
|
||||||
ret = ptrace_get_reg(child, numReg, &tmp2);
|
ret = ptrace_get_reg(child, numReg, &tmp2);
|
||||||
|
@ -207,7 +205,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
||||||
* to be an array of unsigned int (32 bits) - the
|
* to be an array of unsigned int (32 bits) - the
|
||||||
* index passed in is based on this assumption.
|
* index passed in is based on this assumption.
|
||||||
*/
|
*/
|
||||||
((unsigned int *)child->thread.fpr)
|
((unsigned int *)child->thread.fp_state.fpr)
|
||||||
[FPRINDEX(index)] = data;
|
[FPRINDEX(index)] = data;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
@ -251,8 +249,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
||||||
u64 *tmp;
|
u64 *tmp;
|
||||||
flush_fp_to_thread(child);
|
flush_fp_to_thread(child);
|
||||||
/* get 64 bit FPR ... */
|
/* get 64 bit FPR ... */
|
||||||
tmp = &(((u64 *)child->thread.fpr)
|
tmp = &child->thread.fp_state.fpr[numReg - PT_FPR0][0];
|
||||||
[FPRINDEX_3264(numReg)]);
|
|
||||||
/* ... write the 32 bit part we want */
|
/* ... write the 32 bit part we want */
|
||||||
((u32 *)tmp)[index % 2] = data;
|
((u32 *)tmp)[index % 2] = data;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
|
@ -265,27 +265,27 @@ struct rt_sigframe {
|
||||||
unsigned long copy_fpr_to_user(void __user *to,
|
unsigned long copy_fpr_to_user(void __user *to,
|
||||||
struct task_struct *task)
|
struct task_struct *task)
|
||||||
{
|
{
|
||||||
double buf[ELF_NFPREG];
|
u64 buf[ELF_NFPREG];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* save FPR copy to local buffer then write to the thread_struct */
|
/* save FPR copy to local buffer then write to the thread_struct */
|
||||||
for (i = 0; i < (ELF_NFPREG - 1) ; i++)
|
for (i = 0; i < (ELF_NFPREG - 1) ; i++)
|
||||||
buf[i] = task->thread.TS_FPR(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));
|
return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long copy_fpr_from_user(struct task_struct *task,
|
unsigned long copy_fpr_from_user(struct task_struct *task,
|
||||||
void __user *from)
|
void __user *from)
|
||||||
{
|
{
|
||||||
double buf[ELF_NFPREG];
|
u64 buf[ELF_NFPREG];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double)))
|
if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double)))
|
||||||
return 1;
|
return 1;
|
||||||
for (i = 0; i < (ELF_NFPREG - 1) ; i++)
|
for (i = 0; i < (ELF_NFPREG - 1) ; i++)
|
||||||
task->thread.TS_FPR(i) = buf[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;
|
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,
|
unsigned long copy_vsx_to_user(void __user *to,
|
||||||
struct task_struct *task)
|
struct task_struct *task)
|
||||||
{
|
{
|
||||||
double buf[ELF_NVSRHALFREG];
|
u64 buf[ELF_NVSRHALFREG];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* save FPR copy to local buffer then write to the thread_struct */
|
/* save FPR copy to local buffer then write to the thread_struct */
|
||||||
for (i = 0; i < ELF_NVSRHALFREG; i++)
|
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));
|
return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long copy_vsx_from_user(struct task_struct *task,
|
unsigned long copy_vsx_from_user(struct task_struct *task,
|
||||||
void __user *from)
|
void __user *from)
|
||||||
{
|
{
|
||||||
double buf[ELF_NVSRHALFREG];
|
u64 buf[ELF_NVSRHALFREG];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double)))
|
if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double)))
|
||||||
return 1;
|
return 1;
|
||||||
for (i = 0; i < ELF_NVSRHALFREG ; i++)
|
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;
|
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,
|
unsigned long copy_transact_fpr_to_user(void __user *to,
|
||||||
struct task_struct *task)
|
struct task_struct *task)
|
||||||
{
|
{
|
||||||
double buf[ELF_NFPREG];
|
u64 buf[ELF_NFPREG];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* save FPR copy to local buffer then write to the thread_struct */
|
/* save FPR copy to local buffer then write to the thread_struct */
|
||||||
for (i = 0; i < (ELF_NFPREG - 1) ; i++)
|
for (i = 0; i < (ELF_NFPREG - 1) ; i++)
|
||||||
buf[i] = task->thread.TS_TRANS_FPR(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));
|
return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long copy_transact_fpr_from_user(struct task_struct *task,
|
unsigned long copy_transact_fpr_from_user(struct task_struct *task,
|
||||||
void __user *from)
|
void __user *from)
|
||||||
{
|
{
|
||||||
double buf[ELF_NFPREG];
|
u64 buf[ELF_NFPREG];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double)))
|
if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double)))
|
||||||
return 1;
|
return 1;
|
||||||
for (i = 0; i < (ELF_NFPREG - 1) ; i++)
|
for (i = 0; i < (ELF_NFPREG - 1) ; i++)
|
||||||
task->thread.TS_TRANS_FPR(i) = buf[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;
|
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,
|
unsigned long copy_transact_vsx_to_user(void __user *to,
|
||||||
struct task_struct *task)
|
struct task_struct *task)
|
||||||
{
|
{
|
||||||
double buf[ELF_NVSRHALFREG];
|
u64 buf[ELF_NVSRHALFREG];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* save FPR copy to local buffer then write to the thread_struct */
|
/* save FPR copy to local buffer then write to the thread_struct */
|
||||||
for (i = 0; i < ELF_NVSRHALFREG; i++)
|
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));
|
return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long copy_transact_vsx_from_user(struct task_struct *task,
|
unsigned long copy_transact_vsx_from_user(struct task_struct *task,
|
||||||
void __user *from)
|
void __user *from)
|
||||||
{
|
{
|
||||||
double buf[ELF_NVSRHALFREG];
|
u64 buf[ELF_NVSRHALFREG];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double)))
|
if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double)))
|
||||||
return 1;
|
return 1;
|
||||||
for (i = 0; i < ELF_NVSRHALFREG ; i++)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
|
#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,
|
inline unsigned long copy_fpr_to_user(void __user *to,
|
||||||
struct task_struct *task)
|
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));
|
ELF_NFPREG * sizeof(double));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned long copy_fpr_from_user(struct task_struct *task,
|
inline unsigned long copy_fpr_from_user(struct task_struct *task,
|
||||||
void __user *from)
|
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));
|
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,
|
inline unsigned long copy_transact_fpr_to_user(void __user *to,
|
||||||
struct task_struct *task)
|
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));
|
ELF_NFPREG * sizeof(double));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned long copy_transact_fpr_from_user(struct task_struct *task,
|
inline unsigned long copy_transact_fpr_from_user(struct task_struct *task,
|
||||||
void __user *from)
|
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));
|
ELF_NFPREG * sizeof(double));
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
|
#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 */
|
/* save altivec registers */
|
||||||
if (current->thread.used_vr) {
|
if (current->thread.used_vr) {
|
||||||
flush_altivec_to_thread(current);
|
flush_altivec_to_thread(current);
|
||||||
if (__copy_to_user(&frame->mc_vregs, current->thread.vr,
|
if (__copy_to_user(&frame->mc_vregs, ¤t->thread.vr_state,
|
||||||
ELF_NVRREG * sizeof(vector128)))
|
ELF_NVRREG * sizeof(vector128)))
|
||||||
return 1;
|
return 1;
|
||||||
/* set MSR_VEC in the saved MSR value to indicate that
|
/* 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 */
|
/* save altivec registers */
|
||||||
if (current->thread.used_vr) {
|
if (current->thread.used_vr) {
|
||||||
flush_altivec_to_thread(current);
|
flush_altivec_to_thread(current);
|
||||||
if (__copy_to_user(&frame->mc_vregs, current->thread.vr,
|
if (__copy_to_user(&frame->mc_vregs, ¤t->thread.vr_state,
|
||||||
ELF_NVRREG * sizeof(vector128)))
|
ELF_NVRREG * sizeof(vector128)))
|
||||||
return 1;
|
return 1;
|
||||||
if (msr & MSR_VEC) {
|
if (msr & MSR_VEC) {
|
||||||
if (__copy_to_user(&tm_frame->mc_vregs,
|
if (__copy_to_user(&tm_frame->mc_vregs,
|
||||||
current->thread.transact_vr,
|
¤t->thread.transact_vr,
|
||||||
ELF_NVRREG * sizeof(vector128)))
|
ELF_NVRREG * sizeof(vector128)))
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
if (__copy_to_user(&tm_frame->mc_vregs,
|
if (__copy_to_user(&tm_frame->mc_vregs,
|
||||||
current->thread.vr,
|
¤t->thread.vr_state,
|
||||||
ELF_NVRREG * sizeof(vector128)))
|
ELF_NVRREG * sizeof(vector128)))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -692,11 +692,12 @@ static long restore_user_regs(struct pt_regs *regs,
|
||||||
regs->msr &= ~MSR_VEC;
|
regs->msr &= ~MSR_VEC;
|
||||||
if (msr & MSR_VEC) {
|
if (msr & MSR_VEC) {
|
||||||
/* restore altivec registers from the stack */
|
/* restore altivec registers from the stack */
|
||||||
if (__copy_from_user(current->thread.vr, &sr->mc_vregs,
|
if (__copy_from_user(¤t->thread.vr_state, &sr->mc_vregs,
|
||||||
sizeof(sr->mc_vregs)))
|
sizeof(sr->mc_vregs)))
|
||||||
return 1;
|
return 1;
|
||||||
} else if (current->thread.used_vr)
|
} else if (current->thread.used_vr)
|
||||||
memset(current->thread.vr, 0, ELF_NVRREG * sizeof(vector128));
|
memset(¤t->thread.vr_state, 0,
|
||||||
|
ELF_NVRREG * sizeof(vector128));
|
||||||
|
|
||||||
/* Always get VRSAVE back */
|
/* Always get VRSAVE back */
|
||||||
if (__get_user(current->thread.vrsave, (u32 __user *)&sr->mc_vregs[32]))
|
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;
|
return 1;
|
||||||
} else if (current->thread.used_vsr)
|
} else if (current->thread.used_vsr)
|
||||||
for (i = 0; i < 32 ; i++)
|
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 */
|
#endif /* CONFIG_VSX */
|
||||||
/*
|
/*
|
||||||
* force the process to reload the FP registers from
|
* 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;
|
regs->msr &= ~MSR_VEC;
|
||||||
if (msr & MSR_VEC) {
|
if (msr & MSR_VEC) {
|
||||||
/* restore altivec registers from the stack */
|
/* restore altivec registers from the stack */
|
||||||
if (__copy_from_user(current->thread.vr, &sr->mc_vregs,
|
if (__copy_from_user(¤t->thread.vr_state, &sr->mc_vregs,
|
||||||
sizeof(sr->mc_vregs)) ||
|
sizeof(sr->mc_vregs)) ||
|
||||||
__copy_from_user(current->thread.transact_vr,
|
__copy_from_user(¤t->thread.transact_vr,
|
||||||
&tm_sr->mc_vregs,
|
&tm_sr->mc_vregs,
|
||||||
sizeof(sr->mc_vregs)))
|
sizeof(sr->mc_vregs)))
|
||||||
return 1;
|
return 1;
|
||||||
} else if (current->thread.used_vr) {
|
} else if (current->thread.used_vr) {
|
||||||
memset(current->thread.vr, 0, ELF_NVRREG * sizeof(vector128));
|
memset(¤t->thread.vr_state, 0,
|
||||||
memset(current->thread.transact_vr, 0,
|
ELF_NVRREG * sizeof(vector128));
|
||||||
|
memset(¤t->thread.transact_vr, 0,
|
||||||
ELF_NVRREG * sizeof(vector128));
|
ELF_NVRREG * sizeof(vector128));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -838,8 +840,8 @@ static long restore_tm_user_regs(struct pt_regs *regs,
|
||||||
return 1;
|
return 1;
|
||||||
} else if (current->thread.used_vsr)
|
} else if (current->thread.used_vsr)
|
||||||
for (i = 0; i < 32 ; i++) {
|
for (i = 0; i < 32 ; i++) {
|
||||||
current->thread.fpr[i][TS_VSRLOWOFFSET] = 0;
|
current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0;
|
||||||
current->thread.transact_fpr[i][TS_VSRLOWOFFSET] = 0;
|
current->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET] = 0;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_VSX */
|
#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))
|
if (__put_user(0, &rt_sf->uc.uc_link))
|
||||||
goto badframe;
|
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 */
|
/* create a stack frame for the caller of the handler */
|
||||||
newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16);
|
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;
|
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 */
|
/* create a stack frame for the caller of the handler */
|
||||||
newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
|
newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
|
||||||
|
|
|
@ -103,7 +103,8 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
|
||||||
if (current->thread.used_vr) {
|
if (current->thread.used_vr) {
|
||||||
flush_altivec_to_thread(current);
|
flush_altivec_to_thread(current);
|
||||||
/* Copy 33 vec registers (vr0..31 and vscr) to the stack */
|
/* Copy 33 vec registers (vr0..31 and vscr) to the stack */
|
||||||
err |= __copy_to_user(v_regs, current->thread.vr, 33 * sizeof(vector128));
|
err |= __copy_to_user(v_regs, ¤t->thread.vr_state,
|
||||||
|
33 * sizeof(vector128));
|
||||||
/* set MSR_VEC in the MSR value in the frame to indicate that sc->v_reg)
|
/* set MSR_VEC in the MSR value in the frame to indicate that sc->v_reg)
|
||||||
* contains valid data.
|
* contains valid data.
|
||||||
*/
|
*/
|
||||||
|
@ -195,18 +196,18 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc,
|
||||||
if (current->thread.used_vr) {
|
if (current->thread.used_vr) {
|
||||||
flush_altivec_to_thread(current);
|
flush_altivec_to_thread(current);
|
||||||
/* Copy 33 vec registers (vr0..31 and vscr) to the stack */
|
/* Copy 33 vec registers (vr0..31 and vscr) to the stack */
|
||||||
err |= __copy_to_user(v_regs, current->thread.vr,
|
err |= __copy_to_user(v_regs, ¤t->thread.vr_state,
|
||||||
33 * sizeof(vector128));
|
33 * sizeof(vector128));
|
||||||
/* If VEC was enabled there are transactional VRs valid too,
|
/* If VEC was enabled there are transactional VRs valid too,
|
||||||
* else they're a copy of the checkpointed VRs.
|
* else they're a copy of the checkpointed VRs.
|
||||||
*/
|
*/
|
||||||
if (msr & MSR_VEC)
|
if (msr & MSR_VEC)
|
||||||
err |= __copy_to_user(tm_v_regs,
|
err |= __copy_to_user(tm_v_regs,
|
||||||
current->thread.transact_vr,
|
¤t->thread.transact_vr,
|
||||||
33 * sizeof(vector128));
|
33 * sizeof(vector128));
|
||||||
else
|
else
|
||||||
err |= __copy_to_user(tm_v_regs,
|
err |= __copy_to_user(tm_v_regs,
|
||||||
current->thread.vr,
|
¤t->thread.vr_state,
|
||||||
33 * sizeof(vector128));
|
33 * sizeof(vector128));
|
||||||
|
|
||||||
/* set MSR_VEC in the MSR value in the frame to indicate
|
/* set MSR_VEC in the MSR value in the frame to indicate
|
||||||
|
@ -349,10 +350,10 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
/* Copy 33 vec registers (vr0..31 and vscr) from the stack */
|
/* Copy 33 vec registers (vr0..31 and vscr) from the stack */
|
||||||
if (v_regs != NULL && (msr & MSR_VEC) != 0)
|
if (v_regs != NULL && (msr & MSR_VEC) != 0)
|
||||||
err |= __copy_from_user(current->thread.vr, v_regs,
|
err |= __copy_from_user(¤t->thread.vr_state, v_regs,
|
||||||
33 * sizeof(vector128));
|
33 * sizeof(vector128));
|
||||||
else if (current->thread.used_vr)
|
else if (current->thread.used_vr)
|
||||||
memset(current->thread.vr, 0, 33 * sizeof(vector128));
|
memset(¤t->thread.vr_state, 0, 33 * sizeof(vector128));
|
||||||
/* Always get VRSAVE back */
|
/* Always get VRSAVE back */
|
||||||
if (v_regs != NULL)
|
if (v_regs != NULL)
|
||||||
err |= __get_user(current->thread.vrsave, (u32 __user *)&v_regs[33]);
|
err |= __get_user(current->thread.vrsave, (u32 __user *)&v_regs[33]);
|
||||||
|
@ -374,7 +375,7 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
|
||||||
err |= copy_vsx_from_user(current, v_regs);
|
err |= copy_vsx_from_user(current, v_regs);
|
||||||
else
|
else
|
||||||
for (i = 0; i < 32 ; i++)
|
for (i = 0; i < 32 ; i++)
|
||||||
current->thread.fpr[i][TS_VSRLOWOFFSET] = 0;
|
current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0;
|
||||||
#endif
|
#endif
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -468,14 +469,14 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
/* Copy 33 vec registers (vr0..31 and vscr) from the stack */
|
/* Copy 33 vec registers (vr0..31 and vscr) from the stack */
|
||||||
if (v_regs != NULL && tm_v_regs != NULL && (msr & MSR_VEC) != 0) {
|
if (v_regs != NULL && tm_v_regs != NULL && (msr & MSR_VEC) != 0) {
|
||||||
err |= __copy_from_user(current->thread.vr, v_regs,
|
err |= __copy_from_user(¤t->thread.vr_state, v_regs,
|
||||||
33 * sizeof(vector128));
|
33 * sizeof(vector128));
|
||||||
err |= __copy_from_user(current->thread.transact_vr, tm_v_regs,
|
err |= __copy_from_user(¤t->thread.transact_vr, tm_v_regs,
|
||||||
33 * sizeof(vector128));
|
33 * sizeof(vector128));
|
||||||
}
|
}
|
||||||
else if (current->thread.used_vr) {
|
else if (current->thread.used_vr) {
|
||||||
memset(current->thread.vr, 0, 33 * sizeof(vector128));
|
memset(¤t->thread.vr_state, 0, 33 * sizeof(vector128));
|
||||||
memset(current->thread.transact_vr, 0, 33 * sizeof(vector128));
|
memset(¤t->thread.transact_vr, 0, 33 * sizeof(vector128));
|
||||||
}
|
}
|
||||||
/* Always get VRSAVE back */
|
/* Always get VRSAVE back */
|
||||||
if (v_regs != NULL && tm_v_regs != NULL) {
|
if (v_regs != NULL && tm_v_regs != NULL) {
|
||||||
|
@ -507,8 +508,8 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
|
||||||
err |= copy_transact_vsx_from_user(current, tm_v_regs);
|
err |= copy_transact_vsx_from_user(current, tm_v_regs);
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < 32 ; i++) {
|
for (i = 0; i < 32 ; i++) {
|
||||||
current->thread.fpr[i][TS_VSRLOWOFFSET] = 0;
|
current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0;
|
||||||
current->thread.transact_fpr[i][TS_VSRLOWOFFSET] = 0;
|
current->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -747,7 +748,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
|
||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
/* Make sure signal handler doesn't get spurious FP exceptions */
|
/* Make sure signal handler doesn't get spurious FP exceptions */
|
||||||
current->thread.fpscr.val = 0;
|
current->thread.fp_state.fpscr = 0;
|
||||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||||
/* Remove TM bits from thread's MSR. The MSR in the sigcontext
|
/* Remove TM bits from thread's MSR. The MSR in the sigcontext
|
||||||
* just indicates to userland that we were doing a transaction, but we
|
* just indicates to userland that we were doing a transaction, but we
|
||||||
|
|
|
@ -12,16 +12,15 @@
|
||||||
#include <asm/reg.h>
|
#include <asm/reg.h>
|
||||||
|
|
||||||
#ifdef CONFIG_VSX
|
#ifdef CONFIG_VSX
|
||||||
/* See fpu.S, this is very similar but to save/restore checkpointed FPRs/VSRs */
|
/* See fpu.S, this is borrowed from there */
|
||||||
#define __SAVE_32FPRS_VSRS_TRANSACT(n,c,base) \
|
#define __SAVE_32FPRS_VSRS(n,c,base) \
|
||||||
BEGIN_FTR_SECTION \
|
BEGIN_FTR_SECTION \
|
||||||
b 2f; \
|
b 2f; \
|
||||||
END_FTR_SECTION_IFSET(CPU_FTR_VSX); \
|
END_FTR_SECTION_IFSET(CPU_FTR_VSX); \
|
||||||
SAVE_32FPRS_TRANSACT(n,base); \
|
SAVE_32FPRS(n,base); \
|
||||||
b 3f; \
|
b 3f; \
|
||||||
2: SAVE_32VSRS_TRANSACT(n,c,base); \
|
2: SAVE_32VSRS(n,c,base); \
|
||||||
3:
|
3:
|
||||||
/* ...and this is just plain borrowed from there. */
|
|
||||||
#define __REST_32FPRS_VSRS(n,c,base) \
|
#define __REST_32FPRS_VSRS(n,c,base) \
|
||||||
BEGIN_FTR_SECTION \
|
BEGIN_FTR_SECTION \
|
||||||
b 2f; \
|
b 2f; \
|
||||||
|
@ -31,11 +30,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX); \
|
||||||
2: REST_32VSRS(n,c,base); \
|
2: REST_32VSRS(n,c,base); \
|
||||||
3:
|
3:
|
||||||
#else
|
#else
|
||||||
#define __SAVE_32FPRS_VSRS_TRANSACT(n,c,base) SAVE_32FPRS_TRANSACT(n, base)
|
#define __SAVE_32FPRS_VSRS(n,c,base) SAVE_32FPRS(n, base)
|
||||||
#define __REST_32FPRS_VSRS(n,c,base) REST_32FPRS(n, base)
|
#define __REST_32FPRS_VSRS(n,c,base) REST_32FPRS(n, base)
|
||||||
#endif
|
#endif
|
||||||
#define SAVE_32FPRS_VSRS_TRANSACT(n,c,base) \
|
#define SAVE_32FPRS_VSRS(n,c,base) \
|
||||||
__SAVE_32FPRS_VSRS_TRANSACT(n,__REG_##c,__REG_##base)
|
__SAVE_32FPRS_VSRS(n,__REG_##c,__REG_##base)
|
||||||
#define REST_32FPRS_VSRS(n,c,base) \
|
#define REST_32FPRS_VSRS(n,c,base) \
|
||||||
__REST_32FPRS_VSRS(n,__REG_##c,__REG_##base)
|
__REST_32FPRS_VSRS(n,__REG_##c,__REG_##base)
|
||||||
|
|
||||||
|
@ -157,10 +156,11 @@ _GLOBAL(tm_reclaim)
|
||||||
andis. r0, r4, MSR_VEC@h
|
andis. r0, r4, MSR_VEC@h
|
||||||
beq dont_backup_vec
|
beq dont_backup_vec
|
||||||
|
|
||||||
SAVE_32VRS_TRANSACT(0, r6, r3) /* r6 scratch, r3 thread */
|
addi r7, r3, THREAD_TRANSACT_VRSTATE
|
||||||
|
SAVE_32VRS(0, r6, r7) /* r6 scratch, r7 transact vr state */
|
||||||
mfvscr vr0
|
mfvscr vr0
|
||||||
li r6, THREAD_TRANSACT_VSCR
|
li r6, VRSTATE_VSCR
|
||||||
stvx vr0, r3, r6
|
stvx vr0, r7, r6
|
||||||
dont_backup_vec:
|
dont_backup_vec:
|
||||||
mfspr r0, SPRN_VRSAVE
|
mfspr r0, SPRN_VRSAVE
|
||||||
std r0, THREAD_TRANSACT_VRSAVE(r3)
|
std r0, THREAD_TRANSACT_VRSAVE(r3)
|
||||||
|
@ -168,10 +168,11 @@ dont_backup_vec:
|
||||||
andi. r0, r4, MSR_FP
|
andi. r0, r4, MSR_FP
|
||||||
beq dont_backup_fp
|
beq dont_backup_fp
|
||||||
|
|
||||||
SAVE_32FPRS_VSRS_TRANSACT(0, R6, R3) /* r6 scratch, r3 thread */
|
addi r7, r3, THREAD_TRANSACT_FPSTATE
|
||||||
|
SAVE_32FPRS_VSRS(0, R6, R7) /* r6 scratch, r7 transact fp state */
|
||||||
|
|
||||||
mffs fr0
|
mffs fr0
|
||||||
stfd fr0,THREAD_TRANSACT_FPSCR(r3)
|
stfd fr0,FPSTATE_FPSCR(r7)
|
||||||
|
|
||||||
dont_backup_fp:
|
dont_backup_fp:
|
||||||
/* The moment we treclaim, ALL of our GPRs will switch
|
/* The moment we treclaim, ALL of our GPRs will switch
|
||||||
|
@ -358,10 +359,11 @@ _GLOBAL(tm_recheckpoint)
|
||||||
andis. r0, r4, MSR_VEC@h
|
andis. r0, r4, MSR_VEC@h
|
||||||
beq dont_restore_vec
|
beq dont_restore_vec
|
||||||
|
|
||||||
li r5, THREAD_VSCR
|
addi r8, r3, THREAD_VRSTATE
|
||||||
lvx vr0, r3, r5
|
li r5, VRSTATE_VSCR
|
||||||
|
lvx vr0, r8, r5
|
||||||
mtvscr vr0
|
mtvscr vr0
|
||||||
REST_32VRS(0, r5, r3) /* r5 scratch, r3 THREAD ptr */
|
REST_32VRS(0, r5, r8) /* r5 scratch, r8 ptr */
|
||||||
dont_restore_vec:
|
dont_restore_vec:
|
||||||
ld r5, THREAD_VRSAVE(r3)
|
ld r5, THREAD_VRSAVE(r3)
|
||||||
mtspr SPRN_VRSAVE, r5
|
mtspr SPRN_VRSAVE, r5
|
||||||
|
@ -370,9 +372,10 @@ dont_restore_vec:
|
||||||
andi. r0, r4, MSR_FP
|
andi. r0, r4, MSR_FP
|
||||||
beq dont_restore_fp
|
beq dont_restore_fp
|
||||||
|
|
||||||
lfd fr0, THREAD_FPSCR(r3)
|
addi r8, r3, THREAD_FPSTATE
|
||||||
|
lfd fr0, FPSTATE_FPSCR(r8)
|
||||||
MTFSF_L(fr0)
|
MTFSF_L(fr0)
|
||||||
REST_32FPRS_VSRS(0, R4, R3)
|
REST_32FPRS_VSRS(0, R4, R8)
|
||||||
|
|
||||||
dont_restore_fp:
|
dont_restore_fp:
|
||||||
mtmsr r6 /* FP/Vec off again! */
|
mtmsr r6 /* FP/Vec off again! */
|
||||||
|
|
|
@ -816,7 +816,7 @@ static void parse_fpe(struct pt_regs *regs)
|
||||||
|
|
||||||
flush_fp_to_thread(current);
|
flush_fp_to_thread(current);
|
||||||
|
|
||||||
code = __parse_fpscr(current->thread.fpscr.val);
|
code = __parse_fpscr(current->thread.fp_state.fpscr);
|
||||||
|
|
||||||
_exception(SIGFPE, regs, code, regs->nip);
|
_exception(SIGFPE, regs, code, regs->nip);
|
||||||
}
|
}
|
||||||
|
@ -1069,7 +1069,7 @@ static int emulate_math(struct pt_regs *regs)
|
||||||
return 0;
|
return 0;
|
||||||
case 1: {
|
case 1: {
|
||||||
int code = 0;
|
int code = 0;
|
||||||
code = __parse_fpscr(current->thread.fpscr.val);
|
code = __parse_fpscr(current->thread.fp_state.fpscr);
|
||||||
_exception(SIGFPE, regs, code, regs->nip);
|
_exception(SIGFPE, regs, code, regs->nip);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1371,8 +1371,6 @@ void facility_unavailable_exception(struct pt_regs *regs)
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||||
|
|
||||||
extern void do_load_up_fpu(struct pt_regs *regs);
|
|
||||||
|
|
||||||
void fp_unavailable_tm(struct pt_regs *regs)
|
void fp_unavailable_tm(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
/* Note: This does not handle any kind of FP laziness. */
|
/* Note: This does not handle any kind of FP laziness. */
|
||||||
|
@ -1403,8 +1401,6 @@ void fp_unavailable_tm(struct pt_regs *regs)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ALTIVEC
|
#ifdef CONFIG_ALTIVEC
|
||||||
extern void do_load_up_altivec(struct pt_regs *regs);
|
|
||||||
|
|
||||||
void altivec_unavailable_tm(struct pt_regs *regs)
|
void altivec_unavailable_tm(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
/* See the comments in fp_unavailable_tm(). This function operates
|
/* See the comments in fp_unavailable_tm(). This function operates
|
||||||
|
@ -1634,7 +1630,7 @@ void altivec_assist_exception(struct pt_regs *regs)
|
||||||
/* XXX quick hack for now: set the non-Java bit in the VSCR */
|
/* XXX quick hack for now: set the non-Java bit in the VSCR */
|
||||||
printk_ratelimited(KERN_ERR "Unrecognized altivec instruction "
|
printk_ratelimited(KERN_ERR "Unrecognized altivec instruction "
|
||||||
"in %s at %lx\n", current->comm, regs->nip);
|
"in %s at %lx\n", current->comm, regs->nip);
|
||||||
current->thread.vscr.u[3] |= 0x10000;
|
current->thread.vr_state.vscr.u[3] |= 0x10000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_ALTIVEC */
|
#endif /* CONFIG_ALTIVEC */
|
||||||
|
|
|
@ -271,7 +271,7 @@ int emulate_altivec(struct pt_regs *regs)
|
||||||
vb = (instr >> 11) & 0x1f;
|
vb = (instr >> 11) & 0x1f;
|
||||||
vc = (instr >> 6) & 0x1f;
|
vc = (instr >> 6) & 0x1f;
|
||||||
|
|
||||||
vrs = current->thread.vr;
|
vrs = current->thread.vr_state.vr;
|
||||||
switch (instr & 0x3f) {
|
switch (instr & 0x3f) {
|
||||||
case 10:
|
case 10:
|
||||||
switch (vc) {
|
switch (vc) {
|
||||||
|
@ -320,12 +320,12 @@ int emulate_altivec(struct pt_regs *regs)
|
||||||
case 14: /* vctuxs */
|
case 14: /* vctuxs */
|
||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
vrs[vd].u[i] = ctuxs(vrs[vb].u[i], va,
|
vrs[vd].u[i] = ctuxs(vrs[vb].u[i], va,
|
||||||
¤t->thread.vscr.u[3]);
|
¤t->thread.vr_state.vscr.u[3]);
|
||||||
break;
|
break;
|
||||||
case 15: /* vctsxs */
|
case 15: /* vctsxs */
|
||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
vrs[vd].u[i] = ctsxs(vrs[vb].u[i], va,
|
vrs[vd].u[i] = ctsxs(vrs[vb].u[i], va,
|
||||||
¤t->thread.vscr.u[3]);
|
¤t->thread.vr_state.vscr.u[3]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -8,29 +8,6 @@
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||||
/*
|
|
||||||
* Wrapper to call load_up_altivec from C.
|
|
||||||
* void do_load_up_altivec(struct pt_regs *regs);
|
|
||||||
*/
|
|
||||||
_GLOBAL(do_load_up_altivec)
|
|
||||||
mflr r0
|
|
||||||
std r0, 16(r1)
|
|
||||||
stdu r1, -112(r1)
|
|
||||||
|
|
||||||
subi r6, r3, STACK_FRAME_OVERHEAD
|
|
||||||
/* load_up_altivec expects r12=MSR, r13=PACA, and returns
|
|
||||||
* with r12 = new MSR.
|
|
||||||
*/
|
|
||||||
ld r12,_MSR(r6)
|
|
||||||
GET_PACA(r13)
|
|
||||||
bl load_up_altivec
|
|
||||||
std r12,_MSR(r6)
|
|
||||||
|
|
||||||
ld r0, 112+16(r1)
|
|
||||||
addi r1, r1, 112
|
|
||||||
mtlr r0
|
|
||||||
blr
|
|
||||||
|
|
||||||
/* void do_load_up_transact_altivec(struct thread_struct *thread)
|
/* void do_load_up_transact_altivec(struct thread_struct *thread)
|
||||||
*
|
*
|
||||||
* This is similar to load_up_altivec but for the transactional version of the
|
* This is similar to load_up_altivec but for the transactional version of the
|
||||||
|
@ -46,10 +23,11 @@ _GLOBAL(do_load_up_transact_altivec)
|
||||||
li r4,1
|
li r4,1
|
||||||
stw r4,THREAD_USED_VR(r3)
|
stw r4,THREAD_USED_VR(r3)
|
||||||
|
|
||||||
li r10,THREAD_TRANSACT_VSCR
|
li r10,THREAD_TRANSACT_VRSTATE+VRSTATE_VSCR
|
||||||
lvx vr0,r10,r3
|
lvx vr0,r10,r3
|
||||||
mtvscr vr0
|
mtvscr vr0
|
||||||
REST_32VRS_TRANSACT(0,r4,r3)
|
addi r10,r3,THREAD_TRANSACT_VRSTATE
|
||||||
|
REST_32VRS(0,r4,r10)
|
||||||
|
|
||||||
/* Disable VEC again. */
|
/* Disable VEC again. */
|
||||||
MTMSRD(r6)
|
MTMSRD(r6)
|
||||||
|
@ -59,7 +37,6 @@ _GLOBAL(do_load_up_transact_altivec)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* load_up_altivec(unused, unused, tsk)
|
|
||||||
* Disable VMX for the task which had it previously,
|
* Disable VMX for the task which had it previously,
|
||||||
* and save its vector registers in its thread_struct.
|
* and save its vector registers in its thread_struct.
|
||||||
* Enables the VMX for use in the kernel on return.
|
* Enables the VMX for use in the kernel on return.
|
||||||
|
@ -90,10 +67,11 @@ _GLOBAL(load_up_altivec)
|
||||||
/* Save VMX state to last_task_used_altivec's THREAD struct */
|
/* Save VMX state to last_task_used_altivec's THREAD struct */
|
||||||
toreal(r4)
|
toreal(r4)
|
||||||
addi r4,r4,THREAD
|
addi r4,r4,THREAD
|
||||||
SAVE_32VRS(0,r5,r4)
|
addi r7,r4,THREAD_VRSTATE
|
||||||
|
SAVE_32VRS(0,r5,r7)
|
||||||
mfvscr vr0
|
mfvscr vr0
|
||||||
li r10,THREAD_VSCR
|
li r10,VRSTATE_VSCR
|
||||||
stvx vr0,r10,r4
|
stvx vr0,r10,r7
|
||||||
/* Disable VMX for last_task_used_altivec */
|
/* Disable VMX for last_task_used_altivec */
|
||||||
PPC_LL r5,PT_REGS(r4)
|
PPC_LL r5,PT_REGS(r4)
|
||||||
toreal(r5)
|
toreal(r5)
|
||||||
|
@ -125,12 +103,13 @@ _GLOBAL(load_up_altivec)
|
||||||
oris r12,r12,MSR_VEC@h
|
oris r12,r12,MSR_VEC@h
|
||||||
std r12,_MSR(r1)
|
std r12,_MSR(r1)
|
||||||
#endif
|
#endif
|
||||||
|
addi r7,r5,THREAD_VRSTATE
|
||||||
li r4,1
|
li r4,1
|
||||||
li r10,THREAD_VSCR
|
li r10,VRSTATE_VSCR
|
||||||
stw r4,THREAD_USED_VR(r5)
|
stw r4,THREAD_USED_VR(r5)
|
||||||
lvx vr0,r10,r5
|
lvx vr0,r10,r7
|
||||||
mtvscr vr0
|
mtvscr vr0
|
||||||
REST_32VRS(0,r4,r5)
|
REST_32VRS(0,r4,r7)
|
||||||
#ifndef CONFIG_SMP
|
#ifndef CONFIG_SMP
|
||||||
/* Update last_task_used_altivec to 'current' */
|
/* Update last_task_used_altivec to 'current' */
|
||||||
subi r4,r5,THREAD /* Back to 'current' */
|
subi r4,r5,THREAD /* Back to 'current' */
|
||||||
|
@ -165,12 +144,13 @@ _GLOBAL(giveup_altivec)
|
||||||
PPC_LCMPI 0,r3,0
|
PPC_LCMPI 0,r3,0
|
||||||
beqlr /* if no previous owner, done */
|
beqlr /* if no previous owner, done */
|
||||||
addi r3,r3,THREAD /* want THREAD of task */
|
addi r3,r3,THREAD /* want THREAD of task */
|
||||||
|
addi r7,r3,THREAD_VRSTATE
|
||||||
PPC_LL r5,PT_REGS(r3)
|
PPC_LL r5,PT_REGS(r3)
|
||||||
PPC_LCMPI 0,r5,0
|
PPC_LCMPI 0,r5,0
|
||||||
SAVE_32VRS(0,r4,r3)
|
SAVE_32VRS(0,r4,r7)
|
||||||
mfvscr vr0
|
mfvscr vr0
|
||||||
li r4,THREAD_VSCR
|
li r4,VRSTATE_VSCR
|
||||||
stvx vr0,r4,r3
|
stvx vr0,r4,r7
|
||||||
beq 1f
|
beq 1f
|
||||||
PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
|
PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
|
||||||
#ifdef CONFIG_VSX
|
#ifdef CONFIG_VSX
|
||||||
|
|
|
@ -444,7 +444,7 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr)
|
||||||
#ifdef CONFIG_VSX
|
#ifdef CONFIG_VSX
|
||||||
u64 *vcpu_vsx = vcpu->arch.vsr;
|
u64 *vcpu_vsx = vcpu->arch.vsr;
|
||||||
#endif
|
#endif
|
||||||
u64 *thread_fpr = (u64*)t->fpr;
|
u64 *thread_fpr = &t->fp_state.fpr[0][0];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -466,14 +466,14 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr)
|
||||||
/*
|
/*
|
||||||
* Note that on CPUs with VSX, giveup_fpu stores
|
* Note that on CPUs with VSX, giveup_fpu stores
|
||||||
* both the traditional FP registers and the added VSX
|
* both the traditional FP registers and the added VSX
|
||||||
* registers into thread.fpr[].
|
* registers into thread.fp_state.fpr[].
|
||||||
*/
|
*/
|
||||||
if (current->thread.regs->msr & MSR_FP)
|
if (current->thread.regs->msr & MSR_FP)
|
||||||
giveup_fpu(current);
|
giveup_fpu(current);
|
||||||
for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++)
|
for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++)
|
||||||
vcpu_fpr[i] = thread_fpr[get_fpr_index(i)];
|
vcpu_fpr[i] = thread_fpr[get_fpr_index(i)];
|
||||||
|
|
||||||
vcpu->arch.fpscr = t->fpscr.val;
|
vcpu->arch.fpscr = t->fp_state.fpscr;
|
||||||
|
|
||||||
#ifdef CONFIG_VSX
|
#ifdef CONFIG_VSX
|
||||||
if (cpu_has_feature(CPU_FTR_VSX))
|
if (cpu_has_feature(CPU_FTR_VSX))
|
||||||
|
@ -486,8 +486,8 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr)
|
||||||
if (msr & MSR_VEC) {
|
if (msr & MSR_VEC) {
|
||||||
if (current->thread.regs->msr & MSR_VEC)
|
if (current->thread.regs->msr & MSR_VEC)
|
||||||
giveup_altivec(current);
|
giveup_altivec(current);
|
||||||
memcpy(vcpu->arch.vr, t->vr, sizeof(vcpu->arch.vr));
|
memcpy(vcpu->arch.vr, t->vr_state.vr, sizeof(vcpu->arch.vr));
|
||||||
vcpu->arch.vscr = t->vscr;
|
vcpu->arch.vscr = t->vr_state.vscr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -539,7 +539,7 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
|
||||||
#ifdef CONFIG_VSX
|
#ifdef CONFIG_VSX
|
||||||
u64 *vcpu_vsx = vcpu->arch.vsr;
|
u64 *vcpu_vsx = vcpu->arch.vsr;
|
||||||
#endif
|
#endif
|
||||||
u64 *thread_fpr = (u64*)t->fpr;
|
u64 *thread_fpr = &t->fp_state.fpr[0][0];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* When we have paired singles, we emulate in software */
|
/* When we have paired singles, we emulate in software */
|
||||||
|
@ -584,15 +584,15 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
|
||||||
for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr) / 2; i++)
|
for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr) / 2; i++)
|
||||||
thread_fpr[get_fpr_index(i) + 1] = vcpu_vsx[i];
|
thread_fpr[get_fpr_index(i) + 1] = vcpu_vsx[i];
|
||||||
#endif
|
#endif
|
||||||
t->fpscr.val = vcpu->arch.fpscr;
|
t->fp_state.fpscr = vcpu->arch.fpscr;
|
||||||
t->fpexc_mode = 0;
|
t->fpexc_mode = 0;
|
||||||
kvmppc_load_up_fpu();
|
kvmppc_load_up_fpu();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msr & MSR_VEC) {
|
if (msr & MSR_VEC) {
|
||||||
#ifdef CONFIG_ALTIVEC
|
#ifdef CONFIG_ALTIVEC
|
||||||
memcpy(t->vr, vcpu->arch.vr, sizeof(vcpu->arch.vr));
|
memcpy(t->vr_state.vr, vcpu->arch.vr, sizeof(vcpu->arch.vr));
|
||||||
t->vscr = vcpu->arch.vscr;
|
t->vr_state.vscr = vcpu->arch.vscr;
|
||||||
t->vrsave = -1;
|
t->vrsave = -1;
|
||||||
kvmppc_load_up_altivec();
|
kvmppc_load_up_altivec();
|
||||||
#endif
|
#endif
|
||||||
|
@ -1116,12 +1116,10 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
|
||||||
int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
|
int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
double fpr[32][TS_FPRWIDTH];
|
struct thread_fp_state fp;
|
||||||
unsigned int fpscr;
|
|
||||||
int fpexc_mode;
|
int fpexc_mode;
|
||||||
#ifdef CONFIG_ALTIVEC
|
#ifdef CONFIG_ALTIVEC
|
||||||
vector128 vr[32];
|
struct thread_vr_state vr;
|
||||||
vector128 vscr;
|
|
||||||
unsigned long uninitialized_var(vrsave);
|
unsigned long uninitialized_var(vrsave);
|
||||||
int used_vr;
|
int used_vr;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1153,8 +1151,7 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
|
||||||
/* Save FPU state in stack */
|
/* Save FPU state in stack */
|
||||||
if (current->thread.regs->msr & MSR_FP)
|
if (current->thread.regs->msr & MSR_FP)
|
||||||
giveup_fpu(current);
|
giveup_fpu(current);
|
||||||
memcpy(fpr, current->thread.fpr, sizeof(current->thread.fpr));
|
fp = current->thread.fp_state;
|
||||||
fpscr = current->thread.fpscr.val;
|
|
||||||
fpexc_mode = current->thread.fpexc_mode;
|
fpexc_mode = current->thread.fpexc_mode;
|
||||||
|
|
||||||
#ifdef CONFIG_ALTIVEC
|
#ifdef CONFIG_ALTIVEC
|
||||||
|
@ -1163,8 +1160,7 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
|
||||||
if (used_vr) {
|
if (used_vr) {
|
||||||
if (current->thread.regs->msr & MSR_VEC)
|
if (current->thread.regs->msr & MSR_VEC)
|
||||||
giveup_altivec(current);
|
giveup_altivec(current);
|
||||||
memcpy(vr, current->thread.vr, sizeof(current->thread.vr));
|
vr = current->thread.vr_state;
|
||||||
vscr = current->thread.vscr;
|
|
||||||
vrsave = current->thread.vrsave;
|
vrsave = current->thread.vrsave;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1196,15 +1192,13 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
|
||||||
current->thread.regs->msr = ext_msr;
|
current->thread.regs->msr = ext_msr;
|
||||||
|
|
||||||
/* Restore FPU/VSX state from stack */
|
/* Restore FPU/VSX state from stack */
|
||||||
memcpy(current->thread.fpr, fpr, sizeof(current->thread.fpr));
|
current->thread.fp_state = fp;
|
||||||
current->thread.fpscr.val = fpscr;
|
|
||||||
current->thread.fpexc_mode = fpexc_mode;
|
current->thread.fpexc_mode = fpexc_mode;
|
||||||
|
|
||||||
#ifdef CONFIG_ALTIVEC
|
#ifdef CONFIG_ALTIVEC
|
||||||
/* Restore Altivec state from stack */
|
/* Restore Altivec state from stack */
|
||||||
if (used_vr && current->thread.used_vr) {
|
if (used_vr && current->thread.used_vr) {
|
||||||
memcpy(current->thread.vr, vr, sizeof(current->thread.vr));
|
current->thread.vr_state = vr;
|
||||||
current->thread.vscr = vscr;
|
|
||||||
current->thread.vrsave = vrsave;
|
current->thread.vrsave = vrsave;
|
||||||
}
|
}
|
||||||
current->thread.used_vr = used_vr;
|
current->thread.used_vr = used_vr;
|
||||||
|
|
|
@ -656,9 +656,8 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
int ret, s;
|
int ret, s;
|
||||||
#ifdef CONFIG_PPC_FPU
|
#ifdef CONFIG_PPC_FPU
|
||||||
unsigned int fpscr;
|
struct thread_fp_state fp;
|
||||||
int fpexc_mode;
|
int fpexc_mode;
|
||||||
u64 fpr[32];
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!vcpu->arch.sane) {
|
if (!vcpu->arch.sane) {
|
||||||
|
@ -677,13 +676,13 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
|
||||||
#ifdef CONFIG_PPC_FPU
|
#ifdef CONFIG_PPC_FPU
|
||||||
/* Save userspace FPU state in stack */
|
/* Save userspace FPU state in stack */
|
||||||
enable_kernel_fp();
|
enable_kernel_fp();
|
||||||
memcpy(fpr, current->thread.fpr, sizeof(current->thread.fpr));
|
fp = current->thread.fp_state;
|
||||||
fpscr = current->thread.fpscr.val;
|
|
||||||
fpexc_mode = current->thread.fpexc_mode;
|
fpexc_mode = current->thread.fpexc_mode;
|
||||||
|
|
||||||
/* Restore guest FPU state to thread */
|
/* Restore guest FPU state to thread */
|
||||||
memcpy(current->thread.fpr, vcpu->arch.fpr, sizeof(vcpu->arch.fpr));
|
memcpy(current->thread.fp_state.fpr, vcpu->arch.fpr,
|
||||||
current->thread.fpscr.val = vcpu->arch.fpscr;
|
sizeof(vcpu->arch.fpr));
|
||||||
|
current->thread.fp_state.fpscr = vcpu->arch.fpscr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since we can't trap on MSR_FP in GS-mode, we consider the guest
|
* Since we can't trap on MSR_FP in GS-mode, we consider the guest
|
||||||
|
@ -709,12 +708,12 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
|
||||||
vcpu->fpu_active = 0;
|
vcpu->fpu_active = 0;
|
||||||
|
|
||||||
/* Save guest FPU state from thread */
|
/* Save guest FPU state from thread */
|
||||||
memcpy(vcpu->arch.fpr, current->thread.fpr, sizeof(vcpu->arch.fpr));
|
memcpy(vcpu->arch.fpr, current->thread.fp_state.fpr,
|
||||||
vcpu->arch.fpscr = current->thread.fpscr.val;
|
sizeof(vcpu->arch.fpr));
|
||||||
|
vcpu->arch.fpscr = current->thread.fp_state.fpscr;
|
||||||
|
|
||||||
/* Restore userspace FPU state from stack */
|
/* Restore userspace FPU state from stack */
|
||||||
memcpy(current->thread.fpr, fpr, sizeof(current->thread.fpr));
|
current->thread.fp_state = fp;
|
||||||
current->thread.fpscr.val = fpscr;
|
|
||||||
current->thread.fpexc_mode = fpexc_mode;
|
current->thread.fpexc_mode = fpexc_mode;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue