Message ID | 20230808114711.2013842-25-maz@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM: arm64: NV trap forwarding infrastructure | expand |
Hi Marc, On 8/8/23 13:47, Marc Zyngier wrote: > Now that we can evaluate the FGT registers, allow them to be merged > with the hypervisor's own configuration (in the case of HFG{RW}TR_EL2) > or simply set for HFGITR_EL2, HDGFRTR_EL2 and HDFGWTR_EL2. HDFGRTR_EL2 > > Signed-off-by: Marc Zyngier <maz@kernel.org> > --- > arch/arm64/kvm/hyp/include/hyp/switch.h | 48 +++++++++++++++++++++++++ > 1 file changed, 48 insertions(+) > > diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h > index e096b16e85fd..a4750070563f 100644 > --- a/arch/arm64/kvm/hyp/include/hyp/switch.h > +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h > @@ -70,6 +70,13 @@ static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu) > } > } > > +#define compute_clr_set(vcpu, reg, clr, set) \ > + do { \ > + u64 hfg; \ > + hfg = __vcpu_sys_reg(vcpu, reg) & ~__ ## reg ## _RES0; \ > + set |= hfg & __ ## reg ## _MASK; \ > + clr |= ~hfg & __ ## reg ## _nMASK; \ > + } while(0) > > > static inline void __activate_traps_hfgxtr(struct kvm_vcpu *vcpu) > @@ -97,6 +104,10 @@ static inline void __activate_traps_hfgxtr(struct kvm_vcpu *vcpu) > if (cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38)) > w_set |= HFGxTR_EL2_TCR_EL1_MASK; > > + if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) { > + compute_clr_set(vcpu, HFGRTR_EL2, r_clr, r_set); > + compute_clr_set(vcpu, HFGWTR_EL2, w_clr, w_set); > + } > > /* The default is not to trap anything but ACCDATA_EL1 */ > r_val = __HFGRTR_EL2_nMASK & ~HFGxTR_EL2_nACCDATA_EL1; > @@ -109,6 +120,38 @@ static inline void __activate_traps_hfgxtr(struct kvm_vcpu *vcpu) > > write_sysreg_s(r_val, SYS_HFGRTR_EL2); > write_sysreg_s(w_val, SYS_HFGWTR_EL2); > + > + if (!vcpu_has_nv(vcpu) || is_hyp_ctxt(vcpu)) > + return; > + > + ctxt_sys_reg(hctxt, HFGITR_EL2) = read_sysreg_s(SYS_HFGITR_EL2); > + > + r_set = r_clr = 0; > + compute_clr_set(vcpu, HFGITR_EL2, r_clr, r_set); > + r_val = __HFGITR_EL2_nMASK; > + r_val |= r_set; > + r_val &= ~r_clr; > + > + write_sysreg_s(r_val, SYS_HFGITR_EL2); > + > + ctxt_sys_reg(hctxt, HDFGRTR_EL2) = read_sysreg_s(SYS_HDFGRTR_EL2); > + ctxt_sys_reg(hctxt, HDFGWTR_EL2) = read_sysreg_s(SYS_HDFGWTR_EL2); > + > + r_clr = r_set = w_clr = w_set = 0; > + > + compute_clr_set(vcpu, HDFGRTR_EL2, r_clr, r_set); > + compute_clr_set(vcpu, HDFGWTR_EL2, w_clr, w_set); > + > + r_val = __HDFGRTR_EL2_nMASK; > + r_val |= r_set; > + r_val &= ~r_clr; > + > + w_val = __HDFGWTR_EL2_nMASK; > + w_val |= w_set; > + w_val &= ~w_clr; > + > + write_sysreg_s(r_val, SYS_HDFGRTR_EL2); > + write_sysreg_s(w_val, SYS_HDFGWTR_EL2); > } > > static inline void __deactivate_traps_hfgxtr(struct kvm_vcpu *vcpu) > @@ -121,7 +164,12 @@ static inline void __deactivate_traps_hfgxtr(struct kvm_vcpu *vcpu) > write_sysreg_s(ctxt_sys_reg(hctxt, HFGRTR_EL2), SYS_HFGRTR_EL2); > write_sysreg_s(ctxt_sys_reg(hctxt, HFGWTR_EL2), SYS_HFGWTR_EL2); > > + if (!vcpu_has_nv(vcpu) || is_hyp_ctxt(vcpu)) > + return; > > + write_sysreg_s(ctxt_sys_reg(hctxt, HFGITR_EL2), SYS_HFGITR_EL2); > + write_sysreg_s(ctxt_sys_reg(hctxt, HDFGRTR_EL2), SYS_HDFGRTR_EL2); > + write_sysreg_s(ctxt_sys_reg(hctxt, HDFGWTR_EL2), SYS_HDFGWTR_EL2); > } > > static inline void __activate_traps_common(struct kvm_vcpu *vcpu) besides looks good to me Reviewed-by: Eric Auger <eric.auger@redhat.com> Eric
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h index e096b16e85fd..a4750070563f 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -70,6 +70,13 @@ static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu) } } +#define compute_clr_set(vcpu, reg, clr, set) \ + do { \ + u64 hfg; \ + hfg = __vcpu_sys_reg(vcpu, reg) & ~__ ## reg ## _RES0; \ + set |= hfg & __ ## reg ## _MASK; \ + clr |= ~hfg & __ ## reg ## _nMASK; \ + } while(0) static inline void __activate_traps_hfgxtr(struct kvm_vcpu *vcpu) @@ -97,6 +104,10 @@ static inline void __activate_traps_hfgxtr(struct kvm_vcpu *vcpu) if (cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38)) w_set |= HFGxTR_EL2_TCR_EL1_MASK; + if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) { + compute_clr_set(vcpu, HFGRTR_EL2, r_clr, r_set); + compute_clr_set(vcpu, HFGWTR_EL2, w_clr, w_set); + } /* The default is not to trap anything but ACCDATA_EL1 */ r_val = __HFGRTR_EL2_nMASK & ~HFGxTR_EL2_nACCDATA_EL1; @@ -109,6 +120,38 @@ static inline void __activate_traps_hfgxtr(struct kvm_vcpu *vcpu) write_sysreg_s(r_val, SYS_HFGRTR_EL2); write_sysreg_s(w_val, SYS_HFGWTR_EL2); + + if (!vcpu_has_nv(vcpu) || is_hyp_ctxt(vcpu)) + return; + + ctxt_sys_reg(hctxt, HFGITR_EL2) = read_sysreg_s(SYS_HFGITR_EL2); + + r_set = r_clr = 0; + compute_clr_set(vcpu, HFGITR_EL2, r_clr, r_set); + r_val = __HFGITR_EL2_nMASK; + r_val |= r_set; + r_val &= ~r_clr; + + write_sysreg_s(r_val, SYS_HFGITR_EL2); + + ctxt_sys_reg(hctxt, HDFGRTR_EL2) = read_sysreg_s(SYS_HDFGRTR_EL2); + ctxt_sys_reg(hctxt, HDFGWTR_EL2) = read_sysreg_s(SYS_HDFGWTR_EL2); + + r_clr = r_set = w_clr = w_set = 0; + + compute_clr_set(vcpu, HDFGRTR_EL2, r_clr, r_set); + compute_clr_set(vcpu, HDFGWTR_EL2, w_clr, w_set); + + r_val = __HDFGRTR_EL2_nMASK; + r_val |= r_set; + r_val &= ~r_clr; + + w_val = __HDFGWTR_EL2_nMASK; + w_val |= w_set; + w_val &= ~w_clr; + + write_sysreg_s(r_val, SYS_HDFGRTR_EL2); + write_sysreg_s(w_val, SYS_HDFGWTR_EL2); } static inline void __deactivate_traps_hfgxtr(struct kvm_vcpu *vcpu) @@ -121,7 +164,12 @@ static inline void __deactivate_traps_hfgxtr(struct kvm_vcpu *vcpu) write_sysreg_s(ctxt_sys_reg(hctxt, HFGRTR_EL2), SYS_HFGRTR_EL2); write_sysreg_s(ctxt_sys_reg(hctxt, HFGWTR_EL2), SYS_HFGWTR_EL2); + if (!vcpu_has_nv(vcpu) || is_hyp_ctxt(vcpu)) + return; + write_sysreg_s(ctxt_sys_reg(hctxt, HFGITR_EL2), SYS_HFGITR_EL2); + write_sysreg_s(ctxt_sys_reg(hctxt, HDFGRTR_EL2), SYS_HDFGRTR_EL2); + write_sysreg_s(ctxt_sys_reg(hctxt, HDFGWTR_EL2), SYS_HDFGWTR_EL2); } static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
Now that we can evaluate the FGT registers, allow them to be merged with the hypervisor's own configuration (in the case of HFG{RW}TR_EL2) or simply set for HFGITR_EL2, HDGFRTR_EL2 and HDFGWTR_EL2. Signed-off-by: Marc Zyngier <maz@kernel.org> --- arch/arm64/kvm/hyp/include/hyp/switch.h | 48 +++++++++++++++++++++++++ 1 file changed, 48 insertions(+)