Example #1
0
uint64_t sys_getmainvars(HTIFState * htifstate, uint64_t pbuf, uint64_t limit) {
    #ifdef DEBUG_FRONTEND_RISCV
    fprintf(stderr, "%s\n", htifstate->kernel_cmdline);
    #endif

    void * base = htifstate->main_mem_ram_ptr + (uintptr_t)pbuf;

    // assume args are bbl + some kernel for now
    // later, do the right thing
    const char * arg0 = "bbl";
    const char * arg1 = htifstate->kernel_cmdline;

    #define WORDS_LEN 5
    #define START_ARGS (WORDS_LEN*8)
    uint64_t words[WORDS_LEN] = {2, START_ARGS+pbuf, START_ARGS+pbuf+4, 0, 0};
    int i;
    for (i = 0; i < WORDS_LEN; i++) {
        stq_p((void*)(base+i*8), words[i]);
    }
    for (i = 0; i < 4; i++) {
        stb_p((void*)(base + START_ARGS + i), arg0[i]);
    }
    for (i = 0; i < strlen(arg1)+1; i++) {
        stb_p((void*)(base + START_ARGS+4 + i), arg1[i]);
    }
    // currently no support for > 2 args
    return 0;
}
Example #2
0
void glue(address_space_stb, SUFFIX)(ARG1_DECL,
    hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
{
    uint8_t *ptr;
    MemoryRegion *mr;
    hwaddr l = 1;
    hwaddr addr1;
    MemTxResult r;
    bool release_lock = false;

    RCU_READ_LOCK();
    mr = TRANSLATE(addr, &addr1, &l, true);
    if (!IS_DIRECT(mr, true)) {
        release_lock |= prepare_mmio_access(mr);
        r = memory_region_dispatch_write(mr, addr1, val, 1, attrs);
    } else {
        /* RAM case */
        ptr = MAP_RAM(mr, addr1);
        stb_p(ptr, val);
        INVALIDATE(mr, addr1, 1);
        r = MEMTX_OK;
    }
    if (result) {
        *result = r;
    }
    if (release_lock) {
        qemu_mutex_unlock_iothread();
    }
    RCU_READ_UNLOCK();
}
Example #3
0
static void virtio_blk_req_complete(VirtIOBlockReq *req, int status)
{
    VirtIOBlock *s = req->dev;

    trace_virtio_blk_req_complete(req, status);

    stb_p(&req->in->status, status);
    virtqueue_push(s->vq, &req->elem, req->qiov.size + sizeof(*req->in));
    virtio_notify(&s->vdev, s->vq);
}
Example #4
0
static void virtio_blk_complete_request(VirtIOBlockReq *req,
                                        unsigned char status)
{
    VirtIOBlock *s = req->dev;
    VirtIODevice *vdev = VIRTIO_DEVICE(s);

    trace_virtio_blk_req_complete(req, status);

    stb_p(&req->in->status, status);
    virtqueue_push(s->vq, &req->elem, req->in_len);
    virtio_notify(vdev, s->vq);
}
Example #5
0
static void virtio_crypto_req_complete(VirtIOCryptoReq *req, uint8_t status)
{
    VirtIOCrypto *vcrypto = req->vcrypto;
    VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto);

    if (req->flags == CRYPTODEV_BACKEND_ALG_SYM) {
        virtio_crypto_sym_input_data_helper(vdev, req, status,
                                            req->u.sym_op_info);
    }
    stb_p(&req->in->status, status);
    virtqueue_push(req->vq, &req->elem, req->in_len);
    virtio_notify(vdev, req->vq);
}
Example #6
0
static void complete_request_vring(VirtIOBlockReq *req, unsigned char status)
{
    VirtIOBlockDataPlane *s = req->dev->dataplane;
    stb_p(&req->in->status, status);

    vring_push(s->vdev, &req->dev->dataplane->vring, &req->elem, req->in_len);

    /* Suppress notification to guest by BH and its scheduled
     * flag because requests are completed as a batch after io
     * plug & unplug is introduced, and the BH can still be
     * executed in dataplane aio context even after it is
     * stopped, so needn't worry about notification loss with BH.
     */
    qemu_bh_schedule(s->bh);
}
Example #7
0
static void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status)
{
    VirtIOBlock *s = req->dev;
    VirtIODevice *vdev = VIRTIO_DEVICE(s);

    trace_virtio_blk_req_complete(vdev, req, status);

    stb_p(&req->in->status, status);
    virtqueue_push(req->vq, &req->elem, req->in_len);
    if (s->dataplane_started && !s->dataplane_disabled) {
        virtio_blk_data_plane_notify(s->dataplane, req->vq);
    } else {
        virtio_notify(vdev, req->vq);
    }
}
Example #8
0
static void spin_write(void *opaque, hwaddr addr, uint64_t value,
                       unsigned len)
{
    SpinState *s = opaque;
    int env_idx = addr / sizeof(SpinInfo);
    CPUPPCState *env;
    SpinInfo *curspin = &s->spin[env_idx];
    uint8_t *curspin_p = (uint8_t*)curspin;

    for (env = first_cpu; env != NULL; env = env->next_cpu) {
        if (env->cpu_index == env_idx) {
            break;
        }
    }

    if (!env) {
        /* Unknown CPU */
        return;
    }

    if (!env->cpu_index) {
        /* primary CPU doesn't spin */
        return;
    }

    curspin_p = &curspin_p[addr % sizeof(SpinInfo)];
    switch (len) {
    case 1:
        stb_p(curspin_p, value);
        break;
    case 2:
        stw_p(curspin_p, value);
        break;
    case 4:
        stl_p(curspin_p, value);
        break;
    }

    if (!(ldq_p(&curspin->addr) & 1)) {
        /* run CPU */
        SpinKick kick = {
            .cpu = ppc_env_get_cpu(env),
            .spin = curspin,
        };

        run_on_cpu(CPU(kick.cpu), spin_kick, &kick);
    }
Example #9
0
static void spin_write(void *opaque, hwaddr addr, uint64_t value,
                       unsigned len)
{
    SpinState *s = opaque;
    int env_idx = addr / sizeof(SpinInfo);
    CPUState *cpu;
    SpinInfo *curspin = &s->spin[env_idx];
    uint8_t *curspin_p = (uint8_t*)curspin;

    cpu = qemu_get_cpu(env_idx);
    if (cpu == NULL) {
        /* Unknown CPU */
        return;
    }

    if (cpu->cpu_index == 0) {
        /* primary CPU doesn't spin */
        return;
    }

    curspin_p = &curspin_p[addr % sizeof(SpinInfo)];
    switch (len) {
    case 1:
        stb_p(curspin_p, value);
        break;
    case 2:
        stw_p(curspin_p, value);
        break;
    case 4:
        stl_p(curspin_p, value);
        break;
    }

    if (!(ldq_p(&curspin->addr) & 1)) {
        /* run CPU */
        SpinKick kick = {
            .cpu = POWERPC_CPU(cpu),
            .spin = curspin,
        };

        run_on_cpu(cpu, spin_kick, &kick);
    }
Example #10
0
uint64_t sys_pread(HTIFState *htifstate, uint64_t fd, uint64_t pbuf, uint64_t len, uint64_t off) {
    #ifdef DEBUG_FRONTEND_RISCV
    fprintf(stderr, "read fd: %ld, len: %ld, off: %ld\n", fd, len, off);
    #endif
    if (fd != 3) {
        fprintf(stderr, "INVALID pread fd: %ld. only 3 allowed\n", fd);
        exit(1);
    }

    char * buf = malloc(sizeof(char)*len);
    size_t bytes_read = pread(real_kernelfd, buf, len, off);

    void * base = htifstate->main_mem_ram_ptr + (uintptr_t)pbuf;
    int i;
    for (i = 0; i < bytes_read; i++) {
      stb_p((void*)(base + i), buf[i]);
    }
    free(buf);
    return bytes_read;
}
Example #11
0
static void riscv_sifive_board_init(MachineState *args)
{
    ram_addr_t ram_size = args->ram_size;
    const char *cpu_model = args->cpu_model;
    const char *kernel_filename = args->kernel_filename;
    const char *kernel_cmdline = args->kernel_cmdline;
    const char *initrd_filename = args->initrd_filename;
    MemoryRegion *system_memory = get_system_memory();
    MemoryRegion *main_mem = g_new(MemoryRegion, 1);
    RISCVCPU *cpu;
    CPURISCVState *env;
    int i;
    DeviceState *dev = qdev_create(NULL, TYPE_RISCV_SIFIVE_BOARD);
    object_property_set_bool(OBJECT(dev), true, "realized", NULL);

    /* Make sure the first 3 serial ports are associated with a device. */
    for (i = 0; i < 3; i++) {
        if (!serial_hds[i]) {
            char label[32];
            snprintf(label, sizeof(label), "serial%d", i);
            serial_hds[i] = qemu_chr_new(label, "null", NULL);
        }
    }

    /* init CPUs */
    if (cpu_model == NULL) {
        cpu_model = "any";
    }

    for (i = 0; i < smp_cpus; i++) {
        cpu = cpu_riscv_init(cpu_model);
        if (cpu == NULL) {
            fprintf(stderr, "Unable to find CPU definition\n");
            exit(1);
        }
        env = &cpu->env;

        /* Init internal devices */
        cpu_riscv_irq_init_cpu(env);
        cpu_riscv_clock_init(env);
        qemu_register_reset(main_cpu_reset, cpu);
    }
    cpu = RISCV_CPU(first_cpu);
    env = &cpu->env;

    /* register system main memory (actual RAM) */
    memory_region_init_ram(main_mem, NULL, "riscv_sifive_board.ram", 2147483648ll +
                           ram_size, &error_fatal);
    /* for phys mem size check in page table walk */
    env->memsize = ram_size;
    vmstate_register_ram_global(main_mem);
    memory_region_add_subregion(system_memory, 0x0, main_mem);

    if (kernel_filename) {
        loaderparams.ram_size = ram_size;
        loaderparams.kernel_filename = kernel_filename;
        loaderparams.kernel_cmdline = kernel_cmdline;
        loaderparams.initrd_filename = initrd_filename;
        load_kernel();
    }

    uint32_t reset_vec[8] = {
        0x297 + 0x80000000 - 0x1000, /* reset vector */
        0x00028067,                  /* jump to DRAM_BASE */
        0x00000000,                  /* reserved */
        0x0,                         /* config string pointer */
        0, 0, 0, 0                   /* trap vector */
    };
    reset_vec[3] = 0x1000 + sizeof(reset_vec); /* config string pointer */

    /* part one of config string - before memory size specified */
    const char *config_string1 = "platform {\n"
                                 "  vendor ucb;\n"
                                 "  arch spike;\n"
                                 "};\n"
                                 "plic { \n"
                                 "  interface \"plic\"; \n"
                                 "  ndevs 2; \n"
                                 "  priority { mem { 0x60000000 0x60000fff; }; }; \n"
                                 "  pending  { mem { 0x60001000 0x6000107f; }; }; \n"
                                 "  0 { \n"
                                 "    0 { \n"
                                 "      m { \n"
                                 "        ie  { mem { 0x60002000 0x6000207f; }; }; \n"
                                 "        ctl { mem { 0x60200000 0x60200007; }; }; \n"
                                 "      }; \n"
                                 "      s { \n"
                                 "        ie  { mem { 0x60002080 0x600020ff; }; }; \n"
                                 "        ctl { mem { 0x60201000 0x60201007; }; }; \n"
                                 "      }; \n"
                                 "    }; \n"
                                 "  }; \n"
                                 "}; \n"
                                 "rtc {\n"
                                 "  addr 0x" "40000000" ";\n"
                                 "};\n"
                                 "uart {\n"
                                 "  addr 0x40002000;\n"
                                 "};\n"
                                 "ram {\n"
                                 "  0 {\n"
                                 "    addr 0x" "80000000" ";\n"
                                 "    size 0x";


    /* part two of config string - after memory size specified */
    const char *config_string2 =  ";\n"
                                  "  };\n"
                                  "};\n"
                                  "core {\n"
                                  "  0" " {\n"
                                  "    " "0 {\n"
                                  "      isa " "rv64imafd" ";\n"
                                  "      timecmp 0x" "40000008" ";\n"
                                  "      ipi 0x" "40001000" ";\n"
                                  "    };\n"
                                  "  };\n"
                                  "};\n";

    /* build config string with supplied memory size */
    uint64_t rsz = ram_size;
    char *ramsize_as_hex_str = malloc(17);
    sprintf(ramsize_as_hex_str, "%016" PRIx64, rsz);
    char *config_string = malloc(strlen(config_string1) +
                                 strlen(ramsize_as_hex_str) +
                                 strlen(config_string2) + 1);
    config_string[0] = 0;
    strcat(config_string, config_string1);
    strcat(config_string, ramsize_as_hex_str);
    strcat(config_string, config_string2);

    /* copy in the reset vec and configstring */
    int q;
    for (q = 0; q < sizeof(reset_vec) / sizeof(reset_vec[0]); q++) {
        stl_p(memory_region_get_ram_ptr(main_mem) + 0x1000 + q * 4,
              reset_vec[q]);
    }

    int confstrlen = strlen(config_string);
    for (q = 0; q < confstrlen; q++) {
        stb_p(memory_region_get_ram_ptr(main_mem) + reset_vec[3] + q,
              config_string[q]);
    }

    sifive_uart_create(0x40002000, serial_hds[0]);

    /* timer device at 0x40000000, as specified in the config string above */
    timer_mm_init(system_memory, 0x40000000, env);

    /* TODO: VIRTIO */
}