diff options
-rw-r--r-- | arch/arm64/include/asm/assembler.h | 136 | ||||
-rw-r--r-- | arch/arm64/include/asm/cpucaps.h | 13 | ||||
-rw-r--r-- | arch/arm64/include/asm/kvm_asm.h | 2 | ||||
-rw-r--r-- | arch/arm64/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/arm64/kernel/asm-offsets.c | 3 | ||||
-rw-r--r-- | arch/arm64/kernel/bpi.S | 102 | ||||
-rw-r--r-- | arch/arm64/kernel/cpu_errata.c | 97 | ||||
-rw-r--r-- | arch/arm64/kvm/hyp/entry.S | 12 | ||||
-rw-r--r-- | arch/arm64/kvm/hyp/hyp-entry.S | 64 | ||||
-rw-r--r-- | arch/arm64/kvm/hyp/switch.c | 10 |
10 files changed, 242 insertions, 199 deletions
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index 053d83e8db6f..0bcc98dbba56 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h | |||
@@ -565,4 +565,140 @@ USER(\label, ic ivau, \tmp2) // invalidate I line PoU | |||
565 | #endif | 565 | #endif |
566 | .endm | 566 | .endm |
567 | 567 | ||
568 | /* | ||
569 | * frame_push - Push @regcount callee saved registers to the stack, | ||
570 | * starting at x19, as well as x29/x30, and set x29 to | ||
571 | * the new value of sp. Add @extra bytes of stack space | ||
572 | * for locals. | ||
573 | */ | ||
574 | .macro frame_push, regcount:req, extra | ||
575 | __frame st, \regcount, \extra | ||
576 | .endm | ||
577 | |||
578 | /* | ||
579 | * frame_pop - Pop the callee saved registers from the stack that were | ||
580 | * pushed in the most recent call to frame_push, as well | ||
581 | * as x29/x30 and any extra stack space that may have been | ||
582 | * allocated. | ||
583 | */ | ||
584 | .macro frame_pop | ||
585 | __frame ld | ||
586 | .endm | ||
587 | |||
588 | .macro __frame_regs, reg1, reg2, op, num | ||
589 | .if .Lframe_regcount == \num | ||
590 | \op\()r \reg1, [sp, #(\num + 1) * 8] | ||
591 | .elseif .Lframe_regcount > \num | ||
592 | \op\()p \reg1, \reg2, [sp, #(\num + 1) * 8] | ||
593 | .endif | ||
594 | .endm | ||
595 | |||
596 | .macro __frame, op, regcount, extra=0 | ||
597 | .ifc \op, st | ||
598 | .if (\regcount) < 0 || (\regcount) > 10 | ||
599 | .error "regcount should be in the range [0 ... 10]" | ||
600 | .endif | ||
601 | .if ((\extra) % 16) != 0 | ||
602 | .error "extra should be a multiple of 16 bytes" | ||
603 | .endif | ||
604 | .ifdef .Lframe_regcount | ||
605 | .if .Lframe_regcount != -1 | ||
606 | .error "frame_push/frame_pop may not be nested" | ||
607 | .endif | ||
608 | .endif | ||
609 | .set .Lframe_regcount, \regcount | ||
610 | .set .Lframe_extra, \extra | ||
611 | .set .Lframe_local_offset, ((\regcount + 3) / 2) * 16 | ||
612 | stp x29, x30, [sp, #-.Lframe_local_offset - .Lframe_extra]! | ||
613 | mov x29, sp | ||
614 | .endif | ||
615 | |||
616 | __frame_regs x19, x20, \op, 1 | ||
617 | __frame_regs x21, x22, \op, 3 | ||
618 | __frame_regs x23, x24, \op, 5 | ||
619 | __frame_regs x25, x26, \op, 7 | ||
620 | __frame_regs x27, x28, \op, 9 | ||
621 | |||
622 | .ifc \op, ld | ||
623 | .if .Lframe_regcount == -1 | ||
624 | .error "frame_push/frame_pop may not be nested" | ||
625 | .endif | ||
626 | ldp x29, x30, [sp], #.Lframe_local_offset + .Lframe_extra | ||
627 | .set .Lframe_regcount, -1 | ||
628 | .endif | ||
629 | .endm | ||
630 | |||
631 | /* | ||
632 | * Check whether to yield to another runnable task from kernel mode NEON code | ||
633 | * (which runs with preemption disabled). | ||
634 | * | ||
635 | * if_will_cond_yield_neon | ||
636 | * // pre-yield patchup code | ||
637 | * do_cond_yield_neon | ||
638 | * // post-yield patchup code | ||
639 | * endif_yield_neon <label> | ||
640 | * | ||
641 | * where <label> is optional, and marks the point where execution will resume | ||
642 | * after a yield has been performed. If omitted, execution resumes right after | ||
643 | * the endif_yield_neon invocation. Note that the entire sequence, including | ||
644 | * the provided patchup code, will be omitted from the image if CONFIG_PREEMPT | ||
645 | * is not defined. | ||
646 | * | ||
647 | * As a convenience, in the case where no patchup code is required, the above | ||
648 | * sequence may be abbreviated to | ||
649 | * | ||
650 | * cond_yield_neon <label> | ||
651 | * | ||
652 | * Note that the patchup code does not support assembler directives that change | ||
653 | * the output section, any use of such directives is undefined. | ||
654 | * | ||
655 | * The yield itself consists of the following: | ||
656 | * - Check whether the preempt count is exactly 1, in which case disabling | ||
657 | * preemption once will make the task preemptible. If this is not the case, | ||
658 | * yielding is pointless. | ||
659 | * - Check whether TIF_NEED_RESCHED is set, and if so, disable and re-enable | ||
660 | * kernel mode NEON (which will trigger a reschedule), and branch to the | ||
661 | * yield fixup code. | ||
662 | * | ||
663 | * This macro sequence may clobber all CPU state that is not guaranteed by the | ||
664 | * AAPCS to be preserved across an ordinary function call. | ||
665 | */ | ||
666 | |||
667 | .macro cond_yield_neon, lbl | ||
668 | if_will_cond_yield_neon | ||
669 | do_cond_yield_neon | ||
670 | endif_yield_neon \lbl | ||
671 | .endm | ||
672 | |||
673 | .macro if_will_cond_yield_neon | ||
674 | #ifdef CONFIG_PREEMPT | ||
675 | get_thread_info x0 | ||
676 | ldr w1, [x0, #TSK_TI_PREEMPT] | ||
677 | ldr x0, [x0, #TSK_TI_FLAGS] | ||
678 | cmp w1, #PREEMPT_DISABLE_OFFSET | ||
679 | csel x0, x0, xzr, eq | ||
680 | tbnz x0, #TIF_NEED_RESCHED, .Lyield_\@ // needs rescheduling? | ||
681 | /* fall through to endif_yield_neon */ | ||
682 | .subsection 1 | ||
683 | .Lyield_\@ : | ||
684 | #else | ||
685 | .section ".discard.cond_yield_neon", "ax" | ||
686 | #endif | ||
687 | .endm | ||
688 | |||
689 | .macro do_cond_yield_neon | ||
690 | bl kernel_neon_end | ||
691 | bl kernel_neon_begin | ||
692 | .endm | ||
693 | |||
694 | .macro endif_yield_neon, lbl | ||
695 | .ifnb \lbl | ||
696 | b \lbl | ||
697 | .else | ||
698 | b .Lyield_out_\@ | ||
699 | .endif | ||
700 | .previous | ||
701 | .Lyield_out_\@ : | ||
702 | .endm | ||
703 | |||
568 | #endif /* __ASM_ASSEMBLER_H */ | 704 | #endif /* __ASM_ASSEMBLER_H */ |
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h index a311880feb0f..bc51b72fafd4 100644 --- a/arch/arm64/include/asm/cpucaps.h +++ b/arch/arm64/include/asm/cpucaps.h | |||
@@ -43,13 +43,12 @@ | |||
43 | #define ARM64_SVE 22 | 43 | #define ARM64_SVE 22 |
44 | #define ARM64_UNMAP_KERNEL_AT_EL0 23 | 44 | #define ARM64_UNMAP_KERNEL_AT_EL0 23 |
45 | #define ARM64_HARDEN_BRANCH_PREDICTOR 24 | 45 | #define ARM64_HARDEN_BRANCH_PREDICTOR 24 |
46 | #define ARM64_HARDEN_BP_POST_GUEST_EXIT 25 | 46 | #define ARM64_HAS_RAS_EXTN 25 |
47 | #define ARM64_HAS_RAS_EXTN 26 | 47 | #define ARM64_WORKAROUND_843419 26 |
48 | #define ARM64_WORKAROUND_843419 27 | 48 | #define ARM64_HAS_CACHE_IDC 27 |
49 | #define ARM64_HAS_CACHE_IDC 28 | 49 | #define ARM64_HAS_CACHE_DIC 28 |
50 | #define ARM64_HAS_CACHE_DIC 29 | 50 | #define ARM64_HW_DBM 29 |
51 | #define ARM64_HW_DBM 30 | ||
52 | 51 | ||
53 | #define ARM64_NCAPS 31 | 52 | #define ARM64_NCAPS 30 |
54 | 53 | ||
55 | #endif /* __ASM_CPUCAPS_H */ | 54 | #endif /* __ASM_CPUCAPS_H */ |
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index d53d40704416..f6648a3e4152 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h | |||
@@ -71,8 +71,6 @@ extern u32 __kvm_get_mdcr_el2(void); | |||
71 | 71 | ||
72 | extern u32 __init_stage2_translation(void); | 72 | extern u32 __init_stage2_translation(void); |
73 | 73 | ||
74 | extern void __qcom_hyp_sanitize_btac_predictors(void); | ||
75 | |||
76 | #else /* __ASSEMBLY__ */ | 74 | #else /* __ASSEMBLY__ */ |
77 | 75 | ||
78 | .macro get_host_ctxt reg, tmp | 76 | .macro get_host_ctxt reg, tmp |
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 9b55a3f24be7..bf825f38d206 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile | |||
@@ -55,8 +55,6 @@ arm64-reloc-test-y := reloc_test_core.o reloc_test_syms.o | |||
55 | arm64-obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | 55 | arm64-obj-$(CONFIG_CRASH_DUMP) += crash_dump.o |
56 | arm64-obj-$(CONFIG_ARM_SDE_INTERFACE) += sdei.o | 56 | arm64-obj-$(CONFIG_ARM_SDE_INTERFACE) += sdei.o |
57 | 57 | ||
58 | arm64-obj-$(CONFIG_KVM_INDIRECT_VECTORS)+= bpi.o | ||
59 | |||
60 | obj-y += $(arm64-obj-y) vdso/ probes/ | 58 | obj-y += $(arm64-obj-y) vdso/ probes/ |
61 | obj-m += $(arm64-obj-m) | 59 | obj-m += $(arm64-obj-m) |
62 | head-y := head.o | 60 | head-y := head.o |
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index 78e1b0a70aaf..5bdda651bd05 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
24 | #include <linux/dma-mapping.h> | 24 | #include <linux/dma-mapping.h> |
25 | #include <linux/kvm_host.h> | 25 | #include <linux/kvm_host.h> |
26 | #include <linux/preempt.h> | ||
26 | #include <linux/suspend.h> | 27 | #include <linux/suspend.h> |
27 | #include <asm/cpufeature.h> | 28 | #include <asm/cpufeature.h> |
28 | #include <asm/fixmap.h> | 29 | #include <asm/fixmap.h> |
@@ -93,6 +94,8 @@ int main(void) | |||
93 | DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE); | 94 | DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE); |
94 | DEFINE(DMA_FROM_DEVICE, DMA_FROM_DEVICE); | 95 | DEFINE(DMA_FROM_DEVICE, DMA_FROM_DEVICE); |
95 | BLANK(); | 96 | BLANK(); |
97 | DEFINE(PREEMPT_DISABLE_OFFSET, PREEMPT_DISABLE_OFFSET); | ||
98 | BLANK(); | ||
96 | DEFINE(CLOCK_REALTIME, CLOCK_REALTIME); | 99 | DEFINE(CLOCK_REALTIME, CLOCK_REALTIME); |
97 | DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC); | 100 | DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC); |
98 | DEFINE(CLOCK_MONOTONIC_RAW, CLOCK_MONOTONIC_RAW); | 101 | DEFINE(CLOCK_MONOTONIC_RAW, CLOCK_MONOTONIC_RAW); |
diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S deleted file mode 100644 index bb0b67722e86..000000000000 --- a/arch/arm64/kernel/bpi.S +++ /dev/null | |||
@@ -1,102 +0,0 @@ | |||
1 | /* | ||
2 | * Contains CPU specific branch predictor invalidation sequences | ||
3 | * | ||
4 | * Copyright (C) 2018 ARM Ltd. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #include <linux/linkage.h> | ||
20 | #include <linux/arm-smccc.h> | ||
21 | |||
22 | #include <asm/alternative.h> | ||
23 | #include <asm/mmu.h> | ||
24 | |||
25 | .macro hyp_ventry | ||
26 | .align 7 | ||
27 | 1: .rept 27 | ||
28 | nop | ||
29 | .endr | ||
30 | /* | ||
31 | * The default sequence is to directly branch to the KVM vectors, | ||
32 | * using the computed offset. This applies for VHE as well as | ||
33 | * !ARM64_HARDEN_EL2_VECTORS. | ||
34 | * | ||
35 | * For ARM64_HARDEN_EL2_VECTORS configurations, this gets replaced | ||
36 | * with: | ||
37 | * | ||
38 | * stp x0, x1, [sp, #-16]! | ||
39 | * movz x0, #(addr & 0xffff) | ||
40 | * movk x0, #((addr >> 16) & 0xffff), lsl #16 | ||
41 | * movk x0, #((addr >> 32) & 0xffff), lsl #32 | ||
42 | * br x0 | ||
43 | * | ||
44 | * Where addr = kern_hyp_va(__kvm_hyp_vector) + vector-offset + 4. | ||
45 | * See kvm_patch_vector_branch for details. | ||
46 | */ | ||
47 | alternative_cb kvm_patch_vector_branch | ||
48 | b __kvm_hyp_vector + (1b - 0b) | ||
49 | nop | ||
50 | nop | ||
51 | nop | ||
52 | nop | ||
53 | alternative_cb_end | ||
54 | .endm | ||
55 | |||
56 | .macro generate_vectors | ||
57 | 0: | ||
58 | .rept 16 | ||
59 | hyp_ventry | ||
60 | .endr | ||
61 | .org 0b + SZ_2K // Safety measure | ||
62 | .endm | ||
63 | |||
64 | |||
65 | .text | ||
66 | .pushsection .hyp.text, "ax" | ||
67 | |||
68 | .align 11 | ||
69 | ENTRY(__bp_harden_hyp_vecs_start) | ||
70 | .rept BP_HARDEN_EL2_SLOTS | ||
71 | generate_vectors | ||
72 | .endr | ||
73 | ENTRY(__bp_harden_hyp_vecs_end) | ||
74 | |||
75 | .popsection | ||
76 | |||
77 | ENTRY(__qcom_hyp_sanitize_link_stack_start) | ||
78 | stp x29, x30, [sp, #-16]! | ||
79 | .rept 16 | ||
80 | bl . + 4 | ||
81 | .endr | ||
82 | ldp x29, x30, [sp], #16 | ||
83 | ENTRY(__qcom_hyp_sanitize_link_stack_end) | ||
84 | |||
85 | .macro smccc_workaround_1 inst | ||
86 | sub sp, sp, #(8 * 4) | ||
87 | stp x2, x3, [sp, #(8 * 0)] | ||
88 | stp x0, x1, [sp, #(8 * 2)] | ||
89 | mov w0, #ARM_SMCCC_ARCH_WORKAROUND_1 | ||
90 | \inst #0 | ||
91 | ldp x2, x3, [sp, #(8 * 0)] | ||
92 | ldp x0, x1, [sp, #(8 * 2)] | ||
93 | add sp, sp, #(8 * 4) | ||
94 | .endm | ||
95 | |||
96 | ENTRY(__smccc_workaround_1_smc_start) | ||
97 | smccc_workaround_1 smc | ||
98 | ENTRY(__smccc_workaround_1_smc_end) | ||
99 | |||
100 | ENTRY(__smccc_workaround_1_hvc_start) | ||
101 | smccc_workaround_1 hvc | ||
102 | ENTRY(__smccc_workaround_1_hvc_end) | ||
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 9262ec57f5ab..a900befadfe8 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c | |||
@@ -86,13 +86,9 @@ atomic_t arm64_el2_vector_last_slot = ATOMIC_INIT(-1); | |||
86 | 86 | ||
87 | DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data); | 87 | DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data); |
88 | 88 | ||
89 | #ifdef CONFIG_KVM | 89 | #ifdef CONFIG_KVM_INDIRECT_VECTORS |
90 | extern char __qcom_hyp_sanitize_link_stack_start[]; | ||
91 | extern char __qcom_hyp_sanitize_link_stack_end[]; | ||
92 | extern char __smccc_workaround_1_smc_start[]; | 90 | extern char __smccc_workaround_1_smc_start[]; |
93 | extern char __smccc_workaround_1_smc_end[]; | 91 | extern char __smccc_workaround_1_smc_end[]; |
94 | extern char __smccc_workaround_1_hvc_start[]; | ||
95 | extern char __smccc_workaround_1_hvc_end[]; | ||
96 | 92 | ||
97 | static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start, | 93 | static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start, |
98 | const char *hyp_vecs_end) | 94 | const char *hyp_vecs_end) |
@@ -132,12 +128,8 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn, | |||
132 | spin_unlock(&bp_lock); | 128 | spin_unlock(&bp_lock); |
133 | } | 129 | } |
134 | #else | 130 | #else |
135 | #define __qcom_hyp_sanitize_link_stack_start NULL | ||
136 | #define __qcom_hyp_sanitize_link_stack_end NULL | ||
137 | #define __smccc_workaround_1_smc_start NULL | 131 | #define __smccc_workaround_1_smc_start NULL |
138 | #define __smccc_workaround_1_smc_end NULL | 132 | #define __smccc_workaround_1_smc_end NULL |
139 | #define __smccc_workaround_1_hvc_start NULL | ||
140 | #define __smccc_workaround_1_hvc_end NULL | ||
141 | 133 | ||
142 | static void __install_bp_hardening_cb(bp_hardening_cb_t fn, | 134 | static void __install_bp_hardening_cb(bp_hardening_cb_t fn, |
143 | const char *hyp_vecs_start, | 135 | const char *hyp_vecs_start, |
@@ -145,7 +137,7 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn, | |||
145 | { | 137 | { |
146 | __this_cpu_write(bp_hardening_data.fn, fn); | 138 | __this_cpu_write(bp_hardening_data.fn, fn); |
147 | } | 139 | } |
148 | #endif /* CONFIG_KVM */ | 140 | #endif /* CONFIG_KVM_INDIRECT_VECTORS */ |
149 | 141 | ||
150 | static void install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry, | 142 | static void install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry, |
151 | bp_hardening_cb_t fn, | 143 | bp_hardening_cb_t fn, |
@@ -178,12 +170,25 @@ static void call_hvc_arch_workaround_1(void) | |||
178 | arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL); | 170 | arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL); |
179 | } | 171 | } |
180 | 172 | ||
173 | static void qcom_link_stack_sanitization(void) | ||
174 | { | ||
175 | u64 tmp; | ||
176 | |||
177 | asm volatile("mov %0, x30 \n" | ||
178 | ".rept 16 \n" | ||
179 | "bl . + 4 \n" | ||
180 | ".endr \n" | ||
181 | "mov x30, %0 \n" | ||
182 | : "=&r" (tmp)); | ||
183 | } | ||
184 | |||
181 | static void | 185 | static void |
182 | enable_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry) | 186 | enable_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry) |
183 | { | 187 | { |
184 | bp_hardening_cb_t cb; | 188 | bp_hardening_cb_t cb; |
185 | void *smccc_start, *smccc_end; | 189 | void *smccc_start, *smccc_end; |
186 | struct arm_smccc_res res; | 190 | struct arm_smccc_res res; |
191 | u32 midr = read_cpuid_id(); | ||
187 | 192 | ||
188 | if (!entry->matches(entry, SCOPE_LOCAL_CPU)) | 193 | if (!entry->matches(entry, SCOPE_LOCAL_CPU)) |
189 | return; | 194 | return; |
@@ -198,8 +203,9 @@ enable_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry) | |||
198 | if ((int)res.a0 < 0) | 203 | if ((int)res.a0 < 0) |
199 | return; | 204 | return; |
200 | cb = call_hvc_arch_workaround_1; | 205 | cb = call_hvc_arch_workaround_1; |
201 | smccc_start = __smccc_workaround_1_hvc_start; | 206 | /* This is a guest, no need to patch KVM vectors */ |
202 | smccc_end = __smccc_workaround_1_hvc_end; | 207 | smccc_start = NULL; |
208 | smccc_end = NULL; | ||
203 | break; | 209 | break; |
204 | 210 | ||
205 | case PSCI_CONDUIT_SMC: | 211 | case PSCI_CONDUIT_SMC: |
@@ -216,30 +222,14 @@ enable_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry) | |||
216 | return; | 222 | return; |
217 | } | 223 | } |
218 | 224 | ||
225 | if (((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR) || | ||
226 | ((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR_V1)) | ||
227 | cb = qcom_link_stack_sanitization; | ||
228 | |||
219 | install_bp_hardening_cb(entry, cb, smccc_start, smccc_end); | 229 | install_bp_hardening_cb(entry, cb, smccc_start, smccc_end); |
220 | 230 | ||
221 | return; | 231 | return; |
222 | } | 232 | } |
223 | |||
224 | static void qcom_link_stack_sanitization(void) | ||
225 | { | ||
226 | u64 tmp; | ||
227 | |||
228 | asm volatile("mov %0, x30 \n" | ||
229 | ".rept 16 \n" | ||
230 | "bl . + 4 \n" | ||
231 | ".endr \n" | ||
232 | "mov x30, %0 \n" | ||
233 | : "=&r" (tmp)); | ||
234 | } | ||
235 | |||
236 | static void | ||
237 | qcom_enable_link_stack_sanitization(const struct arm64_cpu_capabilities *entry) | ||
238 | { | ||
239 | install_bp_hardening_cb(entry, qcom_link_stack_sanitization, | ||
240 | __qcom_hyp_sanitize_link_stack_start, | ||
241 | __qcom_hyp_sanitize_link_stack_end); | ||
242 | } | ||
243 | #endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */ | 233 | #endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */ |
244 | 234 | ||
245 | #define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max) \ | 235 | #define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max) \ |
@@ -324,33 +314,23 @@ static const struct midr_range arm64_bp_harden_smccc_cpus[] = { | |||
324 | MIDR_ALL_VERSIONS(MIDR_CORTEX_A75), | 314 | MIDR_ALL_VERSIONS(MIDR_CORTEX_A75), |
325 | MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN), | 315 | MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN), |
326 | MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2), | 316 | MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2), |
327 | {}, | ||
328 | }; | ||
329 | |||
330 | static const struct midr_range qcom_bp_harden_cpus[] = { | ||
331 | MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1), | 317 | MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1), |
332 | MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR), | 318 | MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR), |
333 | {}, | 319 | {}, |
334 | }; | 320 | }; |
335 | 321 | ||
336 | static const struct arm64_cpu_capabilities arm64_bp_harden_list[] = { | 322 | #endif |
337 | { | 323 | |
338 | CAP_MIDR_RANGE_LIST(arm64_bp_harden_smccc_cpus), | 324 | #ifdef CONFIG_HARDEN_EL2_VECTORS |
339 | .cpu_enable = enable_smccc_arch_workaround_1, | 325 | |
340 | }, | 326 | static const struct midr_range arm64_harden_el2_vectors[] = { |
341 | { | 327 | MIDR_ALL_VERSIONS(MIDR_CORTEX_A57), |
342 | CAP_MIDR_RANGE_LIST(qcom_bp_harden_cpus), | 328 | MIDR_ALL_VERSIONS(MIDR_CORTEX_A72), |
343 | .cpu_enable = qcom_enable_link_stack_sanitization, | ||
344 | }, | ||
345 | {}, | 329 | {}, |
346 | }; | 330 | }; |
347 | 331 | ||
348 | #endif | 332 | #endif |
349 | 333 | ||
350 | #ifndef ERRATA_MIDR_ALL_VERSIONS | ||
351 | #define ERRATA_MIDR_ALL_VERSIONS(x) MIDR_ALL_VERSIONS(x) | ||
352 | #endif | ||
353 | |||
354 | const struct arm64_cpu_capabilities arm64_errata[] = { | 334 | const struct arm64_cpu_capabilities arm64_errata[] = { |
355 | #if defined(CONFIG_ARM64_ERRATUM_826319) || \ | 335 | #if defined(CONFIG_ARM64_ERRATUM_826319) || \ |
356 | defined(CONFIG_ARM64_ERRATUM_827319) || \ | 336 | defined(CONFIG_ARM64_ERRATUM_827319) || \ |
@@ -495,25 +475,16 @@ const struct arm64_cpu_capabilities arm64_errata[] = { | |||
495 | { | 475 | { |
496 | .capability = ARM64_HARDEN_BRANCH_PREDICTOR, | 476 | .capability = ARM64_HARDEN_BRANCH_PREDICTOR, |
497 | .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, | 477 | .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, |
498 | .matches = multi_entry_cap_matches, | 478 | .cpu_enable = enable_smccc_arch_workaround_1, |
499 | .cpu_enable = multi_entry_cap_cpu_enable, | 479 | ERRATA_MIDR_RANGE_LIST(arm64_bp_harden_smccc_cpus), |
500 | .match_list = arm64_bp_harden_list, | ||
501 | }, | ||
502 | { | ||
503 | .capability = ARM64_HARDEN_BP_POST_GUEST_EXIT, | ||
504 | ERRATA_MIDR_RANGE_LIST(qcom_bp_harden_cpus), | ||
505 | }, | 480 | }, |
506 | #endif | 481 | #endif |
507 | #ifdef CONFIG_HARDEN_EL2_VECTORS | 482 | #ifdef CONFIG_HARDEN_EL2_VECTORS |
508 | { | 483 | { |
509 | .desc = "Cortex-A57 EL2 vector hardening", | 484 | .desc = "EL2 vector hardening", |
510 | .capability = ARM64_HARDEN_EL2_VECTORS, | ||
511 | ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A57), | ||
512 | }, | ||
513 | { | ||
514 | .desc = "Cortex-A72 EL2 vector hardening", | ||
515 | .capability = ARM64_HARDEN_EL2_VECTORS, | 485 | .capability = ARM64_HARDEN_EL2_VECTORS, |
516 | ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72), | 486 | .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, |
487 | ERRATA_MIDR_RANGE_LIST(arm64_harden_el2_vectors), | ||
517 | }, | 488 | }, |
518 | #endif | 489 | #endif |
519 | { | 490 | { |
diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S index 1f458f7c3b44..e41a161d313a 100644 --- a/arch/arm64/kvm/hyp/entry.S +++ b/arch/arm64/kvm/hyp/entry.S | |||
@@ -209,15 +209,3 @@ alternative_endif | |||
209 | 209 | ||
210 | eret | 210 | eret |
211 | ENDPROC(__fpsimd_guest_restore) | 211 | ENDPROC(__fpsimd_guest_restore) |
212 | |||
213 | ENTRY(__qcom_hyp_sanitize_btac_predictors) | ||
214 | /** | ||
215 | * Call SMC64 with Silicon provider serviceID 23<<8 (0xc2001700) | ||
216 | * 0xC2000000-0xC200FFFF: assigned to SiP Service Calls | ||
217 | * b15-b0: contains SiP functionID | ||
218 | */ | ||
219 | movz x0, #0x1700 | ||
220 | movk x0, #0xc200, lsl #16 | ||
221 | smc #0 | ||
222 | ret | ||
223 | ENDPROC(__qcom_hyp_sanitize_btac_predictors) | ||
diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S index 87dfecce82b1..bffece27b5c1 100644 --- a/arch/arm64/kvm/hyp/hyp-entry.S +++ b/arch/arm64/kvm/hyp/hyp-entry.S | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2015 - ARM Ltd | 2 | * Copyright (C) 2015-2018 - ARM Ltd |
3 | * Author: Marc Zyngier <marc.zyngier@arm.com> | 3 | * Author: Marc Zyngier <marc.zyngier@arm.com> |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/kvm_arm.h> | 24 | #include <asm/kvm_arm.h> |
25 | #include <asm/kvm_asm.h> | 25 | #include <asm/kvm_asm.h> |
26 | #include <asm/kvm_mmu.h> | 26 | #include <asm/kvm_mmu.h> |
27 | #include <asm/mmu.h> | ||
27 | 28 | ||
28 | .text | 29 | .text |
29 | .pushsection .hyp.text, "ax" | 30 | .pushsection .hyp.text, "ax" |
@@ -237,3 +238,64 @@ ENTRY(__kvm_hyp_vector) | |||
237 | invalid_vect el1_fiq_invalid // FIQ 32-bit EL1 | 238 | invalid_vect el1_fiq_invalid // FIQ 32-bit EL1 |
238 | valid_vect el1_error // Error 32-bit EL1 | 239 | valid_vect el1_error // Error 32-bit EL1 |
239 | ENDPROC(__kvm_hyp_vector) | 240 | ENDPROC(__kvm_hyp_vector) |
241 | |||
242 | #ifdef CONFIG_KVM_INDIRECT_VECTORS | ||
243 | .macro hyp_ventry | ||
244 | .align 7 | ||
245 | 1: .rept 27 | ||
246 | nop | ||
247 | .endr | ||
248 | /* | ||
249 | * The default sequence is to directly branch to the KVM vectors, | ||
250 | * using the computed offset. This applies for VHE as well as | ||
251 | * !ARM64_HARDEN_EL2_VECTORS. | ||
252 | * | ||
253 | * For ARM64_HARDEN_EL2_VECTORS configurations, this gets replaced | ||
254 | * with: | ||
255 | * | ||
256 | * stp x0, x1, [sp, #-16]! | ||
257 | * movz x0, #(addr & 0xffff) | ||
258 | * movk x0, #((addr >> 16) & 0xffff), lsl #16 | ||
259 | * movk x0, #((addr >> 32) & 0xffff), lsl #32 | ||
260 | * br x0 | ||
261 | * | ||
262 | * Where addr = kern_hyp_va(__kvm_hyp_vector) + vector-offset + 4. | ||
263 | * See kvm_patch_vector_branch for details. | ||
264 | */ | ||
265 | alternative_cb kvm_patch_vector_branch | ||
266 | b __kvm_hyp_vector + (1b - 0b) | ||
267 | nop | ||
268 | nop | ||
269 | nop | ||
270 | nop | ||
271 | alternative_cb_end | ||
272 | .endm | ||
273 | |||
274 | .macro generate_vectors | ||
275 | 0: | ||
276 | .rept 16 | ||
277 | hyp_ventry | ||
278 | .endr | ||
279 | .org 0b + SZ_2K // Safety measure | ||
280 | .endm | ||
281 | |||
282 | .align 11 | ||
283 | ENTRY(__bp_harden_hyp_vecs_start) | ||
284 | .rept BP_HARDEN_EL2_SLOTS | ||
285 | generate_vectors | ||
286 | .endr | ||
287 | ENTRY(__bp_harden_hyp_vecs_end) | ||
288 | |||
289 | .popsection | ||
290 | |||
291 | ENTRY(__smccc_workaround_1_smc_start) | ||
292 | sub sp, sp, #(8 * 4) | ||
293 | stp x2, x3, [sp, #(8 * 0)] | ||
294 | stp x0, x1, [sp, #(8 * 2)] | ||
295 | mov w0, #ARM_SMCCC_ARCH_WORKAROUND_1 | ||
296 | smc #0 | ||
297 | ldp x2, x3, [sp, #(8 * 0)] | ||
298 | ldp x0, x1, [sp, #(8 * 2)] | ||
299 | add sp, sp, #(8 * 4) | ||
300 | ENTRY(__smccc_workaround_1_smc_end) | ||
301 | #endif | ||
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index 07b572173265..d9645236e474 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c | |||
@@ -472,16 +472,6 @@ int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu) | |||
472 | /* And we're baaack! */ | 472 | /* And we're baaack! */ |
473 | } while (fixup_guest_exit(vcpu, &exit_code)); | 473 | } while (fixup_guest_exit(vcpu, &exit_code)); |
474 | 474 | ||
475 | if (cpus_have_const_cap(ARM64_HARDEN_BP_POST_GUEST_EXIT)) { | ||
476 | u32 midr = read_cpuid_id(); | ||
477 | |||
478 | /* Apply BTAC predictors mitigation to all Falkor chips */ | ||
479 | if (((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR) || | ||
480 | ((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR_V1)) { | ||
481 | __qcom_hyp_sanitize_btac_predictors(); | ||
482 | } | ||
483 | } | ||
484 | |||
485 | fp_enabled = __fpsimd_enabled_nvhe(); | 475 | fp_enabled = __fpsimd_enabled_nvhe(); |
486 | 476 | ||
487 | __sysreg_save_state_nvhe(guest_ctxt); | 477 | __sysreg_save_state_nvhe(guest_ctxt); |