vga: convert vga and its derivatives to the memory API

Convert all vga memory to the memory API.  Note we need to fall back to
get_system_memory(), since the various buses don't pass the vga window
as a memory region.

We no longer need to sync the dirty bitmap of the cirrus mapped memory
banks, since the memory API takes care of that for us.

[jan: fix vga-pci logging]

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Avi Kivity 2011-08-08 16:08:57 +03:00 committed by Anthony Liguori
parent 7b619b9ae5
commit b195043003
10 changed files with 440 additions and 438 deletions

View File

@ -32,6 +32,7 @@
#include "console.h"
#include "vga_int.h"
#include "loader.h"
#include "exec-memory.h"
/*
* TODO:
@ -200,9 +201,14 @@ typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
typedef struct CirrusVGAState {
VGACommonState vga;
int cirrus_linear_io_addr;
int cirrus_linear_bitblt_io_addr;
int cirrus_mmio_io_addr;
MemoryRegion cirrus_linear_io;
MemoryRegion cirrus_linear_bitblt_io;
MemoryRegion cirrus_mmio_io;
MemoryRegion pci_bar;
bool linear_vram; /* vga.vram mapped over cirrus_linear_io */
MemoryRegion low_mem_container; /* container for 0xa0000-0xc0000 */
MemoryRegion low_mem; /* always mapped, overridden by: */
MemoryRegion *cirrus_bank[2]; /* aliases at 0xa0000-0xb0000 */
uint32_t cirrus_addr_mask;
uint32_t linear_mmio_mask;
uint8_t cirrus_shadow_gr0;
@ -612,7 +618,7 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask;
off_cur &= TARGET_PAGE_MASK;
while (off_cur < off_cur_end) {
cpu_physical_memory_set_dirty(s->vga.vram_offset + off_cur);
memory_region_set_dirty(&s->vga.vram, off_cur);
off_cur += TARGET_PAGE_SIZE;
}
off_begin += off_pitch;
@ -1177,12 +1183,6 @@ static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index)
}
if (limit > 0) {
/* Thinking about changing bank base? First, drop the dirty bitmap information
* on the current location, otherwise we lose this pointer forever */
if (s->vga.lfb_vram_mapped) {
target_phys_addr_t base_addr = isa_mem_base + 0xa0000 + bank_index * 0x8000;
cpu_physical_sync_dirty_bitmap(base_addr, base_addr + 0x8000);
}
s->cirrus_bank_base[bank_index] = offset;
s->cirrus_bank_limit[bank_index] = limit;
} else {
@ -1921,8 +1921,8 @@ static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
val <<= 1;
dst++;
}
cpu_physical_memory_set_dirty(s->vga.vram_offset + offset);
cpu_physical_memory_set_dirty(s->vga.vram_offset + offset + 7);
memory_region_set_dirty(&s->vga.vram, offset);
memory_region_set_dirty(&s->vga.vram, offset + 7);
}
static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
@ -1946,8 +1946,8 @@ static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
val <<= 1;
dst += 2;
}
cpu_physical_memory_set_dirty(s->vga.vram_offset + offset);
cpu_physical_memory_set_dirty(s->vga.vram_offset + offset + 15);
memory_region_set_dirty(&s->vga.vram, offset);
memory_region_set_dirty(&s->vga.vram, offset + 15);
}
/***************************************
@ -2057,8 +2057,7 @@ static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
mode = s->vga.gr[0x05] & 0x7;
if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) {
*(s->vga.vram_ptr + bank_offset) = mem_value;
cpu_physical_memory_set_dirty(s->vga.vram_offset +
bank_offset);
memory_region_set_dirty(&s->vga.vram, bank_offset);
} else {
if ((s->vga.gr[0x0B] & 0x14) != 0x14) {
cirrus_mem_writeb_mode4and5_8bpp(s, mode,
@ -2099,16 +2098,37 @@ static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_
cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
}
static CPUReadMemoryFunc * const cirrus_vga_mem_read[3] = {
cirrus_vga_mem_readb,
cirrus_vga_mem_readw,
cirrus_vga_mem_readl,
static uint64_t cirrus_vga_mem_read(void *opaque,
target_phys_addr_t addr,
uint32_t size)
{
CirrusVGAState *s = opaque;
switch (size) {
case 1: return cirrus_vga_mem_readb(s, addr);
case 2: return cirrus_vga_mem_readw(s, addr);
case 4: return cirrus_vga_mem_readl(s, addr);
default: abort();
}
}
static void cirrus_vga_mem_write(void *opaque, target_phys_addr_t addr,
uint64_t data, unsigned size)
{
CirrusVGAState *s = opaque;
switch (size) {
case 1: return cirrus_vga_mem_writeb(s, addr, data);
case 2: return cirrus_vga_mem_writew(s, addr, data);
case 4: return cirrus_vga_mem_writel(s, addr, data);
default: abort();
}
};
static CPUWriteMemoryFunc * const cirrus_vga_mem_write[3] = {
cirrus_vga_mem_writeb,
cirrus_vga_mem_writew,
cirrus_vga_mem_writel,
static const MemoryRegionOps cirrus_vga_mem_ops = {
.read = cirrus_vga_mem_read,
.write = cirrus_vga_mem_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
/***************************************
@ -2365,7 +2385,7 @@ static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
mode = s->vga.gr[0x05] & 0x7;
if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) {
*(s->vga.vram_ptr + addr) = (uint8_t) val;
cpu_physical_memory_set_dirty(s->vga.vram_offset + addr);
memory_region_set_dirty(&s->vga.vram, addr);
} else {
if ((s->vga.gr[0x0B] & 0x14) != 0x14) {
cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val);
@ -2393,17 +2413,31 @@ static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr,
}
static CPUReadMemoryFunc * const cirrus_linear_read[3] = {
cirrus_linear_readb,
cirrus_linear_readw,
cirrus_linear_readl,
};
static uint64_t cirrus_linear_read(void *opaque, target_phys_addr_t addr,
unsigned size)
{
CirrusVGAState *s = opaque;
static CPUWriteMemoryFunc * const cirrus_linear_write[3] = {
cirrus_linear_writeb,
cirrus_linear_writew,
cirrus_linear_writel,
};
switch (size) {
case 1: return cirrus_linear_readb(s, addr);
case 2: return cirrus_linear_readw(s, addr);
case 4: return cirrus_linear_readl(s, addr);
default: abort();
}
}
static void cirrus_linear_write(void *opaque, target_phys_addr_t addr,
uint64_t data, unsigned size)
{
CirrusVGAState *s = opaque;
switch (size) {
case 1: return cirrus_linear_writeb(s, addr, data);
case 2: return cirrus_linear_writew(s, addr, data);
case 4: return cirrus_linear_writel(s, addr, data);
default: abort();
}
}
/***************************************
*
@ -2471,67 +2505,95 @@ static void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr,
cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff);
}
static CPUReadMemoryFunc * const cirrus_linear_bitblt_read[3] = {
cirrus_linear_bitblt_readb,
cirrus_linear_bitblt_readw,
cirrus_linear_bitblt_readl,
};
static CPUWriteMemoryFunc * const cirrus_linear_bitblt_write[3] = {
cirrus_linear_bitblt_writeb,
cirrus_linear_bitblt_writew,
cirrus_linear_bitblt_writel,
};
static void map_linear_vram(CirrusVGAState *s)
static uint64_t cirrus_linear_bitblt_read(void *opaque,
target_phys_addr_t addr,
unsigned size)
{
if (!s->vga.map_addr && s->vga.lfb_addr && s->vga.lfb_end) {
s->vga.map_addr = s->vga.lfb_addr;
s->vga.map_end = s->vga.lfb_end;
cpu_register_physical_memory_log(s->vga.map_addr,
s->vga.map_end - s->vga.map_addr,
s->vga.vram_offset, 0, true);
CirrusVGAState *s = opaque;
switch (size) {
case 1: return cirrus_linear_bitblt_readb(s, addr);
case 2: return cirrus_linear_bitblt_readw(s, addr);
case 4: return cirrus_linear_bitblt_readl(s, addr);
default: abort();
}
};
if (!s->vga.map_addr)
return;
static void cirrus_linear_bitblt_write(void *opaque,
target_phys_addr_t addr,
uint64_t data,
unsigned size)
{
CirrusVGAState *s = opaque;
s->vga.lfb_vram_mapped = 0;
switch (size) {
case 1: return cirrus_linear_bitblt_writeb(s, addr, data);
case 2: return cirrus_linear_bitblt_writew(s, addr, data);
case 4: return cirrus_linear_bitblt_writel(s, addr, data);
default: abort();
}
};
static const MemoryRegionOps cirrus_linear_bitblt_io_ops = {
.read = cirrus_linear_bitblt_read,
.write = cirrus_linear_bitblt_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static void unmap_bank(CirrusVGAState *s, unsigned bank)
{
if (s->cirrus_bank[bank]) {
memory_region_del_subregion(&s->low_mem_container,
s->cirrus_bank[bank]);
memory_region_destroy(s->cirrus_bank[bank]);
qemu_free(s->cirrus_bank[bank]);
s->cirrus_bank[bank] = NULL;
}
}
static void map_linear_vram_bank(CirrusVGAState *s, unsigned bank)
{
MemoryRegion *mr;
static const char *names[] = { "vga.bank0", "vga.bank1" };
if (!(s->cirrus_srcptr != s->cirrus_srcptr_end)
&& !((s->vga.sr[0x07] & 0x01) == 0)
&& !((s->vga.gr[0x0B] & 0x14) == 0x14)
&& !(s->vga.gr[0x0B] & 0x02)) {
cpu_register_physical_memory_log(isa_mem_base + 0xa0000, 0x8000,
(s->vga.vram_offset +
s->cirrus_bank_base[0]) |
IO_MEM_RAM, 0, true);
cpu_register_physical_memory_log(isa_mem_base + 0xa8000, 0x8000,
(s->vga.vram_offset +
s->cirrus_bank_base[1]) |
IO_MEM_RAM, 0, true);
s->vga.lfb_vram_mapped = 1;
}
else {
cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x20000,
s->vga.vga_io_memory);
mr = qemu_malloc(sizeof(*mr));
memory_region_init_alias(mr, names[bank], &s->vga.vram,
s->cirrus_bank_base[bank], 0x8000);
memory_region_add_subregion_overlap(
&s->low_mem_container,
0x8000 * bank,
mr,
1);
unmap_bank(s, bank);
s->cirrus_bank[bank] = mr;
} else {
unmap_bank(s, bank);
}
}
vga_dirty_log_start(&s->vga);
static void map_linear_vram(CirrusVGAState *s)
{
if (!s->linear_vram) {
s->linear_vram = true;
memory_region_add_subregion_overlap(&s->pci_bar, 0, &s->vga.vram, 1);
}
map_linear_vram_bank(s, 0);
map_linear_vram_bank(s, 1);
}
static void unmap_linear_vram(CirrusVGAState *s)
{
if (s->vga.map_addr && s->vga.lfb_addr && s->vga.lfb_end) {
s->vga.map_addr = s->vga.map_end = 0;
cpu_register_physical_memory(s->vga.lfb_addr, s->vga.vram_size,
s->cirrus_linear_io_addr);
if (s->linear_vram) {
s->linear_vram = false;
memory_region_del_subregion(&s->pci_bar, &s->vga.vram);
}
cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x20000,
s->vga.vga_io_memory);
unmap_bank(s, 0);
unmap_bank(s, 1);
}
/* Compute the memory access functions */
@ -2829,16 +2891,36 @@ static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr,
}
static CPUReadMemoryFunc * const cirrus_mmio_read[3] = {
cirrus_mmio_readb,
cirrus_mmio_readw,
cirrus_mmio_readl,
static uint64_t cirrus_mmio_read(void *opaque, target_phys_addr_t addr,
unsigned size)
{
CirrusVGAState *s = opaque;
switch (size) {
case 1: return cirrus_mmio_readb(s, addr);
case 2: return cirrus_mmio_readw(s, addr);
case 4: return cirrus_mmio_readl(s, addr);
default: abort();
}
};
static CPUWriteMemoryFunc * const cirrus_mmio_write[3] = {
cirrus_mmio_writeb,
cirrus_mmio_writew,
cirrus_mmio_writel,
static void cirrus_mmio_write(void *opaque, target_phys_addr_t addr,
uint64_t data, unsigned size)
{
CirrusVGAState *s = opaque;
switch (size) {
case 1: return cirrus_mmio_writeb(s, addr, data);
case 2: return cirrus_mmio_writew(s, addr, data);
case 4: return cirrus_mmio_writel(s, addr, data);
default: abort();
}
};
static const MemoryRegionOps cirrus_mmio_io_ops = {
.read = cirrus_mmio_read,
.write = cirrus_mmio_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
/* load/save state */
@ -2947,6 +3029,12 @@ static void cirrus_reset(void *opaque)
s->cirrus_hidden_dac_data = 0;
}
static const MemoryRegionOps cirrus_linear_io_ops = {
.read = cirrus_linear_read,
.write = cirrus_linear_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
{
int i;
@ -2993,28 +3081,33 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
register_ioport_read(0x3ba, 1, 1, cirrus_vga_ioport_read, s);
register_ioport_read(0x3da, 1, 1, cirrus_vga_ioport_read, s);
s->vga.vga_io_memory = cpu_register_io_memory(cirrus_vga_mem_read,
cirrus_vga_mem_write, s,
DEVICE_LITTLE_ENDIAN);
cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
s->vga.vga_io_memory);
qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
memory_region_init(&s->low_mem_container,
"cirrus-lowmem-container",
0x20000);
memory_region_init_io(&s->low_mem, &cirrus_vga_mem_ops, s,
"cirrus-low-memory", 0x20000);
memory_region_add_subregion(&s->low_mem_container, 0, &s->low_mem);
memory_region_add_subregion_overlap(get_system_memory(),
isa_mem_base + 0x000a0000,
&s->low_mem_container,
1);
memory_region_set_coalescing(&s->low_mem);
/* I/O handler for LFB */
s->cirrus_linear_io_addr =
cpu_register_io_memory(cirrus_linear_read, cirrus_linear_write, s,
DEVICE_LITTLE_ENDIAN);
memory_region_init_io(&s->cirrus_linear_io, &cirrus_linear_io_ops, s,
"cirrus-linear-io", VGA_RAM_SIZE);
/* I/O handler for LFB */
s->cirrus_linear_bitblt_io_addr =
cpu_register_io_memory(cirrus_linear_bitblt_read,
cirrus_linear_bitblt_write, s,
DEVICE_LITTLE_ENDIAN);
memory_region_init_io(&s->cirrus_linear_bitblt_io,
&cirrus_linear_bitblt_io_ops,
s,
"cirrus-bitblt-mmio",
0x400000);
/* I/O handler for memory-mapped I/O */
s->cirrus_mmio_io_addr =
cpu_register_io_memory(cirrus_mmio_read, cirrus_mmio_write, s,
DEVICE_LITTLE_ENDIAN);
memory_region_init_io(&s->cirrus_mmio_io, &cirrus_mmio_io_ops, s,
"cirrus-mmio", CIRRUS_PNPMMIO_SIZE);
s->real_vram_size =
(s->device_id == CIRRUS_ID_CLGD5446) ? 4096 * 1024 : 2048 * 1024;
@ -3060,42 +3153,6 @@ void isa_cirrus_vga_init(void)
*
***************************************/
static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
CirrusVGAState *s = &DO_UPCAST(PCICirrusVGAState, dev, d)->cirrus_vga;
/* XXX: add byte swapping apertures */
cpu_register_physical_memory(addr, s->vga.vram_size,
s->cirrus_linear_io_addr);
cpu_register_physical_memory(addr + 0x1000000, 0x400000,
s->cirrus_linear_bitblt_io_addr);
s->vga.map_addr = s->vga.map_end = 0;
s->vga.lfb_addr = addr & TARGET_PAGE_MASK;
s->vga.lfb_end = ((addr + VGA_RAM_SIZE) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
/* account for overflow */
if (s->vga.lfb_end < addr + VGA_RAM_SIZE)
s->vga.lfb_end = addr + VGA_RAM_SIZE;
vga_dirty_log_start(&s->vga);
}
static void pci_cirrus_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len)
{
PCICirrusVGAState *pvs = DO_UPCAST(PCICirrusVGAState, dev, d);
CirrusVGAState *s = &pvs->cirrus_vga;
pci_default_write_config(d, address, val, len);
if (s->vga.map_addr && d->io_regions[0].addr == PCI_BAR_UNMAPPED) {
s->vga.map_addr = 0;
s->vga.lfb_addr = 0;
s->vga.lfb_end = 0;
}
cirrus_update_memory_access(s);
}
static int pci_cirrus_vga_initfn(PCIDevice *dev)
{
PCICirrusVGAState *d = DO_UPCAST(PCICirrusVGAState, dev, dev);
@ -3112,15 +3169,21 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
/* setup PCI */
memory_region_init(&s->pci_bar, "cirrus-pci-bar0", 0x2000000);
/* XXX: add byte swapping apertures */
memory_region_add_subregion(&s->pci_bar, 0, &s->cirrus_linear_io);
memory_region_add_subregion(&s->pci_bar, 0x1000000,
&s->cirrus_linear_bitblt_io);
/* setup memory space */
/* memory #0 LFB */
/* memory #1 memory-mapped I/O */
/* XXX: s->vga.vram_size must be a power of two */
pci_register_bar(&d->dev, 0, 0x2000000,
PCI_BASE_ADDRESS_MEM_PREFETCH, cirrus_pci_lfb_map);
pci_register_bar_region(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH,
&s->pci_bar);
if (device_id == CIRRUS_ID_CLGD5446) {
pci_register_bar_simple(&d->dev, 1, CIRRUS_PNPMMIO_SIZE, 0,
s->cirrus_mmio_io_addr);
pci_register_bar_region(&d->dev, 1, 0, &s->cirrus_mmio_io);
}
return 0;
}
@ -3138,7 +3201,6 @@ static PCIDeviceInfo cirrus_vga_info = {
.no_hotplug = 1,
.init = pci_cirrus_vga_initfn,
.romfile = VGABIOS_CIRRUS_FILENAME,
.config_write = pci_cirrus_write_config,
.vendor_id = PCI_VENDOR_ID_CIRRUS,
.device_id = CIRRUS_ID_CLGD5446,
.class_id = PCI_CLASS_DISPLAY_VGA,

View File

@ -86,7 +86,7 @@ void qxl_render_update(PCIQXLDevice *qxl)
}
qemu_free_displaysurface(vga->ds);
qxl->guest_primary.data = qemu_get_ram_ptr(qxl->vga.vram_offset);
qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
if (qxl->guest_primary.stride < 0) {
/* spice surface is upside down -> need extra buffer to flip */
qxl->guest_primary.stride = -qxl->guest_primary.stride;

135
hw/qxl.c
View File

@ -263,7 +263,7 @@ static ram_addr_t qxl_rom_size(void)
static void init_qxl_rom(PCIQXLDevice *d)
{
QXLRom *rom = qemu_get_ram_ptr(d->rom_offset);
QXLRom *rom = memory_region_get_ram_ptr(&d->rom_bar);
QXLModes *modes = (QXLModes *)(rom + 1);
uint32_t ram_header_size;
uint32_t surface0_area_size;
@ -339,39 +339,37 @@ static void init_qxl_ram(PCIQXLDevice *d)
}
/* can be called from spice server thread context */
static void qxl_set_dirty(ram_addr_t addr, ram_addr_t end)
static void qxl_set_dirty(MemoryRegion *mr, ram_addr_t addr, ram_addr_t end)
{
while (addr < end) {
cpu_physical_memory_set_dirty(addr);
memory_region_set_dirty(mr, addr);
addr += TARGET_PAGE_SIZE;
}
}
static void qxl_rom_set_dirty(PCIQXLDevice *qxl)
{
ram_addr_t addr = qxl->rom_offset;
qxl_set_dirty(addr, addr + qxl->rom_size);
qxl_set_dirty(&qxl->rom_bar, 0, qxl->rom_size);
}
/* called from spice server thread context only */
static void qxl_ram_set_dirty(PCIQXLDevice *qxl, void *ptr)
{
ram_addr_t addr = qxl->vga.vram_offset;
void *base = qxl->vga.vram_ptr;
intptr_t offset;
offset = ptr - base;
offset &= ~(TARGET_PAGE_SIZE-1);
assert(offset < qxl->vga.vram_size);
qxl_set_dirty(addr + offset, addr + offset + TARGET_PAGE_SIZE);
qxl_set_dirty(&qxl->vga.vram, offset, offset + TARGET_PAGE_SIZE);
}
/* can be called from spice server thread context */
static void qxl_ring_set_dirty(PCIQXLDevice *qxl)
{
ram_addr_t addr = qxl->vga.vram_offset + qxl->shadow_rom.ram_header_offset;
ram_addr_t end = qxl->vga.vram_offset + qxl->vga.vram_size;
qxl_set_dirty(addr, end);
ram_addr_t addr = qxl->shadow_rom.ram_header_offset;
ram_addr_t end = qxl->vga.vram_size;
qxl_set_dirty(&qxl->vga.vram, addr, end);
}
/*
@ -819,20 +817,6 @@ static void qxl_set_irq(PCIQXLDevice *d)
qxl_ring_set_dirty(d);
}
static void qxl_write_config(PCIDevice *d, uint32_t address,
uint32_t val, int len)
{
PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, d);
VGACommonState *vga = &qxl->vga;
vga_dirty_log_stop(vga);
pci_default_write_config(d, address, val, len);
if (vga->map_addr && qxl->pci.io_regions[0].addr == -1) {
vga->map_addr = 0;
}
vga_dirty_log_start(vga);
}
static void qxl_check_state(PCIQXLDevice *d)
{
QXLRam *ram = d->ram;
@ -959,10 +943,10 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
switch (pci_region) {
case QXL_RAM_RANGE_INDEX:
virt_start = (intptr_t)qemu_get_ram_ptr(d->vga.vram_offset);
virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vga.vram);
break;
case QXL_VRAM_RANGE_INDEX:
virt_start = (intptr_t)qemu_get_ram_ptr(d->vram_offset);
virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vram_bar);
break;
default:
/* should not happen */
@ -1132,10 +1116,11 @@ static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
qxl_rom_set_dirty(d);
}
static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
static void ioport_write(void *opaque, target_phys_addr_t addr,
uint64_t val, unsigned size)
{
PCIQXLDevice *d = opaque;
uint32_t io_port = addr - d->io_base;
uint32_t io_port = addr;
qxl_async_io async = QXL_SYNC;
#if SPICE_INTERFACE_QXL_MINOR >= 1
uint32_t orig_io_port = io_port;
@ -1241,7 +1226,7 @@ async_common:
d->oom_running = 0;
break;
case QXL_IO_SET_MODE:
dprint(d, 1, "QXL_SET_MODE %d\n", val);
dprint(d, 1, "QXL_SET_MODE %d\n", (int)val);
qxl_set_mode(d, val, 0);
break;
case QXL_IO_LOG:
@ -1348,7 +1333,8 @@ cancel_async:
#endif
}
static uint32_t ioport_read(void *opaque, uint32_t addr)
static uint64_t ioport_read(void *opaque, target_phys_addr_t addr,
unsigned size)
{
PCIQXLDevice *d = opaque;
@ -1356,42 +1342,14 @@ static uint32_t ioport_read(void *opaque, uint32_t addr)
return 0xff;
}
static void qxl_map(PCIDevice *pci, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
static const char *names[] = {
[ QXL_IO_RANGE_INDEX ] = "ioports",
[ QXL_RAM_RANGE_INDEX ] = "devram",
[ QXL_ROM_RANGE_INDEX ] = "rom",
[ QXL_VRAM_RANGE_INDEX ] = "vram",
};
PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, pci);
dprint(qxl, 1, "%s: bar %d [%s] addr 0x%lx size 0x%lx\n", __FUNCTION__,
region_num, names[region_num], addr, size);
switch (region_num) {
case QXL_IO_RANGE_INDEX:
register_ioport_write(addr, size, 1, ioport_write, pci);
register_ioport_read(addr, size, 1, ioport_read, pci);
qxl->io_base = addr;
break;
case QXL_RAM_RANGE_INDEX:
cpu_register_physical_memory(addr, size, qxl->vga.vram_offset | IO_MEM_RAM);
qxl->vga.map_addr = addr;
qxl->vga.map_end = addr + size;
if (qxl->id == 0) {
vga_dirty_log_start(&qxl->vga);
}
break;
case QXL_ROM_RANGE_INDEX:
cpu_register_physical_memory(addr, size, qxl->rom_offset | IO_MEM_ROM);
break;
case QXL_VRAM_RANGE_INDEX:
cpu_register_physical_memory(addr, size, qxl->vram_offset | IO_MEM_RAM);
break;
}
}
static const MemoryRegionOps qxl_io_ops = {
.read = ioport_read,
.write = ioport_write,
.valid = {
.min_access_size = 1,
.max_access_size = 1,
},
};
static void pipe_read(void *opaque)
{
@ -1511,10 +1469,9 @@ static void qxl_vm_change_state_handler(void *opaque, int running, int reason)
* to make sure they are saved */
/* FIXME #1: should go out during "live" stage */
/* FIXME #2: we only need to save the areas which are actually used */
ram_addr_t vram_addr = qxl->vram_offset;
ram_addr_t surface0_addr = qxl->vga.vram_offset + qxl->shadow_rom.draw_area_offset;
qxl_set_dirty(vram_addr, vram_addr + qxl->vram_size);
qxl_set_dirty(surface0_addr, surface0_addr + qxl->shadow_rom.surface0_area_size);
qxl_set_dirty(&qxl->vram_bar, 0, qxl->vram_size);
qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset,
qxl->shadow_rom.surface0_area_size);
}
}
@ -1580,7 +1537,8 @@ static int qxl_init_common(PCIQXLDevice *qxl)
pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
qxl->rom_size = qxl_rom_size();
qxl->rom_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vrom", qxl->rom_size);
memory_region_init_ram(&qxl->rom_bar, &qxl->pci.qdev, "qxl.vrom",
qxl->rom_size);
init_qxl_rom(qxl);
init_qxl_ram(qxl);
@ -1591,26 +1549,32 @@ static int qxl_init_common(PCIQXLDevice *qxl)
qxl->vram_size = 4096;
}
qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
qxl->vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vram", qxl->vram_size);
memory_region_init_ram(&qxl->vram_bar, &qxl->pci.qdev, "qxl.vram",
qxl->vram_size);
io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1);
if (qxl->revision == 1) {
io_size = 8;
}
pci_register_bar(&qxl->pci, QXL_IO_RANGE_INDEX,
io_size, PCI_BASE_ADDRESS_SPACE_IO, qxl_map);
memory_region_init_io(&qxl->io_bar, &qxl_io_ops, qxl,
"qxl-ioports", io_size);
if (qxl->id == 0) {
vga_dirty_log_start(&qxl->vga);
}
pci_register_bar(&qxl->pci, QXL_ROM_RANGE_INDEX,
qxl->rom_size, PCI_BASE_ADDRESS_SPACE_MEMORY,
qxl_map);
pci_register_bar(&qxl->pci, QXL_RAM_RANGE_INDEX,
qxl->vga.vram_size, PCI_BASE_ADDRESS_SPACE_MEMORY,
qxl_map);
pci_register_bar_region(&qxl->pci, QXL_IO_RANGE_INDEX,
PCI_BASE_ADDRESS_SPACE_IO, &qxl->io_bar);
pci_register_bar(&qxl->pci, QXL_VRAM_RANGE_INDEX, qxl->vram_size,
PCI_BASE_ADDRESS_SPACE_MEMORY, qxl_map);
pci_register_bar_region(&qxl->pci, QXL_ROM_RANGE_INDEX,
PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->rom_bar);
pci_register_bar_region(&qxl->pci, QXL_RAM_RANGE_INDEX,
PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->vga.vram);
pci_register_bar_region(&qxl->pci, QXL_VRAM_RANGE_INDEX,
PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->vram_bar);
qxl->ssd.qxl.base.sif = &qxl_interface.base;
qxl->ssd.qxl.id = qxl->id;
@ -1664,9 +1628,9 @@ static int qxl_init_secondary(PCIDevice *dev)
ram_size = 16 * 1024 * 1024;
}
qxl->vga.vram_size = ram_size;
qxl->vga.vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vgavram",
qxl->vga.vram_size);
qxl->vga.vram_ptr = qemu_get_ram_ptr(qxl->vga.vram_offset);
memory_region_init_ram(&qxl->vga.vram, &qxl->pci.qdev, "qxl.vgavram",
qxl->vga.vram_size);
qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram);
return qxl_init_common(qxl);
}
@ -1829,7 +1793,6 @@ static PCIDeviceInfo qxl_info_primary = {
.qdev.vmsd = &qxl_vmstate,
.no_hotplug = 1,
.init = qxl_init_primary,
.config_write = qxl_write_config,
.romfile = "vgabios-qxl.bin",
.vendor_id = REDHAT_PCI_VENDOR_ID,
.device_id = QXL_DEVICE_ID_STABLE,

View File

@ -79,14 +79,14 @@ typedef struct PCIQXLDevice {
QXLRom *rom;
QXLModes *modes;
uint32_t rom_size;
uint64_t rom_offset;
MemoryRegion rom_bar;
/* vram pci bar */
uint32_t vram_size;
uint64_t vram_offset;
MemoryRegion vram_bar;
/* io bar */
uint32_t io_base;
MemoryRegion io_bar;
} PCIQXLDevice;
#define PANIC_ON(x) if ((x)) { \

View File

@ -27,6 +27,7 @@
#include "vga_int.h"
#include "pixel_ops.h"
#include "qemu-timer.h"
#include "exec-memory.h"
typedef struct ISAVGAMMState {
VGACommonState vga;
@ -79,35 +80,44 @@ static void vga_mm_writel (void *opaque,
vga_ioport_write(&s->vga, addr >> s->it_shift, value);
}
static CPUReadMemoryFunc * const vga_mm_read_ctrl[] = {
&vga_mm_readb,
&vga_mm_readw,
&vga_mm_readl,
};
static CPUWriteMemoryFunc * const vga_mm_write_ctrl[] = {
&vga_mm_writeb,
&vga_mm_writew,
&vga_mm_writel,
static const MemoryRegionOps vga_mm_ctrl_ops = {
.old_mmio = {
.read = {
vga_mm_readb,
vga_mm_readw,
vga_mm_readl,
},
.write = {
vga_mm_writeb,
vga_mm_writew,
vga_mm_writel,
},
},
.endianness = DEVICE_NATIVE_ENDIAN,
};
static void vga_mm_init(ISAVGAMMState *s, target_phys_addr_t vram_base,
target_phys_addr_t ctrl_base, int it_shift)
{
int s_ioport_ctrl, vga_io_memory;
MemoryRegion *s_ioport_ctrl, *vga_io_memory;
s->it_shift = it_shift;
s_ioport_ctrl = cpu_register_io_memory(vga_mm_read_ctrl, vga_mm_write_ctrl, s,
DEVICE_NATIVE_ENDIAN);
vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s,
DEVICE_NATIVE_ENDIAN);
s_ioport_ctrl = qemu_malloc(sizeof(*s_ioport_ctrl));
memory_region_init_io(s_ioport_ctrl, &vga_mm_ctrl_ops, s,
"vga-mm-ctrl", 0x100000);
vga_io_memory = qemu_malloc(sizeof(*vga_io_memory));
/* XXX: endianness? */
memory_region_init_io(vga_io_memory, &vga_mem_ops, &s->vga,
"vga-mem", 0x20000);
vmstate_register(NULL, 0, &vmstate_vga_common, s);
cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
memory_region_add_subregion(get_system_memory(), ctrl_base, s_ioport_ctrl);
s->vga.bank_offset = 0;
cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000);
memory_region_add_subregion(get_system_memory(),
vram_base + 0x000a0000, vga_io_memory);
memory_region_set_coalescing(vga_io_memory);
}
int isa_vga_mm_init(target_phys_addr_t vram_base,

View File

@ -28,6 +28,7 @@
#include "pixel_ops.h"
#include "qemu-timer.h"
#include "loader.h"
#include "exec-memory.h"
typedef struct ISAVGAState {
ISADevice dev;
@ -46,13 +47,14 @@ static int vga_initfn(ISADevice *dev)
{
ISAVGAState *d = DO_UPCAST(ISAVGAState, dev, dev);
VGACommonState *s = &d->state;
int vga_io_memory;
MemoryRegion *vga_io_memory;
vga_common_init(s, VGA_RAM_SIZE);
vga_io_memory = vga_init_io(s);
cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
vga_io_memory);
qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
memory_region_add_subregion_overlap(get_system_memory(),
isa_mem_base + 0x000a0000,
vga_io_memory, 1);
memory_region_set_coalescing(vga_io_memory);
isa_init_ioport(dev, 0x3c0);
isa_init_ioport(dev, 0x3b4);
isa_init_ioport(dev, 0x3ba);

View File

@ -47,29 +47,6 @@ static const VMStateDescription vmstate_vga_pci = {
}
};
static void vga_map(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
PCIVGAState *d = (PCIVGAState *)pci_dev;
VGACommonState *s = &d->vga;
cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
s->map_addr = addr;
s->map_end = addr + s->vram_size;
vga_dirty_log_start(s);
}
static void pci_vga_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len)
{
PCIVGAState *pvs = container_of(d, PCIVGAState, dev);
VGACommonState *s = &pvs->vga;
pci_default_write_config(d, address, val, len);
if (s->map_addr && pvs->dev.io_regions[0].addr == -1)
s->map_addr = 0;
}
static int pci_vga_initfn(PCIDevice *dev)
{
PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
@ -83,8 +60,8 @@ static int pci_vga_initfn(PCIDevice *dev)
s->screen_dump, s->text_update, s);
/* XXX: VGA_RAM_SIZE must be a power of two */
pci_register_bar(&d->dev, 0, VGA_RAM_SIZE,
PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map);
pci_register_bar_region(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH,
&s->vram);
if (!dev->rom_bar) {
/* compatibility with pc-0.13 and older */
@ -106,7 +83,6 @@ static PCIDeviceInfo vga_info = {
.qdev.vmsd = &vmstate_vga_pci,
.no_hotplug = 1,
.init = pci_vga_initfn,
.config_write = pci_vga_write_config,
.romfile = "vgabios-stdvga.bin",
/* dummy VGA (same as Bochs ID) */

146
hw/vga.c
View File

@ -28,6 +28,7 @@
#include "vga_int.h"
#include "pixel_ops.h"
#include "qemu-timer.h"
#include "exec-memory.h"
//#define DEBUG_VGA
//#define DEBUG_VGA_MEM
@ -825,7 +826,7 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
#endif
s->plane_updated |= mask; /* only used to detect font change */
cpu_physical_memory_set_dirty(s->vram_offset + addr);
memory_region_set_dirty(&s->vram, addr);
}
} else if (s->gr[5] & 0x10) {
/* odd/even mode (aka text mode mapping) */
@ -838,7 +839,7 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
#endif
s->plane_updated |= mask; /* only used to detect font change */
cpu_physical_memory_set_dirty(s->vram_offset + addr);
memory_region_set_dirty(&s->vram, addr);
}
} else {
/* standard VGA latched access */
@ -912,7 +913,7 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n",
addr * 4, write_mask, val);
#endif
cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
memory_region_set_dirty(&s->vram, addr << 2);
}
}
@ -1553,57 +1554,17 @@ void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
static void vga_sync_dirty_bitmap(VGACommonState *s)
{
if (s->map_addr)
cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
if (s->lfb_vram_mapped) {
cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
}
#ifdef CONFIG_BOCHS_VBE
if (s->vbe_mapped) {
cpu_physical_sync_dirty_bitmap(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
VBE_DISPI_LFB_PHYSICAL_ADDRESS + s->vram_size);
}
#endif
memory_region_sync_dirty_bitmap(&s->vram);
}
void vga_dirty_log_start(VGACommonState *s)
{
if (s->map_addr) {
cpu_physical_log_start(s->map_addr, s->map_end - s->map_addr);
}
if (s->lfb_vram_mapped) {
cpu_physical_log_start(isa_mem_base + 0xa0000, 0x8000);
cpu_physical_log_start(isa_mem_base + 0xa8000, 0x8000);
}
#ifdef CONFIG_BOCHS_VBE
if (s->vbe_mapped) {
cpu_physical_log_start(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
}
#endif
memory_region_set_log(&s->vram, true, DIRTY_MEMORY_VGA);
}
void vga_dirty_log_stop(VGACommonState *s)
{
if (s->map_addr) {
cpu_physical_log_stop(s->map_addr, s->map_end - s->map_addr);
}
if (s->lfb_vram_mapped) {
cpu_physical_log_stop(isa_mem_base + 0xa0000, 0x8000);
cpu_physical_log_stop(isa_mem_base + 0xa8000, 0x8000);
}
#ifdef CONFIG_BOCHS_VBE
if (s->vbe_mapped) {
cpu_physical_log_stop(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
}
#endif
memory_region_set_log(&s->vram, false, DIRTY_MEMORY_VGA);
}
void vga_dirty_log_restart(VGACommonState *s)
@ -1773,15 +1734,16 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
if (!(s->cr[0x17] & 2)) {
addr = (addr & ~0x8000) | ((y1 & 2) << 14);
}
page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
page0 = addr & TARGET_PAGE_MASK;
page1 = (addr + bwidth - 1) & TARGET_PAGE_MASK;
update = full_update |
cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
memory_region_get_dirty(&s->vram, page0, DIRTY_MEMORY_VGA) |
memory_region_get_dirty(&s->vram, page1, DIRTY_MEMORY_VGA);
if ((page1 - page0) > TARGET_PAGE_SIZE) {
/* if wide line, can use another page */
update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
VGA_DIRTY_FLAG);
update |= memory_region_get_dirty(&s->vram,
page0 + TARGET_PAGE_SIZE,
DIRTY_MEMORY_VGA);
}
/* explicit invalidation for the hardware cursor */
update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
@ -1826,8 +1788,10 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
}
/* reset modified pages */
if (page_max >= page_min) {
cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
VGA_DIRTY_FLAG);
memory_region_reset_dirty(&s->vram,
page_min,
page_max + TARGET_PAGE_SIZE - page_min,
DIRTY_MEMORY_VGA);
}
memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
}
@ -1906,11 +1870,6 @@ static void vga_invalidate_display(void *opaque)
void vga_common_reset(VGACommonState *s)
{
s->lfb_addr = 0;
s->lfb_end = 0;
s->map_addr = 0;
s->map_end = 0;
s->lfb_vram_mapped = 0;
s->sr_index = 0;
memset(s->sr, '\0', sizeof(s->sr));
s->gr_index = 0;
@ -2141,16 +2100,36 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
dpy_update(s->ds, 0, 0, s->last_width, height);
}
CPUReadMemoryFunc * const vga_mem_read[3] = {
vga_mem_readb,
vga_mem_readw,
vga_mem_readl,
};
static uint64_t vga_mem_read(void *opaque, target_phys_addr_t addr,
unsigned size)
{
VGACommonState *s = opaque;
CPUWriteMemoryFunc * const vga_mem_write[3] = {
vga_mem_writeb,
vga_mem_writew,
vga_mem_writel,
switch (size) {
case 1: return vga_mem_readb(s, addr);
case 2: return vga_mem_readw(s, addr);
case 4: return vga_mem_readl(s, addr);
default: abort();
}
}
static void vga_mem_write(void *opaque, target_phys_addr_t addr,
uint64_t data, unsigned size)
{
VGACommonState *s = opaque;
switch (size) {
case 1: return vga_mem_writeb(s, addr, data);
case 2: return vga_mem_writew(s, addr, data);
case 4: return vga_mem_writel(s, addr, data);
default: abort();
}
}
const MemoryRegionOps vga_mem_ops = {
.read = vga_mem_read,
.write = vga_mem_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static int vga_common_post_load(void *opaque, int version_id)
@ -2236,8 +2215,8 @@ void vga_common_init(VGACommonState *s, int vga_ram_size)
#else
s->is_vbe_vmstate = 0;
#endif
s->vram_offset = qemu_ram_alloc(NULL, "vga.vram", vga_ram_size);
s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
memory_region_init_ram(&s->vram, NULL, "vga.vram", vga_ram_size);
s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
s->vram_size = vga_ram_size;
s->get_bpp = vga_get_bpp;
s->get_offsets = vga_get_offsets;
@ -2257,11 +2236,14 @@ void vga_common_init(VGACommonState *s, int vga_ram_size)
s->update_retrace_info = vga_precise_update_retrace_info;
break;
}
vga_dirty_log_start(s);
}
/* used by both ISA and PCI */
int vga_init_io(VGACommonState *s)
MemoryRegion *vga_init_io(VGACommonState *s)
{
MemoryRegion *vga_mem;
register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
@ -2292,30 +2274,36 @@ int vga_init_io(VGACommonState *s)
#endif
#endif /* CONFIG_BOCHS_VBE */
return cpu_register_io_memory(vga_mem_read, vga_mem_write, s,
DEVICE_LITTLE_ENDIAN);
vga_mem = qemu_malloc(sizeof(*vga_mem));
memory_region_init_io(vga_mem, &vga_mem_ops, s,
"vga-lowmem", 0x20000);
return vga_mem;
}
void vga_init(VGACommonState *s)
{
int vga_io_memory;
MemoryRegion *vga_io_memory;
qemu_register_reset(vga_reset, s);
s->bank_offset = 0;
vga_io_memory = vga_init_io(s);
cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
vga_io_memory);
qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
memory_region_add_subregion_overlap(get_system_memory(),
isa_mem_base + 0x000a0000,
vga_io_memory,
1);
memory_region_set_coalescing(vga_io_memory);
}
void vga_init_vbe(VGACommonState *s)
{
#ifdef CONFIG_BOCHS_VBE
/* XXX: use optimized standard vga accesses */
cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
VGA_RAM_SIZE, s->vram_offset);
memory_region_add_subregion(get_system_memory(),
VBE_DISPI_LFB_PHYSICAL_ADDRESS,
&s->vram);
s->vbe_mapped = 1;
#endif
}

View File

@ -23,6 +23,7 @@
*/
#include <hw/hw.h>
#include "memory.h"
#define MSR_COLOR_EMULATION 0x01
#define MSR_PAGE_SELECT 0x20
@ -105,11 +106,7 @@ typedef void (* vga_update_retrace_info_fn)(struct VGACommonState *s);
typedef struct VGACommonState {
uint8_t *vram_ptr;
ram_addr_t vram_offset;
target_phys_addr_t lfb_addr;
target_phys_addr_t lfb_end;
target_phys_addr_t map_addr;
target_phys_addr_t map_end;
MemoryRegion vram;
uint32_t vram_size;
uint32_t latch;
uint32_t lfb_vram_mapped; /* whether 0xa0000 is mapped as ram */
@ -134,7 +131,7 @@ typedef struct VGACommonState {
int dac_8bit;
uint8_t palette[768];
int32_t bank_offset;
int vga_io_memory;
MemoryRegion *vga_io_memory;
int (*get_bpp)(struct VGACommonState *s);
void (*get_offsets)(struct VGACommonState *s,
uint32_t *pline_offset,
@ -191,7 +188,7 @@ static inline int c6_to_8(int v)
void vga_common_init(VGACommonState *s, int vga_ram_size);
void vga_init(VGACommonState *s);
int vga_init_io(VGACommonState *s);
MemoryRegion *vga_init_io(VGACommonState *s);
void vga_common_reset(VGACommonState *s);
void vga_dirty_log_start(VGACommonState *s);
@ -229,5 +226,4 @@ extern const uint8_t gr_mask[16];
#define VGABIOS_FILENAME "vgabios.bin"
#define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin"
extern CPUReadMemoryFunc * const vga_mem_read[3];
extern CPUWriteMemoryFunc * const vga_mem_write[3];
extern const MemoryRegionOps vga_mem_ops;

View File

@ -65,10 +65,9 @@ struct vmsvga_state_s {
int syncing;
int fb_size;
ram_addr_t fifo_offset;
MemoryRegion fifo_ram;
uint8_t *fifo_ptr;
unsigned int fifo_size;
target_phys_addr_t fifo_base;
union {
uint32_t *fifo;
@ -92,6 +91,7 @@ struct vmsvga_state_s {
struct pci_vmsvga_state_s {
PCIDevice card;
struct vmsvga_state_s chip;
MemoryRegion io_bar;
};
#define SVGA_MAGIC 0x900000UL
@ -789,8 +789,11 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
#endif
return caps;
case SVGA_REG_MEM_START:
return s->fifo_base;
case SVGA_REG_MEM_START: {
struct pci_vmsvga_state_s *pci_vmsvga
= container_of(s, struct pci_vmsvga_state_s, chip);
return pci_get_bar_addr(&pci_vmsvga->card, 2);
}
case SVGA_REG_MEM_SIZE:
return s->fifo_size;
@ -1135,17 +1138,22 @@ static void vmsvga_vram_writel(void *opaque, target_phys_addr_t addr,
*(uint32_t *) (s->vram_ptr + addr) = value;
}
static CPUReadMemoryFunc * const vmsvga_vram_read[] = {
vmsvga_vram_readb,
vmsvga_vram_readw,
vmsvga_vram_readl,
};
static const MemoryRegionOps vmsvga_vram_io_ops = {
.old_mmio = {
.read = {
vmsvga_vram_readb,
vmsvga_vram_readw,
vmsvga_vram_readl,
},
.write = {
vmsvga_vram_writeb,
vmsvga_vram_writew,
vmsvga_vram_writel,
},
},
.endianness = DEVICE_NATIVE_ENDIAN,
}
static CPUWriteMemoryFunc * const vmsvga_vram_write[] = {
vmsvga_vram_writeb,
vmsvga_vram_writew,
vmsvga_vram_writel,
};
#endif
static int vmsvga_post_load(void *opaque, int version_id)
@ -1211,8 +1219,8 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
s->fifo_size = SVGA_FIFO_SIZE;
s->fifo_offset = qemu_ram_alloc(NULL, "vmsvga.fifo", s->fifo_size);
s->fifo_ptr = qemu_get_ram_ptr(s->fifo_offset);
memory_region_init_ram(&s->fifo_ram, NULL, "vmsvga.fifo", s->fifo_size);
s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram);
vga_common_init(&s->vga, vga_ram_size);
vga_init(&s->vga);
@ -1221,79 +1229,76 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
vmsvga_reset(s);
}
static void pci_vmsvga_map_ioport(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
static uint64_t vmsvga_io_read(void *opaque, target_phys_addr_t addr,
unsigned size)
{
struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
struct vmsvga_state_s *s = &d->chip;
struct vmsvga_state_s *s = opaque;
register_ioport_read(addr + SVGA_IO_MUL * SVGA_INDEX_PORT,
1, 4, vmsvga_index_read, s);
register_ioport_write(addr + SVGA_IO_MUL * SVGA_INDEX_PORT,
1, 4, vmsvga_index_write, s);
register_ioport_read(addr + SVGA_IO_MUL * SVGA_VALUE_PORT,
1, 4, vmsvga_value_read, s);
register_ioport_write(addr + SVGA_IO_MUL * SVGA_VALUE_PORT,
1, 4, vmsvga_value_write, s);
register_ioport_read(addr + SVGA_IO_MUL * SVGA_BIOS_PORT,
1, 4, vmsvga_bios_read, s);
register_ioport_write(addr + SVGA_IO_MUL * SVGA_BIOS_PORT,
1, 4, vmsvga_bios_write, s);
switch (addr) {
case SVGA_IO_MUL * SVGA_INDEX_PORT: return vmsvga_index_read(s, addr);
case SVGA_IO_MUL * SVGA_VALUE_PORT: return vmsvga_value_read(s, addr);
case SVGA_IO_MUL * SVGA_BIOS_PORT: return vmsvga_bios_read(s, addr);
default: return -1u;
}
}
static void pci_vmsvga_map_mem(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
static void vmsvga_io_write(void *opaque, target_phys_addr_t addr,
uint64_t data, unsigned size)
{
struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
struct vmsvga_state_s *s = &d->chip;
ram_addr_t iomemtype;
struct vmsvga_state_s *s = opaque;
#ifdef DIRECT_VRAM
iomemtype = cpu_register_io_memory(vmsvga_vram_read,
vmsvga_vram_write, s, DEVICE_NATIVE_ENDIAN);
#else
iomemtype = s->vga.vram_offset | IO_MEM_RAM;
#endif
cpu_register_physical_memory(addr, s->vga.vram_size,
iomemtype);
s->vga.map_addr = addr;
s->vga.map_end = addr + s->vga.vram_size;
vga_dirty_log_restart(&s->vga);
switch (addr) {
case SVGA_IO_MUL * SVGA_INDEX_PORT:
return vmsvga_index_write(s, addr, data);
case SVGA_IO_MUL * SVGA_VALUE_PORT:
return vmsvga_value_write(s, addr, data);
case SVGA_IO_MUL * SVGA_BIOS_PORT:
return vmsvga_bios_write(s, addr, data);
}
}
static void pci_vmsvga_map_fifo(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
struct vmsvga_state_s *s = &d->chip;
ram_addr_t iomemtype;
s->fifo_base = addr;
iomemtype = s->fifo_offset | IO_MEM_RAM;
cpu_register_physical_memory(s->fifo_base, s->fifo_size,
iomemtype);
}
static const MemoryRegionOps vmsvga_io_ops = {
.read = vmsvga_io_read,
.write = vmsvga_io_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 4,
.max_access_size = 4,
},
};
static int pci_vmsvga_initfn(PCIDevice *dev)
{
struct pci_vmsvga_state_s *s =
DO_UPCAST(struct pci_vmsvga_state_s, card, dev);
MemoryRegion *iomem;
#ifdef DIRECT_VRAM
DirectMem *directmem = qemu_malloc(sizeof(*directmem));
iomem = &directmem->mr;
memory_region_init_io(iomem, &vmsvga_vram_io_ops, &s->chip, "vmsvga",
memory_region_size(&s->chip.vga.vram));
#else
iomem = &s->chip.vga.vram;
#endif
vga_dirty_log_restart(&s->chip.vga);
s->card.config[PCI_CACHE_LINE_SIZE] = 0x08; /* Cache line size */
s->card.config[PCI_LATENCY_TIMER] = 0x40; /* Latency timer */
s->card.config[PCI_INTERRUPT_LINE] = 0xff; /* End */
pci_register_bar(&s->card, 0, 0x10,
PCI_BASE_ADDRESS_SPACE_IO, pci_vmsvga_map_ioport);
pci_register_bar(&s->card, 1, VGA_RAM_SIZE,
PCI_BASE_ADDRESS_MEM_PREFETCH, pci_vmsvga_map_mem);
pci_register_bar(&s->card, 2, SVGA_FIFO_SIZE,
PCI_BASE_ADDRESS_MEM_PREFETCH, pci_vmsvga_map_fifo);
memory_region_init_io(&s->io_bar, &vmsvga_io_ops, &s->chip,
"vmsvga-io", 0x10);
pci_register_bar_region(&s->card, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
vmsvga_init(&s->chip, VGA_RAM_SIZE);
pci_register_bar_region(&s->card, 1, PCI_BASE_ADDRESS_MEM_PREFETCH, iomem);
pci_register_bar_region(&s->card, 2, PCI_BASE_ADDRESS_MEM_PREFETCH,
&s->chip.fifo_ram);
if (!dev->rom_bar) {
/* compatibility with pc-0.13 and older */
vga_init_vbe(&s->chip.vga);