Skip to content

Commit

Permalink
numa: Teach ram block notifiers about resizeable ram blocks
Browse files Browse the repository at this point in the history
Ram block notifiers are currently not aware of resizes. To properly
handle resizes during migration, we want to teach ram block notifiers about
resizeable ram.

Introduce the basic infrastructure but keep using max_size in the
existing notifiers. Supply the max_size when adding and removing ram
blocks. Also, notify on resizes.

Acked-by: Paul Durrant <paul@xen.org>
Reviewed-by: Peter Xu <peterx@redhat.com>
Cc: xen-devel@lists.xenproject.org
Cc: haxm-team@intel.com
Cc: Paul Durrant <paul@xen.org>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Wenchao Wang <wenchao.wang@intel.com>
Cc: Colin Xu <colin.xu@intel.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20210429112708.12291-3-david@redhat.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
  • Loading branch information
davidhildenbrand authored and dagrh committed May 13, 2021
1 parent 082851a commit 8f44304
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 32 deletions.
22 changes: 17 additions & 5 deletions hw/core/numa.c
Expand Up @@ -805,11 +805,12 @@ void query_numa_node_mem(NumaNodeMem node_mem[], MachineState *ms)
static int ram_block_notify_add_single(RAMBlock *rb, void *opaque)
{
const ram_addr_t max_size = qemu_ram_get_max_length(rb);
const ram_addr_t size = qemu_ram_get_used_length(rb);
void *host = qemu_ram_get_host_addr(rb);
RAMBlockNotifier *notifier = opaque;

if (host) {
notifier->ram_block_added(notifier, host, max_size);
notifier->ram_block_added(notifier, host, size, max_size);
}
return 0;
}
Expand All @@ -826,20 +827,31 @@ void ram_block_notifier_remove(RAMBlockNotifier *n)
QLIST_REMOVE(n, next);
}

void ram_block_notify_add(void *host, size_t size)
void ram_block_notify_add(void *host, size_t size, size_t max_size)
{
RAMBlockNotifier *notifier;

QLIST_FOREACH(notifier, &ram_list.ramblock_notifiers, next) {
notifier->ram_block_added(notifier, host, size);
notifier->ram_block_added(notifier, host, size, max_size);
}
}

void ram_block_notify_remove(void *host, size_t size)
void ram_block_notify_remove(void *host, size_t size, size_t max_size)
{
RAMBlockNotifier *notifier;

QLIST_FOREACH(notifier, &ram_list.ramblock_notifiers, next) {
notifier->ram_block_removed(notifier, host, size);
notifier->ram_block_removed(notifier, host, size, max_size);
}
}

void ram_block_notify_resize(void *host, size_t old_size, size_t new_size)
{
RAMBlockNotifier *notifier;

QLIST_FOREACH(notifier, &ram_list.ramblock_notifiers, next) {
if (notifier->ram_block_resized) {
notifier->ram_block_resized(notifier, host, old_size, new_size);
}
}
}
7 changes: 4 additions & 3 deletions hw/i386/xen/xen-mapcache.c
Expand Up @@ -169,7 +169,8 @@ static void xen_remap_bucket(MapCacheEntry *entry,

if (entry->vaddr_base != NULL) {
if (!(entry->flags & XEN_MAPCACHE_ENTRY_DUMMY)) {
ram_block_notify_remove(entry->vaddr_base, entry->size);
ram_block_notify_remove(entry->vaddr_base, entry->size,
entry->size);
}

/*
Expand Down Expand Up @@ -224,7 +225,7 @@ static void xen_remap_bucket(MapCacheEntry *entry,
}

if (!(entry->flags & XEN_MAPCACHE_ENTRY_DUMMY)) {
ram_block_notify_add(vaddr_base, size);
ram_block_notify_add(vaddr_base, size, size);
}

entry->vaddr_base = vaddr_base;
Expand Down Expand Up @@ -465,7 +466,7 @@ static void xen_invalidate_map_cache_entry_unlocked(uint8_t *buffer)
}

pentry->next = entry->next;
ram_block_notify_remove(entry->vaddr_base, entry->size);
ram_block_notify_remove(entry->vaddr_base, entry->size, entry->size);
if (munmap(entry->vaddr_base, entry->size) != 0) {
perror("unmap fails");
exit(-1);
Expand Down
13 changes: 9 additions & 4 deletions include/exec/ramlist.h
Expand Up @@ -65,15 +65,20 @@ void qemu_mutex_lock_ramlist(void);
void qemu_mutex_unlock_ramlist(void);

struct RAMBlockNotifier {
void (*ram_block_added)(RAMBlockNotifier *n, void *host, size_t size);
void (*ram_block_removed)(RAMBlockNotifier *n, void *host, size_t size);
void (*ram_block_added)(RAMBlockNotifier *n, void *host, size_t size,
size_t max_size);
void (*ram_block_removed)(RAMBlockNotifier *n, void *host, size_t size,
size_t max_size);
void (*ram_block_resized)(RAMBlockNotifier *n, void *host, size_t old_size,
size_t new_size);
QLIST_ENTRY(RAMBlockNotifier) next;
};

void ram_block_notifier_add(RAMBlockNotifier *n);
void ram_block_notifier_remove(RAMBlockNotifier *n);
void ram_block_notify_add(void *host, size_t size);
void ram_block_notify_remove(void *host, size_t size);
void ram_block_notify_add(void *host, size_t size, size_t max_size);
void ram_block_notify_remove(void *host, size_t size, size_t max_size);
void ram_block_notify_resize(void *host, size_t old_size, size_t new_size);

void ram_block_dump(Monitor *mon);

Expand Down
12 changes: 10 additions & 2 deletions softmmu/physmem.c
Expand Up @@ -1807,6 +1807,7 @@ static int memory_try_enable_merging(void *addr, size_t len)
*/
int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp)
{
const ram_addr_t oldsize = block->used_length;
const ram_addr_t unaligned_size = newsize;

assert(block);
Expand Down Expand Up @@ -1843,6 +1844,11 @@ int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp)
return -EINVAL;
}

/* Notify before modifying the ram block and touching the bitmaps. */
if (block->host) {
ram_block_notify_resize(block->host, oldsize, newsize);
}

cpu_physical_memory_clear_dirty_range(block->offset, block->used_length);
block->used_length = newsize;
cpu_physical_memory_set_dirty_range(block->offset, block->used_length,
Expand Down Expand Up @@ -2010,7 +2016,8 @@ static void ram_block_add(RAMBlock *new_block, Error **errp, bool shared)
qemu_madvise(new_block->host, new_block->max_length,
QEMU_MADV_DONTFORK);
}
ram_block_notify_add(new_block->host, new_block->max_length);
ram_block_notify_add(new_block->host, new_block->used_length,
new_block->max_length);
}
}

Expand Down Expand Up @@ -2189,7 +2196,8 @@ void qemu_ram_free(RAMBlock *block)
}

if (block->host) {
ram_block_notify_remove(block->host, block->max_length);
ram_block_notify_remove(block->host, block->used_length,
block->max_length);
}

qemu_mutex_lock_ramlist();
Expand Down
5 changes: 3 additions & 2 deletions target/i386/hax/hax-mem.c
Expand Up @@ -293,7 +293,8 @@ static MemoryListener hax_memory_listener = {
.priority = 10,
};

static void hax_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
static void hax_ram_block_added(RAMBlockNotifier *n, void *host, size_t size,
size_t max_size)
{
/*
* We must register each RAM block with the HAXM kernel module, or
Expand All @@ -304,7 +305,7 @@ static void hax_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
* host physical pages for the RAM block as part of this registration
* process, hence the name hax_populate_ram().
*/
if (hax_populate_ram((uint64_t)(uintptr_t)host, size) < 0) {
if (hax_populate_ram((uint64_t)(uintptr_t)host, max_size) < 0) {
fprintf(stderr, "HAX failed to populate RAM\n");
abort();
}
Expand Down
18 changes: 10 additions & 8 deletions target/i386/sev.c
Expand Up @@ -180,7 +180,8 @@ sev_set_guest_state(SevGuestState *sev, SevState new_state)
}

static void
sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size,
size_t max_size)
{
int r;
struct kvm_enc_region range;
Expand All @@ -197,19 +198,20 @@ sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
}

range.addr = (__u64)(unsigned long)host;
range.size = size;
range.size = max_size;

trace_kvm_memcrypt_register_region(host, size);
trace_kvm_memcrypt_register_region(host, max_size);
r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
if (r) {
error_report("%s: failed to register region (%p+%#zx) error '%s'",
__func__, host, size, strerror(errno));
__func__, host, max_size, strerror(errno));
exit(1);
}
}

static void
sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size,
size_t max_size)
{
int r;
struct kvm_enc_region range;
Expand All @@ -226,13 +228,13 @@ sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
}

range.addr = (__u64)(unsigned long)host;
range.size = size;
range.size = max_size;

trace_kvm_memcrypt_unregister_region(host, size);
trace_kvm_memcrypt_unregister_region(host, max_size);
r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range);
if (r) {
error_report("%s: failed to unregister region (%p+%#zx)",
__func__, host, size);
__func__, host, max_size);
}
}

Expand Down
16 changes: 8 additions & 8 deletions util/vfio-helpers.c
Expand Up @@ -459,26 +459,26 @@ static int qemu_vfio_init_pci(QEMUVFIOState *s, const char *device,
return ret;
}

static void qemu_vfio_ram_block_added(RAMBlockNotifier *n,
void *host, size_t size)
static void qemu_vfio_ram_block_added(RAMBlockNotifier *n, void *host,
size_t size, size_t max_size)
{
QEMUVFIOState *s = container_of(n, QEMUVFIOState, ram_notifier);
int ret;

trace_qemu_vfio_ram_block_added(s, host, size);
ret = qemu_vfio_dma_map(s, host, size, false, NULL);
trace_qemu_vfio_ram_block_added(s, host, max_size);
ret = qemu_vfio_dma_map(s, host, max_size, false, NULL);
if (ret) {
error_report("qemu_vfio_dma_map(%p, %zu) failed: %s", host, size,
error_report("qemu_vfio_dma_map(%p, %zu) failed: %s", host, max_size,
strerror(-ret));
}
}

static void qemu_vfio_ram_block_removed(RAMBlockNotifier *n,
void *host, size_t size)
static void qemu_vfio_ram_block_removed(RAMBlockNotifier *n, void *host,
size_t size, size_t max_size)
{
QEMUVFIOState *s = container_of(n, QEMUVFIOState, ram_notifier);
if (host) {
trace_qemu_vfio_ram_block_removed(s, host, size);
trace_qemu_vfio_ram_block_removed(s, host, max_size);
qemu_vfio_dma_unmap(s, host);
}
}
Expand Down

0 comments on commit 8f44304

Please sign in to comment.