treewide: remove redundant IS_ERR() before error code check
[linux/fpc-iii.git] / arch / arm64 / kernel / ssbd.c
blobb26955f567501cc7103435a459dde7700dffba18
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2018 ARM Ltd, All Rights Reserved.
4 */
6 #include <linux/compat.h>
7 #include <linux/errno.h>
8 #include <linux/prctl.h>
9 #include <linux/sched.h>
10 #include <linux/sched/task_stack.h>
11 #include <linux/thread_info.h>
13 #include <asm/cpufeature.h>
15 static void ssbd_ssbs_enable(struct task_struct *task)
17 u64 val = is_compat_thread(task_thread_info(task)) ?
18 PSR_AA32_SSBS_BIT : PSR_SSBS_BIT;
20 task_pt_regs(task)->pstate |= val;
23 static void ssbd_ssbs_disable(struct task_struct *task)
25 u64 val = is_compat_thread(task_thread_info(task)) ?
26 PSR_AA32_SSBS_BIT : PSR_SSBS_BIT;
28 task_pt_regs(task)->pstate &= ~val;
32 * prctl interface for SSBD
34 static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl)
36 int state = arm64_get_ssbd_state();
38 /* Unsupported */
39 if (state == ARM64_SSBD_UNKNOWN)
40 return -ENODEV;
42 /* Treat the unaffected/mitigated state separately */
43 if (state == ARM64_SSBD_MITIGATED) {
44 switch (ctrl) {
45 case PR_SPEC_ENABLE:
46 return -EPERM;
47 case PR_SPEC_DISABLE:
48 case PR_SPEC_FORCE_DISABLE:
49 return 0;
54 * Things are a bit backward here: the arm64 internal API
55 * *enables the mitigation* when the userspace API *disables
56 * speculation*. So much fun.
58 switch (ctrl) {
59 case PR_SPEC_ENABLE:
60 /* If speculation is force disabled, enable is not allowed */
61 if (state == ARM64_SSBD_FORCE_ENABLE ||
62 task_spec_ssb_force_disable(task))
63 return -EPERM;
64 task_clear_spec_ssb_disable(task);
65 clear_tsk_thread_flag(task, TIF_SSBD);
66 ssbd_ssbs_enable(task);
67 break;
68 case PR_SPEC_DISABLE:
69 if (state == ARM64_SSBD_FORCE_DISABLE)
70 return -EPERM;
71 task_set_spec_ssb_disable(task);
72 set_tsk_thread_flag(task, TIF_SSBD);
73 ssbd_ssbs_disable(task);
74 break;
75 case PR_SPEC_FORCE_DISABLE:
76 if (state == ARM64_SSBD_FORCE_DISABLE)
77 return -EPERM;
78 task_set_spec_ssb_disable(task);
79 task_set_spec_ssb_force_disable(task);
80 set_tsk_thread_flag(task, TIF_SSBD);
81 ssbd_ssbs_disable(task);
82 break;
83 default:
84 return -ERANGE;
87 return 0;
90 int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
91 unsigned long ctrl)
93 switch (which) {
94 case PR_SPEC_STORE_BYPASS:
95 return ssbd_prctl_set(task, ctrl);
96 default:
97 return -ENODEV;
101 static int ssbd_prctl_get(struct task_struct *task)
103 switch (arm64_get_ssbd_state()) {
104 case ARM64_SSBD_UNKNOWN:
105 return -ENODEV;
106 case ARM64_SSBD_FORCE_ENABLE:
107 return PR_SPEC_DISABLE;
108 case ARM64_SSBD_KERNEL:
109 if (task_spec_ssb_force_disable(task))
110 return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
111 if (task_spec_ssb_disable(task))
112 return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
113 return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
114 case ARM64_SSBD_FORCE_DISABLE:
115 return PR_SPEC_ENABLE;
116 default:
117 return PR_SPEC_NOT_AFFECTED;
121 int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
123 switch (which) {
124 case PR_SPEC_STORE_BYPASS:
125 return ssbd_prctl_get(task);
126 default:
127 return -ENODEV;