From nobody Tue Sep 29 02:33:19 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EFF6036196E; Thu, 13 Aug 2026 10:25:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786616754; cv=none; b=itxUmDChwZ3dMxn2QYTd+Kh5bLJVfLABHyANsyoE67P6FuN54l8ajLHKvcw/anjiSSUQR0Xp/k84vmDDE0rJaHliC5H0d1b02nSw3mAggnH4e4JzVWlVre06g3xzlIzxHNQWw+p91hguRyXwpdXdnd/rEHWE8GBgyAN3eW8JNRE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786616754; c=relaxed/simple; bh=OuK9pk/zzN0vhb8IOFVugCvZ/3CC7EImWr8tYDDJrDs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=phbYz1Q93bnWttATNicQZZB2cPV0jUdL7KoqaBjFRJ9Cj5ZfNc65TgPEAW1Art2ECq0pZg53VZ/SmZpUnCUAKe0iWS4cwGmJ638JB3i4oPQAq6zV5oQlKFB/p1i8z8msbXKna0vfId19IFnWS98A2EEuSxB5J4l0w4M/nVR3Gao= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GIVWEmZx; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GIVWEmZx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 197721F00A3A; Thu, 13 Aug 2026 10:25:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786616752; bh=XabZ2hWfS6jdH7PFxaix/OtkUgZ46txEKjxMvcXWLco=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=GIVWEmZx9jrdikgyqVtBDit8iXafTBpBIomAYLvCLrD3WHKZ/ew6xzRhiincMsyUD TS1tIEuEvR1Ngfv/SUJObJ4FqY8L/f8qG9iG/GW8FnB5qhC7uZMKHTMWTYw3A1A2i3 Yd+aPZavImK2W86PN3UEK1uOcZXlrsv6TXFFtGbFVrdmDwnc7Am0d1JZyoJulK0Psx TzgS5SeZTkMwgab/rgGK5ZDPZfMd2filMN7bnXX+KxHEjB8BLyDIa4/vvJfg2Xvpsi MTWcgJr0oXLJFw6ysiHS9Puyi0DJ7BbHMiGjA0yoLiCTEqNII08un6PFO5iczy8wCg hLJhA7OSWVdJw== From: "Aneesh Kumar K.V (Arm)" To: iommu@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-coco@lists.linux.dev Cc: Robin Murphy , Marek Szyprowski , Will Deacon , Marc Zyngier , Steven Price , Suzuki K Poulose , Catalin Marinas , Jiri Pirko , Jason Gunthorpe , Mostafa Saleh , Petr Tesarik , Alexey Kardashevskiy , Xu Yilun , linuxppc-dev@lists.ozlabs.org, linux-s390@vger.kernel.org, Madhavan Srinivasan , Michael Ellerman , Nicholas Piggin , Christophe Leroy , Alexander Gordeev , Gerald Schaefer , Heiko Carstens , Vasily Gorbik , Christian Borntraeger , Sven Schnelle , x86@kernel.org, "Aneesh Kumar K.V (Arm)" Subject: [RFC PATCH v2 1/2] dma: swiotlb: Centralize default pool initialization and sizing Date: Thu, 13 Aug 2026 15:55:20 +0530 Message-ID: <20260813102521.1367737-2-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260813102521.1367737-1-aneesh.kumar@kernel.org> References: <20260813102521.1367737-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The addressing_limited argument to swiotlb_init() no longer describes all the reasons why a default swiotlb pool may be needed. Confidential computing systems need a shared pool even without addressing limitations, while some systems need a smaller pool for bouncing unaligned kmalloc buffers. Replace the argument with SWIOTLB_INIT_ADDRESSING_LIMIT and SWIOTLB_INIT_CC_SHARED reason flags, and add swiotlb_should_init() to determine whether initialization is required for limited DMA addressing, confidential-computing shared DMA, unaligned kmalloc bouncing, or swiotlb=3Dforce. Have architectures report addressing-limit and confidential-computing requirements before swiotlb_init(). Mark CC pools shared before their memory attributes are updated, and keep both addressing-limited and CC-shared pools at their normal size instead of applying the reduced kmalloc-only sizing policy. Move the reduced kmalloc-bounce sizing policy from arm64 and RISC-V into the SWIOTLB core. This keeps architecture code responsible for reporting why a pool is needed while centralizing initialization and sizing decisions. Signed-off-by: Aneesh Kumar K.V (Arm) Reviewed-by: Catalin Marinas --- arch/arm/mm/init.c | 6 +++- arch/arm64/mm/init.c | 18 ++++------ arch/loongarch/kernel/setup.c | 2 +- arch/mips/cavium-octeon/dma-octeon.c | 2 +- arch/mips/loongson64/dma.c | 2 +- arch/mips/sibyte/common/dma.c | 2 +- arch/powerpc/kernel/dma-swiotlb.c | 4 ++- arch/powerpc/mm/mem.c | 15 +++++++- arch/powerpc/platforms/pseries/svm.c | 10 ------ arch/powerpc/sysdev/fsl_pci.c | 1 + arch/riscv/mm/init.c | 18 +++------- arch/s390/mm/init.c | 2 +- arch/x86/include/asm/iommu.h | 2 ++ arch/x86/kernel/amd_gart_64.c | 1 + arch/x86/kernel/pci-dma.c | 17 +++++---- arch/x86/mm/mem_encrypt.c | 4 +++ include/linux/swiotlb.h | 12 ++++--- kernel/dma/swiotlb.c | 52 ++++++++++++++++++++++++---- 18 files changed, 109 insertions(+), 61 deletions(-) diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 0cc1bf04686d..aca97a4e5dcd 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -223,7 +223,11 @@ static inline void poison_init_mem(void *s, size_t cou= nt) void __init arch_mm_preinit(void) { #ifdef CONFIG_ARM_LPAE - swiotlb_init(max_pfn > arm_dma_pfn_limit, SWIOTLB_VERBOSE); + unsigned int flags =3D SWIOTLB_VERBOSE; + + if (max_pfn > arm_dma_pfn_limit) + flags |=3D SWIOTLB_INIT_ADDRESSING_LIMIT; + swiotlb_init(flags); #endif =20 #ifdef CONFIG_SA1111 diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index e308a7cabd12..9f5b366d2086 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -338,19 +338,15 @@ void __init arch_setup_zero_pages(void) void __init arch_mm_preinit(void) { unsigned int flags =3D SWIOTLB_VERBOSE; + /* pKVM uses restricted-dma-pool */ + bool cc_guest =3D is_realm_world(); =20 - if (max_pfn <=3D PFN_DOWN(arm64_dma_phys_limit)) { - /* - * If no bouncing needed for ZONE_DMA, reduce the swiotlb - * buffer for kmalloc() bouncing to 1MB per 1GB of RAM. - */ - unsigned long size =3D - DIV_ROUND_UP(memblock_phys_mem_size(), 1024); - - swiotlb_adjust_size(min(swiotlb_size_or_default(), size)); - } + if (cc_guest) + flags |=3D SWIOTLB_INIT_CC_SHARED; + else if (max_pfn > PFN_DOWN(arm64_dma_phys_limit)) + flags |=3D SWIOTLB_INIT_ADDRESSING_LIMIT; =20 - swiotlb_init(true, flags); + swiotlb_init(flags); =20 /* * Check boundaries twice: Some fundamental inconsistencies can be diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c index eaebb52bd36e..5952eec7d570 100644 --- a/arch/loongarch/kernel/setup.c +++ b/arch/loongarch/kernel/setup.c @@ -404,7 +404,7 @@ static void __init arch_mem_init(char **cmdline_p) =20 memblock_set_bottom_up(true); =20 - swiotlb_init(true, SWIOTLB_VERBOSE); + swiotlb_init(SWIOTLB_VERBOSE | SWIOTLB_INIT_ADDRESSING_LIMIT); =20 dma_contiguous_reserve(PFN_PHYS(max_low_pfn)); =20 diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon= /dma-octeon.c index 9fbba6a8fa4c..ca7c37bc070f 100644 --- a/arch/mips/cavium-octeon/dma-octeon.c +++ b/arch/mips/cavium-octeon/dma-octeon.c @@ -235,5 +235,5 @@ void __init plat_swiotlb_setup(void) #endif =20 swiotlb_adjust_size(swiotlbsize); - swiotlb_init(true, SWIOTLB_VERBOSE); + swiotlb_init(SWIOTLB_VERBOSE | SWIOTLB_INIT_ADDRESSING_LIMIT); } diff --git a/arch/mips/loongson64/dma.c b/arch/mips/loongson64/dma.c index 52801442ea86..5b8056e6c5a8 100644 --- a/arch/mips/loongson64/dma.c +++ b/arch/mips/loongson64/dma.c @@ -25,5 +25,5 @@ phys_addr_t dma_to_phys(struct device *dev, dma_addr_t da= ddr) =20 void __init plat_swiotlb_setup(void) { - swiotlb_init(true, SWIOTLB_VERBOSE); + swiotlb_init(SWIOTLB_VERBOSE | SWIOTLB_INIT_ADDRESSING_LIMIT); } diff --git a/arch/mips/sibyte/common/dma.c b/arch/mips/sibyte/common/dma.c index c5c2c782aff6..3835fee21489 100644 --- a/arch/mips/sibyte/common/dma.c +++ b/arch/mips/sibyte/common/dma.c @@ -10,5 +10,5 @@ =20 void __init plat_swiotlb_setup(void) { - swiotlb_init(true, SWIOTLB_VERBOSE); + swiotlb_init(SWIOTLB_VERBOSE | SWIOTLB_INIT_ADDRESSING_LIMIT); } diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-sw= iotlb.c index ba256c37bcc0..97fffa46f05a 100644 --- a/arch/powerpc/kernel/dma-swiotlb.c +++ b/arch/powerpc/kernel/dma-swiotlb.c @@ -14,8 +14,10 @@ unsigned int ppc_swiotlb_flags; =20 void __init swiotlb_detect_4g(void) { - if ((memblock_end_of_DRAM() - 1) > 0xffffffff) + if ((memblock_end_of_DRAM() - 1) > 0xffffffff) { ppc_swiotlb_enable =3D 1; + ppc_swiotlb_flags |=3D SWIOTLB_INIT_ADDRESSING_LIMIT; + } } =20 static int __init check_swiotlb_enabled(void) diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 4c1afab91996..f93a89e18498 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -287,6 +287,19 @@ void __init arch_mm_preinit(void) BUILD_BUG_ON(MMU_PAGE_COUNT > 16); =20 #ifdef CONFIG_SWIOTLB + if (is_secure_guest()) { + + /* Don't release the SWIOTLB buffer. */ + ppc_swiotlb_enable =3D 1; + + /* + * Since the guest memory is inaccessible to the host, + * devices always need to use the SWIOTLB buffer for DMA + * even if dma_capable() says otherwise. + */ + ppc_swiotlb_flags |=3D SWIOTLB_INIT_CC_SHARED | SWIOTLB_ANY; + } + /* * Some platforms (e.g. 85xx) limit DMA-able memory way below * 4G. We force memblock to bottom-up mode to ensure that the @@ -295,7 +308,7 @@ void __init arch_mm_preinit(void) * back to to-down. */ memblock_set_bottom_up(true); - swiotlb_init(ppc_swiotlb_enable, ppc_swiotlb_flags); + swiotlb_init(ppc_swiotlb_flags); #endif =20 kasan_late_init(); diff --git a/arch/powerpc/platforms/pseries/svm.c b/arch/powerpc/platforms/= pseries/svm.c index 7a403dbd35ee..4a0be631dc6d 100644 --- a/arch/powerpc/platforms/pseries/svm.c +++ b/arch/powerpc/platforms/pseries/svm.c @@ -21,16 +21,6 @@ static int __init init_svm(void) if (!is_secure_guest()) return 0; =20 - /* Don't release the SWIOTLB buffer. */ - ppc_swiotlb_enable =3D 1; - - /* - * Since the guest memory is inaccessible to the host, devices always - * need to use the SWIOTLB buffer for DMA even if dma_capable() says - * otherwise. - */ - ppc_swiotlb_flags |=3D SWIOTLB_ANY; - /* Share the SWIOTLB buffer with the host. */ swiotlb_update_mem_attributes(); =20 diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 600f83cea1cd..49264e25108b 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -444,6 +444,7 @@ static void setup_pci_atmu(struct pci_controller *hose) if (hose->dma_window_size < mem) { #ifdef CONFIG_SWIOTLB ppc_swiotlb_enable =3D 1; + ppc_swiotlb_flags |=3D SWIOTLB_INIT_ADDRESSING_LIMIT; #else pr_err("%pOF: ERROR: Memory size exceeds PCI ATMU ability to " "map - enable CONFIG_SWIOTLB to avoid dma errors.\n", diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index 5b1b3c88b4d1..2d7c5aaeea19 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -162,25 +162,15 @@ static void print_vm_layout(void) { } =20 void __init arch_mm_preinit(void) { - bool swiotlb =3D max_pfn > PFN_DOWN(dma32_phys_limit); + unsigned int flags =3D SWIOTLB_VERBOSE; #ifdef CONFIG_FLATMEM BUG_ON(!mem_map); #endif /* CONFIG_FLATMEM */ =20 - if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) && !swiotlb && - dma_cache_alignment !=3D 1) { - /* - * If no bouncing needed for ZONE_DMA, allocate 1MB swiotlb - * buffer per 1GB of RAM for kmalloc() bouncing on - * non-coherent platforms. - */ - unsigned long size =3D - DIV_ROUND_UP(memblock_phys_mem_size(), 1024); - swiotlb_adjust_size(min(swiotlb_size_or_default(), size)); - swiotlb =3D true; - } + if (max_pfn > PFN_DOWN(dma32_phys_limit)) + flags |=3D SWIOTLB_INIT_ADDRESSING_LIMIT; =20 - swiotlb_init(swiotlb, SWIOTLB_VERBOSE); + swiotlb_init(flags); =20 print_vm_layout(); } diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index 8d1de5a2e554..801f8ac95250 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -166,7 +166,7 @@ static void __init pv_init(void) virtio_set_mem_acc_cb(virtio_require_restricted_mem_acc); =20 /* make sure bounce buffers are shared */ - swiotlb_init(true, SWIOTLB_VERBOSE); + swiotlb_init(SWIOTLB_VERBOSE | SWIOTLB_INIT_CC_SHARED); swiotlb_update_mem_attributes(); } =20 diff --git a/arch/x86/include/asm/iommu.h b/arch/x86/include/asm/iommu.h index 3be2451e7bc8..22c8190fe34d 100644 --- a/arch/x86/include/asm/iommu.h +++ b/arch/x86/include/asm/iommu.h @@ -14,8 +14,10 @@ extern bool amd_iommu_snp_en; =20 #ifdef CONFIG_SWIOTLB extern bool x86_swiotlb_enable; +extern unsigned int x86_swiotlb_flags; #else #define x86_swiotlb_enable false +#define x86_swiotlb_flags 0 #endif =20 /* 10 seconds */ diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c index b5f1f031d45b..d0fbc0271e43 100644 --- a/arch/x86/kernel/amd_gart_64.c +++ b/arch/x86/kernel/amd_gart_64.c @@ -814,6 +814,7 @@ int __init gart_iommu_init(void) dma_ops =3D &gart_dma_ops; x86_platform.iommu_shutdown =3D gart_iommu_shutdown; x86_swiotlb_enable =3D false; + x86_swiotlb_flags =3D 0; =20 return 0; } diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 75cf8f6ae8cd..a02a0b098591 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -39,13 +39,15 @@ int iommu_detected __read_mostly =3D 0; =20 #ifdef CONFIG_SWIOTLB bool x86_swiotlb_enable; -static unsigned int x86_swiotlb_flags; +unsigned int x86_swiotlb_flags; =20 static void __init pci_swiotlb_detect(void) { /* don't initialize swiotlb if iommu=3Doff (no_iommu=3D1) */ - if (!no_iommu && max_possible_pfn > MAX_DMA32_PFN) + if (!no_iommu && max_possible_pfn > MAX_DMA32_PFN) { x86_swiotlb_enable =3D true; + x86_swiotlb_flags |=3D SWIOTLB_INIT_ADDRESSING_LIMIT; + } =20 /* * Set swiotlb to 1 so that bounce buffers are allocated and used for @@ -66,7 +68,6 @@ static void __init pci_swiotlb_detect(void) static inline void __init pci_swiotlb_detect(void) { } -#define x86_swiotlb_flags 0 #endif /* CONFIG_SWIOTLB */ =20 #ifdef CONFIG_SWIOTLB_XEN @@ -81,8 +82,8 @@ static void __init pci_xen_swiotlb_init(void) if (!xen_swiotlb_enabled()) return; x86_swiotlb_enable =3D true; - x86_swiotlb_flags |=3D SWIOTLB_ANY; - swiotlb_init_remap(true, x86_swiotlb_flags, xen_swiotlb_fixup); + x86_swiotlb_flags |=3D SWIOTLB_INIT_ADDRESSING_LIMIT | SWIOTLB_ANY; + swiotlb_init_remap(x86_swiotlb_flags, xen_swiotlb_fixup); dma_ops =3D &xen_swiotlb_dma_ops; if (IS_ENABLED(CONFIG_PCI)) pci_request_acs(); @@ -103,7 +104,7 @@ void __init pci_iommu_alloc(void) gart_iommu_hole_init(); amd_iommu_detect(); detect_intel_iommu(); - swiotlb_init(x86_swiotlb_enable, x86_swiotlb_flags); + swiotlb_init(x86_swiotlb_flags); } =20 static __init int iommu_setup(char *p) @@ -149,8 +150,10 @@ static __init int iommu_setup(char *p) return 1; } #ifdef CONFIG_SWIOTLB - if (!strncmp(p, "soft", 4)) + if (!strncmp(p, "soft", 4)) { x86_swiotlb_enable =3D true; + x86_swiotlb_flags |=3D SWIOTLB_INIT_ADDRESSING_LIMIT; + } #endif if (!strncmp(p, "pt", 2)) iommu_set_default_passthrough(true); diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c index 95bae74fdab2..7f17c05a0209 100644 --- a/arch/x86/mm/mem_encrypt.c +++ b/arch/x86/mm/mem_encrypt.c @@ -14,6 +14,7 @@ #include #include =20 +#include #include =20 /* Override for DMA direct allocation check - ARCH_HAS_FORCE_DMA_UNENCRYPT= ED */ @@ -111,6 +112,9 @@ void __init mem_encrypt_setup_arch(void) if (cc_platform_has(CC_ATTR_HOST_SEV_SNP)) snp_fixup_e820_tables(); =20 + if (cc_platform_has(CC_ATTR_MEM_ENCRYPT)) + x86_swiotlb_flags |=3D SWIOTLB_INIT_CC_SHARED; + if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) return; =20 diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h index 277b9aa2edaa..f0548fb81785 100644 --- a/include/linux/swiotlb.h +++ b/include/linux/swiotlb.h @@ -16,6 +16,10 @@ struct scatterlist; =20 #define SWIOTLB_VERBOSE (1 << 0) /* verbose initialization */ #define SWIOTLB_ANY (1 << 1) /* allow any memory for the buffer */ +/* Initialize a default-sized pool for devices with limited DMA addressing= . */ +#define SWIOTLB_INIT_ADDRESSING_LIMIT (1 << 2) +/* Initialize a shared default pool for confidential-computing systems. */ +#define SWIOTLB_INIT_CC_SHARED (1 << 3) =20 /* * Maximum allowable number of contiguous slabs to map, @@ -39,8 +43,8 @@ struct scatterlist; #endif =20 unsigned long swiotlb_size_or_default(void); -void __init swiotlb_init_remap(bool addressing_limit, unsigned int flags, - int (*remap)(void *tlb, unsigned long nslabs)); +void __init swiotlb_init_remap(unsigned int flags, + int (*remap)(void *tlb, unsigned long nslabs)); int swiotlb_init_late(size_t size, gfp_t gfp_mask, int (*remap)(void *tlb, unsigned long nslabs)); extern void __init swiotlb_update_mem_attributes(void); @@ -183,7 +187,7 @@ static inline bool is_swiotlb_force_bounce(struct devic= e *dev) return mem && mem->force_bounce; } =20 -void swiotlb_init(bool addressing_limited, unsigned int flags); +void swiotlb_init(unsigned int flags); void __init swiotlb_exit(void); void swiotlb_dev_init(struct device *dev); size_t swiotlb_max_mapping_size(struct device *dev); @@ -193,7 +197,7 @@ void __init swiotlb_adjust_size(unsigned long size); phys_addr_t default_swiotlb_base(void); phys_addr_t default_swiotlb_limit(void); #else -static inline void swiotlb_init(bool addressing_limited, unsigned int flag= s) +static inline void swiotlb_init(unsigned int flags) { } =20 diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c index 897aba538c5b..dd1bf6c61446 100644 --- a/kernel/dma/swiotlb.c +++ b/kernel/dma/swiotlb.c @@ -382,12 +382,37 @@ static void __init *swiotlb_memblock_alloc(unsigned l= ong nslabs, return tlb; } =20 +static bool __init swiotlb_kmalloc_needs_bounce(void) +{ + return IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) && + (dma_get_cache_alignment() > 1); +} + +static bool __init swiotlb_should_init(unsigned int flags) +{ + if (swiotlb_force_disable) + return false; + + if (flags & SWIOTLB_INIT_ADDRESSING_LIMIT) + return true; + + if (swiotlb_kmalloc_needs_bounce()) + return true; + + if (swiotlb_force_bounce) + return true; + + if (flags & SWIOTLB_INIT_CC_SHARED) + return true; + + return false; +} /* * Statically reserve bounce buffer space and initialize bounce buffer data * structures for the software IO TLB used to implement the DMA API. */ -void __init swiotlb_init_remap(bool addressing_limit, unsigned int flags, - int (*remap)(void *tlb, unsigned long nslabs)) +void __init swiotlb_init_remap(unsigned int flags, + int (*remap)(void *tlb, unsigned long nslabs)) { struct io_tlb_pool *mem =3D &io_tlb_default_mem.defpool; unsigned long nslabs; @@ -395,11 +420,12 @@ void __init swiotlb_init_remap(bool addressing_limit,= unsigned int flags, size_t alloc_size; void *tlb; =20 - if (!addressing_limit && !swiotlb_force_bounce) - return; - if (swiotlb_force_disable) + if (!swiotlb_should_init(flags)) return; =20 + if (flags & SWIOTLB_INIT_CC_SHARED) + io_tlb_default_mem.cc_shared =3D true; + io_tlb_default_mem.force_bounce =3D swiotlb_force_bounce; =20 #ifdef CONFIG_SWIOTLB_DYNAMIC @@ -411,6 +437,18 @@ void __init swiotlb_init_remap(bool addressing_limit, = unsigned int flags, io_tlb_default_mem.phys_limit =3D ARCH_LOW_ADDRESS_LIMIT; #endif =20 + if (!(flags & (SWIOTLB_INIT_ADDRESSING_LIMIT | + SWIOTLB_INIT_CC_SHARED)) && + swiotlb_kmalloc_needs_bounce()) { + /* + * If no bouncing needed for ZONE_DMA, reduce the swiotlb + * buffer for kmalloc() bouncing to 1MB per 1GB of RAM. + */ + unsigned long size =3D + DIV_ROUND_UP(memblock_phys_mem_size(), 1024); + + swiotlb_adjust_size(min(swiotlb_size_or_default(), size)); + } if (!default_nareas) swiotlb_adjust_nareas(num_possible_cpus()); =20 @@ -451,9 +489,9 @@ void __init swiotlb_init_remap(bool addressing_limit, u= nsigned int flags, swiotlb_print_info(); } =20 -void __init swiotlb_init(bool addressing_limit, unsigned int flags) +void __init swiotlb_init(unsigned int flags) { - swiotlb_init_remap(addressing_limit, flags, NULL); + swiotlb_init_remap(flags, NULL); } =20 /* --=20 2.43.0 From nobody Tue Sep 29 02:33:19 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DC5893BBFA9; Thu, 13 Aug 2026 10:26:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786616765; cv=none; b=VHl/5bOWBoVyNUevhfXky0UwfaKCQuIJsPg0o0p6K1lOM0j/kcaMqdrWuttieFowU4vj6K0ud6OnaN8QrQw4/pbnFUj+xfljQVPOSsS5SQMGSZASgA8bC2eQSRvAlsVcdT0SpAhiY1Y1y79Whn0tIhK72mK8CRxoV81ZbUbcfZI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786616765; c=relaxed/simple; bh=w1rZoQgKcVqAHDxDAHE8BXphwtwq2nTt3wv3JpATXoM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=S4oDONm/13wnMByNS8N2OKLMOA3/E16xVhLyYZWgRykMZ1T7jIiU4GT9rkJBM2QjfElaw9Rp8MPHNiQvP57uT/nBGyPs0FQ6nb47lxo49Ig6y5wgo9pKYRmyn45Jn7fEfy6K8vXwl/LZLe2aUtvyL2oY2tPqH+oa6jTsL/CDuvg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VjhLqTpm; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VjhLqTpm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 699F91F000E9; Thu, 13 Aug 2026 10:25:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786616762; bh=5PHCW/v+JKvQwWv1NsSjsLXYqOrxgLeGNzW79kSPybs=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=VjhLqTpmNuACKc18t0b3/0fPvVuC2WT7W8CwhFzRpLuw2RYUAWspOWsTL/3tU9A8m K3dJxQJG5Xoce+jD9MeNMjg/bjmQfnMci+IwDHfaD7czycm723XOEihrbOaTp+G4Mh X/aVFs7j7/FCx5FyXGU/cBY1zDI9odFKn2RfiSqxkR6wbxEVsGfQMVDliG2BUwC8fs vpqvTNHcQSZLnYL4d+oIx8fDqa+CfcjUaM/MsYotAO3++KZNBeGmnOUQEHDvVp2mb/ SheJh4I1cQTHEsVu2ON+AE8ZrEAdcTZGzzk8Mo7fmREXAL2RaktvDcamGxmwgf8iff tUUlpTFec5SbA== From: "Aneesh Kumar K.V (Arm)" To: iommu@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-coco@lists.linux.dev Cc: Robin Murphy , Marek Szyprowski , Will Deacon , Marc Zyngier , Steven Price , Suzuki K Poulose , Catalin Marinas , Jiri Pirko , Jason Gunthorpe , Mostafa Saleh , Petr Tesarik , Alexey Kardashevskiy , Xu Yilun , linuxppc-dev@lists.ozlabs.org, linux-s390@vger.kernel.org, Madhavan Srinivasan , Michael Ellerman , Nicholas Piggin , Christophe Leroy , Alexander Gordeev , Gerald Schaefer , Heiko Carstens , Vasily Gorbik , Christian Borntraeger , Sven Schnelle , x86@kernel.org, "Aneesh Kumar K.V (Arm)" Subject: [RFC PATCH v2 2/2] dma: swiotlb: Initialize and size shared default pools for memory encryption Date: Thu, 13 Aug 2026 15:55:21 +0530 Message-ID: <20260813102521.1367737-3-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260813102521.1367737-1-aneesh.kumar@kernel.org> References: <20260813102521.1367737-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Systems with memory encryption require shared or unencrypted buffers for device DMA. Confidential guests may route all DMA through SWIOTLB, making the default pool too small for I/O-intensive workloads. Host memory encryption also requires a shared default pool when bouncing is needed, but does not require the guest sizing policy. Move the existing x86 sizing policy into the SWIOTLB core. Detect memory encryption before allocating the default pool so that it is initialized and marked shared even without DMA addressing limitations. Increase the pool size to 6% of guest memory, clamped between the default size and 1 GiB, only for confidential guests. The core can determine the confidential-computing requirement directly, so remove SWIOTLB_INIT_CC_SHARED and its architecture uses. Keep the pseries secure-guest setup before swiotlb_init() so that the pool is allocated with SWIOTLB_ANY and is not released later. A restricted DMA pool already supplies shared bounce buffers for its devices. Record its presence during reserved-memory initialization and avoid initializing or marking the default pool as shared solely because memory encryption is enabled. Signed-off-by: Aneesh Kumar K.V (Arm) --- arch/arm64/mm/init.c | 6 +--- arch/powerpc/mm/mem.c | 2 +- arch/s390/mm/init.c | 2 +- arch/x86/mm/mem_encrypt.c | 28 --------------- include/linux/swiotlb.h | 2 -- kernel/dma/swiotlb.c | 72 +++++++++++++++++++++++++++++---------- 6 files changed, 57 insertions(+), 55 deletions(-) diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 9f5b366d2086..c3188ca878f3 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -338,12 +338,8 @@ void __init arch_setup_zero_pages(void) void __init arch_mm_preinit(void) { unsigned int flags =3D SWIOTLB_VERBOSE; - /* pKVM uses restricted-dma-pool */ - bool cc_guest =3D is_realm_world(); =20 - if (cc_guest) - flags |=3D SWIOTLB_INIT_CC_SHARED; - else if (max_pfn > PFN_DOWN(arm64_dma_phys_limit)) + if (max_pfn > PFN_DOWN(arm64_dma_phys_limit)) flags |=3D SWIOTLB_INIT_ADDRESSING_LIMIT; =20 swiotlb_init(flags); diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index f93a89e18498..b77946db3f17 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -297,7 +297,7 @@ void __init arch_mm_preinit(void) * devices always need to use the SWIOTLB buffer for DMA * even if dma_capable() says otherwise. */ - ppc_swiotlb_flags |=3D SWIOTLB_INIT_CC_SHARED | SWIOTLB_ANY; + ppc_swiotlb_flags |=3D SWIOTLB_ANY; } =20 /* diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index 801f8ac95250..ce10292447f1 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -166,7 +166,7 @@ static void __init pv_init(void) virtio_set_mem_acc_cb(virtio_require_restricted_mem_acc); =20 /* make sure bounce buffers are shared */ - swiotlb_init(SWIOTLB_VERBOSE | SWIOTLB_INIT_CC_SHARED); + swiotlb_init(SWIOTLB_VERBOSE); swiotlb_update_mem_attributes(); } =20 diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c index 7f17c05a0209..912f22ca838f 100644 --- a/arch/x86/mm/mem_encrypt.c +++ b/arch/x86/mm/mem_encrypt.c @@ -14,7 +14,6 @@ #include #include =20 -#include #include =20 /* Override for DMA direct allocation check - ARCH_HAS_FORCE_DMA_UNENCRYPT= ED */ @@ -102,9 +101,6 @@ void __init mem_encrypt_init(void) =20 void __init mem_encrypt_setup_arch(void) { - phys_addr_t total_mem =3D memblock_phys_mem_size(); - unsigned long size; - /* * Do RMP table fixups after the e820 tables have been setup by * e820__memory_setup(). @@ -112,33 +108,9 @@ void __init mem_encrypt_setup_arch(void) if (cc_platform_has(CC_ATTR_HOST_SEV_SNP)) snp_fixup_e820_tables(); =20 - if (cc_platform_has(CC_ATTR_MEM_ENCRYPT)) - x86_swiotlb_flags |=3D SWIOTLB_INIT_CC_SHARED; - if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) return; =20 - /* - * For SEV and TDX, all DMA has to occur via shared/unencrypted pages. - * Kernel uses SWIOTLB to make this happen without changing device - * drivers. However, depending on the workload being run, the - * default 64MB of SWIOTLB may not be enough and SWIOTLB may - * run out of buffers for DMA, resulting in I/O errors and/or - * performance degradation especially with high I/O workloads. - * - * Adjust the default size of SWIOTLB using a percentage of guest - * memory for SWIOTLB buffers. Also, as the SWIOTLB bounce buffer - * memory is allocated from low memory, ensure that the adjusted size - * is within the limits of low available memory. - * - * The percentage of guest memory used here for SWIOTLB buffers - * is more of an approximation of the static adjustment which - * 64MB for <1G, and ~128M to 256M for 1G-to-4G, i.e., the 6% - */ - size =3D total_mem * 6 / 100; - size =3D clamp_val(size, IO_TLB_DEFAULT_SIZE, SZ_1G); - swiotlb_adjust_size(size); - /* Set restricted memory access for virtio. */ virtio_set_mem_acc_cb(virtio_require_restricted_mem_acc); } diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h index f0548fb81785..9afb7c9a447a 100644 --- a/include/linux/swiotlb.h +++ b/include/linux/swiotlb.h @@ -18,8 +18,6 @@ struct scatterlist; #define SWIOTLB_ANY (1 << 1) /* allow any memory for the buffer */ /* Initialize a default-sized pool for devices with limited DMA addressing= . */ #define SWIOTLB_INIT_ADDRESSING_LIMIT (1 << 2) -/* Initialize a shared default pool for confidential-computing systems. */ -#define SWIOTLB_INIT_CC_SHARED (1 << 3) =20 /* * Maximum allowable number of contiguous slabs to map, diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c index dd1bf6c61446..67b57831b4bc 100644 --- a/kernel/dma/swiotlb.c +++ b/kernel/dma/swiotlb.c @@ -80,6 +80,7 @@ struct io_tlb_slot { =20 static bool swiotlb_force_bounce; static bool swiotlb_force_disable; +static bool restricted_dma_pool_present __initdata; =20 #ifdef CONFIG_SWIOTLB_DYNAMIC =20 @@ -274,24 +275,15 @@ static void swiotlb_mark_pool_used(struct io_tlb_pool= *pool) void __init swiotlb_update_mem_attributes(void) { struct io_tlb_pool *mem =3D &io_tlb_default_mem.defpool; - unsigned long bytes; - - /* - * if platform support memory encryption, swiotlb buffers are - * shared by default. - */ - if (cc_platform_has(CC_ATTR_MEM_ENCRYPT)) - io_tlb_default_mem.cc_shared =3D true; - else - io_tlb_default_mem.cc_shared =3D false; =20 if (!mem->nslabs || mem->late_alloc) return; - bytes =3D PAGE_ALIGN(mem->nslabs << IO_TLB_SHIFT); =20 if (io_tlb_default_mem.cc_shared) { int ret; + unsigned long bytes; =20 + bytes =3D PAGE_ALIGN(mem->nslabs << IO_TLB_SHIFT); ret =3D set_memory_decrypted((unsigned long)mem->vaddr, bytes >> PAGE_SHIFT); if (ret) { @@ -382,12 +374,54 @@ static void __init *swiotlb_memblock_alloc(unsigned l= ong nslabs, return tlb; } =20 +static void __init swiotlb_adjust_cc_attributes(void) +{ + unsigned long size; + phys_addr_t total_mem =3D memblock_phys_mem_size(); + + /* Do not resize for host memory encryption. */ + if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) + return; + + /* + * For SEV and TDX and CCA, all DMA has to occur via + * shared/unencrypted pages. Kernel uses SWIOTLB to make this + * happen without changing device drivers. However, depending on + * the workload being run, the default 64MB of SWIOTLB may not be + * enough and SWIOTLB may run out of buffers for DMA, resulting in + * I/O errors and/or performance degradation especially with high + * I/O workloads. + * + * Adjust the default size of SWIOTLB using a percentage of guest + * memory for SWIOTLB buffers. Also, as the SWIOTLB bounce buffer + * memory is allocated from low memory, ensure that the adjusted + * size is within the limits of low available memory. + * + * The percentage of guest memory used here for SWIOTLB buffers is + * more of an approximation of the static adjustment which 64MB for + * <1G, and ~128M to 256M for 1G-to-4G, i.e., the 6% + */ + size =3D total_mem * 6 / 100; + size =3D clamp_val(size, IO_TLB_DEFAULT_SIZE, SZ_1G); + swiotlb_adjust_size(size); + + if (!IS_ENABLED(CONFIG_SWIOTLB_DYNAMIC)) + pr_info("Consider enabling CONFIG_SWIOTLB_DYNAMIC for memory-encrypted s= ystems\n"); +} + static bool __init swiotlb_kmalloc_needs_bounce(void) { return IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) && (dma_get_cache_alignment() > 1); } =20 +static bool __init swiotlb_default_pool_needs_cc_shared(void) +{ + /* A restricted DMA pool provides the shared buffers instead. */ + return cc_platform_has(CC_ATTR_MEM_ENCRYPT) && + !restricted_dma_pool_present; +} + static bool __init swiotlb_should_init(unsigned int flags) { if (swiotlb_force_disable) @@ -402,11 +436,12 @@ static bool __init swiotlb_should_init(unsigned int f= lags) if (swiotlb_force_bounce) return true; =20 - if (flags & SWIOTLB_INIT_CC_SHARED) + if (swiotlb_default_pool_needs_cc_shared()) return true; =20 return false; } + /* * Statically reserve bounce buffer space and initialize bounce buffer data * structures for the software IO TLB used to implement the DMA API. @@ -423,9 +458,6 @@ void __init swiotlb_init_remap(unsigned int flags, if (!swiotlb_should_init(flags)) return; =20 - if (flags & SWIOTLB_INIT_CC_SHARED) - io_tlb_default_mem.cc_shared =3D true; - io_tlb_default_mem.force_bounce =3D swiotlb_force_bounce; =20 #ifdef CONFIG_SWIOTLB_DYNAMIC @@ -437,9 +469,11 @@ void __init swiotlb_init_remap(unsigned int flags, io_tlb_default_mem.phys_limit =3D ARCH_LOW_ADDRESS_LIMIT; #endif =20 - if (!(flags & (SWIOTLB_INIT_ADDRESSING_LIMIT | - SWIOTLB_INIT_CC_SHARED)) && - swiotlb_kmalloc_needs_bounce()) { + if (swiotlb_default_pool_needs_cc_shared()) { + io_tlb_default_mem.cc_shared =3D true; + swiotlb_adjust_cc_attributes(); + } else if (!(flags & SWIOTLB_INIT_ADDRESSING_LIMIT) && + swiotlb_kmalloc_needs_bounce()) { /* * If no bouncing needed for ZONE_DMA, reduce the swiotlb * buffer for kmalloc() bouncing to 1MB per 1GB of RAM. @@ -2086,6 +2120,8 @@ static int __init rmem_swiotlb_setup(unsigned long no= de, of_get_flat_dt_prop(node, "no-map", NULL)) return -EINVAL; =20 + restricted_dma_pool_present =3D true; + pr_info("Reserved memory: created restricted DMA pool at %pa, size %ld Mi= B\n", &rmem->base, (unsigned long)rmem->size / SZ_1M); return 0; --=20 2.43.0