process.cc (4793:315e1db6bd39) process.cc (4997:e7380529bd2d)
1/*
2 * Copyright (c) 2003-2004 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Gabe Black
29 * Ali Saidi
30 */
31
32#include "arch/sparc/asi.hh"
33#include "arch/sparc/handlers.hh"
34#include "arch/sparc/isa_traits.hh"
35#include "arch/sparc/process.hh"
36#include "arch/sparc/types.hh"
37#include "base/loader/object_file.hh"
38#include "base/loader/elf_object.hh"
39#include "base/misc.hh"
40#include "cpu/thread_context.hh"
41#include "mem/page_table.hh"
42#include "sim/process_impl.hh"
43#include "mem/translating_port.hh"
44#include "sim/system.hh"
45
46using namespace std;
47using namespace SparcISA;
48
49
50SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile,
51 System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
52 std::vector<std::string> &argv, std::vector<std::string> &envp,
53 const std::string &cwd,
54 uint64_t _uid, uint64_t _euid, uint64_t _gid, uint64_t _egid,
55 uint64_t _pid, uint64_t _ppid)
56 : LiveProcess(nm, objFile, _system, stdin_fd, stdout_fd, stderr_fd,
57 argv, envp, cwd, _uid, _euid, _gid, _egid, _pid, _ppid)
58{
59
60 // XXX all the below need to be updated for SPARC - Ali
61 brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
62 brk_point = roundUp(brk_point, VMPageSize);
63
64 // Set pointer for next thread stack. Reserve 8M for main stack.
65 next_thread_stack_base = stack_base - (8 * 1024 * 1024);
66
67 //Initialize these to 0s
68 fillStart = 0;
69 spillStart = 0;
70}
71
72void SparcLiveProcess::handleTrap(int trapNum, ThreadContext *tc)
73{
74 switch(trapNum)
75 {
76 case 0x03: //Flush window trap
77 warn("Ignoring request to flush register windows.\n");
78 break;
79 default:
80 panic("Unimplemented trap to operating system: trap number %#x.\n", trapNum);
81 }
82}
83
84void
85Sparc32LiveProcess::startup()
86{
87 argsInit(32 / 8, VMPageSize);
88
89 //From the SPARC ABI
90
91 //The process runs in user mode with 32 bit addresses
92 threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x0a);
93
94 //Setup default FP state
95 threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0);
96
97 threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0);
98 //
99 /*
100 * Register window management registers
101 */
102
103 //No windows contain info from other programs
104 //threadContexts[0]->setMiscRegNoEffect(MISCREG_OTHERWIN, 0);
105 threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0);
106 //There are no windows to pop
107 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANRESTORE, 0);
108 threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0);
109 //All windows are available to save into
110 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2);
111 threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2);
112 //All windows are "clean"
113 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows);
114 threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows);
115 //Start with register window 0
116 threadContexts[0]->setMiscRegNoEffect(MISCREG_CWP, 0);
117 //Always use spill and fill traps 0
118 //threadContexts[0]->setMiscRegNoEffect(MISCREG_WSTATE, 0);
119 threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0);
120 //Set the trap level to 0
121 threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0);
122 //Set the ASI register to something fixed
123 threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY);
1/*
2 * Copyright (c) 2003-2004 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Gabe Black
29 * Ali Saidi
30 */
31
32#include "arch/sparc/asi.hh"
33#include "arch/sparc/handlers.hh"
34#include "arch/sparc/isa_traits.hh"
35#include "arch/sparc/process.hh"
36#include "arch/sparc/types.hh"
37#include "base/loader/object_file.hh"
38#include "base/loader/elf_object.hh"
39#include "base/misc.hh"
40#include "cpu/thread_context.hh"
41#include "mem/page_table.hh"
42#include "sim/process_impl.hh"
43#include "mem/translating_port.hh"
44#include "sim/system.hh"
45
46using namespace std;
47using namespace SparcISA;
48
49
50SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile,
51 System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
52 std::vector<std::string> &argv, std::vector<std::string> &envp,
53 const std::string &cwd,
54 uint64_t _uid, uint64_t _euid, uint64_t _gid, uint64_t _egid,
55 uint64_t _pid, uint64_t _ppid)
56 : LiveProcess(nm, objFile, _system, stdin_fd, stdout_fd, stderr_fd,
57 argv, envp, cwd, _uid, _euid, _gid, _egid, _pid, _ppid)
58{
59
60 // XXX all the below need to be updated for SPARC - Ali
61 brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
62 brk_point = roundUp(brk_point, VMPageSize);
63
64 // Set pointer for next thread stack. Reserve 8M for main stack.
65 next_thread_stack_base = stack_base - (8 * 1024 * 1024);
66
67 //Initialize these to 0s
68 fillStart = 0;
69 spillStart = 0;
70}
71
72void SparcLiveProcess::handleTrap(int trapNum, ThreadContext *tc)
73{
74 switch(trapNum)
75 {
76 case 0x03: //Flush window trap
77 warn("Ignoring request to flush register windows.\n");
78 break;
79 default:
80 panic("Unimplemented trap to operating system: trap number %#x.\n", trapNum);
81 }
82}
83
84void
85Sparc32LiveProcess::startup()
86{
87 argsInit(32 / 8, VMPageSize);
88
89 //From the SPARC ABI
90
91 //The process runs in user mode with 32 bit addresses
92 threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x0a);
93
94 //Setup default FP state
95 threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0);
96
97 threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0);
98 //
99 /*
100 * Register window management registers
101 */
102
103 //No windows contain info from other programs
104 //threadContexts[0]->setMiscRegNoEffect(MISCREG_OTHERWIN, 0);
105 threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0);
106 //There are no windows to pop
107 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANRESTORE, 0);
108 threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0);
109 //All windows are available to save into
110 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2);
111 threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2);
112 //All windows are "clean"
113 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows);
114 threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows);
115 //Start with register window 0
116 threadContexts[0]->setMiscRegNoEffect(MISCREG_CWP, 0);
117 //Always use spill and fill traps 0
118 //threadContexts[0]->setMiscRegNoEffect(MISCREG_WSTATE, 0);
119 threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0);
120 //Set the trap level to 0
121 threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0);
122 //Set the ASI register to something fixed
123 threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY);
124
125 /*
126 * T1 specific registers
127 */
128 //Turn on the icache, dcache, dtb translation, and itb translation.
129 threadContexts[0]->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15);
124}
125
126void
127Sparc64LiveProcess::startup()
128{
129 argsInit(sizeof(IntReg), VMPageSize);
130
131 //From the SPARC ABI
132
133 //The process runs in user mode
134 threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x02);
135
136 //Setup default FP state
137 threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0);
138
139 threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0);
130}
131
132void
133Sparc64LiveProcess::startup()
134{
135 argsInit(sizeof(IntReg), VMPageSize);
136
137 //From the SPARC ABI
138
139 //The process runs in user mode
140 threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x02);
141
142 //Setup default FP state
143 threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0);
144
145 threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0);
140 //
146
141 /*
142 * Register window management registers
143 */
144
145 //No windows contain info from other programs
146 //threadContexts[0]->setMiscRegNoEffect(MISCREG_OTHERWIN, 0);
147 threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0);
148 //There are no windows to pop
149 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANRESTORE, 0);
150 threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0);
151 //All windows are available to save into
152 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2);
153 threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2);
154 //All windows are "clean"
155 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows);
156 threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows);
157 //Start with register window 0
158 threadContexts[0]->setMiscRegNoEffect(MISCREG_CWP, 0);
159 //Always use spill and fill traps 0
160 //threadContexts[0]->setMiscRegNoEffect(MISCREG_WSTATE, 0);
161 threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0);
162 //Set the trap level to 0
163 threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0);
164 //Set the ASI register to something fixed
165 threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY);
147 /*
148 * Register window management registers
149 */
150
151 //No windows contain info from other programs
152 //threadContexts[0]->setMiscRegNoEffect(MISCREG_OTHERWIN, 0);
153 threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0);
154 //There are no windows to pop
155 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANRESTORE, 0);
156 threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0);
157 //All windows are available to save into
158 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2);
159 threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2);
160 //All windows are "clean"
161 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows);
162 threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows);
163 //Start with register window 0
164 threadContexts[0]->setMiscRegNoEffect(MISCREG_CWP, 0);
165 //Always use spill and fill traps 0
166 //threadContexts[0]->setMiscRegNoEffect(MISCREG_WSTATE, 0);
167 threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0);
168 //Set the trap level to 0
169 threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0);
170 //Set the ASI register to something fixed
171 threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY);
172
173 /*
174 * T1 specific registers
175 */
176 //Turn on the icache, dcache, dtb translation, and itb translation.
177 threadContexts[0]->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15);
166}
167
168M5_32_auxv_t::M5_32_auxv_t(int32_t type, int32_t val)
169{
170 a_type = TheISA::htog(type);
171 a_val = TheISA::htog(val);
172}
173
174M5_64_auxv_t::M5_64_auxv_t(int64_t type, int64_t val)
175{
176 a_type = TheISA::htog(type);
177 a_val = TheISA::htog(val);
178}
179
180void
181Sparc64LiveProcess::argsInit(int intSize, int pageSize)
182{
183 typedef M5_64_auxv_t auxv_t;
184 Process::startup();
185
186 string filename;
187 if(argv.size() < 1)
188 filename = "";
189 else
190 filename = argv[0];
191
192 Addr alignmentMask = ~(intSize - 1);
193
194 // load object file into target memory
195 objFile->loadSections(initVirtMem);
196
197 enum hardwareCaps
198 {
199 M5_HWCAP_SPARC_FLUSH = 1,
200 M5_HWCAP_SPARC_STBAR = 2,
201 M5_HWCAP_SPARC_SWAP = 4,
202 M5_HWCAP_SPARC_MULDIV = 8,
203 M5_HWCAP_SPARC_V9 = 16,
204 //This one should technically only be set
205 //if there is a cheetah or cheetah_plus tlb,
206 //but we'll use it all the time
207 M5_HWCAP_SPARC_ULTRA3 = 32
208 };
209
210 const int64_t hwcap =
211 M5_HWCAP_SPARC_FLUSH |
212 M5_HWCAP_SPARC_STBAR |
213 M5_HWCAP_SPARC_SWAP |
214 M5_HWCAP_SPARC_MULDIV |
215 M5_HWCAP_SPARC_V9 |
216 M5_HWCAP_SPARC_ULTRA3;
217
218
219 //Setup the auxilliary vectors. These will already have endian conversion.
220 //Auxilliary vectors are loaded only for elf formatted executables.
221 ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
222 if(elfObject)
223 {
224 //Bits which describe the system hardware capabilities
225 auxv.push_back(auxv_t(M5_AT_HWCAP, hwcap));
226 //The system page size
227 auxv.push_back(auxv_t(M5_AT_PAGESZ, SparcISA::VMPageSize));
228 //Defined to be 100 in the kernel source.
229 //Frequency at which times() increments
230 auxv.push_back(auxv_t(M5_AT_CLKTCK, 100));
231 // For statically linked executables, this is the virtual address of the
232 // program header tables if they appear in the executable image
233 auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable()));
234 // This is the size of a program header entry from the elf file.
235 auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize()));
236 // This is the number of program headers from the original elf file.
237 auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount()));
238 //This is the address of the elf "interpreter", It should be set
239 //to 0 for regular executables. It should be something else
240 //(not sure what) for dynamic libraries.
241 auxv.push_back(auxv_t(M5_AT_BASE, 0));
242 //This is hardwired to 0 in the elf loading code in the kernel
243 auxv.push_back(auxv_t(M5_AT_FLAGS, 0));
244 //The entry point to the program
245 auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint()));
246 //Different user and group IDs
247 auxv.push_back(auxv_t(M5_AT_UID, uid()));
248 auxv.push_back(auxv_t(M5_AT_EUID, euid()));
249 auxv.push_back(auxv_t(M5_AT_GID, gid()));
250 auxv.push_back(auxv_t(M5_AT_EGID, egid()));
251 //Whether to enable "secure mode" in the executable
252 auxv.push_back(auxv_t(M5_AT_SECURE, 0));
253 }
254
255 //Figure out how big the initial stack needs to be
256
257 // The unaccounted for 0 at the top of the stack
258 int mysterious_size = intSize;
259
260 //This is the name of the file which is present on the initial stack
261 //It's purpose is to let the user space linker examine the original file.
262 int file_name_size = filename.size() + 1;
263
264 int env_data_size = 0;
265 for (int i = 0; i < envp.size(); ++i) {
266 env_data_size += envp[i].size() + 1;
267 }
268 int arg_data_size = 0;
269 for (int i = 0; i < argv.size(); ++i) {
270 arg_data_size += argv[i].size() + 1;
271 }
272
273 //The info_block needs to be padded so it's size is a multiple of the
274 //alignment mask. Also, it appears that there needs to be at least some
275 //padding, so if the size is already a multiple, we need to increase it
276 //anyway.
277 int info_block_size =
278 (file_name_size +
279 env_data_size +
280 arg_data_size +
281 intSize) & alignmentMask;
282
283 int info_block_padding =
284 info_block_size -
285 file_name_size -
286 env_data_size -
287 arg_data_size;
288
289 //Each auxilliary vector is two 8 byte words
290 int aux_array_size = intSize * 2 * (auxv.size() + 1);
291
292 int envp_array_size = intSize * (envp.size() + 1);
293 int argv_array_size = intSize * (argv.size() + 1);
294
295 int argc_size = intSize;
296 int window_save_size = intSize * 16;
297
298 int space_needed =
299 mysterious_size +
300 info_block_size +
301 aux_array_size +
302 envp_array_size +
303 argv_array_size +
304 argc_size +
305 window_save_size;
306
307 stack_min = stack_base - space_needed;
308 stack_min &= alignmentMask;
309 stack_size = stack_base - stack_min;
310
311 // map memory
312 pTable->allocate(roundDown(stack_min, pageSize),
313 roundUp(stack_size, pageSize));
314
315 // map out initial stack contents
316 Addr mysterious_base = stack_base - mysterious_size;
317 Addr file_name_base = mysterious_base - file_name_size;
318 Addr env_data_base = file_name_base - env_data_size;
319 Addr arg_data_base = env_data_base - arg_data_size;
320 Addr auxv_array_base = arg_data_base - aux_array_size - info_block_padding;
321 Addr envp_array_base = auxv_array_base - envp_array_size;
322 Addr argv_array_base = envp_array_base - argv_array_size;
323 Addr argc_base = argv_array_base - argc_size;
324#ifndef NDEBUG
325 // only used in DPRINTF
326 Addr window_save_base = argc_base - window_save_size;
327#endif
328
329 DPRINTF(Sparc, "The addresses of items on the initial stack:\n");
330 DPRINTF(Sparc, "0x%x - file name\n", file_name_base);
331 DPRINTF(Sparc, "0x%x - env data\n", env_data_base);
332 DPRINTF(Sparc, "0x%x - arg data\n", arg_data_base);
333 DPRINTF(Sparc, "0x%x - auxv array\n", auxv_array_base);
334 DPRINTF(Sparc, "0x%x - envp array\n", envp_array_base);
335 DPRINTF(Sparc, "0x%x - argv array\n", argv_array_base);
336 DPRINTF(Sparc, "0x%x - argc \n", argc_base);
337 DPRINTF(Sparc, "0x%x - window save\n", window_save_base);
338 DPRINTF(Sparc, "0x%x - stack min\n", stack_min);
339
340 // write contents to stack
341
342 // figure out argc
343 uint64_t argc = argv.size();
344 uint64_t guestArgc = TheISA::htog(argc);
345
346 //Write out the mysterious 0
347 uint64_t mysterious_zero = 0;
348 initVirtMem->writeBlob(mysterious_base,
349 (uint8_t*)&mysterious_zero, mysterious_size);
350
351 //Write the file name
352 initVirtMem->writeString(file_name_base, filename.c_str());
353
354 //Copy the aux stuff
355 for(int x = 0; x < auxv.size(); x++)
356 {
357 initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize,
358 (uint8_t*)&(auxv[x].a_type), intSize);
359 initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize,
360 (uint8_t*)&(auxv[x].a_val), intSize);
361 }
362 //Write out the terminating zeroed auxilliary vector
363 const uint64_t zero = 0;
364 initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(),
365 (uint8_t*)&zero, 2 * intSize);
366
367 copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
368 copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
369
370 initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
371
372 //Stuff the trap handlers into the processes address space.
373 //Since the stack grows down and is the highest area in the processes
374 //address space, we can put stuff above it and stay out of the way.
375 int fillSize = sizeof(MachInst) * numFillInsts;
376 int spillSize = sizeof(MachInst) * numSpillInsts;
377 fillStart = stack_base;
378 spillStart = fillStart + fillSize;
379 initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler64, fillSize);
380 initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler64, spillSize);
381
382 //Set up the thread context to start running the process
383 assert(NumArgumentRegs >= 2);
384 threadContexts[0]->setIntReg(ArgumentReg[0], argc);
385 threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base);
386 threadContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias);
387
388 Addr prog_entry = objFile->entryPoint();
389 threadContexts[0]->setPC(prog_entry);
390 threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
391 threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
392
393 //Align the "stack_min" to a page boundary.
394 stack_min = roundDown(stack_min, pageSize);
395
396// num_processes++;
397}
398
399void
400Sparc32LiveProcess::argsInit(int intSize, int pageSize)
401{
402 typedef M5_32_auxv_t auxv_t;
403 Process::startup();
404
405 string filename;
406 if(argv.size() < 1)
407 filename = "";
408 else
409 filename = argv[0];
410
411 //Even though this is a 32 bit process, the ABI says we still need to
412 //maintain double word alignment of the stack pointer.
413 Addr alignmentMask = ~(8 - 1);
414
415 // load object file into target memory
416 objFile->loadSections(initVirtMem);
417
418 //These are the auxilliary vector types
419 enum auxTypes
420 {
421 SPARC_AT_HWCAP = 16,
422 SPARC_AT_PAGESZ = 6,
423 SPARC_AT_CLKTCK = 17,
424 SPARC_AT_PHDR = 3,
425 SPARC_AT_PHENT = 4,
426 SPARC_AT_PHNUM = 5,
427 SPARC_AT_BASE = 7,
428 SPARC_AT_FLAGS = 8,
429 SPARC_AT_ENTRY = 9,
430 SPARC_AT_UID = 11,
431 SPARC_AT_EUID = 12,
432 SPARC_AT_GID = 13,
433 SPARC_AT_EGID = 14,
434 SPARC_AT_SECURE = 23
435 };
436
437 enum hardwareCaps
438 {
439 M5_HWCAP_SPARC_FLUSH = 1,
440 M5_HWCAP_SPARC_STBAR = 2,
441 M5_HWCAP_SPARC_SWAP = 4,
442 M5_HWCAP_SPARC_MULDIV = 8,
443 M5_HWCAP_SPARC_V9 = 16,
444 //This one should technically only be set
445 //if there is a cheetah or cheetah_plus tlb,
446 //but we'll use it all the time
447 M5_HWCAP_SPARC_ULTRA3 = 32
448 };
449
450 const int64_t hwcap =
451 M5_HWCAP_SPARC_FLUSH |
452 M5_HWCAP_SPARC_STBAR |
453 M5_HWCAP_SPARC_SWAP |
454 M5_HWCAP_SPARC_MULDIV |
455 M5_HWCAP_SPARC_V9 |
456 M5_HWCAP_SPARC_ULTRA3;
457
458
459 //Setup the auxilliary vectors. These will already have endian conversion.
460 //Auxilliary vectors are loaded only for elf formatted executables.
461 ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
462 if(elfObject)
463 {
464 //Bits which describe the system hardware capabilities
465 auxv.push_back(auxv_t(SPARC_AT_HWCAP, hwcap));
466 //The system page size
467 auxv.push_back(auxv_t(SPARC_AT_PAGESZ, SparcISA::VMPageSize));
468 //Defined to be 100 in the kernel source.
469 //Frequency at which times() increments
470 auxv.push_back(auxv_t(SPARC_AT_CLKTCK, 100));
471 // For statically linked executables, this is the virtual address of the
472 // program header tables if they appear in the executable image
473 auxv.push_back(auxv_t(SPARC_AT_PHDR, elfObject->programHeaderTable()));
474 // This is the size of a program header entry from the elf file.
475 auxv.push_back(auxv_t(SPARC_AT_PHENT, elfObject->programHeaderSize()));
476 // This is the number of program headers from the original elf file.
477 auxv.push_back(auxv_t(SPARC_AT_PHNUM, elfObject->programHeaderCount()));
478 //This is the address of the elf "interpreter", It should be set
479 //to 0 for regular executables. It should be something else
480 //(not sure what) for dynamic libraries.
481 auxv.push_back(auxv_t(SPARC_AT_BASE, 0));
482 //This is hardwired to 0 in the elf loading code in the kernel
483 auxv.push_back(auxv_t(SPARC_AT_FLAGS, 0));
484 //The entry point to the program
485 auxv.push_back(auxv_t(SPARC_AT_ENTRY, objFile->entryPoint()));
486 //Different user and group IDs
487 auxv.push_back(auxv_t(SPARC_AT_UID, uid()));
488 auxv.push_back(auxv_t(SPARC_AT_EUID, euid()));
489 auxv.push_back(auxv_t(SPARC_AT_GID, gid()));
490 auxv.push_back(auxv_t(SPARC_AT_EGID, egid()));
491 //Whether to enable "secure mode" in the executable
492 auxv.push_back(auxv_t(SPARC_AT_SECURE, 0));
493 }
494
495 //Figure out how big the initial stack needs to be
496
497 // The unaccounted for 8 byte 0 at the top of the stack
498 int mysterious_size = 8;
499
500 //This is the name of the file which is present on the initial stack
501 //It's purpose is to let the user space linker examine the original file.
502 int file_name_size = filename.size() + 1;
503
504 int env_data_size = 0;
505 for (int i = 0; i < envp.size(); ++i) {
506 env_data_size += envp[i].size() + 1;
507 }
508 int arg_data_size = 0;
509 for (int i = 0; i < argv.size(); ++i) {
510 arg_data_size += argv[i].size() + 1;
511 }
512
513 //The info_block - This seems to need an pad for some reason.
514 int info_block_size =
515 (mysterious_size +
516 file_name_size +
517 env_data_size +
518 arg_data_size + intSize);
519
520 //Each auxilliary vector is two 4 byte words
521 int aux_array_size = intSize * 2 * (auxv.size() + 1);
522
523 int envp_array_size = intSize * (envp.size() + 1);
524 int argv_array_size = intSize * (argv.size() + 1);
525
526 int argc_size = intSize;
527 int window_save_size = intSize * 16;
528
529 int space_needed =
530 info_block_size +
531 aux_array_size +
532 envp_array_size +
533 argv_array_size +
534 argc_size +
535 window_save_size;
536
537 stack_min = stack_base - space_needed;
538 stack_min &= alignmentMask;
539 stack_size = stack_base - stack_min;
540
541 // map memory
542 pTable->allocate(roundDown(stack_min, pageSize),
543 roundUp(stack_size, pageSize));
544
545 // map out initial stack contents
546 uint32_t window_save_base = stack_min;
547 uint32_t argc_base = window_save_base + window_save_size;
548 uint32_t argv_array_base = argc_base + argc_size;
549 uint32_t envp_array_base = argv_array_base + argv_array_size;
550 uint32_t auxv_array_base = envp_array_base + envp_array_size;
551 //The info block is pushed up against the top of the stack, while
552 //the rest of the initial stack frame is aligned to an 8 byte boudary.
553 uint32_t arg_data_base = stack_base - info_block_size + intSize;
554 uint32_t env_data_base = arg_data_base + arg_data_size;
555 uint32_t file_name_base = env_data_base + env_data_size;
556 uint32_t mysterious_base = file_name_base + file_name_size;
557
558 DPRINTF(Sparc, "The addresses of items on the initial stack:\n");
559 DPRINTF(Sparc, "0x%x - file name\n", file_name_base);
560 DPRINTF(Sparc, "0x%x - env data\n", env_data_base);
561 DPRINTF(Sparc, "0x%x - arg data\n", arg_data_base);
562 DPRINTF(Sparc, "0x%x - auxv array\n", auxv_array_base);
563 DPRINTF(Sparc, "0x%x - envp array\n", envp_array_base);
564 DPRINTF(Sparc, "0x%x - argv array\n", argv_array_base);
565 DPRINTF(Sparc, "0x%x - argc \n", argc_base);
566 DPRINTF(Sparc, "0x%x - window save\n", window_save_base);
567 DPRINTF(Sparc, "0x%x - stack min\n", stack_min);
568
569 // write contents to stack
570
571 // figure out argc
572 uint32_t argc = argv.size();
573 uint32_t guestArgc = TheISA::htog(argc);
574
575 //Write out the mysterious 0
576 uint64_t mysterious_zero = 0;
577 initVirtMem->writeBlob(mysterious_base,
578 (uint8_t*)&mysterious_zero, mysterious_size);
579
580 //Write the file name
581 initVirtMem->writeString(file_name_base, filename.c_str());
582
583 //Copy the aux stuff
584 for(int x = 0; x < auxv.size(); x++)
585 {
586 initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize,
587 (uint8_t*)&(auxv[x].a_type), intSize);
588 initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize,
589 (uint8_t*)&(auxv[x].a_val), intSize);
590 }
591 //Write out the terminating zeroed auxilliary vector
592 const uint64_t zero = 0;
593 initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(),
594 (uint8_t*)&zero, 2 * intSize);
595
596 copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
597 copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
598
599 initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
600
601 //Stuff the trap handlers into the processes address space.
602 //Since the stack grows down and is the highest area in the processes
603 //address space, we can put stuff above it and stay out of the way.
604 int fillSize = sizeof(MachInst) * numFillInsts;
605 int spillSize = sizeof(MachInst) * numSpillInsts;
606 fillStart = stack_base;
607 spillStart = fillStart + fillSize;
608 initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler32, fillSize);
609 initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler32, spillSize);
610
611 //Set up the thread context to start running the process
612 //assert(NumArgumentRegs >= 2);
613 //threadContexts[0]->setIntReg(ArgumentReg[0], argc);
614 //threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base);
615 threadContexts[0]->setIntReg(StackPointerReg, stack_min);
616
617 uint32_t prog_entry = objFile->entryPoint();
618 threadContexts[0]->setPC(prog_entry);
619 threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
620 threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
621
622 //Align the "stack_min" to a page boundary.
623 stack_min = roundDown(stack_min, pageSize);
624
625// num_processes++;
626}
178}
179
180M5_32_auxv_t::M5_32_auxv_t(int32_t type, int32_t val)
181{
182 a_type = TheISA::htog(type);
183 a_val = TheISA::htog(val);
184}
185
186M5_64_auxv_t::M5_64_auxv_t(int64_t type, int64_t val)
187{
188 a_type = TheISA::htog(type);
189 a_val = TheISA::htog(val);
190}
191
192void
193Sparc64LiveProcess::argsInit(int intSize, int pageSize)
194{
195 typedef M5_64_auxv_t auxv_t;
196 Process::startup();
197
198 string filename;
199 if(argv.size() < 1)
200 filename = "";
201 else
202 filename = argv[0];
203
204 Addr alignmentMask = ~(intSize - 1);
205
206 // load object file into target memory
207 objFile->loadSections(initVirtMem);
208
209 enum hardwareCaps
210 {
211 M5_HWCAP_SPARC_FLUSH = 1,
212 M5_HWCAP_SPARC_STBAR = 2,
213 M5_HWCAP_SPARC_SWAP = 4,
214 M5_HWCAP_SPARC_MULDIV = 8,
215 M5_HWCAP_SPARC_V9 = 16,
216 //This one should technically only be set
217 //if there is a cheetah or cheetah_plus tlb,
218 //but we'll use it all the time
219 M5_HWCAP_SPARC_ULTRA3 = 32
220 };
221
222 const int64_t hwcap =
223 M5_HWCAP_SPARC_FLUSH |
224 M5_HWCAP_SPARC_STBAR |
225 M5_HWCAP_SPARC_SWAP |
226 M5_HWCAP_SPARC_MULDIV |
227 M5_HWCAP_SPARC_V9 |
228 M5_HWCAP_SPARC_ULTRA3;
229
230
231 //Setup the auxilliary vectors. These will already have endian conversion.
232 //Auxilliary vectors are loaded only for elf formatted executables.
233 ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
234 if(elfObject)
235 {
236 //Bits which describe the system hardware capabilities
237 auxv.push_back(auxv_t(M5_AT_HWCAP, hwcap));
238 //The system page size
239 auxv.push_back(auxv_t(M5_AT_PAGESZ, SparcISA::VMPageSize));
240 //Defined to be 100 in the kernel source.
241 //Frequency at which times() increments
242 auxv.push_back(auxv_t(M5_AT_CLKTCK, 100));
243 // For statically linked executables, this is the virtual address of the
244 // program header tables if they appear in the executable image
245 auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable()));
246 // This is the size of a program header entry from the elf file.
247 auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize()));
248 // This is the number of program headers from the original elf file.
249 auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount()));
250 //This is the address of the elf "interpreter", It should be set
251 //to 0 for regular executables. It should be something else
252 //(not sure what) for dynamic libraries.
253 auxv.push_back(auxv_t(M5_AT_BASE, 0));
254 //This is hardwired to 0 in the elf loading code in the kernel
255 auxv.push_back(auxv_t(M5_AT_FLAGS, 0));
256 //The entry point to the program
257 auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint()));
258 //Different user and group IDs
259 auxv.push_back(auxv_t(M5_AT_UID, uid()));
260 auxv.push_back(auxv_t(M5_AT_EUID, euid()));
261 auxv.push_back(auxv_t(M5_AT_GID, gid()));
262 auxv.push_back(auxv_t(M5_AT_EGID, egid()));
263 //Whether to enable "secure mode" in the executable
264 auxv.push_back(auxv_t(M5_AT_SECURE, 0));
265 }
266
267 //Figure out how big the initial stack needs to be
268
269 // The unaccounted for 0 at the top of the stack
270 int mysterious_size = intSize;
271
272 //This is the name of the file which is present on the initial stack
273 //It's purpose is to let the user space linker examine the original file.
274 int file_name_size = filename.size() + 1;
275
276 int env_data_size = 0;
277 for (int i = 0; i < envp.size(); ++i) {
278 env_data_size += envp[i].size() + 1;
279 }
280 int arg_data_size = 0;
281 for (int i = 0; i < argv.size(); ++i) {
282 arg_data_size += argv[i].size() + 1;
283 }
284
285 //The info_block needs to be padded so it's size is a multiple of the
286 //alignment mask. Also, it appears that there needs to be at least some
287 //padding, so if the size is already a multiple, we need to increase it
288 //anyway.
289 int info_block_size =
290 (file_name_size +
291 env_data_size +
292 arg_data_size +
293 intSize) & alignmentMask;
294
295 int info_block_padding =
296 info_block_size -
297 file_name_size -
298 env_data_size -
299 arg_data_size;
300
301 //Each auxilliary vector is two 8 byte words
302 int aux_array_size = intSize * 2 * (auxv.size() + 1);
303
304 int envp_array_size = intSize * (envp.size() + 1);
305 int argv_array_size = intSize * (argv.size() + 1);
306
307 int argc_size = intSize;
308 int window_save_size = intSize * 16;
309
310 int space_needed =
311 mysterious_size +
312 info_block_size +
313 aux_array_size +
314 envp_array_size +
315 argv_array_size +
316 argc_size +
317 window_save_size;
318
319 stack_min = stack_base - space_needed;
320 stack_min &= alignmentMask;
321 stack_size = stack_base - stack_min;
322
323 // map memory
324 pTable->allocate(roundDown(stack_min, pageSize),
325 roundUp(stack_size, pageSize));
326
327 // map out initial stack contents
328 Addr mysterious_base = stack_base - mysterious_size;
329 Addr file_name_base = mysterious_base - file_name_size;
330 Addr env_data_base = file_name_base - env_data_size;
331 Addr arg_data_base = env_data_base - arg_data_size;
332 Addr auxv_array_base = arg_data_base - aux_array_size - info_block_padding;
333 Addr envp_array_base = auxv_array_base - envp_array_size;
334 Addr argv_array_base = envp_array_base - argv_array_size;
335 Addr argc_base = argv_array_base - argc_size;
336#ifndef NDEBUG
337 // only used in DPRINTF
338 Addr window_save_base = argc_base - window_save_size;
339#endif
340
341 DPRINTF(Sparc, "The addresses of items on the initial stack:\n");
342 DPRINTF(Sparc, "0x%x - file name\n", file_name_base);
343 DPRINTF(Sparc, "0x%x - env data\n", env_data_base);
344 DPRINTF(Sparc, "0x%x - arg data\n", arg_data_base);
345 DPRINTF(Sparc, "0x%x - auxv array\n", auxv_array_base);
346 DPRINTF(Sparc, "0x%x - envp array\n", envp_array_base);
347 DPRINTF(Sparc, "0x%x - argv array\n", argv_array_base);
348 DPRINTF(Sparc, "0x%x - argc \n", argc_base);
349 DPRINTF(Sparc, "0x%x - window save\n", window_save_base);
350 DPRINTF(Sparc, "0x%x - stack min\n", stack_min);
351
352 // write contents to stack
353
354 // figure out argc
355 uint64_t argc = argv.size();
356 uint64_t guestArgc = TheISA::htog(argc);
357
358 //Write out the mysterious 0
359 uint64_t mysterious_zero = 0;
360 initVirtMem->writeBlob(mysterious_base,
361 (uint8_t*)&mysterious_zero, mysterious_size);
362
363 //Write the file name
364 initVirtMem->writeString(file_name_base, filename.c_str());
365
366 //Copy the aux stuff
367 for(int x = 0; x < auxv.size(); x++)
368 {
369 initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize,
370 (uint8_t*)&(auxv[x].a_type), intSize);
371 initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize,
372 (uint8_t*)&(auxv[x].a_val), intSize);
373 }
374 //Write out the terminating zeroed auxilliary vector
375 const uint64_t zero = 0;
376 initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(),
377 (uint8_t*)&zero, 2 * intSize);
378
379 copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
380 copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
381
382 initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
383
384 //Stuff the trap handlers into the processes address space.
385 //Since the stack grows down and is the highest area in the processes
386 //address space, we can put stuff above it and stay out of the way.
387 int fillSize = sizeof(MachInst) * numFillInsts;
388 int spillSize = sizeof(MachInst) * numSpillInsts;
389 fillStart = stack_base;
390 spillStart = fillStart + fillSize;
391 initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler64, fillSize);
392 initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler64, spillSize);
393
394 //Set up the thread context to start running the process
395 assert(NumArgumentRegs >= 2);
396 threadContexts[0]->setIntReg(ArgumentReg[0], argc);
397 threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base);
398 threadContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias);
399
400 Addr prog_entry = objFile->entryPoint();
401 threadContexts[0]->setPC(prog_entry);
402 threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
403 threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
404
405 //Align the "stack_min" to a page boundary.
406 stack_min = roundDown(stack_min, pageSize);
407
408// num_processes++;
409}
410
411void
412Sparc32LiveProcess::argsInit(int intSize, int pageSize)
413{
414 typedef M5_32_auxv_t auxv_t;
415 Process::startup();
416
417 string filename;
418 if(argv.size() < 1)
419 filename = "";
420 else
421 filename = argv[0];
422
423 //Even though this is a 32 bit process, the ABI says we still need to
424 //maintain double word alignment of the stack pointer.
425 Addr alignmentMask = ~(8 - 1);
426
427 // load object file into target memory
428 objFile->loadSections(initVirtMem);
429
430 //These are the auxilliary vector types
431 enum auxTypes
432 {
433 SPARC_AT_HWCAP = 16,
434 SPARC_AT_PAGESZ = 6,
435 SPARC_AT_CLKTCK = 17,
436 SPARC_AT_PHDR = 3,
437 SPARC_AT_PHENT = 4,
438 SPARC_AT_PHNUM = 5,
439 SPARC_AT_BASE = 7,
440 SPARC_AT_FLAGS = 8,
441 SPARC_AT_ENTRY = 9,
442 SPARC_AT_UID = 11,
443 SPARC_AT_EUID = 12,
444 SPARC_AT_GID = 13,
445 SPARC_AT_EGID = 14,
446 SPARC_AT_SECURE = 23
447 };
448
449 enum hardwareCaps
450 {
451 M5_HWCAP_SPARC_FLUSH = 1,
452 M5_HWCAP_SPARC_STBAR = 2,
453 M5_HWCAP_SPARC_SWAP = 4,
454 M5_HWCAP_SPARC_MULDIV = 8,
455 M5_HWCAP_SPARC_V9 = 16,
456 //This one should technically only be set
457 //if there is a cheetah or cheetah_plus tlb,
458 //but we'll use it all the time
459 M5_HWCAP_SPARC_ULTRA3 = 32
460 };
461
462 const int64_t hwcap =
463 M5_HWCAP_SPARC_FLUSH |
464 M5_HWCAP_SPARC_STBAR |
465 M5_HWCAP_SPARC_SWAP |
466 M5_HWCAP_SPARC_MULDIV |
467 M5_HWCAP_SPARC_V9 |
468 M5_HWCAP_SPARC_ULTRA3;
469
470
471 //Setup the auxilliary vectors. These will already have endian conversion.
472 //Auxilliary vectors are loaded only for elf formatted executables.
473 ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
474 if(elfObject)
475 {
476 //Bits which describe the system hardware capabilities
477 auxv.push_back(auxv_t(SPARC_AT_HWCAP, hwcap));
478 //The system page size
479 auxv.push_back(auxv_t(SPARC_AT_PAGESZ, SparcISA::VMPageSize));
480 //Defined to be 100 in the kernel source.
481 //Frequency at which times() increments
482 auxv.push_back(auxv_t(SPARC_AT_CLKTCK, 100));
483 // For statically linked executables, this is the virtual address of the
484 // program header tables if they appear in the executable image
485 auxv.push_back(auxv_t(SPARC_AT_PHDR, elfObject->programHeaderTable()));
486 // This is the size of a program header entry from the elf file.
487 auxv.push_back(auxv_t(SPARC_AT_PHENT, elfObject->programHeaderSize()));
488 // This is the number of program headers from the original elf file.
489 auxv.push_back(auxv_t(SPARC_AT_PHNUM, elfObject->programHeaderCount()));
490 //This is the address of the elf "interpreter", It should be set
491 //to 0 for regular executables. It should be something else
492 //(not sure what) for dynamic libraries.
493 auxv.push_back(auxv_t(SPARC_AT_BASE, 0));
494 //This is hardwired to 0 in the elf loading code in the kernel
495 auxv.push_back(auxv_t(SPARC_AT_FLAGS, 0));
496 //The entry point to the program
497 auxv.push_back(auxv_t(SPARC_AT_ENTRY, objFile->entryPoint()));
498 //Different user and group IDs
499 auxv.push_back(auxv_t(SPARC_AT_UID, uid()));
500 auxv.push_back(auxv_t(SPARC_AT_EUID, euid()));
501 auxv.push_back(auxv_t(SPARC_AT_GID, gid()));
502 auxv.push_back(auxv_t(SPARC_AT_EGID, egid()));
503 //Whether to enable "secure mode" in the executable
504 auxv.push_back(auxv_t(SPARC_AT_SECURE, 0));
505 }
506
507 //Figure out how big the initial stack needs to be
508
509 // The unaccounted for 8 byte 0 at the top of the stack
510 int mysterious_size = 8;
511
512 //This is the name of the file which is present on the initial stack
513 //It's purpose is to let the user space linker examine the original file.
514 int file_name_size = filename.size() + 1;
515
516 int env_data_size = 0;
517 for (int i = 0; i < envp.size(); ++i) {
518 env_data_size += envp[i].size() + 1;
519 }
520 int arg_data_size = 0;
521 for (int i = 0; i < argv.size(); ++i) {
522 arg_data_size += argv[i].size() + 1;
523 }
524
525 //The info_block - This seems to need an pad for some reason.
526 int info_block_size =
527 (mysterious_size +
528 file_name_size +
529 env_data_size +
530 arg_data_size + intSize);
531
532 //Each auxilliary vector is two 4 byte words
533 int aux_array_size = intSize * 2 * (auxv.size() + 1);
534
535 int envp_array_size = intSize * (envp.size() + 1);
536 int argv_array_size = intSize * (argv.size() + 1);
537
538 int argc_size = intSize;
539 int window_save_size = intSize * 16;
540
541 int space_needed =
542 info_block_size +
543 aux_array_size +
544 envp_array_size +
545 argv_array_size +
546 argc_size +
547 window_save_size;
548
549 stack_min = stack_base - space_needed;
550 stack_min &= alignmentMask;
551 stack_size = stack_base - stack_min;
552
553 // map memory
554 pTable->allocate(roundDown(stack_min, pageSize),
555 roundUp(stack_size, pageSize));
556
557 // map out initial stack contents
558 uint32_t window_save_base = stack_min;
559 uint32_t argc_base = window_save_base + window_save_size;
560 uint32_t argv_array_base = argc_base + argc_size;
561 uint32_t envp_array_base = argv_array_base + argv_array_size;
562 uint32_t auxv_array_base = envp_array_base + envp_array_size;
563 //The info block is pushed up against the top of the stack, while
564 //the rest of the initial stack frame is aligned to an 8 byte boudary.
565 uint32_t arg_data_base = stack_base - info_block_size + intSize;
566 uint32_t env_data_base = arg_data_base + arg_data_size;
567 uint32_t file_name_base = env_data_base + env_data_size;
568 uint32_t mysterious_base = file_name_base + file_name_size;
569
570 DPRINTF(Sparc, "The addresses of items on the initial stack:\n");
571 DPRINTF(Sparc, "0x%x - file name\n", file_name_base);
572 DPRINTF(Sparc, "0x%x - env data\n", env_data_base);
573 DPRINTF(Sparc, "0x%x - arg data\n", arg_data_base);
574 DPRINTF(Sparc, "0x%x - auxv array\n", auxv_array_base);
575 DPRINTF(Sparc, "0x%x - envp array\n", envp_array_base);
576 DPRINTF(Sparc, "0x%x - argv array\n", argv_array_base);
577 DPRINTF(Sparc, "0x%x - argc \n", argc_base);
578 DPRINTF(Sparc, "0x%x - window save\n", window_save_base);
579 DPRINTF(Sparc, "0x%x - stack min\n", stack_min);
580
581 // write contents to stack
582
583 // figure out argc
584 uint32_t argc = argv.size();
585 uint32_t guestArgc = TheISA::htog(argc);
586
587 //Write out the mysterious 0
588 uint64_t mysterious_zero = 0;
589 initVirtMem->writeBlob(mysterious_base,
590 (uint8_t*)&mysterious_zero, mysterious_size);
591
592 //Write the file name
593 initVirtMem->writeString(file_name_base, filename.c_str());
594
595 //Copy the aux stuff
596 for(int x = 0; x < auxv.size(); x++)
597 {
598 initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize,
599 (uint8_t*)&(auxv[x].a_type), intSize);
600 initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize,
601 (uint8_t*)&(auxv[x].a_val), intSize);
602 }
603 //Write out the terminating zeroed auxilliary vector
604 const uint64_t zero = 0;
605 initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(),
606 (uint8_t*)&zero, 2 * intSize);
607
608 copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
609 copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
610
611 initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
612
613 //Stuff the trap handlers into the processes address space.
614 //Since the stack grows down and is the highest area in the processes
615 //address space, we can put stuff above it and stay out of the way.
616 int fillSize = sizeof(MachInst) * numFillInsts;
617 int spillSize = sizeof(MachInst) * numSpillInsts;
618 fillStart = stack_base;
619 spillStart = fillStart + fillSize;
620 initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler32, fillSize);
621 initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler32, spillSize);
622
623 //Set up the thread context to start running the process
624 //assert(NumArgumentRegs >= 2);
625 //threadContexts[0]->setIntReg(ArgumentReg[0], argc);
626 //threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base);
627 threadContexts[0]->setIntReg(StackPointerReg, stack_min);
628
629 uint32_t prog_entry = objFile->entryPoint();
630 threadContexts[0]->setPC(prog_entry);
631 threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
632 threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
633
634 //Align the "stack_min" to a page boundary.
635 stack_min = roundDown(stack_min, pageSize);
636
637// num_processes++;
638}