From patchwork Wed Dec 8 15:59:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Will Deacon X-Patchwork-Id: 12695382 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 20FCFC433F5 for ; Wed, 8 Dec 2021 16:01:16 +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:MIME-Version:Message-Id:Date:Subject:Cc :To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=kNzAE2ZND6+CqK3jqj0uUU82awqdwlH2JnvIVCQGNco=; b=KbeATJUKGmeWGo WI/KuZhPwlfjZ5UI238GSkE3NgbLNnocfYCSW7R8uMX84MfHh0sHB5Of91z38Xcztiar7YHxLd3p7 52J9hYZBbE9sV2y73xrjLR0ME4nY8Hkc2ICgVrjVpywgjIVCd6Z+sp0R8ypHeV4cMh/oCQLQgoJ87 CUYy4FVAa01I4Smv3wvNd25xiv+vS10cDlMluOgLQ+uo+cVXB+XSAB3fyvhTsu4zO1EaqlwqfDQx6 TjbQOJKTXGJ7uwMIis+vZe28Zqrn1Rl0wWcTtQ7HQldXOntGOUvj1zyR6MJ4nsiiAm7AhokD40uV8 vZbY4jfDz6ht1+x4Mn0Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1muzM3-00DS3K-4E; Wed, 08 Dec 2021 15:59:39 +0000 Received: from ams.source.kernel.org ([2604:1380:4601:e00::1]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1muzLv-00DS0f-2g for linux-arm-kernel@lists.infradead.org; Wed, 08 Dec 2021 15:59:33 +0000 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 3C66AB82137; Wed, 8 Dec 2021 15:59:27 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0C03CC00446; Wed, 8 Dec 2021 15:59:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1638979166; bh=bFsnB2ZDJ+du5gZ4CWhsTFx4+MrKHtQileU/eMoqVao=; h=From:To:Cc:Subject:Date:From; b=NldYPfyAeI5yMpqdFJOnwcOt0y/a11XOX2gnVPY2OhOAxStytKndPiw1UxpkbPWPi 6m1Y4RhAjG4grDj4V9kiWmcZbH0JFbHq4Gmffu684tABhhm41DTzxZ7An6AAo+ld4y W1YSKIM3Ygy4UXnBORBw+hnbYq9+B321VhO9SLH13tfUHqOKCEPBucfcbBVkYdxysJ jhkmQ/1CsaXV/XMPNdhFmcGiAXdfBeW042It/xYh3X35iwKe8y3s0PuKGr5skjCERF nYEsz+fgTAEoALP77gfTbVT6KBGWBYF3UpHkAhnaFF03FOi9FRuFQdd7V/ydPwCUpg y4wcAlVXhOHGQ== From: Will Deacon To: linux-arm-kernel@lists.infradead.org Cc: Will Deacon , Thomas Gleixner , Marc Zyngier Subject: [PATCH] irqchip/gic-v3-its: Mark some in-memory data structures as 'decrypted' Date: Wed, 8 Dec 2021 15:59:16 +0000 Message-Id: <20211208155916.681-1-will@kernel.org> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211208_075931_465787_36D44867 X-CRM114-Status: GOOD ( 19.25 ) 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 GICv3 ITS driver allocates memory for its tables using alloc_pages() and performs explicit cache maintenance if necessary. On systems such as those running pKVM, where the memory encryption API is implemented, memory shared with the ITS must first be transitioned to the "decrypted" state, as it would be if allocated via the DMA API. Allow pKVM guests to interact with an ITS emulation by ensuring that the shared pages are decrypted at the point of allocation and encrypted again upon free(). Cc: Thomas Gleixner Cc: Marc Zyngier Signed-off-by: Will Deacon --- Although pKVM doesn't yet expose share/unshare hypercalls to the guest, this change is agnostic of the hypervisor and could be queued independently as it has no functional impact when the memory encryption API is not implemented. drivers/irqchip/irq-gic-v3-its.c | 40 ++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index eb0882d15366..4559b8dfb9bc 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -2166,6 +2167,7 @@ static void gic_reset_prop_table(void *va) /* Make sure the GIC will observe the written configuration */ gic_flush_dcache_to_poc(va, LPI_PROPBASE_SZ); + set_memory_decrypted((unsigned long)va, LPI_PROPBASE_SZ >> PAGE_SHIFT); } static struct page *its_allocate_prop_table(gfp_t gfp_flags) @@ -2183,8 +2185,10 @@ static struct page *its_allocate_prop_table(gfp_t gfp_flags) static void its_free_prop_table(struct page *prop_page) { - free_pages((unsigned long)page_address(prop_page), - get_order(LPI_PROPBASE_SZ)); + unsigned long va = (unsigned long)page_address(prop_page); + + set_memory_encrypted(va, LPI_PROPBASE_SZ >> PAGE_SHIFT); + free_pages(va, get_order(LPI_PROPBASE_SZ)); } static bool gic_check_reserved_range(phys_addr_t addr, unsigned long size) @@ -2377,6 +2381,8 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser, return -ENXIO; } + set_memory_decrypted((unsigned long)base, + PAGE_ORDER_TO_SIZE(order) >> PAGE_SHIFT); baser->order = order; baser->base = base; baser->psz = psz; @@ -2512,8 +2518,12 @@ static void its_free_tables(struct its_node *its) for (i = 0; i < GITS_BASER_NR_REGS; i++) { if (its->tables[i].base) { - free_pages((unsigned long)its->tables[i].base, - its->tables[i].order); + unsigned long base = (unsigned long)its->tables[i].base; + u32 order = its->tables[i].order; + u32 npages = PAGE_ORDER_TO_SIZE(order) >> PAGE_SHIFT; + + set_memory_encrypted(base, npages); + free_pages(base, order); its->tables[i].base = NULL; } } @@ -2934,6 +2944,7 @@ static int its_alloc_collections(struct its_node *its) static struct page *its_allocate_pending_table(gfp_t gfp_flags) { struct page *pend_page; + void *va; pend_page = alloc_pages(gfp_flags | __GFP_ZERO, get_order(LPI_PENDBASE_SZ)); @@ -2941,14 +2952,19 @@ static struct page *its_allocate_pending_table(gfp_t gfp_flags) return NULL; /* Make sure the GIC will observe the zero-ed page */ - gic_flush_dcache_to_poc(page_address(pend_page), LPI_PENDBASE_SZ); + va = page_address(pend_page); + gic_flush_dcache_to_poc(va, LPI_PENDBASE_SZ); + set_memory_decrypted((unsigned long)va, LPI_PENDBASE_SZ >> PAGE_SHIFT); return pend_page; } static void its_free_pending_table(struct page *pt) { - free_pages((unsigned long)page_address(pt), get_order(LPI_PENDBASE_SZ)); + unsigned long va = (unsigned long)page_address(pt); + + set_memory_encrypted(va, LPI_PENDBASE_SZ >> PAGE_SHIFT); + free_pages(va, get_order(LPI_PENDBASE_SZ)); } /* @@ -3268,14 +3284,20 @@ static bool its_alloc_table_entry(struct its_node *its, /* Allocate memory for 2nd level table */ if (!table[idx]) { + void *l2addr; + page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, get_order(baser->psz)); if (!page) return false; + l2addr = page_address(page); + set_memory_decrypted((unsigned long)l2addr, + baser->psz >> PAGE_SHIFT); + /* Flush Lvl2 table to PoC if hw doesn't support coherency */ if (!(baser->val & GITS_BASER_SHAREABILITY_MASK)) - gic_flush_dcache_to_poc(page_address(page), baser->psz); + gic_flush_dcache_to_poc(l2addr, baser->psz); table[idx] = cpu_to_le64(page_to_phys(page) | GITS_BASER_VALID); @@ -5043,6 +5065,8 @@ static int __init its_probe_one(struct resource *res, its->fwnode_handle = handle; its->get_msi_base = its_irq_get_msi_base; its->msi_domain_flags = IRQ_DOMAIN_FLAG_MSI_REMAP; + set_memory_decrypted((unsigned long)its->cmd_base, + ITS_CMD_QUEUE_SZ >> PAGE_SHIFT); its_enable_quirks(its); @@ -5099,6 +5123,8 @@ static int __init its_probe_one(struct resource *res, out_free_tables: its_free_tables(its); out_free_cmd: + set_memory_encrypted((unsigned long)its->cmd_base, + ITS_CMD_QUEUE_SZ >> PAGE_SHIFT); free_pages((unsigned long)its->cmd_base, get_order(ITS_CMD_QUEUE_SZ)); out_unmap_sgir: if (its->sgir_base)