//
// Called to create the network connection.
//
static VMIOS_INTERCEPT_FN(netInit)
{
    object->domain = vmirtGetProcessorDataDomain(processor);

    Uns32 prefixStringAddr;
    Uns32 localNetAddr;

    getArg(processor, object, 0, &object->diagLevel);
    getArg(processor, object, 1, &object->packets);
    getArg(processor, object, 2, &prefixStringAddr);
    getArg(processor, object, 3, &localNetAddr);
    object->pollCount = 0;

    const char *tftp_path = NULL;
    if(prefixStringAddr) {
         tftp_path = vmirtGetString(object->domain, prefixStringAddr);

         if(DIAG_LOW) {
             vmiMessage("I", PREFIX,
                 "local tftp server is active. Root directory is '%s'",
                 object->tftpPath
             );
         }
    }
    const char *localNet = localNetAddr
        ?  vmirtGetString(object->domain, localNetAddr)
        : "10.0.2.0";


    char vhostname[256];
    vhostname[0] = 0;

    //gethostname(vhostname, sizeof(vhostname));
    const char *bootfile    = NULL;
    const char *vnetmask    = NULL;
    const char *vdhcp_start = NULL;
    const char *vnameserver = NULL;
    const char *vhost       = NULL;
    Bool  restricted        = False;

    object->slirp = net_slirp_init(
        restricted,
        localNet,
        vnetmask,
        vhost,
        vhostname,
        tftp_path,
        bootfile,
        vdhcp_start,
        vnameserver,
        object
    );
    if (!object->slirp) {
        vmiMessage("F", PREFIX, "Unable to start networking");
    }
}
//
//      ESR[EC] = 00001; ESR[W] = isWord; ESR[S] = isWrite; ESR[Rx] = rD
//
static void machineAlignError(vmiProcessorP processor, Uns32 bytes, Uns32 rDidx, Uns32 isWrite) {
    microblazeP microblaze = (microblazeP)processor;

    microblaze->SPR_ESR.reg     = 0x0;
    microblaze->SPR_ESR.bits.EC = UNALIGNED_DATA_ACCESS;
    microblaze->exception = microblaze_E_UNALIGNED_DATA_ACCESS;
    switch (bytes) {
    case 4:
        microblaze->SPR_ESR.bits_ESS_EC_00001.W  = 1;
        break;
    case 2:
    case 1:
        microblaze->SPR_ESR.bits_ESS_EC_00001.W  = 0;
        break;
    default:
        vmiMessage("F", "machineAlignError", "%s bytes=%d",
                (isWrite ? "Write" : "Read"), bytes);
                /* no break */
    }
    microblaze->SPR_ESR.bits_ESS_EC_00001.S  = isWrite;
    microblaze->SPR_ESR.bits_ESS_EC_00001.Rx = rDidx;

    //
    // Call the general Hardware Exception routine
    //
    nonmmuException(microblaze);
}
static VMIOS_INTERCEPT_FN(netPoll)
{
    u_int timeMS;
    getArg(processor, object, 0, &timeMS);

    if(DIAG_HIGH) {
        vmiMessage("I", PREFIX, "netPoll #" FMT_64d " at %d ***********", object->pollCount, timeMS);
    }

    object->pollCount++;

    int nfds = -1;

    Slirp *slirp = object->slirp;

    FD_ZERO(&slirp->rfds);
    FD_ZERO(&slirp->wfds);
    FD_ZERO(&slirp->xfds);

    slirp_select_fill(slirp, &nfds, &slirp->rfds, &slirp->wfds, &slirp->xfds);

    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = 0;

    int r = recSelectSocket(nfds + 1, &slirp->rfds, &slirp->wfds, &slirp->xfds, &tv);
    slirp_select_poll(slirp, &slirp->rfds, &slirp->wfds, &slirp->xfds, timeMS, r >= 0);
}
示例#4
0
//
// __syscall (int number, ...)
//
static VMIOS_INTERCEPT_FN(syscallCB) {

    Uns32 code;

    getArg(processor, object, 0, &code);

    vmiMessage("F", CPU_PREFIX "_UNSUPPORTED", "__syscall with code %d", code);
}
void netRxPacket(void *opaque, const void *buf, Uns32 len)
{
    vmiosObjectP object = opaque;

    if(object->count >= 32) {
        vmiMessage("F", PREFIX, "Too many packets queued in one poll period. Dropped");
        return;
    }
    if(len >= MAX_LENGTH) {
        vmiMessage("E", PREFIX,
            "rxBuffer is too small for packet (needed:%d, space:%d). Dropped",
            len,
            MAX_LENGTH
        );
        return;
    }
    Uns32 packetAddr =object->packets + (sizeof(packet) * object->count);
    vmirtWriteNByteDomain(object->domain, packetAddr,   &len, 4,   NULL, 0);
    vmirtWriteNByteDomain(object->domain, packetAddr+4, buf,  len, NULL, 0);
    object->count++;
}
示例#6
0
//
// Split function result into result (0/-1) and errno (-result)
//
static void setErrnoAndResult(
    vmiProcessorP processor,
    vmiosObjectP  object,
    Int32         result,
    const char   *context
) {
    if(!object->impurePtrDomain) {

        vmiMessage("P", "OR1K_ICF_NEWLIB",
            "Interception of '%s' failed - %s not found "
            "(application does not appear to be compiled with newlib "
            "or has no symbols)",
            context, ERRNO_REF
        );

        vmirtFinish(-1);

    } else if(result<0) {

        memDomainP domain     = object->impurePtrDomain;
        memEndian  endian     = vmirtGetProcessorDataEndian(processor);
        Int32      errnoValue = -result;
        Uns32      impurePtrAddr;

        result = -1;

        // swap errno endianness if required
        if(endian != ENDIAN_NATIVE) {
            errnoValue = swap4(errnoValue);
        }

        // read __impure_ptr value
        vmirtReadNByteDomain(
            domain, object->impurePtrAddr, &impurePtrAddr,
            sizeof(impurePtrAddr), 0, False
        );

        // swap errno address endianness if required
        if(endian != ENDIAN_NATIVE) {
            impurePtrAddr = swap4(impurePtrAddr);
        }

        // write back errno
        vmirtWriteNByteDomain(
            domain, impurePtrAddr+OR1K_ERRNO_OFFSET, &errnoValue,
            sizeof(errnoValue), 0, True
        );
    }

    vmiosRegWrite(processor, object->result, &result);
}
// Constructor
//
static VMIOS_CONSTRUCTOR_FN(constructor)
{
    if(DIAG_LOW)
        vmiMessage("I", PREFIX, "Starting SLIRP");

    // What am I ?
    const char *procType = vmirtProcessorType(processor);
    if (strcmp(procType, "pse") != 0) {
        vmiMessage("F", PREFIX, "Processor must be a PSE");
    }
    memEndian  endian    = vmirtGetProcessorDataEndian(processor);
    if(endian != ENDIAN_NATIVE) {
        vmiMessage("F", PREFIX, "Host processor must have same endianity as a PSE");
    }

    // return register (standard ABI)
    object->result = vmiosGetRegDesc(processor, "eax");

    // stack pointer (standard ABI)
    object->sp = vmiosGetRegDesc(processor, "esp");

    object->count = 0;
}
示例#8
0
//
// Intercept times
//
static VMIOS_INTERCEPT_FN(timesInt) {

    Uns32 bufAddr;
    Int32 result = 0;

    // obtain function arguments
    getArg(processor, object, 0, &bufAddr);

    // ioctl isn't implemented
    vmiMessage("W", "OR1K_UNS_NEWLIB1", "times(0x%x) unsupported\n", bufAddr);

    // write back results
    setErrnoAndResult(processor, object, result, context);
}
static VMIOS_INTERCEPT_FN(netTxPacket)
{
    Uns32 addr, bytes;
    getArg(processor, object, 0, &addr);
    getArg(processor, object, 1, &bytes);

    // copy data from PSE to host memory space.
    Uns8 packet[bytes];
    vmirtReadNByteDomain(object->domain, addr, packet, bytes, NULL, False);

    if(DIAG_HIGH) vmiMessage("I", PREFIX, "netTxPacket bytes:%d", bytes);

    // send to slirp
    slirp_input(object->slirp, packet, bytes);
}
示例#10
0
//
// Read a function argument using the standard ABI
//
static void getArg(
    vmiProcessorP processor,
    vmiosObjectP  object,
    Uns32         index,
    void         *result
) {
    if(index>=REG_ARG_NUM) {
        vmiMessage("P", CPU_PREFIX"_ANS",
            "No more than %u function arguments supported",
            REG_ARG_NUM
        );
        vmirtFinish(-1);
    } else {
        vmiRegInfoCP regCP = getArgCP(processor, object, index);
        vmiosRegRead(processor, regCP, result);
    }
}
示例#11
0
//
// Return the next available file descriptor
//
static Int32 newFileDescriptor(vmiosObjectP object, const char *context) {

    Int32 i;

    // find and return the first unused file descriptor
    for(i=0; i<FILE_DES_NUM; i++) {
        if(object->fileDescriptors[i]==-1) {
            return i;
        }
    }

    vmiMessage("P", "OR1K_TMOF_NEWLIB",
        "Too many open files in %s - semihosting supports up to %u",
        context, FILE_DES_NUM
    );

    return -1;
}
示例#12
0
//
// Intercept ioctl
//
static VMIOS_INTERCEPT_FN(ioctlInt) {

    Int32 d;
    Int32 request;
    Int32 result = 0;

    // obtain function arguments
    getArg(processor, object, 0, &d);
    getArg(processor, object, 1, &request);

    // ioctl isn't implemented
    vmiMessage("W", "OR1K_UNS_NEWLIB2", "ioctl(%d, %d, ...) unsupported\n",
        d, request
    );

    // write back results
    setErrnoAndResult(processor, object, result, context);
}
示例#13
0
//
// Get the Constant pointer for the register
//
static vmiRegInfoCP getArgCP(
    vmiProcessorP processor,
    vmiosObjectP  object,
    Uns32         index
) {
    vmiRegInfoCP regCP = 0;

    if(index>=REG_ARG_NUM) {
        vmiMessage("P", CPU_PREFIX"_ANS",
            "No more than %u function arguments supported",
            REG_ARG_NUM
        );
        vmirtFinish(-1);

    } else {
        regCP = object->args[index];
    }
    return regCP;
}
示例#14
0
//
// Read a function argument using the standard ABI
//
static void getArg(
    vmiProcessorP processor,
    vmiosObjectP  object,
    Uns32         index,
    void         *result
) {
    if(index>=REG_ARG_NUM) {

        vmiMessage("P", "OR1K_ANS_NEWLIB",
            "No more than %u function arguments supported",
            REG_ARG_NUM
        );

        vmirtFinish(-1);

    } else {

        vmiosRegRead(processor, object->args[index], result);
    }
}
示例#15
0
//
// Destructor
//
static VMIOS_DESTRUCTOR_FN(destructor)
{
    if(DIAG_LOW)
        vmiMessage("I" ,PREFIX, "Shutting down SLIRP");
}
示例#16
0
static void redirPort(Slirp *slirp, const char *p, const char *procName)
{
    do {
        Bool udp = False;
        char buf[256], *r;
        struct in_addr host_addr;
        struct in_addr guest_addr;
        int host_port, guest_port;

        memset(&host_addr, 0, sizeof(host_addr));
        host_addr.s_addr = INADDR_ANY;

        if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
            redirStringError("expected tcp: or udp:");

        if (!strcmp(buf, "tcp")) {
            udp = 0;
        } else if (!strcmp(buf, "udp")) {
            udp = 1;
        } else {
            vmiMessage("F", PREFIX,  "expected tcp: or udp:");
        }

        if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
            redirStringError("expected host port number");

        host_port = strtol(buf, &r, 0);
        if (r == buf)
            redirStringError("expected host port number");

        if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
            redirStringError("expected guest ip address");

        if (buf[0] == '\0') {
            strcpy(buf, "10.0.2.15");
        } else {
            if (!inet_aton(buf, &guest_addr))
                redirStringError("expected guest ip address");
        }
        guest_port = strtol(p, &r, 0);
        if (r == p)
            redirStringError("expected guest port number");

        Uns32 actualHostPort = 0;

        int res = slirp_add_hostfwd(
            slirp,
            udp,
            host_addr,
            host_port,
            guest_addr,
            guest_port,
            &actualHostPort
        );

        if (res >= 0) {
            vmiMessage("I", PREFIX,
                "%s Listening on host %s port:%d. Redirecting to guest port:%d",
                procName,
                udp ? "udp" : "tcp",
                // host_port,
                actualHostPort,
                guest_port
            );
        } else {
            vmiMessage("W", PREFIX,  "Failed to set up redirection on port %d", guest_port);
        }
        p = r;
        if(*p != ',')
            break;
        p++;
    } while (1);
}
示例#17
0
static void redirStringError(const char *what)
{
    vmiMessage("F", PREFIX,  "Error parsing redirection : %s", what);
}
//
// Decoder function for a given address
//
void microblazeDecode(
    microblazeP microblaze,
    microblazeAddr thisPC,
    microblazeInstructionInfoP info
) {
    //
    // Initialize the 32 bit decoder table
    //
    static vmidDecodeTableP decodeTable32;
    if(!decodeTable32) {
        decodeTable32 = microblazeCreateDecodeTable32();
    }

    vmiProcessorP processor = (vmiProcessorP)microblaze;

    //
    // Initialize the following info fields before lookup
    //
    info->type = MICROBLAZE_IT_INSTR32;
    info->thisPC = thisPC;
    info->arch = microblaze->configInfo.arch;

    Uns64 instruction = 0;
    info->instrsize = 0;
    //
    // Attempt to match a 32 bit instruction
    //
    if (info->type == MICROBLAZE_IT_INSTR32) {
        Uns64 instr4 = vmicxtFetch4Byte(processor, thisPC);
        info->type = MICROBLAZE_IT_LAST;
        info->type = vmidDecode(decodeTable32, instr4);
        info->nextPC = info->thisPC + 4;
        instruction = instr4;
        info->instrsize = 4;
        info->instruction = instr4;
    }

    //
    // Fatal if there was a match failure
    //
    if (info->type == MICROBLAZE_IT_LAST && MICROBLAZE_DISASSEMBLE(microblaze)) {
        vmiMessage("F", "DECODE_FAIL", "Address=0x" FMT_640Nx " Instruction = 0x" FMT_640Nx, (Uns64)thisPC, instruction);
    }

    microblazeGenInstructionInfo(info, instruction);

    //
    // If this is a decode of an IMM instruction, we decode the next instruction
    //
    if (info->type == MICROBLAZE_IT_IMM_TYPEI1) {
        Uns64 instr4 = vmicxtFetch4Byte(processor, info->nextPC);
        info->type = MICROBLAZE_IT_LAST;
        info->type = vmidDecode(decodeTable32, instr4);
        info->thisPC = info->nextPC;
        info->nextPC = info->thisPC + 4;
        instruction = instr4;
        info->instrsize = 8;
        info->instruction = instr4;

        //
        // Fatal if there was a match failure
        //
        if (info->type == MICROBLAZE_IT_LAST && MICROBLAZE_DISASSEMBLE(microblaze)) {
            vmiMessage("F", "DECODE_FAIL", "Address=0x" FMT_640Nx " Instruction = 0x" FMT_640Nx, (Uns64)info->nextPC, instruction);
        }

        //
        // get the fields for the TYPEB instruction
        //
        microblazeGenInstructionInfo(info, instruction);
    } else {
        // Indicate that the simmhi is unset
        info->simmhi = 0x0000ffff;
    }
}