]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: arm64: nv: Add userspace and guest handling of VNCR_EL2
authorMarc Zyngier <maz@kernel.org>
Wed, 14 May 2025 10:34:51 +0000 (11:34 +0100)
committerMarc Zyngier <maz@kernel.org>
Mon, 19 May 2025 06:59:46 +0000 (07:59 +0100)
Plug VNCR_EL2 in the vcpu_sysreg enum, define its RES0/RES1 bits,
and make it accessible to userspace when the VM is configured to
support FEAT_NV2.

Reviewed-by: Oliver Upton <oliver.upton@linux.dev>
Link: https://lore.kernel.org/r/20250514103501.2225951-9-maz@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/include/asm/kvm_host.h
arch/arm64/kvm/nested.c
arch/arm64/kvm/sys_regs.c

index c762919a2072dd692e4e04dd2702a6f843c51b14..f5ac454dcf66a32a192faf7918e61d420c720bbe 100644 (file)
@@ -562,6 +562,8 @@ enum vcpu_sysreg {
        VNCR(HDFGWTR_EL2),
        VNCR(HAFGRTR_EL2),
 
+       VNCR(VNCR_EL2),
+
        VNCR(CNTVOFF_EL2),
        VNCR(CNTV_CVAL_EL0),
        VNCR(CNTV_CTL_EL0),
index 806e9cf6049a631332b3e8205de2083d851f8e28..32ea6e362bab116f147cfefa66c2b1505a9cba58 100644 (file)
@@ -1400,6 +1400,9 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
        res0 |= ICH_HCR_EL2_DVIM | ICH_HCR_EL2_vSGIEOICount;
        set_sysreg_masks(kvm, ICH_HCR_EL2, res0, res1);
 
+       /* VNCR_EL2 */
+       set_sysreg_masks(kvm, VNCR_EL2, VNCR_EL2_RES0, VNCR_EL2_RES1);
+
 out:
        for (enum vcpu_sysreg sr = __SANITISED_REG_START__; sr < NR_SYS_REGS; sr++)
                (void)__vcpu_sys_reg(vcpu, sr);
index 26e02e17239114528f633ce685d8315e02534c0a..204470283ccc32a4667bd9bb03b69574849fad50 100644 (file)
@@ -2281,15 +2281,6 @@ static bool bad_redir_trap(struct kvm_vcpu *vcpu,
                        "trap of EL2 register redirected to EL1");
 }
 
-#define EL2_REG(name, acc, rst, v) {           \
-       SYS_DESC(SYS_##name),                   \
-       .access = acc,                          \
-       .reset = rst,                           \
-       .reg = name,                            \
-       .visibility = el2_visibility,           \
-       .val = v,                               \
-}
-
 #define EL2_REG_FILTERED(name, acc, rst, v, filter) {  \
        SYS_DESC(SYS_##name),                   \
        .access = acc,                          \
@@ -2299,6 +2290,9 @@ static bool bad_redir_trap(struct kvm_vcpu *vcpu,
        .val = v,                               \
 }
 
+#define EL2_REG(name, acc, rst, v)                     \
+       EL2_REG_FILTERED(name, acc, rst, v, el2_visibility)
+
 #define EL2_REG_VNCR(name, rst, v)     EL2_REG(name, bad_vncr_trap, rst, v)
 #define EL2_REG_REDIR(name, rst, v)    EL2_REG(name, bad_redir_trap, rst, v)
 
@@ -2446,6 +2440,16 @@ static unsigned int sve_el2_visibility(const struct kvm_vcpu *vcpu,
        return __el2_visibility(vcpu, rd, sve_visibility);
 }
 
+static unsigned int vncr_el2_visibility(const struct kvm_vcpu *vcpu,
+                                       const struct sys_reg_desc *rd)
+{
+       if (el2_visibility(vcpu, rd) == 0 &&
+           kvm_has_feat(vcpu->kvm, ID_AA64MMFR4_EL1, NV_frac, NV2_ONLY))
+               return 0;
+
+       return REG_HIDDEN;
+}
+
 static bool access_zcr_el2(struct kvm_vcpu *vcpu,
                           struct sys_reg_params *p,
                           const struct sys_reg_desc *r)
@@ -3263,6 +3267,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
                         tcr2_el2_visibility),
        EL2_REG_VNCR(VTTBR_EL2, reset_val, 0),
        EL2_REG_VNCR(VTCR_EL2, reset_val, 0),
+       EL2_REG_FILTERED(VNCR_EL2, bad_vncr_trap, reset_val, 0,
+                        vncr_el2_visibility),
 
        { SYS_DESC(SYS_DACR32_EL2), undef_access, reset_unknown, DACR32_EL2 },
        EL2_REG_VNCR(HDFGRTR_EL2, reset_val, 0),