base.cc revision 9752
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#include <linux/kvm.h> 41#include <sys/ioctl.h> 42#include <sys/mman.h> 43#include <unistd.h> 44 45#include <cerrno> 46#include <csignal> 47#include <ostream> 48 49#include "arch/utility.hh" 50#include "cpu/kvm/base.hh" 51#include "debug/Checkpoint.hh" 52#include "debug/Kvm.hh" 53#include "debug/KvmIO.hh" 54#include "debug/KvmRun.hh" 55#include "params/BaseKvmCPU.hh" 56#include "sim/process.hh" 57#include "sim/system.hh" 58 59/* Used by some KVM macros */ 60#define PAGE_SIZE pageSize 61 62volatile bool timerOverflowed = false; 63 64static void 65onTimerOverflow(int signo, siginfo_t *si, void *data) 66{ 67 timerOverflowed = true; 68} 69 70BaseKvmCPU::BaseKvmCPU(BaseKvmCPUParams *params) 71 : BaseCPU(params), 72 vm(*params->kvmVM), 73 _status(Idle), 74 dataPort(name() + ".dcache_port", this), 75 instPort(name() + ".icache_port", this), 76 threadContextDirty(true), 77 kvmStateDirty(false), 78 vcpuID(vm.allocVCPUID()), vcpuFD(-1), vcpuMMapSize(0), 79 _kvmRun(NULL), mmioRing(NULL), 80 pageSize(sysconf(_SC_PAGE_SIZE)), 81 tickEvent(*this), 82 perfControlledByTimer(params->usePerfOverflow), 83 hostFactor(params->hostFactor), 84 ctrInsts(0) 85{ 86 if (pageSize == -1) 87 panic("KVM: Failed to determine host page size (%i)\n", 88 errno); 89 90 thread = new SimpleThread(this, 0, params->system, 91 params->itb, params->dtb, params->isa[0]); 92 thread->setStatus(ThreadContext::Halted); 93 tc = thread->getTC(); 94 threadContexts.push_back(tc); 95 96 setupCounters(); 97 setupSignalHandler(); 98 99 if (params->usePerfOverflow) 100 runTimer.reset(new PerfKvmTimer(hwCycles, 101 KVM_TIMER_SIGNAL, 102 params->hostFactor, 103 params->clock)); 104 else 105 runTimer.reset(new PosixKvmTimer(KVM_TIMER_SIGNAL, CLOCK_MONOTONIC, 106 params->hostFactor, 107 params->clock)); 108} 109 110BaseKvmCPU::~BaseKvmCPU() 111{ 112 if (_kvmRun) 113 munmap(_kvmRun, vcpuMMapSize); 114 close(vcpuFD); 115} 116 117void 118BaseKvmCPU::init() 119{ 120 BaseCPU::init(); 121 122 if (numThreads != 1) 123 fatal("KVM: Multithreading not supported"); 124 125 tc->initMemProxies(tc); 126 127 // initialize CPU, including PC 128 if (FullSystem && !switchedOut()) 129 TheISA::initCPU(tc, tc->contextId()); 130 131 mmio_req.setThreadContext(tc->contextId(), 0); 132} 133 134void 135BaseKvmCPU::startup() 136{ 137 const BaseKvmCPUParams * const p( 138 dynamic_cast<const BaseKvmCPUParams *>(params())); 139 140 Kvm &kvm(vm.kvm); 141 142 BaseCPU::startup(); 143 144 assert(vcpuFD == -1); 145 146 // Tell the VM that a CPU is about to start. 147 vm.cpuStartup(); 148 149 // We can't initialize KVM CPUs in BaseKvmCPU::init() since we are 150 // not guaranteed that the parent KVM VM has initialized at that 151 // point. Initialize virtual CPUs here instead. 152 vcpuFD = vm.createVCPU(vcpuID); 153 154 // Map the KVM run structure */ 155 vcpuMMapSize = kvm.getVCPUMMapSize(); 156 _kvmRun = (struct kvm_run *)mmap(0, vcpuMMapSize, 157 PROT_READ | PROT_WRITE, MAP_SHARED, 158 vcpuFD, 0); 159 if (_kvmRun == MAP_FAILED) 160 panic("KVM: Failed to map run data structure\n"); 161 162 // Setup a pointer to the MMIO ring buffer if coalesced MMIO is 163 // available. The offset into the KVM's communication page is 164 // provided by the coalesced MMIO capability. 165 int mmioOffset(kvm.capCoalescedMMIO()); 166 if (!p->useCoalescedMMIO) { 167 inform("KVM: Coalesced MMIO disabled by config.\n"); 168 } else if (mmioOffset) { 169 inform("KVM: Coalesced IO available\n"); 170 mmioRing = (struct kvm_coalesced_mmio_ring *)( 171 (char *)_kvmRun + (mmioOffset * pageSize)); 172 } else { 173 inform("KVM: Coalesced not supported by host OS\n"); 174 } 175 176 thread->startup(); 177} 178 179void 180BaseKvmCPU::regStats() 181{ 182 using namespace Stats; 183 184 BaseCPU::regStats(); 185 186 numInsts 187 .name(name() + ".committedInsts") 188 .desc("Number of instructions committed") 189 ; 190 191 numVMExits 192 .name(name() + ".numVMExits") 193 .desc("total number of KVM exits") 194 ; 195 196 numMMIO 197 .name(name() + ".numMMIO") 198 .desc("number of VM exits due to memory mapped IO") 199 ; 200 201 numCoalescedMMIO 202 .name(name() + ".numCoalescedMMIO") 203 .desc("number of coalesced memory mapped IO requests") 204 ; 205 206 numIO 207 .name(name() + ".numIO") 208 .desc("number of VM exits due to legacy IO") 209 ; 210 211 numHalt 212 .name(name() + ".numHalt") 213 .desc("number of VM exits due to wait for interrupt instructions") 214 ; 215 216 numInterrupts 217 .name(name() + ".numInterrupts") 218 .desc("number of interrupts delivered") 219 ; 220 221 numHypercalls 222 .name(name() + ".numHypercalls") 223 .desc("number of hypercalls") 224 ; 225} 226 227void 228BaseKvmCPU::serializeThread(std::ostream &os, ThreadID tid) 229{ 230 if (DTRACE(Checkpoint)) { 231 DPRINTF(Checkpoint, "KVM: Serializing thread %i:\n", tid); 232 dump(); 233 } 234 235 // Update the thread context so we have something to serialize. 236 syncThreadContext(); 237 238 assert(tid == 0); 239 assert(_status == Idle); 240 thread->serialize(os); 241} 242 243void 244BaseKvmCPU::unserializeThread(Checkpoint *cp, const std::string §ion, 245 ThreadID tid) 246{ 247 DPRINTF(Checkpoint, "KVM: Unserialize thread %i:\n", tid); 248 249 assert(tid == 0); 250 assert(_status == Idle); 251 thread->unserialize(cp, section); 252 threadContextDirty = true; 253} 254 255unsigned int 256BaseKvmCPU::drain(DrainManager *dm) 257{ 258 if (switchedOut()) 259 return 0; 260 261 DPRINTF(Kvm, "drain\n"); 262 263 // De-schedule the tick event so we don't insert any more MMIOs 264 // into the system while it is draining. 265 if (tickEvent.scheduled()) 266 deschedule(tickEvent); 267 268 _status = Idle; 269 return 0; 270} 271 272void 273BaseKvmCPU::drainResume() 274{ 275 assert(!tickEvent.scheduled()); 276 277 // We might have been switched out. In that case, we don't need to 278 // do anything. 279 if (switchedOut()) 280 return; 281 282 DPRINTF(Kvm, "drainResume\n"); 283 verifyMemoryMode(); 284 285 // The tick event is de-scheduled as a part of the draining 286 // process. Re-schedule it if the thread context is active. 287 if (tc->status() == ThreadContext::Active) { 288 schedule(tickEvent, nextCycle()); 289 _status = Running; 290 } else { 291 _status = Idle; 292 } 293} 294 295void 296BaseKvmCPU::switchOut() 297{ 298 DPRINTF(Kvm, "switchOut\n"); 299 300 // Make sure to update the thread context in case, the new CPU 301 // will need to access it. 302 syncThreadContext(); 303 304 BaseCPU::switchOut(); 305 306 // We should have drained prior to executing a switchOut, which 307 // means that the tick event shouldn't be scheduled and the CPU is 308 // idle. 309 assert(!tickEvent.scheduled()); 310 assert(_status == Idle); 311} 312 313void 314BaseKvmCPU::takeOverFrom(BaseCPU *cpu) 315{ 316 DPRINTF(Kvm, "takeOverFrom\n"); 317 318 BaseCPU::takeOverFrom(cpu); 319 320 // We should have drained prior to executing a switchOut, which 321 // means that the tick event shouldn't be scheduled and the CPU is 322 // idle. 323 assert(!tickEvent.scheduled()); 324 assert(_status == Idle); 325 assert(threadContexts.size() == 1); 326 327 // The BaseCPU updated the thread context, make sure that we 328 // synchronize next time we enter start the CPU. 329 threadContextDirty = true; 330} 331 332void 333BaseKvmCPU::verifyMemoryMode() const 334{ 335 if (!(system->isAtomicMode() && system->bypassCaches())) { 336 fatal("The KVM-based CPUs requires the memory system to be in the " 337 "'atomic_noncaching' mode.\n"); 338 } 339} 340 341void 342BaseKvmCPU::wakeup() 343{ 344 DPRINTF(Kvm, "wakeup()\n"); 345 346 if (thread->status() != ThreadContext::Suspended) 347 return; 348 349 thread->activate(); 350} 351 352void 353BaseKvmCPU::activateContext(ThreadID thread_num, Cycles delay) 354{ 355 DPRINTF(Kvm, "ActivateContext %d (%d cycles)\n", thread_num, delay); 356 357 assert(thread_num == 0); 358 assert(thread); 359 360 assert(_status == Idle); 361 assert(!tickEvent.scheduled()); 362 363 numCycles += ticksToCycles(thread->lastActivate - thread->lastSuspend) 364 * hostFactor; 365 366 schedule(tickEvent, clockEdge(delay)); 367 _status = Running; 368} 369 370 371void 372BaseKvmCPU::suspendContext(ThreadID thread_num) 373{ 374 DPRINTF(Kvm, "SuspendContext %d\n", thread_num); 375 376 assert(thread_num == 0); 377 assert(thread); 378 379 if (_status == Idle) 380 return; 381 382 assert(_status == Running); 383 384 // The tick event may no be scheduled if the quest has requested 385 // the monitor to wait for interrupts. The normal CPU models can 386 // get their tick events descheduled by quiesce instructions, but 387 // that can't happen here. 388 if (tickEvent.scheduled()) 389 deschedule(tickEvent); 390 391 _status = Idle; 392} 393 394void 395BaseKvmCPU::deallocateContext(ThreadID thread_num) 396{ 397 // for now, these are equivalent 398 suspendContext(thread_num); 399} 400 401void 402BaseKvmCPU::haltContext(ThreadID thread_num) 403{ 404 // for now, these are equivalent 405 suspendContext(thread_num); 406} 407 408ThreadContext * 409BaseKvmCPU::getContext(int tn) 410{ 411 assert(tn == 0); 412 syncThreadContext(); 413 return tc; 414} 415 416 417Counter 418BaseKvmCPU::totalInsts() const 419{ 420 return ctrInsts; 421} 422 423Counter 424BaseKvmCPU::totalOps() const 425{ 426 hack_once("Pretending totalOps is equivalent to totalInsts()\n"); 427 return ctrInsts; 428} 429 430void 431BaseKvmCPU::dump() 432{ 433 inform("State dumping not implemented."); 434} 435 436void 437BaseKvmCPU::tick() 438{ 439 assert(_status == Running); 440 441 DPRINTF(KvmRun, "Entering KVM...\n"); 442 443 Tick ticksToExecute(mainEventQueue.nextTick() - curTick()); 444 Tick ticksExecuted(kvmRun(ticksToExecute)); 445 446 Tick delay(ticksExecuted + handleKvmExit()); 447 448 switch (_status) { 449 case Running: 450 schedule(tickEvent, clockEdge(ticksToCycles(delay))); 451 break; 452 453 default: 454 /* The CPU is halted or waiting for an interrupt from a 455 * device. Don't start it. */ 456 break; 457 } 458} 459 460uint64_t 461BaseKvmCPU::getHostCycles() const 462{ 463 return hwCycles.read(); 464} 465 466Tick 467BaseKvmCPU::kvmRun(Tick ticks) 468{ 469 // We might need to update the KVM state. 470 syncKvmState(); 471 // Entering into KVM implies that we'll have to reload the thread 472 // context from KVM if we want to access it. Flag the KVM state as 473 // dirty with respect to the cached thread context. 474 kvmStateDirty = true; 475 476 if (ticks < runTimer->resolution()) { 477 DPRINTF(KvmRun, "KVM: Adjusting tick count (%i -> %i)\n", 478 ticks, runTimer->resolution()); 479 ticks = runTimer->resolution(); 480 } 481 482 DPRINTF(KvmRun, "KVM: Executing for %i ticks\n", ticks); 483 timerOverflowed = false; 484 485 // Get hardware statistics after synchronizing contexts. The KVM 486 // state update might affect guest cycle counters. 487 uint64_t baseCycles(getHostCycles()); 488 uint64_t baseInstrs(hwInstructions.read()); 489 490 // Arm the run timer and start the cycle timer if it isn't 491 // controlled by the overflow timer. Starting/stopping the cycle 492 // timer automatically starts the other perf timers as they are in 493 // the same counter group. 494 runTimer->arm(ticks); 495 if (!perfControlledByTimer) 496 hwCycles.start(); 497 498 if (ioctl(KVM_RUN) == -1) { 499 if (errno != EINTR) 500 panic("KVM: Failed to start virtual CPU (errno: %i)\n", 501 errno); 502 } 503 504 runTimer->disarm(); 505 if (!perfControlledByTimer) 506 hwCycles.stop(); 507 508 509 const uint64_t hostCyclesExecuted(getHostCycles() - baseCycles); 510 const uint64_t simCyclesExecuted(hostCyclesExecuted * hostFactor); 511 const uint64_t instsExecuted(hwInstructions.read() - baseInstrs); 512 const Tick ticksExecuted(runTimer->ticksFromHostCycles(hostCyclesExecuted)); 513 514 if (ticksExecuted < ticks && 515 timerOverflowed && 516 _kvmRun->exit_reason == KVM_EXIT_INTR) { 517 // TODO: We should probably do something clever here... 518 warn("KVM: Early timer event, requested %i ticks but got %i ticks.\n", 519 ticks, ticksExecuted); 520 } 521 522 /* Update statistics */ 523 numCycles += simCyclesExecuted;; 524 ++numVMExits; 525 numInsts += instsExecuted; 526 ctrInsts += instsExecuted; 527 system->totalNumInsts += instsExecuted; 528 529 DPRINTF(KvmRun, "KVM: Executed %i instructions in %i cycles (%i ticks, sim cycles: %i).\n", 530 instsExecuted, hostCyclesExecuted, ticksExecuted, simCyclesExecuted); 531 532 return ticksExecuted + flushCoalescedMMIO(); 533} 534 535void 536BaseKvmCPU::kvmNonMaskableInterrupt() 537{ 538 ++numInterrupts; 539 if (ioctl(KVM_NMI) == -1) 540 panic("KVM: Failed to deliver NMI to virtual CPU\n"); 541} 542 543void 544BaseKvmCPU::kvmInterrupt(const struct kvm_interrupt &interrupt) 545{ 546 ++numInterrupts; 547 if (ioctl(KVM_INTERRUPT, (void *)&interrupt) == -1) 548 panic("KVM: Failed to deliver interrupt to virtual CPU\n"); 549} 550 551void 552BaseKvmCPU::getRegisters(struct kvm_regs ®s) const 553{ 554 if (ioctl(KVM_GET_REGS, ®s) == -1) 555 panic("KVM: Failed to get guest registers\n"); 556} 557 558void 559BaseKvmCPU::setRegisters(const struct kvm_regs ®s) 560{ 561 if (ioctl(KVM_SET_REGS, (void *)®s) == -1) 562 panic("KVM: Failed to set guest registers\n"); 563} 564 565void 566BaseKvmCPU::getSpecialRegisters(struct kvm_sregs ®s) const 567{ 568 if (ioctl(KVM_GET_SREGS, ®s) == -1) 569 panic("KVM: Failed to get guest special registers\n"); 570} 571 572void 573BaseKvmCPU::setSpecialRegisters(const struct kvm_sregs ®s) 574{ 575 if (ioctl(KVM_SET_SREGS, (void *)®s) == -1) 576 panic("KVM: Failed to set guest special registers\n"); 577} 578 579void 580BaseKvmCPU::getFPUState(struct kvm_fpu &state) const 581{ 582 if (ioctl(KVM_GET_FPU, &state) == -1) 583 panic("KVM: Failed to get guest FPU state\n"); 584} 585 586void 587BaseKvmCPU::setFPUState(const struct kvm_fpu &state) 588{ 589 if (ioctl(KVM_SET_FPU, (void *)&state) == -1) 590 panic("KVM: Failed to set guest FPU state\n"); 591} 592 593 594void 595BaseKvmCPU::setOneReg(uint64_t id, const void *addr) 596{ 597#ifdef KVM_SET_ONE_REG 598 struct kvm_one_reg reg; 599 reg.id = id; 600 reg.addr = (uint64_t)addr; 601 602 if (ioctl(KVM_SET_ONE_REG, ®) == -1) { 603 panic("KVM: Failed to set register (0x%x) value (errno: %i)\n", 604 id, errno); 605 } 606#else 607 panic("KVM_SET_ONE_REG is unsupported on this platform.\n"); 608#endif 609} 610 611void 612BaseKvmCPU::getOneReg(uint64_t id, void *addr) const 613{ 614#ifdef KVM_GET_ONE_REG 615 struct kvm_one_reg reg; 616 reg.id = id; 617 reg.addr = (uint64_t)addr; 618 619 if (ioctl(KVM_GET_ONE_REG, ®) == -1) { 620 panic("KVM: Failed to get register (0x%x) value (errno: %i)\n", 621 id, errno); 622 } 623#else 624 panic("KVM_GET_ONE_REG is unsupported on this platform.\n"); 625#endif 626} 627 628std::string 629BaseKvmCPU::getAndFormatOneReg(uint64_t id) const 630{ 631#ifdef KVM_GET_ONE_REG 632 std::ostringstream ss; 633 634 ss.setf(std::ios::hex, std::ios::basefield); 635 ss.setf(std::ios::showbase); 636#define HANDLE_INTTYPE(len) \ 637 case KVM_REG_SIZE_U ## len: { \ 638 uint ## len ## _t value; \ 639 getOneReg(id, &value); \ 640 ss << value; \ 641 } break 642 643#define HANDLE_ARRAY(len) \ 644 case KVM_REG_SIZE_U ## len: { \ 645 uint8_t value[len / 8]; \ 646 getOneReg(id, value); \ 647 ss << "[" << value[0]; \ 648 for (int i = 1; i < len / 8; ++i) \ 649 ss << ", " << value[i]; \ 650 ss << "]"; \ 651 } break 652 653 switch (id & KVM_REG_SIZE_MASK) { 654 HANDLE_INTTYPE(8); 655 HANDLE_INTTYPE(16); 656 HANDLE_INTTYPE(32); 657 HANDLE_INTTYPE(64); 658 HANDLE_ARRAY(128); 659 HANDLE_ARRAY(256); 660 HANDLE_ARRAY(512); 661 HANDLE_ARRAY(1024); 662 default: 663 ss << "??"; 664 } 665 666#undef HANDLE_INTTYPE 667#undef HANDLE_ARRAY 668 669 return ss.str(); 670#else 671 panic("KVM_GET_ONE_REG is unsupported on this platform.\n"); 672#endif 673} 674 675void 676BaseKvmCPU::syncThreadContext() 677{ 678 if (!kvmStateDirty) 679 return; 680 681 assert(!threadContextDirty); 682 683 updateThreadContext(); 684 kvmStateDirty = false; 685} 686 687void 688BaseKvmCPU::syncKvmState() 689{ 690 if (!threadContextDirty) 691 return; 692 693 assert(!kvmStateDirty); 694 695 updateKvmState(); 696 threadContextDirty = false; 697} 698 699Tick 700BaseKvmCPU::handleKvmExit() 701{ 702 DPRINTF(KvmRun, "handleKvmExit (exit_reason: %i)\n", _kvmRun->exit_reason); 703 704 switch (_kvmRun->exit_reason) { 705 case KVM_EXIT_UNKNOWN: 706 return handleKvmExitUnknown(); 707 708 case KVM_EXIT_EXCEPTION: 709 return handleKvmExitException(); 710 711 case KVM_EXIT_IO: 712 ++numIO; 713 return handleKvmExitIO(); 714 715 case KVM_EXIT_HYPERCALL: 716 ++numHypercalls; 717 return handleKvmExitHypercall(); 718 719 case KVM_EXIT_HLT: 720 /* The guest has halted and is waiting for interrupts */ 721 DPRINTF(Kvm, "handleKvmExitHalt\n"); 722 ++numHalt; 723 724 // Suspend the thread until the next interrupt arrives 725 thread->suspend(); 726 727 // This is actually ignored since the thread is suspended. 728 return 0; 729 730 case KVM_EXIT_MMIO: 731 /* Service memory mapped IO requests */ 732 DPRINTF(KvmIO, "KVM: Handling MMIO (w: %u, addr: 0x%x, len: %u)\n", 733 _kvmRun->mmio.is_write, 734 _kvmRun->mmio.phys_addr, _kvmRun->mmio.len); 735 736 ++numMMIO; 737 return doMMIOAccess(_kvmRun->mmio.phys_addr, _kvmRun->mmio.data, 738 _kvmRun->mmio.len, _kvmRun->mmio.is_write); 739 740 case KVM_EXIT_IRQ_WINDOW_OPEN: 741 return handleKvmExitIRQWindowOpen(); 742 743 case KVM_EXIT_FAIL_ENTRY: 744 return handleKvmExitFailEntry(); 745 746 case KVM_EXIT_INTR: 747 /* KVM was interrupted by a signal, restart it in the next 748 * tick. */ 749 return 0; 750 751 case KVM_EXIT_INTERNAL_ERROR: 752 panic("KVM: Internal error (suberror: %u)\n", 753 _kvmRun->internal.suberror); 754 755 default: 756 dump(); 757 panic("KVM: Unexpected exit (exit_reason: %u)\n", _kvmRun->exit_reason); 758 } 759} 760 761Tick 762BaseKvmCPU::handleKvmExitIO() 763{ 764 panic("KVM: Unhandled guest IO (dir: %i, size: %i, port: 0x%x, count: %i)\n", 765 _kvmRun->io.direction, _kvmRun->io.size, 766 _kvmRun->io.port, _kvmRun->io.count); 767} 768 769Tick 770BaseKvmCPU::handleKvmExitHypercall() 771{ 772 panic("KVM: Unhandled hypercall\n"); 773} 774 775Tick 776BaseKvmCPU::handleKvmExitIRQWindowOpen() 777{ 778 warn("KVM: Unhandled IRQ window.\n"); 779 return 0; 780} 781 782 783Tick 784BaseKvmCPU::handleKvmExitUnknown() 785{ 786 dump(); 787 panic("KVM: Unknown error when starting vCPU (hw reason: 0x%llx)\n", 788 _kvmRun->hw.hardware_exit_reason); 789} 790 791Tick 792BaseKvmCPU::handleKvmExitException() 793{ 794 dump(); 795 panic("KVM: Got exception when starting vCPU " 796 "(exception: %u, error_code: %u)\n", 797 _kvmRun->ex.exception, _kvmRun->ex.error_code); 798} 799 800Tick 801BaseKvmCPU::handleKvmExitFailEntry() 802{ 803 dump(); 804 panic("KVM: Failed to enter virtualized mode (hw reason: 0x%llx)\n", 805 _kvmRun->fail_entry.hardware_entry_failure_reason); 806} 807 808Tick 809BaseKvmCPU::doMMIOAccess(Addr paddr, void *data, int size, bool write) 810{ 811 mmio_req.setPhys(paddr, size, Request::UNCACHEABLE, dataMasterId()); 812 813 const MemCmd cmd(write ? MemCmd::WriteReq : MemCmd::ReadReq); 814 Packet pkt(&mmio_req, cmd); 815 pkt.dataStatic(data); 816 return dataPort.sendAtomic(&pkt); 817} 818 819int 820BaseKvmCPU::ioctl(int request, long p1) const 821{ 822 if (vcpuFD == -1) 823 panic("KVM: CPU ioctl called before initialization\n"); 824 825 return ::ioctl(vcpuFD, request, p1); 826} 827 828Tick 829BaseKvmCPU::flushCoalescedMMIO() 830{ 831 if (!mmioRing) 832 return 0; 833 834 DPRINTF(KvmIO, "KVM: Flushing the coalesced MMIO ring buffer\n"); 835 836 // TODO: We might need to do synchronization when we start to 837 // support multiple CPUs 838 Tick ticks(0); 839 while (mmioRing->first != mmioRing->last) { 840 struct kvm_coalesced_mmio &ent( 841 mmioRing->coalesced_mmio[mmioRing->first]); 842 843 DPRINTF(KvmIO, "KVM: Handling coalesced MMIO (addr: 0x%x, len: %u)\n", 844 ent.phys_addr, ent.len); 845 846 ++numCoalescedMMIO; 847 ticks += doMMIOAccess(ent.phys_addr, ent.data, ent.len, true); 848 849 mmioRing->first = (mmioRing->first + 1) % KVM_COALESCED_MMIO_MAX; 850 } 851 852 return ticks; 853} 854 855void 856BaseKvmCPU::setupSignalHandler() 857{ 858 struct sigaction sa; 859 860 memset(&sa, 0, sizeof(sa)); 861 sa.sa_sigaction = onTimerOverflow; 862 sa.sa_flags = SA_SIGINFO | SA_RESTART; 863 if (sigaction(KVM_TIMER_SIGNAL, &sa, NULL) == -1) 864 panic("KVM: Failed to setup vCPU signal handler\n"); 865} 866 867void 868BaseKvmCPU::setupCounters() 869{ 870 DPRINTF(Kvm, "Attaching cycle counter...\n"); 871 PerfKvmCounterConfig cfgCycles(PERF_TYPE_HARDWARE, 872 PERF_COUNT_HW_CPU_CYCLES); 873 cfgCycles.disabled(true) 874 .pinned(true); 875 876 if (perfControlledByTimer) { 877 // We need to configure the cycles counter to send overflows 878 // since we are going to use it to trigger timer signals that 879 // trap back into m5 from KVM. In practice, this means that we 880 // need to set some non-zero sample period that gets 881 // overridden when the timer is armed. 882 cfgCycles.wakeupEvents(1) 883 .samplePeriod(42); 884 } 885 886 hwCycles.attach(cfgCycles, 887 0); // TID (0 => currentThread) 888 889 DPRINTF(Kvm, "Attaching instruction counter...\n"); 890 PerfKvmCounterConfig cfgInstructions(PERF_TYPE_HARDWARE, 891 PERF_COUNT_HW_INSTRUCTIONS); 892 hwInstructions.attach(cfgInstructions, 893 0, // TID (0 => currentThread) 894 hwCycles); 895} 896