linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] arm64: KVM: Use instruction patching for GIC world switch
@ 2015-06-12 11:06 Marc Zyngier
  2015-06-12 11:06 ` [PATCH 1/2] arm64: alternative: Introduce feature for GICv3 CPU interface Marc Zyngier
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Marc Zyngier @ 2015-06-12 11:06 UTC (permalink / raw)
  To: linux-arm-kernel

The current way we deal with the GIC world switch on arm64 is a bit
convoluted. As we have two possible backends, we rely on a couple of
indirections set at boot time. These indirection never change, so it
would make more sense to directly patch in a branch to the right
function.

To do this, we introduce a new CPU feature that detect the presence of
a GICv3 CPU interface. When detected, we patch branches to the GICv3
save/restore functions that otherwise point to the GICv2 backend.

Tested on both GICv2 (Juno, Seattle) and GICv3 (FVP Base model).

These patches have been on the various lists for quite a while as part
of a series dealing with instruction patching. Now that the
prerequisite are queued for 4.2, it would make sense for these to be
merged alongside.

Catalin, would you mind taking them through the arm64 tree?

Marc Zyngier (2):
  arm64: alternative: Introduce feature for GICv3 CPU interface
  arm64: KVM: Switch vgic save/restore to alternative_insn

 arch/arm/include/asm/kvm_host.h     |  5 -----
 arch/arm64/include/asm/cpufeature.h |  8 +++++++-
 arch/arm64/include/asm/kvm_asm.h    |  5 -----
 arch/arm64/include/asm/kvm_host.h   | 23 -----------------------
 arch/arm64/kernel/asm-offsets.c     |  1 -
 arch/arm64/kernel/cpufeature.c      | 16 ++++++++++++++++
 arch/arm64/kvm/hyp.S                | 18 ++++--------------
 virt/kvm/arm/vgic.c                 |  3 ---
 8 files changed, 27 insertions(+), 52 deletions(-)

-- 
2.1.4

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

* [PATCH 1/2] arm64: alternative: Introduce feature for GICv3 CPU interface
  2015-06-12 11:06 [PATCH 0/2] arm64: KVM: Use instruction patching for GIC world switch Marc Zyngier
@ 2015-06-12 11:06 ` Marc Zyngier
  2015-06-12 11:06 ` [PATCH 2/2] arm64: KVM: Switch vgic save/restore to alternative_insn Marc Zyngier
  2015-06-12 14:12 ` [PATCH 0/2] arm64: KVM: Use instruction patching for GIC world switch Catalin Marinas
  2 siblings, 0 replies; 4+ messages in thread
From: Marc Zyngier @ 2015-06-12 11:06 UTC (permalink / raw)
  To: linux-arm-kernel

Add a new item to the feature set (ARM64_HAS_SYSREG_GIC_CPUIF)
to indicate that we have a system register GIC CPU interface

This will help KVM switching to alternative instruction patching.

Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/cpufeature.h |  8 +++++++-
 arch/arm64/kernel/cpufeature.c      | 16 ++++++++++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 82cb9f9..c104421 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -24,8 +24,9 @@
 #define ARM64_WORKAROUND_CLEAN_CACHE		0
 #define ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE	1
 #define ARM64_WORKAROUND_845719			2
+#define ARM64_HAS_SYSREG_GIC_CPUIF		3
 
-#define ARM64_NCAPS				3
+#define ARM64_NCAPS				4
 
 #ifndef __ASSEMBLY__
 
@@ -38,6 +39,11 @@ struct arm64_cpu_capabilities {
 			u32 midr_model;
 			u32 midr_range_min, midr_range_max;
 		};
+
+		struct {	/* Feature register checking */
+			u64 register_mask;
+			u64 register_value;
+		};
 	};
 };
 
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 3d9967e..5ad86ce 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -22,7 +22,23 @@
 #include <asm/cpu.h>
 #include <asm/cpufeature.h>
 
+static bool
+has_id_aa64pfr0_feature(const struct arm64_cpu_capabilities *entry)
+{
+	u64 val;
+
+	val = read_cpuid(id_aa64pfr0_el1);
+	return (val & entry->register_mask) == entry->register_value;
+}
+
 static const struct arm64_cpu_capabilities arm64_features[] = {
+	{
+		.desc = "GIC system register CPU interface",
+		.capability = ARM64_HAS_SYSREG_GIC_CPUIF,
+		.matches = has_id_aa64pfr0_feature,
+		.register_mask = (0xf << 24),
+		.register_value = (1 << 24),
+	},
 	{},
 };
 
-- 
2.1.4

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

* [PATCH 2/2] arm64: KVM: Switch vgic save/restore to alternative_insn
  2015-06-12 11:06 [PATCH 0/2] arm64: KVM: Use instruction patching for GIC world switch Marc Zyngier
  2015-06-12 11:06 ` [PATCH 1/2] arm64: alternative: Introduce feature for GICv3 CPU interface Marc Zyngier
@ 2015-06-12 11:06 ` Marc Zyngier
  2015-06-12 14:12 ` [PATCH 0/2] arm64: KVM: Use instruction patching for GIC world switch Catalin Marinas
  2 siblings, 0 replies; 4+ messages in thread
From: Marc Zyngier @ 2015-06-12 11:06 UTC (permalink / raw)
  To: linux-arm-kernel

So far, we configured the world-switch by having a small array
of pointers to the save and restore functions, depending on the
GIC used on the platform.

Loading these values each time is a bit silly (they never change),
and it makes sense to rely on the instruction patching instead.

This leads to a nice cleanup of the code.

Acked-by: Will Deacon <will.deacon@arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/include/asm/kvm_host.h   |  5 -----
 arch/arm64/include/asm/kvm_asm.h  |  5 -----
 arch/arm64/include/asm/kvm_host.h | 23 -----------------------
 arch/arm64/kernel/asm-offsets.c   |  1 -
 arch/arm64/kvm/hyp.S              | 18 ++++--------------
 virt/kvm/arm/vgic.c               |  3 ---
 6 files changed, 4 insertions(+), 51 deletions(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index d71607c..e896d2c 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -218,11 +218,6 @@ static inline int kvm_arch_dev_ioctl_check_extension(long ext)
 	return 0;
 }
 
-static inline void vgic_arch_setup(const struct vgic_params *vgic)
-{
-	BUG_ON(vgic->type != VGIC_V2);
-}
-
 int kvm_perf_init(void);
 int kvm_perf_teardown(void);
 
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 4f7310f..d13bc5e 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -132,11 +132,6 @@ extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
 
 extern u64 __vgic_v3_get_ich_vtr_el2(void);
 
-extern char __save_vgic_v2_state[];
-extern char __restore_vgic_v2_state[];
-extern char __save_vgic_v3_state[];
-extern char __restore_vgic_v3_state[];
-
 #endif
 
 #endif /* __ARM_KVM_ASM_H__ */
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index f0f58c9..2709db2 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -221,29 +221,6 @@ struct vgic_sr_vectors {
 	void	*restore_vgic;
 };
 
-static inline void vgic_arch_setup(const struct vgic_params *vgic)
-{
-	extern struct vgic_sr_vectors __vgic_sr_vectors;
-
-	switch(vgic->type)
-	{
-	case VGIC_V2:
-		__vgic_sr_vectors.save_vgic	= __save_vgic_v2_state;
-		__vgic_sr_vectors.restore_vgic	= __restore_vgic_v2_state;
-		break;
-
-#ifdef CONFIG_ARM_GIC_V3
-	case VGIC_V3:
-		__vgic_sr_vectors.save_vgic	= __save_vgic_v3_state;
-		__vgic_sr_vectors.restore_vgic	= __restore_vgic_v3_state;
-		break;
-#endif
-
-	default:
-		BUG();
-	}
-}
-
 static inline void kvm_arch_hardware_disable(void) {}
 static inline void kvm_arch_hardware_unsetup(void) {}
 static inline void kvm_arch_sync_events(struct kvm *kvm) {}
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index da675cc..c99701a 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -127,7 +127,6 @@ int main(void)
   DEFINE(VCPU_VGIC_CPU,		offsetof(struct kvm_vcpu, arch.vgic_cpu));
   DEFINE(VGIC_SAVE_FN,		offsetof(struct vgic_sr_vectors, save_vgic));
   DEFINE(VGIC_RESTORE_FN,	offsetof(struct vgic_sr_vectors, restore_vgic));
-  DEFINE(VGIC_SR_VECTOR_SZ,	sizeof(struct vgic_sr_vectors));
   DEFINE(VGIC_V2_CPU_HCR,	offsetof(struct vgic_cpu, vgic_v2.vgic_hcr));
   DEFINE(VGIC_V2_CPU_VMCR,	offsetof(struct vgic_cpu, vgic_v2.vgic_vmcr));
   DEFINE(VGIC_V2_CPU_MISR,	offsetof(struct vgic_cpu, vgic_v2.vgic_misr));
diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
index 5befd01..f1f6d90 100644
--- a/arch/arm64/kvm/hyp.S
+++ b/arch/arm64/kvm/hyp.S
@@ -17,8 +17,10 @@
 
 #include <linux/linkage.h>
 
+#include <asm/alternative.h>
 #include <asm/asm-offsets.h>
 #include <asm/assembler.h>
+#include <asm/cpufeature.h>
 #include <asm/debug-monitors.h>
 #include <asm/esr.h>
 #include <asm/fpsimdmacros.h>
@@ -808,10 +810,7 @@
  * Call into the vgic backend for state saving
  */
 .macro save_vgic_state
-	adr	x24, __vgic_sr_vectors
-	ldr	x24, [x24, VGIC_SAVE_FN]
-	kern_hyp_va	x24
-	blr	x24
+	alternative_insn "bl __save_vgic_v2_state", "bl __save_vgic_v3_state", ARM64_HAS_SYSREG_GIC_CPUIF
 	mrs	x24, hcr_el2
 	mov	x25, #HCR_INT_OVERRIDE
 	neg	x25, x25
@@ -828,10 +827,7 @@
 	orr	x24, x24, #HCR_INT_OVERRIDE
 	orr	x24, x24, x25
 	msr	hcr_el2, x24
-	adr	x24, __vgic_sr_vectors
-	ldr	x24, [x24, #VGIC_RESTORE_FN]
-	kern_hyp_va	x24
-	blr	x24
+	alternative_insn "bl __restore_vgic_v2_state", "bl __restore_vgic_v3_state", ARM64_HAS_SYSREG_GIC_CPUIF
 .endm
 
 .macro save_timer_state
@@ -1062,12 +1058,6 @@ ENTRY(__kvm_flush_vm_context)
 	ret
 ENDPROC(__kvm_flush_vm_context)
 
-	// struct vgic_sr_vectors __vgi_sr_vectors;
-	.align 3
-ENTRY(__vgic_sr_vectors)
-	.skip	VGIC_SR_VECTOR_SZ
-ENDPROC(__vgic_sr_vectors)
-
 __kvm_hyp_panic:
 	// Guess the context by looking at VTTBR:
 	// If zero, then we're already a host.
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 78fb820..003ba74 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -2128,9 +2128,6 @@ int kvm_vgic_hyp_init(void)
 		goto out_free_irq;
 	}
 
-	/* Callback into for arch code for setup */
-	vgic_arch_setup(vgic);
-
 	on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1);
 
 	return 0;
-- 
2.1.4

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

* [PATCH 0/2] arm64: KVM: Use instruction patching for GIC world switch
  2015-06-12 11:06 [PATCH 0/2] arm64: KVM: Use instruction patching for GIC world switch Marc Zyngier
  2015-06-12 11:06 ` [PATCH 1/2] arm64: alternative: Introduce feature for GICv3 CPU interface Marc Zyngier
  2015-06-12 11:06 ` [PATCH 2/2] arm64: KVM: Switch vgic save/restore to alternative_insn Marc Zyngier
@ 2015-06-12 14:12 ` Catalin Marinas
  2 siblings, 0 replies; 4+ messages in thread
From: Catalin Marinas @ 2015-06-12 14:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jun 12, 2015 at 12:06:35PM +0100, Marc Zyngier wrote:
> The current way we deal with the GIC world switch on arm64 is a bit
> convoluted. As we have two possible backends, we rely on a couple of
> indirections set at boot time. These indirection never change, so it
> would make more sense to directly patch in a branch to the right
> function.
> 
> To do this, we introduce a new CPU feature that detect the presence of
> a GICv3 CPU interface. When detected, we patch branches to the GICv3
> save/restore functions that otherwise point to the GICv2 backend.
> 
> Tested on both GICv2 (Juno, Seattle) and GICv3 (FVP Base model).
> 
> These patches have been on the various lists for quite a while as part
> of a series dealing with instruction patching. Now that the
> prerequisite are queued for 4.2, it would make sense for these to be
> merged alongside.
> 
> Catalin, would you mind taking them through the arm64 tree?
> 
> Marc Zyngier (2):
>   arm64: alternative: Introduce feature for GICv3 CPU interface
>   arm64: KVM: Switch vgic save/restore to alternative_insn

Applied. Thanks.

-- 
Catalin

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

end of thread, other threads:[~2015-06-12 14:12 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-06-12 11:06 [PATCH 0/2] arm64: KVM: Use instruction patching for GIC world switch Marc Zyngier
2015-06-12 11:06 ` [PATCH 1/2] arm64: alternative: Introduce feature for GICv3 CPU interface Marc Zyngier
2015-06-12 11:06 ` [PATCH 2/2] arm64: KVM: Switch vgic save/restore to alternative_insn Marc Zyngier
2015-06-12 14:12 ` [PATCH 0/2] arm64: KVM: Use instruction patching for GIC world switch Catalin Marinas

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