vm.hh revision 9651:f551c8ad12a5
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 "base/addr_range.hh" 44#include "sim/sim_object.hh" 45 46// forward declarations 47struct KvmVMParams; 48class System; 49 50/** 51 * @defgroup KvmInterrupts KVM Interrupt handling. 52 * 53 * These methods control interrupt delivery to the guest system. 54 */ 55 56/** 57 * @defgroup KvmIoctl KVM low-level ioctl interface. 58 * 59 * These methods provide a low-level interface to the underlying KVM 60 * layer. 61 */ 62 63/** 64 * KVM parent interface 65 * 66 * The main Kvm object is used to provide functionality that is not 67 * specific to a VM or CPU. For example, it allows checking of the 68 * optional features and creation of VM containers. 69 */ 70class Kvm 71{ 72 friend class KvmVM; 73 74 public: 75 virtual ~Kvm(); 76 77 Kvm *create(); 78 79 /** Get the version of the KVM API implemented by the kernel. */ 80 int getAPIVersion() const { return apiVersion; } 81 /** 82 * Get the size of the MMAPed parameter area used to communicate 83 * vCPU parameters between the kernel and userspace. This area, 84 * amongst other things, contains the kvm_run data structure. 85 */ 86 int getVCPUMMapSize() const { return vcpuMMapSize; } 87 88 /** @{ */ 89 /** Support for KvmVM::setUserMemoryRegion() */ 90 bool capUserMemory() const; 91 /** Support for KvmVM::setTSSAddress() */ 92 bool capSetTSSAddress() const; 93 /** Support for BaseKvmCPU::setCPUID2 and getSupportedCPUID(). */ 94 bool capExtendedCPUID() const; 95 /** Support for BaseKvmCPU::kvmNonMaskableInterrupt(). */ 96 bool capUserNMI() const; 97 98 /** 99 * Check if coalesced MMIO is supported and which page in the 100 * MMAP'ed structure it stores requests in. 101 * 102 * @return Offset (in pages) into the mmap'ed vCPU area where the 103 * MMIO buffer is stored. 0 if unsupported. 104 */ 105 int capCoalescedMMIO() const; 106 107 /** 108 * Support for reading and writing single registers. 109 * 110 * @see BaseKvmCPU::getOneReg(), and BaseKvmCPU::setOneReg() 111 */ 112 bool capOneReg() const; 113 114 /** 115 * Support for creating an in-kernel IRQ chip model. 116 * 117 * @see KvmVM::createIRQChip() 118 */ 119 bool capIRQChip() const; 120 /** @} */ 121 122 /** 123 * Get the CPUID features supported by the hardware and Kvm. 124 * 125 * @note Requires capExtendedCPUID(). 126 * 127 * @return False if the allocation is too small, true on success. 128 */ 129 bool getSupportedCPUID(struct kvm_cpuid2 &cpuid) const; 130 131 protected: 132 /** 133 * Check for the presence of an extension to the KVM API. 134 * 135 * The return value depends on the extension, but is always zero 136 * if it is unsupported or positive otherwise. Some extensions use 137 * the return value provide additional data about the extension. 138 * 139 * @return 0 if the extension is unsupported, positive integer 140 * otherwise. 141 */ 142 int checkExtension(int extension) const; 143 144 /** 145 * @addtogroup KvmIoctl 146 * @{ 147 */ 148 /** 149 * Main VM ioctl interface. 150 * 151 * @param request KVM request 152 * @param p1 Optional request parameter 153 * 154 * @return -1 on error (error number in errno), ioctl dependent 155 * value otherwise. 156 */ 157 int ioctl(int request, long p1) const; 158 int ioctl(int request, void *p1) const { 159 return ioctl(request, (long)p1); 160 } 161 int ioctl(int request) const { 162 return ioctl(request, 0L); 163 } 164 /** @} */ 165 166 private: 167 // This object is a singleton, so prevent instantiation. 168 Kvm(); 169 170 // Prevent copying 171 Kvm(const Kvm &kvm); 172 // Prevent assignment 173 Kvm &operator=(const Kvm &kvm); 174 175 /** 176 * Create a KVM Virtual Machine 177 * 178 * @return File descriptor pointing to the VM 179 */ 180 int createVM(); 181 182 /** KVM VM file descriptor */ 183 int kvmFD; 184 /** KVM API version */ 185 int apiVersion; 186 /** Size of the MMAPed vCPU parameter area. */ 187 int vcpuMMapSize; 188 189 /** Singleton instance */ 190 static Kvm *instance; 191}; 192 193/** 194 * KVM VM container 195 * 196 * A KVM VM container normally contains all the CPUs in a shared 197 * memory machine. The VM container handles things like physical 198 * memory and to some extent interrupts. Normally, the VM API is only 199 * used for interrupts when the PIC is emulated by the kernel, which 200 * is a feature we do not use. However, some architectures (notably 201 * ARM) use the VM interface to deliver interrupts to specific CPUs as 202 * well. 203 * 204 * VM initialization is a bit different from that of other 205 * SimObjects. When we initialize the VM, we discover all physical 206 * memory mappings in the system. Since AbstractMem::unserialize 207 * re-maps the guests memory, we need to make sure that this is done 208 * after the memory has been re-mapped, but before the vCPUs are 209 * initialized (KVM requires memory mappings to be setup before CPUs 210 * can be created). Normally, we would just initialize the VM in 211 * init() or startup(), however, we can not use init() since this is 212 * called before AbstractMem::unserialize() and we can not use 213 * startup() since it must be called before BaseKvmCPU::startup() and 214 * the simulator framework does not guarantee call order. We therefore 215 * call cpuStartup() from BaseKvmCPU::startup() instead and execute 216 * the initialization code once when the first CPU in the VM is 217 * starting. 218 */ 219class KvmVM : public SimObject 220{ 221 friend class BaseKvmCPU; 222 223 public: 224 KvmVM(KvmVMParams *params); 225 virtual ~KvmVM(); 226 227 /** 228 * Setup a shared three-page memory region used by the internals 229 * of KVM. This is currently only needed by x86 implementations. 230 * 231 * @param tss_address Physical address of the start of the TSS 232 */ 233 void setTSSAddress(Addr tss_address); 234 235 /** @{ */ 236 /** 237 * Request coalescing MMIO for a memory range. 238 * 239 * @param start Physical start address in guest 240 * @param size Size of the MMIO region 241 */ 242 void coalesceMMIO(Addr start, int size); 243 244 /** 245 * Request coalescing MMIO for a memory range. 246 * 247 * @param range Coalesced MMIO range 248 */ 249 void coalesceMMIO(const AddrRange &range); 250 /** @} */ 251 252 /** 253 * @addtogroup KvmInterrupts 254 * @{ 255 */ 256 /** 257 * Create an in-kernel interrupt controller 258 * 259 * @note This functionality depends on Kvm::capIRQChip(). 260 */ 261 void createIRQChip(); 262 263 /** 264 * Set the status of an IRQ line using KVM_IRQ_LINE. 265 * 266 * @note This ioctl is usually only used if the interrupt 267 * controller is emulated by the kernel (i.e., after calling 268 * createIRQChip()). Some architectures (e.g., ARM) use it instead 269 * of BaseKvmCPU::kvmInterrupt(). 270 * 271 * @param irq Interrupt number 272 * @param high Line level (true for high, false for low) 273 */ 274 void setIRQLine(uint32_t irq, bool high); 275 276 /** 277 * Is in-kernel IRQ chip emulation enabled? 278 */ 279 bool hasKernelIRQChip() const { return _hasKernelIRQChip; } 280 /** @} */ 281 282 /** Global KVM interface */ 283 Kvm kvm; 284 285 protected: 286 /** 287 * VM CPU initialization code. 288 * 289 * This method is called from BaseKvmCPU::startup() when a CPU in 290 * the VM executes its BaseKvmCPU::startup() method. The first 291 * time method is executed on a VM, it calls the delayedStartup() 292 * method. 293 */ 294 void cpuStartup(); 295 296 /** 297 * Delayed initialization, executed once before the first CPU 298 * starts. 299 * 300 * This method provides a way to do VM initialization once before 301 * the first CPU in a VM starts. It is needed since some resources 302 * (e.g., memory mappings) can change in the normal 303 * SimObject::startup() path. Since the call order of 304 * SimObject::startup() is not guaranteed, we simply defer some 305 * initialization until a CPU is about to start. 306 */ 307 void delayedStartup(); 308 309 310 /** @{ */ 311 /** 312 * Setup a region of physical memory in the guest 313 * 314 * @param slot KVM memory slot ID (must be unique) 315 * @param host_addr Memory allocation backing the memory 316 * @param guest_addr Address in the guest 317 * @param guest_range Address range used by guest. 318 * @param len Size of the allocation in bytes 319 * @param flags Flags (see the KVM API documentation) 320 */ 321 void setUserMemoryRegion(uint32_t slot, 322 void *host_addr, Addr guest_addr, 323 uint64_t len, uint32_t flags); 324 void setUserMemoryRegion(uint32_t slot, 325 void *host_addr, AddrRange guest_range, 326 uint32_t flags); 327 /** @} */ 328 329 /** 330 * Create a new vCPU within a VM. 331 * 332 * @param vcpuID ID of the new CPU within the VM. 333 * @return File descriptor referencing the CPU. 334 */ 335 int createVCPU(long vcpuID); 336 337 /** 338 * Allocate a new vCPU ID within the VM. 339 * 340 * The returned vCPU ID is guaranteed to be unique within the 341 * VM. New IDs are allocated sequentially starting from 0. 342 * 343 * @return ID of the new vCPU 344 */ 345 long allocVCPUID(); 346 347 /** 348 * @addtogroup KvmIoctl 349 * @{ 350 */ 351 /** 352 * KVM VM ioctl interface. 353 * 354 * @param request KVM VM request 355 * @param p1 Optional request parameter 356 * 357 * @return -1 on error (error number in errno), ioctl dependent 358 * value otherwise. 359 */ 360 int ioctl(int request, long p1) const; 361 int ioctl(int request, void *p1) const { 362 return ioctl(request, (long)p1); 363 } 364 int ioctl(int request) const { 365 return ioctl(request, 0L); 366 } 367 /**@}*/ 368 369 private: 370 // Prevent copying 371 KvmVM(const KvmVM &vm); 372 // Prevent assignment 373 KvmVM &operator=(const KvmVM &vm); 374 375 System *system; 376 377 /** KVM VM file descriptor */ 378 const int vmFD; 379 380 /** Has delayedStartup() already been called? */ 381 bool started; 382 383 /** Do we have in-kernel IRQ-chip emulation enabled? */ 384 bool _hasKernelIRQChip; 385 386 /** Next unallocated vCPU ID */ 387 long nextVCPUID; 388}; 389 390#endif 391