Re: [PATCH v19 06/14] KVM: arm64: Validate GCS exception lock when emulating ERET
Wei-Lin Chang <[email protected]>
| Newsgroups | org.kernel.vger.linux-kselftest,dev.linux.lists.kvmarm,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <vdmz43ogvmwu4liilfqzdrgsf5v765bucl7mybhfdxj7yrywkd@5mssukdegdwg> |
On Wed, Aug 12, 2026 at 08:12:05PM +0100, Mark Brown wrote: > As per DDI0487 R_TYTWB GCS adds an additional case where an illegal > exception return can be generated. If all of: > > - PSTATE.EXLOCK is 0. > - The EL is not being changed by the ERET. > - GCSCR_ELx.EXLOCKEN is 1. > > are true then the return is illegal. Emulate this behaviour when > emulating ERET for nested guests, while we're at it using the symbolic > definition for EXLOCK in SPSR. > > Signed-off-by: Mark Brown <[email protected]> > --- > arch/arm64/include/asm/kvm_nested.h | 39 +++++++++++++++++++++++++++++++++++++ > arch/arm64/kvm/emulate-nested.c | 5 ++++- > arch/arm64/kvm/hyp/vhe/switch.c | 4 ++++ > 3 files changed, 47 insertions(+), 1 deletion(-) > > diff --git a/arch/arm64/include/asm/kvm_nested.h b/arch/arm64/include/asm/kvm_nested.h > index 012d711034d1..f25ddee89206 100644 > --- a/arch/arm64/include/asm/kvm_nested.h > +++ b/arch/arm64/include/asm/kvm_nested.h > @@ -240,6 +240,45 @@ static inline bool kvm_auth_eretax(struct kvm_vcpu *vcpu, u64 *elr) > } > #endif > > +#ifdef CONFIG_ARM64_GCS > +/* > + * A subset of the pseudocode ELFromSPSR(), validity checks are > + * assumed to have been done in code that is not GCS specific. > + */ > +static inline int exlock_el_from_spsr(u64 spsr) > +{ > + return FIELD_GET(GENMASK(3, 2), spsr); > +} It feels a bit odd to me to have this function named exlock specific, as it's just spsr_to_el, right? Thanks, Wei-Lin Chang > + > +/* See IllegalExceptionReturn() pseudocode */ > +static inline bool kvm_check_illegal_exlock_return(struct kvm_vcpu *vcpu, > + u64 spsr) > +{ > + u64 cur_el, target_el; > + > + if (!kvm_has_gcs(vcpu->kvm)) > + return false; > + > + if (vcpu->arch.ctxt.regs.pstate & PSR_EXLOCK_BIT) > + return false; > + > + cur_el = exlock_el_from_spsr(vcpu->arch.ctxt.regs.pstate); > + target_el = exlock_el_from_spsr(spsr); > + > + if (cur_el != target_el) > + return false; > + > + return vcpu_read_sys_reg(vcpu, GCSCR_EL2) & GCSCR_ELx_EXLOCKEN; > +} > + > +#else > +static inline bool kvm_check_illegal_exlock_return(struct kvm_vcpu *vcpu, > + u64 spsr) > +{ > + return false; > +} > +#endif > + > #define KVM_NV_GUEST_MAP_SZ (KVM_PGTABLE_PROT_SW1 | KVM_PGTABLE_PROT_SW0) > > static inline u64 kvm_encode_nested_level(struct kvm_s2_trans *trans) [...]