process.cc revision 11885:79af314e9f0d
1/*
2 * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
3 * Copyright (c) 2012 ARM Limited
4 * All rights reserved
5 *
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.
14 *
15 * Copyright (c) 2001-2005 The Regents of The University of Michigan
16 * All rights reserved.
17 *
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.
28 *
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.
40 *
41 * Authors: Nathan Binkert
42 *          Steve Reinhardt
43 *          Ali Saidi
44 *          Brandon Potter
45 */
46
47#include "sim/process.hh"
48
49#include <fcntl.h>
50#include <unistd.h>
51
52#include <array>
53#include <map>
54#include <string>
55#include <vector>
56
57#include "base/intmath.hh"
58#include "base/loader/object_file.hh"
59#include "base/loader/symtab.hh"
60#include "base/statistics.hh"
61#include "config/the_isa.hh"
62#include "cpu/thread_context.hh"
63#include "mem/page_table.hh"
64#include "mem/se_translating_port_proxy.hh"
65#include "params/Process.hh"
66#include "sim/emul_driver.hh"
67#include "sim/fd_array.hh"
68#include "sim/fd_entry.hh"
69#include "sim/syscall_desc.hh"
70#include "sim/system.hh"
71
72#if THE_ISA == ALPHA_ISA
73#include "arch/alpha/linux/process.hh"
74#elif THE_ISA == SPARC_ISA
75#include "arch/sparc/linux/process.hh"
76#include "arch/sparc/solaris/process.hh"
77#elif THE_ISA == MIPS_ISA
78#include "arch/mips/linux/process.hh"
79#elif THE_ISA == ARM_ISA
80#include "arch/arm/linux/process.hh"
81#include "arch/arm/freebsd/process.hh"
82#elif THE_ISA == X86_ISA
83#include "arch/x86/linux/process.hh"
84#elif THE_ISA == POWER_ISA
85#include "arch/power/linux/process.hh"
86#elif THE_ISA == RISCV_ISA
87#include "arch/riscv/linux/process.hh"
88#else
89#error "THE_ISA not set"
90#endif
91
92
93using namespace std;
94using namespace TheISA;
95
96Process::Process(ProcessParams * params, ObjectFile * obj_file)
97    : SimObject(params), system(params->system),
98      brk_point(0), stack_base(0), stack_size(0), stack_min(0),
99      max_stack_size(params->max_stack_size),
100      next_thread_stack_base(0),
101      useArchPT(params->useArchPT),
102      kvmInSE(params->kvmInSE),
103      pTable(useArchPT ?
104        static_cast<PageTableBase *>(new ArchPageTable(name(), params->pid,
105            system)) :
106        static_cast<PageTableBase *>(new FuncPageTable(name(), params->pid))),
107      initVirtMem(system->getSystemPort(), this,
108                  SETranslatingPortProxy::Always),
109      objFile(obj_file),
110      argv(params->cmd), envp(params->env), cwd(params->cwd),
111      executable(params->executable),
112      _uid(params->uid), _euid(params->euid),
113      _gid(params->gid), _egid(params->egid),
114      _pid(params->pid), _ppid(params->ppid),
115      _pgid(params->pgid), drivers(params->drivers),
116      fds(make_shared<FDArray>(params->input, params->output, params->errout))
117{
118    mmap_end = 0;
119
120    if (_pid >= System::maxPID)
121        fatal("_pid is too large: %d", _pid);
122
123    auto ret_pair = system->PIDs.emplace(_pid);
124    if (!ret_pair.second)
125        fatal("_pid %d is already used", _pid);
126
127    // load up symbols, if any... these may be used for debugging or
128    // profiling.
129    if (!debugSymbolTable) {
130        debugSymbolTable = new SymbolTable();
131        if (!objFile->loadGlobalSymbols(debugSymbolTable) ||
132            !objFile->loadLocalSymbols(debugSymbolTable) ||
133            !objFile->loadWeakSymbols(debugSymbolTable)) {
134            // didn't load any symbols
135            delete debugSymbolTable;
136            debugSymbolTable = NULL;
137        }
138    }
139}
140
141void
142Process::regStats()
143{
144    SimObject::regStats();
145
146    using namespace Stats;
147
148    num_syscalls
149        .name(name() + ".num_syscalls")
150        .desc("Number of system calls")
151        ;
152}
153
154ThreadContext *
155Process::findFreeContext()
156{
157    for (int id : contextIds) {
158        ThreadContext *tc = system->getThreadContext(id);
159        if (tc->status() == ThreadContext::Halted)
160            return tc;
161    }
162    return NULL;
163}
164
165void
166Process::initState()
167{
168    if (contextIds.empty())
169        fatal("Process %s is not associated with any HW contexts!\n", name());
170
171    // first thread context for this process... initialize & enable
172    ThreadContext *tc = system->getThreadContext(contextIds[0]);
173
174    // mark this context as active so it will start ticking.
175    tc->activate();
176
177    pTable->initState(tc);
178}
179
180DrainState
181Process::drain()
182{
183    fds->updateFileOffsets();
184    return DrainState::Drained;
185}
186
187void
188Process::allocateMem(Addr vaddr, int64_t size, bool clobber)
189{
190    int npages = divCeil(size, (int64_t)PageBytes);
191    Addr paddr = system->allocPhysPages(npages);
192    pTable->map(vaddr, paddr, size,
193                clobber ? PageTableBase::Clobber : PageTableBase::Zero);
194}
195
196bool
197Process::fixupStackFault(Addr vaddr)
198{
199    // Check if this is already on the stack and there's just no page there
200    // yet.
201    if (vaddr >= stack_min && vaddr < stack_base) {
202        allocateMem(roundDown(vaddr, PageBytes), PageBytes);
203        return true;
204    }
205
206    // We've accessed the next page of the stack, so extend it to include
207    // this address.
208    if (vaddr < stack_min && vaddr >= stack_base - max_stack_size) {
209        while (vaddr < stack_min) {
210            stack_min -= TheISA::PageBytes;
211            if (stack_base - stack_min > max_stack_size)
212                fatal("Maximum stack size exceeded\n");
213            allocateMem(stack_min, TheISA::PageBytes);
214            inform("Increasing stack size by one page.");
215        };
216        return true;
217    }
218    return false;
219}
220
221void
222Process::serialize(CheckpointOut &cp) const
223{
224    SERIALIZE_SCALAR(brk_point);
225    SERIALIZE_SCALAR(stack_base);
226    SERIALIZE_SCALAR(stack_size);
227    SERIALIZE_SCALAR(stack_min);
228    SERIALIZE_SCALAR(next_thread_stack_base);
229    SERIALIZE_SCALAR(mmap_end);
230    pTable->serialize(cp);
231    /**
232     * Checkpoints for file descriptors currently do not work. Need to
233     * come back and fix them at a later date.
234     */
235
236    warn("Checkpoints for file descriptors currently do not work.");
237#if 0
238    for (int x = 0; x < fds->getSize(); x++)
239        (*fds)[x].serializeSection(cp, csprintf("FDEntry%d", x));
240#endif
241
242}
243
244void
245Process::unserialize(CheckpointIn &cp)
246{
247    UNSERIALIZE_SCALAR(brk_point);
248    UNSERIALIZE_SCALAR(stack_base);
249    UNSERIALIZE_SCALAR(stack_size);
250    UNSERIALIZE_SCALAR(stack_min);
251    UNSERIALIZE_SCALAR(next_thread_stack_base);
252    UNSERIALIZE_SCALAR(mmap_end);
253    pTable->unserialize(cp);
254    /**
255     * Checkpoints for file descriptors currently do not work. Need to
256     * come back and fix them at a later date.
257     */
258    warn("Checkpoints for file descriptors currently do not work.");
259#if 0
260    for (int x = 0; x < fds->getSize(); x++)
261        (*fds)[x]->unserializeSection(cp, csprintf("FDEntry%d", x));
262    fds->restoreFileOffsets();
263#endif
264    // The above returns a bool so that you could do something if you don't
265    // find the param in the checkpoint if you wanted to, like set a default
266    // but in this case we'll just stick with the instantiated value if not
267    // found.
268}
269
270bool
271Process::map(Addr vaddr, Addr paddr, int size, bool cacheable)
272{
273    pTable->map(vaddr, paddr, size,
274                cacheable ? PageTableBase::Zero : PageTableBase::Uncacheable);
275    return true;
276}
277
278void
279Process::syscall(int64_t callnum, ThreadContext *tc, Fault *fault)
280{
281    num_syscalls++;
282
283    SyscallDesc *desc = getDesc(callnum);
284    if (desc == NULL)
285        fatal("Syscall %d out of range", callnum);
286
287    desc->doSyscall(callnum, this, tc, fault);
288}
289
290IntReg
291Process::getSyscallArg(ThreadContext *tc, int &i, int width)
292{
293    return getSyscallArg(tc, i);
294}
295
296EmulatedDriver *
297Process::findDriver(std::string filename)
298{
299    for (EmulatedDriver *d : drivers) {
300        if (d->match(filename))
301            return d;
302    }
303
304    return NULL;
305}
306
307void
308Process::updateBias()
309{
310    ObjectFile *interp = objFile->getInterpreter();
311
312    if (!interp || !interp->relocatable())
313        return;
314
315    // Determine how large the interpreters footprint will be in the process
316    // address space.
317    Addr interp_mapsize = roundUp(interp->mapSize(), TheISA::PageBytes);
318
319    // We are allocating the memory area; set the bias to the lowest address
320    // in the allocated memory region.
321    Addr ld_bias = mmapGrowsDown() ? mmap_end - interp_mapsize : mmap_end;
322
323    // Adjust the process mmap area to give the interpreter room; the real
324    // execve system call would just invoke the kernel's internal mmap
325    // functions to make these adjustments.
326    mmap_end = mmapGrowsDown() ? ld_bias : mmap_end + interp_mapsize;
327
328    interp->updateBias(ld_bias);
329}
330
331ObjectFile *
332Process::getInterpreter()
333{
334    return objFile->getInterpreter();
335}
336
337Addr
338Process::getBias()
339{
340    ObjectFile *interp = getInterpreter();
341
342    return interp ? interp->bias() : objFile->bias();
343}
344
345Addr
346Process::getStartPC()
347{
348    ObjectFile *interp = getInterpreter();
349
350    return interp ? interp->entryPoint() : objFile->entryPoint();
351}
352
353Process *
354ProcessParams::create()
355{
356    Process *process = NULL;
357
358    // If not specified, set the executable parameter equal to the
359    // simulated system's zeroth command line parameter
360    if (executable == "") {
361        executable = cmd[0];
362    }
363
364    ObjectFile *obj_file = createObjectFile(executable);
365    if (obj_file == NULL) {
366        fatal("Can't load object file %s", executable);
367    }
368
369#if THE_ISA == ALPHA_ISA
370    if (obj_file->getArch() != ObjectFile::Alpha)
371        fatal("Object file architecture does not match compiled ISA (Alpha).");
372
373    switch (obj_file->getOpSys()) {
374      case ObjectFile::UnknownOpSys:
375        warn("Unknown operating system; assuming Linux.");
376        // fall through
377      case ObjectFile::Linux:
378        process = new AlphaLinuxProcess(this, obj_file);
379        break;
380
381      default:
382        fatal("Unknown/unsupported operating system.");
383    }
384#elif THE_ISA == SPARC_ISA
385    if (obj_file->getArch() != ObjectFile::SPARC64 &&
386        obj_file->getArch() != ObjectFile::SPARC32)
387        fatal("Object file architecture does not match compiled ISA (SPARC).");
388    switch (obj_file->getOpSys()) {
389      case ObjectFile::UnknownOpSys:
390        warn("Unknown operating system; assuming Linux.");
391        // fall through
392      case ObjectFile::Linux:
393        if (obj_file->getArch() == ObjectFile::SPARC64) {
394            process = new Sparc64LinuxProcess(this, obj_file);
395        } else {
396            process = new Sparc32LinuxProcess(this, obj_file);
397        }
398        break;
399
400      case ObjectFile::Solaris:
401        process = new SparcSolarisProcess(this, obj_file);
402        break;
403
404      default:
405        fatal("Unknown/unsupported operating system.");
406    }
407#elif THE_ISA == X86_ISA
408    if (obj_file->getArch() != ObjectFile::X86_64 &&
409        obj_file->getArch() != ObjectFile::I386)
410        fatal("Object file architecture does not match compiled ISA (x86).");
411    switch (obj_file->getOpSys()) {
412      case ObjectFile::UnknownOpSys:
413        warn("Unknown operating system; assuming Linux.");
414        // fall through
415      case ObjectFile::Linux:
416        if (obj_file->getArch() == ObjectFile::X86_64) {
417            process = new X86_64LinuxProcess(this, obj_file);
418        } else {
419            process = new I386LinuxProcess(this, obj_file);
420        }
421        break;
422
423      default:
424        fatal("Unknown/unsupported operating system.");
425    }
426#elif THE_ISA == MIPS_ISA
427    if (obj_file->getArch() != ObjectFile::Mips)
428        fatal("Object file architecture does not match compiled ISA (MIPS).");
429    switch (obj_file->getOpSys()) {
430      case ObjectFile::UnknownOpSys:
431        warn("Unknown operating system; assuming Linux.");
432        // fall through
433      case ObjectFile::Linux:
434        process = new MipsLinuxProcess(this, obj_file);
435        break;
436
437      default:
438        fatal("Unknown/unsupported operating system.");
439    }
440#elif THE_ISA == ARM_ISA
441    ObjectFile::Arch arch = obj_file->getArch();
442    if (arch != ObjectFile::Arm && arch != ObjectFile::Thumb &&
443        arch != ObjectFile::Arm64)
444        fatal("Object file architecture does not match compiled ISA (ARM).");
445    switch (obj_file->getOpSys()) {
446      case ObjectFile::UnknownOpSys:
447        warn("Unknown operating system; assuming Linux.");
448        // fall through
449      case ObjectFile::Linux:
450        if (arch == ObjectFile::Arm64) {
451            process = new ArmLinuxProcess64(this, obj_file,
452                                            obj_file->getArch());
453        } else {
454            process = new ArmLinuxProcess32(this, obj_file,
455                                            obj_file->getArch());
456        }
457        break;
458      case ObjectFile::FreeBSD:
459        if (arch == ObjectFile::Arm64) {
460            process = new ArmFreebsdProcess64(this, obj_file,
461                                              obj_file->getArch());
462        } else {
463            process = new ArmFreebsdProcess32(this, obj_file,
464                                              obj_file->getArch());
465        }
466        break;
467      case ObjectFile::LinuxArmOABI:
468        fatal("M5 does not support ARM OABI binaries. Please recompile with an"
469              " EABI compiler.");
470      default:
471        fatal("Unknown/unsupported operating system.");
472    }
473#elif THE_ISA == POWER_ISA
474    if (obj_file->getArch() != ObjectFile::Power)
475        fatal("Object file architecture does not match compiled ISA (Power).");
476    switch (obj_file->getOpSys()) {
477      case ObjectFile::UnknownOpSys:
478        warn("Unknown operating system; assuming Linux.");
479        // fall through
480      case ObjectFile::Linux:
481        process = new PowerLinuxProcess(this, obj_file);
482        break;
483
484      default:
485        fatal("Unknown/unsupported operating system.");
486    }
487#elif THE_ISA == RISCV_ISA
488    if (obj_file->getArch() != ObjectFile::Riscv)
489        fatal("Object file architecture does not match compiled ISA (RISCV).");
490    switch (obj_file->getOpSys()) {
491      case ObjectFile::UnknownOpSys:
492        warn("Unknown operating system; assuming Linux.");
493        // fall through
494      case ObjectFile::Linux:
495        process = new RiscvLinuxProcess(this, obj_file);
496        break;
497      default:
498        fatal("Unknown/unsupported operating system.");
499    }
500#else
501#error "THE_ISA not set"
502#endif
503
504    if (process == NULL)
505        fatal("Unknown error creating process object.");
506    return process;
507}
508
509std::string
510Process::fullPath(const std::string &file_name)
511{
512    if (file_name[0] == '/' || cwd.empty())
513        return file_name;
514
515    std::string full = cwd;
516
517    if (cwd[cwd.size() - 1] != '/')
518        full += '/';
519
520    return full + file_name;
521}
522