From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752633AbdLHIko (ORCPT ); Fri, 8 Dec 2017 03:40:44 -0500 Received: from mail-ot0-f193.google.com ([74.125.82.193]:46039 "EHLO mail-ot0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752522AbdLHIkk (ORCPT ); Fri, 8 Dec 2017 03:40:40 -0500 X-Google-Smtp-Source: AGs4zMYI6dfBzLUGXtKEeEWRt5K6w2bR5BE3aB/0Vstfa7ljW9Z1XQi1/2j7zh6hCwZlGGaxWl1HtA== From: Quan Xu X-Google-Original-From: Quan Xu To: pbonzini@redhat.com, rkrcmar@redhat.com Cc: yang.zhang.wz@gmail.com, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Ben Luo , Quan Xu Subject: [PATCH RFC 2/7] kvm: x86: add a function to exchange value Date: Fri, 8 Dec 2017 16:39:45 +0800 Message-Id: <1512722390-3654-3-git-send-email-quan.xu0@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1512722390-3654-1-git-send-email-quan.xu0@gmail.com> References: <1512722390-3654-1-git-send-email-quan.xu0@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ben Luo Introduce kvm_xchg_guest_cached to exchange value with guest page atomically. Signed-off-by: Yang Zhang Signed-off-by: Quan Xu Signed-off-by: Ben Luo --- include/linux/kvm_host.h | 3 +++ virt/kvm/kvm_main.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 0 deletions(-) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 6882538..32949ed 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -688,6 +688,9 @@ int kvm_write_guest_offset_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc, void *data, int offset, unsigned long len); int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc, gpa_t gpa, unsigned long len); +unsigned long kvm_xchg_guest_cached(struct kvm *kvm, + struct gfn_to_hva_cache *ghc, unsigned long offset, + unsigned long new, int size); int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len); int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len); struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn); diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 9deb5a2..3149e17 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2010,6 +2010,48 @@ int kvm_read_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc, } EXPORT_SYMBOL_GPL(kvm_read_guest_cached); +unsigned long kvm_xchg_guest_cached(struct kvm *kvm, + struct gfn_to_hva_cache *ghc, unsigned long offset, + unsigned long new, int size) +{ + unsigned long r; + void *kva; + struct page *page; + kvm_pfn_t pfn; + + WARN_ON(offset > ghc->len); + + pfn = gfn_to_pfn_atomic(kvm, ghc->gpa >> PAGE_SHIFT); + page = kvm_pfn_to_page(pfn); + + if (is_error_page(page)) + return -EFAULT; + + kva = kmap_atomic(page) + offset_in_page(ghc->gpa) + offset; + switch (size) { + case 1: + r = xchg((char *)kva, new); + break; + case 2: + r = xchg((short *)kva, new); + break; + case 4: + r = xchg((int *)kva, new); + break; + case 8: + r = xchg((long *)kva, new); + break; + default: + kunmap_atomic(kva); + return -EFAULT; + } + + kunmap_atomic(kva); + mark_page_dirty_in_slot(ghc->memslot, ghc->gpa >> PAGE_SHIFT); + + return r; +} + int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len) { const void *zero_page = (const void *) __va(page_to_phys(ZERO_PAGE(0))); -- 1.7.1