arch-riscv: Stop "using namespace std"
[gem5.git] / src / arch / riscv / process.cc
1 /*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
3 * Copyright (c) 2016 The University of Virginia
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include "arch/riscv/process.hh"
31
32 #include <algorithm>
33 #include <cstddef>
34 #include <iostream>
35 #include <iterator>
36 #include <map>
37 #include <string>
38 #include <vector>
39
40 #include "arch/riscv/isa.hh"
41 #include "arch/riscv/isa_traits.hh"
42 #include "arch/riscv/registers.hh"
43 #include "base/loader/elf_object.hh"
44 #include "base/loader/object_file.hh"
45 #include "base/logging.hh"
46 #include "base/random.hh"
47 #include "cpu/thread_context.hh"
48 #include "debug/Stack.hh"
49 #include "mem/page_table.hh"
50 #include "params/Process.hh"
51 #include "sim/aux_vector.hh"
52 #include "sim/process.hh"
53 #include "sim/process_impl.hh"
54 #include "sim/syscall_return.hh"
55 #include "sim/system.hh"
56
57 using namespace RiscvISA;
58
59 RiscvProcess::RiscvProcess(const ProcessParams &params,
60 ::Loader::ObjectFile *objFile) :
61 Process(params,
62 new EmulationPageTable(params.name, params.pid, PageBytes),
63 objFile)
64 {
65 fatal_if(params.useArchPT, "Arch page tables not implemented.");
66 }
67
68 RiscvProcess64::RiscvProcess64(const ProcessParams &params,
69 ::Loader::ObjectFile *objFile) :
70 RiscvProcess(params, objFile)
71 {
72 const Addr stack_base = 0x7FFFFFFFFFFFFFFFL;
73 const Addr max_stack_size = 8 * 1024 * 1024;
74 const Addr next_thread_stack_base = stack_base - max_stack_size;
75 const Addr brk_point = roundUp(image.maxAddr(), PageBytes);
76 const Addr mmap_end = 0x4000000000000000L;
77 memState = std::make_shared<MemState>(this, brk_point, stack_base,
78 max_stack_size, next_thread_stack_base, mmap_end);
79 }
80
81 RiscvProcess32::RiscvProcess32(const ProcessParams &params,
82 ::Loader::ObjectFile *objFile) :
83 RiscvProcess(params, objFile)
84 {
85 const Addr stack_base = 0x7FFFFFFF;
86 const Addr max_stack_size = 8 * 1024 * 1024;
87 const Addr next_thread_stack_base = stack_base - max_stack_size;
88 const Addr brk_point = roundUp(image.maxAddr(), PageBytes);
89 const Addr mmap_end = 0x40000000L;
90 memState = std::make_shared<MemState>(this, brk_point, stack_base,
91 max_stack_size, next_thread_stack_base, mmap_end);
92 }
93
94 void
95 RiscvProcess64::initState()
96 {
97 Process::initState();
98
99 argsInit<uint64_t>(PageBytes);
100 for (ContextID ctx: contextIds)
101 system->threads[ctx]->setMiscRegNoEffect(MISCREG_PRV, PRV_U);
102 }
103
104 void
105 RiscvProcess32::initState()
106 {
107 Process::initState();
108
109 argsInit<uint32_t>(PageBytes);
110 for (ContextID ctx: contextIds) {
111 auto *tc = system->threads[ctx];
112 tc->setMiscRegNoEffect(MISCREG_PRV, PRV_U);
113 PCState pc = tc->pcState();
114 pc.rv32(true);
115 tc->pcState(pc);
116 }
117 }
118
119 template<class IntType> void
120 RiscvProcess::argsInit(int pageSize)
121 {
122 const int RandomBytes = 16;
123 const int addrSize = sizeof(IntType);
124
125 auto *elfObject = dynamic_cast<::Loader::ElfObject*>(objFile);
126 memState->setStackMin(memState->getStackBase());
127
128 // Determine stack size and populate auxv
129 Addr stack_top = memState->getStackMin();
130 stack_top -= RandomBytes;
131 for (const std::string& arg: argv)
132 stack_top -= arg.size() + 1;
133 for (const std::string& env: envp)
134 stack_top -= env.size() + 1;
135 stack_top &= -addrSize;
136
137 std::vector<AuxVector<IntType>> auxv;
138 if (elfObject != nullptr) {
139 auxv.emplace_back(M5_AT_ENTRY, objFile->entryPoint());
140 auxv.emplace_back(M5_AT_PHNUM, elfObject->programHeaderCount());
141 auxv.emplace_back(M5_AT_PHENT, elfObject->programHeaderSize());
142 auxv.emplace_back(M5_AT_PHDR, elfObject->programHeaderTable());
143 auxv.emplace_back(M5_AT_PAGESZ, PageBytes);
144 auxv.emplace_back(M5_AT_SECURE, 0);
145 auxv.emplace_back(M5_AT_RANDOM, stack_top);
146 auxv.emplace_back(M5_AT_NULL, 0);
147 }
148 stack_top -= (1 + argv.size()) * addrSize +
149 (1 + envp.size()) * addrSize +
150 addrSize + 2 * sizeof(IntType) * auxv.size();
151 stack_top &= -2*addrSize;
152 memState->setStackSize(memState->getStackBase() - stack_top);
153 memState->mapRegion(roundDown(stack_top, pageSize),
154 roundUp(memState->getStackSize(), pageSize), "stack");
155
156 // Copy random bytes (for AT_RANDOM) to stack
157 memState->setStackMin(memState->getStackMin() - RandomBytes);
158 uint8_t at_random[RandomBytes];
159 std::generate(std::begin(at_random), std::end(at_random),
160 [&]{ return random_mt.random(0, 0xFF); });
161 initVirtMem->writeBlob(memState->getStackMin(), at_random, RandomBytes);
162
163 // Copy argv to stack
164 std::vector<Addr> argPointers;
165 for (const std::string& arg: argv) {
166 memState->setStackMin(memState->getStackMin() - (arg.size() + 1));
167 initVirtMem->writeString(memState->getStackMin(), arg.c_str());
168 argPointers.push_back(memState->getStackMin());
169 if (DTRACE(Stack)) {
170 std::string wrote;
171 initVirtMem->readString(wrote, argPointers.back());
172 DPRINTFN("Wrote arg \"%s\" to address %p\n",
173 wrote, (void*)memState->getStackMin());
174 }
175 }
176 argPointers.push_back(0);
177
178 // Copy envp to stack
179 std::vector<Addr> envPointers;
180 for (const std::string& env: envp) {
181 memState->setStackMin(memState->getStackMin() - (env.size() + 1));
182 initVirtMem->writeString(memState->getStackMin(), env.c_str());
183 envPointers.push_back(memState->getStackMin());
184 DPRINTF(Stack, "Wrote env \"%s\" to address %p\n",
185 env, (void*)memState->getStackMin());
186 }
187 envPointers.push_back(0);
188
189 // Align stack
190 memState->setStackMin(memState->getStackMin() & -addrSize);
191
192 // Calculate bottom of stack
193 memState->setStackMin(memState->getStackMin() -
194 ((1 + argv.size()) * addrSize +
195 (1 + envp.size()) * addrSize +
196 addrSize + 2 * sizeof(IntType) * auxv.size()));
197 memState->setStackMin(memState->getStackMin() & (-2 * addrSize));
198 Addr sp = memState->getStackMin();
199 const auto pushOntoStack =
200 [this, &sp](IntType data) {
201 initVirtMem->write(sp, data, GuestByteOrder);
202 sp += sizeof(data);
203 };
204
205 // Push argc and argv pointers onto stack
206 IntType argc = argv.size();
207 DPRINTF(Stack, "Wrote argc %d to address %#x\n", argc, sp);
208 pushOntoStack(argc);
209
210 for (const Addr& argPointer: argPointers) {
211 DPRINTF(Stack, "Wrote argv pointer %#x to address %#x\n",
212 argPointer, sp);
213 pushOntoStack(argPointer);
214 }
215
216 // Push env pointers onto stack
217 for (const Addr& envPointer: envPointers) {
218 DPRINTF(Stack, "Wrote envp pointer %#x to address %#x\n",
219 envPointer, sp);
220 pushOntoStack(envPointer);
221 }
222
223 // Push aux vector onto stack
224 std::map<IntType, std::string> aux_keys = {
225 {M5_AT_ENTRY, "M5_AT_ENTRY"},
226 {M5_AT_PHNUM, "M5_AT_PHNUM"},
227 {M5_AT_PHENT, "M5_AT_PHENT"},
228 {M5_AT_PHDR, "M5_AT_PHDR"},
229 {M5_AT_PAGESZ, "M5_AT_PAGESZ"},
230 {M5_AT_SECURE, "M5_AT_SECURE"},
231 {M5_AT_RANDOM, "M5_AT_RANDOM"},
232 {M5_AT_NULL, "M5_AT_NULL"}
233 };
234 for (const auto &aux: auxv) {
235 DPRINTF(Stack, "Wrote aux key %s to address %#x\n",
236 aux_keys[aux.type], sp);
237 pushOntoStack(aux.type);
238 DPRINTF(Stack, "Wrote aux value %x to address %#x\n", aux.val, sp);
239 pushOntoStack(aux.val);
240 }
241
242 ThreadContext *tc = system->threads[contextIds[0]];
243 tc->setIntReg(StackPointerReg, memState->getStackMin());
244 tc->pcState(getStartPC());
245
246 memState->setStackMin(roundDown(memState->getStackMin(), pageSize));
247 }