Commit 7376e582 authored by Avi Kivity's avatar Avi Kivity
Browse files

memory: allow MemoryListeners to observe a specific address space



Ignore any regions not belonging to a specified address space.

Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 8df8a843
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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)
+1 −1
Original line number Diff line number Diff line
@@ -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:
+1 −1
Original line number Diff line number Diff line
@@ -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();

+39 −6
Original line number Diff line number Diff line
@@ -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) {
+3 −1
Original line number Diff line number Diff line
@@ -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()
Loading