Skip to contentSkip to conversation

arm64: KVM: Kiss hyp_alternate_select() goodbye

PATCH In review Marc Zyngier 3 participants 6 messages Sep 1, 2019 – Sep 2, 2019

Subsystems (3)
lore
Share & tools
lore

Marc Zyngier

author maintainer
#0 lore raw

cover arm64: KVM: Kiss hyp_alternate_select() goodbye

hyp_alternate_select() is a leftover from the my second attempt at supporting VHE (the first one was never merged, thankfully), and is now an irrelevant relic. It was a way to patch function pointers without having to dereference memory, a bit like static keys for function calls.

Lovely idea, but since Christoffer mostly separated the VHE and !VHE hypervisor paths, most of the uses of hyp_alternate_select() are gone. What is left is two instances that are better replaced by already existing static keys. One of the instances becomes cpus_have_const_cap(), and the rest is a light sprinkling of has_vhe().

So off it goes.

Marc Zyngier (3):
arm64: KVM: Drop hyp_alternate_select for checking for

    ARM64_WORKAROUND_834220

arm64: KVM: Replace hyp_alternate_select with has_vhe()
arm64: KVM: Kill hyp_alternate_select()

 arch/arm64/include/asm/kvm_hyp.h | 24 ---------------------
 arch/arm64/kvm/hyp/switch.c      | 17 ++-------------
 arch/arm64/kvm/hyp/tlb.c         | 36 +++++++++++++++++++-------------
 3 files changed, 24 insertions(+), 53 deletions(-)
Signature · 1 line
2.20.1
author maintainer
#1 lore raw

PATCH 1/3 arm64: KVM: Drop hyp_alternate_select for checking for ARM64_WORKAROUND_834220

There is no reason for using hyp_alternate_select when checking for ARM64_WORKAROUND_834220, as each of the capabilities is also backed by a static key. Just replace the KVM-specific construct with cpus_have_const_cap(ARM64_WORKAROUND_834220).

---
 arch/arm64/kvm/hyp/switch.c | 17 ++---------------
 1 file changed, 2 insertions(+), 15 deletions(-)
arch/arm64/kvm/hyp/switch.c +2 -15
index adaf266d8de8..a15baca9aca0 100644
@@ -229,20 +229,6 @@ static void __hyp_text __hyp_vgic_restore_state(struct kvm_vcpu *vcpu)
 	}
 }
 
-static bool __hyp_text __true_value(void)
-{
-	return true;
-}
-
-static bool __hyp_text __false_value(void)
-{
-	return false;
-}
-
-static hyp_alternate_select(__check_arm_834220,
-			    __false_value, __true_value,
-			    ARM64_WORKAROUND_834220);
-
 static bool __hyp_text __translate_far_to_hpfar(u64 far, u64 *hpfar)
 {
 	u64 par, tmp;
@@ -298,7 +284,8 @@ static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu)
 	 * resolve the IPA using the AT instruction.
 	 */
 	if (!(esr & ESR_ELx_S1PTW) &&
-	    (__check_arm_834220()() || (esr & ESR_ELx_FSC_TYPE) == FSC_PERM)) {
+	    (cpus_have_const_cap(ARM64_WORKAROUND_834220) ||
+	     (esr & ESR_ELx_FSC_TYPE) == FSC_PERM)) {
 		if (!__translate_far_to_hpfar(far, &hpfar))
 			return false;
 	} else {
Signature · 1 line
2.20.1
author maintainer
#2 lore raw

PATCH 2/3 arm64: KVM: Replace hyp_alternate_select with has_vhe()

In reply to Marc Zyngier

Given that the TLB invalidation path is pretty rarely used, there was never any advantage to using hyp_alternate_select() here. has_vhe(), being a glorified static key, is the right tool for the job.

Off you go.

---
 arch/arm64/kvm/hyp/tlb.c | 36 ++++++++++++++++++++++--------------
 1 file changed, 22 insertions(+), 14 deletions(-)
arch/arm64/kvm/hyp/tlb.c +22 -14
index d49a14497715..f61db7f07619 100644
@@ -67,10 +67,14 @@ static void __hyp_text __tlb_switch_to_guest_nvhe(struct kvm *kvm,
 	isb();
 }
 
-static hyp_alternate_select(__tlb_switch_to_guest,
-			    __tlb_switch_to_guest_nvhe,
-			    __tlb_switch_to_guest_vhe,
-			    ARM64_HAS_VIRT_HOST_EXTN);
+static void __hyp_text __tlb_switch_to_guest(struct kvm *kvm,
+					     struct tlb_inv_context *cxt)
+{
+	if (has_vhe())
+		__tlb_switch_to_guest_vhe(kvm, cxt);
+	else
+		__tlb_switch_to_guest_nvhe(kvm, cxt);
+}
 
 static void __hyp_text __tlb_switch_to_host_vhe(struct kvm *kvm,
 						struct tlb_inv_context *cxt)
@@ -98,10 +102,14 @@ static void __hyp_text __tlb_switch_to_host_nvhe(struct kvm *kvm,
 	write_sysreg(0, vttbr_el2);
 }
 
-static hyp_alternate_select(__tlb_switch_to_host,
-			    __tlb_switch_to_host_nvhe,
-			    __tlb_switch_to_host_vhe,
-			    ARM64_HAS_VIRT_HOST_EXTN);
+static void __hyp_text __tlb_switch_to_host(struct kvm *kvm,
+					    struct tlb_inv_context *cxt)
+{
+	if (has_vhe())
+		__tlb_switch_to_host_vhe(kvm, cxt);
+	else
+		__tlb_switch_to_host_nvhe(kvm, cxt);
+}
 
 void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
 {
@@ -111,7 +119,7 @@ void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
 
 	/* Switch to requested VMID */
 	kvm = kern_hyp_va(kvm);
-	__tlb_switch_to_guest()(kvm, &cxt);
+	__tlb_switch_to_guest(kvm, &cxt);
 
 	/*
 	 * We could do so much better if we had the VA as well.
@@ -154,7 +162,7 @@ void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
 	if (!has_vhe() && icache_is_vpipt())
 		__flush_icache_all();
 
-	__tlb_switch_to_host()(kvm, &cxt);
+	__tlb_switch_to_host(kvm, &cxt);
 }
 
 void __hyp_text __kvm_tlb_flush_vmid(struct kvm *kvm)
@@ -165,13 +173,13 @@ void __hyp_text __kvm_tlb_flush_vmid(struct kvm *kvm)
 
 	/* Switch to requested VMID */
 	kvm = kern_hyp_va(kvm);
-	__tlb_switch_to_guest()(kvm, &cxt);
+	__tlb_switch_to_guest(kvm, &cxt);
 
 	__tlbi(vmalls12e1is);
 	dsb(ish);
 	isb();
 
-	__tlb_switch_to_host()(kvm, &cxt);
+	__tlb_switch_to_host(kvm, &cxt);
 }
 
 void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu)
@@ -180,13 +188,13 @@ void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu)
 	struct tlb_inv_context cxt;
 
 	/* Switch to requested VMID */
-	__tlb_switch_to_guest()(kvm, &cxt);
+	__tlb_switch_to_guest(kvm, &cxt);
 
 	__tlbi(vmalle1);
 	dsb(nsh);
 	isb();
 
-	__tlb_switch_to_host()(kvm, &cxt);
+	__tlb_switch_to_host(kvm, &cxt);
 }
 
 void __hyp_text __kvm_flush_vm_context(void)
Signature · 1 line
2.20.1
author maintainer
#3 lore raw

PATCH 3/3 arm64: KVM: Kill hyp_alternate_select()

In reply to Marc Zyngier

hyp_alternate_select() is now completely unused. Goodbye.

---
 arch/arm64/include/asm/kvm_hyp.h | 24 ------------------------
 1 file changed, 24 deletions(-)
arch/arm64/include/asm/kvm_hyp.h +0 -24
index 86825aa20852..97f21cc66657 100644
@@ -47,30 +47,6 @@
 #define read_sysreg_el2(r)	read_sysreg_elx(r, _EL2, _EL1)
 #define write_sysreg_el2(v,r)	write_sysreg_elx(v, r, _EL2, _EL1)
 
-/**
- * hyp_alternate_select - Generates patchable code sequences that are
- * used to switch between two implementations of a function, depending
- * on the availability of a feature.
- *
- * @fname: a symbol name that will be defined as a function returning a
- * function pointer whose type will match @orig and @alt
- * @orig: A pointer to the default function, as returned by @fname when
- * @cond doesn't hold
- * @alt: A pointer to the alternate function, as returned by @fname
- * when @cond holds
- * @cond: a CPU feature (as described in asm/cpufeature.h)
- */
-#define hyp_alternate_select(fname, orig, alt, cond)			\
-typeof(orig) * __hyp_text fname(void)					\
-{									\
-	typeof(alt) *val = orig;					\
-	asm volatile(ALTERNATIVE("nop		\n",			\
-				 "mov	%0, %1	\n",			\
-				 cond)					\
-		     : "+r" (val) : "r" (alt));				\
-	return val;							\
-}
-
 int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
 
 void __vgic_v3_save_state(struct kvm_vcpu *vcpu);
Signature · 1 line
2.20.1
Reviewed-by on the v1 series
#4 lore raw
In reply to Marc Zyngier
Quoted 6 lines · Marc Zyngier

hyp_alternate_select() is a leftover from the my second attempt at supporting VHE (the first one was never merged, thankfully), and is now an irrelevant relic. It was a way to patch function pointers without having to dereference memory, a bit like static keys for function calls.

Quoted 8 lines

Lovely idea, but since Christoffer mostly separated the VHE and !VHE hypervisor paths, most of the uses of hyp_alternate_select() are gone. What is left is two instances that are better replaced by already existing static keys. One of the instances becomes cpus_have_const_cap(), and the rest is a light sprinkling of has_vhe().

So off it goes.

I'm not sure I want to kiss hyp_alternate_select() at all, but away it must go!

Reviewed-by on the v1 series
#5 lore raw
In reply to Marc Zyngier
Quoted 17 lines · Marc Zyngier

hyp_alternate_select() is a leftover from the my second attempt at supporting VHE (the first one was never merged, thankfully), and is now an irrelevant relic. It was a way to patch function pointers without having to dereference memory, a bit like static keys for function calls.

Lovely idea, but since Christoffer mostly separated the VHE and !VHE hypervisor paths, most of the uses of hyp_alternate_select() are gone. What is left is two instances that are better replaced by already existing static keys. One of the instances becomes cpus_have_const_cap(), and the rest is a light sprinkling of has_vhe().

So off it goes.

Marc Zyngier (3):
arm64: KVM: Drop hyp_alternate_select for checking for

Quoted 12 lines
    ARM64_WORKAROUND_834220

arm64: KVM: Replace hyp_alternate_select with has_vhe()
arm64: KVM: Kill hyp_alternate_select()

 arch/arm64/include/asm/kvm_hyp.h | 24 ---------------------
 arch/arm64/kvm/hyp/switch.c      | 17 ++-------------
 arch/arm64/kvm/hyp/tlb.c         | 36 +++++++++++++++++++-------------
 3 files changed, 24 insertions(+), 53 deletions(-)
Signature · 1 line
2.20.1

Yay! The 'func()(...)' stuff always gave me cross-eyes.