Adapted from the RFI implementation Signed-off-by: Michal Suchanek <msucha...@suse.de> --- arch/powerpc/platforms/pseries/mobility.c | 2 +- arch/powerpc/platforms/pseries/pseries.h | 2 +- arch/powerpc/platforms/pseries/setup.c | 37 ++++++++++++++++++++++--------- 3 files changed, 29 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c index 8a8033a249c7..9d506be1580e 100644 --- a/arch/powerpc/platforms/pseries/mobility.c +++ b/arch/powerpc/platforms/pseries/mobility.c @@ -349,7 +349,7 @@ void post_mobility_fixup(void) "failed: %d\n", rc); /* Possibly switch to a new RFI flush type */ - pseries_setup_rfi_flush(); + pseries_setup_rfi_nospec(); return; } diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index 27cdcb69fd18..d49670c67686 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h @@ -100,6 +100,6 @@ static inline unsigned long cmo_get_page_size(void) int dlpar_workqueue_init(void); -void pseries_setup_rfi_flush(void); +void pseries_setup_rfi_nospec(void); #endif /* _PSERIES_PSERIES_H */ diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 9877c3dfcdc8..4b899a4db6dd 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -459,30 +459,47 @@ static void __init find_and_init_phbs(void) of_pci_check_probe_only(); } -void pseries_setup_rfi_flush(void) +void pseries_setup_rfi_nospec(void) { struct h_cpu_char_result result; - enum l1d_flush_type types; - bool enable; + enum l1d_flush_type flush_types; + enum spec_barrier_type barrier_type; + bool flush_enable; + bool barrier_enable; long rc; /* Enable by default */ - enable = true; - types = L1D_FLUSH_FALLBACK; + flush_enable = true; + flush_types = L1D_FLUSH_FALLBACK; + barrier_enable = true; + /* no fallback available if the firmware does not tell us */ + barrier_type = SPEC_BARRIER_NONE; rc = plpar_get_cpu_characteristics(&result); if (rc == H_SUCCESS) { if (result.character & H_CPU_CHAR_L1D_FLUSH_TRIG2) - types |= L1D_FLUSH_MTTRIG; + flush_types |= L1D_FLUSH_MTTRIG; if (result.character & H_CPU_CHAR_L1D_FLUSH_ORI30) - types |= L1D_FLUSH_ORI; + flush_types |= L1D_FLUSH_ORI; + if (result.character & H_CPU_CHAR_SPEC_BAR_ORI31) + barrier_type |= SPEC_BARRIER_ORI; if ((!(result.behaviour & H_CPU_BEHAV_L1D_FLUSH_PR)) || (!(result.behaviour & H_CPU_BEHAV_FAVOUR_SECURITY))) - enable = false; + flush_enable = false; + /* + * Do not check H_CPU_BEHAV_BNDS_CHK_SPEC_BAR - the ORI does + * nothing anyway when not supported. + */ + if ((!(result.behaviour & H_CPU_BEHAV_FAVOUR_SECURITY))) + barrier_enable = false; + } else { + /* Default to fallback if case hcall is not available */ + flush_types = L1D_FLUSH_FALLBACK; } - setup_rfi_flush(types, enable); + setup_barrier_nospec(barrier_type, barrier_enable); + setup_rfi_flush(flush_types, flush_enable); } #ifdef CONFIG_PCI_IOV @@ -658,7 +675,7 @@ static void __init pSeries_setup_arch(void) fwnmi_init(); - pseries_setup_rfi_flush(); + pseries_setup_rfi_nospec(); /* By default, only probe PCI (can be overridden by rtas_pci) */ pci_add_flags(PCI_PROBE_ONLY); -- 2.13.6