Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b5510d9b authored by Hendrik Brueckner's avatar Hendrik Brueckner Committed by Martin Schwidefsky
Browse files

s390/fpu: always enable the vector facility if it is available



If the kernel detects that the s390 hardware supports the vector
facility, it is enabled by default at an early stage.  To force
it off, use the novx kernel parameter.  Note that there is a small
time window, where the vector facility is enabled before it is
forced to be off.

With enabling the vector facility by default, the FPU save and
restore functions can be improved.  They do not longer require
to manage expensive control register updates to enable or disable
the vector enablement control for particular processes.

Signed-off-by: default avatarHendrik Brueckner <brueckner@linux.vnet.ibm.com>
Reviewed-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 395e6aa1
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -46,8 +46,6 @@ static inline void __ctl_clear_bit(unsigned int cr, unsigned int bit)
	__ctl_load(reg, cr, cr);
}

void __ctl_set_vx(void);

void smp_ctl_set_bit(int cr, int bit);
void smp_ctl_clear_bit(int cr, int bit);

+2 −12
Original line number Diff line number Diff line
@@ -8,10 +8,6 @@
#ifndef _ASM_S390_FPU_INTERNAL_H
#define _ASM_S390_FPU_INTERNAL_H

#define FPU_USE_VX		1	/* Vector extension is active */

#ifndef __ASSEMBLY__

#include <linux/errno.h>
#include <linux/string.h>
#include <asm/linkage.h>
@@ -20,7 +16,6 @@

struct fpu {
	__u32 fpc;			/* Floating-point control */
	__u32 flags;
	union {
		void *regs;
		freg_t *fprs;		/* Floating-point register save area */
@@ -30,9 +25,6 @@ struct fpu {

void save_fpu_regs(void);

#define is_vx_fpu(fpu) (!!((fpu)->flags & FPU_USE_VX))
#define is_vx_task(tsk) (!!((tsk)->thread.fpu.flags & FPU_USE_VX))

/* VX array structure for address operand constraints in inline assemblies */
struct vx_array { __vector128 _[__NUM_VXRS]; };

@@ -89,7 +81,7 @@ static inline void convert_fp_to_vx(__vector128 *vxrs, freg_t *fprs)
static inline void fpregs_store(_s390_fp_regs *fpregs, struct fpu *fpu)
{
	fpregs->pad = 0;
	if (is_vx_fpu(fpu))
	if (MACHINE_HAS_VX)
		convert_vx_to_fp((freg_t *)&fpregs->fprs, fpu->vxrs);
	else
		memcpy((freg_t *)&fpregs->fprs, fpu->fprs,
@@ -98,13 +90,11 @@ static inline void fpregs_store(_s390_fp_regs *fpregs, struct fpu *fpu)

static inline void fpregs_load(_s390_fp_regs *fpregs, struct fpu *fpu)
{
	if (is_vx_fpu(fpu))
	if (MACHINE_HAS_VX)
		convert_fp_to_vx(fpu->vxrs, (freg_t *)&fpregs->fprs);
	else
		memcpy(fpu->fprs, (freg_t *)&fpregs->fprs,
		       sizeof(fpregs->fprs));
}

#endif

#endif /* _ASM_S390_FPU_INTERNAL_H */
+0 −1
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@ int main(void)
	BLANK();
	DEFINE(__THREAD_ksp, offsetof(struct thread_struct, ksp));
	DEFINE(__THREAD_FPU_fpc, offsetof(struct thread_struct, fpu.fpc));
	DEFINE(__THREAD_FPU_flags, offsetof(struct thread_struct, fpu.flags));
	DEFINE(__THREAD_FPU_regs, offsetof(struct thread_struct, fpu.regs));
	DEFINE(__THREAD_per_cause, offsetof(struct thread_struct, per_event.cause));
	DEFINE(__THREAD_per_address, offsetof(struct thread_struct, per_event.address));
+3 −4
Original line number Diff line number Diff line
@@ -249,7 +249,7 @@ static int save_sigregs_ext32(struct pt_regs *regs,
		return -EFAULT;

	/* Save vector registers to signal stack */
	if (is_vx_task(current)) {
	if (MACHINE_HAS_VX) {
		for (i = 0; i < __NUM_VXRS_LOW; i++)
			vxrs[i] = *((__u64 *)(current->thread.fpu.vxrs + i) + 1);
		if (__copy_to_user(&sregs_ext->vxrs_low, vxrs,
@@ -277,7 +277,7 @@ static int restore_sigregs_ext32(struct pt_regs *regs,
		*(__u32 *)&regs->gprs[i] = gprs_high[i];

	/* Restore vector registers from signal stack */
	if (is_vx_task(current)) {
	if (MACHINE_HAS_VX) {
		if (__copy_from_user(vxrs, &sregs_ext->vxrs_low,
				     sizeof(sregs_ext->vxrs_low)) ||
		    __copy_from_user(current->thread.fpu.vxrs + __NUM_VXRS_LOW,
@@ -470,7 +470,6 @@ static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set,
	 */
	uc_flags = UC_GPRS_HIGH;
	if (MACHINE_HAS_VX) {
		if (is_vx_task(current))
		uc_flags |= UC_VXRS;
	} else
		frame_size -= sizeof(frame->uc.uc_mcontext_ext.vxrs_low) +
+11 −1
Original line number Diff line number Diff line
@@ -329,9 +329,19 @@ static __init void detect_machine_facilities(void)
		S390_lowcore.machine_flags |= MACHINE_FLAG_TE;
	if (test_facility(51))
		S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC;
	if (test_facility(129))
	if (test_facility(129)) {
		S390_lowcore.machine_flags |= MACHINE_FLAG_VX;
		__ctl_set_bit(0, 17);
	}
}

static int __init disable_vector_extension(char *str)
{
	S390_lowcore.machine_flags &= ~MACHINE_FLAG_VX;
	__ctl_clear_bit(0, 17);
	return 1;
}
early_param("novx", disable_vector_extension);

static int __init cad_setup(char *str)
{
Loading