Skip to content

Commit ea9d7c8

Browse files
ptosioupton
authored andcommitted
KVM: arm64: Fix __pkvm_init_switch_pgd call ABI
Fix the mismatch between the (incorrect) C signature, C call site, and asm implementation by aligning all three on an API passing the parameters (pgd and SP) separately, instead of as a bundled struct. Remove the now unnecessary memory accesses while the MMU is off from the asm, which simplifies the C caller (as it does not need to convert a VA struct pointer to PA) and makes the code slightly more robust by offsetting the struct fields from C and properly expressing the call to the C compiler (e.g. type checker and kCFI). Fixes: f320bc7 ("KVM: arm64: Prepare the creation of s1 mappings at EL2") Signed-off-by: Pierre-Clément Tosi <[email protected]> Acked-by: Will Deacon <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Oliver Upton <[email protected]>
1 parent a8f0655 commit ea9d7c8

File tree

3 files changed

+17
-15
lines changed

3 files changed

+17
-15
lines changed

arch/arm64/include/asm/kvm_hyp.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ void __noreturn __hyp_do_panic(struct kvm_cpu_context *host_ctxt, u64 spsr,
124124
#endif
125125

126126
#ifdef __KVM_NVHE_HYPERVISOR__
127-
void __pkvm_init_switch_pgd(phys_addr_t phys, unsigned long size,
128-
phys_addr_t pgd, void *sp, void *cont_fn);
127+
void __pkvm_init_switch_pgd(phys_addr_t pgd, unsigned long sp,
128+
void (*fn)(void));
129129
int __pkvm_init(phys_addr_t phys, unsigned long size, unsigned long nr_cpus,
130130
unsigned long *per_cpu_base, u32 hyp_va_bits);
131131
void __noreturn __host_enter(struct kvm_cpu_context *host_ctxt);

arch/arm64/kvm/hyp/nvhe/hyp-init.S

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -265,33 +265,35 @@ alternative_else_nop_endif
265265

266266
SYM_CODE_END(__kvm_handle_stub_hvc)
267267

268+
/*
269+
* void __pkvm_init_switch_pgd(phys_addr_t pgd, unsigned long sp,
270+
* void (*fn)(void));
271+
*/
268272
SYM_FUNC_START(__pkvm_init_switch_pgd)
269273
/* Turn the MMU off */
270274
pre_disable_mmu_workaround
271-
mrs x2, sctlr_el2
272-
bic x3, x2, #SCTLR_ELx_M
273-
msr sctlr_el2, x3
275+
mrs x3, sctlr_el2
276+
bic x4, x3, #SCTLR_ELx_M
277+
msr sctlr_el2, x4
274278
isb
275279

276280
tlbi alle2
277281

278282
/* Install the new pgtables */
279-
ldr x3, [x0, #NVHE_INIT_PGD_PA]
280-
phys_to_ttbr x4, x3
283+
phys_to_ttbr x5, x0
281284
alternative_if ARM64_HAS_CNP
282-
orr x4, x4, #TTBR_CNP_BIT
285+
orr x5, x5, #TTBR_CNP_BIT
283286
alternative_else_nop_endif
284-
msr ttbr0_el2, x4
287+
msr ttbr0_el2, x5
285288

286289
/* Set the new stack pointer */
287-
ldr x0, [x0, #NVHE_INIT_STACK_HYP_VA]
288-
mov sp, x0
290+
mov sp, x1
289291

290292
/* And turn the MMU back on! */
291293
dsb nsh
292294
isb
293-
set_sctlr_el2 x2
294-
ret x1
295+
set_sctlr_el2 x3
296+
ret x2
295297
SYM_FUNC_END(__pkvm_init_switch_pgd)
296298

297299
.popsection

arch/arm64/kvm/hyp/nvhe/setup.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ int __pkvm_init(phys_addr_t phys, unsigned long size, unsigned long nr_cpus,
339339
{
340340
struct kvm_nvhe_init_params *params;
341341
void *virt = hyp_phys_to_virt(phys);
342-
void (*fn)(phys_addr_t params_pa, void *finalize_fn_va);
342+
typeof(__pkvm_init_switch_pgd) *fn;
343343
int ret;
344344

345345
BUG_ON(kvm_check_pvm_sysreg_table());
@@ -363,7 +363,7 @@ int __pkvm_init(phys_addr_t phys, unsigned long size, unsigned long nr_cpus,
363363
/* Jump in the idmap page to switch to the new page-tables */
364364
params = this_cpu_ptr(&kvm_init_params);
365365
fn = (typeof(fn))__hyp_pa(__pkvm_init_switch_pgd);
366-
fn(__hyp_pa(params), __pkvm_init_finalise);
366+
fn(params->pgd_pa, params->stack_hyp_va, __pkvm_init_finalise);
367367

368368
unreachable();
369369
}

0 commit comments

Comments
 (0)