Skip to content

Commit 50f408d

Browse files
Kan LiangPeter Zijlstra
authored andcommitted
x86/fpu/xstate: Add helpers for LBR dynamic supervisor feature
The perf subsystem will only need to save/restore the LBR state. However, the existing helpers save all supported supervisor states to a kernel buffer, which will be unnecessary. Two helpers are introduced to only save/restore requested dynamic supervisor states. The supervisor features in XFEATURE_MASK_SUPERVISOR_SUPPORTED and XFEATURE_MASK_SUPERVISOR_UNSUPPORTED mask cannot be saved/restored using these helpers. The helpers will be used in the following patch. Signed-off-by: Kan Liang <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Dave Hansen <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent f0dccc9 commit 50f408d

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

arch/x86/include/asm/fpu/xstate.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ int copy_xstate_to_user(void __user *ubuf, struct xregs_state *xsave, unsigned i
106106
int copy_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf);
107107
int copy_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf);
108108
void copy_supervisor_to_kernel(struct xregs_state *xsave);
109+
void copy_dynamic_supervisor_to_kernel(struct xregs_state *xstate, u64 mask);
110+
void copy_kernel_to_dynamic_supervisor(struct xregs_state *xstate, u64 mask);
111+
109112

110113
/* Validate an xstate header supplied by userspace (ptrace or sigreturn) */
111114
int validate_user_xstate_header(const struct xstate_header *hdr);

arch/x86/kernel/fpu/xstate.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,6 +1361,78 @@ void copy_supervisor_to_kernel(struct xregs_state *xstate)
13611361
}
13621362
}
13631363

1364+
/**
1365+
* copy_dynamic_supervisor_to_kernel() - Save dynamic supervisor states to
1366+
* an xsave area
1367+
* @xstate: A pointer to an xsave area
1368+
* @mask: Represent the dynamic supervisor features saved into the xsave area
1369+
*
1370+
* Only the dynamic supervisor states sets in the mask are saved into the xsave
1371+
* area (See the comment in XFEATURE_MASK_DYNAMIC for the details of dynamic
1372+
* supervisor feature). Besides the dynamic supervisor states, the legacy
1373+
* region and XSAVE header are also saved into the xsave area. The supervisor
1374+
* features in the XFEATURE_MASK_SUPERVISOR_SUPPORTED and
1375+
* XFEATURE_MASK_SUPERVISOR_UNSUPPORTED are not saved.
1376+
*
1377+
* The xsave area must be 64-bytes aligned.
1378+
*/
1379+
void copy_dynamic_supervisor_to_kernel(struct xregs_state *xstate, u64 mask)
1380+
{
1381+
u64 dynamic_mask = xfeatures_mask_dynamic() & mask;
1382+
u32 lmask, hmask;
1383+
int err;
1384+
1385+
if (WARN_ON_FPU(!boot_cpu_has(X86_FEATURE_XSAVES)))
1386+
return;
1387+
1388+
if (WARN_ON_FPU(!dynamic_mask))
1389+
return;
1390+
1391+
lmask = dynamic_mask;
1392+
hmask = dynamic_mask >> 32;
1393+
1394+
XSTATE_OP(XSAVES, xstate, lmask, hmask, err);
1395+
1396+
/* Should never fault when copying to a kernel buffer */
1397+
WARN_ON_FPU(err);
1398+
}
1399+
1400+
/**
1401+
* copy_kernel_to_dynamic_supervisor() - Restore dynamic supervisor states from
1402+
* an xsave area
1403+
* @xstate: A pointer to an xsave area
1404+
* @mask: Represent the dynamic supervisor features restored from the xsave area
1405+
*
1406+
* Only the dynamic supervisor states sets in the mask are restored from the
1407+
* xsave area (See the comment in XFEATURE_MASK_DYNAMIC for the details of
1408+
* dynamic supervisor feature). Besides the dynamic supervisor states, the
1409+
* legacy region and XSAVE header are also restored from the xsave area. The
1410+
* supervisor features in the XFEATURE_MASK_SUPERVISOR_SUPPORTED and
1411+
* XFEATURE_MASK_SUPERVISOR_UNSUPPORTED are not restored.
1412+
*
1413+
* The xsave area must be 64-bytes aligned.
1414+
*/
1415+
void copy_kernel_to_dynamic_supervisor(struct xregs_state *xstate, u64 mask)
1416+
{
1417+
u64 dynamic_mask = xfeatures_mask_dynamic() & mask;
1418+
u32 lmask, hmask;
1419+
int err;
1420+
1421+
if (WARN_ON_FPU(!boot_cpu_has(X86_FEATURE_XSAVES)))
1422+
return;
1423+
1424+
if (WARN_ON_FPU(!dynamic_mask))
1425+
return;
1426+
1427+
lmask = dynamic_mask;
1428+
hmask = dynamic_mask >> 32;
1429+
1430+
XSTATE_OP(XRSTORS, xstate, lmask, hmask, err);
1431+
1432+
/* Should never fault when copying from a kernel buffer */
1433+
WARN_ON_FPU(err);
1434+
}
1435+
13641436
#ifdef CONFIG_PROC_PID_ARCH_STATUS
13651437
/*
13661438
* Report the amount of time elapsed in millisecond since last AVX512

0 commit comments

Comments
 (0)