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); } }
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(); } }
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); }
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); } } }
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); }
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); }
/* 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); }
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); }
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); }
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); } }
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); } }
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; } }
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); }
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; }