gem5 v23.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
base.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012, 2015, 2017, 2021 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
38#include "cpu/kvm/base.hh"
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 "base/compiler.hh"
50#include "debug/Checkpoint.hh"
51#include "debug/Drain.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
62namespace gem5
63{
64
65BaseKvmCPU::BaseKvmCPU(const BaseKvmCPUParams &params)
66 : BaseCPU(params),
67 vm(nullptr),
68 _status(Idle),
69 dataPort(name() + ".dcache_port", this),
70 instPort(name() + ".icache_port", this),
71 alwaysSyncTC(params.alwaysSyncTC),
72 threadContextDirty(true),
73 kvmStateDirty(false),
74 vcpuID(-1), vcpuFD(-1), vcpuMMapSize(0),
75 _kvmRun(NULL), mmioRing(NULL),
76 pageSize(sysconf(_SC_PAGE_SIZE)),
77 tickEvent([this]{ tick(); }, "BaseKvmCPU tick",
78 false, Event::CPU_Tick_Pri),
79 activeInstPeriod(0),
80 perfControlledByTimer(params.usePerfOverflow),
81 hostFactor(params.hostFactor), stats(this),
82 ctrInsts(0)
83{
84 if (pageSize == -1)
85 panic("KVM: Failed to determine host page size (%i)\n",
86 errno);
87
88 if (FullSystem)
89 thread = new SimpleThread(this, 0, params.system, params.mmu,
90 params.isa[0], params.decoder[0]);
91 else
92 thread = new SimpleThread(this, /* thread_num */ 0, params.system,
93 params.workload[0], params.mmu,
94 params.isa[0], params.decoder[0]);
95
96 thread->setStatus(ThreadContext::Halted);
97 tc = thread->getTC();
98 threadContexts.push_back(tc);
99}
100
102{
103 if (_kvmRun)
104 munmap(_kvmRun, vcpuMMapSize);
105 close(vcpuFD);
106}
107
108void
110{
111 vm = system->getKvmVM();
112 vcpuID = vm->allocVCPUID();
114 fatal_if(numThreads != 1, "KVM: Multithreading not supported");
115}
116
117void
119{
120 const BaseKvmCPUParams &p =
121 dynamic_cast<const BaseKvmCPUParams &>(params());
122
123 Kvm &kvm = *vm->kvm;
124
126
127 assert(vcpuFD == -1);
128
129 // Tell the VM that a CPU is about to start.
130 vm->cpuStartup();
131
132 // We can't initialize KVM CPUs in BaseKvmCPU::init() since we are
133 // not guaranteed that the parent KVM VM has initialized at that
134 // point. Initialize virtual CPUs here instead.
136
137 // Map the KVM run structure
139 _kvmRun = (struct kvm_run *)mmap(0, vcpuMMapSize,
140 PROT_READ | PROT_WRITE, MAP_SHARED,
141 vcpuFD, 0);
142 if (_kvmRun == MAP_FAILED)
143 panic("KVM: Failed to map run data structure\n");
144
145 // Setup a pointer to the MMIO ring buffer if coalesced MMIO is
146 // available. The offset into the KVM's communication page is
147 // provided by the coalesced MMIO capability.
148 int mmioOffset(kvm.capCoalescedMMIO());
149 if (!p.useCoalescedMMIO) {
150 inform("KVM: Coalesced MMIO disabled by config.\n");
151 } else if (mmioOffset) {
152 inform("KVM: Coalesced IO available\n");
153 mmioRing = (struct kvm_coalesced_mmio_ring *)(
154 (char *)_kvmRun + (mmioOffset * pageSize));
155 } else {
156 inform("KVM: Coalesced not supported by host OS\n");
157 }
158
161 }, name(), true), curTick());
162}
163
166{
167 return (activeMMIOReqs || pendingMMIOPkts.size())
169}
170
171Tick
173{
174 if (cpu->system->isAtomicMode()) {
175 Tick delay = sendAtomic(pkt);
176 delete pkt;
177 return delay;
178 } else {
179 if (pendingMMIOPkts.empty() && sendTimingReq(pkt)) {
180 activeMMIOReqs++;
181 } else {
182 pendingMMIOPkts.push(pkt);
183 }
184 // Return value is irrelevant for timing-mode accesses.
185 return 0;
186 }
187}
188
189bool
191{
192 DPRINTF(KvmIO, "KVM: Finished timing request\n");
193
194 delete pkt;
195 activeMMIOReqs--;
196
197 // We can switch back into KVM when all pending and in-flight MMIO
198 // operations have completed.
199 if (!(activeMMIOReqs || pendingMMIOPkts.size())) {
200 DPRINTF(KvmIO, "KVM: Finished all outstanding timing requests\n");
201 cpu->finishMMIOPending();
202 }
203 return true;
204}
205
206void
208{
209 DPRINTF(KvmIO, "KVM: Retry for timing request\n");
210
211 assert(pendingMMIOPkts.size());
212
213 // Assuming that we can issue infinite requests this cycle is a bit
214 // unrealistic, but it's not worth modeling something more complex in
215 // KVM.
216 while (pendingMMIOPkts.size() && sendTimingReq(pendingMMIOPkts.front())) {
217 pendingMMIOPkts.pop();
218 activeMMIOReqs++;
219 }
220}
221
222void
224{
225 assert(_status == RunningMMIOPending);
226 assert(!tickEvent.scheduled());
227
230}
231
232void
234{
235 // Do thread-specific initialization. We need to setup signal
236 // delivery for counters and timers from within the thread that
237 // will execute the event queue to ensure that signals are
238 // delivered to the right threads.
239 const BaseKvmCPUParams &p =
240 dynamic_cast<const BaseKvmCPUParams &>(params());
241
242 vcpuThread = pthread_self();
243
244 // Setup signal handlers. This has to be done after the vCPU is
245 // created since it manipulates the vCPU signal mask.
247
249
250 if (p.usePerfOverflow) {
253 p.hostFactor,
254 p.hostFreq));
255 } else {
256 runTimer.reset(new PosixKvmTimer(KVM_KICK_SIGNAL, CLOCK_MONOTONIC,
257 p.hostFactor,
258 p.hostFreq));
259 }
260}
261
263 : statistics::Group(parent),
264 ADD_STAT(numVMExits, statistics::units::Count::get(),
265 "total number of KVM exits"),
266 ADD_STAT(numVMHalfEntries, statistics::units::Count::get(),
267 "number of KVM entries to finalize pending operations"),
268 ADD_STAT(numExitSignal, statistics::units::Count::get(),
269 "exits due to signal delivery"),
270 ADD_STAT(numMMIO, statistics::units::Count::get(),
271 "number of VM exits due to memory mapped IO"),
272 ADD_STAT(numCoalescedMMIO, statistics::units::Count::get(),
273 "number of coalesced memory mapped IO requests"),
274 ADD_STAT(numIO, statistics::units::Count::get(),
275 "number of VM exits due to legacy IO"),
276 ADD_STAT(numHalt, statistics::units::Count::get(),
277 "number of VM exits due to wait for interrupt instructions"),
278 ADD_STAT(numInterrupts, statistics::units::Count::get(),
279 "number of interrupts delivered"),
280 ADD_STAT(numHypercalls, statistics::units::Count::get(), "number of hypercalls")
281{
282}
283
284void
286{
287 if (debug::Checkpoint) {
288 DPRINTF(Checkpoint, "KVM: Serializing thread %i:\n", tid);
289 dump();
290 }
291
292 assert(tid == 0);
293 assert(_status == Idle);
294 thread->serialize(cp);
295}
296
297void
299{
300 DPRINTF(Checkpoint, "KVM: Unserialize thread %i:\n", tid);
301
302 assert(tid == 0);
303 assert(_status == Idle);
304 thread->unserialize(cp);
305 threadContextDirty = true;
306}
307
310{
311 if (switchedOut())
312 return DrainState::Drained;
313
314 DPRINTF(Drain, "BaseKvmCPU::drain\n");
315
316 // The event queue won't be locked when calling drain since that's
317 // not done from an event. Lock the event queue here to make sure
318 // that scoped migrations continue to work if we need to
319 // synchronize the thread context.
320 std::lock_guard<EventQueue> lock(*this->eventQueue());
321
322 switch (_status) {
323 case Running:
324 // The base KVM code is normally ready when it is in the
325 // Running state, but the architecture specific code might be
326 // of a different opinion. This may happen when the CPU been
327 // notified of an event that hasn't been accepted by the vCPU
328 // yet.
329 if (!archIsDrained())
331
332 // The state of the CPU is consistent, so we don't need to do
333 // anything special to drain it. We simply de-schedule the
334 // tick event and enter the Idle state to prevent nasty things
335 // like MMIOs from happening.
336 if (tickEvent.scheduled())
338 _status = Idle;
339
340 [[fallthrough]];
341 case Idle:
342 // Idle, no need to drain
343 assert(!tickEvent.scheduled());
344
345 // Sync the thread context here since we'll need it when we
346 // switch CPUs or checkpoint the CPU.
348
349 return DrainState::Drained;
350
352 // The CPU has just requested a service that was handled in
353 // the RunningService state, but the results have still not
354 // been reported to the CPU. Now, we /could/ probably just
355 // update the register state ourselves instead of letting KVM
356 // handle it, but that would be tricky. Instead, we enter KVM
357 // and let it do its stuff.
358 DPRINTF(Drain, "KVM CPU is waiting for service completion, "
359 "requesting drain.\n");
361
363 // We need to drain since there are in-flight timing accesses
364 DPRINTF(Drain, "KVM CPU is waiting for timing accesses to complete, "
365 "requesting drain.\n");
367
368 case RunningService:
369 // We need to drain since the CPU is waiting for service (e.g., MMIOs)
370 DPRINTF(Drain, "KVM CPU is waiting for service, requesting drain.\n");
372
373 default:
374 panic("KVM: Unhandled CPU state in drain()\n");
375 return DrainState::Drained;
376 }
377}
378
379void
381{
382 assert(!tickEvent.scheduled());
383
384 // We might have been switched out. In that case, we don't need to
385 // do anything.
386 if (switchedOut())
387 return;
388
389 DPRINTF(Kvm, "drainResume\n");
391
392 /* The simulator may have terminated the threads servicing event
393 * queues. In that case, we need to re-initialize the new
394 * threads. */
397 }, name(), true), curTick());
398
399 // The tick event is de-scheduled as a part of the draining
400 // process. Re-schedule it if the thread context is active.
401 if (tc->status() == ThreadContext::Active) {
404 } else {
405 _status = Idle;
406 }
407}
408
409void
411{
412 // We should have drained prior to forking, which means that the
413 // tick event shouldn't be scheduled and the CPU is idle.
414 assert(!tickEvent.scheduled());
415 assert(_status == Idle);
416
417 if (vcpuFD != -1) {
418 if (close(vcpuFD) == -1)
419 warn("kvm CPU: notifyFork failed to close vcpuFD\n");
420
421 if (_kvmRun)
422 munmap(_kvmRun, vcpuMMapSize);
423
424 vcpuFD = -1;
425 _kvmRun = NULL;
426
429 }
430}
431
432void
434{
435 DPRINTF(Kvm, "switchOut\n");
436
438
439 // We should have drained prior to executing a switchOut, which
440 // means that the tick event shouldn't be scheduled and the CPU is
441 // idle.
442 assert(!tickEvent.scheduled());
443 assert(_status == Idle);
444}
445
446void
448{
449 DPRINTF(Kvm, "takeOverFrom\n");
450
452
453 // We should have drained prior to executing a switchOut, which
454 // means that the tick event shouldn't be scheduled and the CPU is
455 // idle.
456 assert(!tickEvent.scheduled());
457 assert(_status == Idle);
458 assert(threadContexts.size() == 1);
459
460 // Force an update of the KVM state here instead of flagging the
461 // TC as dirty. This is not ideal from a performance point of
462 // view, but it makes debugging easier as it allows meaningful KVM
463 // state to be dumped before and after a takeover.
465 threadContextDirty = false;
466}
467
468void
470{
471 if (!(system->bypassCaches())) {
472 fatal("The KVM-based CPUs requires the memory system to be in the "
473 "'noncaching' mode.\n");
474 }
475}
476
477void
479{
480 DPRINTF(Kvm, "wakeup()\n");
481 // This method might have been called from another
482 // context. Migrate to this SimObject's event queue when
483 // delivering the wakeup signal.
485
486 // Kick the vCPU to get it to come out of KVM.
487 kick();
488
490 return;
491
492 thread->activate();
493}
494
495void
497{
498 DPRINTF(Kvm, "ActivateContext %d\n", thread_num);
499
500 assert(thread_num == 0);
501 assert(thread);
502
503 assert(_status == Idle);
504 assert(!tickEvent.scheduled());
505
508
511}
512
513
514void
516{
517 DPRINTF(Kvm, "SuspendContext %d\n", thread_num);
518
519 assert(thread_num == 0);
520 assert(thread);
521
522 if (_status == Idle)
523 return;
524
526
527 // The tick event may no be scheduled if the quest has requested
528 // the monitor to wait for interrupts. The normal CPU models can
529 // get their tick events descheduled by quiesce instructions, but
530 // that can't happen here.
531 if (tickEvent.scheduled())
533
534 _status = Idle;
535}
536
537void
539{
540 // for now, these are equivalent
541 suspendContext(thread_num);
542}
543
544void
546{
547 // for now, these are equivalent
548 suspendContext(thread_num);
550}
551
554{
555 assert(tn == 0);
557 return tc;
558}
559
560
563{
564 return ctrInsts;
565}
566
569{
570 hack_once("Pretending totalOps is equivalent to totalInsts()\n");
571 return ctrInsts;
572}
573
574void
576{
577 inform("State dumping not implemented.");
578}
579
580void
582{
583 Tick delay(0);
584 assert(_status != Idle && _status != RunningMMIOPending);
585
586 switch (_status) {
587 case RunningService:
588 // handleKvmExit() will determine the next state of the CPU
589 delay = handleKvmExit();
590
591 if (tryDrain())
592 _status = Idle;
593 break;
594
596 case Running: {
597 auto &queue = thread->comInstEventQueue;
598 const uint64_t nextInstEvent(
599 queue.empty() ? MaxTick : queue.nextTick());
600 // Enter into KVM and complete pending IO instructions if we
601 // have an instruction event pending.
602 const Tick ticksToExecute(
603 nextInstEvent > ctrInsts ?
604 curEventQueue()->nextTick() - curTick() : 0);
605
606 if (alwaysSyncTC)
607 threadContextDirty = true;
608
609 // We might need to update the KVM state.
610 syncKvmState();
611
612 // Setup any pending instruction count breakpoints using
613 // PerfEvent if we are going to execute more than just an IO
614 // completion.
615 if (ticksToExecute > 0)
617
618 DPRINTF(KvmRun, "Entering KVM...\n");
620 // Force an immediate exit from KVM after completing
621 // pending operations. The architecture-specific code
622 // takes care to run until it is in a state where it can
623 // safely be drained.
624 delay = kvmRunDrain();
625 } else {
626 delay = kvmRun(ticksToExecute);
627 }
628
629 // The CPU might have been suspended before entering into
630 // KVM. Assume that the CPU was suspended /before/ entering
631 // into KVM and skip the exit handling.
632 if (_status == Idle)
633 break;
634
635 // Entering into KVM implies that we'll have to reload the thread
636 // context from KVM if we want to access it. Flag the KVM state as
637 // dirty with respect to the cached thread context.
638 kvmStateDirty = true;
639
640 if (alwaysSyncTC)
642
643 // Enter into the RunningService state unless the
644 // simulation was stopped by a timer.
645 if (_kvmRun->exit_reason != KVM_EXIT_INTR) {
647 } else {
650 }
651
652 // Service any pending instruction events. The vCPU should
653 // have exited in time for the event using the instruction
654 // counter configured by setupInstStop().
655 queue.serviceEvents(ctrInsts);
656
657 if (tryDrain())
658 _status = Idle;
659 } break;
660
661 default:
662 panic("BaseKvmCPU entered tick() in an illegal state (%i)\n",
663 _status);
664 }
665
666 // Schedule a new tick if we are still running
667 if (_status != Idle && _status != RunningMMIOPending) {
668 if (_kvmRun->exit_reason == KVM_EXIT_INTR && runTimer->expired())
670 curEventQueue()->nextTick() - curTick() + 1)));
671 else
673 }
674}
675
676Tick
678{
679 // By default, the only thing we need to drain is a pending IO
680 // operation which assumes that we are in the
681 // RunningServiceCompletion or RunningMMIOPending state.
684
685 // Deliver the data from the pending IO operation and immediately
686 // exit.
687 return kvmRun(0);
688}
689
690uint64_t
692{
693 return hwCycles.read();
694}
695
696Tick
698{
699 Tick ticksExecuted;
700 fatal_if(vcpuFD == -1,
701 "Trying to run a KVM CPU in a forked child process. "
702 "This is not supported.\n");
703 DPRINTF(KvmRun, "KVM: Executing for %i ticks\n", ticks);
704
705 if (ticks == 0) {
706 // Settings ticks == 0 is a special case which causes an entry
707 // into KVM that finishes pending operations (e.g., IO) and
708 // then immediately exits.
709 DPRINTF(KvmRun, "KVM: Delivering IO without full guest entry\n");
710
712
713 // Send a KVM_KICK_SIGNAL to the vCPU thread (i.e., this
714 // thread). The KVM control signal is masked while executing
715 // in gem5 and gets unmasked temporarily as when entering
716 // KVM. See setSignalMask() and setupSignalHandler().
717 kick();
718
719 // Start the vCPU. KVM will check for signals after completing
720 // pending operations (IO). Since the KVM_KICK_SIGNAL is
721 // pending, this forces an immediate exit to gem5 again. We
722 // don't bother to setup timers since this shouldn't actually
723 // execute any code (other than completing half-executed IO
724 // instructions) in the guest.
725 ioctlRun();
726
727 // We always execute at least one cycle to prevent the
728 // BaseKvmCPU::tick() to be rescheduled on the same tick
729 // twice.
730 ticksExecuted = clockPeriod();
731 } else {
732 // This method is executed as a result of a tick event. That
733 // means that the event queue will be locked when entering the
734 // method. We temporarily unlock the event queue to allow
735 // other threads to steal control of this thread to inject
736 // interrupts. They will typically lock the queue and then
737 // force an exit from KVM by kicking the vCPU.
739
740 if (ticks < runTimer->resolution()) {
741 DPRINTF(KvmRun, "KVM: Adjusting tick count (%i -> %i)\n",
742 ticks, runTimer->resolution());
743 ticks = runTimer->resolution();
744 }
745
746 // Get hardware statistics after synchronizing contexts. The KVM
747 // state update might affect guest cycle counters.
748 uint64_t baseCycles(getHostCycles());
749 uint64_t baseInstrs(hwInstructions.read());
750
751 // Arm the run timer and start the cycle timer if it isn't
752 // controlled by the overflow timer. Starting/stopping the cycle
753 // timer automatically starts the other perf timers as they are in
754 // the same counter group.
755 runTimer->arm(ticks);
757 hwCycles.start();
758
759 ioctlRun();
760
761 runTimer->disarm();
763 hwCycles.stop();
764
765 // The control signal may have been delivered after we exited
766 // from KVM. It will be pending in that case since it is
767 // masked when we aren't executing in KVM. Discard it to make
768 // sure we don't deliver it immediately next time we try to
769 // enter into KVM.
771
772 const uint64_t hostCyclesExecuted(getHostCycles() - baseCycles);
773 const uint64_t simCyclesExecuted(hostCyclesExecuted * hostFactor);
774 const uint64_t instsExecuted(hwInstructions.read() - baseInstrs);
775 ticksExecuted = runTimer->ticksFromHostCycles(hostCyclesExecuted);
776
777 /* Update statistics */
778 baseStats.numCycles += simCyclesExecuted;;
779 commitStats[thread->threadId()]->numInsts += instsExecuted;
780 baseStats.numInsts += instsExecuted;
781 ctrInsts += instsExecuted;
782
783 DPRINTF(KvmRun,
784 "KVM: Executed %i instructions in %i cycles "
785 "(%i ticks, sim cycles: %i).\n",
786 instsExecuted, hostCyclesExecuted, ticksExecuted, simCyclesExecuted);
787 }
788
790
791 return ticksExecuted + flushCoalescedMMIO();
792}
793
794void
796{
798 if (ioctl(KVM_NMI) == -1)
799 panic("KVM: Failed to deliver NMI to virtual CPU\n");
800}
801
802void
803BaseKvmCPU::kvmInterrupt(const struct kvm_interrupt &interrupt)
804{
806 if (ioctl(KVM_INTERRUPT, (void *)&interrupt) == -1)
807 panic("KVM: Failed to deliver interrupt to virtual CPU\n");
808}
809
810void
811BaseKvmCPU::getRegisters(struct kvm_regs &regs) const
812{
813 if (ioctl(KVM_GET_REGS, &regs) == -1)
814 panic("KVM: Failed to get guest registers\n");
815}
816
817void
818BaseKvmCPU::setRegisters(const struct kvm_regs &regs)
819{
820 if (ioctl(KVM_SET_REGS, (void *)&regs) == -1)
821 panic("KVM: Failed to set guest registers\n");
822}
823
824void
825BaseKvmCPU::getSpecialRegisters(struct kvm_sregs &regs) const
826{
827 if (ioctl(KVM_GET_SREGS, &regs) == -1)
828 panic("KVM: Failed to get guest special registers\n");
829}
830
831void
832BaseKvmCPU::setSpecialRegisters(const struct kvm_sregs &regs)
833{
834 if (ioctl(KVM_SET_SREGS, (void *)&regs) == -1)
835 panic("KVM: Failed to set guest special registers\n");
836}
837
838void
839BaseKvmCPU::getFPUState(struct kvm_fpu &state) const
840{
841 if (ioctl(KVM_GET_FPU, &state) == -1)
842 panic("KVM: Failed to get guest FPU state\n");
843}
844
845void
846BaseKvmCPU::setFPUState(const struct kvm_fpu &state)
847{
848 if (ioctl(KVM_SET_FPU, (void *)&state) == -1)
849 panic("KVM: Failed to set guest FPU state\n");
850}
851
852
853void
854BaseKvmCPU::setOneReg(uint64_t id, const void *addr)
855{
856#ifdef KVM_SET_ONE_REG
857 struct kvm_one_reg reg;
858 reg.id = id;
859 reg.addr = (uint64_t)addr;
860
861 if (ioctl(KVM_SET_ONE_REG, &reg) == -1) {
862 panic("KVM: Failed to set register (0x%x) value (errno: %i)\n",
863 id, errno);
864 }
865#else
866 panic("KVM_SET_ONE_REG is unsupported on this platform.\n");
867#endif
868}
869
870void
871BaseKvmCPU::getOneReg(uint64_t id, void *addr) const
872{
873#ifdef KVM_GET_ONE_REG
874 struct kvm_one_reg reg;
875 reg.id = id;
876 reg.addr = (uint64_t)addr;
877
878 if (ioctl(KVM_GET_ONE_REG, &reg) == -1) {
879 panic("KVM: Failed to get register (0x%x) value (errno: %i)\n",
880 id, errno);
881 }
882#else
883 panic("KVM_GET_ONE_REG is unsupported on this platform.\n");
884#endif
885}
886
887std::string
889{
890#ifdef KVM_GET_ONE_REG
891 std::ostringstream ss;
892
893 ss.setf(std::ios::hex, std::ios::basefield);
894 ss.setf(std::ios::showbase);
895#define HANDLE_INTTYPE(len) \
896 case KVM_REG_SIZE_U ## len: { \
897 uint ## len ## _t value; \
898 getOneReg(id, &value); \
899 ss << value; \
900 } break
901
902#define HANDLE_ARRAY(len) \
903 case KVM_REG_SIZE_U ## len: { \
904 uint8_t value[len / 8]; \
905 getOneReg(id, value); \
906 ccprintf(ss, "[0x%x", value[0]); \
907 for (int i = 1; i < len / 8; ++i) \
908 ccprintf(ss, ", 0x%x", value[i]); \
909 ccprintf(ss, "]"); \
910 } break
911
912 switch (id & KVM_REG_SIZE_MASK) {
913 HANDLE_INTTYPE(8);
914 HANDLE_INTTYPE(16);
915 HANDLE_INTTYPE(32);
916 HANDLE_INTTYPE(64);
917 HANDLE_ARRAY(128);
918 HANDLE_ARRAY(256);
919 HANDLE_ARRAY(512);
920 HANDLE_ARRAY(1024);
921 default:
922 ss << "??";
923 }
924
925#undef HANDLE_INTTYPE
926#undef HANDLE_ARRAY
927
928 return ss.str();
929#else
930 panic("KVM_GET_ONE_REG is unsupported on this platform.\n");
931#endif
932}
933
934void
936{
937 if (!kvmStateDirty)
938 return;
939
940 assert(!threadContextDirty);
941
943 kvmStateDirty = false;
944}
945
946void
948{
950 return;
951
952 assert(!kvmStateDirty);
953
955 threadContextDirty = false;
956}
957
958Tick
960{
961 DPRINTF(KvmRun, "handleKvmExit (exit_reason: %i)\n", _kvmRun->exit_reason);
962 assert(_status == RunningService);
963
964 // Switch into the running state by default. Individual handlers
965 // can override this.
967 switch (_kvmRun->exit_reason) {
968 case KVM_EXIT_UNKNOWN:
969 return handleKvmExitUnknown();
970
971 case KVM_EXIT_EXCEPTION:
972 return handleKvmExitException();
973
974 case KVM_EXIT_IO:
975 {
976 ++stats.numIO;
977 Tick ticks = handleKvmExitIO();
979 return ticks;
980 }
981
982 case KVM_EXIT_HYPERCALL:
984 return handleKvmExitHypercall();
985
986 case KVM_EXIT_HLT:
987 /* The guest has halted and is waiting for interrupts */
988 DPRINTF(Kvm, "handleKvmExitHalt\n");
989 ++stats.numHalt;
990
991 // Suspend the thread until the next interrupt arrives
992 thread->suspend();
993
994 // This is actually ignored since the thread is suspended.
995 return 0;
996
997 case KVM_EXIT_MMIO:
998 {
999 /* Service memory mapped IO requests */
1000 DPRINTF(KvmIO, "KVM: Handling MMIO (w: %u, addr: 0x%x, len: %u)\n",
1001 _kvmRun->mmio.is_write,
1002 _kvmRun->mmio.phys_addr, _kvmRun->mmio.len);
1003
1004 ++stats.numMMIO;
1005 Tick ticks = doMMIOAccess(_kvmRun->mmio.phys_addr, _kvmRun->mmio.data,
1006 _kvmRun->mmio.len, _kvmRun->mmio.is_write);
1007 // doMMIOAccess could have triggered a suspend, in which case we don't
1008 // want to overwrite the _status.
1009 if (_status != Idle)
1011 return ticks;
1012 }
1013
1014 case KVM_EXIT_IRQ_WINDOW_OPEN:
1016
1017 case KVM_EXIT_FAIL_ENTRY:
1018 return handleKvmExitFailEntry();
1019
1020 case KVM_EXIT_INTR:
1021 /* KVM was interrupted by a signal, restart it in the next
1022 * tick. */
1023 return 0;
1024
1025 case KVM_EXIT_INTERNAL_ERROR:
1026 panic("KVM: Internal error (suberror: %u)\n",
1027 _kvmRun->internal.suberror);
1028
1029 default:
1030 dump();
1031 panic("KVM: Unexpected exit (exit_reason: %u)\n", _kvmRun->exit_reason);
1032 }
1033}
1034
1035Tick
1037{
1038 panic("KVM: Unhandled guest IO (dir: %i, size: %i, port: 0x%x, count: %i)\n",
1039 _kvmRun->io.direction, _kvmRun->io.size,
1040 _kvmRun->io.port, _kvmRun->io.count);
1041}
1042
1043Tick
1045{
1046 panic("KVM: Unhandled hypercall\n");
1047}
1048
1049Tick
1051{
1052 warn("KVM: Unhandled IRQ window.\n");
1053 return 0;
1054}
1055
1056
1057Tick
1059{
1060 dump();
1061 panic("KVM: Unknown error when starting vCPU (hw reason: 0x%llx)\n",
1062 _kvmRun->hw.hardware_exit_reason);
1063}
1064
1065Tick
1067{
1068 dump();
1069 panic("KVM: Got exception when starting vCPU "
1070 "(exception: %u, error_code: %u)\n",
1071 _kvmRun->ex.exception, _kvmRun->ex.error_code);
1072}
1073
1074Tick
1076{
1077 dump();
1078 panic("KVM: Failed to enter virtualized mode (hw reason: 0x%llx)\n",
1079 _kvmRun->fail_entry.hardware_entry_failure_reason);
1080}
1081
1082Tick
1083BaseKvmCPU::doMMIOAccess(Addr paddr, void *data, int size, bool write)
1084{
1087
1088 RequestPtr mmio_req = std::make_shared<Request>(
1089 paddr, size, Request::UNCACHEABLE, dataRequestorId());
1090
1091 mmio_req->setContext(tc->contextId());
1092 // Some architectures do need to massage physical addresses a bit
1093 // before they are inserted into the memory system. This enables
1094 // APIC accesses on x86 and m5ops where supported through a MMIO
1095 // interface.
1096 BaseMMU::Mode access_type(write ? BaseMMU::Write : BaseMMU::Read);
1097 Fault fault(tc->getMMUPtr()->finalizePhysical(mmio_req, tc, access_type));
1098 if (fault != NoFault)
1099 warn("Finalization of MMIO address failed: %s\n", fault->name());
1100
1101
1102 const MemCmd cmd(write ? MemCmd::WriteReq : MemCmd::ReadReq);
1103 PacketPtr pkt = new Packet(mmio_req, cmd);
1104 pkt->dataStatic(data);
1105
1106 if (mmio_req->isLocalAccess()) {
1107 // Since the PC has already been advanced by KVM, set the next
1108 // PC to the current PC. KVM doesn't use that value, and that
1109 // way any gem5 op or syscall which needs to know what the next
1110 // PC is will be able to get a reasonable value.
1111 //
1112 // We won't be able to rewind the current PC to the "correct"
1113 // value without figuring out how big the current instruction
1114 // is, and that's probably not worth the effort
1115 std::unique_ptr<PCStateBase> pc(tc->pcState().clone());
1116 stutterPC(*pc);
1117 tc->pcState(*pc);
1118 // We currently assume that there is no need to migrate to a
1119 // different event queue when doing local accesses. Currently, they
1120 // are only used for m5ops, so it should be a valid assumption.
1121 const Cycles ipr_delay = mmio_req->localAccessor(tc, pkt);
1122 threadContextDirty = true;
1123 delete pkt;
1124 return clockPeriod() * ipr_delay;
1125 } else {
1126 // Temporarily lock and migrate to the device event queue to
1127 // prevent races in multi-core mode.
1129
1130 return dataPort.submitIO(pkt);
1131 }
1132}
1133
1134void
1136{
1137 std::unique_ptr<struct kvm_signal_mask, void(*)(void *p)>
1138 kvm_mask(nullptr, [](void *p) { operator delete(p); });
1139
1140 if (mask) {
1141 kvm_mask.reset((struct kvm_signal_mask *)operator new(
1142 sizeof(struct kvm_signal_mask) + sizeof(*mask)));
1143 // The kernel and the user-space headers have different ideas
1144 // about the size of sigset_t. This seems like a massive hack,
1145 // but is actually what qemu does.
1146 assert(sizeof(*mask) >= 8);
1147 kvm_mask->len = 8;
1148 memcpy(kvm_mask->sigset, mask, kvm_mask->len);
1149 }
1150
1151 if (ioctl(KVM_SET_SIGNAL_MASK, (void *)kvm_mask.get()) == -1)
1152 panic("KVM: Failed to set vCPU signal mask (errno: %i)\n",
1153 errno);
1154}
1155
1156int
1157BaseKvmCPU::ioctl(int request, long p1) const
1158{
1159 if (vcpuFD == -1)
1160 panic("KVM: CPU ioctl called before initialization\n");
1161
1162 return ::ioctl(vcpuFD, request, p1);
1163}
1164
1165Tick
1167{
1168 if (!mmioRing)
1169 return 0;
1170
1171 DPRINTF(KvmIO, "KVM: Flushing the coalesced MMIO ring buffer\n");
1172
1173 // TODO: We might need to do synchronization when we start to
1174 // support multiple CPUs
1175 Tick ticks(0);
1176 while (mmioRing->first != mmioRing->last) {
1177 struct kvm_coalesced_mmio &ent(
1178 mmioRing->coalesced_mmio[mmioRing->first]);
1179
1180 DPRINTF(KvmIO, "KVM: Handling coalesced MMIO (addr: 0x%x, len: %u)\n",
1181 ent.phys_addr, ent.len);
1182
1184 ticks += doMMIOAccess(ent.phys_addr, ent.data, ent.len, true);
1185
1186 mmioRing->first = (mmioRing->first + 1) % KVM_COALESCED_MMIO_MAX;
1187 }
1188
1189 return ticks;
1190}
1191
1202static void
1203onKickSignal(int signo, siginfo_t *si, void *data)
1204{
1205}
1206
1207void
1209{
1210 struct sigaction sa;
1211
1212 memset(&sa, 0, sizeof(sa));
1213 sa.sa_sigaction = onKickSignal;
1214 sa.sa_flags = SA_SIGINFO | SA_RESTART;
1215 if (sigaction(KVM_KICK_SIGNAL, &sa, NULL) == -1)
1216 panic("KVM: Failed to setup vCPU timer signal handler\n");
1217
1218 sigset_t sigset;
1219 if (pthread_sigmask(SIG_BLOCK, NULL, &sigset) == -1)
1220 panic("KVM: Failed get signal mask\n");
1221
1222 // Request KVM to setup the same signal mask as we're currently
1223 // running with except for the KVM control signal. We'll sometimes
1224 // need to raise the KVM_KICK_SIGNAL to cause immediate exits from
1225 // KVM after servicing IO requests. See kvmRun().
1226 sigdelset(&sigset, KVM_KICK_SIGNAL);
1227 setSignalMask(&sigset);
1228
1229 // Mask our control signals so they aren't delivered unless we're
1230 // actually executing inside KVM.
1231 sigaddset(&sigset, KVM_KICK_SIGNAL);
1232 if (pthread_sigmask(SIG_SETMASK, &sigset, NULL) == -1)
1233 panic("KVM: Failed mask the KVM control signals\n");
1234}
1235
1236bool
1238{
1239 int discardedSignal;
1240
1241 // Setting the timeout to zero causes sigtimedwait to return
1242 // immediately.
1243 struct timespec timeout;
1244 timeout.tv_sec = 0;
1245 timeout.tv_nsec = 0;
1246
1247 sigset_t sigset;
1248 sigemptyset(&sigset);
1249 sigaddset(&sigset, signum);
1250
1251 do {
1252 discardedSignal = sigtimedwait(&sigset, NULL, &timeout);
1253 } while (discardedSignal == -1 && errno == EINTR);
1254
1255 if (discardedSignal == signum)
1256 return true;
1257 else if (discardedSignal == -1 && errno == EAGAIN)
1258 return false;
1259 else
1260 panic("Unexpected return value from sigtimedwait: %i (errno: %i)\n",
1261 discardedSignal, errno);
1262}
1263
1264void
1266{
1267 DPRINTF(Kvm, "Attaching cycle counter...\n");
1268 PerfKvmCounterConfig cfgCycles(PERF_TYPE_HARDWARE,
1269 PERF_COUNT_HW_CPU_CYCLES);
1270 cfgCycles.disabled(true)
1271 .pinned(true);
1272
1273 // Try to exclude the host. We set both exclude_hv and
1274 // exclude_host since different architectures use slightly
1275 // different APIs in the kernel.
1276 cfgCycles.exclude_hv(true)
1277 .exclude_host(true);
1278
1280 // We need to configure the cycles counter to send overflows
1281 // since we are going to use it to trigger timer signals that
1282 // trap back into m5 from KVM. In practice, this means that we
1283 // need to set some non-zero sample period that gets
1284 // overridden when the timer is armed.
1285 cfgCycles.wakeupEvents(1)
1286 .samplePeriod(42);
1287 }
1288
1289 // We might be re-attaching counters due threads being
1290 // re-initialised after fork.
1291 if (hwCycles.attached())
1292 hwCycles.detach();
1293
1294 hwCycles.attach(cfgCycles,
1295 0); // TID (0 => currentThread)
1296
1298}
1299
1300bool
1302{
1304 return false;
1305
1306 if (!archIsDrained()) {
1307 DPRINTF(Drain, "tryDrain: Architecture code is not ready.\n");
1308 return false;
1309 }
1310
1311 if (_status == Idle || _status == Running) {
1312 DPRINTF(Drain,
1313 "tryDrain: CPU transitioned into the Idle state, drain done\n");
1315 return true;
1316 } else {
1317 DPRINTF(Drain, "tryDrain: CPU not ready.\n");
1318 return false;
1319 }
1320}
1321
1322void
1324{
1325 if (ioctl(KVM_RUN) == -1) {
1326 if (errno != EINTR)
1327 panic("KVM: Failed to start virtual CPU (errno: %i)\n",
1328 errno);
1329 }
1330}
1331
1332void
1334{
1337 } else {
1339 assert(next > ctrInsts);
1340 setupInstCounter(next - ctrInsts);
1341 }
1342}
1343
1344void
1346{
1347 // No need to do anything if we aren't attaching for the first
1348 // time or the period isn't changing.
1349 if (period == activeInstPeriod && hwInstructions.attached())
1350 return;
1351
1352 PerfKvmCounterConfig cfgInstructions(PERF_TYPE_HARDWARE,
1353 PERF_COUNT_HW_INSTRUCTIONS);
1354
1355 // Try to exclude the host. We set both exclude_hv and
1356 // exclude_host since different architectures use slightly
1357 // different APIs in the kernel.
1358 cfgInstructions.exclude_hv(true)
1359 .exclude_host(true);
1360
1361 if (period) {
1362 // Setup a sampling counter if that has been requested.
1363 cfgInstructions.wakeupEvents(1)
1364 .samplePeriod(period);
1365 }
1366
1367 // We need to detach and re-attach the counter to reliably change
1368 // sampling settings. See PerfKvmCounter::period() for details.
1371 assert(hwCycles.attached());
1372 hwInstructions.attach(cfgInstructions,
1373 0, // TID (0 => currentThread)
1374 hwCycles);
1375
1376 if (period)
1378
1379 activeInstPeriod = period;
1380}
1381
1382} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
const char data[]
RequestorID dataRequestorId() const
Reads this CPU's unique data requestor ID.
Definition base.hh:193
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition base.cc:310
System * system
Definition base.hh:392
void updateCycleCounters(CPUState state)
base method keeping track of cycle progression
Definition base.hh:561
@ CPU_STATE_SLEEP
Definition base.hh:552
std::vector< std::unique_ptr< CommitCPUStats > > commitStats
Definition base.hh:821
gem5::BaseCPU::BaseCPUStats baseStats
ThreadID numThreads
Number of threads we're actually simulating (<= SMT_MAX_THREADS).
Definition base.hh:390
void startup() override
startup() is the final initialization call before simulation.
Definition base.cc:349
virtual void switchOut()
Prepare for another CPU to take over execution.
Definition base.cc:588
virtual void takeOverFrom(BaseCPU *cpu)
Load the state of a CPU from the previous CPU object, invoked on all new CPUs that are about to be sw...
Definition base.cc:602
std::vector< ThreadContext * > threadContexts
Definition base.hh:260
bool switchedOut() const
Determine if the CPU is switched out.
Definition base.hh:373
std::queue< PacketPtr > pendingMMIOPkts
Pending MMIO packets.
Definition base.hh:621
Status nextIOState() const
Returns next valid state after one or more IO accesses.
Definition base.cc:165
Tick submitIO(PacketPtr pkt)
Interface to send Atomic or Timing IO request.
Definition base.cc:172
void recvReqRetry() override
Called by the peer if sendTimingReq was called on this peer (causing recvTimingReq to be called on th...
Definition base.cc:207
bool recvTimingResp(PacketPtr pkt) override
Receive a timing response from the peer.
Definition base.cc:190
unsigned int activeMMIOReqs
Number of MMIO requests in flight.
Definition base.hh:624
virtual void dump() const
Dump the internal state to the terminal.
Definition base.cc:575
int vcpuFD
KVM vCPU file descriptor.
Definition base.hh:705
void finishMMIOPending()
Callback from KvmCPUPort to transition the CPU out of RunningMMIOPending when all timing requests hav...
Definition base.cc:223
Status _status
CPU run state.
Definition base.hh:240
uint64_t activeInstPeriod
Currently active instruction count breakpoint.
Definition base.hh:756
virtual void updateKvmState()=0
Update the KVM state from the current thread context.
struct kvm_coalesced_mmio_ring * mmioRing
Coalesced MMIO ring buffer.
Definition base.hh:721
virtual Tick handleKvmExitHypercall()
The guest requested a monitor service using a hypercall.
Definition base.cc:1044
long vcpuID
KVM internal ID of the vCPU.
Definition base.hh:657
void drainResume() override
Resume execution after a successful drain.
Definition base.cc:380
void getSpecialRegisters(struct kvm_sregs &regs) const
Definition base.cc:825
virtual void updateThreadContext()=0
Update the current thread context with the KVM state.
void takeOverFrom(BaseCPU *cpu) override
Load the state of a CPU from the previous CPU object, invoked on all new CPUs that are about to be sw...
Definition base.cc:447
virtual uint64_t getHostCycles() const
Get the value of the hardware cycle counter in the guest.
Definition base.cc:691
Counter totalInsts() const override
Definition base.cc:562
void getOneReg(uint64_t id, void *addr) const
Definition base.cc:871
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition base.cc:109
const bool alwaysSyncTC
Be conservative and always synchronize the thread context on KVM entry/exit.
Definition base.hh:642
void suspendContext(ThreadID thread_num) override
Notify the CPU that the indicated context is now suspended.
Definition base.cc:515
virtual Tick handleKvmExitIRQWindowOpen()
The guest exited because an interrupt window was requested.
Definition base.cc:1050
void setSignalMask(const sigset_t *mask)
Set the signal mask used in kvmRun()
Definition base.cc:1135
void notifyFork() override
Notify a child process of a fork.
Definition base.cc:410
PerfKvmCounter hwCycles
Guest cycle counter.
Definition base.hh:766
int vcpuMMapSize
Size of MMAPed kvm_run area.
Definition base.hh:707
void syncKvmState()
Update the KVM if the thread context is dirty.
Definition base.cc:947
bool tryDrain()
Try to drain the CPU if a drain is pending.
Definition base.cc:1301
void setRegisters(const struct kvm_regs &regs)
Definition base.cc:818
BaseKvmCPU(const BaseKvmCPUParams &params)
Definition base.cc:65
virtual Tick handleKvmExitException()
An unhandled virtualization exception occured.
Definition base.cc:1066
void kick() const
Force an exit from KVM.
Definition base.hh:138
@ Running
Running normally.
Definition base.hh:205
@ Idle
Context not scheduled in KVM.
Definition base.hh:199
@ RunningMMIOPending
Timing MMIO request in flight or stalled.
Definition base.hh:227
@ RunningService
Requiring service at the beginning of the next cycle.
Definition base.hh:219
@ RunningServiceCompletion
Service completion in progress.
Definition base.hh:236
void deallocateContext(ThreadID thread_num)
Definition base.cc:538
void getRegisters(struct kvm_regs &regs) const
Get/Set the register state of the guest vCPU.
Definition base.cc:811
void setupSignalHandler()
Setup a signal handler to catch the timer signal used to switch back to the monitor.
Definition base.cc:1208
void setSpecialRegisters(const struct kvm_sregs &regs)
Definition base.cc:832
ThreadContext * getContext(int tn) override
Given a thread num get tho thread context for it.
Definition base.cc:553
virtual Tick handleKvmExitIO()
The guest performed a legacy IO request (out/inp on x86)
Definition base.cc:1036
std::string getAndFormatOneReg(uint64_t id) const
Get and format one register for printout.
Definition base.cc:888
gem5::BaseKvmCPU::StatGroup stats
virtual Tick handleKvmExit()
Main kvmRun exit handler, calls the relevant handleKvmExit* depending on exit type.
Definition base.cc:959
void syncThreadContext()
Update a thread context if the KVM state is dirty with respect to the cached thread context.
Definition base.cc:935
void unserializeThread(CheckpointIn &cp, ThreadID tid) override
Unserialize one thread.
Definition base.cc:298
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
Definition base.cc:309
Tick doMMIOAccess(Addr paddr, void *data, int size, bool write)
Inject a memory mapped IO request into gem5.
Definition base.cc:1083
void wakeup(ThreadID tid=0) override
Definition base.cc:478
void startup() override
startup() is the final initialization call before simulation.
Definition base.cc:118
Counter totalOps() const override
Definition base.cc:568
Tick flushCoalescedMMIO()
Service MMIO requests in the mmioRing.
Definition base.cc:1166
EventFunctionWrapper tickEvent
Definition base.hh:725
bool perfControlledByTimer
Does the runTimer control the performance counters?
Definition base.hh:788
virtual Tick kvmRun(Tick ticks)
Request KVM to run the guest for a given number of ticks.
Definition base.cc:697
void setupInstStop()
Setup an instruction break if there is one pending.
Definition base.cc:1333
KvmVM * vm
Definition base.hh:160
bool discardPendingSignal(int signum) const
Discard a (potentially) pending signal.
Definition base.cc:1237
virtual Tick kvmRunDrain()
Request the CPU to run until draining completes.
Definition base.cc:677
virtual Tick handleKvmExitFailEntry()
KVM failed to start the virtualized CPU.
Definition base.cc:1075
void switchOut() override
Prepare for another CPU to take over execution.
Definition base.cc:433
void restartEqThread()
Thread-specific initialization.
Definition base.cc:233
void setupCounters()
Setup hardware performance counters.
Definition base.cc:1265
void serializeThread(CheckpointOut &cp, ThreadID tid) const override
Serialize a single thread.
Definition base.cc:285
PerfKvmCounter hwInstructions
Guest instruction counter.
Definition base.hh:779
void setupInstCounter(uint64_t period=0)
Setup the guest instruction counter.
Definition base.cc:1345
virtual ~BaseKvmCPU()
Definition base.cc:101
void activateContext(ThreadID thread_num) override
Notify the CPU that the indicated context is now active.
Definition base.cc:496
void tick()
Execute the CPU until the next event in the main event queue or until the guest needs service from ge...
Definition base.cc:581
virtual bool archIsDrained() const
Is the architecture specific code in a state that prevents draining?
Definition base.hh:541
struct kvm_run * _kvmRun
Pointer to the kvm_run structure used to communicate parameters with KVM.
Definition base.hh:716
void setOneReg(uint64_t id, const void *addr)
Get/Set single register using the KVM_(SET|GET)_ONE_REG API.
Definition base.cc:854
std::unique_ptr< BaseKvmTimer > runTimer
Timer used to force execution into the monitor after a specified number of simulation tick equivalent...
Definition base.hh:797
KVMCpuPort dataPort
Port for data requests.
Definition base.hh:633
SimpleThread * thread
A cached copy of a thread's state in the form of a SimpleThread object.
Definition base.hh:153
void setFPUState(const struct kvm_fpu &state)
Definition base.cc:846
virtual Tick handleKvmExitUnknown()
An unknown architecture dependent error occurred when starting the vCPU.
Definition base.cc:1058
void getFPUState(struct kvm_fpu &state) const
Get/Set the guest FPU/vector state.
Definition base.cc:839
void haltContext(ThreadID thread_num) override
Notify the CPU that the indicated context is now halted.
Definition base.cc:545
bool kvmStateDirty
Is the KVM state dirty? Set to true to force an update of the KVM vCPU state upon the next call to kv...
Definition base.hh:654
EventQueue * deviceEventQueue()
Get a pointer to the event queue owning devices.
Definition base.hh:447
void verifyMemoryMode() const override
Verify that the system is in a memory mode supported by the CPU.
Definition base.cc:469
bool threadContextDirty
Is the gem5 context dirty? Set to true to force an update of the KVM vCPU state upon the next call to...
Definition base.hh:648
const long pageSize
Cached page size of the host.
Definition base.hh:723
pthread_t vcpuThread
ID of the vCPU thread.
Definition base.hh:660
Counter ctrInsts
Number of instructions executed by the CPU.
Definition base.hh:820
float hostFactor
Host factor as specified in the configuration.
Definition base.hh:800
ThreadContext * tc
ThreadContext object, provides an interface for external objects to modify this thread's state.
Definition base.hh:158
virtual void ioctlRun()
Execute the KVM_RUN ioctl.
Definition base.cc:1323
virtual void stutterPC(PCStateBase &pc) const =0
Modify a PCStatePtr's value so that its next PC is the current PC.
virtual Fault finalizePhysical(const RequestPtr &req, ThreadContext *tc, Mode mode) const
Definition mmu.cc:125
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
Tick nextCycle() const
Based on the clock of the object, determine the start tick of the first cycle that is at least one cy...
Tick clockPeriod() const
Cycles ticksToCycles(Tick t) const
Cycles is a wrapper class for representing cycle counts, i.e.
Definition types.hh:79
Tick nextTick() const
Definition eventq.hh:836
int createVCPU(long vcpuID)
Create a new vCPU within a VM.
Definition vm.cc:573
Kvm * kvm
Global KVM interface.
Definition vm.hh:421
long allocVCPUID()
Allocate a new vCPU ID within the VM.
Definition vm.cc:585
void cpuStartup()
VM CPU initialization code.
Definition vm.cc:358
KVM parent interface.
Definition vm.hh:81
int getVCPUMMapSize() const
Get the size of the MMAPed parameter area used to communicate vCPU parameters between the kernel and ...
Definition vm.hh:96
int capCoalescedMMIO() const
Check if coalesced MMIO is supported and which page in the MMAP'ed structure it stores requests in.
Definition vm.cc:136
virtual std::string name() const
Definition named.hh:47
virtual PCStateBase * clone() const =0
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
PerfEvent counter configuration.
Definition perfevent.hh:55
PerfKvmCounterConfig & samplePeriod(uint64_t period)
Set the initial sample period (overflow count) of an event.
Definition perfevent.hh:88
PerfKvmCounterConfig & disabled(bool val)
Don't start the performance counter automatically when attaching it.
Definition perfevent.hh:113
PerfKvmCounterConfig & exclude_host(bool val)
Exclude the events from the host (i.e., only include events from the guest system).
Definition perfevent.hh:144
PerfKvmCounterConfig & exclude_hv(bool val)
Exclude the hyper visor (i.e., only include events from the guest system).
Definition perfevent.hh:159
PerfKvmCounterConfig & pinned(bool val)
Force the group to be on the active all the time (i.e., disallow multiplexing).
Definition perfevent.hh:126
PerfKvmCounterConfig & wakeupEvents(uint32_t events)
Set the number of samples that need to be triggered before reporting data as being available on the p...
Definition perfevent.hh:101
uint64_t read() const
Read the current value of a counter.
Definition perfevent.cc:138
void attach(PerfKvmCounterConfig &config, pid_t tid)
Attach a counter.
Definition perfevent.hh:207
void detach()
Detach a counter from PerfEvent.
Definition perfevent.cc:96
bool attached() const
Check if a counter is attached.
Definition perfevent.hh:231
void enableSignals(pid_t tid, int signal)
Enable signal delivery to a thread on counter overflow.
Definition perfevent.cc:147
void start()
Start counting.
Definition perfevent.cc:110
void stop()
Stop counting.
Definition perfevent.cc:117
PerfEvent based timer using the host's CPU cycle counter.
Definition timer.hh:222
Timer based on standard POSIX timers.
Definition timer.hh:188
@ UNCACHEABLE
The request is to an uncacheable address.
Definition request.hh:125
The SimpleThread object provides a combination of the ThreadState object and the ThreadContext interf...
int threadId() const override
void serialize(CheckpointOut &cp) const override
Serialize an object.
Status status() const override
void suspend() override
Set the status to Suspended.
void activate() override
Set the status to Active.
EventQueue comInstEventQueue
An instruction-based event queue.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
ThreadContext * getTC()
Returns the pointer to this SimpleThread's ThreadContext.
KvmVM * getKvmVM() const
Get a pointer to the Kernel Virtual Machine (KVM) SimObject, if present.
Definition system.hh:333
bool bypassCaches() const
Should caches be bypassed?
Definition system.hh:279
ThreadContext is the external interface to all thread state for anything outside of the CPU.
@ Halted
Permanently shut down.
@ Suspended
Temporarily inactive.
virtual const PCStateBase & pcState() const =0
virtual Status status() const =0
virtual BaseMMU * getMMUPtr()=0
virtual ContextID contextId() const =0
Statistics container.
Definition group.hh:93
#define KVM_KICK_SIGNAL
Signal to use to trigger exits from KVM.
Definition base.hh:56
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
void kvmInterrupt(const struct kvm_interrupt &interrupt)
Send a normal interrupt to the guest.
Definition base.cc:803
void kvmNonMaskableInterrupt()
Send a non-maskable interrupt to the guest.
Definition base.cc:795
int ioctl(int request, long p1) const
vCPU ioctl interface.
Definition base.cc:1157
void signalDrainDone() const
Signal that an object is drained.
Definition drain.hh:305
DrainState drainState() const
Return the current drain state of an object.
Definition drain.hh:324
DrainState
Object drain/handover states.
Definition drain.hh:75
@ Draining
Draining buffers pending serialization/handover.
@ Drained
Buffers drained, ready for serialization/handover.
void deschedule(Event &event)
Definition eventq.hh:1021
bool scheduled() const
Determine if the current event is scheduled.
Definition eventq.hh:458
void schedule(Event &event, Tick when)
Definition eventq.hh:1012
bool empty() const
Returns true if no events are queued.
Definition eventq.hh:891
static const Priority CPU_Tick_Pri
CPU ticks must come after other associated CPU events (such as writebacks).
Definition eventq.hh:207
EventQueue * eventQueue() const
Definition eventq.hh:1003
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:236
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:200
#define hack_once(...)
Definition logging.hh:264
const Params & params() const
atomic_var_t state
Definition helpers.cc:188
#define warn(...)
Definition logging.hh:256
#define inform(...)
Definition logging.hh:257
Bitfield< 3 > sa
Bitfield< 3, 0 > mask
Definition pcstate.hh:63
Bitfield< 6 > si
Bitfield< 33 > id
Bitfield< 0 > vm
Bitfield< 21 > ss
Definition misc_types.hh:60
Bitfield< 4 > pc
Bitfield< 0 > p
Bitfield< 5, 3 > reg
Definition types.hh:92
Bitfield< 3 > addr
Definition types.hh:84
Bitfield< 5 > lock
Definition types.hh:82
double Counter
All counters are of 64-bit values.
Definition types.hh:46
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
std::shared_ptr< FaultBase > Fault
Definition types.hh:249
int16_t ThreadID
Thread index/ID type.
Definition types.hh:235
std::shared_ptr< Request > RequestPtr
Definition request.hh:94
static void onKickSignal(int signo, siginfo_t *si, void *data)
Dummy handler for KVM kick signals.
Definition base.cc:1203
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
std::ostream CheckpointOut
Definition serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Definition root.cc:220
uint64_t Tick
Tick count type.
Definition types.hh:58
const Tick MaxTick
Definition types.hh:60
EventQueue * curEventQueue()
Definition eventq.hh:91
constexpr decltype(nullptr) NoFault
Definition types.hh:253
statistics::Scalar numInsts
Definition base.hh:637
statistics::Scalar numCycles
Definition base.hh:640
statistics::Scalar numExitSignal
Definition base.hh:809
StatGroup(statistics::Group *parent)
Definition base.cc:262
statistics::Scalar numIO
Definition base.hh:812
statistics::Scalar numHypercalls
Definition base.hh:815
statistics::Scalar numHalt
Definition base.hh:813
statistics::Scalar numVMHalfEntries
Definition base.hh:808
statistics::Scalar numMMIO
Definition base.hh:810
statistics::Scalar numCoalescedMMIO
Definition base.hh:811
statistics::Scalar numInterrupts
Definition base.hh:814
statistics::Scalar numVMExits
Definition base.hh:807
Tick lastSuspend
Last time suspend was called on this thread.
Tick lastActivate
Last time activate was called on this thread.
const std::string & name()
Definition trace.cc:48

Generated on Mon Jul 10 2023 14:24:29 for gem5 by doxygen 1.9.7