From 7376e5827a898d8ddf10f929047cc84bf65d9f52 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 8 Feb 2012 21:05:17 +0200 Subject: [PATCH] memory: allow MemoryListeners to observe a specific address space Ignore any regions not belonging to a specified address space. Signed-off-by: Avi Kivity --- exec.c | 2 +- hw/vhost.c | 2 +- kvm-all.c | 2 +- memory.c | 45 +++++++++++++++++++++++++++++++++++++++------ memory.h | 4 +++- xen-all.c | 2 +- 6 files changed, 46 insertions(+), 11 deletions(-) diff --git a/exec.c b/exec.c index 7fb5d4e8ed..aa54eb1d7b 100644 --- a/exec.c +++ b/exec.c @@ -3571,7 +3571,7 @@ static void memory_map_init(void) memory_region_init(system_io, "io", 65536); set_system_io_map(system_io); - memory_listener_register(&core_memory_listener); + memory_listener_register(&core_memory_listener, NULL); } MemoryRegion *get_system_memory(void) diff --git a/hw/vhost.c b/hw/vhost.c index e1e7e01584..01f676a959 100644 --- a/hw/vhost.c +++ b/hw/vhost.c @@ -774,7 +774,7 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force) hdev->log_size = 0; hdev->log_enabled = false; hdev->started = false; - memory_listener_register(&hdev->memory_listener); + memory_listener_register(&hdev->memory_listener, NULL); hdev->force = force; return 0; fail: diff --git a/kvm-all.c b/kvm-all.c index a05e591c59..15bc42fcdb 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1049,7 +1049,7 @@ int kvm_init(void) } kvm_state = s; - memory_listener_register(&kvm_memory_listener); + memory_listener_register(&kvm_memory_listener, NULL); s->many_ioeventfds = kvm_check_many_ioeventfds(); diff --git a/memory.c b/memory.c index 12ba60f703..35e1483859 100644 --- a/memory.c +++ b/memory.c @@ -84,7 +84,14 @@ static AddrRange addrrange_intersection(AddrRange r1, AddrRange r2) enum ListenerDirection { Forward, Reverse }; -#define MEMORY_LISTENER_CALL(_callback, _direction, _args...) \ +static bool memory_listener_match(MemoryListener *listener, + MemoryRegionSection *section) +{ + return !listener->address_space_filter + || listener->address_space_filter == section->address_space; +} + +#define MEMORY_LISTENER_CALL_GLOBAL(_callback, _direction, _args...) \ do { \ MemoryListener *_listener; \ \ @@ -105,15 +112,40 @@ enum ListenerDirection { Forward, Reverse }; } \ } while (0) +#define MEMORY_LISTENER_CALL(_callback, _direction, _section, _args...) \ + do { \ + MemoryListener *_listener; \ + \ + switch (_direction) { \ + case Forward: \ + QTAILQ_FOREACH(_listener, &memory_listeners, link) { \ + if (memory_listener_match(_listener, _section)) { \ + _listener->_callback(_listener, _section, ##_args); \ + } \ + } \ + break; \ + case Reverse: \ + QTAILQ_FOREACH_REVERSE(_listener, &memory_listeners, \ + memory_listeners, link) { \ + if (memory_listener_match(_listener, _section)) { \ + _listener->_callback(_listener, _section, ##_args); \ + } \ + } \ + break; \ + default: \ + abort(); \ + } \ + } while (0) + #define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback) \ - MEMORY_LISTENER_CALL(callback, dir, &(MemoryRegionSection) { \ + MEMORY_LISTENER_CALL(callback, dir, (&(MemoryRegionSection) { \ .mr = (fr)->mr, \ .address_space = (as)->root, \ .offset_within_region = (fr)->offset_in_region, \ .size = int128_get64((fr)->addr.size), \ .offset_within_address_space = int128_get64((fr)->addr.start), \ .readonly = (fr)->readonly, \ - }) + })) struct CoalescedMemoryRange { AddrRange addr; @@ -1382,13 +1414,13 @@ void memory_global_sync_dirty_bitmap(MemoryRegion *address_space) void memory_global_dirty_log_start(void) { global_dirty_log = true; - MEMORY_LISTENER_CALL(log_global_start, Forward); + MEMORY_LISTENER_CALL_GLOBAL(log_global_start, Forward); } void memory_global_dirty_log_stop(void) { global_dirty_log = false; - MEMORY_LISTENER_CALL(log_global_stop, Reverse); + MEMORY_LISTENER_CALL_GLOBAL(log_global_stop, Reverse); } static void listener_add_address_space(MemoryListener *listener, @@ -1412,10 +1444,11 @@ static void listener_add_address_space(MemoryListener *listener, } } -void memory_listener_register(MemoryListener *listener) +void memory_listener_register(MemoryListener *listener, MemoryRegion *filter) { MemoryListener *other = NULL; + listener->address_space_filter = filter; if (QTAILQ_EMPTY(&memory_listeners) || listener->priority >= QTAILQ_LAST(&memory_listeners, memory_listeners)->priority) { diff --git a/memory.h b/memory.h index 1d99cee019..bc9600b402 100644 --- a/memory.h +++ b/memory.h @@ -193,6 +193,7 @@ struct MemoryListener { bool match_data, uint64_t data, int fd); /* Lower = earlier (during add), later (during del) */ unsigned priority; + MemoryRegion *address_space_filter; QTAILQ_ENTRY(MemoryListener) link; }; @@ -685,8 +686,9 @@ void memory_region_transaction_commit(void); * space * * @listener: an object containing the callbacks to be called + * @filter: if non-%NULL, only regions in this address space will be observed */ -void memory_listener_register(MemoryListener *listener); +void memory_listener_register(MemoryListener *listener, MemoryRegion *filter); /** * memory_listener_unregister: undo the effect of memory_listener_register() diff --git a/xen-all.c b/xen-all.c index e005b63c7e..dd52f02573 100644 --- a/xen-all.c +++ b/xen-all.c @@ -989,7 +989,7 @@ int xen_hvm_init(void) state->memory_listener = xen_memory_listener; QLIST_INIT(&state->physmap); - memory_listener_register(&state->memory_listener); + memory_listener_register(&state->memory_listener, NULL); state->log_for_dirtybit = NULL; /* Initialize backend core & drivers */