diff options
author | Andreas Sandberg <andreas@sandberg.pp.se> | 2014-03-16 17:30:24 +0100 |
---|---|---|
committer | Andreas Sandberg <andreas@sandberg.pp.se> | 2014-03-16 17:30:24 +0100 |
commit | 5db547bca46f23aa5cf25aa5d38efae9ef1eabc2 (patch) | |
tree | 01db21e126164a21473bc5e4aecca88520562ca3 | |
parent | f791e7b313c6f5c2b30f96c35f675d523def8a3a (diff) | |
download | gem5-5db547bca46f23aa5cf25aa5d38efae9ef1eabc2.tar.xz |
kvm: x86: Adjust PC to remove the CS segment base address
gem5 seems to store the PC as RIP+CS_BASE. This is not what KVM
expects, so we need to subtract CS_BASE prior to transferring the PC
into KVM. This changeset adds the necessary PC manipulation and
refactors thread context updates slightly to avoid reading registers
multiple times from KVM.
--HG--
extra : rebase_source : 3f0569dca06a1fcd8694925f75c8918d954ada44
-rw-r--r-- | src/cpu/kvm/x86_cpu.cc | 51 | ||||
-rw-r--r-- | src/cpu/kvm/x86_cpu.hh | 9 |
2 files changed, 32 insertions, 28 deletions
diff --git a/src/cpu/kvm/x86_cpu.cc b/src/cpu/kvm/x86_cpu.cc index 3313c8db0..ea8c47082 100644 --- a/src/cpu/kvm/x86_cpu.cc +++ b/src/cpu/kvm/x86_cpu.cc @@ -690,7 +690,7 @@ X86KvmCPU::updateKvmStateRegs() FOREACH_IREG(); #undef APPLY_IREG - regs.rip = tc->instAddr(); + regs.rip = tc->instAddr() - tc->readMiscReg(MISCREG_CS_BASE); /* You might think that setting regs.rflags to the contents * MISCREG_RFLAGS here would suffice. In that case you're @@ -936,16 +936,29 @@ X86KvmCPU::updateKvmStateMSRs() void X86KvmCPU::updateThreadContext() { + struct kvm_regs regs; + struct kvm_sregs sregs; + + getRegisters(regs); + getSpecialRegisters(sregs); + DPRINTF(KvmContext, "X86KvmCPU::updateThreadContext():\n"); if (DTRACE(KvmContext)) dump(); - updateThreadContextRegs(); - updateThreadContextSRegs(); - if (useXSave) - updateThreadContextXSave(); - else - updateThreadContextFPU(); + updateThreadContextRegs(regs, sregs); + updateThreadContextSRegs(sregs); + if (useXSave) { + struct kvm_xsave xsave; + getXSave(xsave); + + updateThreadContextXSave(xsave); + } else { + struct kvm_fpu fpu; + getFPUState(fpu); + + updateThreadContextFPU(fpu); + } updateThreadContextMSRs(); // The M5 misc reg caches some values from other @@ -955,18 +968,16 @@ X86KvmCPU::updateThreadContext() } void -X86KvmCPU::updateThreadContextRegs() +X86KvmCPU::updateThreadContextRegs(const struct kvm_regs ®s, + const struct kvm_sregs &sregs) { - struct kvm_regs regs; - getRegisters(regs); - #define APPLY_IREG(kreg, mreg) tc->setIntReg(mreg, regs.kreg) FOREACH_IREG(); #undef APPLY_IREG - tc->pcState(PCState(regs.rip)); + tc->pcState(PCState(regs.rip + sregs.cs.base)); // Flags are spread out across multiple semi-magic registers so we // need some special care when updating them. @@ -1011,11 +1022,8 @@ setContextSegment(ThreadContext *tc, const struct kvm_dtable &kvm_dtable, } void -X86KvmCPU::updateThreadContextSRegs() +X86KvmCPU::updateThreadContextSRegs(const struct kvm_sregs &sregs) { - struct kvm_sregs sregs; - getSpecialRegisters(sregs); - assert(getKvmRunState()->apic_base == sregs.apic_base); assert(getKvmRunState()->cr8 == sregs.cr8); @@ -1070,11 +1078,8 @@ updateThreadContextFPUCommon(ThreadContext *tc, const T &fpu) } void -X86KvmCPU::updateThreadContextFPU() +X86KvmCPU::updateThreadContextFPU(const struct kvm_fpu &fpu) { - struct kvm_fpu fpu; - getFPUState(fpu); - updateThreadContextFPUCommon(tc, fpu); tc->setMiscRegNoEffect(MISCREG_FISEG, 0); @@ -1084,11 +1089,9 @@ X86KvmCPU::updateThreadContextFPU() } void -X86KvmCPU::updateThreadContextXSave() +X86KvmCPU::updateThreadContextXSave(const struct kvm_xsave &kxsave) { - struct kvm_xsave kxsave; - FXSave &xsave(*(FXSave *)kxsave.region); - getXSave(kxsave); + const FXSave &xsave(*(const FXSave *)kxsave.region); updateThreadContextFPUCommon(tc, xsave); diff --git a/src/cpu/kvm/x86_cpu.hh b/src/cpu/kvm/x86_cpu.hh index 7dacdb03f..bfd090ff7 100644 --- a/src/cpu/kvm/x86_cpu.hh +++ b/src/cpu/kvm/x86_cpu.hh @@ -209,13 +209,14 @@ class X86KvmCPU : public BaseKvmCPU * @{ */ /** Update integer registers */ - void updateThreadContextRegs(); + void updateThreadContextRegs(const struct kvm_regs ®s, + const struct kvm_sregs &sregs); /** Update control registers (CRx, segments, etc.) */ - void updateThreadContextSRegs(); + void updateThreadContextSRegs(const struct kvm_sregs &sregs); /** Update FPU and SIMD registers using the legacy API */ - void updateThreadContextFPU(); + void updateThreadContextFPU(const struct kvm_fpu &fpu); /** Update FPU and SIMD registers using the XSave API */ - void updateThreadContextXSave(); + void updateThreadContextXSave(const struct kvm_xsave &kxsave); /** Update MSR registers */ void updateThreadContextMSRs(); /** @} */ |