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
, ObjectFile
* obj_file
)
105 : SimObject(params
), system(params
->system
),
106 useArchPT(params
->useArchPT
),
107 kvmInSE(params
->kvmInSE
),
109 static_cast<PageTableBase
*>(new ArchPageTable(name(), params
->pid
,
111 static_cast<PageTableBase
*>(new FuncPageTable(name(), params
->pid
))),
112 initVirtMem(system
->getSystemPort(), this,
113 SETranslatingPortProxy::Always
),
115 argv(params
->cmd
), envp(params
->env
), cwd(params
->cwd
),
116 executable(params
->executable
),
117 _uid(params
->uid
), _euid(params
->euid
),
118 _gid(params
->gid
), _egid(params
->egid
),
119 _pid(params
->pid
), _ppid(params
->ppid
),
120 _pgid(params
->pgid
), drivers(params
->drivers
),
121 fds(make_shared
<FDArray
>(params
->input
, params
->output
, params
->errout
)),
124 if (_pid
>= System::maxPID
)
125 fatal("_pid is too large: %d", _pid
);
127 auto ret_pair
= system
->PIDs
.emplace(_pid
);
128 if (!ret_pair
.second
)
129 fatal("_pid %d is already used", _pid
);
132 * Linux bundles together processes into this concept called a thread
133 * group. The thread group is responsible for recording which processes
134 * behave as threads within a process context. The thread group leader
135 * is the process who's tgid is equal to its pid. Other processes which
136 * belong to the thread group, but do not lead the thread group, are
137 * treated as child threads. These threads are created by the clone system
138 * call with options specified to create threads (differing from the
139 * options used to implement a fork). By default, set up the tgid/pid
140 * with a new, equivalent value. If CLONE_THREAD is specified, patch
141 * the tgid value with the old process' value.
145 exitGroup
= new bool();
146 sigchld
= new bool();
148 if (!debugSymbolTable
) {
149 debugSymbolTable
= new SymbolTable();
150 if (!objFile
->loadGlobalSymbols(debugSymbolTable
) ||
151 !objFile
->loadLocalSymbols(debugSymbolTable
) ||
152 !objFile
->loadWeakSymbols(debugSymbolTable
)) {
153 delete debugSymbolTable
;
154 debugSymbolTable
= nullptr;
160 Process::clone(ThreadContext
*otc
, ThreadContext
*ntc
,
161 Process
*np
, TheISA::IntReg flags
)
167 #define CLONE_FILES 0
170 #define CLONE_THREAD 0
172 if (CLONE_VM
& flags
) {
174 * Share the process memory address space between the new process
175 * and the old process. Changes in one will be visible in the other
176 * due to the pointer use.
180 ntc
->getMemProxy().setPageTable(np
->pTable
);
182 np
->memState
= memState
;
185 * Duplicate the process memory address space. The state needs to be
186 * copied over (rather than using pointers to share everything).
188 typedef std::vector
<pair
<Addr
,Addr
>> MapVec
;
190 pTable
->getMappings(&mappings
);
192 for (auto map
: mappings
) {
193 Addr paddr
, vaddr
= map
.first
;
194 bool alloc_page
= !(np
->pTable
->translate(vaddr
, paddr
));
195 np
->replicatePage(vaddr
, paddr
, otc
, ntc
, alloc_page
);
198 *np
->memState
= *memState
;
201 if (CLONE_FILES
& flags
) {
203 * The parent and child file descriptors are shared because the
204 * two FDArray pointers are pointing to the same FDArray. Opening
205 * and closing file descriptors will be visible to both processes.
210 * Copy the file descriptors from the old process into the new
211 * child process. The file descriptors entry can be opened and
212 * closed independently of the other process being considered. The
213 * host file descriptors are also dup'd so that the flags for the
214 * host file descriptor is independent of the other process.
216 for (int tgt_fd
= 0; tgt_fd
< fds
->getSize(); tgt_fd
++) {
217 std::shared_ptr
<FDArray
> nfds
= np
->fds
;
218 std::shared_ptr
<FDEntry
> this_fde
= (*fds
)[tgt_fd
];
220 nfds
->setFDEntry(tgt_fd
, nullptr);
223 nfds
->setFDEntry(tgt_fd
, this_fde
->clone());
225 auto this_hbfd
= std::dynamic_pointer_cast
<HBFDEntry
>(this_fde
);
229 int this_sim_fd
= this_hbfd
->getSimFD();
230 if (this_sim_fd
<= 2)
233 int np_sim_fd
= dup(this_sim_fd
);
234 assert(np_sim_fd
!= -1);
236 auto nhbfd
= std::dynamic_pointer_cast
<HBFDEntry
>((*nfds
)[tgt_fd
]);
237 nhbfd
->setSimFD(np_sim_fd
);
241 if (CLONE_THREAD
& flags
) {
243 delete np
->exitGroup
;
244 np
->exitGroup
= exitGroup
;
247 np
->argv
.insert(np
->argv
.end(), argv
.begin(), argv
.end());
248 np
->envp
.insert(np
->envp
.end(), envp
.begin(), envp
.end());
254 SimObject::regStats();
256 using namespace Stats
;
259 .name(name() + ".numSyscalls")
260 .desc("Number of system calls")
265 Process::findFreeContext()
267 for (auto &it
: system
->threadContexts
) {
268 if (ThreadContext::Halted
== it
->status())
275 Process::revokeThreadContext(int context_id
)
277 std::vector
<ContextID
>::iterator it
;
278 for (it
= contextIds
.begin(); it
!= contextIds
.end(); it
++) {
279 if (*it
== context_id
) {
280 contextIds
.erase(it
);
284 warn("Unable to find thread context to revoke");
290 if (contextIds
.empty())
291 fatal("Process %s is not associated with any HW contexts!\n", name());
293 // first thread context for this process... initialize & enable
294 ThreadContext
*tc
= system
->getThreadContext(contextIds
[0]);
296 // mark this context as active so it will start ticking.
299 pTable
->initState(tc
);
305 fds
->updateFileOffsets();
306 return DrainState::Drained
;
310 Process::allocateMem(Addr vaddr
, int64_t size
, bool clobber
)
312 int npages
= divCeil(size
, (int64_t)PageBytes
);
313 Addr paddr
= system
->allocPhysPages(npages
);
314 pTable
->map(vaddr
, paddr
, size
,
315 clobber
? PageTableBase::Clobber
: PageTableBase::Zero
);
319 Process::replicatePage(Addr vaddr
, Addr new_paddr
, ThreadContext
*old_tc
,
320 ThreadContext
*new_tc
, bool allocate_page
)
323 new_paddr
= system
->allocPhysPages(1);
325 // Read from old physical page.
326 uint8_t *buf_p
= new uint8_t[PageBytes
];
327 old_tc
->getMemProxy().readBlob(vaddr
, buf_p
, PageBytes
);
329 // Create new mapping in process address space by clobbering existing
330 // mapping (if any existed) and then write to the new physical page.
332 pTable
->map(vaddr
, new_paddr
, PageBytes
, clobber
);
333 new_tc
->getMemProxy().writeBlob(vaddr
, buf_p
, PageBytes
);
338 Process::fixupStackFault(Addr vaddr
)
340 Addr stack_min
= memState
->getStackMin();
341 Addr stack_base
= memState
->getStackBase();
342 Addr max_stack_size
= memState
->getMaxStackSize();
344 // Check if this is already on the stack and there's just no page there
346 if (vaddr
>= stack_min
&& vaddr
< stack_base
) {
347 allocateMem(roundDown(vaddr
, PageBytes
), PageBytes
);
351 // We've accessed the next page of the stack, so extend it to include
353 if (vaddr
< stack_min
&& vaddr
>= stack_base
- max_stack_size
) {
354 while (vaddr
< stack_min
) {
355 stack_min
-= TheISA::PageBytes
;
356 if (stack_base
- stack_min
> max_stack_size
)
357 fatal("Maximum stack size exceeded\n");
358 allocateMem(stack_min
, TheISA::PageBytes
);
359 inform("Increasing stack size by one page.");
361 memState
->setStackMin(stack_min
);
368 Process::serialize(CheckpointOut
&cp
) const
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 pTable
->unserialize(cp
);
389 * Checkpoints for file descriptors currently do not work. Need to
390 * come back and fix them at a later date.
392 warn("Checkpoints for file descriptors currently do not work.");
394 for (int x
= 0; x
< fds
->getSize(); x
++)
395 (*fds
)[x
]->unserializeSection(cp
, csprintf("FDEntry%d", x
));
396 fds
->restoreFileOffsets();
398 // The above returns a bool so that you could do something if you don't
399 // find the param in the checkpoint if you wanted to, like set a default
400 // but in this case we'll just stick with the instantiated value if not
405 Process::map(Addr vaddr
, Addr paddr
, int size
, bool cacheable
)
407 pTable
->map(vaddr
, paddr
, size
,
408 cacheable
? PageTableBase::Zero
: PageTableBase::Uncacheable
);
413 Process::syscall(int64_t callnum
, ThreadContext
*tc
, Fault
*fault
)
417 SyscallDesc
*desc
= getDesc(callnum
);
419 fatal("Syscall %d out of range", callnum
);
421 desc
->doSyscall(callnum
, this, tc
, fault
);
425 Process::getSyscallArg(ThreadContext
*tc
, int &i
, int width
)
427 return getSyscallArg(tc
, i
);
431 Process::findDriver(std::string filename
)
433 for (EmulatedDriver
*d
: drivers
) {
434 if (d
->match(filename
))
442 Process::updateBias()
444 ObjectFile
*interp
= objFile
->getInterpreter();
446 if (!interp
|| !interp
->relocatable())
449 // Determine how large the interpreters footprint will be in the process
451 Addr interp_mapsize
= roundUp(interp
->mapSize(), TheISA::PageBytes
);
453 // We are allocating the memory area; set the bias to the lowest address
454 // in the allocated memory region.
455 Addr mmap_end
= memState
->getMmapEnd();
456 Addr ld_bias
= mmapGrowsDown() ? mmap_end
- interp_mapsize
: mmap_end
;
458 // Adjust the process mmap area to give the interpreter room; the real
459 // execve system call would just invoke the kernel's internal mmap
460 // functions to make these adjustments.
461 mmap_end
= mmapGrowsDown() ? ld_bias
: mmap_end
+ interp_mapsize
;
462 memState
->setMmapEnd(mmap_end
);
464 interp
->updateBias(ld_bias
);
468 Process::getInterpreter()
470 return objFile
->getInterpreter();
476 ObjectFile
*interp
= getInterpreter();
478 return interp
? interp
->bias() : objFile
->bias();
482 Process::getStartPC()
484 ObjectFile
*interp
= getInterpreter();
486 return interp
? interp
->entryPoint() : objFile
->entryPoint();
490 ProcessParams::create()
492 Process
*process
= nullptr;
494 // If not specified, set the executable parameter equal to the
495 // simulated system's zeroth command line parameter
496 if (executable
== "") {
500 ObjectFile
*obj_file
= createObjectFile(executable
);
501 if (obj_file
== nullptr) {
502 fatal("Can't load object file %s", executable
);
505 #if THE_ISA == ALPHA_ISA
506 if (obj_file
->getArch() != ObjectFile::Alpha
)
507 fatal("Object file architecture does not match compiled ISA (Alpha).");
509 switch (obj_file
->getOpSys()) {
510 case ObjectFile::UnknownOpSys
:
511 warn("Unknown operating system; assuming Linux.");
513 case ObjectFile::Linux
:
514 process
= new AlphaLinuxProcess(this, obj_file
);
518 fatal("Unknown/unsupported operating system.");
520 #elif THE_ISA == SPARC_ISA
521 if (obj_file
->getArch() != ObjectFile::SPARC64
&&
522 obj_file
->getArch() != ObjectFile::SPARC32
)
523 fatal("Object file architecture does not match compiled ISA (SPARC).");
524 switch (obj_file
->getOpSys()) {
525 case ObjectFile::UnknownOpSys
:
526 warn("Unknown operating system; assuming Linux.");
528 case ObjectFile::Linux
:
529 if (obj_file
->getArch() == ObjectFile::SPARC64
) {
530 process
= new Sparc64LinuxProcess(this, obj_file
);
532 process
= new Sparc32LinuxProcess(this, obj_file
);
536 case ObjectFile::Solaris
:
537 process
= new SparcSolarisProcess(this, obj_file
);
541 fatal("Unknown/unsupported operating system.");
543 #elif THE_ISA == X86_ISA
544 if (obj_file
->getArch() != ObjectFile::X86_64
&&
545 obj_file
->getArch() != ObjectFile::I386
)
546 fatal("Object file architecture does not match compiled ISA (x86).");
547 switch (obj_file
->getOpSys()) {
548 case ObjectFile::UnknownOpSys
:
549 warn("Unknown operating system; assuming Linux.");
551 case ObjectFile::Linux
:
552 if (obj_file
->getArch() == ObjectFile::X86_64
) {
553 process
= new X86_64LinuxProcess(this, obj_file
);
555 process
= new I386LinuxProcess(this, obj_file
);
560 fatal("Unknown/unsupported operating system.");
562 #elif THE_ISA == MIPS_ISA
563 if (obj_file
->getArch() != ObjectFile::Mips
)
564 fatal("Object file architecture does not match compiled ISA (MIPS).");
565 switch (obj_file
->getOpSys()) {
566 case ObjectFile::UnknownOpSys
:
567 warn("Unknown operating system; assuming Linux.");
569 case ObjectFile::Linux
:
570 process
= new MipsLinuxProcess(this, obj_file
);
574 fatal("Unknown/unsupported operating system.");
576 #elif THE_ISA == ARM_ISA
577 ObjectFile::Arch arch
= obj_file
->getArch();
578 if (arch
!= ObjectFile::Arm
&& arch
!= ObjectFile::Thumb
&&
579 arch
!= ObjectFile::Arm64
)
580 fatal("Object file architecture does not match compiled ISA (ARM).");
581 switch (obj_file
->getOpSys()) {
582 case ObjectFile::UnknownOpSys
:
583 warn("Unknown operating system; assuming Linux.");
585 case ObjectFile::Linux
:
586 if (arch
== ObjectFile::Arm64
) {
587 process
= new ArmLinuxProcess64(this, obj_file
,
588 obj_file
->getArch());
590 process
= new ArmLinuxProcess32(this, obj_file
,
591 obj_file
->getArch());
594 case ObjectFile::FreeBSD
:
595 if (arch
== ObjectFile::Arm64
) {
596 process
= new ArmFreebsdProcess64(this, obj_file
,
597 obj_file
->getArch());
599 process
= new ArmFreebsdProcess32(this, obj_file
,
600 obj_file
->getArch());
603 case ObjectFile::LinuxArmOABI
:
604 fatal("M5 does not support ARM OABI binaries. Please recompile with an"
607 fatal("Unknown/unsupported operating system.");
609 #elif THE_ISA == POWER_ISA
610 if (obj_file
->getArch() != ObjectFile::Power
)
611 fatal("Object file architecture does not match compiled ISA (Power).");
612 switch (obj_file
->getOpSys()) {
613 case ObjectFile::UnknownOpSys
:
614 warn("Unknown operating system; assuming Linux.");
616 case ObjectFile::Linux
:
617 process
= new PowerLinuxProcess(this, obj_file
);
621 fatal("Unknown/unsupported operating system.");
623 #elif THE_ISA == RISCV_ISA
624 if (obj_file
->getArch() != ObjectFile::Riscv
)
625 fatal("Object file architecture does not match compiled ISA (RISCV).");
626 switch (obj_file
->getOpSys()) {
627 case ObjectFile::UnknownOpSys
:
628 warn("Unknown operating system; assuming Linux.");
630 case ObjectFile::Linux
:
631 process
= new RiscvLinuxProcess(this, obj_file
);
634 fatal("Unknown/unsupported operating system.");
637 #error "THE_ISA not set"
640 if (process
== nullptr)
641 fatal("Unknown error creating process object.");
646 Process::fullPath(const std::string
&file_name
)
648 if (file_name
[0] == '/' || cwd
.empty())
651 std::string full
= cwd
;
653 if (cwd
[cwd
.size() - 1] != '/')
656 return full
+ file_name
;