Stefano Stabellini
2009-Jan-13 12:17 UTC
[Xen-devel] [PATCH 2 of 4] ioemu: populate guest videoram
This patch applies to qemu-xen-unstable and implements the new way of populating the videoram in the guest and mapping it in qemu. Initially the videoram is populated at the address 0xff000000 in the guest memory address space. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index 8c0c1ff..2af2cc9 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -2653,14 +2653,11 @@ static void set_vram_mapping(CirrusVGAState *s, unsigned long begin, unsigned lo fprintf(logfile,"mapping vram to %lx - %lx\n", begin, end); - if (!s->vram_mfns) - return; - xatp.domid = domid; - xatp.space = XENMAPSPACE_mfn; + xatp.space = XENMAPSPACE_gmfn; for (i = 0; i < (end - begin) >> TARGET_PAGE_BITS; i++) { - xatp.idx = s->vram_mfns[i]; + xatp.idx = (s->vram_gmfn >> TARGET_PAGE_BITS) + i; xatp.gpfn = (begin >> TARGET_PAGE_BITS) + i; rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp); if (rc) { @@ -2674,34 +2671,15 @@ static void set_vram_mapping(CirrusVGAState *s, unsigned long begin, unsigned lo begin >> TARGET_PAGE_BITS, end >> TARGET_PAGE_BITS, XEN_DOMCTL_MEM_CACHEATTR_WB); + + s->vram_gmfn = begin; } static void unset_vram_mapping(CirrusVGAState *s, unsigned long begin, unsigned long end) { - if (s->stolen_vram_addr) { + if (s->vram_gmfn) { /* We can put it there for xend to save it efficiently */ - set_vram_mapping(s, s->stolen_vram_addr, s->stolen_vram_addr + VGA_RAM_SIZE); - } else { - /* Old image, we have to unmap them completely */ - struct xen_remove_from_physmap xrfp; - unsigned long i; - int rc; - - if (end > begin + VGA_RAM_SIZE) - end = begin + VGA_RAM_SIZE; - - fprintf(logfile,"unmapping vram from %lx - %lx\n", begin, end); - - xrfp.domid = domid; - - for (i = 0; i < (end - begin) >> TARGET_PAGE_BITS; i++) { - xrfp.gpfn = (begin >> TARGET_PAGE_BITS) + i; - rc = xc_memory_op(xc_handle, XENMEM_remove_from_physmap, &xrfp); - if (rc) { - fprintf(stderr, "remove_from_physmap PFN %"PRI_xen_pfn" failed: %d\n", xrfp.gpfn, rc); - return; - } - } + set_vram_mapping(s, 0xff000000, 0xff000000 + VGA_RAM_SIZE); } } @@ -3165,8 +3143,8 @@ static void cirrus_vga_save(QEMUFile *f, void *opaque) /* XXX old versions saved rubbish here, keeping for compatibility */ qemu_put_be32(f, 0xffffffff); qemu_put_be32(f, s->lfb_end); - qemu_put_be64s(f, &s->stolen_vram_addr); - if (!s->stolen_vram_addr && !vga_acc) + qemu_put_be64s(f, &s->vram_gmfn); + if (!s->vram_gmfn && !vga_acc) /* Old guest: VRAM is not mapped, we have to save it ourselves */ qemu_put_buffer(f, s->vram_ptr, VGA_RAM_SIZE); } @@ -3175,6 +3153,7 @@ static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id) { CirrusVGAState *s = opaque; uint8_t vga_acc = 0; + uint64_t t; int ret; if (version_id > 3) @@ -3227,25 +3206,22 @@ static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id) /* XXX throwing away 32 bits */ qemu_get_be32(f); qemu_get_be32s(f, &s->lfb_end); - if (version_id >= 3) { - qemu_get_be64s(f, &s->stolen_vram_addr); - if (!s->stolen_vram_addr && !vga_acc) { - /* Old guest, VRAM is not mapped, we have to restore it ourselves */ - qemu_get_buffer(f, s->vram_ptr, VGA_RAM_SIZE); - xen_vga_populate_vram(s->lfb_addr); - } else - xen_vga_vram_map(vga_acc ? s->lfb_addr : s->stolen_vram_addr, 0); - - if (vga_acc) { - s->map_addr = s->lfb_addr; - s->map_end = s->lfb_end; - } - } else { - /* Old image, we have to populate and restore VRAM ourselves */ - xen_vga_populate_vram(s->lfb_addr); - qemu_get_buffer(f, s->vram_ptr, VGA_RAM_SIZE); - if (vga_acc) - cirrus_restart_acc(s); + + if (version_id >= 3) + qemu_get_be64s(f, &s->vram_gmfn); + t = s->vram_gmfn; + if (!s->vram_gmfn) { + /* Old guest, VRAM is not mapped, we have to restore it + * ourselves */ + s->vram_gmfn = vga_acc ? s->lfb_addr : 0xff000000; + xen_vga_populate_vram(s->vram_gmfn); + } + xen_vga_vram_map(s->vram_gmfn); + if (version_id < 3 || (!vga_acc && !t)) + qemu_get_buffer(f, s->vram_ptr, VGA_RAM_SIZE); + if (vga_acc) { + s->map_addr = s->lfb_addr; + s->map_end = s->lfb_end; } /* force refresh */ @@ -3335,10 +3311,6 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci) } s->cr[0x27] = device_id; - /* Win2K seems to assume that the pattern buffer is at 0xff - initially ! */ - memset(s->vram_ptr, 0xff, s->real_vram_size); - s->cirrus_hidden_dac_lockindex = 5; s->cirrus_hidden_dac_data = 0; diff --git a/hw/vga.c b/hw/vga.c index 4a6bd1b..e1d6dad 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -2125,8 +2125,8 @@ static void vga_save(QEMUFile *f, void *opaque) #endif vram_size = s->vram_size; qemu_put_be32s(f, &vram_size); - qemu_put_be64s(f, &s->stolen_vram_addr); - if (!s->stolen_vram_addr) + qemu_put_be64s(f, &s->vram_gmfn); + if (!s->vram_gmfn) /* Old guest: VRAM is not mapped, we have to save it ourselves */ qemu_put_buffer(f, s->vram_ptr, VGA_RAM_SIZE); } @@ -2192,13 +2192,17 @@ static int vga_load(QEMUFile *f, void *opaque, int version_id) if (vram_size != s->vram_size) return -EINVAL; if (version_id >= 4) { - qemu_get_be64s(f, &s->stolen_vram_addr); - if (s->stolen_vram_addr) - xen_vga_vram_map(s->stolen_vram_addr, 0); + qemu_get_be64s(f, &s->vram_gmfn); + if (s->vram_gmfn) + xen_vga_vram_map(s->vram_gmfn); } /* Old guest, VRAM is not mapped, we have to restore it ourselves */ - if (!s->stolen_vram_addr) + if (!s->vram_gmfn) { + xen_vga_populate_vram(0xff000000); + xen_vga_vram_map(0xff000000); + s->vram_gmfn = 0xff000000; qemu_get_buffer(f, s->vram_ptr, s->vram_size); + } } /* force refresh */ @@ -2356,7 +2360,7 @@ void vga_bios_init(VGAState *s) static VGAState *xen_vga_state; -/* When loading old images we have to populate the video ram ourselves */ +/* Allocate video memory in the GPFN space */ void xen_vga_populate_vram(uint64_t vram_addr) { unsigned long nr_pfn; @@ -2380,23 +2384,10 @@ void xen_vga_populate_vram(uint64_t vram_addr) exit(1); } free(pfn_list); - - xen_vga_vram_map(vram_addr, 0); - - /* Unmap them from the guest for now. */ - xrfp.domid = domid; - for (i = 0; i < nr_pfn; i++) { - xrfp.gpfn = (vram_addr >> TARGET_PAGE_BITS) + i; - rc = xc_memory_op(xc_handle, XENMEM_remove_from_physmap, &xrfp); - if (rc) { - fprintf(stderr, "remove_from_physmap PFN %"PRI_xen_pfn" failed: %d\n", xrfp.gpfn, rc); - break; - } - } } -/* Called once video memory has been allocated in the GPFN space */ -void xen_vga_vram_map(uint64_t vram_addr, int copy) +/* Mapping the video memory from GPFN space */ +void xen_vga_vram_map(uint64_t vram_addr) { unsigned long nr_pfn; xen_pfn_t *pfn_list; @@ -2424,42 +2415,10 @@ void xen_vga_vram_map(uint64_t vram_addr, int copy) exit(1); } - if (xc_domain_memory_translate_gpfn_list(xc_handle, domid, nr_pfn, - pfn_list, pfn_list)) { - fprintf(stderr, "Failed translation in xen_vga_vram_addr\n"); - exit(1); - } - - if (copy) - memcpy(vram, xen_vga_state->vram_ptr, VGA_RAM_SIZE); - if (xen_vga_state->vram_mfns) { - /* In case this function is called more than once */ - free(xen_vga_state->vram_mfns); - munmap(xen_vga_state->vram_ptr, VGA_RAM_SIZE); - } else { - qemu_free(xen_vga_state->vram_ptr); - } xen_vga_state->vram_ptr = vram; - xen_vga_state->vram_mfns = pfn_list; #ifdef CONFIG_STUBDOM xenfb_pv_display_start(vram); #endif - /* If some display is already working, we need to update it now */ - ds= xen_vga_state->ds; - if (ds) - dpy_update(ds, 0,0, ds->width,ds->height); -} - -/* Called at boot time when the BIOS has allocated video RAM */ -void xen_vga_stolen_vram_addr(uint64_t stolen_vram_addr) -{ - fprintf(logfile, "stolen video RAM at %llx\n", - (unsigned long long)stolen_vram_addr); - - xen_vga_state->stolen_vram_addr = stolen_vram_addr; - - /* And copy from the initialization value */ - xen_vga_vram_map(stolen_vram_addr, 1); } /* when used on xen environment, the vga_ram_base is not used */ @@ -2493,10 +2452,7 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, vga_reset(s); - s->vram_ptr = qemu_mallocz(vga_ram_size); - s->vram_mfns = NULL; xen_vga_state = s; - s->vram_offset = vga_ram_offset; s->vram_size = vga_ram_size; s->ds = ds; @@ -2504,6 +2460,13 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, s->get_bpp = vga_get_bpp; s->get_offsets = vga_get_offsets; s->get_resolution = vga_get_resolution; + + if (!restore) { + xen_vga_populate_vram(0xff000000); + xen_vga_vram_map(0xff000000); + s->vram_gmfn = 0xff000000; + } + graphic_console_init(s->ds, vga_update_display, vga_invalidate_display, vga_screen_dump, vga_update_text, s); diff --git a/hw/vga_int.h b/hw/vga_int.h index 8e4ec93..bd147e5 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -100,8 +100,7 @@ typedef void (* vga_update_retrace_info_fn)(struct VGAState *s); #define VGA_STATE_COMMON \ uint8_t *vram_ptr; \ - xen_pfn_t *vram_mfns; \ - uint64_t stolen_vram_addr; /* Address of stolen RAM */ \ + uint64_t vram_gmfn; \ unsigned long vram_offset; \ unsigned int vram_size; \ unsigned long bios_offset; \ diff --git a/hw/xen_platform.c b/hw/xen_platform.c index 84a2b19..9271d27 100644 --- a/hw/xen_platform.c +++ b/hw/xen_platform.c @@ -45,7 +45,6 @@ typedef struct PCIXenPlatformState { PCIDevice pci_dev; uint8_t platform_flags; - uint64_t vga_stolen_ram; } PCIXenPlatformState; /* We throttle access to dom0 syslog, to avoid DOS attacks. This is @@ -175,47 +174,11 @@ static void xen_platform_ioport_writeb(void *opaque, uint32_t addr, uint32_t val } } - -static uint32_t xen_platform_ioport_readl(void *opaque, uint32_t addr) -{ - PCIXenPlatformState *d = opaque; - - addr &= 0xff; - - switch (addr) { - case 4: /* VGA stolen memory address */ - return d->vga_stolen_ram; - default: - return ~0u; - } -} - -static void xen_platform_ioport_writel(void *opaque, uint32_t addr, uint32_t val) -{ - PCIXenPlatformState *d = opaque; - - addr &= 0xff; - val &= 0xffffffff; - - switch (addr) { - case 4: /* VGA stolen memory address */ - d->vga_stolen_ram = val; - xen_vga_stolen_vram_addr(val); - break; - default: - break; - } -} - - - static void platform_ioport_map(PCIDevice *pci_dev, int region_num, uint32_t addr, uint32_t size, int type) { PCIXenPlatformState *d = (PCIXenPlatformState *)pci_dev; register_ioport_write(addr, size, 1, xen_platform_ioport_writeb, d); - register_ioport_write(addr, size, 4, xen_platform_ioport_writel, d); register_ioport_read(addr, size, 1, xen_platform_ioport_readb, d); - register_ioport_read(addr, size, 4, xen_platform_ioport_readl, d); } static uint32_t platform_mmio_read(void *opaque, target_phys_addr_t addr) @@ -401,10 +364,11 @@ struct pci_config_header { void xen_pci_save(QEMUFile *f, void *opaque) { PCIXenPlatformState *d = opaque; + uint64_t t = 0; pci_device_save(&d->pci_dev, f); qemu_put_8s(f, &d->platform_flags); - qemu_put_be64s(f, &d->vga_stolen_ram); + qemu_put_be64s(f, &t); } int xen_pci_load(QEMUFile *f, void *opaque, int version_id) @@ -423,7 +387,7 @@ int xen_pci_load(QEMUFile *f, void *opaque, int version_id) uint8_t flags; qemu_get_8s(f, &flags); xen_platform_ioport_writeb(d, 0, flags); - qemu_get_be64s(f, &d->vga_stolen_ram); + qemu_get_be64(f); } return 0; diff --git a/qemu-xen.h b/qemu-xen.h index 44467a3..120d5d7 100644 --- a/qemu-xen.h +++ b/qemu-xen.h @@ -1,6 +1,9 @@ #ifndef QEMU_XEN_H #define QEMU_XEN_H +/* vl.c */ +extern int restore; + /* xen_machine_fv.c */ #if (defined(__i386__) || defined(__x86_64__)) && !defined(QEMU_TOOL) @@ -21,9 +24,8 @@ void timeoffset_get(void); /* xen_platform.c */ #ifndef QEMU_TOOL void pci_xen_platform_init(PCIBus *bus); -void xen_vga_stolen_vram_addr(uint64_t vram_addr); void xen_vga_populate_vram(uint64_t vram_addr); -void xen_vga_vram_map(uint64_t vram_addr, int copy); +void xen_vga_vram_map(uint64_t vram_addr); #endif void ide_unplug_harddisks(void); diff --git a/vl.c b/vl.c index 9945b27..e60a9cb 100644 --- a/vl.c +++ b/vl.c @@ -178,6 +178,7 @@ /* Max number of PCI emulation */ #define MAX_PCI_EMULATION 32 +int restore; const char *bios_dir = CONFIG_QEMU_SHAREDIR; const char *bios_name = NULL; static void *ioport_opaque[MAX_IOPORTS]; @@ -9509,6 +9510,7 @@ int main(int argc, char **argv) break; case QEMU_OPTION_loadvm: loadvm = optarg; + restore = 1; break; case QEMU_OPTION_full_screen: full_screen = 1; _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel