/*
* Copyright 2014 Google, Inc.
- * Copyright (c) 2012 ARM Limited
+ * Copyright (c) 2012, 2015 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* Authors: Andreas Sandberg
*/
+#include "cpu/kvm/vm.hh"
+
+#include <fcntl.h>
#include <linux/kvm.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <memory>
-#include "cpu/kvm/vm.hh"
#include "debug/Kvm.hh"
#include "params/KvmVM.hh"
#include "sim/system.hh"
KvmVM::KvmVM(KvmVMParams *params)
: SimObject(params),
- kvm(), system(params->system),
- vmFD(kvm.createVM()),
+ kvm(new Kvm()), system(nullptr),
+ 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
void
KvmVM::delayedStartup()
{
- const std::vector<std::pair<AddrRange, uint8_t*> >&memories(
+ assert(system); // set by the system during its construction
+ const std::vector<BackingStoreEntry> &memories(
system->getPhysMem().getBackingStore());
DPRINTF(Kvm, "Mapping %i memory region(s)\n", memories.size());
for (int slot(0); slot < memories.size(); ++slot) {
- const AddrRange &range(memories[slot].first);
- void *pmem(memories[slot].second);
+ if (!memories[slot].kvmMap) {
+ DPRINTF(Kvm, "Skipping region marked as not usable by KVM\n");
+ continue;
+ }
+
+ const AddrRange &range(memories[slot].range);
+ void *pmem(memories[slot].pmem);
if (pmem) {
DPRINTF(Kvm, "Mapping region: 0x%p -> 0x%llx [size: 0x%llx]\n",
errno);
}
+int
+KvmVM::createDevice(uint32_t type, uint32_t flags)
+{
+#if defined(KVM_CREATE_DEVICE)
+ struct kvm_create_device dev = { type, 0, flags };
+
+ if (ioctl(KVM_CREATE_DEVICE, &dev) == -1) {
+ panic("KVM: Failed to create device (errno: %i)\n",
+ errno);
+ }
+
+ return dev.fd;
+#else
+ panic("Kernel headers don't support KVM_CREATE_DEVICE\n");
+#endif
+}
+
+void
+KvmVM::setSystem(System *s) {
+ panic_if(system != nullptr, "setSystem() can only be called once");
+ panic_if(s == nullptr, "setSystem() called with null System*");
+ system = s;
+}
+
int
KvmVM::createVCPU(long vcpuID)
{
return nextVCPUID++;
}
+#if defined(__aarch64__)
+void
+KvmVM::kvmArmPreferredTarget(struct kvm_vcpu_init &target) const
+{
+ if (ioctl(KVM_ARM_PREFERRED_TARGET, &target) == -1) {
+ panic("KVM: Failed to get ARM preferred CPU target (errno: %i)\n",
+ errno);
+ }
+}
+#endif
+
int
KvmVM::ioctl(int request, long p1) const
{