process.cc revision 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);
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);
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);
146
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);
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}
639