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

Generated on Wed Dec 21 2022 10:22:29 for gem5 by doxygen 1.9.1