Make the process objects use the Params structs in their constructors, and use a...
[gem5.git] / src / arch / sparc / process.cc
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
46 using namespace std;
47 using namespace SparcISA;
48
49
50 SparcLiveProcess::SparcLiveProcess(LiveProcessParams * params,
51 ObjectFile *objFile)
52 : LiveProcess(params, objFile)
53 {
54
55 // XXX all the below need to be updated for SPARC - Ali
56 brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
57 brk_point = roundUp(brk_point, VMPageSize);
58
59 // Set pointer for next thread stack. Reserve 8M for main stack.
60 next_thread_stack_base = stack_base - (8 * 1024 * 1024);
61
62 //Initialize these to 0s
63 fillStart = 0;
64 spillStart = 0;
65 }
66
67 void SparcLiveProcess::handleTrap(int trapNum, ThreadContext *tc)
68 {
69 switch(trapNum)
70 {
71 case 0x01: //Software breakpoint
72 warn("Software breakpoint encountered at pc %#x.\n", tc->readPC());
73 break;
74 case 0x02: //Division by zero
75 warn("Software signaled a division by zero at pc %#x.\n",
76 tc->readPC());
77 break;
78 case 0x03: //Flush window trap
79 flushWindows(tc);
80 break;
81 case 0x04: //Clean windows
82 warn("Ignoring process request for clean register "
83 "windows at pc %#x.\n", tc->readPC());
84 break;
85 case 0x05: //Range check
86 warn("Software signaled a range check at pc %#x.\n",
87 tc->readPC());
88 break;
89 case 0x06: //Fix alignment
90 warn("Ignoring process request for os assisted unaligned accesses "
91 "at pc %#x.\n", tc->readPC());
92 break;
93 case 0x07: //Integer overflow
94 warn("Software signaled an integer overflow at pc %#x.\n",
95 tc->readPC());
96 break;
97 case 0x32: //Get integer condition codes
98 warn("Ignoring process request to get the integer condition codes "
99 "at pc %#x.\n", tc->readPC());
100 break;
101 case 0x33: //Set integer condition codes
102 warn("Ignoring process request to set the integer condition codes "
103 "at pc %#x.\n", tc->readPC());
104 break;
105 default:
106 panic("Unimplemented trap to operating system: trap number %#x.\n", trapNum);
107 }
108 }
109
110 void
111 Sparc32LiveProcess::startup()
112 {
113 argsInit(32 / 8, VMPageSize);
114
115 //From the SPARC ABI
116
117 //The process runs in user mode with 32 bit addresses
118 threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x0a);
119
120 //Setup default FP state
121 threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0);
122
123 threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0);
124 //
125 /*
126 * Register window management registers
127 */
128
129 //No windows contain info from other programs
130 //threadContexts[0]->setMiscRegNoEffect(MISCREG_OTHERWIN, 0);
131 threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0);
132 //There are no windows to pop
133 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANRESTORE, 0);
134 threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0);
135 //All windows are available to save into
136 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2);
137 threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2);
138 //All windows are "clean"
139 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows);
140 threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows);
141 //Start with register window 0
142 threadContexts[0]->setMiscRegNoEffect(MISCREG_CWP, 0);
143 //Always use spill and fill traps 0
144 //threadContexts[0]->setMiscRegNoEffect(MISCREG_WSTATE, 0);
145 threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0);
146 //Set the trap level to 0
147 threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0);
148 //Set the ASI register to something fixed
149 threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY);
150
151 /*
152 * T1 specific registers
153 */
154 //Turn on the icache, dcache, dtb translation, and itb translation.
155 threadContexts[0]->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15);
156 }
157
158 void
159 Sparc64LiveProcess::startup()
160 {
161 argsInit(sizeof(IntReg), VMPageSize);
162
163 //From the SPARC ABI
164
165 //The process runs in user mode
166 threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x02);
167
168 //Setup default FP state
169 threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0);
170
171 threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0);
172
173 /*
174 * Register window management registers
175 */
176
177 //No windows contain info from other programs
178 //threadContexts[0]->setMiscRegNoEffect(MISCREG_OTHERWIN, 0);
179 threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0);
180 //There are no windows to pop
181 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANRESTORE, 0);
182 threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0);
183 //All windows are available to save into
184 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2);
185 threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2);
186 //All windows are "clean"
187 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows);
188 threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows);
189 //Start with register window 0
190 threadContexts[0]->setMiscRegNoEffect(MISCREG_CWP, 0);
191 //Always use spill and fill traps 0
192 //threadContexts[0]->setMiscRegNoEffect(MISCREG_WSTATE, 0);
193 threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0);
194 //Set the trap level to 0
195 threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0);
196 //Set the ASI register to something fixed
197 threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY);
198
199 /*
200 * T1 specific registers
201 */
202 //Turn on the icache, dcache, dtb translation, and itb translation.
203 threadContexts[0]->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15);
204 }
205
206 M5_32_auxv_t::M5_32_auxv_t(int32_t type, int32_t val)
207 {
208 a_type = TheISA::htog(type);
209 a_val = TheISA::htog(val);
210 }
211
212 M5_64_auxv_t::M5_64_auxv_t(int64_t type, int64_t val)
213 {
214 a_type = TheISA::htog(type);
215 a_val = TheISA::htog(val);
216 }
217
218 void
219 Sparc64LiveProcess::argsInit(int intSize, int pageSize)
220 {
221 typedef M5_64_auxv_t auxv_t;
222 Process::startup();
223
224 string filename;
225 if(argv.size() < 1)
226 filename = "";
227 else
228 filename = argv[0];
229
230 Addr alignmentMask = ~(intSize - 1);
231
232 // load object file into target memory
233 objFile->loadSections(initVirtMem);
234
235 enum hardwareCaps
236 {
237 M5_HWCAP_SPARC_FLUSH = 1,
238 M5_HWCAP_SPARC_STBAR = 2,
239 M5_HWCAP_SPARC_SWAP = 4,
240 M5_HWCAP_SPARC_MULDIV = 8,
241 M5_HWCAP_SPARC_V9 = 16,
242 //This one should technically only be set
243 //if there is a cheetah or cheetah_plus tlb,
244 //but we'll use it all the time
245 M5_HWCAP_SPARC_ULTRA3 = 32
246 };
247
248 const int64_t hwcap =
249 M5_HWCAP_SPARC_FLUSH |
250 M5_HWCAP_SPARC_STBAR |
251 M5_HWCAP_SPARC_SWAP |
252 M5_HWCAP_SPARC_MULDIV |
253 M5_HWCAP_SPARC_V9 |
254 M5_HWCAP_SPARC_ULTRA3;
255
256
257 //Setup the auxilliary vectors. These will already have endian conversion.
258 //Auxilliary vectors are loaded only for elf formatted executables.
259 ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
260 if(elfObject)
261 {
262 //Bits which describe the system hardware capabilities
263 auxv.push_back(auxv_t(M5_AT_HWCAP, hwcap));
264 //The system page size
265 auxv.push_back(auxv_t(M5_AT_PAGESZ, SparcISA::VMPageSize));
266 //Defined to be 100 in the kernel source.
267 //Frequency at which times() increments
268 auxv.push_back(auxv_t(M5_AT_CLKTCK, 100));
269 // For statically linked executables, this is the virtual address of the
270 // program header tables if they appear in the executable image
271 auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable()));
272 // This is the size of a program header entry from the elf file.
273 auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize()));
274 // This is the number of program headers from the original elf file.
275 auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount()));
276 //This is the address of the elf "interpreter", It should be set
277 //to 0 for regular executables. It should be something else
278 //(not sure what) for dynamic libraries.
279 auxv.push_back(auxv_t(M5_AT_BASE, 0));
280 //This is hardwired to 0 in the elf loading code in the kernel
281 auxv.push_back(auxv_t(M5_AT_FLAGS, 0));
282 //The entry point to the program
283 auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint()));
284 //Different user and group IDs
285 auxv.push_back(auxv_t(M5_AT_UID, uid()));
286 auxv.push_back(auxv_t(M5_AT_EUID, euid()));
287 auxv.push_back(auxv_t(M5_AT_GID, gid()));
288 auxv.push_back(auxv_t(M5_AT_EGID, egid()));
289 //Whether to enable "secure mode" in the executable
290 auxv.push_back(auxv_t(M5_AT_SECURE, 0));
291 }
292
293 //Figure out how big the initial stack needs to be
294
295 // The unaccounted for 0 at the top of the stack
296 int mysterious_size = intSize;
297
298 //This is the name of the file which is present on the initial stack
299 //It's purpose is to let the user space linker examine the original file.
300 int file_name_size = filename.size() + 1;
301
302 int env_data_size = 0;
303 for (int i = 0; i < envp.size(); ++i) {
304 env_data_size += envp[i].size() + 1;
305 }
306 int arg_data_size = 0;
307 for (int i = 0; i < argv.size(); ++i) {
308 arg_data_size += argv[i].size() + 1;
309 }
310
311 //The info_block needs to be padded so it's size is a multiple of the
312 //alignment mask. Also, it appears that there needs to be at least some
313 //padding, so if the size is already a multiple, we need to increase it
314 //anyway.
315 int info_block_size =
316 (file_name_size +
317 env_data_size +
318 arg_data_size +
319 intSize) & alignmentMask;
320
321 int info_block_padding =
322 info_block_size -
323 file_name_size -
324 env_data_size -
325 arg_data_size;
326
327 //Each auxilliary vector is two 8 byte words
328 int aux_array_size = intSize * 2 * (auxv.size() + 1);
329
330 int envp_array_size = intSize * (envp.size() + 1);
331 int argv_array_size = intSize * (argv.size() + 1);
332
333 int argc_size = intSize;
334 int window_save_size = intSize * 16;
335
336 int space_needed =
337 mysterious_size +
338 info_block_size +
339 aux_array_size +
340 envp_array_size +
341 argv_array_size +
342 argc_size +
343 window_save_size;
344
345 stack_min = stack_base - space_needed;
346 stack_min &= alignmentMask;
347 stack_size = stack_base - stack_min;
348
349 // map memory
350 pTable->allocate(roundDown(stack_min, pageSize),
351 roundUp(stack_size, pageSize));
352
353 // map out initial stack contents
354 Addr mysterious_base = stack_base - mysterious_size;
355 Addr file_name_base = mysterious_base - file_name_size;
356 Addr env_data_base = file_name_base - env_data_size;
357 Addr arg_data_base = env_data_base - arg_data_size;
358 Addr auxv_array_base = arg_data_base - aux_array_size - info_block_padding;
359 Addr envp_array_base = auxv_array_base - envp_array_size;
360 Addr argv_array_base = envp_array_base - argv_array_size;
361 Addr argc_base = argv_array_base - argc_size;
362 #ifndef NDEBUG
363 // only used in DPRINTF
364 Addr window_save_base = argc_base - window_save_size;
365 #endif
366
367 DPRINTF(Sparc, "The addresses of items on the initial stack:\n");
368 DPRINTF(Sparc, "0x%x - file name\n", file_name_base);
369 DPRINTF(Sparc, "0x%x - env data\n", env_data_base);
370 DPRINTF(Sparc, "0x%x - arg data\n", arg_data_base);
371 DPRINTF(Sparc, "0x%x - auxv array\n", auxv_array_base);
372 DPRINTF(Sparc, "0x%x - envp array\n", envp_array_base);
373 DPRINTF(Sparc, "0x%x - argv array\n", argv_array_base);
374 DPRINTF(Sparc, "0x%x - argc \n", argc_base);
375 DPRINTF(Sparc, "0x%x - window save\n", window_save_base);
376 DPRINTF(Sparc, "0x%x - stack min\n", stack_min);
377
378 // write contents to stack
379
380 // figure out argc
381 uint64_t argc = argv.size();
382 uint64_t guestArgc = TheISA::htog(argc);
383
384 //Write out the mysterious 0
385 uint64_t mysterious_zero = 0;
386 initVirtMem->writeBlob(mysterious_base,
387 (uint8_t*)&mysterious_zero, mysterious_size);
388
389 //Write the file name
390 initVirtMem->writeString(file_name_base, filename.c_str());
391
392 //Copy the aux stuff
393 for(int x = 0; x < auxv.size(); x++)
394 {
395 initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize,
396 (uint8_t*)&(auxv[x].a_type), intSize);
397 initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize,
398 (uint8_t*)&(auxv[x].a_val), intSize);
399 }
400 //Write out the terminating zeroed auxilliary vector
401 const uint64_t zero = 0;
402 initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(),
403 (uint8_t*)&zero, 2 * intSize);
404
405 copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
406 copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
407
408 initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
409
410 //Stuff the trap handlers into the processes address space.
411 //Since the stack grows down and is the highest area in the processes
412 //address space, we can put stuff above it and stay out of the way.
413 int fillSize = sizeof(MachInst) * numFillInsts;
414 int spillSize = sizeof(MachInst) * numSpillInsts;
415 fillStart = stack_base;
416 spillStart = fillStart + fillSize;
417 initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler64, fillSize);
418 initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler64, spillSize);
419
420 //Set up the thread context to start running the process
421 assert(NumArgumentRegs >= 2);
422 threadContexts[0]->setIntReg(ArgumentReg[0], argc);
423 threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base);
424 threadContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias);
425
426 Addr prog_entry = objFile->entryPoint();
427 threadContexts[0]->setPC(prog_entry);
428 threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
429 threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
430
431 //Align the "stack_min" to a page boundary.
432 stack_min = roundDown(stack_min, pageSize);
433
434 // num_processes++;
435 }
436
437 void
438 Sparc32LiveProcess::argsInit(int intSize, int pageSize)
439 {
440 typedef M5_32_auxv_t auxv_t;
441 Process::startup();
442
443 string filename;
444 if(argv.size() < 1)
445 filename = "";
446 else
447 filename = argv[0];
448
449 //Even though this is a 32 bit process, the ABI says we still need to
450 //maintain double word alignment of the stack pointer.
451 Addr alignmentMask = ~(8 - 1);
452
453 // load object file into target memory
454 objFile->loadSections(initVirtMem);
455
456 //These are the auxilliary vector types
457 enum auxTypes
458 {
459 SPARC_AT_HWCAP = 16,
460 SPARC_AT_PAGESZ = 6,
461 SPARC_AT_CLKTCK = 17,
462 SPARC_AT_PHDR = 3,
463 SPARC_AT_PHENT = 4,
464 SPARC_AT_PHNUM = 5,
465 SPARC_AT_BASE = 7,
466 SPARC_AT_FLAGS = 8,
467 SPARC_AT_ENTRY = 9,
468 SPARC_AT_UID = 11,
469 SPARC_AT_EUID = 12,
470 SPARC_AT_GID = 13,
471 SPARC_AT_EGID = 14,
472 SPARC_AT_SECURE = 23
473 };
474
475 enum hardwareCaps
476 {
477 M5_HWCAP_SPARC_FLUSH = 1,
478 M5_HWCAP_SPARC_STBAR = 2,
479 M5_HWCAP_SPARC_SWAP = 4,
480 M5_HWCAP_SPARC_MULDIV = 8,
481 M5_HWCAP_SPARC_V9 = 16,
482 //This one should technically only be set
483 //if there is a cheetah or cheetah_plus tlb,
484 //but we'll use it all the time
485 M5_HWCAP_SPARC_ULTRA3 = 32
486 };
487
488 const int64_t hwcap =
489 M5_HWCAP_SPARC_FLUSH |
490 M5_HWCAP_SPARC_STBAR |
491 M5_HWCAP_SPARC_SWAP |
492 M5_HWCAP_SPARC_MULDIV |
493 M5_HWCAP_SPARC_V9 |
494 M5_HWCAP_SPARC_ULTRA3;
495
496
497 //Setup the auxilliary vectors. These will already have endian conversion.
498 //Auxilliary vectors are loaded only for elf formatted executables.
499 ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
500 if(elfObject)
501 {
502 //Bits which describe the system hardware capabilities
503 auxv.push_back(auxv_t(SPARC_AT_HWCAP, hwcap));
504 //The system page size
505 auxv.push_back(auxv_t(SPARC_AT_PAGESZ, SparcISA::VMPageSize));
506 //Defined to be 100 in the kernel source.
507 //Frequency at which times() increments
508 auxv.push_back(auxv_t(SPARC_AT_CLKTCK, 100));
509 // For statically linked executables, this is the virtual address of the
510 // program header tables if they appear in the executable image
511 auxv.push_back(auxv_t(SPARC_AT_PHDR, elfObject->programHeaderTable()));
512 // This is the size of a program header entry from the elf file.
513 auxv.push_back(auxv_t(SPARC_AT_PHENT, elfObject->programHeaderSize()));
514 // This is the number of program headers from the original elf file.
515 auxv.push_back(auxv_t(SPARC_AT_PHNUM, elfObject->programHeaderCount()));
516 //This is the address of the elf "interpreter", It should be set
517 //to 0 for regular executables. It should be something else
518 //(not sure what) for dynamic libraries.
519 auxv.push_back(auxv_t(SPARC_AT_BASE, 0));
520 //This is hardwired to 0 in the elf loading code in the kernel
521 auxv.push_back(auxv_t(SPARC_AT_FLAGS, 0));
522 //The entry point to the program
523 auxv.push_back(auxv_t(SPARC_AT_ENTRY, objFile->entryPoint()));
524 //Different user and group IDs
525 auxv.push_back(auxv_t(SPARC_AT_UID, uid()));
526 auxv.push_back(auxv_t(SPARC_AT_EUID, euid()));
527 auxv.push_back(auxv_t(SPARC_AT_GID, gid()));
528 auxv.push_back(auxv_t(SPARC_AT_EGID, egid()));
529 //Whether to enable "secure mode" in the executable
530 auxv.push_back(auxv_t(SPARC_AT_SECURE, 0));
531 }
532
533 //Figure out how big the initial stack needs to be
534
535 // The unaccounted for 8 byte 0 at the top of the stack
536 int mysterious_size = 8;
537
538 //This is the name of the file which is present on the initial stack
539 //It's purpose is to let the user space linker examine the original file.
540 int file_name_size = filename.size() + 1;
541
542 int env_data_size = 0;
543 for (int i = 0; i < envp.size(); ++i) {
544 env_data_size += envp[i].size() + 1;
545 }
546 int arg_data_size = 0;
547 for (int i = 0; i < argv.size(); ++i) {
548 arg_data_size += argv[i].size() + 1;
549 }
550
551 //The info_block - This seems to need an pad for some reason.
552 int info_block_size =
553 (mysterious_size +
554 file_name_size +
555 env_data_size +
556 arg_data_size + intSize);
557
558 //Each auxilliary vector is two 4 byte words
559 int aux_array_size = intSize * 2 * (auxv.size() + 1);
560
561 int envp_array_size = intSize * (envp.size() + 1);
562 int argv_array_size = intSize * (argv.size() + 1);
563
564 int argc_size = intSize;
565 int window_save_size = intSize * 16;
566
567 int space_needed =
568 info_block_size +
569 aux_array_size +
570 envp_array_size +
571 argv_array_size +
572 argc_size +
573 window_save_size;
574
575 stack_min = stack_base - space_needed;
576 stack_min &= alignmentMask;
577 stack_size = stack_base - stack_min;
578
579 // map memory
580 pTable->allocate(roundDown(stack_min, pageSize),
581 roundUp(stack_size, pageSize));
582
583 // map out initial stack contents
584 uint32_t window_save_base = stack_min;
585 uint32_t argc_base = window_save_base + window_save_size;
586 uint32_t argv_array_base = argc_base + argc_size;
587 uint32_t envp_array_base = argv_array_base + argv_array_size;
588 uint32_t auxv_array_base = envp_array_base + envp_array_size;
589 //The info block is pushed up against the top of the stack, while
590 //the rest of the initial stack frame is aligned to an 8 byte boudary.
591 uint32_t arg_data_base = stack_base - info_block_size + intSize;
592 uint32_t env_data_base = arg_data_base + arg_data_size;
593 uint32_t file_name_base = env_data_base + env_data_size;
594 uint32_t mysterious_base = file_name_base + file_name_size;
595
596 DPRINTF(Sparc, "The addresses of items on the initial stack:\n");
597 DPRINTF(Sparc, "0x%x - file name\n", file_name_base);
598 DPRINTF(Sparc, "0x%x - env data\n", env_data_base);
599 DPRINTF(Sparc, "0x%x - arg data\n", arg_data_base);
600 DPRINTF(Sparc, "0x%x - auxv array\n", auxv_array_base);
601 DPRINTF(Sparc, "0x%x - envp array\n", envp_array_base);
602 DPRINTF(Sparc, "0x%x - argv array\n", argv_array_base);
603 DPRINTF(Sparc, "0x%x - argc \n", argc_base);
604 DPRINTF(Sparc, "0x%x - window save\n", window_save_base);
605 DPRINTF(Sparc, "0x%x - stack min\n", stack_min);
606
607 // write contents to stack
608
609 // figure out argc
610 uint32_t argc = argv.size();
611 uint32_t guestArgc = TheISA::htog(argc);
612
613 //Write out the mysterious 0
614 uint64_t mysterious_zero = 0;
615 initVirtMem->writeBlob(mysterious_base,
616 (uint8_t*)&mysterious_zero, mysterious_size);
617
618 //Write the file name
619 initVirtMem->writeString(file_name_base, filename.c_str());
620
621 //Copy the aux stuff
622 for(int x = 0; x < auxv.size(); x++)
623 {
624 initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize,
625 (uint8_t*)&(auxv[x].a_type), intSize);
626 initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize,
627 (uint8_t*)&(auxv[x].a_val), intSize);
628 }
629 //Write out the terminating zeroed auxilliary vector
630 const uint64_t zero = 0;
631 initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(),
632 (uint8_t*)&zero, 2 * intSize);
633
634 copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
635 copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
636
637 initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
638
639 //Stuff the trap handlers into the processes address space.
640 //Since the stack grows down and is the highest area in the processes
641 //address space, we can put stuff above it and stay out of the way.
642 int fillSize = sizeof(MachInst) * numFillInsts;
643 int spillSize = sizeof(MachInst) * numSpillInsts;
644 fillStart = stack_base;
645 spillStart = fillStart + fillSize;
646 initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler32, fillSize);
647 initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler32, spillSize);
648
649 //Set up the thread context to start running the process
650 //assert(NumArgumentRegs >= 2);
651 //threadContexts[0]->setIntReg(ArgumentReg[0], argc);
652 //threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base);
653 threadContexts[0]->setIntReg(StackPointerReg, stack_min);
654
655 uint32_t prog_entry = objFile->entryPoint();
656 threadContexts[0]->setPC(prog_entry);
657 threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
658 threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
659
660 //Align the "stack_min" to a page boundary.
661 stack_min = roundDown(stack_min, pageSize);
662
663 // num_processes++;
664 }
665
666 void Sparc32LiveProcess::flushWindows(ThreadContext *tc)
667 {
668 IntReg Cansave = tc->readIntReg(NumIntArchRegs + 3);
669 IntReg Canrestore = tc->readIntReg(NumIntArchRegs + 4);
670 IntReg Otherwin = tc->readIntReg(NumIntArchRegs + 6);
671 MiscReg CWP = tc->readMiscReg(MISCREG_CWP);
672 MiscReg origCWP = CWP;
673 CWP = (CWP + Cansave + 2) % NWindows;
674 while(NWindows - 2 - Cansave != 0)
675 {
676 if (Otherwin) {
677 panic("Otherwin non-zero.\n");
678 } else {
679 tc->setMiscReg(MISCREG_CWP, CWP);
680 //Do the stores
681 IntReg sp = tc->readIntReg(StackPointerReg);
682 for (int index = 16; index < 32; index++) {
683 IntReg regVal = tc->readIntReg(index);
684 regVal = htog(regVal);
685 if (!tc->getMemPort()->tryWriteBlob(
686 sp + (index - 16) * 4, (uint8_t *)&regVal, 4)) {
687 warn("Failed to save register to the stack when "
688 "flushing windows.\n");
689 }
690 }
691 Canrestore--;
692 Cansave++;
693 CWP = (CWP + 1) % NWindows;
694 }
695 }
696 tc->setIntReg(NumIntArchRegs + 3, Cansave);
697 tc->setIntReg(NumIntArchRegs + 4, Canrestore);
698 tc->setMiscReg(MISCREG_CWP, origCWP);
699 }
700
701 void Sparc64LiveProcess::flushWindows(ThreadContext *tc)
702 {
703 IntReg Cansave = tc->readIntReg(NumIntArchRegs + 3);
704 IntReg Canrestore = tc->readIntReg(NumIntArchRegs + 4);
705 IntReg Otherwin = tc->readIntReg(NumIntArchRegs + 6);
706 MiscReg CWP = tc->readMiscReg(MISCREG_CWP);
707 MiscReg origCWP = CWP;
708 CWP = (CWP + Cansave + 2) % NWindows;
709 while(NWindows - 2 - Cansave != 0)
710 {
711 if (Otherwin) {
712 panic("Otherwin non-zero.\n");
713 } else {
714 tc->setMiscReg(MISCREG_CWP, CWP);
715 //Do the stores
716 IntReg sp = tc->readIntReg(StackPointerReg);
717 for (int index = 16; index < 32; index++) {
718 IntReg regVal = tc->readIntReg(index);
719 regVal = htog(regVal);
720 if (!tc->getMemPort()->tryWriteBlob(
721 sp + 2047 + (index - 16) * 8, (uint8_t *)&regVal, 8)) {
722 warn("Failed to save register to the stack when "
723 "flushing windows.\n");
724 }
725 }
726 Canrestore--;
727 Cansave++;
728 CWP = (CWP + 1) % NWindows;
729 }
730 }
731 tc->setIntReg(NumIntArchRegs + 3, Cansave);
732 tc->setIntReg(NumIntArchRegs + 4, Canrestore);
733 tc->setMiscReg(MISCREG_CWP, origCWP);
734 }