Commit 4d24e21c authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman

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: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200609070610.846703-7-npiggin@gmail.com
parent 70d7cdaf
...@@ -63,6 +63,8 @@ static inline bool security_ftr_enabled(u64 feature) ...@@ -63,6 +63,8 @@ static inline bool security_ftr_enabled(u64 feature)
// bcctr 2,0,0 triggers a hardware assisted count cache flush // bcctr 2,0,0 triggers a hardware assisted count cache flush
#define SEC_FTR_BCCTR_FLUSH_ASSIST 0x0000000000000800ull #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 // 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 ...@@ -219,24 +219,25 @@ ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, c
if (ccd) if (ccd)
seq_buf_printf(&s, "Indirect branch cache disabled"); 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) { } else if (count_cache_flush_type != BRANCH_CACHE_FLUSH_NONE) {
seq_buf_printf(&s, "Mitigation: Software count cache flush"); seq_buf_printf(&s, "Mitigation: Software count cache flush");
if (count_cache_flush_type == BRANCH_CACHE_FLUSH_HW) if (count_cache_flush_type == BRANCH_CACHE_FLUSH_HW)
seq_buf_printf(&s, " (hardware accelerated)"); 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) { } else if (btb_flush_enabled) {
seq_buf_printf(&s, "Mitigation: Branch predictor state flush"); seq_buf_printf(&s, "Mitigation: Branch predictor state flush");
} else { } else {
seq_buf_printf(&s, "Vulnerable"); 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"); seq_buf_printf(&s, "\n");
return s.len; return s.len;
...@@ -435,6 +436,7 @@ static void update_branch_cache_flush(void) ...@@ -435,6 +436,7 @@ static void update_branch_cache_flush(void)
patch_instruction_site(&patch__call_kvm_flush_link_stack, patch_instruction_site(&patch__call_kvm_flush_link_stack,
ppc_inst(PPC_INST_NOP)); ppc_inst(PPC_INST_NOP));
} else { } else {
// Could use HW flush, but that could also flush count cache
patch_branch_site(&patch__call_kvm_flush_link_stack, patch_branch_site(&patch__call_kvm_flush_link_stack,
(u64)&kvm_flush_link_stack, BRANCH_SET_LINK); (u64)&kvm_flush_link_stack, BRANCH_SET_LINK);
} }
...@@ -445,6 +447,10 @@ static void update_branch_cache_flush(void) ...@@ -445,6 +447,10 @@ static void update_branch_cache_flush(void)
link_stack_flush_type == BRANCH_CACHE_FLUSH_NONE) { link_stack_flush_type == BRANCH_CACHE_FLUSH_NONE) {
patch_instruction_site(&patch__call_flush_branch_caches, patch_instruction_site(&patch__call_flush_branch_caches,
ppc_inst(PPC_INST_NOP)); 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 { } else {
patch_branch_site(&patch__call_flush_branch_caches, patch_branch_site(&patch__call_flush_branch_caches,
(u64)&flush_branch_caches, BRANCH_SET_LINK); (u64)&flush_branch_caches, BRANCH_SET_LINK);
...@@ -485,8 +491,13 @@ static void toggle_branch_cache_flush(bool enable) ...@@ -485,8 +491,13 @@ static void toggle_branch_cache_flush(bool enable)
pr_info("link-stack-flush: flush disabled.\n"); pr_info("link-stack-flush: flush disabled.\n");
} else { } else {
link_stack_flush_type = BRANCH_CACHE_FLUSH_SW; if (security_ftr_enabled(SEC_FTR_BCCTR_LINK_FLUSH_ASSIST)) {
pr_info("link-stack-flush: software flush enabled.\n"); 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(); update_branch_cache_flush();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment