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, From patchwork Thu Jun 23 02:19:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Collingbourne X-Patchwork-Id: 12891726 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 11570C433EF for ; Thu, 23 Jun 2022 02:28:58 +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=SaxRVALBpH+9AoouVEGxO4mjr7fD7FEFebqkgG50FA4=; b=LfF+QHrnmHceoJHVhNuH0+7emu 0Esg55TXiwP67xbDDlGXAW4TrteffDYEQUmGCsA4yRxWyr3rIaFhgdSakiG26Au6ul6byJyQc6yXg KhikEITOjjEkXVpPWqbOXNWCYp8wqyEhXivVBfSVX7ZGAnCu1ZRT45xZzdom8vcdoMjZXo9FrU1Oy vUkkz1Wfxgdw9WoOekUmzWZ2ivpP/m84iUlqoGj+nLlAOGWom5/RrhSIl9yGweShWjcT7qFQoaOWW EN+90II83baAKCgwGMUpqeVeiD3otx/9qoF/MKK+ka3lMMAgnHjeV2vi8ezYDMKO5aGUVZRr/E8hL lodIIoLg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1o4CZN-00D00k-D2; Thu, 23 Jun 2022 02:27:47 +0000 Received: from mail-yb1-xb49.google.com ([2607:f8b0:4864:20::b49]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1o4CRc-00CwQP-Ac for linux-arm-kernel@lists.infradead.org; Thu, 23 Jun 2022 02:19:47 +0000 Received: by mail-yb1-xb49.google.com with SMTP id r6-20020a5b06c6000000b006693f6a6d67so7006980ybq.7 for ; Wed, 22 Jun 2022 19:19:40 -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=qmRSFVhsEhDBpfnqm4N8Fhb131UT2F+11PJ2keCwIs4=; b=qrU4bfPKoBkwTTiKfPve9s0Kfjp8vuFN1z7yGqlBJDfwPofkgZxH2msgkZnA46WpIg xG8zlJh5lI5v7J36zFE22Nf4NWZoPrVMg2ZGyQAjnuv5G1AZbdvGSHrUyzMRK9Md+7ud 1l+fT1dftAhQYN7yJbaLAe0h/bU/teWnLgJkcRE+HPWctxwxdny1yeGSXwyiJLs2wifH kRrK6R/eCfVs5VOt4N6yOFX7UOnpfqC0hY/mE58OymHm0B7puwmwgCi+WonKm5WK/X0+ BSndrmaGkVBWfm99WMNnpXqmrQMZdXDd+7IJAb0CsRMbaBZlDHus7yiwLKlGb0ZGx+r/ LX5g== 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=qmRSFVhsEhDBpfnqm4N8Fhb131UT2F+11PJ2keCwIs4=; b=Ceo9te9vv1aB5ADxXauXHq1hcIG3NpedabP0yxOvIX76hX6JCIF2FOoa9MjLTqYiHX BRM6AEchzAKuaBBwfrU60lnhcE35d9Y9oKqrgk/NXTbtGeZRryOOgXcwtUT9CclkMuhD RSWEAHR3V9f4kmw08hBo18xMEXrN1/1kYgQdXD6TH3WiYPUZLcqG3bL3P5KHNaoqK0pv 2xVQWZv+VFTzvpOS64BJt6L3Ng0YSnCok++jPfNiV81PGL++ZES50VR91ZjHhDIaiUCR iqsQLGzsq/dsytElAxLjWZe8BmlOzqYEC8eV1LsX22+hPEFhqbX/3ubYVCfJnzfWxpM7 SuZQ== X-Gm-Message-State: AJIora+aw6MpG1wv5+Ed8pHdArcJDqZ5d9siPVO/rhvQfnYfaLVhP4hY BVja1bg+MWl/jvOILu8620gsG0o= X-Google-Smtp-Source: AGRyM1vvw84U2jyg/dWdtxTfS7KweL0nv+g/AhyHvwsGSckCZTqHtjS95hVvHN66mkERZ2IvAJ3TsBk= X-Received: from pcc-desktop.svl.corp.google.com ([2620:15c:2ce:200:ba6f:123c:d287:a160]) (user=pcc job=sendgmr) by 2002:a25:8887:0:b0:669:97f5:d0b8 with SMTP id d7-20020a258887000000b0066997f5d0b8mr5089027ybl.432.1655950780321; Wed, 22 Jun 2022 19:19:40 -0700 (PDT) Date: Wed, 22 Jun 2022 19:19:25 -0700 In-Reply-To: <20220623021926.3443240-1-pcc@google.com> Message-Id: <20220623021926.3443240-3-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 2/3] KVM: arm64: disown unused reserved-memory regions 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_191944_565129_6A522E02 X-CRM114-Status: GOOD ( 15.96 ) 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 The meaning of no-map on a reserved-memory node is as follows: Indicates the operating system must not create a virtual mapping of the region as part of its standard mapping of system memory, nor permit speculative access to it under any circumstances other than under the control of the device driver using the region. If there is no compatible property, there is no device driver, so the host kernel has no business accessing the reserved-memory region. Since these regions may represent a route through which the host kernel can gain additional privileges, disown any such memory regions before deprivileging ourselves. Signed-off-by: Peter Collingbourne --- arch/arm64/kvm/arm.c | 46 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index db7cbca6ace4..38f0900b7ddb 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -4,6 +4,7 @@ * Author: Christoffer Dall */ +#include #include #include #include @@ -12,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -1907,6 +1909,48 @@ static bool init_psci_relay(void) return true; } +static void disown_reserved_memory(struct device_node *node) +{ + int addr_cells = of_n_addr_cells(node); + int size_cells = of_n_size_cells(node); + const __be32 *reg, *end; + int len; + + reg = of_get_property(node, "reg", &len); + if (len % (4 * (addr_cells + size_cells))) + return; + + end = reg + (len / 4); + while (reg != end) { + u64 addr, size; + + addr = of_read_number(reg, addr_cells); + reg += addr_cells; + size = of_read_number(reg, size_cells); + reg += size_cells; + + kvm_call_hyp_nvhe(__pkvm_disown_pages, addr, size); + } +} + +static void kvm_reserved_memory_init(void) +{ + struct device_node *parent, *node; + + if (!acpi_disabled || !is_protected_kvm_enabled()) + return; + + parent = of_find_node_by_path("/reserved-memory"); + if (!parent) + return; + + for_each_child_of_node(parent, node) { + if (!of_get_property(node, "compatible", NULL) && + of_get_property(node, "no-map", NULL)) + disown_reserved_memory(node); + } +} + static int init_subsystems(void) { int err = 0; @@ -1947,6 +1991,8 @@ static int init_subsystems(void) kvm_register_perf_callbacks(NULL); + kvm_reserved_memory_init(); + out: if (err || !is_protected_kvm_enabled()) on_each_cpu(_kvm_arch_hardware_disable, NULL, 1); From patchwork Thu Jun 23 02:19:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Collingbourne X-Patchwork-Id: 12891725 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 99FB5C43334 for ; Thu, 23 Jun 2022 02:28:08 +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=yiSLzGj9ia9kOdQdLlOZXzPrPYvkuAii0xJ5WtYNAZI=; b=pu6PcNWCP3C981JpQsDy5RUnNT xmR6nUo4GW+MK3pxSXoB+YRZSE4fSfMHYKQ0az4xEjllW9N4h4cUWXxC5TolAuxPZWKE/6+t0u9ac Q8nWiKutJhgfx3gPFbyFFoN62gMlRnNDnD97fORptV1e+ygtChIDBqa4ImNk8j9jdF2cZ0j28VS92 Ff32Mv1H7cM/rK3c9KK7vlEr7AocwtZwkaEjvjHBccVDa3VS7xkyQ6CbTn/p8Mx0RcnKY4heJfPL2 A43u/3/tM4y4xlCkKaUJ7J4KDvGv0q6b511GPxFy57llOMTbEDmeAz+2aQWEtlhFxLJ/ZC/nvg2Bu AcGd+FxA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1o4CYS-00Czay-U8; Thu, 23 Jun 2022 02:26:49 +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 1o4CRb-00CwRz-Qf for linux-arm-kernel@lists.infradead.org; Thu, 23 Jun 2022 02:19:46 +0000 Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-317ae1236feso98809717b3.11 for ; Wed, 22 Jun 2022 19:19:42 -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=9RRfGBQ63xQ/DdrDFnljmoGGtNK2WWXmVlcIowX+5Eg=; b=PV3Ep9cdQbVSaBsuR1M4h4hPUpnJOpS9PDHgZkbjrc1w8cQjLCjkQPCHzOeNgT9q7/ O+l3GoolI9kSpOJ2B4ayD6iZcOWewtp9fPkzuvtw9ICyv3pE01NHqOO/lRAeT0LGplxr AFE0lS0mvWvMkw1JaGQLmYgu82p7rKcbrlZbcWLFzj1EL1yRcd6oKUrS+S3zN+O5xJAb 8sGEc2DaI/5Vs/LgaKH784z6icQ86E7tzibHduCF77Cv8AA4gYQQSKTp9EyCP2TTQKaJ eiDmWy4/DwF3Lol9Q5avrghJoAy/6G640V2zHlxniozM6/RiXpR+sNyoarfHV1H0gdml bdVQ== 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=9RRfGBQ63xQ/DdrDFnljmoGGtNK2WWXmVlcIowX+5Eg=; b=3ZRQiBf9EGzaJ+vI28PbCWPUHQywHPmJhUzd9QzBhe9abO2SjdOiM9q33ZBFUEW/Q/ SAG1VCmxOdSBTYsSbMMyv9urE9HefNxRSSbUJMTqVgwRyq5G/PKF+jUstlVIY8uiu4uJ unSdmIAhVMrhiWKVfT+iq6VDHPjlqn+s+R/HGKoRh6P+13OZyBoLGz2I/lD3+NXaANZQ gAykGset0ENzzDoJfFx0gi74Hth6AAFD0Wb9TupHfXNTxh4ddSQ9pRYIqh6Ka6vo6mMo AbKXHhB7jGxgTEk54wdCL3i0x9W0kqMD2FJMtkNDui9R1wcHkfqbL3ZTNHVzh6xUHZzm BAhA== X-Gm-Message-State: AJIora/7DxMEgPoFxYHSblNIK8MOIiFRsfL0JiGqg4F1JEPBlEccfuFK Qn4psJMmcZGoF/2LI8jBkIqO9+M= X-Google-Smtp-Source: AGRyM1tktBOoS27VjciOGpSivbIhryk+M35R2Pac1IEIC38+L0K8WXfaVlMRjhkCUF6vj4Cunslz+Wg= X-Received: from pcc-desktop.svl.corp.google.com ([2620:15c:2ce:200:ba6f:123c:d287:a160]) (user=pcc job=sendgmr) by 2002:a25:6609:0:b0:668:e2b4:f7fd with SMTP id a9-20020a256609000000b00668e2b4f7fdmr7353464ybc.226.1655950782391; Wed, 22 Jun 2022 19:19:42 -0700 (PDT) Date: Wed, 22 Jun 2022 19:19:26 -0700 In-Reply-To: <20220623021926.3443240-1-pcc@google.com> Message-Id: <20220623021926.3443240-4-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 3/3] KVM: arm64: allow MTE in protected VMs if the tag storage is known 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_191943_990561_1C8EBB6A X-CRM114-Status: GOOD ( 23.19 ) 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 Because the host may corrupt a protected guest's tag storage unless protected by stage 2 page tables, we can't expose MTE to protected guests if the location of the tag storage is not known. Therefore, only allow protected VM guests to use MTE if the location of the tag storage is described in the device tree, and only after disowning any physical memory accessible tag storage regions. To avoid exposing MTE tags from the host to protected VMs, sanitize tags before donating pages. Signed-off-by: Peter Collingbourne --- arch/arm64/include/asm/kvm_host.h | 6 +++++ arch/arm64/include/asm/kvm_pkvm.h | 4 +++- arch/arm64/kernel/image-vars.h | 3 +++ arch/arm64/kvm/arm.c | 37 ++++++++++++++++++++++++++++--- arch/arm64/kvm/hyp/nvhe/pkvm.c | 8 ++++--- arch/arm64/kvm/mmu.c | 4 +++- 6 files changed, 54 insertions(+), 8 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 0fd184b816b3..973ab0378d01 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -930,6 +930,12 @@ bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu); #define kvm_arm_vcpu_sve_finalized(vcpu) \ ((vcpu)->arch.flags & KVM_ARM64_VCPU_SVE_FINALIZED) +DECLARE_STATIC_KEY_FALSE(pkvm_mte_supported); + +#define kvm_supports_mte(kvm) \ + (system_supports_mte() && \ + (!kvm_vm_is_protected(kvm) || \ + static_branch_unlikely(&pkvm_mte_supported))) #define kvm_has_mte(kvm) \ (system_supports_mte() && \ test_bit(KVM_ARCH_FLAG_MTE_ENABLED, &(kvm)->arch.flags)) diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm_pkvm.h index cd56438a34be..ef5d4870c043 100644 --- a/arch/arm64/include/asm/kvm_pkvm.h +++ b/arch/arm64/include/asm/kvm_pkvm.h @@ -73,10 +73,12 @@ void kvm_shadow_destroy(struct kvm *kvm); * Allow for protected VMs: * - Branch Target Identification * - Speculative Store Bypassing + * - Memory Tagging Extension */ #define PVM_ID_AA64PFR1_ALLOW (\ ARM64_FEATURE_MASK(ID_AA64PFR1_BT) | \ - ARM64_FEATURE_MASK(ID_AA64PFR1_SSBS) \ + ARM64_FEATURE_MASK(ID_AA64PFR1_SSBS) | \ + ARM64_FEATURE_MASK(ID_AA64PFR1_MTE) \ ) /* diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h index 2d4d6836ff47..26a9b31478aa 100644 --- a/arch/arm64/kernel/image-vars.h +++ b/arch/arm64/kernel/image-vars.h @@ -84,6 +84,9 @@ KVM_NVHE_ALIAS(__hyp_stub_vectors); KVM_NVHE_ALIAS(arm64_const_caps_ready); KVM_NVHE_ALIAS(cpu_hwcap_keys); +/* Kernel symbol needed for kvm_supports_mte() check. */ +KVM_NVHE_ALIAS(pkvm_mte_supported); + /* Static keys which are set if a vGIC trap should be handled in hyp. */ KVM_NVHE_ALIAS(vgic_v2_cpuif_trap); KVM_NVHE_ALIAS(vgic_v3_cpuif_trap); diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 38f0900b7ddb..5a780a0f59e3 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -60,6 +60,7 @@ static bool vgic_present; static DEFINE_PER_CPU(unsigned char, kvm_arm_hardware_enabled); DEFINE_STATIC_KEY_FALSE(userspace_irqchip_in_use); +DEFINE_STATIC_KEY_FALSE(pkvm_mte_supported); int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu) { @@ -96,9 +97,7 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm, break; case KVM_CAP_ARM_MTE: mutex_lock(&kvm->lock); - if (!system_supports_mte() || - kvm_vm_is_protected(kvm) || - kvm->created_vcpus) { + if (!kvm_supports_mte(kvm) || kvm->created_vcpus) { r = -EINVAL; } else { r = 0; @@ -334,6 +333,9 @@ static int pkvm_check_extension(struct kvm *kvm, long ext, int kvm_cap) case KVM_CAP_ARM_VM_IPA_SIZE: r = kvm_cap; break; + case KVM_CAP_ARM_MTE: + r = kvm_cap && static_branch_unlikely(&pkvm_mte_supported); + break; case KVM_CAP_GUEST_DEBUG_HW_BPS: r = min(kvm_cap, pkvm_get_max_brps()); break; @@ -1948,9 +1950,36 @@ static void kvm_reserved_memory_init(void) if (!of_get_property(node, "compatible", NULL) && of_get_property(node, "no-map", NULL)) disown_reserved_memory(node); + + if (of_device_is_compatible(node, "arm,mte-tag-storage")) + disown_reserved_memory(node); } } +static void kvm_mte_init(void) +{ + struct device_node *memory; + + if (!system_supports_mte() || !acpi_disabled || + !is_protected_kvm_enabled()) + return; + + /* + * It is only safe to turn on MTE for protected VMs if we can protect + * the guests from host accesses to their tag storage. If every memory + * region has an arm,mte-alloc property we know that all tag storage + * regions exposed to physical memory, if any, are described by a + * reserved-memory compatible with arm,mte-tag-storage. We can use these + * descriptions to unmap these regions from the host's stage 2 page + * tables (see kvm_reserved_memory_init). + */ + for_each_node_by_type(memory, "memory") + if (!of_get_property(memory, "arm,mte-alloc", NULL)) + return; + + static_branch_enable(&pkvm_mte_supported); +} + static int init_subsystems(void) { int err = 0; @@ -1993,6 +2022,8 @@ static int init_subsystems(void) kvm_reserved_memory_init(); + kvm_mte_init(); + out: if (err || !is_protected_kvm_enabled()) on_each_cpu(_kvm_arch_hardware_disable, NULL, 1); diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c index e81a6dd676d0..dcc3084161b3 100644 --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c @@ -88,7 +88,7 @@ static void pvm_init_traps_aa64pfr1(struct kvm_vcpu *vcpu) /* Memory Tagging: Trap and Treat as Untagged if not supported. */ if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR1_MTE), feature_ids)) { hcr_set |= HCR_TID5; - hcr_clear |= HCR_DCT | HCR_ATA; + hcr_clear |= HCR_ATA; } vcpu->arch.hcr_el2 |= hcr_set; @@ -179,8 +179,8 @@ static void pvm_init_trap_regs(struct kvm_vcpu *vcpu) * - Feature id registers: to control features exposed to guests * - Implementation-defined features */ - vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS | - HCR_TID3 | HCR_TACR | HCR_TIDCP | HCR_TID1; + vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS | HCR_TID3 | HCR_TACR | HCR_TIDCP | + HCR_TID1 | HCR_ATA; if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN)) { /* route synchronous external abort exceptions to EL2 */ @@ -459,6 +459,8 @@ static int init_shadow_structs(struct kvm *kvm, struct kvm_shadow_vm *vm, vm->host_kvm = kvm; vm->kvm.created_vcpus = nr_vcpus; vm->kvm.arch.vtcr = host_kvm.arch.vtcr; + if (kvm_supports_mte(kvm) && test_bit(KVM_ARCH_FLAG_MTE_ENABLED, &kvm->arch.flags)) + set_bit(KVM_ARCH_FLAG_MTE_ENABLED, &vm->kvm.arch.flags); vm->kvm.arch.pkvm.enabled = READ_ONCE(kvm->arch.pkvm.enabled); vm->kvm.arch.mmu.last_vcpu_ran = last_ran; vm->last_ran_size = last_ran_size; diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index bca90b7354b9..5e079daf2d8e 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -1228,8 +1228,10 @@ static int pkvm_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, goto dec_account; } - write_lock(&kvm->mmu_lock); pfn = page_to_pfn(page); + sanitise_mte_tags(kvm, pfn, PAGE_SIZE); + + write_lock(&kvm->mmu_lock); ret = pkvm_host_map_guest(pfn, fault_ipa >> PAGE_SHIFT); if (ret) { if (ret == -EAGAIN)