arm, kvm: Override the kernel's default MPIDR value
authorAndreas Sandberg <andreas.sandberg@arm.com>
Mon, 20 Mar 2017 14:36:48 +0000 (14:36 +0000)
committerAndreas Sandberg <andreas.sandberg@arm.com>
Mon, 3 Apr 2017 16:37:55 +0000 (16:37 +0000)
The kernel and gem5 derive MPIDR values from CPU IDs in slightly
different ways. This means that guests running in a multi-CPU setup
sometimes fail to bring up secondary CPUs. Fix this by overriding the
MPIDR value in virtual CPUs just after they have been instantiated.

Change-Id: I916d44978a9c855ab89c80a083af45b0cea6edac
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-by: Sascha Bischoff <sascha.bischoff@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2461
Reviewed-by: Weiping Liao <weipingliao@google.com>
src/arch/arm/kvm/armv8_cpu.cc
src/arch/arm/kvm/armv8_cpu.hh

index 67e2e465ea35bbe8a5954d5da96bb17dad1bf505..48bcc5fe9ee104990a6b217346ff74eb9c55ab97 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 ARM Limited
+ * Copyright (c) 2015, 2017 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -65,6 +65,8 @@ static_assert(NUM_QREGS == 32, "Unexpected number of aarch64 vector regs.");
 #define INT_REG(name) CORE_REG(name, U64)
 #define SIMD_REG(name) CORE_REG(name, U128)
 
+#define SYS_MPIDR_EL1 ARM64_SYS_REG(0b11, 0b000, 0b0000, 0b0000, 0b101)
+
 constexpr uint64_t
 kvmXReg(const int num)
 {
@@ -112,6 +114,10 @@ const std::vector<ArmV8KvmCPU::MiscRegInfo> ArmV8KvmCPU::miscRegMap = {
     MiscRegInfo(INT_REG(fp_regs.fpcr), MISCREG_FPCR, "FPCR"),
 };
 
+const std::vector<ArmV8KvmCPU::MiscRegInfo> ArmV8KvmCPU::miscRegIdMap = {
+    MiscRegInfo(SYS_MPIDR_EL1, MISCREG_MPIDR_EL1, "MPIDR(EL1)"),
+};
+
 ArmV8KvmCPU::ArmV8KvmCPU(ArmV8KvmCPUParams *params)
     : BaseArmKvmCPU(params)
 {
@@ -121,6 +127,19 @@ ArmV8KvmCPU::~ArmV8KvmCPU()
 {
 }
 
+void
+ArmV8KvmCPU::startup()
+{
+    BaseArmKvmCPU::startup();
+
+    // Override ID registers that KVM should "inherit" from gem5.
+    for (const auto &ri : miscRegIdMap) {
+        const uint64_t value(tc->readMiscReg(ri.idx));
+        DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
+        setOneReg(ri.kvm, value);
+    }
+}
+
 void
 ArmV8KvmCPU::dump() const
 {
@@ -140,6 +159,9 @@ ArmV8KvmCPU::dump() const
     for (const auto &ri : miscRegMap)
         inform("  %s: %s\n", ri.name, getAndFormatOneReg(ri.kvm));
 
+    for (const auto &ri : miscRegIdMap)
+        inform("  %s: %s\n", ri.name, getAndFormatOneReg(ri.kvm));
+
     for (const auto &reg : getRegList()) {
         const uint64_t arch(reg & KVM_REG_ARCH_MASK);
         if (arch != KVM_REG_ARM64) {
index d3e390b4f4d55135c5542b679c88cda7a7b3da5a..63e03908fbf513836c7a32b537f5fe3f47fa2e57 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 ARM Limited
+ * Copyright (c) 2015, 2017 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -83,6 +83,8 @@ class ArmV8KvmCPU : public BaseArmKvmCPU
     ArmV8KvmCPU(ArmV8KvmCPUParams *params);
     virtual ~ArmV8KvmCPU();
 
+    void startup() override;
+
     void dump() const override;
 
   protected:
@@ -132,6 +134,8 @@ class ArmV8KvmCPU : public BaseArmKvmCPU
     static const std::vector<ArmV8KvmCPU::IntRegInfo> intRegMap;
     /** Mapping between gem5 misc registers registers and registers in kvm */
     static const std::vector<ArmV8KvmCPU::MiscRegInfo> miscRegMap;
+    /** Mapping between gem5 ID misc registers registers and registers in kvm */
+    static const std::vector<ArmV8KvmCPU::MiscRegInfo> miscRegIdMap;
 
     /** Cached mapping between system registers in kvm and misc regs in gem5 */
     mutable std::vector<ArmV8KvmCPU::MiscRegInfo> sysRegMap;