gem5  v19.0.0.0
system.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2013, 2016 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  * Copyright (c) 2002-2006 The Regents of The University of Michigan
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions are
19  * met: redistributions of source code must retain the above copyright
20  * notice, this list of conditions and the following disclaimer;
21  * redistributions in binary form must reproduce the above copyright
22  * notice, this list of conditions and the following disclaimer in the
23  * documentation and/or other materials provided with the distribution;
24  * neither the name of the copyright holders nor the names of its
25  * contributors may be used to endorse or promote products derived from
26  * this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  *
40  * Authors: Ali Saidi
41  */
42 
43 #include "arch/arm/linux/system.hh"
44 
45 #include "arch/arm/isa_traits.hh"
46 #include "arch/arm/linux/atag.hh"
47 #include "arch/arm/utility.hh"
49 #include "base/loader/dtb_file.hh"
51 #include "base/loader/symtab.hh"
52 #include "cpu/base.hh"
53 #include "cpu/pc_event.hh"
54 #include "cpu/thread_context.hh"
55 #include "debug/Loader.hh"
56 #include "kern/linux/events.hh"
57 #include "kern/linux/helpers.hh"
59 #include "mem/physical.hh"
60 #include "sim/stat_control.hh"
61 
62 using namespace ArmISA;
63 using namespace Linux;
64 
66  : GenericArmSystem(p), dumpStatsPCEvent(nullptr),
67  enableContextSwitchStatsDump(p->enable_context_switch_stats_dump),
68  taskFile(nullptr), kernelPanicEvent(nullptr), kernelOopsEvent(nullptr)
69 {
70  const std::string dmesg_output = name() + ".dmesg";
71  if (p->panic_on_panic) {
72  kernelPanicEvent = addKernelFuncEventOrPanic<Linux::KernelPanicEvent>(
73  "panic", "Kernel panic in simulated kernel", dmesg_output);
74  } else {
75  kernelPanicEvent = addKernelFuncEventOrPanic<Linux::DmesgDumpEvent>(
76  "panic", "Kernel panic in simulated kernel", dmesg_output);
77  }
78 
79  if (p->panic_on_oops) {
80  kernelOopsEvent = addKernelFuncEventOrPanic<Linux::KernelPanicEvent>(
81  "oops_exit", "Kernel oops in guest", dmesg_output);
82  } else {
83  kernelOopsEvent = addKernelFuncEventOrPanic<Linux::DmesgDumpEvent>(
84  "oops_exit", "Kernel oops in guest", dmesg_output);
85  }
86 
87  // With ARM udelay() is #defined to __udelay
88  // newer kernels use __loop_udelay and __loop_const_udelay symbols
89  uDelaySkipEvent = addKernelFuncEvent<UDelayEvent>(
90  "__loop_udelay", "__udelay", 1000, 0);
91  if (!uDelaySkipEvent)
92  uDelaySkipEvent = addKernelFuncEventOrPanic<UDelayEvent>(
93  "__udelay", "__udelay", 1000, 0);
94 
95  // constant arguments to udelay() have some precomputation done ahead of
96  // time. Constant comes from code.
97  constUDelaySkipEvent = addKernelFuncEvent<UDelayEvent>(
98  "__loop_const_udelay", "__const_udelay", 1000, 107374);
99  if (!constUDelaySkipEvent)
100  constUDelaySkipEvent = addKernelFuncEventOrPanic<UDelayEvent>(
101  "__const_udelay", "__const_udelay", 1000, 107374);
102 
103 }
104 
105 void
107 {
108  // Moved from the constructor to here since it relies on the
109  // address map being resolved in the interconnect
110 
111  // Call the initialisation of the super class
113 
114  // Load symbols at physical address, we might not want
115  // to do this permanently, for but early bootup work
116  // it is helpful.
117  if (params()->early_kernel_symbols) {
120  }
121 
122  // Setup boot data structure
123  Addr addr = 0;
124  // Check if the kernel image has a symbol that tells us it supports
125  // device trees.
126  bool kernel_has_fdt_support =
127  kernelSymtab->findAddress("unflatten_device_tree", addr);
128  bool dtb_file_specified = params()->dtb_filename != "";
129 
130  if (kernel_has_fdt_support && dtb_file_specified) {
131  // Kernel supports flattened device tree and dtb file specified.
132  // Using Device Tree Blob to describe system configuration.
133  inform("Loading DTB file: %s at address %#x\n", params()->dtb_filename,
134  params()->atags_addr + loadAddrOffset);
135 
136  DtbFile *dtb_file = new DtbFile(params()->dtb_filename);
137 
138  if (!dtb_file->addBootCmdLine(params()->boot_osflags.c_str(),
139  params()->boot_osflags.size())) {
140  warn("couldn't append bootargs to DTB file: %s\n",
141  params()->dtb_filename);
142  }
143 
144  dtb_file->buildImage().
145  offset(params()->atags_addr + loadAddrOffset).write(physProxy);
146  delete dtb_file;
147  } else {
148  // Using ATAGS
149  // Warn if the kernel supports FDT and we haven't specified one
150  if (kernel_has_fdt_support) {
151  assert(!dtb_file_specified);
152  warn("Kernel supports device tree, but no DTB file specified\n");
153  }
154  // Warn if the kernel doesn't support FDT and we have specified one
155  if (dtb_file_specified) {
156  assert(!kernel_has_fdt_support);
157  warn("DTB file specified, but no device tree support in kernel\n");
158  }
159 
160  AtagCore ac;
161  ac.flags(1); // read-only
162  ac.pagesize(8192);
163  ac.rootdev(0);
164 
165  AddrRangeList atagRanges = physmem.getConfAddrRanges();
166  if (atagRanges.size() != 1) {
167  fatal("Expected a single ATAG memory entry but got %d\n",
168  atagRanges.size());
169  }
170  AtagMem am;
171  am.memSize(atagRanges.begin()->size());
172  am.memStart(atagRanges.begin()->start());
173 
174  AtagCmdline ad;
175  ad.cmdline(params()->boot_osflags);
176 
177  DPRINTF(Loader, "boot command line %d bytes: %s\n",
178  ad.size() <<2, params()->boot_osflags.c_str());
179 
180  AtagNone an;
181 
182  uint32_t size = ac.size() + am.size() + ad.size() + an.size();
183  uint32_t offset = 0;
184  uint8_t *boot_data = new uint8_t[size << 2];
185 
186  offset += ac.copyOut(boot_data + offset);
187  offset += am.copyOut(boot_data + offset);
188  offset += ad.copyOut(boot_data + offset);
189  offset += an.copyOut(boot_data + offset);
190 
191  DPRINTF(Loader, "Boot atags was %d bytes in total\n", size << 2);
192  DDUMP(Loader, boot_data, size << 2);
193 
194  physProxy.writeBlob(params()->atags_addr + loadAddrOffset, boot_data,
195  size << 2);
196 
197  delete[] boot_data;
198  }
199 
200  // Kernel boot requirements to set up r0, r1 and r2 in ARMv7
201  for (int i = 0; i < threadContexts.size(); i++) {
202  threadContexts[i]->setIntReg(0, 0);
203  threadContexts[i]->setIntReg(1, params()->machine_type);
204  threadContexts[i]->setIntReg(2, params()->atags_addr + loadAddrOffset);
205  }
206 }
207 
209 {
210  if (uDelaySkipEvent)
211  delete uDelaySkipEvent;
213  delete constUDelaySkipEvent;
214 
215  if (dumpStatsPCEvent)
216  delete dumpStatsPCEvent;
217 }
218 
220 LinuxArmSystemParams::create()
221 {
222  return new LinuxArmSystem(this);
223 }
224 
225 void
227 {
229  if (!highestELIs64()) {
231  addKernelFuncEvent<DumpStatsPCEvent>("__switch_to");
232  } else {
234  addKernelFuncEvent<DumpStatsPCEvent64>("__switch_to");
235  }
236 
237  if (!dumpStatsPCEvent)
238  panic("dumpStatsPCEvent not created!");
239 
240  std::string task_filename = "tasks.txt";
241  taskFile = simout.create(name() + "." + task_filename);
242 
243  for (const auto tc : threadContexts) {
244  uint32_t pid = tc->getCpuPtr()->getPid();
245  if (pid != BaseCPU::invldPid) {
246  mapPid(tc, pid);
247  tc->getCpuPtr()->taskId(taskMap[pid]);
248  }
249  }
250  }
251 }
252 
253 void
255 {
256  // Create a new unique identifier for this pid
257  std::map<uint32_t, uint32_t>::iterator itr = taskMap.find(pid);
258  if (itr == taskMap.end()) {
259  uint32_t map_size = taskMap.size();
260  if (map_size > ContextSwitchTaskId::MaxNormalTaskId + 1) {
261  warn_once("Error out of identifiers for cache occupancy stats");
263  } else {
264  taskMap[pid] = map_size;
265  }
266  }
267 }
268 
269 void
271 {
272  Linux::dumpDmesg(getThreadContext(0), std::cout);
273 }
274 
283 void
285  uint32_t &tgid, std::string &next_task_str, int32_t &mm) {
286 
287  Linux::ThreadInfo ti(tc);
288  Addr task_descriptor = tc->readIntReg(2);
289  pid = ti.curTaskPID(task_descriptor);
290  tgid = ti.curTaskTGID(task_descriptor);
291  next_task_str = ti.curTaskName(task_descriptor);
292 
293  // Streamline treats pid == -1 as the kernel process.
294  // Also pid == 0 implies idle process (except during Linux boot)
295  mm = ti.curTaskMm(task_descriptor);
296 }
297 
305 void
307  uint32_t &tgid, std::string &next_task_str, int32_t &mm) {
308 
309  Linux::ThreadInfo ti(tc);
310  Addr task_struct = tc->readIntReg(1);
311  pid = ti.curTaskPIDFromTaskStruct(task_struct);
312  tgid = ti.curTaskTGIDFromTaskStruct(task_struct);
313  next_task_str = ti.curTaskNameFromTaskStruct(task_struct);
314 
315  // Streamline treats pid == -1 as the kernel process.
316  // Also pid == 0 implies idle process (except during Linux boot)
317  mm = ti.curTaskMmFromTaskStruct(task_struct);
318 }
319 
323 void
325 {
326  uint32_t pid = 0;
327  uint32_t tgid = 0;
328  std::string next_task_str;
329  int32_t mm = 0;
330 
331  getTaskDetails(tc, pid, tgid, next_task_str, mm);
332 
333  bool is_kernel = (mm == 0);
334  if (is_kernel && (pid != 0)) {
335  pid = -1;
336  tgid = -1;
337  next_task_str = "kernel";
338  }
339 
340  LinuxArmSystem* sys = dynamic_cast<LinuxArmSystem *>(tc->getSystemPtr());
341  if (!sys) {
342  panic("System is not LinuxArmSystem while getting Linux process info!");
343  }
344  std::map<uint32_t, uint32_t>& taskMap = sys->taskMap;
345 
346  // Create a new unique identifier for this pid
347  sys->mapPid(tc, pid);
348 
349  // Set cpu task id, output process info, and dump stats
350  tc->getCpuPtr()->taskId(taskMap[pid]);
351  tc->getCpuPtr()->setPid(pid);
352 
354 
355  // Task file is read by cache occupancy plotting script or
356  // Streamline conversion script.
357  ccprintf(*(taskFile->stream()),
358  "tick=%lld %d cpu_id=%d next_pid=%d next_tgid=%d next_task=%s\n",
359  curTick(), taskMap[pid], tc->cpuId(), (int) pid, (int) tgid,
360  next_task_str);
361  taskFile->stream()->flush();
362 
363  // Dump and reset statistics
364  Stats::schedStatEvent(true, true, curTick(), 0);
365 }
366 
uint32_t taskId() const
Get cpu task id.
Definition: base.hh:207
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
void ccprintf(cp::Print &print)
Definition: cprintf.hh:131
#define DPRINTF(x,...)
Definition: trace.hh:229
OutputDirectory simout
Definition: output.cc:65
virtual System * getSystemPtr()=0
virtual void initState()
Initialise the system.
Definition: system.cc:319
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:175
Bitfield< 7 > i
Definition: mm.h:8
OutputStream * create(const std::string &name, bool binary=false, bool no_gz=false)
Creates a file in this directory (optionally compressed).
Definition: output.cc:206
void startup()
startup() is the final initialization call before simulation.
Definition: system.cc:226
void dumpDmesg(ThreadContext *tc, std::ostream &os)
Dump Linux&#39;s dmesg log buffer to the an output stream.
virtual RegVal readIntReg(RegIndex reg_idx) const =0
const Params * params() const
Definition: system.hh:68
PCEvent * kernelPanicEvent
Event to halt the simulator if the kernel calls panic()
Definition: system.hh:106
Bitfield< 3 > am
Definition: miscregs.hh:130
LinuxArmSystemParams Params
Boilerplate params code.
Definition: system.hh:66
void flags(uint32_t i)
Definition: atag.hh:97
ip6_addr_t addr
Definition: inet.hh:335
#define DDUMP(x, data, count)
Definition: trace.hh:228
void getTaskDetails(ThreadContext *tc, uint32_t &pid, uint32_t &tgid, std::string &next_task_str, int32_t &mm) override
Extracts the information used by the DumpStatsPCEvent64 by reading the task_struct pointer passed to ...
Definition: system.cc:306
bool highestELIs64() const
Returns true if the register width of the highest implemented exception level is 64 bits (ARMv8) ...
Definition: system.hh:221
Definition: atag.hh:91
PhysicalMemory physmem
Definition: system.hh:321
void pagesize(uint32_t i)
Definition: atag.hh:98
void dumpDmesg()
Dump the kernel&#39;s dmesg buffer to stdout.
Definition: system.cc:270
SymbolTable * debugSymbolTable
Global unified debugging symbol table (for target).
Definition: symtab.cc:45
Bitfield< 23, 0 > offset
Definition: types.hh:154
std::map< uint32_t, uint32_t > taskMap
This map stores a mapping of OS process IDs to internal Task IDs.
Definition: system.hh:81
virtual BaseCPU * getCpuPtr()=0
Definition: ccregs.hh:42
Bitfield< 30 > ti
std::string curTaskNameFromTaskStruct(Addr task_struct)
Definition: threadinfo.hh:159
Linux::UDelayEvent * uDelaySkipEvent
PC based event to skip udelay(<time>) calls and quiesce the processor for the appropriate amount of t...
Definition: system.hh:116
ThreadContext is the external interface to all thread state for anything outside of the CPU...
std::ostream * stream() const
Get the output underlying output stream.
Definition: output.hh:64
ThreadContext * getThreadContext(ContextID tid) const
Definition: system.hh:194
int32_t curTaskMmFromTaskStruct(Addr task_struct)
Definition: threadinfo.hh:183
LinuxArmSystem(Params *p)
Definition: system.cc:65
int32_t curTaskPIDFromTaskStruct(Addr task_struct)
Definition: threadinfo.hh:110
PortProxy physProxy
Port to physical memory used for writing object files into ram at boot.
Definition: system.hh:218
#define inform(...)
Definition: logging.hh:213
Tick curTick()
The current simulated tick.
Definition: core.hh:47
DumpStatsPCEvent * dumpStatsPCEvent
Definition: system.hh:62
Bitfield< 18 > ac
Definition: misc.hh:563
void initState()
Initialise the system.
Definition: system.cc:106
bool findAddress(const std::string &symbol, Addr &address) const
Definition: symtab.hh:97
virtual int cpuId() const =0
Linux::UDelayEvent * constUDelaySkipEvent
Another PC based skip event for const_udelay().
Definition: system.hh:123
Addr loadAddrMask
Mask that should be anded for binary/symbol loading.
Definition: system.hh:245
void writeBlob(Addr addr, const void *p, int size) const
Same as tryWriteBlob, but insists on success.
Definition: port_proxy.hh:189
void rootdev(uint32_t i)
Definition: atag.hh:99
int32_t curTaskTGIDFromTaskStruct(Addr task_struct)
Definition: threadinfo.hh:125
virtual void getTaskDetails(ThreadContext *tc, uint32_t &pid, uint32_t &tgid, std::string &next_task_str, int32_t &mm)
Extracts the information used by the DumpStatsPCEvent by reading the thread_info pointer passed to __...
Definition: system.cc:284
std::vector< ThreadContext * > threadContexts
Definition: system.hh:190
uint32_t size() const
Definition: atag.hh:69
AddrRangeList getConfAddrRanges() const
Get the memory ranges for all memories that are to be reported to the configuration table...
Definition: physical.cc:242
virtual void process(ThreadContext *tc)
This function is called whenever the the kernel function "__switch_to" is called to change running ta...
Definition: system.cc:324
void cmdline(const std::string &s)
Definition: atag.hh:149
Definition: atag.hh:105
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
virtual const std::string name() const
Definition: sim_object.hh:120
uint32_t copyOut(uint8_t *p)
Definition: atag.hh:82
#define warn_once(...)
Definition: logging.hh:216
SymbolTable * kernelSymtab
kernel symbol table
Definition: system.hh:221
This implements an image file format to support loading and modifying flattened device tree blobs for...
ObjectFile * kernel
Object pointer for the kernel code.
Definition: system.hh:224
MemoryImage buildImage() const override
Definition: dtb_file.cc:150
int32_t curTaskPID(Addr thread_info=0)
Definition: threadinfo.hh:119
int32_t curTaskMm(Addr thread_info=0)
Definition: threadinfo.hh:193
bool addBootCmdLine(const char *_args, size_t len)
Adds the passed in Command Line options for the kernel to the proper location in the device tree...
Definition: dtb_file.cc:61
TranslatingPortProxy Object Declaration for FS.
bool enableContextSwitchStatsDump
When enabled, dump stats/task info on context switches for Streamline and per-thread cache occupancy ...
Definition: system.hh:75
std::string curTaskName(Addr thread_info=0)
Definition: threadinfo.hh:177
void schedStatEvent(bool dump, bool reset, Tick when, Tick repeat)
Schedule statistics dumping.
void setPid(uint32_t pid)
Definition: base.hh:212
#define warn(...)
Definition: logging.hh:212
PCEvent * kernelOopsEvent
Event to halt the simulator if the kernel calls oopses.
Definition: system.hh:109
Addr loadAddrOffset
Offset that should be used for binary/symbol loading.
Definition: system.hh:252
int32_t curTaskTGID(Addr thread_info=0)
Definition: threadinfo.hh:135
Bitfield< 0 > p
OutputStream * taskFile
This is a file that is placed in the run directory that prints out mappings between taskIds and OS pr...
Definition: system.hh:85
virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr base=0, Addr offset=0, Addr mask=MaxAddr)
Definition: object_file.hh:90
void mapPid(ThreadContext *tc, uint32_t pid)
This function creates a new task Id for the given pid.
Definition: system.cc:254
static const uint32_t invldPid
Invalid or unknown Pid.
Definition: base.hh:276

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