📄 simmisc.c
字号:
static voidJumpToResetVec(void){ int firstCPU; VA entry=FPROM_BASE; int machine; for (machine = 0; machine < NUM_MACHINES; machine++) { /* This deterministically enters detailed mode so that every */ /* instruction is emulated */ firstCPU = FIRST_CPU(machine); SBase[firstCPU].R[4] = 0; SBase[firstCPU].R[5] = 0; SBase[firstCPU].R[6] = 0; SBase[firstCPU].PC = entry; CPUWarning( "Fprom image machine=%d pc=%llx \n", machine, (uint64)SBase[firstCPU].PC); SIM_DEBUG(('g', "Fprom image machine=%d pc=%x \n", machine, SBase[firstCPU].PC)); } SimulatorEnter(simosCPUType, 0, 0); ASSERT(0);}/* * Read and start the program. */static voidLoadNgo(char *pathname, int argc, char **argv){ int retval; int firstCPU; VA entry=0; VA argcVA, argvVA; TagList tags; VA endaddr; bool elfFormat = FALSE; int machine; for (machine = 0; machine < NUM_MACHINES; machine++) { retval = LoadImage(pathname, machine, (VA)SIMCP0_KSEG0_ADDR, /* img addr */ (VA)SIMCP0_KSEG0_ADDR, /* ld addr: no relocation *//* this used to be mem_size/num_cells, which is still valid for SIM32 but not for SIM64 sparse addresses. But this should still work for SIM32. - KG */ MEM_SIZE(machine) / NUM_CPUS(machine), FALSE, &elfFormat, &entry); #ifdef SIM_LINUX if (elfFormat) { retval = 0; TagInit(machine, &tags); /* copy tag data to end of vmem --ejs */ endaddr = (VA)SIMCP0_KSEG0_ADDR + (MEM_SIZE(machine) / NUM_CELLS(machine)); if (memcpy(K0_TO_MEMADDR(machine, BE2HO_4(endaddr - sizeof(TagList))), &tags, sizeof(TagList)) == NULL) { retval = errno; Sim_Warning("Bad tags copy in LoadNgo\n"); Sim_Warning("vaddr = 0x%08x\n", BE2HO_4(endaddr - sizeof(TagList))); perror(pathname); return; } }#endif if (retval != 0) { perror(pathname); return; } /* Must copy argc / argv to simulated memory so that kernel * can read the arguments. */ copy_bootline_args(machine, argc, argv, &argcVA, &argvVA); /* CPUWarning("Boot args copied to 0x%08x 0x%08x\n", argcVA, argvVA); */ /* This deterministically enters detailed mode so that every */ /* instruction is emulated */ firstCPU = FIRST_CPU(machine); SBase[firstCPU].R[4] = argc; SBase[firstCPU].R[5] = argvVA; SBase[firstCPU].R[6] = 0; SBase[firstCPU].PC = entry; CPUWarning( "Load image machine=%d pc=%llx argc=%x argv = %x \n", machine, (uint64)SBase[firstCPU].PC, SBase[firstCPU].R[4], SBase[firstCPU].R[5]); SIM_DEBUG(('g', "Load image machine=%d pc=%x argc=%x argv = %x \n", machine, SBase[firstCPU].PC, SBase[firstCPU].R[4], SBase[firstCPU].R[5])); } SimulatorEnter(simosCPUType, 0, 0); ASSERT(0);}/* * Launch slave cpu : can get here through two different paths: * from simmagic.c:MAGIC_PPC_OP_STARTSLAVENODE for setting the * start address of a slave cpu * from tcl_init.c:hive launchslave for passing arguments to * a cell when booting it * * Returns: * 0 - success * 1 - failure, this CPU has already been launched. */intLaunchSlave(int cpu, VA pc, Reg a0, Reg a1,Reg a2, Reg a3){ ASSERT(0 <= cpu && cpu < TOTAL_CPUS);#if !defined(IRIX6_4) ASSERT(IS_KSEG0(pc));#endif if (SBase[cpu].cpuStatus == cpu_running || SBase[cpu].outOfSlaveLoop != 0) return 1; /* already running */ /* Sim_Warning("LaunchSlave: cpu %d PC 0x%08x" */ /* "a0 0x%08x a1 0x%08x a2 0x%08x a3 0x%08x\n", */ /* cpu, pc, a0, a1, a2, a3); */ SBase[cpu].cpuStatus = cpu_running; /* mipsy polls this each cycle */ SBase[cpu].PC = pc; SBase[cpu].nPC = 4 + pc;#if !defined(SIM_MIPS64) SBase[cpu].R[4] = (int)a0; SBase[cpu].R[5] = (int)a1; SBase[cpu].R[6] = (int)a2; SBase[cpu].R[7] = (int)a3;#else SBase[cpu].R[4] = a0; SBase[cpu].R[5] = a1; SBase[cpu].R[6] = a2; SBase[cpu].R[7] = a3; SBase[cpu].CP0[C0_SR] = SR_KX; /* 64bit kernel mode with interrupt disabled */ SBase[cpu].cpuMode = KERNEL_MODE; SBase[cpu].is32bitMode = FALSE;#endif SBase[cpu].outOfSlaveLoop = 1; /* embra polls this each context switch */ return 0;}intResetCPUs(int firstcpu, int lastcpu){ /* still to be done: reset interrupts, pending sips, etc. */ int err = 0; if (lastcpu != firstcpu) { Sim_Warning("SIMOS: reset cpus %d through %d\n", firstcpu, lastcpu); } else { Sim_Warning("SIMOS: reset cpu %d\n", firstcpu); } for (;firstcpu <= lastcpu; firstcpu++) { if ((err = CPUVec.ResetCPU(firstcpu))) break; SBase[firstcpu].cpuStatus = cpu_not_booted; /* mipsy now skips this cpu */ SBase[firstcpu].outOfSlaveLoop = 0; /* embra now skips this cpu */ } return err;}voidSimHalt(void){ exit(0);}#define MAX_IMG_NAME 256/* Tcl interface into hive-specifics. */intHiveCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ if (argc <= 2) { Tcl_AppendResult(interp, "hive function args...\n", NULL); return TCL_ERROR; } if (!strcmp(argv[1], "loadimage")) { char* img_name; VA start = 0; unsigned len = 0; bool format; VA entryAddr; char result[32]; if (argc != 5) { Tcl_AppendResult(interp, "hive loadimage name start len\n", NULL); return TCL_ERROR; } img_name = argv[2]; Tcl_GetInt(interp, argv[3], (int*)&start); Tcl_GetInt(interp, argv[4], (int*)&len); if (!IS_KSEG0(start) || !IS_KSEG0(start+len)) { Tcl_AppendResult(interp, "hive loadimage bad address range ", argv[3], " ", argv[4], "\n", NULL); return TCL_ERROR; } /* XXX 64bit */ if (LoadImage(img_name, 0, /* machine */ start, /* img addr */ start, /* ld addr */ len, FALSE, /* data reloc */ &format, &entryAddr) != 0) { Tcl_AppendResult(interp, "hive loadimage can't load img ",img_name,"\n",NULL); return TCL_ERROR; } /* return entrypoint address (in hex) */ sprintf(result, "0x%08llx", (Reg64)entryAddr); Tcl_AppendResult(interp, result, NULL); return TCL_OK; } else if (!strcmp(argv[1], "launchslave")) { int cpu = 0; VA entry = 0; VA argvp = 0; VA env = 0; if (argc != 6) { Tcl_AppendResult(interp, "hive launchslave cpu entry argv env\n", NULL); return TCL_ERROR; } Tcl_GetInt(interp, argv[2], (int*)&cpu); Tcl_GetInt(interp, argv[3], (int*)&entry); Tcl_GetInt(interp, argv[4], (int*)&argvp); Tcl_GetInt(interp, argv[5], (int*)&env); if (!IS_KSEG0(entry) || !IS_KSEG0(argvp) || (!IS_KSEG0(env) && env)) { Tcl_AppendResult(interp, "hive launchslave bad address ", argv[3]," ",argv[4]," ",argv[5],"\n",NULL); return TCL_ERROR; } if (LaunchSlave(cpu, (VA)PTR_TO_UINT64(entry), 0, argvp, env, 0) != 0) { Tcl_AppendResult(interp, "1", NULL); /* failure */ } else { Tcl_AppendResult(interp, "0", NULL); /* success */ } return TCL_OK; } else if (!strcmp(argv[1], "resetcpus")) { uint firstcpu = 0; uint lastcpu = 0; if (argc != 4) { Tcl_AppendResult(interp, "hive resetcpus firstcpu lastcpu\n", NULL); return TCL_ERROR; } Tcl_GetInt(interp, argv[2], (int*)&firstcpu); Tcl_GetInt(interp, argv[3], (int*)&lastcpu); if (firstcpu > lastcpu || lastcpu >= TOTAL_CPUS) { Tcl_AppendResult(interp, "hive resetcpus bad cpupair ", argv[2]," ",argv[3], "\n",NULL); return TCL_ERROR; } if (ResetCPUs(firstcpu, lastcpu) != 0) { Tcl_AppendResult(interp, "1", NULL); /* failure */ } else { Tcl_AppendResult(interp, "0", NULL); /* success */ } return TCL_OK; } else { Tcl_AppendResult(interp, "bad hive function\n", NULL); return TCL_ERROR; }}/* * Main loop for master processor startup */voidSimPromEnter(void){ char line[MAXBOOTARGBYTES]; int retval; int i; char prompt[64]; static int prompt_no = 1; int console = 0; char usage[] = "\n\rBoot PROM commands\n\r" "------------------\n\r" "b pathname - Boot the kernel\n\r" "r - Reset\n\r" "q - Quit SimOS\n\r" "h - Halt the machine\n\r" "d - Enter the debugger\n\r" "? - This help listing\r\n\n"; /* indicate that this cpu has launched for other people to check */ for (i = 0; i < NUM_MACHINES; i++) { sim_misc.launchAddr[FIRST_CPU(i)] = (void *)SimPromEnter; /* BOGUS */ } while (1) { sprintf(prompt, "\rsimosboot (%d)> ", prompt_no++); sim_console_write(console, prompt, strlen(prompt)); for (i = 0; i < MAXBOOTARGBYTES; i++) { /* * Expect hooks * - expect characters take priority over user typed chars */ if ((line[i] = ExpectGetChar(console))) { sim_console_write(console, &line[i], 1); } else { line[i] = retval = sim_console_in(console); /* hmmm */ if (retval == -1) {#ifdef sgi sginap(0);#elif sun sleep(1);#endif i--; continue; } sim_console_write(console, &line[i], 1); } if (line[i] == '\n' || line[i] == '\r') { i++; sim_console_write(console, "\r\n", 2); break; } if (line[i] == 'C'-'@') { sim_console_write(console, "\r\n", 2); exit(0); } } line[i] = '\000'; switch (line[0]) { case 'b': case 'B': { /* B pathname - Boot the specified kernel */ char *arg, *file; char* argv[MAXBOOTARGS+1]; /* list of arguments */ int argc; /* argcount (for kernel) */ for (arg = line + 1; *arg == ' '; arg++) ; /* skip spaces */ if (!*arg) { sim_console_write(console, "Must specify kernel file\n", 25); break; } else { file = arg; while (*arg && !isspace(*arg)) arg++; argc = 0; if (*arg) { *arg = 0; /* 0-terminate file name */ arg++; for(argc = 0; argc < MAXBOOTARGS; argc++) { for ( ; isspace(*arg); arg++) ; /* skip spaces */ if (!*arg) break; argv[argc] = arg; while (*arg && !isspace(*arg)) arg++; if (*arg) { *arg = 0; arg++; } } } } LoadNgo(file, argc, argv); break; } case 'r': case 'R': { /* Reset - Execute from the reset vector. */ sim_console_write(console, "Executing from the reset vector\n", 32); JumpToResetVec(); break; } case 'h': case 'H': { /* H - Halt the simulated machine. */ SimHalt(); break; } case 'd': case 'D': { kill((int)getpid(), SIGUSR1); break; } case '?': { sim_console_write(console, usage, sizeof(usage)-1); break; } case 'q': case 'Q': sim_console_write(console, "\r\n", 2); exit(0); break; default: sim_console_write(console, "Unknown command\n", 16); } }}#ifdef IRIX6_4static PA nodeMemSize[MAX_MACHINES][SIM_MAXCPUS];static MA nodeMemStartMA[MAX_MACHINES][SIM_MAXCPUS];static PA memPerNode[MAX_MACHINES];static void InitMemLayout(void){ int i, machine; /* XXX for now assume each node has same amount of memory and that it's contiguous in one bank. This will be changed soon */ for (machine=0; machine<NUM_MACHINES; machine++) { MA startMA = SIM_MEM_ADDR(machine);#ifdef SIM_ORIGIN int numnodes = (NUM_CPUS(machine) + 1)/ 2;#else int numnodes = NUM_CPUS(machine);#endif memPerNode[machine] = MEM_SIZE(machine)/numnodes; for (i=0; i<numnodes; i++) { nodeMemSize[machine][i] = MEM_SIZE(machine)/numnodes; nodeMemStartMA[machine][i] = startMA; startMA += MEM_SIZE(machine)/numnodes; } } }intIsValidPA(int machNo, PA pAddr){ int node = pAddr >> MAGIC_NODE_SIZE_BITS; PA nodeOffset = pAddr & MAGIC_NODE_OFFSET_MASK; if (nodeOffset >= nodeMemSize[machNo][node]) { return 0; } else { return 1; }}MAPhysToMemAddr(int machNo, PA pAddr){ int node = pAddr >> MAGIC_NODE_SIZE_BITS; PA nodeOffset = pAddr & MAGIC_NODE_OFFSET_MASK; ASSERT(node < SIM_MAXCPUS); /* NOTE that '>' is used instead of '>=' because this function is also called to get the end addr */ if (nodeOffset > nodeMemSize[machNo][node]) { ASSERT(0); return 0; /* for compiler warning */ } else { return nodeMemStartMA[machNo][node] + nodeOffset; }}PAMemToPhysAddr(int machNo, MA mAddr){ PA machineOffset = (PA)(mAddr - SIM_MEM_ADDR(machNo)); PA node = machineOffset / memPerNode[machNo]; PA nodeOffset = (PA)(mAddr - nodeMemStartMA[machNo][node]); ASSERT(IS_VALID_MA(machNo, mAddr)); return (node << MAGIC_NODE_SIZE_BITS) | nodeOffset;}#endif /* IRIX6_4 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -