]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - arch/powerpc/platforms/pseries/setup.c
Merge tag 'powerpc-4.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
[linux.git] / arch / powerpc / platforms / pseries / setup.c
index 1a527625acf78dea27f7bde430e23f02f12f5baf..b55ad4286dc7f81f0c9d2e7d130860757773c3b3 100644 (file)
@@ -68,6 +68,7 @@
 #include <asm/plpar_wrappers.h>
 #include <asm/kexec.h>
 #include <asm/isa-bridge.h>
+#include <asm/security_features.h>
 
 #include "pseries.h"
 
@@ -246,7 +247,7 @@ static int alloc_dispatch_logs(void)
                return 0;
 
        for_each_possible_cpu(cpu) {
-               pp = &paca[cpu];
+               pp = paca_ptrs[cpu];
                dtl = kmem_cache_alloc(dtl_cache, GFP_KERNEL);
                if (!dtl) {
                        pr_warn("Failed to allocate dispatch trace log for cpu %d\n",
@@ -459,36 +460,78 @@ static void __init find_and_init_phbs(void)
        of_pci_check_probe_only();
 }
 
-static void pseries_setup_rfi_flush(void)
+static void init_cpu_char_feature_flags(struct h_cpu_char_result *result)
+{
+       /*
+        * The features below are disabled by default, so we instead look to see
+        * if firmware has *enabled* them, and set them if so.
+        */
+       if (result->character & H_CPU_CHAR_SPEC_BAR_ORI31)
+               security_ftr_set(SEC_FTR_SPEC_BAR_ORI31);
+
+       if (result->character & H_CPU_CHAR_BCCTRL_SERIALISED)
+               security_ftr_set(SEC_FTR_BCCTRL_SERIALISED);
+
+       if (result->character & H_CPU_CHAR_L1D_FLUSH_ORI30)
+               security_ftr_set(SEC_FTR_L1D_FLUSH_ORI30);
+
+       if (result->character & H_CPU_CHAR_L1D_FLUSH_TRIG2)
+               security_ftr_set(SEC_FTR_L1D_FLUSH_TRIG2);
+
+       if (result->character & H_CPU_CHAR_L1D_THREAD_PRIV)
+               security_ftr_set(SEC_FTR_L1D_THREAD_PRIV);
+
+       if (result->character & H_CPU_CHAR_COUNT_CACHE_DISABLED)
+               security_ftr_set(SEC_FTR_COUNT_CACHE_DISABLED);
+
+       /*
+        * The features below are enabled by default, so we instead look to see
+        * if firmware has *disabled* them, and clear them if so.
+        */
+       if (!(result->behaviour & H_CPU_BEHAV_FAVOUR_SECURITY))
+               security_ftr_clear(SEC_FTR_FAVOUR_SECURITY);
+
+       if (!(result->behaviour & H_CPU_BEHAV_L1D_FLUSH_PR))
+               security_ftr_clear(SEC_FTR_L1D_FLUSH_PR);
+
+       if (!(result->behaviour & H_CPU_BEHAV_BNDS_CHK_SPEC_BAR))
+               security_ftr_clear(SEC_FTR_BNDS_CHK_SPEC_BAR);
+}
+
+void pseries_setup_rfi_flush(void)
 {
        struct h_cpu_char_result result;
        enum l1d_flush_type types;
        bool enable;
        long rc;
 
-       /* Enable by default */
-       enable = true;
+       /*
+        * Set features to the defaults assumed by init_cpu_char_feature_flags()
+        * so it can set/clear again any features that might have changed after
+        * migration, and in case the hypercall fails and it is not even called.
+        */
+       powerpc_security_features = SEC_FTR_DEFAULT;
 
        rc = plpar_get_cpu_characteristics(&result);
-       if (rc == H_SUCCESS) {
-               types = L1D_FLUSH_NONE;
+       if (rc == H_SUCCESS)
+               init_cpu_char_feature_flags(&result);
 
-               if (result.character & H_CPU_CHAR_L1D_FLUSH_TRIG2)
-                       types |= L1D_FLUSH_MTTRIG;
-               if (result.character & H_CPU_CHAR_L1D_FLUSH_ORI30)
-                       types |= L1D_FLUSH_ORI;
+       /*
+        * We're the guest so this doesn't apply to us, clear it to simplify
+        * handling of it elsewhere.
+        */
+       security_ftr_clear(SEC_FTR_L1D_FLUSH_HV);
 
-               /* Use fallback if nothing set in hcall */
-               if (types == L1D_FLUSH_NONE)
-                       types = L1D_FLUSH_FALLBACK;
+       types = L1D_FLUSH_FALLBACK;
 
-               if ((!(result.behaviour & H_CPU_BEHAV_L1D_FLUSH_PR)) ||
-                   (!(result.behaviour & H_CPU_BEHAV_FAVOUR_SECURITY)))
-                       enable = false;
-       } else {
-               /* Default to fallback if case hcall is not available */
-               types = L1D_FLUSH_FALLBACK;
-       }
+       if (security_ftr_enabled(SEC_FTR_L1D_FLUSH_TRIG2))
+               types |= L1D_FLUSH_MTTRIG;
+
+       if (security_ftr_enabled(SEC_FTR_L1D_FLUSH_ORI30))
+               types |= L1D_FLUSH_ORI;
+
+       enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && \
+                security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR);
 
        setup_rfi_flush(types, enable);
 }
@@ -739,7 +782,7 @@ static int pseries_set_dawr(unsigned long dawr, unsigned long dawrx)
        /* PAPR says we can't set HYP */
        dawrx &= ~DAWRX_HYP;
 
-       return  plapr_set_watchpoint0(dawr, dawrx);
+       return  plpar_set_watchpoint0(dawr, dawrx);
 }
 
 #define CMO_CHARACTERISTICS_TOKEN 44