?? alpha_tru64_process.cc
字號:
break; default: warn("setsysinfo: unknown op %d\n", op); break; } return 0; } /// Target fnctl() handler. static SyscallReturn fcntlFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { int fd = xc->getSyscallArg(0); if (fd < 0 || process->sim_fd(fd) < 0) return -EBADF; int cmd = xc->getSyscallArg(1); switch (cmd) { case 0: // F_DUPFD // if we really wanted to support this, we'd need to do it // in the target fd space. warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd); return -EMFILE; case 1: // F_GETFD (get close-on-exec flag) case 2: // F_SETFD (set close-on-exec flag) return 0; case 3: // F_GETFL (get file flags) case 4: // F_SETFL (set file flags) // not sure if this is totally valid, but we'll pass it through // to the underlying OS warn("fcntl(%d, %d) passed through to host\n", fd, cmd); return fcntl(process->sim_fd(fd), cmd); // return 0; case 7: // F_GETLK (get lock) case 8: // F_SETLK (set lock) case 9: // F_SETLKW (set lock and wait) // don't mess with file locking... just act like it's OK warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd); return 0; default: warn("Unknown fcntl command %d\n", cmd); return 0; } } /// Target getdirentries() handler. static SyscallReturn getdirentriesFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) {#ifdef __CYGWIN__ panic("getdirent not implemented on cygwin!");#else int fd = process->sim_fd(xc->getSyscallArg(0)); Addr tgt_buf = xc->getSyscallArg(1); int tgt_nbytes = xc->getSyscallArg(2); Addr tgt_basep = xc->getSyscallArg(3); char * const host_buf = new char[tgt_nbytes]; // just pass basep through uninterpreted. TypedBufferArg<int64_t> basep(tgt_basep); basep.copyIn(xc->mem); long host_basep = (off_t)*basep; int host_result = getdirentries(fd, host_buf, tgt_nbytes, &host_basep); // check for error if (host_result < 0) { delete [] host_buf; return -errno; } // no error: copy results back to target space Addr tgt_buf_ptr = tgt_buf; char *host_buf_ptr = host_buf; char *host_buf_end = host_buf + host_result; while (host_buf_ptr < host_buf_end) { global_dirent *host_dp = (global_dirent *)host_buf_ptr; int namelen = strlen(host_dp->d_name); // Actual size includes padded string rounded up for alignment. // Subtract 256 for dummy char array in Tru64::dirent definition. // Add 1 to namelen for terminating null char. int tgt_bufsize = sizeof(Tru64::dirent) - 256 + RoundUp(namelen+1, 8); TypedBufferArg<Tru64::dirent> tgt_dp(tgt_buf_ptr, tgt_bufsize); tgt_dp->d_ino = host_dp->d_ino; tgt_dp->d_reclen = tgt_bufsize; tgt_dp->d_namlen = namelen; strcpy(tgt_dp->d_name, host_dp->d_name); tgt_dp.copyOut(xc->mem); tgt_buf_ptr += tgt_bufsize; host_buf_ptr += host_dp->d_reclen; } delete [] host_buf; *basep = host_basep; basep.copyOut(xc->mem); return tgt_buf_ptr - tgt_buf;#endif } /// Target sigreturn() handler. static SyscallReturn sigreturnFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { RegFile *regs = &xc->regs; TypedBufferArg<Tru64::sigcontext> sc(xc->getSyscallArg(0)); sc.copyIn(xc->mem); // Restore state from sigcontext structure. // Note that we'll advance PC <- NPC before the end of the cycle, // so we need to restore the desired PC into NPC. // The current regs->pc will get clobbered. regs->npc = sc->sc_pc; for (int i = 0; i < 31; ++i) { regs->intRegFile[i] = sc->sc_regs[i]; regs->floatRegFile.q[i] = sc->sc_fpregs[i]; } regs->miscRegs.fpcr = sc->sc_fpcr; return 0; } /// Target table() handler. static SyscallReturn tableFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { int id = xc->getSyscallArg(0); // table ID int index = xc->getSyscallArg(1); // index into table // arg 2 is buffer pointer; type depends on table ID int nel = xc->getSyscallArg(3); // number of elements int lel = xc->getSyscallArg(4); // expected element size switch (id) { case Tru64::TBL_SYSINFO: { if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo)) return -EINVAL; TypedBufferArg<Tru64::tbl_sysinfo> elp(xc->getSyscallArg(2)); const int clk_hz = one_million; elp->si_user = curTick / (Clock::Frequency / clk_hz); elp->si_nice = 0; elp->si_sys = 0; elp->si_idle = 0; elp->wait = 0; elp->si_hz = clk_hz; elp->si_phz = clk_hz; elp->si_boottime = seconds_since_epoch; // seconds since epoch? elp->si_max_procs = process->numCpus(); elp.copyOut(xc->mem); return 0; } default: cerr << "table(): id " << id << " unknown." << endl; return -EINVAL; } } /// Array of syscall descriptors, indexed by call number. static SyscallDesc syscallDescs[]; /// Number of syscalls in syscallDescs[]. static const int Num_Syscall_Descs; /// Max supported syscall number. static const int Max_Syscall_Desc; // // Mach syscalls -- identified by negated syscall numbers // /// Create a stack region for a thread. static SyscallReturn stack_createFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { TypedBufferArg<Tru64::vm_stack> argp(xc->getSyscallArg(0)); argp.copyIn(xc->mem); // if the user chose an address, just let them have it. Otherwise // pick one for them. if (argp->address == 0) { argp->address = process->next_thread_stack_base; int stack_size = (argp->rsize + argp->ysize + argp->gsize); process->next_thread_stack_base -= stack_size; argp.copyOut(xc->mem); } return 0; } /// NXM library version stamp. static const int NXM_LIB_VERSION = 301003; /// This call sets up the interface between the user and kernel /// schedulers by creating a shared-memory region. The shared memory /// region has several structs, some global, some per-RAD, some per-VP. static SyscallReturn nxm_task_initFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { TypedBufferArg<Tru64::nxm_task_attr> attrp(xc->getSyscallArg(0)); TypedBufferArg<Addr> configptr_ptr(xc->getSyscallArg(1)); attrp.copyIn(xc->mem); if (attrp->nxm_version != NXM_LIB_VERSION) { cerr << "nxm_task_init: thread library version mismatch! " << "got " << attrp->nxm_version << ", expected " << NXM_LIB_VERSION << endl; abort(); } if (attrp->flags != Tru64::NXM_TASK_INIT_VP) { cerr << "nxm_task_init: bad flag value " << attrp->flags << " (expected " << Tru64::NXM_TASK_INIT_VP << ")" << endl; abort(); } const Addr base_addr = 0x12000; // was 0x3f0000000LL; Addr cur_addr = base_addr; // next addresses to use // first comes the config_info struct Addr config_addr = cur_addr; cur_addr += sizeof(Tru64::nxm_config_info); // next comes the per-cpu state vector Addr slot_state_addr = cur_addr; int slot_state_size = process->numCpus() * sizeof(Tru64::nxm_slot_state_t); cur_addr += slot_state_size; // now the per-RAD state struct (we only support one RAD) cur_addr = 0x14000; // bump up addr for alignment Addr rad_state_addr = cur_addr; int rad_state_size = (sizeof(Tru64::nxm_shared) + (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state)); cur_addr += rad_state_size; // now initialize a config_info struct and copy it out to user space TypedBufferArg<Tru64::nxm_config_info> config(config_addr); config->nxm_nslots_per_rad = process->numCpus(); config->nxm_nrads = 1; // only one RAD in our system! config->nxm_slot_state = slot_state_addr; config->nxm_rad[0] = rad_state_addr; config.copyOut(xc->mem); // initialize the slot_state array and copy it out TypedBufferArg<Tru64::nxm_slot_state_t> slot_state(slot_state_addr, slot_state_size); for (int i = 0; i < process->numCpus(); ++i) { // CPU 0 is bound to the calling process; all others are available slot_state[i] = (i == 0) ? Tru64::NXM_SLOT_BOUND : Tru64::NXM_SLOT_AVAIL; } slot_state.copyOut(xc->mem); // same for the per-RAD "shared" struct. Note that we need to // allocate extra bytes for the per-VP array which is embedded at // the end. TypedBufferArg<Tru64::nxm_shared> rad_state(rad_state_addr, rad_state_size); rad_state->nxm_callback = attrp->nxm_callback; rad_state->nxm_version = attrp->nxm_version; rad_state->nxm_uniq_offset = attrp->nxm_uniq_offset; for (int i = 0; i < process->numCpus(); ++i) { Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[i]; ssp->nxm_u.sigmask = 0; ssp->nxm_u.sig = 0; ssp->nxm_u.flags = 0; ssp->nxm_u.cancel_state = 0; ssp->nxm_u.nxm_ssig = 0; ssp->nxm_bits = 0; ssp->nxm_quantum = attrp->nxm_quantum; ssp->nxm_set_quantum = attrp->nxm_quantum; ssp->nxm_sysevent = 0; if (i == 0) { uint64_t uniq = xc->regs.miscRegs.uniq; ssp->nxm_u.pth_id = uniq + attrp->nxm_uniq_offset; ssp->nxm_u.nxm_active = uniq | 1; } else { ssp->nxm_u.pth_id = 0; ssp->nxm_u.nxm_active = 0; } } rad_state.copyOut(xc->mem); // // copy pointer to shared config area out to user // *configptr_ptr = config_addr; configptr_ptr.copyOut(xc->mem); // Register this as a valid address range with the process process->nxm_start = base_addr; process->nxm_end = cur_addr; return 0; } /// Initialize execution context. static void init_exec_context(ExecContext *ec, Tru64::nxm_thread_attr *attrp, uint64_t uniq_val) { memset(&ec->regs, 0, sizeof(ec->regs)); ec->regs.intRegFile[ArgumentReg0] = attrp->registers.a0; ec->regs.intRegFile[27/*t12*/] = attrp->registers.pc; ec->regs.intRegFile[StackPointerReg] = attrp->registers.sp; ec->regs.miscRegs.uniq = uniq_val; ec->regs.pc = attrp->registers.pc; ec->regs.npc = attrp->registers.pc + sizeof(MachInst); ec->activate(); } /// Create thread. static SyscallReturn nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { TypedBufferArg<Tru64::nxm_thread_attr> attrp(xc->getSyscallArg(0)); TypedBufferArg<uint64_t> kidp(xc->getSyscallArg(1)); int thread_index = xc->getSyscallArg(2); // get attribute args attrp.copyIn(xc->mem); if (attrp->version != NXM_LIB_VERSION) { cerr << "nxm_thread_create: thread library version mismatch! " << "got " << attrp->version << ", expected " << NXM_LIB_VERSION << endl; abort(); } if (thread_index < 0 | thread_index > process->numCpus()) { cerr << "nxm_thread_create: bad thread index " << thread_index << endl; abort(); } // On a real machine, the per-RAD shared structure is in // shared memory, so both the user and kernel can get at it. // We don't have that luxury, so we just copy it in and then // back out again. int rad_state_size = (sizeof(Tru64::nxm_shared) + (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state)); TypedBufferArg<Tru64::nxm_shared> rad_state(0x14000, rad_state_size);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -