⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alpha_tru64_process.cc

📁 linux下基于c++的处理器仿真平台。具有处理器流水线
💻 CC
📖 第 1 页 / 共 5 页
字号:
	    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 + -