Skip to content

Commit dcf89d1

Browse files
misalehoupton
authored andcommitted
KVM: arm64: Add missing BTI instructions
Some bti instructions were missing from commit b53d4a2 ("KVM: arm64: Use BTI for nvhe") 1) kvm_host_psci_cpu_entry kvm_host_psci_cpu_entry is called from __kvm_hyp_init_cpu through "br" instruction as __kvm_hyp_init_cpu resides in idmap section while kvm_host_psci_cpu_entry is in hyp .text so the offset is larger than 128MB range covered by "b". Which means that this function should start with "bti j" instruction. LLVM which is the only compiler supporting BTI for Linux, adds "bti j" for jump tables or by when taking the address of the block [1]. Same behaviour is observed with GCC. As kvm_host_psci_cpu_entry is a C function, this must be done in assembly. Another solution is to use X16/X17 with "br", as according to ARM ARM DDI0487I.a RLJHCL/IGMGRS, PACIASP has an implicit branch target identification instruction that is compatible with PSTATE.BTYPE 0b01 which includes "br X16/X17" And the kvm_host_psci_cpu_entry has PACIASP as it is an external function. Although, using explicit "bti" makes it more clear than relying on which register is used. A third solution is to clear SCTLR_EL2.BT, which would make PACIASP compatible PSTATE.BTYPE 0b11 ("br" to other registers). However this deviates from the kernel behaviour (in bti_enable()). 2) Spectre vector table "br" instructions are generated at runtime for the vector table (__bp_harden_hyp_vecs). These branches would land on vectors in __kvm_hyp_vector at offset 8. As all the macros are defined with valid_vect/invalid_vect, it is sufficient to add "bti j" at the correct offset. [1] https://reviews.llvm.org/D52867 Fixes: b53d4a2 ("KVM: arm64: Use BTI for nvhe") Signed-off-by: Mostafa Saleh <[email protected]> Reported-by: Sudeep Holla <[email protected]> Acked-by: Marc Zyngier <[email protected]> Tested-by: Sudeep Holla <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Oliver Upton <[email protected]>
1 parent df6556a commit dcf89d1

File tree

3 files changed

+19
-1
lines changed

3 files changed

+19
-1
lines changed

arch/arm64/kvm/hyp/hyp-entry.S

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,12 @@ SYM_CODE_END(\label)
154154
esb
155155
stp x0, x1, [sp, #-16]!
156156
662:
157+
/*
158+
* spectre vectors __bp_harden_hyp_vecs generate br instructions at runtime
159+
* that jump at offset 8 at __kvm_hyp_vector.
160+
* As hyp .text is guarded section, it needs bti j.
161+
*/
162+
bti j
157163
b \target
158164

159165
check_preamble_length 661b, 662b
@@ -165,6 +171,8 @@ check_preamble_length 661b, 662b
165171
nop
166172
stp x0, x1, [sp, #-16]!
167173
662:
174+
/* Check valid_vect */
175+
bti j
168176
b \target
169177

170178
check_preamble_length 661b, 662b

arch/arm64/kvm/hyp/nvhe/host.S

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,3 +297,13 @@ SYM_CODE_START(__kvm_hyp_host_forward_smc)
297297

298298
ret
299299
SYM_CODE_END(__kvm_hyp_host_forward_smc)
300+
301+
/*
302+
* kvm_host_psci_cpu_entry is called through br instruction, which requires
303+
* bti j instruction as compilers (gcc and llvm) doesn't insert bti j for external
304+
* functions, but bti c instead.
305+
*/
306+
SYM_CODE_START(kvm_host_psci_cpu_entry)
307+
bti j
308+
b __kvm_host_psci_cpu_entry
309+
SYM_CODE_END(kvm_host_psci_cpu_entry)

arch/arm64/kvm/hyp/nvhe/psci-relay.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ static int psci_system_suspend(u64 func_id, struct kvm_cpu_context *host_ctxt)
200200
__hyp_pa(init_params), 0);
201201
}
202202

203-
asmlinkage void __noreturn kvm_host_psci_cpu_entry(bool is_cpu_on)
203+
asmlinkage void __noreturn __kvm_host_psci_cpu_entry(bool is_cpu_on)
204204
{
205205
struct psci_boot_args *boot_args;
206206
struct kvm_cpu_context *host_ctxt;

0 commit comments

Comments
 (0)