2 * Copyright (c) 2007-2008 The Florida State University
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.
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.
28 * Authors: Stephen Hines
31 #include "arch/arm/isa_traits.hh"
32 #include "arch/arm/process.hh"
33 #include "arch/arm/types.hh"
34 #include "base/loader/elf_object.hh"
35 #include "base/loader/object_file.hh"
36 #include "base/misc.hh"
37 #include "cpu/thread_context.hh"
38 #include "mem/page_table.hh"
39 #include "mem/translating_port.hh"
40 #include "sim/process_impl.hh"
41 #include "sim/system.hh"
44 using namespace ArmISA
;
46 ArmLiveProcess::ArmLiveProcess(LiveProcessParams
*params
, ObjectFile
*objFile
)
47 : LiveProcess(params
, objFile
)
49 stack_base
= 0xc0000000L
;
51 // Set pointer for next thread stack. Reserve 8M for main stack.
52 next_thread_stack_base
= stack_base
- (8 * 1024 * 1024);
54 // Set up break point (Top of Heap)
55 brk_point
= objFile
->dataBase() + objFile
->dataSize() + objFile
->bssSize();
56 brk_point
= roundUp(brk_point
, VMPageSize
);
58 // Set up region for mmaps. For now, start at bottom of kuseg space.
59 mmap_start
= mmap_end
= 0x70000000L
;
63 ArmLiveProcess::startup()
65 argsInit(MachineBytes
, VMPageSize
);
69 ArmLiveProcess::copyStringArray32(std::vector
<std::string
> &strings
,
70 Addr array_ptr
, Addr data_ptr
,
71 TranslatingPort
* memPort
)
74 for (int i
= 0; i
< strings
.size(); ++i
) {
75 data_ptr_swap
= htog(data_ptr
);
76 memPort
->writeBlob(array_ptr
, (uint8_t*)&data_ptr_swap
,
78 memPort
->writeString(data_ptr
, strings
[i
].c_str());
79 array_ptr
+= sizeof(uint32_t);
80 data_ptr
+= strings
[i
].size() + 1;
82 // add NULL terminator
85 memPort
->writeBlob(array_ptr
, (uint8_t*)&data_ptr
, sizeof(uint32_t));
89 ArmLiveProcess::argsInit(int intSize
, int pageSize
)
91 // Overloaded argsInit so that we can fine-tune for ARM architecture
94 // load object file into target memory
95 objFile
->loadSections(initVirtMem
);
97 // Calculate how much space we need for arg & env arrays.
98 int argv_array_size
= intSize
* (argv
.size() + 1);
99 int envp_array_size
= intSize
* (envp
.size() + 1);
100 int arg_data_size
= 0;
101 for (int i
= 0; i
< argv
.size(); ++i
) {
102 arg_data_size
+= argv
[i
].size() + 1;
104 int env_data_size
= 0;
105 for (int i
= 0; i
< envp
.size(); ++i
) {
106 env_data_size
+= envp
[i
].size() + 1;
110 argv_array_size
+ envp_array_size
+ arg_data_size
+ env_data_size
;
111 if (space_needed
< 16*1024)
112 space_needed
= 16*1024;
114 // set bottom of stack
115 stack_min
= stack_base
- space_needed
;
117 stack_min
= roundDown(stack_min
, pageSize
);
118 stack_size
= stack_base
- stack_min
;
120 pTable
->allocate(stack_min
, roundUp(stack_size
, pageSize
));
122 // map out initial stack contents
123 Addr argv_array_base
= stack_min
+ intSize
; // room for argc
124 Addr envp_array_base
= argv_array_base
+ argv_array_size
;
125 Addr arg_data_base
= envp_array_base
+ envp_array_size
;
126 Addr env_data_base
= arg_data_base
+ arg_data_size
;
128 // write contents to stack
129 uint64_t argc
= argv
.size();
131 argc
= htog((uint64_t)argc
);
132 else if (intSize
== 4)
133 argc
= htog((uint32_t)argc
);
135 panic("Unknown int size");
137 initVirtMem
->writeBlob(stack_min
, (uint8_t*)&argc
, intSize
);
139 copyStringArray32(argv
, argv_array_base
, arg_data_base
, initVirtMem
);
140 copyStringArray32(envp
, envp_array_base
, env_data_base
, initVirtMem
);
143 //uint8_t insns[] = {0xe5, 0x9f, 0x00, 0x08, 0xe1, 0xa0, 0xf0, 0x0e};
144 uint8_t insns[] = {0x08, 0x00, 0x9f, 0xe5, 0x0e, 0xf0, 0xa0, 0xe1};
146 initVirtMem->writeBlob(0xffff0fe0, insns, 8);
149 ThreadContext
*tc
= system
->getThreadContext(contextIds
[0]);
151 tc
->setIntReg(ArgumentReg1
, argc
);
152 tc
->setIntReg(ArgumentReg2
, argv_array_base
);
153 tc
->setIntReg(StackPointerReg
, stack_min
);
155 Addr prog_entry
= objFile
->entryPoint();
156 tc
->setPC(prog_entry
);
157 tc
->setNextPC(prog_entry
+ sizeof(MachInst
));
161 ArmLiveProcess::getSyscallArg(ThreadContext
*tc
, int i
)
164 return tc
->readIntReg(ArgumentReg0
+ i
);
168 ArmLiveProcess::setSyscallArg(ThreadContext
*tc
,
169 int i
, ArmISA::IntReg val
)
172 tc
->setIntReg(ArgumentReg0
+ i
, val
);
176 ArmLiveProcess::setSyscallReturn(ThreadContext
*tc
,
177 SyscallReturn return_value
)
179 tc
->setIntReg(ReturnValueReg
, return_value
.value());