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