Skip to content

Commit 5e21d0c

Browse files
committed
Merge tag 'kvmarm-fixes-6.14-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD
KVM/arm64 fixes for 6.14, take #1 - Correctly clean the BSS to the PoC before allowing EL2 to access it on nVHE/hVHE/protected configurations - Propagate ownership of debug registers in protected mode after the rework that landed in 6.14-rc1 - Stop pretending that we can run the protected mode without a GICv3 being present on the host - Fix a use-after-free situation that can occur if a vcpu fails to initialise the NV shadow S2 MMU contexts - Always evaluate the need to arm a background timer for fully emulated guest timers - Fix the emulation of EL1 timers in the absence of FEAT_ECV - Correctly handle the EL2 virtual timer, specially when HCR_EL2.E2H==0
2 parents 35441cd + 0e45981 commit 5e21d0c

File tree

5 files changed

+73
-45
lines changed

5 files changed

+73
-45
lines changed

arch/arm64/kvm/arch_timer.c

Lines changed: 11 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -471,10 +471,8 @@ static void timer_emulate(struct arch_timer_context *ctx)
471471

472472
trace_kvm_timer_emulate(ctx, should_fire);
473473

474-
if (should_fire != ctx->irq.level) {
474+
if (should_fire != ctx->irq.level)
475475
kvm_timer_update_irq(ctx->vcpu, should_fire, ctx);
476-
return;
477-
}
478476

479477
kvm_timer_update_status(ctx, should_fire);
480478

@@ -761,21 +759,6 @@ static void kvm_timer_vcpu_load_nested_switch(struct kvm_vcpu *vcpu,
761759
timer_irq(map->direct_ptimer),
762760
&arch_timer_irq_ops);
763761
WARN_ON_ONCE(ret);
764-
765-
/*
766-
* The virtual offset behaviour is "interesting", as it
767-
* always applies when HCR_EL2.E2H==0, but only when
768-
* accessed from EL1 when HCR_EL2.E2H==1. So make sure we
769-
* track E2H when putting the HV timer in "direct" mode.
770-
*/
771-
if (map->direct_vtimer == vcpu_hvtimer(vcpu)) {
772-
struct arch_timer_offset *offs = &map->direct_vtimer->offset;
773-
774-
if (vcpu_el2_e2h_is_set(vcpu))
775-
offs->vcpu_offset = NULL;
776-
else
777-
offs->vcpu_offset = &__vcpu_sys_reg(vcpu, CNTVOFF_EL2);
778-
}
779762
}
780763
}
781764

@@ -976,31 +959,21 @@ void kvm_timer_sync_nested(struct kvm_vcpu *vcpu)
976959
* which allows trapping of the timer registers even with NV2.
977960
* Still, this is still worse than FEAT_NV on its own. Meh.
978961
*/
979-
if (!vcpu_el2_e2h_is_set(vcpu)) {
980-
if (cpus_have_final_cap(ARM64_HAS_ECV))
981-
return;
982-
983-
/*
984-
* A non-VHE guest hypervisor doesn't have any direct access
985-
* to its timers: the EL2 registers trap (and the HW is
986-
* fully emulated), while the EL0 registers access memory
987-
* despite the access being notionally direct. Boo.
988-
*
989-
* We update the hardware timer registers with the
990-
* latest value written by the guest to the VNCR page
991-
* and let the hardware take care of the rest.
992-
*/
993-
write_sysreg_el0(__vcpu_sys_reg(vcpu, CNTV_CTL_EL0), SYS_CNTV_CTL);
994-
write_sysreg_el0(__vcpu_sys_reg(vcpu, CNTV_CVAL_EL0), SYS_CNTV_CVAL);
995-
write_sysreg_el0(__vcpu_sys_reg(vcpu, CNTP_CTL_EL0), SYS_CNTP_CTL);
996-
write_sysreg_el0(__vcpu_sys_reg(vcpu, CNTP_CVAL_EL0), SYS_CNTP_CVAL);
997-
} else {
962+
if (!cpus_have_final_cap(ARM64_HAS_ECV)) {
998963
/*
999964
* For a VHE guest hypervisor, the EL2 state is directly
1000-
* stored in the host EL1 timers, while the emulated EL0
965+
* stored in the host EL1 timers, while the emulated EL1
1001966
* state is stored in the VNCR page. The latter could have
1002967
* been updated behind our back, and we must reset the
1003968
* emulation of the timers.
969+
*
970+
* A non-VHE guest hypervisor doesn't have any direct access
971+
* to its timers: the EL2 registers trap despite being
972+
* notionally direct (we use the EL1 HW, as for VHE), while
973+
* the EL1 registers access memory.
974+
*
975+
* In both cases, process the emulated timers on each guest
976+
* exit. Boo.
1004977
*/
1005978
struct timer_map map;
1006979
get_timer_map(vcpu, &map);

arch/arm64/kvm/arm.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2290,6 +2290,19 @@ static int __init init_subsystems(void)
22902290
break;
22912291
case -ENODEV:
22922292
case -ENXIO:
2293+
/*
2294+
* No VGIC? No pKVM for you.
2295+
*
2296+
* Protected mode assumes that VGICv3 is present, so no point
2297+
* in trying to hobble along if vgic initialization fails.
2298+
*/
2299+
if (is_protected_kvm_enabled())
2300+
goto out;
2301+
2302+
/*
2303+
* Otherwise, userspace could choose to implement a GIC for its
2304+
* guest on non-cooperative hardware.
2305+
*/
22932306
vgic_present = false;
22942307
err = 0;
22952308
break;
@@ -2400,6 +2413,13 @@ static void kvm_hyp_init_symbols(void)
24002413
kvm_nvhe_sym(id_aa64smfr0_el1_sys_val) = read_sanitised_ftr_reg(SYS_ID_AA64SMFR0_EL1);
24012414
kvm_nvhe_sym(__icache_flags) = __icache_flags;
24022415
kvm_nvhe_sym(kvm_arm_vmid_bits) = kvm_arm_vmid_bits;
2416+
2417+
/*
2418+
* Flush entire BSS since part of its data containing init symbols is read
2419+
* while the MMU is off.
2420+
*/
2421+
kvm_flush_dcache_to_poc(kvm_ksym_ref(__hyp_bss_start),
2422+
kvm_ksym_ref(__hyp_bss_end) - kvm_ksym_ref(__hyp_bss_start));
24032423
}
24042424

24052425
static int __init kvm_hyp_init_protection(u32 hyp_va_bits)

arch/arm64/kvm/hyp/nvhe/hyp-main.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,34 @@ static void fpsimd_sve_sync(struct kvm_vcpu *vcpu)
9191
*host_data_ptr(fp_owner) = FP_STATE_HOST_OWNED;
9292
}
9393

94+
static void flush_debug_state(struct pkvm_hyp_vcpu *hyp_vcpu)
95+
{
96+
struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
97+
98+
hyp_vcpu->vcpu.arch.debug_owner = host_vcpu->arch.debug_owner;
99+
100+
if (kvm_guest_owns_debug_regs(&hyp_vcpu->vcpu))
101+
hyp_vcpu->vcpu.arch.vcpu_debug_state = host_vcpu->arch.vcpu_debug_state;
102+
else if (kvm_host_owns_debug_regs(&hyp_vcpu->vcpu))
103+
hyp_vcpu->vcpu.arch.external_debug_state = host_vcpu->arch.external_debug_state;
104+
}
105+
106+
static void sync_debug_state(struct pkvm_hyp_vcpu *hyp_vcpu)
107+
{
108+
struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
109+
110+
if (kvm_guest_owns_debug_regs(&hyp_vcpu->vcpu))
111+
host_vcpu->arch.vcpu_debug_state = hyp_vcpu->vcpu.arch.vcpu_debug_state;
112+
else if (kvm_host_owns_debug_regs(&hyp_vcpu->vcpu))
113+
host_vcpu->arch.external_debug_state = hyp_vcpu->vcpu.arch.external_debug_state;
114+
}
115+
94116
static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
95117
{
96118
struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
97119

98120
fpsimd_sve_flush();
121+
flush_debug_state(hyp_vcpu);
99122

100123
hyp_vcpu->vcpu.arch.ctxt = host_vcpu->arch.ctxt;
101124

@@ -123,6 +146,7 @@ static void sync_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
123146
unsigned int i;
124147

125148
fpsimd_sve_sync(&hyp_vcpu->vcpu);
149+
sync_debug_state(hyp_vcpu);
126150

127151
host_vcpu->arch.ctxt = hyp_vcpu->vcpu.arch.ctxt;
128152

arch/arm64/kvm/nested.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,26 +67,27 @@ int kvm_vcpu_init_nested(struct kvm_vcpu *vcpu)
6767
if (!tmp)
6868
return -ENOMEM;
6969

70+
swap(kvm->arch.nested_mmus, tmp);
71+
7072
/*
7173
* If we went through a realocation, adjust the MMU back-pointers in
7274
* the previously initialised kvm_pgtable structures.
7375
*/
7476
if (kvm->arch.nested_mmus != tmp)
7577
for (int i = 0; i < kvm->arch.nested_mmus_size; i++)
76-
tmp[i].pgt->mmu = &tmp[i];
78+
kvm->arch.nested_mmus[i].pgt->mmu = &kvm->arch.nested_mmus[i];
7779

7880
for (int i = kvm->arch.nested_mmus_size; !ret && i < num_mmus; i++)
79-
ret = init_nested_s2_mmu(kvm, &tmp[i]);
81+
ret = init_nested_s2_mmu(kvm, &kvm->arch.nested_mmus[i]);
8082

8183
if (ret) {
8284
for (int i = kvm->arch.nested_mmus_size; i < num_mmus; i++)
83-
kvm_free_stage2_pgd(&tmp[i]);
85+
kvm_free_stage2_pgd(&kvm->arch.nested_mmus[i]);
8486

8587
return ret;
8688
}
8789

8890
kvm->arch.nested_mmus_size = num_mmus;
89-
kvm->arch.nested_mmus = tmp;
9091

9192
return 0;
9293
}

arch/arm64/kvm/sys_regs.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,6 +1452,16 @@ static bool access_arch_timer(struct kvm_vcpu *vcpu,
14521452
return true;
14531453
}
14541454

1455+
static bool access_hv_timer(struct kvm_vcpu *vcpu,
1456+
struct sys_reg_params *p,
1457+
const struct sys_reg_desc *r)
1458+
{
1459+
if (!vcpu_el2_e2h_is_set(vcpu))
1460+
return undef_access(vcpu, p, r);
1461+
1462+
return access_arch_timer(vcpu, p, r);
1463+
}
1464+
14551465
static s64 kvm_arm64_ftr_safe_value(u32 id, const struct arm64_ftr_bits *ftrp,
14561466
s64 new, s64 cur)
14571467
{
@@ -3103,9 +3113,9 @@ static const struct sys_reg_desc sys_reg_descs[] = {
31033113
EL2_REG(CNTHP_CTL_EL2, access_arch_timer, reset_val, 0),
31043114
EL2_REG(CNTHP_CVAL_EL2, access_arch_timer, reset_val, 0),
31053115

3106-
{ SYS_DESC(SYS_CNTHV_TVAL_EL2), access_arch_timer },
3107-
EL2_REG(CNTHV_CTL_EL2, access_arch_timer, reset_val, 0),
3108-
EL2_REG(CNTHV_CVAL_EL2, access_arch_timer, reset_val, 0),
3116+
{ SYS_DESC(SYS_CNTHV_TVAL_EL2), access_hv_timer },
3117+
EL2_REG(CNTHV_CTL_EL2, access_hv_timer, reset_val, 0),
3118+
EL2_REG(CNTHV_CVAL_EL2, access_hv_timer, reset_val, 0),
31093119

31103120
{ SYS_DESC(SYS_CNTKCTL_EL12), access_cntkctl_el12 },
31113121

0 commit comments

Comments
 (0)