Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc: create giveup_all()

Create a single function that gives everything up (FP, VMX, VSX, SPE).
Doing this all at once means we only do one MSR write.

A context switch microbenchmark using yield():

http://ozlabs.org/~anton/junkcode/context_switch2.c

./context_switch2 --test=yield --fp --altivec --vector 0 0

shows an improvement of 3% on POWER8.

Signed-off-by: Anton Blanchard <anton@samba.org>
[mpe: giveup_all() needs to be EXPORT_SYMBOL'ed]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

Anton Blanchard and committed by
Michael Ellerman
c2085059 1f2e25b2

+64 -30
+1
arch/powerpc/include/asm/switch_to.h
··· 26 26 extern void giveup_vsx(struct task_struct *); 27 27 extern void enable_kernel_spe(void); 28 28 extern void load_up_spe(struct task_struct *); 29 + extern void giveup_all(struct task_struct *); 29 30 extern void switch_booke_debug_regs(struct debug_reg *new_debug); 30 31 31 32 #ifdef CONFIG_PPC_FPU
+61 -15
arch/powerpc/kernel/process.c
··· 308 308 } 309 309 #endif /* CONFIG_SPE */ 310 310 311 + static unsigned long msr_all_available; 312 + 313 + static int __init init_msr_all_available(void) 314 + { 315 + #ifdef CONFIG_PPC_FPU 316 + msr_all_available |= MSR_FP; 317 + #endif 318 + #ifdef CONFIG_ALTIVEC 319 + if (cpu_has_feature(CPU_FTR_ALTIVEC)) 320 + msr_all_available |= MSR_VEC; 321 + #endif 322 + #ifdef CONFIG_VSX 323 + if (cpu_has_feature(CPU_FTR_VSX)) 324 + msr_all_available |= MSR_VSX; 325 + #endif 326 + #ifdef CONFIG_SPE 327 + if (cpu_has_feature(CPU_FTR_SPE)) 328 + msr_all_available |= MSR_SPE; 329 + #endif 330 + 331 + return 0; 332 + } 333 + early_initcall(init_msr_all_available); 334 + 335 + void giveup_all(struct task_struct *tsk) 336 + { 337 + unsigned long usermsr; 338 + 339 + if (!tsk->thread.regs) 340 + return; 341 + 342 + usermsr = tsk->thread.regs->msr; 343 + 344 + if ((usermsr & msr_all_available) == 0) 345 + return; 346 + 347 + msr_check_and_set(msr_all_available); 348 + 349 + #ifdef CONFIG_PPC_FPU 350 + if (usermsr & MSR_FP) 351 + __giveup_fpu(tsk); 352 + #endif 353 + #ifdef CONFIG_ALTIVEC 354 + if (usermsr & MSR_VEC) 355 + __giveup_altivec(tsk); 356 + #endif 357 + #ifdef CONFIG_VSX 358 + if (usermsr & MSR_VSX) 359 + __giveup_vsx(tsk); 360 + #endif 361 + #ifdef CONFIG_SPE 362 + if (usermsr & MSR_SPE) 363 + __giveup_spe(tsk); 364 + #endif 365 + 366 + msr_check_and_clear(msr_all_available); 367 + } 368 + EXPORT_SYMBOL(giveup_all); 369 + 311 370 #ifdef CONFIG_PPC_ADV_DEBUG_REGS 312 371 void do_send_trap(struct pt_regs *regs, unsigned long address, 313 372 unsigned long error_code, int signal_code, int breakpt) ··· 898 839 899 840 __switch_to_tm(prev); 900 841 901 - if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP)) 902 - giveup_fpu(prev); 903 - #ifdef CONFIG_ALTIVEC 904 - if (prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)) 905 - giveup_altivec(prev); 906 - #endif /* CONFIG_ALTIVEC */ 907 - #ifdef CONFIG_VSX 908 - if (prev->thread.regs && (prev->thread.regs->msr & MSR_VSX)) 909 - /* VMX and FPU registers are already save here */ 910 - __giveup_vsx(prev); 911 - #endif /* CONFIG_VSX */ 912 - #ifdef CONFIG_SPE 913 - if ((prev->thread.regs && (prev->thread.regs->msr & MSR_SPE))) 914 - giveup_spe(prev); 915 - #endif /* CONFIG_SPE */ 842 + /* Save FPU, Altivec, VSX and SPE state */ 843 + giveup_all(prev); 916 844 917 845 #ifdef CONFIG_PPC_ADV_DEBUG_REGS 918 846 switch_booke_debug_regs(&new->thread.debug);
+2 -15
arch/powerpc/kvm/book3s_pr.c
··· 1490 1490 goto out; 1491 1491 /* interrupts now hard-disabled */ 1492 1492 1493 - /* Save FPU state in thread_struct */ 1494 - if (current->thread.regs->msr & MSR_FP) 1495 - giveup_fpu(current); 1496 - 1497 - #ifdef CONFIG_ALTIVEC 1498 - /* Save Altivec state in thread_struct */ 1499 - if (current->thread.regs->msr & MSR_VEC) 1500 - giveup_altivec(current); 1501 - #endif 1502 - 1503 - #ifdef CONFIG_VSX 1504 - /* Save VSX state in thread_struct */ 1505 - if (current->thread.regs->msr & MSR_VSX) 1506 - __giveup_vsx(current); 1507 - #endif 1493 + /* Save FPU, Altivec and VSX state */ 1494 + giveup_all(current); 1508 1495 1509 1496 /* Preload FPU if it's enabled */ 1510 1497 if (kvmppc_get_msr(vcpu) & MSR_FP)