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

Commit 8e221b6d authored by Suresh Siddha's avatar Suresh Siddha Committed by H. Peter Anvin
Browse files

x86: Avoid unnecessary __clear_user() and xrstor in signal handling



fxsave/xsave doesn't touch all the bytes in the memory layout used by
these instructions. Specifically SW reserved (bytes 464..511) fields
in the fxsave frame and the reserved fields in the xsave header.

To present a clean context for the signal handling, just clear these fields
instead of clearing the complete fxsave/xsave memory layout, when we dump these
registers directly to the user signal frame.

Also avoid the call to second xrstor (which inits the state not passed
in the signal frame) in restore_user_xstate() if all the state has already
been restored by the first xrstor.

These changes improve the performance of signal handling(by ~3-5% as measured
by the lat_sig).

Signed-off-by: default avatarSuresh Siddha <suresh.b.siddha@intel.com>
LKML-Reference: <1277249017.2847.85.camel@sbs-t61.sc.intel.com>
Signed-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
parent 815c4163
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -127,6 +127,15 @@ static inline int fxsave_user(struct i387_fxsave_struct __user *fx)
{
	int err;

	/*
	 * Clear the bytes not touched by the fxsave and reserved
	 * for the SW usage.
	 */
	err = __clear_user(&fx->sw_reserved,
			   sizeof(struct _fpx_sw_bytes));
	if (unlikely(err))
		return -EFAULT;

	asm volatile("1:  rex64/fxsave (%[fx])\n\t"
		     "2:\n"
		     ".section .fixup,\"ax\"\n"
+10 −0
Original line number Diff line number Diff line
@@ -59,6 +59,16 @@ static inline int fpu_xrstor_checking(struct fpu *fpu)
static inline int xsave_user(struct xsave_struct __user *buf)
{
	int err;

	/*
	 * Clear the xsave header first, so that reserved fields are
	 * initialized to zero.
	 */
	err = __clear_user(&buf->xsave_hdr,
			   sizeof(struct xsave_hdr_struct));
	if (unlikely(err))
		return -EFAULT;

	__asm__ __volatile__("1: .byte " REX_PREFIX "0x0f,0xae,0x27\n"
			     "2:\n"
			     ".section .fixup,\"ax\"\n"
+2 −10
Original line number Diff line number Diff line
@@ -91,14 +91,6 @@ int save_i387_xstate(void __user *buf)
		return 0;

	if (task_thread_info(tsk)->status & TS_USEDFPU) {
		/*
	 	 * Start with clearing the user buffer. This will present a
	 	 * clean context for the bytes not touched by the fxsave/xsave.
		 */
		err = __clear_user(buf, sig_xstate_size);
		if (err)
			return err;

		if (use_xsave())
			err = xsave_user(buf);
		else
@@ -184,7 +176,7 @@ static int restore_user_xstate(void __user *buf)
	 * init the state skipped by the user.
	 */
	mask = pcntxt_mask & ~mask;

	if (unlikely(mask))
		xrstor_state(init_xstate_buf, mask);

	return 0;