process.cc revision 6701:4842482e1bd1
1955SN/A/* 2955SN/A * Copyright (c) 2003-2004 The Regents of The University of Michigan 311408Sandreas.sandberg@arm.com * All rights reserved. 49812Sandreas.hansson@arm.com * 59812Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 69812Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 79812Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 89812Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 99812Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 109812Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 119812Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 129812Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 139812Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 149812Sandreas.hansson@arm.com * this software without specific prior written permission. 157816Ssteve.reinhardt@amd.com * 165871Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171762SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27955SN/A * 28955SN/A * Authors: Gabe Black 29955SN/A * Ali Saidi 30955SN/A */ 31955SN/A 32955SN/A#include "arch/sparc/asi.hh" 33955SN/A#include "arch/sparc/handlers.hh" 34955SN/A#include "arch/sparc/isa_traits.hh" 35955SN/A#include "arch/sparc/registers.hh" 36955SN/A#include "arch/sparc/process.hh" 37955SN/A#include "arch/sparc/types.hh" 38955SN/A#include "base/loader/object_file.hh" 39955SN/A#include "base/loader/elf_object.hh" 40955SN/A#include "base/misc.hh" 41955SN/A#include "cpu/thread_context.hh" 422665Ssaidi@eecs.umich.edu#include "mem/page_table.hh" 432665Ssaidi@eecs.umich.edu#include "sim/process_impl.hh" 445863Snate@binkert.org#include "mem/translating_port.hh" 45955SN/A#include "sim/system.hh" 46955SN/A 47955SN/Ausing namespace std; 48955SN/Ausing namespace SparcISA; 49955SN/A 508878Ssteve.reinhardt@amd.comstatic const int FirstArgumentReg = 8; 512632Sstever@eecs.umich.edu 528878Ssteve.reinhardt@amd.com 532632Sstever@eecs.umich.eduSparcLiveProcess::SparcLiveProcess(LiveProcessParams * params, 54955SN/A ObjectFile *objFile, Addr _StackBias) 558878Ssteve.reinhardt@amd.com : LiveProcess(params, objFile), StackBias(_StackBias) 562632Sstever@eecs.umich.edu{ 572761Sstever@eecs.umich.edu 582632Sstever@eecs.umich.edu // XXX all the below need to be updated for SPARC - Ali 592632Sstever@eecs.umich.edu brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); 602632Sstever@eecs.umich.edu brk_point = roundUp(brk_point, VMPageSize); 612761Sstever@eecs.umich.edu 622761Sstever@eecs.umich.edu // Set pointer for next thread stack. Reserve 8M for main stack. 632761Sstever@eecs.umich.edu next_thread_stack_base = stack_base - (8 * 1024 * 1024); 648878Ssteve.reinhardt@amd.com 658878Ssteve.reinhardt@amd.com //Initialize these to 0s 662761Sstever@eecs.umich.edu fillStart = 0; 672761Sstever@eecs.umich.edu spillStart = 0; 682761Sstever@eecs.umich.edu} 692761Sstever@eecs.umich.edu 702761Sstever@eecs.umich.eduvoid SparcLiveProcess::handleTrap(int trapNum, ThreadContext *tc) 718878Ssteve.reinhardt@amd.com{ 728878Ssteve.reinhardt@amd.com switch(trapNum) 732632Sstever@eecs.umich.edu { 742632Sstever@eecs.umich.edu case 0x01: //Software breakpoint 758878Ssteve.reinhardt@amd.com warn("Software breakpoint encountered at pc %#x.\n", tc->readPC()); 768878Ssteve.reinhardt@amd.com break; 772632Sstever@eecs.umich.edu case 0x02: //Division by zero 78955SN/A warn("Software signaled a division by zero at pc %#x.\n", 79955SN/A tc->readPC()); 80955SN/A break; 815863Snate@binkert.org case 0x03: //Flush window trap 825863Snate@binkert.org flushWindows(tc); 835863Snate@binkert.org break; 845863Snate@binkert.org case 0x04: //Clean windows 855863Snate@binkert.org warn("Ignoring process request for clean register " 865863Snate@binkert.org "windows at pc %#x.\n", tc->readPC()); 875863Snate@binkert.org break; 885863Snate@binkert.org case 0x05: //Range check 895863Snate@binkert.org warn("Software signaled a range check at pc %#x.\n", 905863Snate@binkert.org tc->readPC()); 915863Snate@binkert.org break; 928878Ssteve.reinhardt@amd.com case 0x06: //Fix alignment 935863Snate@binkert.org warn("Ignoring process request for os assisted unaligned accesses " 945863Snate@binkert.org "at pc %#x.\n", tc->readPC()); 955863Snate@binkert.org break; 969812Sandreas.hansson@arm.com case 0x07: //Integer overflow 979812Sandreas.hansson@arm.com warn("Software signaled an integer overflow at pc %#x.\n", 985863Snate@binkert.org tc->readPC()); 999812Sandreas.hansson@arm.com break; 1005863Snate@binkert.org case 0x32: //Get integer condition codes 1015863Snate@binkert.org warn("Ignoring process request to get the integer condition codes " 1025863Snate@binkert.org "at pc %#x.\n", tc->readPC()); 1039812Sandreas.hansson@arm.com break; 1049812Sandreas.hansson@arm.com case 0x33: //Set integer condition codes 1055863Snate@binkert.org warn("Ignoring process request to set the integer condition codes " 1065863Snate@binkert.org "at pc %#x.\n", tc->readPC()); 1078878Ssteve.reinhardt@amd.com break; 1085863Snate@binkert.org default: 1095863Snate@binkert.org panic("Unimplemented trap to operating system: trap number %#x.\n", trapNum); 1105863Snate@binkert.org } 1116654Snate@binkert.org} 11210196SCurtis.Dunham@arm.com 113955SN/Avoid 1145396Ssaidi@eecs.umich.eduSparcLiveProcess::startup() 11511401Sandreas.sandberg@arm.com{ 1165863Snate@binkert.org Process::startup(); 1175863Snate@binkert.org 1184202Sbinkertn@umich.edu ThreadContext *tc = system->getThreadContext(contextIds[0]); 1195863Snate@binkert.org //From the SPARC ABI 1205863Snate@binkert.org 1215863Snate@binkert.org //Setup default FP state 1225863Snate@binkert.org tc->setMiscRegNoEffect(MISCREG_FSR, 0); 123955SN/A 1246654Snate@binkert.org tc->setMiscRegNoEffect(MISCREG_TICK, 0); 1255273Sstever@gmail.com 1265871Snate@binkert.org /* 1275273Sstever@gmail.com * Register window management registers 1286655Snate@binkert.org */ 1298878Ssteve.reinhardt@amd.com 1306655Snate@binkert.org //No windows contain info from other programs 1316655Snate@binkert.org //tc->setMiscRegNoEffect(MISCREG_OTHERWIN, 0); 1329219Spower.jg@gmail.com tc->setIntReg(NumIntArchRegs + 6, 0); 1336655Snate@binkert.org //There are no windows to pop 1345871Snate@binkert.org //tc->setMiscRegNoEffect(MISCREG_CANRESTORE, 0); 1356654Snate@binkert.org tc->setIntReg(NumIntArchRegs + 4, 0); 1368947Sandreas.hansson@arm.com //All windows are available to save into 1375396Ssaidi@eecs.umich.edu //tc->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2); 1388120Sgblack@eecs.umich.edu tc->setIntReg(NumIntArchRegs + 3, NWindows - 2); 1398120Sgblack@eecs.umich.edu //All windows are "clean" 1408120Sgblack@eecs.umich.edu //tc->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows); 1418120Sgblack@eecs.umich.edu tc->setIntReg(NumIntArchRegs + 5, NWindows); 1428120Sgblack@eecs.umich.edu //Start with register window 0 1438120Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_CWP, 0); 1448120Sgblack@eecs.umich.edu //Always use spill and fill traps 0 1458120Sgblack@eecs.umich.edu //tc->setMiscRegNoEffect(MISCREG_WSTATE, 0); 1468879Ssteve.reinhardt@amd.com tc->setIntReg(NumIntArchRegs + 7, 0); 1478879Ssteve.reinhardt@amd.com //Set the trap level to 0 1488879Ssteve.reinhardt@amd.com tc->setMiscRegNoEffect(MISCREG_TL, 0); 1498879Ssteve.reinhardt@amd.com //Set the ASI register to something fixed 1508879Ssteve.reinhardt@amd.com tc->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY); 1518879Ssteve.reinhardt@amd.com 1528879Ssteve.reinhardt@amd.com /* 1538879Ssteve.reinhardt@amd.com * T1 specific registers 1548879Ssteve.reinhardt@amd.com */ 1558879Ssteve.reinhardt@amd.com //Turn on the icache, dcache, dtb translation, and itb translation. 1568879Ssteve.reinhardt@amd.com tc->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15); 1578879Ssteve.reinhardt@amd.com} 1588879Ssteve.reinhardt@amd.com 1598120Sgblack@eecs.umich.eduvoid 1608120Sgblack@eecs.umich.eduSparc32LiveProcess::startup() 1618120Sgblack@eecs.umich.edu{ 1628120Sgblack@eecs.umich.edu if (checkpointRestored) 1638120Sgblack@eecs.umich.edu return; 1648120Sgblack@eecs.umich.edu 1658120Sgblack@eecs.umich.edu SparcLiveProcess::startup(); 1668120Sgblack@eecs.umich.edu 1678120Sgblack@eecs.umich.edu ThreadContext *tc = system->getThreadContext(contextIds[0]); 1688120Sgblack@eecs.umich.edu //The process runs in user mode with 32 bit addresses 1698120Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_PSTATE, 0x0a); 1708120Sgblack@eecs.umich.edu 1718120Sgblack@eecs.umich.edu argsInit(32 / 8, VMPageSize); 1728120Sgblack@eecs.umich.edu} 1738879Ssteve.reinhardt@amd.com 1748879Ssteve.reinhardt@amd.comvoid 1758879Ssteve.reinhardt@amd.comSparc64LiveProcess::startup() 1768879Ssteve.reinhardt@amd.com{ 17710458Sandreas.hansson@arm.com if (checkpointRestored) 17810458Sandreas.hansson@arm.com return; 17910458Sandreas.hansson@arm.com 1808879Ssteve.reinhardt@amd.com SparcLiveProcess::startup(); 1818879Ssteve.reinhardt@amd.com 1828879Ssteve.reinhardt@amd.com ThreadContext *tc = system->getThreadContext(contextIds[0]); 1838879Ssteve.reinhardt@amd.com //The process runs in user mode 1849227Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_PSTATE, 0x02); 1859227Sandreas.hansson@arm.com 1868879Ssteve.reinhardt@amd.com argsInit(sizeof(IntReg), VMPageSize); 1878879Ssteve.reinhardt@amd.com} 1888879Ssteve.reinhardt@amd.com 1898879Ssteve.reinhardt@amd.comtemplate<class IntType> 19010453SAndrew.Bardsley@arm.comvoid 19110453SAndrew.Bardsley@arm.comSparcLiveProcess::argsInit(int pageSize) 19210453SAndrew.Bardsley@arm.com{ 19310456SCurtis.Dunham@arm.com int intSize = sizeof(IntType); 19410456SCurtis.Dunham@arm.com 19510456SCurtis.Dunham@arm.com typedef AuxVector<IntType> auxv_t; 19610457Sandreas.hansson@arm.com 19710457Sandreas.hansson@arm.com std::vector<auxv_t> auxv; 19811342Sandreas.hansson@arm.com 19911342Sandreas.hansson@arm.com string filename; 2008120Sgblack@eecs.umich.edu if(argv.size() < 1) 2018947Sandreas.hansson@arm.com filename = ""; 2027816Ssteve.reinhardt@amd.com else 2035871Snate@binkert.org filename = argv[0]; 2045871Snate@binkert.org 2056121Snate@binkert.org //Even for a 32 bit process, the ABI says we still need to 2065871Snate@binkert.org //maintain double word alignment of the stack pointer. 2075871Snate@binkert.org uint64_t align = 16; 2089926Sstan.czerniawski@arm.com 2099926Sstan.czerniawski@arm.com // load object file into target memory 2109119Sandreas.hansson@arm.com objFile->loadSections(initVirtMem); 21110068Sandreas.hansson@arm.com 21210068Sandreas.hansson@arm.com enum hardwareCaps 213955SN/A { 2149416SAndreas.Sandberg@ARM.com M5_HWCAP_SPARC_FLUSH = 1, 21511342Sandreas.hansson@arm.com M5_HWCAP_SPARC_STBAR = 2, 21611212Sjoseph.gross@amd.com M5_HWCAP_SPARC_SWAP = 4, 21711212Sjoseph.gross@amd.com M5_HWCAP_SPARC_MULDIV = 8, 21811212Sjoseph.gross@amd.com M5_HWCAP_SPARC_V9 = 16, 21911212Sjoseph.gross@amd.com //This one should technically only be set 22011212Sjoseph.gross@amd.com //if there is a cheetah or cheetah_plus tlb, 2219416SAndreas.Sandberg@ARM.com //but we'll use it all the time 2229416SAndreas.Sandberg@ARM.com M5_HWCAP_SPARC_ULTRA3 = 32 2235871Snate@binkert.org }; 22410584Sandreas.hansson@arm.com 2259416SAndreas.Sandberg@ARM.com const int64_t hwcap = 2269416SAndreas.Sandberg@ARM.com M5_HWCAP_SPARC_FLUSH | 2275871Snate@binkert.org M5_HWCAP_SPARC_STBAR | 228955SN/A M5_HWCAP_SPARC_SWAP | 22910671Sandreas.hansson@arm.com M5_HWCAP_SPARC_MULDIV | 23010671Sandreas.hansson@arm.com M5_HWCAP_SPARC_V9 | 23110671Sandreas.hansson@arm.com M5_HWCAP_SPARC_ULTRA3; 23210671Sandreas.hansson@arm.com 2338881Smarc.orr@gmail.com //Setup the auxilliary vectors. These will already have endian conversion. 2346121Snate@binkert.org //Auxilliary vectors are loaded only for elf formatted executables. 2356121Snate@binkert.org ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile); 2361533SN/A if(elfObject) 2379239Sandreas.hansson@arm.com { 2389239Sandreas.hansson@arm.com //Bits which describe the system hardware capabilities 2399239Sandreas.hansson@arm.com auxv.push_back(auxv_t(M5_AT_HWCAP, hwcap)); 2409239Sandreas.hansson@arm.com //The system page size 2419239Sandreas.hansson@arm.com auxv.push_back(auxv_t(M5_AT_PAGESZ, SparcISA::VMPageSize)); 2429239Sandreas.hansson@arm.com //Defined to be 100 in the kernel source. 2439239Sandreas.hansson@arm.com //Frequency at which times() increments 2449239Sandreas.hansson@arm.com auxv.push_back(auxv_t(M5_AT_CLKTCK, 100)); 2459239Sandreas.hansson@arm.com // For statically linked executables, this is the virtual address of the 2469239Sandreas.hansson@arm.com // program header tables if they appear in the executable image 2479239Sandreas.hansson@arm.com auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable())); 2489239Sandreas.hansson@arm.com // This is the size of a program header entry from the elf file. 2496655Snate@binkert.org auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize())); 2506655Snate@binkert.org // This is the number of program headers from the original elf file. 2516655Snate@binkert.org auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount())); 2526655Snate@binkert.org //This is the address of the elf "interpreter", It should be set 2535871Snate@binkert.org //to 0 for regular executables. It should be something else 2545871Snate@binkert.org //(not sure what) for dynamic libraries. 2555863Snate@binkert.org auxv.push_back(auxv_t(M5_AT_BASE, 0)); 2565871Snate@binkert.org //This is hardwired to 0 in the elf loading code in the kernel 2578878Ssteve.reinhardt@amd.com auxv.push_back(auxv_t(M5_AT_FLAGS, 0)); 2585871Snate@binkert.org //The entry point to the program 2595871Snate@binkert.org auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint())); 2605871Snate@binkert.org //Different user and group IDs 2615863Snate@binkert.org auxv.push_back(auxv_t(M5_AT_UID, uid())); 2626121Snate@binkert.org auxv.push_back(auxv_t(M5_AT_EUID, euid())); 2635863Snate@binkert.org auxv.push_back(auxv_t(M5_AT_GID, gid())); 26411408Sandreas.sandberg@arm.com auxv.push_back(auxv_t(M5_AT_EGID, egid())); 26511408Sandreas.sandberg@arm.com //Whether to enable "secure mode" in the executable 2668336Ssteve.reinhardt@amd.com auxv.push_back(auxv_t(M5_AT_SECURE, 0)); 26711469SCurtis.Dunham@arm.com } 26811469SCurtis.Dunham@arm.com 2698336Ssteve.reinhardt@amd.com //Figure out how big the initial stack needs to be 2704678Snate@binkert.org 27111887Sandreas.sandberg@arm.com // The unaccounted for 8 byte 0 at the top of the stack 27211887Sandreas.sandberg@arm.com int sentry_size = 8; 27311887Sandreas.sandberg@arm.com 27411887Sandreas.sandberg@arm.com //This is the name of the file which is present on the initial stack 27511887Sandreas.sandberg@arm.com //It's purpose is to let the user space linker examine the original file. 27611887Sandreas.sandberg@arm.com int file_name_size = filename.size() + 1; 27711887Sandreas.sandberg@arm.com 27811887Sandreas.sandberg@arm.com int env_data_size = 0; 27911887Sandreas.sandberg@arm.com for (int i = 0; i < envp.size(); ++i) { 28011887Sandreas.sandberg@arm.com env_data_size += envp[i].size() + 1; 28111887Sandreas.sandberg@arm.com } 28211408Sandreas.sandberg@arm.com int arg_data_size = 0; 28311401Sandreas.sandberg@arm.com for (int i = 0; i < argv.size(); ++i) { 28411401Sandreas.sandberg@arm.com arg_data_size += argv[i].size() + 1; 28511401Sandreas.sandberg@arm.com } 28611401Sandreas.sandberg@arm.com 28711401Sandreas.sandberg@arm.com //The info_block. 28811401Sandreas.sandberg@arm.com int base_info_block_size = 2898336Ssteve.reinhardt@amd.com sentry_size + file_name_size + env_data_size + arg_data_size; 2908336Ssteve.reinhardt@amd.com 2918336Ssteve.reinhardt@amd.com int info_block_size = roundUp(base_info_block_size, align); 2924678Snate@binkert.org 29311401Sandreas.sandberg@arm.com int info_block_padding = info_block_size - base_info_block_size; 2944678Snate@binkert.org 2954678Snate@binkert.org //Each auxilliary vector is two words 29611401Sandreas.sandberg@arm.com int aux_array_size = intSize * 2 * (auxv.size() + 1); 29711401Sandreas.sandberg@arm.com 2988336Ssteve.reinhardt@amd.com int envp_array_size = intSize * (envp.size() + 1); 2994678Snate@binkert.org int argv_array_size = intSize * (argv.size() + 1); 3008336Ssteve.reinhardt@amd.com 3018336Ssteve.reinhardt@amd.com int argc_size = intSize; 3028336Ssteve.reinhardt@amd.com int window_save_size = intSize * 16; 3038336Ssteve.reinhardt@amd.com 3048336Ssteve.reinhardt@amd.com //Figure out the size of the contents of the actual initial frame 3058336Ssteve.reinhardt@amd.com int frame_size = 3065871Snate@binkert.org aux_array_size + 3075871Snate@binkert.org envp_array_size + 3088336Ssteve.reinhardt@amd.com argv_array_size + 30911408Sandreas.sandberg@arm.com argc_size + 31011408Sandreas.sandberg@arm.com window_save_size; 31111408Sandreas.sandberg@arm.com 31211408Sandreas.sandberg@arm.com //There needs to be padding after the auxiliary vector data so that the 31311408Sandreas.sandberg@arm.com //very bottom of the stack is aligned properly. 31411408Sandreas.sandberg@arm.com int aligned_partial_size = roundUp(frame_size, align); 31511408Sandreas.sandberg@arm.com int aux_padding = aligned_partial_size - frame_size; 3168336Ssteve.reinhardt@amd.com 31711401Sandreas.sandberg@arm.com int space_needed = 31811401Sandreas.sandberg@arm.com info_block_size + 31911401Sandreas.sandberg@arm.com aux_padding + 3205871Snate@binkert.org frame_size; 3218336Ssteve.reinhardt@amd.com 3228336Ssteve.reinhardt@amd.com stack_min = stack_base - space_needed; 32311401Sandreas.sandberg@arm.com stack_min = roundDown(stack_min, align); 32411401Sandreas.sandberg@arm.com stack_size = stack_base - stack_min; 32511401Sandreas.sandberg@arm.com 32611401Sandreas.sandberg@arm.com // Allocate space for the stack 32711401Sandreas.sandberg@arm.com pTable->allocate(roundDown(stack_min, pageSize), 3284678Snate@binkert.org roundUp(stack_size, pageSize)); 3295871Snate@binkert.org 3304678Snate@binkert.org // map out initial stack contents 33111401Sandreas.sandberg@arm.com IntType sentry_base = stack_base - sentry_size; 33211401Sandreas.sandberg@arm.com IntType file_name_base = sentry_base - file_name_size; 33311401Sandreas.sandberg@arm.com IntType env_data_base = file_name_base - env_data_size; 33411401Sandreas.sandberg@arm.com IntType arg_data_base = env_data_base - arg_data_size; 33511401Sandreas.sandberg@arm.com IntType auxv_array_base = arg_data_base - 33611401Sandreas.sandberg@arm.com info_block_padding - aux_array_size - aux_padding; 33711401Sandreas.sandberg@arm.com IntType envp_array_base = auxv_array_base - envp_array_size; 33811401Sandreas.sandberg@arm.com IntType argv_array_base = envp_array_base - argv_array_size; 33911401Sandreas.sandberg@arm.com IntType argc_base = argv_array_base - argc_size; 34011401Sandreas.sandberg@arm.com#if TRACING_ON 34111401Sandreas.sandberg@arm.com IntType window_save_base = argc_base - window_save_size; 34211401Sandreas.sandberg@arm.com#endif 34311450Sandreas.sandberg@arm.com 34411450Sandreas.sandberg@arm.com DPRINTF(Stack, "The addresses of items on the initial stack:\n"); 34511450Sandreas.sandberg@arm.com DPRINTF(Stack, "%#x - sentry NULL\n", sentry_base); 34611450Sandreas.sandberg@arm.com DPRINTF(Stack, "filename = %s\n", filename); 34711450Sandreas.sandberg@arm.com DPRINTF(Stack, "%#x - file name\n", file_name_base); 34811450Sandreas.sandberg@arm.com DPRINTF(Stack, "%#x - env data\n", env_data_base); 34911450Sandreas.sandberg@arm.com DPRINTF(Stack, "%#x - arg data\n", arg_data_base); 35011450Sandreas.sandberg@arm.com DPRINTF(Stack, "%#x - auxv array\n", auxv_array_base); 35111450Sandreas.sandberg@arm.com DPRINTF(Stack, "%#x - envp array\n", envp_array_base); 35211450Sandreas.sandberg@arm.com DPRINTF(Stack, "%#x - argv array\n", argv_array_base); 35311450Sandreas.sandberg@arm.com DPRINTF(Stack, "%#x - argc \n", argc_base); 35411401Sandreas.sandberg@arm.com DPRINTF(Stack, "%#x - window save\n", window_save_base); 35511450Sandreas.sandberg@arm.com DPRINTF(Stack, "%#x - stack min\n", stack_min); 35611450Sandreas.sandberg@arm.com 35711450Sandreas.sandberg@arm.com assert(window_save_base == stack_min); 35811401Sandreas.sandberg@arm.com 35911450Sandreas.sandberg@arm.com // write contents to stack 36011401Sandreas.sandberg@arm.com 3618336Ssteve.reinhardt@amd.com // figure out argc 3628336Ssteve.reinhardt@amd.com IntType argc = argv.size(); 3638336Ssteve.reinhardt@amd.com IntType guestArgc = SparcISA::htog(argc); 3648336Ssteve.reinhardt@amd.com 3658336Ssteve.reinhardt@amd.com //Write out the sentry void * 3668336Ssteve.reinhardt@amd.com uint64_t sentry_NULL = 0; 3678336Ssteve.reinhardt@amd.com initVirtMem->writeBlob(sentry_base, 3688336Ssteve.reinhardt@amd.com (uint8_t*)&sentry_NULL, sentry_size); 3698336Ssteve.reinhardt@amd.com 3708336Ssteve.reinhardt@amd.com //Write the file name 37111401Sandreas.sandberg@arm.com initVirtMem->writeString(file_name_base, filename.c_str()); 37211401Sandreas.sandberg@arm.com 3738336Ssteve.reinhardt@amd.com //Copy the aux stuff 3748336Ssteve.reinhardt@amd.com for(int x = 0; x < auxv.size(); x++) 3758336Ssteve.reinhardt@amd.com { 3765871Snate@binkert.org initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize, 37711476Sandreas.sandberg@arm.com (uint8_t*)&(auxv[x].a_type), intSize); 37811476Sandreas.sandberg@arm.com initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize, 37911476Sandreas.sandberg@arm.com (uint8_t*)&(auxv[x].a_val), intSize); 38011476Sandreas.sandberg@arm.com } 38111476Sandreas.sandberg@arm.com 38211476Sandreas.sandberg@arm.com //Write out the terminating zeroed auxilliary vector 38311476Sandreas.sandberg@arm.com const IntType zero = 0; 38411476Sandreas.sandberg@arm.com initVirtMem->writeBlob(auxv_array_base + intSize * 2 * auxv.size(), 38511476Sandreas.sandberg@arm.com (uint8_t*)&zero, intSize); 38611887Sandreas.sandberg@arm.com initVirtMem->writeBlob(auxv_array_base + intSize * (2 * auxv.size() + 1), 38711887Sandreas.sandberg@arm.com (uint8_t*)&zero, intSize); 38811887Sandreas.sandberg@arm.com 38911408Sandreas.sandberg@arm.com copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); 39011887Sandreas.sandberg@arm.com copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); 39111887Sandreas.sandberg@arm.com 39211887Sandreas.sandberg@arm.com initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize); 39311887Sandreas.sandberg@arm.com 39411887Sandreas.sandberg@arm.com //Set up space for the trap handlers into the processes address space. 39511887Sandreas.sandberg@arm.com //Since the stack grows down and there is reserved address space abov 39611926Sgabeblack@google.com //it, we can put stuff above it and stay out of the way. 39711926Sgabeblack@google.com fillStart = stack_base; 39811926Sgabeblack@google.com spillStart = fillStart + sizeof(MachInst) * numFillInsts; 39911926Sgabeblack@google.com 40011887Sandreas.sandberg@arm.com ThreadContext *tc = system->getThreadContext(contextIds[0]); 40111887Sandreas.sandberg@arm.com //Set up the thread context to start running the process 40211887Sandreas.sandberg@arm.com //assert(NumArgumentRegs >= 2); 40311887Sandreas.sandberg@arm.com //tc->setIntReg(ArgumentReg[0], argc); 40411887Sandreas.sandberg@arm.com //tc->setIntReg(ArgumentReg[1], argv_array_base); 40511887Sandreas.sandberg@arm.com tc->setIntReg(StackPointerReg, stack_min - StackBias); 40611887Sandreas.sandberg@arm.com 40711887Sandreas.sandberg@arm.com // %g1 is a pointer to a function that should be run at exit. Since we 40811887Sandreas.sandberg@arm.com // don't have anything like that, it should be set to 0. 40911887Sandreas.sandberg@arm.com tc->setIntReg(1, 0); 41011887Sandreas.sandberg@arm.com 41111887Sandreas.sandberg@arm.com Addr prog_entry = objFile->entryPoint(); 41211887Sandreas.sandberg@arm.com tc->setPC(prog_entry); 41311887Sandreas.sandberg@arm.com tc->setNextPC(prog_entry + sizeof(MachInst)); 41411887Sandreas.sandberg@arm.com tc->setNextNPC(prog_entry + (2 * sizeof(MachInst))); 41511887Sandreas.sandberg@arm.com 41611887Sandreas.sandberg@arm.com //Align the "stack_min" to a page boundary. 41711887Sandreas.sandberg@arm.com stack_min = roundDown(stack_min, pageSize); 41811476Sandreas.sandberg@arm.com 41911476Sandreas.sandberg@arm.com// num_processes++; 42011408Sandreas.sandberg@arm.com} 42111408Sandreas.sandberg@arm.com 42211408Sandreas.sandberg@arm.comvoid 42311408Sandreas.sandberg@arm.comSparc64LiveProcess::argsInit(int intSize, int pageSize) 42411408Sandreas.sandberg@arm.com{ 42511408Sandreas.sandberg@arm.com SparcLiveProcess::argsInit<uint64_t>(pageSize); 42611408Sandreas.sandberg@arm.com 42711887Sandreas.sandberg@arm.com // Stuff the trap handlers into the process address space 42811887Sandreas.sandberg@arm.com initVirtMem->writeBlob(fillStart, 42911476Sandreas.sandberg@arm.com (uint8_t*)fillHandler64, sizeof(MachInst) * numFillInsts); 43011887Sandreas.sandberg@arm.com initVirtMem->writeBlob(spillStart, 43111887Sandreas.sandberg@arm.com (uint8_t*)spillHandler64, sizeof(MachInst) * numSpillInsts); 43211476Sandreas.sandberg@arm.com} 43311476Sandreas.sandberg@arm.com 43411476Sandreas.sandberg@arm.comvoid 43511476Sandreas.sandberg@arm.comSparc32LiveProcess::argsInit(int intSize, int pageSize) 4366121Snate@binkert.org{ 437955SN/A SparcLiveProcess::argsInit<uint32_t>(pageSize); 438955SN/A 4392632Sstever@eecs.umich.edu // Stuff the trap handlers into the process address space 4402632Sstever@eecs.umich.edu initVirtMem->writeBlob(fillStart, 441955SN/A (uint8_t*)fillHandler32, sizeof(MachInst) * numFillInsts); 442955SN/A initVirtMem->writeBlob(spillStart, 443955SN/A (uint8_t*)spillHandler32, sizeof(MachInst) * numSpillInsts); 444955SN/A} 4458878Ssteve.reinhardt@amd.com 446955SN/Avoid Sparc32LiveProcess::flushWindows(ThreadContext *tc) 4472632Sstever@eecs.umich.edu{ 4482632Sstever@eecs.umich.edu IntReg Cansave = tc->readIntReg(NumIntArchRegs + 3); 4492632Sstever@eecs.umich.edu IntReg Canrestore = tc->readIntReg(NumIntArchRegs + 4); 4502632Sstever@eecs.umich.edu IntReg Otherwin = tc->readIntReg(NumIntArchRegs + 6); 4512632Sstever@eecs.umich.edu MiscReg CWP = tc->readMiscReg(MISCREG_CWP); 4522632Sstever@eecs.umich.edu MiscReg origCWP = CWP; 4532632Sstever@eecs.umich.edu CWP = (CWP + Cansave + 2) % NWindows; 4548268Ssteve.reinhardt@amd.com while(NWindows - 2 - Cansave != 0) 4558268Ssteve.reinhardt@amd.com { 4568268Ssteve.reinhardt@amd.com if (Otherwin) { 4578268Ssteve.reinhardt@amd.com panic("Otherwin non-zero.\n"); 4588268Ssteve.reinhardt@amd.com } else { 4598268Ssteve.reinhardt@amd.com tc->setMiscReg(MISCREG_CWP, CWP); 4608268Ssteve.reinhardt@amd.com //Do the stores 4612632Sstever@eecs.umich.edu IntReg sp = tc->readIntReg(StackPointerReg); 4622632Sstever@eecs.umich.edu for (int index = 16; index < 32; index++) { 4632632Sstever@eecs.umich.edu uint32_t regVal = tc->readIntReg(index); 4642632Sstever@eecs.umich.edu regVal = htog(regVal); 4658268Ssteve.reinhardt@amd.com if (!tc->getMemPort()->tryWriteBlob( 4662632Sstever@eecs.umich.edu sp + (index - 16) * 4, (uint8_t *)®Val, 4)) { 4678268Ssteve.reinhardt@amd.com warn("Failed to save register to the stack when " 4688268Ssteve.reinhardt@amd.com "flushing windows.\n"); 4698268Ssteve.reinhardt@amd.com } 4708268Ssteve.reinhardt@amd.com } 4713718Sstever@eecs.umich.edu Canrestore--; 4722634Sstever@eecs.umich.edu Cansave++; 4732634Sstever@eecs.umich.edu CWP = (CWP + 1) % NWindows; 4745863Snate@binkert.org } 4752638Sstever@eecs.umich.edu } 4768268Ssteve.reinhardt@amd.com tc->setIntReg(NumIntArchRegs + 3, Cansave); 4772632Sstever@eecs.umich.edu tc->setIntReg(NumIntArchRegs + 4, Canrestore); 4782632Sstever@eecs.umich.edu tc->setMiscReg(MISCREG_CWP, origCWP); 4792632Sstever@eecs.umich.edu} 4802632Sstever@eecs.umich.edu 4812632Sstever@eecs.umich.eduvoid Sparc64LiveProcess::flushWindows(ThreadContext *tc) 4821858SN/A{ 4833716Sstever@eecs.umich.edu IntReg Cansave = tc->readIntReg(NumIntArchRegs + 3); 4842638Sstever@eecs.umich.edu IntReg Canrestore = tc->readIntReg(NumIntArchRegs + 4); 4852638Sstever@eecs.umich.edu IntReg Otherwin = tc->readIntReg(NumIntArchRegs + 6); 4862638Sstever@eecs.umich.edu MiscReg CWP = tc->readMiscReg(MISCREG_CWP); 4872638Sstever@eecs.umich.edu MiscReg origCWP = CWP; 4882638Sstever@eecs.umich.edu CWP = (CWP + Cansave + 2) % NWindows; 4892638Sstever@eecs.umich.edu while(NWindows - 2 - Cansave != 0) 4902638Sstever@eecs.umich.edu { 4915863Snate@binkert.org if (Otherwin) { 4925863Snate@binkert.org panic("Otherwin non-zero.\n"); 4935863Snate@binkert.org } else { 494955SN/A tc->setMiscReg(MISCREG_CWP, CWP); 4955341Sstever@gmail.com //Do the stores 4965341Sstever@gmail.com IntReg sp = tc->readIntReg(StackPointerReg); 4975863Snate@binkert.org for (int index = 16; index < 32; index++) { 4987756SAli.Saidi@ARM.com IntReg regVal = tc->readIntReg(index); 4995341Sstever@gmail.com regVal = htog(regVal); 5006121Snate@binkert.org if (!tc->getMemPort()->tryWriteBlob( 5014494Ssaidi@eecs.umich.edu sp + 2047 + (index - 16) * 8, (uint8_t *)®Val, 8)) { 5026121Snate@binkert.org warn("Failed to save register to the stack when " 5031105SN/A "flushing windows.\n"); 5042667Sstever@eecs.umich.edu } 5052667Sstever@eecs.umich.edu } 5062667Sstever@eecs.umich.edu Canrestore--; 5072667Sstever@eecs.umich.edu Cansave++; 5086121Snate@binkert.org CWP = (CWP + 1) % NWindows; 5092667Sstever@eecs.umich.edu } 5105341Sstever@gmail.com } 5115863Snate@binkert.org tc->setIntReg(NumIntArchRegs + 3, Cansave); 5125341Sstever@gmail.com tc->setIntReg(NumIntArchRegs + 4, Canrestore); 5135341Sstever@gmail.com tc->setMiscReg(MISCREG_CWP, origCWP); 5145341Sstever@gmail.com} 5158120Sgblack@eecs.umich.edu 5165341Sstever@gmail.comIntReg 5178120Sgblack@eecs.umich.eduSparc32LiveProcess::getSyscallArg(ThreadContext *tc, int &i) 5185341Sstever@gmail.com{ 5198120Sgblack@eecs.umich.edu assert(i < 6); 5206121Snate@binkert.org return bits(tc->readIntReg(FirstArgumentReg + i++), 31, 0); 5216121Snate@binkert.org} 5228980Ssteve.reinhardt@amd.com 5239396Sandreas.hansson@arm.comvoid 5245397Ssaidi@eecs.umich.eduSparc32LiveProcess::setSyscallArg(ThreadContext *tc, int i, IntReg val) 5255397Ssaidi@eecs.umich.edu{ 5267727SAli.Saidi@ARM.com assert(i < 6); 5278268Ssteve.reinhardt@amd.com tc->setIntReg(FirstArgumentReg + i, bits(val, 31, 0)); 5286168Snate@binkert.org} 5295341Sstever@gmail.com 5308120Sgblack@eecs.umich.eduIntReg 5318120Sgblack@eecs.umich.eduSparc64LiveProcess::getSyscallArg(ThreadContext *tc, int &i) 5328120Sgblack@eecs.umich.edu{ 5336814Sgblack@eecs.umich.edu assert(i < 6); 5345863Snate@binkert.org return tc->readIntReg(FirstArgumentReg + i++); 5358120Sgblack@eecs.umich.edu} 5365341Sstever@gmail.com 5375863Snate@binkert.orgvoid 5388268Ssteve.reinhardt@amd.comSparc64LiveProcess::setSyscallArg(ThreadContext *tc, int i, IntReg val) 5396121Snate@binkert.org{ 5406121Snate@binkert.org assert(i < 6); 5418268Ssteve.reinhardt@amd.com tc->setIntReg(FirstArgumentReg + i, val); 5425742Snate@binkert.org} 5435742Snate@binkert.org 5445341Sstever@gmail.comvoid 5455742Snate@binkert.orgSparcLiveProcess::setSyscallReturn(ThreadContext *tc, 5465742Snate@binkert.org SyscallReturn return_value) 5475341Sstever@gmail.com{ 5486017Snate@binkert.org // check for error condition. SPARC syscall convention is to 5496121Snate@binkert.org // indicate success/failure in reg the carry bit of the ccr 5506017Snate@binkert.org // and put the return value itself in the standard return value reg (). 5517816Ssteve.reinhardt@amd.com if (return_value.successful()) { 5527756SAli.Saidi@ARM.com // no error, clear XCC.C 5537756SAli.Saidi@ARM.com tc->setIntReg(NumIntArchRegs + 2, 5547756SAli.Saidi@ARM.com tc->readIntReg(NumIntArchRegs + 2) & 0xEE); 5557756SAli.Saidi@ARM.com //tc->setMiscRegNoEffect(MISCREG_CCR, tc->readMiscRegNoEffect(MISCREG_CCR) & 0xEE); 5567756SAli.Saidi@ARM.com IntReg val = return_value.value(); 5577756SAli.Saidi@ARM.com if (bits(tc->readMiscRegNoEffect( 5587756SAli.Saidi@ARM.com SparcISA::MISCREG_PSTATE), 3, 3)) { 5597756SAli.Saidi@ARM.com val = bits(val, 31, 0); 5607816Ssteve.reinhardt@amd.com } 5617816Ssteve.reinhardt@amd.com tc->setIntReg(ReturnValueReg, val); 5627816Ssteve.reinhardt@amd.com } else { 5637816Ssteve.reinhardt@amd.com // got an error, set XCC.C 5647816Ssteve.reinhardt@amd.com tc->setIntReg(NumIntArchRegs + 2, 5657816Ssteve.reinhardt@amd.com tc->readIntReg(NumIntArchRegs + 2) | 0x11); 5667816Ssteve.reinhardt@amd.com //tc->setMiscRegNoEffect(MISCREG_CCR, tc->readMiscRegNoEffect(MISCREG_CCR) | 0x11); 5677816Ssteve.reinhardt@amd.com IntReg val = -return_value.value(); 5687816Ssteve.reinhardt@amd.com if (bits(tc->readMiscRegNoEffect( 5697816Ssteve.reinhardt@amd.com SparcISA::MISCREG_PSTATE), 3, 3)) { 5707756SAli.Saidi@ARM.com val = bits(val, 31, 0); 5717816Ssteve.reinhardt@amd.com } 5727816Ssteve.reinhardt@amd.com tc->setIntReg(ReturnValueReg, val); 5737816Ssteve.reinhardt@amd.com } 5747816Ssteve.reinhardt@amd.com} 5757816Ssteve.reinhardt@amd.com