arm, kvm: fix saving/restoring conditional flags in ARM KVM64
authorRahul Thakur <rjthakur@google.com>
Wed, 1 Mar 2017 18:15:57 +0000 (10:15 -0800)
committerRahul Thakur <rjthakur@google.com>
Fri, 3 Mar 2017 04:53:41 +0000 (04:53 +0000)
The gem5 stores flags separately from other fields CPSR, so we need to
split them out and recombine on trips to/from KVM.

Change-Id: I28ed00eb6f0e2a1436adfbc51b6ccf056958afeb
Reviewed-on: https://gem5-review.googlesource.com/2260
Reviewed-by: Rahul Thakur <rjthakur@google.com>
Maintainer: Rahul Thakur <rjthakur@google.com>

src/arch/arm/kvm/armv8_cpu.cc

index e8a77b07ba88f70820ed748884a6c457732bcb32..08b9011233ab662b18fcc3fddf499b7dc69c3f56 100644 (file)
@@ -102,7 +102,6 @@ const std::vector<ArmV8KvmCPU::IntRegInfo> ArmV8KvmCPU::intRegMap = {
 };
 
 const std::vector<ArmV8KvmCPU::MiscRegInfo> ArmV8KvmCPU::miscRegMap = {
-    MiscRegInfo(INT_REG(regs.pstate), MISCREG_CPSR, "PSTATE"),
     MiscRegInfo(INT_REG(elr_el1), MISCREG_ELR_EL1, "ELR(EL1)"),
     MiscRegInfo(INT_REG(spsr[KVM_SPSR_EL1]), MISCREG_SPSR_EL1, "SPSR(EL1)"),
     MiscRegInfo(INT_REG(spsr[KVM_SPSR_ABT]), MISCREG_SPSR_ABT, "SPSR(ABT)"),
@@ -136,6 +135,8 @@ ArmV8KvmCPU::dump() const
     for (const auto &ri : intRegMap)
         inform("  %s: %s\n", ri.name, getAndFormatOneReg(ri.kvm));
 
+    inform("  %s: %s\n", "PSTATE", getAndFormatOneReg(INT_REG(regs.pstate)));
+
     for (const auto &ri : miscRegMap)
         inform("  %s: %s\n", ri.name, getAndFormatOneReg(ri.kvm));
 
@@ -188,6 +189,20 @@ void
 ArmV8KvmCPU::updateKvmState()
 {
     DPRINTF(KvmContext, "In updateKvmState():\n");
+
+    // update pstate register state
+    CPSR cpsr(tc->readMiscReg(MISCREG_CPSR));
+    cpsr.nz = tc->readCCReg(CCREG_NZ);
+    cpsr.c = tc->readCCReg(CCREG_C);
+    cpsr.v = tc->readCCReg(CCREG_V);
+    if (cpsr.width) {
+        cpsr.ge = tc->readCCReg(CCREG_GE);
+    } else {
+        cpsr.ge = 0;
+    }
+    DPRINTF(KvmContext, "  %s := 0x%x\n", "PSTATE", cpsr);
+    setOneReg(INT_REG(regs.pstate), cpsr);
+
     for (const auto &ri : miscRegMap) {
         const uint64_t value(tc->readMiscReg(ri.idx));
         DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
@@ -231,7 +246,18 @@ ArmV8KvmCPU::updateThreadContext()
 {
     DPRINTF(KvmContext, "In updateThreadContext():\n");
 
-    // Update core misc regs first as they (particularly PSTATE/CPSR)
+    // Update pstate thread context
+    const CPSR cpsr(tc->readMiscRegNoEffect(MISCREG_CPSR));
+    DPRINTF(KvmContext, "  %s := 0x%x\n", "PSTATE", cpsr);
+    tc->setMiscRegNoEffect(MISCREG_CPSR, cpsr);
+    tc->setCCReg(CCREG_NZ, cpsr.nz);
+    tc->setCCReg(CCREG_C, cpsr.c);
+    tc->setCCReg(CCREG_V, cpsr.v);
+    if (cpsr.width) {
+        tc->setCCReg(CCREG_GE, cpsr.ge);
+    }
+
+    // Update core misc regs first as they
     // affect how other registers are mapped.
     for (const auto &ri : miscRegMap) {
         const auto value(getOneRegU64(ri.kvm));
@@ -266,7 +292,6 @@ ArmV8KvmCPU::updateThreadContext()
         tc->setMiscRegNoEffect(ri.idx, value);
     }
 
-    const CPSR cpsr(tc->readMiscRegNoEffect(MISCREG_CPSR));
     PCState pc(getOneRegU64(INT_REG(regs.pc)));
     pc.aarch64(inAArch64(tc));
     pc.thumb(cpsr.t);