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)
[...]