Exemple #1
0
static void cg3_update_display(void *opaque)
{
    CG3State *s = opaque;
    DisplaySurface *surface = qemu_console_surface(s->con);
    const uint8_t *pix;
    uint32_t *data;
    uint32_t dval;
    int x, y, y_start;
    unsigned int width, height;
    ram_addr_t page, page_min, page_max;

    if (surface_bits_per_pixel(surface) != 32) {
        return;
    }
    width = s->width;
    height = s->height;

    y_start = -1;
    page_min = -1;
    page_max = 0;
    page = 0;
    pix = memory_region_get_ram_ptr(&s->vram_mem);
    data = (uint32_t *)surface_data(surface);

    for (y = 0; y < height; y++) {
        int update = s->full_update;

        page = (y * width) & TARGET_PAGE_MASK;
        update |= memory_region_get_dirty(&s->vram_mem, page, page + width,
                                          DIRTY_MEMORY_VGA);
        if (update) {
            if (y_start < 0) {
                y_start = y;
            }
            if (page < page_min) {
                page_min = page;
            }
            if (page > page_max) {
                page_max = page;
            }

            for (x = 0; x < width; x++) {
                dval = *pix++;
                dval = (s->r[dval] << 16) | (s->g[dval] << 8) | s->b[dval];
                *data++ = dval;
            }
        } else {
            if (y_start >= 0) {
                dpy_gfx_update(s->con, 0, y_start, s->width, y - y_start);
                y_start = -1;
            }
            pix += width;
            data += width;
        }
    }
    s->full_update = 0;
    if (y_start >= 0) {
        dpy_gfx_update(s->con, 0, y_start, s->width, y - y_start);
    }
    if (page_max >= page_min) {
        memory_region_reset_dirty(&s->vram_mem,
                              page_min, page_max - page_min + TARGET_PAGE_SIZE,
                              DIRTY_MEMORY_VGA);
    }
    /* vsync interrupt? */
    if (s->regs[0] & CG3_CR_ENABLE_INTS) {
        s->regs[1] |= CG3_SR_PENDING_INT;
        qemu_irq_raise(s->irq);
    }
}
Exemple #2
0
static void kvm_set_phys_mem(MemoryRegionSection *section, bool add)
{
    KVMState *s = kvm_state;
    KVMSlot *mem, old;
    int err;
    MemoryRegion *mr = section->mr;
    bool log_dirty = memory_region_is_logging(mr);
    target_phys_addr_t start_addr = section->offset_within_address_space;
    ram_addr_t size = section->size;
    void *ram = NULL;

    /* kvm works in page size chunks, but the function may be called
       with sub-page size and unaligned start address. */
    size = TARGET_PAGE_ALIGN(size);
    start_addr = TARGET_PAGE_ALIGN(start_addr);

    if (!memory_region_is_ram(mr)) {
        return;
    }

    ram = memory_region_get_ram_ptr(mr) + section->offset_within_region;

    while (1) {
        mem = kvm_lookup_overlapping_slot(s, start_addr, start_addr + size);
        if (!mem) {
            break;
        }

        if (add && start_addr >= mem->start_addr &&
            (start_addr + size <= mem->start_addr + mem->memory_size) &&
            (ram - start_addr == mem->ram - mem->start_addr)) {
            /* The new slot fits into the existing one and comes with
             * identical parameters - update flags and done. */
            kvm_slot_dirty_pages_log_change(mem, log_dirty);
            return;
        }

        old = *mem;

        if (mem->flags & KVM_MEM_LOG_DIRTY_PAGES) {
            kvm_physical_sync_dirty_bitmap(section);
        }

        /* unregister the overlapping slot */
        mem->memory_size = 0;
        err = kvm_set_user_memory_region(s, mem);
        if (err) {
            fprintf(stderr, "%s: error unregistering overlapping slot: %s\n",
                    __func__, strerror(-err));
            abort();
        }

        /* Workaround for older KVM versions: we can't join slots, even not by
         * unregistering the previous ones and then registering the larger
         * slot. We have to maintain the existing fragmentation. Sigh.
         *
         * This workaround assumes that the new slot starts at the same
         * address as the first existing one. If not or if some overlapping
         * slot comes around later, we will fail (not seen in practice so far)
         * - and actually require a recent KVM version. */
        if (s->broken_set_mem_region &&
            old.start_addr == start_addr && old.memory_size < size && add) {
            mem = kvm_alloc_slot(s);
            mem->memory_size = old.memory_size;
            mem->start_addr = old.start_addr;
            mem->ram = old.ram;
            mem->flags = kvm_mem_flags(s, log_dirty);

            err = kvm_set_user_memory_region(s, mem);
            if (err) {
                fprintf(stderr, "%s: error updating slot: %s\n", __func__,
                        strerror(-err));
                abort();
            }

            start_addr += old.memory_size;
            ram += old.memory_size;
            size -= old.memory_size;
            continue;
        }

        /* register prefix slot */
        if (old.start_addr < start_addr) {
            mem = kvm_alloc_slot(s);
            mem->memory_size = start_addr - old.start_addr;
            mem->start_addr = old.start_addr;
            mem->ram = old.ram;
            mem->flags =  kvm_mem_flags(s, log_dirty);

            err = kvm_set_user_memory_region(s, mem);
            if (err) {
                fprintf(stderr, "%s: error registering prefix slot: %s\n",
                        __func__, strerror(-err));
#ifdef TARGET_PPC
                fprintf(stderr, "%s: This is probably because your kernel's " \
                                "PAGE_SIZE is too big. Please try to use 4k " \
                                "PAGE_SIZE!\n", __func__);
#endif
                abort();
            }
        }

        /* register suffix slot */
        if (old.start_addr + old.memory_size > start_addr + size) {
            ram_addr_t size_delta;

            mem = kvm_alloc_slot(s);
            mem->start_addr = start_addr + size;
            size_delta = mem->start_addr - old.start_addr;
            mem->memory_size = old.memory_size - size_delta;
            mem->ram = old.ram + size_delta;
            mem->flags = kvm_mem_flags(s, log_dirty);

            err = kvm_set_user_memory_region(s, mem);
            if (err) {
                fprintf(stderr, "%s: error registering suffix slot: %s\n",
                        __func__, strerror(-err));
                abort();
            }
        }
    }

    /* in case the KVM bug workaround already "consumed" the new slot */
    if (!size) {
        return;
    }
    if (!add) {
        return;
    }
    mem = kvm_alloc_slot(s);
    mem->memory_size = size;
    mem->start_addr = start_addr;
    mem->ram = ram;
    mem->flags = kvm_mem_flags(s, log_dirty);

    err = kvm_set_user_memory_region(s, mem);
    if (err) {
        fprintf(stderr, "%s: error registering slot: %s\n", __func__,
                strerror(-err));
        abort();
    }
}
Exemple #3
0
static void riscv_board_init(QEMUMachineInitArgs *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;
#ifdef CONFIG_RISCV_HTIF
    DriveInfo *htifbd_drive;
    char *htifbd_fname; // htif block device filename
#endif

    DeviceState *dev = qdev_create(NULL, TYPE_RISCV_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 = "riscv-generic";
    }

    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_board.ram", ram_size);
    vmstate_register_ram_global(main_mem);
    memory_region_add_subregion(system_memory, 0x0, main_mem);

    if (kernel_filename) {
        /* Write a small bootloader to the flash location. */
        loaderparams.ram_size = ram_size;
        loaderparams.kernel_filename = kernel_filename;
        loaderparams.kernel_cmdline = kernel_cmdline;
        loaderparams.initrd_filename = initrd_filename;
        load_kernel();
    }

    // write memory amount in MiB to 0x0
    stl_p(memory_region_get_ram_ptr(main_mem), loaderparams.ram_size >> 20);

#ifdef CONFIG_RISCV_HTIF
    serial_mm_init(system_memory, 0x3f8, 0, env->irq[4], 1843200/16, serial_hds[0],
        DEVICE_NATIVE_ENDIAN);

    // setup HTIF Block Device if one is specified as -hda FILENAME
    htifbd_drive = drive_get_by_index(IF_IDE, 0);
    if (NULL == htifbd_drive) {
        htifbd_fname = NULL;
    } else {
        htifbd_fname = (*(htifbd_drive->bdrv)).filename;
    }

    // add htif device 0x400 - 0x410
    htif_mm_init(system_memory, 0x400, env->irq[0], main_mem, htifbd_fname);
#else
    // add serial device 0x3f8-0x3ff
    serial_mm_init(system_memory, 0x3f8, 0, env->irq[1], 1843200/16, serial_hds[0],
        DEVICE_NATIVE_ENDIAN);

    /* Create MMIO transports, to which virtio backends created by the
     * user are automatically connected as needed.  If no backend is
     * present, the transport simply remains harmlessly idle.
     * Each memory-mapped region is 0x200 bytes in size.
     */
    sysbus_create_simple("virtio-mmio", 0x400, env->irq[2]);
    sysbus_create_simple("virtio-mmio", 0x600, env->irq[3]);
    sysbus_create_simple("virtio-mmio", 0x800, env->irq[4]);
#endif

    /* Init internal devices */
    cpu_riscv_irq_init_cpu(env);
    cpu_riscv_clock_init(env);
}
Exemple #4
0
static void
host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
{
    HostMemoryBackend *backend = MEMORY_BACKEND(uc);
    HostMemoryBackendClass *bc = MEMORY_BACKEND_GET_CLASS(uc);
    Error *local_err = NULL;
    void *ptr;
    uint64_t sz;

    if (bc->alloc) {
        bc->alloc(backend, &local_err);
        if (local_err) {
            error_propagate(errp, local_err);
            return;
        }

        ptr = memory_region_get_ram_ptr(&backend->mr);
        sz = memory_region_size(&backend->mr);

        if (backend->merge) {
            qemu_madvise(ptr, sz, QEMU_MADV_MERGEABLE);
        }
        if (!backend->dump) {
            qemu_madvise(ptr, sz, QEMU_MADV_DONTDUMP);
        }
#ifdef CONFIG_NUMA
        unsigned long lastbit = find_last_bit(backend->host_nodes, MAX_NODES);
        /* lastbit == MAX_NODES means maxnode = 0 */
        unsigned long maxnode = (lastbit + 1) % (MAX_NODES + 1);
        /* ensure policy won't be ignored in case memory is preallocated
         * before mbind(). note: MPOL_MF_STRICT is ignored on hugepages so
         * this doesn't catch hugepage case. */
        unsigned flags = MPOL_MF_STRICT | MPOL_MF_MOVE;

        /* check for invalid host-nodes and policies and give more verbose
         * error messages than mbind(). */
        if (maxnode && backend->policy == MPOL_DEFAULT) {
            error_setg(errp, "host-nodes must be empty for policy default,"
                       " or you should explicitly specify a policy other"
                       " than default");
            return;
        } else if (maxnode == 0 && backend->policy != MPOL_DEFAULT) {
            error_setg(errp, "host-nodes must be set for policy %s",
                       HostMemPolicy_lookup[backend->policy]);
            return;
        }

        /* We can have up to MAX_NODES nodes, but we need to pass maxnode+1
         * as argument to mbind() due to an old Linux bug (feature?) which
         * cuts off the last specified node. This means backend->host_nodes
         * must have MAX_NODES+1 bits available.
         */
        assert(sizeof(backend->host_nodes) >=
               BITS_TO_LONGS(MAX_NODES + 1) * sizeof(unsigned long));
        assert(maxnode <= MAX_NODES);
        if (mbind(ptr, sz, backend->policy,
                  maxnode ? backend->host_nodes : NULL, maxnode + 1, flags)) {
            error_setg_errno(errp, errno,
                             "cannot bind memory to host NUMA nodes");
            return;
        }
#endif
        /* Preallocate memory after the NUMA policy has been instantiated.
         * This is necessary to guarantee memory is allocated with
         * specified NUMA policy in place.
         */
        if (backend->prealloc) {
            os_mem_prealloc(memory_region_get_fd(&backend->mr), ptr, sz);
        }
    }
}
Exemple #5
0
static void *vfio_prereg_gpa_to_vaddr(MemoryRegionSection *section, hwaddr gpa)
{
    return memory_region_get_ram_ptr(section->mr) +
        section->offset_within_region +
        (gpa - section->offset_within_address_space);
}
Exemple #6
0
static void cg3_update_display(void *opaque)
{
    CG3State *s = opaque;
    DisplaySurface *surface = qemu_console_surface(s->con);
    const uint8_t *pix;
    uint32_t *data;
    uint32_t dval;
    int x, y, y_start;
    unsigned int width, height;
    ram_addr_t page;
    DirtyBitmapSnapshot *snap = NULL;

    if (surface_bits_per_pixel(surface) != 32) {
        return;
    }
    width = s->width;
    height = s->height;

    y_start = -1;
    pix = memory_region_get_ram_ptr(&s->vram_mem);
    data = (uint32_t *)surface_data(surface);

    if (!s->full_update) {
        snap = memory_region_snapshot_and_clear_dirty(&s->vram_mem, 0x0,
                                              memory_region_size(&s->vram_mem),
                                              DIRTY_MEMORY_VGA);
    }

    for (y = 0; y < height; y++) {
        int update;

        page = (ram_addr_t)y * width;

        if (s->full_update) {
            update = 1;
        } else {
            update = memory_region_snapshot_get_dirty(&s->vram_mem, snap, page,
                                                      width);
        }

        if (update) {
            if (y_start < 0) {
                y_start = y;
            }

            for (x = 0; x < width; x++) {
                dval = *pix++;
                dval = (s->r[dval] << 16) | (s->g[dval] << 8) | s->b[dval];
                *data++ = dval;
            }
        } else {
            if (y_start >= 0) {
                dpy_gfx_update(s->con, 0, y_start, width, y - y_start);
                y_start = -1;
            }
            pix += width;
            data += width;
        }
    }
    s->full_update = 0;
    if (y_start >= 0) {
        dpy_gfx_update(s->con, 0, y_start, width, y - y_start);
    }
    /* vsync interrupt? */
    if (s->regs[0] & CG3_CR_ENABLE_INTS) {
        s->regs[1] |= CG3_SR_PENDING_INT;
        qemu_irq_raise(s->irq);
    }
    g_free(snap);
}
Exemple #7
0
/* Add a new TLB entry. At most one entry for a given virtual address
 * is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the
 * supplied size is only used by tlb_flush_page.
 *
 * Called from TCG-generated code, which is under an RCU read-side
 * critical section.
 */
void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
                             hwaddr paddr, MemTxAttrs attrs, int prot,
                             int mmu_idx, target_ulong size)
{
    CPUArchState *env = cpu->env_ptr;
    MemoryRegionSection *section;
    unsigned int index;
    target_ulong address;
    target_ulong code_address;
    uintptr_t addend;
    CPUTLBEntry *te, tn;
    hwaddr iotlb, xlat, sz, paddr_page;
    target_ulong vaddr_page;
    int asidx = cpu_asidx_from_attrs(cpu, attrs);

    assert_cpu_is_self(cpu);

    if (size <= TARGET_PAGE_SIZE) {
        sz = TARGET_PAGE_SIZE;
    } else {
        tlb_add_large_page(env, mmu_idx, vaddr, size);
        sz = size;
    }
    vaddr_page = vaddr & TARGET_PAGE_MASK;
    paddr_page = paddr & TARGET_PAGE_MASK;

    section = address_space_translate_for_iotlb(cpu, asidx, paddr_page,
                                                &xlat, &sz, attrs, &prot);
    assert(sz >= TARGET_PAGE_SIZE);

    tlb_debug("vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx
              " prot=%x idx=%d\n",
              vaddr, paddr, prot, mmu_idx);

    address = vaddr_page;
    if (size < TARGET_PAGE_SIZE) {
        /*
         * Slow-path the TLB entries; we will repeat the MMU check and TLB
         * fill on every access.
         */
        address |= TLB_RECHECK;
    }
    if (!memory_region_is_ram(section->mr) &&
        !memory_region_is_romd(section->mr)) {
        /* IO memory case */
        address |= TLB_MMIO;
        addend = 0;
    } else {
        /* TLB_MMIO for rom/romd handled below */
        addend = (uintptr_t)memory_region_get_ram_ptr(section->mr) + xlat;
    }

    code_address = address;
    iotlb = memory_region_section_get_iotlb(cpu, section, vaddr_page,
                                            paddr_page, xlat, prot, &address);

    index = tlb_index(env, mmu_idx, vaddr_page);
    te = tlb_entry(env, mmu_idx, vaddr_page);

    /*
     * Hold the TLB lock for the rest of the function. We could acquire/release
     * the lock several times in the function, but it is faster to amortize the
     * acquisition cost by acquiring it just once. Note that this leads to
     * a longer critical section, but this is not a concern since the TLB lock
     * is unlikely to be contended.
     */
    qemu_spin_lock(&env->tlb_c.lock);

    /* Note that the tlb is no longer clean.  */
    env->tlb_c.dirty |= 1 << mmu_idx;

    /* Make sure there's no cached translation for the new page.  */
    tlb_flush_vtlb_page_locked(env, mmu_idx, vaddr_page);

    /*
     * Only evict the old entry to the victim tlb if it's for a
     * different page; otherwise just overwrite the stale data.
     */
    if (!tlb_hit_page_anyprot(te, vaddr_page) && !tlb_entry_is_empty(te)) {
        unsigned vidx = env->tlb_d[mmu_idx].vindex++ % CPU_VTLB_SIZE;
        CPUTLBEntry *tv = &env->tlb_v_table[mmu_idx][vidx];

        /* Evict the old entry into the victim tlb.  */
        copy_tlb_helper_locked(tv, te);
        env->iotlb_v[mmu_idx][vidx] = env->iotlb[mmu_idx][index];
        tlb_n_used_entries_dec(env, mmu_idx);
    }

    /* refill the tlb */
    /*
     * At this point iotlb contains a physical section number in the lower
     * TARGET_PAGE_BITS, and either
     *  + the ram_addr_t of the page base of the target RAM (if NOTDIRTY or ROM)
     *  + the offset within section->mr of the page base (otherwise)
     * We subtract the vaddr_page (which is page aligned and thus won't
     * disturb the low bits) to give an offset which can be added to the
     * (non-page-aligned) vaddr of the eventual memory access to get
     * the MemoryRegion offset for the access. Note that the vaddr we
     * subtract here is that of the page base, and not the same as the
     * vaddr we add back in io_readx()/io_writex()/get_page_addr_code().
     */
    env->iotlb[mmu_idx][index].addr = iotlb - vaddr_page;
    env->iotlb[mmu_idx][index].attrs = attrs;

    /* Now calculate the new entry */
    tn.addend = addend - vaddr_page;
    if (prot & PAGE_READ) {
        tn.addr_read = address;
    } else {
        tn.addr_read = -1;
    }

    if (prot & PAGE_EXEC) {
        tn.addr_code = code_address;
    } else {
        tn.addr_code = -1;
    }

    tn.addr_write = -1;
    if (prot & PAGE_WRITE) {
        if ((memory_region_is_ram(section->mr) && section->readonly)
            || memory_region_is_romd(section->mr)) {
            /* Write access calls the I/O callback.  */
            tn.addr_write = address | TLB_MMIO;
        } else if (memory_region_is_ram(section->mr)
                   && cpu_physical_memory_is_clean(
                       memory_region_get_ram_addr(section->mr) + xlat)) {
            tn.addr_write = address | TLB_NOTDIRTY;
        } else {
            tn.addr_write = address;
        }
        if (prot & PAGE_WRITE_INV) {
            tn.addr_write |= TLB_INVALID_MASK;
        }
    }

    copy_tlb_helper_locked(te, &tn);
    tlb_n_used_entries_inc(env, mmu_idx);
    qemu_spin_unlock(&env->tlb_c.lock);
}
Exemple #8
0
static void tcx_realizefn(DeviceState *dev, Error **errp)
{
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
    TCXState *s = TCX(dev);
    ram_addr_t vram_offset = 0;
    int size, ret;
    uint8_t *vram_base;
    char *fcode_filename;

    memory_region_init_ram(&s->vram_mem, OBJECT(s), "tcx.vram",
                           s->vram_size * (1 + 4 + 4), &error_abort);
    vmstate_register_ram_global(&s->vram_mem);
    vram_base = memory_region_get_ram_ptr(&s->vram_mem);

    /* FCode ROM */
    vmstate_register_ram_global(&s->rom);
    fcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, TCX_ROM_FILE);
    if (fcode_filename) {
        ret = load_image_targphys(fcode_filename, s->prom_addr,
                                  FCODE_MAX_ROM_SIZE);
        if (ret < 0 || ret > FCODE_MAX_ROM_SIZE) {
            error_report("tcx: could not load prom '%s'", TCX_ROM_FILE);
        }
    }

    /* 8-bit plane */
    s->vram = vram_base;
    size = s->vram_size;
    memory_region_init_alias(&s->vram_8bit, OBJECT(s), "tcx.vram.8bit",
                             &s->vram_mem, vram_offset, size);
    sysbus_init_mmio(sbd, &s->vram_8bit);
    vram_offset += size;
    vram_base += size;

    if (s->depth == 24) {
        /* 24-bit plane */
        size = s->vram_size * 4;
        s->vram24 = (uint32_t *)vram_base;
        s->vram24_offset = vram_offset;
        memory_region_init_alias(&s->vram_24bit, OBJECT(s), "tcx.vram.24bit",
                                 &s->vram_mem, vram_offset, size);
        sysbus_init_mmio(sbd, &s->vram_24bit);
        vram_offset += size;
        vram_base += size;

        /* Control plane */
        size = s->vram_size * 4;
        s->cplane = (uint32_t *)vram_base;
        s->cplane_offset = vram_offset;
        memory_region_init_alias(&s->vram_cplane, OBJECT(s), "tcx.vram.cplane",
                                 &s->vram_mem, vram_offset, size);
        sysbus_init_mmio(sbd, &s->vram_cplane);

        s->con = graphic_console_init(DEVICE(dev), 0, &tcx24_ops, s);
    } else {
        /* THC 8 bit (dummy) */
        memory_region_init_io(&s->thc8, OBJECT(s), &dummy_ops, s, "tcx.thc8",
                              TCX_THC_NREGS_8);
        sysbus_init_mmio(sbd, &s->thc8);

        s->con = graphic_console_init(DEVICE(dev), 0, &tcx_ops, s);
    }

    qemu_console_resize(s->con, s->width, s->height);
}
Exemple #9
0
static void mips_jazz_init(MemoryRegion *address_space,
                           MemoryRegion *address_space_io,
                           ram_addr_t ram_size,
                           const char *cpu_model,
                           enum jazz_model_e jazz_model)
{
    char *filename;
    int bios_size, n;
    MIPSCPU *cpu;
    CPUMIPSState *env;
    qemu_irq *rc4030, *i8259;
    rc4030_dma *dmas;
    void* rc4030_opaque;
    MemoryRegion *rtc = g_new(MemoryRegion, 1);
    MemoryRegion *i8042 = g_new(MemoryRegion, 1);
    MemoryRegion *dma_dummy = g_new(MemoryRegion, 1);
    NICInfo *nd;
    DeviceState *dev;
    SysBusDevice *sysbus;
    ISABus *isa_bus;
    ISADevice *pit;
    DriveInfo *fds[MAX_FD];
    qemu_irq esp_reset, dma_enable;
    qemu_irq *cpu_exit_irq;
    MemoryRegion *ram = g_new(MemoryRegion, 1);
    MemoryRegion *bios = g_new(MemoryRegion, 1);
    MemoryRegion *bios2 = g_new(MemoryRegion, 1);

    /* init CPUs */
    if (cpu_model == NULL) {
#ifdef TARGET_MIPS64
        cpu_model = "R4000";
#else
        /* FIXME: All wrong, this maybe should be R3000 for the older JAZZs. */
        cpu_model = "24Kf";
#endif
    }
    cpu = cpu_mips_init(cpu_model);
    if (cpu == NULL) {
        fprintf(stderr, "Unable to find CPU definition\n");
        exit(1);
    }
    env = &cpu->env;
    qemu_register_reset(main_cpu_reset, cpu);

    /* allocate RAM */
    memory_region_init_ram(ram, NULL, "mips_jazz.ram", ram_size);
    vmstate_register_ram_global(ram);
    memory_region_add_subregion(address_space, 0, ram);

    memory_region_init_ram(bios, NULL, "mips_jazz.bios", MAGNUM_BIOS_SIZE);
    vmstate_register_ram_global(bios);
    memory_region_set_readonly(bios, true);
    memory_region_init_alias(bios2, NULL, "mips_jazz.bios", bios,
                             0, MAGNUM_BIOS_SIZE);
    memory_region_add_subregion(address_space, 0x1fc00000LL, bios);
    memory_region_add_subregion(address_space, 0xfff00000LL, bios2);

    /* load the BIOS image. */
    if (bios_name == NULL)
        bios_name = BIOS_FILENAME;
    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
    if (filename) {
        bios_size = load_image_targphys(filename, 0xfff00000LL,
                                        MAGNUM_BIOS_SIZE);
        g_free(filename);
    } else {
        bios_size = -1;
    }
    if (bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) {
        fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n",
                bios_name);
        exit(1);
    }

    /* Init CPU internal devices */
    cpu_mips_irq_init_cpu(env);
    cpu_mips_clock_init(env);

    /* Chipset */
    rc4030_opaque = rc4030_init(env->irq[6], env->irq[3], &rc4030, &dmas,
                                address_space);
    memory_region_init_io(dma_dummy, NULL, &dma_dummy_ops, NULL, "dummy_dma", 0x1000);
    memory_region_add_subregion(address_space, 0x8000d000, dma_dummy);

    /* ISA devices */
    isa_bus = isa_bus_new(NULL, address_space_io);
    i8259 = i8259_init(isa_bus, env->irq[4]);
    isa_bus_irqs(isa_bus, i8259);
    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
    DMA_init(0, cpu_exit_irq);
    pit = pit_init(isa_bus, 0x40, 0, NULL);
    pcspk_init(isa_bus, pit);

    /* ISA IO space at 0x90000000 */
    isa_mmio_init(0x90000000, 0x01000000);
    isa_mem_base = 0x11000000;

    /* Video card */
    switch (jazz_model) {
    case JAZZ_MAGNUM:
        dev = qdev_create(NULL, "sysbus-g364");
        qdev_init_nofail(dev);
        sysbus = SYS_BUS_DEVICE(dev);
        sysbus_mmio_map(sysbus, 0, 0x60080000);
        sysbus_mmio_map(sysbus, 1, 0x40000000);
        sysbus_connect_irq(sysbus, 0, rc4030[3]);
        {
            /* Simple ROM, so user doesn't have to provide one */
            MemoryRegion *rom_mr = g_new(MemoryRegion, 1);
            memory_region_init_ram(rom_mr, NULL, "g364fb.rom", 0x80000);
            vmstate_register_ram_global(rom_mr);
            memory_region_set_readonly(rom_mr, true);
            uint8_t *rom = memory_region_get_ram_ptr(rom_mr);
            memory_region_add_subregion(address_space, 0x60000000, rom_mr);
            rom[0] = 0x10; /* Mips G364 */
        }
        break;
    case JAZZ_PICA61:
        isa_vga_mm_init(0x40000000, 0x60000000, 0, get_system_memory());
        break;
    default:
        break;
    }

    /* Network controller */
    for (n = 0; n < nb_nics; n++) {
        nd = &nd_table[n];
        if (!nd->model)
            nd->model = g_strdup("dp83932");
        if (strcmp(nd->model, "dp83932") == 0) {
            dp83932_init(nd, 0x80001000, 2, get_system_memory(), rc4030[4],
                         rc4030_opaque, rc4030_dma_memory_rw);
            break;
        } else if (is_help_option(nd->model)) {
            fprintf(stderr, "qemu: Supported NICs: dp83932\n");
            exit(1);
        } else {
            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
            exit(1);
        }
    }

    /* SCSI adapter */
    esp_init(0x80002000, 0,
             rc4030_dma_read, rc4030_dma_write, dmas[0],
             rc4030[5], &esp_reset, &dma_enable);

    /* Floppy */
    if (drive_get_max_bus(IF_FLOPPY) >= MAX_FD) {
        fprintf(stderr, "qemu: too many floppy drives\n");
        exit(1);
    }
    for (n = 0; n < MAX_FD; n++) {
        fds[n] = drive_get(IF_FLOPPY, 0, n);
    }
    fdctrl_init_sysbus(rc4030[1], 0, 0x80003000, fds);

    /* Real time clock */
    rtc_init(isa_bus, 1980, NULL);
    memory_region_init_io(rtc, NULL, &rtc_ops, NULL, "rtc", 0x1000);
    memory_region_add_subregion(address_space, 0x80004000, rtc);

    /* Keyboard (i8042) */
    i8042_mm_init(rc4030[6], rc4030[7], i8042, 0x1000, 0x1);
    memory_region_add_subregion(address_space, 0x80005000, i8042);

    /* Serial ports */
    if (serial_hds[0]) {
        serial_mm_init(address_space, 0x80006000, 0, rc4030[8], 8000000/16,
                       serial_hds[0], DEVICE_NATIVE_ENDIAN);
    }
    if (serial_hds[1]) {
        serial_mm_init(address_space, 0x80007000, 0, rc4030[9], 8000000/16,
                       serial_hds[1], DEVICE_NATIVE_ENDIAN);
    }

    /* Parallel port */
    if (parallel_hds[0])
        parallel_mm_init(address_space, 0x80008000, 0, rc4030[0],
                         parallel_hds[0]);

    /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */

    /* NVRAM */
    dev = qdev_create(NULL, "ds1225y");
    qdev_init_nofail(dev);
    sysbus = SYS_BUS_DEVICE(dev);
    sysbus_mmio_map(sysbus, 0, 0x80009000);

    /* LED indicator */
    sysbus_create_simple("jazz-led", 0x8000f000, NULL);
}
Exemple #10
0
static void boston_mach_init(MachineState *machine)
{
    DeviceState *dev;
    BostonState *s;
    Error *err = NULL;
    MemoryRegion *flash, *ddr, *ddr_low_alias, *lcd, *platreg;
    MemoryRegion *sys_mem = get_system_memory();
    XilinxPCIEHost *pcie2;
    PCIDevice *ahci;
    DriveInfo *hd[6];
    Chardev *chr;
    int fw_size, fit_err;
    bool is_64b;

    if ((machine->ram_size % GiB) ||
        (machine->ram_size > (2 * GiB))) {
        error_report("Memory size must be 1GB or 2GB");
        exit(1);
    }

    dev = qdev_create(NULL, TYPE_MIPS_BOSTON);
    qdev_init_nofail(dev);

    s = BOSTON(dev);
    s->mach = machine;

    if (!cpu_supports_cps_smp(machine->cpu_type)) {
        error_report("Boston requires CPUs which support CPS");
        exit(1);
    }

    is_64b = cpu_supports_isa(machine->cpu_type, ISA_MIPS64);

    sysbus_init_child_obj(OBJECT(machine), "cps", OBJECT(&s->cps),
                          sizeof(s->cps), TYPE_MIPS_CPS);
    object_property_set_str(OBJECT(&s->cps), machine->cpu_type, "cpu-type",
                            &err);
    object_property_set_int(OBJECT(&s->cps), smp_cpus, "num-vp", &err);
    object_property_set_bool(OBJECT(&s->cps), true, "realized", &err);

    if (err != NULL) {
        error_report("%s", error_get_pretty(err));
        exit(1);
    }

    sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->cps), 0, 0, 1);

    flash =  g_new(MemoryRegion, 1);
    memory_region_init_rom(flash, NULL, "boston.flash", 128 * MiB, &err);
    memory_region_add_subregion_overlap(sys_mem, 0x18000000, flash, 0);

    ddr = g_new(MemoryRegion, 1);
    memory_region_allocate_system_memory(ddr, NULL, "boston.ddr",
                                         machine->ram_size);
    memory_region_add_subregion_overlap(sys_mem, 0x80000000, ddr, 0);

    ddr_low_alias = g_new(MemoryRegion, 1);
    memory_region_init_alias(ddr_low_alias, NULL, "boston_low.ddr",
                             ddr, 0, MIN(machine->ram_size, (256 * MiB)));
    memory_region_add_subregion_overlap(sys_mem, 0, ddr_low_alias, 0);

    xilinx_pcie_init(sys_mem, 0,
                     0x10000000, 32 * MiB,
                     0x40000000, 1 * GiB,
                     get_cps_irq(&s->cps, 2), false);

    xilinx_pcie_init(sys_mem, 1,
                     0x12000000, 32 * MiB,
                     0x20000000, 512 * MiB,
                     get_cps_irq(&s->cps, 1), false);

    pcie2 = xilinx_pcie_init(sys_mem, 2,
                             0x14000000, 32 * MiB,
                             0x16000000, 1 * MiB,
                             get_cps_irq(&s->cps, 0), true);

    platreg = g_new(MemoryRegion, 1);
    memory_region_init_io(platreg, NULL, &boston_platreg_ops, s,
                          "boston-platregs", 0x1000);
    memory_region_add_subregion_overlap(sys_mem, 0x17ffd000, platreg, 0);

    s->uart = serial_mm_init(sys_mem, 0x17ffe000, 2,
                             get_cps_irq(&s->cps, 3), 10000000,
                             serial_hd(0), DEVICE_NATIVE_ENDIAN);

    lcd = g_new(MemoryRegion, 1);
    memory_region_init_io(lcd, NULL, &boston_lcd_ops, s, "boston-lcd", 0x8);
    memory_region_add_subregion_overlap(sys_mem, 0x17fff000, lcd, 0);

    chr = qemu_chr_new("lcd", "vc:320x240", NULL);
    qemu_chr_fe_init(&s->lcd_display, chr, NULL);
    qemu_chr_fe_set_handlers(&s->lcd_display, NULL, NULL,
                             boston_lcd_event, NULL, s, NULL, true);

    ahci = pci_create_simple_multifunction(&PCI_BRIDGE(&pcie2->root)->sec_bus,
                                           PCI_DEVFN(0, 0),
                                           true, TYPE_ICH9_AHCI);
    g_assert(ARRAY_SIZE(hd) == ahci_get_num_ports(ahci));
    ide_drive_get(hd, ahci_get_num_ports(ahci));
    ahci_ide_create_devs(ahci, hd);

    if (machine->firmware) {
        fw_size = load_image_targphys(machine->firmware,
                                      0x1fc00000, 4 * MiB);
        if (fw_size == -1) {
            error_report("unable to load firmware image '%s'",
                          machine->firmware);
            exit(1);
        }
    } else if (machine->kernel_filename) {
        fit_err = load_fit(&boston_fit_loader, machine->kernel_filename, s);
        if (fit_err) {
            error_report("unable to load FIT image");
            exit(1);
        }

        gen_firmware(memory_region_get_ram_ptr(flash) + 0x7c00000,
                     s->kernel_entry, s->fdt_base, is_64b);
    } else if (!qtest_enabled()) {
        error_report("Please provide either a -kernel or -bios argument");
        exit(1);
    }
}
Exemple #11
0
void qxl_render_update(PCIQXLDevice *qxl)
{
    VGACommonState *vga = &qxl->vga;
    QXLRect dirty[32], update;
    void *ptr;
    int i, redraw = 0;

    if (!is_buffer_shared(vga->ds->surface)) {
        dprint(qxl, 1, "%s: restoring shared displaysurface\n", __func__);
        qxl->guest_primary.resized++;
        qxl->guest_primary.commands++;
        redraw = 1;
    }

    if (qxl->guest_primary.resized) {
        qxl->guest_primary.resized = 0;

        if (qxl->guest_primary.flipped) {
            g_free(qxl->guest_primary.flipped);
            qxl->guest_primary.flipped = NULL;
        }
        qemu_free_displaysurface(vga->ds);

        qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
        if (qxl->guest_primary.qxl_stride < 0) {
            /* spice surface is upside down -> need extra buffer to flip */
            qxl->guest_primary.flipped =
                g_malloc(qxl->guest_primary.surface.width *
                         qxl->guest_primary.abs_stride);
            ptr = qxl->guest_primary.flipped;
        } else {
            ptr = qxl->guest_primary.data;
        }
        dprint(qxl, 1, "%s: %dx%d, stride %d, bpp %d, depth %d, flip %s\n",
               __FUNCTION__,
               qxl->guest_primary.surface.width,
               qxl->guest_primary.surface.height,
               qxl->guest_primary.qxl_stride,
               qxl->guest_primary.bytes_pp,
               qxl->guest_primary.bits_pp,
               qxl->guest_primary.flipped ? "yes" : "no");
        vga->ds->surface =
            qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
                                            qxl->guest_primary.surface.height,
                                            qxl->guest_primary.bits_pp,
                                            qxl->guest_primary.abs_stride,
                                            ptr);
        dpy_resize(vga->ds);
    }

    if (!qxl->guest_primary.commands) {
        return;
    }
    qxl->guest_primary.commands = 0;

    update.left   = 0;
    update.right  = qxl->guest_primary.surface.width;
    update.top    = 0;
    update.bottom = qxl->guest_primary.surface.height;

    memset(dirty, 0, sizeof(dirty));
    qxl_spice_update_area(qxl, 0, &update,
                          dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC);
    if (redraw) {
        memset(dirty, 0, sizeof(dirty));
        dirty[0] = update;
    }

    for (i = 0; i < ARRAY_SIZE(dirty); i++) {
        if (qemu_spice_rect_is_empty(dirty+i)) {
            break;
        }
        if (qxl->guest_primary.flipped) {
            qxl_flip(qxl, dirty+i);
        }
        dpy_update(vga->ds,
                   dirty[i].left, dirty[i].top,
                   dirty[i].right - dirty[i].left,
                   dirty[i].bottom - dirty[i].top);
    }
}
Exemple #12
0
static void balloon_inflate_page(VirtIOBalloon *balloon,
                                 MemoryRegion *mr, hwaddr offset)
{
    void *addr = memory_region_get_ram_ptr(mr) + offset;
    RAMBlock *rb;
    size_t rb_page_size;
    int subpages;
    ram_addr_t ram_offset, host_page_base;

    /* XXX is there a better way to get to the RAMBlock than via a
     * host address? */
    rb = qemu_ram_block_from_host(addr, false, &ram_offset);
    rb_page_size = qemu_ram_pagesize(rb);
    host_page_base = ram_offset & ~(rb_page_size - 1);

    if (rb_page_size == BALLOON_PAGE_SIZE) {
        /* Easy case */

        ram_block_discard_range(rb, ram_offset, rb_page_size);
        /* We ignore errors from ram_block_discard_range(), because it
         * has already reported them, and failing to discard a balloon
         * page is not fatal */
        return;
    }

    /* Hard case
     *
     * We've put a piece of a larger host page into the balloon - we
     * need to keep track until we have a whole host page to
     * discard
     */
    warn_report_once(
"Balloon used with backing page size > 4kiB, this may not be reliable");

    subpages = rb_page_size / BALLOON_PAGE_SIZE;

    if (balloon->pbp
        && (rb != balloon->pbp->rb
            || host_page_base != balloon->pbp->base)) {
        /* We've partially ballooned part of a host page, but now
         * we're trying to balloon part of a different one.  Too hard,
         * give up on the old partial page */
        free(balloon->pbp);
        balloon->pbp = NULL;
    }

    if (!balloon->pbp) {
        /* Starting on a new host page */
        size_t bitlen = BITS_TO_LONGS(subpages) * sizeof(unsigned long);
        balloon->pbp = g_malloc0(sizeof(PartiallyBalloonedPage) + bitlen);
        balloon->pbp->rb = rb;
        balloon->pbp->base = host_page_base;
    }

    bitmap_set(balloon->pbp->bitmap,
               (ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
               subpages);

    if (bitmap_full(balloon->pbp->bitmap, subpages)) {
        /* We've accumulated a full host page, we can actually discard
         * it now */

        ram_block_discard_range(rb, balloon->pbp->base, rb_page_size);
        /* We ignore errors from ram_block_discard_range(), because it
         * has already reported them, and failing to discard a balloon
         * page is not fatal */

        free(balloon->pbp);
        balloon->pbp = NULL;
    }
}
Exemple #13
0
static void old_pc_system_rom_init(MemoryRegion *rom_memory)
{
    char *filename;
    MemoryRegion *bios, *isa_bios;
    int bios_size, isa_bios_size;
    int ret;

    /* BIOS load */
    if (bios_name == NULL) {
        bios_name = BIOS_FILENAME;
    }
    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
    if (filename) {
        bios_size = get_image_size(filename);
    } else {
        bios_size = -1;
    }
    if (bios_size <= 0 ||
        (bios_size % 65536) != 0) {
        goto bios_error;
    }
    bios = g_malloc(sizeof(*bios));
    memory_region_init_ram(bios, "pc.bios", bios_size);

#ifdef CONFIG_S2E
    s2e_register_ram(g_s2e, g_s2e_state, -1, bios_size,
                     (uint64_t) memory_region_get_ram_ptr(bios), 1, 0, "pc.bios");
#endif


    vmstate_register_ram_global(bios);
    memory_region_set_readonly(bios, true);
    ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
    if (ret != 0) {
    bios_error:
        fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name);
        exit(1);
    }
    if (filename) {
        g_free(filename);
    }

    /* map the last 128KB of the BIOS in ISA space */
    isa_bios_size = bios_size;
    if (isa_bios_size > (128 * 1024)) {
        isa_bios_size = 128 * 1024;
    }
    isa_bios = g_malloc(sizeof(*isa_bios));
    memory_region_init_alias(isa_bios, "isa-bios", bios,
                             bios_size - isa_bios_size, isa_bios_size);
    memory_region_add_subregion_overlap(rom_memory,
                                        0x100000 - isa_bios_size,
                                        isa_bios,
                                        1);
    memory_region_set_readonly(isa_bios, true);

    /* map all the bios at the top of memory */
    memory_region_add_subregion(rom_memory,
                                (uint32_t)(-bios_size),
                                bios);
}
Exemple #14
0
static int tcx_init1(SysBusDevice *dev)
{
    TCXState *s = FROM_SYSBUS(TCXState, dev);
    ram_addr_t vram_offset = 0;
    int size;
    uint8_t *vram_base;

    memory_region_init_ram(&s->vram_mem, "tcx.vram",
                           s->vram_size * (1 + 4 + 4));
    vmstate_register_ram_global(&s->vram_mem);
    vram_base = memory_region_get_ram_ptr(&s->vram_mem);

    /* 8-bit plane */
    s->vram = vram_base;
    size = s->vram_size;
    memory_region_init_alias(&s->vram_8bit, "tcx.vram.8bit",
                             &s->vram_mem, vram_offset, size);
    sysbus_init_mmio(dev, &s->vram_8bit);
    vram_offset += size;
    vram_base += size;

    /* DAC */
    memory_region_init_io(&s->dac, &tcx_dac_ops, s, "tcx.dac", TCX_DAC_NREGS);
    sysbus_init_mmio(dev, &s->dac);

    /* TEC (dummy) */
    memory_region_init_io(&s->tec, &dummy_ops, s, "tcx.tec", TCX_TEC_NREGS);
    sysbus_init_mmio(dev, &s->tec);
    /* THC: NetBSD writes here even with 8-bit display: dummy */
    memory_region_init_io(&s->thc24, &dummy_ops, s, "tcx.thc24",
                          TCX_THC_NREGS_24);
    sysbus_init_mmio(dev, &s->thc24);

    if (s->depth == 24) {
        /* 24-bit plane */
        size = s->vram_size * 4;
        s->vram24 = (uint32_t *)vram_base;
        s->vram24_offset = vram_offset;
        memory_region_init_alias(&s->vram_24bit, "tcx.vram.24bit",
                                 &s->vram_mem, vram_offset, size);
        sysbus_init_mmio(dev, &s->vram_24bit);
        vram_offset += size;
        vram_base += size;

        /* Control plane */
        size = s->vram_size * 4;
        s->cplane = (uint32_t *)vram_base;
        s->cplane_offset = vram_offset;
        memory_region_init_alias(&s->vram_cplane, "tcx.vram.cplane",
                                 &s->vram_mem, vram_offset, size);
        sysbus_init_mmio(dev, &s->vram_cplane);

        s->con = graphic_console_init(&tcx24_ops, s);
    } else {
        /* THC 8 bit (dummy) */
        memory_region_init_io(&s->thc8, &dummy_ops, s, "tcx.thc8",
                              TCX_THC_NREGS_8);
        sysbus_init_mmio(dev, &s->thc8);

        s->con = graphic_console_init(&tcx_ops, s);
    }

    qemu_console_resize(s->con, s->width, s->height);
    return 0;
}