aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2013-10-15 05:43:01 -0400
committerAlexander Graf <agraf@suse.de>2014-01-09 04:14:59 -0500
commit09548fdaf32ce77a68e7f9a8a3098c1306b04858 (patch)
tree4f57c5c932068c4aae1ff0aba76dbde7614a73b3 /arch/powerpc
parentb1f0d94c26b64e814243b736f47e7ef40d96432c (diff)
KVM: PPC: Use load_fp/vr_state rather than load_up_fpu/altivec
The 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. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/kvm_book3s.h3
-rw-r--r--arch/powerpc/include/asm/switch_to.h2
-rw-r--r--arch/powerpc/kvm/book3s_exports.c4
-rw-r--r--arch/powerpc/kvm/book3s_pr.c18
-rw-r--r--arch/powerpc/kvm/book3s_rmhandlers.S47
-rw-r--r--arch/powerpc/kvm/booke.h3
6 files changed, 14 insertions, 63 deletions
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index 4a594b76674d..8bb870694616 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -186,9 +186,6 @@ extern void kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr,
186 186
187extern void kvmppc_entry_trampoline(void); 187extern void kvmppc_entry_trampoline(void);
188extern void kvmppc_hv_entry_trampoline(void); 188extern void kvmppc_hv_entry_trampoline(void);
189extern void kvmppc_load_up_fpu(void);
190extern void kvmppc_load_up_altivec(void);
191extern void kvmppc_load_up_vsx(void);
192extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst); 189extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst);
193extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst); 190extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst);
194extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd); 191extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd);
diff --git a/arch/powerpc/include/asm/switch_to.h b/arch/powerpc/include/asm/switch_to.h
index 9ee12610af02..971ca336f451 100644
--- a/arch/powerpc/include/asm/switch_to.h
+++ b/arch/powerpc/include/asm/switch_to.h
@@ -25,10 +25,8 @@ static inline void save_tar(struct thread_struct *prev)
25static inline void save_tar(struct thread_struct *prev) {} 25static inline void save_tar(struct thread_struct *prev) {}
26#endif 26#endif
27 27
28extern void load_up_fpu(void);
29extern void enable_kernel_fp(void); 28extern void enable_kernel_fp(void);
30extern void enable_kernel_altivec(void); 29extern void enable_kernel_altivec(void);
31extern void load_up_altivec(struct task_struct *);
32extern int emulate_altivec(struct pt_regs *); 30extern int emulate_altivec(struct pt_regs *);
33extern void __giveup_vsx(struct task_struct *); 31extern void __giveup_vsx(struct task_struct *);
34extern void giveup_vsx(struct task_struct *); 32extern void giveup_vsx(struct task_struct *);
diff --git a/arch/powerpc/kvm/book3s_exports.c b/arch/powerpc/kvm/book3s_exports.c
index 852989a9bad3..20d4ea8e656d 100644
--- a/arch/powerpc/kvm/book3s_exports.c
+++ b/arch/powerpc/kvm/book3s_exports.c
@@ -25,9 +25,5 @@ EXPORT_SYMBOL_GPL(kvmppc_hv_entry_trampoline);
25#endif 25#endif
26#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE 26#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
27EXPORT_SYMBOL_GPL(kvmppc_entry_trampoline); 27EXPORT_SYMBOL_GPL(kvmppc_entry_trampoline);
28EXPORT_SYMBOL_GPL(kvmppc_load_up_fpu);
29#ifdef CONFIG_ALTIVEC
30EXPORT_SYMBOL_GPL(kvmppc_load_up_altivec);
31#endif
32#endif 28#endif
33 29
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index 21bf7c5c9545..d63a91f825d3 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -691,7 +691,8 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
691#endif 691#endif
692 t->fp_state.fpscr = vcpu->arch.fpscr; 692 t->fp_state.fpscr = vcpu->arch.fpscr;
693 t->fpexc_mode = 0; 693 t->fpexc_mode = 0;
694 kvmppc_load_up_fpu(); 694 enable_kernel_fp();
695 load_fp_state(&t->fp_state);
695 } 696 }
696 697
697 if (msr & MSR_VEC) { 698 if (msr & MSR_VEC) {
@@ -699,7 +700,8 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
699 memcpy(t->vr_state.vr, vcpu->arch.vr, sizeof(vcpu->arch.vr)); 700 memcpy(t->vr_state.vr, vcpu->arch.vr, sizeof(vcpu->arch.vr));
700 t->vr_state.vscr = vcpu->arch.vscr; 701 t->vr_state.vscr = vcpu->arch.vscr;
701 t->vrsave = -1; 702 t->vrsave = -1;
702 kvmppc_load_up_altivec(); 703 enable_kernel_altivec();
704 load_vr_state(&t->vr_state);
703#endif 705#endif
704 } 706 }
705 707
@@ -722,11 +724,15 @@ static void kvmppc_handle_lost_ext(struct kvm_vcpu *vcpu)
722 if (!lost_ext) 724 if (!lost_ext)
723 return; 725 return;
724 726
725 if (lost_ext & MSR_FP) 727 if (lost_ext & MSR_FP) {
726 kvmppc_load_up_fpu(); 728 enable_kernel_fp();
729 load_fp_state(&current->thread.fp_state);
730 }
727#ifdef CONFIG_ALTIVEC 731#ifdef CONFIG_ALTIVEC
728 if (lost_ext & MSR_VEC) 732 if (lost_ext & MSR_VEC) {
729 kvmppc_load_up_altivec(); 733 enable_kernel_altivec();
734 load_vr_state(&current->thread.vr_state);
735 }
730#endif 736#endif
731 current->thread.regs->msr |= lost_ext; 737 current->thread.regs->msr |= lost_ext;
732} 738}
diff --git a/arch/powerpc/kvm/book3s_rmhandlers.S b/arch/powerpc/kvm/book3s_rmhandlers.S
index a38c4c9edab8..c78ffbc371a5 100644
--- a/arch/powerpc/kvm/book3s_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_rmhandlers.S
@@ -166,51 +166,4 @@ _GLOBAL(kvmppc_entry_trampoline)
166 mtsrr1 r6 166 mtsrr1 r6
167 RFI 167 RFI
168 168
169#if defined(CONFIG_PPC_BOOK3S_32)
170#define STACK_LR INT_FRAME_SIZE+4
171
172/* load_up_xxx have to run with MSR_DR=0 on Book3S_32 */
173#define MSR_EXT_START \
174 PPC_STL r20, _NIP(r1); \
175 mfmsr r20; \
176 LOAD_REG_IMMEDIATE(r3, MSR_DR|MSR_EE); \
177 andc r3,r20,r3; /* Disable DR,EE */ \
178 mtmsr r3; \
179 sync
180
181#define MSR_EXT_END \
182 mtmsr r20; /* Enable DR,EE */ \
183 sync; \
184 PPC_LL r20, _NIP(r1)
185
186#elif defined(CONFIG_PPC_BOOK3S_64)
187#define STACK_LR _LINK
188#define MSR_EXT_START
189#define MSR_EXT_END
190#endif
191
192/*
193 * Activate current's external feature (FPU/Altivec/VSX)
194 */
195#define define_load_up(what) \
196 \
197_GLOBAL(kvmppc_load_up_ ## what); \
198 PPC_STLU r1, -INT_FRAME_SIZE(r1); \
199 mflr r3; \
200 PPC_STL r3, STACK_LR(r1); \
201 MSR_EXT_START; \
202 \
203 bl FUNC(load_up_ ## what); \
204 \
205 MSR_EXT_END; \
206 PPC_LL r3, STACK_LR(r1); \
207 mtlr r3; \
208 addi r1, r1, INT_FRAME_SIZE; \
209 blr
210
211define_load_up(fpu)
212#ifdef CONFIG_ALTIVEC
213define_load_up(altivec)
214#endif
215
216#include "book3s_segment.S" 169#include "book3s_segment.S"
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
index 09bfd9bc7cf8..fe59f225327f 100644
--- a/arch/powerpc/kvm/booke.h
+++ b/arch/powerpc/kvm/booke.h
@@ -136,7 +136,8 @@ static inline void kvmppc_load_guest_fp(struct kvm_vcpu *vcpu)
136{ 136{
137#ifdef CONFIG_PPC_FPU 137#ifdef CONFIG_PPC_FPU
138 if (vcpu->fpu_active && !(current->thread.regs->msr & MSR_FP)) { 138 if (vcpu->fpu_active && !(current->thread.regs->msr & MSR_FP)) {
139 load_up_fpu(); 139 enable_kernel_fp();
140 load_fp_state(&current->thread.fp_state);
140 current->thread.regs->msr |= MSR_FP; 141 current->thread.regs->msr |= MSR_FP;
141 } 142 }
142#endif 143#endif