[PATCH] ARM: KVM: Do not let userspace mess with MIDR

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The MIDR register is used, among other things, to find out the
CPU revision, and select matching errata.

Letting userspace set the MIDR register prevents the guest from
selecting errata that apply to the underlying CPU, with possibly
deadly consequences.

Turn MIDR to an invariant register, and only expose the HW one
to the guest. We still keep it stored in a per-vcpu variable in
case we come up with a better scheme some day.

Signed-off-by: Marc Zyngier <marc.zyngier@xxxxxxx>
---
 arch/arm/include/asm/kvm_host.h | 6 ++++--
 arch/arm/kernel/asm-offsets.c   | 2 +-
 arch/arm/kvm/coproc.c           | 5 ++---
 arch/arm/kvm/reset.c            | 2 ++
 4 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 3d4ce42..0956808 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -95,8 +95,7 @@ struct kvm_vcpu_regs {
 
 /* 0 is reserved as an invalid value. */
 enum cp15_regs {
-	c0_MIDR=1,		/* Main ID Register */
-	c0_MPIDR,		/* MultiProcessor ID Register */
+	c0_MPIDR=1,		/* MultiProcessor ID Register */
 	c1_SCTLR,		/* System Control Register */
 	c1_ACTLR,		/* Auxilliary Control Register */
 	c1_CPACR,		/* Coprocessor Access Control */
@@ -133,6 +132,9 @@ struct kvm_vcpu_arch {
 	/* System control coprocessor (cp15) */
 	u32 cp15[nr_cp15_regs];
 
+	/* The CPU type we expose to the VM */
+	u32 midr;
+
 	/* Exception Information */
 	u32 hsr;		/* Hyp Syndrom Register */
 	u32 hdfar;		/* Hyp Data Fault Address Register */
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index e8d8bba..76c373a 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -147,7 +147,7 @@ int main(void)
   DEFINE(DMA_FROM_DEVICE,	DMA_FROM_DEVICE);
 #ifdef CONFIG_KVM_ARM_HOST
   DEFINE(VCPU_KVM,		offsetof(struct kvm_vcpu, kvm));
-  DEFINE(VCPU_MIDR,		offsetof(struct kvm_vcpu, arch.cp15[c0_MIDR]));
+  DEFINE(VCPU_MIDR,		offsetof(struct kvm_vcpu, arch.midr));
   DEFINE(VCPU_MPIDR,		offsetof(struct kvm_vcpu, arch.cp15[c0_MPIDR]));
   DEFINE(VCPU_SCTLR,		offsetof(struct kvm_vcpu, arch.cp15[c1_SCTLR]));
   DEFINE(VCPU_CPACR,		offsetof(struct kvm_vcpu, arch.cp15[c1_CPACR]));
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index 89089fd..bd56dfb 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -390,9 +390,6 @@ static const struct coproc_reg cp15_regs[] = {
  * Important: Must sorted ascending by CRn, CRM, Op1, Op2
  */
 static const struct coproc_reg cp15_cortex_a15_regs[] = {
-	/* MIDR: we use VPIDR for guest access. */
-	{ CRn( 0), CRm( 0), Op1( 0), Op2( 0), is32,
-			NULL, reset_val, c0_MIDR, 0x412FC0F0 },
 	/* MPIDR: we use VMPIDR for guest access. */
 	{ CRn( 0), CRm( 0), Op1( 0), Op2( 5), is32,
 			NULL, reset_mpidr, c0_MPIDR },
@@ -646,6 +643,7 @@ static const struct coproc_reg *index_to_coproc_reg(struct kvm_vcpu *vcpu,
 		((struct coproc_reg *)r)->val = val;			\
 	}
 
+FUNCTION_FOR32(0, 0, 0, 0, MIDR)
 FUNCTION_FOR32(0, 0, 0, 1, CTR)
 FUNCTION_FOR32(0, 0, 0, 2, TCMTR)
 FUNCTION_FOR32(0, 0, 0, 3, TLBTR)
@@ -670,6 +668,7 @@ FUNCTION_FOR32(0, 0, 1, 7, AIDR)
 
 /* ->val is filled in by kvm_invariant_coproc_table_init() */
 static struct coproc_reg invariant_cp15[] = {
+	{ CRn( 0), CRm( 0), Op1( 0), Op2( 0), is32, NULL, get_MIDR },
 	{ CRn( 0), CRm( 0), Op1( 0), Op2( 1), is32, NULL, get_CTR },
 	{ CRn( 0), CRm( 0), Op1( 0), Op2( 2), is32, NULL, get_TCMTR },
 	{ CRn( 0), CRm( 0), Op1( 0), Op2( 3), is32, NULL, get_TLBTR },
diff --git a/arch/arm/kvm/reset.c b/arch/arm/kvm/reset.c
index 8eb0a56..33625c6 100644
--- a/arch/arm/kvm/reset.c
+++ b/arch/arm/kvm/reset.c
@@ -23,6 +23,7 @@
 
 #include <asm/unified.h>
 #include <asm/ptrace.h>
+#include <asm/cputype.h>
 #include <asm/kvm_arm.h>
 
 /******************************************************************************
@@ -56,6 +57,7 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 		if (vcpu->vcpu_id > a15_max_cpu_idx)
 			return -EINVAL;
 		cpu_reset = &a15_regs_reset;
+		vcpu->arch.midr = read_cpuid_id();
 		break;
 	default:
 		return -ENODEV;
-- 
1.7.11.4



_______________________________________________
kvmarm mailing list
kvmarm@xxxxxxxxxxxxxxxxxxxxx
https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm


[Index of Archives]     [Linux KVM]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux