diff options
author | Avi Kivity <avi@redhat.com> | 2012-02-08 21:05:17 +0200 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2012-02-29 13:44:42 +0200 |
commit | 7376e5827a898d8ddf10f929047cc84bf65d9f52 (patch) | |
tree | af5ade26946ff09d19d950d66af6083c6f2f00d2 | |
parent | 8df8a8436fa22442a58b366fbb7e471b4a8d88ce (diff) |
memory: allow MemoryListeners to observe a specific address space
Ignore any regions not belonging to a specified address space.
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | exec.c | 2 | ||||
-rw-r--r-- | hw/vhost.c | 2 | ||||
-rw-r--r-- | kvm-all.c | 2 | ||||
-rw-r--r-- | memory.c | 45 | ||||
-rw-r--r-- | memory.h | 4 | ||||
-rw-r--r-- | xen-all.c | 2 |
6 files changed, 46 insertions, 11 deletions
@@ -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: @@ -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(); @@ -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) { @@ -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() @@ -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 */ |