From patchwork Fri Sep 20 10:21:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 11154199 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6418B14E5 for ; Fri, 20 Sep 2019 10:22:30 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 3AC382086A for ; Fri, 20 Sep 2019 10:22:30 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="A0JNvVrR" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3AC382086A Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:57436 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iBG3Z-0007eC-93 for patchwork-qemu-devel@patchwork.kernel.org; Fri, 20 Sep 2019 06:22:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58709) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iBG2Z-0006TS-Oj for qemu-devel@nongnu.org; Fri, 20 Sep 2019 06:21:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iBG2Y-0004pG-IY for qemu-devel@nongnu.org; Fri, 20 Sep 2019 06:21:27 -0400 Received: from mail-wm1-x342.google.com ([2a00:1450:4864:20::342]:40303) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iBG2Y-0004oy-DK; Fri, 20 Sep 2019 06:21:26 -0400 Received: by mail-wm1-x342.google.com with SMTP id b24so1723280wmj.5; Fri, 20 Sep 2019 03:21:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=GBmysqlZGeXiOxLfV2wubdlWdwMk7uVesxCmd07aVgc=; b=A0JNvVrRS1hvL84Ghupg1hnm8vyxTWIFQsQjUncwmW09fxSD2JMa4cALbONyE05pPu phRZiMBFQY2OBB9xXklPX5i2PuNDqDL63++Sl1621dW11a3Di/qAeSFapzJEs/BVFxjS acPKJbCvM2ww06roIALie+1X8fjUmEq6Va+lDljT7+dMLvS6ONbo3y6srDCjcPvZ29Dg 4JQFOk83B0qIErX1nKr3KagFwsi2gJ5lZhsrKJq2aT5Is8TMBPBjPAJTpFk/zES1FHs9 b3eqCAWui5Pw05O4MltdoTa2wSlpFhlkykSa1N1NQ5d1VRx0GKnLaE5iqAxme4M+lLyY 2YNA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=GBmysqlZGeXiOxLfV2wubdlWdwMk7uVesxCmd07aVgc=; b=nWQnHU3L/3CMgHUebUfVtfFVWEtZwFt3io0Kbgdg8q2NMSSKMgR7SUuRcf/g/3CUMC 7vhmD1cJZQfYG/etwlUMmQDVI+NutG3RofVxbEgc8yyTbyE6YYOopsaY/+fJ8CRQrvac 2MAU8N16sonWz3HX1v9nKMY+8a5oZIijj4VhADReLuhhSQGqzfVTUHnWc1NhN8Rz94Ap o16dVnbcAyfjbDdYA/Td9jtJZLwYCwswIvnHJFyg4ysMfCkKNJDO2bvpRh5vSNOCapJ0 JTGwldGXdlaja/vTKfNokPaxLnbN1Rn55rO5Ik3rZSBRJz1vRR59exlZmjz4daXHstgx AAvQ== X-Gm-Message-State: APjAAAWMIQ7/DOBbKwjWIhAnvUiNZo+L3pbTeHVvL9R+LU3YLfce0HW1 dW1FdVF6nOw5cZlsf6yIfkLr/CkN X-Google-Smtp-Source: APXvYqzeNNkCC+W8me4F8I27T3GPnbUsEVBi3TQXEO1ggCQJv39v+iEv+fYpgqiXFFODk2v0321j8Q== X-Received: by 2002:a1c:3803:: with SMTP id f3mr3093504wma.161.1568974885051; Fri, 20 Sep 2019 03:21:25 -0700 (PDT) Received: from 640k.lan ([93.56.166.5]) by smtp.gmail.com with ESMTPSA id u10sm1331274wmm.0.2019.09.20.03.21.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 20 Sep 2019 03:21:24 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH 1/2] kvm: extract kvm_log_clear_one_slot Date: Fri, 20 Sep 2019 12:21:21 +0200 Message-Id: <1568974882-7419-2-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1568974882-7419-1-git-send-email-pbonzini@redhat.com> References: <1568974882-7419-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::342 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: dgilbert@redhat.com, peterx@redhat.com, qemu-stable@nongnu.org Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" We may need to clear the dirty bitmap for more than one KVM memslot. First do some code movement with no semantic change. Cc: qemu-stable@nongnu.org Signed-off-by: Paolo Bonzini Reviewed-by: Peter Xu --- accel/kvm/kvm-all.c | 102 ++++++++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 46 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index b09bad0..e9e6086 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -575,55 +575,13 @@ out: #define KVM_CLEAR_LOG_ALIGN (qemu_real_host_page_size << KVM_CLEAR_LOG_SHIFT) #define KVM_CLEAR_LOG_MASK (-KVM_CLEAR_LOG_ALIGN) -/** - * kvm_physical_log_clear - Clear the kernel's dirty bitmap for range - * - * NOTE: this will be a no-op if we haven't enabled manual dirty log - * protection in the host kernel because in that case this operation - * will be done within log_sync(). - * - * @kml: the kvm memory listener - * @section: the memory range to clear dirty bitmap - */ -static int kvm_physical_log_clear(KVMMemoryListener *kml, - MemoryRegionSection *section) +static int kvm_log_clear_one_slot(KVMSlot *mem, int as_id, uint64_t start, uint64_t size) { KVMState *s = kvm_state; + uint64_t end, bmap_start, start_delta, bmap_npages; struct kvm_clear_dirty_log d; - uint64_t start, end, bmap_start, start_delta, bmap_npages, size; unsigned long *bmap_clear = NULL, psize = qemu_real_host_page_size; - KVMSlot *mem = NULL; - int ret, i; - - if (!s->manual_dirty_log_protect) { - /* No need to do explicit clear */ - return 0; - } - - start = section->offset_within_address_space; - size = int128_get64(section->size); - - if (!size) { - /* Nothing more we can do... */ - return 0; - } - - kvm_slots_lock(kml); - - /* Find any possible slot that covers the section */ - for (i = 0; i < s->nr_slots; i++) { - mem = &kml->slots[i]; - if (mem->start_addr <= start && - start + size <= mem->start_addr + mem->memory_size) { - break; - } - } - - /* - * We should always find one memslot until this point, otherwise - * there could be something wrong from the upper layer - */ - assert(mem && i != s->nr_slots); + int ret; /* * We need to extend either the start or the size or both to @@ -694,7 +652,7 @@ static int kvm_physical_log_clear(KVMMemoryListener *kml, /* It should never overflow. If it happens, say something */ assert(bmap_npages <= UINT32_MAX); d.num_pages = bmap_npages; - d.slot = mem->slot | (kml->as_id << 16); + d.slot = mem->slot | (as_id << 16); if (kvm_vm_ioctl(s, KVM_CLEAR_DIRTY_LOG, &d) == -1) { ret = -errno; @@ -717,6 +675,58 @@ static int kvm_physical_log_clear(KVMMemoryListener *kml, size / psize); /* This handles the NULL case well */ g_free(bmap_clear); + return ret; +} + + +/** + * kvm_physical_log_clear - Clear the kernel's dirty bitmap for range + * + * NOTE: this will be a no-op if we haven't enabled manual dirty log + * protection in the host kernel because in that case this operation + * will be done within log_sync(). + * + * @kml: the kvm memory listener + * @section: the memory range to clear dirty bitmap + */ +static int kvm_physical_log_clear(KVMMemoryListener *kml, + MemoryRegionSection *section) +{ + KVMState *s = kvm_state; + uint64_t start, size; + KVMSlot *mem = NULL; + int ret, i; + + if (!s->manual_dirty_log_protect) { + /* No need to do explicit clear */ + return 0; + } + + start = section->offset_within_address_space; + size = int128_get64(section->size); + + if (!size) { + /* Nothing more we can do... */ + return 0; + } + + kvm_slots_lock(kml); + + /* Find any possible slot that covers the section */ + for (i = 0; i < s->nr_slots; i++) { + mem = &kml->slots[i]; + if (mem->start_addr <= start && + start + size <= mem->start_addr + mem->memory_size) { + break; + } + } + + /* + * We should always find one memslot until this point, otherwise + * there could be something wrong from the upper layer + */ + assert(mem && i != s->nr_slots); + ret = kvm_log_clear_one_slot(mem, kml->as_id, start, size); kvm_slots_unlock(kml); From patchwork Fri Sep 20 10:21:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 11154201 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EE020195A for ; Fri, 20 Sep 2019 10:24:03 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id C55062086A for ; Fri, 20 Sep 2019 10:24:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="LSjJ/snW" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C55062086A Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:57456 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iBG54-0000nh-VA for patchwork-qemu-devel@patchwork.kernel.org; Fri, 20 Sep 2019 06:24:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58719) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iBG2a-0006TZ-LX for qemu-devel@nongnu.org; Fri, 20 Sep 2019 06:21:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iBG2Z-0004pY-Cm for qemu-devel@nongnu.org; Fri, 20 Sep 2019 06:21:28 -0400 Received: from mail-wm1-x344.google.com ([2a00:1450:4864:20::344]:53872) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iBG2Z-0004pL-7v; Fri, 20 Sep 2019 06:21:27 -0400 Received: by mail-wm1-x344.google.com with SMTP id i16so1850825wmd.3; Fri, 20 Sep 2019 03:21:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=DgP8/pEnm8kvMDx4y/uLQ5qKZyMG7wRIy9Zx1xfwJ+A=; b=LSjJ/snWlox2WJDWTtfQS7lL2dF/2ZodmjaSkdaWN9rJse2MamJqJXTYQ5aQY1slBi ngXtIt4j2JUUiErSf+rcO+1VI5J3Jqsh5LrM3GuBOkBUgu2MRfy91u4aTLQFi4ijeMF7 9EGF7xNarX9hzWVxLQxZXVlwyef1ffGRgz+m/uhjlDawsxoMoVvr5q/Upx1aijBFRvS0 PQ+fAR0feQd9d6ht5wGbw6sG2gQ0+puJ274blRM5NXAZXkErQtgUSr8pZVsGnegEZBVt NXP0PSkAF0totp32x/SuwD/JPPrDStwhTV2Mxyvbs9KOfojb8W+VIxVXJAJ2KFqGkRV9 UPWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=DgP8/pEnm8kvMDx4y/uLQ5qKZyMG7wRIy9Zx1xfwJ+A=; b=aZzSbDXZc6qjC2DXc3c/iDkTo4z6KP8PwZceycOkjp0HBm2li3CUwoVEZ1rxmZOB5n O0qE133H3QLmpkulxi5lfYEG1AkTJ4l13XP7VVji1VVRM/CKpcmjQgoLZB7O4/EJeWtF 8LVVnf69rr6IfDOTc2nHaAVRIA7f5FofDo7wKCD2lMRXWe5TYXpW74zoHRMdldJ6J/4E HfZHK5iTD94FJlP72N58zuI7dAsl+DoHJmKT0w2S/2X9rWzyk0rIPbfWTpQTuOLHi3Qe PWWgy3UtratqFz3yri4kwqX/C3AYhA/uoEe652dW6Dqyt/LD3/Y+t2rNGIoizz79Frt2 FBPg== X-Gm-Message-State: APjAAAXxpxO10FrmtY4i3sgxYwx18TAQzExfA7ZEayaX18nDRUXrjYLf A1gHejvOLsP/g7xvCLqWs+0JQAKu X-Google-Smtp-Source: APXvYqytK/KN2dxGYQvkw5ooNAo5uIgPCenPypzuAcGLGf2c7tbm4MWm6tib2wIKjIMlvM/yolgC8A== X-Received: by 2002:a05:600c:2208:: with SMTP id z8mr3091863wml.113.1568974886040; Fri, 20 Sep 2019 03:21:26 -0700 (PDT) Received: from 640k.lan ([93.56.166.5]) by smtp.gmail.com with ESMTPSA id u10sm1331274wmm.0.2019.09.20.03.21.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 20 Sep 2019 03:21:25 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH 2/2] kvm: clear dirty bitmaps from all overlapping memslots Date: Fri, 20 Sep 2019 12:21:22 +0200 Message-Id: <1568974882-7419-3-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1568974882-7419-1-git-send-email-pbonzini@redhat.com> References: <1568974882-7419-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::344 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: dgilbert@redhat.com, peterx@redhat.com, qemu-stable@nongnu.org Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" Since the KVM dirty page reporting works on guest physical addresses, we need to clear all of the aliases when a page is migrated, or there is a risk of losing writes to the aliases that were not cleared. Note that this is only an issue for manual clearing of the bitmap; if the bitmap is cleared at the same time as it's retrieved, all the aliases get cleared correctly. Reported-by: Dr. David Alan Gilbert Fixes: ff4aa11419242c835b03d274f08f797c129ed7ba Cc: qemu-stable@nongnu.org Signed-off-by: Paolo Bonzini --- accel/kvm/kvm-all.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index e9e6086..315a915 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -588,8 +588,8 @@ static int kvm_log_clear_one_slot(KVMSlot *mem, int as_id, uint64_t start, uint6 * satisfy the KVM interface requirement. Firstly, do the start * page alignment on 64 host pages */ - bmap_start = (start - mem->start_addr) & KVM_CLEAR_LOG_MASK; - start_delta = start - mem->start_addr - bmap_start; + bmap_start = start & KVM_CLEAR_LOG_MASK; + start_delta = start - bmap_start; bmap_start /= psize; /* @@ -693,8 +693,8 @@ static int kvm_physical_log_clear(KVMMemoryListener *kml, MemoryRegionSection *section) { KVMState *s = kvm_state; - uint64_t start, size; - KVMSlot *mem = NULL; + uint64_t start, size, offset, count; + KVMSlot *mem; int ret, i; if (!s->manual_dirty_log_protect) { @@ -712,22 +712,30 @@ static int kvm_physical_log_clear(KVMMemoryListener *kml, kvm_slots_lock(kml); - /* Find any possible slot that covers the section */ for (i = 0; i < s->nr_slots; i++) { mem = &kml->slots[i]; - if (mem->start_addr <= start && - start + size <= mem->start_addr + mem->memory_size) { + /* Discard slots that are empty or do not overlap the section */ + if (!mem->memory_size || + mem->start_addr > start + size - 1 || + start > mem->start_addr + mem->memory_size - 1) { + continue; + } + + if (start >= mem->start_addr) { + /* The slot starts before section or is aligned to it. */ + offset = start - mem->start_addr; + count = MIN(mem->memory_size - offset, size); + } else { + /* The slot starts after section. */ + offset = 0; + count = MIN(mem->memory_size, size - (mem->start_addr - start)); + } + ret = kvm_log_clear_one_slot(mem, kml->as_id, offset, count); + if (ret < 0) { break; } } - /* - * We should always find one memslot until this point, otherwise - * there could be something wrong from the upper layer - */ - assert(mem && i != s->nr_slots); - ret = kvm_log_clear_one_slot(mem, kml->as_id, start, size); - kvm_slots_unlock(kml); return ret;