process.cc revision 12334
12SN/A/* 210905Sandreas.sandberg@arm.com * Copyright (c) 2003-2004 The Regents of The University of Michigan 310905Sandreas.sandberg@arm.com * All rights reserved. 410905Sandreas.sandberg@arm.com * 510905Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without 610905Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are 710905Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright 810905Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer; 910905Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright 1010905Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the 1110905Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution; 1210905Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its 1310905Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from 141762SN/A * this software without specific prior written permission. 159983Sstever@gmail.com * 169983Sstever@gmail.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272SN/A * 282SN/A * Authors: Gabe Black 292SN/A * Ali Saidi 302SN/A */ 312SN/A 322SN/A#include "arch/sparc/process.hh" 332SN/A 342SN/A#include "arch/sparc/asi.hh" 352SN/A#include "arch/sparc/handlers.hh" 362SN/A#include "arch/sparc/isa_traits.hh" 372SN/A#include "arch/sparc/registers.hh" 382SN/A#include "arch/sparc/types.hh" 392SN/A#include "base/loader/elf_object.hh" 402SN/A#include "base/loader/object_file.hh" 412665Ssaidi@eecs.umich.edu#include "base/logging.hh" 422760Sbinkertn@umich.edu#include "cpu/thread_context.hh" 432760Sbinkertn@umich.edu#include "debug/Stack.hh" 442665Ssaidi@eecs.umich.edu#include "mem/page_table.hh" 4510905Sandreas.sandberg@arm.com#include "sim/aux_vector.hh" 462SN/A#include "sim/process_impl.hh" 472SN/A#include "sim/syscall_return.hh" 488229Snate@binkert.org#include "sim/system.hh" 492SN/A 50363SN/Ausing namespace std; 512SN/Ausing namespace SparcISA; 528229Snate@binkert.org 532SN/Astatic const int FirstArgumentReg = 8; 542SN/A 552SN/A 562SN/ASparcProcess::SparcProcess(ProcessParams * params, ObjectFile *objFile, 572SN/A Addr _StackBias) 5810907Sandreas.sandberg@arm.com : Process(params, objFile), StackBias(_StackBias) 59363SN/A{ 6056SN/A // Initialize these to 0s 611388SN/A fillStart = 0; 62217SN/A spillStart = 0; 63363SN/A} 6410905Sandreas.sandberg@arm.com 6556SN/Avoid 6656SN/ASparcProcess::handleTrap(int trapNum, ThreadContext *tc, Fault *fault) 6756SN/A{ 681638SN/A PCState pc = tc->pcState(); 6956SN/A switch (trapNum) { 702SN/A case 0x01: // Software breakpoint 712356SN/A warn("Software breakpoint encountered at pc %#x.\n", pc.pc()); 722356SN/A break; 732356SN/A case 0x02: // Division by zero 742SN/A warn("Software signaled a division by zero at pc %#x.\n", pc.pc()); 752SN/A break; 764762Snate@binkert.org case 0x03: // Flush window trap 774762Snate@binkert.org flushWindows(tc); 784762Snate@binkert.org break; 794762Snate@binkert.org case 0x04: // Clean windows 804762Snate@binkert.org warn("Ignoring process request for clean register " 814762Snate@binkert.org "windows at pc %#x.\n", pc.pc()); 824762Snate@binkert.org break; 834762Snate@binkert.org case 0x05: // Range check 844762Snate@binkert.org warn("Software signaled a range check at pc %#x.\n", pc.pc()); 854762Snate@binkert.org break; 864762Snate@binkert.org case 0x06: // Fix alignment 874762Snate@binkert.org warn("Ignoring process request for os assisted unaligned accesses " 884762Snate@binkert.org "at pc %#x.\n", pc.pc()); 8910905Sandreas.sandberg@arm.com break; 904762Snate@binkert.org case 0x07: // Integer overflow 914762Snate@binkert.org warn("Software signaled an integer overflow at pc %#x.\n", pc.pc()); 924762Snate@binkert.org break; 934762Snate@binkert.org case 0x32: // Get integer condition codes 944762Snate@binkert.org warn("Ignoring process request to get the integer condition codes " 954762Snate@binkert.org "at pc %#x.\n", pc.pc()); 964762Snate@binkert.org break; 974762Snate@binkert.org case 0x33: // Set integer condition codes 984762Snate@binkert.org warn("Ignoring process request to set the integer condition codes " 994762Snate@binkert.org "at pc %#x.\n", pc.pc()); 1004762Snate@binkert.org break; 1014762Snate@binkert.org default: 1024762Snate@binkert.org panic("Unimplemented trap to operating system: trap number %#x.\n", trapNum); 1034762Snate@binkert.org } 1044762Snate@binkert.org} 10510905Sandreas.sandberg@arm.com 1067494Ssteve.reinhardt@amd.comvoid 1077494Ssteve.reinhardt@amd.comSparcProcess::initState() 1087494Ssteve.reinhardt@amd.com{ 1097494Ssteve.reinhardt@amd.com Process::initState(); 1107494Ssteve.reinhardt@amd.com 1117494Ssteve.reinhardt@amd.com ThreadContext *tc = system->getThreadContext(contextIds[0]); 1127494Ssteve.reinhardt@amd.com // From the SPARC ABI 11310905Sandreas.sandberg@arm.com 1144762Snate@binkert.org // Setup default FP state 1154762Snate@binkert.org tc->setMiscRegNoEffect(MISCREG_FSR, 0); 1164762Snate@binkert.org 1174762Snate@binkert.org tc->setMiscRegNoEffect(MISCREG_TICK, 0); 1184762Snate@binkert.org 1194762Snate@binkert.org /* 1204762Snate@binkert.org * Register window management registers 12110905Sandreas.sandberg@arm.com */ 1224762Snate@binkert.org 1234762Snate@binkert.org // No windows contain info from other programs 1244762Snate@binkert.org // tc->setMiscRegNoEffect(MISCREG_OTHERWIN, 0); 1254762Snate@binkert.org tc->setIntReg(NumIntArchRegs + 6, 0); 1264762Snate@binkert.org // There are no windows to pop 1274762Snate@binkert.org // tc->setMiscRegNoEffect(MISCREG_CANRESTORE, 0); 1284762Snate@binkert.org tc->setIntReg(NumIntArchRegs + 4, 0); 1294762Snate@binkert.org // All windows are available to save into 1304762Snate@binkert.org // tc->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2); 13110386Sandreas.hansson@arm.com tc->setIntReg(NumIntArchRegs + 3, NWindows - 2); 1324762Snate@binkert.org // All windows are "clean" 1334762Snate@binkert.org // tc->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows); 1344762Snate@binkert.org tc->setIntReg(NumIntArchRegs + 5, NWindows); 1354762Snate@binkert.org // Start with register window 0 1364762Snate@binkert.org tc->setMiscReg(MISCREG_CWP, 0); 1374762Snate@binkert.org // Always use spill and fill traps 0 13810386Sandreas.hansson@arm.com // tc->setMiscRegNoEffect(MISCREG_WSTATE, 0); 1394762Snate@binkert.org tc->setIntReg(NumIntArchRegs + 7, 0); 1404762Snate@binkert.org // Set the trap level to 0 1414762Snate@binkert.org tc->setMiscRegNoEffect(MISCREG_TL, 0); 1424762Snate@binkert.org // Set the ASI register to something fixed 1434762Snate@binkert.org tc->setMiscReg(MISCREG_ASI, ASI_PRIMARY); 1444762Snate@binkert.org 14510386Sandreas.hansson@arm.com // Set the MMU Primary Context Register to hold the process' pid 1464762Snate@binkert.org tc->setMiscReg(MISCREG_MMU_P_CONTEXT, _pid); 1474762Snate@binkert.org 1484762Snate@binkert.org /* 1494762Snate@binkert.org * T1 specific registers 1504762Snate@binkert.org */ 15110905Sandreas.sandberg@arm.com // Turn on the icache, dcache, dtb translation, and itb translation. 1524762Snate@binkert.org tc->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15); 1534762Snate@binkert.org} 1544762Snate@binkert.org 1554762Snate@binkert.orgvoid 1564762Snate@binkert.orgSparc32Process::initState() 1574762Snate@binkert.org{ 1584762Snate@binkert.org SparcProcess::initState(); 1594762Snate@binkert.org 1604762Snate@binkert.org ThreadContext *tc = system->getThreadContext(contextIds[0]); 1614762Snate@binkert.org // The process runs in user mode with 32 bit addresses 1624762Snate@binkert.org PSTATE pstate = 0; 1634762Snate@binkert.org pstate.ie = 1; 1644762Snate@binkert.org pstate.am = 1; 1654762Snate@binkert.org tc->setMiscReg(MISCREG_PSTATE, pstate); 1662287SN/A 1672287SN/A argsInit(32 / 8, PageBytes); 1682287SN/A} 16910905Sandreas.sandberg@arm.com 1702SN/Avoid 171217SN/ASparc64Process::initState() 1722SN/A{ 17310905Sandreas.sandberg@arm.com SparcProcess::initState(); 1742SN/A 175217SN/A ThreadContext *tc = system->getThreadContext(contextIds[0]); 176217SN/A // The process runs in user mode 177217SN/A PSTATE pstate = 0; 1782SN/A pstate.ie = 1; 1792SN/A tc->setMiscReg(MISCREG_PSTATE, pstate); 1804841Ssaidi@eecs.umich.edu 1814841Ssaidi@eecs.umich.edu argsInit(sizeof(IntReg), PageBytes); 18210905Sandreas.sandberg@arm.com} 1834841Ssaidi@eecs.umich.edu 1846227Snate@binkert.orgtemplate<class IntType> 1854841Ssaidi@eecs.umich.eduvoid 1864841Ssaidi@eecs.umich.eduSparcProcess::argsInit(int pageSize) 1874841Ssaidi@eecs.umich.edu{ 1886227Snate@binkert.org int intSize = sizeof(IntType); 1894841Ssaidi@eecs.umich.edu 1904841Ssaidi@eecs.umich.edu typedef AuxVector<IntType> auxv_t; 1914841Ssaidi@eecs.umich.edu 1924841Ssaidi@eecs.umich.edu std::vector<auxv_t> auxv; 1934841Ssaidi@eecs.umich.edu 1944841Ssaidi@eecs.umich.edu string filename; 1957948SAli.Saidi@ARM.com if (argv.size() < 1) 1967948SAli.Saidi@ARM.com filename = ""; 19710905Sandreas.sandberg@arm.com else 1987948SAli.Saidi@ARM.com filename = argv[0]; 1997948SAli.Saidi@ARM.com 2007948SAli.Saidi@ARM.com // Even for a 32 bit process, the ABI says we still need to 2017948SAli.Saidi@ARM.com // maintain double word alignment of the stack pointer. 2027948SAli.Saidi@ARM.com uint64_t align = 16; 2037948SAli.Saidi@ARM.com 2047948SAli.Saidi@ARM.com // Patch the ld_bias for dynamic executables. 2057948SAli.Saidi@ARM.com updateBias(); 2067948SAli.Saidi@ARM.com 2077948SAli.Saidi@ARM.com // load object file into target memory 2087948SAli.Saidi@ARM.com objFile->loadSections(initVirtMem); 2097948SAli.Saidi@ARM.com 2107948SAli.Saidi@ARM.com enum hardwareCaps 2117948SAli.Saidi@ARM.com { 212217SN/A M5_HWCAP_SPARC_FLUSH = 1, 213217SN/A M5_HWCAP_SPARC_STBAR = 2, 214217SN/A M5_HWCAP_SPARC_SWAP = 4, 21511076SCurtis.Dunham@arm.com M5_HWCAP_SPARC_MULDIV = 8, 21611076SCurtis.Dunham@arm.com M5_HWCAP_SPARC_V9 = 16, 21711076SCurtis.Dunham@arm.com // This one should technically only be set 21811076SCurtis.Dunham@arm.com // if there is a cheetah or cheetah_plus tlb, 21911076SCurtis.Dunham@arm.com // but we'll use it all the time 22011076SCurtis.Dunham@arm.com M5_HWCAP_SPARC_ULTRA3 = 32 22111076SCurtis.Dunham@arm.com }; 22211076SCurtis.Dunham@arm.com 22311076SCurtis.Dunham@arm.com const int64_t hwcap = 22411076SCurtis.Dunham@arm.com M5_HWCAP_SPARC_FLUSH | 22511076SCurtis.Dunham@arm.com M5_HWCAP_SPARC_STBAR | 22611076SCurtis.Dunham@arm.com M5_HWCAP_SPARC_SWAP | 22711076SCurtis.Dunham@arm.com M5_HWCAP_SPARC_MULDIV | 22811076SCurtis.Dunham@arm.com M5_HWCAP_SPARC_V9 | 22911076SCurtis.Dunham@arm.com M5_HWCAP_SPARC_ULTRA3; 23011076SCurtis.Dunham@arm.com 23111076SCurtis.Dunham@arm.com // Setup the auxilliary vectors. These will already have endian conversion. 23211076SCurtis.Dunham@arm.com // Auxilliary vectors are loaded only for elf formatted executables. 23310905Sandreas.sandberg@arm.com ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile); 2342SN/A if (elfObject) { 23510905Sandreas.sandberg@arm.com // Bits which describe the system hardware capabilities 2366225Snate@binkert.org auxv.push_back(auxv_t(M5_AT_HWCAP, hwcap)); 23710905Sandreas.sandberg@arm.com // The system page size 238217SN/A auxv.push_back(auxv_t(M5_AT_PAGESZ, SparcISA::PageBytes)); 239217SN/A // Defined to be 100 in the kernel source. 2402SN/A // Frequency at which times() increments 2412SN/A auxv.push_back(auxv_t(M5_AT_CLKTCK, 100)); 2426820SLisa.Hsu@amd.com // For statically linked executables, this is the virtual address of the 2436820SLisa.Hsu@amd.com // program header tables if they appear in the executable image 24411075SCurtis.Dunham@arm.com auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable())); 2456820SLisa.Hsu@amd.com // This is the size of a program header entry from the elf file. 24610905Sandreas.sandberg@arm.com auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize())); 2476820SLisa.Hsu@amd.com // This is the number of program headers from the original elf file. 24810905Sandreas.sandberg@arm.com auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount())); 24911075SCurtis.Dunham@arm.com // This is the base address of the ELF interpreter; it should be 25011075SCurtis.Dunham@arm.com // zero for static executables or contain the base address for 2516820SLisa.Hsu@amd.com // dynamic executables. 2526820SLisa.Hsu@amd.com auxv.push_back(auxv_t(M5_AT_BASE, getBias())); 2536820SLisa.Hsu@amd.com // This is hardwired to 0 in the elf loading code in the kernel 2546820SLisa.Hsu@amd.com auxv.push_back(auxv_t(M5_AT_FLAGS, 0)); 2556820SLisa.Hsu@amd.com // The entry point to the program 256217SN/A auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint())); 257217SN/A // Different user and group IDs 258217SN/A auxv.push_back(auxv_t(M5_AT_UID, uid())); 25910905Sandreas.sandberg@arm.com auxv.push_back(auxv_t(M5_AT_EUID, euid())); 26010905Sandreas.sandberg@arm.com auxv.push_back(auxv_t(M5_AT_GID, gid())); 261217SN/A auxv.push_back(auxv_t(M5_AT_EGID, egid())); 262217SN/A // Whether to enable "secure mode" in the executable 263217SN/A auxv.push_back(auxv_t(M5_AT_SECURE, 0)); 264217SN/A } 2656227Snate@binkert.org 266217SN/A // Figure out how big the initial stack needs to be 267217SN/A 268217SN/A // The unaccounted for 8 byte 0 at the top of the stack 269217SN/A int sentry_size = 8; 270217SN/A 271217SN/A // This is the name of the file which is present on the initial stack 272217SN/A // It's purpose is to let the user space linker examine the original file. 273217SN/A int file_name_size = filename.size() + 1; 274217SN/A 27510905Sandreas.sandberg@arm.com int env_data_size = 0; 276217SN/A for (int i = 0; i < envp.size(); ++i) { 27710905Sandreas.sandberg@arm.com env_data_size += envp[i].size() + 1; 2786225Snate@binkert.org } 27910905Sandreas.sandberg@arm.com int arg_data_size = 0; 280217SN/A for (int i = 0; i < argv.size(); ++i) { 281217SN/A arg_data_size += argv[i].size() + 1; 282217SN/A } 283217SN/A 284217SN/A // The info_block. 285217SN/A int base_info_block_size = 286217SN/A sentry_size + file_name_size + env_data_size + arg_data_size; 287217SN/A 288217SN/A int info_block_size = roundUp(base_info_block_size, align); 289217SN/A 290217SN/A int info_block_padding = info_block_size - base_info_block_size; 291217SN/A 292217SN/A // Each auxilliary vector is two words 293217SN/A int aux_array_size = intSize * 2 * (auxv.size() + 1); 294217SN/A 295217SN/A int envp_array_size = intSize * (envp.size() + 1); 296217SN/A int argv_array_size = intSize * (argv.size() + 1); 2976227Snate@binkert.org 298217SN/A int argc_size = intSize; 299217SN/A int window_save_size = intSize * 16; 300217SN/A 301217SN/A // Figure out the size of the contents of the actual initial frame 30210905Sandreas.sandberg@arm.com int frame_size = 303217SN/A aux_array_size + 304217SN/A envp_array_size + 305217SN/A argv_array_size + 306217SN/A argc_size + 307217SN/A window_save_size; 308217SN/A 309217SN/A // There needs to be padding after the auxiliary vector data so that the 310217SN/A // very bottom of the stack is aligned properly. 311217SN/A int aligned_partial_size = roundUp(frame_size, align); 312217SN/A int aux_padding = aligned_partial_size - frame_size; 313217SN/A 314217SN/A int space_needed = 315217SN/A info_block_size + 316217SN/A aux_padding + 3174841Ssaidi@eecs.umich.edu frame_size; 3184841Ssaidi@eecs.umich.edu 31910905Sandreas.sandberg@arm.com memState->setStackMin(memState->getStackBase() - space_needed); 3204841Ssaidi@eecs.umich.edu memState->setStackMin(roundDown(memState->getStackMin(), align)); 32110905Sandreas.sandberg@arm.com memState->setStackSize(memState->getStackBase() - memState->getStackMin()); 3226225Snate@binkert.org 32310905Sandreas.sandberg@arm.com // Allocate space for the stack 3244841Ssaidi@eecs.umich.edu allocateMem(roundDown(memState->getStackMin(), pageSize), 3254841Ssaidi@eecs.umich.edu roundUp(memState->getStackSize(), pageSize)); 3264841Ssaidi@eecs.umich.edu 3274841Ssaidi@eecs.umich.edu // map out initial stack contents 3284841Ssaidi@eecs.umich.edu IntType sentry_base = memState->getStackBase() - sentry_size; 3294841Ssaidi@eecs.umich.edu IntType file_name_base = sentry_base - file_name_size; 3304841Ssaidi@eecs.umich.edu IntType env_data_base = file_name_base - env_data_size; 3314841Ssaidi@eecs.umich.edu IntType arg_data_base = env_data_base - arg_data_size; 3324841Ssaidi@eecs.umich.edu IntType auxv_array_base = arg_data_base - 3334841Ssaidi@eecs.umich.edu info_block_padding - aux_array_size - aux_padding; 3344841Ssaidi@eecs.umich.edu IntType envp_array_base = auxv_array_base - envp_array_size; 3354841Ssaidi@eecs.umich.edu IntType argv_array_base = envp_array_base - argv_array_size; 3364841Ssaidi@eecs.umich.edu IntType argc_base = argv_array_base - argc_size; 3374841Ssaidi@eecs.umich.edu#if TRACING_ON 3384841Ssaidi@eecs.umich.edu IntType window_save_base = argc_base - window_save_size; 3396227Snate@binkert.org#endif 3404841Ssaidi@eecs.umich.edu 3414841Ssaidi@eecs.umich.edu DPRINTF(Stack, "The addresses of items on the initial stack:\n"); 3424841Ssaidi@eecs.umich.edu DPRINTF(Stack, "%#x - sentry NULL\n", sentry_base); 3434841Ssaidi@eecs.umich.edu DPRINTF(Stack, "filename = %s\n", filename); 34410905Sandreas.sandberg@arm.com DPRINTF(Stack, "%#x - file name\n", file_name_base); 3454841Ssaidi@eecs.umich.edu DPRINTF(Stack, "%#x - env data\n", env_data_base); 3464841Ssaidi@eecs.umich.edu DPRINTF(Stack, "%#x - arg data\n", arg_data_base); 3474841Ssaidi@eecs.umich.edu DPRINTF(Stack, "%#x - auxv array\n", auxv_array_base); 3484841Ssaidi@eecs.umich.edu DPRINTF(Stack, "%#x - envp array\n", envp_array_base); 3494841Ssaidi@eecs.umich.edu DPRINTF(Stack, "%#x - argv array\n", argv_array_base); 3504841Ssaidi@eecs.umich.edu DPRINTF(Stack, "%#x - argc \n", argc_base); 3514841Ssaidi@eecs.umich.edu DPRINTF(Stack, "%#x - window save\n", window_save_base); 3524841Ssaidi@eecs.umich.edu DPRINTF(Stack, "%#x - stack min\n", memState->getStackMin()); 3534841Ssaidi@eecs.umich.edu 3544841Ssaidi@eecs.umich.edu assert(window_save_base == memState->getStackMin()); 3554841Ssaidi@eecs.umich.edu 3564841Ssaidi@eecs.umich.edu // write contents to stack 3574841Ssaidi@eecs.umich.edu 3584841Ssaidi@eecs.umich.edu // figure out argc 3597948SAli.Saidi@ARM.com IntType argc = argv.size(); 3607948SAli.Saidi@ARM.com IntType guestArgc = SparcISA::htog(argc); 36110905Sandreas.sandberg@arm.com 3627948SAli.Saidi@ARM.com // Write out the sentry void * 36310905Sandreas.sandberg@arm.com uint64_t sentry_NULL = 0; 3647948SAli.Saidi@ARM.com initVirtMem.writeBlob(sentry_base, 36510905Sandreas.sandberg@arm.com (uint8_t*)&sentry_NULL, sentry_size); 3667948SAli.Saidi@ARM.com 3677948SAli.Saidi@ARM.com // Write the file name 3687948SAli.Saidi@ARM.com initVirtMem.writeString(file_name_base, filename.c_str()); 3697948SAli.Saidi@ARM.com 3707948SAli.Saidi@ARM.com // Copy the aux stuff 3717948SAli.Saidi@ARM.com for (int x = 0; x < auxv.size(); x++) { 3727948SAli.Saidi@ARM.com initVirtMem.writeBlob(auxv_array_base + x * 2 * intSize, 3737948SAli.Saidi@ARM.com (uint8_t*)&(auxv[x].a_type), intSize); 37410905Sandreas.sandberg@arm.com initVirtMem.writeBlob(auxv_array_base + (x * 2 + 1) * intSize, 3757948SAli.Saidi@ARM.com (uint8_t*)&(auxv[x].a_val), intSize); 3767948SAli.Saidi@ARM.com } 3777948SAli.Saidi@ARM.com 3787948SAli.Saidi@ARM.com // Write out the terminating zeroed auxilliary vector 3797948SAli.Saidi@ARM.com const IntType zero = 0; 3807948SAli.Saidi@ARM.com initVirtMem.writeBlob(auxv_array_base + intSize * 2 * auxv.size(), 3817948SAli.Saidi@ARM.com (uint8_t*)&zero, intSize); 3827948SAli.Saidi@ARM.com initVirtMem.writeBlob(auxv_array_base + intSize * (2 * auxv.size() + 1), 3837948SAli.Saidi@ARM.com (uint8_t*)&zero, intSize); 3847948SAli.Saidi@ARM.com 3857948SAli.Saidi@ARM.com copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); 3867948SAli.Saidi@ARM.com copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); 3877948SAli.Saidi@ARM.com 3887948SAli.Saidi@ARM.com initVirtMem.writeBlob(argc_base, (uint8_t*)&guestArgc, intSize); 38911076SCurtis.Dunham@arm.com 39011076SCurtis.Dunham@arm.com // Set up space for the trap handlers into the processes address space. 39111076SCurtis.Dunham@arm.com // Since the stack grows down and there is reserved address space abov 39211076SCurtis.Dunham@arm.com // it, we can put stuff above it and stay out of the way. 39311076SCurtis.Dunham@arm.com fillStart = memState->getStackBase(); 39411076SCurtis.Dunham@arm.com spillStart = fillStart + sizeof(MachInst) * numFillInsts; 39511076SCurtis.Dunham@arm.com 39611076SCurtis.Dunham@arm.com ThreadContext *tc = system->getThreadContext(contextIds[0]); 39711076SCurtis.Dunham@arm.com // Set up the thread context to start running the process 39811076SCurtis.Dunham@arm.com // assert(NumArgumentRegs >= 2); 39911076SCurtis.Dunham@arm.com // tc->setIntReg(ArgumentReg[0], argc); 40011076SCurtis.Dunham@arm.com // tc->setIntReg(ArgumentReg[1], argv_array_base); 40111076SCurtis.Dunham@arm.com tc->setIntReg(StackPointerReg, memState->getStackMin() - StackBias); 40211076SCurtis.Dunham@arm.com 40311076SCurtis.Dunham@arm.com // %g1 is a pointer to a function that should be run at exit. Since we 40411076SCurtis.Dunham@arm.com // don't have anything like that, it should be set to 0. 40511076SCurtis.Dunham@arm.com tc->setIntReg(1, 0); 40611076SCurtis.Dunham@arm.com 40711076SCurtis.Dunham@arm.com tc->pcState(getStartPC()); 40811076SCurtis.Dunham@arm.com 40911076SCurtis.Dunham@arm.com // Align the "stack_min" to a page boundary. 41011076SCurtis.Dunham@arm.com memState->setStackMin(roundDown(memState->getStackMin(), pageSize)); 41111076SCurtis.Dunham@arm.com} 41211076SCurtis.Dunham@arm.com 41311076SCurtis.Dunham@arm.comvoid 41411076SCurtis.Dunham@arm.comSparc64Process::argsInit(int intSize, int pageSize) 41511076SCurtis.Dunham@arm.com{ 41611076SCurtis.Dunham@arm.com SparcProcess::argsInit<uint64_t>(pageSize); 41711076SCurtis.Dunham@arm.com 41811076SCurtis.Dunham@arm.com // Stuff the trap handlers into the process address space 4197948SAli.Saidi@ARM.com initVirtMem.writeBlob(fillStart, 420237SN/A (uint8_t*)fillHandler64, sizeof(MachInst) * numFillInsts); 42110905Sandreas.sandberg@arm.com initVirtMem.writeBlob(spillStart, 422237SN/A (uint8_t*)spillHandler64, sizeof(MachInst) * numSpillInsts); 42310905Sandreas.sandberg@arm.com} 42410905Sandreas.sandberg@arm.com 425237SN/Avoid 426237SN/ASparc32Process::argsInit(int intSize, int pageSize) 427237SN/A{ 428237SN/A SparcProcess::argsInit<uint32_t>(pageSize); 429237SN/A 4305543Ssaidi@eecs.umich.edu // Stuff the trap handlers into the process address space 43110905Sandreas.sandberg@arm.com initVirtMem.writeBlob(fillStart, 43210905Sandreas.sandberg@arm.com (uint8_t*)fillHandler32, sizeof(MachInst) * numFillInsts); 43310905Sandreas.sandberg@arm.com initVirtMem.writeBlob(spillStart, 43410905Sandreas.sandberg@arm.com (uint8_t*)spillHandler32, sizeof(MachInst) * numSpillInsts); 43510905Sandreas.sandberg@arm.com} 43611075SCurtis.Dunham@arm.com 43711075SCurtis.Dunham@arm.comvoid Sparc32Process::flushWindows(ThreadContext *tc) 43810905Sandreas.sandberg@arm.com{ 43910905Sandreas.sandberg@arm.com IntReg Cansave = tc->readIntReg(NumIntArchRegs + 3); 44010905Sandreas.sandberg@arm.com IntReg Canrestore = tc->readIntReg(NumIntArchRegs + 4); 44110905Sandreas.sandberg@arm.com IntReg Otherwin = tc->readIntReg(NumIntArchRegs + 6); 44210905Sandreas.sandberg@arm.com MiscReg CWP = tc->readMiscReg(MISCREG_CWP); 44310905Sandreas.sandberg@arm.com MiscReg origCWP = CWP; 44410905Sandreas.sandberg@arm.com CWP = (CWP + Cansave + 2) % NWindows; 44510905Sandreas.sandberg@arm.com while (NWindows - 2 - Cansave != 0) { 44610905Sandreas.sandberg@arm.com if (Otherwin) { 44710905Sandreas.sandberg@arm.com panic("Otherwin non-zero.\n"); 44810905Sandreas.sandberg@arm.com } else { 44910905Sandreas.sandberg@arm.com tc->setMiscReg(MISCREG_CWP, CWP); 45010905Sandreas.sandberg@arm.com // Do the stores 45110905Sandreas.sandberg@arm.com IntReg sp = tc->readIntReg(StackPointerReg); 45210905Sandreas.sandberg@arm.com for (int index = 16; index < 32; index++) { 45310905Sandreas.sandberg@arm.com uint32_t regVal = tc->readIntReg(index); 45410905Sandreas.sandberg@arm.com regVal = htog(regVal); 45510905Sandreas.sandberg@arm.com if (!tc->getMemProxy().tryWriteBlob( 456217SN/A sp + (index - 16) * 4, (uint8_t *)®Val, 4)) { 4577494Ssteve.reinhardt@amd.com warn("Failed to save register to the stack when " 4581642SN/A "flushing windows.\n"); 4591642SN/A } 4601642SN/A } 4611642SN/A Canrestore--; 4621642SN/A Cansave++; 4631642SN/A CWP = (CWP + 1) % NWindows; 4641642SN/A } 4651642SN/A } 4661642SN/A tc->setIntReg(NumIntArchRegs + 3, Cansave); 4671642SN/A tc->setIntReg(NumIntArchRegs + 4, Canrestore); 468219SN/A tc->setMiscReg(MISCREG_CWP, origCWP); 4695992Snate@binkert.org} 4705992Snate@binkert.org 471217SN/Avoid 47210907Sandreas.sandberg@arm.comSparc64Process::flushWindows(ThreadContext *tc) 473217SN/A{ 47411076SCurtis.Dunham@arm.com IntReg Cansave = tc->readIntReg(NumIntArchRegs + 3); 47511076SCurtis.Dunham@arm.com IntReg Canrestore = tc->readIntReg(NumIntArchRegs + 4); 47611076SCurtis.Dunham@arm.com IntReg Otherwin = tc->readIntReg(NumIntArchRegs + 6); 47711076SCurtis.Dunham@arm.com MiscReg CWP = tc->readMiscReg(MISCREG_CWP); 47811076SCurtis.Dunham@arm.com MiscReg origCWP = CWP; 479217SN/A CWP = (CWP + Cansave + 2) % NWindows; 480395SN/A while (NWindows - 2 - Cansave != 0) { 481395SN/A if (Otherwin) { 482395SN/A panic("Otherwin non-zero.\n"); 483395SN/A } else { 484395SN/A tc->setMiscReg(MISCREG_CWP, CWP); 4852SN/A // Do the stores 486395SN/A IntReg sp = tc->readIntReg(StackPointerReg); 48710905Sandreas.sandberg@arm.com for (int index = 16; index < 32; index++) { 48810905Sandreas.sandberg@arm.com IntReg regVal = tc->readIntReg(index); 48910905Sandreas.sandberg@arm.com regVal = htog(regVal); 49010905Sandreas.sandberg@arm.com if (!tc->getMemProxy().tryWriteBlob( 49110905Sandreas.sandberg@arm.com sp + 2047 + (index - 16) * 8, (uint8_t *)®Val, 8)) { 49210905Sandreas.sandberg@arm.com warn("Failed to save register to the stack when " 49310905Sandreas.sandberg@arm.com "flushing windows.\n"); 494395SN/A } 4952SN/A } 496395SN/A Canrestore--; 497395SN/A Cansave++; 4982SN/A CWP = (CWP + 1) % NWindows; 49910905Sandreas.sandberg@arm.com } 50010905Sandreas.sandberg@arm.com } 5012SN/A tc->setIntReg(NumIntArchRegs + 3, Cansave); 50210905Sandreas.sandberg@arm.com tc->setIntReg(NumIntArchRegs + 4, Canrestore); 5032SN/A tc->setMiscReg(MISCREG_CWP, origCWP); 5042SN/A} 5052SN/A 50610905Sandreas.sandberg@arm.comIntReg 5072SN/ASparc32Process::getSyscallArg(ThreadContext *tc, int &i) 50810905Sandreas.sandberg@arm.com{ 5092SN/A assert(i < 6); 5102SN/A return bits(tc->readIntReg(FirstArgumentReg + i++), 31, 0); 5115739Snate@binkert.org} 5125739Snate@binkert.org 5135739Snate@binkert.orgvoid 5145739Snate@binkert.orgSparc32Process::setSyscallArg(ThreadContext *tc, int i, IntReg val) 5155739Snate@binkert.org{ 5165739Snate@binkert.org assert(i < 6); 5175739Snate@binkert.org tc->setIntReg(FirstArgumentReg + i, bits(val, 31, 0)); 5185739Snate@binkert.org} 5195739Snate@binkert.org 52010905Sandreas.sandberg@arm.comIntReg 5215739Snate@binkert.orgSparc64Process::getSyscallArg(ThreadContext *tc, int &i) 52210905Sandreas.sandberg@arm.com{ 52310905Sandreas.sandberg@arm.com assert(i < 6); 5245739Snate@binkert.org return tc->readIntReg(FirstArgumentReg + i++); 5255739Snate@binkert.org} 5265739Snate@binkert.org 52710905Sandreas.sandberg@arm.comvoid 5285739Snate@binkert.orgSparc64Process::setSyscallArg(ThreadContext *tc, int i, IntReg val) 52910905Sandreas.sandberg@arm.com{ 53010905Sandreas.sandberg@arm.com assert(i < 6); 53110905Sandreas.sandberg@arm.com tc->setIntReg(FirstArgumentReg + i, val); 53210905Sandreas.sandberg@arm.com} 53310905Sandreas.sandberg@arm.com 53410905Sandreas.sandberg@arm.comvoid 53510905Sandreas.sandberg@arm.comSparcProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret) 53610905Sandreas.sandberg@arm.com{ 53710905Sandreas.sandberg@arm.com // check for error condition. SPARC syscall convention is to 5385739Snate@binkert.org // indicate success/failure in reg the carry bit of the ccr 5395739Snate@binkert.org // and put the return value itself in the standard return value reg (). 5402SN/A PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE); 5416225Snate@binkert.org if (sysret.successful()) { 5422SN/A // no error, clear XCC.C 54310905Sandreas.sandberg@arm.com tc->setIntReg(NumIntArchRegs + 2, 544363SN/A tc->readIntReg(NumIntArchRegs + 2) & 0xEE); 545449SN/A IntReg val = sysret.returnValue(); 546363SN/A if (pstate.am) 54710905Sandreas.sandberg@arm.com val = bits(val, 31, 0); 548395SN/A tc->setIntReg(ReturnValueReg, val); 5492SN/A } else { 5505581Ssaidi@eecs.umich.edu // got an error, set XCC.C 5515581Ssaidi@eecs.umich.edu tc->setIntReg(NumIntArchRegs + 2, 5526818SLisa.Hsu@amd.com tc->readIntReg(NumIntArchRegs + 2) | 0x11); 5532SN/A IntReg val = sysret.errnoValue(); 55410905Sandreas.sandberg@arm.com if (pstate.am) 55510905Sandreas.sandberg@arm.com val = bits(val, 31, 0); 556395SN/A tc->setIntReg(ReturnValueReg, val); 557395SN/A } 5582SN/A} 5592797Sktlim@umich.edu