2 * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
3 * Copyright (c) 2012 ARM Limited
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
15 * Copyright (c) 2001-2005 The Regents of The University of Michigan
16 * All rights reserved.
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 #include "sim/process.hh"
54 #include "base/intmath.hh"
55 #include "base/loader/object_file.hh"
56 #include "base/loader/symtab.hh"
57 #include "base/statistics.hh"
58 #include "config/the_isa.hh"
59 #include "cpu/thread_context.hh"
60 #include "mem/page_table.hh"
61 #include "mem/se_translating_port_proxy.hh"
62 #include "params/Process.hh"
63 #include "sim/emul_driver.hh"
64 #include "sim/fd_array.hh"
65 #include "sim/fd_entry.hh"
66 #include "sim/redirect_path.hh"
67 #include "sim/syscall_desc.hh"
68 #include "sim/system.hh"
73 typedef std::vector
<Process::Loader
*> LoaderList
;
78 static LoaderList loaders
;
82 } // anonymous namespace
84 Process::Loader::Loader()
86 process_loaders().emplace_back(this);
90 Process::tryLoaders(const ProcessParams
¶ms
,
91 ::Loader::ObjectFile
*obj_file
)
93 for (auto &loader
: process_loaders()) {
94 Process
*p
= loader
->load(params
, obj_file
);
103 normalize(const std::string
& directory
)
105 if (directory
.back() != '/')
106 return directory
+ '/';
110 Process::Process(const ProcessParams
¶ms
, EmulationPageTable
*pTable
,
111 ::Loader::ObjectFile
*obj_file
)
112 : SimObject(params
), system(params
.system
),
113 useArchPT(params
.useArchPT
),
114 kvmInSE(params
.kvmInSE
),
118 argv(params
.cmd
), envp(params
.env
),
119 executable(params
.executable
== "" ? params
.cmd
[0] : params
.executable
),
120 tgtCwd(normalize(params
.cwd
)),
121 hostCwd(checkPathRedirect(tgtCwd
)),
122 release(params
.release
),
123 _uid(params
.uid
), _euid(params
.euid
),
124 _gid(params
.gid
), _egid(params
.egid
),
125 _pid(params
.pid
), _ppid(params
.ppid
),
126 _pgid(params
.pgid
), drivers(params
.drivers
),
127 fds(std::make_shared
<FDArray
>(
128 params
.input
, params
.output
, params
.errout
)),
130 ADD_STAT(numSyscalls
, UNIT_COUNT
, "Number of system calls")
132 if (_pid
>= System::maxPID
)
133 fatal("_pid is too large: %d", _pid
);
135 auto ret_pair
= system
->PIDs
.emplace(_pid
);
136 if (!ret_pair
.second
)
137 fatal("_pid %d is already used", _pid
);
140 * Linux bundles together processes into this concept called a thread
141 * group. The thread group is responsible for recording which processes
142 * behave as threads within a process context. The thread group leader
143 * is the process who's tgid is equal to its pid. Other processes which
144 * belong to the thread group, but do not lead the thread group, are
145 * treated as child threads. These threads are created by the clone system
146 * call with options specified to create threads (differing from the
147 * options used to implement a fork). By default, set up the tgid/pid
148 * with a new, equivalent value. If CLONE_THREAD is specified, patch
149 * the tgid value with the old process' value.
153 exitGroup
= new bool();
154 sigchld
= new bool();
156 image
= objFile
->buildImage();
158 if (::Loader::debugSymbolTable
.empty())
159 ::Loader::debugSymbolTable
= objFile
->symtab();
163 Process::clone(ThreadContext
*otc
, ThreadContext
*ntc
,
164 Process
*np
, RegVal flags
)
170 #define CLONE_FILES 0
173 #define CLONE_THREAD 0
175 if (CLONE_VM
& flags
) {
177 * Share the process memory address space between the new process
178 * and the old process. Changes in one will be visible in the other
179 * due to the pointer use.
184 np
->memState
= memState
;
187 * Duplicate the process memory address space. The state needs to be
188 * copied over (rather than using pointers to share everything).
190 typedef std::vector
<std::pair
<Addr
,Addr
>> MapVec
;
192 pTable
->getMappings(&mappings
);
194 for (auto map
: mappings
) {
195 Addr paddr
, vaddr
= map
.first
;
196 bool alloc_page
= !(np
->pTable
->translate(vaddr
, paddr
));
197 np
->replicatePage(vaddr
, paddr
, otc
, ntc
, alloc_page
);
200 *np
->memState
= *memState
;
203 if (CLONE_FILES
& flags
) {
205 * The parent and child file descriptors are shared because the
206 * two FDArray pointers are pointing to the same FDArray. Opening
207 * and closing file descriptors will be visible to both processes.
212 * Copy the file descriptors from the old process into the new
213 * child process. The file descriptors entry can be opened and
214 * closed independently of the other process being considered. The
215 * host file descriptors are also dup'd so that the flags for the
216 * host file descriptor is independent of the other process.
218 std::shared_ptr
<FDArray
> nfds
= np
->fds
;
219 for (int tgt_fd
= 0; tgt_fd
< fds
->getSize(); tgt_fd
++) {
220 std::shared_ptr
<FDEntry
> this_fde
= (*fds
)[tgt_fd
];
222 nfds
->setFDEntry(tgt_fd
, nullptr);
225 nfds
->setFDEntry(tgt_fd
, this_fde
->clone());
227 auto this_hbfd
= std::dynamic_pointer_cast
<HBFDEntry
>(this_fde
);
231 int this_sim_fd
= this_hbfd
->getSimFD();
232 if (this_sim_fd
<= 2)
235 int np_sim_fd
= dup(this_sim_fd
);
236 assert(np_sim_fd
!= -1);
238 auto nhbfd
= std::dynamic_pointer_cast
<HBFDEntry
>((*nfds
)[tgt_fd
]);
239 nhbfd
->setSimFD(np_sim_fd
);
243 if (CLONE_THREAD
& flags
) {
245 delete np
->exitGroup
;
246 np
->exitGroup
= exitGroup
;
249 np
->argv
.insert(np
->argv
.end(), argv
.begin(), argv
.end());
250 np
->envp
.insert(np
->envp
.end(), envp
.begin(), envp
.end());
254 Process::revokeThreadContext(int context_id
)
256 std::vector
<ContextID
>::iterator it
;
257 for (it
= contextIds
.begin(); it
!= contextIds
.end(); it
++) {
258 if (*it
== context_id
) {
259 contextIds
.erase(it
);
263 warn("Unable to find thread context to revoke");
269 // Patch the ld_bias for dynamic executables.
272 if (objFile
->getInterpreter())
273 interpImage
= objFile
->getInterpreter()->buildImage();
279 if (contextIds
.empty())
280 fatal("Process %s is not associated with any HW contexts!\n", name());
282 // first thread context for this process... initialize & enable
283 ThreadContext
*tc
= system
->threads
[contextIds
[0]];
285 // mark this context as active so it will start ticking.
290 initVirtMem
.reset(new SETranslatingPortProxy(
291 tc
, SETranslatingPortProxy::Always
));
293 // load object file into target memory
294 image
.write(*initVirtMem
);
295 interpImage
.write(*initVirtMem
);
301 fds
->updateFileOffsets();
302 return DrainState::Drained
;
306 Process::allocateMem(Addr vaddr
, int64_t size
, bool clobber
)
308 // Check if the page has been mapped by other cores if not to clobber.
309 // When running multithreaded programs in SE-mode with DerivO3CPU model,
310 // there are cases where two or more cores have page faults on the same
311 // page in nearby ticks. When the cores try to handle the faults at the
312 // commit stage (also in nearby ticks/cycles), the first core will ask for
313 // a physical page frame to map with the virtual page. Other cores can
314 // return if the page has been mapped and `!clobber`.
316 const EmulationPageTable::Entry
*pte
= pTable
->lookup(vaddr
);
318 warn("Process::allocateMem: addr %#x already mapped\n", vaddr
);
323 int npages
= divCeil(size
, pTable
->pageSize());
324 Addr paddr
= system
->allocPhysPages(npages
);
325 pTable
->map(vaddr
, paddr
, size
,
326 clobber
? EmulationPageTable::Clobber
:
327 EmulationPageTable::MappingFlags(0));
331 Process::replicatePage(Addr vaddr
, Addr new_paddr
, ThreadContext
*old_tc
,
332 ThreadContext
*new_tc
, bool allocate_page
)
335 new_paddr
= system
->allocPhysPages(1);
337 // Read from old physical page.
338 uint8_t buf_p
[pTable
->pageSize()];
339 old_tc
->getVirtProxy().readBlob(vaddr
, buf_p
, sizeof(buf_p
));
341 // Create new mapping in process address space by clobbering existing
342 // mapping (if any existed) and then write to the new physical page.
344 pTable
->map(vaddr
, new_paddr
, sizeof(buf_p
), clobber
);
345 new_tc
->getVirtProxy().writeBlob(vaddr
, buf_p
, sizeof(buf_p
));
349 Process::fixupFault(Addr vaddr
)
351 return memState
->fixupFault(vaddr
);
355 Process::serialize(CheckpointOut
&cp
) const
357 memState
->serialize(cp
);
358 pTable
->serialize(cp
);
360 * Checkpoints for file descriptors currently do not work. Need to
361 * come back and fix them at a later date.
364 warn("Checkpoints for file descriptors currently do not work.");
368 Process::unserialize(CheckpointIn
&cp
)
370 memState
->unserialize(cp
);
371 pTable
->unserialize(cp
);
373 * Checkpoints for file descriptors currently do not work. Need to
374 * come back and fix them at a later date.
376 warn("Checkpoints for file descriptors currently do not work.");
377 // The above returns a bool so that you could do something if you don't
378 // find the param in the checkpoint if you wanted to, like set a default
379 // but in this case we'll just stick with the instantiated value if not
384 Process::map(Addr vaddr
, Addr paddr
, int size
, bool cacheable
)
386 pTable
->map(vaddr
, paddr
, size
,
387 cacheable
? EmulationPageTable::MappingFlags(0) :
388 EmulationPageTable::Uncacheable
);
393 Process::findDriver(std::string filename
)
395 for (EmulatedDriver
*d
: drivers
) {
396 if (d
->match(filename
))
404 Process::checkPathRedirect(const std::string
&filename
)
406 // If the input parameter contains a relative path, convert it.
407 // The target version of the current working directory is fine since
408 // we immediately convert it using redirect paths into a host version.
409 auto abs_path
= absolutePath(filename
, false);
411 for (auto path
: system
->redirectPaths
) {
412 // Search through the redirect paths to see if a starting substring of
413 // our path falls into any buckets which need to redirected.
414 if (startswith(abs_path
, path
->appPath())) {
415 std::string tail
= abs_path
.substr(path
->appPath().size());
417 // If this path needs to be redirected, search through a list
418 // of targets to see if we can match a valid file (or directory).
419 for (auto host_path
: path
->hostPaths()) {
420 if (access((host_path
+ tail
).c_str(), R_OK
) == 0) {
421 // Return the valid match.
422 return host_path
+ tail
;
425 // The path needs to be redirected, but the file or directory
426 // does not exist on the host filesystem. Return the first
427 // host path as a default.
428 return path
->hostPaths()[0] + tail
;
432 // The path does not need to be redirected.
437 Process::updateBias()
439 auto *interp
= objFile
->getInterpreter();
441 if (!interp
|| !interp
->relocatable())
444 // Determine how large the interpreters footprint will be in the process
446 Addr interp_mapsize
= roundUp(interp
->mapSize(), pTable
->pageSize());
448 // We are allocating the memory area; set the bias to the lowest address
449 // in the allocated memory region.
450 Addr mmap_end
= memState
->getMmapEnd();
451 Addr ld_bias
= mmapGrowsDown() ? mmap_end
- interp_mapsize
: mmap_end
;
453 // Adjust the process mmap area to give the interpreter room; the real
454 // execve system call would just invoke the kernel's internal mmap
455 // functions to make these adjustments.
456 mmap_end
= mmapGrowsDown() ? ld_bias
: mmap_end
+ interp_mapsize
;
457 memState
->setMmapEnd(mmap_end
);
459 interp
->updateBias(ld_bias
);
463 Process::getInterpreter()
465 return objFile
->getInterpreter();
471 auto *interp
= getInterpreter();
473 return interp
? interp
->bias() : objFile
->bias();
477 Process::getStartPC()
479 auto *interp
= getInterpreter();
481 return interp
? interp
->entryPoint() : objFile
->entryPoint();
485 Process::absolutePath(const std::string
&filename
, bool host_filesystem
)
487 if (filename
.empty() || startswith(filename
, "/"))
490 // Construct the absolute path given the current working directory for
491 // either the host filesystem or target filesystem. The distinction only
492 // matters if filesystem redirection is utilized in the simulation.
493 auto path_base
= std::string();
494 if (host_filesystem
) {
496 assert(!hostCwd
.empty());
499 assert(!tgtCwd
.empty());
502 // Add a trailing '/' if the current working directory did not have one.
503 normalize(path_base
);
505 // Append the filename onto the current working path.
506 auto absolute_path
= path_base
+ filename
;
508 return absolute_path
;
512 ProcessParams::create() const
514 // If not specified, set the executable parameter equal to the
515 // simulated system's zeroth command line parameter
516 const std::string
&exec
= (executable
== "") ? cmd
[0] : executable
;
518 auto *obj_file
= Loader::createObjectFile(exec
);
519 fatal_if(!obj_file
, "Cannot load object file %s.", exec
);
521 Process
*process
= Process::tryLoaders(*this, obj_file
);
522 fatal_if(!process
, "Unknown error creating process object.");