/*
+ * Copyright (c) 2012 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2001-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Ali Saidi
*/
-#include <unistd.h>
#include <fcntl.h>
+#include <unistd.h>
#include <cstdio>
#include <string>
-#include "base/intmath.hh"
#include "base/loader/object_file.hh"
#include "base/loader/symtab.hh"
+#include "base/intmath.hh"
#include "base/statistics.hh"
-#include "config/full_system.hh"
#include "config/the_isa.hh"
#include "cpu/thread_context.hh"
#include "mem/page_table.hh"
-#include "mem/physical.hh"
-#include "mem/translating_port.hh"
-#include "params/Process.hh"
+#include "mem/se_translating_port_proxy.hh"
#include "params/LiveProcess.hh"
+#include "params/Process.hh"
#include "sim/debug.hh"
#include "sim/process.hh"
#include "sim/process_impl.hh"
using namespace std;
using namespace TheISA;
-//
-// The purpose of this code is to fake the loader & syscall mechanism
-// when there's no OS: thus there's no resone to use it in FULL_SYSTEM
-// mode when we do have an OS
-//
-#if FULL_SYSTEM
-#error "process.cc not compatible with FULL_SYSTEM"
-#endif
-
// current number of allocated processes
int num_processes = 0;
a_val = TheISA::htog(val);
}
-template class AuxVector<uint32_t>;
-template class AuxVector<uint64_t>;
+template struct AuxVector<uint32_t>;
+template struct AuxVector<uint64_t>;
Process::Process(ProcessParams * params)
- : SimObject(params), system(params->system), checkpointRestored(false),
- max_stack_size(params->max_stack_size)
+ : SimObject(params), system(params->system),
+ max_stack_size(params->max_stack_size),
+ M5_pid(system->allocatePID()),
+ pTable(new PageTable(name(), M5_pid)),
+ initVirtMem(system->getSystemPort(), this,
+ SETranslatingPortProxy::Always)
{
string in = params->input;
string out = params->output;
else
stderr_fd = Process::openOutputFile(err);
- M5_pid = system->allocatePID();
// initialize first 3 fds (stdin, stdout, stderr)
Process::FdMap *fdo = &fd_map[STDIN_FILENO];
fdo->fd = stdin_fd;
mmap_start = mmap_end = 0;
nxm_start = nxm_end = 0;
- pTable = new PageTable(this);
// other parameters will be initialized when the program is loaded
}
using namespace Stats;
num_syscalls
- .name(name() + ".PROG:num_syscalls")
+ .name(name() + ".num_syscalls")
.desc("Number of system calls")
;
}
}
void
-Process::startup()
+Process::initState()
{
if (contextIds.empty())
fatal("Process %s is not associated with any HW contexts!\n", name());
ThreadContext *tc = system->getThreadContext(contextIds[0]);
// mark this context as active so it will start ticking.
- tc->activate(0);
-
- Port *mem_port;
- mem_port = system->physmem->getPort("functional");
- initVirtMem = new TranslatingPort("process init port", this,
- TranslatingPort::Always);
- mem_port->setPeer(initVirtMem);
- initVirtMem->setPeer(mem_port);
+ tc->activate(Cycles(0));
}
// map simulator fd sim_fd to target fd tgt_fd
int
Process::sim_fd(int tgt_fd)
{
- if (tgt_fd > MAX_FD)
+ if (tgt_fd < 0 || tgt_fd > MAX_FD)
return -1;
return fd_map[tgt_fd].fd;
Process::FdMap *
Process::sim_fd_obj(int tgt_fd)
{
- if (tgt_fd > MAX_FD)
- panic("sim_fd_obj called in fd out of range.");
+ if (tgt_fd < 0 || tgt_fd > MAX_FD)
+ return NULL;
return &fd_map[tgt_fd];
}
+void
+Process::allocateMem(Addr vaddr, int64_t size, bool clobber)
+{
+ int npages = divCeil(size, (int64_t)VMPageSize);
+ Addr paddr = system->allocPhysPages(npages);
+ pTable->map(vaddr, paddr, size, clobber);
+}
+
bool
-Process::checkAndAllocNextPage(Addr vaddr)
+Process::fixupStackFault(Addr vaddr)
{
- // if this is an initial write we might not have
+ // Check if this is already on the stack and there's just no page there
+ // yet.
if (vaddr >= stack_min && vaddr < stack_base) {
- pTable->allocate(roundDown(vaddr, VMPageSize), VMPageSize);
+ allocateMem(roundDown(vaddr, VMPageSize), VMPageSize);
return true;
}
- // We've accessed the next page of the stack, so extend the stack
- // to cover it.
+ // We've accessed the next page of the stack, so extend it to include
+ // this address.
if (vaddr < stack_min && vaddr >= stack_base - max_stack_size) {
while (vaddr < stack_min) {
stack_min -= TheISA::PageBytes;
- if(stack_base - stack_min > max_stack_size)
+ if (stack_base - stack_min > max_stack_size)
fatal("Maximum stack size exceeded\n");
- if(stack_base - stack_min > 8*1024*1024)
+ if (stack_base - stack_min > 8 * 1024 * 1024)
fatal("Over max stack size for one thread\n");
- pTable->allocate(stack_min, TheISA::PageBytes);
+ allocateMem(stack_min, TheISA::PageBytes);
inform("Increasing stack size by one page.");
};
return true;
void
Process::serialize(std::ostream &os)
{
- SERIALIZE_SCALAR(initialContextLoaded);
SERIALIZE_SCALAR(brk_point);
SERIALIZE_SCALAR(stack_base);
SERIALIZE_SCALAR(stack_size);
void
Process::unserialize(Checkpoint *cp, const std::string §ion)
{
- UNSERIALIZE_SCALAR(initialContextLoaded);
UNSERIALIZE_SCALAR(brk_point);
UNSERIALIZE_SCALAR(stack_base);
UNSERIALIZE_SCALAR(stack_size);
// find the param in the checkpoint if you wanted to, like set a default
// but in this case we'll just stick with the instantianted value if not
// found.
+}
- checkpointRestored = true;
+bool
+Process::map(Addr vaddr, Addr paddr, int size)
+{
+ pTable->map(vaddr, paddr, size);
+ return true;
}
__pid = params->pid;
__ppid = params->ppid;
- prog_fname = params->cmd[0];
-
// load up symbols, if any... these may be used for debugging or
// profiling.
if (!debugSymbolTable) {
}
}
-void
-LiveProcess::argsInit(int intSize, int pageSize)
-{
- Process::startup();
-
- // load object file into target memory
- objFile->loadSections(initVirtMem);
-
- // Calculate how much space we need for arg & env arrays.
- int argv_array_size = intSize * (argv.size() + 1);
- int envp_array_size = intSize * (envp.size() + 1);
- int arg_data_size = 0;
- for (vector<string>::size_type i = 0; i < argv.size(); ++i) {
- arg_data_size += argv[i].size() + 1;
- }
- int env_data_size = 0;
- for (vector<string>::size_type i = 0; i < envp.size(); ++i) {
- env_data_size += envp[i].size() + 1;
- }
-
- int space_needed =
- argv_array_size + envp_array_size + arg_data_size + env_data_size;
- if (space_needed < 32*1024)
- space_needed = 32*1024;
-
- // set bottom of stack
- stack_min = stack_base - space_needed;
- // align it
- stack_min = roundDown(stack_min, pageSize);
- stack_size = stack_base - stack_min;
- // map memory
- pTable->allocate(stack_min, roundUp(stack_size, pageSize));
-
- // map out initial stack contents
- Addr argv_array_base = stack_min + intSize; // room for argc
- Addr envp_array_base = argv_array_base + argv_array_size;
- Addr arg_data_base = envp_array_base + envp_array_size;
- Addr env_data_base = arg_data_base + arg_data_size;
-
- // write contents to stack
- uint64_t argc = argv.size();
- if (intSize == 8)
- argc = htog((uint64_t)argc);
- else if (intSize == 4)
- argc = htog((uint32_t)argc);
- else
- panic("Unknown int size");
-
- initVirtMem->writeBlob(stack_min, (uint8_t*)&argc, intSize);
-
- copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
- copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
-
- ThreadContext *tc = system->getThreadContext(contextIds[0]);
-
- setSyscallArg(tc, 0, argc);
- setSyscallArg(tc, 1, argv_array_base);
- tc->setIntReg(StackPointerReg, stack_min);
-
- Addr prog_entry = objFile->entryPoint();
- tc->setPC(prog_entry);
- tc->setNextPC(prog_entry + sizeof(MachInst));
-
-#if THE_ISA != ALPHA_ISA && THE_ISA != POWER_ISA //e.g. MIPS or Sparc
- tc->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
-#endif
-
- num_processes++;
-}
-
void
LiveProcess::syscall(int64_t callnum, ThreadContext *tc)
{
#error "THE_ISA not set"
#endif
-
if (process == NULL)
fatal("Unknown error creating process object.");
return process;