tru64.hh

来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· HH 代码 · 共 1,211 行 · 第 1/3 页

HH
1,211
字号
        TypedBufferArg<T> tgt(addr);#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__)        tgt->f_type = 0;#else        tgt->f_type = htog(host->f_type);#endif        tgt->f_bsize = htog(host->f_bsize);        tgt->f_blocks = htog(host->f_blocks);        tgt->f_bfree = htog(host->f_bfree);        tgt->f_bavail = htog(host->f_bavail);        tgt->f_files = htog(host->f_files);        tgt->f_ffree = htog(host->f_ffree);        // Is this as string normally?        memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid));        tgt.copyOut(mem);    }    /// The target system's hostname.    static const char *hostname;    /// Target getdirentries() handler.    static SyscallReturn    getdirentriesFunc(SyscallDesc *desc, int callnum, LiveProcess *process,                      ThreadContext *tc)    {        using namespace TheISA;#ifdef __CYGWIN__        panic("getdirent not implemented on cygwin!");#else        int fd = process->sim_fd(tc->getSyscallArg(0));        Addr tgt_buf = tc->getSyscallArg(1);        int tgt_nbytes = tc->getSyscallArg(2);        Addr tgt_basep = tc->getSyscallArg(3);        char * const host_buf = new char[tgt_nbytes];        // just pass basep through uninterpreted.        TypedBufferArg<int64_t> basep(tgt_basep);        basep.copyIn(tc->getMemPort());        long host_basep = (off_t)htog((int64_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(tc->getMemPort());            tgt_buf_ptr += tgt_bufsize;            host_buf_ptr += host_dp->d_reclen;        }        delete [] host_buf;        *basep = htog((int64_t)host_basep);        basep.copyOut(tc->getMemPort());        return tgt_buf_ptr - tgt_buf;#endif    }    /// Target sigreturn() handler.    static SyscallReturn    sigreturnFunc(SyscallDesc *desc, int callnum, LiveProcess *process,                  ThreadContext *tc)    {        using namespace TheISA;        using TheISA::RegFile;        TypedBufferArg<Tru64::sigcontext> sc(tc->getSyscallArg(0));        sc.copyIn(tc->getMemPort());        // 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.        tc->setNextPC(htog(sc->sc_pc));        for (int i = 0; i < 31; ++i) {            tc->setIntReg(i, htog(sc->sc_regs[i]));            tc->setFloatRegBits(i, htog(sc->sc_fpregs[i]));        }        tc->setMiscRegNoEffect(AlphaISA::MISCREG_FPCR, htog(sc->sc_fpcr));        return 0;    }    //    // Mach syscalls -- identified by negated syscall numbers    //    /// Create a stack region for a thread.    static SyscallReturn    stack_createFunc(SyscallDesc *desc, int callnum, LiveProcess *process,                     ThreadContext *tc)    {        using namespace TheISA;        TypedBufferArg<Tru64::vm_stack> argp(tc->getSyscallArg(0));        argp.copyIn(tc->getMemPort());        int stack_size =            gtoh(argp->rsize) + gtoh(argp->ysize) + gtoh(argp->gsize);        // if the user chose an address, just let them have it.  Otherwise        // pick one for them.        Addr stack_base = gtoh(argp->address);        if (stack_base == 0) {            stack_base = process->next_thread_stack_base;            process->next_thread_stack_base -= stack_size;        }        Addr rounded_stack_base = roundDown(stack_base, VMPageSize);        Addr rounded_stack_size = roundUp(stack_size, VMPageSize);        DPRINTF(SyscallVerbose,                "stack_create: allocating stack @ %#x size %#x "                "(rounded from %#x, %#x)\n",                rounded_stack_base, rounded_stack_size,                stack_base, stack_size);        // map memory        process->pTable->allocate(rounded_stack_base, rounded_stack_size);        argp->address = gtoh(rounded_stack_base);        argp.copyOut(tc->getMemPort());        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, LiveProcess *process,                      ThreadContext *tc)    {        using namespace std;        using namespace TheISA;        TypedBufferArg<Tru64::nxm_task_attr> attrp(tc->getSyscallArg(0));        TypedBufferArg<Addr> configptr_ptr(tc->getSyscallArg(1));        attrp.copyIn(tc->getMemPort());        if (gtoh(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 (gtoh(attrp->flags) != Tru64::NXM_TASK_INIT_VP) {            cerr << "nxm_task_init: bad flag value " << attrp->flags                 << " (expected " << Tru64::NXM_TASK_INIT_VP << ")" << endl;            abort();        }        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 = htog(process->numCpus());        config->nxm_nrads = htog(1);	// only one RAD in our system!        config->nxm_slot_state = htog(slot_state_addr);        config->nxm_rad[0] = htog(rad_state_addr);        // 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            // XXX this code should have an endian conversion, but I don't think            // it works anyway            slot_state[i] =                (i == 0) ? Tru64::NXM_SLOT_BOUND : Tru64::NXM_SLOT_AVAIL;        }        // 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 = htog(0);            ssp->nxm_u.sig = htog(0);            ssp->nxm_u.flags = htog(0);            ssp->nxm_u.cancel_state = htog(0);            ssp->nxm_u.nxm_ssig = 0;            ssp->nxm_bits = htog(0);            ssp->nxm_quantum = attrp->nxm_quantum;            ssp->nxm_set_quantum = attrp->nxm_quantum;            ssp->nxm_sysevent = htog(0);            if (i == 0) {                uint64_t uniq = tc->readMiscRegNoEffect(AlphaISA::MISCREG_UNIQ);                ssp->nxm_u.pth_id = htog(uniq + gtoh(attrp->nxm_uniq_offset));                ssp->nxm_u.nxm_active = htog(uniq | 1);            }            else {                ssp->nxm_u.pth_id = htog(0);                ssp->nxm_u.nxm_active = htog(0);            }        }        //        // copy pointer to shared config area out to user        //        *configptr_ptr = htog(config_addr);        // Register this as a valid address range with the process        base_addr = roundDown(base_addr, VMPageSize);        int size = cur_addr - base_addr;        process->pTable->allocate(base_addr, roundUp(size, VMPageSize));        config.copyOut(tc->getMemPort());        slot_state.copyOut(tc->getMemPort());        rad_state.copyOut(tc->getMemPort());        configptr_ptr.copyOut(tc->getMemPort());        return 0;    }    /// Initialize thread context.    static void    init_thread_context(ThreadContext *tc,                      Tru64::nxm_thread_attr *attrp, uint64_t uniq_val)    {        using namespace TheISA;        tc->clearArchRegs();        tc->setIntReg(TheISA::ArgumentReg[0], gtoh(attrp->registers.a0));        tc->setIntReg(27/*t12*/, gtoh(attrp->registers.pc));        tc->setIntReg(TheISA::StackPointerReg, gtoh(attrp->registers.sp));        tc->setMiscRegNoEffect(AlphaISA::MISCREG_UNIQ, uniq_val);        tc->setPC(gtoh(attrp->registers.pc));        tc->setNextPC(gtoh(attrp->registers.pc) + sizeof(TheISA::MachInst));        tc->activate();    }    /// Create thread.    static SyscallReturn    nxm_thread_createFunc(SyscallDesc *desc, int callnum, LiveProcess *process,                          ThreadContext *tc)    {        using namespace std;        using namespace TheISA;        TypedBufferArg<Tru64::nxm_thread_attr> attrp(tc->getSyscallArg(0));        TypedBufferArg<uint64_t> kidp(tc->getSyscallArg(1));        int thread_index = tc->getSyscallArg(2);        // get attribute args        attrp.copyIn(tc->getMemPort());        if (gtoh(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);        rad_state.copyIn(tc->getMemPort());        uint64_t uniq_val = gtoh(attrp->pthid) - gtoh(rad_state->nxm_uniq_offset);        if (gtoh(attrp->type) == Tru64::NXM_TYPE_MANAGER) {            // DEC pthreads seems to always create one of these (in            // addition to N application threads), but we don't use it,            // so don't bother creating it.            // This is supposed to be a port number.  Make something up.            *kidp = htog(99);            kidp.copyOut(tc->getMemPort());            return 0;        } else if (gtoh(attrp->type) == Tru64::NXM_TYPE_VP) {            // A real "virtual processor" kernel thread.  Need to fork            // this thread on another CPU.            Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[thread_index];            if (gtoh(ssp->nxm_u.nxm_active) != 0)                return (int) Tru64::KERN_NOT_RECEIVER;            ssp->nxm_u.pth_id = attrp->pthid;            ssp->nxm_u.nxm_active = htog(uniq_val | 1);            rad_state.copyOut(tc->getMemPort());            Addr slot_state_addr = 0x12000 + sizeof(Tru64::nxm_config_info);            int slot_state_size =                process->numCpus() * sizeof(Tru64::nxm_slot_state_t);            TypedBufferArg<Tru64::nxm_slot_state_t>                slot_state(slot_state_addr,                           slot_state_size);            slot_state.copyIn(tc->getMemPort());            if (slot_state[thread_index] != Tru64::NXM_SLOT_AVAIL) {                cerr << "nxm_thread_createFunc: requested VP slot "                     << thread_index << " not available!" << endl;                fatal("");            }            // XXX This should have an endian conversion but I think this code            // doesn't work anyway            slot_state[thread_index] = Tru64::NXM_SLOT_BOUND;            slot_state.copyOut(tc->getMemPort());            // Find a free simulator thread context.            for (int i = 0; i < process->numCpus(); ++i) {                ThreadContext *tc = process->threadContexts[i];                if (tc->status() == ThreadContext::Unallocated) {                    // inactive context... grab it                    init_thread_context(tc, attrp, uniq_val);                    // This is supposed to be a port number, but we'll try                    // and get away with just sticking the thread index                    // here.                    *kidp = htog(thread_index);                    kidp.copyOut(tc->getMemPort());                    return 0;                }            }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?