From nobody Sun Sep 14 03:51:51 2025 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6B372C38142 for ; Fri, 27 Jan 2023 11:30:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229873AbjA0La4 (ORCPT ); Fri, 27 Jan 2023 06:30:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38002 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229700AbjA0LaJ (ORCPT ); Fri, 27 Jan 2023 06:30:09 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 880304108E for ; Fri, 27 Jan 2023 03:29:07 -0800 (PST) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id C93751691; Fri, 27 Jan 2023 03:29:26 -0800 (PST) Received: from e122027.cambridge.arm.com (e122027.cambridge.arm.com [10.1.35.16]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id AD78A3F64C; Fri, 27 Jan 2023 03:28:42 -0800 (PST) From: Steven Price To: kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: Steven Price , Catalin Marinas , Ard Biesheuvel , Marc Zyngier , Will Deacon , Suzuki K Poulose , James Morse , Oliver Upton , Zenghui Yu , linux-kernel@vger.kernel.org, Joey Gouly , Alexandru Elisei , Christoffer Dall , Fuad Tabba , linux-coco@lists.linux.dev Subject: [RFC PATCH 13/14] arm64: realm: Support nonsecure ITS emulation shared Date: Fri, 27 Jan 2023 11:27:57 +0000 Message-Id: <20230127112758.37891-14-steven.price@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230127112758.37891-1-steven.price@arm.com> References: <20230127112248.136810-1-suzuki.poulose@arm.com> <20230127112758.37891-1-steven.price@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Within a realm guest the ITS is emulated by the host. This means the allocations must have been made available to the host by a call to set_memory_decrypted(). Introduce an allocation function which performs this extra call. Co-developed-by: Suzuki K Poulose Signed-off-by: Suzuki K Poulose Signed-off-by: Steven Price --- drivers/irqchip/irq-gic-v3-its.c | 95 ++++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 24 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-= its.c index 973ede0197e3..5f9829376f6c 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include #include #include =20 @@ -165,6 +167,7 @@ struct its_device { struct its_node *its; struct event_lpi_map event_map; void *itt; + u32 itt_order; u32 nr_ites; u32 device_id; bool shared; @@ -200,6 +203,33 @@ static DEFINE_IDA(its_vpeid_ida); #define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base) #define gic_data_rdist_vlpi_base() (gic_data_rdist_rd_base() + SZ_128K) =20 +static struct page *its_alloc_shared_pages_node(int node, gfp_t gfp, + unsigned int order) +{ + struct page *page; + + if (node =3D=3D NUMA_NO_NODE) + page =3D alloc_pages(gfp, order); + else + page =3D alloc_pages_node(node, gfp, order); + + if (page) + set_memory_decrypted((unsigned long)page_address(page), + 1 << order); + return page; +} + +static struct page *its_alloc_shared_pages(gfp_t gfp, unsigned int order) +{ + return its_alloc_shared_pages_node(NUMA_NO_NODE, gfp, order); +} + +static void its_free_shared_pages(void *addr, unsigned int order) +{ + set_memory_encrypted((unsigned long)addr, 1 << order); + free_pages((unsigned long)addr, order); +} + /* * Skip ITSs that have no vLPIs mapped, unless we're on GICv4.1, as we * always have vSGIs mapped. @@ -2178,7 +2208,8 @@ static struct page *its_allocate_prop_table(gfp_t gfp= _flags) { struct page *prop_page; =20 - prop_page =3D alloc_pages(gfp_flags, get_order(LPI_PROPBASE_SZ)); + prop_page =3D its_alloc_shared_pages(gfp_flags, + get_order(LPI_PROPBASE_SZ)); if (!prop_page) return NULL; =20 @@ -2189,8 +2220,8 @@ static struct page *its_allocate_prop_table(gfp_t gfp= _flags) =20 static void its_free_prop_table(struct page *prop_page) { - free_pages((unsigned long)page_address(prop_page), - get_order(LPI_PROPBASE_SZ)); + its_free_shared_pages(page_address(prop_page), + get_order(LPI_PROPBASE_SZ)); } =20 static bool gic_check_reserved_range(phys_addr_t addr, unsigned long size) @@ -2312,10 +2343,10 @@ static int its_setup_baser(struct its_node *its, st= ruct its_baser *baser, order =3D get_order(GITS_BASER_PAGES_MAX * psz); } =20 - page =3D alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, order); + page =3D its_alloc_shared_pages_node(its->numa_node, + GFP_KERNEL | __GFP_ZERO, order); if (!page) return -ENOMEM; - base =3D (void *)page_address(page); baser_phys =3D virt_to_phys(base); =20 @@ -2325,7 +2356,7 @@ static int its_setup_baser(struct its_node *its, stru= ct its_baser *baser, /* 52bit PA is supported only when PageSize=3D64K */ if (psz !=3D SZ_64K) { pr_err("ITS: no 52bit PA support when psz=3D%d\n", psz); - free_pages((unsigned long)base, order); + its_free_shared_pages(base, order); return -ENXIO; } =20 @@ -2379,7 +2410,7 @@ static int its_setup_baser(struct its_node *its, stru= ct its_baser *baser, pr_err("ITS@%pa: %s doesn't stick: %llx %llx\n", &its->phys_base, its_base_type_string[type], val, tmp); - free_pages((unsigned long)base, order); + its_free_shared_pages(base, order); return -ENXIO; } =20 @@ -2518,8 +2549,8 @@ static void its_free_tables(struct its_node *its) =20 for (i =3D 0; i < GITS_BASER_NR_REGS; i++) { if (its->tables[i].base) { - free_pages((unsigned long)its->tables[i].base, - its->tables[i].order); + its_free_shared_pages(its->tables[i].base, + its->tables[i].order); its->tables[i].base =3D NULL; } } @@ -2778,7 +2809,8 @@ static bool allocate_vpe_l2_table(int cpu, u32 id) =20 /* Allocate memory for 2nd level table */ if (!table[idx]) { - page =3D alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(psz)); + page =3D its_alloc_shared_pages(GFP_KERNEL | __GFP_ZERO, + get_order(psz)); if (!page) return false; =20 @@ -2897,7 +2929,8 @@ static int allocate_vpe_l1_table(void) =20 pr_debug("np =3D %d, npg =3D %lld, psz =3D %d, epp =3D %d, esz =3D %d\n", np, npg, psz, epp, esz); - page =3D alloc_pages(GFP_ATOMIC | __GFP_ZERO, get_order(np * PAGE_SIZE)); + page =3D its_alloc_shared_pages(GFP_ATOMIC | __GFP_ZERO, + get_order(np * PAGE_SIZE)); if (!page) return -ENOMEM; =20 @@ -2941,8 +2974,8 @@ static struct page *its_allocate_pending_table(gfp_t = gfp_flags) { struct page *pend_page; =20 - pend_page =3D alloc_pages(gfp_flags | __GFP_ZERO, - get_order(LPI_PENDBASE_SZ)); + pend_page =3D its_alloc_shared_pages(gfp_flags | __GFP_ZERO, + get_order(LPI_PENDBASE_SZ)); if (!pend_page) return NULL; =20 @@ -2954,7 +2987,8 @@ static struct page *its_allocate_pending_table(gfp_t = gfp_flags) =20 static void its_free_pending_table(struct page *pt) { - free_pages((unsigned long)page_address(pt), get_order(LPI_PENDBASE_SZ)); + its_free_shared_pages(page_address(pt), + get_order(LPI_PENDBASE_SZ)); } =20 /* @@ -3283,8 +3317,9 @@ static bool its_alloc_table_entry(struct its_node *it= s, =20 /* Allocate memory for 2nd level table */ if (!table[idx]) { - page =3D alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, - get_order(baser->psz)); + page =3D its_alloc_shared_pages_node(its->numa_node, + GFP_KERNEL | __GFP_ZERO, + get_order(baser->psz)); if (!page) return false; =20 @@ -3367,7 +3402,9 @@ static struct its_device *its_create_device(struct it= s_node *its, u32 dev_id, unsigned long *lpi_map =3D NULL; unsigned long flags; u16 *col_map =3D NULL; + struct page *page; void *itt; + int itt_order; int lpi_base; int nr_lpis; int nr_ites; @@ -3379,7 +3416,6 @@ static struct its_device *its_create_device(struct it= s_node *its, u32 dev_id, if (WARN_ON(!is_power_of_2(nvecs))) nvecs =3D roundup_pow_of_two(nvecs); =20 - dev =3D kzalloc(sizeof(*dev), GFP_KERNEL); /* * Even if the device wants a single LPI, the ITT must be * sized as a power of two (and you need at least one bit...). @@ -3387,7 +3423,16 @@ static struct its_device *its_create_device(struct i= ts_node *its, u32 dev_id, nr_ites =3D max(2, nvecs); sz =3D nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1); sz =3D max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1; - itt =3D kzalloc_node(sz, GFP_KERNEL, its->numa_node); + itt_order =3D get_order(sz); + page =3D its_alloc_shared_pages_node(its->numa_node, + GFP_KERNEL | __GFP_ZERO, + itt_order); + if (!page) + return NULL; + itt =3D (void *)page_address(page); + + dev =3D kzalloc(sizeof(*dev), GFP_KERNEL); + if (alloc_lpis) { lpi_map =3D its_lpi_alloc(nvecs, &lpi_base, &nr_lpis); if (lpi_map) @@ -3399,9 +3444,9 @@ static struct its_device *its_create_device(struct it= s_node *its, u32 dev_id, lpi_base =3D 0; } =20 - if (!dev || !itt || !col_map || (!lpi_map && alloc_lpis)) { + if (!dev || !col_map || (!lpi_map && alloc_lpis)) { kfree(dev); - kfree(itt); + its_free_shared_pages(itt, itt_order); bitmap_free(lpi_map); kfree(col_map); return NULL; @@ -3411,6 +3456,7 @@ static struct its_device *its_create_device(struct it= s_node *its, u32 dev_id, =20 dev->its =3D its; dev->itt =3D itt; + dev->itt_order =3D itt_order; dev->nr_ites =3D nr_ites; dev->event_map.lpi_map =3D lpi_map; dev->event_map.col_map =3D col_map; @@ -3438,7 +3484,7 @@ static void its_free_device(struct its_device *its_de= v) list_del(&its_dev->entry); raw_spin_unlock_irqrestore(&its_dev->its->lock, flags); kfree(its_dev->event_map.col_map); - kfree(its_dev->itt); + its_free_shared_pages(its_dev->itt, its_dev->itt_order); kfree(its_dev); } =20 @@ -5064,8 +5110,9 @@ static int __init its_probe_one(struct resource *res, =20 its->numa_node =3D numa_node; =20 - page =3D alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, - get_order(ITS_CMD_QUEUE_SZ)); + page =3D its_alloc_shared_pages_node(its->numa_node, + GFP_KERNEL | __GFP_ZERO, + get_order(ITS_CMD_QUEUE_SZ)); if (!page) { err =3D -ENOMEM; goto out_unmap_sgir; @@ -5131,7 +5178,7 @@ static int __init its_probe_one(struct resource *res, out_free_tables: its_free_tables(its); out_free_cmd: - free_pages((unsigned long)its->cmd_base, get_order(ITS_CMD_QUEUE_SZ)); + its_free_shared_pages(its->cmd_base, get_order(ITS_CMD_QUEUE_SZ)); out_unmap_sgir: if (its->sgir_base) iounmap(its->sgir_base); --=20 2.34.1