1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2018 ARM Ltd, All Rights Reserved.
6 #include <linux/compat.h>
7 #include <linux/errno.h>
8 #include <linux/sched.h>
9 #include <linux/sched/task_stack.h>
10 #include <linux/thread_info.h>
12 #include <asm/cpufeature.h>
14 static void ssbd_ssbs_enable(struct task_struct *task)
16 u64 val = is_compat_thread(task_thread_info(task)) ?
17 PSR_AA32_SSBS_BIT : PSR_SSBS_BIT;
19 task_pt_regs(task)->pstate |= val;
22 static void ssbd_ssbs_disable(struct task_struct *task)
24 u64 val = is_compat_thread(task_thread_info(task)) ?
25 PSR_AA32_SSBS_BIT : PSR_SSBS_BIT;
27 task_pt_regs(task)->pstate &= ~val;
31 * prctl interface for SSBD
33 static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl)
35 int state = arm64_get_ssbd_state();
38 if (state == ARM64_SSBD_UNKNOWN)
41 /* Treat the unaffected/mitigated state separately */
42 if (state == ARM64_SSBD_MITIGATED) {
47 case PR_SPEC_FORCE_DISABLE:
53 * Things are a bit backward here: the arm64 internal API
54 * *enables the mitigation* when the userspace API *disables
55 * speculation*. So much fun.
59 /* If speculation is force disabled, enable is not allowed */
60 if (state == ARM64_SSBD_FORCE_ENABLE ||
61 task_spec_ssb_force_disable(task))
63 task_clear_spec_ssb_disable(task);
64 clear_tsk_thread_flag(task, TIF_SSBD);
65 ssbd_ssbs_enable(task);
68 if (state == ARM64_SSBD_FORCE_DISABLE)
70 task_set_spec_ssb_disable(task);
71 set_tsk_thread_flag(task, TIF_SSBD);
72 ssbd_ssbs_disable(task);
74 case PR_SPEC_FORCE_DISABLE:
75 if (state == ARM64_SSBD_FORCE_DISABLE)
77 task_set_spec_ssb_disable(task);
78 task_set_spec_ssb_force_disable(task);
79 set_tsk_thread_flag(task, TIF_SSBD);
80 ssbd_ssbs_disable(task);
89 int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
93 case PR_SPEC_STORE_BYPASS:
94 return ssbd_prctl_set(task, ctrl);
100 static int ssbd_prctl_get(struct task_struct *task)
102 switch (arm64_get_ssbd_state()) {
103 case ARM64_SSBD_UNKNOWN:
105 case ARM64_SSBD_FORCE_ENABLE:
106 return PR_SPEC_DISABLE;
107 case ARM64_SSBD_KERNEL:
108 if (task_spec_ssb_force_disable(task))
109 return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
110 if (task_spec_ssb_disable(task))
111 return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
112 return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
113 case ARM64_SSBD_FORCE_DISABLE:
114 return PR_SPEC_ENABLE;
116 return PR_SPEC_NOT_AFFECTED;
120 int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
123 case PR_SPEC_STORE_BYPASS:
124 return ssbd_prctl_get(task);