base.hh revision 9651
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_BASE_HH__ 41#define __CPU_KVM_BASE_HH__ 42 43#include <memory> 44 45#include "base/statistics.hh" 46#include "cpu/kvm/perfevent.hh" 47#include "cpu/kvm/timer.hh" 48#include "cpu/kvm/vm.hh" 49#include "cpu/base.hh" 50#include "cpu/simple_thread.hh" 51 52/** Signal to use to trigger time-based exits from KVM */ 53#define KVM_TIMER_SIGNAL SIGRTMIN 54 55// forward declarations 56class ThreadContext; 57struct BaseKvmCPUParams; 58 59/** 60 * Base class for KVM based CPU models 61 * 62 * All architecture specific KVM implementation should inherit from 63 * this class. The most basic CPU models only need to override the 64 * updateKvmState() and updateThreadContext() methods to implement 65 * state synchronization between gem5 and KVM. 66 * 67 * The architecture specific implementation is also responsible for 68 * delivering interrupts into the VM. This is typically done by 69 * overriding tick() and checking the thread context before entering 70 * into the VM. In order to deliver an interrupt, the implementation 71 * then calls KvmVM::setIRQLine() or BaseKvmCPU::kvmInterrupt() 72 * depending on the specifics of the underlying hardware/drivers. 73 */ 74class BaseKvmCPU : public BaseCPU 75{ 76 public: 77 BaseKvmCPU(BaseKvmCPUParams *params); 78 virtual ~BaseKvmCPU(); 79 80 void init(); 81 void startup(); 82 void regStats(); 83 84 void serializeThread(std::ostream &os, ThreadID tid); 85 void unserializeThread(Checkpoint *cp, const std::string §ion, 86 ThreadID tid); 87 88 unsigned int drain(DrainManager *dm); 89 void drainResume(); 90 91 void switchOut(); 92 void takeOverFrom(BaseCPU *cpu); 93 94 void verifyMemoryMode() const; 95 96 CpuPort &getDataPort() { return dataPort; } 97 CpuPort &getInstPort() { return instPort; } 98 99 void wakeup(); 100 void activateContext(ThreadID thread_num, Cycles delay); 101 void suspendContext(ThreadID thread_num); 102 void deallocateContext(ThreadID thread_num); 103 void haltContext(ThreadID thread_num); 104 105 Counter totalInsts() const; 106 Counter totalOps() const; 107 108 /** Dump the internal state to the terminal. */ 109 virtual void dump(); 110 111 /** SimpleThread object, provides all the architectural state. */ 112 SimpleThread *thread; 113 114 /** ThreadContext object, provides an interface for external 115 * objects to modify this thread's state. 116 */ 117 ThreadContext *tc; 118 119 KvmVM &vm; 120 121 protected: 122 enum Status { 123 /** Context not scheduled in KVM */ 124 Idle, 125 /** Running normally */ 126 Running, 127 }; 128 129 /** CPU run state */ 130 Status _status; 131 132 /** 133 * Execute the CPU until the next event in the main event queue or 134 * until the guest needs service from gem5. 135 * 136 * @note This method is virtual in order to allow implementations 137 * to check for architecture specific events (e.g., interrupts) 138 * before entering the VM. 139 */ 140 virtual void tick(); 141 142 /** 143 * Request KVM to run the guest for a given number of ticks. The 144 * method returns the approximate number of ticks executed. 145 * 146 * @note The returned number of ticks can be both larger or 147 * smaller than the requested number of ticks. A smaller number 148 * can, for example, occur when the guest executes MMIO. A larger 149 * number is typically due to performance counter inaccuracies. 150 * 151 * @param ticks Number of ticks to execute 152 * @return Number of ticks executed (see note) 153 */ 154 Tick kvmRun(Tick ticks); 155 156 /** 157 * Get a pointer to the kvm_run structure containing all the input 158 * and output parameters from kvmRun(). 159 */ 160 struct kvm_run *getKvmRunState() { return _kvmRun; }; 161 162 /** 163 * Retrieve a pointer to guest data stored at the end of the 164 * kvm_run structure. This is mainly used for PIO operations 165 * (KVM_EXIT_IO). 166 * 167 * @param offset Offset as specified by the kvm_run structure 168 * @return Pointer to guest data 169 */ 170 uint8_t *getGuestData(uint64_t offset) const { 171 return (uint8_t *)_kvmRun + offset; 172 }; 173 174 /** 175 * @addtogroup KvmInterrupts 176 * @{ 177 */ 178 /** 179 * Send a non-maskable interrupt to the guest 180 * 181 * @note The presence of this call depends on Kvm::capUserNMI(). 182 */ 183 void kvmNonMaskableInterrupt(); 184 185 /** 186 * Send a normal interrupt to the guest 187 * 188 * @note Make sure that ready_for_interrupt_injection in kvm_run 189 * is set prior to calling this function. If not, an interrupt 190 * window must be requested by setting request_interrupt_window in 191 * kvm_run to 1 and restarting the guest. 192 * 193 * @param interrupt Structure describing the interrupt to send 194 */ 195 void kvmInterrupt(const struct kvm_interrupt &interrupt); 196 197 /** @} */ 198 199 /** @{ */ 200 /** 201 * Get/Set the register state of the guest vCPU 202 * 203 * KVM has two different interfaces for accessing the state of the 204 * guest CPU. One interface updates 'normal' registers and one 205 * updates 'special' registers. The distinction between special 206 * and normal registers isn't very clear and is architecture 207 * dependent. 208 */ 209 void getRegisters(struct kvm_regs ®s) const; 210 void setRegisters(const struct kvm_regs ®s); 211 void getSpecialRegisters(struct kvm_sregs ®s) const; 212 void setSpecialRegisters(const struct kvm_sregs ®s); 213 /** @} */ 214 215 /** @{ */ 216 /** 217 * Get/Set the guest FPU/vector state 218 */ 219 void getFPUState(struct kvm_fpu &state) const; 220 void setFPUState(const struct kvm_fpu &state); 221 /** @} */ 222 223 /** @{ */ 224 /** 225 * Get/Set single register using the KVM_(SET|GET)_ONE_REG API. 226 * 227 * @note The presence of this call depends on Kvm::capOneReg(). 228 */ 229 void setOneReg(uint64_t id, const void *addr); 230 void setOneReg(uint64_t id, uint64_t value) { setOneReg(id, &value); } 231 void setOneReg(uint64_t id, uint32_t value) { setOneReg(id, &value); } 232 void getOneReg(uint64_t id, void *addr) const; 233 uint64_t getOneRegU64(uint64_t id) const { 234 uint64_t value; 235 getOneReg(id, &value); 236 return value; 237 } 238 uint32_t getOneRegU32(uint64_t id) const { 239 uint32_t value; 240 getOneReg(id, &value); 241 return value; 242 } 243 /** @} */ 244 245 /** 246 * Get and format one register for printout. 247 * 248 * This function call getOneReg() to retrieve the contents of one 249 * register and automatically formats it for printing. 250 * 251 * @note The presence of this call depends on Kvm::capOneReg(). 252 */ 253 std::string getAndFormatOneReg(uint64_t id) const; 254 255 /** @{ */ 256 /** 257 * Update the KVM state from the current thread context 258 * 259 * The base CPU calls this method before starting the guest CPU 260 * when the contextDirty flag is set. The architecture dependent 261 * CPU implementation is expected to update all guest state 262 * (registers, special registers, and FPU state). 263 */ 264 virtual void updateKvmState() = 0; 265 266 /** 267 * Update the current thread context with the KVM state 268 * 269 * The base CPU after the guest updates any of the KVM state. In 270 * practice, this happens after kvmRun is called. The architecture 271 * dependent code is expected to read the state of the guest CPU 272 * and update gem5's thread state. 273 */ 274 virtual void updateThreadContext() = 0; 275 /** @} */ 276 277 /** @{ */ 278 /** 279 * Main kvmRun exit handler, calls the relevant handleKvmExit* 280 * depending on exit type. 281 * 282 * @return Number of ticks spent servicing the exit request 283 */ 284 virtual Tick handleKvmExit(); 285 286 /** 287 * The guest performed a legacy IO request (out/inp on x86) 288 * 289 * @return Number of ticks spent servicing the IO request 290 */ 291 virtual Tick handleKvmExitIO(); 292 293 /** 294 * The guest requested a monitor service using a hypercall 295 * 296 * @return Number of ticks spent servicing the hypercall 297 */ 298 virtual Tick handleKvmExitHypercall(); 299 300 /** 301 * The guest exited because an interrupt window was requested 302 * 303 * The guest exited because an interrupt window was requested 304 * (request_interrupt_window in the kvm_run structure was set to 1 305 * before calling kvmRun) and it is now ready to receive 306 * 307 * @return Number of ticks spent servicing the IRQ 308 */ 309 virtual Tick handleKvmExitIRQWindowOpen(); 310 311 /** 312 * An unknown architecture dependent error occurred when starting 313 * the vCPU 314 * 315 * The kvm_run data structure contains the hardware error 316 * code. The defaults behavior of this method just prints the HW 317 * error code and panics. Architecture dependent implementations 318 * may want to override this method to provide better, 319 * hardware-aware, error messages. 320 * 321 * @return Number of ticks delay the next CPU tick 322 */ 323 virtual Tick handleKvmExitUnknown(); 324 325 /** 326 * An unhandled virtualization exception occured 327 * 328 * Some KVM virtualization drivers return unhandled exceptions to 329 * the user-space monitor. This interface is currently only used 330 * by the Intel VMX KVM driver. 331 * 332 * @return Number of ticks delay the next CPU tick 333 */ 334 virtual Tick handleKvmExitException(); 335 336 /** 337 * KVM failed to start the virtualized CPU 338 * 339 * The kvm_run data structure contains the hardware-specific error 340 * code. 341 * 342 * @return Number of ticks delay the next CPU tick 343 */ 344 virtual Tick handleKvmExitFailEntry(); 345 /** @} */ 346 347 /** 348 * Inject a memory mapped IO request into gem5 349 * 350 * @param paddr Physical address 351 * @param data Pointer to the source/destination buffer 352 * @param size Memory access size 353 * @param write True if write, False if read 354 * @return Number of ticks spent servicing the memory access 355 */ 356 Tick doMMIOAccess(Addr paddr, void *data, int size, bool write); 357 358 359 /** 360 * @addtogroup KvmIoctl 361 * @{ 362 */ 363 /** 364 * vCPU ioctl interface. 365 * 366 * @param request KVM vCPU request 367 * @param p1 Optional request parameter 368 * 369 * @return -1 on error (error number in errno), ioctl dependent 370 * value otherwise. 371 */ 372 int ioctl(int request, long p1) const; 373 int ioctl(int request, void *p1) const { 374 return ioctl(request, (long)p1); 375 } 376 int ioctl(int request) const { 377 return ioctl(request, 0L); 378 } 379 /** @} */ 380 381 /** Port for data requests */ 382 CpuPort dataPort; 383 384 /** Unused dummy port for the instruction interface */ 385 CpuPort instPort; 386 387 /** Pre-allocated MMIO memory request */ 388 Request mmio_req; 389 390 /** 391 * Is the gem5 context dirty? Set to true to force an update of 392 * the KVM vCPU state upon the next call to kvmRun(). 393 */ 394 bool contextDirty; 395 396 /** KVM internal ID of the vCPU */ 397 const long vcpuID; 398 399 private: 400 struct TickEvent : public Event 401 { 402 BaseKvmCPU &cpu; 403 404 TickEvent(BaseKvmCPU &c) 405 : Event(CPU_Tick_Pri), cpu(c) {} 406 407 void process() { cpu.tick(); } 408 409 const char *description() const { 410 return "BaseKvmCPU tick"; 411 } 412 }; 413 414 /** 415 * Service MMIO requests in the mmioRing. 416 * 417 * 418 * @return Number of ticks spent servicing the MMIO requests in 419 * the MMIO ring buffer 420 */ 421 Tick flushCoalescedMMIO(); 422 423 /** 424 * Setup a signal handler to catch the timer signal used to 425 * switch back to the monitor. 426 */ 427 void setupSignalHandler(); 428 429 /** Setup hardware performance counters */ 430 void setupCounters(); 431 432 /** @{ */ 433 /** Start/stop counting HW performance events */ 434 void startCounters(); 435 void stopCounters(); 436 /** @} */ 437 438 /** KVM vCPU file descriptor */ 439 int vcpuFD; 440 /** Size of MMAPed kvm_run area */ 441 int vcpuMMapSize; 442 /** 443 * Pointer to the kvm_run structure used to communicate parameters 444 * with KVM. 445 * 446 * @note This is the base pointer of the MMAPed KVM region. The 447 * first page contains the kvm_run structure. Subsequent pages may 448 * contain other data such as the MMIO ring buffer. 449 */ 450 struct kvm_run *_kvmRun; 451 /** 452 * Coalesced MMIO ring buffer. NULL if coalesced MMIO is not 453 * supported. 454 */ 455 struct kvm_coalesced_mmio_ring *mmioRing; 456 /** Cached page size of the host */ 457 const long pageSize; 458 459 TickEvent tickEvent; 460 461 /** @{ */ 462 /** Guest performance counters */ 463 PerfKvmCounter hwCycles; 464 PerfKvmCounter hwInstructions; 465 /** @} */ 466 467 /** 468 * Timer used to force execution into the monitor after a 469 * specified number of simulation tick equivalents have executed 470 * in the guest. This counter generates the signal specified by 471 * KVM_TIMER_SIGNAL. 472 */ 473 std::unique_ptr<BaseKvmTimer> runTimer; 474 475 float hostFactor; 476 477 public: 478 /* @{ */ 479 Stats::Scalar numVMExits; 480 Stats::Scalar numMMIO; 481 Stats::Scalar numCoalescedMMIO; 482 Stats::Scalar numIO; 483 Stats::Scalar numHalt; 484 Stats::Scalar numInterrupts; 485 Stats::Scalar numHypercalls; 486 /* @} */ 487}; 488 489#endif 490