1/* 2 * Copyright (c) 2001-2005 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: Nathan Binkert 29 * Steve Reinhardt 30 * Ali Saidi 31 */ 32 33#include <unistd.h> 34#include <fcntl.h> 35#include <string> 36 37#include "arch/remote_gdb.hh" 38#include "base/intmath.hh" 39#include "base/loader/object_file.hh" 40#include "base/loader/symtab.hh" 41#include "base/statistics.hh" 42#include "config/full_system.hh" 43#include "cpu/thread_context.hh" 44#include "mem/page_table.hh" 45#include "mem/physical.hh" 46#include "mem/translating_port.hh" 47#include "params/Process.hh" 48#include "params/LiveProcess.hh"
|
213 214 // return CPU number to caller 215 return myIndex; 216} 217 218void 219Process::startup() 220{ 221 if (threadContexts.empty()) 222 fatal("Process %s is not associated with any CPUs!\n", name()); 223 224 // first thread context for this process... initialize & enable 225 ThreadContext *tc = threadContexts[0]; 226 227 // mark this context as active so it will start ticking. 228 tc->activate(0); 229 230 Port *mem_port; 231 mem_port = system->physmem->getPort("functional"); 232 initVirtMem = new TranslatingPort("process init port", this, 233 TranslatingPort::Always); 234 mem_port->setPeer(initVirtMem); 235 initVirtMem->setPeer(mem_port); 236} 237 238void 239Process::replaceThreadContext(ThreadContext *tc, int tcIndex) 240{ 241 if (tcIndex >= threadContexts.size()) { 242 panic("replaceThreadContext: bad tcIndex, %d >= %d\n", 243 tcIndex, threadContexts.size()); 244 } 245 246 threadContexts[tcIndex] = tc; 247} 248 249// map simulator fd sim_fd to target fd tgt_fd 250void 251Process::dup_fd(int sim_fd, int tgt_fd) 252{ 253 if (tgt_fd < 0 || tgt_fd > MAX_FD) 254 panic("Process::dup_fd tried to dup past MAX_FD (%d)", tgt_fd); 255 256 Process::FdMap *fdo = &fd_map[tgt_fd]; 257 fdo->fd = sim_fd; 258} 259 260 261// generate new target fd for sim_fd 262int 263Process::alloc_fd(int sim_fd, string filename, int flags, int mode, bool pipe) 264{ 265 // in case open() returns an error, don't allocate a new fd 266 if (sim_fd == -1) 267 return -1; 268 269 // find first free target fd 270 for (int free_fd = 0; free_fd <= MAX_FD; ++free_fd) { 271 Process::FdMap *fdo = &fd_map[free_fd]; 272 if (fdo->fd == -1) { 273 fdo->fd = sim_fd; 274 fdo->filename = filename; 275 fdo->mode = mode; 276 fdo->fileOffset = 0; 277 fdo->flags = flags; 278 fdo->isPipe = pipe; 279 fdo->readPipeSource = 0; 280 return free_fd; 281 } 282 } 283 284 panic("Process::alloc_fd: out of file descriptors!"); 285} 286 287 288// free target fd (e.g., after close) 289void 290Process::free_fd(int tgt_fd) 291{ 292 Process::FdMap *fdo = &fd_map[tgt_fd]; 293 if (fdo->fd == -1) 294 warn("Process::free_fd: request to free unused fd %d", tgt_fd); 295 296 fdo->fd = -1; 297 fdo->filename = "NULL"; 298 fdo->mode = 0; 299 fdo->fileOffset = 0; 300 fdo->flags = 0; 301 fdo->isPipe = false; 302 fdo->readPipeSource = 0; 303} 304 305 306// look up simulator fd for given target fd 307int 308Process::sim_fd(int tgt_fd) 309{ 310 if (tgt_fd > MAX_FD) 311 return -1; 312 313 return fd_map[tgt_fd].fd; 314} 315 316Process::FdMap * 317Process::sim_fd_obj(int tgt_fd) 318{ 319 if (tgt_fd > MAX_FD) 320 panic("sim_fd_obj called in fd out of range."); 321 322 return &fd_map[tgt_fd]; 323} 324bool 325Process::checkAndAllocNextPage(Addr vaddr) 326{ 327 // if this is an initial write we might not have 328 if (vaddr >= stack_min && vaddr < stack_base) { 329 pTable->allocate(roundDown(vaddr, VMPageSize), VMPageSize); 330 return true; 331 } 332 333 // We've accessed the next page of the stack, so extend the stack 334 // to cover it. 335 if (vaddr < stack_min && vaddr >= stack_base - max_stack_size) { 336 while (vaddr < stack_min) { 337 stack_min -= TheISA::PageBytes; 338 if(stack_base - stack_min > max_stack_size) 339 fatal("Maximum stack size exceeded\n"); 340 if(stack_base - stack_min > 8*1024*1024) 341 fatal("Over max stack size for one thread\n"); 342 pTable->allocate(stack_min, TheISA::PageBytes); 343 warn("Increasing stack size by one page."); 344 }; 345 return true; 346 } 347 return false; 348} 349 350 // find all offsets for currently open files and save them 351void 352Process::fix_file_offsets() { 353 Process::FdMap *fdo_stdin = &fd_map[STDIN_FILENO]; 354 Process::FdMap *fdo_stdout = &fd_map[STDOUT_FILENO]; 355 Process::FdMap *fdo_stderr = &fd_map[STDERR_FILENO]; 356 string in = fdo_stdin->filename; 357 string out = fdo_stdout->filename; 358 359 // initialize file descriptors to default: same as simulator 360 int stdin_fd, stdout_fd, stderr_fd; 361 362 if (in == "stdin" || in == "cin") 363 stdin_fd = STDIN_FILENO; 364 else if (in == "None") 365 stdin_fd = -1; 366 else{ 367 //OPEN standard in and seek to the right location 368 stdin_fd = Process::openInputFile(in); 369 if (lseek(stdin_fd, fdo_stdin->fileOffset, SEEK_SET) < 0) 370 panic("Unable to seek to correct location in file: %s", in); 371 } 372 373 if (out == "stdout" || out == "cout") 374 stdout_fd = STDOUT_FILENO; 375 else if (out == "stderr" || out == "cerr") 376 stdout_fd = STDERR_FILENO; 377 else if (out == "None") 378 stdout_fd = -1; 379 else{ 380 stdout_fd = Process::openOutputFile(out); 381 if (lseek(stdin_fd, fdo_stdout->fileOffset, SEEK_SET) < 0) 382 panic("Unable to seek to correct in file: %s", out); 383 } 384 385 stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO; 386 387 fdo_stdin->fd = stdin_fd; 388 fdo_stdout->fd = stdout_fd; 389 fdo_stderr->fd = stderr_fd; 390 391 392 for (int free_fd = 3; free_fd <= MAX_FD; ++free_fd) { 393 Process::FdMap *fdo = &fd_map[free_fd]; 394 if (fdo->fd != -1) { 395 if (fdo->isPipe){ 396 if (fdo->filename == "PIPE-WRITE") 397 continue; 398 else { 399 assert (fdo->filename == "PIPE-READ"); 400 //create a new pipe 401 int fds[2]; 402 int pipe_retval = pipe(fds); 403 404 if (pipe_retval < 0) { 405 // error 406 panic("Unable to create new pipe."); 407 } 408 fdo->fd = fds[0]; //set read pipe 409 Process::FdMap *fdo_write = &fd_map[fdo->readPipeSource]; 410 if (fdo_write->filename != "PIPE-WRITE") 411 panic ("Couldn't find write end of the pipe"); 412 413 fdo_write->fd = fds[1];//set write pipe 414 } 415 } else { 416 //Open file 417 int fd = open(fdo->filename.c_str(), fdo->flags, fdo->mode); 418 419 if (fd == -1) 420 panic("Unable to open file: %s", fdo->filename); 421 fdo->fd = fd; 422 423 //Seek to correct location before checkpoint 424 if (lseek(fd,fdo->fileOffset, SEEK_SET) < 0) 425 panic("Unable to seek to correct location in file: %s", fdo->filename); 426 } 427 } 428 } 429} 430void 431Process::find_file_offsets(){ 432 for (int free_fd = 0; free_fd <= MAX_FD; ++free_fd) { 433 Process::FdMap *fdo = &fd_map[free_fd]; 434 if (fdo->fd != -1) { 435 fdo->fileOffset = lseek(fdo->fd, 0, SEEK_CUR); 436 } else { 437 fdo->filename = "NULL"; 438 fdo->fileOffset = 0; 439 } 440 } 441} 442 443void 444Process::setReadPipeSource(int read_pipe_fd, int source_fd){ 445 Process::FdMap *fdo = &fd_map[read_pipe_fd]; 446 fdo->readPipeSource = source_fd; 447} 448 449void 450Process::FdMap::serialize(std::ostream &os) 451{ 452 SERIALIZE_SCALAR(fd); 453 SERIALIZE_SCALAR(isPipe); 454 SERIALIZE_SCALAR(filename); 455 SERIALIZE_SCALAR(flags); 456 SERIALIZE_SCALAR(readPipeSource); 457 SERIALIZE_SCALAR(fileOffset); 458} 459 460void 461Process::FdMap::unserialize(Checkpoint *cp, const std::string §ion) 462{ 463 UNSERIALIZE_SCALAR(fd); 464 UNSERIALIZE_SCALAR(isPipe); 465 UNSERIALIZE_SCALAR(filename); 466 UNSERIALIZE_SCALAR(flags); 467 UNSERIALIZE_SCALAR(readPipeSource); 468 UNSERIALIZE_SCALAR(fileOffset); 469} 470 471void 472Process::serialize(std::ostream &os) 473{ 474 SERIALIZE_SCALAR(initialContextLoaded); 475 SERIALIZE_SCALAR(brk_point); 476 SERIALIZE_SCALAR(stack_base); 477 SERIALIZE_SCALAR(stack_size); 478 SERIALIZE_SCALAR(stack_min); 479 SERIALIZE_SCALAR(next_thread_stack_base); 480 SERIALIZE_SCALAR(mmap_start); 481 SERIALIZE_SCALAR(mmap_end); 482 SERIALIZE_SCALAR(nxm_start); 483 SERIALIZE_SCALAR(nxm_end); 484 find_file_offsets(); 485 pTable->serialize(os); 486 for (int x = 0; x <= MAX_FD; x++) { 487 nameOut(os, csprintf("%s.FdMap%d", name(), x)); 488 fd_map[x].serialize(os); 489 } 490 491} 492 493void 494Process::unserialize(Checkpoint *cp, const std::string §ion) 495{ 496 UNSERIALIZE_SCALAR(initialContextLoaded); 497 UNSERIALIZE_SCALAR(brk_point); 498 UNSERIALIZE_SCALAR(stack_base); 499 UNSERIALIZE_SCALAR(stack_size); 500 UNSERIALIZE_SCALAR(stack_min); 501 UNSERIALIZE_SCALAR(next_thread_stack_base); 502 UNSERIALIZE_SCALAR(mmap_start); 503 UNSERIALIZE_SCALAR(mmap_end); 504 UNSERIALIZE_SCALAR(nxm_start); 505 UNSERIALIZE_SCALAR(nxm_end); 506 pTable->unserialize(cp, section); 507 for (int x = 0; x <= MAX_FD; x++) { 508 fd_map[x].unserialize(cp, csprintf("%s.FdMap%d", section, x)); 509 } 510 fix_file_offsets(); 511 512 checkpointRestored = true; 513 514} 515 516 517//////////////////////////////////////////////////////////////////////// 518// 519// LiveProcess member definitions 520// 521//////////////////////////////////////////////////////////////////////// 522 523 524LiveProcess::LiveProcess(LiveProcessParams * params, ObjectFile *_objFile) 525 : Process(params), objFile(_objFile), 526 argv(params->cmd), envp(params->env), cwd(params->cwd) 527{ 528 __uid = params->uid; 529 __euid = params->euid; 530 __gid = params->gid; 531 __egid = params->egid; 532 __pid = params->pid; 533 __ppid = params->ppid; 534 535 prog_fname = params->cmd[0]; 536 537 // load up symbols, if any... these may be used for debugging or 538 // profiling. 539 if (!debugSymbolTable) { 540 debugSymbolTable = new SymbolTable(); 541 if (!objFile->loadGlobalSymbols(debugSymbolTable) || 542 !objFile->loadLocalSymbols(debugSymbolTable)) { 543 // didn't load any symbols 544 delete debugSymbolTable; 545 debugSymbolTable = NULL; 546 } 547 } 548} 549 550void 551LiveProcess::argsInit(int intSize, int pageSize) 552{ 553 Process::startup(); 554 555 // load object file into target memory 556 objFile->loadSections(initVirtMem); 557 558 // Calculate how much space we need for arg & env arrays. 559 int argv_array_size = intSize * (argv.size() + 1); 560 int envp_array_size = intSize * (envp.size() + 1); 561 int arg_data_size = 0; 562 for (int i = 0; i < argv.size(); ++i) { 563 arg_data_size += argv[i].size() + 1; 564 } 565 int env_data_size = 0; 566 for (int i = 0; i < envp.size(); ++i) { 567 env_data_size += envp[i].size() + 1; 568 } 569 570 int space_needed = 571 argv_array_size + envp_array_size + arg_data_size + env_data_size; 572 if (space_needed < 32*1024) 573 space_needed = 32*1024; 574 575 // set bottom of stack 576 stack_min = stack_base - space_needed; 577 // align it 578 stack_min = roundDown(stack_min, pageSize); 579 stack_size = stack_base - stack_min; 580 // map memory 581 pTable->allocate(stack_min, roundUp(stack_size, pageSize)); 582 583 // map out initial stack contents 584 Addr argv_array_base = stack_min + intSize; // room for argc 585 Addr envp_array_base = argv_array_base + argv_array_size; 586 Addr arg_data_base = envp_array_base + envp_array_size; 587 Addr env_data_base = arg_data_base + arg_data_size; 588 589 // write contents to stack 590 uint64_t argc = argv.size(); 591 if (intSize == 8) 592 argc = htog((uint64_t)argc); 593 else if (intSize == 4) 594 argc = htog((uint32_t)argc); 595 else 596 panic("Unknown int size"); 597 598 initVirtMem->writeBlob(stack_min, (uint8_t*)&argc, intSize); 599 600 copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); 601 copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); 602 603 assert(NumArgumentRegs >= 2); 604 threadContexts[0]->setIntReg(ArgumentReg[0], argc); 605 threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base); 606 threadContexts[0]->setIntReg(StackPointerReg, stack_min); 607 608 Addr prog_entry = objFile->entryPoint(); 609 threadContexts[0]->setPC(prog_entry); 610 threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst)); 611 612#if THE_ISA != ALPHA_ISA //e.g. MIPS or Sparc 613 threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst))); 614#endif 615 616 num_processes++; 617} 618 619void 620LiveProcess::syscall(int64_t callnum, ThreadContext *tc) 621{ 622 num_syscalls++; 623 624 SyscallDesc *desc = getDesc(callnum); 625 if (desc == NULL) 626 fatal("Syscall %d out of range", callnum); 627 628 desc->doSyscall(callnum, this, tc); 629} 630 631LiveProcess * 632LiveProcess::create(LiveProcessParams * params) 633{ 634 LiveProcess *process = NULL; 635 636 string executable = 637 params->executable == "" ? params->cmd[0] : params->executable; 638 ObjectFile *objFile = createObjectFile(executable); 639 if (objFile == NULL) { 640 fatal("Can't load object file %s", executable); 641 } 642 643 if (objFile->isDynamic()) 644 fatal("Object file is a dynamic executable however only static " 645 "executables are supported!\n Please recompile your " 646 "executable as a static binary and try again.\n"); 647 648#if THE_ISA == ALPHA_ISA 649 if (objFile->hasTLS()) 650 fatal("Object file has a TLS section and single threaded TLS is not\n" 651 " currently supported for Alpha! Please recompile your " 652 "executable with \n a non-TLS toolchain.\n"); 653 654 if (objFile->getArch() != ObjectFile::Alpha) 655 fatal("Object file architecture does not match compiled ISA (Alpha)."); 656 switch (objFile->getOpSys()) { 657 case ObjectFile::Tru64: 658 process = new AlphaTru64Process(params, objFile); 659 break; 660 661 case ObjectFile::Linux: 662 process = new AlphaLinuxProcess(params, objFile); 663 break; 664 665 default: 666 fatal("Unknown/unsupported operating system."); 667 } 668#elif THE_ISA == SPARC_ISA 669 if (objFile->getArch() != ObjectFile::SPARC64 && objFile->getArch() != ObjectFile::SPARC32) 670 fatal("Object file architecture does not match compiled ISA (SPARC)."); 671 switch (objFile->getOpSys()) { 672 case ObjectFile::Linux: 673 if (objFile->getArch() == ObjectFile::SPARC64) { 674 process = new Sparc64LinuxProcess(params, objFile); 675 } else { 676 process = new Sparc32LinuxProcess(params, objFile); 677 } 678 break; 679 680 681 case ObjectFile::Solaris: 682 process = new SparcSolarisProcess(params, objFile); 683 break; 684 default: 685 fatal("Unknown/unsupported operating system."); 686 } 687#elif THE_ISA == X86_ISA 688 if (objFile->getArch() != ObjectFile::X86) 689 fatal("Object file architecture does not match compiled ISA (x86)."); 690 switch (objFile->getOpSys()) { 691 case ObjectFile::Linux: 692 process = new X86LinuxProcess(params, objFile); 693 break; 694 default: 695 fatal("Unknown/unsupported operating system."); 696 } 697#elif THE_ISA == MIPS_ISA 698 if (objFile->getArch() != ObjectFile::Mips) 699 fatal("Object file architecture does not match compiled ISA (MIPS)."); 700 switch (objFile->getOpSys()) { 701 case ObjectFile::Linux: 702 process = new MipsLinuxProcess(params, objFile); 703 break; 704 705 default: 706 fatal("Unknown/unsupported operating system."); 707 } 708#elif THE_ISA == ARM_ISA 709 if (objFile->getArch() != ObjectFile::Arm) 710 fatal("Object file architecture does not match compiled ISA (ARM)."); 711 switch (objFile->getOpSys()) { 712 case ObjectFile::Linux: 713 process = new ArmLinuxProcess(params, objFile); 714 break; 715 716 default: 717 fatal("Unknown/unsupported operating system."); 718 } 719#else 720#error "THE_ISA not set" 721#endif 722 723 724 if (process == NULL) 725 fatal("Unknown error creating process object."); 726 return process; 727} 728 729LiveProcess * 730LiveProcessParams::create() 731{ 732 return LiveProcess::create(this); 733}
|