process.cc revision 5004
1/* 2 * Copyright (c) 2003-2004 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Gabe Black 29 * Ali Saidi 30 */ 31 32#include "arch/sparc/asi.hh" 33#include "arch/sparc/handlers.hh" 34#include "arch/sparc/isa_traits.hh" 35#include "arch/sparc/process.hh" 36#include "arch/sparc/types.hh" 37#include "base/loader/object_file.hh" 38#include "base/loader/elf_object.hh" 39#include "base/misc.hh" 40#include "cpu/thread_context.hh" 41#include "mem/page_table.hh" 42#include "sim/process_impl.hh" 43#include "mem/translating_port.hh" 44#include "sim/system.hh" 45 46using namespace std; 47using namespace SparcISA; 48 49 50SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile, 51 System *_system, int stdin_fd, int stdout_fd, int stderr_fd, 52 std::vector<std::string> &argv, std::vector<std::string> &envp, 53 const std::string &cwd, 54 uint64_t _uid, uint64_t _euid, uint64_t _gid, uint64_t _egid, 55 uint64_t _pid, uint64_t _ppid) 56 : LiveProcess(nm, objFile, _system, stdin_fd, stdout_fd, stderr_fd, 57 argv, envp, cwd, _uid, _euid, _gid, _egid, _pid, _ppid) 58{ 59 60 // XXX all the below need to be updated for SPARC - Ali 61 brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); 62 brk_point = roundUp(brk_point, VMPageSize); 63 64 // Set pointer for next thread stack. Reserve 8M for main stack. 65 next_thread_stack_base = stack_base - (8 * 1024 * 1024); 66 67 //Initialize these to 0s 68 fillStart = 0; 69 spillStart = 0; 70} 71 72void SparcLiveProcess::handleTrap(int trapNum, ThreadContext *tc) 73{ 74 switch(trapNum) 75 { 76 case 0x03: //Flush window trap 77 warn("Ignoring request to flush register windows.\n"); 78 break; 79 default: 80 panic("Unimplemented trap to operating system: trap number %#x.\n", trapNum); 81 } 82} 83 84void 85Sparc32LiveProcess::startup() 86{ 87 argsInit(32 / 8, VMPageSize); 88 89 //From the SPARC ABI 90 91 //The process runs in user mode with 32 bit addresses 92 threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x0a); 93 94 //Setup default FP state 95 threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0); 96 97 threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0); 98 // 99 /* 100 * Register window management registers 101 */ 102 103 //No windows contain info from other programs 104 //threadContexts[0]->setMiscRegNoEffect(MISCREG_OTHERWIN, 0); 105 threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0); 106 //There are no windows to pop 107 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANRESTORE, 0); 108 threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0); 109 //All windows are available to save into 110 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2); 111 threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2); 112 //All windows are "clean" 113 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows); 114 threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows); 115 //Start with register window 0 116 threadContexts[0]->setMiscRegNoEffect(MISCREG_CWP, 0); 117 //Always use spill and fill traps 0 118 //threadContexts[0]->setMiscRegNoEffect(MISCREG_WSTATE, 0); 119 threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0); 120 //Set the trap level to 0 121 threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0); 122 //Set the ASI register to something fixed 123 threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY); 124 125 /* 126 * T1 specific registers 127 */ 128 //Turn on the icache, dcache, dtb translation, and itb translation. 129 threadContexts[0]->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15); 130} 131 132void 133Sparc64LiveProcess::startup() 134{ 135 argsInit(sizeof(IntReg), VMPageSize); 136 137 //From the SPARC ABI 138 139 //The process runs in user mode 140 threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x02); 141 142 //Setup default FP state 143 threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0); 144 145 threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0); 146 147 /* 148 * Register window management registers 149 */ 150 151 //No windows contain info from other programs 152 //threadContexts[0]->setMiscRegNoEffect(MISCREG_OTHERWIN, 0); 153 threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0); 154 //There are no windows to pop 155 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANRESTORE, 0); 156 threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0); 157 //All windows are available to save into 158 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2); 159 threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2); 160 //All windows are "clean" 161 //threadContexts[0]->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows); 162 threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows); 163 //Start with register window 0 164 threadContexts[0]->setMiscRegNoEffect(MISCREG_CWP, 0); 165 //Always use spill and fill traps 0 166 //threadContexts[0]->setMiscRegNoEffect(MISCREG_WSTATE, 0); 167 threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0); 168 //Set the trap level to 0 169 threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0); 170 //Set the ASI register to something fixed 171 threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY); 172 173 /* 174 * T1 specific registers 175 */ 176 //Turn on the icache, dcache, dtb translation, and itb translation. 177 threadContexts[0]->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15); 178} 179 180M5_32_auxv_t::M5_32_auxv_t(int32_t type, int32_t val) 181{ 182 a_type = TheISA::htog(type); 183 a_val = TheISA::htog(val); 184} 185 186M5_64_auxv_t::M5_64_auxv_t(int64_t type, int64_t val) 187{ 188 a_type = TheISA::htog(type); 189 a_val = TheISA::htog(val); 190} 191 192void 193Sparc64LiveProcess::argsInit(int intSize, int pageSize) 194{ 195 typedef M5_64_auxv_t auxv_t; 196 Process::startup(); 197 198 string filename; 199 if(argv.size() < 1) 200 filename = ""; 201 else 202 filename = argv[0]; 203 204 Addr alignmentMask = ~(intSize - 1); 205 206 // load object file into target memory 207 objFile->loadSections(initVirtMem); 208 209 enum hardwareCaps 210 { 211 M5_HWCAP_SPARC_FLUSH = 1, 212 M5_HWCAP_SPARC_STBAR = 2, 213 M5_HWCAP_SPARC_SWAP = 4, 214 M5_HWCAP_SPARC_MULDIV = 8, 215 M5_HWCAP_SPARC_V9 = 16, 216 //This one should technically only be set 217 //if there is a cheetah or cheetah_plus tlb, 218 //but we'll use it all the time 219 M5_HWCAP_SPARC_ULTRA3 = 32 220 }; 221 222 const int64_t hwcap = 223 M5_HWCAP_SPARC_FLUSH | 224 M5_HWCAP_SPARC_STBAR | 225 M5_HWCAP_SPARC_SWAP | 226 M5_HWCAP_SPARC_MULDIV | 227 M5_HWCAP_SPARC_V9 | 228 M5_HWCAP_SPARC_ULTRA3; 229 230 231 //Setup the auxilliary vectors. These will already have endian conversion. 232 //Auxilliary vectors are loaded only for elf formatted executables. 233 ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile); 234 if(elfObject) 235 { 236 //Bits which describe the system hardware capabilities 237 auxv.push_back(auxv_t(M5_AT_HWCAP, hwcap)); 238 //The system page size 239 auxv.push_back(auxv_t(M5_AT_PAGESZ, SparcISA::VMPageSize)); 240 //Defined to be 100 in the kernel source. 241 //Frequency at which times() increments 242 auxv.push_back(auxv_t(M5_AT_CLKTCK, 100)); 243 // For statically linked executables, this is the virtual address of the 244 // program header tables if they appear in the executable image 245 auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable())); 246 // This is the size of a program header entry from the elf file. 247 auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize())); 248 // This is the number of program headers from the original elf file. 249 auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount())); 250 //This is the address of the elf "interpreter", It should be set 251 //to 0 for regular executables. It should be something else 252 //(not sure what) for dynamic libraries. 253 auxv.push_back(auxv_t(M5_AT_BASE, 0)); 254 //This is hardwired to 0 in the elf loading code in the kernel 255 auxv.push_back(auxv_t(M5_AT_FLAGS, 0)); 256 //The entry point to the program 257 auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint())); 258 //Different user and group IDs 259 auxv.push_back(auxv_t(M5_AT_UID, uid())); 260 auxv.push_back(auxv_t(M5_AT_EUID, euid())); 261 auxv.push_back(auxv_t(M5_AT_GID, gid())); 262 auxv.push_back(auxv_t(M5_AT_EGID, egid())); 263 //Whether to enable "secure mode" in the executable 264 auxv.push_back(auxv_t(M5_AT_SECURE, 0)); 265 } 266 267 //Figure out how big the initial stack needs to be 268 269 // The unaccounted for 0 at the top of the stack 270 int mysterious_size = intSize; 271 272 //This is the name of the file which is present on the initial stack 273 //It's purpose is to let the user space linker examine the original file. 274 int file_name_size = filename.size() + 1; 275 276 int env_data_size = 0; 277 for (int i = 0; i < envp.size(); ++i) { 278 env_data_size += envp[i].size() + 1; 279 } 280 int arg_data_size = 0; 281 for (int i = 0; i < argv.size(); ++i) { 282 arg_data_size += argv[i].size() + 1; 283 } 284 285 //The info_block needs to be padded so it's size is a multiple of the 286 //alignment mask. Also, it appears that there needs to be at least some 287 //padding, so if the size is already a multiple, we need to increase it 288 //anyway. 289 int info_block_size = 290 (file_name_size + 291 env_data_size + 292 arg_data_size + 293 intSize) & alignmentMask; 294 295 int info_block_padding = 296 info_block_size - 297 file_name_size - 298 env_data_size - 299 arg_data_size; 300 301 //Each auxilliary vector is two 8 byte words 302 int aux_array_size = intSize * 2 * (auxv.size() + 1); 303 304 int envp_array_size = intSize * (envp.size() + 1); 305 int argv_array_size = intSize * (argv.size() + 1); 306 307 int argc_size = intSize; 308 int window_save_size = intSize * 16; 309 310 int space_needed = 311 mysterious_size + 312 info_block_size + 313 aux_array_size + 314 envp_array_size + 315 argv_array_size + 316 argc_size + 317 window_save_size; 318 319 stack_min = stack_base - space_needed; 320 stack_min &= alignmentMask; 321 stack_size = stack_base - stack_min; 322 323 // map memory 324 pTable->allocate(roundDown(stack_min, pageSize), 325 roundUp(stack_size, pageSize)); 326 327 // map out initial stack contents 328 Addr mysterious_base = stack_base - mysterious_size; 329 Addr file_name_base = mysterious_base - file_name_size; 330 Addr env_data_base = file_name_base - env_data_size; 331 Addr arg_data_base = env_data_base - arg_data_size; 332 Addr auxv_array_base = arg_data_base - aux_array_size - info_block_padding; 333 Addr envp_array_base = auxv_array_base - envp_array_size; 334 Addr argv_array_base = envp_array_base - argv_array_size; 335 Addr argc_base = argv_array_base - argc_size; 336#ifndef NDEBUG 337 // only used in DPRINTF 338 Addr window_save_base = argc_base - window_save_size; 339#endif 340 341 DPRINTF(Sparc, "The addresses of items on the initial stack:\n"); 342 DPRINTF(Sparc, "0x%x - file name\n", file_name_base); 343 DPRINTF(Sparc, "0x%x - env data\n", env_data_base); 344 DPRINTF(Sparc, "0x%x - arg data\n", arg_data_base); 345 DPRINTF(Sparc, "0x%x - auxv array\n", auxv_array_base); 346 DPRINTF(Sparc, "0x%x - envp array\n", envp_array_base); 347 DPRINTF(Sparc, "0x%x - argv array\n", argv_array_base); 348 DPRINTF(Sparc, "0x%x - argc \n", argc_base); 349 DPRINTF(Sparc, "0x%x - window save\n", window_save_base); 350 DPRINTF(Sparc, "0x%x - stack min\n", stack_min); 351 352 // write contents to stack 353 354 // figure out argc 355 uint64_t argc = argv.size(); 356 uint64_t guestArgc = TheISA::htog(argc); 357 358 //Write out the mysterious 0 359 uint64_t mysterious_zero = 0; 360 initVirtMem->writeBlob(mysterious_base, 361 (uint8_t*)&mysterious_zero, mysterious_size); 362 363 //Write the file name 364 initVirtMem->writeString(file_name_base, filename.c_str()); 365 366 //Copy the aux stuff 367 for(int x = 0; x < auxv.size(); x++) 368 { 369 initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize, 370 (uint8_t*)&(auxv[x].a_type), intSize); 371 initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize, 372 (uint8_t*)&(auxv[x].a_val), intSize); 373 } 374 //Write out the terminating zeroed auxilliary vector 375 const uint64_t zero = 0; 376 initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(), 377 (uint8_t*)&zero, 2 * intSize); 378 379 copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); 380 copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); 381 382 initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize); 383 384 //Stuff the trap handlers into the processes address space. 385 //Since the stack grows down and is the highest area in the processes 386 //address space, we can put stuff above it and stay out of the way. 387 int fillSize = sizeof(MachInst) * numFillInsts; 388 int spillSize = sizeof(MachInst) * numSpillInsts; 389 fillStart = stack_base; 390 spillStart = fillStart + fillSize; 391 initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler64, fillSize); 392 initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler64, spillSize); 393 394 //Set up the thread context to start running the process 395 assert(NumArgumentRegs >= 2); 396 threadContexts[0]->setIntReg(ArgumentReg[0], argc); 397 threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base); 398 threadContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias); 399 400 Addr prog_entry = objFile->entryPoint(); 401 threadContexts[0]->setPC(prog_entry); 402 threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst)); 403 threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst))); 404 405 //Align the "stack_min" to a page boundary. 406 stack_min = roundDown(stack_min, pageSize); 407 408// num_processes++; 409} 410 411void 412Sparc32LiveProcess::argsInit(int intSize, int pageSize) 413{ 414 typedef M5_32_auxv_t auxv_t; 415 Process::startup(); 416 417 string filename; 418 if(argv.size() < 1) 419 filename = ""; 420 else 421 filename = argv[0]; 422 423 //Even though this is a 32 bit process, the ABI says we still need to 424 //maintain double word alignment of the stack pointer. 425 Addr alignmentMask = ~(8 - 1); 426 427 // load object file into target memory 428 objFile->loadSections(initVirtMem); 429 430 //These are the auxilliary vector types 431 enum auxTypes 432 { 433 SPARC_AT_HWCAP = 16, 434 SPARC_AT_PAGESZ = 6, 435 SPARC_AT_CLKTCK = 17, 436 SPARC_AT_PHDR = 3, 437 SPARC_AT_PHENT = 4, 438 SPARC_AT_PHNUM = 5, 439 SPARC_AT_BASE = 7, 440 SPARC_AT_FLAGS = 8, 441 SPARC_AT_ENTRY = 9, 442 SPARC_AT_UID = 11, 443 SPARC_AT_EUID = 12, 444 SPARC_AT_GID = 13, 445 SPARC_AT_EGID = 14, 446 SPARC_AT_SECURE = 23 447 }; 448 449 enum hardwareCaps 450 { 451 M5_HWCAP_SPARC_FLUSH = 1, 452 M5_HWCAP_SPARC_STBAR = 2, 453 M5_HWCAP_SPARC_SWAP = 4, 454 M5_HWCAP_SPARC_MULDIV = 8, 455 M5_HWCAP_SPARC_V9 = 16, 456 //This one should technically only be set 457 //if there is a cheetah or cheetah_plus tlb, 458 //but we'll use it all the time 459 M5_HWCAP_SPARC_ULTRA3 = 32 460 }; 461 462 const int64_t hwcap = 463 M5_HWCAP_SPARC_FLUSH | 464 M5_HWCAP_SPARC_STBAR | 465 M5_HWCAP_SPARC_SWAP | 466 M5_HWCAP_SPARC_MULDIV | 467 M5_HWCAP_SPARC_V9 | 468 M5_HWCAP_SPARC_ULTRA3; 469 470 471 //Setup the auxilliary vectors. These will already have endian conversion. 472 //Auxilliary vectors are loaded only for elf formatted executables. 473 ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile); 474 if(elfObject) 475 { 476 //Bits which describe the system hardware capabilities 477 auxv.push_back(auxv_t(SPARC_AT_HWCAP, hwcap)); 478 //The system page size 479 auxv.push_back(auxv_t(SPARC_AT_PAGESZ, SparcISA::VMPageSize)); 480 //Defined to be 100 in the kernel source. 481 //Frequency at which times() increments 482 auxv.push_back(auxv_t(SPARC_AT_CLKTCK, 100)); 483 // For statically linked executables, this is the virtual address of the 484 // program header tables if they appear in the executable image 485 auxv.push_back(auxv_t(SPARC_AT_PHDR, elfObject->programHeaderTable())); 486 // This is the size of a program header entry from the elf file. 487 auxv.push_back(auxv_t(SPARC_AT_PHENT, elfObject->programHeaderSize())); 488 // This is the number of program headers from the original elf file. 489 auxv.push_back(auxv_t(SPARC_AT_PHNUM, elfObject->programHeaderCount())); 490 //This is the address of the elf "interpreter", It should be set 491 //to 0 for regular executables. It should be something else 492 //(not sure what) for dynamic libraries. 493 auxv.push_back(auxv_t(SPARC_AT_BASE, 0)); 494 //This is hardwired to 0 in the elf loading code in the kernel 495 auxv.push_back(auxv_t(SPARC_AT_FLAGS, 0)); 496 //The entry point to the program 497 auxv.push_back(auxv_t(SPARC_AT_ENTRY, objFile->entryPoint())); 498 //Different user and group IDs 499 auxv.push_back(auxv_t(SPARC_AT_UID, uid())); 500 auxv.push_back(auxv_t(SPARC_AT_EUID, euid())); 501 auxv.push_back(auxv_t(SPARC_AT_GID, gid())); 502 auxv.push_back(auxv_t(SPARC_AT_EGID, egid())); 503 //Whether to enable "secure mode" in the executable 504 auxv.push_back(auxv_t(SPARC_AT_SECURE, 0)); 505 } 506 507 //Figure out how big the initial stack needs to be 508 509 // The unaccounted for 8 byte 0 at the top of the stack 510 int mysterious_size = 8; 511 512 //This is the name of the file which is present on the initial stack 513 //It's purpose is to let the user space linker examine the original file. 514 int file_name_size = filename.size() + 1; 515 516 int env_data_size = 0; 517 for (int i = 0; i < envp.size(); ++i) { 518 env_data_size += envp[i].size() + 1; 519 } 520 int arg_data_size = 0; 521 for (int i = 0; i < argv.size(); ++i) { 522 arg_data_size += argv[i].size() + 1; 523 } 524 525 //The info_block - This seems to need an pad for some reason. 526 int info_block_size = 527 (mysterious_size + 528 file_name_size + 529 env_data_size + 530 arg_data_size + intSize); 531 532 //Each auxilliary vector is two 4 byte words 533 int aux_array_size = intSize * 2 * (auxv.size() + 1); 534 535 int envp_array_size = intSize * (envp.size() + 1); 536 int argv_array_size = intSize * (argv.size() + 1); 537 538 int argc_size = intSize; 539 int window_save_size = intSize * 16; 540 541 int space_needed = 542 info_block_size + 543 aux_array_size + 544 envp_array_size + 545 argv_array_size + 546 argc_size + 547 window_save_size; 548 549 stack_min = stack_base - space_needed; 550 stack_min &= alignmentMask; 551 stack_size = stack_base - stack_min; 552 553 // map memory 554 pTable->allocate(roundDown(stack_min, pageSize), 555 roundUp(stack_size, pageSize)); 556 557 // map out initial stack contents 558 uint32_t window_save_base = stack_min; 559 uint32_t argc_base = window_save_base + window_save_size; 560 uint32_t argv_array_base = argc_base + argc_size; 561 uint32_t envp_array_base = argv_array_base + argv_array_size; 562 uint32_t auxv_array_base = envp_array_base + envp_array_size; 563 //The info block is pushed up against the top of the stack, while 564 //the rest of the initial stack frame is aligned to an 8 byte boudary. 565 uint32_t arg_data_base = stack_base - info_block_size + intSize; 566 uint32_t env_data_base = arg_data_base + arg_data_size; 567 uint32_t file_name_base = env_data_base + env_data_size; 568 uint32_t mysterious_base = file_name_base + file_name_size; 569 570 DPRINTF(Sparc, "The addresses of items on the initial stack:\n"); 571 DPRINTF(Sparc, "0x%x - file name\n", file_name_base); 572 DPRINTF(Sparc, "0x%x - env data\n", env_data_base); 573 DPRINTF(Sparc, "0x%x - arg data\n", arg_data_base); 574 DPRINTF(Sparc, "0x%x - auxv array\n", auxv_array_base); 575 DPRINTF(Sparc, "0x%x - envp array\n", envp_array_base); 576 DPRINTF(Sparc, "0x%x - argv array\n", argv_array_base); 577 DPRINTF(Sparc, "0x%x - argc \n", argc_base); 578 DPRINTF(Sparc, "0x%x - window save\n", window_save_base); 579 DPRINTF(Sparc, "0x%x - stack min\n", stack_min); 580 581 // write contents to stack 582 583 // figure out argc 584 uint32_t argc = argv.size(); 585 uint32_t guestArgc = TheISA::htog(argc); 586 587 //Write out the mysterious 0 588 uint64_t mysterious_zero = 0; 589 initVirtMem->writeBlob(mysterious_base, 590 (uint8_t*)&mysterious_zero, mysterious_size); 591 592 //Write the file name 593 initVirtMem->writeString(file_name_base, filename.c_str()); 594 595 //Copy the aux stuff 596 for(int x = 0; x < auxv.size(); x++) 597 { 598 initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize, 599 (uint8_t*)&(auxv[x].a_type), intSize); 600 initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize, 601 (uint8_t*)&(auxv[x].a_val), intSize); 602 } 603 //Write out the terminating zeroed auxilliary vector 604 const uint64_t zero = 0; 605 initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(), 606 (uint8_t*)&zero, 2 * intSize); 607 608 copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); 609 copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); 610 611 initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize); 612 613 //Stuff the trap handlers into the processes address space. 614 //Since the stack grows down and is the highest area in the processes 615 //address space, we can put stuff above it and stay out of the way. 616 int fillSize = sizeof(MachInst) * numFillInsts; 617 int spillSize = sizeof(MachInst) * numSpillInsts; 618 fillStart = stack_base; 619 spillStart = fillStart + fillSize; 620 initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler32, fillSize); 621 initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler32, spillSize); 622 623 //Set up the thread context to start running the process 624 //assert(NumArgumentRegs >= 2); 625 //threadContexts[0]->setIntReg(ArgumentReg[0], argc); 626 //threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base); 627 threadContexts[0]->setIntReg(StackPointerReg, stack_min); 628 629 uint32_t prog_entry = objFile->entryPoint(); 630 threadContexts[0]->setPC(prog_entry); 631 threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst)); 632 threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst))); 633 634 //Align the "stack_min" to a page boundary. 635 stack_min = roundDown(stack_min, pageSize); 636 637// num_processes++; 638} 639