Message ID | 20240122201852.262057-23-maz@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM/arm64: VM configuration enforcement | expand |
Hello, On Mon, Jan 22, 2024 at 08:18:49PM +0000, Marc Zyngier wrote: > As part of the ongoing effort to honor the guest configuration, > add the necessary checks to make PIR_EL1 and co UNDEF if not > advertised to the guest, and avoid context switching them. > > Signed-off-by: Marc Zyngier <maz@kernel.org> > --- > arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h | 15 ++++++++++++++- > arch/arm64/kvm/sys_regs.c | 4 ++++ > 2 files changed, 18 insertions(+), 1 deletion(-) > > diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h > index bb6b571ec627..b34743292ca7 100644 > --- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h > +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h > @@ -37,6 +37,19 @@ static inline bool ctxt_has_mte(struct kvm_cpu_context *ctxt) > return kvm_has_mte(kern_hyp_va(vcpu->kvm)); > } > > +static inline bool ctxt_has_s1pie(struct kvm_cpu_context *ctxt) > +{ > + struct kvm_vcpu *vcpu = ctxt->__hyp_running_vcpu; > + > + if (!cpus_have_final_cap(ARM64_HAS_S1PIE)) > + return false; > + > + if (!vcpu) > + vcpu = container_of(ctxt, struct kvm_vcpu, arch.ctxt); > + > + return kvm_has_feat(kern_hyp_va(vcpu->kvm), ID_AA64MMFR3_EL1, S1PIE, IMP); > +} > + > static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) > { > ctxt_sys_reg(ctxt, SCTLR_EL1) = read_sysreg_el1(SYS_SCTLR); > @@ -55,7 +68,7 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) > ctxt_sys_reg(ctxt, CONTEXTIDR_EL1) = read_sysreg_el1(SYS_CONTEXTIDR); > ctxt_sys_reg(ctxt, AMAIR_EL1) = read_sysreg_el1(SYS_AMAIR); > ctxt_sys_reg(ctxt, CNTKCTL_EL1) = read_sysreg_el1(SYS_CNTKCTL); > - if (cpus_have_final_cap(ARM64_HAS_S1PIE)) { > + if (ctxt_has_s1pie(ctxt)) { > ctxt_sys_reg(ctxt, PIR_EL1) = read_sysreg_el1(SYS_PIR); > ctxt_sys_reg(ctxt, PIRE0_EL1) = read_sysreg_el1(SYS_PIRE0); > } Missing the corresponding change in __sysreg_restore_el1_state(). > diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c > index 3c939ea4a28f..bcde43b81755 100644 > --- a/arch/arm64/kvm/sys_regs.c > +++ b/arch/arm64/kvm/sys_regs.c > @@ -3990,6 +3990,10 @@ void kvm_init_sysreg(struct kvm_vcpu *vcpu) > HFGITR_EL2_TLBIRVAAE1OS | > HFGITR_EL2_TLBIRVAE1OS); > > + if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, S1PIE, IMP)) > + kvm->arch.fgu[HFGxTR_GROUP] |= (HFGxTR_EL2_nPIRE0_EL1 | > + HFGxTR_EL2_nPIR_EL1); > + > set_bit(KVM_ARCH_FLAG_FGU_INITIALIZED, &kvm->arch.flags); > out: > mutex_unlock(&kvm->arch.config_lock); Thanks, Joey
On Tue, 23 Jan 2024 11:48:10 +0000, Joey Gouly <joey.gouly@arm.com> wrote: > > Hello, > > On Mon, Jan 22, 2024 at 08:18:49PM +0000, Marc Zyngier wrote: > > As part of the ongoing effort to honor the guest configuration, > > add the necessary checks to make PIR_EL1 and co UNDEF if not > > advertised to the guest, and avoid context switching them. > > > > Signed-off-by: Marc Zyngier <maz@kernel.org> > > --- > > arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h | 15 ++++++++++++++- > > arch/arm64/kvm/sys_regs.c | 4 ++++ > > 2 files changed, 18 insertions(+), 1 deletion(-) > > > > diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h > > index bb6b571ec627..b34743292ca7 100644 > > --- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h > > +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h > > @@ -37,6 +37,19 @@ static inline bool ctxt_has_mte(struct kvm_cpu_context *ctxt) > > return kvm_has_mte(kern_hyp_va(vcpu->kvm)); > > } > > > > +static inline bool ctxt_has_s1pie(struct kvm_cpu_context *ctxt) > > +{ > > + struct kvm_vcpu *vcpu = ctxt->__hyp_running_vcpu; > > + > > + if (!cpus_have_final_cap(ARM64_HAS_S1PIE)) > > + return false; > > + > > + if (!vcpu) > > + vcpu = container_of(ctxt, struct kvm_vcpu, arch.ctxt); > > + > > + return kvm_has_feat(kern_hyp_va(vcpu->kvm), ID_AA64MMFR3_EL1, S1PIE, IMP); > > +} > > + > > static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) > > { > > ctxt_sys_reg(ctxt, SCTLR_EL1) = read_sysreg_el1(SYS_SCTLR); > > @@ -55,7 +68,7 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) > > ctxt_sys_reg(ctxt, CONTEXTIDR_EL1) = read_sysreg_el1(SYS_CONTEXTIDR); > > ctxt_sys_reg(ctxt, AMAIR_EL1) = read_sysreg_el1(SYS_AMAIR); > > ctxt_sys_reg(ctxt, CNTKCTL_EL1) = read_sysreg_el1(SYS_CNTKCTL); > > - if (cpus_have_final_cap(ARM64_HAS_S1PIE)) { > > + if (ctxt_has_s1pie(ctxt)) { > > ctxt_sys_reg(ctxt, PIR_EL1) = read_sysreg_el1(SYS_PIR); > > ctxt_sys_reg(ctxt, PIRE0_EL1) = read_sysreg_el1(SYS_PIRE0); > > } > > Missing the corresponding change in __sysreg_restore_el1_state(). Gah. Thanks for spotting it. I'm pretty sure I had it at some point, and somehow lost it. Probably on another machine somewhere... Cheers, M.
diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h index bb6b571ec627..b34743292ca7 100644 --- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h @@ -37,6 +37,19 @@ static inline bool ctxt_has_mte(struct kvm_cpu_context *ctxt) return kvm_has_mte(kern_hyp_va(vcpu->kvm)); } +static inline bool ctxt_has_s1pie(struct kvm_cpu_context *ctxt) +{ + struct kvm_vcpu *vcpu = ctxt->__hyp_running_vcpu; + + if (!cpus_have_final_cap(ARM64_HAS_S1PIE)) + return false; + + if (!vcpu) + vcpu = container_of(ctxt, struct kvm_vcpu, arch.ctxt); + + return kvm_has_feat(kern_hyp_va(vcpu->kvm), ID_AA64MMFR3_EL1, S1PIE, IMP); +} + static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) { ctxt_sys_reg(ctxt, SCTLR_EL1) = read_sysreg_el1(SYS_SCTLR); @@ -55,7 +68,7 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) ctxt_sys_reg(ctxt, CONTEXTIDR_EL1) = read_sysreg_el1(SYS_CONTEXTIDR); ctxt_sys_reg(ctxt, AMAIR_EL1) = read_sysreg_el1(SYS_AMAIR); ctxt_sys_reg(ctxt, CNTKCTL_EL1) = read_sysreg_el1(SYS_CNTKCTL); - if (cpus_have_final_cap(ARM64_HAS_S1PIE)) { + if (ctxt_has_s1pie(ctxt)) { ctxt_sys_reg(ctxt, PIR_EL1) = read_sysreg_el1(SYS_PIR); ctxt_sys_reg(ctxt, PIRE0_EL1) = read_sysreg_el1(SYS_PIRE0); } diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 3c939ea4a28f..bcde43b81755 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -3990,6 +3990,10 @@ void kvm_init_sysreg(struct kvm_vcpu *vcpu) HFGITR_EL2_TLBIRVAAE1OS | HFGITR_EL2_TLBIRVAE1OS); + if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, S1PIE, IMP)) + kvm->arch.fgu[HFGxTR_GROUP] |= (HFGxTR_EL2_nPIRE0_EL1 | + HFGxTR_EL2_nPIR_EL1); + set_bit(KVM_ARCH_FLAG_FGU_INITIALIZED, &kvm->arch.flags); out: mutex_unlock(&kvm->arch.config_lock);
As part of the ongoing effort to honor the guest configuration, add the necessary checks to make PIR_EL1 and co UNDEF if not advertised to the guest, and avoid context switching them. Signed-off-by: Marc Zyngier <maz@kernel.org> --- arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h | 15 ++++++++++++++- arch/arm64/kvm/sys_regs.c | 4 ++++ 2 files changed, 18 insertions(+), 1 deletion(-)