5e9c2b5e73fac28db1fe523515ddc01f774e79ef
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.
41 * Authors: Nathan Binkert
47 #include "sim/process.hh"
58 #include "base/intmath.hh"
59 #include "base/loader/object_file.hh"
60 #include "base/loader/symtab.hh"
61 #include "base/statistics.hh"
62 #include "config/the_isa.hh"
63 #include "cpu/thread_context.hh"
64 #include "mem/page_table.hh"
65 #include "mem/se_translating_port_proxy.hh"
66 #include "params/Process.hh"
67 #include "sim/emul_driver.hh"
68 #include "sim/fd_array.hh"
69 #include "sim/fd_entry.hh"
70 #include "sim/syscall_desc.hh"
71 #include "sim/system.hh"
73 #if THE_ISA == ALPHA_ISA
74 #include "arch/alpha/linux/process.hh"
76 #elif THE_ISA == SPARC_ISA
77 #include "arch/sparc/linux/process.hh"
78 #include "arch/sparc/solaris/process.hh"
80 #elif THE_ISA == MIPS_ISA
81 #include "arch/mips/linux/process.hh"
83 #elif THE_ISA == ARM_ISA
84 #include "arch/arm/freebsd/process.hh"
85 #include "arch/arm/linux/process.hh"
87 #elif THE_ISA == X86_ISA
88 #include "arch/x86/linux/process.hh"
90 #elif THE_ISA == POWER_ISA
91 #include "arch/power/linux/process.hh"
93 #elif THE_ISA == RISCV_ISA
94 #include "arch/riscv/linux/process.hh"
97 #error "THE_ISA not set"
102 using namespace TheISA
;
104 Process::Process(ProcessParams
*params
, EmulationPageTable
*pTable
,
105 ObjectFile
*obj_file
)
106 : SimObject(params
), system(params
->system
),
107 useArchPT(params
->useArchPT
),
108 kvmInSE(params
->kvmInSE
),
110 initVirtMem(system
->getSystemPort(), this,
111 SETranslatingPortProxy::Always
),
113 argv(params
->cmd
), envp(params
->env
), cwd(params
->cwd
),
114 executable(params
->executable
),
115 _uid(params
->uid
), _euid(params
->euid
),
116 _gid(params
->gid
), _egid(params
->egid
),
117 _pid(params
->pid
), _ppid(params
->ppid
),
118 _pgid(params
->pgid
), drivers(params
->drivers
),
119 fds(make_shared
<FDArray
>(params
->input
, params
->output
, params
->errout
)),
122 if (_pid
>= System::maxPID
)
123 fatal("_pid is too large: %d", _pid
);
125 auto ret_pair
= system
->PIDs
.emplace(_pid
);
126 if (!ret_pair
.second
)
127 fatal("_pid %d is already used", _pid
);
130 * Linux bundles together processes into this concept called a thread
131 * group. The thread group is responsible for recording which processes
132 * behave as threads within a process context. The thread group leader
133 * is the process who's tgid is equal to its pid. Other processes which
134 * belong to the thread group, but do not lead the thread group, are
135 * treated as child threads. These threads are created by the clone system
136 * call with options specified to create threads (differing from the
137 * options used to implement a fork). By default, set up the tgid/pid
138 * with a new, equivalent value. If CLONE_THREAD is specified, patch
139 * the tgid value with the old process' value.
143 exitGroup
= new bool();
144 sigchld
= new bool();
146 if (!debugSymbolTable
) {
147 debugSymbolTable
= new SymbolTable();
148 if (!objFile
->loadGlobalSymbols(debugSymbolTable
) ||
149 !objFile
->loadLocalSymbols(debugSymbolTable
) ||
150 !objFile
->loadWeakSymbols(debugSymbolTable
)) {
151 delete debugSymbolTable
;
152 debugSymbolTable
= nullptr;
158 Process::clone(ThreadContext
*otc
, ThreadContext
*ntc
,
159 Process
*np
, TheISA::IntReg flags
)
165 #define CLONE_FILES 0
168 #define CLONE_THREAD 0
170 if (CLONE_VM
& flags
) {
172 * Share the process memory address space between the new process
173 * and the old process. Changes in one will be visible in the other
174 * due to the pointer use.
178 ntc
->getMemProxy().setPageTable(np
->pTable
);
180 np
->memState
= memState
;
183 * Duplicate the process memory address space. The state needs to be
184 * copied over (rather than using pointers to share everything).
186 typedef std::vector
<pair
<Addr
,Addr
>> MapVec
;
188 pTable
->getMappings(&mappings
);
190 for (auto map
: mappings
) {
191 Addr paddr
, vaddr
= map
.first
;
192 bool alloc_page
= !(np
->pTable
->translate(vaddr
, paddr
));
193 np
->replicatePage(vaddr
, paddr
, otc
, ntc
, alloc_page
);
196 *np
->memState
= *memState
;
199 if (CLONE_FILES
& flags
) {
201 * The parent and child file descriptors are shared because the
202 * two FDArray pointers are pointing to the same FDArray. Opening
203 * and closing file descriptors will be visible to both processes.
208 * Copy the file descriptors from the old process into the new
209 * child process. The file descriptors entry can be opened and
210 * closed independently of the other process being considered. The
211 * host file descriptors are also dup'd so that the flags for the
212 * host file descriptor is independent of the other process.
214 for (int tgt_fd
= 0; tgt_fd
< fds
->getSize(); tgt_fd
++) {
215 std::shared_ptr
<FDArray
> nfds
= np
->fds
;
216 std::shared_ptr
<FDEntry
> this_fde
= (*fds
)[tgt_fd
];
218 nfds
->setFDEntry(tgt_fd
, nullptr);
221 nfds
->setFDEntry(tgt_fd
, this_fde
->clone());
223 auto this_hbfd
= std::dynamic_pointer_cast
<HBFDEntry
>(this_fde
);
227 int this_sim_fd
= this_hbfd
->getSimFD();
228 if (this_sim_fd
<= 2)
231 int np_sim_fd
= dup(this_sim_fd
);
232 assert(np_sim_fd
!= -1);
234 auto nhbfd
= std::dynamic_pointer_cast
<HBFDEntry
>((*nfds
)[tgt_fd
]);
235 nhbfd
->setSimFD(np_sim_fd
);
239 if (CLONE_THREAD
& flags
) {
241 delete np
->exitGroup
;
242 np
->exitGroup
= exitGroup
;
245 np
->argv
.insert(np
->argv
.end(), argv
.begin(), argv
.end());
246 np
->envp
.insert(np
->envp
.end(), envp
.begin(), envp
.end());
252 SimObject::regStats();
254 using namespace Stats
;
257 .name(name() + ".numSyscalls")
258 .desc("Number of system calls")
263 Process::findFreeContext()
265 for (auto &it
: system
->threadContexts
) {
266 if (ThreadContext::Halted
== it
->status())
273 Process::revokeThreadContext(int context_id
)
275 std::vector
<ContextID
>::iterator it
;
276 for (it
= contextIds
.begin(); it
!= contextIds
.end(); it
++) {
277 if (*it
== context_id
) {
278 contextIds
.erase(it
);
282 warn("Unable to find thread context to revoke");
288 if (contextIds
.empty())
289 fatal("Process %s is not associated with any HW contexts!\n", name());
291 // first thread context for this process... initialize & enable
292 ThreadContext
*tc
= system
->getThreadContext(contextIds
[0]);
294 // mark this context as active so it will start ticking.
297 pTable
->initState(tc
);
303 fds
->updateFileOffsets();
304 return DrainState::Drained
;
308 Process::allocateMem(Addr vaddr
, int64_t size
, bool clobber
)
310 int npages
= divCeil(size
, (int64_t)PageBytes
);
311 Addr paddr
= system
->allocPhysPages(npages
);
312 pTable
->map(vaddr
, paddr
, size
,
313 clobber
? EmulationPageTable::Clobber
:
314 EmulationPageTable::MappingFlags(0));
318 Process::replicatePage(Addr vaddr
, Addr new_paddr
, ThreadContext
*old_tc
,
319 ThreadContext
*new_tc
, bool allocate_page
)
322 new_paddr
= system
->allocPhysPages(1);
324 // Read from old physical page.
325 uint8_t *buf_p
= new uint8_t[PageBytes
];
326 old_tc
->getMemProxy().readBlob(vaddr
, buf_p
, PageBytes
);
328 // Create new mapping in process address space by clobbering existing
329 // mapping (if any existed) and then write to the new physical page.
331 pTable
->map(vaddr
, new_paddr
, PageBytes
, clobber
);
332 new_tc
->getMemProxy().writeBlob(vaddr
, buf_p
, PageBytes
);
337 Process::fixupStackFault(Addr vaddr
)
339 Addr stack_min
= memState
->getStackMin();
340 Addr stack_base
= memState
->getStackBase();
341 Addr max_stack_size
= memState
->getMaxStackSize();
343 // Check if this is already on the stack and there's just no page there
345 if (vaddr
>= stack_min
&& vaddr
< stack_base
) {
346 allocateMem(roundDown(vaddr
, PageBytes
), PageBytes
);
350 // We've accessed the next page of the stack, so extend it to include
352 if (vaddr
< stack_min
&& vaddr
>= stack_base
- max_stack_size
) {
353 while (vaddr
< stack_min
) {
354 stack_min
-= TheISA::PageBytes
;
355 if (stack_base
- stack_min
> max_stack_size
)
356 fatal("Maximum stack size exceeded\n");
357 allocateMem(stack_min
, TheISA::PageBytes
);
358 inform("Increasing stack size by one page.");
360 memState
->setStackMin(stack_min
);
367 Process::serialize(CheckpointOut
&cp
) const
369 memState
->serialize(cp
);
370 pTable
->serialize(cp
);
372 * Checkpoints for file descriptors currently do not work. Need to
373 * come back and fix them at a later date.
376 warn("Checkpoints for file descriptors currently do not work.");
378 for (int x
= 0; x
< fds
->getSize(); x
++)
379 (*fds
)[x
].serializeSection(cp
, csprintf("FDEntry%d", x
));
385 Process::unserialize(CheckpointIn
&cp
)
387 memState
->unserialize(cp
);
388 pTable
->unserialize(cp
);
390 * Checkpoints for file descriptors currently do not work. Need to
391 * come back and fix them at a later date.
393 warn("Checkpoints for file descriptors currently do not work.");
395 for (int x
= 0; x
< fds
->getSize(); x
++)
396 (*fds
)[x
]->unserializeSection(cp
, csprintf("FDEntry%d", x
));
397 fds
->restoreFileOffsets();
399 // The above returns a bool so that you could do something if you don't
400 // find the param in the checkpoint if you wanted to, like set a default
401 // but in this case we'll just stick with the instantiated value if not
406 Process::map(Addr vaddr
, Addr paddr
, int size
, bool cacheable
)
408 pTable
->map(vaddr
, paddr
, size
,
409 cacheable
? EmulationPageTable::MappingFlags(0) :
410 EmulationPageTable::Uncacheable
);
415 Process::syscall(int64_t callnum
, ThreadContext
*tc
, Fault
*fault
)
419 SyscallDesc
*desc
= getDesc(callnum
);
421 fatal("Syscall %d out of range", callnum
);
423 desc
->doSyscall(callnum
, this, tc
, fault
);
427 Process::getSyscallArg(ThreadContext
*tc
, int &i
, int width
)
429 return getSyscallArg(tc
, i
);
433 Process::findDriver(std::string filename
)
435 for (EmulatedDriver
*d
: drivers
) {
436 if (d
->match(filename
))
444 Process::updateBias()
446 ObjectFile
*interp
= objFile
->getInterpreter();
448 if (!interp
|| !interp
->relocatable())
451 // Determine how large the interpreters footprint will be in the process
453 Addr interp_mapsize
= roundUp(interp
->mapSize(), TheISA::PageBytes
);
455 // We are allocating the memory area; set the bias to the lowest address
456 // in the allocated memory region.
457 Addr mmap_end
= memState
->getMmapEnd();
458 Addr ld_bias
= mmapGrowsDown() ? mmap_end
- interp_mapsize
: mmap_end
;
460 // Adjust the process mmap area to give the interpreter room; the real
461 // execve system call would just invoke the kernel's internal mmap
462 // functions to make these adjustments.
463 mmap_end
= mmapGrowsDown() ? ld_bias
: mmap_end
+ interp_mapsize
;
464 memState
->setMmapEnd(mmap_end
);
466 interp
->updateBias(ld_bias
);
470 Process::getInterpreter()
472 return objFile
->getInterpreter();
478 ObjectFile
*interp
= getInterpreter();
480 return interp
? interp
->bias() : objFile
->bias();
484 Process::getStartPC()
486 ObjectFile
*interp
= getInterpreter();
488 return interp
? interp
->entryPoint() : objFile
->entryPoint();
492 ProcessParams::create()
494 Process
*process
= nullptr;
496 // If not specified, set the executable parameter equal to the
497 // simulated system's zeroth command line parameter
498 if (executable
== "") {
502 ObjectFile
*obj_file
= createObjectFile(executable
);
503 if (obj_file
== nullptr) {
504 fatal("Can't load object file %s", executable
);
507 #if THE_ISA == ALPHA_ISA
508 if (obj_file
->getArch() != ObjectFile::Alpha
)
509 fatal("Object file architecture does not match compiled ISA (Alpha).");
511 switch (obj_file
->getOpSys()) {
512 case ObjectFile::UnknownOpSys
:
513 warn("Unknown operating system; assuming Linux.");
515 case ObjectFile::Linux
:
516 process
= new AlphaLinuxProcess(this, obj_file
);
520 fatal("Unknown/unsupported operating system.");
522 #elif THE_ISA == SPARC_ISA
523 if (obj_file
->getArch() != ObjectFile::SPARC64
&&
524 obj_file
->getArch() != ObjectFile::SPARC32
)
525 fatal("Object file architecture does not match compiled ISA (SPARC).");
526 switch (obj_file
->getOpSys()) {
527 case ObjectFile::UnknownOpSys
:
528 warn("Unknown operating system; assuming Linux.");
530 case ObjectFile::Linux
:
531 if (obj_file
->getArch() == ObjectFile::SPARC64
) {
532 process
= new Sparc64LinuxProcess(this, obj_file
);
534 process
= new Sparc32LinuxProcess(this, obj_file
);
538 case ObjectFile::Solaris
:
539 process
= new SparcSolarisProcess(this, obj_file
);
543 fatal("Unknown/unsupported operating system.");
545 #elif THE_ISA == X86_ISA
546 if (obj_file
->getArch() != ObjectFile::X86_64
&&
547 obj_file
->getArch() != ObjectFile::I386
)
548 fatal("Object file architecture does not match compiled ISA (x86).");
549 switch (obj_file
->getOpSys()) {
550 case ObjectFile::UnknownOpSys
:
551 warn("Unknown operating system; assuming Linux.");
553 case ObjectFile::Linux
:
554 if (obj_file
->getArch() == ObjectFile::X86_64
) {
555 process
= new X86_64LinuxProcess(this, obj_file
);
557 process
= new I386LinuxProcess(this, obj_file
);
562 fatal("Unknown/unsupported operating system.");
564 #elif THE_ISA == MIPS_ISA
565 if (obj_file
->getArch() != ObjectFile::Mips
)
566 fatal("Object file architecture does not match compiled ISA (MIPS).");
567 switch (obj_file
->getOpSys()) {
568 case ObjectFile::UnknownOpSys
:
569 warn("Unknown operating system; assuming Linux.");
571 case ObjectFile::Linux
:
572 process
= new MipsLinuxProcess(this, obj_file
);
576 fatal("Unknown/unsupported operating system.");
578 #elif THE_ISA == ARM_ISA
579 ObjectFile::Arch arch
= obj_file
->getArch();
580 if (arch
!= ObjectFile::Arm
&& arch
!= ObjectFile::Thumb
&&
581 arch
!= ObjectFile::Arm64
)
582 fatal("Object file architecture does not match compiled ISA (ARM).");
583 switch (obj_file
->getOpSys()) {
584 case ObjectFile::UnknownOpSys
:
585 warn("Unknown operating system; assuming Linux.");
587 case ObjectFile::Linux
:
588 if (arch
== ObjectFile::Arm64
) {
589 process
= new ArmLinuxProcess64(this, obj_file
,
590 obj_file
->getArch());
592 process
= new ArmLinuxProcess32(this, obj_file
,
593 obj_file
->getArch());
596 case ObjectFile::FreeBSD
:
597 if (arch
== ObjectFile::Arm64
) {
598 process
= new ArmFreebsdProcess64(this, obj_file
,
599 obj_file
->getArch());
601 process
= new ArmFreebsdProcess32(this, obj_file
,
602 obj_file
->getArch());
605 case ObjectFile::LinuxArmOABI
:
606 fatal("M5 does not support ARM OABI binaries. Please recompile with an"
609 fatal("Unknown/unsupported operating system.");
611 #elif THE_ISA == POWER_ISA
612 if (obj_file
->getArch() != ObjectFile::Power
)
613 fatal("Object file architecture does not match compiled ISA (Power).");
614 switch (obj_file
->getOpSys()) {
615 case ObjectFile::UnknownOpSys
:
616 warn("Unknown operating system; assuming Linux.");
618 case ObjectFile::Linux
:
619 process
= new PowerLinuxProcess(this, obj_file
);
623 fatal("Unknown/unsupported operating system.");
625 #elif THE_ISA == RISCV_ISA
626 if (obj_file
->getArch() != ObjectFile::Riscv
)
627 fatal("Object file architecture does not match compiled ISA (RISCV).");
628 switch (obj_file
->getOpSys()) {
629 case ObjectFile::UnknownOpSys
:
630 warn("Unknown operating system; assuming Linux.");
632 case ObjectFile::Linux
:
633 process
= new RiscvLinuxProcess(this, obj_file
);
636 fatal("Unknown/unsupported operating system.");
639 #error "THE_ISA not set"
642 if (process
== nullptr)
643 fatal("Unknown error creating process object.");
648 Process::fullPath(const std::string
&file_name
)
650 if (file_name
[0] == '/' || cwd
.empty())
653 std::string full
= cwd
;
655 if (cwd
[cwd
.size() - 1] != '/')
658 return full
+ file_name
;