Skip to content

Commit d0d81e0

Browse files
committed
KVM: arm64: Load VPIDR_EL2 with the VM's MIDR_EL1 value
Userspace will soon be able to change the value of MIDR_EL1. Prepare by loading VPIDR_EL2 with the guest value for non-nested VMs. Since VPIDR_EL2 is set for any VM, get rid of the NV-specific cleanup of reloading the hardware value on vcpu_put(). And for nVHE, load the hardware value before switching to the host. Link: https://lore.kernel.org/r/20250225005401.679536-4-oliver.upton@linux.dev Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
1 parent b4043e7 commit d0d81e0

File tree

3 files changed

+20
-20
lines changed

3 files changed

+20
-20
lines changed

arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ static inline u64 *ctxt_mdscr_el1(struct kvm_cpu_context *ctxt)
4343
return &ctxt_sys_reg(ctxt, MDSCR_EL1);
4444
}
4545

46+
static inline u64 ctxt_midr_el1(struct kvm_cpu_context *ctxt)
47+
{
48+
return read_cpuid_id();
49+
}
50+
4651
static inline void __sysreg_save_common_state(struct kvm_cpu_context *ctxt)
4752
{
4853
*ctxt_mdscr_el1(ctxt) = read_sysreg(mdscr_el1);
@@ -168,8 +173,9 @@ static inline void __sysreg_restore_user_state(struct kvm_cpu_context *ctxt)
168173
}
169174

170175
static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt,
171-
u64 mpidr)
176+
u64 midr, u64 mpidr)
172177
{
178+
write_sysreg(midr, vpidr_el2);
173179
write_sysreg(mpidr, vmpidr_el2);
174180

175181
if (has_vhe() ||

arch/arm64/kvm/hyp/nvhe/sysreg-sr.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ void __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt)
2828

2929
void __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt)
3030
{
31-
__sysreg_restore_el1_state(ctxt, ctxt_sys_reg(ctxt, MPIDR_EL1));
31+
u64 midr = ctxt_midr_el1(ctxt);
32+
33+
__sysreg_restore_el1_state(ctxt, midr, ctxt_sys_reg(ctxt, MPIDR_EL1));
3234
__sysreg_restore_common_state(ctxt);
3335
__sysreg_restore_user_state(ctxt);
3436
__sysreg_restore_el2_return_state(ctxt);

arch/arm64/kvm/hyp/vhe/sysreg-sr.c

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,12 @@ static void __sysreg_restore_vel2_state(struct kvm_vcpu *vcpu)
8787
write_sysreg(__vcpu_sys_reg(vcpu, PAR_EL1), par_el1);
8888
write_sysreg(__vcpu_sys_reg(vcpu, TPIDR_EL1), tpidr_el1);
8989

90-
write_sysreg(__vcpu_sys_reg(vcpu, MPIDR_EL1), vmpidr_el2);
91-
write_sysreg_el1(__vcpu_sys_reg(vcpu, MAIR_EL2), SYS_MAIR);
92-
write_sysreg_el1(__vcpu_sys_reg(vcpu, VBAR_EL2), SYS_VBAR);
93-
write_sysreg_el1(__vcpu_sys_reg(vcpu, CONTEXTIDR_EL2), SYS_CONTEXTIDR);
94-
write_sysreg_el1(__vcpu_sys_reg(vcpu, AMAIR_EL2), SYS_AMAIR);
90+
write_sysreg(ctxt_midr_el1(&vcpu->arch.ctxt), vpidr_el2);
91+
write_sysreg(__vcpu_sys_reg(vcpu, MPIDR_EL1), vmpidr_el2);
92+
write_sysreg_el1(__vcpu_sys_reg(vcpu, MAIR_EL2), SYS_MAIR);
93+
write_sysreg_el1(__vcpu_sys_reg(vcpu, VBAR_EL2), SYS_VBAR);
94+
write_sysreg_el1(__vcpu_sys_reg(vcpu, CONTEXTIDR_EL2), SYS_CONTEXTIDR);
95+
write_sysreg_el1(__vcpu_sys_reg(vcpu, AMAIR_EL2), SYS_AMAIR);
9596

9697
if (vcpu_el2_e2h_is_set(vcpu)) {
9798
/*
@@ -191,7 +192,7 @@ void __vcpu_load_switch_sysregs(struct kvm_vcpu *vcpu)
191192
{
192193
struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt;
193194
struct kvm_cpu_context *host_ctxt;
194-
u64 mpidr;
195+
u64 midr, mpidr;
195196

196197
host_ctxt = host_data_ptr(host_ctxt);
197198
__sysreg_save_user_state(host_ctxt);
@@ -220,23 +221,18 @@ void __vcpu_load_switch_sysregs(struct kvm_vcpu *vcpu)
220221
__sysreg_restore_vel2_state(vcpu);
221222
} else {
222223
if (vcpu_has_nv(vcpu)) {
223-
/*
224-
* Use the guest hypervisor's VPIDR_EL2 when in a
225-
* nested state. The hardware value of MIDR_EL1 gets
226-
* restored on put.
227-
*/
228-
write_sysreg(ctxt_sys_reg(guest_ctxt, VPIDR_EL2), vpidr_el2);
229-
230224
/*
231225
* As we're restoring a nested guest, set the value
232226
* provided by the guest hypervisor.
233227
*/
228+
midr = ctxt_sys_reg(guest_ctxt, VPIDR_EL2);
234229
mpidr = ctxt_sys_reg(guest_ctxt, VMPIDR_EL2);
235230
} else {
231+
midr = ctxt_midr_el1(guest_ctxt);
236232
mpidr = ctxt_sys_reg(guest_ctxt, MPIDR_EL1);
237233
}
238234

239-
__sysreg_restore_el1_state(guest_ctxt, mpidr);
235+
__sysreg_restore_el1_state(guest_ctxt, midr, mpidr);
240236
}
241237

242238
vcpu_set_flag(vcpu, SYSREGS_ON_CPU);
@@ -271,9 +267,5 @@ void __vcpu_put_switch_sysregs(struct kvm_vcpu *vcpu)
271267
/* Restore host user state */
272268
__sysreg_restore_user_state(host_ctxt);
273269

274-
/* If leaving a nesting guest, restore MIDR_EL1 default view */
275-
if (vcpu_has_nv(vcpu))
276-
write_sysreg(read_cpuid_id(), vpidr_el2);
277-
278270
vcpu_clear_flag(vcpu, SYSREGS_ON_CPU);
279271
}

0 commit comments

Comments
 (0)