vm.hh revision 9883:7e0dff1c165b
1/* 2 * Copyright (c) 2012 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Andreas Sandberg 38 */ 39 40#ifndef __CPU_KVM_KVMVM_HH__ 41#define __CPU_KVM_KVMVM_HH__ 42 43#include <vector> 44 45#include "base/addr_range.hh" 46#include "sim/sim_object.hh" 47 48// forward declarations 49struct KvmVMParams; 50class System; 51 52/** 53 * @defgroup KvmInterrupts KVM Interrupt handling. 54 * 55 * These methods control interrupt delivery to the guest system. 56 */ 57 58/** 59 * @defgroup KvmIoctl KVM low-level ioctl interface. 60 * 61 * These methods provide a low-level interface to the underlying KVM 62 * layer. 63 */ 64 65/** 66 * KVM parent interface 67 * 68 * The main Kvm object is used to provide functionality that is not 69 * specific to a VM or CPU. For example, it allows checking of the 70 * optional features and creation of VM containers. 71 */ 72class Kvm 73{ 74 friend class KvmVM; 75 76 public: 77 typedef std::vector<struct kvm_cpuid_entry2> CPUIDVector; 78 typedef std::vector<uint32_t> MSRIndexVector; 79 80 virtual ~Kvm(); 81 82 Kvm *create(); 83 84 /** Get the version of the KVM API implemented by the kernel. */ 85 int getAPIVersion() const { return apiVersion; } 86 /** 87 * Get the size of the MMAPed parameter area used to communicate 88 * vCPU parameters between the kernel and userspace. This area, 89 * amongst other things, contains the kvm_run data structure. 90 */ 91 int getVCPUMMapSize() const { return vcpuMMapSize; } 92 93 /** @{ */ 94 /** Support for KvmVM::setUserMemoryRegion() */ 95 bool capUserMemory() const; 96 /** Support for KvmVM::setTSSAddress() */ 97 bool capSetTSSAddress() const; 98 /** Support for BaseKvmCPU::setCPUID2 and getSupportedCPUID(). */ 99 bool capExtendedCPUID() const; 100 /** Support for BaseKvmCPU::kvmNonMaskableInterrupt(). */ 101 bool capUserNMI() const; 102 103 /** 104 * Check if coalesced MMIO is supported and which page in the 105 * MMAP'ed structure it stores requests in. 106 * 107 * @return Offset (in pages) into the mmap'ed vCPU area where the 108 * MMIO buffer is stored. 0 if unsupported. 109 */ 110 int capCoalescedMMIO() const; 111 112 /** 113 * Support for reading and writing single registers. 114 * 115 * @see BaseKvmCPU::getOneReg(), and BaseKvmCPU::setOneReg() 116 */ 117 bool capOneReg() const; 118 119 /** 120 * Support for creating an in-kernel IRQ chip model. 121 * 122 * @see KvmVM::createIRQChip() 123 */ 124 bool capIRQChip() const; 125 126 /** Support for getting and setting the kvm_vcpu_events structure. */ 127 bool capVCPUEvents() const; 128 129 /** Support for getting and setting the kvm_debugregs structure. */ 130 bool capDebugRegs() const; 131 132 /** Support for getting and setting the x86 XCRs. */ 133 bool capXCRs() const; 134 135 /** Support for getting and setting the kvm_xsave structure. */ 136 bool capXSave() const; 137 /** @} */ 138 139 /** 140 * Get the CPUID features supported by the hardware and Kvm. 141 * 142 * @note Requires capExtendedCPUID(). 143 * 144 * @return False if the allocation is too small, true on success. 145 */ 146 bool getSupportedCPUID(struct kvm_cpuid2 &cpuid) const; 147 148 /** 149 * Get the CPUID features supported by the hardware and Kvm. 150 * 151 * @note Requires capExtendedCPUID(). 152 * 153 * @note This method uses an internal cache to minimize the number 154 * of calls into the kernel. 155 * 156 * @return Reference to cached MSR index list. 157 */ 158 const CPUIDVector &getSupportedCPUID() const; 159 160 /** 161 * Get the MSRs supported by the hardware and Kvm. 162 * 163 * @return False if the allocation is too small, true on success. 164 */ 165 bool getSupportedMSRs(struct kvm_msr_list &msrs) const; 166 167 /** 168 * Get the MSRs supported by the hardware and Kvm. 169 * 170 * @note This method uses an internal cache to minimize the number 171 * of calls into the kernel. 172 * 173 * @return Reference to cached MSR index list. 174 */ 175 const MSRIndexVector &getSupportedMSRs() const; 176 177 protected: 178 /** 179 * Check for the presence of an extension to the KVM API. 180 * 181 * The return value depends on the extension, but is always zero 182 * if it is unsupported or positive otherwise. Some extensions use 183 * the return value provide additional data about the extension. 184 * 185 * @return 0 if the extension is unsupported, positive integer 186 * otherwise. 187 */ 188 int checkExtension(int extension) const; 189 190 /** 191 * @addtogroup KvmIoctl 192 * @{ 193 */ 194 /** 195 * Main VM ioctl interface. 196 * 197 * @param request KVM request 198 * @param p1 Optional request parameter 199 * 200 * @return -1 on error (error number in errno), ioctl dependent 201 * value otherwise. 202 */ 203 int ioctl(int request, long p1) const; 204 int ioctl(int request, void *p1) const { 205 return ioctl(request, (long)p1); 206 } 207 int ioctl(int request) const { 208 return ioctl(request, 0L); 209 } 210 /** @} */ 211 212 private: 213 // This object is a singleton, so prevent instantiation. 214 Kvm(); 215 216 // Prevent copying 217 Kvm(const Kvm &kvm); 218 // Prevent assignment 219 Kvm &operator=(const Kvm &kvm); 220 221 /** 222 * Create a KVM Virtual Machine 223 * 224 * @return File descriptor pointing to the VM 225 */ 226 int createVM(); 227 228 /** KVM VM file descriptor */ 229 int kvmFD; 230 /** KVM API version */ 231 int apiVersion; 232 /** Size of the MMAPed vCPU parameter area. */ 233 int vcpuMMapSize; 234 235 /** Cached vector of supported CPUID entries. */ 236 mutable CPUIDVector supportedCPUIDCache; 237 238 /** Cached vector of supported MSRs. */ 239 mutable MSRIndexVector supportedMSRCache; 240 241 /** Singleton instance */ 242 static Kvm *instance; 243}; 244 245/** 246 * KVM VM container 247 * 248 * A KVM VM container normally contains all the CPUs in a shared 249 * memory machine. The VM container handles things like physical 250 * memory and to some extent interrupts. Normally, the VM API is only 251 * used for interrupts when the PIC is emulated by the kernel, which 252 * is a feature we do not use. However, some architectures (notably 253 * ARM) use the VM interface to deliver interrupts to specific CPUs as 254 * well. 255 * 256 * VM initialization is a bit different from that of other 257 * SimObjects. When we initialize the VM, we discover all physical 258 * memory mappings in the system. Since AbstractMem::unserialize 259 * re-maps the guests memory, we need to make sure that this is done 260 * after the memory has been re-mapped, but before the vCPUs are 261 * initialized (KVM requires memory mappings to be setup before CPUs 262 * can be created). Normally, we would just initialize the VM in 263 * init() or startup(), however, we can not use init() since this is 264 * called before AbstractMem::unserialize() and we can not use 265 * startup() since it must be called before BaseKvmCPU::startup() and 266 * the simulator framework does not guarantee call order. We therefore 267 * call cpuStartup() from BaseKvmCPU::startup() instead and execute 268 * the initialization code once when the first CPU in the VM is 269 * starting. 270 */ 271class KvmVM : public SimObject 272{ 273 friend class BaseKvmCPU; 274 275 public: 276 KvmVM(KvmVMParams *params); 277 virtual ~KvmVM(); 278 279 /** 280 * Setup a shared three-page memory region used by the internals 281 * of KVM. This is currently only needed by x86 implementations. 282 * 283 * @param tss_address Physical address of the start of the TSS 284 */ 285 void setTSSAddress(Addr tss_address); 286 287 /** @{ */ 288 /** 289 * Request coalescing MMIO for a memory range. 290 * 291 * @param start Physical start address in guest 292 * @param size Size of the MMIO region 293 */ 294 void coalesceMMIO(Addr start, int size); 295 296 /** 297 * Request coalescing MMIO for a memory range. 298 * 299 * @param range Coalesced MMIO range 300 */ 301 void coalesceMMIO(const AddrRange &range); 302 /** @} */ 303 304 /** 305 * @addtogroup KvmInterrupts 306 * @{ 307 */ 308 /** 309 * Create an in-kernel interrupt controller 310 * 311 * @note This functionality depends on Kvm::capIRQChip(). 312 */ 313 void createIRQChip(); 314 315 /** 316 * Set the status of an IRQ line using KVM_IRQ_LINE. 317 * 318 * @note This ioctl is usually only used if the interrupt 319 * controller is emulated by the kernel (i.e., after calling 320 * createIRQChip()). Some architectures (e.g., ARM) use it instead 321 * of BaseKvmCPU::kvmInterrupt(). 322 * 323 * @param irq Interrupt number 324 * @param high Line level (true for high, false for low) 325 */ 326 void setIRQLine(uint32_t irq, bool high); 327 328 /** 329 * Is in-kernel IRQ chip emulation enabled? 330 */ 331 bool hasKernelIRQChip() const { return _hasKernelIRQChip; } 332 /** @} */ 333 334 /** Global KVM interface */ 335 Kvm kvm; 336 337 protected: 338 /** 339 * VM CPU initialization code. 340 * 341 * This method is called from BaseKvmCPU::startup() when a CPU in 342 * the VM executes its BaseKvmCPU::startup() method. The first 343 * time method is executed on a VM, it calls the delayedStartup() 344 * method. 345 */ 346 void cpuStartup(); 347 348 /** 349 * Delayed initialization, executed once before the first CPU 350 * starts. 351 * 352 * This method provides a way to do VM initialization once before 353 * the first CPU in a VM starts. It is needed since some resources 354 * (e.g., memory mappings) can change in the normal 355 * SimObject::startup() path. Since the call order of 356 * SimObject::startup() is not guaranteed, we simply defer some 357 * initialization until a CPU is about to start. 358 */ 359 void delayedStartup(); 360 361 362 /** @{ */ 363 /** 364 * Setup a region of physical memory in the guest 365 * 366 * @param slot KVM memory slot ID (must be unique) 367 * @param host_addr Memory allocation backing the memory 368 * @param guest_addr Address in the guest 369 * @param guest_range Address range used by guest. 370 * @param len Size of the allocation in bytes 371 * @param flags Flags (see the KVM API documentation) 372 */ 373 void setUserMemoryRegion(uint32_t slot, 374 void *host_addr, Addr guest_addr, 375 uint64_t len, uint32_t flags); 376 void setUserMemoryRegion(uint32_t slot, 377 void *host_addr, AddrRange guest_range, 378 uint32_t flags); 379 /** @} */ 380 381 /** 382 * Create a new vCPU within a VM. 383 * 384 * @param vcpuID ID of the new CPU within the VM. 385 * @return File descriptor referencing the CPU. 386 */ 387 int createVCPU(long vcpuID); 388 389 /** 390 * Allocate a new vCPU ID within the VM. 391 * 392 * The returned vCPU ID is guaranteed to be unique within the 393 * VM. New IDs are allocated sequentially starting from 0. 394 * 395 * @return ID of the new vCPU 396 */ 397 long allocVCPUID(); 398 399 /** 400 * @addtogroup KvmIoctl 401 * @{ 402 */ 403 /** 404 * KVM VM ioctl interface. 405 * 406 * @param request KVM VM request 407 * @param p1 Optional request parameter 408 * 409 * @return -1 on error (error number in errno), ioctl dependent 410 * value otherwise. 411 */ 412 int ioctl(int request, long p1) const; 413 int ioctl(int request, void *p1) const { 414 return ioctl(request, (long)p1); 415 } 416 int ioctl(int request) const { 417 return ioctl(request, 0L); 418 } 419 /**@}*/ 420 421 private: 422 // Prevent copying 423 KvmVM(const KvmVM &vm); 424 // Prevent assignment 425 KvmVM &operator=(const KvmVM &vm); 426 427 System *system; 428 429 /** KVM VM file descriptor */ 430 const int vmFD; 431 432 /** Has delayedStartup() already been called? */ 433 bool started; 434 435 /** Do we have in-kernel IRQ-chip emulation enabled? */ 436 bool _hasKernelIRQChip; 437 438 /** Next unallocated vCPU ID */ 439 long nextVCPUID; 440}; 441 442#endif 443