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