From patchwork Fri Sep 9 08:11:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Emanuele Giuseppe Esposito X-Patchwork-Id: 12971224 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 88D88ECAAD3 for ; Fri, 9 Sep 2022 08:28:56 +0000 (UTC) Received: from localhost ([::1]:43728 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oWZNf-0003pq-IZ for qemu-devel@archiver.kernel.org; Fri, 09 Sep 2022 04:28:55 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:54790) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oWZ7N-0008DL-TD for qemu-devel@nongnu.org; Fri, 09 Sep 2022 04:12:09 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]:39190) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oWZ7J-0003Ph-6l for qemu-devel@nongnu.org; Fri, 09 Sep 2022 04:12:05 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1662711120; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Dv8E089/Ce3sIyDZyw/7/MM/uy1FTYMuPvEb8JTQjDM=; b=ARTv0ijpj7KkYRgJAy3+ExqYbIR9hR1y46KY02ECogp/L9JkEwXdTdoTojX9ouNMFI1rf7 s94ZnCUKbEi9esKxJyHnwRPq3EK0O1+cJWJ36nfMVu0rJgNDURm6DC+R+a+Pl8gekvQ1km J4ZJXS2N3TQwLsbowtwHe6J+Zzo6/TI= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-249-1dsDE7UqPz6AH0JP1Uuj6w-1; Fri, 09 Sep 2022 04:11:56 -0400 X-MC-Unique: 1dsDE7UqPz6AH0JP1Uuj6w-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 263E0101E167; Fri, 9 Sep 2022 08:11:56 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id D4D2A400EA8F; Fri, 9 Sep 2022 08:11:55 +0000 (UTC) From: Emanuele Giuseppe Esposito To: qemu-devel@nongnu.org Cc: Paolo Bonzini , "Michael S. Tsirkin" , Cornelia Huck , Peter Xu , David Hildenbrand , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Maxim Levitsky , kvm@vger.kernel.org, Emanuele Giuseppe Esposito Subject: [RFC PATCH v2 1/3] linux-headers/linux/kvm.h: introduce kvm_userspace_memory_region_list ioctl Date: Fri, 9 Sep 2022 04:11:48 -0400 Message-Id: <20220909081150.709060-2-eesposit@redhat.com> In-Reply-To: <20220909081150.709060-1-eesposit@redhat.com> References: <20220909081150.709060-1-eesposit@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.11.54.1 Received-SPF: pass client-ip=170.10.129.124; envelope-from=eesposit@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Introduce new KVM_SET_USER_MEMORY_REGION_LIST ioctl and kvm_userspace_memory_region_list that will be used to pass multiple memory region updates at once to KVM. Signed-off-by: Emanuele Giuseppe Esposito --- linux-headers/linux/kvm.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index f089349149..671cdfb8de 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -103,6 +103,24 @@ struct kvm_userspace_memory_region { __u64 userspace_addr; /* start of the userspace allocated memory */ }; +/* for KVM_SET_USER_MEMORY_REGION_LIST */ +struct kvm_userspace_memory_region_entry { + __u32 slot; + __u32 flags; + __u64 guest_phys_addr; + __u64 memory_size; /* bytes */ + __u64 userspace_addr; /* start of the userspace allocated memory */ + __u8 invalidate_slot; + __u8 padding[31]; +}; + +/* for KVM_SET_USER_MEMORY_REGION_LIST */ +struct kvm_userspace_memory_region_list { + __u32 nent; + __u32 flags; + struct kvm_userspace_memory_region_entry entries[0]; +}; + /* * The bit 0 ~ bit 15 of kvm_memory_region::flags are visible for userspace, * other bits are reserved for kvm internal use which are defined in @@ -1426,6 +1444,8 @@ struct kvm_vfio_spapr_tce { struct kvm_userspace_memory_region) #define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47) #define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64) +#define KVM_SET_USER_MEMORY_REGION_LIST _IOW(KVMIO, 0x49, \ + struct kvm_userspace_memory_region_list) /* enable ucontrol for s390 */ struct kvm_s390_ucas_mapping { From patchwork Fri Sep 9 08:11:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Emanuele Giuseppe Esposito X-Patchwork-Id: 12971221 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A56CEECAAA1 for ; Fri, 9 Sep 2022 08:24:51 +0000 (UTC) Received: from localhost ([::1]:50642 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oWZJi-0008L5-Cx for qemu-devel@archiver.kernel.org; Fri, 09 Sep 2022 04:24:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51850) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oWZ7M-00089q-Pg for qemu-devel@nongnu.org; Fri, 09 Sep 2022 04:12:05 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:24619) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oWZ7J-0003Pn-Fx for qemu-devel@nongnu.org; Fri, 09 Sep 2022 04:12:02 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1662711120; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WfbTGILIwnlqrhBy2hpfPOMOrZst7fDmliV6QGcqmGY=; b=iO1WsOFomZvJ6cfNamYUw1aYsosHVhwlQXw7sUIZHai+LZY4SSU48mA/xrbJ5aVA7pXJS1 Ti1jPaxZvppM6pCnhFxnjXlqa6PFy8OY+Pk8mRaagobbQF7tdbz7r/HyN72rLYlivXxlLN 4+yF8EWuFnYoSlwr0w3oIhL5EGgzZ60= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-462-0YNmnC_oO_m-mxQhTD3Adg-1; Fri, 09 Sep 2022 04:11:56 -0400 X-MC-Unique: 0YNmnC_oO_m-mxQhTD3Adg-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 73129185A7A4; Fri, 9 Sep 2022 08:11:56 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2EB524011960; Fri, 9 Sep 2022 08:11:56 +0000 (UTC) From: Emanuele Giuseppe Esposito To: qemu-devel@nongnu.org Cc: Paolo Bonzini , "Michael S. Tsirkin" , Cornelia Huck , Peter Xu , David Hildenbrand , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Maxim Levitsky , kvm@vger.kernel.org, Emanuele Giuseppe Esposito Subject: [RFC PATCH v2 2/3] accel/kvm/kvm-all.c: pass kvm_userspace_memory_region_entry instead Date: Fri, 9 Sep 2022 04:11:49 -0400 Message-Id: <20220909081150.709060-3-eesposit@redhat.com> In-Reply-To: <20220909081150.709060-1-eesposit@redhat.com> References: <20220909081150.709060-1-eesposit@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.11.54.1 Received-SPF: pass client-ip=170.10.133.124; envelope-from=eesposit@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" It won't change anything from the kernel side, but prepares the logic for KVM_SET_USER_MEMORY_REGION_LIST ioctl, where all requests are sent at once. Because QEMU does not send any memslot MOVE request to KVM, simplify mem.invalidate_slot logic to only detect DELETE requests. Signed-off-by: Emanuele Giuseppe Esposito --- accel/kvm/kvm-all.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 645f0a249a..e9947ec18b 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -360,7 +360,7 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram, static int kvm_set_user_memory_region(KVMMemoryListener *kml, KVMSlot *slot, bool new) { KVMState *s = kvm_state; - struct kvm_userspace_memory_region mem; + struct kvm_userspace_memory_region_entry mem; int ret; mem.slot = slot->slot | (kml->as_id << 16); @@ -372,12 +372,29 @@ static int kvm_set_user_memory_region(KVMMemoryListener *kml, KVMSlot *slot, boo /* Set the slot size to 0 before setting the slot to the desired * value. This is needed based on KVM commit 75d61fbc. */ mem.memory_size = 0; + mem.invalidate_slot = 1; + /* + * Note that mem is struct kvm_userspace_memory_region_entry, while the + * kernel expects a kvm_userspace_memory_region, so it will currently + * ignore mem->invalidate_slot and mem->padding. + */ ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem); if (ret < 0) { goto err; } } mem.memory_size = slot->memory_size; + /* + * Invalidate if it's a kvm memslot MOVE or DELETE operation, but + * currently QEMU does not perform any memslot MOVE operation. + */ + mem.invalidate_slot = slot->memory_size == 0; + + /* + * Note that mem is struct kvm_userspace_memory_region_entry, while the + * kernel expects a kvm_userspace_memory_region, so it will currently + * ignore mem->invalidate_slot and mem->padding. + */ ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem); slot->old_flags = mem.flags; err: From patchwork Fri Sep 9 08:11:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Emanuele Giuseppe Esposito X-Patchwork-Id: 12971225 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B621BECAAD3 for ; Fri, 9 Sep 2022 08:32:43 +0000 (UTC) Received: from localhost ([::1]:33392 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oWZRK-0005oG-KC for qemu-devel@archiver.kernel.org; Fri, 09 Sep 2022 04:32:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:54792) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oWZ7O-0008DQ-4J for qemu-devel@nongnu.org; Fri, 09 Sep 2022 04:12:09 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:44826) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oWZ7J-0003Pi-93 for qemu-devel@nongnu.org; Fri, 09 Sep 2022 04:12:05 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1662711120; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OaVxRmOqhUa1BGCUbms2VhwQdBBdao4awVXqKCRWbOw=; b=a34oYsr7NzCU6K/y05f/5qtzRsEOU89KoNC2/fzE+lrwK3mTWCoeu/M4TYfg9j9Hlb8E0K w1tv/V1gt0lIhzKH4Tg++ipA3qs0jByeETMrQkpl5NeiwyWZRK/YEmhX/5X+h9mCMUVmvk 3uyyZ5KGaTGfDku3fO8gow+e7kTji+U= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-424-ZxpyqabtNHedvw_2JaB1SA-1; Fri, 09 Sep 2022 04:11:57 -0400 X-MC-Unique: ZxpyqabtNHedvw_2JaB1SA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id C6FAB1C05AAD; Fri, 9 Sep 2022 08:11:56 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7D266400EA8F; Fri, 9 Sep 2022 08:11:56 +0000 (UTC) From: Emanuele Giuseppe Esposito To: qemu-devel@nongnu.org Cc: Paolo Bonzini , "Michael S. Tsirkin" , Cornelia Huck , Peter Xu , David Hildenbrand , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Maxim Levitsky , kvm@vger.kernel.org, Emanuele Giuseppe Esposito Subject: [RFC PATCH v2 3/3] kvm/kvm-all.c: listener should delay kvm_vm_ioctl to the commit phase Date: Fri, 9 Sep 2022 04:11:50 -0400 Message-Id: <20220909081150.709060-4-eesposit@redhat.com> In-Reply-To: <20220909081150.709060-1-eesposit@redhat.com> References: <20220909081150.709060-1-eesposit@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.11.54.1 Received-SPF: pass client-ip=170.10.133.124; envelope-from=eesposit@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Instead of sending a single ioctl every time ->region_* or ->log_* callbacks are called, "queue" all memory regions in a kvm_userspace_memory_region_list that will be sent only when committing. This allow the KVM kernel API to be extended and support multiple memslots updates in a single call. Signed-off-by: Emanuele Giuseppe Esposito --- accel/kvm/kvm-all.c | 131 ++++++++++++++++++++++++++------------- include/sysemu/kvm_int.h | 8 +++ 2 files changed, 96 insertions(+), 43 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index e9947ec18b..9780f3d2da 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -357,56 +357,50 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram, return ret; } +static struct kvm_userspace_memory_region_entry *kvm_memory_region_entry_get( + KVMMemoryListener *kml) +{ + struct MemoryRegionNodeArray *arr = &kml->mem_array; + struct kvm_userspace_memory_region_list *list = arr->list; + + if (list->nent == arr->max_entries) { + arr->max_entries += DEFAULT_KVM_MEMORY_REGION_ARRAY_GROW; + list = g_realloc(list, + sizeof(struct kvm_userspace_memory_region_list) + + arr->max_entries * + sizeof(struct kvm_userspace_memory_region_entry)); + } + + return &list->entries[list->nent++]; +} + static int kvm_set_user_memory_region(KVMMemoryListener *kml, KVMSlot *slot, bool new) { - KVMState *s = kvm_state; - struct kvm_userspace_memory_region_entry mem; - int ret; + struct kvm_userspace_memory_region_entry *mem; + + mem = kvm_memory_region_entry_get(kml); + + mem->slot = slot->slot | (kml->as_id << 16); + mem->guest_phys_addr = slot->start_addr; + mem->userspace_addr = (unsigned long)slot->ram; + mem->flags = slot->flags; - mem.slot = slot->slot | (kml->as_id << 16); - mem.guest_phys_addr = slot->start_addr; - mem.userspace_addr = (unsigned long)slot->ram; - mem.flags = slot->flags; + if (slot->memory_size && !new && (mem->flags ^ slot->old_flags) & + KVM_MEM_READONLY) { + struct kvm_userspace_memory_region_entry *mem2 = mem; - if (slot->memory_size && !new && (mem.flags ^ slot->old_flags) & KVM_MEM_READONLY) { + mem = kvm_memory_region_entry_get(kml); + memcpy(mem, mem2, sizeof(struct kvm_userspace_memory_region_entry)); /* Set the slot size to 0 before setting the slot to the desired * value. This is needed based on KVM commit 75d61fbc. */ - mem.memory_size = 0; - mem.invalidate_slot = 1; - /* - * Note that mem is struct kvm_userspace_memory_region_entry, while the - * kernel expects a kvm_userspace_memory_region, so it will currently - * ignore mem->invalidate_slot and mem->padding. - */ - ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem); - if (ret < 0) { - goto err; - } + mem2->memory_size = 0; + mem2->invalidate_slot = 1; } - mem.memory_size = slot->memory_size; - /* - * Invalidate if it's a kvm memslot MOVE or DELETE operation, but - * currently QEMU does not perform any memslot MOVE operation. - */ - mem.invalidate_slot = slot->memory_size == 0; + mem->memory_size = slot->memory_size; + mem->invalidate_slot = slot->memory_size == 0; - /* - * Note that mem is struct kvm_userspace_memory_region_entry, while the - * kernel expects a kvm_userspace_memory_region, so it will currently - * ignore mem->invalidate_slot and mem->padding. - */ - ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem); - slot->old_flags = mem.flags; -err: - trace_kvm_set_user_memory(mem.slot, mem.flags, mem.guest_phys_addr, - mem.memory_size, mem.userspace_addr, ret); - if (ret < 0) { - error_report("%s: KVM_SET_USER_MEMORY_REGION failed, slot=%d," - " start=0x%" PRIx64 ", size=0x%" PRIx64 ": %s", - __func__, mem.slot, slot->start_addr, - (uint64_t)mem.memory_size, strerror(errno)); - } - return ret; + slot->old_flags = mem->flags; + return 0; } static int do_kvm_destroy_vcpu(CPUState *cpu) @@ -1534,12 +1528,54 @@ static void kvm_region_add(MemoryListener *listener, static void kvm_region_del(MemoryListener *listener, MemoryRegionSection *section) { - KVMMemoryListener *kml = container_of(listener, KVMMemoryListener, listener); + KVMMemoryListener *kml = container_of(listener, KVMMemoryListener, + listener); kvm_set_phys_mem(kml, section, false); memory_region_unref(section->mr); } +static void kvm_begin(MemoryListener *listener) +{ + KVMMemoryListener *kml = container_of(listener, KVMMemoryListener, + listener); + assert(kml->mem_array.list->nent == 0); +} + +static void kvm_commit(MemoryListener *listener) +{ + KVMMemoryListener *kml = container_of(listener, KVMMemoryListener, + listener); + KVMState *s = kvm_state; + int i; + + for (i = 0; i < kml->mem_array.list->nent; i++) { + struct kvm_userspace_memory_region_entry *mem; + int ret; + + mem = &kml->mem_array.list->entries[i]; + + /* + * Note that mem is struct kvm_userspace_memory_region_entry, while the + * kernel expects a kvm_userspace_memory_region, so it will currently + * ignore mem->invalidate_slot and mem->padding. + */ + ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, mem); + + trace_kvm_set_user_memory(mem->slot, mem->flags, mem->guest_phys_addr, + mem->memory_size, mem->userspace_addr, 0); + + if (ret < 0) { + error_report("%s: KVM_SET_USER_MEMORY_REGION failed, slot=%d," + " start=0x%" PRIx64 ": %s", + __func__, mem->slot, + (uint64_t)mem->memory_size, strerror(errno)); + } + } + + kml->mem_array.list->nent = 0; +} + static void kvm_log_sync(MemoryListener *listener, MemoryRegionSection *section) { @@ -1681,8 +1717,16 @@ void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml, kml->slots[i].slot = i; } + kml->mem_array.max_entries = DEFAULT_KVM_MEMORY_REGION_ARRAY_GROW; + kml->mem_array.list = g_malloc0( + sizeof(struct kvm_userspace_memory_region_list) + + sizeof(struct kvm_userspace_memory_region_entry) * + kml->mem_array.max_entries); + kml->listener.region_add = kvm_region_add; kml->listener.region_del = kvm_region_del; + kml->listener.begin = kvm_begin; + kml->listener.commit = kvm_commit; kml->listener.log_start = kvm_log_start; kml->listener.log_stop = kvm_log_stop; kml->listener.priority = 10; @@ -2691,6 +2735,7 @@ err: close(s->fd); } g_free(s->memory_listener.slots); + g_free(s->memory_listener.mem_array.list); return ret; } diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h index 1f5487d9b7..1adc1c8722 100644 --- a/include/sysemu/kvm_int.h +++ b/include/sysemu/kvm_int.h @@ -30,9 +30,17 @@ typedef struct KVMSlot ram_addr_t ram_start_offset; } KVMSlot; +#define DEFAULT_KVM_MEMORY_REGION_ARRAY_GROW 10 + +struct MemoryRegionNodeArray { + struct kvm_userspace_memory_region_list *list; + int max_entries; +}; + typedef struct KVMMemoryListener { MemoryListener listener; KVMSlot *slots; + struct MemoryRegionNodeArray mem_array; int as_id; } KVMMemoryListener;