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"
71 using namespace TheISA
;
76 typedef std::vector
<Process::Loader
*> LoaderList
;
81 static LoaderList loaders
;
85 } // anonymous namespace
87 Process::Loader::Loader()
89 process_loaders().emplace_back(this);
93 Process::tryLoaders(ProcessParams
*params
, ::Loader::ObjectFile
*obj_file
)
95 for (auto &loader
: process_loaders()) {
96 Process
*p
= loader
->load(params
, obj_file
);
105 normalize(std::string
& directory
)
107 if (directory
.back() != '/')
112 Process::Process(ProcessParams
*params
, EmulationPageTable
*pTable
,
113 ::Loader::ObjectFile
*obj_file
)
114 : SimObject(params
), system(params
->system
),
115 useArchPT(params
->useArchPT
),
116 kvmInSE(params
->kvmInSE
),
120 argv(params
->cmd
), envp(params
->env
),
121 executable(params
->executable
),
122 tgtCwd(normalize(params
->cwd
)),
123 hostCwd(checkPathRedirect(tgtCwd
)),
124 release(params
->release
),
125 _uid(params
->uid
), _euid(params
->euid
),
126 _gid(params
->gid
), _egid(params
->egid
),
127 _pid(params
->pid
), _ppid(params
->ppid
),
128 _pgid(params
->pgid
), drivers(params
->drivers
),
129 fds(make_shared
<FDArray
>(params
->input
, params
->output
, params
->errout
)),
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
<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());
256 SimObject::regStats();
258 using namespace Stats
;
261 .name(name() + ".numSyscalls")
262 .desc("Number of system calls")
267 Process::revokeThreadContext(int context_id
)
269 std::vector
<ContextID
>::iterator it
;
270 for (it
= contextIds
.begin(); it
!= contextIds
.end(); it
++) {
271 if (*it
== context_id
) {
272 contextIds
.erase(it
);
276 warn("Unable to find thread context to revoke");
282 // Patch the ld_bias for dynamic executables.
285 if (objFile
->getInterpreter())
286 interpImage
= objFile
->getInterpreter()->buildImage();
292 if (contextIds
.empty())
293 fatal("Process %s is not associated with any HW contexts!\n", name());
295 // first thread context for this process... initialize & enable
296 ThreadContext
*tc
= system
->threads
[contextIds
[0]];
298 // mark this context as active so it will start ticking.
303 initVirtMem
.reset(new SETranslatingPortProxy(
304 tc
, SETranslatingPortProxy::Always
));
306 // load object file into target memory
307 image
.write(*initVirtMem
);
308 interpImage
.write(*initVirtMem
);
314 fds
->updateFileOffsets();
315 return DrainState::Drained
;
319 Process::allocateMem(Addr vaddr
, int64_t size
, bool clobber
)
321 int npages
= divCeil(size
, (int64_t)system
->getPageBytes());
322 Addr paddr
= system
->allocPhysPages(npages
);
323 pTable
->map(vaddr
, paddr
, size
,
324 clobber
? EmulationPageTable::Clobber
:
325 EmulationPageTable::MappingFlags(0));
329 Process::replicatePage(Addr vaddr
, Addr new_paddr
, ThreadContext
*old_tc
,
330 ThreadContext
*new_tc
, bool allocate_page
)
333 new_paddr
= system
->allocPhysPages(1);
335 // Read from old physical page.
336 uint8_t *buf_p
= new uint8_t[system
->getPageBytes()];
337 old_tc
->getVirtProxy().readBlob(vaddr
, buf_p
, system
->getPageBytes());
339 // Create new mapping in process address space by clobbering existing
340 // mapping (if any existed) and then write to the new physical page.
342 pTable
->map(vaddr
, new_paddr
, system
->getPageBytes(), clobber
);
343 new_tc
->getVirtProxy().writeBlob(vaddr
, buf_p
, system
->getPageBytes());
348 Process::fixupFault(Addr vaddr
)
350 return memState
->fixupFault(vaddr
);
354 Process::serialize(CheckpointOut
&cp
) const
356 memState
->serialize(cp
);
357 pTable
->serialize(cp
);
359 * Checkpoints for file descriptors currently do not work. Need to
360 * come back and fix them at a later date.
363 warn("Checkpoints for file descriptors currently do not work.");
367 Process::unserialize(CheckpointIn
&cp
)
369 memState
->unserialize(cp
);
370 pTable
->unserialize(cp
);
372 * Checkpoints for file descriptors currently do not work. Need to
373 * come back and fix them at a later date.
375 warn("Checkpoints for file descriptors currently do not work.");
376 // The above returns a bool so that you could do something if you don't
377 // find the param in the checkpoint if you wanted to, like set a default
378 // but in this case we'll just stick with the instantiated value if not
383 Process::map(Addr vaddr
, Addr paddr
, int size
, bool cacheable
)
385 pTable
->map(vaddr
, paddr
, size
,
386 cacheable
? EmulationPageTable::MappingFlags(0) :
387 EmulationPageTable::Uncacheable
);
392 Process::findDriver(std::string filename
)
394 for (EmulatedDriver
*d
: drivers
) {
395 if (d
->match(filename
))
403 Process::checkPathRedirect(const std::string
&filename
)
405 // If the input parameter contains a relative path, convert it.
406 // The target version of the current working directory is fine since
407 // we immediately convert it using redirect paths into a host version.
408 auto abs_path
= absolutePath(filename
, false);
410 for (auto path
: system
->redirectPaths
) {
411 // Search through the redirect paths to see if a starting substring of
412 // our path falls into any buckets which need to redirected.
413 if (startswith(abs_path
, path
->appPath())) {
414 std::string tail
= abs_path
.substr(path
->appPath().size());
416 // If this path needs to be redirected, search through a list
417 // of targets to see if we can match a valid file (or directory).
418 for (auto host_path
: path
->hostPaths()) {
419 if (access((host_path
+ tail
).c_str(), R_OK
) == 0) {
420 // Return the valid match.
421 return host_path
+ tail
;
424 // The path needs to be redirected, but the file or directory
425 // does not exist on the host filesystem. Return the first
426 // host path as a default.
427 return path
->hostPaths()[0] + tail
;
431 // The path does not need to be redirected.
436 Process::updateBias()
438 auto *interp
= objFile
->getInterpreter();
440 if (!interp
|| !interp
->relocatable())
443 // Determine how large the interpreters footprint will be in the process
445 Addr interp_mapsize
= roundUp(interp
->mapSize(), system
->getPageBytes());
447 // We are allocating the memory area; set the bias to the lowest address
448 // in the allocated memory region.
449 Addr mmap_end
= memState
->getMmapEnd();
450 Addr ld_bias
= mmapGrowsDown() ? mmap_end
- interp_mapsize
: mmap_end
;
452 // Adjust the process mmap area to give the interpreter room; the real
453 // execve system call would just invoke the kernel's internal mmap
454 // functions to make these adjustments.
455 mmap_end
= mmapGrowsDown() ? ld_bias
: mmap_end
+ interp_mapsize
;
456 memState
->setMmapEnd(mmap_end
);
458 interp
->updateBias(ld_bias
);
462 Process::getInterpreter()
464 return objFile
->getInterpreter();
470 auto *interp
= getInterpreter();
472 return interp
? interp
->bias() : objFile
->bias();
476 Process::getStartPC()
478 auto *interp
= getInterpreter();
480 return interp
? interp
->entryPoint() : objFile
->entryPoint();
484 Process::absolutePath(const std::string
&filename
, bool host_filesystem
)
486 if (filename
.empty() || startswith(filename
, "/"))
489 // Construct the absolute path given the current working directory for
490 // either the host filesystem or target filesystem. The distinction only
491 // matters if filesystem redirection is utilized in the simulation.
492 auto path_base
= std::string();
493 if (host_filesystem
) {
495 assert(!hostCwd
.empty());
498 assert(!tgtCwd
.empty());
501 // Add a trailing '/' if the current working directory did not have one.
502 normalize(path_base
);
504 // Append the filename onto the current working path.
505 auto absolute_path
= path_base
+ filename
;
507 return absolute_path
;
511 ProcessParams::create()
513 // If not specified, set the executable parameter equal to the
514 // simulated system's zeroth command line parameter
515 if (executable
== "") {
519 auto *obj_file
= Loader::createObjectFile(executable
);
520 fatal_if(!obj_file
, "Cannot load object file %s.", executable
);
522 Process
*process
= Process::tryLoaders(this, obj_file
);
523 fatal_if(!process
, "Unknown error creating process object.");