From patchwork Thu Jun 23 02:19:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Collingbourne X-Patchwork-Id: 12891724 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 6C80FC433EF for ; Thu, 23 Jun 2022 02:27:17 +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=vvla2cirlDMUJFCgV3DxGWWWMt7uDHaPXTcHTHaKGps=; b=tpW2I/OwkA1IGNQWqA/RESyuZx KHjYEVJdAFD4EOl/9eqQW2CMm7DlJ3zue+CzlgxAnuSZJBE7ukNZfN6Cbqd4FUyUyRe6ZPdpWiIi4 7x7qZiwA5bQAXcAvZExUA3aKeN7GiEuoWNZh5N02yLYXg6WehwNVu9dhqBSDqMHpiLVMl0RO6F+XI q6o958ZaEXAY8dCkq4xbXB8hzOBz6OGUz4vaXHvpnY6b8s25wQhEggohJkQHmrnx6bY/5JrGGg4L8 Mp3TdPEvX2N2KDnve0j9W+bA3Q+b2Wj/e76JMWMt0HcDF8OXrBbDzGoLb4fs2BH6Hz1OkMRjFRpcR GxiCGTwQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1o4CXj-00CzFY-RC; Thu, 23 Jun 2022 02:26:04 +0000 Received: from mail-yw1-x114a.google.com ([2607:f8b0:4864:20::114a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1o4CRX-00CwPd-NG for linux-arm-kernel@lists.infradead.org; Thu, 23 Jun 2022 02:19:41 +0000 Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-317b6ecba61so94447087b3.9 for ; Wed, 22 Jun 2022 19:19:38 -0700 (PDT) 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=wT4jHGlHPHF9dlfcKzGZH8nhD8vpeQwEkQou9JzLU60=; b=RVgxxUJl2hpXa33b+kJtJXbExaoizJzs1IRtinNk7nfyr7rfAQugUZA7d+RrpYEKbL lxHsdenRl/U81vQWHbh2ieO7b0GgcNVgtAhi1jrLMUgeR2LQmBpGScCtRjSisDCCaNgw zdPf2LmgZwlaYXYa6Bcw8e323ZhLCyGNLakWlg9g8HJ/vvSbzKJfCY5eMJrUzBoC+ios G2TiaYtk35xp/tudhc3eyll3CHRE2CqXUFC2BmGOE4Thxb5xXeM6xtAEDe+RLRGLZeIf n317+ev8I08NprsuGzNYGVhK0NJX54k1qixYjDwqClxClfhLPNYSu8+7KEWWyZxdW6dh W8lA== 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=wT4jHGlHPHF9dlfcKzGZH8nhD8vpeQwEkQou9JzLU60=; b=JPL1uag2RbzUS8Igv0VBMrTOS/x0epuDxZqZPhqatwIvV9CxvgDjy54HmW/zKnOhNR 01IbwSUYoT1hxe0kZCIcdSAce3TxKLy2Rlt05mxSTrRnsFfR1B2fEMoL0fwzDfT82mtL roKv8Dl6fS4w80c9XSRZiKNoZzGQPvxGZhAARsYK1LDJes9xN1PKYNnJeYiT555xDjIX 9dAFSC/LAXIInOqC3ftq5WuSA5k+ECbU5eOwdj57YGrSIn8/mygW/0neMziOnKF8C/8O cqcZR8MmbTEYZmVYtKL+n0vB2FAv8Di1RJzIQa489HZFL+IC9MWiYwLnotNHjhIXqgSj vZmw== X-Gm-Message-State: AJIora8D+dblKWUGK/vpgGsy+1xhuIo8aMz74vkwsfaaYXdfXbcPbTxb 9aNQuhm8szNWiCle6vKAhh+eTzs= X-Google-Smtp-Source: AGRyM1ub1xVH1VRZd14aVuV55xQTwS7KIATb7Hw6lN8inguHsebJ3kq2h0VMLDkavIHjfGw2R83JCkQ= X-Received: from pcc-desktop.svl.corp.google.com ([2620:15c:2ce:200:ba6f:123c:d287:a160]) (user=pcc job=sendgmr) by 2002:a0d:dd81:0:b0:317:cd05:1d94 with SMTP id g123-20020a0ddd81000000b00317cd051d94mr8038901ywe.189.1655950778275; Wed, 22 Jun 2022 19:19:38 -0700 (PDT) Date: Wed, 22 Jun 2022 19:19:24 -0700 In-Reply-To: <20220623021926.3443240-1-pcc@google.com> Message-Id: <20220623021926.3443240-2-pcc@google.com> Mime-Version: 1.0 References: <20220623021926.3443240-1-pcc@google.com> X-Mailer: git-send-email 2.37.0.rc0.104.g0611611a94-goog Subject: [PATCH 1/3] KVM: arm64: add a hypercall for disowning pages From: Peter Collingbourne To: kvmarm@lists.cs.columbia.edu Cc: Peter Collingbourne , Marc Zyngier , kvm@vger.kernel.org, Andy Lutomirski , linux-arm-kernel@lists.infradead.org, Michael Roth , Catalin Marinas , Chao Peng , Will Deacon , Evgenii Stepanov X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220622_191939_832696_9714DD29 X-CRM114-Status: GOOD ( 16.41 ) 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 Currently we only deny the host access to hyp and guest pages. However, there may be other pages that could potentially be used to indirectly compromise the hypervisor or the other guests. Therefore introduce a __pkvm_disown_pages hypercall that the host kernel may use to deny its future self access to those pages before deprivileging itself. Signed-off-by: Peter Collingbourne --- arch/arm64/include/asm/kvm_asm.h | 1 + arch/arm64/kvm/hyp/include/nvhe/mem_protect.h | 1 + arch/arm64/kvm/hyp/include/nvhe/pkvm.h | 1 + arch/arm64/kvm/hyp/nvhe/hyp-main.c | 9 +++++++++ arch/arm64/kvm/hyp/nvhe/mem_protect.c | 11 +++++++++++ arch/arm64/kvm/hyp/pgtable.c | 5 +++-- 6 files changed, 26 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index 411cfbe3ebbd..1a177d9ed517 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h @@ -63,6 +63,7 @@ enum __kvm_host_smccc_func { __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_ipa, __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid, __KVM_HOST_SMCCC_FUNC___kvm_flush_cpu_context, + __KVM_HOST_SMCCC_FUNC___pkvm_disown_pages, __KVM_HOST_SMCCC_FUNC___pkvm_prot_finalize, /* Hypercalls available after pKVM finalisation */ diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h index e0bbb1726fa3..e88a9dab9cd5 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h +++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h @@ -58,6 +58,7 @@ enum pkvm_component_id { PKVM_ID_HOST, PKVM_ID_HYP, PKVM_ID_GUEST, + PKVM_ID_NOBODY, }; extern unsigned long hyp_nr_cpus; diff --git a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h index c1987115b217..fbd991a46ab3 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h +++ b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h @@ -98,6 +98,7 @@ int __pkvm_init_shadow(struct kvm *kvm, unsigned long pgd_hva, unsigned long last_ran_hva, size_t last_ran_size); int __pkvm_teardown_shadow(unsigned int shadow_handle); +int __pkvm_disown_pages(phys_addr_t phys, size_t size); struct kvm_shadow_vcpu_state * pkvm_load_shadow_vcpu_state(unsigned int shadow_handle, unsigned int vcpu_idx); diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c index ddb36d172b60..b81908ef13e2 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -1055,6 +1055,14 @@ static void handle___pkvm_teardown_shadow(struct kvm_cpu_context *host_ctxt) cpu_reg(host_ctxt, 1) = __pkvm_teardown_shadow(shadow_handle); } +static void handle___pkvm_disown_pages(struct kvm_cpu_context *host_ctxt) +{ + DECLARE_REG(phys_addr_t, phys, host_ctxt, 1); + DECLARE_REG(size_t, size, host_ctxt, 2); + + cpu_reg(host_ctxt, 1) = __pkvm_disown_pages(phys, size); +} + typedef void (*hcall_t)(struct kvm_cpu_context *); #define HANDLE_FUNC(x) [__KVM_HOST_SMCCC_FUNC_##x] = (hcall_t)handle_##x @@ -1072,6 +1080,7 @@ static const hcall_t host_hcall[] = { HANDLE_FUNC(__kvm_tlb_flush_vmid_ipa), HANDLE_FUNC(__kvm_tlb_flush_vmid), HANDLE_FUNC(__kvm_flush_cpu_context), + HANDLE_FUNC(__pkvm_disown_pages), HANDLE_FUNC(__pkvm_prot_finalize), HANDLE_FUNC(__pkvm_host_share_hyp), diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c index d839bb573b49..b3a2ad8454cc 100644 --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -1756,3 +1756,14 @@ int __pkvm_host_reclaim_page(u64 pfn) return ret; } + +int __pkvm_disown_pages(phys_addr_t phys, size_t size) +{ + int ret; + + host_lock_component(); + ret = host_stage2_set_owner_locked(phys, size, PKVM_ID_NOBODY); + host_unlock_component(); + + return ret; +} diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c index 756bbb15c1f3..e1ecddd43885 100644 --- a/arch/arm64/kvm/hyp/pgtable.c +++ b/arch/arm64/kvm/hyp/pgtable.c @@ -10,6 +10,7 @@ #include #include #include +#include #define KVM_PTE_TYPE BIT(1) @@ -677,9 +678,9 @@ static bool stage2_pte_is_counted(kvm_pte_t pte) /* * The refcount tracks valid entries as well as invalid entries if they * encode ownership of a page to another entity than the page-table - * owner, whose id is 0. + * owner, whose id is 0, or NOBODY, which does not correspond to a page-table. */ - return !!pte; + return !!pte && pte != kvm_init_invalid_leaf_owner(PKVM_ID_NOBODY); } static void stage2_put_pte(kvm_pte_t *ptep, struct kvm_s2_mmu *mmu, u64 addr,