vm.hh revision 10859:0ba6f47025d1
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 /** 299 * Setup a shared three-page memory region used by the internals 300 * of KVM. This is currently only needed by x86 implementations. 301 * 302 * @param tss_address Physical address of the start of the TSS 303 */ 304 void setTSSAddress(Addr tss_address); 305 306 /** @{ */ 307 /** 308 * Request coalescing MMIO for a memory range. 309 * 310 * @param start Physical start address in guest 311 * @param size Size of the MMIO region 312 */ 313 void coalesceMMIO(Addr start, int size); 314 315 /** 316 * Request coalescing MMIO for a memory range. 317 * 318 * @param range Coalesced MMIO range 319 */ 320 void coalesceMMIO(const AddrRange &range); 321 /** @} */ 322 323 /** 324 * @addtogroup KvmInterrupts 325 * @{ 326 */ 327 /** 328 * Create an in-kernel interrupt controller 329 * 330 * @note This functionality depends on Kvm::capIRQChip(). 331 */ 332 void createIRQChip(); 333 334 /** 335 * Set the status of an IRQ line using KVM_IRQ_LINE. 336 * 337 * @note This ioctl is usually only used if the interrupt 338 * controller is emulated by the kernel (i.e., after calling 339 * createIRQChip()). Some architectures (e.g., ARM) use it instead 340 * of BaseKvmCPU::kvmInterrupt(). 341 * 342 * @param irq Interrupt number 343 * @param high Line level (true for high, false for low) 344 */ 345 void setIRQLine(uint32_t irq, bool high); 346 347 /** 348 * Is in-kernel IRQ chip emulation enabled? 349 */ 350 bool hasKernelIRQChip() const { return _hasKernelIRQChip; } 351 /** @} */ 352 353 struct MemSlot 354 { 355 MemSlot(uint32_t _num) : num(_num) 356 {} 357 MemSlot() : num(-1) 358 {} 359 360 int32_t num; 361 }; 362 363 /** 364 * Allocate a memory slot within the VM. 365 */ 366 const MemSlot allocMemSlot(uint64_t size); 367 368 /** 369 * Setup a region of physical memory in the guest 370 * 371 * @param slot KVM memory slot ID returned by allocMemSlot 372 * @param host_addr Memory allocation backing the memory 373 * @param guest_addr Address in the guest 374 * @param flags Flags (see the KVM API documentation) 375 */ 376 void setupMemSlot(const MemSlot slot, void *host_addr, Addr guest_addr, 377 uint32_t flags); 378 379 /** 380 * Disable a memory slot. 381 */ 382 void disableMemSlot(const MemSlot slot); 383 384 /** 385 * Free a previously allocated memory slot. 386 */ 387 void freeMemSlot(const MemSlot slot); 388 389 /** 390 * Create an in-kernel device model. 391 * 392 * @param type Device type (KVM_DEV_TYPE_xxx) 393 * @param flags Creation flags (KVM_CREATE_DEVICE_xxx) 394 * @return Device file descriptor 395 */ 396 int createDevice(uint32_t type, uint32_t flags = 0); 397 398 /** Global KVM interface */ 399 Kvm kvm; 400 401 protected: 402 /** 403 * VM CPU initialization code. 404 * 405 * This method is called from BaseKvmCPU::startup() when a CPU in 406 * the VM executes its BaseKvmCPU::startup() method. The first 407 * time method is executed on a VM, it calls the delayedStartup() 408 * method. 409 */ 410 void cpuStartup(); 411 412 /** 413 * Delayed initialization, executed once before the first CPU 414 * starts. 415 * 416 * This method provides a way to do VM initialization once before 417 * the first CPU in a VM starts. It is needed since some resources 418 * (e.g., memory mappings) can change in the normal 419 * SimObject::startup() path. Since the call order of 420 * SimObject::startup() is not guaranteed, we simply defer some 421 * initialization until a CPU is about to start. 422 */ 423 void delayedStartup(); 424 425 426 /** @{ */ 427 /** 428 * Setup a region of physical memory in the guest 429 * 430 * @param slot KVM memory slot ID (must be unique) 431 * @param host_addr Memory allocation backing the memory 432 * @param guest_addr Address in the guest 433 * @param len Size of the allocation in bytes 434 * @param flags Flags (see the KVM API documentation) 435 */ 436 void setUserMemoryRegion(uint32_t slot, 437 void *host_addr, Addr guest_addr, 438 uint64_t len, uint32_t flags); 439 /** @} */ 440 441 /** 442 * Create a new vCPU within a VM. 443 * 444 * @param vcpuID ID of the new CPU within the VM. 445 * @return File descriptor referencing the CPU. 446 */ 447 int createVCPU(long vcpuID); 448 449 /** 450 * Allocate a new vCPU ID within the VM. 451 * 452 * The returned vCPU ID is guaranteed to be unique within the 453 * VM. New IDs are allocated sequentially starting from 0. 454 * 455 * @return ID of the new vCPU 456 */ 457 long allocVCPUID(); 458 459 /** 460 * @addtogroup KvmIoctl 461 * @{ 462 */ 463 /** 464 * KVM VM ioctl interface. 465 * 466 * @param request KVM VM request 467 * @param p1 Optional request parameter 468 * 469 * @return -1 on error (error number in errno), ioctl dependent 470 * value otherwise. 471 */ 472 int ioctl(int request, long p1) const; 473 int ioctl(int request, void *p1) const { 474 return ioctl(request, (long)p1); 475 } 476 int ioctl(int request) const { 477 return ioctl(request, 0L); 478 } 479 /**@}*/ 480 481 private: 482 // Prevent copying 483 KvmVM(const KvmVM &vm); 484 // Prevent assignment 485 KvmVM &operator=(const KvmVM &vm); 486 487 System *system; 488 489 /** KVM VM file descriptor */ 490 const int vmFD; 491 492 /** Has delayedStartup() already been called? */ 493 bool started; 494 495 /** Do we have in-kernel IRQ-chip emulation enabled? */ 496 bool _hasKernelIRQChip; 497 498 /** Next unallocated vCPU ID */ 499 long nextVCPUID; 500 501 /** 502 * Structures tracking memory slots. 503 */ 504 class MemorySlot 505 { 506 public: 507 uint64_t size; 508 uint32_t slot; 509 bool active; 510 }; 511 std::vector<MemorySlot> memorySlots; 512 uint32_t maxMemorySlot; 513}; 514 515#endif 516