process.cc revision 12432
16145Snate@binkert.org/* 26145Snate@binkert.org * Copyright (c) 2010, 2012 ARM Limited 36145Snate@binkert.org * All rights reserved 46145Snate@binkert.org * 56145Snate@binkert.org * The license below extends only to copyright in the software and shall 66145Snate@binkert.org * not be construed as granting a license to any other intellectual 76145Snate@binkert.org * property including but not limited to intellectual property relating 86145Snate@binkert.org * to a hardware implementation of the functionality of the software 96145Snate@binkert.org * licensed hereunder. You may use the software subject to the license 106145Snate@binkert.org * terms below provided that you ensure that this notice is replicated 116145Snate@binkert.org * unmodified and in its entirety in all distributions of the software, 126145Snate@binkert.org * modified or unmodified, in source code or in binary form. 136145Snate@binkert.org * 146145Snate@binkert.org * Copyright (c) 2007-2008 The Florida State University 156145Snate@binkert.org * All rights reserved. 166145Snate@binkert.org * 176145Snate@binkert.org * Redistribution and use in source and binary forms, with or without 186145Snate@binkert.org * modification, are permitted provided that the following conditions are 196145Snate@binkert.org * met: redistributions of source code must retain the above copyright 206145Snate@binkert.org * notice, this list of conditions and the following disclaimer; 216145Snate@binkert.org * redistributions in binary form must reproduce the above copyright 226145Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 236145Snate@binkert.org * documentation and/or other materials provided with the distribution; 246145Snate@binkert.org * neither the name of the copyright holders nor the names of its 256145Snate@binkert.org * contributors may be used to endorse or promote products derived from 266145Snate@binkert.org * this software without specific prior written permission. 276145Snate@binkert.org * 286145Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2910467Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 308229Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 317056Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 327632SBrad.Beckmann@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 338232Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 348232Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 358615Snilay@cs.wisc.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 369104Shestness@cs.utexas.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 378615Snilay@cs.wisc.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 388615Snilay@cs.wisc.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 397039Snate@binkert.org * 408229Snate@binkert.org * Authors: Stephen Hines 416154Snate@binkert.org * Ali Saidi 426154Snate@binkert.org */ 437550SBrad.Beckmann@amd.com 4410467Sandreas.hansson@arm.com#include "arch/arm/process.hh" 456876Ssteve.reinhardt@amd.com 467055Snate@binkert.org#include "arch/arm/isa_traits.hh" 477055Snate@binkert.org#include "arch/arm/types.hh" 486876Ssteve.reinhardt@amd.com#include "base/loader/elf_object.hh" 496876Ssteve.reinhardt@amd.com#include "base/loader/object_file.hh" 506285Snate@binkert.org#include "base/logging.hh" 516876Ssteve.reinhardt@amd.com#include "cpu/thread_context.hh" 526285Snate@binkert.org#include "debug/Stack.hh" 537039Snate@binkert.org#include "mem/page_table.hh" 546876Ssteve.reinhardt@amd.com#include "params/Process.hh" 5510012Snilay@cs.wisc.edu#include "sim/aux_vector.hh" 566876Ssteve.reinhardt@amd.com#include "sim/byteswap.hh" 576876Ssteve.reinhardt@amd.com#include "sim/process_impl.hh" 586285Snate@binkert.org#include "sim/syscall_return.hh" 596876Ssteve.reinhardt@amd.com#include "sim/system.hh" 606876Ssteve.reinhardt@amd.com 6111019Sjthestness@gmail.comusing namespace std; 6211019Sjthestness@gmail.comusing namespace ArmISA; 636876Ssteve.reinhardt@amd.com 646876Ssteve.reinhardt@amd.comArmProcess::ArmProcess(ProcessParams *params, ObjectFile *objFile, 656899SBrad.Beckmann@amd.com ObjectFile::Arch _arch) 666876Ssteve.reinhardt@amd.com : Process(params, new FuncPageTable(params->name, params->pid, PageBytes), 676876Ssteve.reinhardt@amd.com objFile), 686876Ssteve.reinhardt@amd.com arch(_arch) 696876Ssteve.reinhardt@amd.com{ 7011019Sjthestness@gmail.com fatal_if(!params->useArchPT, "Arch page tables not implemented."); 7111019Sjthestness@gmail.com} 728171Stushar@csail.mit.edu 738171Stushar@csail.mit.eduArmProcess32::ArmProcess32(ProcessParams *params, ObjectFile *objFile, 746145Snate@binkert.org ObjectFile::Arch _arch) 756145Snate@binkert.org : ArmProcess(params, objFile, _arch) 767039Snate@binkert.org{ 777039Snate@binkert.org Addr brk_point = roundUp(objFile->dataBase() + objFile->dataSize() + 786145Snate@binkert.org objFile->bssSize(), PageBytes); 796145Snate@binkert.org Addr stack_base = 0xbf000000L; 807039Snate@binkert.org Addr max_stack_size = 8 * 1024 * 1024; 817039Snate@binkert.org Addr next_thread_stack_base = stack_base - max_stack_size; 827039Snate@binkert.org Addr mmap_end = 0x40000000L; 8310913Sandreas.sandberg@arm.com 849245Shestness@cs.wisc.edu memState = make_shared<MemState>(brk_point, stack_base, max_stack_size, 857039Snate@binkert.org next_thread_stack_base, mmap_end); 869501Snilay@cs.wisc.edu} 876145Snate@binkert.org 887039Snate@binkert.orgArmProcess64::ArmProcess64(ProcessParams *params, ObjectFile *objFile, 897039Snate@binkert.org ObjectFile::Arch _arch) 906285Snate@binkert.org : ArmProcess(params, objFile, _arch) 917455Snate@binkert.org{ 927455Snate@binkert.org Addr brk_point = roundUp(objFile->dataBase() + objFile->dataSize() + 937455Snate@binkert.org objFile->bssSize(), PageBytes); 947455Snate@binkert.org Addr stack_base = 0x7fffff0000L; 957455Snate@binkert.org Addr max_stack_size = 8 * 1024 * 1024; 967455Snate@binkert.org Addr next_thread_stack_base = stack_base - max_stack_size; 977455Snate@binkert.org Addr mmap_end = 0x4000000000L; 987805Snilay@cs.wisc.edu 9911025Snilay@cs.wisc.edu memState = make_shared<MemState>(brk_point, stack_base, max_stack_size, 10011025Snilay@cs.wisc.edu next_thread_stack_base, mmap_end); 10111025Snilay@cs.wisc.edu} 1029467Smalek.musleh@gmail.com 1039467Smalek.musleh@gmail.comvoid 1046145Snate@binkert.orgArmProcess32::initState() 1056145Snate@binkert.org{ 1067455Snate@binkert.org Process::initState(); 1077455Snate@binkert.org argsInit<uint32_t>(PageBytes, INTREG_SP); 1087455Snate@binkert.org for (int i = 0; i < contextIds.size(); i++) { 1097455Snate@binkert.org ThreadContext * tc = system->getThreadContext(contextIds[i]); 1107455Snate@binkert.org CPACR cpacr = tc->readMiscReg(MISCREG_CPACR); 1117455Snate@binkert.org // Enable the floating point coprocessors. 1127455Snate@binkert.org cpacr.cp10 = 0x3; 1137805Snilay@cs.wisc.edu cpacr.cp11 = 0x3; 11411025Snilay@cs.wisc.edu tc->setMiscReg(MISCREG_CPACR, cpacr); 11511025Snilay@cs.wisc.edu // Generically enable floating point support. 11611025Snilay@cs.wisc.edu FPEXC fpexc = tc->readMiscReg(MISCREG_FPEXC); 1179467Smalek.musleh@gmail.com fpexc.en = 1; 1189467Smalek.musleh@gmail.com tc->setMiscReg(MISCREG_FPEXC, fpexc); 1196145Snate@binkert.org } 1206285Snate@binkert.org} 1217039Snate@binkert.org 1227039Snate@binkert.orgvoid 1236145Snate@binkert.orgArmProcess64::initState() 1247039Snate@binkert.org{ 1257039Snate@binkert.org Process::initState(); 1267039Snate@binkert.org argsInit<uint64_t>(PageBytes, INTREG_SP0); 1277039Snate@binkert.org for (int i = 0; i < contextIds.size(); i++) { 1289465Snilay@cs.wisc.edu ThreadContext * tc = system->getThreadContext(contextIds[i]); 1297039Snate@binkert.org CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 1306145Snate@binkert.org cpsr.mode = MODE_EL0T; 1316145Snate@binkert.org tc->setMiscReg(MISCREG_CPSR, cpsr); 13210012Snilay@cs.wisc.edu CPACR cpacr = tc->readMiscReg(MISCREG_CPACR_EL1); 1339598Snilay@cs.wisc.edu // Enable the floating point coprocessors. 13410012Snilay@cs.wisc.edu cpacr.cp10 = 0x3; 13510012Snilay@cs.wisc.edu cpacr.cp11 = 0x3; 13610012Snilay@cs.wisc.edu tc->setMiscReg(MISCREG_CPACR_EL1, cpacr); 1379773Snilay@cs.wisc.edu // Generically enable floating point support. 13810012Snilay@cs.wisc.edu FPEXC fpexc = tc->readMiscReg(MISCREG_FPEXC); 13910012Snilay@cs.wisc.edu fpexc.en = 1; 14010012Snilay@cs.wisc.edu tc->setMiscReg(MISCREG_FPEXC, fpexc); 1419773Snilay@cs.wisc.edu } 14210012Snilay@cs.wisc.edu} 14310012Snilay@cs.wisc.edu 1449773Snilay@cs.wisc.edutemplate <class IntType> 1459773Snilay@cs.wisc.eduvoid 1469773Snilay@cs.wisc.eduArmProcess::argsInit(int pageSize, IntRegIndex spIndex) 14710012Snilay@cs.wisc.edu{ 14810012Snilay@cs.wisc.edu int intSize = sizeof(IntType); 14910012Snilay@cs.wisc.edu 1509773Snilay@cs.wisc.edu typedef AuxVector<IntType> auxv_t; 15110012Snilay@cs.wisc.edu std::vector<auxv_t> auxv; 15210012Snilay@cs.wisc.edu 15310012Snilay@cs.wisc.edu string filename; 15410012Snilay@cs.wisc.edu if (argv.size() < 1) 1559773Snilay@cs.wisc.edu filename = ""; 1569773Snilay@cs.wisc.edu else 1579773Snilay@cs.wisc.edu filename = argv[0]; 1589598Snilay@cs.wisc.edu 1599598Snilay@cs.wisc.edu //We want 16 byte alignment 1607039Snate@binkert.org uint64_t align = 16; 1617039Snate@binkert.org 1627039Snate@binkert.org // Patch the ld_bias for dynamic executables. 1637039Snate@binkert.org updateBias(); 1647039Snate@binkert.org 1657039Snate@binkert.org // load object file into target memory 16610919Sbrandon.potter@amd.com objFile->loadSections(initVirtMem); 1677039Snate@binkert.org 1687039Snate@binkert.org enum ArmCpuFeature { 1696145Snate@binkert.org Arm_Swp = 1 << 0, 1707455Snate@binkert.org Arm_Half = 1 << 1, 1717455Snate@binkert.org Arm_Thumb = 1 << 2, 1726145Snate@binkert.org Arm_26Bit = 1 << 3, 1737039Snate@binkert.org Arm_FastMult = 1 << 4, 1747455Snate@binkert.org Arm_Fpa = 1 << 5, 1757455Snate@binkert.org Arm_Vfp = 1 << 6, 1767455Snate@binkert.org Arm_Edsp = 1 << 7, 1777455Snate@binkert.org Arm_Java = 1 << 8, 1787039Snate@binkert.org Arm_Iwmmxt = 1 << 9, 1797039Snate@binkert.org Arm_Crunch = 1 << 10, 1807039Snate@binkert.org Arm_ThumbEE = 1 << 11, 1817039Snate@binkert.org Arm_Neon = 1 << 12, 1826145Snate@binkert.org Arm_Vfpv3 = 1 << 13, 1837039Snate@binkert.org Arm_Vfpv3d16 = 1 << 14 1846145Snate@binkert.org }; 1857455Snate@binkert.org 1867455Snate@binkert.org //Setup the auxilliary vectors. These will already have endian conversion. 1876285Snate@binkert.org //Auxilliary vectors are loaded only for elf formatted executables. 1887039Snate@binkert.org ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile); 1897455Snate@binkert.org if (elfObject) { 1907455Snate@binkert.org 1917455Snate@binkert.org if (objFile->getOpSys() == ObjectFile::Linux) { 1927455Snate@binkert.org IntType features = 1937039Snate@binkert.org Arm_Swp | 1947039Snate@binkert.org Arm_Half | 1957039Snate@binkert.org Arm_Thumb | 1967039Snate@binkert.org// Arm_26Bit | 1977039Snate@binkert.org Arm_FastMult | 1987039Snate@binkert.org// Arm_Fpa | 1997039Snate@binkert.org Arm_Vfp | 2007039Snate@binkert.org Arm_Edsp | 2017039Snate@binkert.org// Arm_Java | 2027039Snate@binkert.org// Arm_Iwmmxt | 2037039Snate@binkert.org// Arm_Crunch | 2047039Snate@binkert.org Arm_ThumbEE | 2057039Snate@binkert.org Arm_Neon | 2067039Snate@binkert.org Arm_Vfpv3 | 2077039Snate@binkert.org Arm_Vfpv3d16 | 2087039Snate@binkert.org 0; 2096145Snate@binkert.org 2106145Snate@binkert.org //Bits which describe the system hardware capabilities 2116145Snate@binkert.org //XXX Figure out what these should be 2126145Snate@binkert.org auxv.push_back(auxv_t(M5_AT_HWCAP, features)); 2138615Snilay@cs.wisc.edu //Frequency at which times() increments 2148615Snilay@cs.wisc.edu auxv.push_back(auxv_t(M5_AT_CLKTCK, 0x64)); 2157039Snate@binkert.org //Whether to enable "secure mode" in the executable 2168641Snate@binkert.org auxv.push_back(auxv_t(M5_AT_SECURE, 0)); 2178641Snate@binkert.org // Pointer to 16 bytes of random data 2186145Snate@binkert.org auxv.push_back(auxv_t(M5_AT_RANDOM, 0)); 2197039Snate@binkert.org //The filename of the program 2209342SAndreas.Sandberg@arm.com auxv.push_back(auxv_t(M5_AT_EXECFN, 0)); 22110913Sandreas.sandberg@arm.com //The string "v71" -- ARM v7 architecture 2229465Snilay@cs.wisc.edu auxv.push_back(auxv_t(M5_AT_PLATFORM, 0)); 2237039Snate@binkert.org } 2246145Snate@binkert.org 22511025Snilay@cs.wisc.edu //The system page size 2269224Sandreas.hansson@arm.com auxv.push_back(auxv_t(M5_AT_PAGESZ, ArmISA::PageBytes)); 2279224Sandreas.hansson@arm.com // For statically linked executables, this is the virtual address of the 2289224Sandreas.hansson@arm.com // program header tables if they appear in the executable image 2299224Sandreas.hansson@arm.com auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable())); 2309224Sandreas.hansson@arm.com // This is the size of a program header entry from the elf file. 2318615Snilay@cs.wisc.edu auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize())); 2328615Snilay@cs.wisc.edu // This is the number of program headers from the original elf file. 2338615Snilay@cs.wisc.edu auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount())); 2348615Snilay@cs.wisc.edu // This is the base address of the ELF interpreter; it should be 2358615Snilay@cs.wisc.edu // zero for static executables or contain the base address for 2368615Snilay@cs.wisc.edu // dynamic executables. 2378615Snilay@cs.wisc.edu auxv.push_back(auxv_t(M5_AT_BASE, getBias())); 2388615Snilay@cs.wisc.edu //XXX Figure out what this should be. 2398615Snilay@cs.wisc.edu auxv.push_back(auxv_t(M5_AT_FLAGS, 0)); 2408615Snilay@cs.wisc.edu //The entry point to the program 2418615Snilay@cs.wisc.edu auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint())); 2428615Snilay@cs.wisc.edu //Different user and group IDs 24310012Snilay@cs.wisc.edu auxv.push_back(auxv_t(M5_AT_UID, uid())); 2448615Snilay@cs.wisc.edu auxv.push_back(auxv_t(M5_AT_EUID, euid())); 2458615Snilay@cs.wisc.edu auxv.push_back(auxv_t(M5_AT_GID, gid())); 2468615Snilay@cs.wisc.edu auxv.push_back(auxv_t(M5_AT_EGID, egid())); 2477455Snate@binkert.org } 2489224Sandreas.hansson@arm.com 2498615Snilay@cs.wisc.edu //Figure out how big the initial stack nedes to be 2508615Snilay@cs.wisc.edu 2519465Snilay@cs.wisc.edu // A sentry NULL void pointer at the top of the stack. 2528615Snilay@cs.wisc.edu int sentry_size = intSize; 2538615Snilay@cs.wisc.edu 2548615Snilay@cs.wisc.edu string platform = "v71"; 25510012Snilay@cs.wisc.edu int platform_size = platform.size() + 1; 2568615Snilay@cs.wisc.edu 2578615Snilay@cs.wisc.edu // Bytes for AT_RANDOM above, we'll just keep them 0 2588615Snilay@cs.wisc.edu int aux_random_size = 16; // as per the specification 2598615Snilay@cs.wisc.edu 2608615Snilay@cs.wisc.edu // The aux vectors are put on the stack in two groups. The first group are 2618615Snilay@cs.wisc.edu // the vectors that are generated as the elf is loaded. The second group 26210012Snilay@cs.wisc.edu // are the ones that were computed ahead of time and include the platform 2638615Snilay@cs.wisc.edu // string. 2648615Snilay@cs.wisc.edu int aux_data_size = filename.size() + 1; 2657039Snate@binkert.org 2667455Snate@binkert.org int env_data_size = 0; 2679224Sandreas.hansson@arm.com for (int i = 0; i < envp.size(); ++i) { 2687039Snate@binkert.org env_data_size += envp[i].size() + 1; 2698615Snilay@cs.wisc.edu } 2708615Snilay@cs.wisc.edu int arg_data_size = 0; 2719465Snilay@cs.wisc.edu for (int i = 0; i < argv.size(); ++i) { 2728615Snilay@cs.wisc.edu arg_data_size += argv[i].size() + 1; 2738615Snilay@cs.wisc.edu } 2748615Snilay@cs.wisc.edu 27510012Snilay@cs.wisc.edu int info_block_size = 2768615Snilay@cs.wisc.edu sentry_size + env_data_size + arg_data_size + 2777039Snate@binkert.org aux_data_size + platform_size + aux_random_size; 2786145Snate@binkert.org 2796145Snate@binkert.org //Each auxilliary vector is two 4 byte words 28010012Snilay@cs.wisc.edu int aux_array_size = intSize * 2 * (auxv.size() + 1); 2818641Snate@binkert.org 2828641Snate@binkert.org int envp_array_size = intSize * (envp.size() + 1); 2836145Snate@binkert.org int argv_array_size = intSize * (argv.size() + 1); 2848615Snilay@cs.wisc.edu 2856145Snate@binkert.org int argc_size = intSize; 2866145Snate@binkert.org 2877039Snate@binkert.org //Figure out the size of the contents of the actual initial frame 2887455Snate@binkert.org int frame_size = 2897455Snate@binkert.org info_block_size + 2907455Snate@binkert.org aux_array_size + 2917455Snate@binkert.org envp_array_size + 2927455Snate@binkert.org argv_array_size + 2937455Snate@binkert.org argc_size; 2947455Snate@binkert.org 2957455Snate@binkert.org //There needs to be padding after the auxiliary vector data so that the 2967039Snate@binkert.org //very bottom of the stack is aligned properly. 2977039Snate@binkert.org int partial_size = frame_size; 2987039Snate@binkert.org int aligned_partial_size = roundUp(partial_size, align); 2997039Snate@binkert.org int aux_padding = aligned_partial_size - partial_size; 3006145Snate@binkert.org 30111025Snilay@cs.wisc.edu int space_needed = frame_size + aux_padding; 3028615Snilay@cs.wisc.edu 3038615Snilay@cs.wisc.edu memState->setStackMin(memState->getStackBase() - space_needed); 3048615Snilay@cs.wisc.edu memState->setStackMin(roundDown(memState->getStackMin(), align)); 3058615Snilay@cs.wisc.edu memState->setStackSize(memState->getStackBase() - memState->getStackMin()); 3068615Snilay@cs.wisc.edu 3078615Snilay@cs.wisc.edu // map memory 3088615Snilay@cs.wisc.edu allocateMem(roundDown(memState->getStackMin(), pageSize), 3097455Snate@binkert.org roundUp(memState->getStackSize(), pageSize)); 3107039Snate@binkert.org 3117455Snate@binkert.org // map out initial stack contents 3127039Snate@binkert.org IntType sentry_base = memState->getStackBase() - sentry_size; 3136285Snate@binkert.org IntType aux_data_base = sentry_base - aux_data_size; 3147455Snate@binkert.org IntType env_data_base = aux_data_base - env_data_size; 3156145Snate@binkert.org IntType arg_data_base = env_data_base - arg_data_size; 3166145Snate@binkert.org IntType platform_base = arg_data_base - platform_size; 3179563Sgope@wisc.edu IntType aux_random_base = platform_base - aux_random_size; 31811025Snilay@cs.wisc.edu IntType auxv_array_base = aux_random_base - aux_array_size - aux_padding; 3199563Sgope@wisc.edu IntType envp_array_base = auxv_array_base - envp_array_size; 3209563Sgope@wisc.edu IntType argv_array_base = envp_array_base - argv_array_size; 3219563Sgope@wisc.edu IntType argc_base = argv_array_base - argc_size; 3229563Sgope@wisc.edu 3239563Sgope@wisc.edu DPRINTF(Stack, "The addresses of items on the initial stack:\n"); 3249563Sgope@wisc.edu DPRINTF(Stack, "0x%x - aux data\n", aux_data_base); 3259563Sgope@wisc.edu DPRINTF(Stack, "0x%x - env data\n", env_data_base); 3269563Sgope@wisc.edu DPRINTF(Stack, "0x%x - arg data\n", arg_data_base); 3279563Sgope@wisc.edu DPRINTF(Stack, "0x%x - random data\n", aux_random_base); 3289563Sgope@wisc.edu DPRINTF(Stack, "0x%x - platform base\n", platform_base); 3299563Sgope@wisc.edu DPRINTF(Stack, "0x%x - auxv array\n", auxv_array_base); 3309563Sgope@wisc.edu DPRINTF(Stack, "0x%x - envp array\n", envp_array_base); 3317560SBrad.Beckmann@amd.com DPRINTF(Stack, "0x%x - argv array\n", argv_array_base); 33211025Snilay@cs.wisc.edu DPRINTF(Stack, "0x%x - argc \n", argc_base); 3337550SBrad.Beckmann@amd.com DPRINTF(Stack, "0x%x - stack min\n", memState->getStackMin()); 3347560SBrad.Beckmann@amd.com 3357560SBrad.Beckmann@amd.com // write contents to stack 3367560SBrad.Beckmann@amd.com 3377560SBrad.Beckmann@amd.com // figure out argc 3387560SBrad.Beckmann@amd.com IntType argc = argv.size(); 3397560SBrad.Beckmann@amd.com IntType guestArgc = ArmISA::htog(argc); 3408615Snilay@cs.wisc.edu 3417550SBrad.Beckmann@amd.com //Write out the sentry void * 3427550SBrad.Beckmann@amd.com IntType sentry_NULL = 0; 3437550SBrad.Beckmann@amd.com initVirtMem.writeBlob(sentry_base, 3447550SBrad.Beckmann@amd.com (uint8_t*)&sentry_NULL, sentry_size); 3457550SBrad.Beckmann@amd.com 3468615Snilay@cs.wisc.edu //Fix up the aux vectors which point to other data 3477560SBrad.Beckmann@amd.com for (int i = auxv.size() - 1; i >= 0; i--) { 3487550SBrad.Beckmann@amd.com if (auxv[i].a_type == M5_AT_PLATFORM) { 3497550SBrad.Beckmann@amd.com auxv[i].a_val = platform_base; 3507550SBrad.Beckmann@amd.com initVirtMem.writeString(platform_base, platform.c_str()); 35110917Sbrandon.potter@amd.com } else if (auxv[i].a_type == M5_AT_EXECFN) { 3527550SBrad.Beckmann@amd.com auxv[i].a_val = aux_data_base; 3538615Snilay@cs.wisc.edu initVirtMem.writeString(aux_data_base, filename.c_str()); 3547550SBrad.Beckmann@amd.com } else if (auxv[i].a_type == M5_AT_RANDOM) { 3557560SBrad.Beckmann@amd.com auxv[i].a_val = aux_random_base; 3567560SBrad.Beckmann@amd.com // Just leave the value 0, we don't want randomness 3577560SBrad.Beckmann@amd.com } 3587550SBrad.Beckmann@amd.com } 3598615Snilay@cs.wisc.edu 3607550SBrad.Beckmann@amd.com //Copy the aux stuff 3617550SBrad.Beckmann@amd.com for (int x = 0; x < auxv.size(); x++) { 3627550SBrad.Beckmann@amd.com initVirtMem.writeBlob(auxv_array_base + x * 2 * intSize, 3637550SBrad.Beckmann@amd.com (uint8_t*)&(auxv[x].a_type), intSize); 3647550SBrad.Beckmann@amd.com initVirtMem.writeBlob(auxv_array_base + (x * 2 + 1) * intSize, 3658615Snilay@cs.wisc.edu (uint8_t*)&(auxv[x].a_val), intSize); 3668615Snilay@cs.wisc.edu } 3677550SBrad.Beckmann@amd.com //Write out the terminating zeroed auxilliary vector 3687550SBrad.Beckmann@amd.com const uint64_t zero = 0; 3697550SBrad.Beckmann@amd.com initVirtMem.writeBlob(auxv_array_base + 2 * intSize * auxv.size(), 3707550SBrad.Beckmann@amd.com (uint8_t*)&zero, 2 * intSize); 3717550SBrad.Beckmann@amd.com 3727560SBrad.Beckmann@amd.com copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); 3737550SBrad.Beckmann@amd.com copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); 3747550SBrad.Beckmann@amd.com 3757550SBrad.Beckmann@amd.com initVirtMem.writeBlob(argc_base, (uint8_t*)&guestArgc, intSize); 3769773Snilay@cs.wisc.edu 3779773Snilay@cs.wisc.edu ThreadContext *tc = system->getThreadContext(contextIds[0]); 3789773Snilay@cs.wisc.edu //Set the stack pointer register 3799773Snilay@cs.wisc.edu tc->setIntReg(spIndex, memState->getStackMin()); 3809773Snilay@cs.wisc.edu //A pointer to a function to run when the program exits. We'll set this 3819773Snilay@cs.wisc.edu //to zero explicitly to make sure this isn't used. 3827039Snate@binkert.org tc->setIntReg(ArgumentReg0, 0); 38310012Snilay@cs.wisc.edu //Set argument regs 1 and 2 to argv[0] and envp[0] respectively 38410012Snilay@cs.wisc.edu if (argv.size() > 0) { 3859773Snilay@cs.wisc.edu tc->setIntReg(ArgumentReg1, arg_data_base + arg_data_size - 3869773Snilay@cs.wisc.edu argv[argv.size() - 1].size() - 1); 38710012Snilay@cs.wisc.edu } else { 38810012Snilay@cs.wisc.edu tc->setIntReg(ArgumentReg1, 0); 3899773Snilay@cs.wisc.edu } 3909773Snilay@cs.wisc.edu if (envp.size() > 0) { 39110012Snilay@cs.wisc.edu tc->setIntReg(ArgumentReg2, env_data_base + env_data_size - 39210012Snilay@cs.wisc.edu envp[envp.size() - 1].size() - 1); 3939773Snilay@cs.wisc.edu } else { 3949773Snilay@cs.wisc.edu tc->setIntReg(ArgumentReg2, 0); 3959773Snilay@cs.wisc.edu } 3969773Snilay@cs.wisc.edu 3979773Snilay@cs.wisc.edu PCState pc; 3989773Snilay@cs.wisc.edu pc.thumb(arch == ObjectFile::Thumb); 39910012Snilay@cs.wisc.edu pc.nextThumb(pc.thumb()); 4009773Snilay@cs.wisc.edu pc.aarch64(arch == ObjectFile::Arm64); 40110012Snilay@cs.wisc.edu pc.nextAArch64(pc.aarch64()); 4029773Snilay@cs.wisc.edu pc.set(getStartPC() & ~mask(1)); 40310012Snilay@cs.wisc.edu tc->pcState(pc); 4049773Snilay@cs.wisc.edu 40510012Snilay@cs.wisc.edu //Align the "stackMin" to a page boundary. 4069773Snilay@cs.wisc.edu memState->setStackMin(roundDown(memState->getStackMin(), pageSize)); 4079773Snilay@cs.wisc.edu} 4089773Snilay@cs.wisc.edu 4099773Snilay@cs.wisc.eduArmISA::IntReg 4109773Snilay@cs.wisc.eduArmProcess32::getSyscallArg(ThreadContext *tc, int &i) 4119773Snilay@cs.wisc.edu{ 41210012Snilay@cs.wisc.edu assert(i < 6); 41310012Snilay@cs.wisc.edu return tc->readIntReg(ArgumentReg0 + i++); 4149773Snilay@cs.wisc.edu} 4159773Snilay@cs.wisc.edu 41610012Snilay@cs.wisc.eduArmISA::IntReg 41710012Snilay@cs.wisc.eduArmProcess64::getSyscallArg(ThreadContext *tc, int &i) 4189773Snilay@cs.wisc.edu{ 4199773Snilay@cs.wisc.edu assert(i < 8); 4207546SBrad.Beckmann@amd.com return tc->readIntReg(ArgumentReg0 + i++); 4217546SBrad.Beckmann@amd.com} 4227546SBrad.Beckmann@amd.com 42311025Snilay@cs.wisc.eduArmISA::IntReg 4249773Snilay@cs.wisc.eduArmProcess32::getSyscallArg(ThreadContext *tc, int &i, int width) 4259773Snilay@cs.wisc.edu{ 4269773Snilay@cs.wisc.edu assert(width == 32 || width == 64); 4279773Snilay@cs.wisc.edu if (width == 32) 4287565SBrad.Beckmann@amd.com return getSyscallArg(tc, i); 42911025Snilay@cs.wisc.edu 43011025Snilay@cs.wisc.edu // 64 bit arguments are passed starting in an even register 4316145Snate@binkert.org if (i % 2 != 0) 4327455Snate@binkert.org i++; 4337455Snate@binkert.org 4347455Snate@binkert.org // Registers r0-r6 can be used 4356145Snate@binkert.org assert(i < 5); 4367455Snate@binkert.org uint64_t val; 4377455Snate@binkert.org val = tc->readIntReg(ArgumentReg0 + i++); 4386846Spdudnik@cs.wisc.edu val |= ((uint64_t)tc->readIntReg(ArgumentReg0 + i++) << 32); 4398615Snilay@cs.wisc.edu return val; 4408615Snilay@cs.wisc.edu} 4418615Snilay@cs.wisc.edu 4428615Snilay@cs.wisc.eduArmISA::IntReg 4438615Snilay@cs.wisc.eduArmProcess64::getSyscallArg(ThreadContext *tc, int &i, int width) 4448615Snilay@cs.wisc.edu{ 4458615Snilay@cs.wisc.edu return getSyscallArg(tc, i); 4468615Snilay@cs.wisc.edu} 4478615Snilay@cs.wisc.edu 4488184Ssomayeh@cs.wisc.edu 4497550SBrad.Beckmann@amd.comvoid 4507550SBrad.Beckmann@amd.comArmProcess32::setSyscallArg(ThreadContext *tc, int i, ArmISA::IntReg val) 4517550SBrad.Beckmann@amd.com{ 4527550SBrad.Beckmann@amd.com assert(i < 6); 4538171Stushar@csail.mit.edu tc->setIntReg(ArgumentReg0 + i, val); 4548171Stushar@csail.mit.edu} 4558171Stushar@csail.mit.edu 4568171Stushar@csail.mit.eduvoid 4578171Stushar@csail.mit.eduArmProcess64::setSyscallArg(ThreadContext *tc, int i, ArmISA::IntReg val) 4587550SBrad.Beckmann@amd.com{ 4598615Snilay@cs.wisc.edu assert(i < 8); 4607039Snate@binkert.org tc->setIntReg(ArgumentReg0 + i, val); 4618615Snilay@cs.wisc.edu} 4627039Snate@binkert.org 4637039Snate@binkert.orgvoid 4646863Sdrh5@cs.wisc.eduArmProcess32::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret) 4659773Snilay@cs.wisc.edu{ 4667565SBrad.Beckmann@amd.com 4676145Snate@binkert.org if (objFile->getOpSys() == ObjectFile::FreeBSD) { 4686145Snate@binkert.org // Decode return value 4697039Snate@binkert.org if (sysret.encodedValue() >= 0) 47011025Snilay@cs.wisc.edu // FreeBSD checks the carry bit to determine if syscall is succeeded 4719773Snilay@cs.wisc.edu tc->setCCReg(CCREG_C, 0); 4729507Snilay@cs.wisc.edu else { 4739507Snilay@cs.wisc.edu sysret = -sysret.encodedValue(); 4749507Snilay@cs.wisc.edu } 4757565SBrad.Beckmann@amd.com } 47611025Snilay@cs.wisc.edu 47711025Snilay@cs.wisc.edu tc->setIntReg(ReturnValueReg, sysret.encodedValue()); 4786145Snate@binkert.org} 4797455Snate@binkert.org 4807455Snate@binkert.orgvoid 4817455Snate@binkert.orgArmProcess64::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret) 4827455Snate@binkert.org{ 4837455Snate@binkert.org 4847455Snate@binkert.org if (objFile->getOpSys() == ObjectFile::FreeBSD) { 4856145Snate@binkert.org // Decode return value 4868615Snilay@cs.wisc.edu if (sysret.encodedValue() >= 0) 4878615Snilay@cs.wisc.edu // FreeBSD checks the carry bit to determine if syscall is succeeded 4886285Snate@binkert.org tc->setCCReg(CCREG_C, 0); 4899773Snilay@cs.wisc.edu else { 4907565SBrad.Beckmann@amd.com sysret = -sysret.encodedValue(); 4916145Snate@binkert.org } 4926145Snate@binkert.org } 4937039Snate@binkert.org 4949773Snilay@cs.wisc.edu tc->setIntReg(ReturnValueReg, sysret.encodedValue()); 4959773Snilay@cs.wisc.edu} 4969773Snilay@cs.wisc.edu