vm.cc revision 10859
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 <linux/kvm.h> 42#include <sys/ioctl.h> 43#include <sys/stat.h> 44#include <sys/types.h> 45#include <fcntl.h> 46#include <unistd.h> 47 48#include <cerrno> 49#include <memory> 50 51#include "cpu/kvm/vm.hh" 52#include "debug/Kvm.hh" 53#include "params/KvmVM.hh" 54#include "sim/system.hh" 55 56#define EXPECTED_KVM_API_VERSION 12 57 58#if EXPECTED_KVM_API_VERSION != KVM_API_VERSION 59#error Unsupported KVM version 60#endif 61 62Kvm *Kvm::instance = NULL; 63 64Kvm::Kvm() 65 : kvmFD(-1), apiVersion(-1), vcpuMMapSize(0) 66{ 67 kvmFD = ::open("/dev/kvm", O_RDWR); 68 if (kvmFD == -1) 69 fatal("KVM: Failed to open /dev/kvm\n"); 70 71 apiVersion = ioctl(KVM_GET_API_VERSION); 72 if (apiVersion != EXPECTED_KVM_API_VERSION) 73 fatal("KVM: Incompatible API version\n"); 74 75 vcpuMMapSize = ioctl(KVM_GET_VCPU_MMAP_SIZE); 76 if (vcpuMMapSize == -1) 77 panic("KVM: Failed to get virtual CPU MMAP size\n"); 78} 79 80Kvm::~Kvm() 81{ 82 close(kvmFD); 83} 84 85Kvm * 86Kvm::create() 87{ 88 if (!instance) 89 instance = new Kvm(); 90 91 return instance; 92} 93 94bool 95Kvm::capUserMemory() const 96{ 97 return checkExtension(KVM_CAP_USER_MEMORY) != 0; 98} 99 100bool 101Kvm::capSetTSSAddress() const 102{ 103 return checkExtension(KVM_CAP_SET_TSS_ADDR) != 0; 104} 105 106bool 107Kvm::capExtendedCPUID() const 108{ 109 return checkExtension(KVM_CAP_EXT_CPUID) != 0; 110} 111 112bool 113Kvm::capUserNMI() const 114{ 115#ifdef KVM_CAP_USER_NMI 116 return checkExtension(KVM_CAP_USER_NMI) != 0; 117#else 118 return false; 119#endif 120} 121 122int 123Kvm::capCoalescedMMIO() const 124{ 125 return checkExtension(KVM_CAP_COALESCED_MMIO); 126} 127 128int 129Kvm::capNumMemSlots() const 130{ 131#ifdef KVM_CAP_NR_MEMSLOTS 132 return checkExtension(KVM_CAP_NR_MEMSLOTS); 133#else 134 return 0; 135#endif 136} 137 138bool 139Kvm::capOneReg() const 140{ 141#ifdef KVM_CAP_ONE_REG 142 return checkExtension(KVM_CAP_ONE_REG) != 0; 143#else 144 return false; 145#endif 146} 147 148bool 149Kvm::capIRQChip() const 150{ 151 return checkExtension(KVM_CAP_IRQCHIP) != 0; 152} 153 154bool 155Kvm::capVCPUEvents() const 156{ 157#ifdef KVM_CAP_VCPU_EVENTS 158 return checkExtension(KVM_CAP_VCPU_EVENTS) != 0; 159#else 160 return false; 161#endif 162} 163 164bool 165Kvm::capDebugRegs() const 166{ 167#ifdef KVM_CAP_DEBUGREGS 168 return checkExtension(KVM_CAP_DEBUGREGS) != 0; 169#else 170 return false; 171#endif 172} 173 174bool 175Kvm::capXCRs() const 176{ 177#ifdef KVM_CAP_XCRS 178 return checkExtension(KVM_CAP_XCRS) != 0; 179#else 180 return false; 181#endif 182} 183 184bool 185Kvm::capXSave() const 186{ 187#ifdef KVM_CAP_XSAVE 188 return checkExtension(KVM_CAP_XSAVE) != 0; 189#else 190 return false; 191#endif 192} 193 194 195#if defined(__i386__) || defined(__x86_64__) 196bool 197Kvm::getSupportedCPUID(struct kvm_cpuid2 &cpuid) const 198{ 199 if (ioctl(KVM_GET_SUPPORTED_CPUID, (void *)&cpuid) == -1) { 200 if (errno == E2BIG) 201 return false; 202 else 203 panic("KVM: Failed to get supported CPUID (errno: %i)\n", errno); 204 } else 205 return true; 206} 207 208const Kvm::CPUIDVector & 209Kvm::getSupportedCPUID() const 210{ 211 if (supportedCPUIDCache.empty()) { 212 std::unique_ptr<struct kvm_cpuid2> cpuid; 213 int i(1); 214 do { 215 cpuid.reset((struct kvm_cpuid2 *)operator new( 216 sizeof(kvm_cpuid2) + i * sizeof(kvm_cpuid_entry2))); 217 218 cpuid->nent = i; 219 ++i; 220 } while (!getSupportedCPUID(*cpuid)); 221 supportedCPUIDCache.assign(cpuid->entries, 222 cpuid->entries + cpuid->nent); 223 } 224 225 return supportedCPUIDCache; 226} 227 228bool 229Kvm::getSupportedMSRs(struct kvm_msr_list &msrs) const 230{ 231 if (ioctl(KVM_GET_MSR_INDEX_LIST, (void *)&msrs) == -1) { 232 if (errno == E2BIG) 233 return false; 234 else 235 panic("KVM: Failed to get supported CPUID (errno: %i)\n", errno); 236 } else 237 return true; 238} 239 240const Kvm::MSRIndexVector & 241Kvm::getSupportedMSRs() const 242{ 243 if (supportedMSRCache.empty()) { 244 std::unique_ptr<struct kvm_msr_list> msrs; 245 int i(0); 246 do { 247 msrs.reset((struct kvm_msr_list *)operator new( 248 sizeof(kvm_msr_list) + i * sizeof(uint32_t))); 249 250 msrs->nmsrs = i; 251 ++i; 252 } while (!getSupportedMSRs(*msrs)); 253 supportedMSRCache.assign(msrs->indices, msrs->indices + msrs->nmsrs); 254 } 255 256 return supportedMSRCache; 257} 258 259#endif // x86-specific 260 261 262int 263Kvm::checkExtension(int extension) const 264{ 265 int ret = ioctl(KVM_CHECK_EXTENSION, extension); 266 if (ret == -1) 267 panic("KVM: ioctl failed when checking for extension\n"); 268 return ret; 269} 270 271int 272Kvm::ioctl(int request, long p1) const 273{ 274 assert(kvmFD != -1); 275 276 return ::ioctl(kvmFD, request, p1); 277} 278 279int 280Kvm::createVM() 281{ 282 int vmFD; 283 284 vmFD = ioctl(KVM_CREATE_VM); 285 if (vmFD == -1) 286 panic("Failed to create KVM VM\n"); 287 288 return vmFD; 289} 290 291 292KvmVM::KvmVM(KvmVMParams *params) 293 : SimObject(params), 294 kvm(), system(params->system), 295 vmFD(kvm.createVM()), 296 started(false), 297 nextVCPUID(0) 298{ 299 maxMemorySlot = kvm.capNumMemSlots(); 300 /* If we couldn't determine how memory slots there are, guess 32. */ 301 if (!maxMemorySlot) 302 maxMemorySlot = 32; 303 /* Setup the coalesced MMIO regions */ 304 for (int i = 0; i < params->coalescedMMIO.size(); ++i) 305 coalesceMMIO(params->coalescedMMIO[i]); 306} 307 308KvmVM::~KvmVM() 309{ 310 close(vmFD); 311} 312 313void 314KvmVM::cpuStartup() 315{ 316 if (started) 317 return; 318 started = true; 319 320 delayedStartup(); 321} 322 323void 324KvmVM::delayedStartup() 325{ 326 const std::vector<std::pair<AddrRange, uint8_t*> >&memories( 327 system->getPhysMem().getBackingStore()); 328 329 DPRINTF(Kvm, "Mapping %i memory region(s)\n", memories.size()); 330 for (int slot(0); slot < memories.size(); ++slot) { 331 const AddrRange &range(memories[slot].first); 332 void *pmem(memories[slot].second); 333 334 if (pmem) { 335 DPRINTF(Kvm, "Mapping region: 0x%p -> 0x%llx [size: 0x%llx]\n", 336 pmem, range.start(), range.size()); 337 338 if (range.interleaved()) { 339 panic("Tried to map an interleaved memory range into " 340 "a KVM VM.\n"); 341 } 342 343 const MemSlot slot = allocMemSlot(range.size()); 344 setupMemSlot(slot, pmem, range.start(), 0/* flags */); 345 } else { 346 DPRINTF(Kvm, "Zero-region not mapped: [0x%llx]\n", range.start()); 347 hack("KVM: Zero memory handled as IO\n"); 348 } 349 } 350} 351 352const KvmVM::MemSlot 353KvmVM::allocMemSlot(uint64_t size) 354{ 355 if (!size) 356 panic("Memory slots must have non-zero size.\n"); 357 358 std::vector<MemorySlot>::iterator pos; 359 for (pos = memorySlots.begin(); pos != memorySlots.end(); pos++) { 360 if (!pos->size) { 361 pos->size = size; 362 pos->active = false; 363 return pos->slot; 364 } 365 } 366 367 uint32_t nextSlot = memorySlots.size(); 368 if (nextSlot > maxMemorySlot) 369 panic("Out of memory slots.\n"); 370 371 MemorySlot slot; 372 slot.size = size; 373 slot.slot = nextSlot; 374 slot.active = false; 375 376 memorySlots.push_back(slot); 377 return MemSlot(slot.slot); 378} 379 380void 381KvmVM::setupMemSlot(const KvmVM::MemSlot num, void *host_addr, Addr guest, 382 uint32_t flags) 383{ 384 MemorySlot &slot = memorySlots.at(num.num); 385 slot.active = true; 386 setUserMemoryRegion(num.num, host_addr, guest, slot.size, flags); 387} 388 389void 390KvmVM::disableMemSlot(const KvmVM::MemSlot num) 391{ 392 MemorySlot &slot = memorySlots.at(num.num); 393 if (slot.active) 394 setUserMemoryRegion(num.num, NULL, 0, 0, 0); 395 slot.active = false; 396} 397 398void 399KvmVM::freeMemSlot(const KvmVM::MemSlot num) 400{ 401 disableMemSlot(num.num); 402 MemorySlot &slot = memorySlots.at(num.num); 403 slot.size = 0; 404} 405 406void 407KvmVM::setUserMemoryRegion(uint32_t slot, 408 void *host_addr, Addr guest_addr, 409 uint64_t len, uint32_t flags) 410{ 411 struct kvm_userspace_memory_region m; 412 413 memset(&m, 0, sizeof(m)); 414 m.slot = slot; 415 m.flags = flags; 416 m.guest_phys_addr = (uint64_t)guest_addr; 417 m.memory_size = len; 418 m.userspace_addr = (__u64)host_addr; 419 420 if (ioctl(KVM_SET_USER_MEMORY_REGION, (void *)&m) == -1) { 421 panic("Failed to setup KVM memory region:\n" 422 "\tHost Address: 0x%p\n" 423 "\tGuest Address: 0x%llx\n", 424 "\tSize: %ll\n", 425 "\tFlags: 0x%x\n", 426 m.userspace_addr, m.guest_phys_addr, 427 m.memory_size, m.flags); 428 } 429} 430 431void 432KvmVM::coalesceMMIO(const AddrRange &range) 433{ 434 coalesceMMIO(range.start(), range.size()); 435} 436 437void 438KvmVM::coalesceMMIO(Addr start, int size) 439{ 440 struct kvm_coalesced_mmio_zone zone; 441 442 zone.addr = start; 443 zone.size = size; 444 zone.pad = 0; 445 446 DPRINTF(Kvm, "KVM: Registering coalesced MMIO region [0x%x, 0x%x]\n", 447 zone.addr, zone.addr + zone.size - 1); 448 if (ioctl(KVM_REGISTER_COALESCED_MMIO, (void *)&zone) == -1) 449 panic("KVM: Failed to register coalesced MMIO region (%i)\n", 450 errno); 451} 452 453void 454KvmVM::setTSSAddress(Addr tss_address) 455{ 456 if (ioctl(KVM_SET_TSS_ADDR, (unsigned long)tss_address) == -1) 457 panic("KVM: Failed to set VM TSS address\n"); 458} 459 460void 461KvmVM::createIRQChip() 462{ 463 if (_hasKernelIRQChip) 464 panic("KvmVM::createIRQChip called twice.\n"); 465 466 if (ioctl(KVM_CREATE_IRQCHIP) != -1) { 467 _hasKernelIRQChip = true; 468 } else { 469 warn("KVM: Failed to create in-kernel IRQ chip (errno: %i)\n", 470 errno); 471 _hasKernelIRQChip = false; 472 } 473} 474 475void 476KvmVM::setIRQLine(uint32_t irq, bool high) 477{ 478 struct kvm_irq_level kvm_level; 479 480 kvm_level.irq = irq; 481 kvm_level.level = high ? 1 : 0; 482 483 if (ioctl(KVM_IRQ_LINE, &kvm_level) == -1) 484 panic("KVM: Failed to set IRQ line level (errno: %i)\n", 485 errno); 486} 487 488int 489KvmVM::createDevice(uint32_t type, uint32_t flags) 490{ 491#if defined(KVM_CREATE_DEVICE) 492 struct kvm_create_device dev = { type, 0, flags }; 493 494 if (ioctl(KVM_CREATE_DEVICE, &dev) == -1) { 495 panic("KVM: Failed to create device (errno: %i)\n", 496 errno); 497 } 498 499 return dev.fd; 500#else 501 panic("Kernel headers don't support KVM_CREATE_DEVICE\n"); 502#endif 503} 504 505int 506KvmVM::createVCPU(long vcpuID) 507{ 508 int fd; 509 510 fd = ioctl(KVM_CREATE_VCPU, vcpuID); 511 if (fd == -1) 512 panic("KVM: Failed to create virtual CPU"); 513 514 return fd; 515} 516 517long 518KvmVM::allocVCPUID() 519{ 520 return nextVCPUID++; 521} 522 523int 524KvmVM::ioctl(int request, long p1) const 525{ 526 assert(vmFD != -1); 527 528 return ::ioctl(vmFD, request, p1); 529} 530 531 532KvmVM * 533KvmVMParams::create() 534{ 535 static bool created = false; 536 if (created) 537 warn_once("Use of multiple KvmVMs is currently untested!\n"); 538 539 created = true; 540 541 return new KvmVM(this); 542} 543