process.cc revision 11886:43b882cada33
12497SN/A/* 210719SMarco.Balboni@ARM.com * Copyright (c) 2004-2005 The Regents of The University of Michigan 38711SN/A * All rights reserved. 48711SN/A * 58711SN/A * Redistribution and use in source and binary forms, with or without 68711SN/A * modification, are permitted provided that the following conditions are 78711SN/A * met: redistributions of source code must retain the above copyright 88711SN/A * notice, this list of conditions and the following disclaimer; 98711SN/A * redistributions in binary form must reproduce the above copyright 108711SN/A * notice, this list of conditions and the following disclaimer in the 118711SN/A * documentation and/or other materials provided with the distribution; 128711SN/A * neither the name of the copyright holders nor the names of its 138711SN/A * contributors may be used to endorse or promote products derived from 142497SN/A * this software without specific prior written permission. 152497SN/A * 162497SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172497SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182497SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192497SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202497SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212497SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222497SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232497SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242497SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252497SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262497SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272497SN/A * 282497SN/A * Authors: Gabe Black 292497SN/A * Ali Saidi 302497SN/A * Korey Sewell 312497SN/A */ 322497SN/A 332497SN/A#include "arch/mips/process.hh" 342497SN/A 352497SN/A#include "arch/mips/isa_traits.hh" 362497SN/A#include "base/loader/elf_object.hh" 372497SN/A#include "base/loader/object_file.hh" 382497SN/A#include "base/misc.hh" 392665SN/A#include "cpu/thread_context.hh" 402665SN/A#include "debug/Loader.hh" 418715SN/A#include "mem/page_table.hh" 428922SN/A#include "sim/aux_vector.hh" 432497SN/A#include "sim/process.hh" 442497SN/A#include "sim/process_impl.hh" 452497SN/A#include "sim/syscall_return.hh" 462982SN/A#include "sim/system.hh" 4710405Sandreas.hansson@arm.com 482497SN/Ausing namespace std; 492497SN/Ausing namespace MipsISA; 502846SN/A 512548SN/AMipsProcess::MipsProcess(ProcessParams * params, ObjectFile *objFile) 5210405Sandreas.hansson@arm.com : Process(params, objFile) 5310405Sandreas.hansson@arm.com{ 5410405Sandreas.hansson@arm.com // Set up stack. On MIPS, stack starts at the top of kuseg 559524SN/A // user address space. MIPS stack grows down from here 562497SN/A memState->stackBase = 0x7FFFFFFF; 5710405Sandreas.hansson@arm.com 5810719SMarco.Balboni@ARM.com // Set pointer for next thread stack. Reserve 8M for main stack. 5910719SMarco.Balboni@ARM.com memState->nextThreadStackBase = memState->stackBase - (8 * 1024 * 1024); 607523SN/A 618851SN/A // Set up break point (Top of Heap) 628948SN/A memState->brkPoint = objFile->dataBase() + objFile->dataSize() + 638948SN/A objFile->bssSize(); 648851SN/A memState->brkPoint = roundUp(memState->brkPoint, PageBytes); 659095SN/A 6610405Sandreas.hansson@arm.com // Set up region for mmaps. Start it 1GB above the top of the heap. 678922SN/A memState->mmapEnd = memState->brkPoint + 0x40000000L; 689715SN/A} 699715SN/A 7010713Sandreas.hansson@arm.comvoid 7110713Sandreas.hansson@arm.comMipsProcess::initState() 728851SN/A{ 738851SN/A Process::initState(); 748948SN/A 758948SN/A argsInit<uint32_t>(PageBytes); 768915SN/A} 779031SN/A 789095SN/Atemplate<class IntType> 7910405Sandreas.hansson@arm.comvoid 809036SN/AMipsProcess::argsInit(int pageSize) 818922SN/A{ 829715SN/A int intSize = sizeof(IntType); 839715SN/A 8410713Sandreas.hansson@arm.com // Patch the ld_bias for dynamic executables. 8510713Sandreas.hansson@arm.com updateBias(); 8610713Sandreas.hansson@arm.com 878915SN/A // load object file into target memory 888915SN/A objFile->loadSections(initVirtMem); 898948SN/A 908851SN/A typedef AuxVector<IntType> auxv_t; 919095SN/A std::vector<auxv_t> auxv; 9210888Sandreas.hansson@arm.com 938922SN/A ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile); 949715SN/A if (elfObject) 959715SN/A { 969716SN/A // Set the system page size 978851SN/A auxv.push_back(auxv_t(M5_AT_PAGESZ, MipsISA::PageBytes)); 988851SN/A // Set the frequency at which time() increments 9910402SN/A auxv.push_back(auxv_t(M5_AT_CLKTCK, 100)); 10010402SN/A // For statically linked executables, this is the virtual 10110402SN/A // address of the program header tables if they appear in the 1027523SN/A // executable image. 1037523SN/A auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable())); 1047523SN/A DPRINTF(Loader, "auxv at PHDR %08p\n", elfObject->programHeaderTable()); 10510405Sandreas.hansson@arm.com // This is the size of a program header entry from the elf file. 1069715SN/A auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize())); 10710405Sandreas.hansson@arm.com // This is the number of program headers from the original elf file. 10810405Sandreas.hansson@arm.com auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount())); 10910405Sandreas.hansson@arm.com // This is the base address of the ELF interpreter; it should be 11010405Sandreas.hansson@arm.com // zero for static executables or contain the base address for 11110405Sandreas.hansson@arm.com // dynamic executables. 11210405Sandreas.hansson@arm.com auxv.push_back(auxv_t(M5_AT_BASE, getBias())); 11310405Sandreas.hansson@arm.com //The entry point to the program 11410405Sandreas.hansson@arm.com auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint())); 1159715SN/A //Different user and group IDs 1169715SN/A auxv.push_back(auxv_t(M5_AT_UID, uid())); 1172568SN/A auxv.push_back(auxv_t(M5_AT_EUID, euid())); 11810405Sandreas.hansson@arm.com auxv.push_back(auxv_t(M5_AT_GID, gid())); 1192568SN/A auxv.push_back(auxv_t(M5_AT_EGID, egid())); 1209278SN/A } 12110405Sandreas.hansson@arm.com 1229278SN/A // Calculate how much space we need for arg & env & auxv arrays. 1238948SN/A int argv_array_size = intSize * (argv.size() + 1); 1248948SN/A int envp_array_size = intSize * (envp.size() + 1); 12510405Sandreas.hansson@arm.com int auxv_array_size = intSize * 2 * (auxv.size() + 1); 1269088SN/A 12710405Sandreas.hansson@arm.com int arg_data_size = 0; 12810405Sandreas.hansson@arm.com for (vector<string>::size_type i = 0; i < argv.size(); ++i) { 12910405Sandreas.hansson@arm.com arg_data_size += argv[i].size() + 1; 13010405Sandreas.hansson@arm.com } 1318711SN/A int env_data_size = 0; 1328711SN/A for (vector<string>::size_type i = 0; i < envp.size(); ++i) { 1332568SN/A env_data_size += envp[i].size() + 1; 1349036SN/A } 13510405Sandreas.hansson@arm.com 1363244SN/A int space_needed = 1373244SN/A argv_array_size + 1388948SN/A envp_array_size + 13910405Sandreas.hansson@arm.com auxv_array_size + 1403244SN/A arg_data_size + 14110883Sali.jafri@arm.com env_data_size; 14210883Sali.jafri@arm.com 14310883Sali.jafri@arm.com // set bottom of stack 14410883Sali.jafri@arm.com memState->stackMin = memState->stackBase - space_needed; 14510883Sali.jafri@arm.com // align it 14610883Sali.jafri@arm.com memState->stackMin = roundDown(memState->stackMin, pageSize); 1478975SN/A memState->stackSize = memState->stackBase - memState->stackMin; 1489032SN/A // map memory 1493244SN/A allocateMem(memState->stackMin, roundUp(memState->stackSize, pageSize)); 1509091SN/A 1519091SN/A // map out initial stack contents 15210656Sandreas.hansson@arm.com IntType argv_array_base = memState->stackMin + intSize; // room for argc 15310656Sandreas.hansson@arm.com IntType envp_array_base = argv_array_base + argv_array_size; 15410656Sandreas.hansson@arm.com IntType auxv_array_base = envp_array_base + envp_array_size; 15510656Sandreas.hansson@arm.com IntType arg_data_base = auxv_array_base + auxv_array_size; 1569091SN/A IntType env_data_base = arg_data_base + arg_data_size; 1579612SN/A 1589712SN/A // write contents to stack 1599612SN/A IntType argc = argv.size(); 16010405Sandreas.hansson@arm.com 1619033SN/A argc = htog((IntType)argc); 1629715SN/A 16310405Sandreas.hansson@arm.com initVirtMem.writeBlob(memState->stackMin, (uint8_t*)&argc, intSize); 1648949SN/A 1653244SN/A copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); 1663244SN/A 1673244SN/A copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); 16810405Sandreas.hansson@arm.com 1699091SN/A // Copy the aux vector 1709091SN/A for (typename vector<auxv_t>::size_type x = 0; x < auxv.size(); x++) { 1715197SN/A initVirtMem.writeBlob(auxv_array_base + x * 2 * intSize, 1729712SN/A (uint8_t*)&(auxv[x].a_type), intSize); 1739712SN/A initVirtMem.writeBlob(auxv_array_base + (x * 2 + 1) * intSize, 1749712SN/A (uint8_t*)&(auxv[x].a_val), intSize); 1759712SN/A } 1769712SN/A 17710719SMarco.Balboni@ARM.com // Write out the terminating zeroed auxilliary vector 17810719SMarco.Balboni@ARM.com for (unsigned i = 0; i < 2; i++) { 17910719SMarco.Balboni@ARM.com const IntType zero = 0; 18010719SMarco.Balboni@ARM.com const Addr addr = auxv_array_base + 2 * intSize * (auxv.size() + i); 18110719SMarco.Balboni@ARM.com initVirtMem.writeBlob(addr, (uint8_t*)&zero, intSize); 18210719SMarco.Balboni@ARM.com } 18310719SMarco.Balboni@ARM.com 18410719SMarco.Balboni@ARM.com ThreadContext *tc = system->getThreadContext(contextIds[0]); 18510719SMarco.Balboni@ARM.com 18610719SMarco.Balboni@ARM.com setSyscallArg(tc, 0, argc); 18710719SMarco.Balboni@ARM.com setSyscallArg(tc, 1, argv_array_base); 1884912SN/A tc->setIntReg(StackPointerReg, memState->stackMin); 18910821Sandreas.hansson@arm.com 19011127Sandreas.hansson@arm.com tc->pcState(getStartPC()); 19111127Sandreas.hansson@arm.com} 1928979SN/A 1938979SN/A 19410402SN/AMipsISA::IntReg 19510402SN/AMipsProcess::getSyscallArg(ThreadContext *tc, int &i) 19610402SN/A{ 19711126Sandreas.hansson@arm.com assert(i < 6); 19811126Sandreas.hansson@arm.com return tc->readIntReg(FirstArgumentReg + i++); 19911126Sandreas.hansson@arm.com} 20010719SMarco.Balboni@ARM.com 20110405Sandreas.hansson@arm.comvoid 20210402SN/AMipsProcess::setSyscallArg(ThreadContext *tc, int i, MipsISA::IntReg val) 20310402SN/A{ 20410402SN/A assert(i < 6); 20510402SN/A tc->setIntReg(FirstArgumentReg + i, val); 20610402SN/A} 20710402SN/A 20810402SN/Avoid 20911127Sandreas.hansson@arm.comMipsProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret) 21011127Sandreas.hansson@arm.com{ 21111127Sandreas.hansson@arm.com if (sysret.successful()) { 21211127Sandreas.hansson@arm.com // no error 2138979SN/A tc->setIntReg(SyscallSuccessReg, 0); 2148948SN/A tc->setIntReg(ReturnValueReg, sysret.returnValue()); 21510883Sali.jafri@arm.com } else { 21610883Sali.jafri@arm.com // got an error, return details 21710883Sali.jafri@arm.com tc->setIntReg(SyscallSuccessReg, (IntReg) -1); 21810883Sali.jafri@arm.com tc->setIntReg(ReturnValueReg, sysret.errnoValue()); 21910883Sali.jafri@arm.com } 22010883Sali.jafri@arm.com} 22110883Sali.jafri@arm.com