vm.hh revision 11363:f3f72c0ab03e
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#ifndef __CPU_KVM_KVMVM_HH__ 42#define __CPU_KVM_KVMVM_HH__ 43 44#include <vector> 45 46#include "base/addr_range.hh" 47#include "sim/sim_object.hh" 48 49// forward declarations 50struct KvmVMParams; 51class System; 52 53/** 54 * @defgroup KvmInterrupts KVM Interrupt handling. 55 * 56 * These methods control interrupt delivery to the guest system. 57 */ 58 59/** 60 * @defgroup KvmIoctl KVM low-level ioctl interface. 61 * 62 * These methods provide a low-level interface to the underlying KVM 63 * layer. 64 */ 65 66/** 67 * KVM parent interface 68 * 69 * The main Kvm object is used to provide functionality that is not 70 * specific to a VM or CPU. For example, it allows checking of the 71 * optional features and creation of VM containers. 72 */ 73class Kvm 74{ 75 friend class KvmVM; 76 77 public: 78 virtual ~Kvm(); 79 80 Kvm *create(); 81 82 /** Get the version of the KVM API implemented by the kernel. */ 83 int getAPIVersion() const { return apiVersion; } 84 /** 85 * Get the size of the MMAPed parameter area used to communicate 86 * vCPU parameters between the kernel and userspace. This area, 87 * amongst other things, contains the kvm_run data structure. 88 */ 89 int getVCPUMMapSize() const { return vcpuMMapSize; } 90 91 /** @{ */ 92 /** Support for KvmVM::setUserMemoryRegion() */ 93 bool capUserMemory() const; 94 /** Support for KvmVM::setTSSAddress() */ 95 bool capSetTSSAddress() const; 96 /** Support for BaseKvmCPU::setCPUID2 and getSupportedCPUID(). */ 97 bool capExtendedCPUID() const; 98 /** Support for BaseKvmCPU::kvmNonMaskableInterrupt(). */ 99 bool capUserNMI() const; 100 101 /** 102 * Check if coalesced MMIO is supported and which page in the 103 * MMAP'ed structure it stores requests in. 104 * 105 * @return Offset (in pages) into the mmap'ed vCPU area where the 106 * MMIO buffer is stored. 0 if unsupported. 107 */ 108 int capCoalescedMMIO() const; 109 110 /** 111 * Attempt to determine how many memory slots are available. If it can't 112 * be determined, this function returns 0. 113 */ 114 int capNumMemSlots() const; 115 116 /** 117 * Support for reading and writing single registers. 118 * 119 * @see BaseKvmCPU::getOneReg(), and BaseKvmCPU::setOneReg() 120 */ 121 bool capOneReg() const; 122 123 /** 124 * Support for creating an in-kernel IRQ chip model. 125 * 126 * @see KvmVM::createIRQChip() 127 */ 128 bool capIRQChip() const; 129 130 /** Support for getting and setting the kvm_vcpu_events structure. */ 131 bool capVCPUEvents() const; 132 133 /** Support for getting and setting the kvm_debugregs structure. */ 134 bool capDebugRegs() const; 135 136 /** Support for getting and setting the x86 XCRs. */ 137 bool capXCRs() const; 138 139 /** Support for getting and setting the kvm_xsave structure. */ 140 bool capXSave() const; 141 /** @} */ 142 143#if defined(__i386__) || defined(__x86_64__) 144 public: // x86-specific 145 /** 146 * @{ 147 * @name X86-specific APIs 148 */ 149 150 typedef std::vector<struct kvm_cpuid_entry2> CPUIDVector; 151 typedef std::vector<uint32_t> MSRIndexVector; 152 153 /** 154 * Get the CPUID features supported by the hardware and Kvm. 155 * 156 * @note Requires capExtendedCPUID(). 157 * 158 * @return False if the allocation is too small, true on success. 159 */ 160 bool getSupportedCPUID(struct kvm_cpuid2 &cpuid) const; 161 162 /** 163 * Get the CPUID features supported by the hardware and Kvm. 164 * 165 * @note Requires capExtendedCPUID(). 166 * 167 * @note This method uses an internal cache to minimize the number 168 * of calls into the kernel. 169 * 170 * @return Reference to cached MSR index list. 171 */ 172 const CPUIDVector &getSupportedCPUID() const; 173 174 /** 175 * Get the MSRs supported by the hardware and Kvm. 176 * 177 * @return False if the allocation is too small, true on success. 178 */ 179 bool getSupportedMSRs(struct kvm_msr_list &msrs) const; 180 181 /** 182 * Get the MSRs supported by the hardware and Kvm. 183 * 184 * @note This method uses an internal cache to minimize the number 185 * of calls into the kernel. 186 * 187 * @return Reference to cached MSR index list. 188 */ 189 const MSRIndexVector &getSupportedMSRs() const; 190 191 private: // x86-specific 192 /** Cached vector of supported CPUID entries. */ 193 mutable CPUIDVector supportedCPUIDCache; 194 195 /** Cached vector of supported MSRs. */ 196 mutable MSRIndexVector supportedMSRCache; 197 198 199 /** @} */ 200#endif 201 202 protected: 203 /** 204 * Check for the presence of an extension to the KVM API. 205 * 206 * The return value depends on the extension, but is always zero 207 * if it is unsupported or positive otherwise. Some extensions use 208 * the return value provide additional data about the extension. 209 * 210 * @return 0 if the extension is unsupported, positive integer 211 * otherwise. 212 */ 213 int checkExtension(int extension) const; 214 215 /** 216 * @addtogroup KvmIoctl 217 * @{ 218 */ 219 /** 220 * Main VM ioctl interface. 221 * 222 * @param request KVM request 223 * @param p1 Optional request parameter 224 * 225 * @return -1 on error (error number in errno), ioctl dependent 226 * value otherwise. 227 */ 228 int ioctl(int request, long p1) const; 229 int ioctl(int request, void *p1) const { 230 return ioctl(request, (long)p1); 231 } 232 int ioctl(int request) const { 233 return ioctl(request, 0L); 234 } 235 /** @} */ 236 237 private: 238 // This object is a singleton, so prevent instantiation. 239 Kvm(); 240 241 // Prevent copying 242 Kvm(const Kvm &kvm); 243 // Prevent assignment 244 Kvm &operator=(const Kvm &kvm); 245 246 /** 247 * Create a KVM Virtual Machine 248 * 249 * @return File descriptor pointing to the VM 250 */ 251 int createVM(); 252 253 /** KVM VM file descriptor */ 254 int kvmFD; 255 /** KVM API version */ 256 int apiVersion; 257 /** Size of the MMAPed vCPU parameter area. */ 258 int vcpuMMapSize; 259 260 /** Singleton instance */ 261 static Kvm *instance; 262}; 263 264/** 265 * KVM VM container 266 * 267 * A KVM VM container normally contains all the CPUs in a shared 268 * memory machine. The VM container handles things like physical 269 * memory and to some extent interrupts. Normally, the VM API is only 270 * used for interrupts when the PIC is emulated by the kernel, which 271 * is a feature we do not use. However, some architectures (notably 272 * ARM) use the VM interface to deliver interrupts to specific CPUs as 273 * well. 274 * 275 * VM initialization is a bit different from that of other 276 * SimObjects. When we initialize the VM, we discover all physical 277 * memory mappings in the system. Since AbstractMem::unserialize 278 * re-maps the guests memory, we need to make sure that this is done 279 * after the memory has been re-mapped, but before the vCPUs are 280 * initialized (KVM requires memory mappings to be setup before CPUs 281 * can be created). Normally, we would just initialize the VM in 282 * init() or startup(), however, we can not use init() since this is 283 * called before AbstractMem::unserialize() and we can not use 284 * startup() since it must be called before BaseKvmCPU::startup() and 285 * the simulator framework does not guarantee call order. We therefore 286 * call cpuStartup() from BaseKvmCPU::startup() instead and execute 287 * the initialization code once when the first CPU in the VM is 288 * starting. 289 */ 290class KvmVM : public SimObject 291{ 292 friend class BaseKvmCPU; 293 294 public: 295 KvmVM(KvmVMParams *params); 296 virtual ~KvmVM(); 297 298 void notifyFork(); 299 300 /** 301 * Setup a shared three-page memory region used by the internals 302 * of KVM. This is currently only needed by x86 implementations. 303 * 304 * @param tss_address Physical address of the start of the TSS 305 */ 306 void setTSSAddress(Addr tss_address); 307 308 /** @{ */ 309 /** 310 * Request coalescing MMIO for a memory range. 311 * 312 * @param start Physical start address in guest 313 * @param size Size of the MMIO region 314 */ 315 void coalesceMMIO(Addr start, int size); 316 317 /** 318 * Request coalescing MMIO for a memory range. 319 * 320 * @param range Coalesced MMIO range 321 */ 322 void coalesceMMIO(const AddrRange &range); 323 /** @} */ 324 325 /** 326 * @addtogroup KvmInterrupts 327 * @{ 328 */ 329 /** 330 * Create an in-kernel interrupt controller 331 * 332 * @note This functionality depends on Kvm::capIRQChip(). 333 */ 334 void createIRQChip(); 335 336 /** 337 * Set the status of an IRQ line using KVM_IRQ_LINE. 338 * 339 * @note This ioctl is usually only used if the interrupt 340 * controller is emulated by the kernel (i.e., after calling 341 * createIRQChip()). Some architectures (e.g., ARM) use it instead 342 * of BaseKvmCPU::kvmInterrupt(). 343 * 344 * @param irq Interrupt number 345 * @param high Line level (true for high, false for low) 346 */ 347 void setIRQLine(uint32_t irq, bool high); 348 349 /** 350 * Is in-kernel IRQ chip emulation enabled? 351 */ 352 bool hasKernelIRQChip() const { return _hasKernelIRQChip; } 353 /** @} */ 354 355 struct MemSlot 356 { 357 MemSlot(uint32_t _num) : num(_num) 358 {} 359 MemSlot() : num(-1) 360 {} 361 362 int32_t num; 363 }; 364 365 /** 366 * Allocate a memory slot within the VM. 367 */ 368 const MemSlot allocMemSlot(uint64_t size); 369 370 /** 371 * Setup a region of physical memory in the guest 372 * 373 * @param slot KVM memory slot ID returned by allocMemSlot 374 * @param host_addr Memory allocation backing the memory 375 * @param guest_addr Address in the guest 376 * @param flags Flags (see the KVM API documentation) 377 */ 378 void setupMemSlot(const MemSlot slot, void *host_addr, Addr guest_addr, 379 uint32_t flags); 380 381 /** 382 * Disable a memory slot. 383 */ 384 void disableMemSlot(const MemSlot slot); 385 386 /** 387 * Free a previously allocated memory slot. 388 */ 389 void freeMemSlot(const MemSlot slot); 390 391 /** 392 * Create an in-kernel device model. 393 * 394 * @param type Device type (KVM_DEV_TYPE_xxx) 395 * @param flags Creation flags (KVM_CREATE_DEVICE_xxx) 396 * @return Device file descriptor 397 */ 398 int createDevice(uint32_t type, uint32_t flags = 0); 399 400 /** Global KVM interface */ 401 Kvm *kvm; 402 403#if defined(__aarch64__) 404 public: // ARM-specific 405 /** 406 * Ask the kernel for the preferred CPU target to simulate. 407 * 408 * When creating an ARM vCPU in Kvm, we need to initialize it with 409 * a call to BaseArmKvmCPU::kvmArmVCpuInit(). When calling this 410 * function, we need to know what type of CPU the host has. This 411 * call sets up the kvm_vcpu_init structure with the values the 412 * kernel wants. 413 * 414 * @param[out] target Target structure to initialize. 415 */ 416 void kvmArmPreferredTarget(struct kvm_vcpu_init &target) const; 417 418#endif 419 420 protected: 421 /** 422 * VM CPU initialization code. 423 * 424 * This method is called from BaseKvmCPU::startup() when a CPU in 425 * the VM executes its BaseKvmCPU::startup() method. The first 426 * time method is executed on a VM, it calls the delayedStartup() 427 * method. 428 */ 429 void cpuStartup(); 430 431 /** 432 * Delayed initialization, executed once before the first CPU 433 * starts. 434 * 435 * This method provides a way to do VM initialization once before 436 * the first CPU in a VM starts. It is needed since some resources 437 * (e.g., memory mappings) can change in the normal 438 * SimObject::startup() path. Since the call order of 439 * SimObject::startup() is not guaranteed, we simply defer some 440 * initialization until a CPU is about to start. 441 */ 442 void delayedStartup(); 443 444 445 /** @{ */ 446 /** 447 * Setup a region of physical memory in the guest 448 * 449 * @param slot KVM memory slot ID (must be unique) 450 * @param host_addr Memory allocation backing the memory 451 * @param guest_addr Address in the guest 452 * @param len Size of the allocation in bytes 453 * @param flags Flags (see the KVM API documentation) 454 */ 455 void setUserMemoryRegion(uint32_t slot, 456 void *host_addr, Addr guest_addr, 457 uint64_t len, uint32_t flags); 458 /** @} */ 459 460 /** 461 * Create a new vCPU within a VM. 462 * 463 * @param vcpuID ID of the new CPU within the VM. 464 * @return File descriptor referencing the CPU. 465 */ 466 int createVCPU(long vcpuID); 467 468 /** 469 * Allocate a new vCPU ID within the VM. 470 * 471 * The returned vCPU ID is guaranteed to be unique within the 472 * VM. New IDs are allocated sequentially starting from 0. 473 * 474 * @return ID of the new vCPU 475 */ 476 long allocVCPUID(); 477 478 /** 479 * @addtogroup KvmIoctl 480 * @{ 481 */ 482 /** 483 * KVM VM ioctl interface. 484 * 485 * @param request KVM VM request 486 * @param p1 Optional request parameter 487 * 488 * @return -1 on error (error number in errno), ioctl dependent 489 * value otherwise. 490 */ 491 int ioctl(int request, long p1) const; 492 int ioctl(int request, void *p1) const { 493 return ioctl(request, (long)p1); 494 } 495 int ioctl(int request) const { 496 return ioctl(request, 0L); 497 } 498 /**@}*/ 499 500 private: 501 // Prevent copying 502 KvmVM(const KvmVM &vm); 503 // Prevent assignment 504 KvmVM &operator=(const KvmVM &vm); 505 506 System *system; 507 508 /** KVM VM file descriptor */ 509 int vmFD; 510 511 /** Has delayedStartup() already been called? */ 512 bool started; 513 514 /** Do we have in-kernel IRQ-chip emulation enabled? */ 515 bool _hasKernelIRQChip; 516 517 /** Next unallocated vCPU ID */ 518 long nextVCPUID; 519 520 /** 521 * Structures tracking memory slots. 522 */ 523 class MemorySlot 524 { 525 public: 526 uint64_t size; 527 uint32_t slot; 528 bool active; 529 }; 530 std::vector<MemorySlot> memorySlots; 531 uint32_t maxMemorySlot; 532}; 533 534#endif 535