process.hh revision 6701:4842482e1bd1
19651SAndreas.Sandberg@ARM.com/* 29651SAndreas.Sandberg@ARM.com * Copyright (c) 2001-2005 The Regents of The University of Michigan 39651SAndreas.Sandberg@ARM.com * All rights reserved. 49651SAndreas.Sandberg@ARM.com * 59651SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without 69651SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are 79651SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright 89651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer; 99651SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright 109651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the 119651SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution; 129651SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its 139651SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from 149651SAndreas.Sandberg@ARM.com * this software without specific prior written permission. 159651SAndreas.Sandberg@ARM.com * 169651SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 179651SAndreas.Sandberg@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 189651SAndreas.Sandberg@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 199651SAndreas.Sandberg@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 209651SAndreas.Sandberg@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 219651SAndreas.Sandberg@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 229651SAndreas.Sandberg@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 239651SAndreas.Sandberg@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 249651SAndreas.Sandberg@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 259651SAndreas.Sandberg@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 269651SAndreas.Sandberg@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 279651SAndreas.Sandberg@ARM.com * 289651SAndreas.Sandberg@ARM.com * Authors: Nathan Binkert 299651SAndreas.Sandberg@ARM.com * Steve Reinhardt 309651SAndreas.Sandberg@ARM.com */ 319651SAndreas.Sandberg@ARM.com 329651SAndreas.Sandberg@ARM.com#ifndef __PROCESS_HH__ 339651SAndreas.Sandberg@ARM.com#define __PROCESS_HH__ 349651SAndreas.Sandberg@ARM.com 359651SAndreas.Sandberg@ARM.com// 369651SAndreas.Sandberg@ARM.com// The purpose of this code is to fake the loader & syscall mechanism 379651SAndreas.Sandberg@ARM.com// when there's no OS: thus there's no reason to use it in FULL_SYSTEM 389651SAndreas.Sandberg@ARM.com// mode when we do have an OS. 399651SAndreas.Sandberg@ARM.com// 409651SAndreas.Sandberg@ARM.com#include "config/full_system.hh" 419651SAndreas.Sandberg@ARM.com 429651SAndreas.Sandberg@ARM.com#if !FULL_SYSTEM 439651SAndreas.Sandberg@ARM.com 449651SAndreas.Sandberg@ARM.com#include <string> 459655SAndreas.Sandberg@ARM.com#include <vector> 469651SAndreas.Sandberg@ARM.com 479651SAndreas.Sandberg@ARM.com#include "arch/registers.hh" 489651SAndreas.Sandberg@ARM.com#include "base/statistics.hh" 499651SAndreas.Sandberg@ARM.com#include "base/types.hh" 509651SAndreas.Sandberg@ARM.com#include "config/the_isa.hh" 519651SAndreas.Sandberg@ARM.com#include "sim/sim_object.hh" 529651SAndreas.Sandberg@ARM.com#include "sim/syscallreturn.hh" 539651SAndreas.Sandberg@ARM.com 549651SAndreas.Sandberg@ARM.comclass BaseRemoteGDB; 559651SAndreas.Sandberg@ARM.comclass GDBListener; 569651SAndreas.Sandberg@ARM.comclass PageTable; 579651SAndreas.Sandberg@ARM.comclass ProcessParams; 589651SAndreas.Sandberg@ARM.comclass LiveProcessParams; 599651SAndreas.Sandberg@ARM.comclass SyscallDesc; 609651SAndreas.Sandberg@ARM.comclass System; 619651SAndreas.Sandberg@ARM.comclass ThreadContext; 629651SAndreas.Sandberg@ARM.comclass TranslatingPort; 639651SAndreas.Sandberg@ARM.com 649651SAndreas.Sandberg@ARM.comtemplate<class IntType> 659651SAndreas.Sandberg@ARM.comstruct AuxVector 669651SAndreas.Sandberg@ARM.com{ 679651SAndreas.Sandberg@ARM.com IntType a_type; 689651SAndreas.Sandberg@ARM.com IntType a_val; 699651SAndreas.Sandberg@ARM.com 709651SAndreas.Sandberg@ARM.com AuxVector() 719651SAndreas.Sandberg@ARM.com {} 729651SAndreas.Sandberg@ARM.com 739651SAndreas.Sandberg@ARM.com AuxVector(IntType type, IntType val); 749651SAndreas.Sandberg@ARM.com}; 759651SAndreas.Sandberg@ARM.com 769651SAndreas.Sandberg@ARM.comclass Process : public SimObject 779651SAndreas.Sandberg@ARM.com{ 789651SAndreas.Sandberg@ARM.com public: 799651SAndreas.Sandberg@ARM.com 809651SAndreas.Sandberg@ARM.com /// Pointer to object representing the system this process is 819651SAndreas.Sandberg@ARM.com /// running on. 829651SAndreas.Sandberg@ARM.com System *system; 839651SAndreas.Sandberg@ARM.com 849651SAndreas.Sandberg@ARM.com // have we initialized a thread context from this process? If 859651SAndreas.Sandberg@ARM.com // yes, subsequent contexts are assumed to be for dynamically 869651SAndreas.Sandberg@ARM.com // created threads and are not initialized. 879651SAndreas.Sandberg@ARM.com bool initialContextLoaded; 889651SAndreas.Sandberg@ARM.com 899651SAndreas.Sandberg@ARM.com bool checkpointRestored; 909651SAndreas.Sandberg@ARM.com 919651SAndreas.Sandberg@ARM.com // thread contexts associated with this process 929651SAndreas.Sandberg@ARM.com std::vector<int> contextIds; 939651SAndreas.Sandberg@ARM.com 949651SAndreas.Sandberg@ARM.com // remote gdb objects 959651SAndreas.Sandberg@ARM.com std::vector<BaseRemoteGDB *> remoteGDB; 969651SAndreas.Sandberg@ARM.com std::vector<GDBListener *> gdbListen; 979651SAndreas.Sandberg@ARM.com bool breakpoint(); 989651SAndreas.Sandberg@ARM.com 999651SAndreas.Sandberg@ARM.com // number of CPUs (esxec contexts, really) assigned to this process. 1009651SAndreas.Sandberg@ARM.com unsigned int numCpus() { return contextIds.size(); } 1019651SAndreas.Sandberg@ARM.com 1029651SAndreas.Sandberg@ARM.com // record of blocked context 1039651SAndreas.Sandberg@ARM.com struct WaitRec 1049651SAndreas.Sandberg@ARM.com { 1059651SAndreas.Sandberg@ARM.com Addr waitChan; 1069651SAndreas.Sandberg@ARM.com ThreadContext *waitingContext; 1079651SAndreas.Sandberg@ARM.com 1089651SAndreas.Sandberg@ARM.com WaitRec(Addr chan, ThreadContext *ctx) 1099651SAndreas.Sandberg@ARM.com : waitChan(chan), waitingContext(ctx) 1109651SAndreas.Sandberg@ARM.com { } 1119651SAndreas.Sandberg@ARM.com }; 1129651SAndreas.Sandberg@ARM.com 1139651SAndreas.Sandberg@ARM.com // list of all blocked contexts 1149651SAndreas.Sandberg@ARM.com std::list<WaitRec> waitList; 1159651SAndreas.Sandberg@ARM.com 1169651SAndreas.Sandberg@ARM.com Addr brk_point; // top of the data segment 1179651SAndreas.Sandberg@ARM.com 1189651SAndreas.Sandberg@ARM.com Addr stack_base; // stack segment base (highest address) 1199651SAndreas.Sandberg@ARM.com unsigned stack_size; // initial stack size 1209651SAndreas.Sandberg@ARM.com Addr stack_min; // lowest address accessed on the stack 1219651SAndreas.Sandberg@ARM.com 1229651SAndreas.Sandberg@ARM.com // The maximum size allowed for the stack. 1239651SAndreas.Sandberg@ARM.com Addr max_stack_size; 1249651SAndreas.Sandberg@ARM.com 1259651SAndreas.Sandberg@ARM.com // addr to use for next stack region (for multithreaded apps) 1269651SAndreas.Sandberg@ARM.com Addr next_thread_stack_base; 1279651SAndreas.Sandberg@ARM.com 1289651SAndreas.Sandberg@ARM.com // Base of region for mmaps (when user doesn't specify an address). 1299651SAndreas.Sandberg@ARM.com Addr mmap_start; 1309651SAndreas.Sandberg@ARM.com Addr mmap_end; 1319651SAndreas.Sandberg@ARM.com 1329651SAndreas.Sandberg@ARM.com // Base of region for nxm data 1339651SAndreas.Sandberg@ARM.com Addr nxm_start; 1349651SAndreas.Sandberg@ARM.com Addr nxm_end; 1359651SAndreas.Sandberg@ARM.com 1369651SAndreas.Sandberg@ARM.com std::string prog_fname; // file name 1379651SAndreas.Sandberg@ARM.com 1389651SAndreas.Sandberg@ARM.com Stats::Scalar num_syscalls; // number of syscalls executed 1399651SAndreas.Sandberg@ARM.com 1409651SAndreas.Sandberg@ARM.com 1419651SAndreas.Sandberg@ARM.com protected: 1429651SAndreas.Sandberg@ARM.com // constructor 1439651SAndreas.Sandberg@ARM.com Process(ProcessParams * params); 1449651SAndreas.Sandberg@ARM.com 1459651SAndreas.Sandberg@ARM.com // post initialization startup 1469651SAndreas.Sandberg@ARM.com virtual void startup(); 1479651SAndreas.Sandberg@ARM.com 1489651SAndreas.Sandberg@ARM.com protected: 1499651SAndreas.Sandberg@ARM.com /// Memory object for initialization (image loading) 1509651SAndreas.Sandberg@ARM.com TranslatingPort *initVirtMem; 1519651SAndreas.Sandberg@ARM.com 1529651SAndreas.Sandberg@ARM.com public: 1539651SAndreas.Sandberg@ARM.com PageTable *pTable; 1549651SAndreas.Sandberg@ARM.com 1559651SAndreas.Sandberg@ARM.com //This id is assigned by m5 and is used to keep process' tlb entries 1569651SAndreas.Sandberg@ARM.com //separated. 1579651SAndreas.Sandberg@ARM.com uint64_t M5_pid; 1589651SAndreas.Sandberg@ARM.com 1599651SAndreas.Sandberg@ARM.com class FdMap 1609651SAndreas.Sandberg@ARM.com { 1619651SAndreas.Sandberg@ARM.com public: 1629651SAndreas.Sandberg@ARM.com int fd; 1639651SAndreas.Sandberg@ARM.com std::string filename; 1649651SAndreas.Sandberg@ARM.com int mode; 1659651SAndreas.Sandberg@ARM.com int flags; 1669651SAndreas.Sandberg@ARM.com bool isPipe; 1679651SAndreas.Sandberg@ARM.com int readPipeSource; 1689651SAndreas.Sandberg@ARM.com uint64_t fileOffset; 1699651SAndreas.Sandberg@ARM.com 1709651SAndreas.Sandberg@ARM.com 1719651SAndreas.Sandberg@ARM.com FdMap() 1729651SAndreas.Sandberg@ARM.com { 1739651SAndreas.Sandberg@ARM.com fd = -1; 1749651SAndreas.Sandberg@ARM.com filename = "NULL"; 1759651SAndreas.Sandberg@ARM.com mode = 0; 1769651SAndreas.Sandberg@ARM.com flags = 0; 1779651SAndreas.Sandberg@ARM.com isPipe = false; 1789651SAndreas.Sandberg@ARM.com readPipeSource = 0; 1799651SAndreas.Sandberg@ARM.com fileOffset = 0; 1809651SAndreas.Sandberg@ARM.com 1819651SAndreas.Sandberg@ARM.com } 1829651SAndreas.Sandberg@ARM.com 1839651SAndreas.Sandberg@ARM.com void serialize(std::ostream &os); 1849651SAndreas.Sandberg@ARM.com void unserialize(Checkpoint *cp, const std::string §ion); 1859651SAndreas.Sandberg@ARM.com 1869651SAndreas.Sandberg@ARM.com }; 1879651SAndreas.Sandberg@ARM.com 1889651SAndreas.Sandberg@ARM.com private: 1899651SAndreas.Sandberg@ARM.com // file descriptor remapping support 1909651SAndreas.Sandberg@ARM.com static const int MAX_FD = 256; // max legal fd value 1919651SAndreas.Sandberg@ARM.com FdMap fd_map[MAX_FD+1]; 1929651SAndreas.Sandberg@ARM.com 1939651SAndreas.Sandberg@ARM.com 1949651SAndreas.Sandberg@ARM.com public: 1959651SAndreas.Sandberg@ARM.com // static helper functions to generate file descriptors for constructor 1969651SAndreas.Sandberg@ARM.com static int openInputFile(const std::string &filename); 1979651SAndreas.Sandberg@ARM.com static int openOutputFile(const std::string &filename); 1989651SAndreas.Sandberg@ARM.com 1999651SAndreas.Sandberg@ARM.com // override of virtual SimObject method: register statistics 2009651SAndreas.Sandberg@ARM.com virtual void regStats(); 2019651SAndreas.Sandberg@ARM.com 2029651SAndreas.Sandberg@ARM.com // After getting registered with system object, tell process which 2039651SAndreas.Sandberg@ARM.com // system-wide context id it is assigned. 2049651SAndreas.Sandberg@ARM.com void assignThreadContext(int context_id) 2059651SAndreas.Sandberg@ARM.com { 2069651SAndreas.Sandberg@ARM.com contextIds.push_back(context_id); 2079655SAndreas.Sandberg@ARM.com } 2089655SAndreas.Sandberg@ARM.com 2099655SAndreas.Sandberg@ARM.com // Find a free context to use 2109655SAndreas.Sandberg@ARM.com ThreadContext * findFreeContext(); 2119655SAndreas.Sandberg@ARM.com 2129655SAndreas.Sandberg@ARM.com // map simulator fd sim_fd to target fd tgt_fd 2139655SAndreas.Sandberg@ARM.com void dup_fd(int sim_fd, int tgt_fd); 2149655SAndreas.Sandberg@ARM.com 2159655SAndreas.Sandberg@ARM.com // generate new target fd for sim_fd 2169655SAndreas.Sandberg@ARM.com int alloc_fd(int sim_fd, std::string filename, int flags, int mode, bool pipe); 2179655SAndreas.Sandberg@ARM.com 2189655SAndreas.Sandberg@ARM.com // free target fd (e.g., after close) 2199655SAndreas.Sandberg@ARM.com void free_fd(int tgt_fd); 2209655SAndreas.Sandberg@ARM.com 2219655SAndreas.Sandberg@ARM.com // look up simulator fd for given target fd 2229655SAndreas.Sandberg@ARM.com int sim_fd(int tgt_fd); 2239655SAndreas.Sandberg@ARM.com 2249655SAndreas.Sandberg@ARM.com // look up simulator fd_map object for a given target fd 2259655SAndreas.Sandberg@ARM.com FdMap * sim_fd_obj(int tgt_fd); 2269655SAndreas.Sandberg@ARM.com 2279655SAndreas.Sandberg@ARM.com // fix all offsets for currently open files and save them 2289655SAndreas.Sandberg@ARM.com void fix_file_offsets(); 2299655SAndreas.Sandberg@ARM.com 2309655SAndreas.Sandberg@ARM.com // find all offsets for currently open files and save them 2319655SAndreas.Sandberg@ARM.com void find_file_offsets(); 2329655SAndreas.Sandberg@ARM.com 2339655SAndreas.Sandberg@ARM.com // set the source of this read pipe for a checkpoint resume 2349655SAndreas.Sandberg@ARM.com void setReadPipeSource(int read_pipe_fd, int source_fd); 2359655SAndreas.Sandberg@ARM.com 2369655SAndreas.Sandberg@ARM.com virtual void syscall(int64_t callnum, ThreadContext *tc) = 0; 2379655SAndreas.Sandberg@ARM.com 2389655SAndreas.Sandberg@ARM.com // check if the this addr is on the next available page and allocate it 2399655SAndreas.Sandberg@ARM.com // if it's not we'll panic 2409655SAndreas.Sandberg@ARM.com bool checkAndAllocNextPage(Addr vaddr); 2419655SAndreas.Sandberg@ARM.com 2429655SAndreas.Sandberg@ARM.com void serialize(std::ostream &os); 2439655SAndreas.Sandberg@ARM.com void unserialize(Checkpoint *cp, const std::string §ion); 2449655SAndreas.Sandberg@ARM.com}; 2459655SAndreas.Sandberg@ARM.com 2469655SAndreas.Sandberg@ARM.com// 2479651SAndreas.Sandberg@ARM.com// "Live" process with system calls redirected to host system 248// 249class ObjectFile; 250class LiveProcess : public Process 251{ 252 protected: 253 ObjectFile *objFile; 254 std::vector<std::string> argv; 255 std::vector<std::string> envp; 256 std::string cwd; 257 258 LiveProcess(LiveProcessParams * params, ObjectFile *objFile); 259 260 virtual void argsInit(int intSize, int pageSize); 261 262 // Id of the owner of the process 263 uint64_t __uid; 264 uint64_t __euid; 265 uint64_t __gid; 266 uint64_t __egid; 267 268 // pid of the process and it's parent 269 uint64_t __pid; 270 uint64_t __ppid; 271 272 public: 273 274 enum AuxiliaryVectorType { 275 M5_AT_NULL = 0, 276 M5_AT_IGNORE = 1, 277 M5_AT_EXECFD = 2, 278 M5_AT_PHDR = 3, 279 M5_AT_PHENT = 4, 280 M5_AT_PHNUM = 5, 281 M5_AT_PAGESZ = 6, 282 M5_AT_BASE = 7, 283 M5_AT_FLAGS = 8, 284 M5_AT_ENTRY = 9, 285 M5_AT_NOTELF = 10, 286 M5_AT_UID = 11, 287 M5_AT_EUID = 12, 288 M5_AT_GID = 13, 289 M5_AT_EGID = 14, 290 // The following may be specific to Linux 291 M5_AT_PLATFORM = 15, 292 M5_AT_HWCAP = 16, 293 M5_AT_CLKTCK = 17, 294 295 M5_AT_SECURE = 23, 296 M5_BASE_PLATFORM = 24, 297 M5_AT_RANDOM = 25, 298 299 M5_AT_EXECFN = 31, 300 301 M5_AT_VECTOR_SIZE = 44 302 }; 303 304 inline uint64_t uid() {return __uid;} 305 inline uint64_t euid() {return __euid;} 306 inline uint64_t gid() {return __gid;} 307 inline uint64_t egid() {return __egid;} 308 inline uint64_t pid() {return __pid;} 309 inline uint64_t ppid() {return __ppid;} 310 311 std::string 312 fullPath(const std::string &filename) 313 { 314 if (filename[0] == '/' || cwd.empty()) 315 return filename; 316 317 std::string full = cwd; 318 319 if (cwd[cwd.size() - 1] != '/') 320 full += '/'; 321 322 return full + filename; 323 } 324 325 std::string getcwd() const { return cwd; } 326 327 virtual void syscall(int64_t callnum, ThreadContext *tc); 328 329 virtual TheISA::IntReg getSyscallArg(ThreadContext *tc, int &i) = 0; 330 virtual TheISA::IntReg getSyscallArg(ThreadContext *tc, int &i, int width); 331 virtual void setSyscallArg(ThreadContext *tc, 332 int i, TheISA::IntReg val) = 0; 333 virtual void setSyscallReturn(ThreadContext *tc, 334 SyscallReturn return_value) = 0; 335 336 virtual SyscallDesc* getDesc(int callnum) = 0; 337 338 // this function is used to create the LiveProcess object, since 339 // we can't tell which subclass of LiveProcess to use until we 340 // open and look at the object file. 341 static LiveProcess *create(LiveProcessParams * params); 342}; 343 344 345#endif // !FULL_SYSTEM 346 347#endif // __PROCESS_HH__ 348