* [PATCH 00/14] KVM: arm64: NV userspace ABI
@ 2025-02-15 17:38 Marc Zyngier
2025-02-15 17:38 ` [PATCH 01/14] arm64: cpufeature: Handle NV_frac as a synonym of NV2 Marc Zyngier
` (14 more replies)
0 siblings, 15 replies; 23+ messages in thread
From: Marc Zyngier @ 2025-02-15 17:38 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Eric Auger
Since the previous incarnation of the ABI was proved to be subtly
wrong, I have reworked it to be more in line with the current way KVM
operates.
No more late NV-specific adjustment nor writable ID_AA64MMFR0_EL1.VH.
The NV configuration is now entirely selected from the vcpu flags.
I've preserved the KVM_ARM_VCPU_EL2 flag which enables NV with VHE,
and added KVM_ARM_VCPU_EL2_E2H0 which alters the NV behaviour to only
allow nVHE guests without recursive NV support.
This series is actually very little new code. The bulk of it is
converting the feature downgrade to be per-idreg, essentially going
back to the state before 44241f34fac96 ("KVM: arm64: nv: Use accessors
for modifying ID registers"), only slightly modernised. This then
becomes part of the reset value computing.
The rest is simply what you'd expect in terms of being able to write
the ID_AA64MMFR4_EL1.NV_frac field, making the correct bits RES0 when
needed, probing for capabilities and handling the init flags.
Patches on top of -rc2, with the integration branch at the usual
location.
Marc Zyngier (14):
arm64: cpufeature: Handle NV_frac as a synonym of NV2
KVM: arm64: Hide ID_AA64MMFR2_EL1.NV from guest and userspace
KVM: arm64: Mark HCR.EL2.E2H RES0 when ID_AA64MMFR1_EL1.VH is zero
KVM: arm64: Mark HCR.EL2.{NV*,AT} RES0 when ID_AA64MMFR4_EL1.NV_frac
is 0
KVM: arm64: Advertise NV2 in the boot messages
KVM: arm64: Consolidate idreg reset method
KVM: arm64: Make ID_REG_LIMIT_FIELD_ENUM() more widely available
KVM: arm64: Enforce NV limits on a per-idregs basis
KVM: arm64: Move NV-specific capping to idreg sanitisation
KVM: arm64: Allow userspace to limit NV support to nVHE
KVM: arm64: Make ID_AA64MMFR4_EL1.NV_frac writable
KVM: arm64: Advertise FEAT_ECV when possible
KVM: arm64: Allow userspace to request KVM_ARM_VCPU_EL2*
KVM: arm64: Document NV caps and vcpu flags
Documentation/virt/kvm/api.rst | 14 +-
arch/arm64/include/asm/kvm_host.h | 2 +-
arch/arm64/include/asm/kvm_nested.h | 1 +
arch/arm64/include/uapi/asm/kvm.h | 1 +
arch/arm64/kernel/cpufeature.c | 15 +-
arch/arm64/kvm/arm.c | 11 +-
arch/arm64/kvm/nested.c | 285 +++++++++++++++-------------
arch/arm64/kvm/sys_regs.c | 25 +--
arch/arm64/kvm/sys_regs.h | 10 +
include/uapi/linux/kvm.h | 2 +
10 files changed, 209 insertions(+), 157 deletions(-)
--
2.39.2
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 01/14] arm64: cpufeature: Handle NV_frac as a synonym of NV2
2025-02-15 17:38 [PATCH 00/14] KVM: arm64: NV userspace ABI Marc Zyngier
@ 2025-02-15 17:38 ` Marc Zyngier
2025-02-24 7:41 ` Aneesh Kumar K.V
2025-02-15 17:38 ` [PATCH 02/14] KVM: arm64: Hide ID_AA64MMFR2_EL1.NV from guest and userspace Marc Zyngier
` (13 subsequent siblings)
14 siblings, 1 reply; 23+ messages in thread
From: Marc Zyngier @ 2025-02-15 17:38 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Eric Auger
With ARMv9.5, an implementation supporting Nested Virtualization
is allowed to only support NV2, and to avoid supporting the old
(and useless) ARMv8.3 variant.
This is indicated by ID_AA64MMFR2_EL1.NV being 0 (as if NV wasn't
implemented) and ID_AA64MMDR4_EL1.NV_frac being 1 (indicating that
NV2 is actually supported).
Given that KVM only deals with NV2 and refuses to use the old NV,
detecting NV2 or NV_frac is what we need to enable it.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kernel/cpufeature.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 4eb7c6698ae43..94605e91f0e5f 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -497,6 +497,7 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr3[] = {
static const struct arm64_ftr_bits ftr_id_aa64mmfr4[] = {
S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR4_EL1_E2H0_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR4_EL1_NV_frac_SHIFT, 4, 0),
ARM64_FTR_END,
};
@@ -2162,7 +2163,7 @@ static bool has_nested_virt_support(const struct arm64_cpu_capabilities *cap,
if (kvm_get_mode() != KVM_MODE_NV)
return false;
- if (!has_cpuid_feature(cap, scope)) {
+ if (!cpucap_multi_entry_cap_matches(cap, scope)) {
pr_warn("unavailable: %s\n", cap->desc);
return false;
}
@@ -2519,7 +2520,17 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.capability = ARM64_HAS_NESTED_VIRT,
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
.matches = has_nested_virt_support,
- ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, NV, NV2)
+ .match_list = (const struct arm64_cpu_capabilities []){
+ {
+ .matches = has_cpuid_feature,
+ ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, NV, NV2)
+ },
+ {
+ .matches = has_cpuid_feature,
+ ARM64_CPUID_FIELDS(ID_AA64MMFR4_EL1, NV_frac, NV2_ONLY)
+ },
+ { /* Sentinel */ }
+ },
},
{
.capability = ARM64_HAS_32BIT_EL0_DO_NOT_USE,
--
2.39.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 02/14] KVM: arm64: Hide ID_AA64MMFR2_EL1.NV from guest and userspace
2025-02-15 17:38 [PATCH 00/14] KVM: arm64: NV userspace ABI Marc Zyngier
2025-02-15 17:38 ` [PATCH 01/14] arm64: cpufeature: Handle NV_frac as a synonym of NV2 Marc Zyngier
@ 2025-02-15 17:38 ` Marc Zyngier
2025-02-15 17:38 ` [PATCH 03/14] KVM: arm64: Mark HCR.EL2.E2H RES0 when ID_AA64MMFR1_EL1.VH is zero Marc Zyngier
` (12 subsequent siblings)
14 siblings, 0 replies; 23+ messages in thread
From: Marc Zyngier @ 2025-02-15 17:38 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Eric Auger
Since our take on FEAT_NV is to only support FEAT_NV2, we should
never expose ID_AA64MMFR2_EL1.NV to a guest nor userspace.
Make sure we mask this field for good.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/sys_regs.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 82430c1e1dd02..9f10dbd26e348 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1627,6 +1627,7 @@ static u64 __kvm_read_sanitised_id_reg(const struct kvm_vcpu *vcpu,
break;
case SYS_ID_AA64MMFR2_EL1:
val &= ~ID_AA64MMFR2_EL1_CCIDX_MASK;
+ val &= ~ID_AA64MMFR2_EL1_NV;
break;
case SYS_ID_AA64MMFR3_EL1:
val &= ID_AA64MMFR3_EL1_TCRX | ID_AA64MMFR3_EL1_S1POE |
--
2.39.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 03/14] KVM: arm64: Mark HCR.EL2.E2H RES0 when ID_AA64MMFR1_EL1.VH is zero
2025-02-15 17:38 [PATCH 00/14] KVM: arm64: NV userspace ABI Marc Zyngier
2025-02-15 17:38 ` [PATCH 01/14] arm64: cpufeature: Handle NV_frac as a synonym of NV2 Marc Zyngier
2025-02-15 17:38 ` [PATCH 02/14] KVM: arm64: Hide ID_AA64MMFR2_EL1.NV from guest and userspace Marc Zyngier
@ 2025-02-15 17:38 ` Marc Zyngier
2025-02-24 7:39 ` Aneesh Kumar K.V
2025-02-15 17:38 ` [PATCH 04/14] KVM: arm64: Mark HCR.EL2.{NV*,AT} RES0 when ID_AA64MMFR4_EL1.NV_frac is 0 Marc Zyngier
` (11 subsequent siblings)
14 siblings, 1 reply; 23+ messages in thread
From: Marc Zyngier @ 2025-02-15 17:38 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Eric Auger
Enforce HCR_EL2.E2H being RES0 when VHE is disabled, so that we can
actually rely on that bit never being flipped behind our back.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/nested.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index 0c9387d2f5070..ed3add7d32f66 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -1034,6 +1034,8 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
res0 |= (HCR_TEA | HCR_TERR);
if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, LO, IMP))
res0 |= HCR_TLOR;
+ if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, VH, IMP))
+ res0 |= HCR_E2H;
if (!kvm_has_feat(kvm, ID_AA64MMFR4_EL1, E2H0, IMP))
res1 |= HCR_E2H;
set_sysreg_masks(kvm, HCR_EL2, res0, res1);
--
2.39.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 04/14] KVM: arm64: Mark HCR.EL2.{NV*,AT} RES0 when ID_AA64MMFR4_EL1.NV_frac is 0
2025-02-15 17:38 [PATCH 00/14] KVM: arm64: NV userspace ABI Marc Zyngier
` (2 preceding siblings ...)
2025-02-15 17:38 ` [PATCH 03/14] KVM: arm64: Mark HCR.EL2.E2H RES0 when ID_AA64MMFR1_EL1.VH is zero Marc Zyngier
@ 2025-02-15 17:38 ` Marc Zyngier
2025-02-15 17:38 ` [PATCH 05/14] KVM: arm64: Advertise NV2 in the boot messages Marc Zyngier
` (10 subsequent siblings)
14 siblings, 0 replies; 23+ messages in thread
From: Marc Zyngier @ 2025-02-15 17:38 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Eric Auger
Enforce HCR_EL2.{NV*,AT} being RES0 when NV2 is disabled, so that
we can actually rely on these bits never being flipped behind our back.
This of course relies on our earlier ID reg sanitising.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/nested.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index ed3add7d32f66..9f140560a6f5d 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -1021,10 +1021,11 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
res0 |= HCR_FIEN;
if (!kvm_has_feat(kvm, ID_AA64MMFR2_EL1, FWB, IMP))
res0 |= HCR_FWB;
- if (!kvm_has_feat(kvm, ID_AA64MMFR2_EL1, NV, NV2))
- res0 |= HCR_NV2;
- if (!kvm_has_feat(kvm, ID_AA64MMFR2_EL1, NV, IMP))
- res0 |= (HCR_AT | HCR_NV1 | HCR_NV);
+ /* Implementation choice: NV2 is the only supported config */
+ if (!kvm_has_feat(kvm, ID_AA64MMFR4_EL1, NV_frac, NV2_ONLY))
+ res0 |= (HCR_NV2 | HCR_NV | HCR_AT);
+ if (!kvm_has_feat(kvm, ID_AA64MMFR4_EL1, E2H0, NI))
+ res0 |= HCR_NV1;
if (!(kvm_vcpu_has_feature(kvm, KVM_ARM_VCPU_PTRAUTH_ADDRESS) &&
kvm_vcpu_has_feature(kvm, KVM_ARM_VCPU_PTRAUTH_GENERIC)))
res0 |= (HCR_API | HCR_APK);
--
2.39.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 05/14] KVM: arm64: Advertise NV2 in the boot messages
2025-02-15 17:38 [PATCH 00/14] KVM: arm64: NV userspace ABI Marc Zyngier
` (3 preceding siblings ...)
2025-02-15 17:38 ` [PATCH 04/14] KVM: arm64: Mark HCR.EL2.{NV*,AT} RES0 when ID_AA64MMFR4_EL1.NV_frac is 0 Marc Zyngier
@ 2025-02-15 17:38 ` Marc Zyngier
2025-02-15 17:38 ` [PATCH 06/14] KVM: arm64: Consolidate idreg reset method Marc Zyngier
` (9 subsequent siblings)
14 siblings, 0 replies; 23+ messages in thread
From: Marc Zyngier @ 2025-02-15 17:38 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Eric Auger
Make it a bit easier to understand what people are running by
adding a +NV2 string to the successful KVM initialisation.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/arm.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 071a7d75be689..4746c6cace2a8 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -2814,11 +2814,12 @@ static __init int kvm_arm_init(void)
if (err)
goto out_hyp;
- kvm_info("%s%sVHE mode initialized successfully\n",
+ kvm_info("%s%sVHE%s mode initialized successfully\n",
in_hyp_mode ? "" : (is_protected_kvm_enabled() ?
"Protected " : "Hyp "),
in_hyp_mode ? "" : (cpus_have_final_cap(ARM64_KVM_HVHE) ?
- "h" : "n"));
+ "h" : "n"),
+ cpus_have_final_cap(ARM64_HAS_NESTED_VIRT) ? "+NV2": "");
/*
* FIXME: Do something reasonable if kvm_init() fails after pKVM
--
2.39.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 06/14] KVM: arm64: Consolidate idreg reset method
2025-02-15 17:38 [PATCH 00/14] KVM: arm64: NV userspace ABI Marc Zyngier
` (4 preceding siblings ...)
2025-02-15 17:38 ` [PATCH 05/14] KVM: arm64: Advertise NV2 in the boot messages Marc Zyngier
@ 2025-02-15 17:38 ` Marc Zyngier
2025-02-15 17:38 ` [PATCH 07/14] KVM: arm64: Make ID_REG_LIMIT_FIELD_ENUM() more widely available Marc Zyngier
` (8 subsequent siblings)
14 siblings, 0 replies; 23+ messages in thread
From: Marc Zyngier @ 2025-02-15 17:38 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Eric Auger
Since all the ID_DESC() users are using kvm_read_sanitised_id_reg()
as the .reset method, consolidate all the uses into that particular
macro.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/sys_regs.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 9f10dbd26e348..b1bd1a47e7caa 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -2270,14 +2270,14 @@ static bool bad_redir_trap(struct kvm_vcpu *vcpu,
#define ID_DESC(name) \
SYS_DESC(SYS_##name), \
.access = access_id_reg, \
- .get_user = get_id_reg \
+ .get_user = get_id_reg, \
+ .reset = kvm_read_sanitised_id_reg
/* sys_reg_desc initialiser for known cpufeature ID registers */
#define ID_SANITISED(name) { \
ID_DESC(name), \
.set_user = set_id_reg, \
.visibility = id_visibility, \
- .reset = kvm_read_sanitised_id_reg, \
.val = 0, \
}
@@ -2286,7 +2286,6 @@ static bool bad_redir_trap(struct kvm_vcpu *vcpu,
ID_DESC(name), \
.set_user = set_id_reg, \
.visibility = aa32_id_visibility, \
- .reset = kvm_read_sanitised_id_reg, \
.val = 0, \
}
@@ -2295,7 +2294,6 @@ static bool bad_redir_trap(struct kvm_vcpu *vcpu,
ID_DESC(name), \
.set_user = set_id_reg, \
.visibility = id_visibility, \
- .reset = kvm_read_sanitised_id_reg, \
.val = mask, \
}
@@ -2304,7 +2302,6 @@ static bool bad_redir_trap(struct kvm_vcpu *vcpu,
ID_DESC(sysreg), \
.set_user = set_##name, \
.visibility = id_visibility, \
- .reset = kvm_read_sanitised_id_reg, \
.val = (mask), \
}
@@ -2319,7 +2316,6 @@ static bool bad_redir_trap(struct kvm_vcpu *vcpu,
.get_user = get_id_reg, \
.set_user = set_id_reg, \
.visibility = raz_visibility, \
- .reset = kvm_read_sanitised_id_reg, \
.val = 0, \
}
@@ -2332,7 +2328,6 @@ static bool bad_redir_trap(struct kvm_vcpu *vcpu,
ID_DESC(name), \
.set_user = set_id_reg, \
.visibility = raz_visibility, \
- .reset = kvm_read_sanitised_id_reg, \
.val = 0, \
}
--
2.39.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 07/14] KVM: arm64: Make ID_REG_LIMIT_FIELD_ENUM() more widely available
2025-02-15 17:38 [PATCH 00/14] KVM: arm64: NV userspace ABI Marc Zyngier
` (5 preceding siblings ...)
2025-02-15 17:38 ` [PATCH 06/14] KVM: arm64: Consolidate idreg reset method Marc Zyngier
@ 2025-02-15 17:38 ` Marc Zyngier
2025-02-15 17:38 ` [PATCH 08/14] KVM: arm64: Enforce NV limits on a per-idregs basis Marc Zyngier
` (7 subsequent siblings)
14 siblings, 0 replies; 23+ messages in thread
From: Marc Zyngier @ 2025-02-15 17:38 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Eric Auger
ID_REG_LIMIT_FIELD_ENUM() is a useful macro to limit the idreg
features exposed to guest and userspace, and the NV code can
make use of it.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/sys_regs.c | 10 ----------
arch/arm64/kvm/sys_regs.h | 10 ++++++++++
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index b1bd1a47e7caa..885cdef77d01e 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1803,16 +1803,6 @@ static u64 sanitise_id_aa64pfr0_el1(const struct kvm_vcpu *vcpu, u64 val)
return val;
}
-#define ID_REG_LIMIT_FIELD_ENUM(val, reg, field, limit) \
-({ \
- u64 __f_val = FIELD_GET(reg##_##field##_MASK, val); \
- (val) &= ~reg##_##field##_MASK; \
- (val) |= FIELD_PREP(reg##_##field##_MASK, \
- min(__f_val, \
- (u64)SYS_FIELD_VALUE(reg, field, limit))); \
- (val); \
-})
-
static u64 sanitise_id_aa64dfr0_el1(const struct kvm_vcpu *vcpu, u64 val)
{
val = ID_REG_LIMIT_FIELD_ENUM(val, ID_AA64DFR0_EL1, DebugVer, V8P8);
diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
index 1d94ed6efad2c..cc6338d387663 100644
--- a/arch/arm64/kvm/sys_regs.h
+++ b/arch/arm64/kvm/sys_regs.h
@@ -247,4 +247,14 @@ int kvm_finalize_sys_regs(struct kvm_vcpu *vcpu);
CRn(sys_reg_CRn(reg)), CRm(sys_reg_CRm(reg)), \
Op2(sys_reg_Op2(reg))
+#define ID_REG_LIMIT_FIELD_ENUM(val, reg, field, limit) \
+({ \
+ u64 __f_val = FIELD_GET(reg##_##field##_MASK, val); \
+ (val) &= ~reg##_##field##_MASK; \
+ (val) |= FIELD_PREP(reg##_##field##_MASK, \
+ min(__f_val, \
+ (u64)SYS_FIELD_VALUE(reg, field, limit))); \
+ (val); \
+})
+
#endif /* __ARM64_KVM_SYS_REGS_LOCAL_H__ */
--
2.39.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 08/14] KVM: arm64: Enforce NV limits on a per-idregs basis
2025-02-15 17:38 [PATCH 00/14] KVM: arm64: NV userspace ABI Marc Zyngier
` (6 preceding siblings ...)
2025-02-15 17:38 ` [PATCH 07/14] KVM: arm64: Make ID_REG_LIMIT_FIELD_ENUM() more widely available Marc Zyngier
@ 2025-02-15 17:38 ` Marc Zyngier
2025-02-15 17:38 ` [PATCH 09/14] KVM: arm64: Move NV-specific capping to idreg sanitisation Marc Zyngier
` (6 subsequent siblings)
14 siblings, 0 replies; 23+ messages in thread
From: Marc Zyngier @ 2025-02-15 17:38 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Eric Auger
As we are about to change the way the idreg reset values are computed,
move all the NV limits into a function that initialises one register
at a time.
This will be most useful in the upcoming patches. We take this opportunity
to remove the NV_FTR() macro and rely on the generated names instead.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/nested.c | 239 +++++++++++++++++++++++-----------------
1 file changed, 136 insertions(+), 103 deletions(-)
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index 9f140560a6f5d..2cc82e69ab523 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -16,9 +16,6 @@
#include "sys_regs.h"
-/* Protection against the sysreg repainting madness... */
-#define NV_FTR(r, f) ID_AA64##r##_EL1_##f
-
/*
* Ratio of live shadow S2 MMU per vcpu. This is a trade-off between
* memory usage and potential number of different sets of S2 PTs in
@@ -807,133 +804,169 @@ void kvm_arch_flush_shadow_all(struct kvm *kvm)
* This list should get updated as new features get added to the NV
* support, and new extension to the architecture.
*/
+static u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val)
+{
+ switch (reg) {
+ case SYS_ID_AA64ISAR0_EL1:
+ /* Support everything but TME */
+ val &= ~ID_AA64ISAR0_EL1_TME;
+ break;
+
+ case SYS_ID_AA64ISAR1_EL1:
+ /* Support everything but LS64 and Spec Invalidation */
+ val &= ~(ID_AA64ISAR1_EL1_LS64 |
+ ID_AA64ISAR1_EL1_SPECRES);
+ break;
+
+ case SYS_ID_AA64PFR0_EL1:
+ /* No RME, AMU, MPAM, S-EL2, or RAS */
+ val &= ~(ID_AA64PFR0_EL1_RME |
+ ID_AA64PFR0_EL1_AMU |
+ ID_AA64PFR0_EL1_MPAM |
+ ID_AA64PFR0_EL1_SEL2 |
+ ID_AA64PFR0_EL1_RAS |
+ ID_AA64PFR0_EL1_EL3 |
+ ID_AA64PFR0_EL1_EL2 |
+ ID_AA64PFR0_EL1_EL1 |
+ ID_AA64PFR0_EL1_EL0);
+ /* 64bit only at any EL */
+ val |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, EL0, IMP);
+ val |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, EL1, IMP);
+ val |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, EL2, IMP);
+ val |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, EL3, IMP);
+ break;
+
+ case SYS_ID_AA64PFR1_EL1:
+ /* Only support BTI, SSBS, CSV2_frac */
+ val &= (ID_AA64PFR1_EL1_BT |
+ ID_AA64PFR1_EL1_SSBS |
+ ID_AA64PFR1_EL1_CSV2_frac);
+ break;
+
+ case SYS_ID_AA64MMFR0_EL1:
+ /* Hide ECV, ExS, Secure Memory */
+ val &= ~(ID_AA64MMFR0_EL1_EVC |
+ ID_AA64MMFR0_EL1_EXS |
+ ID_AA64MMFR0_EL1_TGRAN4_2 |
+ ID_AA64MMFR0_EL1_TGRAN16_2 |
+ ID_AA64MMFR0_EL1_TGRAN64_2 |
+ ID_AA64MMFR0_EL1_SNSMEM);
+
+ /* Disallow unsupported S2 page sizes */
+ switch (PAGE_SIZE) {
+ case SZ_64K:
+ val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN16_2, NI);
+ fallthrough;
+ case SZ_16K:
+ val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN4_2, NI);
+ fallthrough;
+ case SZ_4K:
+ /* Support everything */
+ break;
+ }
+
+ /*
+ * Since we can't support a guest S2 page size smaller
+ * than the host's own page size (due to KVM only
+ * populating its own S2 using the kernel's page
+ * size), advertise the limitation using FEAT_GTG.
+ */
+ switch (PAGE_SIZE) {
+ case SZ_4K:
+ val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN4_2, IMP);
+ fallthrough;
+ case SZ_16K:
+ val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN16_2, IMP);
+ fallthrough;
+ case SZ_64K:
+ val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN64_2, IMP);
+ break;
+ }
+
+ /* Cap PARange to 48bits */
+ val = ID_REG_LIMIT_FIELD_ENUM(val, ID_AA64MMFR0_EL1, PARANGE, 48);
+ break;
+
+ case SYS_ID_AA64MMFR1_EL1:
+ val &= (ID_AA64MMFR1_EL1_HCX |
+ ID_AA64MMFR1_EL1_PAN |
+ ID_AA64MMFR1_EL1_LO |
+ ID_AA64MMFR1_EL1_HPDS |
+ ID_AA64MMFR1_EL1_VH |
+ ID_AA64MMFR1_EL1_VMIDBits);
+ break;
+
+ case SYS_ID_AA64MMFR2_EL1:
+ val &= ~(ID_AA64MMFR2_EL1_BBM |
+ ID_AA64MMFR2_EL1_TTL |
+ GENMASK_ULL(47, 44) |
+ ID_AA64MMFR2_EL1_ST |
+ ID_AA64MMFR2_EL1_CCIDX |
+ ID_AA64MMFR2_EL1_VARange);
+
+ /* Force TTL support */
+ val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR2_EL1, TTL, IMP);
+ break;
+
+ case SYS_ID_AA64MMFR4_EL1:
+ val = SYS_FIELD_PREP_ENUM(ID_AA64MMFR4_EL1, NV_frac, NV2_ONLY);
+ val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR4_EL1, E2H0, NI_NV1);
+ break;
+
+ case SYS_ID_AA64DFR0_EL1:
+ /* Only limited support for PMU, Debug, BPs, WPs, and HPMN0 */
+ val &= (ID_AA64DFR0_EL1_PMUVer |
+ ID_AA64DFR0_EL1_WRPs |
+ ID_AA64DFR0_EL1_BRPs |
+ ID_AA64DFR0_EL1_DebugVer|
+ ID_AA64DFR0_EL1_HPMN0);
+
+ /* Cap Debug to ARMv8.1 */
+ val = ID_REG_LIMIT_FIELD_ENUM(val, ID_AA64DFR0_EL1, DebugVer, VHE);
+ break;
+ }
+
+ return val;
+}
+
static void limit_nv_id_regs(struct kvm *kvm)
{
- u64 val, tmp;
+ u64 val;
- /* Support everything but TME */
val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64ISAR0_EL1);
- val &= ~NV_FTR(ISAR0, TME);
+ val = limit_nv_id_reg(kvm, SYS_ID_AA64ISAR0_EL1, val);
kvm_set_vm_id_reg(kvm, SYS_ID_AA64ISAR0_EL1, val);
- /* Support everything but Spec Invalidation and LS64 */
val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64ISAR1_EL1);
- val &= ~(NV_FTR(ISAR1, LS64) |
- NV_FTR(ISAR1, SPECRES));
+ val = limit_nv_id_reg(kvm, SYS_ID_AA64ISAR1_EL1, val);
kvm_set_vm_id_reg(kvm, SYS_ID_AA64ISAR1_EL1, val);
- /* No AMU, MPAM, S-EL2, or RAS */
val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1);
- val &= ~(GENMASK_ULL(55, 52) |
- NV_FTR(PFR0, AMU) |
- NV_FTR(PFR0, MPAM) |
- NV_FTR(PFR0, SEL2) |
- NV_FTR(PFR0, RAS) |
- NV_FTR(PFR0, EL3) |
- NV_FTR(PFR0, EL2) |
- NV_FTR(PFR0, EL1) |
- NV_FTR(PFR0, EL0));
- /* 64bit only at any EL */
- val |= FIELD_PREP(NV_FTR(PFR0, EL0), 0b0001);
- val |= FIELD_PREP(NV_FTR(PFR0, EL1), 0b0001);
- val |= FIELD_PREP(NV_FTR(PFR0, EL2), 0b0001);
- val |= FIELD_PREP(NV_FTR(PFR0, EL3), 0b0001);
+ val = limit_nv_id_reg(kvm, SYS_ID_AA64PFR0_EL1, val);
kvm_set_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1, val);
- /* Only support BTI, SSBS, CSV2_frac */
val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR1_EL1);
- val &= (NV_FTR(PFR1, BT) |
- NV_FTR(PFR1, SSBS) |
- NV_FTR(PFR1, CSV2_frac));
+ val = limit_nv_id_reg(kvm, SYS_ID_AA64PFR1_EL1, val);
kvm_set_vm_id_reg(kvm, SYS_ID_AA64PFR1_EL1, val);
- /* Hide ECV, ExS, Secure Memory */
val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64MMFR0_EL1);
- val &= ~(NV_FTR(MMFR0, ECV) |
- NV_FTR(MMFR0, EXS) |
- NV_FTR(MMFR0, TGRAN4_2) |
- NV_FTR(MMFR0, TGRAN16_2) |
- NV_FTR(MMFR0, TGRAN64_2) |
- NV_FTR(MMFR0, SNSMEM));
-
- /* Disallow unsupported S2 page sizes */
- switch (PAGE_SIZE) {
- case SZ_64K:
- val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN16_2), 0b0001);
- fallthrough;
- case SZ_16K:
- val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN4_2), 0b0001);
- fallthrough;
- case SZ_4K:
- /* Support everything */
- break;
- }
- /*
- * Since we can't support a guest S2 page size smaller than
- * the host's own page size (due to KVM only populating its
- * own S2 using the kernel's page size), advertise the
- * limitation using FEAT_GTG.
- */
- switch (PAGE_SIZE) {
- case SZ_4K:
- val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN4_2), 0b0010);
- fallthrough;
- case SZ_16K:
- val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN16_2), 0b0010);
- fallthrough;
- case SZ_64K:
- val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN64_2), 0b0010);
- break;
- }
- /* Cap PARange to 48bits */
- tmp = FIELD_GET(NV_FTR(MMFR0, PARANGE), val);
- if (tmp > 0b0101) {
- val &= ~NV_FTR(MMFR0, PARANGE);
- val |= FIELD_PREP(NV_FTR(MMFR0, PARANGE), 0b0101);
- }
+ val = limit_nv_id_reg(kvm, SYS_ID_AA64MMFR0_EL1, val);
kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR0_EL1, val);
val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64MMFR1_EL1);
- val &= (NV_FTR(MMFR1, HCX) |
- NV_FTR(MMFR1, PAN) |
- NV_FTR(MMFR1, LO) |
- NV_FTR(MMFR1, HPDS) |
- NV_FTR(MMFR1, VH) |
- NV_FTR(MMFR1, VMIDBits));
+ val = limit_nv_id_reg(kvm, SYS_ID_AA64MMFR1_EL1, val);
kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR1_EL1, val);
val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64MMFR2_EL1);
- val &= ~(NV_FTR(MMFR2, BBM) |
- NV_FTR(MMFR2, TTL) |
- GENMASK_ULL(47, 44) |
- NV_FTR(MMFR2, ST) |
- NV_FTR(MMFR2, CCIDX) |
- NV_FTR(MMFR2, VARange));
-
- /* Force TTL support */
- val |= FIELD_PREP(NV_FTR(MMFR2, TTL), 0b0001);
+ val = limit_nv_id_reg(kvm, SYS_ID_AA64MMFR2_EL1, val);
kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR2_EL1, val);
- val = 0;
- if (!cpus_have_final_cap(ARM64_HAS_HCR_NV1))
- val |= FIELD_PREP(NV_FTR(MMFR4, E2H0),
- ID_AA64MMFR4_EL1_E2H0_NI_NV1);
+ val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64MMFR4_EL1);
+ val = limit_nv_id_reg(kvm, SYS_ID_AA64MMFR4_EL1, val);
kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR4_EL1, val);
- /* Only limited support for PMU, Debug, BPs, WPs, and HPMN0 */
val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64DFR0_EL1);
- val &= (NV_FTR(DFR0, PMUVer) |
- NV_FTR(DFR0, WRPs) |
- NV_FTR(DFR0, BRPs) |
- NV_FTR(DFR0, DebugVer) |
- NV_FTR(DFR0, HPMN0));
-
- /* Cap Debug to ARMv8.1 */
- tmp = FIELD_GET(NV_FTR(DFR0, DebugVer), val);
- if (tmp > 0b0111) {
- val &= ~NV_FTR(DFR0, DebugVer);
- val |= FIELD_PREP(NV_FTR(DFR0, DebugVer), 0b0111);
- }
+ val = limit_nv_id_reg(kvm, SYS_ID_AA64DFR0_EL1, val);
kvm_set_vm_id_reg(kvm, SYS_ID_AA64DFR0_EL1, val);
}
--
2.39.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 09/14] KVM: arm64: Move NV-specific capping to idreg sanitisation
2025-02-15 17:38 [PATCH 00/14] KVM: arm64: NV userspace ABI Marc Zyngier
` (7 preceding siblings ...)
2025-02-15 17:38 ` [PATCH 08/14] KVM: arm64: Enforce NV limits on a per-idregs basis Marc Zyngier
@ 2025-02-15 17:38 ` Marc Zyngier
2025-02-15 17:38 ` [PATCH 10/14] KVM: arm64: Allow userspace to limit NV support to nVHE Marc Zyngier
` (5 subsequent siblings)
14 siblings, 0 replies; 23+ messages in thread
From: Marc Zyngier @ 2025-02-15 17:38 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Eric Auger
Instead of applying the NV idreg limits at run time, switch to
doing it at the same time as the reset of the VM initialisation.
This will make things much simpler once we introduce vcpu-driven
variants of NV.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/include/asm/kvm_nested.h | 1 +
arch/arm64/kvm/nested.c | 45 +----------------------------
arch/arm64/kvm/sys_regs.c | 3 ++
3 files changed, 5 insertions(+), 44 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_nested.h b/arch/arm64/include/asm/kvm_nested.h
index 56c4bcd35e2e5..692f403c1896e 100644
--- a/arch/arm64/include/asm/kvm_nested.h
+++ b/arch/arm64/include/asm/kvm_nested.h
@@ -188,6 +188,7 @@ static inline bool kvm_supported_tlbi_s1e2_op(struct kvm_vcpu *vpcu, u32 instr)
}
int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu);
+u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val);
#ifdef CONFIG_ARM64_PTR_AUTH
bool kvm_auth_eretax(struct kvm_vcpu *vcpu, u64 *elr);
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index 2cc82e69ab523..96d1d300e79f9 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -804,7 +804,7 @@ void kvm_arch_flush_shadow_all(struct kvm *kvm)
* This list should get updated as new features get added to the NV
* support, and new extension to the architecture.
*/
-static u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val)
+u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val)
{
switch (reg) {
case SYS_ID_AA64ISAR0_EL1:
@@ -929,47 +929,6 @@ static u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val)
return val;
}
-static void limit_nv_id_regs(struct kvm *kvm)
-{
- u64 val;
-
- val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64ISAR0_EL1);
- val = limit_nv_id_reg(kvm, SYS_ID_AA64ISAR0_EL1, val);
- kvm_set_vm_id_reg(kvm, SYS_ID_AA64ISAR0_EL1, val);
-
- val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64ISAR1_EL1);
- val = limit_nv_id_reg(kvm, SYS_ID_AA64ISAR1_EL1, val);
- kvm_set_vm_id_reg(kvm, SYS_ID_AA64ISAR1_EL1, val);
-
- val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1);
- val = limit_nv_id_reg(kvm, SYS_ID_AA64PFR0_EL1, val);
- kvm_set_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1, val);
-
- val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR1_EL1);
- val = limit_nv_id_reg(kvm, SYS_ID_AA64PFR1_EL1, val);
- kvm_set_vm_id_reg(kvm, SYS_ID_AA64PFR1_EL1, val);
-
- val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64MMFR0_EL1);
- val = limit_nv_id_reg(kvm, SYS_ID_AA64MMFR0_EL1, val);
- kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR0_EL1, val);
-
- val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64MMFR1_EL1);
- val = limit_nv_id_reg(kvm, SYS_ID_AA64MMFR1_EL1, val);
- kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR1_EL1, val);
-
- val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64MMFR2_EL1);
- val = limit_nv_id_reg(kvm, SYS_ID_AA64MMFR2_EL1, val);
- kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR2_EL1, val);
-
- val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64MMFR4_EL1);
- val = limit_nv_id_reg(kvm, SYS_ID_AA64MMFR4_EL1, val);
- kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR4_EL1, val);
-
- val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64DFR0_EL1);
- val = limit_nv_id_reg(kvm, SYS_ID_AA64DFR0_EL1, val);
- kvm_set_vm_id_reg(kvm, SYS_ID_AA64DFR0_EL1, val);
-}
-
u64 kvm_vcpu_apply_reg_masks(const struct kvm_vcpu *vcpu,
enum vcpu_sysreg sr, u64 v)
{
@@ -1014,8 +973,6 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
if (!kvm->arch.sysreg_masks)
return -ENOMEM;
- limit_nv_id_regs(kvm);
-
/* VTTBR_EL2 */
res0 = res1 = 0;
if (!kvm_has_feat_enum(kvm, ID_AA64MMFR1_EL1, VMIDBits, 16))
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 885cdef77d01e..c1e050a58fb2e 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1638,6 +1638,9 @@ static u64 __kvm_read_sanitised_id_reg(const struct kvm_vcpu *vcpu,
break;
}
+ if (vcpu_has_nv(vcpu))
+ val = limit_nv_id_reg(vcpu->kvm, id, val);
+
return val;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 10/14] KVM: arm64: Allow userspace to limit NV support to nVHE
2025-02-15 17:38 [PATCH 00/14] KVM: arm64: NV userspace ABI Marc Zyngier
` (8 preceding siblings ...)
2025-02-15 17:38 ` [PATCH 09/14] KVM: arm64: Move NV-specific capping to idreg sanitisation Marc Zyngier
@ 2025-02-15 17:38 ` Marc Zyngier
2025-02-15 17:38 ` [PATCH 11/14] KVM: arm64: Make ID_AA64MMFR4_EL1.NV_frac writable Marc Zyngier
` (4 subsequent siblings)
14 siblings, 0 replies; 23+ messages in thread
From: Marc Zyngier @ 2025-02-15 17:38 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Eric Auger
NV is hard. No kidding.
In order to make things simpler, we have established that NV would
support two mutually exclusive configurations:
- VHE-only, and supporting recursive virtualisation
- mVHE-only, and not supporting recursive virtualisation
For that purpose, introduce a new vcpu feature flag that denotes
the second configuration. We use this flag to limit the idregs
further.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/include/uapi/asm/kvm.h | 1 +
arch/arm64/kvm/nested.c | 28 ++++++++++++++++++++++++++--
2 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 568bf858f3198..3bcab2a106c98 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -105,6 +105,7 @@ struct kvm_regs {
#define KVM_ARM_VCPU_PTRAUTH_ADDRESS 5 /* VCPU uses address authentication */
#define KVM_ARM_VCPU_PTRAUTH_GENERIC 6 /* VCPU uses generic authentication */
#define KVM_ARM_VCPU_HAS_EL2 7 /* Support nested virtualization */
+#define KVM_ARM_VCPU_HAS_EL2_E2H0 8 /* Limit NV support to E2H RES0 */
struct kvm_vcpu_init {
__u32 target;
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index 96d1d300e79f9..5ec5acb6310e9 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -51,6 +51,10 @@ int kvm_vcpu_init_nested(struct kvm_vcpu *vcpu)
struct kvm_s2_mmu *tmp;
int num_mmus, ret = 0;
+ if (test_bit(KVM_ARM_VCPU_HAS_EL2_E2H0, kvm->arch.vcpu_features) &&
+ !cpus_have_final_cap(ARM64_HAS_HCR_NV1))
+ return -EINVAL;
+
/*
* Let's treat memory allocation failures as benign: If we fail to
* allocate anything, return an error and keep the allocated array
@@ -894,6 +898,9 @@ u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val)
ID_AA64MMFR1_EL1_HPDS |
ID_AA64MMFR1_EL1_VH |
ID_AA64MMFR1_EL1_VMIDBits);
+ /* FEAT_E2H0 implies no VHE */
+ if (test_bit(KVM_ARM_VCPU_HAS_EL2_E2H0, kvm->arch.vcpu_features))
+ val &= ~ID_AA64MMFR1_EL1_VH;
break;
case SYS_ID_AA64MMFR2_EL1:
@@ -909,8 +916,25 @@ u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val)
break;
case SYS_ID_AA64MMFR4_EL1:
- val = SYS_FIELD_PREP_ENUM(ID_AA64MMFR4_EL1, NV_frac, NV2_ONLY);
- val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR4_EL1, E2H0, NI_NV1);
+ /*
+ * You get EITHER
+ *
+ * - FEAT_VHE without FEAT_E2H0
+ * - FEAT_NV limited to FEAT_NV2
+ * - HCR_EL2.NV1 being RES0
+ *
+ * OR
+ *
+ * - FEAT_E2H0 without FEAT_VHE nor FEAT_NV
+ *
+ * Life is too short for anything else.
+ */
+ if (test_bit(KVM_ARM_VCPU_HAS_EL2_E2H0, kvm->arch.vcpu_features)) {
+ val = 0;
+ } else {
+ val = SYS_FIELD_PREP_ENUM(ID_AA64MMFR4_EL1, NV_frac, NV2_ONLY);
+ val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR4_EL1, E2H0, NI_NV1);
+ }
break;
case SYS_ID_AA64DFR0_EL1:
--
2.39.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 11/14] KVM: arm64: Make ID_AA64MMFR4_EL1.NV_frac writable
2025-02-15 17:38 [PATCH 00/14] KVM: arm64: NV userspace ABI Marc Zyngier
` (9 preceding siblings ...)
2025-02-15 17:38 ` [PATCH 10/14] KVM: arm64: Allow userspace to limit NV support to nVHE Marc Zyngier
@ 2025-02-15 17:38 ` Marc Zyngier
2025-02-15 17:38 ` [PATCH 12/14] KVM: arm64: Advertise FEAT_ECV when possible Marc Zyngier
` (3 subsequent siblings)
14 siblings, 0 replies; 23+ messages in thread
From: Marc Zyngier @ 2025-02-15 17:38 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Eric Auger
We want to make sure that it is possible for userspace to configure
whether recursive NV is possible. Make NV_frac writable for that
purpose.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/sys_regs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index c1e050a58fb2e..db7c4e791b99c 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -2669,7 +2669,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
ID_WRITABLE(ID_AA64MMFR3_EL1, (ID_AA64MMFR3_EL1_TCRX |
ID_AA64MMFR3_EL1_S1PIE |
ID_AA64MMFR3_EL1_S1POE)),
- ID_SANITISED(ID_AA64MMFR4_EL1),
+ ID_WRITABLE(ID_AA64MMFR4_EL1, ID_AA64MMFR4_EL1_NV_frac),
ID_UNALLOCATED(7,5),
ID_UNALLOCATED(7,6),
ID_UNALLOCATED(7,7),
--
2.39.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 12/14] KVM: arm64: Advertise FEAT_ECV when possible
2025-02-15 17:38 [PATCH 00/14] KVM: arm64: NV userspace ABI Marc Zyngier
` (10 preceding siblings ...)
2025-02-15 17:38 ` [PATCH 11/14] KVM: arm64: Make ID_AA64MMFR4_EL1.NV_frac writable Marc Zyngier
@ 2025-02-15 17:38 ` Marc Zyngier
2025-02-15 17:38 ` [PATCH 13/14] KVM: arm64: Allow userspace to request KVM_ARM_VCPU_EL2* Marc Zyngier
` (2 subsequent siblings)
14 siblings, 0 replies; 23+ messages in thread
From: Marc Zyngier @ 2025-02-15 17:38 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Eric Auger
We can advertise support for FEAT_ECV if supported on the HW as
long as we limit it to the basic trap bits, and not advertise
CNTPOFF_EL2 support, even if the host has it (the short story
being that CNTPOFF_EL2 is not virtualisable).
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/nested.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index 5ec5acb6310e9..d55c296fcb27a 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -848,14 +848,16 @@ u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val)
break;
case SYS_ID_AA64MMFR0_EL1:
- /* Hide ECV, ExS, Secure Memory */
- val &= ~(ID_AA64MMFR0_EL1_EVC |
- ID_AA64MMFR0_EL1_EXS |
+ /* Hide ExS, Secure Memory */
+ val &= ~(ID_AA64MMFR0_EL1_EXS |
ID_AA64MMFR0_EL1_TGRAN4_2 |
ID_AA64MMFR0_EL1_TGRAN16_2 |
ID_AA64MMFR0_EL1_TGRAN64_2 |
ID_AA64MMFR0_EL1_SNSMEM);
+ /* Hide CNTPOFF if present */
+ val = ID_REG_LIMIT_FIELD_ENUM(val, ID_AA64MMFR0_EL1, ECV, IMP);
+
/* Disallow unsupported S2 page sizes */
switch (PAGE_SIZE) {
case SZ_64K:
--
2.39.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 13/14] KVM: arm64: Allow userspace to request KVM_ARM_VCPU_EL2*
2025-02-15 17:38 [PATCH 00/14] KVM: arm64: NV userspace ABI Marc Zyngier
` (11 preceding siblings ...)
2025-02-15 17:38 ` [PATCH 12/14] KVM: arm64: Advertise FEAT_ECV when possible Marc Zyngier
@ 2025-02-15 17:38 ` Marc Zyngier
2025-02-19 23:19 ` Oliver Upton
2025-02-15 17:38 ` [PATCH 14/14] KVM: arm64: Document NV caps and vcpu flags Marc Zyngier
2025-02-19 23:17 ` [PATCH 00/14] KVM: arm64: NV userspace ABI Oliver Upton
14 siblings, 1 reply; 23+ messages in thread
From: Marc Zyngier @ 2025-02-15 17:38 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Eric Auger
Since we're (almost) feature complete, let's allow userspace to
request KVM_ARM_VCPU_EL2* by bumping KVM_VCPU_MAX_FEATURES up.
We also now advertise the features to userspace with a new capabilities.
It's going to be great...
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/include/asm/kvm_host.h | 2 +-
arch/arm64/kvm/arm.c | 6 ++++++
include/uapi/linux/kvm.h | 2 ++
3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 7cfa024de4e34..2a9ab9abf0f81 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -39,7 +39,7 @@
#define KVM_MAX_VCPUS VGIC_V3_MAX_CPUS
-#define KVM_VCPU_MAX_FEATURES 7
+#define KVM_VCPU_MAX_FEATURES 9
#define KVM_VCPU_VALID_FEATURES (BIT(KVM_VCPU_MAX_FEATURES) - 1)
#define KVM_REQ_SLEEP \
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 4746c6cace2a8..6554379cdcada 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -359,6 +359,12 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_ARM_EL1_32BIT:
r = cpus_have_final_cap(ARM64_HAS_32BIT_EL1);
break;
+ case KVM_CAP_ARM_EL2:
+ r = cpus_have_final_cap(ARM64_HAS_NESTED_VIRT);
+ break;
+ case KVM_CAP_ARM_EL2_E2H0:
+ r = cpus_have_final_cap(ARM64_HAS_HCR_NV1);
+ break;
case KVM_CAP_GUEST_DEBUG_HW_BPS:
r = get_num_brps();
break;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 45e6d8fca9b99..9a6674f51b8be 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -929,6 +929,8 @@ struct kvm_enable_cap {
#define KVM_CAP_PRE_FAULT_MEMORY 236
#define KVM_CAP_X86_APIC_BUS_CYCLES_NS 237
#define KVM_CAP_X86_GUEST_MODE 238
+#define KVM_CAP_ARM_EL2 239
+#define KVM_CAP_ARM_EL2_E2H0 240
struct kvm_irq_routing_irqchip {
__u32 irqchip;
--
2.39.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 14/14] KVM: arm64: Document NV caps and vcpu flags
2025-02-15 17:38 [PATCH 00/14] KVM: arm64: NV userspace ABI Marc Zyngier
` (12 preceding siblings ...)
2025-02-15 17:38 ` [PATCH 13/14] KVM: arm64: Allow userspace to request KVM_ARM_VCPU_EL2* Marc Zyngier
@ 2025-02-15 17:38 ` Marc Zyngier
2025-02-19 23:19 ` Oliver Upton
2025-02-19 23:17 ` [PATCH 00/14] KVM: arm64: NV userspace ABI Oliver Upton
14 siblings, 1 reply; 23+ messages in thread
From: Marc Zyngier @ 2025-02-15 17:38 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Eric Auger
Describe the two new vcpu flags that control NV, together with
the capabilities that advertise them.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
Documentation/virt/kvm/api.rst | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 2b52eb77e29cb..2d7b516ae408d 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -3456,7 +3456,8 @@ The initial values are defined as:
- FPSIMD/NEON registers: set to 0
- SVE registers: set to 0
- System registers: Reset to their architecturally defined
- values as for a warm reset to EL1 (resp. SVC)
+ values as for a warm reset to EL1 (resp. SVC) or EL2 (in the
+ case of EL2 being enabled).
Note that because some registers reflect machine topology, all vcpus
should be created before this ioctl is invoked.
@@ -3523,6 +3524,17 @@ Possible features:
- the KVM_REG_ARM64_SVE_VLS pseudo-register is immutable, and can
no longer be written using KVM_SET_ONE_REG.
+ - KVM_ARM_VCPU_HAS_EL2: Enable Nested Virtualisation support,
+ booting the guest from EL2 instead of EL1.
+ Depends on KVM_CAP_ARM_EL2.
+ The VM is running with HCR_EL2.E2H being RES1 (VHE) unless
+ KVM_ARM_VCPU_HAS_EL2_E2H0 is also set.
+
+ - KVM_ARM_VCPU_HAS_EL2_E2H0: Restrict Nested Virtualisation
+ support to HCR_EL2.E2H being RES0 (non-VHE).
+ Depends on KVM_CAP_ARM_EL2_E2H0.
+ KVM_ARM_VCPU_HAS_EL2 must also be set.
+
4.83 KVM_ARM_PREFERRED_TARGET
-----------------------------
--
2.39.2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH 00/14] KVM: arm64: NV userspace ABI
2025-02-15 17:38 [PATCH 00/14] KVM: arm64: NV userspace ABI Marc Zyngier
` (13 preceding siblings ...)
2025-02-15 17:38 ` [PATCH 14/14] KVM: arm64: Document NV caps and vcpu flags Marc Zyngier
@ 2025-02-19 23:17 ` Oliver Upton
2025-02-20 13:07 ` Marc Zyngier
14 siblings, 1 reply; 23+ messages in thread
From: Oliver Upton @ 2025-02-19 23:17 UTC (permalink / raw)
To: Marc Zyngier
Cc: kvmarm, kvm, linux-arm-kernel, Joey Gouly, Suzuki K Poulose,
Zenghui Yu, Eric Auger
On Sat, Feb 15, 2025 at 05:38:02PM +0000, Marc Zyngier wrote:
> Since the previous incarnation of the ABI was proved to be subtly
> wrong, I have reworked it to be more in line with the current way KVM
> operates.
>
> No more late NV-specific adjustment nor writable ID_AA64MMFR0_EL1.VH.
> The NV configuration is now entirely selected from the vcpu flags.
> I've preserved the KVM_ARM_VCPU_EL2 flag which enables NV with VHE,
> and added KVM_ARM_VCPU_EL2_E2H0 which alters the NV behaviour to only
> allow nVHE guests without recursive NV support.
>
> This series is actually very little new code. The bulk of it is
> converting the feature downgrade to be per-idreg, essentially going
> back to the state before 44241f34fac96 ("KVM: arm64: nv: Use accessors
> for modifying ID registers"), only slightly modernised. This then
> becomes part of the reset value computing.
>
> The rest is simply what you'd expect in terms of being able to write
> the ID_AA64MMFR4_EL1.NV_frac field, making the correct bits RES0 when
> needed, probing for capabilities and handling the init flags.
>
> Patches on top of -rc2, with the integration branch at the usual
> location.
This all looks reasonable to me. NV won't be ready for the limelight
this time around so unless someone shouts I plan on taking the first 12
patches of this series in 6.15.
Thanks,
Oliver
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 13/14] KVM: arm64: Allow userspace to request KVM_ARM_VCPU_EL2*
2025-02-15 17:38 ` [PATCH 13/14] KVM: arm64: Allow userspace to request KVM_ARM_VCPU_EL2* Marc Zyngier
@ 2025-02-19 23:19 ` Oliver Upton
0 siblings, 0 replies; 23+ messages in thread
From: Oliver Upton @ 2025-02-19 23:19 UTC (permalink / raw)
To: Marc Zyngier
Cc: kvmarm, kvm, linux-arm-kernel, Joey Gouly, Suzuki K Poulose,
Zenghui Yu, Eric Auger
On Sat, Feb 15, 2025 at 05:38:15PM +0000, Marc Zyngier wrote:
> Since we're (almost) feature complete, let's allow userspace to
> request KVM_ARM_VCPU_EL2* by bumping KVM_VCPU_MAX_FEATURES up.
>
> We also now advertise the features to userspace with a new capabilities.
>
> It's going to be great...
>
> Signed-off-by: Marc Zyngier <maz@kernel.org>
Reviewed-by: Oliver Upton <oliver.upton@linux.dev>
Thanks,
Oliver
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 14/14] KVM: arm64: Document NV caps and vcpu flags
2025-02-15 17:38 ` [PATCH 14/14] KVM: arm64: Document NV caps and vcpu flags Marc Zyngier
@ 2025-02-19 23:19 ` Oliver Upton
0 siblings, 0 replies; 23+ messages in thread
From: Oliver Upton @ 2025-02-19 23:19 UTC (permalink / raw)
To: Marc Zyngier
Cc: kvmarm, kvm, linux-arm-kernel, Joey Gouly, Suzuki K Poulose,
Zenghui Yu, Eric Auger
On Sat, Feb 15, 2025 at 05:38:16PM +0000, Marc Zyngier wrote:
> Describe the two new vcpu flags that control NV, together with
> the capabilities that advertise them.
>
> Signed-off-by: Marc Zyngier <maz@kernel.org>
Reviewed-by: Oliver Upton <oliver.upton@linux.dev>
Thanks,
Oliver
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 00/14] KVM: arm64: NV userspace ABI
2025-02-19 23:17 ` [PATCH 00/14] KVM: arm64: NV userspace ABI Oliver Upton
@ 2025-02-20 13:07 ` Marc Zyngier
0 siblings, 0 replies; 23+ messages in thread
From: Marc Zyngier @ 2025-02-20 13:07 UTC (permalink / raw)
To: Oliver Upton
Cc: kvmarm, kvm, linux-arm-kernel, Joey Gouly, Suzuki K Poulose,
Zenghui Yu, Eric Auger
On Wed, 19 Feb 2025 23:17:31 +0000,
Oliver Upton <oliver.upton@linux.dev> wrote:
>
> On Sat, Feb 15, 2025 at 05:38:02PM +0000, Marc Zyngier wrote:
> > Since the previous incarnation of the ABI was proved to be subtly
> > wrong, I have reworked it to be more in line with the current way KVM
> > operates.
> >
> > No more late NV-specific adjustment nor writable ID_AA64MMFR0_EL1.VH.
> > The NV configuration is now entirely selected from the vcpu flags.
> > I've preserved the KVM_ARM_VCPU_EL2 flag which enables NV with VHE,
> > and added KVM_ARM_VCPU_EL2_E2H0 which alters the NV behaviour to only
> > allow nVHE guests without recursive NV support.
> >
> > This series is actually very little new code. The bulk of it is
> > converting the feature downgrade to be per-idreg, essentially going
> > back to the state before 44241f34fac96 ("KVM: arm64: nv: Use accessors
> > for modifying ID registers"), only slightly modernised. This then
> > becomes part of the reset value computing.
> >
> > The rest is simply what you'd expect in terms of being able to write
> > the ID_AA64MMFR4_EL1.NV_frac field, making the correct bits RES0 when
> > needed, probing for capabilities and handling the init flags.
> >
> > Patches on top of -rc2, with the integration branch at the usual
> > location.
>
> This all looks reasonable to me. NV won't be ready for the limelight
> this time around so unless someone shouts I plan on taking the first 12
> patches of this series in 6.15.
Let me repost it first, as I fixed an embarrassing bug that led to
mishandling of ID_UNALLOCATED() registers (solved by consolidating the
ID_DESC() macro maze a bit further).
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 03/14] KVM: arm64: Mark HCR.EL2.E2H RES0 when ID_AA64MMFR1_EL1.VH is zero
2025-02-15 17:38 ` [PATCH 03/14] KVM: arm64: Mark HCR.EL2.E2H RES0 when ID_AA64MMFR1_EL1.VH is zero Marc Zyngier
@ 2025-02-24 7:39 ` Aneesh Kumar K.V
2025-02-24 8:32 ` Marc Zyngier
0 siblings, 1 reply; 23+ messages in thread
From: Aneesh Kumar K.V @ 2025-02-24 7:39 UTC (permalink / raw)
To: Marc Zyngier, kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Eric Auger
Marc Zyngier <maz@kernel.org> writes:
> Enforce HCR_EL2.E2H being RES0 when VHE is disabled, so that we can
> actually rely on that bit never being flipped behind our back.
>
> Signed-off-by: Marc Zyngier <maz@kernel.org>
> ---
> arch/arm64/kvm/nested.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
> index 0c9387d2f5070..ed3add7d32f66 100644
> --- a/arch/arm64/kvm/nested.c
> +++ b/arch/arm64/kvm/nested.c
> @@ -1034,6 +1034,8 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
> res0 |= (HCR_TEA | HCR_TERR);
> if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, LO, IMP))
> res0 |= HCR_TLOR;
> + if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, VH, IMP))
> + res0 |= HCR_E2H;
> if (!kvm_has_feat(kvm, ID_AA64MMFR4_EL1, E2H0, IMP))
> res1 |= HCR_E2H;
>
Does it make sense to check for E2H0 if MMFR1_EL1.VH == 0 ?
Should the above check be
if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, VH, IMP))
res0 |= HCR_E2H;
else if (!kvm_has_feat(kvm, ID_AA64MMFR4_EL1, E2H0, IMP))
res1 |= HCR_E2H;
> set_sysreg_masks(kvm, HCR_EL2, res0, res1);
> --
> 2.39.2
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 01/14] arm64: cpufeature: Handle NV_frac as a synonym of NV2
2025-02-15 17:38 ` [PATCH 01/14] arm64: cpufeature: Handle NV_frac as a synonym of NV2 Marc Zyngier
@ 2025-02-24 7:41 ` Aneesh Kumar K.V
2025-02-24 8:26 ` Marc Zyngier
0 siblings, 1 reply; 23+ messages in thread
From: Aneesh Kumar K.V @ 2025-02-24 7:41 UTC (permalink / raw)
To: Marc Zyngier, kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Eric Auger
Marc Zyngier <maz@kernel.org> writes:
> With ARMv9.5, an implementation supporting Nested Virtualization
> is allowed to only support NV2, and to avoid supporting the old
> (and useless) ARMv8.3 variant.
>
> This is indicated by ID_AA64MMFR2_EL1.NV being 0 (as if NV wasn't
> implemented) and ID_AA64MMDR4_EL1.NV_frac being 1 (indicating that
^ F
The register name is wrong there.
> NV2 is actually supported).
>
-aneesh
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 01/14] arm64: cpufeature: Handle NV_frac as a synonym of NV2
2025-02-24 7:41 ` Aneesh Kumar K.V
@ 2025-02-24 8:26 ` Marc Zyngier
0 siblings, 0 replies; 23+ messages in thread
From: Marc Zyngier @ 2025-02-24 8:26 UTC (permalink / raw)
To: Aneesh Kumar K.V
Cc: kvmarm, kvm, linux-arm-kernel, Joey Gouly, Suzuki K Poulose,
Oliver Upton, Zenghui Yu, Eric Auger
On Mon, 24 Feb 2025 07:41:18 +0000,
Aneesh Kumar K.V <aneesh.kumar@kernel.org> wrote:
>
> Marc Zyngier <maz@kernel.org> writes:
>
> > With ARMv9.5, an implementation supporting Nested Virtualization
> > is allowed to only support NV2, and to avoid supporting the old
> > (and useless) ARMv8.3 variant.
> >
> > This is indicated by ID_AA64MMFR2_EL1.NV being 0 (as if NV wasn't
> > implemented) and ID_AA64MMDR4_EL1.NV_frac being 1 (indicating that
> ^ F
> The register name is wrong there.
Already reported by Joey on v2 of this series.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 03/14] KVM: arm64: Mark HCR.EL2.E2H RES0 when ID_AA64MMFR1_EL1.VH is zero
2025-02-24 7:39 ` Aneesh Kumar K.V
@ 2025-02-24 8:32 ` Marc Zyngier
0 siblings, 0 replies; 23+ messages in thread
From: Marc Zyngier @ 2025-02-24 8:32 UTC (permalink / raw)
To: Aneesh Kumar K.V
Cc: kvmarm, kvm, linux-arm-kernel, Joey Gouly, Suzuki K Poulose,
Oliver Upton, Zenghui Yu, Eric Auger
On Mon, 24 Feb 2025 07:39:30 +0000,
Aneesh Kumar K.V <aneesh.kumar@kernel.org> wrote:
>
> Marc Zyngier <maz@kernel.org> writes:
>
> > Enforce HCR_EL2.E2H being RES0 when VHE is disabled, so that we can
> > actually rely on that bit never being flipped behind our back.
> >
> > Signed-off-by: Marc Zyngier <maz@kernel.org>
> > ---
> > arch/arm64/kvm/nested.c | 2 ++
> > 1 file changed, 2 insertions(+)
> >
> > diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
> > index 0c9387d2f5070..ed3add7d32f66 100644
> > --- a/arch/arm64/kvm/nested.c
> > +++ b/arch/arm64/kvm/nested.c
> > @@ -1034,6 +1034,8 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
> > res0 |= (HCR_TEA | HCR_TERR);
> > if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, LO, IMP))
> > res0 |= HCR_TLOR;
> > + if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, VH, IMP))
> > + res0 |= HCR_E2H;
> > if (!kvm_has_feat(kvm, ID_AA64MMFR4_EL1, E2H0, IMP))
> > res1 |= HCR_E2H;
> >
>
> Does it make sense to check for E2H0 if MMFR1_EL1.VH == 0 ?
> Should the above check be
> if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, VH, IMP))
> res0 |= HCR_E2H;
> else if (!kvm_has_feat(kvm, ID_AA64MMFR4_EL1, E2H0, IMP))
> res1 |= HCR_E2H;
What difference does it make? This bit can only have a reserved value,
and can never be actively modified. If you *really* wanted to optimise
this for reasons that I really cannot fathom, you could have this:
if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, VH, IMP))
res0 |= HCR_E2H;
else
res1 |= HCR_E2H;
because that's what we really implement.
Does it matter? I don't think so. If anything, I'd rather we keep the
code as is and have a run-time warning if a bit is simultaneously RES0
and RES1, because that'd be indicative of a much bigger problem.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2025-02-24 8:45 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-15 17:38 [PATCH 00/14] KVM: arm64: NV userspace ABI Marc Zyngier
2025-02-15 17:38 ` [PATCH 01/14] arm64: cpufeature: Handle NV_frac as a synonym of NV2 Marc Zyngier
2025-02-24 7:41 ` Aneesh Kumar K.V
2025-02-24 8:26 ` Marc Zyngier
2025-02-15 17:38 ` [PATCH 02/14] KVM: arm64: Hide ID_AA64MMFR2_EL1.NV from guest and userspace Marc Zyngier
2025-02-15 17:38 ` [PATCH 03/14] KVM: arm64: Mark HCR.EL2.E2H RES0 when ID_AA64MMFR1_EL1.VH is zero Marc Zyngier
2025-02-24 7:39 ` Aneesh Kumar K.V
2025-02-24 8:32 ` Marc Zyngier
2025-02-15 17:38 ` [PATCH 04/14] KVM: arm64: Mark HCR.EL2.{NV*,AT} RES0 when ID_AA64MMFR4_EL1.NV_frac is 0 Marc Zyngier
2025-02-15 17:38 ` [PATCH 05/14] KVM: arm64: Advertise NV2 in the boot messages Marc Zyngier
2025-02-15 17:38 ` [PATCH 06/14] KVM: arm64: Consolidate idreg reset method Marc Zyngier
2025-02-15 17:38 ` [PATCH 07/14] KVM: arm64: Make ID_REG_LIMIT_FIELD_ENUM() more widely available Marc Zyngier
2025-02-15 17:38 ` [PATCH 08/14] KVM: arm64: Enforce NV limits on a per-idregs basis Marc Zyngier
2025-02-15 17:38 ` [PATCH 09/14] KVM: arm64: Move NV-specific capping to idreg sanitisation Marc Zyngier
2025-02-15 17:38 ` [PATCH 10/14] KVM: arm64: Allow userspace to limit NV support to nVHE Marc Zyngier
2025-02-15 17:38 ` [PATCH 11/14] KVM: arm64: Make ID_AA64MMFR4_EL1.NV_frac writable Marc Zyngier
2025-02-15 17:38 ` [PATCH 12/14] KVM: arm64: Advertise FEAT_ECV when possible Marc Zyngier
2025-02-15 17:38 ` [PATCH 13/14] KVM: arm64: Allow userspace to request KVM_ARM_VCPU_EL2* Marc Zyngier
2025-02-19 23:19 ` Oliver Upton
2025-02-15 17:38 ` [PATCH 14/14] KVM: arm64: Document NV caps and vcpu flags Marc Zyngier
2025-02-19 23:19 ` Oliver Upton
2025-02-19 23:17 ` [PATCH 00/14] KVM: arm64: NV userspace ABI Oliver Upton
2025-02-20 13:07 ` Marc Zyngier
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).