process.hh revision 7447:3fc243687abb
14123Sbinkertn@umich.edu/*
24123Sbinkertn@umich.edu * Copyright (c) 2001-2005 The Regents of The University of Michigan
39983Sstever@gmail.com * All rights reserved.
49983Sstever@gmail.com *
54123Sbinkertn@umich.edu * Redistribution and use in source and binary forms, with or without
64123Sbinkertn@umich.edu * modification, are permitted provided that the following conditions are
74123Sbinkertn@umich.edu * met: redistributions of source code must retain the above copyright
84123Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer;
94123Sbinkertn@umich.edu * redistributions in binary form must reproduce the above copyright
104123Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer in the
114123Sbinkertn@umich.edu * documentation and/or other materials provided with the distribution;
124123Sbinkertn@umich.edu * neither the name of the copyright holders nor the names of its
134123Sbinkertn@umich.edu * contributors may be used to endorse or promote products derived from
144123Sbinkertn@umich.edu * this software without specific prior written permission.
154123Sbinkertn@umich.edu *
164123Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
174123Sbinkertn@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
184123Sbinkertn@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
194123Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
204123Sbinkertn@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
214123Sbinkertn@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
224123Sbinkertn@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
234123Sbinkertn@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
244123Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
254123Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
264123Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
274123Sbinkertn@umich.edu *
284123Sbinkertn@umich.edu * Authors: Nathan Binkert
294123Sbinkertn@umich.edu *          Steve Reinhardt
304123Sbinkertn@umich.edu */
314123Sbinkertn@umich.edu
324123Sbinkertn@umich.edu#ifndef __PROCESS_HH__
334123Sbinkertn@umich.edu#define __PROCESS_HH__
349983Sstever@gmail.com
359983Sstever@gmail.com//
369983Sstever@gmail.com// The purpose of this code is to fake the loader & syscall mechanism
374123Sbinkertn@umich.edu// when there's no OS: thus there's no reason to use it in FULL_SYSTEM
384123Sbinkertn@umich.edu// mode when we do have an OS.
396216Snate@binkert.org//
404123Sbinkertn@umich.edu#include "config/full_system.hh"
419356Snilay@cs.wisc.edu
424123Sbinkertn@umich.edu#if !FULL_SYSTEM
434123Sbinkertn@umich.edu
444123Sbinkertn@umich.edu#include <string>
456216Snate@binkert.org#include <vector>
464123Sbinkertn@umich.edu
479983Sstever@gmail.com#include "arch/registers.hh"
489983Sstever@gmail.com#include "base/statistics.hh"
499983Sstever@gmail.com#include "base/types.hh"
509983Sstever@gmail.com#include "config/the_isa.hh"
519983Sstever@gmail.com#include "sim/sim_object.hh"
529983Sstever@gmail.com#include "sim/syscallreturn.hh"
539983Sstever@gmail.com
549983Sstever@gmail.comclass PageTable;
559983Sstever@gmail.comclass ProcessParams;
569983Sstever@gmail.comclass LiveProcessParams;
579983Sstever@gmail.comclass SyscallDesc;
589983Sstever@gmail.comclass System;
599983Sstever@gmail.comclass ThreadContext;
609983Sstever@gmail.comclass TranslatingPort;
619983Sstever@gmail.com
629983Sstever@gmail.comtemplate<class IntType>
639983Sstever@gmail.comstruct AuxVector
649983Sstever@gmail.com{
659983Sstever@gmail.com    IntType a_type;
669983Sstever@gmail.com    IntType a_val;
679983Sstever@gmail.com
689983Sstever@gmail.com    AuxVector()
699983Sstever@gmail.com    {}
709983Sstever@gmail.com
719983Sstever@gmail.com    AuxVector(IntType type, IntType val);
729983Sstever@gmail.com};
739983Sstever@gmail.com
7410762SCurtis.Dunham@arm.comclass Process : public SimObject
7510756SCurtis.Dunham@arm.com{
764123Sbinkertn@umich.edu  public:
774123Sbinkertn@umich.edu
784123Sbinkertn@umich.edu    /// Pointer to object representing the system this process is
794123Sbinkertn@umich.edu    /// running on.
804123Sbinkertn@umich.edu    System *system;
819983Sstever@gmail.com
824123Sbinkertn@umich.edu    // have we initialized a thread context from this process?  If
834123Sbinkertn@umich.edu    // yes, subsequent contexts are assumed to be for dynamically
849983Sstever@gmail.com    // created threads and are not initialized.
859983Sstever@gmail.com    bool initialContextLoaded;
869983Sstever@gmail.com
879983Sstever@gmail.com    bool checkpointRestored;
889983Sstever@gmail.com
899983Sstever@gmail.com    // thread contexts associated with this process
909983Sstever@gmail.com    std::vector<int> contextIds;
919983Sstever@gmail.com
929983Sstever@gmail.com    // number of CPUs (esxec contexts, really) assigned to this process.
939983Sstever@gmail.com    unsigned int numCpus() { return contextIds.size(); }
949983Sstever@gmail.com
959983Sstever@gmail.com    // record of blocked context
969983Sstever@gmail.com    struct WaitRec
979983Sstever@gmail.com    {
989983Sstever@gmail.com        Addr waitChan;
999983Sstever@gmail.com        ThreadContext *waitingContext;
1009983Sstever@gmail.com
10110762SCurtis.Dunham@arm.com        WaitRec(Addr chan, ThreadContext *ctx)
10210762SCurtis.Dunham@arm.com            : waitChan(chan), waitingContext(ctx)
10310762SCurtis.Dunham@arm.com        {       }
1049983Sstever@gmail.com    };
1059983Sstever@gmail.com
1067823Ssteve.reinhardt@amd.com    // list of all blocked contexts
1074123Sbinkertn@umich.edu    std::list<WaitRec> waitList;
1089174Satgutier@umich.edu
1099174Satgutier@umich.edu    Addr brk_point;             // top of the data segment
1109174Satgutier@umich.edu
1114123Sbinkertn@umich.edu    Addr stack_base;            // stack segment base (highest address)
1124123Sbinkertn@umich.edu    unsigned stack_size;        // initial stack size
11310762SCurtis.Dunham@arm.com    Addr stack_min;             // lowest address accessed on the stack
1149983Sstever@gmail.com
1159983Sstever@gmail.com    // The maximum size allowed for the stack.
1169983Sstever@gmail.com    Addr max_stack_size;
1179983Sstever@gmail.com
1189983Sstever@gmail.com    // addr to use for next stack region (for multithreaded apps)
1199983Sstever@gmail.com    Addr next_thread_stack_base;
1209983Sstever@gmail.com
12110101Sandreas@sandberg.pp.se    // Base of region for mmaps (when user doesn't specify an address).
1229983Sstever@gmail.com    Addr mmap_start;
1239983Sstever@gmail.com    Addr mmap_end;
1249983Sstever@gmail.com
1259983Sstever@gmail.com    // Base of region for nxm data
1269983Sstever@gmail.com    Addr nxm_start;
1279983Sstever@gmail.com    Addr nxm_end;
1289983Sstever@gmail.com
1299983Sstever@gmail.com    std::string prog_fname;     // file name
1309983Sstever@gmail.com
1319983Sstever@gmail.com    Stats::Scalar num_syscalls;       // number of syscalls executed
1329983Sstever@gmail.com
1339983Sstever@gmail.com
1349983Sstever@gmail.com  protected:
1359983Sstever@gmail.com    // constructor
1369983Sstever@gmail.com    Process(ProcessParams * params);
1379983Sstever@gmail.com
1389983Sstever@gmail.com    // post initialization startup
1399983Sstever@gmail.com    virtual void startup();
1409983Sstever@gmail.com
1419983Sstever@gmail.com  protected:
1429983Sstever@gmail.com    /// Memory object for initialization (image loading)
1439983Sstever@gmail.com    TranslatingPort *initVirtMem;
1449983Sstever@gmail.com
1459983Sstever@gmail.com  public:
1469983Sstever@gmail.com    PageTable *pTable;
1479983Sstever@gmail.com
1489983Sstever@gmail.com    //This id is assigned by m5 and is used to keep process' tlb entries
1499983Sstever@gmail.com    //separated.
1509983Sstever@gmail.com    uint64_t M5_pid;
1519983Sstever@gmail.com
1529983Sstever@gmail.com    class FdMap
1539983Sstever@gmail.com    {
1549983Sstever@gmail.com      public:
1559983Sstever@gmail.com            int fd;
1569983Sstever@gmail.com            std::string filename;
1579983Sstever@gmail.com            int mode;
1589983Sstever@gmail.com            int flags;
1599983Sstever@gmail.com            bool isPipe;
1609983Sstever@gmail.com            int readPipeSource;
1619983Sstever@gmail.com            uint64_t fileOffset;
1629983Sstever@gmail.com
1639983Sstever@gmail.com
1649983Sstever@gmail.com            FdMap()
1659983Sstever@gmail.com            {
1669983Sstever@gmail.com                    fd = -1;
1679983Sstever@gmail.com                    filename = "NULL";
1689983Sstever@gmail.com                    mode = 0;
1699983Sstever@gmail.com                    flags = 0;
1709983Sstever@gmail.com                    isPipe = false;
1719983Sstever@gmail.com                    readPipeSource = 0;
1729983Sstever@gmail.com                    fileOffset = 0;
1739983Sstever@gmail.com
1749983Sstever@gmail.com            }
1759983Sstever@gmail.com
1769983Sstever@gmail.com        void serialize(std::ostream &os);
1779983Sstever@gmail.com        void unserialize(Checkpoint *cp, const std::string &section);
1789983Sstever@gmail.com
1799983Sstever@gmail.com    };
1809983Sstever@gmail.com
1819983Sstever@gmail.com  private:
1829983Sstever@gmail.com    // file descriptor remapping support
1839983Sstever@gmail.com    static const int MAX_FD = 256;    // max legal fd value
1844123Sbinkertn@umich.edu    FdMap fd_map[MAX_FD+1];
1854123Sbinkertn@umich.edu
1864123Sbinkertn@umich.edu
1874123Sbinkertn@umich.edu  public:
1889983Sstever@gmail.com    // static helper functions to generate file descriptors for constructor
1899983Sstever@gmail.com    static int openInputFile(const std::string &filename);
1904123Sbinkertn@umich.edu    static int openOutputFile(const std::string &filename);
1914123Sbinkertn@umich.edu
1929983Sstever@gmail.com    // override of virtual SimObject method: register statistics
19310153Sandreas@sandberg.pp.se    virtual void regStats();
19410153Sandreas@sandberg.pp.se
19510153Sandreas@sandberg.pp.se    // After getting registered with system object, tell process which
1964123Sbinkertn@umich.edu    // system-wide context id it is assigned.
1977822Ssteve.reinhardt@amd.com    void assignThreadContext(int context_id)
1984123Sbinkertn@umich.edu    {
1994123Sbinkertn@umich.edu        contextIds.push_back(context_id);
2004123Sbinkertn@umich.edu    }
2014123Sbinkertn@umich.edu
20210670SCurtis.Dunham@arm.com    // Find a free context to use
20310670SCurtis.Dunham@arm.com    ThreadContext * findFreeContext();
20410670SCurtis.Dunham@arm.com
20510670SCurtis.Dunham@arm.com    // map simulator fd sim_fd to target fd tgt_fd
20610670SCurtis.Dunham@arm.com    void dup_fd(int sim_fd, int tgt_fd);
2074123Sbinkertn@umich.edu
2084123Sbinkertn@umich.edu    // generate new target fd for sim_fd
2094123Sbinkertn@umich.edu    int alloc_fd(int sim_fd, std::string filename, int flags, int mode, bool pipe);
2104123Sbinkertn@umich.edu
2114123Sbinkertn@umich.edu    // free target fd (e.g., after close)
2124123Sbinkertn@umich.edu    void free_fd(int tgt_fd);
2134123Sbinkertn@umich.edu
2144123Sbinkertn@umich.edu    // look up simulator fd for given target fd
2154123Sbinkertn@umich.edu    int sim_fd(int tgt_fd);
2164123Sbinkertn@umich.edu
21710670SCurtis.Dunham@arm.com    // look up simulator fd_map object for a given target fd
21810670SCurtis.Dunham@arm.com    FdMap * sim_fd_obj(int tgt_fd);
21910670SCurtis.Dunham@arm.com
22010670SCurtis.Dunham@arm.com    // fix all offsets for currently open files and save them
22110670SCurtis.Dunham@arm.com    void fix_file_offsets();
2224123Sbinkertn@umich.edu
2234123Sbinkertn@umich.edu    // find all offsets for currently open files and save them
2244123Sbinkertn@umich.edu    void find_file_offsets();
2254123Sbinkertn@umich.edu
226    // set the source of this read pipe for a checkpoint resume
227    void setReadPipeSource(int read_pipe_fd, int source_fd);
228
229    virtual void syscall(int64_t callnum, ThreadContext *tc) = 0;
230
231    // check if the this addr is on the next available page and allocate it
232    // if it's not we'll panic
233    bool checkAndAllocNextPage(Addr vaddr);
234
235    void serialize(std::ostream &os);
236    void unserialize(Checkpoint *cp, const std::string &section);
237};
238
239//
240// "Live" process with system calls redirected to host system
241//
242class ObjectFile;
243class LiveProcess : public Process
244{
245  protected:
246    ObjectFile *objFile;
247    std::vector<std::string> argv;
248    std::vector<std::string> envp;
249    std::string cwd;
250
251    LiveProcess(LiveProcessParams * params, ObjectFile *objFile);
252
253    virtual void argsInit(int intSize, int pageSize);
254
255    // Id of the owner of the process
256    uint64_t __uid;
257    uint64_t __euid;
258    uint64_t __gid;
259    uint64_t __egid;
260
261    // pid of the process and it's parent
262    uint64_t __pid;
263    uint64_t __ppid;
264
265  public:
266
267    enum AuxiliaryVectorType {
268        M5_AT_NULL = 0,
269        M5_AT_IGNORE = 1,
270        M5_AT_EXECFD = 2,
271        M5_AT_PHDR = 3,
272        M5_AT_PHENT = 4,
273        M5_AT_PHNUM = 5,
274        M5_AT_PAGESZ = 6,
275        M5_AT_BASE = 7,
276        M5_AT_FLAGS = 8,
277        M5_AT_ENTRY = 9,
278        M5_AT_NOTELF = 10,
279        M5_AT_UID = 11,
280        M5_AT_EUID = 12,
281        M5_AT_GID = 13,
282        M5_AT_EGID = 14,
283        // The following may be specific to Linux
284        M5_AT_PLATFORM = 15,
285        M5_AT_HWCAP = 16,
286        M5_AT_CLKTCK = 17,
287
288        M5_AT_SECURE = 23,
289        M5_BASE_PLATFORM = 24,
290        M5_AT_RANDOM = 25,
291
292        M5_AT_EXECFN = 31,
293
294        M5_AT_VECTOR_SIZE = 44
295    };
296
297    inline uint64_t uid() {return __uid;}
298    inline uint64_t euid() {return __euid;}
299    inline uint64_t gid() {return __gid;}
300    inline uint64_t egid() {return __egid;}
301    inline uint64_t pid() {return __pid;}
302    inline uint64_t ppid() {return __ppid;}
303
304    std::string
305    fullPath(const std::string &filename)
306    {
307        if (filename[0] == '/' || cwd.empty())
308            return filename;
309
310        std::string full = cwd;
311
312        if (cwd[cwd.size() - 1] != '/')
313            full += '/';
314
315        return full + filename;
316    }
317
318    std::string getcwd() const { return cwd; }
319
320    virtual void syscall(int64_t callnum, ThreadContext *tc);
321
322    virtual TheISA::IntReg getSyscallArg(ThreadContext *tc, int &i) = 0;
323    virtual TheISA::IntReg getSyscallArg(ThreadContext *tc, int &i, int width);
324    virtual void setSyscallArg(ThreadContext *tc,
325            int i, TheISA::IntReg val) = 0;
326    virtual void setSyscallReturn(ThreadContext *tc,
327            SyscallReturn return_value) = 0;
328
329    virtual SyscallDesc* getDesc(int callnum) = 0;
330
331    // this function is used to create the LiveProcess object, since
332    // we can't tell which subclass of LiveProcess to use until we
333    // open and look at the object file.
334    static LiveProcess *create(LiveProcessParams * params);
335};
336
337
338#endif // !FULL_SYSTEM
339
340#endif // __PROCESS_HH__
341