linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] KVM: arm64: Disable OS double lock visibility by default and ignore VMM writes
@ 2024-08-08 12:57 Shameer Kolothum
  2024-08-08 17:39 ` Oliver Upton
  0 siblings, 1 reply; 6+ messages in thread
From: Shameer Kolothum @ 2024-08-08 12:57 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: maz, will, catalin.marinas, oliver.upton, james.morse,
	suzuki.poulose, yuzenghui, wangzhou1, linuxarm

KVM exposes the OS double lock feature bit to Guests but returns
RAZ/WI on Guest OSDLR_EL1 access. Make sure we are hiding OS double
lock from Guests now. However we can't hide DoubleLock if the reported
DebugVer is < 8.2. So report a minimum DebugVer of 8.2 to Guests.

All this may break migration from the older kernels. Take care of
that by ignoring VMM writes for these values.

Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
Note:
 - I am not very sure on reporting DebugVer a min of 8.2. Hopefully this is
   fine. Please let me know.
   
Thanks,
Shameer
---  
 arch/arm64/kvm/sys_regs.c | 36 ++++++++++++++++++++++++++++++++----
 1 file changed, 32 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index c90324060436..06e57d7730d8 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1704,13 +1704,14 @@ static u64 read_sanitised_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
 	return val;
 }
 
-#define ID_REG_LIMIT_FIELD_ENUM(val, reg, field, limit)			       \
+#define ID_REG_LIMIT_FIELD_ENUM(val, reg, field, min_val, max_val)	       \
 ({									       \
 	u64 __f_val = FIELD_GET(reg##_##field##_MASK, val);		       \
+	(__f_val) = max_t(u64, __f_val, SYS_FIELD_VALUE(reg, field, min_val)); \
 	(val) &= ~reg##_##field##_MASK;					       \
 	(val) |= FIELD_PREP(reg##_##field##_MASK,			       \
 			    min(__f_val,				       \
-				(u64)SYS_FIELD_VALUE(reg, field, limit)));     \
+				(u64)SYS_FIELD_VALUE(reg, field, max_val)));   \
 	(val);								       \
 })
 
@@ -1719,7 +1720,7 @@ static u64 read_sanitised_id_aa64dfr0_el1(struct kvm_vcpu *vcpu,
 {
 	u64 val = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
 
-	val = ID_REG_LIMIT_FIELD_ENUM(val, ID_AA64DFR0_EL1, DebugVer, V8P8);
+	val = ID_REG_LIMIT_FIELD_ENUM(val, ID_AA64DFR0_EL1, DebugVer, V8P2, V8P8);
 
 	/*
 	 * Only initialize the PMU version if the vCPU was configured with one.
@@ -1732,6 +1733,10 @@ static u64 read_sanitised_id_aa64dfr0_el1(struct kvm_vcpu *vcpu,
 	/* Hide SPE from guests */
 	val &= ~ID_AA64DFR0_EL1_PMSVer_MASK;
 
+	/* Hide DoubleLock from guests */
+	val &= ~ID_AA64DFR0_EL1_DoubleLock_MASK;
+	val |= SYS_FIELD_PREP_ENUM(ID_AA64DFR0_EL1, DoubleLock, NI);
+
 	return val;
 }
 
@@ -1739,6 +1744,7 @@ static int set_id_aa64dfr0_el1(struct kvm_vcpu *vcpu,
 			       const struct sys_reg_desc *rd,
 			       u64 val)
 {
+	u64 hw_val = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
 	u8 debugver = SYS_FIELD_GET(ID_AA64DFR0_EL1, DebugVer, val);
 	u8 pmuver = SYS_FIELD_GET(ID_AA64DFR0_EL1, PMUVer, val);
 
@@ -1765,6 +1771,28 @@ static int set_id_aa64dfr0_el1(struct kvm_vcpu *vcpu,
 	 */
 	if (debugver < ID_AA64DFR0_EL1_DebugVer_IMP)
 		return -EINVAL;
+	else if (debugver < ID_AA64DFR0_EL1_DebugVer_V8P2) {
+		/*
+		 * KVM now reports a minimum DebugVer 8.2 to Guests. In order to keep
+		 * the migration working from old kernels, check and ignore the VMM
+		 * write.
+		 */
+		if ((hw_val & ID_AA64DFR0_EL1_DebugVer_MASK) ==
+		    (val & ID_AA64DFR0_EL1_DebugVer_MASK)) {
+			val &= ~ID_AA64DFR0_EL1_DebugVer_MASK;
+			val |= SYS_FIELD_PREP_ENUM(ID_AA64DFR0_EL1, DebugVer, V8P2);
+		}
+	}
+	/*
+	 * KVM used to expose OS double lock feature bit to Guests but returned
+	 * RAZ/WI on Guest OSDLR_EL1 access. We are hiding OS double lock now.
+	 * But for migration from old kernels to work ignore the VMM write.
+	 */
+	if ((hw_val & ID_AA64DFR0_EL1_DoubleLock_MASK) ==
+	    (val & ID_AA64DFR0_EL1_DoubleLock_MASK)) {
+		val &= ~ID_AA64DFR0_EL1_DoubleLock_MASK;
+		val |= SYS_FIELD_PREP_ENUM(ID_AA64DFR0_EL1, DoubleLock, NI);
+	}
 
 	return set_id_reg(vcpu, rd, val);
 }
@@ -1779,7 +1807,7 @@ static u64 read_sanitised_id_dfr0_el1(struct kvm_vcpu *vcpu,
 	if (kvm_vcpu_has_pmu(vcpu))
 		val |= SYS_FIELD_PREP(ID_DFR0_EL1, PerfMon, perfmon);
 
-	val = ID_REG_LIMIT_FIELD_ENUM(val, ID_DFR0_EL1, CopDbg, Debugv8p8);
+	val = ID_REG_LIMIT_FIELD_ENUM(val, ID_DFR0_EL1, CopDbg, NI, Debugv8p8);
 
 	return val;
 }
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2024-08-08 23:20 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-08 12:57 [PATCH] KVM: arm64: Disable OS double lock visibility by default and ignore VMM writes Shameer Kolothum
2024-08-08 17:39 ` Oliver Upton
2024-08-08 18:10   ` Shameerali Kolothum Thodi
2024-08-08 18:31     ` Oliver Upton
2024-08-08 18:38       ` Shameerali Kolothum Thodi
2024-08-08 23:19         ` Oliver Upton

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