gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
gic.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-2017 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions are
16  * met: redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer;
18  * redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution;
21  * neither the name of the copyright holders nor the names of its
22  * contributors may be used to endorse or promote products derived from
23  * this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  *
37  * Authors: Andreas Sandberg
38  * Curtis Dunham
39  */
40 
41 #include "arch/arm/kvm/gic.hh"
42 
43 #include <linux/kvm.h>
44 
45 #include "arch/arm/kvm/base_cpu.hh"
46 #include "debug/GIC.hh"
47 #include "debug/Interrupt.hh"
48 #include "params/MuxingKvmGic.hh"
49 
50 KvmKernelGicV2::KvmKernelGicV2(KvmVM &_vm, Addr cpu_addr, Addr dist_addr,
51  unsigned it_lines)
52  : cpuRange(RangeSize(cpu_addr, KVM_VGIC_V2_CPU_SIZE)),
53  distRange(RangeSize(dist_addr, KVM_VGIC_V2_DIST_SIZE)),
54  vm(_vm),
55  kdev(vm.createDevice(KVM_DEV_TYPE_ARM_VGIC_V2))
56 {
57  // Tell the VM that we will emulate the GIC in the kernel. This
58  // disables IRQ and FIQ handling in the KVM CPU model.
60 
61  kdev.setAttr<uint64_t>(
62  KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V2_ADDR_TYPE_DIST, dist_addr);
63  kdev.setAttr<uint64_t>(
64  KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V2_ADDR_TYPE_CPU, cpu_addr);
65 
66  kdev.setAttr<uint32_t>(KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0, it_lines);
67 }
68 
70 {
71 }
72 
73 void
75 {
76  setIntState(KVM_ARM_IRQ_TYPE_SPI, 0, spi, true);
77 }
78 
79 void
81 {
82  setIntState(KVM_ARM_IRQ_TYPE_SPI, 0, spi, false);
83 }
84 
85 void
86 KvmKernelGicV2::setPPI(unsigned vcpu, unsigned ppi)
87 {
88  setIntState(KVM_ARM_IRQ_TYPE_PPI, vcpu, ppi, true);
89 }
90 
91 void
92 KvmKernelGicV2::clearPPI(unsigned vcpu, unsigned ppi)
93 {
94  setIntState(KVM_ARM_IRQ_TYPE_PPI, vcpu, ppi, false);
95 }
96 
97 void
98 KvmKernelGicV2::setIntState(unsigned type, unsigned vcpu, unsigned irq,
99  bool high)
100 {
101  assert(type <= KVM_ARM_IRQ_TYPE_MASK);
102  assert(vcpu <= KVM_ARM_IRQ_VCPU_MASK);
103  assert(irq <= KVM_ARM_IRQ_NUM_MASK);
104  const uint32_t line(
105  (type << KVM_ARM_IRQ_TYPE_SHIFT) |
106  (vcpu << KVM_ARM_IRQ_VCPU_SHIFT) |
107  (irq << KVM_ARM_IRQ_NUM_SHIFT));
108 
109  vm.setIRQLine(line, high);
110 }
111 
112 uint32_t
113 KvmKernelGicV2::getGicReg(unsigned group, unsigned vcpu, unsigned offset)
114 {
115  uint64_t reg;
116 
117  assert(vcpu <= KVM_ARM_IRQ_VCPU_MASK);
118  const uint64_t attr(
119  ((uint64_t)vcpu << KVM_DEV_ARM_VGIC_CPUID_SHIFT) |
120  (offset << KVM_DEV_ARM_VGIC_OFFSET_SHIFT));
121 
122  kdev.getAttrPtr(group, attr, &reg);
123  return (uint32_t) reg;
124 }
125 
126 void
127 KvmKernelGicV2::setGicReg(unsigned group, unsigned vcpu, unsigned offset,
128  unsigned value)
129 {
130  uint64_t reg = value;
131 
132  assert(vcpu <= KVM_ARM_IRQ_VCPU_MASK);
133  const uint64_t attr(
134  ((uint64_t)vcpu << KVM_DEV_ARM_VGIC_CPUID_SHIFT) |
135  (offset << KVM_DEV_ARM_VGIC_OFFSET_SHIFT));
136 
137  kdev.setAttrPtr(group, attr, &reg);
138 }
139 
140 uint32_t
142 {
143  auto vcpu = vm.contextIdToVCpuId(ctx);
144  return getGicReg(KVM_DEV_ARM_VGIC_GRP_DIST_REGS, vcpu, daddr);
145 }
146 
147 uint32_t
149 {
150  auto vcpu = vm.contextIdToVCpuId(ctx);
151  return getGicReg(KVM_DEV_ARM_VGIC_GRP_CPU_REGS, vcpu, daddr);
152 }
153 
154 void
156 {
157  auto vcpu = vm.contextIdToVCpuId(ctx);
158  setGicReg(KVM_DEV_ARM_VGIC_GRP_DIST_REGS, vcpu, daddr, data);
159 }
160 
161 void
163 {
164  auto vcpu = vm.contextIdToVCpuId(ctx);
165  setGicReg(KVM_DEV_ARM_VGIC_GRP_CPU_REGS, vcpu, daddr, data);
166 }
167 
168 
169 
170 MuxingKvmGic::MuxingKvmGic(const MuxingKvmGicParams *p)
171  : GicV2(p),
172  system(*p->system),
173  kernelGic(nullptr),
174  usingKvm(false)
175 {
176  if (auto vm = system.getKvmVM()) {
177  kernelGic = new KvmKernelGicV2(*vm, p->cpu_addr, p->dist_addr,
178  p->it_lines);
179  }
180 }
181 
183 {
184 }
185 
186 void
188 {
189  GicV2::startup();
190  usingKvm = (kernelGic != nullptr) && system.validKvmEnvironment();
191  if (usingKvm)
192  fromGicV2ToKvm();
193 }
194 
197 {
198  if (usingKvm)
199  fromKvmToGicV2();
200  return GicV2::drain();
201 }
202 
203 void
205 {
207  bool use_kvm = (kernelGic != nullptr) && system.validKvmEnvironment();
208  if (use_kvm != usingKvm) {
209  // Should only occur due to CPU switches
210  if (use_kvm) // from simulation to KVM emulation
211  fromGicV2ToKvm();
212  // otherwise, drain() already sync'd the state back to the GicV2
213 
214  usingKvm = use_kvm;
215  }
216 }
217 
218 Tick
220 {
221  if (!usingKvm)
222  return GicV2::read(pkt);
223 
224  panic("MuxingKvmGic: PIO from gem5 is currently unsupported\n");
225 }
226 
227 Tick
229 {
230  if (!usingKvm)
231  return GicV2::write(pkt);
232 
233  panic("MuxingKvmGic: PIO from gem5 is currently unsupported\n");
234 }
235 
236 void
238 {
239  if (!usingKvm)
240  return GicV2::sendInt(num);
241 
242  DPRINTF(Interrupt, "Set SPI %d\n", num);
243  kernelGic->setSPI(num);
244 }
245 
246 void
248 {
249  if (!usingKvm)
250  return GicV2::clearInt(num);
251 
252  DPRINTF(Interrupt, "Clear SPI %d\n", num);
253  kernelGic->clearSPI(num);
254 }
255 
256 void
257 MuxingKvmGic::sendPPInt(uint32_t num, uint32_t cpu)
258 {
259  if (!usingKvm)
260  return GicV2::sendPPInt(num, cpu);
261  DPRINTF(Interrupt, "Set PPI %d:%d\n", cpu, num);
262  kernelGic->setPPI(cpu, num);
263 }
264 
265 void
266 MuxingKvmGic::clearPPInt(uint32_t num, uint32_t cpu)
267 {
268  if (!usingKvm)
269  return GicV2::clearPPInt(num, cpu);
270 
271  DPRINTF(Interrupt, "Clear PPI %d:%d\n", cpu, num);
272  kernelGic->clearPPI(cpu, num);
273 }
274 
275 void
277 {
278  // During Kvm->GicV2 state transfer, writes to the GicV2 will call
279  // updateIntState() which can post an interrupt. Since we're only
280  // using the GicV2 model for holding state in this circumstance, we
281  // short-circuit this behavior, as the GicV2 is not actually active.
282  if (!usingKvm)
283  return GicV2::updateIntState(hint);
284 }
285 
286 void
288  ContextID ctx, Addr daddr)
289 {
290  auto val = from->readDistributor(ctx, daddr);
291  DPRINTF(GIC, "copy dist 0x%x 0x%08x\n", daddr, val);
292  to->writeDistributor(ctx, daddr, val);
293 }
294 
295 void
297  ContextID ctx, Addr daddr)
298 {
299  auto val = from->readCpu(ctx, daddr);
300  DPRINTF(GIC, "copy cpu 0x%x 0x%08x\n", daddr, val);
301  to->writeCpu(ctx, daddr, val);
302 }
303 
304 void
306  Addr daddr, size_t size)
307 {
308  for (int ctx = 0; ctx < system.numContexts(); ++ctx)
309  for (auto a = daddr; a < daddr + size; a += 4)
310  copyDistRegister(from, to, ctx, a);
311 }
312 
313 void
315  Addr daddr, size_t size)
316 {
317  for (int ctx = 0; ctx < system.numContexts(); ++ctx)
318  for (auto a = daddr; a < daddr + size; a += 4)
319  to->writeDistributor(ctx, a, 0xFFFFFFFF);
320 }
321 
322 void
324  Addr daddr, size_t size)
325 {
326  for (auto a = daddr; a < daddr + size; a += 4)
327  copyDistRegister(from, to, 0, a);
328 }
329 
330 void
332  Addr daddr, size_t size)
333 {
334  for (auto a = daddr; a < daddr + size; a += 4)
335  to->writeDistributor(0, a, 0xFFFFFFFF);
336 }
337 
338 void
340 {
341  Addr set, clear;
342  size_t size;
343 
345  // Copy CPU Interface Control Register (CTLR),
346  // Interrupt Priority Mask Register (PMR), and
347  // Binary Point Register (BPR)
348  for (int ctx = 0; ctx < system.numContexts(); ++ctx) {
349  copyCpuRegister(from, to, ctx, GICC_CTLR);
350  copyCpuRegister(from, to, ctx, GICC_PMR);
351  copyCpuRegister(from, to, ctx, GICC_BPR);
352  }
353 
354 
356  // Copy Distributor Control Register (CTLR)
357  copyDistRegister(from, to, 0, GICD_CTLR);
358 
359  // Copy interrupt-enabled statuses (I[CS]ENABLERn; R0 is per-CPU banked)
361  clear = GicV2::GICD_ICENABLER.start();
362  size = GicV2::itLines / 8;
363  clearBankedDistRange(to, clear, 4);
364  copyBankedDistRange(from, to, set, 4);
365 
366  set += 4, clear += 4, size -= 4;
367  clearDistRange(to, clear, size);
368  copyDistRange(from, to, set, size);
369 
370  // Copy pending interrupts (I[CS]PENDRn; R0 is per-CPU banked)
371  set = GicV2::GICD_ISPENDR.start();
372  clear = GicV2::GICD_ICPENDR.start();
373  size = GicV2::itLines / 8;
374  clearBankedDistRange(to, clear, 4);
375  copyBankedDistRange(from, to, set, 4);
376 
377  set += 4, clear += 4, size -= 4;
378  clearDistRange(to, clear, size);
379  copyDistRange(from, to, set, size);
380 
381  // Copy active interrupts (I[CS]ACTIVERn; R0 is per-CPU banked)
383  clear = GicV2::GICD_ICACTIVER.start();
384  size = GicV2::itLines / 8;
385  clearBankedDistRange(to, clear, 4);
386  copyBankedDistRange(from, to, set, 4);
387 
388  set += 4, clear += 4, size -= 4;
389  clearDistRange(to, clear, size);
390  copyDistRange(from, to, set, size);
391 
392  // Copy interrupt priorities (IPRIORITYRn; R0-7 are per-CPU banked)
394  copyBankedDistRange(from, to, set, 32);
395 
396  set += 32;
397  size = GicV2::itLines - 32;
398  copyDistRange(from, to, set, size);
399 
400  // Copy interrupt processor target regs (ITARGETRn; R0-7 are read-only)
401  set = GicV2::GICD_ITARGETSR.start() + 32;
402  size = GicV2::itLines - 32;
403  copyDistRange(from, to, set, size);
404 
405  // Copy interrupt configuration registers (ICFGRn)
406  set = GicV2::GICD_ICFGR.start();
407  size = GicV2::itLines / 4;
408  copyDistRange(from, to, set, size);
409 }
410 
411 void
413 {
414  copyGicState(static_cast<GicV2*>(this), kernelGic);
415 }
416 
417 void
419 {
420  copyGicState(kernelGic, static_cast<GicV2*>(this));
421 
422  // the values read for the Interrupt Priority Mask Register (PMR)
423  // have been shifted by three bits due to its having been emulated by
424  // a VGIC with only 5 PMR bits in its VMCR register. Presently the
425  // Linux kernel does not repair this inaccuracy, so we correct it here.
426  for (int cpu = 0; cpu < system.numContexts(); ++cpu) {
427  cpuPriority[cpu] <<= 3;
428  assert((cpuPriority[cpu] & ~0xff) == 0);
429  }
430 }
431 
432 MuxingKvmGic *
433 MuxingKvmGicParams::create()
434 {
435  return new MuxingKvmGic(this);
436 }
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
void clearInt(ContextID ctx, uint32_t int_num)
Clears a cpu IRQ or FIQ signal.
Definition: gic_v2.cc:916
void writeDistributor(ContextID ctx, Addr daddr, uint32_t data) override
Definition: gic.cc:155
#define DPRINTF(x,...)
Definition: trace.hh:229
AddrRange RangeSize(Addr start, Addr size)
Definition: addr_range.hh:584
uint32_t getGicReg(unsigned group, unsigned vcpu, unsigned offset)
Get value of GIC register "from" a cpu.
Definition: gic.cc:113
System & system
System this interrupt controller belongs to.
Definition: gic.hh:197
void sendInt(uint32_t num) override
Post an interrupt from a device that is connected to the GIC.
Definition: gic.cc:237
void setPPI(unsigned vcpu, unsigned ppi)
Raise a private peripheral interrupt.
Definition: gic.cc:86
virtual uint32_t readCpu(ContextID ctx, Addr daddr)=0
Bitfield< 5, 3 > reg
Definition: types.hh:89
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: gic.cc:219
void clearPPInt(uint32_t num, uint32_t cpu) override
Definition: gic.cc:266
virtual uint32_t readDistributor(ContextID ctx, Addr daddr)=0
DrainState
Object drain/handover states.
Definition: drain.hh:71
void copyDistRange(BaseGicRegisters *from, BaseGicRegisters *to, Addr daddr, size_t size)
Definition: gic.cc:323
void enableKernelIRQChip()
Tell the VM and VCPUs to use an in-kernel IRQ chip for interrupt delivery.
Definition: vm.hh:362
void setAttr(uint32_t group, uint64_t attr, const T &data) const
Get the value of an attribute.
Definition: device.hh:94
static const AddrRange GICD_ISENABLER
Definition: gic_v2.hh:83
static const AddrRange GICD_ICENABLER
Definition: gic_v2.hh:84
Bitfield< 8 > a
void updateIntState(int hint) override
See if some processor interrupt flags need to be enabled/disabled.
Definition: gic.cc:276
void fromKvmToGicV2()
Definition: gic.cc:418
void sendPPInt(uint32_t num, uint32_t cpu) override
Interface call for private peripheral interrupts.
Definition: gic.cc:257
Tick write(PacketPtr pkt) override
A PIO read to the device, immediately split up into writeDistributor() or writeCpu() ...
Definition: gic_v2.cc:127
Bitfield< 23, 0 > offset
Definition: types.hh:154
void fromGicV2ToKvm()
Multiplexing implementation.
Definition: gic.cc:412
void setIntState(unsigned type, unsigned vcpu, unsigned irq, bool high)
Update the kernel&#39;s VGIC interrupt state.
Definition: gic.cc:98
virtual void updateIntState(int hint)
See if some processor interrupt flags need to be enabled/disabled.
Definition: gic_v2.cc:738
static const AddrRange GICD_ISACTIVER
Definition: gic_v2.hh:87
static const AddrRange GICD_IPRIORITYR
Definition: gic_v2.hh:89
void setIRQLine(uint32_t irq, bool high)
Set the status of an IRQ line using KVM_IRQ_LINE.
Definition: vm.cc:502
bool usingKvm
Definition: gic.hh:203
Bitfield< 63 > val
Definition: misc.hh:771
Tick read(PacketPtr pkt) override
A PIO read to the device, immediately split up into readDistributor() or readCpu() ...
Definition: gic_v2.cc:113
void clearDistRange(BaseGicRegisters *to, Addr daddr, size_t size)
Definition: gic.cc:331
uint8_t type
Definition: inet.hh:333
~MuxingKvmGic()
Definition: gic.cc:182
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: gic.cc:228
long contextIdToVCpuId(ContextID ctx) const
Get the VCPUID for a given context.
Definition: vm.cc:540
uint64_t Tick
Tick count type.
Definition: types.hh:63
void copyCpuRegister(BaseGicRegisters *from, BaseGicRegisters *to, ContextID ctx, Addr daddr)
Definition: gic.cc:296
void clearBankedDistRange(BaseGicRegisters *to, Addr daddr, size_t size)
Definition: gic.cc:314
KvmVM * getKvmVM()
Get a pointer to the Kernel Virtual Machine (KVM) SimObject, if present.
Definition: system.hh:259
unsigned numContexts() const
Definition: system.hh:206
DrainState drain() override
Notify an object that it needs to drain its state.
Definition: gic.cc:196
uint8_t cpuPriority[CPU_MAX]
CPU priority.
Definition: gic_v2.hh:376
void copyBankedDistRange(BaseGicRegisters *from, BaseGicRegisters *to, Addr daddr, size_t size)
Definition: gic.cc:305
DrainState drain() override
Notify an object that it needs to drain its state.
Definition: gic_v2.cc:970
static const AddrRange GICD_ICACTIVER
Definition: gic_v2.hh:88
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
void clearPPI(unsigned vcpu, unsigned ppi)
Clear a private peripheral interrupt.
Definition: gic.cc:92
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:255
void sendInt(uint32_t number) override
Post an interrupt from a device that is connected to the GIC.
Definition: gic_v2.cc:865
void getAttrPtr(uint32_t group, uint64_t attr, void *data) const
Definition: device.cc:62
static const AddrRange GICD_ICPENDR
Definition: gic_v2.hh:86
virtual void writeDistributor(ContextID ctx, Addr daddr, uint32_t data)=0
Bitfield< 15 > system
Definition: misc.hh:999
void copyDistRegister(BaseGicRegisters *from, BaseGicRegisters *to, ContextID ctx, Addr daddr)
Definition: gic.cc:287
void setAttrPtr(uint32_t group, uint64_t attr, const void *data) const
Definition: device.cc:82
KvmKernelGicV2 * kernelGic
Kernel GIC device.
Definition: gic.hh:200
void startup() override
startup() is the final initialization call before simulation.
Definition: gic.cc:187
Definition: gic_v2.hh:61
void clearPPInt(uint32_t num, uint32_t cpu) override
Definition: gic_v2.cc:907
void writeCpu(ContextID ctx, Addr daddr, uint32_t data) override
Definition: gic.cc:162
bool validKvmEnvironment() const
Verify gem5 configuration will support KVM emulation.
Definition: system.cc:410
KVM VM container.
Definition: vm.hh:291
Bitfield< 1 > irq
KVM in-kernel GIC abstraction.
Definition: gic.hh:57
KvmVM & vm
KVM VM in the parent system.
Definition: gic.hh:162
virtual ~KvmKernelGicV2()
Definition: gic.cc:69
uint32_t itLines
Number of itLines enabled.
Definition: gic_v2.hh:177
virtual void writeCpu(ContextID ctx, Addr daddr, uint32_t data)=0
void drainResume() override
Resume execution after a successful drain.
Definition: gic.cc:204
static const AddrRange GICD_ITARGETSR
Definition: gic_v2.hh:90
Addr start() const
Get the start address of the range.
Definition: addr_range.hh:297
void copyGicState(BaseGicRegisters *from, BaseGicRegisters *to)
Definition: gic.cc:339
KvmDevice kdev
Kernel interface to the GIC.
Definition: gic.hh:165
KvmKernelGicV2(KvmVM &vm, Addr cpu_addr, Addr dist_addr, unsigned it_lines)
Instantiate a KVM in-kernel GIC model.
Definition: gic.cc:50
void drainResume() override
Resume execution after a successful drain.
Definition: gic_v2.cc:981
static const AddrRange GICD_ICFGR
Definition: gic_v2.hh:91
void setSPI(unsigned spi)
Raise a shared peripheral interrupt.
Definition: gic.cc:74
void setGicReg(unsigned group, unsigned vcpu, unsigned offset, unsigned value)
Set value of GIC register "from" a cpu.
Definition: gic.cc:127
static const AddrRange GICD_ISPENDR
Definition: gic_v2.hh:85
void clearSPI(unsigned spi)
Clear a shared peripheral interrupt.
Definition: gic.cc:80
Bitfield< 0 > vm
void sendPPInt(uint32_t num, uint32_t cpu) override
Interface call for private peripheral interrupts.
Definition: gic_v2.cc:879
void clearInt(uint32_t num) override
Clear an interrupt from a device that is connected to the GIC.
Definition: gic.cc:247
Bitfield< 0 > p
MuxingKvmGic(const MuxingKvmGicParams *p)
Definition: gic.cc:170
const char data[]
int ContextID
Globally unique thread context ID.
Definition: types.hh:231
uint32_t readDistributor(ContextID ctx, Addr daddr) override
BaseGicRegisters interface.
Definition: gic.cc:141
uint32_t readCpu(ContextID ctx, Addr daddr) override
Definition: gic.cc:148
virtual void startup()
startup() is the final initialization call before simulation.
Definition: sim_object.cc:99

Generated on Fri Feb 28 2020 16:26:56 for gem5 by doxygen 1.8.13