Skip to content

Commit e893bb1

Browse files
balbir-awsKAGA-KOKO
authored andcommitted
x86, prctl: Hook L1D flushing in via prctl
Use the existing PR_GET/SET_SPECULATION_CTRL API to expose the L1D flush capability. For L1D flushing PR_SPEC_FORCE_DISABLE and PR_SPEC_DISABLE_NOEXEC are not supported. Enabling L1D flush does not check if the task is running on an SMT enabled core, rather a check is done at runtime (at the time of flush), if the task runs on a SMT sibling then the task is sent a SIGBUS which is executed before the task returns to user space or to a guest. This is better than the other alternatives of: a. Ensuring strict affinity of the task (hard to enforce without further changes in the scheduler) b. Silently skipping flush for tasks that move to SMT enabled cores. Hook up the core prctl and implement the x86 specific parts which in turn makes it functional. Suggested-by: Thomas Gleixner <[email protected]> Signed-off-by: Balbir Singh <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent b5f06f6 commit e893bb1

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

arch/x86/kernel/cpu/bugs.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,6 +1252,24 @@ static void task_update_spec_tif(struct task_struct *tsk)
12521252
speculation_ctrl_update_current();
12531253
}
12541254

1255+
static int l1d_flush_prctl_set(struct task_struct *task, unsigned long ctrl)
1256+
{
1257+
1258+
if (!static_branch_unlikely(&switch_mm_cond_l1d_flush))
1259+
return -EPERM;
1260+
1261+
switch (ctrl) {
1262+
case PR_SPEC_ENABLE:
1263+
set_ti_thread_flag(&task->thread_info, TIF_SPEC_L1D_FLUSH);
1264+
return 0;
1265+
case PR_SPEC_DISABLE:
1266+
clear_ti_thread_flag(&task->thread_info, TIF_SPEC_L1D_FLUSH);
1267+
return 0;
1268+
default:
1269+
return -ERANGE;
1270+
}
1271+
}
1272+
12551273
static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
12561274
{
12571275
if (ssb_mode != SPEC_STORE_BYPASS_PRCTL &&
@@ -1361,6 +1379,8 @@ int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
13611379
return ssb_prctl_set(task, ctrl);
13621380
case PR_SPEC_INDIRECT_BRANCH:
13631381
return ib_prctl_set(task, ctrl);
1382+
case PR_SPEC_L1D_FLUSH:
1383+
return l1d_flush_prctl_set(task, ctrl);
13641384
default:
13651385
return -ENODEV;
13661386
}
@@ -1377,6 +1397,17 @@ void arch_seccomp_spec_mitigate(struct task_struct *task)
13771397
}
13781398
#endif
13791399

1400+
static int l1d_flush_prctl_get(struct task_struct *task)
1401+
{
1402+
if (!static_branch_unlikely(&switch_mm_cond_l1d_flush))
1403+
return PR_SPEC_FORCE_DISABLE;
1404+
1405+
if (test_ti_thread_flag(&task->thread_info, TIF_SPEC_L1D_FLUSH))
1406+
return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
1407+
else
1408+
return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
1409+
}
1410+
13801411
static int ssb_prctl_get(struct task_struct *task)
13811412
{
13821413
switch (ssb_mode) {
@@ -1427,6 +1458,8 @@ int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
14271458
return ssb_prctl_get(task);
14281459
case PR_SPEC_INDIRECT_BRANCH:
14291460
return ib_prctl_get(task);
1461+
case PR_SPEC_L1D_FLUSH:
1462+
return l1d_flush_prctl_get(task);
14301463
default:
14311464
return -ENODEV;
14321465
}

include/uapi/linux/prctl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ struct prctl_mm_map {
213213
/* Speculation control variants */
214214
# define PR_SPEC_STORE_BYPASS 0
215215
# define PR_SPEC_INDIRECT_BRANCH 1
216+
# define PR_SPEC_L1D_FLUSH 2
216217
/* Return and control values for PR_SET/GET_SPECULATION_CTRL */
217218
# define PR_SPEC_NOT_AFFECTED 0
218219
# define PR_SPEC_PRCTL (1UL << 0)

0 commit comments

Comments
 (0)