Merge tag 'nfsd-4.20' of git://linux-nfs.org/~bfields/linux
[sfrench/cifs-2.6.git] / arch / arm64 / kernel / ssbd.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2018 ARM Ltd, All Rights Reserved.
4  */
5
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>
11
12 #include <asm/cpufeature.h>
13
14 static void ssbd_ssbs_enable(struct task_struct *task)
15 {
16         u64 val = is_compat_thread(task_thread_info(task)) ?
17                   PSR_AA32_SSBS_BIT : PSR_SSBS_BIT;
18
19         task_pt_regs(task)->pstate |= val;
20 }
21
22 static void ssbd_ssbs_disable(struct task_struct *task)
23 {
24         u64 val = is_compat_thread(task_thread_info(task)) ?
25                   PSR_AA32_SSBS_BIT : PSR_SSBS_BIT;
26
27         task_pt_regs(task)->pstate &= ~val;
28 }
29
30 /*
31  * prctl interface for SSBD
32  */
33 static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl)
34 {
35         int state = arm64_get_ssbd_state();
36
37         /* Unsupported */
38         if (state == ARM64_SSBD_UNKNOWN)
39                 return -EINVAL;
40
41         /* Treat the unaffected/mitigated state separately */
42         if (state == ARM64_SSBD_MITIGATED) {
43                 switch (ctrl) {
44                 case PR_SPEC_ENABLE:
45                         return -EPERM;
46                 case PR_SPEC_DISABLE:
47                 case PR_SPEC_FORCE_DISABLE:
48                         return 0;
49                 }
50         }
51
52         /*
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.
56          */
57         switch (ctrl) {
58         case PR_SPEC_ENABLE:
59                 /* If speculation is force disabled, enable is not allowed */
60                 if (state == ARM64_SSBD_FORCE_ENABLE ||
61                     task_spec_ssb_force_disable(task))
62                         return -EPERM;
63                 task_clear_spec_ssb_disable(task);
64                 clear_tsk_thread_flag(task, TIF_SSBD);
65                 ssbd_ssbs_enable(task);
66                 break;
67         case PR_SPEC_DISABLE:
68                 if (state == ARM64_SSBD_FORCE_DISABLE)
69                         return -EPERM;
70                 task_set_spec_ssb_disable(task);
71                 set_tsk_thread_flag(task, TIF_SSBD);
72                 ssbd_ssbs_disable(task);
73                 break;
74         case PR_SPEC_FORCE_DISABLE:
75                 if (state == ARM64_SSBD_FORCE_DISABLE)
76                         return -EPERM;
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);
81                 break;
82         default:
83                 return -ERANGE;
84         }
85
86         return 0;
87 }
88
89 int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
90                              unsigned long ctrl)
91 {
92         switch (which) {
93         case PR_SPEC_STORE_BYPASS:
94                 return ssbd_prctl_set(task, ctrl);
95         default:
96                 return -ENODEV;
97         }
98 }
99
100 static int ssbd_prctl_get(struct task_struct *task)
101 {
102         switch (arm64_get_ssbd_state()) {
103         case ARM64_SSBD_UNKNOWN:
104                 return -EINVAL;
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;
115         default:
116                 return PR_SPEC_NOT_AFFECTED;
117         }
118 }
119
120 int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
121 {
122         switch (which) {
123         case PR_SPEC_STORE_BYPASS:
124                 return ssbd_prctl_get(task);
125         default:
126                 return -ENODEV;
127         }
128 }