Diana Madalina Craciun <diana.craciun@xxxxxxx> writes: > Hi Michael, > > There are some missing NXP Spectre v2 patches. I can send them > separately if the series will be accepted. I have merged them, but I did > not test them, I was sick today and incapable of doing that. No worries, there's no rush :) Sorry I missed them, I thought I had a list that included everything. Which commits was it I missed? I guess post them as a reply to this thread? That way whether the series is merged by Greg or not, there's a record here of what the backports look like. cheers > On 4/21/2019 5:21 PM, Michael Ellerman wrote: >> -----BEGIN PGP SIGNED MESSAGE----- >> Hash: SHA1 >> >> Hi Greg/Sasha, >> >> Please queue up these powerpc patches for 4.4 if you have no objections. >> >> cheers >> >> >> Christophe Leroy (1): >> powerpc/fsl: Fix the flush of branch predictor. >> >> Diana Craciun (10): >> powerpc/64: Disable the speculation barrier from the command line >> powerpc/64: Make stf barrier PPC_BOOK3S_64 specific. >> powerpc/64: Make meltdown reporting Book3S 64 specific >> powerpc/fsl: Add barrier_nospec implementation for NXP PowerPC Book3E >> powerpc/fsl: Add infrastructure to fixup branch predictor flush >> powerpc/fsl: Add macro to flush the branch predictor >> powerpc/fsl: Fix spectre_v2 mitigations reporting >> powerpc/fsl: Add nospectre_v2 command line argument >> powerpc/fsl: Flush the branch predictor at each kernel entry (64bit) >> powerpc/fsl: Update Spectre v2 reporting >> >> Mauricio Faria de Oliveira (4): >> powerpc/rfi-flush: Differentiate enabled and patched flush types >> powerpc/pseries: Fix clearing of security feature flags >> powerpc: Move default security feature flags >> powerpc/pseries: Restore default security feature flags on setup >> >> Michael Ellerman (29): >> powerpc/xmon: Add RFI flush related fields to paca dump >> powerpc/pseries: Support firmware disable of RFI flush >> powerpc/powernv: Support firmware disable of RFI flush >> powerpc/rfi-flush: Move the logic to avoid a redo into the debugfs >> code >> powerpc/rfi-flush: Make it possible to call setup_rfi_flush() again >> powerpc/rfi-flush: Always enable fallback flush on pseries >> powerpc/pseries: Add new H_GET_CPU_CHARACTERISTICS flags >> powerpc/rfi-flush: Call setup_rfi_flush() after LPM migration >> powerpc: Add security feature flags for Spectre/Meltdown >> powerpc/pseries: Set or clear security feature flags >> powerpc/powernv: Set or clear security feature flags >> powerpc/64s: Move cpu_show_meltdown() >> powerpc/64s: Enhance the information in cpu_show_meltdown() >> powerpc/powernv: Use the security flags in pnv_setup_rfi_flush() >> powerpc/pseries: Use the security flags in pseries_setup_rfi_flush() >> powerpc/64s: Wire up cpu_show_spectre_v1() >> powerpc/64s: Wire up cpu_show_spectre_v2() >> powerpc/64s: Fix section mismatch warnings from setup_rfi_flush() >> powerpc/64: Use barrier_nospec in syscall entry >> powerpc: Use barrier_nospec in copy_from_user() >> powerpc64s: Show ori31 availability in spectre_v1 sysfs file not v2 >> powerpc/64: Add CONFIG_PPC_BARRIER_NOSPEC >> powerpc/64: Call setup_barrier_nospec() from setup_arch() >> powerpc/asm: Add a patch_site macro & helpers for patching >> instructions >> powerpc/64s: Add new security feature flags for count cache flush >> powerpc/64s: Add support for software count cache flush >> powerpc/pseries: Query hypervisor for count cache flush settings >> powerpc/powernv: Query firmware for count cache flush settings >> powerpc/security: Fix spectre_v2 reporting >> >> Michael Neuling (1): >> powerpc: Avoid code patching freed init sections >> >> Michal Suchanek (5): >> powerpc/64s: Add barrier_nospec >> powerpc/64s: Add support for ori barrier_nospec patching >> powerpc/64s: Patch barrier_nospec in modules >> powerpc/64s: Enable barrier_nospec based on firmware settings >> powerpc/64s: Enhance the information in cpu_show_spectre_v1() >> >> Nicholas Piggin (2): >> powerpc/64s: Improve RFI L1-D cache flush fallback >> powerpc/64s: Add support for a store forwarding barrier at kernel >> entry/exit >> >> arch/powerpc/Kconfig | 7 +- >> arch/powerpc/include/asm/asm-prototypes.h | 21 + >> arch/powerpc/include/asm/barrier.h | 21 + >> arch/powerpc/include/asm/code-patching-asm.h | 18 + >> arch/powerpc/include/asm/code-patching.h | 2 + >> arch/powerpc/include/asm/exception-64s.h | 35 ++ >> arch/powerpc/include/asm/feature-fixups.h | 40 ++ >> arch/powerpc/include/asm/hvcall.h | 5 + >> arch/powerpc/include/asm/paca.h | 3 +- >> arch/powerpc/include/asm/ppc-opcode.h | 1 + >> arch/powerpc/include/asm/ppc_asm.h | 11 + >> arch/powerpc/include/asm/security_features.h | 92 ++++ >> arch/powerpc/include/asm/setup.h | 23 +- >> arch/powerpc/include/asm/uaccess.h | 18 +- >> arch/powerpc/kernel/Makefile | 1 + >> arch/powerpc/kernel/asm-offsets.c | 3 +- >> arch/powerpc/kernel/entry_64.S | 69 +++ >> arch/powerpc/kernel/exceptions-64e.S | 27 +- >> arch/powerpc/kernel/exceptions-64s.S | 98 +++-- >> arch/powerpc/kernel/module.c | 10 +- >> arch/powerpc/kernel/security.c | 433 +++++++++++++++++++ >> arch/powerpc/kernel/setup_32.c | 2 + >> arch/powerpc/kernel/setup_64.c | 50 +-- >> arch/powerpc/kernel/vmlinux.lds.S | 33 +- >> arch/powerpc/lib/code-patching.c | 29 ++ >> arch/powerpc/lib/feature-fixups.c | 218 +++++++++- >> arch/powerpc/mm/mem.c | 2 + >> arch/powerpc/mm/tlb_low_64e.S | 7 + >> arch/powerpc/platforms/powernv/setup.c | 99 +++-- >> arch/powerpc/platforms/pseries/mobility.c | 3 + >> arch/powerpc/platforms/pseries/pseries.h | 2 + >> arch/powerpc/platforms/pseries/setup.c | 88 +++- >> arch/powerpc/xmon/xmon.c | 2 + >> 33 files changed, 1345 insertions(+), 128 deletions(-) >> create mode 100644 arch/powerpc/include/asm/asm-prototypes.h >> create mode 100644 arch/powerpc/include/asm/code-patching-asm.h >> create mode 100644 arch/powerpc/include/asm/security_features.h >> create mode 100644 arch/powerpc/kernel/security.c >> >> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig >> index 58a1fa979655..01b6c00a7060 100644 >> - --- a/arch/powerpc/Kconfig >> +++ b/arch/powerpc/Kconfig >> @@ -136,7 +136,7 @@ config PPC >> select GENERIC_SMP_IDLE_THREAD >> select GENERIC_CMOS_UPDATE >> select GENERIC_TIME_VSYSCALL_OLD >> - - select GENERIC_CPU_VULNERABILITIES if PPC_BOOK3S_64 >> + select GENERIC_CPU_VULNERABILITIES if PPC_BARRIER_NOSPEC >> select GENERIC_CLOCKEVENTS >> select GENERIC_CLOCKEVENTS_BROADCAST if SMP >> select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST >> @@ -162,6 +162,11 @@ config PPC >> select ARCH_HAS_DMA_SET_COHERENT_MASK >> select HAVE_ARCH_SECCOMP_FILTER >> >> +config PPC_BARRIER_NOSPEC >> + bool >> + default y >> + depends on PPC_BOOK3S_64 || PPC_FSL_BOOK3E >> + >> config GENERIC_CSUM >> def_bool CPU_LITTLE_ENDIAN >> >> diff --git a/arch/powerpc/include/asm/asm-prototypes.h b/arch/powerpc/include/asm/asm-prototypes.h >> new file mode 100644 >> index 000000000000..8944c55591cf >> - --- /dev/null >> +++ b/arch/powerpc/include/asm/asm-prototypes.h >> @@ -0,0 +1,21 @@ >> +#ifndef _ASM_POWERPC_ASM_PROTOTYPES_H >> +#define _ASM_POWERPC_ASM_PROTOTYPES_H >> +/* >> + * This file is for prototypes of C functions that are only called >> + * from asm, and any associated variables. >> + * >> + * Copyright 2016, Daniel Axtens, IBM Corporation. >> + * >> + * This program is free software; you can redistribute it and/or >> + * modify it under the terms of the GNU General Public License >> + * as published by the Free Software Foundation; either version 2 >> + * of the License, or (at your option) any later version. >> + */ >> + >> +/* Patch sites */ >> +extern s32 patch__call_flush_count_cache; >> +extern s32 patch__flush_count_cache_return; >> + >> +extern long flush_count_cache; >> + >> +#endif /* _ASM_POWERPC_ASM_PROTOTYPES_H */ >> diff --git a/arch/powerpc/include/asm/barrier.h b/arch/powerpc/include/asm/barrier.h >> index b9e16855a037..e7cb72cdb2ba 100644 >> - --- a/arch/powerpc/include/asm/barrier.h >> +++ b/arch/powerpc/include/asm/barrier.h >> @@ -92,4 +92,25 @@ do { \ >> #define smp_mb__after_atomic() smp_mb() >> #define smp_mb__before_spinlock() smp_mb() >> >> +#ifdef CONFIG_PPC_BOOK3S_64 >> +#define NOSPEC_BARRIER_SLOT nop >> +#elif defined(CONFIG_PPC_FSL_BOOK3E) >> +#define NOSPEC_BARRIER_SLOT nop; nop >> +#endif >> + >> +#ifdef CONFIG_PPC_BARRIER_NOSPEC >> +/* >> + * Prevent execution of subsequent instructions until preceding branches have >> + * been fully resolved and are no longer executing speculatively. >> + */ >> +#define barrier_nospec_asm NOSPEC_BARRIER_FIXUP_SECTION; NOSPEC_BARRIER_SLOT >> + >> +// This also acts as a compiler barrier due to the memory clobber. >> +#define barrier_nospec() asm (stringify_in_c(barrier_nospec_asm) ::: "memory") >> + >> +#else /* !CONFIG_PPC_BARRIER_NOSPEC */ >> +#define barrier_nospec_asm >> +#define barrier_nospec() >> +#endif /* CONFIG_PPC_BARRIER_NOSPEC */ >> + >> #endif /* _ASM_POWERPC_BARRIER_H */ >> diff --git a/arch/powerpc/include/asm/code-patching-asm.h b/arch/powerpc/include/asm/code-patching-asm.h >> new file mode 100644 >> index 000000000000..ed7b1448493a >> - --- /dev/null >> +++ b/arch/powerpc/include/asm/code-patching-asm.h >> @@ -0,0 +1,18 @@ >> +/* SPDX-License-Identifier: GPL-2.0+ */ >> +/* >> + * Copyright 2018, Michael Ellerman, IBM Corporation. >> + */ >> +#ifndef _ASM_POWERPC_CODE_PATCHING_ASM_H >> +#define _ASM_POWERPC_CODE_PATCHING_ASM_H >> + >> +/* Define a "site" that can be patched */ >> +.macro patch_site label name >> + .pushsection ".rodata" >> + .balign 4 >> + .global \name >> +\name: >> + .4byte \label - . >> + .popsection >> +.endm >> + >> +#endif /* _ASM_POWERPC_CODE_PATCHING_ASM_H */ >> diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h >> index 840a5509b3f1..a734b4b34d26 100644 >> - --- a/arch/powerpc/include/asm/code-patching.h >> +++ b/arch/powerpc/include/asm/code-patching.h >> @@ -28,6 +28,8 @@ unsigned int create_cond_branch(const unsigned int *addr, >> unsigned long target, int flags); >> int patch_branch(unsigned int *addr, unsigned long target, int flags); >> int patch_instruction(unsigned int *addr, unsigned int instr); >> +int patch_instruction_site(s32 *addr, unsigned int instr); >> +int patch_branch_site(s32 *site, unsigned long target, int flags); >> >> int instr_is_relative_branch(unsigned int instr); >> int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr); >> diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h >> index 9bddbec441b8..3ed536bec462 100644 >> - --- a/arch/powerpc/include/asm/exception-64s.h >> +++ b/arch/powerpc/include/asm/exception-64s.h >> @@ -50,6 +50,27 @@ >> #define EX_PPR 88 /* SMT thread status register (priority) */ >> #define EX_CTR 96 >> >> +#define STF_ENTRY_BARRIER_SLOT \ >> + STF_ENTRY_BARRIER_FIXUP_SECTION; \ >> + nop; \ >> + nop; \ >> + nop >> + >> +#define STF_EXIT_BARRIER_SLOT \ >> + STF_EXIT_BARRIER_FIXUP_SECTION; \ >> + nop; \ >> + nop; \ >> + nop; \ >> + nop; \ >> + nop; \ >> + nop >> + >> +/* >> + * r10 must be free to use, r13 must be paca >> + */ >> +#define INTERRUPT_TO_KERNEL \ >> + STF_ENTRY_BARRIER_SLOT >> + >> /* >> * Macros for annotating the expected destination of (h)rfid >> * >> @@ -66,16 +87,19 @@ >> rfid >> >> #define RFI_TO_USER \ >> + STF_EXIT_BARRIER_SLOT; \ >> RFI_FLUSH_SLOT; \ >> rfid; \ >> b rfi_flush_fallback >> >> #define RFI_TO_USER_OR_KERNEL \ >> + STF_EXIT_BARRIER_SLOT; \ >> RFI_FLUSH_SLOT; \ >> rfid; \ >> b rfi_flush_fallback >> >> #define RFI_TO_GUEST \ >> + STF_EXIT_BARRIER_SLOT; \ >> RFI_FLUSH_SLOT; \ >> rfid; \ >> b rfi_flush_fallback >> @@ -84,21 +108,25 @@ >> hrfid >> >> #define HRFI_TO_USER \ >> + STF_EXIT_BARRIER_SLOT; \ >> RFI_FLUSH_SLOT; \ >> hrfid; \ >> b hrfi_flush_fallback >> >> #define HRFI_TO_USER_OR_KERNEL \ >> + STF_EXIT_BARRIER_SLOT; \ >> RFI_FLUSH_SLOT; \ >> hrfid; \ >> b hrfi_flush_fallback >> >> #define HRFI_TO_GUEST \ >> + STF_EXIT_BARRIER_SLOT; \ >> RFI_FLUSH_SLOT; \ >> hrfid; \ >> b hrfi_flush_fallback >> >> #define HRFI_TO_UNKNOWN \ >> + STF_EXIT_BARRIER_SLOT; \ >> RFI_FLUSH_SLOT; \ >> hrfid; \ >> b hrfi_flush_fallback >> @@ -226,6 +254,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) >> #define __EXCEPTION_PROLOG_1(area, extra, vec) \ >> OPT_SAVE_REG_TO_PACA(area+EX_PPR, r9, CPU_FTR_HAS_PPR); \ >> OPT_SAVE_REG_TO_PACA(area+EX_CFAR, r10, CPU_FTR_CFAR); \ >> + INTERRUPT_TO_KERNEL; \ >> SAVE_CTR(r10, area); \ >> mfcr r9; \ >> extra(vec); \ >> @@ -512,6 +541,12 @@ label##_relon_hv: \ >> #define _MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \ >> __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) >> >> +#define MASKABLE_EXCEPTION_OOL(vec, label) \ >> + .globl label##_ool; \ >> +label##_ool: \ >> + EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_TEST_PR, vec); \ >> + EXCEPTION_PROLOG_PSERIES_1(label##_common, EXC_STD); >> + >> #define MASKABLE_EXCEPTION_PSERIES(loc, vec, label) \ >> . = loc; \ >> .globl label##_pSeries; \ >> diff --git a/arch/powerpc/include/asm/feature-fixups.h b/arch/powerpc/include/asm/feature-fixups.h >> index 7068bafbb2d6..145a37ab2d3e 100644 >> - --- a/arch/powerpc/include/asm/feature-fixups.h >> +++ b/arch/powerpc/include/asm/feature-fixups.h >> @@ -184,6 +184,22 @@ label##3: \ >> FTR_ENTRY_OFFSET label##1b-label##3b; \ >> .popsection; >> >> +#define STF_ENTRY_BARRIER_FIXUP_SECTION \ >> +953: \ >> + .pushsection __stf_entry_barrier_fixup,"a"; \ >> + .align 2; \ >> +954: \ >> + FTR_ENTRY_OFFSET 953b-954b; \ >> + .popsection; >> + >> +#define STF_EXIT_BARRIER_FIXUP_SECTION \ >> +955: \ >> + .pushsection __stf_exit_barrier_fixup,"a"; \ >> + .align 2; \ >> +956: \ >> + FTR_ENTRY_OFFSET 955b-956b; \ >> + .popsection; >> + >> #define RFI_FLUSH_FIXUP_SECTION \ >> 951: \ >> .pushsection __rfi_flush_fixup,"a"; \ >> @@ -192,10 +208,34 @@ label##3: \ >> FTR_ENTRY_OFFSET 951b-952b; \ >> .popsection; >> >> +#define NOSPEC_BARRIER_FIXUP_SECTION \ >> +953: \ >> + .pushsection __barrier_nospec_fixup,"a"; \ >> + .align 2; \ >> +954: \ >> + FTR_ENTRY_OFFSET 953b-954b; \ >> + .popsection; >> + >> +#define START_BTB_FLUSH_SECTION \ >> +955: \ >> + >> +#define END_BTB_FLUSH_SECTION \ >> +956: \ >> + .pushsection __btb_flush_fixup,"a"; \ >> + .align 2; \ >> +957: \ >> + FTR_ENTRY_OFFSET 955b-957b; \ >> + FTR_ENTRY_OFFSET 956b-957b; \ >> + .popsection; >> >> #ifndef __ASSEMBLY__ >> >> +extern long stf_barrier_fallback; >> +extern long __start___stf_entry_barrier_fixup, __stop___stf_entry_barrier_fixup; >> +extern long __start___stf_exit_barrier_fixup, __stop___stf_exit_barrier_fixup; >> extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup; >> +extern long __start___barrier_nospec_fixup, __stop___barrier_nospec_fixup; >> +extern long __start__btb_flush_fixup, __stop__btb_flush_fixup; >> >> #endif >> >> diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h >> index 449bbb87c257..b57db9d09db9 100644 >> - --- a/arch/powerpc/include/asm/hvcall.h >> +++ b/arch/powerpc/include/asm/hvcall.h >> @@ -292,10 +292,15 @@ >> #define H_CPU_CHAR_L1D_FLUSH_ORI30 (1ull << 61) // IBM bit 2 >> #define H_CPU_CHAR_L1D_FLUSH_TRIG2 (1ull << 60) // IBM bit 3 >> #define H_CPU_CHAR_L1D_THREAD_PRIV (1ull << 59) // IBM bit 4 >> +#define H_CPU_CHAR_BRANCH_HINTS_HONORED (1ull << 58) // IBM bit 5 >> +#define H_CPU_CHAR_THREAD_RECONFIG_CTRL (1ull << 57) // IBM bit 6 >> +#define H_CPU_CHAR_COUNT_CACHE_DISABLED (1ull << 56) // IBM bit 7 >> +#define H_CPU_CHAR_BCCTR_FLUSH_ASSIST (1ull << 54) // IBM bit 9 >> >> #define H_CPU_BEHAV_FAVOUR_SECURITY (1ull << 63) // IBM bit 0 >> #define H_CPU_BEHAV_L1D_FLUSH_PR (1ull << 62) // IBM bit 1 >> #define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR (1ull << 61) // IBM bit 2 >> +#define H_CPU_BEHAV_FLUSH_COUNT_CACHE (1ull << 58) // IBM bit 5 >> >> #ifndef __ASSEMBLY__ >> #include <linux/types.h> >> diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h >> index 45e2aefece16..08e5df3395fa 100644 >> - --- a/arch/powerpc/include/asm/paca.h >> +++ b/arch/powerpc/include/asm/paca.h >> @@ -199,8 +199,7 @@ struct paca_struct { >> */ >> u64 exrfi[13] __aligned(0x80); >> void *rfi_flush_fallback_area; >> - - u64 l1d_flush_congruence; >> - - u64 l1d_flush_sets; >> + u64 l1d_flush_size; >> #endif >> }; >> >> diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h >> index 7ab04fc59e24..faf1bb045dee 100644 >> - --- a/arch/powerpc/include/asm/ppc-opcode.h >> +++ b/arch/powerpc/include/asm/ppc-opcode.h >> @@ -147,6 +147,7 @@ >> #define PPC_INST_LWSYNC 0x7c2004ac >> #define PPC_INST_SYNC 0x7c0004ac >> #define PPC_INST_SYNC_MASK 0xfc0007fe >> +#define PPC_INST_ISYNC 0x4c00012c >> #define PPC_INST_LXVD2X 0x7c000698 >> #define PPC_INST_MCRXR 0x7c000400 >> #define PPC_INST_MCRXR_MASK 0xfc0007fe >> diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h >> index 160bb2311bbb..d219816b3e19 100644 >> - --- a/arch/powerpc/include/asm/ppc_asm.h >> +++ b/arch/powerpc/include/asm/ppc_asm.h >> @@ -821,4 +821,15 @@ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,945) >> .long 0x2400004c /* rfid */ >> #endif /* !CONFIG_PPC_BOOK3E */ >> #endif /* __ASSEMBLY__ */ >> + >> +#ifdef CONFIG_PPC_FSL_BOOK3E >> +#define BTB_FLUSH(reg) \ >> + lis reg,BUCSR_INIT@h; \ >> + ori reg,reg,BUCSR_INIT@l; \ >> + mtspr SPRN_BUCSR,reg; \ >> + isync; >> +#else >> +#define BTB_FLUSH(reg) >> +#endif /* CONFIG_PPC_FSL_BOOK3E */ >> + >> #endif /* _ASM_POWERPC_PPC_ASM_H */ >> diff --git a/arch/powerpc/include/asm/security_features.h b/arch/powerpc/include/asm/security_features.h >> new file mode 100644 >> index 000000000000..759597bf0fd8 >> - --- /dev/null >> +++ b/arch/powerpc/include/asm/security_features.h >> @@ -0,0 +1,92 @@ >> +/* SPDX-License-Identifier: GPL-2.0+ */ >> +/* >> + * Security related feature bit definitions. >> + * >> + * Copyright 2018, Michael Ellerman, IBM Corporation. >> + */ >> + >> +#ifndef _ASM_POWERPC_SECURITY_FEATURES_H >> +#define _ASM_POWERPC_SECURITY_FEATURES_H >> + >> + >> +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); >> +void setup_count_cache_flush(void); >> + >> +static inline void security_ftr_set(unsigned long feature) >> +{ >> + powerpc_security_features |= feature; >> +} >> + >> +static inline void security_ftr_clear(unsigned long feature) >> +{ >> + powerpc_security_features &= ~feature; >> +} >> + >> +static inline bool security_ftr_enabled(unsigned long feature) >> +{ >> + return !!(powerpc_security_features & feature); >> +} >> + >> + >> +// Features indicating support for Spectre/Meltdown mitigations >> + >> +// The L1-D cache can be flushed with ori r30,r30,0 >> +#define SEC_FTR_L1D_FLUSH_ORI30 0x0000000000000001ull >> + >> +// The L1-D cache can be flushed with mtspr 882,r0 (aka SPRN_TRIG2) >> +#define SEC_FTR_L1D_FLUSH_TRIG2 0x0000000000000002ull >> + >> +// ori r31,r31,0 acts as a speculation barrier >> +#define SEC_FTR_SPEC_BAR_ORI31 0x0000000000000004ull >> + >> +// Speculation past bctr is disabled >> +#define SEC_FTR_BCCTRL_SERIALISED 0x0000000000000008ull >> + >> +// Entries in L1-D are private to a SMT thread >> +#define SEC_FTR_L1D_THREAD_PRIV 0x0000000000000010ull >> + >> +// Indirect branch prediction cache disabled >> +#define SEC_FTR_COUNT_CACHE_DISABLED 0x0000000000000020ull >> + >> +// bcctr 2,0,0 triggers a hardware assisted count cache flush >> +#define SEC_FTR_BCCTR_FLUSH_ASSIST 0x0000000000000800ull >> + >> + >> +// Features indicating need for Spectre/Meltdown mitigations >> + >> +// The L1-D cache should be flushed on MSR[HV] 1->0 transition (hypervisor to guest) >> +#define SEC_FTR_L1D_FLUSH_HV 0x0000000000000040ull >> + >> +// The L1-D cache should be flushed on MSR[PR] 0->1 transition (kernel to userspace) >> +#define SEC_FTR_L1D_FLUSH_PR 0x0000000000000080ull >> + >> +// A speculation barrier should be used for bounds checks (Spectre variant 1) >> +#define SEC_FTR_BNDS_CHK_SPEC_BAR 0x0000000000000100ull >> + >> +// Firmware configuration indicates user favours security over performance >> +#define SEC_FTR_FAVOUR_SECURITY 0x0000000000000200ull >> + >> +// Software required to flush count cache on context switch >> +#define SEC_FTR_FLUSH_COUNT_CACHE 0x0000000000000400ull >> + >> + >> +// Features enabled by default >> +#define SEC_FTR_DEFAULT \ >> + (SEC_FTR_L1D_FLUSH_HV | \ >> + SEC_FTR_L1D_FLUSH_PR | \ >> + SEC_FTR_BNDS_CHK_SPEC_BAR | \ >> + SEC_FTR_FAVOUR_SECURITY) >> + >> +#endif /* _ASM_POWERPC_SECURITY_FEATURES_H */ >> diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h >> index 7916b56f2e60..d299479c770b 100644 >> - --- a/arch/powerpc/include/asm/setup.h >> +++ b/arch/powerpc/include/asm/setup.h >> @@ -8,6 +8,7 @@ extern void ppc_printk_progress(char *s, unsigned short hex); >> >> extern unsigned int rtas_data; >> extern unsigned long long memory_limit; >> +extern bool init_mem_is_free; >> extern unsigned long klimit; >> extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask); >> >> @@ -36,8 +37,28 @@ enum l1d_flush_type { >> L1D_FLUSH_MTTRIG = 0x8, >> }; >> >> - -void __init setup_rfi_flush(enum l1d_flush_type, bool enable); >> +void setup_rfi_flush(enum l1d_flush_type, bool enable); >> void do_rfi_flush_fixups(enum l1d_flush_type types); >> +#ifdef CONFIG_PPC_BARRIER_NOSPEC >> +void setup_barrier_nospec(void); >> +#else >> +static inline void setup_barrier_nospec(void) { }; >> +#endif >> +void do_barrier_nospec_fixups(bool enable); >> +extern bool barrier_nospec_enabled; >> + >> +#ifdef CONFIG_PPC_BARRIER_NOSPEC >> +void do_barrier_nospec_fixups_range(bool enable, void *start, void *end); >> +#else >> +static inline void do_barrier_nospec_fixups_range(bool enable, void *start, void *end) { }; >> +#endif >> + >> +#ifdef CONFIG_PPC_FSL_BOOK3E >> +void setup_spectre_v2(void); >> +#else >> +static inline void setup_spectre_v2(void) {}; >> +#endif >> +void do_btb_flush_fixups(void); >> >> #endif /* !__ASSEMBLY__ */ >> >> diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h >> index 05f1389228d2..e51ce5a0e221 100644 >> - --- a/arch/powerpc/include/asm/uaccess.h >> +++ b/arch/powerpc/include/asm/uaccess.h >> @@ -269,6 +269,7 @@ do { \ >> __chk_user_ptr(ptr); \ >> if (!is_kernel_addr((unsigned long)__gu_addr)) \ >> might_fault(); \ >> + barrier_nospec(); \ >> __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ >> (x) = (__typeof__(*(ptr)))__gu_val; \ >> __gu_err; \ >> @@ -283,6 +284,7 @@ do { \ >> __chk_user_ptr(ptr); \ >> if (!is_kernel_addr((unsigned long)__gu_addr)) \ >> might_fault(); \ >> + barrier_nospec(); \ >> __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ >> (x) = (__force __typeof__(*(ptr)))__gu_val; \ >> __gu_err; \ >> @@ -295,8 +297,10 @@ do { \ >> unsigned long __gu_val = 0; \ >> __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ >> might_fault(); \ >> - - if (access_ok(VERIFY_READ, __gu_addr, (size))) \ >> + if (access_ok(VERIFY_READ, __gu_addr, (size))) { \ >> + barrier_nospec(); \ >> __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ >> + } \ >> (x) = (__force __typeof__(*(ptr)))__gu_val; \ >> __gu_err; \ >> }) >> @@ -307,6 +311,7 @@ do { \ >> unsigned long __gu_val; \ >> __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ >> __chk_user_ptr(ptr); \ >> + barrier_nospec(); \ >> __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ >> (x) = (__force __typeof__(*(ptr)))__gu_val; \ >> __gu_err; \ >> @@ -323,8 +328,10 @@ extern unsigned long __copy_tofrom_user(void __user *to, >> static inline unsigned long copy_from_user(void *to, >> const void __user *from, unsigned long n) >> { >> - - if (likely(access_ok(VERIFY_READ, from, n))) >> + if (likely(access_ok(VERIFY_READ, from, n))) { >> + barrier_nospec(); >> return __copy_tofrom_user((__force void __user *)to, from, n); >> + } >> memset(to, 0, n); >> return n; >> } >> @@ -359,21 +366,27 @@ static inline unsigned long __copy_from_user_inatomic(void *to, >> >> switch (n) { >> case 1: >> + barrier_nospec(); >> __get_user_size(*(u8 *)to, from, 1, ret); >> break; >> case 2: >> + barrier_nospec(); >> __get_user_size(*(u16 *)to, from, 2, ret); >> break; >> case 4: >> + barrier_nospec(); >> __get_user_size(*(u32 *)to, from, 4, ret); >> break; >> case 8: >> + barrier_nospec(); >> __get_user_size(*(u64 *)to, from, 8, ret); >> break; >> } >> if (ret == 0) >> return 0; >> } >> + >> + barrier_nospec(); >> return __copy_tofrom_user((__force void __user *)to, from, n); >> } >> >> @@ -400,6 +413,7 @@ static inline unsigned long __copy_to_user_inatomic(void __user *to, >> if (ret == 0) >> return 0; >> } >> + >> return __copy_tofrom_user(to, (__force const void __user *)from, n); >> } >> >> diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile >> index ba336930d448..22ed3c32fca8 100644 >> - --- a/arch/powerpc/kernel/Makefile >> +++ b/arch/powerpc/kernel/Makefile >> @@ -44,6 +44,7 @@ obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_power.o >> obj-$(CONFIG_PPC_BOOK3S_64) += mce.o mce_power.o >> obj64-$(CONFIG_RELOCATABLE) += reloc_64.o >> obj-$(CONFIG_PPC_BOOK3E_64) += exceptions-64e.o idle_book3e.o >> +obj-$(CONFIG_PPC_BARRIER_NOSPEC) += security.o >> obj-$(CONFIG_PPC64) += vdso64/ >> obj-$(CONFIG_ALTIVEC) += vecemu.o >> obj-$(CONFIG_PPC_970_NAP) += idle_power4.o >> diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c >> index d92705e3a0c1..de3c29c51503 100644 >> - --- a/arch/powerpc/kernel/asm-offsets.c >> +++ b/arch/powerpc/kernel/asm-offsets.c >> @@ -245,8 +245,7 @@ int main(void) >> DEFINE(PACA_IN_MCE, offsetof(struct paca_struct, in_mce)); >> DEFINE(PACA_RFI_FLUSH_FALLBACK_AREA, offsetof(struct paca_struct, rfi_flush_fallback_area)); >> DEFINE(PACA_EXRFI, offsetof(struct paca_struct, exrfi)); >> - - DEFINE(PACA_L1D_FLUSH_CONGRUENCE, offsetof(struct paca_struct, l1d_flush_congruence)); >> - - DEFINE(PACA_L1D_FLUSH_SETS, offsetof(struct paca_struct, l1d_flush_sets)); >> + DEFINE(PACA_L1D_FLUSH_SIZE, offsetof(struct paca_struct, l1d_flush_size)); >> #endif >> DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); >> DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state)); >> diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S >> index 59be96917369..6d36a4fb4acf 100644 >> - --- a/arch/powerpc/kernel/entry_64.S >> +++ b/arch/powerpc/kernel/entry_64.S >> @@ -25,6 +25,7 @@ >> #include <asm/page.h> >> #include <asm/mmu.h> >> #include <asm/thread_info.h> >> +#include <asm/code-patching-asm.h> >> #include <asm/ppc_asm.h> >> #include <asm/asm-offsets.h> >> #include <asm/cputable.h> >> @@ -36,6 +37,7 @@ >> #include <asm/hw_irq.h> >> #include <asm/context_tracking.h> >> #include <asm/tm.h> >> +#include <asm/barrier.h> >> #ifdef CONFIG_PPC_BOOK3S >> #include <asm/exception-64s.h> >> #else >> @@ -75,6 +77,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM) >> std r0,GPR0(r1) >> std r10,GPR1(r1) >> beq 2f /* if from kernel mode */ >> +#ifdef CONFIG_PPC_FSL_BOOK3E >> +START_BTB_FLUSH_SECTION >> + BTB_FLUSH(r10) >> +END_BTB_FLUSH_SECTION >> +#endif >> ACCOUNT_CPU_USER_ENTRY(r10, r11) >> 2: std r2,GPR2(r1) >> std r3,GPR3(r1) >> @@ -177,6 +184,15 @@ system_call: /* label this so stack traces look sane */ >> clrldi r8,r8,32 >> 15: >> slwi r0,r0,4 >> + >> + barrier_nospec_asm >> + /* >> + * Prevent the load of the handler below (based on the user-passed >> + * system call number) being speculatively executed until the test >> + * against NR_syscalls and branch to .Lsyscall_enosys above has >> + * committed. >> + */ >> + >> ldx r12,r11,r0 /* Fetch system call handler [ptr] */ >> mtctr r12 >> bctrl /* Call handler */ >> @@ -440,6 +456,57 @@ _GLOBAL(ret_from_kernel_thread) >> li r3,0 >> b .Lsyscall_exit >> >> +#ifdef CONFIG_PPC_BOOK3S_64 >> + >> +#define FLUSH_COUNT_CACHE \ >> +1: nop; \ >> + patch_site 1b, patch__call_flush_count_cache >> + >> + >> +#define BCCTR_FLUSH .long 0x4c400420 >> + >> +.macro nops number >> + .rept \number >> + nop >> + .endr >> +.endm >> + >> +.balign 32 >> +.global flush_count_cache >> +flush_count_cache: >> + /* Save LR into r9 */ >> + mflr r9 >> + >> + .rept 64 >> + bl .+4 >> + .endr >> + b 1f >> + nops 6 >> + >> + .balign 32 >> + /* Restore LR */ >> +1: mtlr r9 >> + li r9,0x7fff >> + mtctr r9 >> + >> + BCCTR_FLUSH >> + >> +2: nop >> + patch_site 2b patch__flush_count_cache_return >> + >> + nops 3 >> + >> + .rept 278 >> + .balign 32 >> + BCCTR_FLUSH >> + nops 7 >> + .endr >> + >> + blr >> +#else >> +#define FLUSH_COUNT_CACHE >> +#endif /* CONFIG_PPC_BOOK3S_64 */ >> + >> /* >> * This routine switches between two different tasks. The process >> * state of one is saved on its kernel stack. Then the state >> @@ -503,6 +570,8 @@ BEGIN_FTR_SECTION >> END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) >> #endif >> >> + FLUSH_COUNT_CACHE >> + >> #ifdef CONFIG_SMP >> /* We need a sync somewhere here to make sure that if the >> * previous task gets rescheduled on another CPU, it sees all >> diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S >> index 5cc93f0b52ca..48ec841ea1bf 100644 >> - --- a/arch/powerpc/kernel/exceptions-64e.S >> +++ b/arch/powerpc/kernel/exceptions-64e.S >> @@ -295,7 +295,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV) >> andi. r10,r11,MSR_PR; /* save stack pointer */ \ >> beq 1f; /* branch around if supervisor */ \ >> ld r1,PACAKSAVE(r13); /* get kernel stack coming from usr */\ >> - -1: cmpdi cr1,r1,0; /* check if SP makes sense */ \ >> +1: type##_BTB_FLUSH \ >> + cmpdi cr1,r1,0; /* check if SP makes sense */ \ >> bge- cr1,exc_##n##_bad_stack;/* bad stack (TODO: out of line) */ \ >> mfspr r10,SPRN_##type##_SRR0; /* read SRR0 before touching stack */ >> >> @@ -327,6 +328,30 @@ END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV) >> #define SPRN_MC_SRR0 SPRN_MCSRR0 >> #define SPRN_MC_SRR1 SPRN_MCSRR1 >> >> +#ifdef CONFIG_PPC_FSL_BOOK3E >> +#define GEN_BTB_FLUSH \ >> + START_BTB_FLUSH_SECTION \ >> + beq 1f; \ >> + BTB_FLUSH(r10) \ >> + 1: \ >> + END_BTB_FLUSH_SECTION >> + >> +#define CRIT_BTB_FLUSH \ >> + START_BTB_FLUSH_SECTION \ >> + BTB_FLUSH(r10) \ >> + END_BTB_FLUSH_SECTION >> + >> +#define DBG_BTB_FLUSH CRIT_BTB_FLUSH >> +#define MC_BTB_FLUSH CRIT_BTB_FLUSH >> +#define GDBELL_BTB_FLUSH GEN_BTB_FLUSH >> +#else >> +#define GEN_BTB_FLUSH >> +#define CRIT_BTB_FLUSH >> +#define DBG_BTB_FLUSH >> +#define MC_BTB_FLUSH >> +#define GDBELL_BTB_FLUSH >> +#endif >> + >> #define NORMAL_EXCEPTION_PROLOG(n, intnum, addition) \ >> EXCEPTION_PROLOG(n, intnum, GEN, addition##_GEN(n)) >> >> diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S >> index 938a30fef031..10e7cec9553d 100644 >> - --- a/arch/powerpc/kernel/exceptions-64s.S >> +++ b/arch/powerpc/kernel/exceptions-64s.S >> @@ -36,6 +36,7 @@ BEGIN_FTR_SECTION \ >> END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \ >> mr r9,r13 ; \ >> GET_PACA(r13) ; \ >> + INTERRUPT_TO_KERNEL ; \ >> mfspr r11,SPRN_SRR0 ; \ >> 0: >> >> @@ -292,7 +293,9 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE) >> . = 0x900 >> .globl decrementer_pSeries >> decrementer_pSeries: >> - - _MASKABLE_EXCEPTION_PSERIES(0x900, decrementer, EXC_STD, SOFTEN_TEST_PR) >> + SET_SCRATCH0(r13) >> + EXCEPTION_PROLOG_0(PACA_EXGEN) >> + b decrementer_ool >> >> STD_EXCEPTION_HV(0x980, 0x982, hdecrementer) >> >> @@ -319,6 +322,7 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE) >> OPT_GET_SPR(r9, SPRN_PPR, CPU_FTR_HAS_PPR); >> HMT_MEDIUM; >> std r10,PACA_EXGEN+EX_R10(r13) >> + INTERRUPT_TO_KERNEL >> OPT_SAVE_REG_TO_PACA(PACA_EXGEN+EX_PPR, r9, CPU_FTR_HAS_PPR); >> mfcr r9 >> KVMTEST(0xc00) >> @@ -607,6 +611,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR) >> >> .align 7 >> /* moved from 0xe00 */ >> + MASKABLE_EXCEPTION_OOL(0x900, decrementer) >> STD_EXCEPTION_HV_OOL(0xe02, h_data_storage) >> KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0xe02) >> STD_EXCEPTION_HV_OOL(0xe22, h_instr_storage) >> @@ -1564,6 +1569,21 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) >> blr >> #endif >> >> + .balign 16 >> + .globl stf_barrier_fallback >> +stf_barrier_fallback: >> + std r9,PACA_EXRFI+EX_R9(r13) >> + std r10,PACA_EXRFI+EX_R10(r13) >> + sync >> + ld r9,PACA_EXRFI+EX_R9(r13) >> + ld r10,PACA_EXRFI+EX_R10(r13) >> + ori 31,31,0 >> + .rept 14 >> + b 1f >> +1: >> + .endr >> + blr >> + >> .globl rfi_flush_fallback >> rfi_flush_fallback: >> SET_SCRATCH0(r13); >> @@ -1571,39 +1591,37 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) >> std r9,PACA_EXRFI+EX_R9(r13) >> std r10,PACA_EXRFI+EX_R10(r13) >> std r11,PACA_EXRFI+EX_R11(r13) >> - - std r12,PACA_EXRFI+EX_R12(r13) >> - - std r8,PACA_EXRFI+EX_R13(r13) >> mfctr r9 >> ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13) >> - - ld r11,PACA_L1D_FLUSH_SETS(r13) >> - - ld r12,PACA_L1D_FLUSH_CONGRUENCE(r13) >> - - /* >> - - * The load adresses are at staggered offsets within cachelines, >> - - * which suits some pipelines better (on others it should not >> - - * hurt). >> - - */ >> - - addi r12,r12,8 >> + ld r11,PACA_L1D_FLUSH_SIZE(r13) >> + srdi r11,r11,(7 + 3) /* 128 byte lines, unrolled 8x */ >> mtctr r11 >> DCBT_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */ >> >> /* order ld/st prior to dcbt stop all streams with flushing */ >> sync >> - -1: li r8,0 >> - - .rept 8 /* 8-way set associative */ >> - - ldx r11,r10,r8 >> - - add r8,r8,r12 >> - - xor r11,r11,r11 // Ensure r11 is 0 even if fallback area is not >> - - add r8,r8,r11 // Add 0, this creates a dependency on the ldx >> - - .endr >> - - addi r10,r10,128 /* 128 byte cache line */ >> + >> + /* >> + * The load adresses are at staggered offsets within cachelines, >> + * which suits some pipelines better (on others it should not >> + * hurt). >> + */ >> +1: >> + ld r11,(0x80 + 8)*0(r10) >> + ld r11,(0x80 + 8)*1(r10) >> + ld r11,(0x80 + 8)*2(r10) >> + ld r11,(0x80 + 8)*3(r10) >> + ld r11,(0x80 + 8)*4(r10) >> + ld r11,(0x80 + 8)*5(r10) >> + ld r11,(0x80 + 8)*6(r10) >> + ld r11,(0x80 + 8)*7(r10) >> + addi r10,r10,0x80*8 >> bdnz 1b >> >> mtctr r9 >> ld r9,PACA_EXRFI+EX_R9(r13) >> ld r10,PACA_EXRFI+EX_R10(r13) >> ld r11,PACA_EXRFI+EX_R11(r13) >> - - ld r12,PACA_EXRFI+EX_R12(r13) >> - - ld r8,PACA_EXRFI+EX_R13(r13) >> GET_SCRATCH0(r13); >> rfid >> >> @@ -1614,39 +1632,37 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) >> std r9,PACA_EXRFI+EX_R9(r13) >> std r10,PACA_EXRFI+EX_R10(r13) >> std r11,PACA_EXRFI+EX_R11(r13) >> - - std r12,PACA_EXRFI+EX_R12(r13) >> - - std r8,PACA_EXRFI+EX_R13(r13) >> mfctr r9 >> ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13) >> - - ld r11,PACA_L1D_FLUSH_SETS(r13) >> - - ld r12,PACA_L1D_FLUSH_CONGRUENCE(r13) >> - - /* >> - - * The load adresses are at staggered offsets within cachelines, >> - - * which suits some pipelines better (on others it should not >> - - * hurt). >> - - */ >> - - addi r12,r12,8 >> + ld r11,PACA_L1D_FLUSH_SIZE(r13) >> + srdi r11,r11,(7 + 3) /* 128 byte lines, unrolled 8x */ >> mtctr r11 >> DCBT_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */ >> >> /* order ld/st prior to dcbt stop all streams with flushing */ >> sync >> - -1: li r8,0 >> - - .rept 8 /* 8-way set associative */ >> - - ldx r11,r10,r8 >> - - add r8,r8,r12 >> - - xor r11,r11,r11 // Ensure r11 is 0 even if fallback area is not >> - - add r8,r8,r11 // Add 0, this creates a dependency on the ldx >> - - .endr >> - - addi r10,r10,128 /* 128 byte cache line */ >> + >> + /* >> + * The load adresses are at staggered offsets within cachelines, >> + * which suits some pipelines better (on others it should not >> + * hurt). >> + */ >> +1: >> + ld r11,(0x80 + 8)*0(r10) >> + ld r11,(0x80 + 8)*1(r10) >> + ld r11,(0x80 + 8)*2(r10) >> + ld r11,(0x80 + 8)*3(r10) >> + ld r11,(0x80 + 8)*4(r10) >> + ld r11,(0x80 + 8)*5(r10) >> + ld r11,(0x80 + 8)*6(r10) >> + ld r11,(0x80 + 8)*7(r10) >> + addi r10,r10,0x80*8 >> bdnz 1b >> >> mtctr r9 >> ld r9,PACA_EXRFI+EX_R9(r13) >> ld r10,PACA_EXRFI+EX_R10(r13) >> ld r11,PACA_EXRFI+EX_R11(r13) >> - - ld r12,PACA_EXRFI+EX_R12(r13) >> - - ld r8,PACA_EXRFI+EX_R13(r13) >> GET_SCRATCH0(r13); >> hrfid >> >> diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c >> index 9547381b631a..ff009be97a42 100644 >> - --- a/arch/powerpc/kernel/module.c >> +++ b/arch/powerpc/kernel/module.c >> @@ -67,7 +67,15 @@ int module_finalize(const Elf_Ehdr *hdr, >> do_feature_fixups(powerpc_firmware_features, >> (void *)sect->sh_addr, >> (void *)sect->sh_addr + sect->sh_size); >> - -#endif >> +#endif /* CONFIG_PPC64 */ >> + >> +#ifdef CONFIG_PPC_BARRIER_NOSPEC >> + sect = find_section(hdr, sechdrs, "__spec_barrier_fixup"); >> + if (sect != NULL) >> + do_barrier_nospec_fixups_range(barrier_nospec_enabled, >> + (void *)sect->sh_addr, >> + (void *)sect->sh_addr + sect->sh_size); >> +#endif /* CONFIG_PPC_BARRIER_NOSPEC */ >> >> sect = find_section(hdr, sechdrs, "__lwsync_fixup"); >> if (sect != NULL) >> diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c >> new file mode 100644 >> index 000000000000..58f0602a92b9 >> - --- /dev/null >> +++ b/arch/powerpc/kernel/security.c >> @@ -0,0 +1,433 @@ >> +// SPDX-License-Identifier: GPL-2.0+ >> +// >> +// Security related flags and so on. >> +// >> +// Copyright 2018, Michael Ellerman, IBM Corporation. >> + >> +#include <linux/kernel.h> >> +#include <linux/debugfs.h> >> +#include <linux/device.h> >> +#include <linux/seq_buf.h> >> + >> +#include <asm/debug.h> >> +#include <asm/asm-prototypes.h> >> +#include <asm/code-patching.h> >> +#include <asm/security_features.h> >> +#include <asm/setup.h> >> + >> + >> +unsigned long powerpc_security_features __read_mostly = SEC_FTR_DEFAULT; >> + >> +enum count_cache_flush_type { >> + COUNT_CACHE_FLUSH_NONE = 0x1, >> + COUNT_CACHE_FLUSH_SW = 0x2, >> + COUNT_CACHE_FLUSH_HW = 0x4, >> +}; >> +static enum count_cache_flush_type count_cache_flush_type = COUNT_CACHE_FLUSH_NONE; >> + >> +bool barrier_nospec_enabled; >> +static bool no_nospec; >> +static bool btb_flush_enabled; >> +#ifdef CONFIG_PPC_FSL_BOOK3E >> +static bool no_spectrev2; >> +#endif >> + >> +static void enable_barrier_nospec(bool enable) >> +{ >> + barrier_nospec_enabled = enable; >> + do_barrier_nospec_fixups(enable); >> +} >> + >> +void setup_barrier_nospec(void) >> +{ >> + bool enable; >> + >> + /* >> + * It would make sense to check SEC_FTR_SPEC_BAR_ORI31 below as well. >> + * But there's a good reason not to. The two flags we check below are >> + * both are enabled by default in the kernel, so if the hcall is not >> + * functional they will be enabled. >> + * On a system where the host firmware has been updated (so the ori >> + * functions as a barrier), but on which the hypervisor (KVM/Qemu) has >> + * not been updated, we would like to enable the barrier. Dropping the >> + * check for SEC_FTR_SPEC_BAR_ORI31 achieves that. The only downside is >> + * we potentially enable the barrier on systems where the host firmware >> + * is not updated, but that's harmless as it's a no-op. >> + */ >> + enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && >> + security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR); >> + >> + if (!no_nospec) >> + enable_barrier_nospec(enable); >> +} >> + >> +static int __init handle_nospectre_v1(char *p) >> +{ >> + no_nospec = true; >> + >> + return 0; >> +} >> +early_param("nospectre_v1", handle_nospectre_v1); >> + >> +#ifdef CONFIG_DEBUG_FS >> +static int barrier_nospec_set(void *data, u64 val) >> +{ >> + switch (val) { >> + case 0: >> + case 1: >> + break; >> + default: >> + return -EINVAL; >> + } >> + >> + if (!!val == !!barrier_nospec_enabled) >> + return 0; >> + >> + enable_barrier_nospec(!!val); >> + >> + return 0; >> +} >> + >> +static int barrier_nospec_get(void *data, u64 *val) >> +{ >> + *val = barrier_nospec_enabled ? 1 : 0; >> + return 0; >> +} >> + >> +DEFINE_SIMPLE_ATTRIBUTE(fops_barrier_nospec, >> + barrier_nospec_get, barrier_nospec_set, "%llu\n"); >> + >> +static __init int barrier_nospec_debugfs_init(void) >> +{ >> + debugfs_create_file("barrier_nospec", 0600, powerpc_debugfs_root, NULL, >> + &fops_barrier_nospec); >> + return 0; >> +} >> +device_initcall(barrier_nospec_debugfs_init); >> +#endif /* CONFIG_DEBUG_FS */ >> + >> +#ifdef CONFIG_PPC_FSL_BOOK3E >> +static int __init handle_nospectre_v2(char *p) >> +{ >> + no_spectrev2 = true; >> + >> + return 0; >> +} >> +early_param("nospectre_v2", handle_nospectre_v2); >> +void setup_spectre_v2(void) >> +{ >> + if (no_spectrev2) >> + do_btb_flush_fixups(); >> + else >> + btb_flush_enabled = true; >> +} >> +#endif /* CONFIG_PPC_FSL_BOOK3E */ >> + >> +#ifdef CONFIG_PPC_BOOK3S_64 >> +ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf) >> +{ >> + bool thread_priv; >> + >> + thread_priv = security_ftr_enabled(SEC_FTR_L1D_THREAD_PRIV); >> + >> + if (rfi_flush || thread_priv) { >> + struct seq_buf s; >> + seq_buf_init(&s, buf, PAGE_SIZE - 1); >> + >> + seq_buf_printf(&s, "Mitigation: "); >> + >> + if (rfi_flush) >> + seq_buf_printf(&s, "RFI Flush"); >> + >> + if (rfi_flush && thread_priv) >> + seq_buf_printf(&s, ", "); >> + >> + if (thread_priv) >> + seq_buf_printf(&s, "L1D private per thread"); >> + >> + seq_buf_printf(&s, "\n"); >> + >> + return s.len; >> + } >> + >> + 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"); >> +} >> +#endif >> + >> +ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr, char *buf) >> +{ >> + struct seq_buf s; >> + >> + seq_buf_init(&s, buf, PAGE_SIZE - 1); >> + >> + if (security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR)) { >> + if (barrier_nospec_enabled) >> + seq_buf_printf(&s, "Mitigation: __user pointer sanitization"); >> + else >> + seq_buf_printf(&s, "Vulnerable"); >> + >> + if (security_ftr_enabled(SEC_FTR_SPEC_BAR_ORI31)) >> + seq_buf_printf(&s, ", ori31 speculation barrier enabled"); >> + >> + seq_buf_printf(&s, "\n"); >> + } else >> + seq_buf_printf(&s, "Not affected\n"); >> + >> + return s.len; >> +} >> + >> +ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, char *buf) >> +{ >> + struct seq_buf s; >> + bool bcs, ccd; >> + >> + seq_buf_init(&s, buf, PAGE_SIZE - 1); >> + >> + bcs = security_ftr_enabled(SEC_FTR_BCCTRL_SERIALISED); >> + ccd = security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED); >> + >> + if (bcs || ccd) { >> + seq_buf_printf(&s, "Mitigation: "); >> + >> + if (bcs) >> + seq_buf_printf(&s, "Indirect branch serialisation (kernel only)"); >> + >> + if (bcs && ccd) >> + seq_buf_printf(&s, ", "); >> + >> + if (ccd) >> + seq_buf_printf(&s, "Indirect branch cache disabled"); >> + } else if (count_cache_flush_type != COUNT_CACHE_FLUSH_NONE) { >> + seq_buf_printf(&s, "Mitigation: Software count cache flush"); >> + >> + if (count_cache_flush_type == COUNT_CACHE_FLUSH_HW) >> + seq_buf_printf(&s, " (hardware accelerated)"); >> + } else if (btb_flush_enabled) { >> + seq_buf_printf(&s, "Mitigation: Branch predictor state flush"); >> + } else { >> + seq_buf_printf(&s, "Vulnerable"); >> + } >> + >> + seq_buf_printf(&s, "\n"); >> + >> + return s.len; >> +} >> + >> +#ifdef CONFIG_PPC_BOOK3S_64 >> +/* >> + * 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 */ >> + 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 */ >> + >> +static void toggle_count_cache_flush(bool enable) >> +{ >> + if (!enable || !security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE)) { >> + patch_instruction_site(&patch__call_flush_count_cache, PPC_INST_NOP); >> + count_cache_flush_type = COUNT_CACHE_FLUSH_NONE; >> + pr_info("count-cache-flush: software flush disabled.\n"); >> + return; >> + } >> + >> + patch_branch_site(&patch__call_flush_count_cache, >> + (u64)&flush_count_cache, BRANCH_SET_LINK); >> + >> + if (!security_ftr_enabled(SEC_FTR_BCCTR_FLUSH_ASSIST)) { >> + count_cache_flush_type = COUNT_CACHE_FLUSH_SW; >> + pr_info("count-cache-flush: full software flush sequence enabled.\n"); >> + return; >> + } >> + >> + patch_instruction_site(&patch__flush_count_cache_return, PPC_INST_BLR); >> + count_cache_flush_type = COUNT_CACHE_FLUSH_HW; >> + pr_info("count-cache-flush: hardware assisted flush sequence enabled\n"); >> +} >> + >> +void setup_count_cache_flush(void) >> +{ >> + toggle_count_cache_flush(true); >> +} >> + >> +#ifdef CONFIG_DEBUG_FS >> +static int count_cache_flush_set(void *data, u64 val) >> +{ >> + bool enable; >> + >> + if (val == 1) >> + enable = true; >> + else if (val == 0) >> + enable = false; >> + else >> + return -EINVAL; >> + >> + toggle_count_cache_flush(enable); >> + >> + return 0; >> +} >> + >> +static int count_cache_flush_get(void *data, u64 *val) >> +{ >> + if (count_cache_flush_type == COUNT_CACHE_FLUSH_NONE) >> + *val = 0; >> + else >> + *val = 1; >> + >> + return 0; >> +} >> + >> +DEFINE_SIMPLE_ATTRIBUTE(fops_count_cache_flush, count_cache_flush_get, >> + count_cache_flush_set, "%llu\n"); >> + >> +static __init int count_cache_flush_debugfs_init(void) >> +{ >> + debugfs_create_file("count_cache_flush", 0600, powerpc_debugfs_root, >> + NULL, &fops_count_cache_flush); >> + return 0; >> +} >> +device_initcall(count_cache_flush_debugfs_init); >> +#endif /* CONFIG_DEBUG_FS */ >> +#endif /* CONFIG_PPC_BOOK3S_64 */ >> diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c >> index ad8c9db61237..5a9f035bcd6b 100644 >> - --- a/arch/powerpc/kernel/setup_32.c >> +++ b/arch/powerpc/kernel/setup_32.c >> @@ -322,6 +322,8 @@ void __init setup_arch(char **cmdline_p) >> ppc_md.setup_arch(); >> if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab); >> >> + setup_barrier_nospec(); >> + >> paging_init(); >> >> /* Initialize the MMU context management stuff */ >> diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c >> index 9eb469bed22b..6bb731ababc6 100644 >> - --- a/arch/powerpc/kernel/setup_64.c >> +++ b/arch/powerpc/kernel/setup_64.c >> @@ -736,6 +736,8 @@ void __init setup_arch(char **cmdline_p) >> if (ppc_md.setup_arch) >> ppc_md.setup_arch(); >> >> + setup_barrier_nospec(); >> + >> paging_init(); >> >> /* Initialize the MMU context management stuff */ >> @@ -873,9 +875,6 @@ static void do_nothing(void *unused) >> >> void rfi_flush_enable(bool enable) >> { >> - - if (rfi_flush == enable) >> - - return; >> - - >> if (enable) { >> do_rfi_flush_fixups(enabled_flush_types); >> on_each_cpu(do_nothing, NULL, 1); >> @@ -885,11 +884,15 @@ void rfi_flush_enable(bool enable) >> rfi_flush = enable; >> } >> >> - -static void init_fallback_flush(void) >> +static void __ref init_fallback_flush(void) >> { >> u64 l1d_size, limit; >> int cpu; >> >> + /* Only allocate the fallback flush area once (at boot time). */ >> + if (l1d_flush_fallback_area) >> + return; >> + >> l1d_size = ppc64_caches.dsize; >> limit = min(safe_stack_limit(), ppc64_rma_size); >> >> @@ -902,34 +905,23 @@ static void init_fallback_flush(void) >> memset(l1d_flush_fallback_area, 0, l1d_size * 2); >> >> for_each_possible_cpu(cpu) { >> - - /* >> - - * The fallback flush is currently coded for 8-way >> - - * associativity. Different associativity is possible, but it >> - - * will be treated as 8-way and may not evict the lines as >> - - * effectively. >> - - * >> - - * 128 byte lines are mandatory. >> - - */ >> - - u64 c = l1d_size / 8; >> - - >> paca[cpu].rfi_flush_fallback_area = l1d_flush_fallback_area; >> - - paca[cpu].l1d_flush_congruence = c; >> - - paca[cpu].l1d_flush_sets = c / 128; >> + paca[cpu].l1d_flush_size = l1d_size; >> } >> } >> >> - -void __init setup_rfi_flush(enum l1d_flush_type types, bool enable) >> +void setup_rfi_flush(enum l1d_flush_type types, bool enable) >> { >> if (types & L1D_FLUSH_FALLBACK) { >> - - pr_info("rfi-flush: Using fallback displacement flush\n"); >> + pr_info("rfi-flush: fallback displacement flush available\n"); >> init_fallback_flush(); >> } >> >> if (types & L1D_FLUSH_ORI) >> - - pr_info("rfi-flush: Using ori type flush\n"); >> + pr_info("rfi-flush: ori type flush available\n"); >> >> if (types & L1D_FLUSH_MTTRIG) >> - - pr_info("rfi-flush: Using mttrig type flush\n"); >> + pr_info("rfi-flush: mttrig type flush available\n"); >> >> enabled_flush_types = types; >> >> @@ -940,13 +932,19 @@ void __init setup_rfi_flush(enum l1d_flush_type types, bool enable) >> #ifdef CONFIG_DEBUG_FS >> static int rfi_flush_set(void *data, u64 val) >> { >> + bool enable; >> + >> if (val == 1) >> - - rfi_flush_enable(true); >> + enable = true; >> else if (val == 0) >> - - rfi_flush_enable(false); >> + enable = false; >> else >> return -EINVAL; >> >> + /* Only do anything if we're changing state */ >> + if (enable != rfi_flush) >> + rfi_flush_enable(enable); >> + >> return 0; >> } >> >> @@ -965,12 +963,4 @@ static __init int rfi_flush_debugfs_init(void) >> } >> device_initcall(rfi_flush_debugfs_init); >> #endif >> - - >> - -ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf) >> - -{ >> - - if (rfi_flush) >> - - return sprintf(buf, "Mitigation: RFI Flush\n"); >> - - >> - - return sprintf(buf, "Vulnerable\n"); >> - -} >> #endif /* CONFIG_PPC_BOOK3S_64 */ >> diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S >> index 072a23a17350..876ac9d52afc 100644 >> - --- a/arch/powerpc/kernel/vmlinux.lds.S >> +++ b/arch/powerpc/kernel/vmlinux.lds.S >> @@ -73,14 +73,45 @@ SECTIONS >> RODATA >> >> #ifdef CONFIG_PPC64 >> + . = ALIGN(8); >> + __stf_entry_barrier_fixup : AT(ADDR(__stf_entry_barrier_fixup) - LOAD_OFFSET) { >> + __start___stf_entry_barrier_fixup = .; >> + *(__stf_entry_barrier_fixup) >> + __stop___stf_entry_barrier_fixup = .; >> + } >> + >> + . = ALIGN(8); >> + __stf_exit_barrier_fixup : AT(ADDR(__stf_exit_barrier_fixup) - LOAD_OFFSET) { >> + __start___stf_exit_barrier_fixup = .; >> + *(__stf_exit_barrier_fixup) >> + __stop___stf_exit_barrier_fixup = .; >> + } >> + >> . = ALIGN(8); >> __rfi_flush_fixup : AT(ADDR(__rfi_flush_fixup) - LOAD_OFFSET) { >> __start___rfi_flush_fixup = .; >> *(__rfi_flush_fixup) >> __stop___rfi_flush_fixup = .; >> } >> - -#endif >> +#endif /* CONFIG_PPC64 */ >> >> +#ifdef CONFIG_PPC_BARRIER_NOSPEC >> + . = ALIGN(8); >> + __spec_barrier_fixup : AT(ADDR(__spec_barrier_fixup) - LOAD_OFFSET) { >> + __start___barrier_nospec_fixup = .; >> + *(__barrier_nospec_fixup) >> + __stop___barrier_nospec_fixup = .; >> + } >> +#endif /* CONFIG_PPC_BARRIER_NOSPEC */ >> + >> +#ifdef CONFIG_PPC_FSL_BOOK3E >> + . = ALIGN(8); >> + __spec_btb_flush_fixup : AT(ADDR(__spec_btb_flush_fixup) - LOAD_OFFSET) { >> + __start__btb_flush_fixup = .; >> + *(__btb_flush_fixup) >> + __stop__btb_flush_fixup = .; >> + } >> +#endif >> EXCEPTION_TABLE(0) >> >> NOTES :kernel :notes >> diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c >> index d5edbeb8eb82..570c06a00db6 100644 >> - --- a/arch/powerpc/lib/code-patching.c >> +++ b/arch/powerpc/lib/code-patching.c >> @@ -14,12 +14,25 @@ >> #include <asm/page.h> >> #include <asm/code-patching.h> >> #include <asm/uaccess.h> >> +#include <asm/setup.h> >> +#include <asm/sections.h> >> >> >> +static inline bool is_init(unsigned int *addr) >> +{ >> + return addr >= (unsigned int *)__init_begin && addr < (unsigned int *)__init_end; >> +} >> + >> int patch_instruction(unsigned int *addr, unsigned int instr) >> { >> int err; >> >> + /* Make sure we aren't patching a freed init section */ >> + if (init_mem_is_free && is_init(addr)) { >> + pr_debug("Skipping init section patching addr: 0x%px\n", addr); >> + return 0; >> + } >> + >> __put_user_size(instr, addr, 4, err); >> if (err) >> return err; >> @@ -32,6 +45,22 @@ int patch_branch(unsigned int *addr, unsigned long target, int flags) >> return patch_instruction(addr, create_branch(addr, target, flags)); >> } >> >> +int patch_branch_site(s32 *site, unsigned long target, int flags) >> +{ >> + unsigned int *addr; >> + >> + addr = (unsigned int *)((unsigned long)site + *site); >> + return patch_instruction(addr, create_branch(addr, target, flags)); >> +} >> + >> +int patch_instruction_site(s32 *site, unsigned int instr) >> +{ >> + unsigned int *addr; >> + >> + addr = (unsigned int *)((unsigned long)site + *site); >> + return patch_instruction(addr, instr); >> +} >> + >> unsigned int create_branch(const unsigned int *addr, >> unsigned long target, int flags) >> { >> diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c >> index 3af014684872..7bdfc19a491d 100644 >> - --- a/arch/powerpc/lib/feature-fixups.c >> +++ b/arch/powerpc/lib/feature-fixups.c >> @@ -21,7 +21,7 @@ >> #include <asm/page.h> >> #include <asm/sections.h> >> #include <asm/setup.h> >> - - >> +#include <asm/security_features.h> >> >> struct fixup_entry { >> unsigned long mask; >> @@ -115,6 +115,120 @@ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end) >> } >> >> #ifdef CONFIG_PPC_BOOK3S_64 >> +void do_stf_entry_barrier_fixups(enum stf_barrier_type types) >> +{ >> + unsigned int instrs[3], *dest; >> + long *start, *end; >> + int i; >> + >> + start = PTRRELOC(&__start___stf_entry_barrier_fixup), >> + end = PTRRELOC(&__stop___stf_entry_barrier_fixup); >> + >> + instrs[0] = 0x60000000; /* nop */ >> + instrs[1] = 0x60000000; /* nop */ >> + instrs[2] = 0x60000000; /* nop */ >> + >> + i = 0; >> + if (types & STF_BARRIER_FALLBACK) { >> + instrs[i++] = 0x7d4802a6; /* mflr r10 */ >> + instrs[i++] = 0x60000000; /* branch patched below */ >> + instrs[i++] = 0x7d4803a6; /* mtlr r10 */ >> + } else if (types & STF_BARRIER_EIEIO) { >> + instrs[i++] = 0x7e0006ac; /* eieio + bit 6 hint */ >> + } else if (types & STF_BARRIER_SYNC_ORI) { >> + instrs[i++] = 0x7c0004ac; /* hwsync */ >> + instrs[i++] = 0xe94d0000; /* ld r10,0(r13) */ >> + instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */ >> + } >> + >> + for (i = 0; start < end; start++, i++) { >> + dest = (void *)start + *start; >> + >> + pr_devel("patching dest %lx\n", (unsigned long)dest); >> + >> + patch_instruction(dest, instrs[0]); >> + >> + if (types & STF_BARRIER_FALLBACK) >> + patch_branch(dest + 1, (unsigned long)&stf_barrier_fallback, >> + BRANCH_SET_LINK); >> + else >> + patch_instruction(dest + 1, instrs[1]); >> + >> + patch_instruction(dest + 2, instrs[2]); >> + } >> + >> + printk(KERN_DEBUG "stf-barrier: patched %d entry locations (%s barrier)\n", i, >> + (types == STF_BARRIER_NONE) ? "no" : >> + (types == STF_BARRIER_FALLBACK) ? "fallback" : >> + (types == STF_BARRIER_EIEIO) ? "eieio" : >> + (types == (STF_BARRIER_SYNC_ORI)) ? "hwsync" >> + : "unknown"); >> +} >> + >> +void do_stf_exit_barrier_fixups(enum stf_barrier_type types) >> +{ >> + unsigned int instrs[6], *dest; >> + long *start, *end; >> + int i; >> + >> + start = PTRRELOC(&__start___stf_exit_barrier_fixup), >> + end = PTRRELOC(&__stop___stf_exit_barrier_fixup); >> + >> + instrs[0] = 0x60000000; /* nop */ >> + instrs[1] = 0x60000000; /* nop */ >> + instrs[2] = 0x60000000; /* nop */ >> + instrs[3] = 0x60000000; /* nop */ >> + instrs[4] = 0x60000000; /* nop */ >> + instrs[5] = 0x60000000; /* nop */ >> + >> + i = 0; >> + if (types & STF_BARRIER_FALLBACK || types & STF_BARRIER_SYNC_ORI) { >> + if (cpu_has_feature(CPU_FTR_HVMODE)) { >> + instrs[i++] = 0x7db14ba6; /* mtspr 0x131, r13 (HSPRG1) */ >> + instrs[i++] = 0x7db04aa6; /* mfspr r13, 0x130 (HSPRG0) */ >> + } else { >> + instrs[i++] = 0x7db243a6; /* mtsprg 2,r13 */ >> + instrs[i++] = 0x7db142a6; /* mfsprg r13,1 */ >> + } >> + instrs[i++] = 0x7c0004ac; /* hwsync */ >> + instrs[i++] = 0xe9ad0000; /* ld r13,0(r13) */ >> + instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */ >> + if (cpu_has_feature(CPU_FTR_HVMODE)) { >> + instrs[i++] = 0x7db14aa6; /* mfspr r13, 0x131 (HSPRG1) */ >> + } else { >> + instrs[i++] = 0x7db242a6; /* mfsprg r13,2 */ >> + } >> + } else if (types & STF_BARRIER_EIEIO) { >> + instrs[i++] = 0x7e0006ac; /* eieio + bit 6 hint */ >> + } >> + >> + for (i = 0; start < end; start++, i++) { >> + dest = (void *)start + *start; >> + >> + pr_devel("patching dest %lx\n", (unsigned long)dest); >> + >> + patch_instruction(dest, instrs[0]); >> + patch_instruction(dest + 1, instrs[1]); >> + patch_instruction(dest + 2, instrs[2]); >> + patch_instruction(dest + 3, instrs[3]); >> + patch_instruction(dest + 4, instrs[4]); >> + patch_instruction(dest + 5, instrs[5]); >> + } >> + printk(KERN_DEBUG "stf-barrier: patched %d exit locations (%s barrier)\n", i, >> + (types == STF_BARRIER_NONE) ? "no" : >> + (types == STF_BARRIER_FALLBACK) ? "fallback" : >> + (types == STF_BARRIER_EIEIO) ? "eieio" : >> + (types == (STF_BARRIER_SYNC_ORI)) ? "hwsync" >> + : "unknown"); >> +} >> + >> + >> +void do_stf_barrier_fixups(enum stf_barrier_type types) >> +{ >> + do_stf_entry_barrier_fixups(types); >> + do_stf_exit_barrier_fixups(types); >> +} >> + >> void do_rfi_flush_fixups(enum l1d_flush_type types) >> { >> unsigned int instrs[3], *dest; >> @@ -151,10 +265,110 @@ void do_rfi_flush_fixups(enum l1d_flush_type types) >> patch_instruction(dest + 2, instrs[2]); >> } >> >> - - printk(KERN_DEBUG "rfi-flush: patched %d locations\n", i); >> + printk(KERN_DEBUG "rfi-flush: patched %d locations (%s flush)\n", i, >> + (types == L1D_FLUSH_NONE) ? "no" : >> + (types == L1D_FLUSH_FALLBACK) ? "fallback displacement" : >> + (types & L1D_FLUSH_ORI) ? (types & L1D_FLUSH_MTTRIG) >> + ? "ori+mttrig type" >> + : "ori type" : >> + (types & L1D_FLUSH_MTTRIG) ? "mttrig type" >> + : "unknown"); >> +} >> + >> +void do_barrier_nospec_fixups_range(bool enable, void *fixup_start, void *fixup_end) >> +{ >> + unsigned int instr, *dest; >> + long *start, *end; >> + int i; >> + >> + start = fixup_start; >> + end = fixup_end; >> + >> + instr = 0x60000000; /* nop */ >> + >> + if (enable) { >> + pr_info("barrier-nospec: using ORI speculation barrier\n"); >> + instr = 0x63ff0000; /* ori 31,31,0 speculation barrier */ >> + } >> + >> + for (i = 0; start < end; start++, i++) { >> + dest = (void *)start + *start; >> + >> + pr_devel("patching dest %lx\n", (unsigned long)dest); >> + patch_instruction(dest, instr); >> + } >> + >> + printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i); >> } >> + >> #endif /* CONFIG_PPC_BOOK3S_64 */ >> >> +#ifdef CONFIG_PPC_BARRIER_NOSPEC >> +void do_barrier_nospec_fixups(bool enable) >> +{ >> + void *start, *end; >> + >> + start = PTRRELOC(&__start___barrier_nospec_fixup), >> + end = PTRRELOC(&__stop___barrier_nospec_fixup); >> + >> + do_barrier_nospec_fixups_range(enable, start, end); >> +} >> +#endif /* CONFIG_PPC_BARRIER_NOSPEC */ >> + >> +#ifdef CONFIG_PPC_FSL_BOOK3E >> +void do_barrier_nospec_fixups_range(bool enable, void *fixup_start, void *fixup_end) >> +{ >> + unsigned int instr[2], *dest; >> + long *start, *end; >> + int i; >> + >> + start = fixup_start; >> + end = fixup_end; >> + >> + instr[0] = PPC_INST_NOP; >> + instr[1] = PPC_INST_NOP; >> + >> + if (enable) { >> + pr_info("barrier-nospec: using isync; sync as speculation barrier\n"); >> + instr[0] = PPC_INST_ISYNC; >> + instr[1] = PPC_INST_SYNC; >> + } >> + >> + for (i = 0; start < end; start++, i++) { >> + dest = (void *)start + *start; >> + >> + pr_devel("patching dest %lx\n", (unsigned long)dest); >> + patch_instruction(dest, instr[0]); >> + patch_instruction(dest + 1, instr[1]); >> + } >> + >> + printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i); >> +} >> + >> +static void patch_btb_flush_section(long *curr) >> +{ >> + unsigned int *start, *end; >> + >> + start = (void *)curr + *curr; >> + end = (void *)curr + *(curr + 1); >> + for (; start < end; start++) { >> + pr_devel("patching dest %lx\n", (unsigned long)start); >> + patch_instruction(start, PPC_INST_NOP); >> + } >> +} >> + >> +void do_btb_flush_fixups(void) >> +{ >> + long *start, *end; >> + >> + start = PTRRELOC(&__start__btb_flush_fixup); >> + end = PTRRELOC(&__stop__btb_flush_fixup); >> + >> + for (; start < end; start += 2) >> + patch_btb_flush_section(start); >> +} >> +#endif /* CONFIG_PPC_FSL_BOOK3E */ >> + >> void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end) >> { >> long *start, *end; >> diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c >> index 22d94c3e6fc4..1efe5ca5c3bc 100644 >> - --- a/arch/powerpc/mm/mem.c >> +++ b/arch/powerpc/mm/mem.c >> @@ -62,6 +62,7 @@ >> #endif >> >> unsigned long long memory_limit; >> +bool init_mem_is_free; >> >> #ifdef CONFIG_HIGHMEM >> pte_t *kmap_pte; >> @@ -381,6 +382,7 @@ void __init mem_init(void) >> void free_initmem(void) >> { >> ppc_md.progress = ppc_printk_progress; >> + init_mem_is_free = true; >> free_initmem_default(POISON_FREE_INITMEM); >> } >> >> diff --git a/arch/powerpc/mm/tlb_low_64e.S b/arch/powerpc/mm/tlb_low_64e.S >> index 29d6987c37ba..5486d56da289 100644 >> - --- a/arch/powerpc/mm/tlb_low_64e.S >> +++ b/arch/powerpc/mm/tlb_low_64e.S >> @@ -69,6 +69,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV) >> std r15,EX_TLB_R15(r12) >> std r10,EX_TLB_CR(r12) >> #ifdef CONFIG_PPC_FSL_BOOK3E >> +START_BTB_FLUSH_SECTION >> + mfspr r11, SPRN_SRR1 >> + andi. r10,r11,MSR_PR >> + beq 1f >> + BTB_FLUSH(r10) >> +1: >> +END_BTB_FLUSH_SECTION >> std r7,EX_TLB_R7(r12) >> #endif >> TLB_MISS_PROLOG_STATS >> diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c >> index c57afc619b20..e14b52c7ebd8 100644 >> - --- a/arch/powerpc/platforms/powernv/setup.c >> +++ b/arch/powerpc/platforms/powernv/setup.c >> @@ -37,53 +37,99 @@ >> #include <asm/smp.h> >> #include <asm/tm.h> >> #include <asm/setup.h> >> +#include <asm/security_features.h> >> >> #include "powernv.h" >> >> + >> +static bool fw_feature_is(const char *state, const char *name, >> + struct device_node *fw_features) >> +{ >> + struct device_node *np; >> + bool rc = false; >> + >> + np = of_get_child_by_name(fw_features, name); >> + if (np) { >> + rc = of_property_read_bool(np, state); >> + of_node_put(np); >> + } >> + >> + return rc; >> +} >> + >> +static void init_fw_feat_flags(struct device_node *np) >> +{ >> + if (fw_feature_is("enabled", "inst-spec-barrier-ori31,31,0", np)) >> + security_ftr_set(SEC_FTR_SPEC_BAR_ORI31); >> + >> + if (fw_feature_is("enabled", "fw-bcctrl-serialized", np)) >> + security_ftr_set(SEC_FTR_BCCTRL_SERIALISED); >> + >> + if (fw_feature_is("enabled", "inst-l1d-flush-ori30,30,0", np)) >> + security_ftr_set(SEC_FTR_L1D_FLUSH_ORI30); >> + >> + if (fw_feature_is("enabled", "inst-l1d-flush-trig2", np)) >> + security_ftr_set(SEC_FTR_L1D_FLUSH_TRIG2); >> + >> + if (fw_feature_is("enabled", "fw-l1d-thread-split", np)) >> + security_ftr_set(SEC_FTR_L1D_THREAD_PRIV); >> + >> + if (fw_feature_is("enabled", "fw-count-cache-disabled", np)) >> + security_ftr_set(SEC_FTR_COUNT_CACHE_DISABLED); >> + >> + if (fw_feature_is("enabled", "fw-count-cache-flush-bcctr2,0,0", np)) >> + security_ftr_set(SEC_FTR_BCCTR_FLUSH_ASSIST); >> + >> + if (fw_feature_is("enabled", "needs-count-cache-flush-on-context-switch", np)) >> + security_ftr_set(SEC_FTR_FLUSH_COUNT_CACHE); >> + >> + /* >> + * The features below are enabled by default, so we instead look to see >> + * if firmware has *disabled* them, and clear them if so. >> + */ >> + if (fw_feature_is("disabled", "speculation-policy-favor-security", np)) >> + security_ftr_clear(SEC_FTR_FAVOUR_SECURITY); >> + >> + if (fw_feature_is("disabled", "needs-l1d-flush-msr-pr-0-to-1", np)) >> + security_ftr_clear(SEC_FTR_L1D_FLUSH_PR); >> + >> + if (fw_feature_is("disabled", "needs-l1d-flush-msr-hv-1-to-0", np)) >> + security_ftr_clear(SEC_FTR_L1D_FLUSH_HV); >> + >> + if (fw_feature_is("disabled", "needs-spec-barrier-for-bound-checks", np)) >> + security_ftr_clear(SEC_FTR_BNDS_CHK_SPEC_BAR); >> +} >> + >> static void pnv_setup_rfi_flush(void) >> { >> struct device_node *np, *fw_features; >> enum l1d_flush_type type; >> - - int enable; >> + bool enable; >> >> /* Default to fallback in case fw-features are not available */ >> type = L1D_FLUSH_FALLBACK; >> - - enable = 1; >> >> np = of_find_node_by_name(NULL, "ibm,opal"); >> fw_features = of_get_child_by_name(np, "fw-features"); >> of_node_put(np); >> >> if (fw_features) { >> - - np = of_get_child_by_name(fw_features, "inst-l1d-flush-trig2"); >> - - if (np && of_property_read_bool(np, "enabled")) >> - - type = L1D_FLUSH_MTTRIG; >> + init_fw_feat_flags(fw_features); >> + of_node_put(fw_features); >> >> - - of_node_put(np); >> + if (security_ftr_enabled(SEC_FTR_L1D_FLUSH_TRIG2)) >> + type = L1D_FLUSH_MTTRIG; >> >> - - np = of_get_child_by_name(fw_features, "inst-l1d-flush-ori30,30,0"); >> - - if (np && of_property_read_bool(np, "enabled")) >> + if (security_ftr_enabled(SEC_FTR_L1D_FLUSH_ORI30)) >> type = L1D_FLUSH_ORI; >> - - >> - - of_node_put(np); >> - - >> - - /* Enable unless firmware says NOT to */ >> - - enable = 2; >> - - np = of_get_child_by_name(fw_features, "needs-l1d-flush-msr-hv-1-to-0"); >> - - if (np && of_property_read_bool(np, "disabled")) >> - - enable--; >> - - >> - - of_node_put(np); >> - - >> - - np = of_get_child_by_name(fw_features, "needs-l1d-flush-msr-pr-0-to-1"); >> - - if (np && of_property_read_bool(np, "disabled")) >> - - enable--; >> - - >> - - of_node_put(np); >> - - of_node_put(fw_features); >> } >> >> - - setup_rfi_flush(type, enable > 0); >> + enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && \ >> + (security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR) || \ >> + security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV)); >> + >> + setup_rfi_flush(type, enable); >> + setup_count_cache_flush(); >> } >> >> static void __init pnv_setup_arch(void) >> @@ -91,6 +137,7 @@ static void __init pnv_setup_arch(void) >> set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT); >> >> pnv_setup_rfi_flush(); >> + setup_stf_barrier(); >> >> /* Initialize SMP */ >> pnv_smp_init(); >> diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c >> index 8dd0c8edefd6..c773396d0969 100644 >> - --- a/arch/powerpc/platforms/pseries/mobility.c >> +++ b/arch/powerpc/platforms/pseries/mobility.c >> @@ -314,6 +314,9 @@ void post_mobility_fixup(void) >> printk(KERN_ERR "Post-mobility device tree update " >> "failed: %d\n", rc); >> >> + /* Possibly switch to a new RFI flush type */ >> + pseries_setup_rfi_flush(); >> + >> return; >> } >> >> diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h >> index 8411c27293e4..e7d80797384d 100644 >> - --- a/arch/powerpc/platforms/pseries/pseries.h >> +++ b/arch/powerpc/platforms/pseries/pseries.h >> @@ -81,4 +81,6 @@ extern struct pci_controller_ops pseries_pci_controller_ops; >> >> unsigned long pseries_memory_block_size(void); >> >> +void pseries_setup_rfi_flush(void); >> + >> #endif /* _PSERIES_PSERIES_H */ >> diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c >> index dd2545fc9947..9cc976ff7fec 100644 >> - --- a/arch/powerpc/platforms/pseries/setup.c >> +++ b/arch/powerpc/platforms/pseries/setup.c >> @@ -67,6 +67,7 @@ >> #include <asm/eeh.h> >> #include <asm/reg.h> >> #include <asm/plpar_wrappers.h> >> +#include <asm/security_features.h> >> >> #include "pseries.h" >> >> @@ -499,37 +500,87 @@ 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); >> + >> + if (result->character & H_CPU_CHAR_BCCTR_FLUSH_ASSIST) >> + security_ftr_set(SEC_FTR_BCCTR_FLUSH_ASSIST); >> + >> + if (result->behaviour & H_CPU_BEHAV_FLUSH_COUNT_CACHE) >> + security_ftr_set(SEC_FTR_FLUSH_COUNT_CACHE); >> + >> + /* >> + * 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)) >> - - 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); >> + setup_count_cache_flush(); >> } >> >> static void __init pSeries_setup_arch(void) >> @@ -549,6 +600,7 @@ static void __init pSeries_setup_arch(void) >> fwnmi_init(); >> >> pseries_setup_rfi_flush(); >> + setup_stf_barrier(); >> >> /* By default, only probe PCI (can be overridden by rtas_pci) */ >> pci_add_flags(PCI_PROBE_ONLY); >> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c >> index 786bf01691c9..83619ebede93 100644 >> - --- a/arch/powerpc/xmon/xmon.c >> +++ b/arch/powerpc/xmon/xmon.c >> @@ -2144,6 +2144,8 @@ static void dump_one_paca(int cpu) >> DUMP(p, slb_cache_ptr, "x"); >> for (i = 0; i < SLB_CACHE_ENTRIES; i++) >> printf(" slb_cache[%d]: = 0x%016lx\n", i, p->slb_cache[i]); >> + >> + DUMP(p, rfi_flush_fallback_area, "px"); >> #endif >> DUMP(p, dscr_default, "llx"); >> #ifdef CONFIG_PPC_BOOK3E >> - -- >> 2.20.1 >> >> -----BEGIN PGP SIGNATURE----- >> >> iQIcBAEBAgAGBQJcvHWhAAoJEFHr6jzI4aWA6nsP/0YskmAfLovcUmERQ7+bIjq6 >> IcS1T466dvy6MlqeBXU4x8pVgInWeHKEC9XJdkM1lOeib/SLW7Hbz4kgJeOGwFGY >> lOTaexrxvsBqPm7f6GC0zbl9obEIIIIUs+TielFQANBgqm+q8Wio+XXPP9bpKeKY >> agSpQ3nwL/PYixznbNmN/lP9py5p89LQ0IBcR7dDBGGWJtD/AXeZ9hslsZxPbPtI >> nZJ0vdnjuoB2z+hCxfKWlYfLwH0VfoTpqP5x3ALCkvbBr67e8bf6EK8+trnvhyQ8 >> iLY4bp1pm2epAI0/3NfyEiDMsGjVJ6IFlkyhDkHJgJNu0BGcGOSX2GpyU3juviAK >> c95FtBft/i8AwigOMCivg2mN5edYjsSiPoEItwT5KWqgByJsdr5i5mYVx8cUjMOz >> iAxLZCdg+UHZYuCBCAO2ZI1G9bVXI1Pa3btMspiCOOOsYGjXGf0oFfKQ+7957hUO >> ftYYJoGHlMHiHR1OPas6T3lk6YKF9uvfIDTE3OKw2obHbbRz3u82xoWMRGW503MN >> 7WpkpAP7oZ9RgqIWFVhatWy5f+7GFL0akEi4o2tsZHhYlPau7YWo+nToTd87itwt >> GBaWJipzge4s13VkhAE+jWFO35Fvwi8uNZ7UgpuKMBECEjkGbtzBTq2MjSF5G8wc >> yPEod5jby/Iqb7DkGPVG >> =6DnF >> -----END PGP SIGNATURE----- >>