static void vhost_client_set_memory(CPUPhysMemoryClient *client, target_phys_addr_t start_addr, ram_addr_t size, ram_addr_t phys_offset) { struct vhost_dev *dev = container_of(client, struct vhost_dev, client); ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK; int s = offsetof(struct vhost_memory, regions) + (dev->mem->nregions + 1) * sizeof dev->mem->regions[0]; uint64_t log_size; int r; dev->mem = qemu_realloc(dev->mem, s); assert(size); vhost_dev_unassign_memory(dev, start_addr, size); if (flags == IO_MEM_RAM) { /* Add given mapping, merging adjacent regions if any */ vhost_dev_assign_memory(dev, start_addr, size, (uintptr_t)qemu_get_ram_ptr(phys_offset)); } else { /* Remove old mapping for this memory, if any. */ vhost_dev_unassign_memory(dev, start_addr, size); } if (!dev->started) { return; } if (dev->started) { r = vhost_verify_ring_mappings(dev, start_addr, size); assert(r >= 0); } if (!dev->log_enabled) { r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem); assert(r >= 0); return; } log_size = vhost_get_log_size(dev); /* We allocate an extra 4K bytes to log, * to reduce the * number of reallocations. */ #define VHOST_LOG_BUFFER (0x1000 / sizeof *dev->log) /* To log more, must increase log size before table update. */ if (dev->log_size < log_size) { vhost_dev_log_resize(dev, log_size + VHOST_LOG_BUFFER); } r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem); assert(r >= 0); /* To log less, can only decrease log size after table update. */ if (dev->log_size > log_size + VHOST_LOG_BUFFER) { vhost_dev_log_resize(dev, log_size); } }
static int vhost_client_migration_log(CPUPhysMemoryClient *client, int enable) { struct vhost_dev *dev = container_of(client, struct vhost_dev, client); int r; if (!!enable == dev->log_enabled) { return 0; } if (!dev->started) { dev->log_enabled = enable; return 0; } if (!enable) { r = vhost_dev_set_log(dev, false); if (r < 0) { return r; } if (dev->log) { qemu_free(dev->log); } dev->log = NULL; dev->log_size = 0; } else { vhost_dev_log_resize(dev, vhost_get_log_size(dev)); r = vhost_dev_set_log(dev, true); if (r < 0) { return r; } } dev->log_enabled = enable; return 0; }
static int vhost_migration_log(MemoryListener *listener, int enable) { struct vhost_dev *dev = container_of(listener, struct vhost_dev, memory_listener); int r; if (!!enable == dev->log_enabled) { return 0; } if (!dev->started) { dev->log_enabled = enable; return 0; } if (!enable) { r = vhost_dev_set_log(dev, false); if (r < 0) { return r; } if (dev->log) { g_free(dev->log); } dev->log = NULL; dev->log_size = 0; } else { vhost_dev_log_resize(dev, vhost_get_log_size(dev)); r = vhost_dev_set_log(dev, true); if (r < 0) { return r; } } dev->log_enabled = enable; return 0; }
static void vhost_client_set_memory(CPUPhysMemoryClient *client, target_phys_addr_t start_addr, ram_addr_t size, ram_addr_t phys_offset) { struct vhost_dev *dev = container_of(client, struct vhost_dev, client); ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK; int s = offsetof(struct vhost_memory, regions) + (dev->mem->nregions + 1) * sizeof dev->mem->regions[0]; uint64_t log_size; int r; /* TODO: this is a hack. * At least one vga card (cirrus) changes the gpa to hva * memory maps on data path, which slows us down. * Since we should never need to DMA into VGA memory * anyway, lets just skip these regions. */ if (ranges_overlap(start_addr, size, 0xa0000, 0x10000)) { return; } dev->mem = qemu_realloc(dev->mem, s); assert(size); vhost_mem_unassign_memory(dev->mem, start_addr, size); if (flags == IO_MEM_RAM) { /* Add given mapping, merging adjacent regions if any */ vhost_mem_assign_memory(dev->mem, start_addr, size, (uintptr_t)qemu_get_ram_ptr(phys_offset)); } else { /* Remove old mapping for this memory, if any. */ vhost_mem_unassign_memory(dev->mem, start_addr, size); } if (!dev->started) { return; } if (dev->started) { r = vhost_verify_ring_mappings(dev, start_addr, size); assert(r >= 0); } if (!dev->log_enabled) { r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem); assert(r >= 0); return; } log_size = vhost_get_log_size(dev); /* We allocate an extra 4K bytes to log, * to reduce the * number of reallocations. */ #define VHOST_LOG_BUFFER (0x1000 / sizeof *dev->log) /* To log more, must increase log size before table update. */ if (dev->log_size < log_size) { vhost_dev_log_resize(dev, log_size + VHOST_LOG_BUFFER); } r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem); assert(r >= 0); /* To log less, can only decrease log size after table update. */ if (dev->log_size > log_size + VHOST_LOG_BUFFER) { vhost_dev_log_resize(dev, log_size); } }
static void vhost_set_memory(MemoryListener *listener, MemoryRegionSection *section, bool add) { 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; dev->mem = g_realloc(dev->mem, s); if (log_dirty) { add = false; } assert(size); /* Optimize no-change case. At least cirrus_vga does this a lot at this time. */ ram = memory_region_get_ram_ptr(section->mr) + section->offset_within_region; if (add) { if (!vhost_dev_cmp_memory(dev, start_addr, size, (uintptr_t)ram)) { /* Region exists with same address. Nothing to do. */ return; } } else { if (!vhost_dev_find_reg(dev, start_addr, size)) { /* Removing region that we don't access. Nothing to do. */ return; } } vhost_dev_unassign_memory(dev, start_addr, size); if (add) { /* Add given mapping, merging adjacent regions if any */ 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); } if (!dev->started) { return; } if (dev->started) { r = vhost_verify_ring_mappings(dev, start_addr, size); assert(r >= 0); } if (!dev->log_enabled) { r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem); assert(r >= 0); return; } log_size = vhost_get_log_size(dev); /* We allocate an extra 4K bytes to log, * to reduce the * number of reallocations. */ #define VHOST_LOG_BUFFER (0x1000 / sizeof *dev->log) /* To log more, must increase log size before table update. */ if (dev->log_size < log_size) { vhost_dev_log_resize(dev, log_size + VHOST_LOG_BUFFER); } r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem); assert(r >= 0); /* To log less, can only decrease log size after table update. */ if (dev->log_size > log_size + VHOST_LOG_BUFFER) { vhost_dev_log_resize(dev, log_size); } }