diff --git a/src/cpu/kvm/base.cc b/src/cpu/kvm/base.cc index 32f94eca8..ea0f494e3 100644 --- a/src/cpu/kvm/base.cc +++ b/src/cpu/kvm/base.cc @@ -125,7 +125,7 @@ BaseKvmCPU::startup() const BaseKvmCPUParams * const p( dynamic_cast(params())); - Kvm &kvm(vm.kvm); + Kvm &kvm(*vm.kvm); BaseCPU::startup(); @@ -362,6 +362,29 @@ BaseKvmCPU::drainResume() } } +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() { @@ -617,6 +640,9 @@ Tick 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 --git a/src/cpu/kvm/base.hh b/src/cpu/kvm/base.hh index 4aeed2286..dd27328be 100644 --- a/src/cpu/kvm/base.hh +++ b/src/cpu/kvm/base.hh @@ -89,6 +89,7 @@ class BaseKvmCPU : public BaseCPU DrainState drain() override; void drainResume() override; + void notifyFork() override; void switchOut() override; void takeOverFrom(BaseCPU *cpu) override; diff --git a/src/cpu/kvm/vm.cc b/src/cpu/kvm/vm.cc index 87a76c242..ccf739305 100644 --- a/src/cpu/kvm/vm.cc +++ b/src/cpu/kvm/vm.cc @@ -291,12 +291,12 @@ Kvm::createVM() 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(KvmVMParams *params) 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 --git a/src/cpu/kvm/vm.hh b/src/cpu/kvm/vm.hh index 8f834a06e..560efb606 100644 --- a/src/cpu/kvm/vm.hh +++ b/src/cpu/kvm/vm.hh @@ -295,6 +295,8 @@ class KvmVM : public SimObject 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 @@ class KvmVM : public SimObject 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 @@ class KvmVM : public SimObject System *system; /** KVM VM file descriptor */ - const int vmFD; + int vmFD; /** Has delayedStartup() already been called? */ bool started; diff --git a/src/cpu/kvm/x86_cpu.cc b/src/cpu/kvm/x86_cpu.cc index f3e5edaed..c6c874dc4 100644 --- a/src/cpu/kvm/x86_cpu.cc +++ b/src/cpu/kvm/x86_cpu.cc @@ -519,7 +519,7 @@ X86KvmCPU::X86KvmCPU(X86KvmCPUParams *params) : 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 @@ X86KvmCPU::dumpVCpuEvents() const 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 @@ const Kvm::MSRIndexVector & 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) {