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)

[...]

Reply via email to