powerpc/security: Allow for processors that flush the link stack using the special bcctr
If both count cache and link stack are to be flushed, and can be flushed with the special bcctr, patch that in directly to the flush/branch nop site. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20200609070610.846703-7-npiggin@gmail.com
This commit is contained in:
parent
70d7cdaf05
commit
4d24e21cc6
@ -63,6 +63,8 @@ static inline bool security_ftr_enabled(u64 feature)
|
||||
// bcctr 2,0,0 triggers a hardware assisted count cache flush
|
||||
#define SEC_FTR_BCCTR_FLUSH_ASSIST 0x0000000000000800ull
|
||||
|
||||
// bcctr 2,0,0 triggers a hardware assisted link stack flush
|
||||
#define SEC_FTR_BCCTR_LINK_FLUSH_ASSIST 0x0000000000002000ull
|
||||
|
||||
// Features indicating need for Spectre/Meltdown mitigations
|
||||
|
||||
|
@ -219,24 +219,25 @@ ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, c
|
||||
if (ccd)
|
||||
seq_buf_printf(&s, "Indirect branch cache disabled");
|
||||
|
||||
if (link_stack_flush_type == BRANCH_CACHE_FLUSH_SW)
|
||||
seq_buf_printf(&s, ", Software link stack flush");
|
||||
|
||||
} else if (count_cache_flush_type != BRANCH_CACHE_FLUSH_NONE) {
|
||||
seq_buf_printf(&s, "Mitigation: Software count cache flush");
|
||||
|
||||
if (count_cache_flush_type == BRANCH_CACHE_FLUSH_HW)
|
||||
seq_buf_printf(&s, " (hardware accelerated)");
|
||||
|
||||
if (link_stack_flush_type == BRANCH_CACHE_FLUSH_SW)
|
||||
seq_buf_printf(&s, ", Software link stack flush");
|
||||
|
||||
} else if (btb_flush_enabled) {
|
||||
seq_buf_printf(&s, "Mitigation: Branch predictor state flush");
|
||||
} else {
|
||||
seq_buf_printf(&s, "Vulnerable");
|
||||
}
|
||||
|
||||
if (bcs || ccd || count_cache_flush_type != BRANCH_CACHE_FLUSH_NONE) {
|
||||
if (link_stack_flush_type != BRANCH_CACHE_FLUSH_NONE)
|
||||
seq_buf_printf(&s, ", Software link stack flush");
|
||||
if (link_stack_flush_type == BRANCH_CACHE_FLUSH_HW)
|
||||
seq_buf_printf(&s, " (hardware accelerated)");
|
||||
}
|
||||
|
||||
seq_buf_printf(&s, "\n");
|
||||
|
||||
return s.len;
|
||||
@ -435,6 +436,7 @@ static void update_branch_cache_flush(void)
|
||||
patch_instruction_site(&patch__call_kvm_flush_link_stack,
|
||||
ppc_inst(PPC_INST_NOP));
|
||||
} else {
|
||||
// Could use HW flush, but that could also flush count cache
|
||||
patch_branch_site(&patch__call_kvm_flush_link_stack,
|
||||
(u64)&kvm_flush_link_stack, BRANCH_SET_LINK);
|
||||
}
|
||||
@ -445,6 +447,10 @@ static void update_branch_cache_flush(void)
|
||||
link_stack_flush_type == BRANCH_CACHE_FLUSH_NONE) {
|
||||
patch_instruction_site(&patch__call_flush_branch_caches,
|
||||
ppc_inst(PPC_INST_NOP));
|
||||
} else if (count_cache_flush_type == BRANCH_CACHE_FLUSH_HW &&
|
||||
link_stack_flush_type == BRANCH_CACHE_FLUSH_HW) {
|
||||
patch_instruction_site(&patch__call_flush_branch_caches,
|
||||
ppc_inst(PPC_INST_BCCTR_FLUSH));
|
||||
} else {
|
||||
patch_branch_site(&patch__call_flush_branch_caches,
|
||||
(u64)&flush_branch_caches, BRANCH_SET_LINK);
|
||||
@ -485,8 +491,13 @@ static void toggle_branch_cache_flush(bool enable)
|
||||
|
||||
pr_info("link-stack-flush: flush disabled.\n");
|
||||
} else {
|
||||
link_stack_flush_type = BRANCH_CACHE_FLUSH_SW;
|
||||
pr_info("link-stack-flush: software flush enabled.\n");
|
||||
if (security_ftr_enabled(SEC_FTR_BCCTR_LINK_FLUSH_ASSIST)) {
|
||||
link_stack_flush_type = BRANCH_CACHE_FLUSH_HW;
|
||||
pr_info("link-stack-flush: hardware flush enabled.\n");
|
||||
} else {
|
||||
link_stack_flush_type = BRANCH_CACHE_FLUSH_SW;
|
||||
pr_info("link-stack-flush: software flush enabled.\n");
|
||||
}
|
||||
}
|
||||
|
||||
update_branch_cache_flush();
|
||||
|
Loading…
Reference in New Issue
Block a user