diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2012-01-03 14:39:05 -0600 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2012-01-03 14:39:05 -0600 |
commit | f3c6a169a39d188e98c17a0a0ebfa7f85e5aafdd (patch) | |
tree | 11e695213b30090174108824425014ddb5e76da2 /hw | |
parent | 8d3bc5178fbc06cdd89c064ae8f44e77c503e91e (diff) | |
parent | 586c6230c012d1aced38e5a5614d15052ca4ae7a (diff) | |
download | qemu-f3c6a169a39d188e98c17a0a0ebfa7f85e5aafdd.zip |
Merge remote-tracking branch 'qemu-kvm/memory/page_desc' into staging
* qemu-kvm/memory/page_desc: (22 commits)
Remove cpu_get_physical_page_desc()
sparc: avoid cpu_get_physical_page_desc()
virtio-balloon: avoid cpu_get_physical_page_desc()
vhost: avoid cpu_get_physical_page_desc()
kvm: avoid cpu_get_physical_page_desc()
memory: remove CPUPhysMemoryClient
xen: convert to MemoryListener API
memory: temporarily add memory_region_get_ram_addr()
xen, vga: add API for registering the framebuffer
vhost: convert to MemoryListener API
kvm: convert to MemoryListener API
kvm: switch kvm slots to use host virtual address instead of ram_addr_t
memory: add API for observing updates to the physical memory map
memory: replace cpu_physical_sync_dirty_bitmap() with a memory API
framebuffer: drop use of cpu_physical_sync_dirty_bitmap()
loader: remove calls to cpu_get_physical_page_desc()
framebuffer: drop use of cpu_get_physical_page_desc()
memory: introduce memory_region_find()
memory: add memory_region_is_logging()
memory: add memory_region_is_rom()
...
Diffstat (limited to 'hw')
-rw-r--r-- | hw/framebuffer.c | 32 | ||||
-rw-r--r-- | hw/framebuffer.h | 3 | ||||
-rw-r--r-- | hw/loader.c | 9 | ||||
-rw-r--r-- | hw/milkymist-vgafb.c | 2 | ||||
-rw-r--r-- | hw/omap_lcdc.c | 4 | ||||
-rw-r--r-- | hw/pl110.c | 2 | ||||
-rw-r--r-- | hw/pxa2xx_lcd.c | 10 | ||||
-rw-r--r-- | hw/sysbus.c | 5 | ||||
-rw-r--r-- | hw/sysbus.h | 1 | ||||
-rw-r--r-- | hw/vga.c | 2 | ||||
-rw-r--r-- | hw/vhost.c | 167 | ||||
-rw-r--r-- | hw/vhost.h | 5 | ||||
-rw-r--r-- | hw/virtio-balloon.c | 13 | ||||
-rw-r--r-- | hw/xen.h | 3 |
14 files changed, 187 insertions, 71 deletions
diff --git a/hw/framebuffer.c b/hw/framebuffer.c index 56cf16e27a..b43bcdff40 100644 --- a/hw/framebuffer.c +++ b/hw/framebuffer.c @@ -22,6 +22,7 @@ void framebuffer_update_display( DisplayState *ds, + MemoryRegion *address_space, target_phys_addr_t base, int cols, /* Width in pixels. */ int rows, /* Leight in pixels. */ @@ -42,28 +43,22 @@ void framebuffer_update_display( int dirty; int i; ram_addr_t addr; - ram_addr_t pd; - ram_addr_t pd2; + MemoryRegionSection mem_section; + MemoryRegion *mem; i = *first_row; *first_row = -1; src_len = src_width * rows; - cpu_physical_sync_dirty_bitmap(base, base + src_len); - pd = cpu_get_physical_page_desc(base); - pd2 = cpu_get_physical_page_desc(base + src_len - 1); - /* We should reall check that this is a continuous ram region. - Instead we just check that the first and last pages are - both ram, and the right distance apart. */ - if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM - || (pd2 & ~TARGET_PAGE_MASK) > IO_MEM_ROM) { - return; - } - pd = (pd & TARGET_PAGE_MASK) + (base & ~TARGET_PAGE_MASK); - if (((pd + src_len - 1) & TARGET_PAGE_MASK) != (pd2 & TARGET_PAGE_MASK)) { + mem_section = memory_region_find(address_space, base, src_len); + if (mem_section.size != src_len || !memory_region_is_ram(mem_section.mr)) { return; } + mem = mem_section.mr; + assert(mem); + assert(mem_section.offset_within_address_space == base); + memory_region_sync_dirty_bitmap(mem); src_base = cpu_physical_memory_map(base, &src_len, 0); /* If we can't map the framebuffer then bail. We could try harder, but it's not really worth it as dirty flag tracking will probably @@ -82,7 +77,7 @@ void framebuffer_update_display( dest -= dest_row_pitch * (rows - 1); } first = -1; - addr = pd; + addr = mem_section.offset_within_region; addr += i * src_width; src += i * src_width; @@ -93,8 +88,8 @@ void framebuffer_update_display( dirty = 0; dirty_offset = 0; while (addr + dirty_offset < TARGET_PAGE_ALIGN(addr + src_width)) { - dirty |= cpu_physical_memory_get_dirty(addr + dirty_offset, - VGA_DIRTY_FLAG); + dirty |= memory_region_get_dirty(mem, addr + dirty_offset, + DIRTY_MEMORY_VGA); dirty_offset += TARGET_PAGE_SIZE; } @@ -112,7 +107,8 @@ void framebuffer_update_display( if (first < 0) { return; } - cpu_physical_memory_reset_dirty(pd, pd + src_len, VGA_DIRTY_FLAG); + memory_region_reset_dirty(mem, mem_section.offset_within_region, src_len, + DIRTY_MEMORY_VGA); *first_row = first; *last_row = last; return; diff --git a/hw/framebuffer.h b/hw/framebuffer.h index a3a214649d..527a6b85f8 100644 --- a/hw/framebuffer.h +++ b/hw/framebuffer.h @@ -1,12 +1,15 @@ #ifndef QEMU_FRAMEBUFFER_H #define QEMU_FRAMEBUFFER_H +#include "memory.h" + /* Framebuffer device helper routines. */ typedef void (*drawfn)(void *, uint8_t *, const uint8_t *, int, int); void framebuffer_update_display( DisplayState *ds, + MemoryRegion *address_space, target_phys_addr_t base, int cols, int rows, diff --git a/hw/loader.c b/hw/loader.c index 9bbcddd424..446b62874e 100644 --- a/hw/loader.c +++ b/hw/loader.c @@ -49,6 +49,8 @@ #include "uboot_image.h" #include "loader.h" #include "fw_cfg.h" +#include "memory.h" +#include "exec-memory.h" #include <zlib.h> @@ -674,7 +676,7 @@ static void rom_reset(void *unused) int rom_load_all(void) { target_phys_addr_t addr = 0; - int memtype; + MemoryRegionSection section; Rom *rom; QTAILQ_FOREACH(rom, &roms, next) { @@ -690,9 +692,8 @@ int rom_load_all(void) } addr = rom->addr; addr += rom->romsize; - memtype = cpu_get_physical_page_desc(rom->addr) & (3 << IO_MEM_SHIFT); - if (memtype == IO_MEM_ROM) - rom->isrom = 1; + section = memory_region_find(get_system_memory(), rom->addr, 1); + rom->isrom = section.size && memory_region_is_rom(section.mr); } qemu_register_reset(rom_reset, NULL); roms_loaded = 1; diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c index 01cd309ca3..108115e300 100644 --- a/hw/milkymist-vgafb.c +++ b/hw/milkymist-vgafb.c @@ -120,7 +120,7 @@ static void vgafb_update_display(void *opaque) break; } - framebuffer_update_display(s->ds, + framebuffer_update_display(s->ds, sysbus_address_space(&s->busdev), s->regs[R_BASEADDRESS] + s->fb_offset, s->regs[R_HRES], s->regs[R_VRES], diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c index 8484f7058d..f265306556 100644 --- a/hw/omap_lcdc.c +++ b/hw/omap_lcdc.c @@ -22,6 +22,7 @@ #include "framebuffer.h" struct omap_lcd_panel_s { + MemoryRegion *sysmem; MemoryRegion iomem; qemu_irq irq; DisplayState *state; @@ -211,7 +212,7 @@ static void omap_update_display(void *opaque) step = width * bpp >> 3; linesize = ds_get_linesize(omap_lcd->state); - framebuffer_update_display(omap_lcd->state, + framebuffer_update_display(omap_lcd->state, omap_lcd->sysmem, frame_base, width, height, step, linesize, 0, omap_lcd->invalidate, @@ -440,6 +441,7 @@ struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem, s->irq = irq; s->dma = dma; + s->sysmem = sysmem; omap_lcdc_reset(s); memory_region_init_io(&s->iomem, &omap_lcdc_ops, s, "omap.lcdc", 0x100); diff --git a/hw/pl110.c b/hw/pl110.c index cc1eb6d986..303a9bcdbd 100644 --- a/hw/pl110.c +++ b/hw/pl110.c @@ -229,7 +229,7 @@ static void pl110_update_display(void *opaque) } dest_width *= s->cols; first = 0; - framebuffer_update_display(s->ds, + framebuffer_update_display(s->ds, sysbus_address_space(&s->busdev), s->upbase, s->cols, s->rows, src_width, dest_width, 0, s->invalidate, diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c index fd23d63a64..5dd4ef06d6 100644 --- a/hw/pxa2xx_lcd.c +++ b/hw/pxa2xx_lcd.c @@ -30,6 +30,7 @@ struct DMAChannel { }; struct PXA2xxLCDState { + MemoryRegion *sysmem; MemoryRegion iomem; qemu_irq irq; int irqlevel; @@ -681,7 +682,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s, dest_width = s->xres * s->dest_width; *miny = 0; - framebuffer_update_display(s->ds, + framebuffer_update_display(s->ds, s->sysmem, addr, s->xres, s->yres, src_width, dest_width, s->dest_width, s->invalidated, @@ -708,7 +709,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s, dest_width = s->yres * s->dest_width; *miny = 0; - framebuffer_update_display(s->ds, + framebuffer_update_display(s->ds, s->sysmem, addr, s->xres, s->yres, src_width, s->dest_width, -dest_width, s->invalidated, @@ -739,7 +740,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s, dest_width = s->xres * s->dest_width; *miny = 0; - framebuffer_update_display(s->ds, + framebuffer_update_display(s->ds, s->sysmem, addr, s->xres, s->yres, src_width, -dest_width, -s->dest_width, s->invalidated, @@ -769,7 +770,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s, dest_width = s->yres * s->dest_width; *miny = 0; - framebuffer_update_display(s->ds, + framebuffer_update_display(s->ds, s->sysmem, addr, s->xres, s->yres, src_width, -s->dest_width, dest_width, s->invalidated, @@ -985,6 +986,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem, s = (PXA2xxLCDState *) g_malloc0(sizeof(PXA2xxLCDState)); s->invalidated = 1; s->irq = irq; + s->sysmem = sysmem; pxa2xx_lcdc_orientation(s, graphic_rotate); diff --git a/hw/sysbus.c b/hw/sysbus.c index 24f619f65c..2e06fe823c 100644 --- a/hw/sysbus.c +++ b/hw/sysbus.c @@ -253,3 +253,8 @@ void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem) { memory_region_del_subregion(get_system_io(), mem); } + +MemoryRegion *sysbus_address_space(SysBusDevice *dev) +{ + return get_system_memory(); +} diff --git a/hw/sysbus.h b/hw/sysbus.h index 2f4025b221..899756bf7f 100644 --- a/hw/sysbus.h +++ b/hw/sysbus.h @@ -57,6 +57,7 @@ void sysbus_del_memory(SysBusDevice *dev, MemoryRegion *mem); void sysbus_add_io(SysBusDevice *dev, target_phys_addr_t addr, MemoryRegion *mem); void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem); +MemoryRegion *sysbus_address_space(SysBusDevice *dev); /* Legacy helper function for creating devices. */ DeviceState *sysbus_create_varargs(const char *name, @@ -28,6 +28,7 @@ #include "vga_int.h" #include "pixel_ops.h" #include "qemu-timer.h" +#include "xen.h" //#define DEBUG_VGA //#define DEBUG_VGA_MEM @@ -2222,6 +2223,7 @@ void vga_common_init(VGACommonState *s, int vga_ram_size) s->is_vbe_vmstate = 0; #endif memory_region_init_ram(&s->vram, NULL, "vga.vram", vga_ram_size); + xen_register_framebuffer(&s->vram); s->vram_ptr = memory_region_get_ram_ptr(&s->vram); s->vram_size = vga_ram_size; s->get_bpp = vga_get_bpp; diff --git a/hw/vhost.c b/hw/vhost.c index 0870cb7d85..cd56e75d0a 100644 --- a/hw/vhost.c +++ b/hw/vhost.c @@ -17,6 +17,7 @@ #include <linux/vhost.h> static void vhost_dev_sync_region(struct vhost_dev *dev, + MemoryRegionSection *section, uint64_t mfirst, uint64_t mlast, uint64_t rfirst, uint64_t rlast) { @@ -49,38 +50,50 @@ static void vhost_dev_sync_region(struct vhost_dev *dev, ffsll(log) : ffs(log))) { ram_addr_t ram_addr; bit -= 1; - ram_addr = cpu_get_physical_page_desc(addr + bit * VHOST_LOG_PAGE); - cpu_physical_memory_set_dirty(ram_addr); + ram_addr = section->offset_within_region + bit * VHOST_LOG_PAGE; + memory_region_set_dirty(section->mr, ram_addr); log &= ~(0x1ull << bit); } addr += VHOST_LOG_CHUNK; } } -static int vhost_client_sync_dirty_bitmap(CPUPhysMemoryClient *client, - target_phys_addr_t start_addr, - target_phys_addr_t end_addr) +static int vhost_sync_dirty_bitmap(struct vhost_dev *dev, + MemoryRegionSection *section, + target_phys_addr_t start_addr, + target_phys_addr_t end_addr) { - struct vhost_dev *dev = container_of(client, struct vhost_dev, client); int i; + if (!dev->log_enabled || !dev->started) { return 0; } for (i = 0; i < dev->mem->nregions; ++i) { struct vhost_memory_region *reg = dev->mem->regions + i; - vhost_dev_sync_region(dev, start_addr, end_addr, + vhost_dev_sync_region(dev, section, start_addr, end_addr, reg->guest_phys_addr, range_get_last(reg->guest_phys_addr, reg->memory_size)); } for (i = 0; i < dev->nvqs; ++i) { struct vhost_virtqueue *vq = dev->vqs + i; - vhost_dev_sync_region(dev, start_addr, end_addr, vq->used_phys, + vhost_dev_sync_region(dev, section, start_addr, end_addr, vq->used_phys, range_get_last(vq->used_phys, vq->used_size)); } return 0; } +static void vhost_log_sync(MemoryListener *listener, + MemoryRegionSection *section) +{ + struct vhost_dev *dev = container_of(listener, struct vhost_dev, + memory_listener); + target_phys_addr_t start_addr = section->offset_within_address_space; + target_phys_addr_t end_addr = start_addr + section->size; + + vhost_sync_dirty_bitmap(dev, section, start_addr, end_addr); +} + /* Assign/unassign. Keep an unsorted array of non-overlapping * memory regions in dev->mem. */ static void vhost_dev_unassign_memory(struct vhost_dev *dev, @@ -250,7 +263,7 @@ static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size) { vhost_log_chunk_t *log; uint64_t log_base; - int r; + int r, i; if (size) { log = g_malloc0(size * sizeof *log); } else { @@ -259,8 +272,10 @@ static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size) log_base = (uint64_t)(unsigned long)log; r = ioctl(dev->control, VHOST_SET_LOG_BASE, &log_base); assert(r >= 0); - vhost_client_sync_dirty_bitmap(&dev->client, 0, - (target_phys_addr_t)~0x0ull); + for (i = 0; i < dev->n_mem_sections; ++i) { + vhost_sync_dirty_bitmap(dev, &dev->mem_sections[i], + 0, (target_phys_addr_t)~0x0ull); + } if (dev->log) { g_free(dev->log); } @@ -335,31 +350,37 @@ static bool vhost_dev_cmp_memory(struct vhost_dev *dev, return uaddr != reg->userspace_addr + start_addr - reg->guest_phys_addr; } -static void vhost_client_set_memory(CPUPhysMemoryClient *client, - target_phys_addr_t start_addr, - ram_addr_t size, - ram_addr_t phys_offset, - bool log_dirty) +static void vhost_set_memory(MemoryListener *listener, + MemoryRegionSection *section, + bool add) { - struct vhost_dev *dev = container_of(client, struct vhost_dev, client); - ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK; + struct vhost_dev *dev = container_of(listener, struct vhost_dev, + memory_listener); + target_phys_addr_t start_addr = section->offset_within_address_space; + ram_addr_t size = section->size; + bool log_dirty = memory_region_is_logging(section->mr); int s = offsetof(struct vhost_memory, regions) + (dev->mem->nregions + 1) * sizeof dev->mem->regions[0]; uint64_t log_size; int r; + void *ram; + + if (!memory_region_is_ram(section->mr)) { + return; + } dev->mem = g_realloc(dev->mem, s); if (log_dirty) { - flags = IO_MEM_UNASSIGNED; + add = false; } assert(size); /* Optimize no-change case. At least cirrus_vga does this a lot at this time. */ - if (flags == IO_MEM_RAM) { - if (!vhost_dev_cmp_memory(dev, start_addr, size, - (uintptr_t)qemu_get_ram_ptr(phys_offset))) { + ram = memory_region_get_ram_ptr(section->mr); + if (add) { + if (!vhost_dev_cmp_memory(dev, start_addr, size, (uintptr_t)ram)) { /* Region exists with same address. Nothing to do. */ return; } @@ -371,10 +392,9 @@ static void vhost_client_set_memory(CPUPhysMemoryClient *client, } vhost_dev_unassign_memory(dev, start_addr, size); - if (flags == IO_MEM_RAM) { + if (add) { /* Add given mapping, merging adjacent regions if any */ - vhost_dev_assign_memory(dev, start_addr, size, - (uintptr_t)qemu_get_ram_ptr(phys_offset)); + vhost_dev_assign_memory(dev, start_addr, size, (uintptr_t)ram); } else { /* Remove old mapping for this memory, if any. */ vhost_dev_unassign_memory(dev, start_addr, size); @@ -410,6 +430,38 @@ static void vhost_client_set_memory(CPUPhysMemoryClient *client, } } +static void vhost_region_add(MemoryListener *listener, + MemoryRegionSection *section) +{ + struct vhost_dev *dev = container_of(listener, struct vhost_dev, + memory_listener); + + ++dev->n_mem_sections; + dev->mem_sections = g_renew(MemoryRegionSection, dev->mem_sections, + dev->n_mem_sections); + dev->mem_sections[dev->n_mem_sections - 1] = *section; + vhost_set_memory(listener, section, true); +} + +static void vhost_region_del(MemoryListener *listener, + MemoryRegionSection *section) +{ + struct vhost_dev *dev = container_of(listener, struct vhost_dev, + memory_listener); + int i; + + vhost_set_memory(listener, section, false); + for (i = 0; i < dev->n_mem_sections; ++i) { + if (dev->mem_sections[i].offset_within_address_space + == section->offset_within_address_space) { + --dev->n_mem_sections; + memmove(&dev->mem_sections[i], &dev->mem_sections[i+1], + dev->n_mem_sections - i); + break; + } + } +} + static int vhost_virtqueue_set_addr(struct vhost_dev *dev, struct vhost_virtqueue *vq, unsigned idx, bool enable_log) @@ -467,10 +519,10 @@ err_features: return r; } -static int vhost_client_migration_log(CPUPhysMemoryClient *client, - int enable) +static int vhost_migration_log(MemoryListener *listener, int enable) { - struct vhost_dev *dev = container_of(client, struct vhost_dev, client); + struct vhost_dev *dev = container_of(listener, struct vhost_dev, + memory_listener); int r; if (!!enable == dev->log_enabled) { return 0; @@ -500,6 +552,38 @@ static int vhost_client_migration_log(CPUPhysMemoryClient *client, return 0; } +static void vhost_log_global_start(MemoryListener *listener) +{ + int r; + + r = vhost_migration_log(listener, true); + if (r < 0) { + abort(); + } +} + +static void vhost_log_global_stop(MemoryListener *listener) +{ + int r; + + r = vhost_migration_log(listener, false); + if (r < 0) { + abort(); + } +} + +static void vhost_log_start(MemoryListener *listener, + MemoryRegionSection *section) +{ + /* FIXME: implement */ +} + +static void vhost_log_stop(MemoryListener *listener, + MemoryRegionSection *section) +{ + /* FIXME: implement */ +} + static int vhost_virtqueue_init(struct vhost_dev *dev, struct VirtIODevice *vdev, struct vhost_virtqueue *vq, @@ -645,17 +729,23 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force) } hdev->features = features; - hdev->client.set_memory = vhost_client_set_memory; - hdev->client.sync_dirty_bitmap = vhost_client_sync_dirty_bitmap; - hdev->client.migration_log = vhost_client_migration_log; - hdev->client.log_start = NULL; - hdev->client.log_stop = NULL; + hdev->memory_listener = (MemoryListener) { + .region_add = vhost_region_add, + .region_del = vhost_region_del, + .log_start = vhost_log_start, + .log_stop = vhost_log_stop, + .log_sync = vhost_log_sync, + .log_global_start = vhost_log_global_start, + .log_global_stop = vhost_log_global_stop, + }; hdev->mem = g_malloc0(offsetof(struct vhost_memory, regions)); + hdev->n_mem_sections = 0; + hdev->mem_sections = NULL; hdev->log = NULL; hdev->log_size = 0; hdev->log_enabled = false; hdev->started = false; - cpu_register_phys_memory_client(&hdev->client); + memory_listener_register(&hdev->memory_listener); hdev->force = force; return 0; fail: @@ -666,8 +756,9 @@ fail: void vhost_dev_cleanup(struct vhost_dev *hdev) { - cpu_unregister_phys_memory_client(&hdev->client); + memory_listener_unregister(&hdev->memory_listener); g_free(hdev->mem); + g_free(hdev->mem_sections); close(hdev->control); } @@ -808,8 +899,10 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) hdev->vqs + i, i); } - vhost_client_sync_dirty_bitmap(&hdev->client, 0, - (target_phys_addr_t)~0x0ull); + for (i = 0; i < hdev->n_mem_sections; ++i) { + vhost_sync_dirty_bitmap(hdev, &hdev->mem_sections[i], + 0, (target_phys_addr_t)~0x0ull); + } r = vdev->binding->set_guest_notifiers(vdev->binding_opaque, false); if (r < 0) { fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r); diff --git a/hw/vhost.h b/hw/vhost.h index c9452f0732..80e64df860 100644 --- a/hw/vhost.h +++ b/hw/vhost.h @@ -3,6 +3,7 @@ #include "hw/hw.h" #include "hw/virtio.h" +#include "memory.h" /* Generic structures common for any vhost based device. */ struct vhost_virtqueue { @@ -26,9 +27,11 @@ typedef unsigned long vhost_log_chunk_t; struct vhost_memory; struct vhost_dev { - CPUPhysMemoryClient client; + MemoryListener memory_listener; int control; struct vhost_memory *mem; + int n_mem_sections; + MemoryRegionSection *mem_sections; struct vhost_virtqueue *vqs; int nvqs; unsigned long long features; diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c index e24a2bf1f3..ce9d2c9759 100644 --- a/hw/virtio-balloon.c +++ b/hw/virtio-balloon.c @@ -21,6 +21,7 @@ #include "balloon.h" #include "virtio-balloon.h" #include "kvm.h" +#include "exec-memory.h" #if defined(__linux__) #include <sys/mman.h> @@ -70,6 +71,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) { VirtIOBalloon *s = to_virtio_balloon(vdev); VirtQueueElement elem; + MemoryRegionSection section; while (virtqueue_pop(vq, &elem)) { size_t offset = 0; @@ -82,13 +84,16 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) pa = (ram_addr_t)ldl_p(&pfn) << VIRTIO_BALLOON_PFN_SHIFT; offset += 4; - addr = cpu_get_physical_page_desc(pa); - if ((addr & ~TARGET_PAGE_MASK) != IO_MEM_RAM) + /* FIXME: remove get_system_memory(), but how? */ + section = memory_region_find(get_system_memory(), pa, 1); + if (!section.size || !memory_region_is_ram(section.mr)) continue; - /* Using qemu_get_ram_ptr is bending the rules a bit, but + /* Using memory_region_get_ram_ptr is bending the rules a bit, but should be OK because we only want a single page. */ - balloon_page(qemu_get_ram_ptr(addr), !!(vq == s->dvq)); + addr = section.offset_within_region; + balloon_page(memory_region_get_ram_ptr(section.mr) + addr, + !!(vq == s->dvq)); } virtqueue_push(vq, &elem, offset); @@ -49,6 +49,9 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, struct MemoryRegion *mr); #endif +struct MemoryRegion; +void xen_register_framebuffer(struct MemoryRegion *mr); + #if defined(CONFIG_XEN) && CONFIG_XEN_CTRL_INTERFACE_VERSION < 400 # define HVM_MAX_VCPUS 32 #endif |