74f9fc7755cb5fa81c3ef3a7aa244ab1ea63b6eb
[gem5.git] / src / sim / kernel_workload.cc
1 /*
2 * Copyright 2019 Google Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met: redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer;
8 * redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution;
11 * neither the name of the copyright holders nor the names of its
12 * contributors may be used to endorse or promote products derived from
13 * this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include "sim/kernel_workload.hh"
29
30 #include "debug/Loader.hh"
31 #include "params/KernelWorkload.hh"
32 #include "sim/system.hh"
33
34 KernelWorkload::KernelWorkload(const Params &p) : Workload(&p), _params(p),
35 _loadAddrMask(p.load_addr_mask), _loadAddrOffset(p.load_addr_offset),
36 kernelSymtab(new Loader::SymbolTable), commandLine(p.command_line)
37 {
38 if (params().object_file == "") {
39 inform("No kernel set for full system simulation. "
40 "Assuming you know what you're doing.");
41 } else {
42 kernelObj = Loader::createObjectFile(params().object_file);
43 inform("kernel located at: %s", params().object_file);
44
45 fatal_if(!kernelObj,
46 "Could not load kernel file %s", params().object_file);
47
48 image = kernelObj->buildImage();
49
50 _start = image.minAddr();
51 _end = image.maxAddr();
52
53 // If load_addr_mask is set to 0x0, then calculate the smallest mask to
54 // cover all kernel addresses so gem5 can relocate the kernel to a new
55 // offset.
56 if (_loadAddrMask == 0)
57 _loadAddrMask = mask(findMsbSet(_end - _start) + 1);
58
59 image.move([this](Addr a) {
60 return (a & _loadAddrMask) + _loadAddrOffset;
61 });
62
63 // load symbols
64 fatal_if(!kernelObj->loadGlobalSymbols(kernelSymtab),
65 "Could not load kernel symbols.");
66
67 fatal_if(!kernelObj->loadLocalSymbols(kernelSymtab),
68 "Could not load kernel local symbols.");
69
70 fatal_if(!kernelObj->loadGlobalSymbols(&Loader::debugSymbolTable),
71 "Could not load kernel symbols.");
72
73 fatal_if(!kernelObj->loadLocalSymbols(&Loader::debugSymbolTable),
74 "Could not load kernel local symbols.");
75 }
76
77 // Loading only needs to happen once and after memory system is
78 // connected so it will happen in initState()
79
80 std::vector<Addr> extras_addrs = p.extras_addrs;
81 if (extras_addrs.empty())
82 extras_addrs.resize(p.extras.size(), MaxAddr);
83 fatal_if(p.extras.size() != extras_addrs.size(),
84 "Additional kernel objects, not all load addresses specified\n");
85 for (int ker_idx = 0; ker_idx < p.extras.size(); ker_idx++) {
86 const std::string &obj_name = p.extras[ker_idx];
87 const bool raw = extras_addrs[ker_idx] != MaxAddr;
88 auto *obj = Loader::createObjectFile(obj_name, raw);
89 fatal_if(!obj, "Failed to build additional kernel object '%s'.\n",
90 obj_name);
91 extras.push_back(obj);
92 }
93 }
94
95 KernelWorkload::~KernelWorkload()
96 {
97 delete kernelSymtab;
98 }
99
100 void
101 KernelWorkload::initState()
102 {
103 auto &phys_mem = system->physProxy;
104 /**
105 * Load the kernel code into memory.
106 */
107 auto mapper = [this](Addr a) {
108 return (a & _loadAddrMask) + _loadAddrOffset;
109 };
110 if (params().object_file != "") {
111 if (params().addr_check) {
112 // Validate kernel mapping before loading binary
113 fatal_if(!system->isMemAddr(mapper(_start)) ||
114 !system->isMemAddr(mapper(_end)),
115 "Kernel is mapped to invalid location (not memory). "
116 "start (%#x) - end (%#x) %#x:%#x\n",
117 _start, _end, mapper(_start), mapper(_end));
118 }
119 // Load program sections into memory
120 image.write(phys_mem);
121
122 DPRINTF(Loader, "Kernel start = %#x\n", _start);
123 DPRINTF(Loader, "Kernel end = %#x\n", _end);
124 DPRINTF(Loader, "Kernel entry = %#x\n", kernelObj->entryPoint());
125 DPRINTF(Loader, "Kernel loaded...\n");
126 }
127
128 std::vector<Addr> extras_addrs = params().extras_addrs;
129 if (extras_addrs.empty())
130 extras_addrs.resize(params().extras.size(), MaxAddr);
131 for (int idx = 0; idx < extras.size(); idx++) {
132 const Addr load_addr = extras_addrs[idx];
133 auto image = extras[idx]->buildImage();
134 if (load_addr != MaxAddr)
135 image = image.offset(load_addr);
136 else
137 image = image.move(mapper);
138 image.write(phys_mem);
139 }
140 }
141
142 void
143 KernelWorkload::serialize(CheckpointOut &cp) const
144 {
145 kernelSymtab->serialize("symtab", cp);
146 }
147
148 void
149 KernelWorkload::unserialize(CheckpointIn &cp)
150 {
151 kernelSymtab->unserialize("symtab", cp);
152 }
153
154 KernelWorkload *
155 KernelWorkloadParams::create()
156 {
157 return new KernelWorkload(*this);
158 }