From patchwork Wed Dec 1 17:04:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Quentin Perret X-Patchwork-Id: 12694355 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 0B052C433F5 for ; Wed, 1 Dec 2021 17:08:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=VAWtH2iuqic3+nePYqwh80KFL0Oc9sIti2b7cm3QV0c=; b=d1E9/umUj7GvDTgyk87J4RMSOm MZ7w3tBvkdwVGR3S6L/yqw9Tl9dTog4FVFrHB+DI82Y8xER4GJk7fofW2NbW6jTBnXHz7pofbdJtZ 8W29jIKoOAzoH5hQ9Qjn7O9g2maEsyRhY9diPkbxXDUngss0Eg7SIIJapjsWuCeN1V8NEH2i1i7hy qVN5bmBNT8TiDR+kBW/gdkxIaAAaXq0JMn8nlJLHWvXuiq6zAcxSu69+hMh/lVfFxlQFCkav5tqZd 80AI22xjfanNGO8nm4chDpHgzqyqA0JIIa6Wg5DHndLRdBeS2fsf8nwWZau1sQt7sAgdrNaczU+VI o/EFMsrg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1msT4I-009T2S-K0; Wed, 01 Dec 2021 17:06:54 +0000 Received: from mail-wm1-x349.google.com ([2a00:1450:4864:20::349]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1msT2G-009RwE-1C for linux-arm-kernel@lists.infradead.org; Wed, 01 Dec 2021 17:04:49 +0000 Received: by mail-wm1-x349.google.com with SMTP id m18-20020a05600c3b1200b0033283ea5facso611274wms.1 for ; Wed, 01 Dec 2021 09:04:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=3kGqtrkDX/7YFDJqNxF3cw4ExJXKG5GDRcsjJYQ/JVo=; b=TMO4hW6gBvmBsrzVeqH/Hwa2gs9Xbv3N2Qp7sh2MQz/vWRh6mkuEatIkrGrTZf3Z4I J4ZT0n9fQuNxYUa41Q/bfrGeXJfXoAxp0fVLJYsUlcz4fJ9elw13634GMg/GtfXBD9gS HgsZuqhwLHubwI2YpiTsQ5gPYmF4oiPV0t0LYGbZQsqW5tsVfYeH3pZdLC20OCtG9SBk hhssObLi/zjJz/dfhhWUJZkRS15K+o5PXPkzjL6lAnmts21mdTmxYXoGDWcbisE6lvjw Zdp4uo94fV72wWfRF6SQkDM9TrvSF/jxNwMbnGAP2S4QVSSagWKieTx6L10xi1OZqvWY FH7g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=3kGqtrkDX/7YFDJqNxF3cw4ExJXKG5GDRcsjJYQ/JVo=; b=D1X71rE5wJCAHa5/T9Bg8xU7f7ifNtnwDAySLCl5c+aahEmUiefL7RlQSqF/C3uVtu YEALHv9jTpkomliBDBZV4qrG8l/rWmjXtuC9olnQw97UfyT49sUDQOjMtumYlg0ufad2 kneUzjfmoDMG/NHECg1LyzjjxIETJuBWaI+SWRPuafPAqqHPwtsijRDZrfRCn39CULKC pixPtP+idMhjulKQ/9rlGEtHKs88IRq056K3pMW+1skJHC8Slbq6aE8mmL/anWzfVlmW MUOroE01/Z+jueEu1aa3qcuu9pokjKlHXKGL+Nm8dIgpxkRA+2lK/NDHnSOzB6mVd5YZ Zg7g== X-Gm-Message-State: AOAM532Mz+Cr2VVohpr9CNZVQ6LQ6fTITO3s4/RXWbNt1pDfwBWWUVyX YFiZ9E27MVDgVLfpkSzPUfsUXcsDJjOB X-Google-Smtp-Source: ABdhPJzzYr8OrnKjxfmfCT1wD/gpPb9rlHIvVwT+T1gmq0Ql8fSZ2Xu5j+Ura+iJuS9E70AhlNnb1YCGJ043 X-Received: from luke.lon.corp.google.com ([2a00:79e0:d:210:1cab:1a20:2ef1:ddde]) (user=qperret job=sendgmr) by 2002:a05:600c:4e07:: with SMTP id b7mr8305933wmq.16.1638378285742; Wed, 01 Dec 2021 09:04:45 -0800 (PST) Date: Wed, 1 Dec 2021 17:04:02 +0000 In-Reply-To: <20211201170411.1561936-1-qperret@google.com> Message-Id: <20211201170411.1561936-9-qperret@google.com> Mime-Version: 1.0 References: <20211201170411.1561936-1-qperret@google.com> X-Mailer: git-send-email 2.34.0.rc2.393.gf8c9666880-goog Subject: [PATCH v3 08/15] KVM: arm64: pkvm: Refcount the pages shared with EL2 From: Quentin Perret To: Marc Zyngier , James Morse , Alexandru Elisei , Suzuki K Poulose , Catalin Marinas , Will Deacon Cc: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu, linux-kernel@vger.kernel.org, kernel-team@android.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211201_090448_113499_3949A67F X-CRM114-Status: GOOD ( 16.22 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org In order to simplify the page tracking infrastructure at EL2 in nVHE protected mode, move the responsibility of refcounting pages that are shared multiple times on the host. In order to do so, let's create a red-black tree tracking all the PFNs that have been shared, along with a refcount. Signed-off-by: Quentin Perret Acked-by: Will Deacon --- arch/arm64/kvm/mmu.c | 78 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 68 insertions(+), 10 deletions(-) diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index fd868fb9d922..d72566896755 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -284,23 +284,72 @@ static phys_addr_t kvm_kaddr_to_phys(void *kaddr) } } -static int pkvm_share_hyp(phys_addr_t start, phys_addr_t end) +struct hyp_shared_pfn { + u64 pfn; + int count; + struct rb_node node; +}; + +static DEFINE_MUTEX(hyp_shared_pfns_lock); +static struct rb_root hyp_shared_pfns = RB_ROOT; + +static struct hyp_shared_pfn *find_shared_pfn(u64 pfn, struct rb_node ***node, + struct rb_node **parent) { - phys_addr_t addr; - int ret; + struct hyp_shared_pfn *this; + + *node = &hyp_shared_pfns.rb_node; + *parent = NULL; + while (**node) { + this = container_of(**node, struct hyp_shared_pfn, node); + *parent = **node; + if (this->pfn < pfn) + *node = &((**node)->rb_left); + else if (this->pfn > pfn) + *node = &((**node)->rb_right); + else + return this; + } - for (addr = ALIGN_DOWN(start, PAGE_SIZE); addr < end; addr += PAGE_SIZE) { - ret = kvm_call_hyp_nvhe(__pkvm_host_share_hyp, - __phys_to_pfn(addr)); - if (ret) - return ret; + return NULL; +} + +static int share_pfn_hyp(u64 pfn) +{ + struct rb_node **node, *parent; + struct hyp_shared_pfn *this; + int ret = 0; + + mutex_lock(&hyp_shared_pfns_lock); + this = find_shared_pfn(pfn, &node, &parent); + if (this) { + this->count++; + goto unlock; } - return 0; + this = kzalloc(sizeof(*this), GFP_KERNEL); + if (!this) { + ret = -ENOMEM; + goto unlock; + } + + this->pfn = pfn; + this->count = 1; + rb_link_node(&this->node, parent, node); + rb_insert_color(&this->node, &hyp_shared_pfns); + ret = kvm_call_hyp_nvhe(__pkvm_host_share_hyp, pfn, 1); +unlock: + mutex_unlock(&hyp_shared_pfns_lock); + + return ret; } int kvm_share_hyp(void *from, void *to) { + phys_addr_t start, end, cur; + u64 pfn; + int ret; + if (is_kernel_in_hyp_mode()) return 0; @@ -315,7 +364,16 @@ int kvm_share_hyp(void *from, void *to) if (kvm_host_owns_hyp_mappings()) return create_hyp_mappings(from, to, PAGE_HYP); - return pkvm_share_hyp(__pa(from), __pa(to)); + start = ALIGN_DOWN(__pa(from), PAGE_SIZE); + end = PAGE_ALIGN(__pa(to)); + for (cur = start; cur < end; cur += PAGE_SIZE) { + pfn = __phys_to_pfn(cur); + ret = share_pfn_hyp(pfn); + if (ret) + return ret; + } + + return 0; } /**