Home Home > GIT Browse > SLE11-SP4
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2018-06-08 15:34:34 +0200
committerJiri Kosina <jkosina@suse.cz>2018-06-08 15:34:34 +0200
commit649255e04b6f3965bc83988fb8a55c0149c3a1df (patch)
treeeea51ebe80d91217c5d8f3ec9ddcdee7e51d36fa
parent840f2b9c88feefae3618c1881380b13be96e0234 (diff)
parent0833bf42e4b3e0806c8554382b5d8a723749d256 (diff)
Merge remote-tracking branch 'origin/users/msuchanek/SLE11-SP4/for-next' into SLE11-SP4
-rw-r--r--arch/powerpc/include/asm/exception-64s.h6
-rw-r--r--arch/powerpc/include/asm/security_features.h11
-rw-r--r--arch/powerpc/include/asm/setup.h12
-rw-r--r--arch/powerpc/kernel/security.c151
-rw-r--r--arch/powerpc/kernel/setup_64.c120
-rw-r--r--arch/powerpc/lib/feature-fixups.c1
6 files changed, 172 insertions, 129 deletions
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
index 074462348848..cfdba7295c02 100644
--- a/arch/powerpc/include/asm/exception-64s.h
+++ b/arch/powerpc/include/asm/exception-64s.h
@@ -54,9 +54,9 @@
#define STF_ENTRY_BARRIER_SLOT \
STF_ENTRY_BARRIER_FIXUP_SECTION; \
- mflr r10; \
- bl stf_barrier_fallback; \
- mtlr r10
+ nop; \
+ nop; \
+ nop
#define STF_EXIT_BARRIER_SLOT \
STF_EXIT_BARRIER_FIXUP_SECTION; \
diff --git a/arch/powerpc/include/asm/security_features.h b/arch/powerpc/include/asm/security_features.h
index fa4d2e1cf772..44989b22383c 100644
--- a/arch/powerpc/include/asm/security_features.h
+++ b/arch/powerpc/include/asm/security_features.h
@@ -12,6 +12,17 @@
extern unsigned long powerpc_security_features;
extern bool rfi_flush;
+/* These are bit flags */
+enum stf_barrier_type {
+ STF_BARRIER_NONE = 0x1,
+ STF_BARRIER_FALLBACK = 0x2,
+ STF_BARRIER_EIEIO = 0x4,
+ STF_BARRIER_SYNC_ORI = 0x8,
+};
+
+void setup_stf_barrier(void);
+void do_stf_barrier_fixups(enum stf_barrier_type types);
+
static inline void security_ftr_set(unsigned long feature)
{
powerpc_security_features |= feature;
diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h
index f94982c5b1a8..ee02b4ac321a 100644
--- a/arch/powerpc/include/asm/setup.h
+++ b/arch/powerpc/include/asm/setup.h
@@ -9,17 +9,9 @@ void check_for_initrd(void);
void do_init_bootmem(void);
void setup_panic(void);
-/* These are bit flags */
-enum stf_barrier_type {
- STF_BARRIER_NONE = 0x1,
- STF_BARRIER_FALLBACK = 0x2,
- STF_BARRIER_EIEIO = 0x4,
- STF_BARRIER_SYNC_ORI = 0x8,
-};
-
-void setup_stf_barrier(void);
-void do_stf_barrier_fixups(enum stf_barrier_type types);
+void rfi_flush_enable(bool enable);
+/* These are bit flags */
enum l1d_flush_type {
L1D_FLUSH_NONE = 0x1,
L1D_FLUSH_FALLBACK = 0x2,
diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c
index bd4894034af7..b340a611b4ca 100644
--- a/arch/powerpc/kernel/security.c
+++ b/arch/powerpc/kernel/security.c
@@ -158,3 +158,154 @@ ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, c
return s.len;
}
+
+/*
+ * Store-forwarding barrier support.
+ */
+
+static enum stf_barrier_type stf_enabled_flush_types;
+static bool no_stf_barrier;
+bool stf_barrier;
+
+static int __init handle_no_stf_barrier(char *p)
+{
+ pr_info("stf-barrier: disabled on command line.");
+ no_stf_barrier = true;
+ return 0;
+}
+
+early_param("no_stf_barrier", handle_no_stf_barrier);
+
+/* This is the generic flag used by other architectures */
+static int __init handle_ssbd(char *p)
+{
+ if (!p || strncmp(p, "auto", 5) == 0 || strncmp(p, "on", 2) == 0 ) {
+ /* Until firmware tells us, we have the barrier with auto */
+ return 0;
+ } else if (strncmp(p, "off", 3) == 0) {
+ handle_no_stf_barrier(NULL);
+ return 0;
+ } else
+ return 1;
+
+ return 0;
+}
+early_param("spec_store_bypass_disable", handle_ssbd);
+
+/* This is the generic flag used by other architectures */
+static int __init handle_no_ssbd(char *p)
+{
+ handle_no_stf_barrier(NULL);
+ return 0;
+}
+early_param("nospec_store_bypass_disable", handle_no_ssbd);
+
+static void stf_barrier_enable(bool enable)
+{
+ if (enable)
+ do_stf_barrier_fixups(stf_enabled_flush_types);
+ else
+ do_stf_barrier_fixups(STF_BARRIER_NONE);
+
+ stf_barrier = enable;
+}
+
+void setup_stf_barrier(void)
+{
+ enum stf_barrier_type type;
+ bool enable, hv;
+
+ hv = cpu_has_feature(CPU_FTR_HVMODE);
+
+ /* Default to fallback in case fw-features are not available */
+#ifdef CPU_FTR_ARCH_300
+ if (cpu_has_feature(CPU_FTR_ARCH_300))
+ type = STF_BARRIER_EIEIO;
+ else
+#endif
+ if (cpu_has_feature(CPU_FTR_ARCH_207S))
+ type = STF_BARRIER_SYNC_ORI;
+ else if (cpu_has_feature(CPU_FTR_ARCH_206))
+ type = STF_BARRIER_FALLBACK;
+ else
+ type = STF_BARRIER_NONE;
+
+ enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
+ (security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR) ||
+ (security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) && hv));
+
+ if (type == STF_BARRIER_FALLBACK) {
+ pr_info("stf-barrier: fallback barrier available\n");
+ } else if (type == STF_BARRIER_SYNC_ORI) {
+ pr_info("stf-barrier: hwsync barrier available\n");
+ } else if (type == STF_BARRIER_EIEIO) {
+ pr_info("stf-barrier: eieio barrier available\n");
+ }
+
+ stf_enabled_flush_types = type;
+
+ if (!no_stf_barrier)
+ stf_barrier_enable(enable);
+}
+
+ssize_t cpu_show_spec_store_bypass(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ if (stf_barrier && stf_enabled_flush_types != STF_BARRIER_NONE) {
+ const char *type;
+ switch (stf_enabled_flush_types) {
+ case STF_BARRIER_EIEIO:
+ type = "eieio";
+ break;
+ case STF_BARRIER_SYNC_ORI:
+ type = "hwsync";
+ break;
+ case STF_BARRIER_FALLBACK:
+ type = "fallback";
+ break;
+ default:
+ type = "unknown";
+ }
+ return sprintf(buf, "Mitigation: Kernel entry/exit barrier (%s)\n", type);
+ }
+
+ if (!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) &&
+ !security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR))
+ return sprintf(buf, "Not affected\n");
+
+ return sprintf(buf, "Vulnerable\n");
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int stf_barrier_set(void *data, u64 val)
+{
+ bool enable;
+
+ if (val == 1)
+ enable = true;
+ else if (val == 0)
+ enable = false;
+ else
+ return -EINVAL;
+
+ /* Only do anything if we're changing state */
+ if (enable != stf_barrier)
+ stf_barrier_enable(enable);
+
+ return 0;
+}
+
+static int stf_barrier_get(void *data, u64 *val)
+{
+ *val = stf_barrier ? 1 : 0;
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_stf_barrier, stf_barrier_get, stf_barrier_set, "%llu\n");
+
+static __init int stf_barrier_debugfs_init(void)
+{
+ debugfs_create_file("stf_barrier", 0600, powerpc_debugfs_root, NULL, &fops_stf_barrier);
+ return 0;
+}
+device_initcall(stf_barrier_debugfs_init);
+#endif /* CONFIG_DEBUG_FS */
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 136e526e6eb5..40de4cb7a830 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -65,7 +65,6 @@
#include <asm/kexec.h>
#include <asm/mmu_context.h>
#include <asm/code-patching.h>
-#include <asm/security_features.h>
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
@@ -675,48 +674,11 @@ EXPORT_SYMBOL(ppc_pci_io);
#endif /* CONFIG_PPC_INDIRECT_IO */
#ifdef CONFIG_PPC_BOOK3S_64
-static enum stf_barrier_type stf_enabled_flush_types;
-static bool no_stf_barrier;
-bool stf_barrier;
-
-static enum l1d_flush_type rfi_enabled_flush_types;
+static enum l1d_flush_type enabled_flush_types;
static void *l1d_flush_fallback_area;
static bool no_rfi_flush;
bool rfi_flush;
-static int __init handle_no_stf_barrier(char *p)
-{
- pr_info("stf-barrier: disabled on command line.");
- no_stf_barrier = true;
- return 0;
-}
-
-early_param("no_stf_barrier", handle_no_stf_barrier);
-
-/* This is the generic flag used by other architectures */
-static int __init handle_ssbd(char *p)
-{
- if (!p || strncmp(p, "off", 3) == 0) {
- handle_no_stf_barrier(NULL);
- return 0;
- } else if (strncmp(p, "auto", 5) == 0 || strncmp(p, "on", 2) == 0 )
- /* Until firmware tells us, we have the barrier with auto */
- return 0;
- else
- return 1;
-
- return 0;
-}
-early_param("spec_store_bypass_disable", handle_ssbd);
-
-/* This is the generic flag used by other architectures */
-static int __init handle_no_ssbd(char *p)
-{
- handle_no_stf_barrier(NULL);
- return 0;
-}
-early_param("nospec_store_bypass_disable", handle_no_ssbd);
-
static int __init handle_no_rfi_flush(char *p)
{
pr_info("rfi-flush: disabled on command line.");
@@ -745,21 +707,10 @@ static void do_nothing(void *unused)
*/
}
-static void stf_barrier_enable(bool enable)
-{
- if (enable) {
- do_stf_barrier_fixups(stf_enabled_flush_types);
- on_each_cpu(do_nothing, NULL, 1);
- } else
- do_stf_barrier_fixups(STF_BARRIER_NONE);
-
- stf_barrier = enable;
-}
-
-static void rfi_flush_enable(bool enable)
+void rfi_flush_enable(bool enable)
{
if (enable) {
- do_rfi_flush_fixups(rfi_enabled_flush_types);
+ do_rfi_flush_fixups(enabled_flush_types);
on_each_cpu(do_nothing, NULL, 1);
} else
do_rfi_flush_fixups(L1D_FLUSH_NONE);
@@ -767,42 +718,6 @@ static void rfi_flush_enable(bool enable)
rfi_flush = enable;
}
-void setup_stf_barrier(void)
-{
- enum stf_barrier_type type;
- bool enable;
-
- /* Default to fallback in case fw-features are not available */
-#ifdef CPU_FTR_ARCH_300 /* POWER9 support */
- if (cpu_has_feature(CPU_FTR_ARCH_300))
- type = STF_BARRIER_EIEIO;
- else
-#endif
- if (cpu_has_feature(CPU_FTR_ARCH_207S))
- type = STF_BARRIER_SYNC_ORI;
- /* CPU_FTR_HVMODE_206 only set in hv mode */
- else if (cpu_has_feature(CPU_FTR_ASYM_SMT))
- type = STF_BARRIER_FALLBACK;
- else
- type = STF_BARRIER_NONE;
-
- enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
- (security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR));
-
- if (type == STF_BARRIER_FALLBACK) {
- pr_info("stf-barrier: fallback barrier available\n");
- } else if (type == STF_BARRIER_SYNC_ORI) {
- pr_info("stf-barrier: hwsync barrier available\n");
- } else if (type == STF_BARRIER_EIEIO) {
- pr_info("stf-barrier: eieio barrier available\n");
- }
-
- stf_enabled_flush_types = type;
-
- if (!no_stf_barrier)
- stf_barrier_enable(enable);
-}
-
static void __ref init_fallback_flush(void)
{
u64 l1d_size, limit;
@@ -844,39 +759,13 @@ void setup_rfi_flush(enum l1d_flush_type types, bool enable)
if (types & L1D_FLUSH_MTTRIG)
pr_info("rfi-flush: mttrig type flush available\n");
- rfi_enabled_flush_types = types;
+ enabled_flush_types = types;
if (!no_rfi_flush)
rfi_flush_enable(enable);
}
#ifdef CONFIG_DEBUG_FS
-static int stf_barrier_set(void *data, u64 val)
-{
- bool enable;
-
- if (val == 1)
- enable = true;
- else if (val == 0)
- enable = false;
- else
- return -EINVAL;
-
- /* Only do anything if we're changing state */
- if (enable != stf_barrier)
- stf_barrier_enable(enable);
-
- return 0;
-}
-
-static int stf_barrier_get(void *data, u64 *val)
-{
- *val = stf_barrier ? 1 : 0;
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(fops_stf_barrier, stf_barrier_get, stf_barrier_set, "%llu\n");
-
static int rfi_flush_set(void *data, u64 val)
{
bool enable;
@@ -906,7 +795,6 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_rfi_flush, rfi_flush_get, rfi_flush_set, "%llu\n");
static __init int rfi_flush_debugfs_init(void)
{
debugfs_create_file("rfi_flush", 0600, powerpc_debugfs_root, NULL, &fops_rfi_flush);
- debugfs_create_file("stf_barrier", 0600, powerpc_debugfs_root, NULL, &fops_stf_barrier);
return 0;
}
device_initcall(rfi_flush_debugfs_init);
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index 6fb164040918..776d218a3c73 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -21,6 +21,7 @@
#include <asm/page.h>
#include <asm/sections.h>
#include <asm/setup.h>
+#include <asm/security_features.h>
struct fixup_entry {