On Tue, 23 Dec 2025 at 01:22, Mark Brown <[email protected]> wrote: > > SME adds a new thread ID register, TPIDR2_EL0. This is used in userspace > for delayed saving of the ZA state but in terms of the architecture is > not really connected to SME other than being part of FEAT_SME. It has an > independent fine grained trap and the runtime connection with the rest > of SME is purely software defined. > > Expose the register as a system register if the guest supports SME, > context switching it along with the other EL0 TPIDRs. > > Signed-off-by: Mark Brown <[email protected]>
Reviewed-by: Fuad Tabba <[email protected]> Cheers, /fuad > --- > arch/arm64/include/asm/kvm_host.h | 1 + > arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h | 15 +++++++++++++++ > arch/arm64/kvm/sys_regs.c | 3 ++- > 3 files changed, 18 insertions(+), 1 deletion(-) > > diff --git a/arch/arm64/include/asm/kvm_host.h > b/arch/arm64/include/asm/kvm_host.h > index f24441244a68..825b74f752d6 100644 > --- a/arch/arm64/include/asm/kvm_host.h > +++ b/arch/arm64/include/asm/kvm_host.h > @@ -448,6 +448,7 @@ enum vcpu_sysreg { > CSSELR_EL1, /* Cache Size Selection Register */ > TPIDR_EL0, /* Thread ID, User R/W */ > TPIDRRO_EL0, /* Thread ID, User R/O */ > + TPIDR2_EL0, /* Thread ID, Register 2 */ > TPIDR_EL1, /* Thread ID, Privileged */ > CNTKCTL_EL1, /* Timer Control Register (EL1) */ > PAR_EL1, /* Physical Address Register */ > diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h > b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h > index 5624fd705ae3..8c3b3d6df99f 100644 > --- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h > +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h > @@ -88,6 +88,17 @@ static inline bool ctxt_has_sctlr2(struct kvm_cpu_context > *ctxt) > return kvm_has_sctlr2(kern_hyp_va(vcpu->kvm)); > } > > +static inline bool ctxt_has_sme(struct kvm_cpu_context *ctxt) > +{ > + struct kvm_vcpu *vcpu; > + > + if (!system_supports_sme()) > + return false; > + > + vcpu = ctxt_to_vcpu(ctxt); > + return kvm_has_sme(kern_hyp_va(vcpu->kvm)); > +} > + > static inline bool ctxt_is_guest(struct kvm_cpu_context *ctxt) > { > return host_data_ptr(host_ctxt) != ctxt; > @@ -127,6 +138,8 @@ static inline void __sysreg_save_user_state(struct > kvm_cpu_context *ctxt) > { > ctxt_sys_reg(ctxt, TPIDR_EL0) = read_sysreg(tpidr_el0); > ctxt_sys_reg(ctxt, TPIDRRO_EL0) = read_sysreg(tpidrro_el0); > + if (ctxt_has_sme(ctxt)) > + ctxt_sys_reg(ctxt, TPIDR2_EL0) = > read_sysreg_s(SYS_TPIDR2_EL0); > } > > static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) > @@ -204,6 +217,8 @@ static inline void __sysreg_restore_user_state(struct > kvm_cpu_context *ctxt) > { > write_sysreg(ctxt_sys_reg(ctxt, TPIDR_EL0), tpidr_el0); > write_sysreg(ctxt_sys_reg(ctxt, TPIDRRO_EL0), tpidrro_el0); > + if (ctxt_has_sme(ctxt)) > + write_sysreg_s(ctxt_sys_reg(ctxt, TPIDR2_EL0), > SYS_TPIDR2_EL0); > } > > static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt, > diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c > index 5c912139d264..7e550f045f4d 100644 > --- a/arch/arm64/kvm/sys_regs.c > +++ b/arch/arm64/kvm/sys_regs.c > @@ -3504,7 +3504,8 @@ static const struct sys_reg_desc sys_reg_descs[] = { > .visibility = s1poe_visibility }, > { SYS_DESC(SYS_TPIDR_EL0), NULL, reset_unknown, TPIDR_EL0 }, > { SYS_DESC(SYS_TPIDRRO_EL0), NULL, reset_unknown, TPIDRRO_EL0 }, > - { SYS_DESC(SYS_TPIDR2_EL0), undef_access }, > + { SYS_DESC(SYS_TPIDR2_EL0), NULL, reset_unknown, TPIDR2_EL0, > + .visibility = sme_visibility}, > > { SYS_DESC(SYS_SCXTNUM_EL0), undef_access }, > > > -- > 2.47.3 >
