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