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