summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2012-01-03 14:39:05 -0600
committerAnthony Liguori <aliguori@us.ibm.com>2012-01-03 14:39:05 -0600
commitf3c6a169a39d188e98c17a0a0ebfa7f85e5aafdd (patch)
tree11e695213b30090174108824425014ddb5e76da2 /hw
parent8d3bc5178fbc06cdd89c064ae8f44e77c503e91e (diff)
parent586c6230c012d1aced38e5a5614d15052ca4ae7a (diff)
downloadqemu-f3c6a169a39d188e98c17a0a0ebfa7f85e5aafdd.tar.gz
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.c32
-rw-r--r--hw/framebuffer.h3
-rw-r--r--hw/loader.c9
-rw-r--r--hw/milkymist-vgafb.c2
-rw-r--r--hw/omap_lcdc.c4
-rw-r--r--hw/pl110.c2
-rw-r--r--hw/pxa2xx_lcd.c10
-rw-r--r--hw/sysbus.c5
-rw-r--r--hw/sysbus.h1
-rw-r--r--hw/vga.c2
-rw-r--r--hw/vhost.c167
-rw-r--r--hw/vhost.h5
-rw-r--r--hw/virtio-balloon.c13
-rw-r--r--hw/xen.h3
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,
diff --git a/hw/vga.c b/hw/vga.c
index ca79aa157d..7e1dd5ac80 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -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);
diff --git a/hw/xen.h b/hw/xen.h
index f9f66e83ef..b46879c6f7 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -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