Merge tag 'ieee802154-for-davem-2019-11-13' of git://git.kernel.org/pub/scm/linux...
[linux-2.6-microblaze.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/prctl.h>
9 #include <linux/sched.h>
10 #include <linux/sched/task_stack.h>
11 #include <linux/thread_info.h>
12
13 #include <asm/cpufeature.h>
14
15 static void ssbd_ssbs_enable(struct task_struct *task)
16 {
17         u64 val = is_compat_thread(task_thread_info(task)) ?
18                   PSR_AA32_SSBS_BIT : PSR_SSBS_BIT;
19
20         task_pt_regs(task)->pstate |= val;
21 }
22
23 static void ssbd_ssbs_disable(struct task_struct *task)
24 {
25         u64 val = is_compat_thread(task_thread_info(task)) ?
26                   PSR_AA32_SSBS_BIT : PSR_SSBS_BIT;
27
28         task_pt_regs(task)->pstate &= ~val;
29 }
30
31 /*
32  * prctl interface for SSBD
33  */
34 static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl)
35 {
36         int state = arm64_get_ssbd_state();
37
38         /* Unsupported */
39         if (state == ARM64_SSBD_UNKNOWN)
40                 return -EINVAL;
41
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;
50                 }
51         }
52
53         /*
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.
57          */
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;
85         }
86
87         return 0;
88 }
89
90 int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
91                              unsigned long ctrl)
92 {
93         switch (which) {
94         case PR_SPEC_STORE_BYPASS:
95                 return ssbd_prctl_set(task, ctrl);
96         default:
97                 return -ENODEV;
98         }
99 }
100
101 static int ssbd_prctl_get(struct task_struct *task)
102 {
103         switch (arm64_get_ssbd_state()) {
104         case ARM64_SSBD_UNKNOWN:
105                 return -EINVAL;
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;
118         }
119 }
120
121 int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
122 {
123         switch (which) {
124         case PR_SPEC_STORE_BYPASS:
125                 return ssbd_prctl_get(task);
126         default:
127                 return -ENODEV;
128         }
129 }