📄 simmisc.c
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees * of Leland Stanford Junior University. * * This file is part of the SimOS distribution. * See LICENSE file for terms of the license. * *//***************************************************************** * simmisc.c * * Miscellaneous SimOS stuff which had no better place to go. * Dan Teodosiu, 07/96 * *****************************************************************/#include <sys/signal.h>#ifndef i386#include <sys/sysinfo.h>#endif#include <sys/times.h>#include <sys/types.h>#include <sys/termios.h>#include <sys/time.h>#include <sys/file.h>#include <sys/socket.h>#include <netinet/in.h>#include <netinet/tcp.h>#include <sys/mman.h>#include <errno.h>#include <unistd.h>#include <fcntl.h>#include <stdio.h>#include <setjmp.h>#include <string.h>#include <memory.h>#include <ctype.h>#include <math.h>#include <stdlib.h>#include <sys/wait.h>#include <sys/socket.h>#include <netdb.h>#include <signal.h>#include <setjmp.h>#include "syslimits.h"#include "sim.h"#include "machine_params.h"#include "simstats.h"#include "cpu_interface.h"#include "cpu_state.h"#include "sim_error.h"#include "cpu_interface.h"#include "registry.h"#include "expect.h"#include "file_formats.h"#include "console.h"#include "simmisc.h"#include "machine_defs.h"#include "../../caches/memref.h"#include "../../cpus/mipsy/mipsy_simos.h"#include "../../cpus/embra/embra_interface.h"#include "linux_init.h"#define MAX_SCNS 48#ifdef IRIX6_4#define PromWord Reg64#else#define PromWord Reg32#endif/* Storage for sim_misc catch-all structure */SimMisc sim_misc;/* Boot prom file name */char *FPromFile;/* Shared array of CPUStates */extern CPUState* SBase;#define CPUlaunchRoutine(i) (sim_misc.launchAddr[i])#define CPUlaunched(i) (CPUlaunchRoutine(i) != 0)static int LoadFPROMImage(char* pathname, VA promAddr, char * promSimAddr, VA ramAddr, char * ramSimAddr);static int LoadCoffHeaders(char *pathname, FILHDR *fileHeader, AOUTHDR *aoutHeader, SCNHDR secHeaders[MAX_SCNS], int *fd, VA *entry);static int LoadElf32Headers(char *pathname, Elf32_Ehdr *ehdr, FILHDR *fileHeader, AOUTHDR *aoutHeader, SCNHDR secHeaders[MAX_SCNS], int *fd, VA *entry);static int LoadElf64Headers(char *pathname, Elf64_Ehdr *ehdr, FILHDR *fileHeader, AOUTHDR *aoutHeader, SCNHDR secHeaders[MAX_SCNS], int *fd, VA* entry);static void InitMemLayout(void);/***************************************************************** * SimulatorEnter - * This guy is called on the initial switch into a detailed cpu * simulator. All switches after this go through SimulatorSwitch. *****************************************************************/voidSimulatorEnter(CPUType simulator, int restoreCkpt, int swtch){ int cpu; sim_misc.enterThisCPU = simulator; for (cpu = 0; cpu < TOTAL_CPUS; cpu++) { /* Print where we are */ CPUPrint("CPU %d is at 0x%llx %s\r\n", cpu, (Reg64)SBase[cpu].PC, simName[simulator]); if ((swtch || restoreCkpt) && (SBase[cpu].cpuStatus == cpu_not_booted)) { /* don't change state for failed cpus */ } else if ((!CPUlaunched(cpu)) && (!restoreCkpt) && (!swtch) ) { SBase[cpu].outOfSlaveLoop = 0; SBase[cpu].cpuStatus = cpu_not_booted; } else { SBase[cpu].outOfSlaveLoop = 1; SBase[cpu].cpuStatus = cpu_running; } sim_misc.myCPUType = simulator; } simosCPUType = simulator; switch (simulator) { case NO_CPU: exit(0); break; case EMBRA_PAGE: case EMBRA_CACHE:#ifndef NO_EMBRA EmbraEnter(swtch);#else CPUError("Can't start Embra - simulator compiled -DNO_EMBRA\n");#endif break; case MIPSY: MipsyEnter(swtch); break; default: ASSERT(0); break; } } /***************************************************************** * SimulatorSwitch * * For now, the simulators just call this function to switch to each * other... if we get into serious sampling, we can't have the stack * grow that much. *****************************************************************/static struct { jmp_buf jmpEnv; int defined;} simulatorSwitch;void SimulatorSwitch(CPUType oldSimulator, CPUType newSimulator){ if (newSimulator != NO_CPU) { Sim_Warning("SimOS: SWITCHING from %s to %s\n", simName[oldSimulator], simName[newSimulator]); } else { Sim_Warning("SimOS: exit\n"); } ASSERT(sim_misc.myCPUType == oldSimulator); sim_misc.myCPUType = newSimulator; simosCPUType = newSimulator; if (!simulatorSwitch.defined) { setjmp(simulatorSwitch.jmpEnv); simulatorSwitch.defined = 1; } else { longjmp(simulatorSwitch.jmpEnv,1); } /* becasue cpu switch causes cyclecount to drop to 0, need to adjust callbacks */ /* xxx AdjustEventCallbackTime(); */ SimulatorEnter(sim_misc.myCPUType, 0, 1);}/* **************************************************************** * Restrictions on Printf: * Only the first argument (s) can be a string pointer! * Additional arguments must be integers (no K0_TO_MEMADDR) * At most 3 integer arguments (unless if you use int64s) * ****************************************************************/void Printf(char *s,...){#ifndef __alpha char buf[1024]; va_list ap; int cpu = CPUVec.CurrentCpuNum(); va_start(ap, s); /* we do not support %s */ vsprintf(buf, K0_TO_MEMADDR(M_FROM_CPU(cpu), s), ap); LogEntry("printf", cpu, "%s\n", buf); CPUPrint(buf); va_end(ap);#endif}/***************************************************************** * Initialize (some of the) values in sim_misc. *****************************************************************/voidSimMiscInit(int debug_intr){ int i; sim_misc.enterThisCPU = EMBRA_PAGE; /* load the FProm if specified */ if (strlen(FPromFile) != 0) { /* they have to be at least a page to copy over the FRAM cache error handler */ ASSERT(FPROM_SIZE > SIM_PAGE_SIZE); ASSERT(FRAM_SIZE > SIM_PAGE_SIZE); /* allocate space to hold the fprom and fram. * NOTE: we only need one copy of the fprom. */ sim_misc.fprom[0] = malloc(FPROM_SIZE); ASSERT(sim_misc.fprom); for (i = 0; i < TOTAL_CPUS; i++) { sim_misc.fram[i] = calloc(1, FRAM_SIZE); ASSERT(sim_misc.fram[i]); sim_misc.fprom[i] = sim_misc.fprom[0]; /* share copy */ } /* load fprom image */ if (LoadFPROMImage(FPromFile,FPROM_BASE, sim_misc.fprom[0], FRAM_BASE + SIM_PAGE_SIZE, sim_misc.fram[0] + SIM_PAGE_SIZE)) CPUError("LoadFPROMImage failed for FPROM (%s)\n", FPromFile); /* copy the first page of fprom to fram to install the cache err handler */ memcpy(sim_misc.fram[0], sim_misc.fprom[0], SIM_PAGE_SIZE); /* duplicate cpu 0's fram to other cpus */ for (i = 1; i < TOTAL_CPUS; i++) { memcpy(sim_misc.fram[i], sim_misc.fram[0], FRAM_SIZE); } /* note: fprom is already shared by all cpus */ } else { for (i = 0; i < TOTAL_CPUS; i++) { sim_misc.fram[i] = NULL; sim_misc.fprom[i] = NULL; } } /* array with 1 bit per page. 0 => coherent. 1 => incoherent */ sim_misc.incoherentPages = calloc(1,MEM_SIZE(0)/SIM_PAGE_SIZE/sizeof(char) + 1); sim_misc.debug_intr = debug_intr;#ifdef IRIX6_4 InitMemLayout();#endif}/***************************************************************** * * Support for loading and starting a kernel image. * *****************************************************************/static intLoadHeaders(char *pathname, HeaderBuf *header, FILHDR *fileHeader, bool *elfFormat, AOUTHDR *aoutHeader, SCNHDR secHeaders[MAX_SCNS], int *fd, VA *entry){ int retval; if ((*fd = open(pathname, O_RDONLY, 0)) < 0) { Sim_Warning("Problem opening kernel named %s\n", pathname); retval = errno; goto error; } retval = read(*fd,(char *)header, sizeof(HeaderBuf)); if ((retval != sizeof(HeaderBuf))) { Sim_Warning("LoadHeaders: Bad file header\n"); retval = ENOEXEC; goto error; } if (!IS_ELF(header->hb.elfHeader)) { *elfFormat = FALSE; return (LoadCoffHeaders(pathname, &(header->hb.coffHeader), aoutHeader, secHeaders, fd,entry)); } else { *elfFormat = TRUE; if (header->hb.elfHeader.e_ident[EI_CLASS] == ELFCLASS32) { return (LoadElf32Headers(pathname, &(header->hb.elfHeader), fileHeader, aoutHeader, secHeaders, fd,entry )); } else if (header->hb.elfHeader.e_ident[EI_CLASS] == ELFCLASS64) { return (LoadElf64Headers(pathname, &(header->hb.elf64Header), fileHeader, aoutHeader, secHeaders, fd,entry )); } else { Sim_Warning("Unknown elf class %d\n",header->hb.elfHeader.e_ident[EI_CLASS]); retval = ENOEXEC; } } error: (void) close(*fd); return retval;} /***************************************************************** * * Support for loading and starting a linux kernel image * (assumes elf format) * *****************************************************************/#define MAX_STRINGLEN 512static intLoadElf32Headers(char *pathname, Elf32_Ehdr *ehdr, FILHDR *fileHeader, AOUTHDR *aoutHeader, SCNHDR secHeaders[MAX_SCNS], int *fd, VA *entry){ int retval; int i; char strs[MAX_STRINGLEN]; char *secName; Elf32_Shdr shdr[MAX_SCNS]; Elf32_Shdr *strSecHdr; if (BE2HO_2(ehdr->e_shnum) >= MAX_SCNS) { Sim_Warning("Not enough section headers in Elf32LoadHeaders\n"); retval = ENOEXEC; goto error; } fileHeader->f_nscns = BE2HO_2(ehdr->e_shnum); *entry = BE2HO_2(ehdr->e_entry); if (lseek(*fd, BE2HO_4(ehdr->e_shoff), SEEK_SET) < 0) { retval = errno; Sim_Warning("Could not lseek to section headers in ElfLoadHeaders\n"); goto error; } retval = read(*fd,(char *)shdr, (BE2HO_2(ehdr->e_shnum)*sizeof(Elf32_Shdr))); if (retval < 0) { retval = errno; Sim_Warning("Could not read section headers in Elf32LoadHeaders\n"); goto error; } if (retval != sizeof(Elf32_Shdr) * BE2HO_2(ehdr->e_shnum)) { Sim_Warning("Read too few section headers in Elf32LoadHeaders\n"); retval = ENOEXEC; goto error; } strSecHdr = &shdr[BE2HO_2(ehdr->e_shstrndx)]; if (lseek(*fd, BE2HO_2(strSecHdr->sh_offset), SEEK_SET) < 0) { retval = errno; Sim_Warning("Could not lseek to strings in ElfLoadHeaders\n"); goto error; } if ( BE2HO_2(strSecHdr->sh_size) >= sizeof(strs)) { Sim_Warning("String table too large if ElfLoadHeaders\n"); retval = ENOEXEC; goto error; } retval = read(*fd,(char*)strs, BE2HO_2(strSecHdr->sh_size)); if (retval != BE2HO_2(strSecHdr->sh_size)){ if (retval < 0) { retval = errno; Sim_Warning("Could not reads strings in ElfLoadHeaders\n"); } else { retval = ENOEXEC; Sim_Warning("Read too few strings in Elf32LoadHeaders\n"); } goto error; } for (i=0; i<BE2HO_2(ehdr->e_shnum); i++) { secName = strs + BE2HO_4(shdr[i].sh_name); memcpy(secHeaders[i].s_name,secName,8); secHeaders[i].s_vaddr = BE2HO_4(shdr[i].sh_addr); secHeaders[i].s_size = BE2HO_2(shdr[i].sh_size); secHeaders[i].s_scnptr = BE2HO_2(shdr[i].sh_offset); } return 0; error: (void) close(*fd); return retval;}static intLoadElf64Headers(char *pathname, Elf64_Ehdr *ehdr, FILHDR *fileHeader, AOUTHDR *aoutHeader, SCNHDR secHeaders[MAX_SCNS], int *fd, VA *entry){ int retval; int i; char strs[MAX_STRINGLEN]; char *secName; Elf64_Shdr shdr[MAX_SCNS]; Elf64_Shdr *strSecHdr; if (BE2HO_2(ehdr->e_shnum) >= MAX_SCNS) { CPUError("Not enough section headers in Elf64LoadHeaders %d>%d\n", BE2HO_2(ehdr->e_shnum),MAX_SCNS ); retval = ENOEXEC; goto error; } fileHeader->f_nscns = BE2HO_2(ehdr->e_shnum);#if defined(TORNADO) *entry = BE2HO_8(ehdr->e_entry);#else if (IS_XKPHYS(BE2HO_8(ehdr->e_entry))) { *entry = XKPHYS_TO_CKSEG0(BE2HO_8(ehdr->e_entry)); } else if (IS_XKSEG(BE2HO_8(ehdr->e_entry))) { *entry = XKPHYS_FOUR_PAGE_OFFSET(BE2HO_8(ehdr->e_entry)) + CKSEG0_START_ADDR; } else { /* Some of the entry addresses, e.g., that of the boot prom, are not in xkphys. */ *entry = BE2HO_8(ehdr->e_entry); }#endif /* TORNADO */ if (lseek(*fd, (off_t)BE2HO_8(ehdr->e_shoff), SEEK_SET) < 0) { retval = errno; Sim_Warning("Could not lseek to section headers in Elf64LoadHeaders\n"); goto error; } retval = read(*fd,(char *)shdr, (BE2HO_2(ehdr->e_shnum)*sizeof(Elf64_Shdr))); if (retval < 0) { retval = errno; Sim_Warning("Could not read section headers in Elf64LoadHeaders\n"); goto error; } if (retval != sizeof(Elf64_Shdr) * BE2HO_2(ehdr->e_shnum)) { Sim_Warning("Read too few section headers in Elf32LoadHeaders\n"); retval = ENOEXEC; goto error; } strSecHdr = &shdr[BE2HO_2(ehdr->e_shstrndx)]; if (lseek(*fd, BE2HO_8(strSecHdr->sh_offset), SEEK_SET) < 0) { retval = errno; Sim_Warning("Could not lseek to strings in Elf64LoadHeaders\n"); goto error;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -