vm.cc revision 11793
1/* 2 * Copyright 2014 Google, Inc. 3 * Copyright (c) 2012, 2015 ARM Limited 4 * All rights reserved 5 * 6 * The license below extends only to copyright in the software and shall 7 * not be construed as granting a license to any other intellectual 8 * property including but not limited to intellectual property relating 9 * to a hardware implementation of the functionality of the software 10 * licensed hereunder. You may use the software subject to the license 11 * terms below provided that you ensure that this notice is replicated 12 * unmodified and in its entirety in all distributions of the software, 13 * modified or unmodified, in source code or in binary form. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions are 17 * met: redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer; 19 * redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution; 22 * neither the name of the copyright holders nor the names of its 23 * contributors may be used to endorse or promote products derived from 24 * this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 * 38 * Authors: Andreas Sandberg 39 */ 40 41#include "cpu/kvm/vm.hh" 42 43#include <fcntl.h> 44#include <linux/kvm.h> 45#include <sys/ioctl.h> 46#include <sys/stat.h> 47#include <sys/types.h> 48#include <unistd.h> 49 50#include <cerrno> 51#include <memory> 52 53#include "debug/Kvm.hh" 54#include "params/KvmVM.hh" 55#include "sim/system.hh" 56 57#define EXPECTED_KVM_API_VERSION 12 58 59#if EXPECTED_KVM_API_VERSION != KVM_API_VERSION 60#error Unsupported KVM version 61#endif 62 63Kvm *Kvm::instance = NULL; 64 65Kvm::Kvm() 66 : kvmFD(-1), apiVersion(-1), vcpuMMapSize(0) 67{ 68 kvmFD = ::open("/dev/kvm", O_RDWR); 69 if (kvmFD == -1) 70 fatal("KVM: Failed to open /dev/kvm\n"); 71 72 apiVersion = ioctl(KVM_GET_API_VERSION); 73 if (apiVersion != EXPECTED_KVM_API_VERSION) 74 fatal("KVM: Incompatible API version\n"); 75 76 vcpuMMapSize = ioctl(KVM_GET_VCPU_MMAP_SIZE); 77 if (vcpuMMapSize == -1) 78 panic("KVM: Failed to get virtual CPU MMAP size\n"); 79} 80 81Kvm::~Kvm() 82{ 83 close(kvmFD); 84} 85 86Kvm * 87Kvm::create() 88{ 89 if (!instance) 90 instance = new Kvm(); 91 92 return instance; 93} 94 95bool 96Kvm::capUserMemory() const 97{ 98 return checkExtension(KVM_CAP_USER_MEMORY) != 0; 99} 100 101bool 102Kvm::capSetTSSAddress() const 103{ 104 return checkExtension(KVM_CAP_SET_TSS_ADDR) != 0; 105} 106 107bool 108Kvm::capExtendedCPUID() const 109{ 110 return checkExtension(KVM_CAP_EXT_CPUID) != 0; 111} 112 113bool 114Kvm::capUserNMI() const 115{ 116#ifdef KVM_CAP_USER_NMI 117 return checkExtension(KVM_CAP_USER_NMI) != 0; 118#else 119 return false; 120#endif 121} 122 123int 124Kvm::capCoalescedMMIO() const 125{ 126 return checkExtension(KVM_CAP_COALESCED_MMIO); 127} 128 129int 130Kvm::capNumMemSlots() const 131{ 132#ifdef KVM_CAP_NR_MEMSLOTS 133 return checkExtension(KVM_CAP_NR_MEMSLOTS); 134#else 135 return 0; 136#endif 137} 138 139bool 140Kvm::capOneReg() const 141{ 142#ifdef KVM_CAP_ONE_REG 143 return checkExtension(KVM_CAP_ONE_REG) != 0; 144#else 145 return false; 146#endif 147} 148 149bool 150Kvm::capIRQChip() const 151{ 152 return checkExtension(KVM_CAP_IRQCHIP) != 0; 153} 154 155bool 156Kvm::capVCPUEvents() const 157{ 158#ifdef KVM_CAP_VCPU_EVENTS 159 return checkExtension(KVM_CAP_VCPU_EVENTS) != 0; 160#else 161 return false; 162#endif 163} 164 165bool 166Kvm::capDebugRegs() const 167{ 168#ifdef KVM_CAP_DEBUGREGS 169 return checkExtension(KVM_CAP_DEBUGREGS) != 0; 170#else 171 return false; 172#endif 173} 174 175bool 176Kvm::capXCRs() const 177{ 178#ifdef KVM_CAP_XCRS 179 return checkExtension(KVM_CAP_XCRS) != 0; 180#else 181 return false; 182#endif 183} 184 185bool 186Kvm::capXSave() const 187{ 188#ifdef KVM_CAP_XSAVE 189 return checkExtension(KVM_CAP_XSAVE) != 0; 190#else 191 return false; 192#endif 193} 194 195 196#if defined(__i386__) || defined(__x86_64__) 197bool 198Kvm::getSupportedCPUID(struct kvm_cpuid2 &cpuid) const 199{ 200 if (ioctl(KVM_GET_SUPPORTED_CPUID, (void *)&cpuid) == -1) { 201 if (errno == E2BIG) 202 return false; 203 else 204 panic("KVM: Failed to get supported CPUID (errno: %i)\n", errno); 205 } else 206 return true; 207} 208 209const Kvm::CPUIDVector & 210Kvm::getSupportedCPUID() const 211{ 212 if (supportedCPUIDCache.empty()) { 213 std::unique_ptr<struct kvm_cpuid2> cpuid; 214 int i(1); 215 do { 216 cpuid.reset((struct kvm_cpuid2 *)operator new( 217 sizeof(kvm_cpuid2) + i * sizeof(kvm_cpuid_entry2))); 218 219 cpuid->nent = i; 220 ++i; 221 } while (!getSupportedCPUID(*cpuid)); 222 supportedCPUIDCache.assign(cpuid->entries, 223 cpuid->entries + cpuid->nent); 224 } 225 226 return supportedCPUIDCache; 227} 228 229bool 230Kvm::getSupportedMSRs(struct kvm_msr_list &msrs) const 231{ 232 if (ioctl(KVM_GET_MSR_INDEX_LIST, (void *)&msrs) == -1) { 233 if (errno == E2BIG) 234 return false; 235 else 236 panic("KVM: Failed to get supported CPUID (errno: %i)\n", errno); 237 } else 238 return true; 239} 240 241const Kvm::MSRIndexVector & 242Kvm::getSupportedMSRs() const 243{ 244 if (supportedMSRCache.empty()) { 245 std::unique_ptr<struct kvm_msr_list> msrs; 246 int i(0); 247 do { 248 msrs.reset((struct kvm_msr_list *)operator new( 249 sizeof(kvm_msr_list) + i * sizeof(uint32_t))); 250 251 msrs->nmsrs = i; 252 ++i; 253 } while (!getSupportedMSRs(*msrs)); 254 supportedMSRCache.assign(msrs->indices, msrs->indices + msrs->nmsrs); 255 } 256 257 return supportedMSRCache; 258} 259 260#endif // x86-specific 261 262 263int 264Kvm::checkExtension(int extension) const 265{ 266 int ret = ioctl(KVM_CHECK_EXTENSION, extension); 267 if (ret == -1) 268 panic("KVM: ioctl failed when checking for extension\n"); 269 return ret; 270} 271 272int 273Kvm::ioctl(int request, long p1) const 274{ 275 assert(kvmFD != -1); 276 277 return ::ioctl(kvmFD, request, p1); 278} 279 280int 281Kvm::createVM() 282{ 283 int vmFD; 284 285 vmFD = ioctl(KVM_CREATE_VM); 286 if (vmFD == -1) 287 panic("Failed to create KVM VM\n"); 288 289 return vmFD; 290} 291 292 293KvmVM::KvmVM(KvmVMParams *params) 294 : SimObject(params), 295 kvm(new Kvm()), system(params->system), 296 vmFD(kvm->createVM()), 297 started(false), 298 nextVCPUID(0) 299{ 300 maxMemorySlot = kvm->capNumMemSlots(); 301 /* If we couldn't determine how memory slots there are, guess 32. */ 302 if (!maxMemorySlot) 303 maxMemorySlot = 32; 304 /* Setup the coalesced MMIO regions */ 305 for (int i = 0; i < params->coalescedMMIO.size(); ++i) 306 coalesceMMIO(params->coalescedMMIO[i]); 307} 308 309KvmVM::~KvmVM() 310{ 311 if (vmFD != -1) 312 close(vmFD); 313 314 if (kvm) 315 delete kvm; 316} 317 318void 319KvmVM::notifyFork() 320{ 321 if (vmFD != -1) { 322 if (close(vmFD) == -1) 323 warn("kvm VM: notifyFork failed to close vmFD\n"); 324 325 vmFD = -1; 326 327 delete kvm; 328 kvm = NULL; 329 } 330} 331 332void 333KvmVM::cpuStartup() 334{ 335 if (started) 336 return; 337 started = true; 338 339 delayedStartup(); 340} 341 342void 343KvmVM::delayedStartup() 344{ 345 const std::vector<BackingStoreEntry> &memories( 346 system->getPhysMem().getBackingStore()); 347 348 DPRINTF(Kvm, "Mapping %i memory region(s)\n", memories.size()); 349 for (int slot(0); slot < memories.size(); ++slot) { 350 if (!memories[slot].kvmMap) { 351 DPRINTF(Kvm, "Skipping region marked as not usable by KVM\n"); 352 continue; 353 } 354 355 const AddrRange &range(memories[slot].range); 356 void *pmem(memories[slot].pmem); 357 358 if (pmem) { 359 DPRINTF(Kvm, "Mapping region: 0x%p -> 0x%llx [size: 0x%llx]\n", 360 pmem, range.start(), range.size()); 361 362 if (range.interleaved()) { 363 panic("Tried to map an interleaved memory range into " 364 "a KVM VM.\n"); 365 } 366 367 const MemSlot slot = allocMemSlot(range.size()); 368 setupMemSlot(slot, pmem, range.start(), 0/* flags */); 369 } else { 370 DPRINTF(Kvm, "Zero-region not mapped: [0x%llx]\n", range.start()); 371 hack("KVM: Zero memory handled as IO\n"); 372 } 373 } 374} 375 376const KvmVM::MemSlot 377KvmVM::allocMemSlot(uint64_t size) 378{ 379 if (!size) 380 panic("Memory slots must have non-zero size.\n"); 381 382 std::vector<MemorySlot>::iterator pos; 383 for (pos = memorySlots.begin(); pos != memorySlots.end(); pos++) { 384 if (!pos->size) { 385 pos->size = size; 386 pos->active = false; 387 return pos->slot; 388 } 389 } 390 391 uint32_t nextSlot = memorySlots.size(); 392 if (nextSlot > maxMemorySlot) 393 panic("Out of memory slots.\n"); 394 395 MemorySlot slot; 396 slot.size = size; 397 slot.slot = nextSlot; 398 slot.active = false; 399 400 memorySlots.push_back(slot); 401 return MemSlot(slot.slot); 402} 403 404void 405KvmVM::setupMemSlot(const KvmVM::MemSlot num, void *host_addr, Addr guest, 406 uint32_t flags) 407{ 408 MemorySlot &slot = memorySlots.at(num.num); 409 slot.active = true; 410 setUserMemoryRegion(num.num, host_addr, guest, slot.size, flags); 411} 412 413void 414KvmVM::disableMemSlot(const KvmVM::MemSlot num) 415{ 416 MemorySlot &slot = memorySlots.at(num.num); 417 if (slot.active) 418 setUserMemoryRegion(num.num, NULL, 0, 0, 0); 419 slot.active = false; 420} 421 422void 423KvmVM::freeMemSlot(const KvmVM::MemSlot num) 424{ 425 disableMemSlot(num.num); 426 MemorySlot &slot = memorySlots.at(num.num); 427 slot.size = 0; 428} 429 430void 431KvmVM::setUserMemoryRegion(uint32_t slot, 432 void *host_addr, Addr guest_addr, 433 uint64_t len, uint32_t flags) 434{ 435 struct kvm_userspace_memory_region m; 436 437 memset(&m, 0, sizeof(m)); 438 m.slot = slot; 439 m.flags = flags; 440 m.guest_phys_addr = (uint64_t)guest_addr; 441 m.memory_size = len; 442 m.userspace_addr = (__u64)host_addr; 443 444 if (ioctl(KVM_SET_USER_MEMORY_REGION, (void *)&m) == -1) { 445 panic("Failed to setup KVM memory region:\n" 446 "\tHost Address: 0x%p\n" 447 "\tGuest Address: 0x%llx\n", 448 "\tSize: %ll\n", 449 "\tFlags: 0x%x\n", 450 m.userspace_addr, m.guest_phys_addr, 451 m.memory_size, m.flags); 452 } 453} 454 455void 456KvmVM::coalesceMMIO(const AddrRange &range) 457{ 458 coalesceMMIO(range.start(), range.size()); 459} 460 461void 462KvmVM::coalesceMMIO(Addr start, int size) 463{ 464 struct kvm_coalesced_mmio_zone zone; 465 466 zone.addr = start; 467 zone.size = size; 468 zone.pad = 0; 469 470 DPRINTF(Kvm, "KVM: Registering coalesced MMIO region [0x%x, 0x%x]\n", 471 zone.addr, zone.addr + zone.size - 1); 472 if (ioctl(KVM_REGISTER_COALESCED_MMIO, (void *)&zone) == -1) 473 panic("KVM: Failed to register coalesced MMIO region (%i)\n", 474 errno); 475} 476 477void 478KvmVM::setTSSAddress(Addr tss_address) 479{ 480 if (ioctl(KVM_SET_TSS_ADDR, (unsigned long)tss_address) == -1) 481 panic("KVM: Failed to set VM TSS address\n"); 482} 483 484void 485KvmVM::createIRQChip() 486{ 487 if (_hasKernelIRQChip) 488 panic("KvmVM::createIRQChip called twice.\n"); 489 490 if (ioctl(KVM_CREATE_IRQCHIP) != -1) { 491 _hasKernelIRQChip = true; 492 } else { 493 warn("KVM: Failed to create in-kernel IRQ chip (errno: %i)\n", 494 errno); 495 _hasKernelIRQChip = false; 496 } 497} 498 499void 500KvmVM::setIRQLine(uint32_t irq, bool high) 501{ 502 struct kvm_irq_level kvm_level; 503 504 kvm_level.irq = irq; 505 kvm_level.level = high ? 1 : 0; 506 507 if (ioctl(KVM_IRQ_LINE, &kvm_level) == -1) 508 panic("KVM: Failed to set IRQ line level (errno: %i)\n", 509 errno); 510} 511 512int 513KvmVM::createDevice(uint32_t type, uint32_t flags) 514{ 515#if defined(KVM_CREATE_DEVICE) 516 struct kvm_create_device dev = { type, 0, flags }; 517 518 if (ioctl(KVM_CREATE_DEVICE, &dev) == -1) { 519 panic("KVM: Failed to create device (errno: %i)\n", 520 errno); 521 } 522 523 return dev.fd; 524#else 525 panic("Kernel headers don't support KVM_CREATE_DEVICE\n"); 526#endif 527} 528 529int 530KvmVM::createVCPU(long vcpuID) 531{ 532 int fd; 533 534 fd = ioctl(KVM_CREATE_VCPU, vcpuID); 535 if (fd == -1) 536 panic("KVM: Failed to create virtual CPU"); 537 538 return fd; 539} 540 541long 542KvmVM::allocVCPUID() 543{ 544 return nextVCPUID++; 545} 546 547#if defined(__aarch64__) 548void 549KvmVM::kvmArmPreferredTarget(struct kvm_vcpu_init &target) const 550{ 551 if (ioctl(KVM_ARM_PREFERRED_TARGET, &target) == -1) { 552 panic("KVM: Failed to get ARM preferred CPU target (errno: %i)\n", 553 errno); 554 } 555} 556#endif 557 558int 559KvmVM::ioctl(int request, long p1) const 560{ 561 assert(vmFD != -1); 562 563 return ::ioctl(vmFD, request, p1); 564} 565 566 567KvmVM * 568KvmVMParams::create() 569{ 570 static bool created = false; 571 if (created) 572 warn_once("Use of multiple KvmVMs is currently untested!\n"); 573 574 created = true; 575 576 return new KvmVM(this); 577} 578