base.hh revision 9752:a152d7f114b8
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 MasterPort &getDataPort() { return dataPort; } 97 MasterPort &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 ThreadContext *getContext(int tn); 106 107 Counter totalInsts() const; 108 Counter totalOps() const; 109 110 /** Dump the internal state to the terminal. */ 111 virtual void dump(); 112 113 /** 114 * A cached copy of a thread's state in the form of a SimpleThread 115 * object. 116 * 117 * Normally the actual thread state is stored in the KVM vCPU. If KVM has 118 * been running this copy is will be out of date. If we recently handled 119 * some events within gem5 that required state to be updated this could be 120 * the most up-to-date copy. When getContext() or updateThreadContext() is 121 * called this copy gets updated. The method syncThreadContext can 122 * be used within a KVM CPU to update the thread context if the 123 * KVM state is dirty (i.e., the vCPU has been run since the last 124 * update). 125 */ 126 SimpleThread *thread; 127 128 /** ThreadContext object, provides an interface for external 129 * objects to modify this thread's state. 130 */ 131 ThreadContext *tc; 132 133 KvmVM &vm; 134 135 protected: 136 enum Status { 137 /** Context not scheduled in KVM */ 138 Idle, 139 /** Running normally */ 140 Running, 141 }; 142 143 /** CPU run state */ 144 Status _status; 145 146 /** 147 * Execute the CPU until the next event in the main event queue or 148 * until the guest needs service from gem5. 149 * 150 * @note This method is virtual in order to allow implementations 151 * to check for architecture specific events (e.g., interrupts) 152 * before entering the VM. 153 */ 154 virtual void tick(); 155 156 /** 157 * Get the value of the hardware cycle counter in the guest. 158 * 159 * This method is supposed to return the total number of cycles 160 * executed in hardware mode relative to some arbitrary point in 161 * the past. It's mainly used when estimating the number of cycles 162 * actually executed by the CPU in kvmRun(). The default behavior 163 * of this method is to use the cycles performance counter, but 164 * some architectures may want to use internal registers instead. 165 * 166 * @return Number of host cycles executed relative to an undefined 167 * point in the past. 168 */ 169 virtual uint64_t getHostCycles() const; 170 171 /** 172 * Request KVM to run the guest for a given number of ticks. The 173 * method returns the approximate number of ticks executed. 174 * 175 * @note The returned number of ticks can be both larger or 176 * smaller than the requested number of ticks. A smaller number 177 * can, for example, occur when the guest executes MMIO. A larger 178 * number is typically due to performance counter inaccuracies. 179 * 180 * @param ticks Number of ticks to execute 181 * @return Number of ticks executed (see note) 182 */ 183 Tick kvmRun(Tick ticks); 184 185 /** 186 * Get a pointer to the kvm_run structure containing all the input 187 * and output parameters from kvmRun(). 188 */ 189 struct kvm_run *getKvmRunState() { return _kvmRun; }; 190 191 /** 192 * Retrieve a pointer to guest data stored at the end of the 193 * kvm_run structure. This is mainly used for PIO operations 194 * (KVM_EXIT_IO). 195 * 196 * @param offset Offset as specified by the kvm_run structure 197 * @return Pointer to guest data 198 */ 199 uint8_t *getGuestData(uint64_t offset) const { 200 return (uint8_t *)_kvmRun + offset; 201 }; 202 203 /** 204 * @addtogroup KvmInterrupts 205 * @{ 206 */ 207 /** 208 * Send a non-maskable interrupt to the guest 209 * 210 * @note The presence of this call depends on Kvm::capUserNMI(). 211 */ 212 void kvmNonMaskableInterrupt(); 213 214 /** 215 * Send a normal interrupt to the guest 216 * 217 * @note Make sure that ready_for_interrupt_injection in kvm_run 218 * is set prior to calling this function. If not, an interrupt 219 * window must be requested by setting request_interrupt_window in 220 * kvm_run to 1 and restarting the guest. 221 * 222 * @param interrupt Structure describing the interrupt to send 223 */ 224 void kvmInterrupt(const struct kvm_interrupt &interrupt); 225 226 /** @} */ 227 228 /** @{ */ 229 /** 230 * Get/Set the register state of the guest vCPU 231 * 232 * KVM has two different interfaces for accessing the state of the 233 * guest CPU. One interface updates 'normal' registers and one 234 * updates 'special' registers. The distinction between special 235 * and normal registers isn't very clear and is architecture 236 * dependent. 237 */ 238 void getRegisters(struct kvm_regs ®s) const; 239 void setRegisters(const struct kvm_regs ®s); 240 void getSpecialRegisters(struct kvm_sregs ®s) const; 241 void setSpecialRegisters(const struct kvm_sregs ®s); 242 /** @} */ 243 244 /** @{ */ 245 /** 246 * Get/Set the guest FPU/vector state 247 */ 248 void getFPUState(struct kvm_fpu &state) const; 249 void setFPUState(const struct kvm_fpu &state); 250 /** @} */ 251 252 /** @{ */ 253 /** 254 * Get/Set single register using the KVM_(SET|GET)_ONE_REG API. 255 * 256 * @note The presence of this call depends on Kvm::capOneReg(). 257 */ 258 void setOneReg(uint64_t id, const void *addr); 259 void setOneReg(uint64_t id, uint64_t value) { setOneReg(id, &value); } 260 void setOneReg(uint64_t id, uint32_t value) { setOneReg(id, &value); } 261 void getOneReg(uint64_t id, void *addr) const; 262 uint64_t getOneRegU64(uint64_t id) const { 263 uint64_t value; 264 getOneReg(id, &value); 265 return value; 266 } 267 uint32_t getOneRegU32(uint64_t id) const { 268 uint32_t value; 269 getOneReg(id, &value); 270 return value; 271 } 272 /** @} */ 273 274 /** 275 * Get and format one register for printout. 276 * 277 * This function call getOneReg() to retrieve the contents of one 278 * register and automatically formats it for printing. 279 * 280 * @note The presence of this call depends on Kvm::capOneReg(). 281 */ 282 std::string getAndFormatOneReg(uint64_t id) const; 283 284 /** @{ */ 285 /** 286 * Update the KVM state from the current thread context 287 * 288 * The base CPU calls this method before starting the guest CPU 289 * when the contextDirty flag is set. The architecture dependent 290 * CPU implementation is expected to update all guest state 291 * (registers, special registers, and FPU state). 292 */ 293 virtual void updateKvmState() = 0; 294 295 /** 296 * Update the current thread context with the KVM state 297 * 298 * The base CPU after the guest updates any of the KVM state. In 299 * practice, this happens after kvmRun is called. The architecture 300 * dependent code is expected to read the state of the guest CPU 301 * and update gem5's thread state. 302 */ 303 virtual void updateThreadContext() = 0; 304 305 /** 306 * Update a thread context if the KVM state is dirty with respect 307 * to the cached thread context. 308 */ 309 void syncThreadContext(); 310 311 /** 312 * Update the KVM if the thread context is dirty. 313 */ 314 void syncKvmState(); 315 /** @} */ 316 317 /** @{ */ 318 /** 319 * Main kvmRun exit handler, calls the relevant handleKvmExit* 320 * depending on exit type. 321 * 322 * @return Number of ticks spent servicing the exit request 323 */ 324 virtual Tick handleKvmExit(); 325 326 /** 327 * The guest performed a legacy IO request (out/inp on x86) 328 * 329 * @return Number of ticks spent servicing the IO request 330 */ 331 virtual Tick handleKvmExitIO(); 332 333 /** 334 * The guest requested a monitor service using a hypercall 335 * 336 * @return Number of ticks spent servicing the hypercall 337 */ 338 virtual Tick handleKvmExitHypercall(); 339 340 /** 341 * The guest exited because an interrupt window was requested 342 * 343 * The guest exited because an interrupt window was requested 344 * (request_interrupt_window in the kvm_run structure was set to 1 345 * before calling kvmRun) and it is now ready to receive 346 * 347 * @return Number of ticks spent servicing the IRQ 348 */ 349 virtual Tick handleKvmExitIRQWindowOpen(); 350 351 /** 352 * An unknown architecture dependent error occurred when starting 353 * the vCPU 354 * 355 * The kvm_run data structure contains the hardware error 356 * code. The defaults behavior of this method just prints the HW 357 * error code and panics. Architecture dependent implementations 358 * may want to override this method to provide better, 359 * hardware-aware, error messages. 360 * 361 * @return Number of ticks delay the next CPU tick 362 */ 363 virtual Tick handleKvmExitUnknown(); 364 365 /** 366 * An unhandled virtualization exception occured 367 * 368 * Some KVM virtualization drivers return unhandled exceptions to 369 * the user-space monitor. This interface is currently only used 370 * by the Intel VMX KVM driver. 371 * 372 * @return Number of ticks delay the next CPU tick 373 */ 374 virtual Tick handleKvmExitException(); 375 376 /** 377 * KVM failed to start the virtualized CPU 378 * 379 * The kvm_run data structure contains the hardware-specific error 380 * code. 381 * 382 * @return Number of ticks delay the next CPU tick 383 */ 384 virtual Tick handleKvmExitFailEntry(); 385 /** @} */ 386 387 /** 388 * Inject a memory mapped IO request into gem5 389 * 390 * @param paddr Physical address 391 * @param data Pointer to the source/destination buffer 392 * @param size Memory access size 393 * @param write True if write, False if read 394 * @return Number of ticks spent servicing the memory access 395 */ 396 Tick doMMIOAccess(Addr paddr, void *data, int size, bool write); 397 398 399 /** 400 * @addtogroup KvmIoctl 401 * @{ 402 */ 403 /** 404 * vCPU ioctl interface. 405 * 406 * @param request KVM vCPU 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 422 /** 423 * KVM memory port. Uses the default MasterPort behavior, but 424 * panics on timing accesses. 425 */ 426 class KVMCpuPort : public MasterPort 427 { 428 429 public: 430 KVMCpuPort(const std::string &_name, BaseKvmCPU *_cpu) 431 : MasterPort(_name, _cpu) 432 { } 433 434 protected: 435 bool recvTimingResp(PacketPtr pkt) 436 { 437 panic("The KVM CPU doesn't expect recvTimingResp!\n"); 438 return true; 439 } 440 441 void recvRetry() 442 { 443 panic("The KVM CPU doesn't expect recvRetry!\n"); 444 } 445 446 }; 447 448 /** Port for data requests */ 449 KVMCpuPort dataPort; 450 451 /** Unused dummy port for the instruction interface */ 452 KVMCpuPort instPort; 453 454 /** Pre-allocated MMIO memory request */ 455 Request mmio_req; 456 457 /** 458 * Is the gem5 context dirty? Set to true to force an update of 459 * the KVM vCPU state upon the next call to kvmRun(). 460 */ 461 bool threadContextDirty; 462 463 /** 464 * Is the KVM state dirty? Set to true to force an update of 465 * the KVM vCPU state upon the next call to kvmRun(). 466 */ 467 bool kvmStateDirty; 468 469 /** KVM internal ID of the vCPU */ 470 const long vcpuID; 471 472 private: 473 struct TickEvent : public Event 474 { 475 BaseKvmCPU &cpu; 476 477 TickEvent(BaseKvmCPU &c) 478 : Event(CPU_Tick_Pri), cpu(c) {} 479 480 void process() { cpu.tick(); } 481 482 const char *description() const { 483 return "BaseKvmCPU tick"; 484 } 485 }; 486 487 /** 488 * Service MMIO requests in the mmioRing. 489 * 490 * 491 * @return Number of ticks spent servicing the MMIO requests in 492 * the MMIO ring buffer 493 */ 494 Tick flushCoalescedMMIO(); 495 496 /** 497 * Setup a signal handler to catch the timer signal used to 498 * switch back to the monitor. 499 */ 500 void setupSignalHandler(); 501 502 /** Setup hardware performance counters */ 503 void setupCounters(); 504 505 /** KVM vCPU file descriptor */ 506 int vcpuFD; 507 /** Size of MMAPed kvm_run area */ 508 int vcpuMMapSize; 509 /** 510 * Pointer to the kvm_run structure used to communicate parameters 511 * with KVM. 512 * 513 * @note This is the base pointer of the MMAPed KVM region. The 514 * first page contains the kvm_run structure. Subsequent pages may 515 * contain other data such as the MMIO ring buffer. 516 */ 517 struct kvm_run *_kvmRun; 518 /** 519 * Coalesced MMIO ring buffer. NULL if coalesced MMIO is not 520 * supported. 521 */ 522 struct kvm_coalesced_mmio_ring *mmioRing; 523 /** Cached page size of the host */ 524 const long pageSize; 525 526 TickEvent tickEvent; 527 528 /** @{ */ 529 /** Guest performance counters */ 530 PerfKvmCounter hwCycles; 531 PerfKvmCounter hwInstructions; 532 /** @} */ 533 534 /** 535 * Does the runTimer control the performance counters? 536 * 537 * The run timer will automatically enable and disable performance 538 * counters if a PerfEvent-based timer is used to control KVM 539 * exits. 540 */ 541 bool perfControlledByTimer; 542 543 /** 544 * Timer used to force execution into the monitor after a 545 * specified number of simulation tick equivalents have executed 546 * in the guest. This counter generates the signal specified by 547 * KVM_TIMER_SIGNAL. 548 */ 549 std::unique_ptr<BaseKvmTimer> runTimer; 550 551 float hostFactor; 552 553 public: 554 /* @{ */ 555 Stats::Scalar numInsts; 556 Stats::Scalar numVMExits; 557 Stats::Scalar numMMIO; 558 Stats::Scalar numCoalescedMMIO; 559 Stats::Scalar numIO; 560 Stats::Scalar numHalt; 561 Stats::Scalar numInterrupts; 562 Stats::Scalar numHypercalls; 563 /* @} */ 564 565 /** Number of instructions executed by the CPU */ 566 Counter ctrInsts; 567}; 568 569#endif 570