gem5 v24.0.0.0
Loading...
Searching...
No Matches
fs_workload.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010-2013, 2016, 2020, 2023 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
42
44#include "arch/arm/system.hh"
45#include "arch/arm/utility.hh"
49#include "base/loader/symtab.hh"
50#include "cpu/base.hh"
51#include "cpu/pc_event.hh"
52#include "cpu/thread_context.hh"
53#include "debug/Loader.hh"
54#include "kern/linux/events.hh"
55#include "kern/linux/helpers.hh"
56#include "kern/system_events.hh"
57#include "mem/physical.hh"
58#include "sim/stat_control.hh"
59
60namespace gem5
61{
62
63using namespace linux;
64
65namespace ArmISA
66{
67
69 enableContextSwitchStatsDump(p.enable_context_switch_stats_dump)
70{}
71
72void
74{
76
77 // Load symbols at physical address, we might not want
78 // to do this permanently, for but early bootup work
79 // it is helpful.
80 if (params().early_kernel_symbols) {
81 auto phys_globals = kernelObj->symtab().globals()->mask(_loadAddrMask);
82 kernelSymtab.insert(*phys_globals);
83 loader::debugSymbolTable.insert(*phys_globals);
84 }
85
86 // Setup boot data structure
87 // Check if the kernel image has a symbol that tells us it supports
88 // device trees.
89 bool kernel_has_fdt_support =
90 kernelSymtab.find("unflatten_device_tree") != kernelSymtab.end();
91 bool dtb_file_specified = params().dtb_filename != "";
92
93 if (kernel_has_fdt_support && dtb_file_specified) {
94 bool initrd_file_specified = params().initrd_filename != "";
95 size_t initrd_len = 0;
96
97 if (initrd_file_specified) {
98 inform("Loading initrd file: %s at address %#x\n",
99 params().initrd_filename, params().initrd_addr);
100
101 loader::ImageFileDataPtr initrd_file_data(
102 new loader::ImageFileData(params().initrd_filename));
103 system->physProxy.writeBlob(params().initrd_addr,
104 initrd_file_data->data(),
105 initrd_file_data->len());
106 initrd_len = initrd_file_data->len();
107 }
108
109 // Kernel supports flattened device tree and dtb file specified.
110 // Using Device Tree Blob to describe system configuration.
111 inform("Loading DTB file: %s at address %#x\n", params().dtb_filename,
112 params().dtb_addr);
113
114 auto *dtb_file = new loader::DtbFile(params().dtb_filename);
115
116 if (!dtb_file->addBootData(commandLine.c_str(), commandLine.size(),
117 params().initrd_addr, initrd_len)) {
118 warn("couldn't append bootargs to DTB file: %s\n",
119 params().dtb_filename);
120 }
121
122 dtb_file->buildImage().offset(params().dtb_addr)
123 .write(system->physProxy);
124 delete dtb_file;
125 } else {
126 // Using ATAGS
127 // Warn if the kernel supports FDT and we haven't specified one
128 if (kernel_has_fdt_support) {
129 assert(!dtb_file_specified);
130 warn("Kernel supports device tree, but no DTB file specified\n");
131 }
132 // Warn if the kernel doesn't support FDT and we have specified one
133 if (dtb_file_specified) {
134 assert(!kernel_has_fdt_support);
135 warn("DTB file specified, but no device tree support in kernel\n");
136 }
137
138 AtagCore ac;
139 ac.flags(1); // read-only
140 ac.pagesize(8192);
141 ac.rootdev(0);
142
144 fatal_if(atagRanges.size() != 1,
145 "Expected a single ATAG memory entry but got %d",
146 atagRanges.size());
147 AtagMem am;
148 am.memSize(atagRanges.begin()->size());
149 am.memStart(atagRanges.begin()->start());
150
151 AtagCmdline ad;
153
154 DPRINTF(Loader, "boot command line %d bytes: %s\n",
155 ad.size() << 2, commandLine);
156
157 AtagNone an;
158
159 uint32_t size = ac.size() + am.size() + ad.size() + an.size();
160 uint32_t offset = 0;
161 uint8_t *boot_data = new uint8_t[size << 2];
162
163 offset += ac.copyOut(boot_data + offset);
164 offset += am.copyOut(boot_data + offset);
165 offset += ad.copyOut(boot_data + offset);
166 offset += an.copyOut(boot_data + offset);
167
168 DPRINTF(Loader, "Boot atags was %d bytes in total\n", size << 2);
169 DDUMP(Loader, boot_data, size << 2);
170
171 system->physProxy.writeBlob(params().dtb_addr,
172 boot_data, size << 2);
173
174 delete[] boot_data;
175 }
176
177 if (getArch() == loader::Arm64) {
178 // We inform the bootloader of the kernel entry point. This was added
179 // originally done because the entry offset changed in kernel v5.8.
180 // Previously the bootloader just used a hardcoded address.
181 for (auto *tc: system->threads) {
182 tc->setReg(int_reg::X0, params().dtb_addr);
183 tc->setReg(int_reg::X5, params().cpu_release_addr);
184 }
185 } else {
186 // Kernel boot requirements to set up r0, r1 and r2 in ARMv7
187 for (auto *tc: system->threads) {
188 tc->setReg(int_reg::R0, (RegVal)0);
189 tc->setReg(int_reg::R1, params().machine_type);
190 tc->setReg(int_reg::R2, params().dtb_addr);
191 }
192 }
193}
194
196{
197 delete debugPrintk;
198 delete skipUDelay;
199 delete skipConstUDelay;
200 delete kernelOops;
201 delete kernelPanic;
202
203 delete dumpStats;
204}
205
206void
208{
210
212 if (getArch() == loader::Arm64)
214 else
216
217 panic_if(!dumpStats, "dumpStats not created!");
218
219 std::string task_filename = "tasks.txt";
220 taskFile = simout.create(name() + "." + task_filename);
221
222 for (auto *tc: system->threads) {
223 uint32_t pid = tc->getCpuPtr()->getPid();
224 if (pid != BaseCPU::invldPid) {
225 mapPid(tc, pid);
226 tc->getCpuPtr()->taskId(taskMap[pid]);
227 }
228 }
229 }
230
231 const std::string dmesg_output_fname = name() + ".dmesg";
232
234 "panic", "Kernel panic in simulated kernel",
235 dmesg_output_fname, params().on_panic);
236 if (kernelPanic == nullptr) {
237 warn("Could not add Kernel Panic event handler. "
238 "`panic` symbol not found.");
239 }
240
242 "oops_exit", "Kernel oops in guest",
243 dmesg_output_fname, params().on_oops);
244 if (kernelOops == nullptr) {
245 warn("Could not add Kernel Oops event handler. "
246 "`oops_exit` symbol not found.");
247 }
248
249 // With ARM udelay() is #defined to __udelay
250 // newer kernels use __loop_udelay and __loop_const_udelay symbols
252 "__loop_udelay", "__udelay", 1000, 0);
253 if (!skipUDelay) {
255 "__udelay", "__udelay", 1000, 0);
256 }
257
258 // constant arguments to udelay() have some precomputation done ahead of
259 // time. Constant comes from code.
261 "__loop_const_udelay", "__const_udelay", 1000, 107374);
262 if (!skipConstUDelay) {
264 "__const_udelay", "__const_udelay", 1000, 107374);
265 }
266
268}
269
270void
272{
273 // Create a new unique identifier for this pid
274 std::map<uint32_t, uint32_t>::iterator itr = taskMap.find(pid);
275 if (itr == taskMap.end()) {
276 uint32_t map_size = taskMap.size();
277 if (map_size > context_switch_task_id::MaxNormalTaskId + 1) {
278 warn_once("Error out of identifiers for cache occupancy stats");
280 } else {
281 taskMap[pid] = map_size;
282 }
283 }
284}
285
286void
288{
289 linux::dumpDmesg(system->threads[0], std::cout);
290}
291
300void
302 uint32_t &tgid, std::string &next_task_str, int32_t &mm) {
303
305 Addr task_descriptor = tc->getReg(int_reg::R2);
306 pid = ti.curTaskPID(task_descriptor);
307 tgid = ti.curTaskTGID(task_descriptor);
308 next_task_str = ti.curTaskName(task_descriptor);
309
310 // Streamline treats pid == -1 as the kernel process.
311 // Also pid == 0 implies idle process (except during Linux boot)
312 mm = ti.curTaskMm(task_descriptor);
313}
314
322void
324 uint32_t &tgid, std::string &next_task_str, int32_t &mm) {
325
327 Addr task_struct = tc->getReg(int_reg::X1);
328 pid = ti.curTaskPIDFromTaskStruct(task_struct);
329 tgid = ti.curTaskTGIDFromTaskStruct(task_struct);
330 next_task_str = ti.curTaskNameFromTaskStruct(task_struct);
331
332 // Streamline treats pid == -1 as the kernel process.
333 // Also pid == 0 implies idle process (except during Linux boot)
334 mm = ti.curTaskMmFromTaskStruct(task_struct);
335}
336
340void
342{
343 uint32_t pid = 0;
344 uint32_t tgid = 0;
345 std::string next_task_str;
346 int32_t mm = 0;
347
348 getTaskDetails(tc, pid, tgid, next_task_str, mm);
349
350 bool is_kernel = (mm == 0);
351 if (is_kernel && (pid != 0)) {
352 pid = -1;
353 tgid = -1;
354 next_task_str = "kernel";
355 }
356
357 FsLinux* wl = dynamic_cast<FsLinux *>(tc->getSystemPtr()->workload);
358 panic_if(!wl, "System workload is not ARM Linux!");
359 std::map<uint32_t, uint32_t>& taskMap = wl->taskMap;
360
361 // Create a new unique identifier for this pid
362 wl->mapPid(tc, pid);
363
364 // Set cpu task id, output process info, and dump stats
365 tc->getCpuPtr()->taskId(taskMap[pid]);
366 tc->getCpuPtr()->setPid(pid);
367
368 OutputStream* taskFile = wl->taskFile;
369
370 // Task file is read by cache occupancy plotting script or
371 // Streamline conversion script.
372 ccprintf(*(taskFile->stream()),
373 "tick=%lld %d cpu_id=%d next_pid=%d next_tgid=%d next_task=%s\n",
374 curTick(), taskMap[pid], tc->cpuId(), (int)pid, (int)tgid,
375 next_task_str);
376 taskFile->stream()->flush();
377
378 // Dump and reset statistics
379 statistics::schedStatEvent(true, true, curTick(), 0);
380}
381
382} // namespace ArmISA
383} // namespace gem5
#define DDUMP(x, data, count)
DPRINTF is a debugging trace facility that allows one to selectively enable tracing statements.
Definition trace.hh:204
#define DPRINTF(x,...)
Definition trace.hh:210
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 ...
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 __...
void process(ThreadContext *tc) override
This function is called whenever the the kernel function "__switch_to" is called to change running ta...
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
PCEvent * kernelPanic
Event to halt the simulator if the kernel calls panic()
bool enableContextSwitchStatsDump
When enabled, dump stats/task info on context switches for Streamline and per-thread cache occupancy ...
std::map< uint32_t, uint32_t > taskMap
This map stores a mapping of OS process IDs to internal Task IDs.
FsLinux(const Params &p)
PCEvent * skipConstUDelay
Another PC based skip event for const_udelay().
PCEvent * debugPrintk
PC based event to skip the dprink() call and emulate its functionality.
void startup() override
startup() is the final initialization call before simulation.
OutputStream * taskFile
This is a file that is placed in the run directory that prints out mappings between taskIds and OS pr...
void dumpDmesg()
Dump the kernel's dmesg buffer to stdout.
PCEvent * kernelOops
Event to halt the simulator if the kernel calls oopses
PCEvent * skipUDelay
PC based event to skip udelay(<time>) calls and quiesce the processor for the appropriate amount of t...
void mapPid(ThreadContext *tc, uint32_t pid)
This function creates a new task Id for the given pid.
PCEvent * addSkipFuncOrPanic(Args... args)
loader::Arch getArch() const override
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
PCEvent * addSkipFunc(Args... args)
void cmdline(const std::string &s)
Definition atag.hh:151
void flags(uint32_t i)
Definition atag.hh:99
uint32_t size() const
Definition atag.hh:71
uint32_t copyOut(uint8_t *p)
Definition atag.hh:84
void memSize(uint32_t i)
Definition atag.hh:113
static const uint32_t invldPid
Invalid or unknown Pid.
Definition base.hh:269
uint32_t taskId() const
Get cpu task id.
Definition base.hh:211
void setPid(uint32_t pid)
Definition base.hh:216
loader::SymbolTable kernelSymtab
const std::string commandLine
loader::ObjectFile * kernelObj
T * addKernelFuncEvent(const char *lbl, Args... args)
Add a function-based event to a kernel symbol.
Addr _loadAddrMask
Mask that should be anded for binary/symbol loading.
virtual std::string name() const
Definition named.hh:47
OutputStream * create(const std::string &name, bool binary=false, bool no_gz=false)
Creates a file in this directory (optionally compressed).
Definition output.cc:210
std::ostream * stream() const
Get the output underlying output stream.
Definition output.hh:62
void writeBlob(Addr addr, const void *p, uint64_t size) const
Same as tryWriteBlob, but insists on success.
SimObjectParams Params
memory::PhysicalMemory & getPhysMem()
Get a pointer to access the physical memory of the system.
Definition system.hh:342
Workload * workload
OS kernel.
Definition system.hh:326
PortProxy physProxy
Port to physical memory used for writing object files into ram at boot.
Definition system.hh:323
Threads threads
Definition system.hh:310
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual RegVal getReg(const RegId &reg) const
virtual System * getSystemPtr()=0
virtual BaseCPU * getCpuPtr()=0
virtual int cpuId() const =0
System * system
Definition workload.hh:81
const SymbolTable & symtab() const
SymbolTablePtr globals() const
Generates a new symbol table containing only global symbols.
Definition symtab.hh:369
const_iterator end() const
Definition symtab.hh:278
bool insert(const Symbol &symbol)
Insert a new symbol in the table if it does not already exist.
Definition symtab.cc:66
const_iterator find(Addr address) const
Search for a symbol by its address.
Definition symtab.hh:435
AddrRangeList getConfAddrRanges() const
Get the memory ranges for all memories that are to be reported to the configuration table.
Definition physical.cc:279
Definition mm.h:9
This implements an image file format to support loading and modifying flattened device tree blobs for...
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:236
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:214
const Params & params() const
virtual void startup()
startup() is the final initialization call before simulation.
Definition sim_object.cc:96
#define warn(...)
Definition logging.hh:256
#define warn_once(...)
Definition logging.hh:260
#define inform(...)
Definition logging.hh:257
constexpr RegId X0
Definition int.hh:240
constexpr RegId X1
Definition int.hh:241
constexpr RegId R2
Definition int.hh:188
constexpr RegId R1
Definition int.hh:187
constexpr RegId X5
Definition int.hh:245
constexpr RegId R0
Definition int.hh:186
Bitfield< 23, 0 > offset
Definition types.hh:144
Bitfield< 0 > p
Bitfield< 30 > ti
Bitfield< 3 > am
Definition misc.hh:132
Bitfield< 18 > ac
Definition misc.hh:576
void dumpDmesg(ThreadContext *tc, std::ostream &os)
Dump Linux's dmesg log buffer to the an output stream.
Definition helpers.cc:780
SymbolTable debugSymbolTable
Global unified debugging symbol table (for target).
Definition symtab.cc:55
std::shared_ptr< ImageFileData > ImageFileDataPtr
void schedStatEvent(bool dump, bool reset, Tick when, Tick repeat)
Schedule statistics dumping.
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
uint64_t RegVal
Definition types.hh:173
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
OutputDirectory simout
Definition output.cc:62
void ccprintf(cp::Print &print)
Definition cprintf.hh:130

Generated on Tue Jun 18 2024 16:24:00 for gem5 by doxygen 1.11.0