Skip to contentSkip to conversation

KVM/arm64: Minor/trivial fixes from pKVM mega-patch

PATCH Applied Will Deacon 3 participants 10 messages Jun 9, 2022 – Jun 14, 2022

Subsystems (3)
lore
Share & tools
lore

Will Deacon

author maintainer
#0 lore raw

cover KVM/arm64: Minor/trivial fixes from pKVM mega-patch

Hi folks,

These six KVM/arm64 patches are very minor fixes (including "fixes" to comments) which were previously posted as part of the pKVM mega-patch but which can be merged independently of the rest of that. Marc -- I'm not sure whether it's even worth taking these for 5.19, but here they are so you can have a look and decide yourself.

Series based on 5.19-rc1.

Cheers,

Will

--->8

Marc Zyngier (2):
KVM: arm64: Handle all ID registers trapped for a protected VM
KVM: arm64: Drop stale comment

Will Deacon (4):
KVM: arm64: Return error from kvm_arch_init_vm() on allocation failure
KVM: arm64: Ignore 'kvm-arm.mode=protected' when using VHE
KVM: arm64: Extend comment in has_vhe()
KVM: arm64: Remove redundant hyp_assert_lock_held() assertions

 .../admin-guide/kernel-parameters.txt         |  1 -
 arch/arm64/include/asm/kvm_host.h             |  5 ---
 arch/arm64/include/asm/virt.h                 |  3 ++
 arch/arm64/kernel/cpufeature.c                | 10 +----
 arch/arm64/kvm/arm.c                          | 10 ++++-
 arch/arm64/kvm/hyp/nvhe/mem_protect.c         |  4 --
 arch/arm64/kvm/hyp/nvhe/sys_regs.c            | 42 +++++++++++++++----
 7 files changed, 46 insertions(+), 29 deletions(-)
Signature · 6 lines
2.36.1.255.ge46751e96f-goog

_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
author maintainer
#1 lore raw

PATCH 1/6 KVM: arm64: Return error from kvm_arch_init_vm() on allocation failure

If we fail to allocate the 'supported_cpus' cpumask in kvm_arch_init_vm() then be sure to return -ENOMEM instead of success (0) on the failure path.

---
 arch/arm64/kvm/arm.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
arch/arm64/kvm/arm.c +3 -1
index 400bb0fe2745..0da0f06037db 100644
@@ -150,8 +150,10 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 	if (ret)
 		goto out_free_stage2_pgd;
 
-	if (!zalloc_cpumask_var(&kvm->arch.supported_cpus, GFP_KERNEL))
+	if (!zalloc_cpumask_var(&kvm->arch.supported_cpus, GFP_KERNEL)) {
+		ret = -ENOMEM;
 		goto out_free_stage2_pgd;
+	}
 	cpumask_copy(kvm->arch.supported_cpus, cpu_possible_mask);
 
 	kvm_vgic_early_init(kvm);
Signature · 6 lines
2.36.1.255.ge46751e96f-goog

_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
author maintainer
#2 lore raw

PATCH 2/6 KVM: arm64: Handle all ID registers trapped for a protected VM

In reply to Will Deacon

From: Marc Zyngier <[email protected]>

A protected VM accessing ID_AA64ISAR2_EL1 gets punished with an UNDEF, while it really should only get a zero back if the register is not handled by the hypervisor emulation (as mandated by the architecture).

Introduce all the missing ID registers (including the unallocated ones), and have them to return 0.

---
 arch/arm64/kvm/hyp/nvhe/sys_regs.c | 42 ++++++++++++++++++++++++------
 1 file changed, 34 insertions(+), 8 deletions(-)
arch/arm64/kvm/hyp/nvhe/sys_regs.c +34 -8
index b6d86e423319..35a4331ba5f3 100644
@@ -243,15 +243,9 @@ u64 pvm_read_id_reg(const struct kvm_vcpu *vcpu, u32 id)
 	case SYS_ID_AA64MMFR2_EL1:
 		return get_pvm_id_aa64mmfr2(vcpu);
 	default:
-		/*
-		 * Should never happen because all cases are covered in
-		 * pvm_sys_reg_descs[].
-		 */
-		WARN_ON(1);
-		break;
+		/* Unhandled ID register, RAZ */
+		return 0;
 	}
-
-	return 0;
 }
 
 static u64 read_id_reg(const struct kvm_vcpu *vcpu,
@@ -332,6 +326,16 @@ static bool pvm_gic_read_sre(struct kvm_vcpu *vcpu,
 /* Mark the specified system register as an AArch64 feature id register. */
 #define AARCH64(REG) { SYS_DESC(REG), .access = pvm_access_id_aarch64 }
 
+/*
+ * sys_reg_desc initialiser for architecturally unallocated cpufeature ID
+ * register with encoding Op0=3, Op1=0, CRn=0, CRm=crm, Op2=op2
+ * (1 <= crm < 8, 0 <= Op2 < 8).
+ */
+#define ID_UNALLOCATED(crm, op2) {			\
+	Op0(3), Op1(0), CRn(0), CRm(crm), Op2(op2),	\
+	.access = pvm_access_id_aarch64,		\
+}
+
 /* Mark the specified system register as Read-As-Zero/Write-Ignored */
 #define RAZ_WI(REG) { SYS_DESC(REG), .access = pvm_access_raz_wi }
 
@@ -375,24 +379,46 @@ static const struct sys_reg_desc pvm_sys_reg_descs[] = {
 	AARCH32(SYS_MVFR0_EL1),
 	AARCH32(SYS_MVFR1_EL1),
 	AARCH32(SYS_MVFR2_EL1),
+	ID_UNALLOCATED(3,3),
 	AARCH32(SYS_ID_PFR2_EL1),
 	AARCH32(SYS_ID_DFR1_EL1),
 	AARCH32(SYS_ID_MMFR5_EL1),
+	ID_UNALLOCATED(3,7),
 
 	/* AArch64 ID registers */
 	/* CRm=4 */
 	AARCH64(SYS_ID_AA64PFR0_EL1),
 	AARCH64(SYS_ID_AA64PFR1_EL1),
+	ID_UNALLOCATED(4,2),
+	ID_UNALLOCATED(4,3),
 	AARCH64(SYS_ID_AA64ZFR0_EL1),
+	ID_UNALLOCATED(4,5),
+	ID_UNALLOCATED(4,6),
+	ID_UNALLOCATED(4,7),
 	AARCH64(SYS_ID_AA64DFR0_EL1),
 	AARCH64(SYS_ID_AA64DFR1_EL1),
+	ID_UNALLOCATED(5,2),
+	ID_UNALLOCATED(5,3),
 	AARCH64(SYS_ID_AA64AFR0_EL1),
 	AARCH64(SYS_ID_AA64AFR1_EL1),
+	ID_UNALLOCATED(5,6),
+	ID_UNALLOCATED(5,7),
 	AARCH64(SYS_ID_AA64ISAR0_EL1),
 	AARCH64(SYS_ID_AA64ISAR1_EL1),
+	AARCH64(SYS_ID_AA64ISAR2_EL1),
+	ID_UNALLOCATED(6,3),
+	ID_UNALLOCATED(6,4),
+	ID_UNALLOCATED(6,5),
+	ID_UNALLOCATED(6,6),
+	ID_UNALLOCATED(6,7),
 	AARCH64(SYS_ID_AA64MMFR0_EL1),
 	AARCH64(SYS_ID_AA64MMFR1_EL1),
 	AARCH64(SYS_ID_AA64MMFR2_EL1),
+	ID_UNALLOCATED(7,3),
+	ID_UNALLOCATED(7,4),
+	ID_UNALLOCATED(7,5),
+	ID_UNALLOCATED(7,6),
+	ID_UNALLOCATED(7,7),
 
 	/* Scalable Vector Registers are restricted. */
 
Signature · 6 lines
2.36.1.255.ge46751e96f-goog

_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Reviewed-by on v1 2/6
#3 lore raw

Re: [PATCH 2/6] KVM: arm64: Handle all ID registers trapped for a protected VM

Quoted 7 lines · Will Deacon

From: Marc Zyngier <[email protected]>

A protected VM accessing ID_AA64ISAR2_EL1 gets punished with an UNDEF, while it really should only get a zero back if the register is not handled by the hypervisor emulation (as mandated by the architecture).

Quoted 5 lines

Introduce all the missing ID registers (including the unallocated ones), and have them to return 0.

_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

author maintainer
#4 lore raw

PATCH 3/6 KVM: arm64: Ignore 'kvm-arm.mode=protected' when using VHE

In reply to Will Deacon

Ignore 'kvm-arm.mode=protected' when using VHE so that kvm_get_mode() only returns KVM_MODE_PROTECTED on systems where the feature is available.

---
 Documentation/admin-guide/kernel-parameters.txt |  1 -
 arch/arm64/kernel/cpufeature.c                  | 10 +---------
 arch/arm64/kvm/arm.c                            |  6 +++++-
 3 files changed, 6 insertions(+), 11 deletions(-)
Documentation/admin-guide/kernel-parameters.txt +0 -1
index 8090130b544b..97c16aa2f53f 100644
@@ -2469,7 +2469,6 @@
 
 			protected: nVHE-based mode with support for guests whose
 				   state is kept private from the host.
-				   Not valid if the kernel is running in EL2.
 
 			Defaults to VHE/nVHE based on hardware support. Setting
 			mode to "protected" will disable kexec and hibernation
arch/arm64/kernel/cpufeature.c +1 -9
index 42ea2bd856c6..79fac13ab2ef 100644
@@ -1974,15 +1974,7 @@ static void cpu_enable_mte(struct arm64_cpu_capabilities const *cap)
 #ifdef CONFIG_KVM
 static bool is_kvm_protected_mode(const struct arm64_cpu_capabilities *entry, int __unused)
 {
-	if (kvm_get_mode() != KVM_MODE_PROTECTED)
-		return false;
-
-	if (is_kernel_in_hyp_mode()) {
-		pr_warn("Protected KVM not available with VHE\n");
-		return false;
-	}
-
-	return true;
+	return kvm_get_mode() == KVM_MODE_PROTECTED;
 }
 #endif /* CONFIG_KVM */
 
arch/arm64/kvm/arm.c +5 -1
index 0da0f06037db..a0188144a122 100644
@@ -2273,7 +2273,11 @@ static int __init early_kvm_mode_cfg(char *arg)
 		return -EINVAL;
 
 	if (strcmp(arg, "protected") == 0) {
-		kvm_mode = KVM_MODE_PROTECTED;
+		if (!is_kernel_in_hyp_mode())
+			kvm_mode = KVM_MODE_PROTECTED;
+		else
+			pr_warn_once("Protected KVM not available with VHE\n");
+
 		return 0;
 	}
 
Signature · 6 lines
2.36.1.255.ge46751e96f-goog

_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
author maintainer
#5 lore raw

PATCH 4/6 KVM: arm64: Extend comment in has_vhe()

In reply to Will Deacon

has_vhe() expands to a compile-time constant when evaluated from the VHE or nVHE code, alternatively checking a static key when called from elsewhere in the kernel. On face value, this looks like a case of premature optimization, but in fact this allows symbol references on VHE-specific code paths to be dropped from the nVHE object.

Expand the comment in has_vhe() to make this clearer, hopefully discouraging anybody from simplifying the code.

---
 arch/arm64/include/asm/virt.h | 3 +++
 1 file changed, 3 insertions(+)
arch/arm64/include/asm/virt.h +3 -0
index 3c8af033a997..0e80db4327b6 100644
@@ -113,6 +113,9 @@ static __always_inline bool has_vhe(void)
 	/*
 	 * Code only run in VHE/NVHE hyp context can assume VHE is present or
 	 * absent. Otherwise fall back to caps.
+	 * This allows the compiler to discard VHE-specific code from the
+	 * nVHE object, reducing the number of external symbol references
+	 * needed to link.
 	 */
 	if (is_vhe_hyp_code())
 		return true;
Signature · 6 lines
2.36.1.255.ge46751e96f-goog

_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
author maintainer
#6 lore raw

PATCH 5/6 KVM: arm64: Remove redundant hyp_assert_lock_held() assertions

In reply to Will Deacon

host_stage2_try() asserts that the KVM host lock is held, so there's no need to duplicate the assertion in its wrappers.

---
 arch/arm64/kvm/hyp/nvhe/mem_protect.c | 4 ----
 1 file changed, 4 deletions(-)
arch/arm64/kvm/hyp/nvhe/mem_protect.c +0 -4
index 78edf077fa3b..1e78acf9662e 100644
@@ -314,15 +314,11 @@ static int host_stage2_adjust_range(u64 addr, struct kvm_mem_range *range)
 int host_stage2_idmap_locked(phys_addr_t addr, u64 size,
 			     enum kvm_pgtable_prot prot)
 {
-	hyp_assert_lock_held(&host_kvm.lock);
-
 	return host_stage2_try(__host_stage2_idmap, addr, addr + size, prot);
 }
 
 int host_stage2_set_owner_locked(phys_addr_t addr, u64 size, u8 owner_id)
 {
-	hyp_assert_lock_held(&host_kvm.lock);
-
 	return host_stage2_try(kvm_pgtable_stage2_set_owner, &host_kvm.pgt,
 			       addr, size, &host_s2_pool, owner_id);
 }
Signature · 6 lines
2.36.1.255.ge46751e96f-goog

_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
author maintainer
#7 lore raw

PATCH 6/6 KVM: arm64: Drop stale comment

In reply to Will Deacon

From: Marc Zyngier <[email protected]>

The layout of 'struct kvm_vcpu_arch' has evolved significantly since the initial port of KVM/arm64, so remove the stale comment suggesting that a prefix of the structure is used exclusively from assembly code.

---
 arch/arm64/include/asm/kvm_host.h | 5 -----
 1 file changed, 5 deletions(-)
arch/arm64/include/asm/kvm_host.h +0 -5
index 47a1e25e25bb..de32152cea04 100644
@@ -362,11 +362,6 @@ struct kvm_vcpu_arch {
 	struct arch_timer_cpu timer_cpu;
 	struct kvm_pmu pmu;
 
-	/*
-	 * Anything that is not used directly from assembly code goes
-	 * here.
-	 */
-
 	/*
 	 * Guest registers we preserve during guest debugging.
 	 *
Signature · 6 lines
2.36.1.255.ge46751e96f-goog

_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
maintainer
#8 lore raw
In reply to Will Deacon
Quoted 8 lines · Will Deacon

Hi folks,

These six KVM/arm64 patches are very minor fixes (including "fixes" to comments) which were previously posted as part of the pKVM mega-patch but which can be merged independently of the rest of that. Marc -- I'm not sure whether it's even worth taking these for 5.19, but here they are so you can have a look and decide yourself.

They are all tragically simple, and patch 2 actually qualifies as a fix (a legitimate guest would fail to run correctly).

Also, the pKVM series could do with a bit of diet, so I'm inclined to take these in right now.

	M.
Signature · 5 lines
Without deviation from the norm, progress is not possible.
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
maintainer Applied
#9 lore raw
In reply to Will Deacon
Quoted 9 lines · Will Deacon

These six KVM/arm64 patches are very minor fixes (including "fixes" to comments) which were previously posted as part of the pKVM mega-patch but which can be merged independently of the rest of that. Marc -- I'm not sure whether it's even worth taking these for 5.19, but here they are so you can have a look and decide yourself.

Series based on 5.19-rc1.

[...]

Applied to fixes, thanks!

[1/6] KVM: arm64: Return error from kvm_arch_init_vm() on allocation failure

      commit: ae187fec75aa670a551d9662f83e3947d3f02a69
[2/6] KVM: arm64: Handle all ID registers trapped for a protected VM
      commit: fa7a17214488ef7df347dcd1a5594f69ea17f4dc
[3/6] KVM: arm64: Ignore 'kvm-arm.mode=protected' when using VHE
      commit: cde5042adf11b0a30a6ce0ec3d071afcf8d2efaf
[4/6] KVM: arm64: Extend comment in has_vhe()
      commit: 112f3bab41113dc53b4f35e9034b2208245bc002
[5/6] KVM: arm64: Remove redundant hyp_assert_lock_held() assertions
      commit: 5879c97f37022ff22a3f13174c24fcf2807fdbc0
[6/6] KVM: arm64: Drop stale comment
      commit: bcbfb588cf323929ac46767dd14e392016bbce04

Cheers,

	M.
Signature · 6 lines
Marc Zyngier <[email protected]>

_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm