KVM_CAP_LAST_INFO
};
+#define kvm_slots_lock(kml) qemu_mutex_lock(&(kml)->slots_lock)
+#define kvm_slots_unlock(kml) qemu_mutex_unlock(&(kml)->slots_lock)
+
int kvm_get_max_memslots(void)
{
KVMState *s = KVM_STATE(current_machine->accelerator);
return 1;
}
+/* Called with KVMMemoryListener.slots_lock held */
static KVMSlot *kvm_get_free_slot(KVMMemoryListener *kml)
{
KVMState *s = kvm_state;
bool kvm_has_free_slot(MachineState *ms)
{
KVMState *s = KVM_STATE(ms->accelerator);
+ bool result;
+ KVMMemoryListener *kml = &s->memory_listener;
+
+ kvm_slots_lock(kml);
+ result = !!kvm_get_free_slot(kml);
+ kvm_slots_unlock(kml);
- return kvm_get_free_slot(&s->memory_listener);
+ return result;
}
+/* Called with KVMMemoryListener.slots_lock held */
static KVMSlot *kvm_alloc_slot(KVMMemoryListener *kml)
{
KVMSlot *slot = kvm_get_free_slot(kml);
hwaddr *phys_addr)
{
KVMMemoryListener *kml = &s->memory_listener;
- int i;
+ int i, ret = 0;
+ kvm_slots_lock(kml);
for (i = 0; i < s->nr_slots; i++) {
KVMSlot *mem = &kml->slots[i];
if (ram >= mem->ram && ram < mem->ram + mem->memory_size) {
*phys_addr = mem->start_addr + (ram - mem->ram);
- return 1;
+ ret = 1;
+ break;
}
}
+ kvm_slots_unlock(kml);
- return 0;
+ return ret;
}
static int kvm_set_user_memory_region(KVMMemoryListener *kml, KVMSlot *slot, bool new)
return flags;
}
+/* Called with KVMMemoryListener.slots_lock held */
static int kvm_slot_update_flags(KVMMemoryListener *kml, KVMSlot *mem,
MemoryRegion *mr)
{
{
hwaddr start_addr, size;
KVMSlot *mem;
+ int ret = 0;
size = kvm_align_section(section, &start_addr);
if (!size) {
return 0;
}
+ kvm_slots_lock(kml);
+
mem = kvm_lookup_matching_slot(kml, start_addr, size);
if (!mem) {
/* We don't have a slot if we want to trap every access. */
- return 0;
+ goto out;
}
- return kvm_slot_update_flags(kml, mem, section->mr);
+ ret = kvm_slot_update_flags(kml, mem, section->mr);
+
+out:
+ kvm_slots_unlock(kml);
+ return ret;
}
static void kvm_log_start(MemoryListener *listener,
* This function will first try to fetch dirty bitmap from the kernel,
* and then updates qemu's dirty bitmap.
*
+ * NOTE: caller must be with kml->slots_lock held.
+ *
* @kml: the KVM memory listener object
* @section: the memory section to sync the dirty bitmap with
*/
struct kvm_dirty_log d = {};
KVMSlot *mem;
hwaddr start_addr, size;
+ int ret = 0;
size = kvm_align_section(section, &start_addr);
if (size) {
mem = kvm_lookup_matching_slot(kml, start_addr, size);
if (!mem) {
/* We don't have a slot if we want to trap every access. */
- return 0;
+ goto out;
}
/* XXX bad kernel interface alert
d.slot = mem->slot | (kml->as_id << 16);
if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) {
DPRINTF("ioctl failed %d\n", errno);
- return -1;
+ ret = -1;
+ goto out;
}
kvm_get_dirty_pages_log_range(section, d.dirty_bitmap);
}
-
- return 0;
+out:
+ return ret;
}
static void kvm_coalesce_mmio_region(MemoryListener *listener,
ram = memory_region_get_ram_ptr(mr) + section->offset_within_region +
(start_addr - section->offset_within_address_space);
+ kvm_slots_lock(kml);
+
if (!add) {
mem = kvm_lookup_matching_slot(kml, start_addr, size);
if (!mem) {
- return;
+ goto out;
}
if (mem->flags & KVM_MEM_LOG_DIRTY_PAGES) {
kvm_physical_sync_dirty_bitmap(kml, section);
__func__, strerror(-err));
abort();
}
- return;
+ goto out;
}
/* register the new slot */
strerror(-err));
abort();
}
+
+out:
+ kvm_slots_unlock(kml);
}
static void kvm_region_add(MemoryListener *listener,
KVMMemoryListener *kml = container_of(listener, KVMMemoryListener, listener);
int r;
+ kvm_slots_lock(kml);
r = kvm_physical_sync_dirty_bitmap(kml, section);
+ kvm_slots_unlock(kml);
if (r < 0) {
abort();
}
{
int i;
+ qemu_mutex_init(&kml->slots_lock);
kml->slots = g_malloc0(s->nr_slots * sizeof(KVMSlot));
kml->as_id = as_id;