base.cc revision 9904
14403Srdreslin@umich.edu/* 21693Sstever@eecs.umich.edu * Copyright (c) 2012 ARM Limited 31693Sstever@eecs.umich.edu * All rights reserved 41693Sstever@eecs.umich.edu * 51693Sstever@eecs.umich.edu * The license below extends only to copyright in the software and shall 61693Sstever@eecs.umich.edu * not be construed as granting a license to any other intellectual 71693Sstever@eecs.umich.edu * property including but not limited to intellectual property relating 81693Sstever@eecs.umich.edu * to a hardware implementation of the functionality of the software 91693Sstever@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 101693Sstever@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 111693Sstever@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 121693Sstever@eecs.umich.edu * modified or unmodified, in source code or in binary form. 131693Sstever@eecs.umich.edu * 141693Sstever@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 151693Sstever@eecs.umich.edu * modification, are permitted provided that the following conditions are 161693Sstever@eecs.umich.edu * met: redistributions of source code must retain the above copyright 171693Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 181693Sstever@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 191693Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 201693Sstever@eecs.umich.edu * documentation and/or other materials provided with the distribution; 211693Sstever@eecs.umich.edu * neither the name of the copyright holders nor the names of its 221693Sstever@eecs.umich.edu * contributors may be used to endorse or promote products derived from 231693Sstever@eecs.umich.edu * this software without specific prior written permission. 241693Sstever@eecs.umich.edu * 251693Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 261693Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 271693Sstever@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 281693Sstever@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 293358Srdreslin@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 303358Srdreslin@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 311516SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 326654Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 336654Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 346654Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 356654Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 363358Srdreslin@umich.edu * 373358Srdreslin@umich.edu * Authors: Andreas Sandberg 386654Snate@binkert.org */ 396654Snate@binkert.org 401516SN/A#include <linux/kvm.h> 413358Srdreslin@umich.edu#include <sys/ioctl.h> 423358Srdreslin@umich.edu#include <sys/mman.h> 433358Srdreslin@umich.edu#include <unistd.h> 443358Srdreslin@umich.edu 453358Srdreslin@umich.edu#include <cerrno> 463358Srdreslin@umich.edu#include <csignal> 473358Srdreslin@umich.edu#include <ostream> 483358Srdreslin@umich.edu 493358Srdreslin@umich.edu#include "arch/mmapped_ipr.hh" 503358Srdreslin@umich.edu#include "arch/utility.hh" 513358Srdreslin@umich.edu#include "cpu/kvm/base.hh" 523358Srdreslin@umich.edu#include "debug/Checkpoint.hh" 533360Srdreslin@umich.edu#include "debug/Drain.hh" 543358Srdreslin@umich.edu#include "debug/Kvm.hh" 553360Srdreslin@umich.edu#include "debug/KvmIO.hh" 563360Srdreslin@umich.edu#include "debug/KvmRun.hh" 573360Srdreslin@umich.edu#include "params/BaseKvmCPU.hh" 585255Ssaidi@eecs.umich.edu#include "sim/process.hh" 593360Srdreslin@umich.edu#include "sim/system.hh" 603360Srdreslin@umich.edu 613360Srdreslin@umich.edu#include <signal.h> 625255Ssaidi@eecs.umich.edu 633358Srdreslin@umich.edu/* Used by some KVM macros */ 644403Srdreslin@umich.edu#define PAGE_SIZE pageSize 653360Srdreslin@umich.edu 663358Srdreslin@umich.eduvolatile bool timerOverflowed = false; 673358Srdreslin@umich.edu 683358Srdreslin@umich.eduBaseKvmCPU::BaseKvmCPU(BaseKvmCPUParams *params) 693358Srdreslin@umich.edu : BaseCPU(params), 703358Srdreslin@umich.edu vm(*params->kvmVM), 713358Srdreslin@umich.edu _status(Idle), 723358Srdreslin@umich.edu dataPort(name() + ".dcache_port", this), 733358Srdreslin@umich.edu instPort(name() + ".icache_port", this), 743358Srdreslin@umich.edu threadContextDirty(true), 753360Srdreslin@umich.edu kvmStateDirty(false), 763360Srdreslin@umich.edu vcpuID(vm.allocVCPUID()), vcpuFD(-1), vcpuMMapSize(0), 773360Srdreslin@umich.edu _kvmRun(NULL), mmioRing(NULL), 783360Srdreslin@umich.edu pageSize(sysconf(_SC_PAGE_SIZE)), 793358Srdreslin@umich.edu tickEvent(*this), 803358Srdreslin@umich.edu activeInstPeriod(0), 813358Srdreslin@umich.edu perfControlledByTimer(params->usePerfOverflow), 823358Srdreslin@umich.edu hostFreq(params->hostFreq), 834403Srdreslin@umich.edu hostFactor(params->hostFactor), 844403Srdreslin@umich.edu drainManager(NULL), 855256Ssaidi@eecs.umich.edu ctrInsts(0) 865255Ssaidi@eecs.umich.edu{ 873358Srdreslin@umich.edu if (pageSize == -1) 883358Srdreslin@umich.edu panic("KVM: Failed to determine host page size (%i)\n", 894403Srdreslin@umich.edu errno); 904403Srdreslin@umich.edu 915255Ssaidi@eecs.umich.edu thread = new SimpleThread(this, 0, params->system, 923358Srdreslin@umich.edu params->itb, params->dtb, params->isa[0]); 933358Srdreslin@umich.edu thread->setStatus(ThreadContext::Halted); 944403Srdreslin@umich.edu tc = thread->getTC(); 955255Ssaidi@eecs.umich.edu threadContexts.push_back(tc); 964403Srdreslin@umich.edu 973358Srdreslin@umich.edu setupCounters(); 983358Srdreslin@umich.edu 994403Srdreslin@umich.edu if (params->usePerfOverflow) 1005255Ssaidi@eecs.umich.edu runTimer.reset(new PerfKvmTimer(hwCycles, 1014403Srdreslin@umich.edu KVM_TIMER_SIGNAL, 1023358Srdreslin@umich.edu params->hostFactor, 1033358Srdreslin@umich.edu params->hostFreq)); 1044403Srdreslin@umich.edu else 1055255Ssaidi@eecs.umich.edu runTimer.reset(new PosixKvmTimer(KVM_TIMER_SIGNAL, CLOCK_MONOTONIC, 1064403Srdreslin@umich.edu params->hostFactor, 1073358Srdreslin@umich.edu params->hostFreq)); 1083358Srdreslin@umich.edu} 1094403Srdreslin@umich.edu 1105255Ssaidi@eecs.umich.eduBaseKvmCPU::~BaseKvmCPU() 1114403Srdreslin@umich.edu{ 1124403Srdreslin@umich.edu if (_kvmRun) 1133358Srdreslin@umich.edu munmap(_kvmRun, vcpuMMapSize); 1143358Srdreslin@umich.edu close(vcpuFD); 1154403Srdreslin@umich.edu} 1165255Ssaidi@eecs.umich.edu 1174403Srdreslin@umich.eduvoid 1184403Srdreslin@umich.eduBaseKvmCPU::init() 1194403Srdreslin@umich.edu{ 1203360Srdreslin@umich.edu BaseCPU::init(); 1214403Srdreslin@umich.edu 1223358Srdreslin@umich.edu if (numThreads != 1) 1233358Srdreslin@umich.edu fatal("KVM: Multithreading not supported"); 1244403Srdreslin@umich.edu 1255255Ssaidi@eecs.umich.edu tc->initMemProxies(tc); 1264403Srdreslin@umich.edu 1273358Srdreslin@umich.edu // initialize CPU, including PC 1283358Srdreslin@umich.edu if (FullSystem && !switchedOut()) 1294403Srdreslin@umich.edu TheISA::initCPU(tc, tc->contextId()); 1305255Ssaidi@eecs.umich.edu 1314403Srdreslin@umich.edu mmio_req.setThreadContext(tc->contextId(), 0); 1323358Srdreslin@umich.edu} 1333358Srdreslin@umich.edu 1344403Srdreslin@umich.eduvoid 1355256Ssaidi@eecs.umich.eduBaseKvmCPU::startup() 1365255Ssaidi@eecs.umich.edu{ 1374403Srdreslin@umich.edu const BaseKvmCPUParams * const p( 1383358Srdreslin@umich.edu dynamic_cast<const BaseKvmCPUParams *>(params())); 1393358Srdreslin@umich.edu 1404403Srdreslin@umich.edu Kvm &kvm(vm.kvm); 1415255Ssaidi@eecs.umich.edu 1424403Srdreslin@umich.edu BaseCPU::startup(); 1434403Srdreslin@umich.edu 1444403Srdreslin@umich.edu assert(vcpuFD == -1); 1453360Srdreslin@umich.edu 1464403Srdreslin@umich.edu // Tell the VM that a CPU is about to start. 1473358Srdreslin@umich.edu vm.cpuStartup(); 1483358Srdreslin@umich.edu 1494403Srdreslin@umich.edu // We can't initialize KVM CPUs in BaseKvmCPU::init() since we are 1505255Ssaidi@eecs.umich.edu // not guaranteed that the parent KVM VM has initialized at that 1514403Srdreslin@umich.edu // point. Initialize virtual CPUs here instead. 1524403Srdreslin@umich.edu vcpuFD = vm.createVCPU(vcpuID); 1534403Srdreslin@umich.edu 1543360Srdreslin@umich.edu // Setup signal handlers. This has to be done after the vCPU is 1554403Srdreslin@umich.edu // created since it manipulates the vCPU signal mask. 1563358Srdreslin@umich.edu setupSignalHandler(); 1573358Srdreslin@umich.edu 1583358Srdreslin@umich.edu // Map the KVM run structure */ 1593358Srdreslin@umich.edu vcpuMMapSize = kvm.getVCPUMMapSize(); 1603358Srdreslin@umich.edu _kvmRun = (struct kvm_run *)mmap(0, vcpuMMapSize, 1613358Srdreslin@umich.edu PROT_READ | PROT_WRITE, MAP_SHARED, 1623358Srdreslin@umich.edu vcpuFD, 0); 1633358Srdreslin@umich.edu if (_kvmRun == MAP_FAILED) 1643358Srdreslin@umich.edu panic("KVM: Failed to map run data structure\n"); 1653358Srdreslin@umich.edu 1663358Srdreslin@umich.edu // Setup a pointer to the MMIO ring buffer if coalesced MMIO is 1673358Srdreslin@umich.edu // available. The offset into the KVM's communication page is 1683358Srdreslin@umich.edu // provided by the coalesced MMIO capability. 1693358Srdreslin@umich.edu int mmioOffset(kvm.capCoalescedMMIO()); 1703358Srdreslin@umich.edu if (!p->useCoalescedMMIO) { 1713358Srdreslin@umich.edu inform("KVM: Coalesced MMIO disabled by config.\n"); 1723358Srdreslin@umich.edu } else if (mmioOffset) { 1733358Srdreslin@umich.edu inform("KVM: Coalesced IO available\n"); 1743358Srdreslin@umich.edu mmioRing = (struct kvm_coalesced_mmio_ring *)( 1753358Srdreslin@umich.edu (char *)_kvmRun + (mmioOffset * pageSize)); 1763358Srdreslin@umich.edu } else { 1773358Srdreslin@umich.edu inform("KVM: Coalesced not supported by host OS\n"); 1783358Srdreslin@umich.edu } 1793358Srdreslin@umich.edu 1803358Srdreslin@umich.edu thread->startup(); 1813358Srdreslin@umich.edu} 1823358Srdreslin@umich.edu 1833358Srdreslin@umich.eduvoid 1843358Srdreslin@umich.eduBaseKvmCPU::regStats() 1853358Srdreslin@umich.edu{ 1863358Srdreslin@umich.edu using namespace Stats; 1873358Srdreslin@umich.edu 1883358Srdreslin@umich.edu BaseCPU::regStats(); 1893358Srdreslin@umich.edu 1901516SN/A numInsts 1913358Srdreslin@umich.edu .name(name() + ".committedInsts") 1923358Srdreslin@umich.edu .desc("Number of instructions committed") 1933358Srdreslin@umich.edu ; 1941516SN/A 1953358Srdreslin@umich.edu numVMExits 1963358Srdreslin@umich.edu .name(name() + ".numVMExits") 1973358Srdreslin@umich.edu .desc("total number of KVM exits") 1988931Sandreas.hansson@arm.com ; 19910720Sandreas.hansson@arm.com 2009790Sakash.bagdia@arm.com numVMHalfEntries 2011516SN/A .name(name() + ".numVMHalfEntries") 20210720Sandreas.hansson@arm.com .desc("number of KVM entries to finalize pending operations") 2033358Srdreslin@umich.edu ; 2043358Srdreslin@umich.edu 2053358Srdreslin@umich.edu numExitSignal 2063358Srdreslin@umich.edu .name(name() + ".numExitSignal") 2073358Srdreslin@umich.edu .desc("exits due to signal delivery") 2083358Srdreslin@umich.edu ; 2098847Sandreas.hansson@arm.com 2108847Sandreas.hansson@arm.com numMMIO 2118847Sandreas.hansson@arm.com .name(name() + ".numMMIO") 2128847Sandreas.hansson@arm.com .desc("number of VM exits due to memory mapped IO") 2133358Srdreslin@umich.edu ; 2143358Srdreslin@umich.edu 2153358Srdreslin@umich.edu numCoalescedMMIO 2163358Srdreslin@umich.edu .name(name() + ".numCoalescedMMIO") 2173358Srdreslin@umich.edu .desc("number of coalesced memory mapped IO requests") 2183358Srdreslin@umich.edu ; 2193358Srdreslin@umich.edu 2203358Srdreslin@umich.edu numIO 2217876Sgblack@eecs.umich.edu .name(name() + ".numIO") 2223358Srdreslin@umich.edu .desc("number of VM exits due to legacy IO") 2233358Srdreslin@umich.edu ; 2243358Srdreslin@umich.edu 2253358Srdreslin@umich.edu numHalt 2263358Srdreslin@umich.edu .name(name() + ".numHalt") 2273358Srdreslin@umich.edu .desc("number of VM exits due to wait for interrupt instructions") 2288801Sgblack@eecs.umich.edu ; 2293358Srdreslin@umich.edu 2303358Srdreslin@umich.edu numInterrupts 2313358Srdreslin@umich.edu .name(name() + ".numInterrupts") 2323358Srdreslin@umich.edu .desc("number of interrupts delivered") 2333358Srdreslin@umich.edu ; 2343358Srdreslin@umich.edu 2353358Srdreslin@umich.edu numHypercalls 2363358Srdreslin@umich.edu .name(name() + ".numHypercalls") 2373358Srdreslin@umich.edu .desc("number of hypercalls") 2383358Srdreslin@umich.edu ; 2393358Srdreslin@umich.edu} 2403358Srdreslin@umich.edu 2413358Srdreslin@umich.eduvoid 2423358Srdreslin@umich.eduBaseKvmCPU::serializeThread(std::ostream &os, ThreadID tid) 2433358Srdreslin@umich.edu{ 2443358Srdreslin@umich.edu if (DTRACE(Checkpoint)) { 2453358Srdreslin@umich.edu DPRINTF(Checkpoint, "KVM: Serializing thread %i:\n", tid); 2463358Srdreslin@umich.edu dump(); 2473358Srdreslin@umich.edu } 2483358Srdreslin@umich.edu 2493358Srdreslin@umich.edu assert(tid == 0); 2503358Srdreslin@umich.edu assert(_status == Idle); 2513358Srdreslin@umich.edu thread->serialize(os); 2523358Srdreslin@umich.edu} 2533358Srdreslin@umich.edu 2543358Srdreslin@umich.eduvoid 2553358Srdreslin@umich.eduBaseKvmCPU::unserializeThread(Checkpoint *cp, const std::string §ion, 2563358Srdreslin@umich.edu ThreadID tid) 2571516SN/A{ 2585256Ssaidi@eecs.umich.edu DPRINTF(Checkpoint, "KVM: Unserialize thread %i:\n", tid); 2595256Ssaidi@eecs.umich.edu 2605256Ssaidi@eecs.umich.edu assert(tid == 0); 2615256Ssaidi@eecs.umich.edu assert(_status == Idle); 2623358Srdreslin@umich.edu thread->unserialize(cp, section); 2633358Srdreslin@umich.edu threadContextDirty = true; 2643358Srdreslin@umich.edu} 2653358Srdreslin@umich.edu 2663358Srdreslin@umich.eduunsigned int 2673358Srdreslin@umich.eduBaseKvmCPU::drain(DrainManager *dm) 2683358Srdreslin@umich.edu{ 2693358Srdreslin@umich.edu if (switchedOut()) 2703358Srdreslin@umich.edu return 0; 2713358Srdreslin@umich.edu 2723358Srdreslin@umich.edu DPRINTF(Drain, "BaseKvmCPU::drain\n"); 2733358Srdreslin@umich.edu switch (_status) { 2743358Srdreslin@umich.edu case Running: 2753358Srdreslin@umich.edu // The base KVM code is normally ready when it is in the 2763358Srdreslin@umich.edu // Running state, but the architecture specific code might be 2773358Srdreslin@umich.edu // of a different opinion. This may happen when the CPU been 2787525Ssteve.reinhardt@amd.com // notified of an event that hasn't been accepted by the vCPU 2793358Srdreslin@umich.edu // yet. 2803358Srdreslin@umich.edu if (!archIsDrained()) { 2813358Srdreslin@umich.edu drainManager = dm; 2823358Srdreslin@umich.edu return 1; 2833358Srdreslin@umich.edu } 2843646Srdreslin@umich.edu 2853358Srdreslin@umich.edu // The state of the CPU is consistent, so we don't need to do 2863358Srdreslin@umich.edu // anything special to drain it. We simply de-schedule the 2873358Srdreslin@umich.edu // tick event and enter the Idle state to prevent nasty things 288 // like MMIOs from happening. 289 if (tickEvent.scheduled()) 290 deschedule(tickEvent); 291 _status = Idle; 292 293 /** FALLTHROUGH */ 294 case Idle: 295 // Idle, no need to drain 296 assert(!tickEvent.scheduled()); 297 298 // Sync the thread context here since we'll need it when we 299 // switch CPUs or checkpoint the CPU. 300 syncThreadContext(); 301 302 return 0; 303 304 case RunningServiceCompletion: 305 // The CPU has just requested a service that was handled in 306 // the RunningService state, but the results have still not 307 // been reported to the CPU. Now, we /could/ probably just 308 // update the register state ourselves instead of letting KVM 309 // handle it, but that would be tricky. Instead, we enter KVM 310 // and let it do its stuff. 311 drainManager = dm; 312 313 DPRINTF(Drain, "KVM CPU is waiting for service completion, " 314 "requesting drain.\n"); 315 return 1; 316 317 case RunningService: 318 // We need to drain since the CPU is waiting for service (e.g., MMIOs) 319 drainManager = dm; 320 321 DPRINTF(Drain, "KVM CPU is waiting for service, requesting drain.\n"); 322 return 1; 323 324 default: 325 panic("KVM: Unhandled CPU state in drain()\n"); 326 return 0; 327 } 328} 329 330void 331BaseKvmCPU::drainResume() 332{ 333 assert(!tickEvent.scheduled()); 334 335 // We might have been switched out. In that case, we don't need to 336 // do anything. 337 if (switchedOut()) 338 return; 339 340 DPRINTF(Kvm, "drainResume\n"); 341 verifyMemoryMode(); 342 343 // The tick event is de-scheduled as a part of the draining 344 // process. Re-schedule it if the thread context is active. 345 if (tc->status() == ThreadContext::Active) { 346 schedule(tickEvent, nextCycle()); 347 _status = Running; 348 } else { 349 _status = Idle; 350 } 351} 352 353void 354BaseKvmCPU::switchOut() 355{ 356 DPRINTF(Kvm, "switchOut\n"); 357 358 BaseCPU::switchOut(); 359 360 // We should have drained prior to executing a switchOut, which 361 // means that the tick event shouldn't be scheduled and the CPU is 362 // idle. 363 assert(!tickEvent.scheduled()); 364 assert(_status == Idle); 365} 366 367void 368BaseKvmCPU::takeOverFrom(BaseCPU *cpu) 369{ 370 DPRINTF(Kvm, "takeOverFrom\n"); 371 372 BaseCPU::takeOverFrom(cpu); 373 374 // We should have drained prior to executing a switchOut, which 375 // means that the tick event shouldn't be scheduled and the CPU is 376 // idle. 377 assert(!tickEvent.scheduled()); 378 assert(_status == Idle); 379 assert(threadContexts.size() == 1); 380 381 // Force an update of the KVM state here instead of flagging the 382 // TC as dirty. This is not ideal from a performance point of 383 // view, but it makes debugging easier as it allows meaningful KVM 384 // state to be dumped before and after a takeover. 385 updateKvmState(); 386 threadContextDirty = false; 387} 388 389void 390BaseKvmCPU::verifyMemoryMode() const 391{ 392 if (!(system->isAtomicMode() && system->bypassCaches())) { 393 fatal("The KVM-based CPUs requires the memory system to be in the " 394 "'atomic_noncaching' mode.\n"); 395 } 396} 397 398void 399BaseKvmCPU::wakeup() 400{ 401 DPRINTF(Kvm, "wakeup()\n"); 402 403 if (thread->status() != ThreadContext::Suspended) 404 return; 405 406 thread->activate(); 407} 408 409void 410BaseKvmCPU::activateContext(ThreadID thread_num, Cycles delay) 411{ 412 DPRINTF(Kvm, "ActivateContext %d (%d cycles)\n", thread_num, delay); 413 414 assert(thread_num == 0); 415 assert(thread); 416 417 assert(_status == Idle); 418 assert(!tickEvent.scheduled()); 419 420 numCycles += ticksToCycles(thread->lastActivate - thread->lastSuspend); 421 422 schedule(tickEvent, clockEdge(delay)); 423 _status = Running; 424} 425 426 427void 428BaseKvmCPU::suspendContext(ThreadID thread_num) 429{ 430 DPRINTF(Kvm, "SuspendContext %d\n", thread_num); 431 432 assert(thread_num == 0); 433 assert(thread); 434 435 if (_status == Idle) 436 return; 437 438 assert(_status == Running); 439 440 // The tick event may no be scheduled if the quest has requested 441 // the monitor to wait for interrupts. The normal CPU models can 442 // get their tick events descheduled by quiesce instructions, but 443 // that can't happen here. 444 if (tickEvent.scheduled()) 445 deschedule(tickEvent); 446 447 _status = Idle; 448} 449 450void 451BaseKvmCPU::deallocateContext(ThreadID thread_num) 452{ 453 // for now, these are equivalent 454 suspendContext(thread_num); 455} 456 457void 458BaseKvmCPU::haltContext(ThreadID thread_num) 459{ 460 // for now, these are equivalent 461 suspendContext(thread_num); 462} 463 464ThreadContext * 465BaseKvmCPU::getContext(int tn) 466{ 467 assert(tn == 0); 468 syncThreadContext(); 469 return tc; 470} 471 472 473Counter 474BaseKvmCPU::totalInsts() const 475{ 476 return ctrInsts; 477} 478 479Counter 480BaseKvmCPU::totalOps() const 481{ 482 hack_once("Pretending totalOps is equivalent to totalInsts()\n"); 483 return ctrInsts; 484} 485 486void 487BaseKvmCPU::dump() 488{ 489 inform("State dumping not implemented."); 490} 491 492void 493BaseKvmCPU::tick() 494{ 495 Tick delay(0); 496 assert(_status != Idle); 497 498 switch (_status) { 499 case RunningService: 500 // handleKvmExit() will determine the next state of the CPU 501 delay = handleKvmExit(); 502 503 if (tryDrain()) 504 _status = Idle; 505 break; 506 507 case RunningServiceCompletion: 508 case Running: { 509 Tick ticksToExecute(mainEventQueue.nextTick() - curTick()); 510 511 // We might need to update the KVM state. 512 syncKvmState(); 513 514 // Setup any pending instruction count breakpoints using 515 // PerfEvent. 516 setupInstStop(); 517 518 DPRINTF(KvmRun, "Entering KVM...\n"); 519 if (drainManager) { 520 // Force an immediate exit from KVM after completing 521 // pending operations. The architecture-specific code 522 // takes care to run until it is in a state where it can 523 // safely be drained. 524 delay = kvmRunDrain(); 525 } else { 526 delay = kvmRun(ticksToExecute); 527 } 528 529 // Entering into KVM implies that we'll have to reload the thread 530 // context from KVM if we want to access it. Flag the KVM state as 531 // dirty with respect to the cached thread context. 532 kvmStateDirty = true; 533 534 // Enter into the RunningService state unless the 535 // simulation was stopped by a timer. 536 if (_kvmRun->exit_reason != KVM_EXIT_INTR) { 537 _status = RunningService; 538 } else { 539 ++numExitSignal; 540 _status = Running; 541 } 542 543 // Service any pending instruction events. The vCPU should 544 // have exited in time for the event using the instruction 545 // counter configured by setupInstStop(). 546 comInstEventQueue[0]->serviceEvents(ctrInsts); 547 system->instEventQueue.serviceEvents(system->totalNumInsts); 548 549 if (tryDrain()) 550 _status = Idle; 551 } break; 552 553 default: 554 panic("BaseKvmCPU entered tick() in an illegal state (%i)\n", 555 _status); 556 } 557 558 // Schedule a new tick if we are still running 559 if (_status != Idle) 560 schedule(tickEvent, clockEdge(ticksToCycles(delay))); 561} 562 563Tick 564BaseKvmCPU::kvmRunDrain() 565{ 566 // By default, the only thing we need to drain is a pending IO 567 // operation which assumes that we are in the 568 // RunningServiceCompletion state. 569 assert(_status == RunningServiceCompletion); 570 571 // Deliver the data from the pending IO operation and immediately 572 // exit. 573 return kvmRun(0); 574} 575 576uint64_t 577BaseKvmCPU::getHostCycles() const 578{ 579 return hwCycles.read(); 580} 581 582Tick 583BaseKvmCPU::kvmRun(Tick ticks) 584{ 585 Tick ticksExecuted; 586 DPRINTF(KvmRun, "KVM: Executing for %i ticks\n", ticks); 587 timerOverflowed = false; 588 589 if (ticks == 0) { 590 // Settings ticks == 0 is a special case which causes an entry 591 // into KVM that finishes pending operations (e.g., IO) and 592 // then immediately exits. 593 DPRINTF(KvmRun, "KVM: Delivering IO without full guest entry\n"); 594 595 ++numVMHalfEntries; 596 597 // This signal is always masked while we are executing in gem5 598 // and gets unmasked temporarily as soon as we enter into 599 // KVM. See setSignalMask() and setupSignalHandler(). 600 raise(KVM_TIMER_SIGNAL); 601 602 // Enter into KVM. KVM will check for signals after completing 603 // pending operations (IO). Since the KVM_TIMER_SIGNAL is 604 // pending, this forces an immediate exit into gem5 again. We 605 // don't bother to setup timers since this shouldn't actually 606 // execute any code in the guest. 607 ioctlRun(); 608 609 // We always execute at least one cycle to prevent the 610 // BaseKvmCPU::tick() to be rescheduled on the same tick 611 // twice. 612 ticksExecuted = clockPeriod(); 613 } else { 614 if (ticks < runTimer->resolution()) { 615 DPRINTF(KvmRun, "KVM: Adjusting tick count (%i -> %i)\n", 616 ticks, runTimer->resolution()); 617 ticks = runTimer->resolution(); 618 } 619 620 // Get hardware statistics after synchronizing contexts. The KVM 621 // state update might affect guest cycle counters. 622 uint64_t baseCycles(getHostCycles()); 623 uint64_t baseInstrs(hwInstructions.read()); 624 625 // Arm the run timer and start the cycle timer if it isn't 626 // controlled by the overflow timer. Starting/stopping the cycle 627 // timer automatically starts the other perf timers as they are in 628 // the same counter group. 629 runTimer->arm(ticks); 630 if (!perfControlledByTimer) 631 hwCycles.start(); 632 633 ioctlRun(); 634 635 runTimer->disarm(); 636 if (!perfControlledByTimer) 637 hwCycles.stop(); 638 639 // The timer signal may have been delivered after we exited 640 // from KVM. It will be pending in that case since it is 641 // masked when we aren't executing in KVM. Discard it to make 642 // sure we don't deliver it immediately next time we try to 643 // enter into KVM. 644 discardPendingSignal(KVM_TIMER_SIGNAL); 645 discardPendingSignal(KVM_INST_SIGNAL); 646 647 const uint64_t hostCyclesExecuted(getHostCycles() - baseCycles); 648 const uint64_t simCyclesExecuted(hostCyclesExecuted * hostFactor); 649 const uint64_t instsExecuted(hwInstructions.read() - baseInstrs); 650 ticksExecuted = runTimer->ticksFromHostCycles(hostCyclesExecuted); 651 652 if (ticksExecuted < ticks && 653 timerOverflowed && 654 _kvmRun->exit_reason == KVM_EXIT_INTR) { 655 // TODO: We should probably do something clever here... 656 warn("KVM: Early timer event, requested %i ticks but got %i ticks.\n", 657 ticks, ticksExecuted); 658 } 659 660 /* Update statistics */ 661 numCycles += simCyclesExecuted;; 662 numInsts += instsExecuted; 663 ctrInsts += instsExecuted; 664 system->totalNumInsts += instsExecuted; 665 666 DPRINTF(KvmRun, 667 "KVM: Executed %i instructions in %i cycles " 668 "(%i ticks, sim cycles: %i).\n", 669 instsExecuted, hostCyclesExecuted, ticksExecuted, simCyclesExecuted); 670 } 671 672 ++numVMExits; 673 674 return ticksExecuted + flushCoalescedMMIO(); 675} 676 677void 678BaseKvmCPU::kvmNonMaskableInterrupt() 679{ 680 ++numInterrupts; 681 if (ioctl(KVM_NMI) == -1) 682 panic("KVM: Failed to deliver NMI to virtual CPU\n"); 683} 684 685void 686BaseKvmCPU::kvmInterrupt(const struct kvm_interrupt &interrupt) 687{ 688 ++numInterrupts; 689 if (ioctl(KVM_INTERRUPT, (void *)&interrupt) == -1) 690 panic("KVM: Failed to deliver interrupt to virtual CPU\n"); 691} 692 693void 694BaseKvmCPU::getRegisters(struct kvm_regs ®s) const 695{ 696 if (ioctl(KVM_GET_REGS, ®s) == -1) 697 panic("KVM: Failed to get guest registers\n"); 698} 699 700void 701BaseKvmCPU::setRegisters(const struct kvm_regs ®s) 702{ 703 if (ioctl(KVM_SET_REGS, (void *)®s) == -1) 704 panic("KVM: Failed to set guest registers\n"); 705} 706 707void 708BaseKvmCPU::getSpecialRegisters(struct kvm_sregs ®s) const 709{ 710 if (ioctl(KVM_GET_SREGS, ®s) == -1) 711 panic("KVM: Failed to get guest special registers\n"); 712} 713 714void 715BaseKvmCPU::setSpecialRegisters(const struct kvm_sregs ®s) 716{ 717 if (ioctl(KVM_SET_SREGS, (void *)®s) == -1) 718 panic("KVM: Failed to set guest special registers\n"); 719} 720 721void 722BaseKvmCPU::getFPUState(struct kvm_fpu &state) const 723{ 724 if (ioctl(KVM_GET_FPU, &state) == -1) 725 panic("KVM: Failed to get guest FPU state\n"); 726} 727 728void 729BaseKvmCPU::setFPUState(const struct kvm_fpu &state) 730{ 731 if (ioctl(KVM_SET_FPU, (void *)&state) == -1) 732 panic("KVM: Failed to set guest FPU state\n"); 733} 734 735 736void 737BaseKvmCPU::setOneReg(uint64_t id, const void *addr) 738{ 739#ifdef KVM_SET_ONE_REG 740 struct kvm_one_reg reg; 741 reg.id = id; 742 reg.addr = (uint64_t)addr; 743 744 if (ioctl(KVM_SET_ONE_REG, ®) == -1) { 745 panic("KVM: Failed to set register (0x%x) value (errno: %i)\n", 746 id, errno); 747 } 748#else 749 panic("KVM_SET_ONE_REG is unsupported on this platform.\n"); 750#endif 751} 752 753void 754BaseKvmCPU::getOneReg(uint64_t id, void *addr) const 755{ 756#ifdef KVM_GET_ONE_REG 757 struct kvm_one_reg reg; 758 reg.id = id; 759 reg.addr = (uint64_t)addr; 760 761 if (ioctl(KVM_GET_ONE_REG, ®) == -1) { 762 panic("KVM: Failed to get register (0x%x) value (errno: %i)\n", 763 id, errno); 764 } 765#else 766 panic("KVM_GET_ONE_REG is unsupported on this platform.\n"); 767#endif 768} 769 770std::string 771BaseKvmCPU::getAndFormatOneReg(uint64_t id) const 772{ 773#ifdef KVM_GET_ONE_REG 774 std::ostringstream ss; 775 776 ss.setf(std::ios::hex, std::ios::basefield); 777 ss.setf(std::ios::showbase); 778#define HANDLE_INTTYPE(len) \ 779 case KVM_REG_SIZE_U ## len: { \ 780 uint ## len ## _t value; \ 781 getOneReg(id, &value); \ 782 ss << value; \ 783 } break 784 785#define HANDLE_ARRAY(len) \ 786 case KVM_REG_SIZE_U ## len: { \ 787 uint8_t value[len / 8]; \ 788 getOneReg(id, value); \ 789 ss << "[" << value[0]; \ 790 for (int i = 1; i < len / 8; ++i) \ 791 ss << ", " << value[i]; \ 792 ss << "]"; \ 793 } break 794 795 switch (id & KVM_REG_SIZE_MASK) { 796 HANDLE_INTTYPE(8); 797 HANDLE_INTTYPE(16); 798 HANDLE_INTTYPE(32); 799 HANDLE_INTTYPE(64); 800 HANDLE_ARRAY(128); 801 HANDLE_ARRAY(256); 802 HANDLE_ARRAY(512); 803 HANDLE_ARRAY(1024); 804 default: 805 ss << "??"; 806 } 807 808#undef HANDLE_INTTYPE 809#undef HANDLE_ARRAY 810 811 return ss.str(); 812#else 813 panic("KVM_GET_ONE_REG is unsupported on this platform.\n"); 814#endif 815} 816 817void 818BaseKvmCPU::syncThreadContext() 819{ 820 if (!kvmStateDirty) 821 return; 822 823 assert(!threadContextDirty); 824 825 updateThreadContext(); 826 kvmStateDirty = false; 827} 828 829void 830BaseKvmCPU::syncKvmState() 831{ 832 if (!threadContextDirty) 833 return; 834 835 assert(!kvmStateDirty); 836 837 updateKvmState(); 838 threadContextDirty = false; 839} 840 841Tick 842BaseKvmCPU::handleKvmExit() 843{ 844 DPRINTF(KvmRun, "handleKvmExit (exit_reason: %i)\n", _kvmRun->exit_reason); 845 assert(_status == RunningService); 846 847 // Switch into the running state by default. Individual handlers 848 // can override this. 849 _status = Running; 850 switch (_kvmRun->exit_reason) { 851 case KVM_EXIT_UNKNOWN: 852 return handleKvmExitUnknown(); 853 854 case KVM_EXIT_EXCEPTION: 855 return handleKvmExitException(); 856 857 case KVM_EXIT_IO: 858 _status = RunningServiceCompletion; 859 ++numIO; 860 return handleKvmExitIO(); 861 862 case KVM_EXIT_HYPERCALL: 863 ++numHypercalls; 864 return handleKvmExitHypercall(); 865 866 case KVM_EXIT_HLT: 867 /* The guest has halted and is waiting for interrupts */ 868 DPRINTF(Kvm, "handleKvmExitHalt\n"); 869 ++numHalt; 870 871 // Suspend the thread until the next interrupt arrives 872 thread->suspend(); 873 874 // This is actually ignored since the thread is suspended. 875 return 0; 876 877 case KVM_EXIT_MMIO: 878 _status = RunningServiceCompletion; 879 /* Service memory mapped IO requests */ 880 DPRINTF(KvmIO, "KVM: Handling MMIO (w: %u, addr: 0x%x, len: %u)\n", 881 _kvmRun->mmio.is_write, 882 _kvmRun->mmio.phys_addr, _kvmRun->mmio.len); 883 884 ++numMMIO; 885 return doMMIOAccess(_kvmRun->mmio.phys_addr, _kvmRun->mmio.data, 886 _kvmRun->mmio.len, _kvmRun->mmio.is_write); 887 888 case KVM_EXIT_IRQ_WINDOW_OPEN: 889 return handleKvmExitIRQWindowOpen(); 890 891 case KVM_EXIT_FAIL_ENTRY: 892 return handleKvmExitFailEntry(); 893 894 case KVM_EXIT_INTR: 895 /* KVM was interrupted by a signal, restart it in the next 896 * tick. */ 897 return 0; 898 899 case KVM_EXIT_INTERNAL_ERROR: 900 panic("KVM: Internal error (suberror: %u)\n", 901 _kvmRun->internal.suberror); 902 903 default: 904 dump(); 905 panic("KVM: Unexpected exit (exit_reason: %u)\n", _kvmRun->exit_reason); 906 } 907} 908 909Tick 910BaseKvmCPU::handleKvmExitIO() 911{ 912 panic("KVM: Unhandled guest IO (dir: %i, size: %i, port: 0x%x, count: %i)\n", 913 _kvmRun->io.direction, _kvmRun->io.size, 914 _kvmRun->io.port, _kvmRun->io.count); 915} 916 917Tick 918BaseKvmCPU::handleKvmExitHypercall() 919{ 920 panic("KVM: Unhandled hypercall\n"); 921} 922 923Tick 924BaseKvmCPU::handleKvmExitIRQWindowOpen() 925{ 926 warn("KVM: Unhandled IRQ window.\n"); 927 return 0; 928} 929 930 931Tick 932BaseKvmCPU::handleKvmExitUnknown() 933{ 934 dump(); 935 panic("KVM: Unknown error when starting vCPU (hw reason: 0x%llx)\n", 936 _kvmRun->hw.hardware_exit_reason); 937} 938 939Tick 940BaseKvmCPU::handleKvmExitException() 941{ 942 dump(); 943 panic("KVM: Got exception when starting vCPU " 944 "(exception: %u, error_code: %u)\n", 945 _kvmRun->ex.exception, _kvmRun->ex.error_code); 946} 947 948Tick 949BaseKvmCPU::handleKvmExitFailEntry() 950{ 951 dump(); 952 panic("KVM: Failed to enter virtualized mode (hw reason: 0x%llx)\n", 953 _kvmRun->fail_entry.hardware_entry_failure_reason); 954} 955 956Tick 957BaseKvmCPU::doMMIOAccess(Addr paddr, void *data, int size, bool write) 958{ 959 ThreadContext *tc(thread->getTC()); 960 syncThreadContext(); 961 962 mmio_req.setPhys(paddr, size, Request::UNCACHEABLE, dataMasterId()); 963 // Some architectures do need to massage physical addresses a bit 964 // before they are inserted into the memory system. This enables 965 // APIC accesses on x86 and m5ops where supported through a MMIO 966 // interface. 967 BaseTLB::Mode tlb_mode(write ? BaseTLB::Write : BaseTLB::Read); 968 Fault fault(tc->getDTBPtr()->finalizePhysical(&mmio_req, tc, tlb_mode)); 969 if (fault != NoFault) 970 warn("Finalization of MMIO address failed: %s\n", fault->name()); 971 972 973 const MemCmd cmd(write ? MemCmd::WriteReq : MemCmd::ReadReq); 974 Packet pkt(&mmio_req, cmd); 975 pkt.dataStatic(data); 976 977 if (mmio_req.isMmappedIpr()) { 978 const Cycles ipr_delay(write ? 979 TheISA::handleIprWrite(tc, &pkt) : 980 TheISA::handleIprRead(tc, &pkt)); 981 return clockEdge(ipr_delay); 982 } else { 983 return dataPort.sendAtomic(&pkt); 984 } 985} 986 987void 988BaseKvmCPU::setSignalMask(const sigset_t *mask) 989{ 990 std::unique_ptr<struct kvm_signal_mask> kvm_mask; 991 992 if (mask) { 993 kvm_mask.reset((struct kvm_signal_mask *)operator new( 994 sizeof(struct kvm_signal_mask) + sizeof(*mask))); 995 // The kernel and the user-space headers have different ideas 996 // about the size of sigset_t. This seems like a massive hack, 997 // but is actually what qemu does. 998 assert(sizeof(*mask) >= 8); 999 kvm_mask->len = 8; 1000 memcpy(kvm_mask->sigset, mask, kvm_mask->len); 1001 } 1002 1003 if (ioctl(KVM_SET_SIGNAL_MASK, (void *)kvm_mask.get()) == -1) 1004 panic("KVM: Failed to set vCPU signal mask (errno: %i)\n", 1005 errno); 1006} 1007 1008int 1009BaseKvmCPU::ioctl(int request, long p1) const 1010{ 1011 if (vcpuFD == -1) 1012 panic("KVM: CPU ioctl called before initialization\n"); 1013 1014 return ::ioctl(vcpuFD, request, p1); 1015} 1016 1017Tick 1018BaseKvmCPU::flushCoalescedMMIO() 1019{ 1020 if (!mmioRing) 1021 return 0; 1022 1023 DPRINTF(KvmIO, "KVM: Flushing the coalesced MMIO ring buffer\n"); 1024 1025 // TODO: We might need to do synchronization when we start to 1026 // support multiple CPUs 1027 Tick ticks(0); 1028 while (mmioRing->first != mmioRing->last) { 1029 struct kvm_coalesced_mmio &ent( 1030 mmioRing->coalesced_mmio[mmioRing->first]); 1031 1032 DPRINTF(KvmIO, "KVM: Handling coalesced MMIO (addr: 0x%x, len: %u)\n", 1033 ent.phys_addr, ent.len); 1034 1035 ++numCoalescedMMIO; 1036 ticks += doMMIOAccess(ent.phys_addr, ent.data, ent.len, true); 1037 1038 mmioRing->first = (mmioRing->first + 1) % KVM_COALESCED_MMIO_MAX; 1039 } 1040 1041 return ticks; 1042} 1043 1044/** 1045 * Cycle timer overflow when running in KVM. Forces the KVM syscall to 1046 * exit with EINTR and allows us to run the event queue. 1047 */ 1048static void 1049onTimerOverflow(int signo, siginfo_t *si, void *data) 1050{ 1051 timerOverflowed = true; 1052} 1053 1054/** 1055 * Instruction counter overflow when running in KVM. Forces the KVM 1056 * syscall to exit with EINTR and allows us to handle instruction 1057 * count events. 1058 */ 1059static void 1060onInstEvent(int signo, siginfo_t *si, void *data) 1061{ 1062} 1063 1064void 1065BaseKvmCPU::setupSignalHandler() 1066{ 1067 struct sigaction sa; 1068 1069 memset(&sa, 0, sizeof(sa)); 1070 sa.sa_sigaction = onTimerOverflow; 1071 sa.sa_flags = SA_SIGINFO | SA_RESTART; 1072 if (sigaction(KVM_TIMER_SIGNAL, &sa, NULL) == -1) 1073 panic("KVM: Failed to setup vCPU timer signal handler\n"); 1074 1075 memset(&sa, 0, sizeof(sa)); 1076 sa.sa_sigaction = onInstEvent; 1077 sa.sa_flags = SA_SIGINFO | SA_RESTART; 1078 if (sigaction(KVM_INST_SIGNAL, &sa, NULL) == -1) 1079 panic("KVM: Failed to setup vCPU instruction signal handler\n"); 1080 1081 sigset_t sigset; 1082 if (sigprocmask(SIG_BLOCK, NULL, &sigset) == -1) 1083 panic("KVM: Failed get signal mask\n"); 1084 1085 // Request KVM to setup the same signal mask as we're currently 1086 // running with. We'll sometimes need to mask the KVM_TIMER_SIGNAL 1087 // to cause immediate exits from KVM after servicing IO 1088 // requests. See kvmRun(). 1089 setSignalMask(&sigset); 1090 1091 // Mask our control signals so they aren't delivered unless we're 1092 // actually executing inside KVM. 1093 sigaddset(&sigset, KVM_TIMER_SIGNAL); 1094 sigaddset(&sigset, KVM_INST_SIGNAL); 1095 if (sigprocmask(SIG_SETMASK, &sigset, NULL) == -1) 1096 panic("KVM: Failed mask the KVM control signals\n"); 1097} 1098 1099bool 1100BaseKvmCPU::discardPendingSignal(int signum) const 1101{ 1102 int discardedSignal; 1103 1104 // Setting the timeout to zero causes sigtimedwait to return 1105 // immediately. 1106 struct timespec timeout; 1107 timeout.tv_sec = 0; 1108 timeout.tv_nsec = 0; 1109 1110 sigset_t sigset; 1111 sigemptyset(&sigset); 1112 sigaddset(&sigset, signum); 1113 1114 do { 1115 discardedSignal = sigtimedwait(&sigset, NULL, &timeout); 1116 } while (discardedSignal == -1 && errno == EINTR); 1117 1118 if (discardedSignal == signum) 1119 return true; 1120 else if (discardedSignal == -1 && errno == EAGAIN) 1121 return false; 1122 else 1123 panic("Unexpected return value from sigtimedwait: %i (errno: %i)\n", 1124 discardedSignal, errno); 1125} 1126 1127void 1128BaseKvmCPU::setupCounters() 1129{ 1130 DPRINTF(Kvm, "Attaching cycle counter...\n"); 1131 PerfKvmCounterConfig cfgCycles(PERF_TYPE_HARDWARE, 1132 PERF_COUNT_HW_CPU_CYCLES); 1133 cfgCycles.disabled(true) 1134 .pinned(true); 1135 1136 if (perfControlledByTimer) { 1137 // We need to configure the cycles counter to send overflows 1138 // since we are going to use it to trigger timer signals that 1139 // trap back into m5 from KVM. In practice, this means that we 1140 // need to set some non-zero sample period that gets 1141 // overridden when the timer is armed. 1142 cfgCycles.wakeupEvents(1) 1143 .samplePeriod(42); 1144 } 1145 1146 hwCycles.attach(cfgCycles, 1147 0); // TID (0 => currentThread) 1148 1149 setupInstCounter(); 1150} 1151 1152bool 1153BaseKvmCPU::tryDrain() 1154{ 1155 if (!drainManager) 1156 return false; 1157 1158 if (!archIsDrained()) { 1159 DPRINTF(Drain, "tryDrain: Architecture code is not ready.\n"); 1160 return false; 1161 } 1162 1163 if (_status == Idle || _status == Running) { 1164 DPRINTF(Drain, 1165 "tryDrain: CPU transitioned into the Idle state, drain done\n"); 1166 drainManager->signalDrainDone(); 1167 drainManager = NULL; 1168 return true; 1169 } else { 1170 DPRINTF(Drain, "tryDrain: CPU not ready.\n"); 1171 return false; 1172 } 1173} 1174 1175void 1176BaseKvmCPU::ioctlRun() 1177{ 1178 if (ioctl(KVM_RUN) == -1) { 1179 if (errno != EINTR) 1180 panic("KVM: Failed to start virtual CPU (errno: %i)\n", 1181 errno); 1182 } 1183} 1184 1185void 1186BaseKvmCPU::setupInstStop() 1187{ 1188 if (comInstEventQueue[0]->empty()) { 1189 setupInstCounter(0); 1190 } else { 1191 const uint64_t next(comInstEventQueue[0]->nextTick()); 1192 1193 assert(next > ctrInsts); 1194 setupInstCounter(next - ctrInsts); 1195 } 1196} 1197 1198void 1199BaseKvmCPU::setupInstCounter(uint64_t period) 1200{ 1201 // No need to do anything if we aren't attaching for the first 1202 // time or the period isn't changing. 1203 if (period == activeInstPeriod && hwInstructions.attached()) 1204 return; 1205 1206 PerfKvmCounterConfig cfgInstructions(PERF_TYPE_HARDWARE, 1207 PERF_COUNT_HW_INSTRUCTIONS); 1208 1209 if (period) { 1210 // Setup a sampling counter if that has been requested. 1211 cfgInstructions.wakeupEvents(1) 1212 .samplePeriod(period); 1213 } 1214 1215 // We need to detach and re-attach the counter to reliably change 1216 // sampling settings. See PerfKvmCounter::period() for details. 1217 if (hwInstructions.attached()) 1218 hwInstructions.detach(); 1219 assert(hwCycles.attached()); 1220 hwInstructions.attach(cfgInstructions, 1221 0, // TID (0 => currentThread) 1222 hwCycles); 1223 1224 if (period) 1225 hwInstructions.enableSignals(KVM_INST_SIGNAL); 1226 1227 activeInstPeriod = period; 1228} 1229