diff -r a3879dcefc27 -r 5d97d819326e 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(); void takeOverFrom(BaseCPU *cpu); diff -r a3879dcefc27 -r 5d97d819326e 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(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 a3879dcefc27 -r 5d97d819326e 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 a3879dcefc27 -r 5d97d819326e 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 a3879dcefc27 -r 5d97d819326e 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 msrs( newVarStruct( 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) {