base.hh revision 11399
12914Ssaidi@eecs.umich.edu/* 22914Ssaidi@eecs.umich.edu * Copyright (c) 2012 ARM Limited 32914Ssaidi@eecs.umich.edu * All rights reserved 42914Ssaidi@eecs.umich.edu * 52914Ssaidi@eecs.umich.edu * The license below extends only to copyright in the software and shall 62914Ssaidi@eecs.umich.edu * not be construed as granting a license to any other intellectual 72914Ssaidi@eecs.umich.edu * property including but not limited to intellectual property relating 82914Ssaidi@eecs.umich.edu * to a hardware implementation of the functionality of the software 92914Ssaidi@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 102914Ssaidi@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 112914Ssaidi@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 122914Ssaidi@eecs.umich.edu * modified or unmodified, in source code or in binary form. 132914Ssaidi@eecs.umich.edu * 142914Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 152914Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are 162914Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright 172914Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 182914Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 192914Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 202914Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution; 212914Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its 222914Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from 232914Ssaidi@eecs.umich.edu * this software without specific prior written permission. 242914Ssaidi@eecs.umich.edu * 252914Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 262914Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 272914Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 282914Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 292914Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 302914Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 312914Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 322914Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 332914Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 343091Sstever@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 353091Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 363342Srdreslin@umich.edu * 373342Srdreslin@umich.edu * Authors: Andreas Sandberg 383296Ssaidi@eecs.umich.edu */ 393342Srdreslin@umich.edu 403342Srdreslin@umich.edu#ifndef __CPU_KVM_BASE_HH__ 413342Srdreslin@umich.edu#define __CPU_KVM_BASE_HH__ 423342Srdreslin@umich.edu 433284Srdreslin@umich.edu#include <pthread.h> 443284Srdreslin@umich.edu 453284Srdreslin@umich.edu#include <csignal> 463296Ssaidi@eecs.umich.edu#include <memory> 473296Ssaidi@eecs.umich.edu 483284Srdreslin@umich.edu#include "base/statistics.hh" 493284Srdreslin@umich.edu#include "cpu/kvm/perfevent.hh" 503342Srdreslin@umich.edu#include "cpu/kvm/timer.hh" 513284Srdreslin@umich.edu#include "cpu/kvm/vm.hh" 523342Srdreslin@umich.edu#include "cpu/base.hh" 533296Ssaidi@eecs.umich.edu#include "cpu/simple_thread.hh" 543091Sstever@eecs.umich.edu 553091Sstever@eecs.umich.edu/** Signal to use to trigger exits from KVM */ 563091Sstever@eecs.umich.edu#define KVM_KICK_SIGNAL SIGRTMIN 573091Sstever@eecs.umich.edu 583091Sstever@eecs.umich.edu// forward declarations 593091Sstever@eecs.umich.educlass ThreadContext; 603091Sstever@eecs.umich.edustruct BaseKvmCPUParams; 613091Sstever@eecs.umich.edu 623091Sstever@eecs.umich.edu/** 633091Sstever@eecs.umich.edu * Base class for KVM based CPU models 643091Sstever@eecs.umich.edu * 653091Sstever@eecs.umich.edu * All architecture specific KVM implementation should inherit from 663175Srdreslin@umich.edu * this class. The most basic CPU models only need to override the 673175Srdreslin@umich.edu * updateKvmState() and updateThreadContext() methods to implement 683175Srdreslin@umich.edu * state synchronization between gem5 and KVM. 693175Srdreslin@umich.edu * 703175Srdreslin@umich.edu * The architecture specific implementation is also responsible for 713309Srdreslin@umich.edu * delivering interrupts into the VM. This is typically done by 723309Srdreslin@umich.edu * overriding tick() and checking the thread context before entering 733309Srdreslin@umich.edu * into the VM. In order to deliver an interrupt, the implementation 743309Srdreslin@umich.edu * then calls KvmVM::setIRQLine() or BaseKvmCPU::kvmInterrupt() 753309Srdreslin@umich.edu * depending on the specifics of the underlying hardware/drivers. 763309Srdreslin@umich.edu */ 773309Srdreslin@umich.educlass BaseKvmCPU : public BaseCPU 783091Sstever@eecs.umich.edu{ 793091Sstever@eecs.umich.edu public: 803091Sstever@eecs.umich.edu BaseKvmCPU(BaseKvmCPUParams *params); 813091Sstever@eecs.umich.edu virtual ~BaseKvmCPU(); 822914Ssaidi@eecs.umich.edu 832914Ssaidi@eecs.umich.edu void init() override; 843263Srdreslin@umich.edu void startup() override; 853263Srdreslin@umich.edu void regStats() override; 863263Srdreslin@umich.edu 873263Srdreslin@umich.edu void serializeThread(CheckpointOut &cp, ThreadID tid) const override; 883263Srdreslin@umich.edu void unserializeThread(CheckpointIn &cp, ThreadID tid) override; 893263Srdreslin@umich.edu 903263Srdreslin@umich.edu DrainState drain() override; 913263Srdreslin@umich.edu void drainResume() override; 923263Srdreslin@umich.edu void notifyFork() override; 933219Sgblack@eecs.umich.edu 943263Srdreslin@umich.edu void switchOut() override; 953091Sstever@eecs.umich.edu void takeOverFrom(BaseCPU *cpu) override; 963091Sstever@eecs.umich.edu 973091Sstever@eecs.umich.edu void verifyMemoryMode() const override; 982914Ssaidi@eecs.umich.edu 992914Ssaidi@eecs.umich.edu MasterPort &getDataPort() override { return dataPort; } 1002914Ssaidi@eecs.umich.edu MasterPort &getInstPort() override { return instPort; } 1012914Ssaidi@eecs.umich.edu 1022914Ssaidi@eecs.umich.edu void wakeup(ThreadID tid = 0) override; 1033263Srdreslin@umich.edu void activateContext(ThreadID thread_num) override; 1043263Srdreslin@umich.edu void suspendContext(ThreadID thread_num) override; 1053263Srdreslin@umich.edu void deallocateContext(ThreadID thread_num); 1063219Sgblack@eecs.umich.edu void haltContext(ThreadID thread_num) override; 1073241Sgblack@eecs.umich.edu 1083219Sgblack@eecs.umich.edu ThreadContext *getContext(int tn) override; 1093263Srdreslin@umich.edu 1103263Srdreslin@umich.edu Counter totalInsts() const override; 1113263Srdreslin@umich.edu Counter totalOps() const override; 1123263Srdreslin@umich.edu 1133263Srdreslin@umich.edu /** Dump the internal state to the terminal. */ 1143263Srdreslin@umich.edu virtual void dump() const; 1153263Srdreslin@umich.edu 1163091Sstever@eecs.umich.edu /** 1173091Sstever@eecs.umich.edu * Force an exit from KVM. 1183091Sstever@eecs.umich.edu * 1193091Sstever@eecs.umich.edu * Send a signal to the thread owning this vCPU to get it to exit 1203091Sstever@eecs.umich.edu * from KVM. Ignored if the vCPU is not executing. 1213263Srdreslin@umich.edu */ 1223263Srdreslin@umich.edu void kick() const { pthread_kill(vcpuThread, KVM_KICK_SIGNAL); } 1233263Srdreslin@umich.edu 1243263Srdreslin@umich.edu /** 1253091Sstever@eecs.umich.edu * A cached copy of a thread's state in the form of a SimpleThread 1262914Ssaidi@eecs.umich.edu * object. 1272914Ssaidi@eecs.umich.edu * 1282914Ssaidi@eecs.umich.edu * Normally the actual thread state is stored in the KVM vCPU. If KVM has 1292914Ssaidi@eecs.umich.edu * been running this copy is will be out of date. If we recently handled 1302914Ssaidi@eecs.umich.edu * some events within gem5 that required state to be updated this could be 1312914Ssaidi@eecs.umich.edu * the most up-to-date copy. When getContext() or updateThreadContext() is 1322914Ssaidi@eecs.umich.edu * called this copy gets updated. The method syncThreadContext can 1332914Ssaidi@eecs.umich.edu * be used within a KVM CPU to update the thread context if the 1342914Ssaidi@eecs.umich.edu * KVM state is dirty (i.e., the vCPU has been run since the last 1352914Ssaidi@eecs.umich.edu * update). 1362914Ssaidi@eecs.umich.edu */ 137 SimpleThread *thread; 138 139 /** ThreadContext object, provides an interface for external 140 * objects to modify this thread's state. 141 */ 142 ThreadContext *tc; 143 144 KvmVM &vm; 145 146 protected: 147 /** 148 * 149 * @dot 150 * digraph { 151 * Idle; 152 * Running; 153 * RunningService; 154 * RunningServiceCompletion; 155 * 156 * Idle -> Idle; 157 * Idle -> Running [label="activateContext()", URL="\ref activateContext"]; 158 * Running -> Running [label="tick()", URL="\ref tick"]; 159 * Running -> RunningService [label="tick()", URL="\ref tick"]; 160 * Running -> Idle [label="suspendContext()", URL="\ref suspendContext"]; 161 * Running -> Idle [label="drain()", URL="\ref drain"]; 162 * Idle -> Running [label="drainResume()", URL="\ref drainResume"]; 163 * RunningService -> RunningServiceCompletion [label="handleKvmExit()", URL="\ref handleKvmExit"]; 164 * RunningServiceCompletion -> Running [label="tick()", URL="\ref tick"]; 165 * RunningServiceCompletion -> RunningService [label="tick()", URL="\ref tick"]; 166 * } 167 * @enddot 168 */ 169 enum Status { 170 /** Context not scheduled in KVM. 171 * 172 * The CPU generally enters this state when the guest execute 173 * an instruction that halts the CPU (e.g., WFI on ARM or HLT 174 * on X86) if KVM traps this instruction. Ticks are not 175 * scheduled in this state. 176 * 177 * @see suspendContext() 178 */ 179 Idle, 180 /** Running normally. 181 * 182 * This is the normal run state of the CPU. KVM will be 183 * entered next time tick() is called. 184 */ 185 Running, 186 /** Requiring service at the beginning of the next cycle. 187 * 188 * The virtual machine has exited and requires service, tick() 189 * will call handleKvmExit() on the next cycle. The next state 190 * after running service is determined in handleKvmExit() and 191 * depends on what kind of service the guest requested: 192 * <ul> 193 * <li>IO/MMIO: RunningServiceCompletion 194 * <li>Halt: Idle 195 * <li>Others: Running 196 * </ul> 197 */ 198 RunningService, 199 /** Service completion in progress. 200 * 201 * The VM has requested service that requires KVM to be 202 * entered once in order to get to a consistent state. This 203 * happens in handleKvmExit() or one of its friends after IO 204 * exits. After executing tick(), the CPU will transition into 205 * the Running or RunningService state. 206 */ 207 RunningServiceCompletion, 208 }; 209 210 /** CPU run state */ 211 Status _status; 212 213 /** 214 * Execute the CPU until the next event in the main event queue or 215 * until the guest needs service from gem5. 216 */ 217 void tick(); 218 219 /** 220 * Get the value of the hardware cycle counter in the guest. 221 * 222 * This method is supposed to return the total number of cycles 223 * executed in hardware mode relative to some arbitrary point in 224 * the past. It's mainly used when estimating the number of cycles 225 * actually executed by the CPU in kvmRun(). The default behavior 226 * of this method is to use the cycles performance counter, but 227 * some architectures may want to use internal registers instead. 228 * 229 * @return Number of host cycles executed relative to an undefined 230 * point in the past. 231 */ 232 virtual uint64_t getHostCycles() const; 233 234 /** 235 * Request KVM to run the guest for a given number of ticks. The 236 * method returns the approximate number of ticks executed. 237 * 238 * @note The returned number of ticks can be both larger or 239 * smaller than the requested number of ticks. A smaller number 240 * can, for example, occur when the guest executes MMIO. A larger 241 * number is typically due to performance counter inaccuracies. 242 * 243 * @note This method is virtual in order to allow implementations 244 * to check for architecture specific events (e.g., interrupts) 245 * before entering the VM. 246 * 247 * @note It is the response of the caller (normally tick()) to 248 * make sure that the KVM state is synchronized and that the TC is 249 * invalidated after entering KVM. 250 * 251 * @note This method does not normally cause any state 252 * transitions. However, if it may suspend the CPU by suspending 253 * the thread, which leads to a transition to the Idle state. In 254 * such a case, kvm <i>must not</i> be entered. 255 * 256 * @param ticks Number of ticks to execute, set to 0 to exit 257 * immediately after finishing pending operations. 258 * @return Number of ticks executed (see note) 259 */ 260 virtual Tick kvmRun(Tick ticks); 261 262 /** 263 * Request the CPU to run until draining completes. 264 * 265 * This function normally calls kvmRun(0) to make KVM finish 266 * pending MMIO operations. Architecures implementing 267 * archIsDrained() must override this method. 268 * 269 * @see BaseKvmCPU::archIsDrained() 270 * 271 * @return Number of ticks executed 272 */ 273 virtual Tick kvmRunDrain(); 274 275 /** 276 * Get a pointer to the kvm_run structure containing all the input 277 * and output parameters from kvmRun(). 278 */ 279 struct kvm_run *getKvmRunState() { return _kvmRun; }; 280 281 /** 282 * Retrieve a pointer to guest data stored at the end of the 283 * kvm_run structure. This is mainly used for PIO operations 284 * (KVM_EXIT_IO). 285 * 286 * @param offset Offset as specified by the kvm_run structure 287 * @return Pointer to guest data 288 */ 289 uint8_t *getGuestData(uint64_t offset) const { 290 return (uint8_t *)_kvmRun + offset; 291 }; 292 293 /** 294 * @addtogroup KvmInterrupts 295 * @{ 296 */ 297 /** 298 * Send a non-maskable interrupt to the guest 299 * 300 * @note The presence of this call depends on Kvm::capUserNMI(). 301 */ 302 void kvmNonMaskableInterrupt(); 303 304 /** 305 * Send a normal interrupt to the guest 306 * 307 * @note Make sure that ready_for_interrupt_injection in kvm_run 308 * is set prior to calling this function. If not, an interrupt 309 * window must be requested by setting request_interrupt_window in 310 * kvm_run to 1 and restarting the guest. 311 * 312 * @param interrupt Structure describing the interrupt to send 313 */ 314 void kvmInterrupt(const struct kvm_interrupt &interrupt); 315 316 /** @} */ 317 318 /** @{ */ 319 /** 320 * Get/Set the register state of the guest vCPU 321 * 322 * KVM has two different interfaces for accessing the state of the 323 * guest CPU. One interface updates 'normal' registers and one 324 * updates 'special' registers. The distinction between special 325 * and normal registers isn't very clear and is architecture 326 * dependent. 327 */ 328 void getRegisters(struct kvm_regs ®s) const; 329 void setRegisters(const struct kvm_regs ®s); 330 void getSpecialRegisters(struct kvm_sregs ®s) const; 331 void setSpecialRegisters(const struct kvm_sregs ®s); 332 /** @} */ 333 334 /** @{ */ 335 /** 336 * Get/Set the guest FPU/vector state 337 */ 338 void getFPUState(struct kvm_fpu &state) const; 339 void setFPUState(const struct kvm_fpu &state); 340 /** @} */ 341 342 /** @{ */ 343 /** 344 * Get/Set single register using the KVM_(SET|GET)_ONE_REG API. 345 * 346 * @note The presence of this call depends on Kvm::capOneReg(). 347 */ 348 void setOneReg(uint64_t id, const void *addr); 349 void setOneReg(uint64_t id, uint64_t value) { setOneReg(id, &value); } 350 void setOneReg(uint64_t id, uint32_t value) { setOneReg(id, &value); } 351 void getOneReg(uint64_t id, void *addr) const; 352 uint64_t getOneRegU64(uint64_t id) const { 353 uint64_t value; 354 getOneReg(id, &value); 355 return value; 356 } 357 uint32_t getOneRegU32(uint64_t id) const { 358 uint32_t value; 359 getOneReg(id, &value); 360 return value; 361 } 362 /** @} */ 363 364 /** 365 * Get and format one register for printout. 366 * 367 * This function call getOneReg() to retrieve the contents of one 368 * register and automatically formats it for printing. 369 * 370 * @note The presence of this call depends on Kvm::capOneReg(). 371 */ 372 std::string getAndFormatOneReg(uint64_t id) const; 373 374 /** @{ */ 375 /** 376 * Update the KVM state from the current thread context 377 * 378 * The base CPU calls this method before starting the guest CPU 379 * when the contextDirty flag is set. The architecture dependent 380 * CPU implementation is expected to update all guest state 381 * (registers, special registers, and FPU state). 382 */ 383 virtual void updateKvmState() = 0; 384 385 /** 386 * Update the current thread context with the KVM state 387 * 388 * The base CPU after the guest updates any of the KVM state. In 389 * practice, this happens after kvmRun is called. The architecture 390 * dependent code is expected to read the state of the guest CPU 391 * and update gem5's thread state. 392 */ 393 virtual void updateThreadContext() = 0; 394 395 /** 396 * Update a thread context if the KVM state is dirty with respect 397 * to the cached thread context. 398 */ 399 void syncThreadContext(); 400 401 /** 402 * Update the KVM if the thread context is dirty. 403 */ 404 void syncKvmState(); 405 /** @} */ 406 407 /** @{ */ 408 /** 409 * Main kvmRun exit handler, calls the relevant handleKvmExit* 410 * depending on exit type. 411 * 412 * @return Number of ticks spent servicing the exit request 413 */ 414 virtual Tick handleKvmExit(); 415 416 /** 417 * The guest performed a legacy IO request (out/inp on x86) 418 * 419 * @return Number of ticks spent servicing the IO request 420 */ 421 virtual Tick handleKvmExitIO(); 422 423 /** 424 * The guest requested a monitor service using a hypercall 425 * 426 * @return Number of ticks spent servicing the hypercall 427 */ 428 virtual Tick handleKvmExitHypercall(); 429 430 /** 431 * The guest exited because an interrupt window was requested 432 * 433 * The guest exited because an interrupt window was requested 434 * (request_interrupt_window in the kvm_run structure was set to 1 435 * before calling kvmRun) and it is now ready to receive 436 * 437 * @return Number of ticks spent servicing the IRQ 438 */ 439 virtual Tick handleKvmExitIRQWindowOpen(); 440 441 /** 442 * An unknown architecture dependent error occurred when starting 443 * the vCPU 444 * 445 * The kvm_run data structure contains the hardware error 446 * code. The defaults behavior of this method just prints the HW 447 * error code and panics. Architecture dependent implementations 448 * may want to override this method to provide better, 449 * hardware-aware, error messages. 450 * 451 * @return Number of ticks delay the next CPU tick 452 */ 453 virtual Tick handleKvmExitUnknown(); 454 455 /** 456 * An unhandled virtualization exception occured 457 * 458 * Some KVM virtualization drivers return unhandled exceptions to 459 * the user-space monitor. This interface is currently only used 460 * by the Intel VMX KVM driver. 461 * 462 * @return Number of ticks delay the next CPU tick 463 */ 464 virtual Tick handleKvmExitException(); 465 466 /** 467 * KVM failed to start the virtualized CPU 468 * 469 * The kvm_run data structure contains the hardware-specific error 470 * code. 471 * 472 * @return Number of ticks delay the next CPU tick 473 */ 474 virtual Tick handleKvmExitFailEntry(); 475 /** @} */ 476 477 /** 478 * Is the architecture specific code in a state that prevents 479 * draining? 480 * 481 * This method should return false if there are any pending events 482 * in the guest vCPU that won't be carried over to the gem5 state 483 * and thus will prevent correct checkpointing or CPU handover. It 484 * might, for example, check for pending interrupts that have been 485 * passed to the vCPU but not acknowledged by the OS. Architecures 486 * implementing this method <i>must</i> override 487 * kvmRunDrain(). 488 * 489 * @see BaseKvmCPU::kvmRunDrain() 490 * 491 * @return true if the vCPU is drained, false otherwise. 492 */ 493 virtual bool archIsDrained() const { return true; } 494 495 /** 496 * Inject a memory mapped IO request into gem5 497 * 498 * @param paddr Physical address 499 * @param data Pointer to the source/destination buffer 500 * @param size Memory access size 501 * @param write True if write, False if read 502 * @return Number of ticks spent servicing the memory access 503 */ 504 Tick doMMIOAccess(Addr paddr, void *data, int size, bool write); 505 506 /** @{ */ 507 /** 508 * Set the signal mask used in kvmRun() 509 * 510 * This method allows the signal mask of the thread executing 511 * kvmRun() to be overridden inside the actual system call. This 512 * allows us to mask timer signals used to force KVM exits while 513 * in gem5. 514 * 515 * The signal mask can be disabled by setting it to NULL. 516 * 517 * @param mask Signals to mask 518 */ 519 void setSignalMask(const sigset_t *mask); 520 /** @} */ 521 522 /** 523 * @addtogroup KvmIoctl 524 * @{ 525 */ 526 /** 527 * vCPU ioctl interface. 528 * 529 * @param request KVM vCPU request 530 * @param p1 Optional request parameter 531 * 532 * @return -1 on error (error number in errno), ioctl dependent 533 * value otherwise. 534 */ 535 int ioctl(int request, long p1) const; 536 int ioctl(int request, void *p1) const { 537 return ioctl(request, (long)p1); 538 } 539 int ioctl(int request) const { 540 return ioctl(request, 0L); 541 } 542 /** @} */ 543 544 545 /** 546 * KVM memory port. Uses the default MasterPort behavior, but 547 * panics on timing accesses. 548 */ 549 class KVMCpuPort : public MasterPort 550 { 551 552 public: 553 KVMCpuPort(const std::string &_name, BaseKvmCPU *_cpu) 554 : MasterPort(_name, _cpu) 555 { } 556 557 protected: 558 bool recvTimingResp(PacketPtr pkt) 559 { 560 panic("The KVM CPU doesn't expect recvTimingResp!\n"); 561 return true; 562 } 563 564 void recvReqRetry() 565 { 566 panic("The KVM CPU doesn't expect recvReqRetry!\n"); 567 } 568 569 }; 570 571 /** Port for data requests */ 572 KVMCpuPort dataPort; 573 574 /** Unused dummy port for the instruction interface */ 575 KVMCpuPort instPort; 576 577 /** 578 * Be conservative and always synchronize the thread context on 579 * KVM entry/exit. 580 */ 581 const bool alwaysSyncTC; 582 583 /** 584 * Is the gem5 context dirty? Set to true to force an update of 585 * the KVM vCPU state upon the next call to kvmRun(). 586 */ 587 bool threadContextDirty; 588 589 /** 590 * Is the KVM state dirty? Set to true to force an update of 591 * the KVM vCPU state upon the next call to kvmRun(). 592 */ 593 bool kvmStateDirty; 594 595 /** KVM internal ID of the vCPU */ 596 const long vcpuID; 597 598 /** ID of the vCPU thread */ 599 pthread_t vcpuThread; 600 601 private: 602 struct TickEvent : public Event 603 { 604 BaseKvmCPU &cpu; 605 606 TickEvent(BaseKvmCPU &c) 607 : Event(CPU_Tick_Pri), cpu(c) {} 608 609 void process() { cpu.tick(); } 610 611 const char *description() const { 612 return "BaseKvmCPU tick"; 613 } 614 }; 615 616 /** 617 * Service MMIO requests in the mmioRing. 618 * 619 * 620 * @return Number of ticks spent servicing the MMIO requests in 621 * the MMIO ring buffer 622 */ 623 Tick flushCoalescedMMIO(); 624 625 /** 626 * Setup a signal handler to catch the timer signal used to 627 * switch back to the monitor. 628 */ 629 void setupSignalHandler(); 630 631 /** 632 * Discard a (potentially) pending signal. 633 * 634 * @param signum Signal to discard 635 * @return true if the signal was pending, false otherwise. 636 */ 637 bool discardPendingSignal(int signum) const; 638 639 /** 640 * Thread-specific initialization. 641 * 642 * Some KVM-related initialization requires us to know the TID of 643 * the thread that is going to execute our event queue. For 644 * example, when setting up timers, we need to know the TID of the 645 * thread executing in KVM in order to deliver the timer signal to 646 * that thread. This method is called as the first event in this 647 * SimObject's event queue. 648 * 649 * @see startup 650 */ 651 void startupThread(); 652 653 /** Try to drain the CPU if a drain is pending */ 654 bool tryDrain(); 655 656 /** Execute the KVM_RUN ioctl */ 657 void ioctlRun(); 658 659 /** KVM vCPU file descriptor */ 660 int vcpuFD; 661 /** Size of MMAPed kvm_run area */ 662 int vcpuMMapSize; 663 /** 664 * Pointer to the kvm_run structure used to communicate parameters 665 * with KVM. 666 * 667 * @note This is the base pointer of the MMAPed KVM region. The 668 * first page contains the kvm_run structure. Subsequent pages may 669 * contain other data such as the MMIO ring buffer. 670 */ 671 struct kvm_run *_kvmRun; 672 /** 673 * Coalesced MMIO ring buffer. NULL if coalesced MMIO is not 674 * supported. 675 */ 676 struct kvm_coalesced_mmio_ring *mmioRing; 677 /** Cached page size of the host */ 678 const long pageSize; 679 680 TickEvent tickEvent; 681 682 /** 683 * Setup an instruction break if there is one pending. 684 * 685 * Check if there are pending instruction breaks in the CPU's 686 * instruction event queue and schedule an instruction break using 687 * PerfEvent. 688 * 689 * @note This method doesn't currently handle the main system 690 * instruction event queue. 691 */ 692 void setupInstStop(); 693 694 /** @{ */ 695 /** Setup hardware performance counters */ 696 void setupCounters(); 697 698 /** 699 * Setup the guest instruction counter. 700 * 701 * Setup the guest instruction counter and optionally request a 702 * signal every N instructions executed by the guest. This method 703 * will re-attach the counter if the counter has already been 704 * attached and its sampling settings have changed. 705 * 706 * @param period Signal period, set to 0 to disable signaling. 707 */ 708 void setupInstCounter(uint64_t period = 0); 709 710 /** Currently active instruction count breakpoint */ 711 uint64_t activeInstPeriod; 712 713 /** 714 * Guest cycle counter. 715 * 716 * This is the group leader of all performance counters measuring 717 * the guest system. It can be used in conjunction with the 718 * PerfKvmTimer (see perfControlledByTimer) to trigger exits from 719 * KVM. 720 */ 721 PerfKvmCounter hwCycles; 722 723 /** 724 * Guest instruction counter. 725 * 726 * This counter is typically only used to measure the number of 727 * instructions executed by the guest. However, it can also be 728 * used to trigger exits from KVM if the configuration script 729 * requests an exit after a certain number of instructions. 730 * 731 * @see setupInstBreak 732 * @see scheduleInstStop 733 */ 734 PerfKvmCounter hwInstructions; 735 736 /** 737 * Does the runTimer control the performance counters? 738 * 739 * The run timer will automatically enable and disable performance 740 * counters if a PerfEvent-based timer is used to control KVM 741 * exits. 742 */ 743 bool perfControlledByTimer; 744 /** @} */ 745 746 /** 747 * Timer used to force execution into the monitor after a 748 * specified number of simulation tick equivalents have executed 749 * in the guest. This counter generates the signal specified by 750 * KVM_TIMER_SIGNAL. 751 */ 752 std::unique_ptr<BaseKvmTimer> runTimer; 753 754 /** Host factor as specified in the configuration */ 755 float hostFactor; 756 757 public: 758 /* @{ */ 759 Stats::Scalar numInsts; 760 Stats::Scalar numVMExits; 761 Stats::Scalar numVMHalfEntries; 762 Stats::Scalar numExitSignal; 763 Stats::Scalar numMMIO; 764 Stats::Scalar numCoalescedMMIO; 765 Stats::Scalar numIO; 766 Stats::Scalar numHalt; 767 Stats::Scalar numInterrupts; 768 Stats::Scalar numHypercalls; 769 /* @} */ 770 771 /** Number of instructions executed by the CPU */ 772 Counter ctrInsts; 773}; 774 775#endif 776