const BaseKvmCPUParams * const p(
dynamic_cast<const BaseKvmCPUParams *>(params()));
- Kvm &kvm(vm.kvm);
+ Kvm &kvm(*vm.kvm);
BaseCPU::startup();
}
}
+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()
{
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) {
DrainState drain() override;
void drainResume() override;
+ void notifyFork() override;
void switchOut() override;
void takeOverFrom(BaseCPU *cpu) override;
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;
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
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.
int createDevice(uint32_t type, uint32_t flags = 0);
/** Global KVM interface */
- Kvm kvm;
+ Kvm *kvm;
#if defined(__aarch64__)
public: // ARM-specific
System *system;
/** KVM VM file descriptor */
- const int vmFD;
+ int vmFD;
/** Has delayedStartup() already been called? */
bool started;
: 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");
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()));
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) {