Пример #1
0
/* CPUClass::reset() */
static void mb_cpu_reset(CPUState *s)
{
    MicroBlazeCPU *cpu = MICROBLAZE_CPU(s);
    MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_GET_CLASS(cpu);
    CPUMBState *env = &cpu->env;

    mcc->parent_reset(s);

    memset(env, 0, offsetof(CPUMBState, end_reset_fields));
    env->res_addr = RES_ADDR_NONE;

    /* Disable stack protector.  */
    env->shr = ~0;

    env->sregs[SR_PC] = cpu->cfg.base_vectors;

#if defined(CONFIG_USER_ONLY)
    /* start in user mode with interrupts enabled.  */
    env->sregs[SR_MSR] = MSR_EE | MSR_IE | MSR_VM | MSR_UM;
#else
    env->sregs[SR_MSR] = 0;
    mmu_init(&env->mmu);
    env->mmu.c_mmu = 3;
    env->mmu.c_mmu_tlb_access = 3;
    env->mmu.c_mmu_zones = 16;
#endif
}
static void secondary_cpu_reset(void *opaque)
{
    MicroBlazeCPU *cpu = MICROBLAZE_CPU(opaque);

    /* Configure secondary cores.  */
    microblaze_generic_fdt_reset(cpu);
}
Пример #3
0
void mb_cpu_unassigned_access(CPUState *cs, hwaddr addr,
                              bool is_write, bool is_exec, int is_asi,
                              unsigned size)
{
    MicroBlazeCPU *cpu;
    CPUMBState *env;

    qemu_log_mask(CPU_LOG_INT, "Unassigned " TARGET_FMT_plx " wr=%d exe=%d\n",
             addr, is_write ? 1 : 0, is_exec ? 1 : 0);
    if (cs == NULL) {
        return;
    }
    cpu = MICROBLAZE_CPU(cs);
    env = &cpu->env;
    if (!(env->sregs[SR_MSR] & MSR_EE)) {
        return;
    }

    env->sregs[SR_EAR] = addr;
    if (is_exec) {
        if ((env->pvr.regs[2] & PVR2_IOPB_BUS_EXC_MASK)) {
            env->sregs[SR_ESR] = ESR_EC_INSN_BUS;
            helper_raise_exception(env, EXCP_HW_EXCP);
        }
    } else {
        if ((env->pvr.regs[2] & PVR2_DOPB_BUS_EXC_MASK)) {
            env->sregs[SR_ESR] = ESR_EC_DATA_BUS;
            helper_raise_exception(env, EXCP_HW_EXCP);
        }
    }
}
Пример #4
0
/* CPUClass::reset() */
static void mb_cpu_reset(CPUState *s)
{
    MicroBlazeCPU *cpu = MICROBLAZE_CPU(s);
    MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_GET_CLASS(cpu);
    CPUMBState *env = &cpu->env;

    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
        log_cpu_state(env, 0);
    }

    mcc->parent_reset(s);

    memset(env, 0, offsetof(CPUMBState, breakpoints));
    env->res_addr = RES_ADDR_NONE;
    tlb_flush(env, 1);

    /* Disable stack protector.  */
    env->shr = ~0;

    env->pvr.regs[0] = PVR0_PVR_FULL_MASK \
                       | PVR0_USE_BARREL_MASK \
                       | PVR0_USE_DIV_MASK \
                       | PVR0_USE_HW_MUL_MASK \
                       | PVR0_USE_EXC_MASK \
                       | PVR0_USE_ICACHE_MASK \
                       | PVR0_USE_DCACHE_MASK \
                       | PVR0_USE_MMU \
                       | (0xb << 8);
    env->pvr.regs[2] = PVR2_D_OPB_MASK \
                        | PVR2_D_LMB_MASK \
                        | PVR2_I_OPB_MASK \
                        | PVR2_I_LMB_MASK \
                        | PVR2_USE_MSR_INSTR \
                        | PVR2_USE_PCMP_INSTR \
                        | PVR2_USE_BARREL_MASK \
                        | PVR2_USE_DIV_MASK \
                        | PVR2_USE_HW_MUL_MASK \
                        | PVR2_USE_MUL64_MASK \
                        | PVR2_USE_FPU_MASK \
                        | PVR2_USE_FPU2_MASK \
                        | PVR2_FPU_EXC_MASK \
                        | 0;
    env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family.  */
    env->pvr.regs[11] = PVR11_USE_MMU | (16 << 17);

#if defined(CONFIG_USER_ONLY)
    /* start in user mode with interrupts enabled.  */
    env->sregs[SR_MSR] = MSR_EE | MSR_IE | MSR_VM | MSR_UM;
    env->pvr.regs[10] = 0x0c000000; /* Spartan 3a dsp.  */
#else
    env->sregs[SR_MSR] = 0;
    mmu_init(&env->mmu);
    env->mmu.c_mmu = 3;
    env->mmu.c_mmu_tlb_access = 3;
    env->mmu.c_mmu_zones = 16;
#endif
}
Пример #5
0
void mb_cpu_do_interrupt(CPUState *cs)
{
    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
    CPUMBState *env = &cpu->env;

    cs->exception_index = -1;
    env->res_addr = RES_ADDR_NONE;
    env->regs[14] = env->sregs[SR_PC];
}
Пример #6
0
static void mb_cpu_realizefn(DeviceState *dev, Error **errp)
{
    MicroBlazeCPU *cpu = MICROBLAZE_CPU(dev);
    MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_GET_CLASS(dev);

    cpu_reset(CPU(cpu));

    mcc->parent_realize(dev, errp);
}
Пример #7
0
static void mb_cpu_initfn(Object *obj)
{
    MicroBlazeCPU *cpu = MICROBLAZE_CPU(obj);
    CPUMBState *env = &cpu->env;

    cpu_exec_init(env);

    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
}
Пример #8
0
bool mb_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
    CPUMBState *env = &cpu->env;

    if ((interrupt_request & CPU_INTERRUPT_HARD)
        && (env->sregs[SR_MSR] & MSR_IE)
        && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
        && !(env->iflags & (D_FLAG | IMM_FLAG))) {
        cs->exception_index = EXCP_IRQ;
        mb_cpu_do_interrupt(cs);
        return true;
    }
    return false;
}
Пример #9
0
static void mb_cpu_initfn(Object *obj)
{
    CPUState *cs = CPU(obj);
    MicroBlazeCPU *cpu = MICROBLAZE_CPU(obj);
    CPUMBState *env = &cpu->env;

    cs->env_ptr = env;

    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);

#ifndef CONFIG_USER_ONLY
    /* Inbound IRQ and FIR lines */
    qdev_init_gpio_in(DEVICE(cpu), microblaze_cpu_set_irq, 2);
#endif
}
Пример #10
0
static void mb_cpu_initfn(Object *obj)
{
    CPUState *cs = CPU(obj);
    MicroBlazeCPU *cpu = MICROBLAZE_CPU(obj);
    CPUMBState *env = &cpu->env;
    static bool tcg_initialized;

    cs->env_ptr = env;
    cpu_exec_init(env);

    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);

    if (tcg_enabled() && !tcg_initialized) {
        tcg_initialized = true;
        mb_tcg_init();
    }
}
Пример #11
0
hwaddr mb_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
{
    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
    CPUMBState *env = &cpu->env;
    target_ulong vaddr, paddr = 0;
    struct microblaze_mmu_lookup lu;
    unsigned int hit;

    if (env->sregs[SR_MSR] & MSR_VM) {
        hit = mmu_translate(&env->mmu, &lu, addr, 0, 0);
        if (hit) {
            vaddr = addr & TARGET_PAGE_MASK;
            paddr = lu.paddr + vaddr - lu.vaddr;
        } else
            paddr = 0; /* ???.  */
    } else
        paddr = addr & TARGET_PAGE_MASK;

    return paddr;
}
Пример #12
0
static void mb_cpu_initfn(Object *obj)
{
    CPUState *cs = CPU(obj);
    MicroBlazeCPU *cpu = MICROBLAZE_CPU(obj);
    CPUMBState *env = &cpu->env;
    static bool tcg_initialized;

    cs->env_ptr = env;
    cpu_exec_init(env);

    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);

#ifndef CONFIG_USER_ONLY
    /* Inbound IRQ and FIR lines */
    qdev_init_gpio_in(DEVICE(cpu), microblaze_cpu_set_irq, 2);
#endif

    if (tcg_enabled() && !tcg_initialized) {
        tcg_initialized = true;
        mb_tcg_init();
    }
}
Пример #13
0
static void
petalogix_s3adsp1800_init(MachineState *machine)
{
    ram_addr_t ram_size = machine->ram_size;
    DeviceState *dev;
    MicroBlazeCPU *cpu;
    DriveInfo *dinfo;
    int i;
    hwaddr ddr_base = MEMORY_BASEADDR;
    MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1);
    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
    qemu_irq irq[32];
    MemoryRegion *sysmem = get_system_memory();

    cpu = MICROBLAZE_CPU(object_new(TYPE_MICROBLAZE_CPU));
    object_property_set_str(OBJECT(cpu), "7.10.d", "version", &error_abort);
    object_property_set_bool(OBJECT(cpu), true, "realized", &error_abort);

    /* Attach emulated BRAM through the LMB.  */
    memory_region_init_ram(phys_lmb_bram, NULL,
                           "petalogix_s3adsp1800.lmb_bram", LMB_BRAM_SIZE,
                           &error_fatal);
    memory_region_add_subregion(sysmem, 0x00000000, phys_lmb_bram);

    memory_region_init_ram(phys_ram, NULL, "petalogix_s3adsp1800.ram",
                           ram_size, &error_fatal);
    memory_region_add_subregion(sysmem, ddr_base, phys_ram);

    dinfo = drive_get(IF_PFLASH, 0, 0);
    pflash_cfi01_register(FLASH_BASEADDR,
                          NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE,
                          dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                          64 * KiB, FLASH_SIZE >> 16,
                          1, 0x89, 0x18, 0x0000, 0x0, 1);

    dev = qdev_create(NULL, "xlnx.xps-intc");
    qdev_prop_set_uint32(dev, "kind-of-intr",
                         1 << ETHLITE_IRQ | 1 << UARTLITE_IRQ);
    qdev_init_nofail(dev);
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, INTC_BASEADDR);
    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
                       qdev_get_gpio_in(DEVICE(cpu), MB_CPU_IRQ));
    for (i = 0; i < 32; i++) {
        irq[i] = qdev_get_gpio_in(dev, i);
    }

    xilinx_uartlite_create(UARTLITE_BASEADDR, irq[UARTLITE_IRQ],
                           serial_hd(0));

    /* 2 timers at irq 2 @ 62 Mhz.  */
    dev = qdev_create(NULL, "xlnx.xps-timer");
    qdev_prop_set_uint32(dev, "one-timer-only", 0);
    qdev_prop_set_uint32(dev, "clock-frequency", 62 * 1000000);
    qdev_init_nofail(dev);
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, TIMER_BASEADDR);
    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[TIMER_IRQ]);

    qemu_check_nic_model(&nd_table[0], "xlnx.xps-ethernetlite");
    dev = qdev_create(NULL, "xlnx.xps-ethernetlite");
    qdev_set_nic_properties(dev, &nd_table[0]);
    qdev_prop_set_uint32(dev, "tx-ping-pong", 0);
    qdev_prop_set_uint32(dev, "rx-ping-pong", 0);
    qdev_init_nofail(dev);
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, ETHLITE_BASEADDR);
    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[ETHLITE_IRQ]);

    create_unimplemented_device("gpio", GPIO_BASEADDR, 0x10000);

    microblaze_load_kernel(cpu, ddr_base, ram_size,
                           machine->initrd_filename,
                           BINARY_DEVICE_TREE_FILE,
                           NULL);
}
Пример #14
0
static void
microblaze_generic_fdt_init(MachineState *machine)
{
    CPUState *cpu;
    ram_addr_t ram_kernel_base = 0, ram_kernel_size = 0;
    void *fdt = NULL;
    const char *dtb_arg, *hw_dtb_arg;
    QemuOpts *machine_opts;
    int fdt_size;

    /* for memory node */
    char node_path[DT_PATH_LENGTH];
    FDTMachineInfo *fdti;
    MemoryRegion *main_mem;

    /* For DMA node */
    char dma_path[DT_PATH_LENGTH] = { 0 };
    uint32_t memory_phandle;

    /* For Ethernet nodes */
    char **eth_paths;
    char *phy_path;
    char *mdio_path;
    uint32_t n_eth;
    uint32_t prop_val;

    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
    if (!machine_opts) {
        goto no_dtb_arg;
    }
    dtb_arg = qemu_opt_get(machine_opts, "dtb");
    hw_dtb_arg = qemu_opt_get(machine_opts, "hw-dtb");
    if (!dtb_arg && !hw_dtb_arg) {
        goto no_dtb_arg;
    }

    /* If the user only provided a -dtb, use it as the hw description.  */
    if (!hw_dtb_arg) {
        hw_dtb_arg = dtb_arg;
    }

    fdt = load_device_tree(hw_dtb_arg, &fdt_size);
    if (!fdt) {
        hw_error("Error: Unable to load Device Tree %s\n", hw_dtb_arg);
        return;
    }

    if (IS_PETALINUX_MACHINE) {
        /* Mark the simple-bus as incompatible as it breaks the Microblaze
         * PetaLinux boot
         */
        add_to_compat_table(NULL, "compatible:simple-bus", NULL);
    }

    /* find memory node or add new one if needed */
    while (qemu_fdt_get_node_by_name(fdt, node_path, "memory")) {
        qemu_fdt_add_subnode(fdt, "/memory@0");
        qemu_fdt_setprop_cells(fdt, "/memory@0", "reg", 0, machine->ram_size);
    }

    if (!qemu_fdt_getprop(fdt, "/memory", "compatible", NULL, 0, NULL)) {
        qemu_fdt_setprop_string(fdt, "/memory", "compatible",
                                "qemu:memory-region");
        qemu_fdt_setprop_cells(fdt, "/memory", "qemu,ram", 1);
    }

    if (IS_PETALINUX_MACHINE) {
        /* If using a *-plnx machine, the AXI DMA memory links are not included
         * in the DTB by default. To avoid seg faults, add the links in here if
         * they have not already been added by the user
         */
        qemu_fdt_get_node_by_name(fdt, dma_path, "dma");

        if (strcmp(dma_path, "") != 0) {
            memory_phandle = qemu_fdt_check_phandle(fdt, node_path);

            if (!memory_phandle) {
                memory_phandle = qemu_fdt_alloc_phandle(fdt);

                qemu_fdt_setprop_cells(fdt, "/memory", "linux,phandle",
                                       memory_phandle);
                qemu_fdt_setprop_cells(fdt, "/memory", "phandle",
                                       memory_phandle);
            }

            if (!qemu_fdt_getprop(fdt, dma_path, "sg", NULL, 0, NULL)) {
                qemu_fdt_setprop_phandle(fdt, dma_path, "sg", node_path);
            }

            if (!qemu_fdt_getprop(fdt, dma_path, "s2mm", NULL, 0, NULL)) {
                qemu_fdt_setprop_phandle(fdt, dma_path, "s2mm", node_path);
            }

            if (!qemu_fdt_getprop(fdt, dma_path, "mm2s", NULL, 0, NULL)) {
                qemu_fdt_setprop_phandle(fdt, dma_path, "mm2s", node_path);
            }
        }

        /* Copy phyaddr value from phy node reg property */
        n_eth = qemu_fdt_get_n_nodes_by_name(fdt, &eth_paths, "ethernet");

        while (n_eth--) {
            mdio_path = qemu_fdt_get_child_by_name(fdt, eth_paths[n_eth],
                                                       "mdio");
            if (mdio_path) {
                phy_path = qemu_fdt_get_child_by_name(fdt, mdio_path,
                                                          "phy");
                if (phy_path) {
                    prop_val = qemu_fdt_getprop_cell(fdt, phy_path, "reg", NULL, 0,
                                                     NULL, &error_abort);
                    qemu_fdt_setprop_cell(fdt, eth_paths[n_eth], "xlnx,phyaddr",
                                          prop_val);
                    g_free(phy_path);
                } else {
                    qemu_log_mask(LOG_GUEST_ERROR, "phy not found in %s",
                                  mdio_path);
                }
                g_free(mdio_path);
            }
            g_free(eth_paths[n_eth]);
        }
        g_free(eth_paths);
    }

    /* Instantiate peripherals from the FDT.  */
    fdti = fdt_generic_create_machine(fdt, NULL);
    main_mem = MEMORY_REGION(object_resolve_path(node_path, NULL));

    ram_kernel_base = object_property_get_int(OBJECT(main_mem), "addr", NULL);
    ram_kernel_size = object_property_get_int(OBJECT(main_mem), "size", NULL);

    if (!memory_region_is_mapped(main_mem)) {
        /* If the memory region is not mapped, map it here.
         * It has to be mapped somewhere, so guess that the base address
         * is where the kernel starts
         */
        memory_region_add_subregion(get_system_memory(), ram_kernel_base,
                                    main_mem);

        if (ram_kernel_base && IS_PETALINUX_MACHINE) {
            /* If the memory added is at an offset from zero QEMU will error
             * when an ISR/exception is triggered. Add a small amount of hack
             * RAM to handle this.
             */
            MemoryRegion *hack_ram = g_new(MemoryRegion, 1);
            memory_region_init_ram(hack_ram, NULL, "hack_ram", 0x1000,
                                   &error_abort);
            vmstate_register_ram_global(hack_ram);
            memory_region_add_subregion(get_system_memory(), 0, hack_ram);
        }
    }

    fdt_init_destroy_fdti(fdti);

    fdt_g = fdt;
    microblaze_load_kernel(MICROBLAZE_CPU(first_cpu), ram_kernel_base,
                           ram_kernel_size, machine->initrd_filename, NULL,
                           microblaze_generic_fdt_reset, 0, fdt, fdt_size);

    /* Register FDT to prop mapper for secondary cores.  */
    cpu = CPU_NEXT(first_cpu);
    while (cpu) {
        qemu_register_reset(secondary_cpu_reset, cpu);
        cpu = CPU_NEXT(cpu);
    }

    return;
no_dtb_arg:
    if (!QTEST_RUNNING) {
        hw_error("DTB must be specified for %s machine model\n", MACHINE_NAME);
    }
    return;
}
Пример #15
0
static void
petalogix_ml605_init(MachineState *machine)
{
    ram_addr_t ram_size = machine->ram_size;
    MemoryRegion *address_space_mem = get_system_memory();
    DeviceState *dev, *dma, *eth0;
    Object *ds, *cs;
    MicroBlazeCPU *cpu;
    SysBusDevice *busdev;
    DriveInfo *dinfo;
    int i;
    MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1);
    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
    qemu_irq irq[32];

    /* init CPUs */
    cpu = MICROBLAZE_CPU(object_new(TYPE_MICROBLAZE_CPU));
    object_property_set_str(OBJECT(cpu), "8.10.a", "version", &error_abort);
    /* Use FPU but don't use floating point conversion and square
     * root instructions
     */
    object_property_set_int(OBJECT(cpu), 1, "use-fpu", &error_abort);
    object_property_set_bool(OBJECT(cpu), true, "dcache-writeback",
                             &error_abort);
    object_property_set_bool(OBJECT(cpu), true, "endianness", &error_abort);
    object_property_set_bool(OBJECT(cpu), true, "realized", &error_abort);

    /* Attach emulated BRAM through the LMB.  */
    memory_region_init_ram(phys_lmb_bram, NULL, "petalogix_ml605.lmb_bram",
                           LMB_BRAM_SIZE, &error_fatal);
    vmstate_register_ram_global(phys_lmb_bram);
    memory_region_add_subregion(address_space_mem, 0x00000000, phys_lmb_bram);

    memory_region_init_ram(phys_ram, NULL, "petalogix_ml605.ram", ram_size,
                           &error_fatal);
    vmstate_register_ram_global(phys_ram);
    memory_region_add_subregion(address_space_mem, MEMORY_BASEADDR, phys_ram);

    dinfo = drive_get(IF_PFLASH, 0, 0);
    /* 5th parameter 2 means bank-width
     * 10th paremeter 0 means little-endian */
    pflash_cfi01_register(FLASH_BASEADDR,
                          NULL, "petalogix_ml605.flash", FLASH_SIZE,
                          dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                          (64 * 1024), FLASH_SIZE >> 16,
                          2, 0x89, 0x18, 0x0000, 0x0, 0);


    dev = qdev_create(NULL, "xlnx.xps-intc");
    qdev_prop_set_uint32(dev, "kind-of-intr", 1 << TIMER_IRQ);
    qdev_init_nofail(dev);
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, INTC_BASEADDR);
    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
                       qdev_get_gpio_in(DEVICE(cpu), MB_CPU_IRQ));
    for (i = 0; i < 32; i++) {
        irq[i] = qdev_get_gpio_in(dev, i);
    }

    serial_mm_init(address_space_mem, UART16550_BASEADDR + 0x1000, 2,
                   irq[UART16550_IRQ], 115200, serial_hds[0],
                   DEVICE_LITTLE_ENDIAN);

    /* 2 timers at irq 2 @ 100 Mhz.  */
    dev = qdev_create(NULL, "xlnx.xps-timer");
    qdev_prop_set_uint32(dev, "one-timer-only", 0);
    qdev_prop_set_uint32(dev, "clock-frequency", 100 * 1000000);
    qdev_init_nofail(dev);
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, TIMER_BASEADDR);
    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[TIMER_IRQ]);

    /* axi ethernet and dma initialization. */
    qemu_check_nic_model(&nd_table[0], "xlnx.axi-ethernet");
    eth0 = qdev_create(NULL, "xlnx.axi-ethernet");
    dma = qdev_create(NULL, "xlnx.axi-dma");

    /* FIXME: attach to the sysbus instead */
    object_property_add_child(qdev_get_machine(), "xilinx-eth", OBJECT(eth0),
                              NULL);
    object_property_add_child(qdev_get_machine(), "xilinx-dma", OBJECT(dma),
                              NULL);

    ds = object_property_get_link(OBJECT(dma),
                                  "axistream-connected-target", NULL);
    cs = object_property_get_link(OBJECT(dma),
                                  "axistream-control-connected-target", NULL);
    qdev_set_nic_properties(eth0, &nd_table[0]);
    qdev_prop_set_uint32(eth0, "rxmem", 0x1000);
    qdev_prop_set_uint32(eth0, "txmem", 0x1000);
    object_property_set_link(OBJECT(eth0), OBJECT(ds),
                             "axistream-connected", &error_abort);
    object_property_set_link(OBJECT(eth0), OBJECT(cs),
                             "axistream-control-connected", &error_abort);
    qdev_init_nofail(eth0);
    sysbus_mmio_map(SYS_BUS_DEVICE(eth0), 0, AXIENET_BASEADDR);
    sysbus_connect_irq(SYS_BUS_DEVICE(eth0), 0, irq[AXIENET_IRQ]);

    ds = object_property_get_link(OBJECT(eth0),
                                  "axistream-connected-target", NULL);
    cs = object_property_get_link(OBJECT(eth0),
                                  "axistream-control-connected-target", NULL);
    qdev_prop_set_uint32(dma, "freqhz", 100 * 1000000);
    object_property_set_link(OBJECT(dma), OBJECT(ds),
                             "axistream-connected", &error_abort);
    object_property_set_link(OBJECT(dma), OBJECT(cs),
                             "axistream-control-connected", &error_abort);
    qdev_init_nofail(dma);
    sysbus_mmio_map(SYS_BUS_DEVICE(dma), 0, AXIDMA_BASEADDR);
    sysbus_connect_irq(SYS_BUS_DEVICE(dma), 0, irq[AXIDMA_IRQ0]);
    sysbus_connect_irq(SYS_BUS_DEVICE(dma), 1, irq[AXIDMA_IRQ1]);

    {
        SSIBus *spi;

        dev = qdev_create(NULL, "xlnx.xps-spi");
        qdev_prop_set_uint8(dev, "num-ss-bits", NUM_SPI_FLASHES);
        qdev_init_nofail(dev);
        busdev = SYS_BUS_DEVICE(dev);
        sysbus_mmio_map(busdev, 0, SPI_BASEADDR);
        sysbus_connect_irq(busdev, 0, irq[SPI_IRQ]);

        spi = (SSIBus *)qdev_get_child_bus(dev, "spi");

        for (i = 0; i < NUM_SPI_FLASHES; i++) {
            qemu_irq cs_line;

            dev = ssi_create_slave(spi, "n25q128");
            cs_line = qdev_get_gpio_in_named(dev, SSI_GPIO_CS, 0);
            sysbus_connect_irq(busdev, i+1, cs_line);
        }
    }

    /* setup PVR to match kernel settings */
    cpu->env.pvr.regs[4] = 0xc56b8000;
    cpu->env.pvr.regs[5] = 0xc56be000;
    cpu->env.pvr.regs[10] = 0x0e000000; /* virtex 6 */

    microblaze_load_kernel(cpu, MEMORY_BASEADDR, ram_size,
                           machine->initrd_filename,
                           BINARY_DEVICE_TREE_FILE,
                           NULL);

}
Пример #16
0
static void mb_cpu_realizefn(DeviceState *dev, Error **errp)
{
    CPUState *cs = CPU(dev);
    MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_GET_CLASS(dev);
    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
    CPUMBState *env = &cpu->env;
    uint8_t version_code = 0;
    int i = 0;
    Error *local_err = NULL;

    cpu_exec_realizefn(cs, &local_err);
    if (local_err != NULL) {
        error_propagate(errp, local_err);
        return;
    }

    qemu_init_vcpu(cs);

    env->pvr.regs[0] = PVR0_USE_EXC_MASK \
                       | PVR0_USE_ICACHE_MASK \
                       | PVR0_USE_DCACHE_MASK;
    env->pvr.regs[2] = PVR2_D_OPB_MASK \
                        | PVR2_D_LMB_MASK \
                        | PVR2_I_OPB_MASK \
                        | PVR2_I_LMB_MASK \
                        | PVR2_FPU_EXC_MASK \
                        | 0;

    for (i = 0; mb_cpu_lookup[i].name && cpu->cfg.version; i++) {
        if (strcmp(mb_cpu_lookup[i].name, cpu->cfg.version) == 0) {
            version_code = mb_cpu_lookup[i].version_id;
            break;
        }
    }

    if (!version_code) {
        qemu_log("Invalid MicroBlaze version number: %s\n", cpu->cfg.version);
    }

    env->pvr.regs[0] |= (cpu->cfg.stackprot ? PVR0_SPROT_MASK : 0) |
                        (cpu->cfg.use_fpu ? PVR0_USE_FPU_MASK : 0) |
                        (cpu->cfg.use_hw_mul ? PVR0_USE_HW_MUL_MASK : 0) |
                        (cpu->cfg.use_barrel ? PVR0_USE_BARREL_MASK : 0) |
                        (cpu->cfg.use_div ? PVR0_USE_DIV_MASK : 0) |
                        (cpu->cfg.use_mmu ? PVR0_USE_MMU_MASK : 0) |
                        (cpu->cfg.endi ? PVR0_ENDI_MASK : 0) |
                        (version_code << PVR0_VERSION_SHIFT) |
                        (cpu->cfg.pvr == C_PVR_FULL ? PVR0_PVR_FULL_MASK : 0);

    env->pvr.regs[2] |= (cpu->cfg.use_fpu ? PVR2_USE_FPU_MASK : 0) |
                        (cpu->cfg.use_fpu > 1 ? PVR2_USE_FPU2_MASK : 0) |
                        (cpu->cfg.use_hw_mul ? PVR2_USE_HW_MUL_MASK : 0) |
                        (cpu->cfg.use_hw_mul > 1 ? PVR2_USE_MUL64_MASK : 0) |
                        (cpu->cfg.use_barrel ? PVR2_USE_BARREL_MASK : 0) |
                        (cpu->cfg.use_div ? PVR2_USE_DIV_MASK : 0) |
                        (cpu->cfg.use_msr_instr ? PVR2_USE_MSR_INSTR : 0) |
                        (cpu->cfg.use_pcmp_instr ? PVR2_USE_PCMP_INSTR : 0);

    env->pvr.regs[5] |= cpu->cfg.dcache_writeback ?
                                        PVR5_DCACHE_WRITEBACK_MASK : 0;

    env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family.  */
    env->pvr.regs[11] = PVR11_USE_MMU | (16 << 17);

    mcc->parent_realize(dev, errp);
}
Пример #17
0
int mb_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
                            int mmu_idx)
{
    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
    CPUMBState *env = &cpu->env;
    unsigned int hit;
    unsigned int mmu_available;
    int r = 1;
    int prot;

    mmu_available = 0;
    if (env->pvr.regs[0] & PVR0_USE_MMU) {
        mmu_available = 1;
        if ((env->pvr.regs[0] & PVR0_PVR_FULL_MASK)
            && (env->pvr.regs[11] & PVR11_USE_MMU) != PVR11_USE_MMU) {
            mmu_available = 0;
        }
    }

    /* Translate if the MMU is available and enabled.  */
    if (mmu_available && (env->sregs[SR_MSR] & MSR_VM)) {
        target_ulong vaddr, paddr;
        struct microblaze_mmu_lookup lu;

        hit = mmu_translate(&env->mmu, &lu, address, rw, mmu_idx);
        if (hit) {
            vaddr = address & TARGET_PAGE_MASK;
            paddr = lu.paddr + vaddr - lu.vaddr;

            qemu_log_mask(CPU_LOG_MMU, "MMU map mmu=%d v=%x p=%x prot=%x\n",
                    mmu_idx, vaddr, paddr, lu.prot);
            tlb_set_page(cs, vaddr, paddr, lu.prot, mmu_idx, TARGET_PAGE_SIZE);
            r = 0;
        } else {
            env->sregs[SR_EAR] = address;
            qemu_log_mask(CPU_LOG_MMU, "mmu=%d miss v=%" VADDR_PRIx "\n",
                                        mmu_idx, address);

            switch (lu.err) {
                case ERR_PROT:
                    env->sregs[SR_ESR] = rw == 2 ? 17 : 16;
                    env->sregs[SR_ESR] |= (rw == 1) << 10;
                    break;
                case ERR_MISS:
                    env->sregs[SR_ESR] = rw == 2 ? 19 : 18;
                    env->sregs[SR_ESR] |= (rw == 1) << 10;
                    break;
                default:
                    abort();
                    break;
            }

            if (cs->exception_index == EXCP_MMU) {
                cpu_abort(cs, "recursive faults\n");
            }

            /* TLB miss.  */
            cs->exception_index = EXCP_MMU;
        }
    } else {
        /* MMU disabled or not available.  */
        address &= TARGET_PAGE_MASK;
        prot = PAGE_BITS;
        tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
        r = 0;
    }
    return r;
}
Пример #18
0
static void mb_cpu_set_pc(CPUState *cs, vaddr value)
{
    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);

    cpu->env.sregs[SR_PC] = value;
}
Пример #19
0
static void
sprite_engine_init(MachineState *machine)
{
    ram_addr_t ram_size = machine->ram_size;
    MemoryRegion *address_space_mem = get_system_memory();
    DeviceState *dev;
    MicroBlazeCPU *cpu;
    DriveInfo *dinfo;
    int i;
    MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1);
    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
    qemu_irq irq[32];

    /* init CPUs */
    cpu = MICROBLAZE_CPU(object_new(TYPE_MICROBLAZE_CPU));
    /* Use FPU but don't use floating point conversion and square
     * root instructions
     */
    object_property_set_int(OBJECT(cpu), 1, "use-fpu", &error_abort);
    object_property_set_bool(OBJECT(cpu), true, "dcache-writeback",
                             &error_abort);
    object_property_set_bool(OBJECT(cpu), true, "endianness", &error_abort);
    object_property_set_bool(OBJECT(cpu), true, "realized", &error_abort);

    /* Attach emulated BRAM through the LMB.  */
    memory_region_init_ram(phys_lmb_bram, NULL, "sprite_engine.lmb_bram",
                           LMB_BRAM_SIZE, &error_fatal);
    vmstate_register_ram_global(phys_lmb_bram);
    memory_region_add_subregion(address_space_mem, 0x00000000, phys_lmb_bram);

    memory_region_init_ram(phys_ram, NULL, "sprite_engine.ram", ram_size,
                           &error_fatal);
    vmstate_register_ram_global(phys_ram);
    memory_region_add_subregion(address_space_mem, MEMORY_BASEADDR, phys_ram);

    dinfo = drive_get(IF_PFLASH, 0, 0);
    /* 5th parameter 2 means bank-width
     * 10th paremeter 0 means little-endian */
    pflash_cfi01_register(FLASH_BASEADDR,
                          NULL, "sprite_engine.flash", FLASH_SIZE,
                          dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                          (64 * 1024), FLASH_SIZE >> 16,
                          2, 0x89, 0x18, 0x0000, 0x0, 0);


    dev = qdev_create(NULL, "xlnx.xps-intc");
    qdev_prop_set_uint32(dev, "kind-of-intr", 1 << TIMER_IRQ);
    qdev_init_nofail(dev);
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, INTC_BASEADDR);
    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
                       qdev_get_gpio_in(DEVICE(cpu), MB_CPU_IRQ));
    for (i = 0; i < 32; i++) {
        irq[i] = qdev_get_gpio_in(dev, i);
    }

    // create a uartlite
    sysbus_create_simple("xlnx.xps-uartlite", UARTLITE_BASEADDR,
                         irq[UARTLITE_IRQ]);

    // Create the vsync timer, and connect it to TIMER_IRQ
    dev = qdev_create(NULL, "sprite-engine.vsync");
    qdev_prop_set_uint32(dev, "clock-frequency", 60000);
    qdev_init_nofail(dev);
    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[TIMER_IRQ]);

    /* sprite engine init */
    dev = qdev_create(NULL, "sprite-engine");
    qdev_init_nofail(dev);
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, SPRITE_ENGINE_BASEADDR);

    /* sprite engine controllers init */
    dev = qdev_create(NULL, "sprite-engine-controller");
    qdev_prop_set_uint32(dev, "port", 1986);
    qdev_init_nofail(dev);
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, SPRITE_ENGINE_CONTROLLER_1);
    dev = qdev_create(NULL, "sprite-engine-controller");
    qdev_prop_set_uint32(dev, "port", 1987);
    qdev_init_nofail(dev);
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, SPRITE_ENGINE_CONTROLLER_2);
    dev = qdev_create(NULL, "sprite-engine-controller");
    qdev_prop_set_uint32(dev, "port", 1988);
    qdev_init_nofail(dev);
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, SPRITE_ENGINE_CONTROLLER_3);
    dev = qdev_create(NULL, "sprite-engine-controller");
    qdev_prop_set_uint32(dev, "port", 1989);
    qdev_init_nofail(dev);
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, SPRITE_ENGINE_CONTROLLER_4);

    /* setup PVR to match kernel settings */
    cpu->env.pvr.regs[4] = 0xc56b8000;
    cpu->env.pvr.regs[5] = 0xc56be000;
    cpu->env.pvr.regs[10] = 0x0e000000; /* virtex 6 */

    microblaze_load_kernel(cpu, MEMORY_BASEADDR, ram_size,
                           machine->initrd_filename,
                           BINARY_DEVICE_TREE_FILE,
                           NULL);

}
Пример #20
0
void mb_cpu_do_interrupt(CPUState *cs)
{
    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
    CPUMBState *env = &cpu->env;
    uint32_t t;

    /* IMM flag cannot propagate across a branch and into the dslot.  */
    assert(!((env->iflags & D_FLAG) && (env->iflags & IMM_FLAG)));
    assert(!(env->iflags & (DRTI_FLAG | DRTE_FLAG | DRTB_FLAG)));
/*    assert(env->sregs[SR_MSR] & (MSR_EE)); Only for HW exceptions.  */
    env->res_addr = RES_ADDR_NONE;
    switch (cs->exception_index) {
        case EXCP_HW_EXCP:
            if (!(env->pvr.regs[0] & PVR0_USE_EXC_MASK)) {
                qemu_log("Exception raised on system without exceptions!\n");
                return;
            }

            env->regs[17] = env->sregs[SR_PC] + 4;
            env->sregs[SR_ESR] &= ~(1 << 12);

            /* Exception breaks branch + dslot sequence?  */
            if (env->iflags & D_FLAG) {
                env->sregs[SR_ESR] |= 1 << 12 ;
                env->sregs[SR_BTR] = env->btarget;
            }

            /* Disable the MMU.  */
            t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1;
            env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM);
            env->sregs[SR_MSR] |= t;
            /* Exception in progress.  */
            env->sregs[SR_MSR] |= MSR_EIP;

            qemu_log_mask(CPU_LOG_INT,
                          "hw exception at pc=%x ear=%x esr=%x iflags=%x\n",
                          env->sregs[SR_PC], env->sregs[SR_EAR],
                          env->sregs[SR_ESR], env->iflags);
            log_cpu_state_mask(CPU_LOG_INT, cs, 0);
            env->iflags &= ~(IMM_FLAG | D_FLAG);
            env->sregs[SR_PC] = cpu->base_vectors + 0x20;
            break;

        case EXCP_MMU:
            env->regs[17] = env->sregs[SR_PC];

            env->sregs[SR_ESR] &= ~(1 << 12);
            /* Exception breaks branch + dslot sequence?  */
            if (env->iflags & D_FLAG) {
                D(qemu_log("D_FLAG set at exception bimm=%d\n", env->bimm));
                env->sregs[SR_ESR] |= 1 << 12 ;
                env->sregs[SR_BTR] = env->btarget;

                /* Reexecute the branch.  */
                env->regs[17] -= 4;
                /* was the branch immprefixed?.  */
                if (env->bimm) {
                    qemu_log_mask(CPU_LOG_INT,
                                  "bimm exception at pc=%x iflags=%x\n",
                                  env->sregs[SR_PC], env->iflags);
                    env->regs[17] -= 4;
                    log_cpu_state_mask(CPU_LOG_INT, cs, 0);
                }
            } else if (env->iflags & IMM_FLAG) {
                D(qemu_log("IMM_FLAG set at exception\n"));
                env->regs[17] -= 4;
            }

            /* Disable the MMU.  */
            t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1;
            env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM);
            env->sregs[SR_MSR] |= t;
            /* Exception in progress.  */
            env->sregs[SR_MSR] |= MSR_EIP;

            qemu_log_mask(CPU_LOG_INT,
                          "exception at pc=%x ear=%x iflags=%x\n",
                          env->sregs[SR_PC], env->sregs[SR_EAR], env->iflags);
            log_cpu_state_mask(CPU_LOG_INT, cs, 0);
            env->iflags &= ~(IMM_FLAG | D_FLAG);
            env->sregs[SR_PC] = cpu->base_vectors + 0x20;
            break;

        case EXCP_IRQ:
            assert(!(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP)));
            assert(env->sregs[SR_MSR] & MSR_IE);
            assert(!(env->iflags & D_FLAG));

            t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1;

#if 0
#include "disas/disas.h"

/* Useful instrumentation when debugging interrupt issues in either
   the models or in sw.  */
            {
                const char *sym;

                sym = lookup_symbol(env->sregs[SR_PC]);
                if (sym
                    && (!strcmp("netif_rx", sym)
                        || !strcmp("process_backlog", sym))) {

                    qemu_log(
                         "interrupt at pc=%x msr=%x %x iflags=%x sym=%s\n",
                         env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags,
                         sym);

                    log_cpu_state(cs, 0);
                }
            }
#endif
            qemu_log_mask(CPU_LOG_INT,
                         "interrupt at pc=%x msr=%x %x iflags=%x\n",
                         env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags);

            env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM \
                                    | MSR_UM | MSR_IE);
            env->sregs[SR_MSR] |= t;

            env->regs[14] = env->sregs[SR_PC];
            env->sregs[SR_PC] = cpu->base_vectors + 0x10;
            //log_cpu_state_mask(CPU_LOG_INT, cs, 0);
            break;

        case EXCP_BREAK:
        case EXCP_HW_BREAK:
            assert(!(env->iflags & IMM_FLAG));
            assert(!(env->iflags & D_FLAG));
            t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1;
            qemu_log_mask(CPU_LOG_INT,
                        "break at pc=%x msr=%x %x iflags=%x\n",
                        env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags);
            log_cpu_state_mask(CPU_LOG_INT, cs, 0);
            env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM);
            env->sregs[SR_MSR] |= t;
            env->sregs[SR_MSR] |= MSR_BIP;
            if (cs->exception_index == EXCP_HW_BREAK) {
                env->regs[16] = env->sregs[SR_PC];
                env->sregs[SR_MSR] |= MSR_BIP;
                env->sregs[SR_PC] = cpu->base_vectors + 0x18;
            } else
                env->sregs[SR_PC] = env->btarget;
            break;
        default:
            cpu_abort(cs, "unhandled exception type=%d\n",
                      cs->exception_index);
            break;
    }
}