changeset f3f72c0ab03e in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=f3f72c0ab03e
description:
kvm: Shutdown KVM and disconnect performance counters on fork
We can't/shouldn't use KVM after a fork since the child and parent
probably point to the same VM. Knowing the exact effects of this is
hard, but they are likely to be messy. We also disconnect the
performance counters attached to the guest. This works around what
seems to be a kernel bug where spurious SIGIOs get delivered to the
forked child process.
Signed-off-by: Andreas Sandberg <[email protected]>
[[email protected]: Rebased patches onto a newer gem5 version]
Signed-off-by: Sascha Bischoff <[email protected]>
[[email protected]: Fatal if entering KVM in child process ]
Signed-off-by: Andreas Sandberg <[email protected]>
diffstat:
src/cpu/kvm/base.cc | 28 +++++++++++++++++++++++++++-
src/cpu/kvm/base.hh | 1 +
src/cpu/kvm/vm.cc | 26 ++++++++++++++++++++++----
src/cpu/kvm/vm.hh | 6 ++++--
src/cpu/kvm/x86_cpu.cc | 6 +++---
5 files changed, 57 insertions(+), 10 deletions(-)
diffs (169 lines):
diff -r 04966a265ff9 -r f3f72c0ab03e src/cpu/kvm/base.cc
--- a/src/cpu/kvm/base.cc Thu Nov 26 10:11:57 2015 +0000
+++ b/src/cpu/kvm/base.cc Fri Nov 27 14:52:10 2015 +0000
@@ -125,7 +125,7 @@
const BaseKvmCPUParams * const p(
dynamic_cast<const BaseKvmCPUParams *>(params()));
- Kvm &kvm(vm.kvm);
+ Kvm &kvm(*vm.kvm);
BaseCPU::startup();
@@ -363,6 +363,29 @@
}
void
+BaseKvmCPU::notifyFork()
+{
+ // We should have drained prior to forking, which means that the
+ // tick event shouldn't be scheduled and the CPU is idle.
+ assert(!tickEvent.scheduled());
+ assert(_status == Idle);
+
+ if (vcpuFD != -1) {
+ if (close(vcpuFD) == -1)
+ warn("kvm CPU: notifyFork failed to close vcpuFD\n");
+
+ if (_kvmRun)
+ munmap(_kvmRun, vcpuMMapSize);
+
+ vcpuFD = -1;
+ _kvmRun = NULL;
+
+ hwInstructions.detach();
+ hwCycles.detach();
+ }
+}
+
+void
BaseKvmCPU::switchOut()
{
DPRINTF(Kvm, "switchOut\n");
@@ -617,6 +640,9 @@
BaseKvmCPU::kvmRun(Tick ticks)
{
Tick ticksExecuted;
+ fatal_if(vcpuFD == -1,
+ "Trying to run a KVM CPU in a forked child process. "
+ "This is not supported.\n");
DPRINTF(KvmRun, "KVM: Executing for %i ticks\n", ticks);
if (ticks == 0) {
diff -r 04966a265ff9 -r f3f72c0ab03e src/cpu/kvm/base.hh
--- a/src/cpu/kvm/base.hh Thu Nov 26 10:11:57 2015 +0000
+++ b/src/cpu/kvm/base.hh Fri Nov 27 14:52:10 2015 +0000
@@ -89,6 +89,7 @@
DrainState drain() override;
void drainResume() override;
+ void notifyFork() override;
void switchOut() override;
void takeOverFrom(BaseCPU *cpu) override;
diff -r 04966a265ff9 -r f3f72c0ab03e src/cpu/kvm/vm.cc
--- a/src/cpu/kvm/vm.cc Thu Nov 26 10:11:57 2015 +0000
+++ b/src/cpu/kvm/vm.cc Fri Nov 27 14:52:10 2015 +0000
@@ -291,12 +291,12 @@
KvmVM::KvmVM(KvmVMParams *params)
: SimObject(params),
- kvm(), system(params->system),
- vmFD(kvm.createVM()),
+ kvm(new Kvm()), system(params->system),
+ vmFD(kvm->createVM()),
started(false),
nextVCPUID(0)
{
- maxMemorySlot = kvm.capNumMemSlots();
+ maxMemorySlot = kvm->capNumMemSlots();
/* If we couldn't determine how memory slots there are, guess 32. */
if (!maxMemorySlot)
maxMemorySlot = 32;
@@ -307,7 +307,25 @@
KvmVM::~KvmVM()
{
- close(vmFD);
+ if (vmFD != -1)
+ close(vmFD);
+
+ if (kvm)
+ delete kvm;
+}
+
+void
+KvmVM::notifyFork()
+{
+ if (vmFD != -1) {
+ if (close(vmFD) == -1)
+ warn("kvm VM: notifyFork failed to close vmFD\n");
+
+ vmFD = -1;
+
+ delete kvm;
+ kvm = NULL;
+ }
}
void
diff -r 04966a265ff9 -r f3f72c0ab03e src/cpu/kvm/vm.hh
--- a/src/cpu/kvm/vm.hh Thu Nov 26 10:11:57 2015 +0000
+++ b/src/cpu/kvm/vm.hh Fri Nov 27 14:52:10 2015 +0000
@@ -295,6 +295,8 @@
KvmVM(KvmVMParams *params);
virtual ~KvmVM();
+ void notifyFork();
+
/**
* Setup a shared three-page memory region used by the internals
* of KVM. This is currently only needed by x86 implementations.
@@ -396,7 +398,7 @@
int createDevice(uint32_t type, uint32_t flags = 0);
/** Global KVM interface */
- Kvm kvm;
+ Kvm *kvm;
#if defined(__aarch64__)
public: // ARM-specific
@@ -504,7 +506,7 @@
System *system;
/** KVM VM file descriptor */
- const int vmFD;
+ int vmFD;
/** Has delayedStartup() already been called? */
bool started;
diff -r 04966a265ff9 -r f3f72c0ab03e src/cpu/kvm/x86_cpu.cc
--- a/src/cpu/kvm/x86_cpu.cc Thu Nov 26 10:11:57 2015 +0000
+++ b/src/cpu/kvm/x86_cpu.cc Fri Nov 27 14:52:10 2015 +0000
@@ -519,7 +519,7 @@
: BaseKvmCPU(params),
useXSave(params->useXSave)
{
- Kvm &kvm(vm.kvm);
+ Kvm &kvm(*vm.kvm);
if (!kvm.capSetTSSAddress())
panic("KVM: Missing capability (KVM_CAP_SET_TSS_ADDR)\n");
@@ -649,7 +649,7 @@
void
X86KvmCPU::dumpMSRs() const
{
- const Kvm::MSRIndexVector &supported_msrs(vm.kvm.getSupportedMSRs());
+ const Kvm::MSRIndexVector &supported_msrs(vm.kvm->getSupportedMSRs());
std::unique_ptr<struct kvm_msrs> msrs(
newVarStruct<struct kvm_msrs, struct kvm_msr_entry>(
supported_msrs.size()));
@@ -1539,7 +1539,7 @@
X86KvmCPU::getMsrIntersection() const
{
if (cachedMsrIntersection.empty()) {
- const Kvm::MSRIndexVector &kvm_msrs(vm.kvm.getSupportedMSRs());
+ const Kvm::MSRIndexVector &kvm_msrs(vm.kvm->getSupportedMSRs());
DPRINTF(Kvm, "kvm-x86: Updating MSR intersection\n");
for (auto it = kvm_msrs.cbegin(); it != kvm_msrs.cend(); ++it) {
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev