gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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"
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  ObjectFile *dtb_file = createObjectFile(params()->dtb_filename, true);
137  if (!dtb_file) {
138  fatal("couldn't load DTB file: %s\n", params()->dtb_filename);
139  }
140 
141  DtbObject *_dtb_file = dynamic_cast<DtbObject*>(dtb_file);
142 
143  if (_dtb_file) {
144  if (!_dtb_file->addBootCmdLine(params()->boot_osflags.c_str(),
145  params()->boot_osflags.size())) {
146  warn("couldn't append bootargs to DTB file: %s\n",
147  params()->dtb_filename);
148  }
149  } else {
150  warn("dtb_file cast failed; couldn't append bootargs "
151  "to DTB file: %s\n", params()->dtb_filename);
152  }
153 
154  dtb_file->setTextBase(params()->atags_addr + loadAddrOffset);
155  dtb_file->loadSections(physProxy);
156  delete dtb_file;
157  } else {
158  // Using ATAGS
159  // Warn if the kernel supports FDT and we haven't specified one
160  if (kernel_has_fdt_support) {
161  assert(!dtb_file_specified);
162  warn("Kernel supports device tree, but no DTB file specified\n");
163  }
164  // Warn if the kernel doesn't support FDT and we have specified one
165  if (dtb_file_specified) {
166  assert(!kernel_has_fdt_support);
167  warn("DTB file specified, but no device tree support in kernel\n");
168  }
169 
170  AtagCore ac;
171  ac.flags(1); // read-only
172  ac.pagesize(8192);
173  ac.rootdev(0);
174 
175  AddrRangeList atagRanges = physmem.getConfAddrRanges();
176  if (atagRanges.size() != 1) {
177  fatal("Expected a single ATAG memory entry but got %d\n",
178  atagRanges.size());
179  }
180  AtagMem am;
181  am.memSize(atagRanges.begin()->size());
182  am.memStart(atagRanges.begin()->start());
183 
184  AtagCmdline ad;
185  ad.cmdline(params()->boot_osflags);
186 
187  DPRINTF(Loader, "boot command line %d bytes: %s\n",
188  ad.size() <<2, params()->boot_osflags.c_str());
189 
190  AtagNone an;
191 
192  uint32_t size = ac.size() + am.size() + ad.size() + an.size();
193  uint32_t offset = 0;
194  uint8_t *boot_data = new uint8_t[size << 2];
195 
196  offset += ac.copyOut(boot_data + offset);
197  offset += am.copyOut(boot_data + offset);
198  offset += ad.copyOut(boot_data + offset);
199  offset += an.copyOut(boot_data + offset);
200 
201  DPRINTF(Loader, "Boot atags was %d bytes in total\n", size << 2);
202  DDUMP(Loader, boot_data, size << 2);
203 
204  physProxy.writeBlob(params()->atags_addr + loadAddrOffset, boot_data,
205  size << 2);
206 
207  delete[] boot_data;
208  }
209 
210  // Kernel boot requirements to set up r0, r1 and r2 in ARMv7
211  for (int i = 0; i < threadContexts.size(); i++) {
212  threadContexts[i]->setIntReg(0, 0);
213  threadContexts[i]->setIntReg(1, params()->machine_type);
214  threadContexts[i]->setIntReg(2, params()->atags_addr + loadAddrOffset);
215  }
216 }
217 
219 {
220  if (uDelaySkipEvent)
221  delete uDelaySkipEvent;
223  delete constUDelaySkipEvent;
224 
225  if (dumpStatsPCEvent)
226  delete dumpStatsPCEvent;
227 }
228 
230 LinuxArmSystemParams::create()
231 {
232  return new LinuxArmSystem(this);
233 }
234 
235 void
237 {
239  dumpStatsPCEvent = addKernelFuncEvent<DumpStatsPCEvent>("__switch_to");
240  if (!dumpStatsPCEvent)
241  panic("dumpStatsPCEvent not created!");
242 
243  std::string task_filename = "tasks.txt";
244  taskFile = simout.create(name() + "." + task_filename);
245 
246  for (int i = 0; i < _numContexts; i++) {
248  uint32_t pid = tc->getCpuPtr()->getPid();
249  if (pid != BaseCPU::invldPid) {
250  mapPid(tc, pid);
251  tc->getCpuPtr()->taskId(taskMap[pid]);
252  }
253  }
254  }
255 }
256 
257 void
259 {
260  // Create a new unique identifier for this pid
261  std::map<uint32_t, uint32_t>::iterator itr = taskMap.find(pid);
262  if (itr == taskMap.end()) {
263  uint32_t map_size = taskMap.size();
264  if (map_size > ContextSwitchTaskId::MaxNormalTaskId + 1) {
265  warn_once("Error out of identifiers for cache occupancy stats");
267  } else {
268  taskMap[pid] = map_size;
269  }
270  }
271 }
272 
273 void
275 {
276  Linux::dumpDmesg(getThreadContext(0), std::cout);
277 }
278 
286 void
288 {
289  Linux::ThreadInfo ti(tc);
290  Addr task_descriptor = tc->readIntReg(2);
291  uint32_t pid = ti.curTaskPID(task_descriptor);
292  uint32_t tgid = ti.curTaskTGID(task_descriptor);
293  std::string next_task_str = ti.curTaskName(task_descriptor);
294 
295  // Streamline treats pid == -1 as the kernel process.
296  // Also pid == 0 implies idle process (except during Linux boot)
297  int32_t mm = ti.curTaskMm(task_descriptor);
298  bool is_kernel = (mm == 0);
299  if (is_kernel && (pid != 0)) {
300  pid = -1;
301  tgid = -1;
302  next_task_str = "kernel";
303  }
304 
305  LinuxArmSystem* sys = dynamic_cast<LinuxArmSystem *>(tc->getSystemPtr());
306  if (!sys) {
307  panic("System is not LinuxArmSystem while getting Linux process info!");
308  }
309  std::map<uint32_t, uint32_t>& taskMap = sys->taskMap;
310 
311  // Create a new unique identifier for this pid
312  sys->mapPid(tc, pid);
313 
314  // Set cpu task id, output process info, and dump stats
315  tc->getCpuPtr()->taskId(taskMap[pid]);
316  tc->getCpuPtr()->setPid(pid);
317 
318  OutputStream* taskFile = sys->taskFile;
319 
320  // Task file is read by cache occupancy plotting script or
321  // Streamline conversion script.
322  ccprintf(*(taskFile->stream()),
323  "tick=%lld %d cpu_id=%d next_pid=%d next_tgid=%d next_task=%s\n",
324  curTick(), taskMap[pid], tc->cpuId(), (int) pid, (int) tgid,
325  next_task_str);
326  taskFile->stream()->flush();
327 
328  // Dump and reset statistics
329  Stats::schedStatEvent(true, true, curTick(), 0);
330 }
331 
uint32_t size() const
Definition: atag.hh:69
void ccprintf(cp::Print &print)
Definition: cprintf.hh:130
#define DPRINTF(x,...)
Definition: trace.hh:212
OutputDirectory simout
Definition: output.cc:65
std::ostream * stream() const
Get the output underlying output stream.
Definition: output.hh:64
virtual System * getSystemPtr()=0
virtual void initState()
Initialise the system.
Definition: system.cc:270
Bitfield< 7 > i
Definition: miscregs.hh:1378
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
#define panic(...)
Definition: misc.hh:153
void startup()
startup() is the final initialization call before simulation.
Definition: system.cc:236
virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr base=0, Addr offset=0, Addr mask=maxAddr)=0
void dumpDmesg(ThreadContext *tc, std::ostream &os)
Dump Linux's dmesg log buffer to the an output stream.
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
int _numContexts
Definition: system.hh:200
ip6_addr_t addr
Definition: inet.hh:335
#define DDUMP(x, data, count)
Definition: trace.hh:211
Definition: atag.hh:91
PhysicalMemory physmem
Definition: system.hh:307
#define warn_once(...)
Definition: misc.hh:226
void pagesize(uint32_t i)
Definition: atag.hh:98
void dumpDmesg()
Dump the kernel's dmesg buffer to stdout.
Definition: system.cc:274
SymbolTable * debugSymbolTable
Global unified debugging symbol table (for target).
Definition: symtab.cc:45
This implements an object file format to support loading and modifying flattened device tree blobs fo...
Bitfield< 23, 0 > offset
Definition: types.hh:149
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
bool findAddress(const std::string &symbol, Addr &address) const
Definition: symtab.hh:97
Bitfield< 30 > ti
void memStart(uint32_t i)
Definition: atag.hh:112
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...
#define warn(...)
Definition: misc.hh:219
LinuxArmSystem(Params *p)
Definition: system.cc:65
PortProxy physProxy
Port to physical memory used for writing object files into ram at boot.
Definition: system.hh:224
Tick curTick()
The current simulated tick.
Definition: core.hh:47
DumpStatsPCEvent * dumpStatsPCEvent
Definition: system.hh:62
virtual uint64_t readIntReg(int reg_idx)=0
Bitfield< 18 > ac
Definition: misc.hh:562
This class encapsulates the types, structures, constants, functions, and syscall-number mappings spec...
Definition: linux.hh:48
AddrRangeList getConfAddrRanges() const
Get the memory ranges for all memories that are to be reported to the configuration table...
Definition: physical.cc:256
void initState()
Initialise the system.
Definition: system.cc:106
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:247
void rootdev(uint32_t i)
Definition: atag.hh:99
const Params * params() const
Definition: system.hh:68
std::vector< ThreadContext * > threadContexts
Definition: system.hh:199
#define fatal(...)
Definition: misc.hh:163
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:287
void cmdline(const std::string &s)
Definition: atag.hh:149
Definition: atag.hh:105
ThreadContext * getThreadContext(ContextID tid)
Definition: system.hh:203
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
virtual bool loadSections(PortProxy &mem_proxy, Addr mask=maxAddr, Addr offset=0)
Definition: object_file.cc:93
uint32_t copyOut(uint8_t *p)
Definition: atag.hh:82
SymbolTable * kernelSymtab
kernel symbol table
Definition: system.hh:227
ObjectFile * kernel
Object pointer for the kernel code.
Definition: system.hh:230
int size()
Definition: pagetable.hh:146
virtual const std::string name() const
Definition: sim_object.hh:117
int32_t curTaskPID(Addr thread_info=0)
Definition: threadinfo.hh:112
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_object.cc:87
ObjectFile * createObjectFile(const string &fname, bool raw)
Definition: object_file.cc:157
int32_t curTaskMm(Addr thread_info=0)
Definition: threadinfo.hh:171
virtual void writeBlob(Addr addr, const uint8_t *p, int size) const
Write size bytes from p to address.
Definition: port_proxy.cc:58
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:153
void schedStatEvent(bool dump, bool reset, Tick when, Tick repeat)
Schedule statistics dumping.
Bitfield< 7, 6 > mm
Definition: miscregs.hh:132
void setTextBase(Addr a)
Definition: object_file.hh:151
PCEvent * kernelOopsEvent
Event to halt the simulator if the kernel calls oopses.
Definition: system.hh:109
void memSize(uint32_t i)
Definition: atag.hh:111
Addr loadAddrOffset
Offset that should be used for binary/symbol loading.
Definition: system.hh:254
int32_t curTaskTGID(Addr thread_info=0)
Definition: threadinfo.hh:125
#define inform(...)
Definition: misc.hh:221
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
void mapPid(ThreadContext *tc, uint32_t pid)
This function creates a new task Id for the given pid.
Definition: system.cc:258

Generated on Fri Jun 9 2017 13:03:34 for gem5 by doxygen 1.8.6