53#include "debug/Loader.hh"
80 if (
params().early_kernel_symbols) {
89 bool kernel_has_fdt_support =
91 bool dtb_file_specified =
params().dtb_filename !=
"";
93 if (kernel_has_fdt_support && dtb_file_specified) {
94 bool initrd_file_specified =
params().initrd_filename !=
"";
95 size_t initrd_len = 0;
97 if (initrd_file_specified) {
98 inform(
"Loading initrd file: %s at address %#x\n",
104 initrd_file_data->data(),
105 initrd_file_data->len());
106 initrd_len = initrd_file_data->len();
111 inform(
"Loading DTB file: %s at address %#x\n",
params().dtb_filename,
117 params().initrd_addr, initrd_len)) {
118 warn(
"couldn't append bootargs to DTB file: %s\n",
122 dtb_file->buildImage().offset(
params().dtb_addr)
123 .write(
system->physProxy);
128 if (kernel_has_fdt_support) {
129 assert(!dtb_file_specified);
130 warn(
"Kernel supports device tree, but no DTB file specified\n");
133 if (dtb_file_specified) {
134 assert(!kernel_has_fdt_support);
135 warn(
"DTB file specified, but no device tree support in kernel\n");
145 "Expected a single ATAG memory entry but got %d",
148 am.memSize(atagRanges.begin()->size());
149 am.memStart(atagRanges.begin()->start());
154 DPRINTF(Loader,
"boot command line %d bytes: %s\n",
159 uint32_t size =
ac.size() +
am.size() + ad.
size() + an.
size();
161 uint8_t *boot_data =
new uint8_t[size << 2];
168 DPRINTF(Loader,
"Boot atags was %d bytes in total\n", size << 2);
169 DDUMP(Loader, boot_data, size << 2);
172 boot_data, size << 2);
181 for (
auto *tc:
system->threads) {
187 for (
auto *tc:
system->threads) {
219 std::string task_filename =
"tasks.txt";
222 for (
auto *tc:
system->threads) {
223 uint32_t pid = tc->getCpuPtr()->getPid();
226 tc->getCpuPtr()->taskId(
taskMap[pid]);
231 const std::string dmesg_output_fname =
name() +
".dmesg";
234 "panic",
"Kernel panic in simulated kernel",
235 dmesg_output_fname,
params().on_panic);
237 warn(
"Could not add Kernel Panic event handler. "
238 "`panic` symbol not found.");
242 "oops_exit",
"Kernel oops in guest",
243 dmesg_output_fname,
params().on_oops);
245 warn(
"Could not add Kernel Oops event handler. "
246 "`oops_exit` symbol not found.");
252 "__loop_udelay",
"__udelay", 1000, 0);
255 "__udelay",
"__udelay", 1000, 0);
261 "__loop_const_udelay",
"__const_udelay", 1000, 107374);
264 "__const_udelay",
"__const_udelay", 1000, 107374);
274 std::map<uint32_t, uint32_t>::iterator itr =
taskMap.find(pid);
276 uint32_t map_size =
taskMap.size();
278 warn_once(
"Error out of identifiers for cache occupancy stats");
302 uint32_t &tgid, std::string &next_task_str, int32_t &
mm) {
306 pid =
ti.curTaskPID(task_descriptor);
307 tgid =
ti.curTaskTGID(task_descriptor);
308 next_task_str =
ti.curTaskName(task_descriptor);
312 mm =
ti.curTaskMm(task_descriptor);
324 uint32_t &tgid, std::string &next_task_str, int32_t &
mm) {
328 pid =
ti.curTaskPIDFromTaskStruct(task_struct);
329 tgid =
ti.curTaskTGIDFromTaskStruct(task_struct);
330 next_task_str =
ti.curTaskNameFromTaskStruct(task_struct);
334 mm =
ti.curTaskMmFromTaskStruct(task_struct);
345 std::string next_task_str;
350 bool is_kernel = (
mm == 0);
351 if (is_kernel && (pid != 0)) {
354 next_task_str =
"kernel";
358 panic_if(!wl,
"System workload is not ARM Linux!");
359 std::map<uint32_t, uint32_t>& taskMap = wl->
taskMap;
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,
376 taskFile->
stream()->flush();
#define DDUMP(x, data, count)
DPRINTF is a debugging trace facility that allows one to selectively enable tracing statements.
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.
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.
FsWorkload(const Params &p)
PCEvent * addSkipFunc(Args... args)
void cmdline(const std::string &s)
static const uint32_t invldPid
Invalid or unknown Pid.
uint32_t taskId() const
Get cpu task id.
void setPid(uint32_t pid)
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
std::ostream * stream() const
Get the output underlying output stream.
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual RegVal getReg(const RegId ®) const
virtual System * getSystemPtr()=0
virtual BaseCPU * getCpuPtr()=0
virtual int cpuId() const =0
This implements an image file format to support loading and modifying flattened device tree blobs for...
std::list< AddrRange > AddrRangeList
Convenience typedef for a collection of address ranges.
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
const Params & params() const
virtual void startup()
startup() is the final initialization call before simulation.
void dumpDmesg(ThreadContext *tc, std::ostream &os)
Dump Linux's dmesg log buffer to the an output stream.
SymbolTable debugSymbolTable
Global unified debugging symbol table (for target).
std::shared_ptr< ImageFileData > ImageFileDataPtr
void schedStatEvent(bool dump, bool reset, Tick when, Tick repeat)
Schedule statistics dumping.
Copyright (c) 2024 Arm Limited All rights reserved.
Tick curTick()
The universal simulation clock.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
void ccprintf(cp::Print &print)