Beispiel #1
0
Datei: r2d.c Projekt: agocke/qemu
static void r2d_init(ram_addr_t ram_size, int vga_ram_size,
              const char *boot_device,
	      const char *kernel_filename, const char *kernel_cmdline,
	      const char *initrd_filename, const char *cpu_model)
{
    CPUState *env;
    struct SH7750State *s;
    ram_addr_t sdram_addr, sm501_vga_ram_addr;
    qemu_irq *irq;
    PCIBus *pci;
    int i;

    if (!cpu_model)
        cpu_model = "SH7751R";

    env = cpu_init(cpu_model);
    if (!env) {
        fprintf(stderr, "Unable to find CPU definition\n");
        exit(1);
    }

    /* Allocate memory space */
    sdram_addr = qemu_ram_alloc(SDRAM_SIZE);
    cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr);
    /* Register peripherals */
    s = sh7750_init(env);
    irq = r2d_fpga_init(0x04000000, sh7750_irl(s));
    pci = sh_pci_register_bus(r2d_pci_set_irq, r2d_pci_map_irq, irq, 0, 4);

    sm501_vga_ram_addr = qemu_ram_alloc(SM501_VRAM_SIZE);
    sm501_init(0x10000000, sm501_vga_ram_addr, SM501_VRAM_SIZE,
	       serial_hds[2]);

    /* onboard CF (True IDE mode, Master only). */
    mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1,
        drives_table[drive_get_index(IF_IDE, 0, 0)].bdrv, NULL);

    /* NIC: rtl8139 on-board, and 2 slots. */
    pci_nic_init(pci, &nd_table[0], 2 << 3, "rtl8139");
    for (i = 1; i < nb_nics; i++)
        pci_nic_init(pci, &nd_table[i], -1, "ne2k_pci");

    /* Todo: register on board registers */
    {
      int kernel_size;
      /* initialization which should be done by firmware */
      stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */
      stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */

      kernel_size = load_image(kernel_filename, phys_ram_base);

      if (kernel_size < 0) {
        fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
        exit(1);
      }

      env->pc = SDRAM_BASE | 0xa0000000; /* Start from P2 area */
    }
}
Beispiel #2
0
static inline void vring_avail_event(VirtQueue *vq, uint16_t val)
{
    hwaddr pa;
    if (!vq->notification) {
        return;
    }
    pa = vq->vring.used + offsetof(VRingUsed, ring[vq->vring.num]);
    stw_phys(pa, val);
}
Beispiel #3
0
static inline void vring_used_flags_unset_bit(VirtQueue *vq, int mask)
{
    hwaddr pa;
    pa = vq->vring.used + offsetof(VRingUsed, flags);
    stw_phys(pa, lduw_phys(pa) & ~mask);
}
Beispiel #4
0
static inline void vring_used_idx_set(VirtQueue *vq, uint16_t val)
{
    hwaddr pa;
    pa = vq->vring.used + offsetof(VRingUsed, idx);
    stw_phys(pa, val);
}
Beispiel #5
0
static inline void vring_used_flags_set_bit(VirtQueue *vq, int mask)
{
    target_phys_addr_t pa;
    pa = vq->vring.used + offsetof(VRingUsed, flags);
    stw_phys(pa, lduw_phys(pa) | mask);
}
Beispiel #6
0
/*
 * Handle writes to CSRs and any resulting special behavior
 *
 * Note: mtohost and mfromhost are not handled here
 */
inline void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
        target_ulong csrno)
{
    #ifdef RISCV_DEBUG_PRINT
    fprintf(stderr, "Write CSR reg: 0x" TARGET_FMT_lx "\n", csrno);
    fprintf(stderr, "Write CSR val: 0x" TARGET_FMT_lx "\n", val_to_write);
    #endif

    switch (csrno)
    {
    case NEW_CSR_FFLAGS:
        env->csr[NEW_CSR_MSTATUS] |= MSTATUS_FS | MSTATUS64_SD;
        env->csr[NEW_CSR_FFLAGS] = val_to_write & (FSR_AEXC >> FSR_AEXC_SHIFT);
        break;
    case NEW_CSR_FRM:
        env->csr[NEW_CSR_MSTATUS] |= MSTATUS_FS | MSTATUS64_SD;
        env->csr[NEW_CSR_FRM] = val_to_write & (FSR_RD >> FSR_RD_SHIFT);
        break;
    case NEW_CSR_FCSR:
        env->csr[NEW_CSR_MSTATUS] |= MSTATUS_FS | MSTATUS64_SD;
        env->csr[NEW_CSR_FFLAGS] = (val_to_write & FSR_AEXC) >> FSR_AEXC_SHIFT;
        env->csr[NEW_CSR_FRM] = (val_to_write & FSR_RD) >> FSR_RD_SHIFT;
        break;
    case NEW_CSR_MTIME:
    case NEW_CSR_STIMEW:
        // this implementation ignores writes to MTIME
        break;
    case NEW_CSR_MTIMEH:
    case NEW_CSR_STIMEHW:
        // this implementation ignores writes to MTIME
        break;
    case NEW_CSR_TIMEW:
        cpu_riscv_store_timew(env, val_to_write);
        break;
    case NEW_CSR_TIMEHW:
        fprintf(stderr, "CSR_TIMEHW unsupported on RV64I\n");
        exit(1);
        break;
    case NEW_CSR_CYCLEW:
    case NEW_CSR_INSTRETW:
        cpu_riscv_store_instretw(env, val_to_write);
        break;
    case NEW_CSR_CYCLEHW:
    case NEW_CSR_INSTRETHW:
        fprintf(stderr, "CSR_CYCLEHW/INSTRETHW unsupported on RV64I\n");
        exit(1);
        break;
    case NEW_CSR_MSTATUS: {
        target_ulong mstatus = env->csr[NEW_CSR_MSTATUS];
        #ifdef RISCV_DEBUG_PRINT
        target_ulong debug_mstatus = mstatus;
        #endif
        if ((val_to_write ^ mstatus) &
                (MSTATUS_VM | MSTATUS_PRV | MSTATUS_PRV1 | MSTATUS_MPRV)) {
            #ifdef RISCV_DEBUG_PRINT
            fprintf(stderr, "flushing TLB\n");
            #endif
            helper_tlb_flush(env);
        }

        // no extension support
        target_ulong mask = MSTATUS_IE | MSTATUS_IE1 | MSTATUS_IE2
            | MSTATUS_MPRV | MSTATUS_FS;

        if (validate_vm(get_field(val_to_write, MSTATUS_VM))) {
            mask |= MSTATUS_VM;
        }
        if (validate_priv(get_field(val_to_write, MSTATUS_PRV))) {
            mask |= MSTATUS_PRV;
        }
        if (validate_priv(get_field(val_to_write, MSTATUS_PRV1))) {
            mask |= MSTATUS_PRV1;
        }
        if (validate_priv(get_field(val_to_write, MSTATUS_PRV2))) {
            mask |= MSTATUS_PRV2;
        }

        mstatus = (mstatus & ~mask) | (val_to_write & mask);

        int dirty = (mstatus & MSTATUS_FS) == MSTATUS_FS;
        dirty |= (mstatus & MSTATUS_XS) == MSTATUS_XS;
        mstatus = set_field(mstatus, MSTATUS64_SD, dirty);
        env->csr[NEW_CSR_MSTATUS] = mstatus;
        break;
    }
    case NEW_CSR_MIP: {
        target_ulong mask = MIP_SSIP | MIP_MSIP | MIP_STIP;
        env->csr[NEW_CSR_MIP] = (env->csr[NEW_CSR_MIP] & ~mask) |
            (val_to_write & mask);
        CPUState *cs = CPU(riscv_env_get_cpu(env));
        if (env->csr[NEW_CSR_MIP] & MIP_SSIP) {
            stw_phys(cs->as, 0xFFFFFFFFF0000020, 0x1);
        } else {
            stw_phys(cs->as, 0xFFFFFFFFF0000020, 0x0);
        }
        if (env->csr[NEW_CSR_MIP] & MIP_STIP) {
            stw_phys(cs->as, 0xFFFFFFFFF0000040, 0x1);
        } else {
            stw_phys(cs->as, 0xFFFFFFFFF0000040, 0x0);
        }
        if (env->csr[NEW_CSR_MIP] & MIP_MSIP) {
            stw_phys(cs->as, 0xFFFFFFFFF0000060, 0x1);
        } else {
            stw_phys(cs->as, 0xFFFFFFFFF0000060, 0x0);
        }
        break;
    }
    case NEW_CSR_MIPI: {
        CPUState *cs = CPU(riscv_env_get_cpu(env));
        env->csr[NEW_CSR_MIP] = set_field(env->csr[NEW_CSR_MIP], MIP_MSIP, val_to_write & 1);
        if (env->csr[NEW_CSR_MIP] & MIP_MSIP) {
            stw_phys(cs->as, 0xFFFFFFFFF0000060, 0x1);
        } else {
            stw_phys(cs->as, 0xFFFFFFFFF0000060, 0x0);
        }
        break;
    }
    case NEW_CSR_MIE: {
        target_ulong mask = MIP_SSIP | MIP_MSIP | MIP_STIP | MIP_MTIP;
        env->csr[NEW_CSR_MIE] = (env->csr[NEW_CSR_MIE] & ~mask) |
            (val_to_write & mask);
        break;
    }
    case NEW_CSR_SSTATUS: {
        target_ulong ms = env->csr[NEW_CSR_MSTATUS];
        ms = set_field(ms, MSTATUS_IE, get_field(val_to_write, SSTATUS_IE));
        ms = set_field(ms, MSTATUS_IE1, get_field(val_to_write, SSTATUS_PIE));
        ms = set_field(ms, MSTATUS_PRV1, get_field(val_to_write, SSTATUS_PS));
        ms = set_field(ms, MSTATUS_FS, get_field(val_to_write, SSTATUS_FS));
        ms = set_field(ms, MSTATUS_XS, get_field(val_to_write, SSTATUS_XS));
        ms = set_field(ms, MSTATUS_MPRV, get_field(val_to_write, SSTATUS_MPRV));
        csr_write_helper(env, ms, NEW_CSR_MSTATUS);
        break;
    }
    case NEW_CSR_SIP: {
        target_ulong mask = MIP_SSIP;
        env->csr[NEW_CSR_MIP] = (env->csr[NEW_CSR_MIP] & ~mask) |
            (val_to_write & mask);
        CPUState *cs = CPU(riscv_env_get_cpu(env));
        if (env->csr[NEW_CSR_MIP] & MIP_SSIP) {
            stw_phys(cs->as, 0xFFFFFFFFF0000020, 0x1);
        } else {
            stw_phys(cs->as, 0xFFFFFFFFF0000020, 0x0);
        }
        break;
    }
    case NEW_CSR_SIE: {
        target_ulong mask = MIP_SSIP | MIP_STIP | MIP_SXIP;
        env->csr[NEW_CSR_MIE] = (env->csr[NEW_CSR_MIE] & ~mask) |
            (val_to_write & mask);
        break;
    }
    case NEW_CSR_SEPC:
        env->csr[NEW_CSR_SEPC] = val_to_write;
        break;
    case NEW_CSR_STVEC:
        env->csr[NEW_CSR_STVEC] = val_to_write >> 2 << 2;
        break;
    case NEW_CSR_SPTBR:
        env->csr[NEW_CSR_SPTBR] = val_to_write & -(1L << PGSHIFT);
        break;
    case NEW_CSR_SSCRATCH:
        env->csr[NEW_CSR_SSCRATCH] = val_to_write;
        break;
    case NEW_CSR_MEPC:
        env->csr[NEW_CSR_MEPC] = val_to_write;
        break;
    case NEW_CSR_MSCRATCH:
        env->csr[NEW_CSR_MSCRATCH] = val_to_write;
        break;
    case NEW_CSR_MCAUSE:
        env->csr[NEW_CSR_MCAUSE] = val_to_write;
        break;
    case NEW_CSR_MBADADDR:
        env->csr[NEW_CSR_MBADADDR] = val_to_write;
        break;
    case NEW_CSR_MTIMECMP:
        // NOTE: clearing bit in MIP handled in cpu_riscv_store_compare
        cpu_riscv_store_compare(env, val_to_write);
        break;
    case NEW_CSR_MTOHOST:
        fprintf(stderr, "Write to mtohost should not be handled here\n");
        exit(1);
        break;
    case NEW_CSR_MFROMHOST:
        fprintf(stderr, "Write to mfromhost should not be handled here\n");
        exit(1);
        break;
    }
}
Beispiel #7
0
void do_smm_enter(X86CPU *cpu)
{
    CPUX86State *env = &cpu->env;
    CPUState *cs = CPU(cpu);
    target_ulong sm_state;
    SegmentCache *dt;
    int i, offset;

    qemu_log_mask(CPU_LOG_INT, "SMM: enter\n");
    log_cpu_state_mask(CPU_LOG_INT, CPU(cpu), CPU_DUMP_CCOP);

    env->hflags |= HF_SMM_MASK;
    cpu_smm_update(env);

    sm_state = env->smbase + 0x8000;

#ifdef TARGET_X86_64
    for (i = 0; i < 6; i++) {
        dt = &env->segs[i];
        offset = 0x7e00 + i * 16;
        stw_phys(cs->as, sm_state + offset, dt->selector);
        stw_phys(cs->as, sm_state + offset + 2, (dt->flags >> 8) & 0xf0ff);
        stl_phys(cs->as, sm_state + offset + 4, dt->limit);
        stq_phys(cs->as, sm_state + offset + 8, dt->base);
    }

    stq_phys(cs->as, sm_state + 0x7e68, env->gdt.base);
    stl_phys(cs->as, sm_state + 0x7e64, env->gdt.limit);

    stw_phys(cs->as, sm_state + 0x7e70, env->ldt.selector);
    stq_phys(cs->as, sm_state + 0x7e78, env->ldt.base);
    stl_phys(cs->as, sm_state + 0x7e74, env->ldt.limit);
    stw_phys(cs->as, sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);

    stq_phys(cs->as, sm_state + 0x7e88, env->idt.base);
    stl_phys(cs->as, sm_state + 0x7e84, env->idt.limit);

    stw_phys(cs->as, sm_state + 0x7e90, env->tr.selector);
    stq_phys(cs->as, sm_state + 0x7e98, env->tr.base);
    stl_phys(cs->as, sm_state + 0x7e94, env->tr.limit);
    stw_phys(cs->as, sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);

    stq_phys(cs->as, sm_state + 0x7ed0, env->efer);

    stq_phys(cs->as, sm_state + 0x7ff8, env->regs[R_EAX]);
    stq_phys(cs->as, sm_state + 0x7ff0, env->regs[R_ECX]);
    stq_phys(cs->as, sm_state + 0x7fe8, env->regs[R_EDX]);
    stq_phys(cs->as, sm_state + 0x7fe0, env->regs[R_EBX]);
    stq_phys(cs->as, sm_state + 0x7fd8, env->regs[R_ESP]);
    stq_phys(cs->as, sm_state + 0x7fd0, env->regs[R_EBP]);
    stq_phys(cs->as, sm_state + 0x7fc8, env->regs[R_ESI]);
    stq_phys(cs->as, sm_state + 0x7fc0, env->regs[R_EDI]);
    for (i = 8; i < 16; i++) {
        stq_phys(cs->as, sm_state + 0x7ff8 - i * 8, env->regs[i]);
    }
    stq_phys(cs->as, sm_state + 0x7f78, env->eip);
    stl_phys(cs->as, sm_state + 0x7f70, cpu_compute_eflags(env));
    stl_phys(cs->as, sm_state + 0x7f68, env->dr[6]);
    stl_phys(cs->as, sm_state + 0x7f60, env->dr[7]);

    stl_phys(cs->as, sm_state + 0x7f48, env->cr[4]);
    stl_phys(cs->as, sm_state + 0x7f50, env->cr[3]);
    stl_phys(cs->as, sm_state + 0x7f58, env->cr[0]);

    stl_phys(cs->as, sm_state + 0x7efc, SMM_REVISION_ID);
    stl_phys(cs->as, sm_state + 0x7f00, env->smbase);
#else
    stl_phys(cs->as, sm_state + 0x7ffc, env->cr[0]);
    stl_phys(cs->as, sm_state + 0x7ff8, env->cr[3]);
    stl_phys(cs->as, sm_state + 0x7ff4, cpu_compute_eflags(env));
    stl_phys(cs->as, sm_state + 0x7ff0, env->eip);
    stl_phys(cs->as, sm_state + 0x7fec, env->regs[R_EDI]);
    stl_phys(cs->as, sm_state + 0x7fe8, env->regs[R_ESI]);
    stl_phys(cs->as, sm_state + 0x7fe4, env->regs[R_EBP]);
    stl_phys(cs->as, sm_state + 0x7fe0, env->regs[R_ESP]);
    stl_phys(cs->as, sm_state + 0x7fdc, env->regs[R_EBX]);
    stl_phys(cs->as, sm_state + 0x7fd8, env->regs[R_EDX]);
    stl_phys(cs->as, sm_state + 0x7fd4, env->regs[R_ECX]);
    stl_phys(cs->as, sm_state + 0x7fd0, env->regs[R_EAX]);
    stl_phys(cs->as, sm_state + 0x7fcc, env->dr[6]);
    stl_phys(cs->as, sm_state + 0x7fc8, env->dr[7]);

    stl_phys(cs->as, sm_state + 0x7fc4, env->tr.selector);
    stl_phys(cs->as, sm_state + 0x7f64, env->tr.base);
    stl_phys(cs->as, sm_state + 0x7f60, env->tr.limit);
    stl_phys(cs->as, sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);

    stl_phys(cs->as, sm_state + 0x7fc0, env->ldt.selector);
    stl_phys(cs->as, sm_state + 0x7f80, env->ldt.base);
    stl_phys(cs->as, sm_state + 0x7f7c, env->ldt.limit);
    stl_phys(cs->as, sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);

    stl_phys(cs->as, sm_state + 0x7f74, env->gdt.base);
    stl_phys(cs->as, sm_state + 0x7f70, env->gdt.limit);

    stl_phys(cs->as, sm_state + 0x7f58, env->idt.base);
    stl_phys(cs->as, sm_state + 0x7f54, env->idt.limit);

    for (i = 0; i < 6; i++) {
        dt = &env->segs[i];
        if (i < 3) {
            offset = 0x7f84 + i * 12;
        } else {
            offset = 0x7f2c + (i - 3) * 12;
        }
        stl_phys(cs->as, sm_state + 0x7fa8 + i * 4, dt->selector);
        stl_phys(cs->as, sm_state + offset + 8, dt->base);
        stl_phys(cs->as, sm_state + offset + 4, dt->limit);
        stl_phys(cs->as, sm_state + offset, (dt->flags >> 8) & 0xf0ff);
    }
    stl_phys(cs->as, sm_state + 0x7f14, env->cr[4]);

    stl_phys(cs->as, sm_state + 0x7efc, SMM_REVISION_ID);
    stl_phys(cs->as, sm_state + 0x7ef8, env->smbase);
#endif
    /* init SMM cpu state */

#ifdef TARGET_X86_64
    cpu_load_efer(env, 0);
#endif
    cpu_load_eflags(env, 0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C |
                              DF_MASK));
    env->eip = 0x00008000;
    cpu_x86_update_cr0(env,
                       env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK |
                                      CR0_PG_MASK));
    cpu_x86_update_cr4(env, 0);
    env->dr[7] = 0x00000400;

    cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
                           0xffffffff,
                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
                           DESC_A_MASK);
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff,
                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
                           DESC_A_MASK);
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff,
                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
                           DESC_A_MASK);
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff,
                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
                           DESC_A_MASK);
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff,
                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
                           DESC_A_MASK);
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff,
                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
                           DESC_A_MASK);
}
Beispiel #8
0
static void r2d_init(ram_addr_t ram_size,
              const char *boot_device,
	      const char *kernel_filename, const char *kernel_cmdline,
	      const char *initrd_filename, const char *cpu_model)
{
    CPUState *env;
    struct SH7750State *s;
    ram_addr_t sdram_addr;
    qemu_irq *irq;
    PCIBus *pci;
    DriveInfo *dinfo;
    int i;

    if (!cpu_model)
        cpu_model = "SH7751R";

    env = cpu_init(cpu_model);
    if (!env) {
        fprintf(stderr, "Unable to find CPU definition\n");
        exit(1);
    }

    /* Allocate memory space */
    sdram_addr = qemu_ram_alloc(SDRAM_SIZE);
    cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr);
    /* Register peripherals */
    s = sh7750_init(env);
    irq = r2d_fpga_init(0x04000000, sh7750_irl(s));
    pci = sh_pci_register_bus(r2d_pci_set_irq, r2d_pci_map_irq, irq, 0, 4);

    sm501_init(0x10000000, SM501_VRAM_SIZE, irq[SM501], serial_hds[2]);

    /* onboard CF (True IDE mode, Master only). */
    if ((dinfo = drive_get(IF_IDE, 0, 0)) != NULL)
	mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1,
		      dinfo, NULL);

    /* NIC: rtl8139 on-board, and 2 slots. */
    for (i = 0; i < nb_nics; i++)
        pci_nic_init_nofail(&nd_table[i], "rtl8139", i==0 ? "2" : NULL);

    /* Todo: register on board registers */
    if (kernel_filename) {
      int kernel_size;
      /* initialization which should be done by firmware */
      stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */
      stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */

      if (kernel_cmdline) {
          kernel_size = load_image_targphys(kernel_filename,
				   SDRAM_BASE + LINUX_LOAD_OFFSET,
				   SDRAM_SIZE - LINUX_LOAD_OFFSET);
          env->pc = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000;
          pstrcpy_targphys("cmdline", SDRAM_BASE + 0x10100, 256, kernel_cmdline);
      } else {
          kernel_size = load_image_targphys(kernel_filename, SDRAM_BASE, SDRAM_SIZE);
          env->pc = SDRAM_BASE | 0xa0000000; /* Start from P2 area */
      }

      if (kernel_size < 0) {
        fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
        exit(1);
      }
    }
}
Beispiel #9
0
static void r2d_init(ram_addr_t ram_size,
              const char *boot_device,
	      const char *kernel_filename, const char *kernel_cmdline,
	      const char *initrd_filename, const char *cpu_model)
{
    CPUState *env;
    struct SH7750State *s;
    ram_addr_t sdram_addr;
    qemu_irq *irq;
    DriveInfo *dinfo;
    int i;

    if (!cpu_model)
        cpu_model = "SH7751R";

    env = cpu_init(cpu_model);
    if (!env) {
        fprintf(stderr, "Unable to find CPU definition\n");
        exit(1);
    }

    /* Allocate memory space */
    sdram_addr = qemu_ram_alloc(NULL, "r2d.sdram", SDRAM_SIZE);
    cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr);
    /* Register peripherals */
    s = sh7750_init(env);
    irq = r2d_fpga_init(0x04000000, sh7750_irl(s));
    sh_pci_register_bus(r2d_pci_set_irq, r2d_pci_map_irq, irq, 0, 4);

    sm501_init(0x10000000, SM501_VRAM_SIZE, irq[SM501], serial_hds[2]);

    /* onboard CF (True IDE mode, Master only). */
    dinfo = drive_get(IF_IDE, 0, 0);
    mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1,
                  dinfo, NULL);

    /* onboard flash memory */
    dinfo = drive_get(IF_PFLASH, 0, 0);
    pflash_cfi02_register(0x0, qemu_ram_alloc(NULL, "r2d.flash", FLASH_SIZE),
                          dinfo ? dinfo->bdrv : NULL, (16 * 1024),
                          FLASH_SIZE >> 16,
                          1, 4, 0x0000, 0x0000, 0x0000, 0x0000,
                          0x555, 0x2aa, 0);

    /* NIC: rtl8139 on-board, and 2 slots. */
    for (i = 0; i < nb_nics; i++)
        pci_nic_init_nofail(&nd_table[i], "rtl8139", i==0 ? "2" : NULL);

    /* USB keyboard */
    usbdevice_create("keyboard");

    /* Todo: register on board registers */
    memset(&boot_params, 0, sizeof(boot_params));

    if (kernel_filename) {
        int kernel_size;

        kernel_size = load_image_targphys(kernel_filename,
                                          SDRAM_BASE + LINUX_LOAD_OFFSET,
                                          INITRD_LOAD_OFFSET - LINUX_LOAD_OFFSET);
        if (kernel_size < 0) {
          fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
          exit(1);
        }

        /* initialization which should be done by firmware */
        stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */
        stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */
        env->pc = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */
    }

    if (initrd_filename) {
        int initrd_size;

        initrd_size = load_image_targphys(initrd_filename,
                                          SDRAM_BASE + INITRD_LOAD_OFFSET,
                                          SDRAM_SIZE - INITRD_LOAD_OFFSET);

        if (initrd_size < 0) {
          fprintf(stderr, "qemu: could not load initrd '%s'\n", initrd_filename);
          exit(1);
        }

        /* initialization which should be done by firmware */
        boot_params.loader_type = 1;
        boot_params.initrd_start = INITRD_LOAD_OFFSET;
        boot_params.initrd_size = initrd_size;
    }

    if (kernel_cmdline) {
        strncpy(boot_params.kernel_cmdline, kernel_cmdline,
                sizeof(boot_params.kernel_cmdline));
    }

    rom_add_blob_fixed("boot_params", &boot_params, sizeof(boot_params),
                       SDRAM_BASE + BOOT_PARAMS_OFFSET);
}
Beispiel #10
0
static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
{
    int ret;
    VqInfoBlock info;
    uint8_t status;
    VirtioFeatDesc features;
    void *config;
    hwaddr indicators;
    VqConfigBlock vq_config;
    VirtioCcwDevice *dev = sch->driver_data;
    bool check_len;
    int len;
    hwaddr hw_len;

    if (!dev) {
        return -EINVAL;
    }

    trace_virtio_ccw_interpret_ccw(sch->cssid, sch->ssid, sch->schid,
                                   ccw.cmd_code);
    check_len = !((ccw.flags & CCW_FLAG_SLI) && !(ccw.flags & CCW_FLAG_DC));

    /* Look at the command. */
    switch (ccw.cmd_code) {
    case CCW_CMD_SET_VQ:
        if (check_len) {
            if (ccw.count != sizeof(info)) {
                ret = -EINVAL;
                break;
            }
        } else if (ccw.count < sizeof(info)) {
            /* Can't execute command. */
            ret = -EINVAL;
            break;
        }
        if (!ccw.cda) {
            ret = -EFAULT;
        } else {
            info.queue = ldq_phys(ccw.cda);
            info.align = ldl_phys(ccw.cda + sizeof(info.queue));
            info.index = lduw_phys(ccw.cda + sizeof(info.queue)
                                   + sizeof(info.align));
            info.num = lduw_phys(ccw.cda + sizeof(info.queue)
                                 + sizeof(info.align)
                                 + sizeof(info.index));
            ret = virtio_ccw_set_vqs(sch, info.queue, info.align, info.index,
                                     info.num);
            sch->curr_status.scsw.count = 0;
        }
        break;
    case CCW_CMD_VDEV_RESET:
        virtio_reset(dev->vdev);
        ret = 0;
        break;
    case CCW_CMD_READ_FEAT:
        if (check_len) {
            if (ccw.count != sizeof(features)) {
                ret = -EINVAL;
                break;
            }
        } else if (ccw.count < sizeof(features)) {
            /* Can't execute command. */
            ret = -EINVAL;
            break;
        }
        if (!ccw.cda) {
            ret = -EFAULT;
        } else {
            features.index = ldub_phys(ccw.cda + sizeof(features.features));
            if (features.index < ARRAY_SIZE(dev->host_features)) {
                features.features = dev->host_features[features.index];
            } else {
                /* Return zeroes if the guest supports more feature bits. */
                features.features = 0;
            }
            stl_le_phys(ccw.cda, features.features);
            sch->curr_status.scsw.count = ccw.count - sizeof(features);
            ret = 0;
        }
        break;
    case CCW_CMD_WRITE_FEAT:
        if (check_len) {
            if (ccw.count != sizeof(features)) {
                ret = -EINVAL;
                break;
            }
        } else if (ccw.count < sizeof(features)) {
            /* Can't execute command. */
            ret = -EINVAL;
            break;
        }
        if (!ccw.cda) {
            ret = -EFAULT;
        } else {
            features.index = ldub_phys(ccw.cda + sizeof(features.features));
            features.features = ldl_le_phys(ccw.cda);
            if (features.index < ARRAY_SIZE(dev->host_features)) {
                if (dev->vdev->set_features) {
                    dev->vdev->set_features(dev->vdev, features.features);
                }
                dev->vdev->guest_features = features.features;
            } else {
                /*
                 * If the guest supports more feature bits, assert that it
                 * passes us zeroes for those we don't support.
                 */
                if (features.features) {
                    fprintf(stderr, "Guest bug: features[%i]=%x (expected 0)\n",
                            features.index, features.features);
                    /* XXX: do a unit check here? */
                }
            }
            sch->curr_status.scsw.count = ccw.count - sizeof(features);
            ret = 0;
        }
        break;
    case CCW_CMD_READ_CONF:
        if (check_len) {
            if (ccw.count > dev->vdev->config_len) {
                ret = -EINVAL;
                break;
            }
        }
        len = MIN(ccw.count, dev->vdev->config_len);
        if (!ccw.cda) {
            ret = -EFAULT;
        } else {
            dev->vdev->get_config(dev->vdev, dev->vdev->config);
            /* XXX config space endianness */
            cpu_physical_memory_write(ccw.cda, dev->vdev->config, len);
            sch->curr_status.scsw.count = ccw.count - len;
            ret = 0;
        }
        break;
    case CCW_CMD_WRITE_CONF:
        if (check_len) {
            if (ccw.count > dev->vdev->config_len) {
                ret = -EINVAL;
                break;
            }
        }
        len = MIN(ccw.count, dev->vdev->config_len);
        hw_len = len;
        if (!ccw.cda) {
            ret = -EFAULT;
        } else {
            config = cpu_physical_memory_map(ccw.cda, &hw_len, 0);
            if (!config) {
                ret = -EFAULT;
            } else {
                len = hw_len;
                /* XXX config space endianness */
                memcpy(dev->vdev->config, config, len);
                cpu_physical_memory_unmap(config, hw_len, 0, hw_len);
                if (dev->vdev->set_config) {
                    dev->vdev->set_config(dev->vdev, dev->vdev->config);
                }
                sch->curr_status.scsw.count = ccw.count - len;
                ret = 0;
            }
        }
        break;
    case CCW_CMD_WRITE_STATUS:
        if (check_len) {
            if (ccw.count != sizeof(status)) {
                ret = -EINVAL;
                break;
            }
        } else if (ccw.count < sizeof(status)) {
            /* Can't execute command. */
            ret = -EINVAL;
            break;
        }
        if (!ccw.cda) {
            ret = -EFAULT;
        } else {
            status = ldub_phys(ccw.cda);
            virtio_set_status(dev->vdev, status);
            if (dev->vdev->status == 0) {
                virtio_reset(dev->vdev);
            }
            sch->curr_status.scsw.count = ccw.count - sizeof(status);
            ret = 0;
        }
        break;
    case CCW_CMD_SET_IND:
        if (check_len) {
            if (ccw.count != sizeof(indicators)) {
                ret = -EINVAL;
                break;
            }
        } else if (ccw.count < sizeof(indicators)) {
            /* Can't execute command. */
            ret = -EINVAL;
            break;
        }
        indicators = ldq_phys(ccw.cda);
        if (!indicators) {
            ret = -EFAULT;
        } else {
            dev->indicators = indicators;
            sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
            ret = 0;
        }
        break;
    case CCW_CMD_SET_CONF_IND:
        if (check_len) {
            if (ccw.count != sizeof(indicators)) {
                ret = -EINVAL;
                break;
            }
        } else if (ccw.count < sizeof(indicators)) {
            /* Can't execute command. */
            ret = -EINVAL;
            break;
        }
        indicators = ldq_phys(ccw.cda);
        if (!indicators) {
            ret = -EFAULT;
        } else {
            dev->indicators2 = indicators;
            sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
            ret = 0;
        }
        break;
    case CCW_CMD_READ_VQ_CONF:
        if (check_len) {
            if (ccw.count != sizeof(vq_config)) {
                ret = -EINVAL;
                break;
            }
        } else if (ccw.count < sizeof(vq_config)) {
            /* Can't execute command. */
            ret = -EINVAL;
            break;
        }
        if (!ccw.cda) {
            ret = -EFAULT;
        } else {
            vq_config.index = lduw_phys(ccw.cda);
            vq_config.num_max = virtio_queue_get_num(dev->vdev,
                                                     vq_config.index);
            stw_phys(ccw.cda + sizeof(vq_config.index), vq_config.num_max);
            sch->curr_status.scsw.count = ccw.count - sizeof(vq_config);
            ret = 0;
        }
        break;
    default:
        ret = -ENOSYS;
        break;
    }
    return ret;
}
Beispiel #11
0
static inline void vring_used_idx_increment(VirtQueue *vq, uint16_t val)
{
    target_phys_addr_t pa;
    pa = vq->vring.used + offsetof(VRingUsed, idx);
    stw_phys(pa, vring_used_idx(vq) + val);
}