1 // SPDX-License-Identifier: GPL-2.0+
3 // Security related flags and so on.
5 // Copyright 2018, Michael Ellerman, IBM Corporation.
7 #include <linux/kernel.h>
8 #include <linux/device.h>
9 #include <linux/seq_buf.h>
11 #include <asm/debugfs.h>
12 #include <asm/security_features.h>
15 unsigned long powerpc_security_features __read_mostly
= SEC_FTR_DEFAULT
;
17 ssize_t
cpu_show_meltdown(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
21 thread_priv
= security_ftr_enabled(SEC_FTR_L1D_THREAD_PRIV
);
23 if (rfi_flush
|| thread_priv
) {
25 seq_buf_init(&s
, buf
, PAGE_SIZE
- 1);
27 seq_buf_printf(&s
, "Mitigation: ");
30 seq_buf_printf(&s
, "RFI Flush");
32 if (rfi_flush
&& thread_priv
)
33 seq_buf_printf(&s
, ", ");
36 seq_buf_printf(&s
, "L1D private per thread");
38 seq_buf_printf(&s
, "\n");
43 if (!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV
) &&
44 !security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR
))
45 return sprintf(buf
, "Not affected\n");
47 return sprintf(buf
, "Vulnerable\n");
50 ssize_t
cpu_show_spectre_v1(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
52 if (!security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR
))
53 return sprintf(buf
, "Not affected\n");
55 return sprintf(buf
, "Vulnerable\n");
58 ssize_t
cpu_show_spectre_v2(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
63 seq_buf_init(&s
, buf
, PAGE_SIZE
- 1);
65 bcs
= security_ftr_enabled(SEC_FTR_BCCTRL_SERIALISED
);
66 ccd
= security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED
);
67 ori
= security_ftr_enabled(SEC_FTR_SPEC_BAR_ORI31
);
70 seq_buf_printf(&s
, "Mitigation: ");
73 seq_buf_printf(&s
, "Indirect branch serialisation (kernel only)");
76 seq_buf_printf(&s
, ", ");
79 seq_buf_printf(&s
, "Indirect branch cache disabled");
81 seq_buf_printf(&s
, "Vulnerable");
84 seq_buf_printf(&s
, ", ori31 speculation barrier enabled");
86 seq_buf_printf(&s
, "\n");
92 * Store-forwarding barrier support.
95 static enum stf_barrier_type stf_enabled_flush_types
;
96 static bool no_stf_barrier
;
99 static int __init
handle_no_stf_barrier(char *p
)
101 pr_info("stf-barrier: disabled on command line.");
102 no_stf_barrier
= true;
106 early_param("no_stf_barrier", handle_no_stf_barrier
);
108 /* This is the generic flag used by other architectures */
109 static int __init
handle_ssbd(char *p
)
111 if (!p
|| strncmp(p
, "auto", 5) == 0 || strncmp(p
, "on", 2) == 0 ) {
112 /* Until firmware tells us, we have the barrier with auto */
114 } else if (strncmp(p
, "off", 3) == 0) {
115 handle_no_stf_barrier(NULL
);
122 early_param("spec_store_bypass_disable", handle_ssbd
);
124 /* This is the generic flag used by other architectures */
125 static int __init
handle_no_ssbd(char *p
)
127 handle_no_stf_barrier(NULL
);
130 early_param("nospec_store_bypass_disable", handle_no_ssbd
);
132 static void stf_barrier_enable(bool enable
)
135 do_stf_barrier_fixups(stf_enabled_flush_types
);
137 do_stf_barrier_fixups(STF_BARRIER_NONE
);
139 stf_barrier
= enable
;
142 void setup_stf_barrier(void)
144 enum stf_barrier_type type
;
147 hv
= cpu_has_feature(CPU_FTR_HVMODE
);
149 /* Default to fallback in case fw-features are not available */
150 if (cpu_has_feature(CPU_FTR_ARCH_300
))
151 type
= STF_BARRIER_EIEIO
;
152 else if (cpu_has_feature(CPU_FTR_ARCH_207S
))
153 type
= STF_BARRIER_SYNC_ORI
;
154 else if (cpu_has_feature(CPU_FTR_ARCH_206
))
155 type
= STF_BARRIER_FALLBACK
;
157 type
= STF_BARRIER_NONE
;
159 enable
= security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY
) &&
160 (security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR
) ||
161 (security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV
) && hv
));
163 if (type
== STF_BARRIER_FALLBACK
) {
164 pr_info("stf-barrier: fallback barrier available\n");
165 } else if (type
== STF_BARRIER_SYNC_ORI
) {
166 pr_info("stf-barrier: hwsync barrier available\n");
167 } else if (type
== STF_BARRIER_EIEIO
) {
168 pr_info("stf-barrier: eieio barrier available\n");
171 stf_enabled_flush_types
= type
;
174 stf_barrier_enable(enable
);
177 ssize_t
cpu_show_spec_store_bypass(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
179 if (stf_barrier
&& stf_enabled_flush_types
!= STF_BARRIER_NONE
) {
181 switch (stf_enabled_flush_types
) {
182 case STF_BARRIER_EIEIO
:
185 case STF_BARRIER_SYNC_ORI
:
188 case STF_BARRIER_FALLBACK
:
194 return sprintf(buf
, "Mitigation: Kernel entry/exit barrier (%s)\n", type
);
197 if (!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV
) &&
198 !security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR
))
199 return sprintf(buf
, "Not affected\n");
201 return sprintf(buf
, "Vulnerable\n");
204 #ifdef CONFIG_DEBUG_FS
205 static int stf_barrier_set(void *data
, u64 val
)
216 /* Only do anything if we're changing state */
217 if (enable
!= stf_barrier
)
218 stf_barrier_enable(enable
);
223 static int stf_barrier_get(void *data
, u64
*val
)
225 *val
= stf_barrier
? 1 : 0;
229 DEFINE_SIMPLE_ATTRIBUTE(fops_stf_barrier
, stf_barrier_get
, stf_barrier_set
, "%llu\n");
231 static __init
int stf_barrier_debugfs_init(void)
233 debugfs_create_file("stf_barrier", 0600, powerpc_debugfs_root
, NULL
, &fops_stf_barrier
);
236 device_initcall(stf_barrier_debugfs_init
);
237 #endif /* CONFIG_DEBUG_FS */