Eliminate double-copying of FP/VMX/VSX state
Subsystems (4)
cover Eliminate double-copying of FP/VMX/VSX state
At present, PR KVM and BookE KVM does multiple copies of FP and related state because of the way that they use the arrays in the thread_struct as an intermediate staging post for the state. They do this so that they can use the existing system functions for loading and saving state, and so that they can keep guest state in the CPU registers while executing general kernel code.
This patch series reorganizes things so that KVM and the main kernel use the same representation for FP/VMX/VSX state, and so that guest state can be loaded/save directly from/to the vcpu struct instead of having to go via the thread_struct. This simplifies things and should be a little faster.
This series is against Alex Graf's kvm-ppc-queue branch plus my recent series of 23 patches to make PR and HV KVM coexist.
Paul.
RFC PATCH 1/5 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.
---
Note that the removal of SAVE_VSRU, REST_VSRU etc. overlaps with a recent patch of Anton's removing the same things.
arch/powerpc/include/asm/ppc_asm.h | 108 ++------------------------------- arch/powerpc/include/asm/processor.h | 40 ++++++------ arch/powerpc/include/asm/sfp-machine.h | 2 +- arch/powerpc/kernel/align.c | 6 +- arch/powerpc/kernel/asm-offsets.c | 25 +++----- arch/powerpc/kernel/fpu.S | 59 ++++-------------- arch/powerpc/kernel/process.c | 8 +-- arch/powerpc/kernel/ptrace.c | 49 +++++++-------- arch/powerpc/kernel/ptrace32.c | 11 ++-- arch/powerpc/kernel/signal_32.c | 72 +++++++++++----------- arch/powerpc/kernel/signal_64.c | 29 ++++----- arch/powerpc/kernel/tm.S | 41 +++++++------ arch/powerpc/kernel/traps.c | 12 ++-- arch/powerpc/kernel/vecemu.c | 6 +- arch/powerpc/kernel/vector.S | 50 +++++---------- arch/powerpc/kvm/book3s_pr.c | 36 +++++------ arch/powerpc/kvm/booke.c | 19 +++--- 17 files changed, 201 insertions(+), 372 deletions(-)
arch/powerpc/include/asm/ppc_asm.h +6 -102
@@ -97,141 +97,45 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)#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 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_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_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 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_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_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 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_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_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 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_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_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) -/* 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 */ -#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_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_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 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_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_16VSRS (n,b,base) REST_8VSRS(n,b,base); REST_8VSRS(n+8,b,base)#define REST_32VSRS (n,b,base) REST_16VSRS(n,b,base); REST_16VSRS(n+16,b,base) -/* Save the upper 32 VSRs (32-63) in the thread VSX region (0-31) */ -#define SAVE_VSRU (n,b,base) li b,THREAD_VR0+(16*(n)); STXVD2X(n+32,R##base,R##b) -#define SAVE_2VSRSU (n,b,base) SAVE_VSRU(n,b,base); SAVE_VSRU(n+1,b,base) -#define SAVE_4VSRSU (n,b,base) SAVE_2VSRSU(n,b,base); SAVE_2VSRSU(n+2,b,base) -#define SAVE_8VSRSU (n,b,base) SAVE_4VSRSU(n,b,base); SAVE_4VSRSU(n+4,b,base) -#define SAVE_16VSRSU (n,b,base) SAVE_8VSRSU(n,b,base); SAVE_8VSRSU(n+8,b,base) -#define SAVE_32VSRSU (n,b,base) SAVE_16VSRSU(n,b,base); SAVE_16VSRSU(n+16,b,base) -#define REST_VSRU (n,b,base) li b,THREAD_VR0+(16*(n)); LXVD2X(n+32,R##base,R##b) -#define REST_2VSRSU (n,b,base) REST_VSRU(n,b,base); REST_VSRU(n+1,b,base) -#define REST_4VSRSU (n,b,base) REST_2VSRSU(n,b,base); REST_2VSRSU(n+2,b,base) -#define REST_8VSRSU (n,b,base) REST_4VSRSU(n,b,base); REST_4VSRSU(n+4,b,base) -#define REST_16VSRSU (n,b,base) REST_8VSRSU(n,b,base); REST_8VSRSU(n+8,b,base) -#define REST_32VSRSU (n,b,base) REST_16VSRSU(n,b,base); REST_16VSRSU(n+16,b,base)/* * b = base register for addressing, o = base offset from register of 1st EVR
arch/powerpc/include/asm/processor.h +18 -22
@@ -144,8 +144,20 @@ typedef struct {#define TS_FPROFFSET 0#define TS_VSRLOWOFFSET 1 -#define TS_FPR (i) fpr[i][TS_FPROFFSET] -#define TS_TRANS_FPR (i) transact_fpr[i][TS_FPROFFSET] +#define TS_FPR (i) fp_state.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 {unsigned long ksp;/* Kernel stack pointer */
@@ -199,13 +211,7 @@ struct thread_struct {unsigned long dvc2;#endif #endif -/* FP and VSX 0-31 register set */ -double fpr[32 ][TS_FPRWIDTH ]; -struct { - -unsigned int pad; -unsigned int val;/* Floating point status */ - } fpscr; +struct thread_fp_state fp_state;int fpexc_mode;/* floating-point exception mode */ unsigned int align_ctl;/* alignment handling control */ #ifdef CONFIG_PPC64
@@ -223,10 +229,7 @@ struct thread_struct {struct arch_hw_breakpoint hw_brk;/* info on the hardware breakpoint */ unsigned long trap_nr;/* last trap # on this thread */ #ifdef CONFIG_ALTIVEC -/* Complete AltiVec register set */ - vector128 vr[32] __attribute__((aligned(16))); -/* AltiVec status */ - vector128 vscr __attribute__((aligned(16))); +struct thread_vr_state vr_state;unsigned long vrsave;int used_vr;/* set if process has used altivec */ #endif /* CONFIG_ALTIVEC */
@@ -259,13 +262,8 @@ struct thread_struct {* transact_fpr[] is the new set of transactional values. * VRs work the same way. */ -double transact_fpr[32 ][TS_FPRWIDTH ]; -struct { -unsigned int pad; -unsigned int val;/* Floating point status */ - } transact_fpscr; - vector128 transact_vr[32] __attribute__((aligned(16))); - vector128 transact_vscr __attribute__((aligned(16))); +struct thread_fp_state transact_fp; +struct thread_vr_state transact_vr;unsigned long transact_vrsave;#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ #ifdef CONFIG_KVM_BOOK3S_32_HANDLER
@@ -320,8 +318,6 @@ struct thread_struct { .ksp_limit = INIT_SP_LIMIT, \ .regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \ .fs = KERNEL_DS, \ - .fpr = {{0}}, \ - .fpscr = { .val = 0, }, \ .fpexc_mode = 0, \ .ppr = INIT_PPR, \ }
arch/powerpc/include/asm/sfp-machine.h +1 -1
@@ -125,7 +125,7 @@#define FP_EX_DIVZERO (1 << (31 - 5))#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 * if exceptions signalled (if any) will not trap.
arch/powerpc/kernel/align.c +3 -3
@@ -656,7 +656,7 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg,if (reg <32 ) ptr = (char *) ¤t->thread.TS_FPR (reg);else - ptr = (char *) ¤t->thread.vr[reg -32 ]; + ptr = (char *) ¤t->thread.vr_state.vr[reg -32 ]; lptr = (unsigned long *) ptr;
@@ -883,7 +883,7 @@ int fix_alignment(struct pt_regs *regs)return -EFAULT ; } }else if (flags &F ) { - data.dd = current->thread.TS_FPR (reg); + data.ll = current->thread.TS_FPR (reg);if (flags &S ) {/* Single-precision FP store requires conversion... */ #ifdef CONFIG_PPC_FPU
@@ -961,7 +961,7 @@ int fix_alignment(struct pt_regs *regs)if (unlikely (ret))return -EFAULT ; }else if (flags &F ) - current->thread.TS_FPR (reg) = data.dd; + current->thread.TS_FPR (reg) = data.ll;else regs->gpr[reg] = data.ll;
arch/powerpc/kernel/asm-offsets.c +8 -17
@@ -89,16 +89,15 @@ int main(void) DEFINE(THREAD_NORMSAVES, offsetof(struct thread_struct, normsave[0]));#endif DEFINE (THREAD_FPEXC_MODE , offsetof(struct thread_struct , fpexc_mode)); - DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); -DEFINE (THREAD_FPSCR , offsetof(struct thread_struct , fpscr)); +DEFINE (THREAD_FPSTATE , offsetof(struct thread_struct , fp_state)); +DEFINE (FPSTATE_FPSCR , offsetof(struct thread_fp_state , fpscr));#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_VSCR , offsetof(struct thread_struct , vscr));DEFINE (THREAD_USED_VR , offsetof(struct thread_struct , used_vr)); +DEFINE (VRSTATE_VSCR , offsetof(struct thread_vr_state , vscr));#endif /* CONFIG_ALTIVEC */ #ifdef CONFIG_VSX -DEFINE (THREAD_VSR0 , offsetof(struct thread_struct , fpr));DEFINE (THREAD_USED_VSR , offsetof(struct thread_struct , used_vsr));#endif /* CONFIG_VSX */ #ifdef CONFIG_PPC64
@@ -140,20 +139,12 @@ int main(void)DEFINE (THREAD_TM_TEXASR , offsetof(struct thread_struct , tm_texasr));DEFINE (THREAD_TM_TFIAR , offsetof(struct thread_struct , tm_tfiar));DEFINE (PT_CKPT_REGS , offsetof(struct thread_struct , ckpt_regs)); -DEFINE (THREAD_TRANSACT_VR0 , offsetof(struct thread_struct , - transact_vr[0])); -DEFINE (THREAD_TRANSACT_VSCR , offsetof(struct thread_struct , - transact_vscr)); +DEFINE (THREAD_TRANSACT_VRSTATE , offsetof(struct thread_struct , + transact_vr));DEFINE (THREAD_TRANSACT_VRSAVE , offsetof(struct thread_struct , transact_vrsave)); -DEFINE (THREAD_TRANSACT_FPR0 , offsetof(struct thread_struct , - transact_fpr[0])); -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 +DEFINE (THREAD_TRANSACT_FPSTATE , offsetof(struct thread_struct , + transact_fp));/* Local pt_regs on stack for Transactional Memory funcs. */ DEFINE (TM_FRAME_SIZE ,STACK_FRAME_OVERHEAD +sizeof (struct pt_regs ) +16 );
arch/powerpc/kernel/fpu.S +13 -46
111 lines not on this page · raw message
arch/powerpc/kernel/process.c +3 -5
@@ -1096,12 +1096,10 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)#ifdef CONFIG_VSX current->thread.used_vsr =0 ;#endif -memset (current->thread.fpr,0 ,sizeof (current->thread.fpr)); - current->thread.fpscr.val =0 ; +memset (¤t->thread.fp_state,0 ,sizeof (current->thread.fp_state));#ifdef CONFIG_ALTIVEC -memset (current->thread.vr,0 ,sizeof (current->thread.vr)); -memset (¤t->thread.vscr,0 ,sizeof (current->thread.vscr)); - current->thread.vscr.u[3 ] =0x00010000 ;/* Java mode disabled */ +memset (¤t->thread.vr_state,0 ,sizeof (current->thread.vr_state)); + current->thread.vr_state.vscr.u[3 ] =0x00010000 ;/* Java mode disabled */ current->thread.vrsave =0 ; current->thread.used_vr =0 ;#endif /* CONFIG_ALTIVEC */
arch/powerpc/kernel/ptrace.c +25 -24
137 lines not on this page · raw message
arch/powerpc/kernel/ptrace32.c +4 -7
@@ -43,7 +43,6 @@#define FPRNUMBER (i) (((i) - PT_FPR0) >> 1)#define FPRHALF (i) (((i) - PT_FPR0) & 1)#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,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 * index passed in is based on this assumption. */ - tmp = ((unsigned int *)child->thread.fpr) + tmp = ((unsigned int *)child->thread.fp_state.fpr) [FPRINDEX (index)]; } 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 ) {flush_fp_to_thread (child);/* get 64 bit FPR */ - tmp = ((u64 *)child->thread.fpr) - [FPRINDEX_3264 (numReg)]; + tmp = child->thread.fp_state.fpr[numReg -PT_FPR0 ][0 ]; }else {/* register within PT_REGS struct */ unsigned long 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 * index passed in is based on this assumption. */ - ((unsigned int *)child->thread.fpr) + ((unsigned int *)child->thread.fp_state.fpr) [FPRINDEX (index)] = data; ret =0 ; }
@@ -251,8 +249,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,u64 *tmp;flush_fp_to_thread (child);/* get 64 bit FPR ... */ - tmp = &(((u64 *)child->thread.fpr) - [FPRINDEX_3264 (numReg)]); + tmp = &child->thread.fp_state.fpr[numReg -PT_FPR0 ][0 ];/* ... write the 32 bit part we want */ ((u32 *)tmp)[index %2 ] = data; ret =0 ;
arch/powerpc/kernel/signal_32.c +37 -35
248 lines not on this page · raw message
arch/powerpc/kernel/signal_64.c +15 -14
@@ -105,7 +105,8 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,if (current->thread.used_vr) {flush_altivec_to_thread (current);/* 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) * contains valid data. */
@@ -195,18 +196,18 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc,if (current->thread.used_vr) {flush_altivec_to_thread (current);/* 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));/* If VEC was enabled there are transactional VRs valid too, * else they're a copy of the checkpointed VRs. */ if (msr &MSR_VEC ) err |=__copy_to_user (tm_v_regs, - current->thread.transact_vr, + ¤t->thread.transact_vr,33 *sizeof (vector128));else err |=__copy_to_user (tm_v_regs, - current->thread.vr, + ¤t->thread.vr_state,33 *sizeof (vector128));/* set MSR_VEC in the MSR value in the frame to indicate
@@ -347,10 +348,10 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,return -EFAULT ;/* Copy 33 vec registers (vr0..31 and vscr) from the stack */ if (v_regs !=0 && (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));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 */ if (v_regs !=0 ) err |=__get_user (current->thread.vrsave, (u32 __user *)&v_regs[33 ]);
@@ -370,7 +371,7 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, err |=copy_vsx_from_user (current, v_regs); else for (i = 0; i < 32 ; i++) - current->thread.fpr[i][TS_VSRLOWOFFSET ] =0 ; + current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET ] =0 ;#endif return err; }
@@ -460,14 +461,14 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,return -EFAULT ;/* Copy 33 vec registers (vr0..31 and vscr) from the stack */ if (v_regs !=0 && tm_v_regs !=0 && (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)); - 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)); }else if (current->thread.used_vr) { -memset (current->thread.vr,0 ,33 *sizeof (vector128)); -memset (current->thread.transact_vr,0 ,33 *sizeof (vector128)); +memset (¤t->thread.vr_state,0 ,33 *sizeof (vector128)); +memset (¤t->thread.transact_vr,0 ,33 *sizeof (vector128)); }/* Always get VRSAVE back */ if (v_regs !=0 && tm_v_regs !=0 ) {
@@ -497,8 +498,8 @@ static long restore_tm_sigcontexts(struct pt_regs *regs, err |= copy_transact_vsx_from_user(current, tm_v_regs); }else {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
@@ -739,7 +740,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, goto badframe;/* 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 /* Remove TM bits from thread's MSR. The MSR in the sigcontext * just indicates to userland that we were doing a transaction, but we
arch/powerpc/kernel/tm.S +22 -19
88 lines not on this page · raw message
arch/powerpc/kernel/traps.c +4 -8
@@ -815,7 +815,7 @@ static void parse_fpe(struct pt_regs *regs)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); }
@@ -1132,7 +1132,7 @@ void __kprobes program_check_exception(struct pt_regs *regs) goto bail;case 1 : {int code =0 ; - code =__parse_fpscr (current->thread.fpscr.val); + code =__parse_fpscr (current->thread.fp_state.fpscr);_exception (SIGFPE , regs, code, regs->nip); goto bail; }
@@ -1305,8 +1305,6 @@ void tm_unavailable_exception(struct pt_regs *regs)#ifdef CONFIG_PPC_TRANSACTIONAL_MEM -extern void do_load_up_fpu (struct pt_regs *regs); -void fp_unavailable_tm (struct pt_regs *regs) {/* Note: This does not handle any kind of FP laziness. */
@@ -1337,8 +1335,6 @@ void fp_unavailable_tm(struct pt_regs *regs) }#ifdef CONFIG_ALTIVEC -extern void do_load_up_altivec (struct pt_regs *regs); -void altivec_unavailable_tm (struct pt_regs *regs) {/* See the comments in fp_unavailable_tm(). This function operates
@@ -1419,7 +1415,7 @@ void SoftwareEmulation(struct pt_regs *regs)return ;case 1 : {int code =0 ; - code =__parse_fpscr (current->thread.fpscr.val); + code =__parse_fpscr (current->thread.fp_state.fpscr);_exception (SIGFPE , regs, code, regs->nip);return ; }
@@ -1612,7 +1608,7 @@ void altivec_assist_exception(struct pt_regs *regs)/* XXX quick hack for now: set the non-Java bit in the VSCR */ printk_ratelimited (KERN_ERR "Unrecognized altivec instruction " "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 */
arch/powerpc/kernel/vecemu.c +3 -3
@@ -271,7 +271,7 @@ int emulate_altivec(struct pt_regs *regs) vb = (instr >>11 ) &0x1f ; vc = (instr >>6 ) &0x1f ; - vrs = current->thread.vr; + vrs = current->thread.vr_state.vr;switch (instr &0x3f ) {case 10 :switch (vc) {
@@ -320,12 +320,12 @@ int emulate_altivec(struct pt_regs *regs)case 14 :/* vctuxs */ for (i =0 ; i <4 ; ++i) vrs[vd].u[i] =ctuxs (vrs[vb].u[i], va, - ¤t->thread.vscr.u[3 ]); + ¤t->thread.vr_state.vscr.u[3 ]);break ;case 15 :/* vctsxs */ for (i =0 ; i <4 ; ++i) vrs[vd].u[i] =ctsxs (vrs[vb].u[i], va, - ¤t->thread.vscr.u[3 ]); + ¤t->thread.vr_state.vscr.u[3 ]);break ;default :return -EINVAL ;
arch/powerpc/kernel/vector.S +15 -35
95 lines not on this page · raw message
arch/powerpc/kvm/book3s_pr.c +15 -21
@@ -540,7 +540,7 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr)#ifdef CONFIG_VSX u64 *vcpu_vsx = vcpu->arch.vsr;#endif -u64 *thread_fpr = (u64 *)t->fpr; +u64 *thread_fpr = &t->fp_state.fpr[0 ][0 ];int i;/*
@@ -562,14 +562,14 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr)/* * Note that on CPUs with VSX, giveup_fpu stores * 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 )giveup_fpu (current);for (i =0 ; i <ARRAY_SIZE (vcpu->arch.fpr); 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 if (cpu_has_feature (CPU_FTR_VSX ))
@@ -582,8 +582,8 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr)if (msr &MSR_VEC ) {if (current->thread.regs->msr &MSR_VEC )giveup_altivec (current); -memcpy (vcpu->arch.vr, t->vr,sizeof (vcpu->arch.vr)); - vcpu->arch.vscr = t->vscr; +memcpy (vcpu->arch.vr, t->vr_state.vr,sizeof (vcpu->arch.vr)); + vcpu->arch.vscr = t->vr_state.vscr; }#endif
@@ -635,7 +635,7 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,#ifdef CONFIG_VSX u64 *vcpu_vsx = vcpu->arch.vsr;#endif -u64 *thread_fpr = (u64 *)t->fpr; +u64 *thread_fpr = &t->fp_state.fpr[0 ][0 ];int i;/* When we have paired singles, we emulate in software */
@@ -680,15 +680,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++) thread_fpr[get_fpr_index (i) +1 ] = vcpu_vsx[i];#endif - t->fpscr.val = vcpu->arch.fpscr; + t->fp_state.fpscr = vcpu->arch.fpscr; t->fpexc_mode =0 ;kvmppc_load_up_fpu (); }if (msr &MSR_VEC ) {#ifdef CONFIG_ALTIVEC -memcpy (t->vr, vcpu->arch.vr,sizeof (vcpu->arch.vr)); - t->vscr = vcpu->arch.vscr; +memcpy (t->vr_state.vr, vcpu->arch.vr,sizeof (vcpu->arch.vr)); + t->vr_state.vscr = vcpu->arch.vscr; t->vrsave =-1 ;kvmppc_load_up_altivec ();#endif
@@ -1298,12 +1298,10 @@ static void enable_relon_interrupts(struct kvm *kvm)int kvmppc_vcpu_run_pr (struct kvm_run *kvm_run,struct kvm_vcpu *vcpu) {int ret; -double fpr[32 ][TS_FPRWIDTH ]; -unsigned int fpscr; +struct thread_fp_state fp;int fpexc_mode;#ifdef CONFIG_ALTIVEC -vector128 vr[32 ]; -vector128 vscr; +struct thread_vr_state vr;unsigned long uninitialized_var (vrsave );int used_vr;#endif
@@ -1338,8 +1336,7 @@ int kvmppc_vcpu_run_pr(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)/* Save FPU state in stack */ if (current->thread.regs->msr &MSR_FP )giveup_fpu (current); -memcpy (fpr, current->thread.fpr,sizeof (current->thread.fpr)); - fpscr = current->thread.fpscr.val; + fp = current->thread.fp_state; fpexc_mode = current->thread.fpexc_mode;#ifdef CONFIG_ALTIVEC
@@ -1348,8 +1345,7 @@ int kvmppc_vcpu_run_pr(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)if (used_vr) {if (current->thread.regs->msr &MSR_VEC )giveup_altivec (current); -memcpy (vr, current->thread.vr,sizeof (current->thread.vr)); - vscr = current->thread.vscr; + vr = current->thread.vr_state; vrsave = current->thread.vrsave; }#endif
@@ -1381,15 +1377,13 @@ int kvmppc_vcpu_run_pr(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) current->thread.regs->msr = ext_msr;/* Restore FPU/VSX state from stack */ -memcpy (current->thread.fpr, fpr,sizeof (current->thread.fpr)); - current->thread.fpscr.val = fpscr; + current->thread.fp_state = fp; current->thread.fpexc_mode = fpexc_mode;#ifdef CONFIG_ALTIVEC /* Restore Altivec state from stack */ if (used_vr && current->thread.used_vr) { -memcpy (current->thread.vr, vr,sizeof (current->thread.vr)); - current->thread.vscr = vscr; + current->thread.vr_state = vr; current->thread.vrsave = vrsave; } current->thread.used_vr = used_vr;
arch/powerpc/kvm/booke.c +9 -10
@@ -656,9 +656,8 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) {int ret, s;#ifdef CONFIG_PPC_FPU -unsigned int fpscr; +struct thread_fp_state fp;int fpexc_mode; -u64 fpr[32 ];#endif 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 /* Save userspace FPU state in stack */ enable_kernel_fp (); -memcpy (fpr, current->thread.fpr,sizeof (current->thread.fpr)); - fpscr = current->thread.fpscr.val; + fp = current->thread.fp_state; fpexc_mode = current->thread.fpexc_mode;/* Restore guest FPU state to thread */ -memcpy (current->thread.fpr, vcpu->arch.fpr,sizeof (vcpu->arch.fpr)); - current->thread.fpscr.val = vcpu->arch.fpscr; +memcpy (current->thread.fp_state.fpr, vcpu->arch.fpr, +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
@@ -709,12 +708,12 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) vcpu->fpu_active =0 ;/* Save guest FPU state from thread */ -memcpy (vcpu->arch.fpr, current->thread.fpr,sizeof (vcpu->arch.fpr)); - vcpu->arch.fpscr = current->thread.fpscr.val; +memcpy (vcpu->arch.fpr, current->thread.fp_state.fpr, +sizeof (vcpu->arch.fpr)); + vcpu->arch.fpscr = current->thread.fp_state.fpscr;/* Restore userspace FPU state from stack */ -memcpy (current->thread.fpr, fpr,sizeof (current->thread.fpr)); - current->thread.fpscr.val = fpscr; + current->thread.fp_state = fp; current->thread.fpexc_mode = fpexc_mode;#endif
Signature · 1 line
1.8.3.1
RFC PATCH 2/5 powerpc: Provide for giveup_fpu/altivec to save state in alternate location
In reply to Paul MackerrasThis provides a facility which is intended for use by KVM, where the contents of the FP/VSX and VMX (Altivec) registers can be saved away to somewhere other than the thread_struct when kernel code wants to use floating point or VMX instructions. This is done by providing a pointer in the thread_struct to indicate where the state should be saved to. The giveup_fpu() and giveup_altivec() functions test these pointers and save state to the indicated location if they are non-NULL. Note that the MSR_FP/VEC bits in task->thread.regs->msr are still used to indicate whether the CPU register state is live, even when an alternate save location is being used.
This also provides load_fp_state() and load_vr_state() functions, which load up FP/VSX and VMX state from memory into the CPU registers.
--- arch/powerpc/include/asm/processor.h | 5 +++++ arch/powerpc/kernel/asm-offsets.c | 2 ++ arch/powerpc/kernel/fpu.S | 15 ++++++++++++++- arch/powerpc/kernel/ppc_ksyms.c | 4 ++++ arch/powerpc/kernel/process.c | 7 +++++++ arch/powerpc/kernel/vector.S | 18 ++++++++++++++++-- 6 files changed, 48 insertions(+), 3 deletions(-)
arch/powerpc/include/asm/processor.h +5 -0
@@ -212,6 +212,7 @@ struct thread_struct {#endif #endif struct thread_fp_state fp_state; +struct thread_fp_state *fp_save_area;int fpexc_mode;/* floating-point exception mode */ unsigned int align_ctl;/* alignment handling control */ #ifdef CONFIG_PPC64
@@ -230,6 +231,7 @@ struct thread_struct {unsigned long trap_nr;/* last trap # on this thread */ #ifdef CONFIG_ALTIVEC struct thread_vr_state vr_state; +struct thread_vr_state *vr_save_area;unsigned long vrsave;int used_vr;/* set if process has used altivec */ #endif /* CONFIG_ALTIVEC */
@@ -355,6 +357,9 @@ extern int set_endian(struct task_struct *tsk, unsigned int val);extern int get_unalign_ctl (struct task_struct *tsk,unsigned long adr);extern int set_unalign_ctl (struct task_struct *tsk,unsigned int val); +extern void load_fp_state (struct thread_fp_state *fp); +extern void load_vr_state (struct thread_vr_state *vr); +static inline unsigned int __unpack_fe01 (unsigned long msr_bits) {return ((msr_bits &MSR_FE0 ) >>10 ) | ((msr_bits &MSR_FE1 ) >>8 );
arch/powerpc/kernel/asm-offsets.c +2 -0
@@ -90,9 +90,11 @@ int main(void)#endif DEFINE (THREAD_FPEXC_MODE , offsetof(struct thread_struct , fpexc_mode));DEFINE (THREAD_FPSTATE , offsetof(struct thread_struct , fp_state)); +DEFINE (THREAD_FPSAVEAREA , offsetof(struct thread_struct , fp_save_area));DEFINE (FPSTATE_FPSCR , offsetof(struct thread_fp_state , fpscr));#ifdef CONFIG_ALTIVEC DEFINE (THREAD_VRSTATE , offsetof(struct thread_struct , vr_state)); +DEFINE (THREAD_VRSAVEAREA , offsetof(struct thread_struct , vr_save_area));DEFINE (THREAD_VRSAVE , offsetof(struct thread_struct , vrsave));DEFINE (THREAD_USED_VR , offsetof(struct thread_struct , used_vr));DEFINE (VRSTATE_VSCR , offsetof(struct thread_vr_state , vscr));
arch/powerpc/kernel/fpu.S +14 -1
@@ -81,6 +81,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ /* + * Load state from memory into FP registers including FPSCR. + * Assumes the caller has enabled FP in the MSR. + */ +_GLOBAL(load_fp_state) + lfd fr0,FPSTATE_FPSCR(r3) + MTFSF_L(fr0) + REST_32FPVSRS(0, R4, R3) + blr + +/* * This task wants to use the FPU now. * On UP, disable FP for the task which had the FPU previously, * and save its floating-point registers in its thread_struct.
@@ -172,9 +182,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) PPC_LCMPI 0,r3,0 beqlr- /* if no previous owner, done */ addi r3,r3,THREAD /* want THREAD of task */ + PPC_LL r6,THREAD_FPSAVEAREA(r3) PPC_LL r5,PT_REGS(r3) - PPC_LCMPI 0,r5,0 + PPC_LCMPI 0,r6,0 + bne 2f addi r6,r3,THREAD_FPSTATE +2: PPC_LCMPI 0,r5,0 SAVE_32FPVSRS(0, R4, R6) mffs fr0 stfd fr0,FPSTATE_FPSCR(r6)
arch/powerpc/kernel/ppc_ksyms.c +4 -0
@@ -97,8 +97,12 @@ EXPORT_SYMBOL(pci_dram_offset);EXPORT_SYMBOL (start_thread);EXPORT_SYMBOL (giveup_fpu); +#ifdef CONFIG_PPC_FPU +EXPORT_SYMBOL (load_fp_state); +#endif #ifdef CONFIG_ALTIVEC EXPORT_SYMBOL (giveup_altivec); +EXPORT_SYMBOL (load_vr_state);#endif /* CONFIG_ALTIVEC */ #ifdef CONFIG_VSX EXPORT_SYMBOL (giveup_vsx);
arch/powerpc/kernel/process.c +7 -0
@@ -991,6 +991,11 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, p->thread.ptrace_bps[0 ] =NULL ;#endif + p->thread.fp_save_area =NULL ; +#ifdef CONFIG_ALTIVEC + p->thread.vr_save_area =NULL ; +#endif +#ifdef CONFIG_PPC_STD_MMU_64 if (mmu_has_feature (MMU_FTR_SLB )) {unsigned long sp_vsid;
@@ -1097,9 +1102,11 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) current->thread.used_vsr =0 ;#endif memset (¤t->thread.fp_state,0 ,sizeof (current->thread.fp_state)); + current->thread.fp_save_area =NULL ;#ifdef CONFIG_ALTIVEC memset (¤t->thread.vr_state,0 ,sizeof (current->thread.vr_state)); current->thread.vr_state.vscr.u[3 ] =0x00010000 ;/* Java mode disabled */ + current->thread.vr_save_area =NULL ; current->thread.vrsave =0 ; current->thread.used_vr =0 ;#endif /* CONFIG_ALTIVEC */
arch/powerpc/kernel/vector.S +16 -2
@@ -37,6 +37,17 @@ _GLOBAL(do_load_up_transact_altivec) #endif /* + * Load state from memory into VMX registers including VSCR. + * Assumes the caller has enabled VMX in the MSR. + */ +_GLOBAL(load_vr_state) + li r4,VRSTATE_VSCR + lvx vr0,r4,r3 + mtvscr vr0 + REST_32VRS(0,r4,r3) + blr + +/* * Disable VMX for the task which had it previously, * and save its vector registers in its thread_struct. * Enables the VMX for use in the kernel on return.
@@ -144,9 +155,12 @@ _GLOBAL(giveup_altivec) PPC_LCMPI 0,r3,0 beqlr /* if no previous owner, done */ addi r3,r3,THREAD /* want THREAD of task */ - addi r7,r3,THREAD_VRSTATE + PPC_LL r7,THREAD_VRSAVEAREA(r3) PPC_LL r5,PT_REGS(r3) - PPC_LCMPI 0,r5,0 + PPC_LCMPI 0,r7,0 + bne 2f + addi r7,r3,THREAD_VRSTATE +2: PPC_LCMPI 0,r5,0 SAVE_32VRS(0,r4,r7) mfvscr vr0 li r4,VRSTATE_VSCR
Signature · 1 line
1.8.3.1
RFC PATCH 3/5 KVM: PPC: Use load_fp/vr_state rather than load_up_fpu/altivec
In reply to Paul MackerrasThe load_up_fpu and load_up_altivec functions were never intended to be called from C, and do things like modifying the MSR value in their callers' stack frames, which are assumed to be interrupt frames. In addition, on 32-bit Book S they require the MMU to be off.
This makes KVM use the new load_fp_state() and load_vr_state() functions instead of load_up_fpu/altivec. This means we can remove the assembler glue in book3s_rmhandlers.S, and potentially fixes a bug on Book E, where load_up_fpu was called directly from C.
--- arch/powerpc/include/asm/kvm_book3s.h | 3 --- arch/powerpc/include/asm/switch_to.h | 2 -- arch/powerpc/kvm/book3s_exports.c | 4 --- arch/powerpc/kvm/book3s_pr.c | 18 +++++++++----- arch/powerpc/kvm/book3s_rmhandlers.S | 47 ----------------------------------- arch/powerpc/kvm/booke.h | 3 ++- 6 files changed, 14 insertions(+), 63 deletions(-)
arch/powerpc/include/asm/kvm_book3s.h +0 -3
@@ -186,9 +186,6 @@ extern long kvmppc_hv_get_dirty_log(struct kvm *kvm,extern void kvmppc_entry_trampoline (void );extern void kvmppc_hv_entry_trampoline (void ); -extern void kvmppc_load_up_fpu (void ); -extern void kvmppc_load_up_altivec (void ); -extern void kvmppc_load_up_vsx (void );extern u32 kvmppc_alignment_dsisr (struct kvm_vcpu *vcpu,unsigned int inst);extern ulong kvmppc_alignment_dar (struct kvm_vcpu *vcpu,unsigned int inst);extern int kvmppc_h_pr (struct kvm_vcpu *vcpu,unsigned long cmd);
arch/powerpc/include/asm/switch_to.h +0 -2
@@ -17,12 +17,10 @@ extern struct task_struct *_switch(struct thread_struct *prev, struct thread_struct *next);extern void giveup_fpu (struct task_struct *); -extern void load_up_fpu (void );extern void disable_kernel_fp (void );extern void enable_kernel_fp (void );extern void flush_fp_to_thread (struct task_struct *);extern void enable_kernel_altivec (void ); -extern void load_up_altivec (struct task_struct *);extern int emulate_altivec (struct pt_regs *);extern void __giveup_vsx (struct task_struct *);extern void giveup_vsx (struct task_struct *);
arch/powerpc/kvm/book3s_exports.c +0 -4
@@ -25,9 +25,5 @@ EXPORT_SYMBOL_GPL(kvmppc_hv_entry_trampoline);#endif #ifdef CONFIG_KVM_BOOK3S_PR EXPORT_SYMBOL_GPL (kvmppc_entry_trampoline); -EXPORT_SYMBOL_GPL (kvmppc_load_up_fpu); -#ifdef CONFIG_ALTIVEC -EXPORT_SYMBOL_GPL (kvmppc_load_up_altivec); -#endif #endif
arch/powerpc/kvm/book3s_pr.c +12 -6
@@ -682,7 +682,8 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,#endif t->fp_state.fpscr = vcpu->arch.fpscr; t->fpexc_mode =0 ; -kvmppc_load_up_fpu (); +enable_kernel_fp (); +load_fp_state (&t->fp_state); }if (msr &MSR_VEC ) {
@@ -690,7 +691,8 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,memcpy (t->vr_state.vr, vcpu->arch.vr,sizeof (vcpu->arch.vr)); t->vr_state.vscr = vcpu->arch.vscr; t->vrsave =-1 ; -kvmppc_load_up_altivec (); +enable_kernel_altivec (); +load_vr_state (&t->vr_state);#endif }
@@ -713,10 +715,14 @@ static void kvmppc_handle_lost_ext(struct kvm_vcpu *vcpu)if (!lost_ext)return ; -if (lost_ext &MSR_FP ) -kvmppc_load_up_fpu (); -if (lost_ext &MSR_VEC ) -kvmppc_load_up_altivec (); +if (lost_ext &MSR_FP ) { +enable_kernel_fp (); +load_fp_state (¤t->thread.fp_state); + } +if (lost_ext &MSR_VEC ) { +enable_kernel_altivec (); +load_vr_state (¤t->thread.vr_state); + } current->thread.regs->msr |= lost_ext; }
arch/powerpc/kvm/book3s_rmhandlers.S +0 -47
51 lines not on this page · raw message
arch/powerpc/kvm/booke.h +2 -1
@@ -112,7 +112,8 @@ static inline void kvmppc_load_guest_fp(struct kvm_vcpu *vcpu) {#ifdef CONFIG_PPC_FPU if (vcpu->fpu_active && !(current->thread.regs->msr &MSR_FP )) { -load_up_fpu (); +enable_kernel_fp (); +load_fp_state (¤t->thread.fp_state); current->thread.regs->msr |=MSR_FP ; }#endif
Signature · 1 line
1.8.3.1
RFC PATCH 4/5 KVM: PPC: Store FP/VSX/VMX state in thread_fp/vr_state structures
In reply to Paul MackerrasThis uses struct thread_fp_state and struct thread_vr_state to store the floating-point, VMX/Altivec and VSX state, rather than flat arrays. This makes transferring the state to/from the thread_struct simpler and allows us to unify the get/set_one_reg implementations for the VSX registers.
--- arch/powerpc/include/asm/kvm_host.h | 12 +-- arch/powerpc/kernel/asm-offsets.c | 11 +- arch/powerpc/kvm/book3s.c | 38 +++++-- arch/powerpc/kvm/book3s_hv.c | 42 -------- arch/powerpc/kvm/book3s_hv_rmhandlers.S | 4 +- arch/powerpc/kvm/book3s_paired_singles.c | 169 +++++++++++++++---------------- arch/powerpc/kvm/book3s_pr.c | 63 +----------- arch/powerpc/kvm/booke.c | 8 +- arch/powerpc/kvm/powerpc.c | 4 +- 9 files changed, 131 insertions(+), 220 deletions(-)
arch/powerpc/include/asm/kvm_host.h +4 -8
@@ -427,8 +427,7 @@ struct kvm_vcpu_arch {ulong gpr[32 ]; -u64 fpr[32 ]; -u64 fpscr; +struct thread_fp_state fp;#ifdef CONFIG_SPE ulong evr[32 ];
@@ -437,12 +436,7 @@ struct kvm_vcpu_arch {u64 acc;#endif #ifdef CONFIG_ALTIVEC -vector128 vr[32 ]; -vector128 vscr; -#endif - -#ifdef CONFIG_VSX -u64 vsr[64 ]; +struct thread_vr_state vr;#endif #ifdef CONFIG_KVM_BOOKE_HV
@@ -630,6 +624,8 @@ struct kvm_vcpu_arch {#endif }; +#define VCPU_FPR (vcpu, i) (vcpu)->arch.fp.fpr[i][TS_FPROFFSET] +/* Values for vcpu->arch.state */ #define KVMPPC_VCPU_NOTREADY 0#define KVMPPC_VCPU_RUNNABLE 1
arch/powerpc/kernel/asm-offsets.c +4 -7
@@ -422,14 +422,11 @@ int main(void) DEFINE(VCPU_GUEST_PID, offsetof(struct kvm_vcpu, arch.pid)); DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr)); DEFINE(VCPU_VRSAVE, offsetof(struct kvm_vcpu, arch.vrsave)); - DEFINE(VCPU_FPRS, offsetof(struct kvm_vcpu, arch.fpr)); - DEFINE(VCPU_FPSCR, offsetof(struct kvm_vcpu, arch.fpscr)); + DEFINE(VCPU_FPRS, offsetof(struct kvm_vcpu, arch.fp.fpr)); + DEFINE(VCPU_FPSCR, offsetof(struct kvm_vcpu, arch.fp.fpscr));#ifdef CONFIG_ALTIVEC - DEFINE(VCPU_VRS, offsetof(struct kvm_vcpu, arch.vr)); - DEFINE(VCPU_VSCR, offsetof(struct kvm_vcpu, arch.vscr)); -#endif -#ifdef CONFIG_VSX - DEFINE(VCPU_VSRS, offsetof(struct kvm_vcpu, arch.vsr)); + DEFINE(VCPU_VRS, offsetof(struct kvm_vcpu, arch.vr.vr)); + DEFINE(VCPU_VSCR, offsetof(struct kvm_vcpu, arch.vr.vscr));#endif DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer)); DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr));
arch/powerpc/kvm/book3s.c +30 -8
@@ -582,10 +582,10 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)break ; case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: i = reg->id -KVM_REG_PPC_FPR0 ; - val =get_reg_val (reg->id, vcpu->arch.fpr[i]); + val =get_reg_val (reg->id,VCPU_FPR (vcpu, i));break ;case KVM_REG_PPC_FPSCR : - val =get_reg_val (reg->id, vcpu->arch.fpscr); + val =get_reg_val (reg->id, vcpu->arch.fp.fpscr);break ;#ifdef CONFIG_ALTIVEC case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31:
@@ -593,16 +593,27 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) r = -ENXIO ;break ; } - val.vval = vcpu->arch.vr[reg->id -KVM_REG_PPC_VR0 ]; + val.vval = vcpu->arch.vr.vr[reg->id -KVM_REG_PPC_VR0 ];break ;case KVM_REG_PPC_VSCR :if (!cpu_has_feature (CPU_FTR_ALTIVEC )) { r = -ENXIO ;break ; } - val =get_reg_val (reg->id, vcpu->arch.vscr.u[3 ]); + val =get_reg_val (reg->id, vcpu->arch.vr.vscr.u[3 ]);break ;#endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_VSX + case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31: +if (cpu_has_feature (CPU_FTR_VSX )) { +long int i = reg->id -KVM_REG_PPC_VSR0 ; + val.vsxval[0 ] = vcpu->arch.fp.fpr[i][0 ]; + val.vsxval[1 ] = vcpu->arch.fp.fpr[i][1 ]; + }else { + r = -ENXIO ; + } +break ; +#endif /* CONFIG_VSX */ case KVM_REG_PPC_DEBUG_INST : {u32 opcode =INS_TW ; r = copy_to_user((u32 __user *)(long)reg->addr,
@@ -660,10 +671,10 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)break ; case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: i = reg->id -KVM_REG_PPC_FPR0 ; - vcpu->arch.fpr[i] =set_reg_val (reg->id, val); +VCPU_FPR (vcpu, i) =set_reg_val (reg->id, val);break ;case KVM_REG_PPC_FPSCR : - vcpu->arch.fpscr =set_reg_val (reg->id, val); + vcpu->arch.fp.fpscr =set_reg_val (reg->id, val);break ;#ifdef CONFIG_ALTIVEC case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31:
@@ -671,16 +682,27 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) r = -ENXIO ;break ; } - vcpu->arch.vr[reg->id -KVM_REG_PPC_VR0 ] = val.vval; + vcpu->arch.vr.vr[reg->id -KVM_REG_PPC_VR0 ] = val.vval;break ;case KVM_REG_PPC_VSCR :if (!cpu_has_feature (CPU_FTR_ALTIVEC )) { r = -ENXIO ;break ; } - vcpu->arch.vscr.u[3 ] =set_reg_val (reg->id, val); + vcpu->arch.vr.vscr.u[3 ] =set_reg_val (reg->id, val);break ;#endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_VSX + case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31: +if (cpu_has_feature (CPU_FTR_VSX )) { +long int i = reg->id -KVM_REG_PPC_VSR0 ; + vcpu->arch.fp.fpr[i][0 ] = val.vsxval[0 ]; + vcpu->arch.fp.fpr[i][1 ] = val.vsxval[1 ]; + }else { + r = -ENXIO ; + } +break ; +#endif /* CONFIG_VSX */ #ifdef CONFIG_KVM_XICS case KVM_REG_PPC_ICP_STATE :if (!vcpu->arch.icp) {
arch/powerpc/kvm/book3s_hv.c +0 -42
54 lines not on this page · raw message
arch/powerpc/kvm/book3s_hv_rmhandlers.S +2 -2
@@ -1766,7 +1766,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) BEGIN_FTR_SECTION reg = 0 .rept 32 - li r6,reg*16+VCPU_VSRS + li r6,reg*16+VCPU_FPRS STXVD2X(reg,R6,R3) reg = reg + 1 .endr
@@ -1828,7 +1828,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) BEGIN_FTR_SECTION reg = 0 .rept 32 - li r7,reg*16+VCPU_VSRS + li r7,reg*16+VCPU_FPRS LXVD2X(reg,R7,R4) reg = reg + 1 .endr
arch/powerpc/kvm/book3s_paired_singles.c +83 -86
455 lines not on this page · raw message
arch/powerpc/kvm/book3s_pr.c +4 -59
111 lines not on this page · raw message
arch/powerpc/kvm/booke.c +2 -6
@@ -680,9 +680,7 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) fpexc_mode = current->thread.fpexc_mode;/* Restore guest FPU state to thread */ -memcpy (current->thread.fp_state.fpr, vcpu->arch.fpr, -sizeof (vcpu->arch.fpr)); - current->thread.fp_state.fpscr = vcpu->arch.fpscr; + current->thread.fp_state = vcpu->arch.fp;/* * Since we can't trap on MSR_FP in GS-mode, we consider the guest
@@ -708,9 +706,7 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) vcpu->fpu_active =0 ;/* Save guest FPU state from thread */ -memcpy (vcpu->arch.fpr, current->thread.fp_state.fpr, -sizeof (vcpu->arch.fpr)); - vcpu->arch.fpscr = current->thread.fp_state.fpscr; + vcpu->arch.fp = current->thread.fp_state;/* Restore userspace FPU state from stack */ current->thread.fp_state = fp;
arch/powerpc/kvm/powerpc.c +2 -2
@@ -612,14 +612,14 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,kvmppc_set_gpr (vcpu, vcpu->arch.io_gpr, gpr);break ;case KVM_MMIO_REG_FPR : - vcpu->arch.fpr[vcpu->arch.io_gpr &KVM_MMIO_REG_MASK ] = gpr; +VCPU_FPR (vcpu, vcpu->arch.io_gpr &KVM_MMIO_REG_MASK ) = gpr;break ;#ifdef CONFIG_PPC_BOOK3S case KVM_MMIO_REG_QPR : vcpu->arch.qpr[vcpu->arch.io_gpr &KVM_MMIO_REG_MASK ] = gpr;break ;case KVM_MMIO_REG_FQPR : - vcpu->arch.fpr[vcpu->arch.io_gpr &KVM_MMIO_REG_MASK ] = gpr; +VCPU_FPR (vcpu, vcpu->arch.io_gpr &KVM_MMIO_REG_MASK ) = gpr; vcpu->arch.qpr[vcpu->arch.io_gpr &KVM_MMIO_REG_MASK ] = gpr;break ;#endif
Signature · 1 line
1.8.3.1
RFC PATCH 5/5 KVM: PPC: Book3S: Load/save FP/VMX/VSX state directly to/from vcpu struct
In reply to Paul MackerrasNow that we have the vcpu floating-point and vector state stored in the same type of struct as the main kernel uses, we can load that state directly from the vcpu struct instead of having extra copies to/from the thread_struct. Similarly, when the guest state needs to be saved, we can have it saved it directly to the vcpu struct by setting the current->thread.fp_save_area and current->thread.vr_save_area pointers. That also means that we don't need to back up and restore userspace's FP/vector state. This all makes the code simpler and faster.
Note that it's not necessary to save or modify current->thread.fpexc_mode, since nothing in KVM uses or is affected by its value. Nor is it necessary to touch used_vr or used_vsr.
--- arch/powerpc/kvm/book3s_pr.c | 72 ++++++++++---------------------------------- arch/powerpc/kvm/booke.c | 16 ---------- arch/powerpc/kvm/booke.h | 4 ++- 3 files changed, 19 insertions(+), 73 deletions(-)
arch/powerpc/kvm/book3s_pr.c +16 -56
@@ -558,16 +558,16 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr)* both the traditional FP registers and the added VSX * registers into thread.fp_state.fpr[]. */ -if (current->thread.regs->msr &MSR_FP ) +if (t->regs->msr &MSR_FP )giveup_fpu (current); - vcpu->arch.fp = t->fp_state; + t->fp_save_area =NULL ; }#ifdef CONFIG_ALTIVEC if (msr &MSR_VEC ) {if (current->thread.regs->msr &MSR_VEC )giveup_altivec (current); - vcpu->arch.vr = t->vr_state; + t->vr_save_area =NULL ; }#endif
@@ -652,22 +652,20 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,#endif if (msr &MSR_FP ) { - t->fp_state = vcpu->arch.fp; - t->fpexc_mode =0 ;enable_kernel_fp (); -load_fp_state (&t->fp_state); +load_fp_state (&vcpu->arch.fp); + t->fp_save_area = &vcpu->arch.fp; }if (msr &MSR_VEC ) {#ifdef CONFIG_ALTIVEC - t->vr_state = vcpu->arch.vr; - t->vrsave =-1 ;enable_kernel_altivec (); -load_vr_state (&t->vr_state); +load_vr_state (&vcpu->arch.vr); + t->vr_save_area = &vcpu->arch.vr;#endif } - current->thread.regs->msr |= msr; + t->regs->msr |= msr; vcpu->arch.guest_owned_ext |= msr;kvmppc_recalc_shadow_msr (vcpu);
@@ -688,11 +686,11 @@ static void kvmppc_handle_lost_ext(struct kvm_vcpu *vcpu)if (lost_ext &MSR_FP ) {enable_kernel_fp (); -load_fp_state (¤t->thread.fp_state); +load_fp_state (&vcpu->arch.fp); }if (lost_ext &MSR_VEC ) {enable_kernel_altivec (); -load_vr_state (¤t->thread.vr_state); +load_vr_state (&vcpu->arch.vr); } current->thread.regs->msr |= lost_ext; }
@@ -1249,17 +1247,9 @@ static void enable_relon_interrupts(struct kvm *kvm)int kvmppc_vcpu_run_pr (struct kvm_run *kvm_run,struct kvm_vcpu *vcpu) {int ret; -struct thread_fp_state fp; -int fpexc_mode;#ifdef CONFIG_ALTIVEC -struct thread_vr_state vr;unsigned long uninitialized_var (vrsave ); -int used_vr;#endif -#ifdef CONFIG_VSX -int used_vsr; -#endif -ulong ext_msr;/* Check if we can run the vcpu at all */ if (!vcpu->arch.sane) {
@@ -1284,33 +1274,22 @@ int kvmppc_vcpu_run_pr(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)if (!vcpu->kvm->arch.relon_disabled)disable_relon_interrupts (vcpu->kvm); -/* Save FPU state in stack */ +/* Save FPU state in thread_struct */ if (current->thread.regs->msr &MSR_FP )giveup_fpu (current); - fp = current->thread.fp_state; - fpexc_mode = current->thread.fpexc_mode;#ifdef CONFIG_ALTIVEC -/* Save Altivec state in stack */ - used_vr = current->thread.used_vr; -if (used_vr) { -if (current->thread.regs->msr &MSR_VEC ) -giveup_altivec (current); - vr = current->thread.vr_state; - vrsave = current->thread.vrsave; - } +/* Save Altivec state in thread_struct */ +if (current->thread.regs->msr &MSR_VEC ) +giveup_altivec (current);#endif #ifdef CONFIG_VSX -/* Save VSX state in stack */ - used_vsr = current->thread.used_vsr; -if (used_vsr && (current->thread.regs->msr &MSR_VSX )) +/* Save VSX state in thread_struct */ +if (current->thread.regs->msr &MSR_VSX )__giveup_vsx (current);#endif -/* Remember the MSR with disabled extensions */ - ext_msr = current->thread.regs->msr; -/* Preload FPU if it's enabled */ if (vcpu->arch.shared->msr &MSR_FP )kvmppc_handle_ext (vcpu,BOOK3S_INTERRUPT_FP_UNAVAIL ,MSR_FP );
@@ -1325,25 +1304,6 @@ int kvmppc_vcpu_run_pr(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)/* Make sure we save the guest FPU/Altivec/VSX state */ kvmppc_giveup_ext (vcpu,MSR_FP |MSR_VEC |MSR_VSX ); - current->thread.regs->msr = ext_msr; - -/* Restore FPU/VSX state from stack */ - current->thread.fp_state = fp; - current->thread.fpexc_mode = fpexc_mode; - -#ifdef CONFIG_ALTIVEC -/* Restore Altivec state from stack */ -if (used_vr && current->thread.used_vr) { - current->thread.vr_state = vr; - current->thread.vrsave = vrsave; - } - current->thread.used_vr = used_vr; -#endif - -#ifdef CONFIG_VSX - current->thread.used_vsr = used_vsr; -#endif - out: vcpu->mode =OUTSIDE_GUEST_MODE ;return ret;
arch/powerpc/kvm/booke.c +0 -16
@@ -655,10 +655,6 @@ int kvmppc_core_check_requests(struct kvm_vcpu *vcpu)int kvmppc_vcpu_run (struct kvm_run *kvm_run,struct kvm_vcpu *vcpu) {int ret, s; -#ifdef CONFIG_PPC_FPU -struct thread_fp_state fp; -int fpexc_mode; -#endif if (!vcpu->arch.sane) { kvm_run->exit_reason =KVM_EXIT_INTERNAL_ERROR ;
@@ -676,11 +672,6 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)#ifdef CONFIG_PPC_FPU /* Save userspace FPU state in stack */ enable_kernel_fp (); - fp = current->thread.fp_state; - fpexc_mode = current->thread.fpexc_mode; - -/* Restore guest FPU state to thread */ - current->thread.fp_state = vcpu->arch.fp;/* * Since we can't trap on MSR_FP in GS-mode, we consider the guest
@@ -704,13 +695,6 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)kvmppc_save_guest_fp (vcpu); vcpu->fpu_active =0 ; - -/* Save guest FPU state from thread */ - vcpu->arch.fp = current->thread.fp_state; - -/* Restore userspace FPU state from stack */ - current->thread.fp_state = fp; - current->thread.fpexc_mode = fpexc_mode;#endif out:
arch/powerpc/kvm/booke.h +3 -1
@@ -113,7 +113,8 @@ static inline void kvmppc_load_guest_fp(struct kvm_vcpu *vcpu)#ifdef CONFIG_PPC_FPU if (vcpu->fpu_active && !(current->thread.regs->msr &MSR_FP )) {enable_kernel_fp (); -load_fp_state (¤t->thread.fp_state); +load_fp_state (&vcpu->arch.fp); + current->thread.fp_save_area = &vcpu->arch.fp; current->thread.regs->msr |=MSR_FP ; }#endif
@@ -128,6 +129,7 @@ static inline void kvmppc_save_guest_fp(struct kvm_vcpu *vcpu)#ifdef CONFIG_PPC_FPU if (vcpu->fpu_active && (current->thread.regs->msr &MSR_FP ))giveup_fpu (current); + current->thread.fp_save_area =NULL ; #endif }#endif /* __KVM_BOOKE_H__ */
Signature · 1 line
1.8.3.1
Quoted 15 lines
-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Paul Mackerras
Sent: Wednesday, August 07, 2013 9:52 AM
To: Alexander Graf; Benjamin Herrenschmidt
Cc: [email protected]; [email protected]
Subject: [PATCH RFC 0/5] Eliminate double-copying of FP/VMX/VSX stateAt present, PR KVM and BookE KVM does multiple copies of FP and related state because of the way that they use the arrays in the
thread_structas an intermediate staging post for the state. They do this so that they can use the existing system functions for loading and saving state, and so that they can keep guest state in the CPU registers while executing general kernel code.
Quoted 8 lines
This patch series reorganizes things so that KVM and the main kernel use the same representation for FP/VMX/VSX state, and so that guest state can be loaded/save directly from/to the vcpu struct instead of having to go via the
thread_struct. This simplifies things and should be a little faster.This series is against Alex Graf's kvm-ppc-queue branch plus my recent series of 23 patches to make PR and HV KVM coexist.
Nice work Paul! What do you suggest for KVM BookE AltiVec v2 patchset, should I wait for this RFC or should I go ahead with the version based on the existing infrastructure?
-Mike
Quoted 4 lines · On Wed, Aug 07, 2013 at 08:37:24AM +0000, Caraman Mihai Claudiu-B02008 wrote:
Nice work Paul! What do you suggest for KVM BookE AltiVec v2 patchset, should I wait for this RFC or should I go ahead with the version based on the existing infrastructure?
It's really up to you and whether you find that the changes I am proposing would simplify your code. If they would, please tell Alex once he's back. :)
Paul.
Quoted 11 lines
-----Original Message-----
From: Paul Mackerras [mailto:[email protected]]
Sent: Thursday, August 08, 2013 3:08 PM
To: Caraman Mihai Claudiu-B02008
Cc: Alexander Graf; Benjamin Herrenschmidt; [email protected]; [email protected]
Subject: Re: [PATCH RFC 0/5] Eliminate double-copying of FP/VMX/VSX stateQuoted 1 line · On Wed, Aug 07, 2013 at 08:37:24AM +0000, Caraman Mihai Claudiu-B02008 wrote:
Quoted 7 lines
Quoted 3 lines
Nice work Paul! What do you suggest for KVM BookE AltiVec v2 patchset, should I wait for this RFC or should I go ahead with the version based on the existing infrastructure?
It's really up to you and whether you find that the changes I am proposing would simplify your code. If they would, please tell Alex once he's back. :)
I am not sure it simplifies the code. It's a more natural (and optimized) approach to have a common structure for kernel and KVM even though this implies touching lot of code.
I don't like the idea to send the BookE AltiVec patchset just to be modified afterward but on the other hand e6500 core support depends on it and I would like to have it the next kernel release. As you suggested I would wait for Alex to comment on this.
-Mike
Quoted 7 lines
At present, PR KVM and BookE KVM does multiple copies of FP and related state because of the way that they use the arrays in the
thread_structas an intermediate staging post for the state. They do this so that they can use the existing system functions for loading and saving state, and so that they can keep guest state in the CPU registers while executing general kernel code.
Quoted 8 lines
This patch series reorganizes things so that KVM and the main kernel use the same representation for FP/VMX/VSX state, and so that guest state can be loaded/save directly from/to the vcpu struct instead of having to go via the
thread_struct. This simplifies things and should be a little faster.This series is against Alex Graf's kvm-ppc-queue branch plus my recent series of 23 patches to make PR and HV KVM coexist.
This is great!
Alex, can you pull this into your tree? It's going to be very useful for POWER8 transactional memory as we have to save another set of VSX state. The changes in 4/5 are going to make coding this up a lot cleaner
There are a lot of generic powerpc changes in here also. Perhaps, if Alex is fine with these, he can ACK them and benh can pull this in?
Mikey
Quoted 7 lines
Paul.
--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 13 lines · Michael Neuling
Quoted 13 lines
At present, PR KVM and BookE KVM does multiple copies of FP and related state because of the way that they use the arrays in the
thread_structas an intermediate staging post for the state. They do this so that they can use the existing system functions for loading and saving state, and so that they can keep guest state in the CPU registers while executing general kernel code.This patch series reorganizes things so that KVM and the main kernel use the same representation for FP/VMX/VSX state, and so that guest state can be loaded/save directly from/to the vcpu struct instead of having to go via the
thread_struct. This simplifies things and should be a little faster.
Quoted 6 lines
Quoted 2 lines
This series is against Alex Graf's kvm-ppc-queue branch plus my recent series of 23 patches to make PR and HV KVM coexist.
This is great!
Alex, can you pull this into your tree?
I never apply RFC patches if I can avoid it. Paul, if you think they're ready for inclusion, please repost them as actual patches.
Alex
Quoted 17 lines
It's going to be very useful
for POWER8 transactional memory as we have to save another set of VSX state. The changes in 4/5 are going to make coding this up a lot cleanerThere are a lot of generic powerpc changes in here also. Perhaps, if Alex is fine with these, he can ACK them and benh can pull this in?
Mikey
Quoted 7 lines
Paul.
--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 19 lines · Alexander Graf
Quoted 16 lines · Michael Neuling
Quoted 15 lines
At present, PR KVM and BookE KVM does multiple copies of FP and related state because of the way that they use the arrays in the
thread_structas an intermediate staging post for the state. They do this so that they can use the existing system functions for loading and saving state, and so that they can keep guest state in the CPU registers while executing general kernel code.This patch series reorganizes things so that KVM and the main kernel use the same representation for FP/VMX/VSX state, and so that guest state can be loaded/save directly from/to the vcpu struct instead of having to go via the
thread_struct. This simplifies things and should be a little faster.This series is against Alex Graf's kvm-ppc-queue branch plus my recent series of 23 patches to make PR and HV KVM coexist.
Quoted 6 lines
Quoted 3 lines
This is great!
Alex, can you pull this into your tree?
I never apply RFC patches if I can avoid it. Paul, if you think they're ready for inclusion, please repost them as actual patches.
Arrh, good point. I'll talk to paulus about reposting them.
Your kvm-ppc-queue branch on github seems to be based on 3.11-rc1. Is that the tree we should be aiming for currently?
Mikey
Quoted 25 lines · Michael Neuling
Quoted 23 lines · Alexander Graf
Quoted 19 lines · Michael Neuling
Quoted 7 lines
At present, PR KVM and BookE KVM does multiple copies of FP and related state because of the way that they use the arrays in the
thread_structas an intermediate staging post for the state. They do this so that they can use the existing system functions for loading and saving state, and so that they can keep guest state in the CPU registers while executing general kernel code.Quoted 8 lines
This patch series reorganizes things so that KVM and the main kernel use the same representation for FP/VMX/VSX state, and so that guest state can be loaded/save directly from/to the vcpu struct instead of having to go via the
thread_struct. This simplifies things and should be a little faster.This series is against Alex Graf's kvm-ppc-queue branch plus my recent series of 23 patches to make PR and HV KVM coexist.
This is great!
Alex, can you pull this into your tree?
Quoted 7 lines
Quoted 2 lines
I never apply RFC patches if I can avoid it. Paul, if you think they're ready for inclusion, please repost them as actual patches.
Arrh, good point. I'll talk to paulus about reposting them.
Your kvm-ppc-queue branch on github seems to be based on 3.11-rc1. Is that the tree we should be aiming for currently?
If kvm/next is newer, please base them on that for the meantime. I'll bump it up a few days after kvm/next.
Alex