19a868f63SMichael Ellerman // SPDX-License-Identifier: GPL-2.0+ 29a868f63SMichael Ellerman // 39a868f63SMichael Ellerman // Security related flags and so on. 49a868f63SMichael Ellerman // 59a868f63SMichael Ellerman // Copyright 2018, Michael Ellerman, IBM Corporation. 69a868f63SMichael Ellerman 79a868f63SMichael Ellerman #include <linux/kernel.h> 88ad33041SMichael Ellerman #include <linux/device.h> 9ff348355SMichael Ellerman #include <linux/seq_buf.h> 108ad33041SMichael Ellerman 11cb3d6759SMichal Suchanek #include <asm/debugfs.h> 129a868f63SMichael Ellerman #include <asm/security_features.h> 132eea7f06SMichal Suchanek #include <asm/setup.h> 149a868f63SMichael Ellerman 159a868f63SMichael Ellerman 16e7347a86SMauricio Faria de Oliveira unsigned long powerpc_security_features __read_mostly = SEC_FTR_DEFAULT; 178ad33041SMichael Ellerman 18815069caSMichal Suchanek bool barrier_nospec_enabled; 192eea7f06SMichal Suchanek 202eea7f06SMichal Suchanek static void enable_barrier_nospec(bool enable) 212eea7f06SMichal Suchanek { 222eea7f06SMichal Suchanek barrier_nospec_enabled = enable; 232eea7f06SMichal Suchanek do_barrier_nospec_fixups(enable); 242eea7f06SMichal Suchanek } 252eea7f06SMichal Suchanek 26cb3d6759SMichal Suchanek void setup_barrier_nospec(void) 27cb3d6759SMichal Suchanek { 28cb3d6759SMichal Suchanek bool enable; 29cb3d6759SMichal Suchanek 30cb3d6759SMichal Suchanek /* 31cb3d6759SMichal Suchanek * It would make sense to check SEC_FTR_SPEC_BAR_ORI31 below as well. 32cb3d6759SMichal Suchanek * But there's a good reason not to. The two flags we check below are 33cb3d6759SMichal Suchanek * both are enabled by default in the kernel, so if the hcall is not 34cb3d6759SMichal Suchanek * functional they will be enabled. 35cb3d6759SMichal Suchanek * On a system where the host firmware has been updated (so the ori 36cb3d6759SMichal Suchanek * functions as a barrier), but on which the hypervisor (KVM/Qemu) has 37cb3d6759SMichal Suchanek * not been updated, we would like to enable the barrier. Dropping the 38cb3d6759SMichal Suchanek * check for SEC_FTR_SPEC_BAR_ORI31 achieves that. The only downside is 39cb3d6759SMichal Suchanek * we potentially enable the barrier on systems where the host firmware 40cb3d6759SMichal Suchanek * is not updated, but that's harmless as it's a no-op. 41cb3d6759SMichal Suchanek */ 42cb3d6759SMichal Suchanek enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && 43cb3d6759SMichal Suchanek security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR); 44cb3d6759SMichal Suchanek 45cb3d6759SMichal Suchanek enable_barrier_nospec(enable); 46cb3d6759SMichal Suchanek } 47cb3d6759SMichal Suchanek 48cb3d6759SMichal Suchanek #ifdef CONFIG_DEBUG_FS 49cb3d6759SMichal Suchanek static int barrier_nospec_set(void *data, u64 val) 50cb3d6759SMichal Suchanek { 51cb3d6759SMichal Suchanek switch (val) { 52cb3d6759SMichal Suchanek case 0: 53cb3d6759SMichal Suchanek case 1: 54cb3d6759SMichal Suchanek break; 55cb3d6759SMichal Suchanek default: 56cb3d6759SMichal Suchanek return -EINVAL; 57cb3d6759SMichal Suchanek } 58cb3d6759SMichal Suchanek 59cb3d6759SMichal Suchanek if (!!val == !!barrier_nospec_enabled) 60cb3d6759SMichal Suchanek return 0; 61cb3d6759SMichal Suchanek 62cb3d6759SMichal Suchanek enable_barrier_nospec(!!val); 63cb3d6759SMichal Suchanek 64cb3d6759SMichal Suchanek return 0; 65cb3d6759SMichal Suchanek } 66cb3d6759SMichal Suchanek 67cb3d6759SMichal Suchanek static int barrier_nospec_get(void *data, u64 *val) 68cb3d6759SMichal Suchanek { 69cb3d6759SMichal Suchanek *val = barrier_nospec_enabled ? 1 : 0; 70cb3d6759SMichal Suchanek return 0; 71cb3d6759SMichal Suchanek } 72cb3d6759SMichal Suchanek 73cb3d6759SMichal Suchanek DEFINE_SIMPLE_ATTRIBUTE(fops_barrier_nospec, 74cb3d6759SMichal Suchanek barrier_nospec_get, barrier_nospec_set, "%llu\n"); 75cb3d6759SMichal Suchanek 76cb3d6759SMichal Suchanek static __init int barrier_nospec_debugfs_init(void) 77cb3d6759SMichal Suchanek { 78cb3d6759SMichal Suchanek debugfs_create_file("barrier_nospec", 0600, powerpc_debugfs_root, NULL, 79cb3d6759SMichal Suchanek &fops_barrier_nospec); 80cb3d6759SMichal Suchanek return 0; 81cb3d6759SMichal Suchanek } 82cb3d6759SMichal Suchanek device_initcall(barrier_nospec_debugfs_init); 83cb3d6759SMichal Suchanek #endif /* CONFIG_DEBUG_FS */ 84cb3d6759SMichal Suchanek 858ad33041SMichael Ellerman ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf) 868ad33041SMichael Ellerman { 87ff348355SMichael Ellerman bool thread_priv; 88ff348355SMichael Ellerman 89ff348355SMichael Ellerman thread_priv = security_ftr_enabled(SEC_FTR_L1D_THREAD_PRIV); 90ff348355SMichael Ellerman 91ff348355SMichael Ellerman if (rfi_flush || thread_priv) { 92ff348355SMichael Ellerman struct seq_buf s; 93ff348355SMichael Ellerman seq_buf_init(&s, buf, PAGE_SIZE - 1); 94ff348355SMichael Ellerman 95ff348355SMichael Ellerman seq_buf_printf(&s, "Mitigation: "); 96ff348355SMichael Ellerman 978ad33041SMichael Ellerman if (rfi_flush) 98ff348355SMichael Ellerman seq_buf_printf(&s, "RFI Flush"); 99ff348355SMichael Ellerman 100ff348355SMichael Ellerman if (rfi_flush && thread_priv) 101ff348355SMichael Ellerman seq_buf_printf(&s, ", "); 102ff348355SMichael Ellerman 103ff348355SMichael Ellerman if (thread_priv) 104ff348355SMichael Ellerman seq_buf_printf(&s, "L1D private per thread"); 105ff348355SMichael Ellerman 106ff348355SMichael Ellerman seq_buf_printf(&s, "\n"); 107ff348355SMichael Ellerman 108ff348355SMichael Ellerman return s.len; 109ff348355SMichael Ellerman } 110ff348355SMichael Ellerman 111ff348355SMichael Ellerman if (!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) && 112ff348355SMichael Ellerman !security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR)) 113ff348355SMichael Ellerman return sprintf(buf, "Not affected\n"); 1148ad33041SMichael Ellerman 1158ad33041SMichael Ellerman return sprintf(buf, "Vulnerable\n"); 1168ad33041SMichael Ellerman } 11756986016SMichael Ellerman 11856986016SMichael Ellerman ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr, char *buf) 11956986016SMichael Ellerman { 12056986016SMichael Ellerman if (!security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR)) 12156986016SMichael Ellerman return sprintf(buf, "Not affected\n"); 12256986016SMichael Ellerman 123*a3775145SMichal Suchanek if (barrier_nospec_enabled) 124*a3775145SMichal Suchanek return sprintf(buf, "Mitigation: __user pointer sanitization\n"); 125*a3775145SMichal Suchanek 12656986016SMichael Ellerman return sprintf(buf, "Vulnerable\n"); 12756986016SMichael Ellerman } 128d6fbe1c5SMichael Ellerman 129d6fbe1c5SMichael Ellerman ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, char *buf) 130d6fbe1c5SMichael Ellerman { 131d6fbe1c5SMichael Ellerman bool bcs, ccd, ori; 132d6fbe1c5SMichael Ellerman struct seq_buf s; 133d6fbe1c5SMichael Ellerman 134d6fbe1c5SMichael Ellerman seq_buf_init(&s, buf, PAGE_SIZE - 1); 135d6fbe1c5SMichael Ellerman 136d6fbe1c5SMichael Ellerman bcs = security_ftr_enabled(SEC_FTR_BCCTRL_SERIALISED); 137d6fbe1c5SMichael Ellerman ccd = security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED); 138d6fbe1c5SMichael Ellerman ori = security_ftr_enabled(SEC_FTR_SPEC_BAR_ORI31); 139d6fbe1c5SMichael Ellerman 140d6fbe1c5SMichael Ellerman if (bcs || ccd) { 141d6fbe1c5SMichael Ellerman seq_buf_printf(&s, "Mitigation: "); 142d6fbe1c5SMichael Ellerman 143d6fbe1c5SMichael Ellerman if (bcs) 144d6fbe1c5SMichael Ellerman seq_buf_printf(&s, "Indirect branch serialisation (kernel only)"); 145d6fbe1c5SMichael Ellerman 146d6fbe1c5SMichael Ellerman if (bcs && ccd) 147d6fbe1c5SMichael Ellerman seq_buf_printf(&s, ", "); 148d6fbe1c5SMichael Ellerman 149d6fbe1c5SMichael Ellerman if (ccd) 150d6fbe1c5SMichael Ellerman seq_buf_printf(&s, "Indirect branch cache disabled"); 151d6fbe1c5SMichael Ellerman } else 152d6fbe1c5SMichael Ellerman seq_buf_printf(&s, "Vulnerable"); 153d6fbe1c5SMichael Ellerman 154d6fbe1c5SMichael Ellerman if (ori) 155d6fbe1c5SMichael Ellerman seq_buf_printf(&s, ", ori31 speculation barrier enabled"); 156d6fbe1c5SMichael Ellerman 157d6fbe1c5SMichael Ellerman seq_buf_printf(&s, "\n"); 158d6fbe1c5SMichael Ellerman 159d6fbe1c5SMichael Ellerman return s.len; 160d6fbe1c5SMichael Ellerman } 161