[PATCH RFC 1/4] arm64: KVM: add MIDR_EL1 switching

Tushar Jagad tushar.jagad at linaro.org
Wed Sep 9 01:38:31 PDT 2015


From: Marc Zyngier <marc.zyngier at arm.com>

Move MIDR_EL1 to be a world-switched register, instead of being
unchanged from the host.

The behaviour is preserved by using the host's MIDR_EL1 as a
reset value for the guest's register.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Tushar Jagad <tushar.jagad at linaro.org>
---
 arch/arm64/include/asm/kvm_asm.h |   16 +++++++++-------
 arch/arm64/kvm/hyp.S             |    4 ++++
 arch/arm64/kvm/sys_regs.c        |   18 +++++++++++++-----
 3 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 3c5fe68..c1d5bde 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -55,17 +55,19 @@
 #define DBGWVR0_EL1	71	/* Debug Watchpoint Value Registers (0-15) */
 #define DBGWVR15_EL1	86
 #define MDCCINT_EL1	87	/* Monitor Debug Comms Channel Interrupt Enable Reg */
+#define MIDR_EL1	88	/* Main ID Register */
 
 /* 32bit specific registers. Keep them at the end of the range */
-#define	DACR32_EL2	88	/* Domain Access Control Register */
-#define	IFSR32_EL2	89	/* Instruction Fault Status Register */
-#define	FPEXC32_EL2	90	/* Floating-Point Exception Control Register */
-#define	DBGVCR32_EL2	91	/* Debug Vector Catch Register */
-#define	TEECR32_EL1	92	/* ThumbEE Configuration Register */
-#define	TEEHBR32_EL1	93	/* ThumbEE Handler Base Register */
-#define	NR_SYS_REGS	94
+#define	DACR32_EL2	89	/* Domain Access Control Register */
+#define	IFSR32_EL2	90	/* Instruction Fault Status Register */
+#define	FPEXC32_EL2	91	/* Floating-Point Exception Control Register */
+#define	DBGVCR32_EL2	92	/* Debug Vector Catch Register */
+#define	TEECR32_EL1	93	/* ThumbEE Configuration Register */
+#define	TEEHBR32_EL1	94	/* ThumbEE Handler Base Register */
+#define	NR_SYS_REGS	95
 
 /* 32bit mapping */
+#define c0_MIDR		(MIDR_EL1 * 2)	/* Main ID Register */
 #define c0_MPIDR	(MPIDR_EL1 * 2)	/* MultiProcessor ID Register */
 #define c0_CSSELR	(CSSELR_EL1 * 2)/* Cache Size Selection Register */
 #define c1_SCTLR	(SCTLR_EL1 * 2)	/* System Control Register */
diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
index 17a8fb1..6013347 100644
--- a/arch/arm64/kvm/hyp.S
+++ b/arch/arm64/kvm/hyp.S
@@ -216,6 +216,7 @@
 	mrs	x23, 	cntkctl_el1
 	mrs	x24,	par_el1
 	mrs	x25,	mdscr_el1
+	mrs	x26,	vpidr_el2
 
 	stp	x4, x5, [x3]
 	stp	x6, x7, [x3, #16]
@@ -228,6 +229,7 @@
 	stp	x20, x21, [x3, #128]
 	stp	x22, x23, [x3, #144]
 	stp	x24, x25, [x3, #160]
+	str	x26, [x3, #696]
 .endm
 
 .macro save_debug
@@ -442,6 +444,7 @@
 	ldp	x20, x21, [x3, #128]
 	ldp	x22, x23, [x3, #144]
 	ldp	x24, x25, [x3, #160]
+	ldr	x26, [x3, #696]
 
 	msr	vmpidr_el2,	x4
 	msr	csselr_el1,	x5
@@ -465,6 +468,7 @@
 	msr	cntkctl_el1,	x23
 	msr	par_el1,	x24
 	msr	mdscr_el1,	x25
+	msr	vpidr_el2,	x26
 .endm
 
 .macro restore_debug
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index c370b40..7047292 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -170,17 +170,25 @@ static bool trap_dbgauthstatus_el1(struct kvm_vcpu *vcpu,
 	}
 }
 
+static void reset_midr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+{
+	/*
+	 * We only export the host's MPIDR_EL1 for now.
+	 */
+	vcpu_sys_reg(vcpu, MIDR_EL1) = read_cpuid_id();
+}
+
 /*
  * We want to avoid world-switching all the DBG registers all the
  * time:
- * 
+ *
  * - If we've touched any debug register, it is likely that we're
  *   going to touch more of them. It then makes sense to disable the
  *   traps and start doing the save/restore dance
  * - If debug is active (DBG_MDSCR_KDE or DBG_MDSCR_MDE set), it is
  *   then mandatory to save/restore the registers, as the guest
  *   depends on them.
- * 
+ *
  * For this, we use a DIRTY bit, indicating the guest has modified the
  * debug registers, used as follow:
  *
@@ -350,6 +358,9 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 	{ Op0(0b10), Op1(0b100), CRn(0b0000), CRm(0b0111), Op2(0b000),
 	  NULL, reset_val, DBGVCR32_EL2, 0 },
 
+	/* MIDR_EL1 */
+	{ Op0(0b11), Op1(0b000), CRn(0b0000), CRm(0b0000), Op2(0b000),
+	  NULL, reset_midr, MIDR_EL1 },
 	/* MPIDR_EL1 */
 	{ Op0(0b11), Op1(0b000), CRn(0b0000), CRm(0b0000), Op2(0b101),
 	  NULL, reset_mpidr, MPIDR_EL1 },
@@ -1091,7 +1102,6 @@ static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu,
 		((struct sys_reg_desc *)r)->val = val;			\
 	}
 
-FUNCTION_INVARIANT(midr_el1)
 FUNCTION_INVARIANT(ctr_el0)
 FUNCTION_INVARIANT(revidr_el1)
 FUNCTION_INVARIANT(id_pfr0_el1)
@@ -1113,8 +1123,6 @@ FUNCTION_INVARIANT(aidr_el1)
 
 /* ->val is filled in by kvm_sys_reg_table_init() */
 static struct sys_reg_desc invariant_sys_regs[] = {
-	{ Op0(0b11), Op1(0b000), CRn(0b0000), CRm(0b0000), Op2(0b000),
-	  NULL, get_midr_el1 },
 	{ Op0(0b11), Op1(0b000), CRn(0b0000), CRm(0b0000), Op2(0b110),
 	  NULL, get_revidr_el1 },
 	{ Op0(0b11), Op1(0b000), CRn(0b0000), CRm(0b0001), Op2(0b000),
-- 
1.7.9.5




More information about the linux-arm-kernel mailing list