Skip to content

Commit 1c9604b

Browse files
ouptonMarc Zyngier
authored andcommitted
KVM: arm64: selftests: Alias EL1 registers to EL2 counterparts
FEAT_VHE has the somewhat nice property of implicitly redirecting EL1 register aliases to their corresponding EL2 representations when E2H=1. Unfortunately, there's no such abstraction for userspace and EL2 registers are always accessed by their canonical encoding. Introduce a helper that applies EL2 redirections to sysregs and use aggressive inlining to catch misuse at compile time. Go a little past the architectural definition for ease of use for test authors (e.g. the stack pointer). Signed-off-by: Oliver Upton <oliver.upton@linux.dev> Signed-off-by: Marc Zyngier <maz@kernel.org>
1 parent 8911c7d commit 1c9604b

4 files changed

Lines changed: 69 additions & 11 deletions

File tree

tools/testing/selftests/kvm/arm64/vpmu_counter_access.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ static void run_access_test(uint64_t pmcr_n)
517517
vcpu = vpmu_vm.vcpu;
518518

519519
/* Save the initial sp to restore them later to run the guest again */
520-
sp = vcpu_get_reg(vcpu, ARM64_CORE_REG(sp_el1));
520+
sp = vcpu_get_reg(vcpu, ctxt_reg_alias(vcpu, SYS_SP_EL1));
521521

522522
run_vcpu(vcpu, pmcr_n);
523523

@@ -529,7 +529,7 @@ static void run_access_test(uint64_t pmcr_n)
529529
init.features[0] |= (1 << KVM_ARM_VCPU_PMU_V3);
530530
aarch64_vcpu_setup(vcpu, &init);
531531
vcpu_init_descriptor_tables(vcpu);
532-
vcpu_set_reg(vcpu, ARM64_CORE_REG(sp_el1), sp);
532+
vcpu_set_reg(vcpu, ctxt_reg_alias(vcpu, SYS_SP_EL1), sp);
533533
vcpu_set_reg(vcpu, ARM64_CORE_REG(regs.pc), (uint64_t)guest_code);
534534

535535
run_vcpu(vcpu, pmcr_n);

tools/testing/selftests/kvm/include/arm64/processor.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,4 +303,58 @@ void wfi(void);
303303
void test_wants_mte(void);
304304
void test_disable_default_vgic(void);
305305

306+
static bool vcpu_has_el2(struct kvm_vcpu *vcpu)
307+
{
308+
return vcpu->init.features[0] & BIT(KVM_ARM_VCPU_HAS_EL2);
309+
}
310+
311+
#define MAPPED_EL2_SYSREG(el2, el1) \
312+
case SYS_##el1: \
313+
if (vcpu_has_el2(vcpu)) \
314+
alias = SYS_##el2; \
315+
break
316+
317+
318+
static __always_inline u64 ctxt_reg_alias(struct kvm_vcpu *vcpu, u32 encoding)
319+
{
320+
u32 alias = encoding;
321+
322+
BUILD_BUG_ON(!__builtin_constant_p(encoding));
323+
324+
switch (encoding) {
325+
MAPPED_EL2_SYSREG(SCTLR_EL2, SCTLR_EL1);
326+
MAPPED_EL2_SYSREG(CPTR_EL2, CPACR_EL1);
327+
MAPPED_EL2_SYSREG(TTBR0_EL2, TTBR0_EL1);
328+
MAPPED_EL2_SYSREG(TTBR1_EL2, TTBR1_EL1);
329+
MAPPED_EL2_SYSREG(TCR_EL2, TCR_EL1);
330+
MAPPED_EL2_SYSREG(VBAR_EL2, VBAR_EL1);
331+
MAPPED_EL2_SYSREG(AFSR0_EL2, AFSR0_EL1);
332+
MAPPED_EL2_SYSREG(AFSR1_EL2, AFSR1_EL1);
333+
MAPPED_EL2_SYSREG(ESR_EL2, ESR_EL1);
334+
MAPPED_EL2_SYSREG(FAR_EL2, FAR_EL1);
335+
MAPPED_EL2_SYSREG(MAIR_EL2, MAIR_EL1);
336+
MAPPED_EL2_SYSREG(TCR2_EL2, TCR2_EL1);
337+
MAPPED_EL2_SYSREG(PIR_EL2, PIR_EL1);
338+
MAPPED_EL2_SYSREG(PIRE0_EL2, PIRE0_EL1);
339+
MAPPED_EL2_SYSREG(POR_EL2, POR_EL1);
340+
MAPPED_EL2_SYSREG(AMAIR_EL2, AMAIR_EL1);
341+
MAPPED_EL2_SYSREG(ELR_EL2, ELR_EL1);
342+
MAPPED_EL2_SYSREG(SPSR_EL2, SPSR_EL1);
343+
MAPPED_EL2_SYSREG(ZCR_EL2, ZCR_EL1);
344+
MAPPED_EL2_SYSREG(CONTEXTIDR_EL2, CONTEXTIDR_EL1);
345+
MAPPED_EL2_SYSREG(SCTLR2_EL2, SCTLR2_EL1);
346+
MAPPED_EL2_SYSREG(CNTHCTL_EL2, CNTKCTL_EL1);
347+
case SYS_SP_EL1:
348+
if (!vcpu_has_el2(vcpu))
349+
return ARM64_CORE_REG(sp_el1);
350+
351+
alias = SYS_SP_EL2;
352+
break;
353+
default:
354+
BUILD_BUG();
355+
}
356+
357+
return KVM_ARM64_SYS_REG(alias);
358+
}
359+
306360
#endif /* SELFTEST_KVM_PROCESSOR_H */

tools/testing/selftests/kvm/include/kvm_util.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ struct kvm_vcpu {
6363
struct kvm_run *run;
6464
#ifdef __x86_64__
6565
struct kvm_cpuid2 *cpuid;
66+
#endif
67+
#ifdef __aarch64__
68+
struct kvm_vcpu_init init;
6669
#endif
6770
struct kvm_binary_stats stats;
6871
struct kvm_dirty_gfn *dirty_gfns;

tools/testing/selftests/kvm/lib/arm64/processor.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -283,15 +283,16 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
283283
}
284284

285285
vcpu_ioctl(vcpu, KVM_ARM_VCPU_INIT, init);
286+
vcpu->init = *init;
286287

287288
/*
288289
* Enable FP/ASIMD to avoid trapping when accessing Q0-Q15
289290
* registers, which the variable argument list macros do.
290291
*/
291-
vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_CPACR_EL1), 3 << 20);
292+
vcpu_set_reg(vcpu, ctxt_reg_alias(vcpu, SYS_CPACR_EL1), 3 << 20);
292293

293-
sctlr_el1 = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_SCTLR_EL1));
294-
tcr_el1 = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_TCR_EL1));
294+
sctlr_el1 = vcpu_get_reg(vcpu, ctxt_reg_alias(vcpu, SYS_SCTLR_EL1));
295+
tcr_el1 = vcpu_get_reg(vcpu, ctxt_reg_alias(vcpu, SYS_TCR_EL1));
295296

296297
/* Configure base granule size */
297298
switch (vm->mode) {
@@ -358,10 +359,10 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
358359
if (use_lpa2_pte_format(vm))
359360
tcr_el1 |= TCR_DS;
360361

361-
vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_SCTLR_EL1), sctlr_el1);
362-
vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_TCR_EL1), tcr_el1);
363-
vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_MAIR_EL1), DEFAULT_MAIR_EL1);
364-
vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_TTBR0_EL1), ttbr0_el1);
362+
vcpu_set_reg(vcpu, ctxt_reg_alias(vcpu, SYS_SCTLR_EL1), sctlr_el1);
363+
vcpu_set_reg(vcpu, ctxt_reg_alias(vcpu, SYS_TCR_EL1), tcr_el1);
364+
vcpu_set_reg(vcpu, ctxt_reg_alias(vcpu, SYS_MAIR_EL1), DEFAULT_MAIR_EL1);
365+
vcpu_set_reg(vcpu, ctxt_reg_alias(vcpu, SYS_TTBR0_EL1), ttbr0_el1);
365366
vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_TPIDR_EL1), vcpu->id);
366367
}
367368

@@ -396,7 +397,7 @@ static struct kvm_vcpu *__aarch64_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id,
396397

397398
aarch64_vcpu_setup(vcpu, init);
398399

399-
vcpu_set_reg(vcpu, ARM64_CORE_REG(sp_el1), stack_vaddr + stack_size);
400+
vcpu_set_reg(vcpu, ctxt_reg_alias(vcpu, SYS_SP_EL1), stack_vaddr + stack_size);
400401
return vcpu;
401402
}
402403

@@ -466,7 +467,7 @@ void vcpu_init_descriptor_tables(struct kvm_vcpu *vcpu)
466467
{
467468
extern char vectors;
468469

469-
vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_VBAR_EL1), (uint64_t)&vectors);
470+
vcpu_set_reg(vcpu, ctxt_reg_alias(vcpu, SYS_VBAR_EL1), (uint64_t)&vectors);
470471
}
471472

472473
void route_exception(struct ex_regs *regs, int vector)

0 commit comments

Comments
 (0)