dma: swiotlb: Centralize default pool policy and sizing
Subsystems (14)
v6 cover dma: swiotlb: Centralize default pool policy and sizing
Hi,
This series centralizes swiotlb default-pool selection and sizing, and simplifies the initialization flags used to describe pool placement.
The first patch replaces the addressing-limit argument with initialization flags and introduces explicit policies for the different reasons a default pool may be needed. Architectures now report DMA addressing constraints with SWIOTLB_INIT_ADDRESSING_LIMIT, while the core selects the corresponding pool policy.
The second patch moves the reduced sizing used when the pool is needed only for unaligned kmalloc bouncing from arm64 and RISC-V into the swiotlb core.
The third patch centralizes swiotlb sizing for memory-encrypted systems. It moves the existing x86 guest-sizing policy into the core. Host memory encryption retains the normal pool size, and a shared default pool is not selected solely for guest memory encryption when a restricted DMA pool is present.
The fourth patch removes SWIOTLB_ANY. Pool placement is derived directly from SWIOTLB_INIT_ADDRESSING_LIMIT: pools required for limited DMA addressing are allocated below the architecture's low address limit, while other pools may be allocated anywhere in directly mapped memory. Xen continues to request a pool explicitly with SWIOTLB_INIT_REMAP without imposing a low-address constraint.
Changes from v5:
https://lore.kernel.org/all/[email protected]
* Collect Reviewed-by tags.
* Drop the x86 crash changes
* Add two new patches:
"dma: swiotlb: Consolidate slab rounding" "dma: swiotlb: Rename swiotlb_size_or_default()"
* Drop the swiotlb_default_size_changed() helper.
* Simplify swiotlb_adjust_pool_size().
Changes from v4:
https://lore.kernel.org/all/[email protected]
* Collect Reviewed-by tags.
* Add a new patch, "dma: swiotlb: Track whether the pool size was explicitly set".
* Retain SWIOTLB_ANY usage for RISC-V until patch 6.
* Rename SWIOTLB_INIT_FORCE_DISABLE to SWIOTLB_INIT_DEFAULT_OFF.
Changes from v3:
https://lore.kernel.org/all/[email protected]
* Add a new patch, "dma: swiotlb: Add an overridable architecture pool opt-out".
* Clarify the change in default behavior with the removal of SWIOTLB_ANY.
Changes from v2:
https://lore.kernel.org/all/[email protected]
* Rebase to latest tree.
* Drop SWIOTLB_ANY and derive that based on SWIOTLB_INIT_ADDRESSING_LIMIT
* Add SWIOTLB_INIT_REMAP.
v1:
https://lore.kernel.org/all/[email protected]
Aneesh Kumar K.V (Arm) (8):
dma: swiotlb: Rename swiotlb_size_or_default()
dma: swiotlb: Consolidate slab rounding
dma: swiotlb: Track whether the pool size was explicitly set
dma: swiotlb: Centralize default pool policy selection
dma: swiotlb: Centralize minimal pool sizing
dma: swiotlb: Centralize memory-encryption pool sizing
dma: swiotlb: Add an overridable architecture pool opt-out
dma: swiotlb: Remove SWIOTLB_ANY
Documentation/core-api/swiotlb.rst | 8 +- arch/arm/mm/init.c | 6 +- arch/arm/xen/mm.c | 2 +- arch/arm64/mm/init.c | 14 +- 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 | 17 ++- arch/powerpc/platforms/pseries/svm.c | 10 -- arch/powerpc/sysdev/fsl_pci.c | 1 + arch/riscv/mm/init.c | 24 +--- arch/s390/mm/init.c | 2 +- arch/x86/include/asm/crash_reserve.h | 4 +- arch/x86/kernel/pci-dma.c | 23 +++- arch/x86/mm/mem_encrypt.c | 24 ---- include/linux/swiotlb.h | 17 ++- kernel/dma/swiotlb.c | 193 +++++++++++++++++++-------- 19 files changed, 210 insertions(+), 147 deletions(-)
base-commit: 704340f1cd0dcef829eb62f5b48ae95a2ce17bdf
Signature · 1 line
2.43.0
PATCH v6 1/8 dma: swiotlb: Rename swiotlb_size_or_default()
Rename swiotlb_size_or_default() to swiotlb_default_pool_size() to make clear that it returns the current size of the default SWIOTLB pool. This includes changes made by command-line options or sizing heuristics, not just the compiled-in default.
No functional change.
--- arch/arm/xen/mm.c | 2 +- arch/arm64/mm/init.c | 2 +- arch/riscv/mm/init.c | 2 +- arch/x86/include/asm/crash_reserve.h | 4 ++-- include/linux/swiotlb.h | 2 +- kernel/dma/swiotlb.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-)
arch/arm/xen/mm.c +1 -1
@@ -125,7 +125,7 @@ static int __init xen_mm_init(void)return 0 ;/* we can work with the default swiotlb */ - rc =swiotlb_init_late (swiotlb_size_or_default (), + rc =swiotlb_init_late (swiotlb_default_pool_size (),xen_swiotlb_gfp (),NULL );if (rc <0 )return rc;
arch/arm64/mm/init.c +1 -1
@@ -348,7 +348,7 @@ void __init arch_mm_preinit(void)unsigned long size =DIV_ROUND_UP (memblock_phys_mem_size (),1024 ); -swiotlb_adjust_size (min (swiotlb_size_or_default (), size)); +swiotlb_adjust_size (min (swiotlb_default_pool_size (), size)); }swiotlb_init (true, flags);
arch/riscv/mm/init.c +1 -1
@@ -185,7 +185,7 @@ void __init arch_mm_preinit(void)*/ unsigned long size =DIV_ROUND_UP (memblock_phys_mem_size (),1024 ); -swiotlb_adjust_size (min (swiotlb_size_or_default (), size)); +swiotlb_adjust_size (min (swiotlb_default_pool_size (), size)); swiotlb = true; swiotlb_flags |=SWIOTLB_ANY ; }
arch/x86/include/asm/crash_reserve.h +2 -2
@@ -18,7 +18,7 @@* no good way to detect the paging mode of the target kernel which will be * loaded for dumping. */ -extern unsigned long swiotlb_size_or_default (void ); +extern unsigned long swiotlb_default_pool_size (void );#ifdef CONFIG_X86_32 # define CRASH_ADDR_LOW_MAX SZ_512M
@@ -33,7 +33,7 @@ extern unsigned long swiotlb_size_or_default(void);static inline unsigned long crash_low_size_default (void ) {#ifdef CONFIG_X86_64 -return max (swiotlb_size_or_default () + (8UL <<20 ),256UL <<20 ); +return max (swiotlb_default_pool_size () + (8UL <<20 ),256UL <<20 );#else return 0 ;#endif
include/linux/swiotlb.h +1 -1
@@ -38,7 +38,7 @@ struct scatterlist;#define IO_TLB_DEFAULT_SIZE (64UL << 20)#endif -unsigned long swiotlb_size_or_default (void ); +unsigned long swiotlb_default_pool_size (void );void __init swiotlb_init_remap (bool addressing_limit,unsigned int flags,int (*remap)(void *tlb,unsigned long nslabs)); int swiotlb_init_late(size_t size, gfp_t gfp_mask,
kernel/dma/swiotlb.c +1 -1
@@ -285,7 +285,7 @@ setup_io_tlb_npages(char *str) }early_param ("swiotlb" , setup_io_tlb_npages); -unsigned long swiotlb_size_or_default (void ) +unsigned long swiotlb_default_pool_size (void ) {return default_nslabs <<IO_TLB_SHIFT ; }
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH v6 1/8] dma: swiotlb: Rename swiotlb_size_or_default()
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Low] docs: missed function rename to swiotlb_default_pool_size() --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] docs: missed function rename to swiotlb_default_pool_size()
--
commit 88c990f98bc8ebb1b961e1f014a4e9bab02d6131
Author: Aneesh Kumar K.V (Arm) <[email protected]>
dma: swiotlb: Rename swiotlb_size_or_default()
This commit renames swiotlb_size_or_default() to swiotlb_default_pool_size() to clarify that it returns the current size of the default pool. This includes sizes resulting from command-line modifications or heuristics, not just the compiled-in default.
Quoted 4 lines
arch/x86/include/asm/crash_reserve.h +0
-0
[ ... ]
arch/x86/include/asm/crash_reserve.h extern unsigned long swiotlb_size_or_default(void); · line 36
Quoted 6 lines
arch/x86/include/asm/crash_reserve.h +1
-1@@ -33,7 +33,7 @@ extern unsigned long swiotlb_size_or_default(void);static inline unsigned long crash_low_size_default (void ) {#ifdef CONFIG_X86_64 -return max (swiotlb_size_or_default () + (8UL <<20 ),256UL <<20 ); +return max (swiotlb_default_pool_size () + (8UL <<20 ),256UL <<20 );
[Severity: Low]
Since the function swiotlb_size_or_default() is renamed to swiotlb_default_pool_size() here in crash_low_size_default(), does the corresponding documentation in Documentation/admin-guide/kernel-parameters.txt also need to be updated?
The documentation string currently still uses the old function name to explain the crashkernel reservation formula on x86:
Documentation/admin-guide/kernel-parameters.txt:
--> x86: max(swiotlb_size_or_default() + 8MiB, 256MiB)
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
PATCH v6 2/8 dma: swiotlb: Consolidate slab rounding
In reply to Aneesh Kumar K.V (Arm)Pass the area count explicitly to swiotlb_calc_nslabs() and keep the calculation separate from updates to the default_nslabs . Move the default_nslabs update into swiotlb_adjust_nareas().
Round slabs to a power of two even before the area count is initialized. For early swiotlb_adjust_size() calls, this moves rounding from area initialization to size adjustment, so early queries see the rounded size.
--- kernel/dma/swiotlb.c | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-)
kernel/dma/swiotlb.c +20 -24
@@ -117,27 +117,20 @@ struct io_tlb_area {spinlock_t lock; }; -/* -* Round up number of slabs to the next power of 2. The last area is going -* be smaller than the rest if default_nslabs is not power of two. -* The number of slot in an area should be a multiple of IO_TLB_SEGSIZE, -* otherwise a segment may span two or more areas. It conflicts with free -* contiguous slots tracking: free slots are treated contiguous no matter -* whether they cross an area boundary. -* -* Return true if default_nslabs is rounded up. -*/ -static bool round_up_default_nslabs (void ) +/* Return a power-of-two number of slabs that can be split between areas. */ +static unsigned long swiotlb_calc_nslabs (unsigned long size, +unsigned long nareas) { -if (!default_nareas) -return false; +unsigned long nslabs; -if (default_nslabs <IO_TLB_SEGSIZE * default_nareas) - default_nslabs =IO_TLB_SEGSIZE * default_nareas; -else if (is_power_of_2 (default_nslabs)) -return false; - default_nslabs =roundup_pow_of_two (default_nslabs); -return true; + nslabs =ALIGN (DIV_ROUND_UP (size,IO_TLB_SIZE ),IO_TLB_SEGSIZE ); +if (nareas && nslabs <IO_TLB_SEGSIZE * nareas) + nslabs =IO_TLB_SEGSIZE * nareas; + +if (!is_power_of_2 (nslabs)) + nslabs =roundup_pow_of_two (nslabs); + +return nslabs; }/**
@@ -150,6 +143,8 @@ static bool round_up_default_nslabs(void)*/ static void swiotlb_adjust_nareas (unsigned int nareas) { +unsigned long nslabs; +if (!nareas) nareas =1 ;else if (!is_power_of_2 (nareas))
@@ -158,9 +153,12 @@ static void swiotlb_adjust_nareas(unsigned int nareas) default_nareas = nareas;pr_info ("area num %d.\n" , nareas); -if (round_up_default_nslabs ()) + nslabs =swiotlb_calc_nslabs (default_nslabs <<IO_TLB_SHIFT , nareas); +if (nslabs != default_nslabs) { + default_nslabs = nslabs;pr_info ("SWIOTLB bounce buffer size roundup to %luMB" , (default_nslabs <<IO_TLB_SHIFT ) >>20 ); + } }/**
@@ -300,10 +298,8 @@ void __init swiotlb_adjust_size(unsigned long size)if (default_nslabs !=IO_TLB_DEFAULT_SIZE >>IO_TLB_SHIFT )return ; - size =ALIGN (size,IO_TLB_SIZE ); - default_nslabs =ALIGN (size >>IO_TLB_SHIFT ,IO_TLB_SEGSIZE ); -if (round_up_default_nslabs ()) - size = default_nslabs <<IO_TLB_SHIFT ; + default_nslabs =swiotlb_calc_nslabs (size, default_nareas); + size = default_nslabs <<IO_TLB_SHIFT ;pr_info ("SWIOTLB bounce buffer size adjusted to %luMB" , size >>20 ); }
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH v6 2/8] dma: swiotlb: Consolidate slab rounding
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 4 lines
Pass the area count explicitly to
swiotlb_calc_nslabs()and keep the calculation separate from updates to thedefault_nslabs. Move thedefault_nslabsupdate intoswiotlb_adjust_nareas().
Quoted 8 lines
Round slabs to a power of two even before the area count is initialized. For early
swiotlb_adjust_size()calls, this moves rounding from area initialization to size adjustment, so early queries see the rounded size.Cc Marek Szyprowski <[email protected]>Cc Robin Murphy <[email protected]>Signed-off-by Aneesh Kumar K.V (Arm) <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
PATCH v6 3/8 dma: swiotlb: Track whether the pool size was explicitly set
In reply to Aneesh Kumar K.V (Arm)swiotlb_adjust_size() must not override a pool size supplied through the swiotlb= command-line parameter.
Currently, it determines whether a size was supplied by comparing default_nslabs with IO_TLB_DEFAULT_SIZE. This fails when the user explicitly requests the compiled-in default size, allowing the request to be overwritten by automatic pool sizing.
Record whether swiotlb= supplied a numeric size in swiotlb_cmdline_size_set and check that flag directly before adjusting the pool size.
--- kernel/dma/swiotlb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
kernel/dma/swiotlb.c +3 -1
@@ -100,6 +100,7 @@ static struct io_tlb_mem io_tlb_default_mem;static unsigned long default_nslabs =IO_TLB_DEFAULT_SIZE >>IO_TLB_SHIFT ;static unsigned long default_nareas; +static bool swiotlb_cmdline_size_set__initdata ;/** * struct io_tlb_area - IO TLB memory area descriptor
@@ -253,6 +254,7 @@ setup_io_tlb_npages(char *str)/* avoid tail segment of size < IO_TLB_SEGSIZE */ default_nslabs =ALIGN (simple_strtoul (str, &str,0 ),IO_TLB_SEGSIZE ); + swiotlb_cmdline_size_set = true; }if (*str ==',' ) ++str;
@@ -295,7 +297,7 @@ void __init swiotlb_adjust_size(unsigned long size)* architectures such as those supporting memory encryption to * adjust/expand SWIOTLB size for their use. */ -if (default_nslabs !=IO_TLB_DEFAULT_SIZE >>IO_TLB_SHIFT ) +if (swiotlb_cmdline_size_set)return ; default_nslabs =swiotlb_calc_nslabs (size, default_nareas);
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH v6 3/8] dma: swiotlb: Track whether the pool size was explicitly set
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 8 lines
swiotlb_adjust_size()must not override a pool size supplied through the swiotlb= command-line parameter.Currently, it determines whether a size was supplied by comparing
default_nslabswithIO_TLB_DEFAULT_SIZE. This fails when the user explicitly requests the compiled-in default size, allowing the request to be overwritten by automatic pool sizing.
Quoted 8 lines
Record whether swiotlb= supplied a numeric size in
swiotlb_cmdline_size_setand check that flag directly before adjusting the pool size.Reviewed-by Catalin Marinas <[email protected]>Reviewed-by Robin Murphy <[email protected]>Cc Marek Szyprowski <[email protected]>Cc Robin Murphy <[email protected]>Signed-off-by Aneesh Kumar K.V (Arm) <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=3
PATCH v6 4/8 dma: swiotlb: Centralize default pool policy selection
In reply to Aneesh Kumar K.V (Arm)The addressing_limited argument to swiotlb_init() describes only one reason for allocating a default SWIOTLB pool. A pool may also be needed for memory encryption, unaligned kmalloc bouncing, or swiotlb=force.
Replace the boolean argument with the SWIOTLB_INIT_ADDRESSING_LIMIT flag and have architectures report their DMA addressing constraints through the initialization flags.
Introduce SWIOTLB pool policies and select the policy in the core before allocating the default pool. This separates the decision to allocate a pool from the policy used to size it, allowing subsequent changes to centralize minimal and confidential-guest sizing.
Set the shared-pool state before memory attributes are updated. Also move the pseries secure-guest setup before swiotlb_init() so its initialization flags are available when the policy is selected.
--- arch/arm/mm/init.c | 6 +- arch/arm64/mm/init.c | 5 +- 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 | 6 +- arch/s390/mm/init.c | 2 +- arch/x86/kernel/pci-dma.c | 16 +++-- include/linux/swiotlb.h | 12 ++-- kernel/dma/swiotlb.c | 90 ++++++++++++++++++++++------ 15 files changed, 128 insertions(+), 47 deletions(-)
arch/arm/mm/init.c +5 -1
@@ -223,7 +223,11 @@ static inline void poison_init_mem(void *s, size_t count)void __init arch_mm_preinit (void ) {#ifdef CONFIG_ARM_LPAE -swiotlb_init (max_pfn > arm_dma_pfn_limit,SWIOTLB_VERBOSE ); +unsigned int flags =SWIOTLB_VERBOSE ; + +if (max_pfn > arm_dma_pfn_limit) + flags |=SWIOTLB_INIT_ADDRESSING_LIMIT ; +swiotlb_init (flags);#endif #ifdef CONFIG_SA1111
arch/arm64/mm/init.c +4 -1
@@ -351,7 +351,10 @@ void __init arch_mm_preinit(void)swiotlb_adjust_size (min (swiotlb_default_pool_size (), size)); } -swiotlb_init (true, flags); +if (max_pfn >PFN_DOWN (arm64_dma_phys_limit)) + flags |=SWIOTLB_INIT_ADDRESSING_LIMIT ; + +swiotlb_init (flags);/* * Check boundaries twice: Some fundamental inconsistencies can be
arch/loongarch/kernel/setup.c +1 -1
@@ -404,7 +404,7 @@ static void __init arch_mem_init(char **cmdline_p)memblock_set_bottom_up (true); -swiotlb_init (true,SWIOTLB_VERBOSE ); +swiotlb_init (SWIOTLB_VERBOSE |SWIOTLB_INIT_ADDRESSING_LIMIT );dma_contiguous_reserve (PFN_PHYS (max_low_pfn));
arch/mips/cavium-octeon/dma-octeon.c +1 -1
@@ -235,5 +235,5 @@ void __init plat_swiotlb_setup(void)#endif swiotlb_adjust_size (swiotlbsize); -swiotlb_init (true,SWIOTLB_VERBOSE ); +swiotlb_init (SWIOTLB_VERBOSE |SWIOTLB_INIT_ADDRESSING_LIMIT ); }
arch/mips/loongson64/dma.c +1 -1
@@ -25,5 +25,5 @@ phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)void __init plat_swiotlb_setup (void ) { -swiotlb_init (true,SWIOTLB_VERBOSE ); +swiotlb_init (SWIOTLB_VERBOSE |SWIOTLB_INIT_ADDRESSING_LIMIT ); }
arch/mips/sibyte/common/dma.c +1 -1
@@ -10,5 +10,5 @@void __init plat_swiotlb_setup (void ) { -swiotlb_init (true,SWIOTLB_VERBOSE ); +swiotlb_init (SWIOTLB_VERBOSE |SWIOTLB_INIT_ADDRESSING_LIMIT ); }
arch/powerpc/kernel/dma-swiotlb.c +3 -1
@@ -14,8 +14,10 @@ unsigned int ppc_swiotlb_flags;void __init swiotlb_detect_4g (void ) { -if ((memblock_end_of_DRAM () -1 ) >0xffffffff ) +if ((memblock_end_of_DRAM () -1 ) >0xffffffff ) { ppc_swiotlb_enable =1 ; + ppc_swiotlb_flags |=SWIOTLB_INIT_ADDRESSING_LIMIT ; + } }static int __init check_swiotlb_enabled (void )
arch/powerpc/mm/mem.c +14 -1
@@ -287,6 +287,19 @@ void __init arch_mm_preinit(void)BUILD_BUG_ON (MMU_PAGE_COUNT >16 );#ifdef CONFIG_SWIOTLB +if (is_secure_guest ()) { + +/* Don't release the SWIOTLB buffer. */ + ppc_swiotlb_enable =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 |=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 kasan_late_init ();
arch/powerpc/platforms/pseries/svm.c +0 -10
@@ -21,16 +21,6 @@ static int __init init_svm(void)if (!is_secure_guest ())return 0 ; -/* Don't release the SWIOTLB buffer. */ - ppc_swiotlb_enable =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 |=SWIOTLB_ANY ; -/* Share the SWIOTLB buffer with the host. */ swiotlb_update_mem_attributes ();
arch/powerpc/sysdev/fsl_pci.c +1 -0
@@ -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 =1 ; + ppc_swiotlb_flags |=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",
arch/riscv/mm/init.c +5 -1
@@ -190,7 +190,11 @@ void __init arch_mm_preinit(void) swiotlb_flags |=SWIOTLB_ANY ; } -swiotlb_init (swiotlb, swiotlb_flags); +if ((max_pfn >PFN_DOWN (dma32_phys_limit)) && + (memblock_start_of_DRAM () < dma32_phys_limit)) + swiotlb_flags |=SWIOTLB_INIT_ADDRESSING_LIMIT ; + +swiotlb_init (swiotlb_flags);print_vm_layout (); }
arch/s390/mm/init.c +1 -1
@@ -166,7 +166,7 @@ static void __init pv_init(void)virtio_set_mem_acc_cb (virtio_require_restricted_mem_acc);/* make sure bounce buffers are shared */ -swiotlb_init (true,SWIOTLB_VERBOSE |SWIOTLB_ANY ); +swiotlb_init (SWIOTLB_VERBOSE |SWIOTLB_ANY );swiotlb_update_mem_attributes (); }
arch/x86/kernel/pci-dma.c +11 -5
@@ -44,8 +44,10 @@ static unsigned int x86_swiotlb_flags;static void __init pci_swiotlb_detect (void ) {/* don't initialize swiotlb if iommu=off (no_iommu=1) */ -if (!no_iommu && max_possible_pfn >MAX_DMA32_PFN ) +if (!no_iommu && max_possible_pfn >MAX_DMA32_PFN ) { x86_swiotlb_enable = true; + x86_swiotlb_flags |=SWIOTLB_INIT_ADDRESSING_LIMIT ; + }/* * Set swiotlb to 1 so that bounce buffers are allocated and used for
@@ -81,8 +83,10 @@ static void __init pci_xen_swiotlb_init(void)if (!xen_swiotlb_enabled ())return ; x86_swiotlb_enable = true; - x86_swiotlb_flags |=SWIOTLB_ANY ; -swiotlb_init_remap (true, x86_swiotlb_flags, xen_swiotlb_fixup); +/* Xen can use a SWIOTLB pool anywhere in directly mapped memory. */ + x86_swiotlb_flags &= ~SWIOTLB_INIT_ADDRESSING_LIMIT ; + x86_swiotlb_flags |=SWIOTLB_INIT_REMAP |SWIOTLB_ANY ; +swiotlb_init_remap (x86_swiotlb_flags, xen_swiotlb_fixup); dma_ops = &xen_swiotlb_dma_ops;if (IS_ENABLED (CONFIG_PCI ))pci_request_acs ();
@@ -103,7 +107,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); }static __init int iommu_setup (char *p)
@@ -149,8 +153,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 = true; + x86_swiotlb_flags |=SWIOTLB_INIT_ADDRESSING_LIMIT ; + }#endif if (!strncmp (p,"pt" ,2 ))iommu_set_default_passthrough (true);
include/linux/swiotlb.h +8 -4
@@ -16,6 +16,10 @@ struct scatterlist;#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 default-sized pool that requires architecture remapping. */ +#define SWIOTLB_INIT_REMAP (1 << 3)/* * Maximum allowable number of contiguous slabs to map,
@@ -39,8 +43,8 @@ struct scatterlist;#endif unsigned long swiotlb_default_pool_size (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 device *dev)return mem && mem->force_bounce; } -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 flags) +static inline void swiotlb_init (unsigned int flags) { }
kernel/dma/swiotlb.c +72 -18
139 lines not on this page · raw message
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH v6 4/8] dma: swiotlb: Centralize default pool policy selection
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 13 lines
The
addressing_limitedargument toswiotlb_init()describes only one reason for allocating a default SWIOTLB pool. A pool may also be needed for memory encryption, unaligned kmalloc bouncing, or swiotlb=force.Replace the boolean argument with the
SWIOTLB_INIT_ADDRESSING_LIMITflag and have architectures report their DMA addressing constraints through the initialization flags.Introduce SWIOTLB pool policies and select the policy in the core before allocating the default pool. This separates the decision to allocate a pool from the policy used to size it, allowing subsequent changes to centralize minimal and confidential-guest sizing.
Quoted 8 lines
Set the shared-pool state before memory attributes are updated. Also move the pseries secure-guest setup before
swiotlb_init()so its initialization[ ... ]Cc "H. Peter Anvin" <[email protected]>Cc Marek Szyprowski <[email protected]>Cc Robin Murphy <[email protected]>Signed-off-by Aneesh Kumar K.V (Arm) <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=4
PATCH v6 5/8 dma: swiotlb: Centralize minimal pool sizing
In reply to Aneesh Kumar K.V (Arm)A default SWIOTLB pool used only for unaligned kmalloc bouncing can be smaller than one required for limited DMA addressing. Arm64 and RISC-V currently implement this sizing independently, using 1 MiB of SWIOTLB space per GiB of RAM.
The SWIOTLB core now identifies this case with SWIOTLB_POOL_MINIMAL. Size that policy in swiotlb_adjust_pool_size() and remove the architecture-specific adjustments.
Explicit swiotlb= sizing remains unchanged because swiotlb_adjust_size() preserves a user-configured size.
--- arch/arm64/mm/init.c | 11 ----------- arch/riscv/mm/init.c | 4 ---- kernel/dma/swiotlb.c | 9 ++++++++- 3 files changed, 8 insertions(+), 16 deletions(-)
arch/arm64/mm/init.c +0 -11
@@ -340,17 +340,6 @@ void __init arch_mm_preinit(void) {unsigned int flags =SWIOTLB_VERBOSE ; -if (max_pfn <=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 = -DIV_ROUND_UP (memblock_phys_mem_size (),1024 ); - -swiotlb_adjust_size (min (swiotlb_default_pool_size (), size)); - } -if (max_pfn >PFN_DOWN (arm64_dma_phys_limit)) flags |=SWIOTLB_INIT_ADDRESSING_LIMIT ;
arch/riscv/mm/init.c +0 -4
@@ -183,10 +183,6 @@ void __init arch_mm_preinit(void)* memory when DRAM starts above dma32_phys_limit. Allocate * ~1 MB per 1 GB of RAM. */ -unsigned long size = -DIV_ROUND_UP (memblock_phys_mem_size (),1024 ); -swiotlb_adjust_size (min (swiotlb_default_pool_size (), size)); - swiotlb = true; swiotlb_flags |=SWIOTLB_ANY ; }
kernel/dma/swiotlb.c +8 -1
@@ -469,9 +469,14 @@ static bool __init swiotlb_kmalloc_needs_bounce(void)static void __init swiotlb_adjust_pool_size (enum swiotlb_pool_policy policy) { +unsigned long size; +switch (policy) {case SWIOTLB_POOL_MINIMAL : -return ; +/* Use 1MB per 1GB of RAM for kmalloc() bouncing. */ + size =DIV_ROUND_UP (memblock_phys_mem_size (),1024 ); + size =min (swiotlb_default_pool_size (), size); +break ;case SWIOTLB_POOL_CC_GUEST :return ;case SWIOTLB_POOL_NONE :
@@ -481,6 +486,8 @@ swiotlb_adjust_pool_size(enum swiotlb_pool_policy policy)default :return ; } + +swiotlb_adjust_size (size); } static enum swiotlb_pool_policy __init
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH v6 5/8] dma: swiotlb: Centralize minimal pool sizing
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 12 lines
A default SWIOTLB pool used only for unaligned kmalloc bouncing can be smaller than one required for limited DMA addressing. Arm64 and RISC-V currently implement this sizing independently, using 1 MiB of SWIOTLB space per GiB of RAM.
The SWIOTLB core now identifies this case with
SWIOTLB_POOL_MINIMAL. Size that policy inswiotlb_adjust_pool_size()and remove the architecture-specific adjustments.Explicit swiotlb= sizing remains unchanged because
swiotlb_adjust_size()preserves a user-configured size.
Quoted 11 lines
Reviewed-by Catalin Marinas <[email protected]>Cc Catalin Marinas <[email protected]>Cc Will Deacon <[email protected]>Cc Mark Rutland <[email protected]>Cc Paul Walmsley <[email protected]>Cc Palmer Dabbelt <[email protected]>Cc Albert Ou <[email protected]>Cc Alexandre Ghiti <[email protected]>Cc Marek Szyprowski <[email protected]>Cc Robin Murphy <[email protected]>Signed-off-by Aneesh Kumar K.V (Arm) <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5
PATCH v6 6/8 dma: swiotlb: Centralize memory-encryption pool sizing
In reply to Aneesh Kumar K.V (Arm)Memory-encrypted guests use shared or unencrypted memory for DMA and may route all DMA through SWIOTLB. The default pool can therefore be too small for I/O-intensive workloads.
Move the existing x86 guest-sizing policy into the SWIOTLB core. For SWIOTLB_POOL_CC_GUEST, size the pool to 6% of guest memory, clamped between the normal default and 1 GiB. Preserve an explicit swiotlb= size.
Host memory encryption still selects a normal-sized shared pool and does not use the guest-sizing policy.
A restricted DMA pool already provides shared bounce buffers for its devices. Record its presence during reserved-memory initialization and do not select the confidential-guest default-pool policy solely because guest memory encryption is active.
--- arch/x86/mm/mem_encrypt.c | 24 ------------------------ kernel/dma/swiotlb.c | 27 +++++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 26 deletions(-)
arch/x86/mm/mem_encrypt.c +0 -24
@@ -101,9 +101,6 @@ void __init mem_encrypt_init(void)void __init mem_encrypt_setup_arch (void ) { -phys_addr_t total_mem =memblock_phys_mem_size (); -unsigned long size; -/* * Do RMP table fixups after the e820 tables have been setup by * e820__memory_setup().
@@ -114,27 +111,6 @@ void __init mem_encrypt_setup_arch(void)if (!cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT ))return ; -/* -* 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 = total_mem *6 /100 ; - size =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); }
kernel/dma/swiotlb.c +25 -2
@@ -33,6 +33,7 @@#include <linux/kmsan-checks.h> #include <linux/iommu-helper.h> #include <linux/init.h> +#include <linux/math64.h> #include <linux/memblock.h> #include <linux/mm.h> #include <linux/pfn.h>
@@ -80,6 +81,7 @@ struct io_tlb_slot {static bool swiotlb_force_bounce;static bool swiotlb_force_disable; +static bool restricted_dma_pool_present__initdata ;enum swiotlb_pool_policy {SWIOTLB_POOL_NONE ,
@@ -478,7 +480,25 @@ swiotlb_adjust_pool_size(enum swiotlb_pool_policy policy) size =min (swiotlb_default_pool_size (), size);break ;case SWIOTLB_POOL_CC_GUEST : -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. +* +* 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 =div_u64 ((u64 )memblock_phys_mem_size () *6 ,100 ); + size =clamp_val (size,IO_TLB_DEFAULT_SIZE ,SZ_1G ); +break ;case SWIOTLB_POOL_NONE :WARN (true,"Cannot adjust SWIOTLB size without a pool\n" );return ;
@@ -496,7 +516,8 @@ swiotlb_select_pool_policy(unsigned int flags)if (swiotlb_force_disable)return SWIOTLB_POOL_NONE ; -if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT )) +if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT ) && + !restricted_dma_pool_present)return SWIOTLB_POOL_CC_GUEST ;if (cc_platform_has (CC_ATTR_HOST_MEM_ENCRYPT ))
@@ -2142,6 +2163,8 @@ static int __init rmem_swiotlb_setup(unsigned long node, of_get_flat_dt_prop(node, "no-map", NULL))return -EINVAL ; + restricted_dma_pool_present = true; +pr_info ("Reserved memory: created restricted DMA pool at %pa, size %ld MiB\n" , &rmem->base, (unsigned long )rmem->size /SZ_1M );return 0 ;
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH v6 6/8] dma: swiotlb: Centralize memory-encryption pool sizing
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [High] dma: swiotlb: missing fallback disables default pool on CC guests with restricted DMA - [High]…
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] dma: swiotlb: missing fallback disables default pool on CC guests with restricted DMA
- [High] x86: crash_reserve: low memory reservation undersized for CC guests
--
commit b7ccaf6e292795b26ab1ca8eb765bb8952de98b5
Author: Aneesh Kumar K.V (Arm) <[email protected]>
dma: swiotlb: Centralize memory-encryption pool sizing
Memory-encrypted guests use shared or unencrypted memory for DMA and may route all DMA through SWIOTLB. The default pool can therefore be too small for I/O-intensive workloads.
Quoted 4 lines
arch/x86/mm/mem_encrypt.c +0
-0
[ ... ]
Quoted 15 lines
arch/x86/mm/mem_encrypt.c +0
-11@@ -114,27 +111,6 @@ void __init mem_encrypt_setup_arch(void)if (!cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT ))return ; -/* -* 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
arch/x86/mm/mem_encrypt.c void __init mem_encrypt_setup_arch(void) · line 137
Quoted 10 lines
arch/x86/mm/mem_encrypt.c +0
-10-* 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 = total_mem *6 /100 ; - size =clamp_val (size,IO_TLB_DEFAULT_SIZE ,SZ_1G ); -swiotlb_adjust_size (size); -
[Severity: High]
Does moving this SWIOTLB adjustment run too late for crashkernel reservation?
When this was called during mem_encrypt_setup_arch(), the SWIOTLB size was adjusted before arch_reserve_crashkernel() called crash_low_size_default().
Now the dynamic guest sizing is evaluated later, so crash_low_size_default() only sees the unadjusted 64MB default.
If the crash kernel is provided with a large amount of memory (e.g., crashkernel=4G,high), its own dynamically calculated SWIOTLB size could exhaust the 256MB of low memory reserved by the main kernel.
Could this lead to out-of-memory errors in the low memory zone and break kdump functionality on x86 memory-encrypted guests?
Quoted 7 lines
arch/x86/mm/mem_encrypt.c +0
-0/* Set restricted memory access for virtio. */ virtio_set_mem_acc_cb (virtio_require_restricted_mem_acc); }kernel/dma/swiotlb.c +0
-0
[ ... ]
kernel/dma/swiotlb.c swiotlb_select_pool_policy(unsigned int flags) · line 523
Quoted 10 lines
kernel/dma/swiotlb.c +2
-1@@ -496,7 +516,8 @@ swiotlb_select_pool_policy(unsigned int flags)if (swiotlb_force_disable)return SWIOTLB_POOL_NONE ; -if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT )) +if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT ) && + !restricted_dma_pool_present)return SWIOTLB_POOL_CC_GUEST ;if (cc_platform_has (CC_ATTR_HOST_MEM_ENCRYPT ))
[Severity: High]
Does this disable the default SWIOTLB pool entirely for confidential guests with a restricted DMA pool?
If restricted_dma_pool_present is true on a confidential guest, this condition fails.
If no other conditions match later in swiotlb_select_pool_policy() (for instance, if there are no addressing limits because guest RAM is small, such as on arm64 CCA), the function falls through and returns SWIOTLB_POOL_NONE.
Could this result in devices not explicitly assigned to the restricted DMA pool failing to map memory, leading to device malfunction or a system panic?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=6
Will Deacon
maintainerRe: [PATCH v6 6/8] dma: swiotlb: Centralize memory-encryption pool sizing
In reply to Aneesh Kumar K.V (Arm)Quoted 124 lines · Aneesh Kumar K.V (Arm)
Memory-encrypted guests use shared or unencrypted memory for DMA and may route all DMA through SWIOTLB. The default pool can therefore be too small for I/O-intensive workloads.
Move the existing x86 guest-sizing policy into the SWIOTLB core. For
SWIOTLB_POOL_CC_GUEST, size the pool to 6% of guest memory, clamped between the normal default and 1 GiB. Preserve an explicit swiotlb= size.Host memory encryption still selects a normal-sized shared pool and does not use the guest-sizing policy.
A restricted DMA pool already provides shared bounce buffers for its devices. Record its presence during reserved-memory initialization and do not select the confidential-guest default-pool policy solely because guest memory encryption is active.
Reviewed-by Catalin Marinas <[email protected]>Cc Dave Hansen <[email protected]>Cc Andy Lutomirski <[email protected]>Cc Peter Zijlstra <[email protected]>Cc Thomas Gleixner <[email protected]>Cc Ingo Molnar <[email protected]>Cc Borislav Petkov <[email protected]>Cc "H. Peter Anvin" <[email protected]>Cc Marek Szyprowski <[email protected]>Cc Robin Murphy <[email protected]>Signed-off-by Aneesh Kumar K.V (Arm) <[email protected]>--- arch/x86/mm/mem_encrypt.c | 24 ------------------------ kernel/dma/swiotlb.c | 27 +++++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 26 deletions(-)arch/x86/mm/mem_encrypt.c +0
-24@@ -101,9 +101,6 @@ void __init mem_encrypt_init(void)void __init mem_encrypt_setup_arch (void ) { -phys_addr_t total_mem =memblock_phys_mem_size (); -unsigned long size; -/* * Do RMP table fixups after the e820 tables have been setup by * e820__memory_setup(). @@ -114,27 +111,6 @@ void __init mem_encrypt_setup_arch(void)if (!cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT ))return ; -/* -* 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 = total_mem *6 /100 ; - size =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); }kernel/dma/swiotlb.c +21
-1@@ -33,6 +33,7 @@#include <linux/kmsan-checks.h> #include <linux/iommu-helper.h> #include <linux/init.h> +#include <linux/math64.h> #include <linux/memblock.h> #include <linux/mm.h> #include <linux/pfn.h> @@ -80,6 +81,7 @@ struct io_tlb_slot {static bool swiotlb_force_bounce;static bool swiotlb_force_disable; +static bool restricted_dma_pool_present__initdata ;enum swiotlb_pool_policy {SWIOTLB_POOL_NONE ,@@ -478,7 +480,25 @@ swiotlb_adjust_pool_size(enum swiotlb_pool_policy policy) size =min (swiotlb_default_pool_size (), size);break ;case SWIOTLB_POOL_CC_GUEST : -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. +* +* 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 =div_u64 ((u64 )memblock_phys_mem_size () *6 ,100 ); + size =clamp_val (size,IO_TLB_DEFAULT_SIZE ,SZ_1G ); +break ;case SWIOTLB_POOL_NONE :WARN (true,"Cannot adjust SWIOTLB size without a pool\n" );return ;
kernel/dma/swiotlb.c swiotlb_select_pool_policy(unsigned int flags) · line 521
Quoted 7 lines
kernel/dma/swiotlb.c +2
-1@@ -496,7 +516,8 @@ swiotlb_select_pool_policy(unsigned int flags)if (swiotlb_force_disable)return SWIOTLB_POOL_NONE ; -if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT )) +if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT ) && + !restricted_dma_pool_present)return SWIOTLB_POOL_CC_GUEST ;
I think this check on the restricted DMA pool is too general -- the pool could be tied to a specific DMA-capable peripheral and so treating its presence as a global property isn't right.
Will
Catalin Marinas
maintainerRe: [PATCH v6 6/8] dma: swiotlb: Centralize memory-encryption pool sizing
Quoted 5 lines · Will Deacon
Quoted 4 lines · Aneesh Kumar K.V (Arm)
kernel/dma/swiotlb.c +0
-0@@ -496,7 +516,8 @@ swiotlb_select_pool_policy(unsigned int flags)if (swiotlb_force_disable)return SWIOTLB_POOL_NONE ;
Quoted 8 lines
kernel/dma/swiotlb.c swiotlb_select_pool_policy(unsigned int flags) · line 521
Quoted 4 lines
kernel/dma/swiotlb.c +2
-1-if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT )) +if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT ) && + !restricted_dma_pool_present)return SWIOTLB_POOL_CC_GUEST ;I think this check on the restricted DMA pool is too general -- the pool could be tied to a specific DMA-capable peripheral and so treating its presence as a global property isn't right.
I agree it's a hack but that was the simplest way to avoid the pVMs getting a bounce buffer after this patch. More than happy to leave it out and reduce the buffer on cmdline or we come up with some better heuristics.
Another option could be the arch code passing another flag that it doesn't want an encrypted pool (e.g. when running in a pKVM guest) but I don't particularly this either. The arch code doesn't know whether there's an alternative pool.
That said, such heuristics should have been a separate patch to make it easier to review/drop.
Signature · 1 line
Catalin
Will Deacon
maintainerRe: [PATCH v6 6/8] dma: swiotlb: Centralize memory-encryption pool sizing
Quoted 15 lines · Catalin Marinas
Quoted 5 lines · Will Deacon
Quoted 4 lines · Aneesh Kumar K.V (Arm)
kernel/dma/swiotlb.c +0
-0@@ -496,7 +516,8 @@ swiotlb_select_pool_policy(unsigned int flags)if (swiotlb_force_disable)return SWIOTLB_POOL_NONE ;Quoted 8 lines
kernel/dma/swiotlb.c swiotlb_select_pool_policy(unsigned int flags) · line 521
Quoted 4 lines
kernel/dma/swiotlb.c +2
-1-if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT )) +if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT ) && + !restricted_dma_pool_present)return SWIOTLB_POOL_CC_GUEST ;I think this check on the restricted DMA pool is too general -- the pool could be tied to a specific DMA-capable peripheral and so treating its presence as a global property isn't right.
Quoted 4 lines
I agree it's a hack but that was the simplest way to avoid the pVMs getting a bounce buffer after this patch. More than happy to leave it out and reduce the buffer on cmdline or we come up with some better heuristics.
Hrm, that does mean that reverting just this part will regress pVMs because they'll suddenly be allocating a tonne more memory for an entirely unused swiotlb buffer. So I think I'd prefer to drop the entire series until this has been worked out properly.
Quoted 4 lines
Another option could be the arch code passing another flag that it doesn't want an encrypted pool (e.g. when running in a pKVM guest) but I don't particularly this either. The arch code doesn't know whether there's an alternative pool.
At that point, the default size may as well be driven by the drivers/virt/coco driver.
Quoted 2 lines
That said, such heuristics should have been a separate patch to make it easier to review/drop.
I think the only right way to get a semi-accurate heuristic is to take into account the set of dma-capable devices that will use the swiotlb pool, but that's fiddly and should probably be tackled as a separate series. Maybe a simpler hack in that direction would be to take the SWIOTLB_POOL_CC_GUEST if _any_ device is going to use swiotlb? You'll run into the usual problem of not being able to tell if a device is DMA-capable or not, but you could probably look for a global restricted DMA pool and, if that doesn't exist, check for per-device restricted pools on dma-coherent devices (since restricted DMA isn't supported by ACPI) as a reasonable approximation.
Will
Catalin Marinas
maintainerRe: [PATCH v6 6/8] dma: swiotlb: Centralize memory-encryption pool sizing
Quoted 15 lines · Will Deacon
Quoted 14 lines · Catalin Marinas
Quoted 13 lines · Will Deacon
kernel/dma/swiotlb.c swiotlb_select_pool_policy(unsigned int flags) · line 521
Quoted 8 lines · Aneesh Kumar K.V (Arm)
kernel/dma/swiotlb.c +2
-1@@ -496,7 +516,8 @@ swiotlb_select_pool_policy(unsigned int flags)if (swiotlb_force_disable)return SWIOTLB_POOL_NONE ; -if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT )) +if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT ) && + !restricted_dma_pool_present)return SWIOTLB_POOL_CC_GUEST ;I think this check on the restricted DMA pool is too general -- the pool could be tied to a specific DMA-capable peripheral and so treating its presence as a global property isn't right.
[...]
Quoted 13 lines
Quoted 2 lines
That said, such heuristics should have been a separate patch to make it easier to review/drop.
I think the only right way to get a semi-accurate heuristic is to take into account the set of dma-capable devices that will use the swiotlb pool, but that's fiddly and should probably be tackled as a separate series. Maybe a simpler hack in that direction would be to take the
SWIOTLB_POOL_CC_GUESTif _any_ device is going to use swiotlb? You'll run into the usual problem of not being able to tell if a device is DMA-capable or not, but you could probably look for a global restricted DMA pool and, if that doesn't exist, check for per-device restricted pools on dma-coherent devices (since restricted DMA isn't supported by ACPI) as a reasonable approximation.
Yes, I think that's reasonable. We'd need to drive this from the arch code or, as you suggested, drivers/virt/coco rather than generic heuristics in the swiotlb code.
Signature · 1 line
Catalin
Re: [PATCH v6 6/8] dma: swiotlb: Centralize memory-encryption pool sizing
In reply to Will DeaconQuoted 37 lines · Will Deacon
Quoted 15 lines · Catalin Marinas
Quoted 5 lines · Will Deacon
Quoted 4 lines · Aneesh Kumar K.V (Arm)
kernel/dma/swiotlb.c +0
-0@@ -496,7 +516,8 @@ swiotlb_select_pool_policy(unsigned int flags)if (swiotlb_force_disable)return SWIOTLB_POOL_NONE ;Quoted 8 lines
kernel/dma/swiotlb.c swiotlb_select_pool_policy(unsigned int flags) · line 521
Quoted 4 lines
kernel/dma/swiotlb.c +2
-1-if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT )) +if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT ) && + !restricted_dma_pool_present)return SWIOTLB_POOL_CC_GUEST ;I think this check on the restricted DMA pool is too general -- the pool could be tied to a specific DMA-capable peripheral and so treating its presence as a global property isn't right.
Quoted 4 lines
I agree it's a hack but that was the simplest way to avoid the pVMs getting a bounce buffer after this patch. More than happy to leave it out and reduce the buffer on cmdline or we come up with some better heuristics.
Hrm, that does mean that reverting just this part will regress pVMs because they'll suddenly be allocating a tonne more memory for an entirely unused swiotlb buffer. So I think I'd prefer to drop the entire series until this has been worked out properly.
Quoted 4 lines
Another option could be the arch code passing another flag that it doesn't want an encrypted pool (e.g. when running in a pKVM guest) but I don't particularly this either. The arch code doesn't know whether there's an alternative pool.
At that point, the default size may as well be driven by the
drivers/virt/cocodriver.Quoted 2 lines
That said, such heuristics should have been a separate patch to make it easier to review/drop.
Quoted 10 lines
I think the only right way to get a semi-accurate heuristic is to take into account the set of dma-capable devices that will use the swiotlb pool, but that's fiddly and should probably be tackled as a separate series. Maybe a simpler hack in that direction would be to take the
SWIOTLB_POOL_CC_GUESTif _any_ device is going to use swiotlb? You'll run into the usual problem of not being able to tell if a device is DMA-capable or not, but you could probably look for a global restricted DMA pool and, if that doesn't exist, check for per-device restricted pools on dma-coherent devices (since restricted DMA isn't supported by ACPI) as a reasonable approximation.
So, something like this?
if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT) && swiotlb_cc_guest_needs_default_pool()) return SWIOTLB_POOL_CC_GUEST;
where:
static bool swiotlb_cc_guest_needs_default_pool(void)
{
for_each_of_allnodes(np) {
if (swiotlb_of_dma_needs_default_pool(np))
return true;
}
return false;
}I didn't quite follow the ACPI-related feedback. IIUC, on ACPI systems we will end up using SWIOTLB_POOL_CC_GUEST?
-aneesh
Re: [PATCH v6 6/8] dma: swiotlb: Centralize memory-encryption pool sizing
Quoted 50 lines · Aneesh Kumar K.V
Quoted 37 lines · Will Deacon
Quoted 15 lines · Catalin Marinas
Quoted 5 lines · Will Deacon
Quoted 4 lines · Aneesh Kumar K.V (Arm)
kernel/dma/swiotlb.c +0
-0@@ -496,7 +516,8 @@ swiotlb_select_pool_policy(unsigned int flags)if (swiotlb_force_disable)return SWIOTLB_POOL_NONE ;Quoted 8 lines
kernel/dma/swiotlb.c swiotlb_select_pool_policy(unsigned int flags) · line 521
Quoted 4 lines
kernel/dma/swiotlb.c +2
-1-if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT )) +if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT ) && + !restricted_dma_pool_present)return SWIOTLB_POOL_CC_GUEST ;I think this check on the restricted DMA pool is too general -- the pool could be tied to a specific DMA-capable peripheral and so treating its presence as a global property isn't right.
Quoted 4 lines
I agree it's a hack but that was the simplest way to avoid the pVMs getting a bounce buffer after this patch. More than happy to leave it out and reduce the buffer on cmdline or we come up with some better heuristics.
Hrm, that does mean that reverting just this part will regress pVMs because they'll suddenly be allocating a tonne more memory for an entirely unused swiotlb buffer. So I think I'd prefer to drop the entire series until this has been worked out properly.
Quoted 4 lines
Another option could be the arch code passing another flag that it doesn't want an encrypted pool (e.g. when running in a pKVM guest) but I don't particularly this either. The arch code doesn't know whether there's an alternative pool.
At that point, the default size may as well be driven by the
drivers/virt/cocodriver.Quoted 2 lines
That said, such heuristics should have been a separate patch to make it easier to review/drop.
Quoted 10 lines
I think the only right way to get a semi-accurate heuristic is to take into account the set of dma-capable devices that will use the swiotlb pool, but that's fiddly and should probably be tackled as a separate series. Maybe a simpler hack in that direction would be to take the
SWIOTLB_POOL_CC_GUESTif _any_ device is going to use swiotlb? You'll run into the usual problem of not being able to tell if a device is DMA-capable or not, but you could probably look for a global restricted DMA pool and, if that doesn't exist, check for per-device restricted pools on dma-coherent devices (since restricted DMA isn't supported by ACPI) as a reasonable approximation.
Quoted 6 lines
So, something like this?
if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT) && swiotlb_cc_guest_needs_default_pool()) return SWIOTLB_POOL_CC_GUEST;
Detecting a DMA-capable device is not straightforward, and if we get it wrong, we will enable SWIOTLB_POOL_CC_GUEST unnecessarily. Would the code below be a reasonable approximation of what you suggested?
Another option would be to make swiotlb_cc_guest_needs_default_pool() a weak function that architectures can override. arm64 pKVM could then use a different scheme (for this patch series default to false). Would that be preferable?
#ifdef CONFIG_DMA_RESTRICTED_POOL
static bool __init swiotlb_of_dma_candidate(struct device_node *np)
{
struct device_node *node __free(device_node) = of_node_get(np);
/*
* Ignore nodes that don't have compatible and reg property
* So we don't wrongly consider a node as device node.
*/
if (!of_property_present(np, "compatible") ||
!of_property_present(np, "reg"))
return false;
while (node) {
if (!of_device_is_available(node))
return false;
/*
* Ignore reserved-memory nodes because that have compatible
* and reg property
*/
if (node->parent == of_root &&
of_node_name_eq(node, "reserved-memory"))
return false;
node = of_get_next_parent(node);
}
return of_dma_is_coherent(np);
}static bool __init swiotlb_of_dma_needs_default_pool(struct device_node *np)
{
if (!of_dma_get_restricted_pool(np))
return true;
return false;
}#endif
static bool __init swiotlb_cc_guest_needs_default_pool(void) {
#ifdef CONFIG_DMA_RESTRICTED_POOL
struct device_node *np;
bool found = false;
if (!of_root)
return true;
/*
* DMA capability is not explicitly described for every DT device.
* Use coherent, addressed device nodes as an approximation, and keep
* guest sizing unless every candidate has an initialized restricted
* pool.
*/
for_each_of_allnodes(np) {
if (!swiotlb_of_dma_candidate(np))
continue;
found = true;
if (swiotlb_of_dma_needs_default_pool(np))
return true;
}
return !found;
#else
return true;#endif
}
Catalin Marinas
maintainerRe: [PATCH v6 6/8] dma: swiotlb: Centralize memory-encryption pool sizing
Quoted 57 lines · Aneesh Kumar K.V
Quoted 49 lines · Aneesh Kumar K.V
Quoted 37 lines · Will Deacon
Quoted 15 lines · Catalin Marinas
Quoted 5 lines · Will Deacon
Quoted 4 lines · Aneesh Kumar K.V (Arm)
kernel/dma/swiotlb.c +0
-0@@ -496,7 +516,8 @@ swiotlb_select_pool_policy(unsigned int flags)if (swiotlb_force_disable)return SWIOTLB_POOL_NONE ;Quoted 8 lines
kernel/dma/swiotlb.c swiotlb_select_pool_policy(unsigned int flags) · line 521
Quoted 4 lines
kernel/dma/swiotlb.c +2
-1-if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT )) +if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT ) && + !restricted_dma_pool_present)return SWIOTLB_POOL_CC_GUEST ;I think this check on the restricted DMA pool is too general -- the pool could be tied to a specific DMA-capable peripheral and so treating its presence as a global property isn't right.
Quoted 4 lines
I agree it's a hack but that was the simplest way to avoid the pVMs getting a bounce buffer after this patch. More than happy to leave it out and reduce the buffer on cmdline or we come up with some better heuristics.
Hrm, that does mean that reverting just this part will regress pVMs because they'll suddenly be allocating a tonne more memory for an entirely unused swiotlb buffer. So I think I'd prefer to drop the entire series until this has been worked out properly.
Quoted 4 lines
Another option could be the arch code passing another flag that it doesn't want an encrypted pool (e.g. when running in a pKVM guest) but I don't particularly this either. The arch code doesn't know whether there's an alternative pool.
At that point, the default size may as well be driven by the
drivers/virt/cocodriver.Quoted 2 lines
That said, such heuristics should have been a separate patch to make it easier to review/drop.
Quoted 10 lines
I think the only right way to get a semi-accurate heuristic is to take into account the set of dma-capable devices that will use the swiotlb pool, but that's fiddly and should probably be tackled as a separate series. Maybe a simpler hack in that direction would be to take the
SWIOTLB_POOL_CC_GUESTif _any_ device is going to use swiotlb? You'll run into the usual problem of not being able to tell if a device is DMA-capable or not, but you could probably look for a global restricted DMA pool and, if that doesn't exist, check for per-device restricted pools on dma-coherent devices (since restricted DMA isn't supported by ACPI) as a reasonable approximation.Quoted 6 lines
So, something like this?
if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT) && swiotlb_cc_guest_needs_default_pool()) return SWIOTLB_POOL_CC_GUEST;
Quoted 8 lines
Detecting a DMA-capable device is not straightforward, and if we get it wrong, we will enable
SWIOTLB_POOL_CC_GUESTunnecessarily. Would the code below be a reasonable approximation of what you suggested?Another option would be to make
swiotlb_cc_guest_needs_default_pool()a weak function that architectures can override. arm64 pKVM could then use a different scheme (for this patch series default to false). Would that be preferable?
Even the rmem check for each device is still a hack that may bite us in the future (private devices for example would not need swiotlb). I'm thinking more and more of leaving the sizing an arch-specific decision, don't bother generalising it at all.
On pKVM vs CCA guests, there's really nothing specific here to pKVM guests. The only difference is that confidential guests that so far have run without a swiotlb buffer will regress if their memory is tight. For confidential guests without dedicated rmem (either CCA or pKVM), I think our options are either command line swiotlb sizing or dynamic swiotlb.
Could you respin your series while leaving out the generic sizing? IOW, no x86 code generalisation. We can discuss the best strategy on sizing later (I haven't checked how much of this series still makes sense without the generic sizing).
Signature · 1 line
Catalin
Re: [PATCH v6 6/8] dma: swiotlb: Centralize memory-encryption pool sizing
Quoted 78 lines · Catalin Marinas
Quoted 57 lines · Aneesh Kumar K.V
Quoted 49 lines · Aneesh Kumar K.V
Quoted 37 lines · Will Deacon
Quoted 15 lines · Catalin Marinas
Quoted 5 lines · Will Deacon
Quoted 4 lines · Aneesh Kumar K.V (Arm)
(quoted diff) +0
-0@@ -496,7 +516,8 @@ swiotlb_select_pool_policy(unsigned int flags) if (swiotlb_force_disable) return SWIOTLB_POOL_NONE;Quoted 8 lines
Review swiotlb_select_pool_policy(unsigned int flags) · line 521
Quoted 4 lines
(quoted diff) +2
-1- if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) + if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT) && + !restricted_dma_pool_present) return SWIOTLB_POOL_CC_GUEST;I think this check on the restricted DMA pool is too general -- the pool could be tied to a specific DMA-capable peripheral and so treating its presence as a global property isn't right.
Quoted 4 lines
I agree it's a hack but that was the simplest way to avoid the pVMs getting a bounce buffer after this patch. More than happy to leave it out and reduce the buffer on cmdline or we come up with some better heuristics.
Hrm, that does mean that reverting just this part will regress pVMs because they'll suddenly be allocating a tonne more memory for an entirely unused swiotlb buffer. So I think I'd prefer to drop the entire series until this has been worked out properly.
Quoted 4 lines
Another option could be the arch code passing another flag that it doesn't want an encrypted pool (e.g. when running in a pKVM guest) but I don't particularly this either. The arch code doesn't know whether there's an alternative pool.
At that point, the default size may as well be driven by the
drivers/virt/cocodriver.Quoted 2 lines
That said, such heuristics should have been a separate patch to make it easier to review/drop.
Quoted 10 lines
I think the only right way to get a semi-accurate heuristic is to take into account the set of dma-capable devices that will use the swiotlb pool, but that's fiddly and should probably be tackled as a separate series. Maybe a simpler hack in that direction would be to take the
SWIOTLB_POOL_CC_GUESTif _any_ device is going to use swiotlb? You'll run into the usual problem of not being able to tell if a device is DMA-capable or not, but you could probably look for a global restricted DMA pool and, if that doesn't exist, check for per-device restricted pools on dma-coherent devices (since restricted DMA isn't supported by ACPI) as a reasonable approximation.Quoted 6 lines
So, something like this?
if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT) && swiotlb_cc_guest_needs_default_pool()) return SWIOTLB_POOL_CC_GUEST;Quoted 8 lines
Detecting a DMA-capable device is not straightforward, and if we get it wrong, we will enable
SWIOTLB_POOL_CC_GUESTunnecessarily. Would the code below be a reasonable approximation of what you suggested?Another option would be to make
swiotlb_cc_guest_needs_default_pool()a weak function that architectures can override. arm64 pKVM could then use a different scheme (for this patch series default to false). Would that be preferable?Even the rmem check for each device is still a hack that may bite us in the future (private devices for example would not need swiotlb). I'm thinking more and more of leaving the sizing an arch-specific decision, don't bother generalising it at all.
On pKVM vs CCA guests, there's really nothing specific here to pKVM guests. The only difference is that confidential guests that so far have run without a swiotlb buffer will regress if their memory is tight. For confidential guests without dedicated rmem (either CCA or pKVM), I think our options are either command line swiotlb sizing or dynamic swiotlb.
Quoted 5 lines
Could you respin your series while leaving out the generic sizing? IOW, no x86 code generalisation. We can discuss the best strategy on sizing later (I haven't checked how much of this series still makes sense without the generic sizing).
It would mostly consist of the first three cleanup patches, followed by three patches that replace the addressing_limit argument with flags.
#define SWIOTLB_VERBOSE (1 << 0) /* verbose initialization */
/* Initialize a pool for devices with limited DMA addressing. */
#define SWIOTLB_INIT_ADDRESSING_LIMIT (1 << 1)
/* Initialize a pool that requires architecture remapping. */
#define SWIOTLB_INIT_REMAP (1 << 2)
/* Initialize a pool for DMA to memory-encrypted host or guest memory. */
#define SWIOTLB_INIT_MEM_ENCRYPT (1 << 3)
/* Initialize a pool for unaligned kmalloc bouncing. */
#define SWIOTLB_INIT_KMALLOC (1 << 4)
/* Do not initialize a pool unless SWIOTLB is explicitly required. */
#define SWIOTLB_INIT_DEFAULT_OFF (1 << 5)
This results in the large change below. I'm not sure we want to do this for no real benefit other than making swiotlb_should_init() slightly easier to follow.
static bool __init swiotlb_should_init(unsigned int flags)
{
if (swiotlb_force_disable)
return false;
if (swiotlb_force_bounce)
return true;
if (flags & (SWIOTLB_INIT_REMAP | SWIOTLB_INIT_MEM_ENCRYPT)))
return true;
/* Explicit requirements override an architecture's default opt-out. */
if (flags & SWIOTLB_INIT_DEFAULT_OFF)
return false;
return flags & (SWIOTLB_INIT_ADDRESSING_LIMIT | SWIOTLB_INIT_KMALLOC);
}Marek,
Patch 3 is a fix, so you may want to take it even if we drop the rest of the series. Perhaps the first three patches could be taken together?
modified arch/arm/mm/init.c
@@ -223,7 +223,11 @@ static inline void poison_init_mem(void *s, size_t count)
void __init arch_mm_preinit(void)
{
#ifdef CONFIG_ARM_LPAE
- swiotlb_init(max_pfn > arm_dma_pfn_limit, SWIOTLB_VERBOSE);
+ unsigned int flags = SWIOTLB_VERBOSE;
+
+ if (max_pfn > arm_dma_pfn_limit)
+ flags |= SWIOTLB_INIT_ADDRESSING_LIMIT;
+ swiotlb_init(flags);
#endif
#ifdef CONFIG_SA1111
modified arch/arm64/mm/init.c
@@ -351,7 +351,10 @@ void __init arch_mm_preinit(void)
swiotlb_adjust_size(min(swiotlb_default_pool_size(), size));
}
- swiotlb_init(true, flags);
+ if (max_pfn > PFN_DOWN(arm64_dma_phys_limit))
+ flags |= SWIOTLB_INIT_ADDRESSING_LIMIT;
+
+ swiotlb_init(flags);
/*
* Check boundaries twice: Some fundamental inconsistencies can be
modified arch/loongarch/kernel/setup.c
@@ -404,7 +404,7 @@ static void __init arch_mem_init(char **cmdline_p)
memblock_set_bottom_up(true);
- swiotlb_init(true, SWIOTLB_VERBOSE);
+ swiotlb_init(SWIOTLB_VERBOSE | SWIOTLB_INIT_ADDRESSING_LIMIT);
dma_contiguous_reserve(PFN_PHYS(max_low_pfn));
modified arch/mips/cavium-octeon/dma-octeon.c
@@ -235,5 +235,5 @@ void __init plat_swiotlb_setup(void)
#endif
swiotlb_adjust_size(swiotlbsize);
- swiotlb_init(true, SWIOTLB_VERBOSE);
+ swiotlb_init(SWIOTLB_VERBOSE | SWIOTLB_INIT_ADDRESSING_LIMIT);
}
modified arch/mips/loongson64/dma.c
@@ -25,5 +25,5 @@ phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
void __init plat_swiotlb_setup(void)
{
- swiotlb_init(true, SWIOTLB_VERBOSE);
+ swiotlb_init(SWIOTLB_VERBOSE | SWIOTLB_INIT_ADDRESSING_LIMIT);
}
modified arch/mips/sibyte/common/dma.c
@@ -10,5 +10,5 @@
void __init plat_swiotlb_setup(void)
{
- swiotlb_init(true, SWIOTLB_VERBOSE);
+ swiotlb_init(SWIOTLB_VERBOSE | SWIOTLB_INIT_ADDRESSING_LIMIT);
}
modified arch/powerpc/kernel/dma-swiotlb.c
@@ -14,8 +14,10 @@ unsigned int ppc_swiotlb_flags;
void __init swiotlb_detect_4g(void)
{
- if ((memblock_end_of_DRAM() - 1) > 0xffffffff)
+ if ((memblock_end_of_DRAM() - 1) > 0xffffffff) {
ppc_swiotlb_enable = 1;
+ ppc_swiotlb_flags |= SWIOTLB_INIT_ADDRESSING_LIMIT;
+ }
}
static int __init check_swiotlb_enabled(void)
modified arch/powerpc/mm/mem.c
@@ -287,6 +287,19 @@ void __init arch_mm_preinit(void)
BUILD_BUG_ON(MMU_PAGE_COUNT > 16);
#ifdef CONFIG_SWIOTLB
+ if (is_secure_guest()) {
+
+ /* Don't release the SWIOTLB buffer. */
+ ppc_swiotlb_enable = 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 |= 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
kasan_late_init();
modified arch/powerpc/platforms/pseries/svm.c
@@ -21,16 +21,6 @@ static int __init init_svm(void)
if (!is_secure_guest())
return 0;
- /* Don't release the SWIOTLB buffer. */
- ppc_swiotlb_enable = 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 |= SWIOTLB_ANY;
-
/* Share the SWIOTLB buffer with the host. */ swiotlb_update_mem_attributes();
modified 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 = 1;
+ ppc_swiotlb_flags |= 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",
modified arch/riscv/mm/init.c
@@ -165,14 +165,17 @@ static void print_vm_layout(void) { }
void __init arch_mm_preinit(void)
{
- bool swiotlb = max_pfn > PFN_DOWN(dma32_phys_limit) &&
- memblock_start_of_DRAM() < dma32_phys_limit;
unsigned int swiotlb_flags = SWIOTLB_VERBOSE;
#ifdef CONFIG_FLATMEM
BUG_ON(!mem_map);
#endif /* CONFIG_FLATMEM */
- if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) && !swiotlb &&
+ if (max_pfn > PFN_DOWN(dma32_phys_limit) &&
+ memblock_start_of_DRAM() < dma32_phys_limit)
+ swiotlb_flags |= SWIOTLB_INIT_ADDRESSING_LIMIT;
+
+ if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) &&
+ !(swiotlb_flags & SWIOTLB_INIT_ADDRESSING_LIMIT) &&
dma_cache_alignment != 1) {
/*
* No 32-bit DMA bouncing needed (either all DRAM is within
@@ -186,11 +189,10 @@ void __init arch_mm_preinit(void)
unsigned long size =
DIV_ROUND_UP(memblock_phys_mem_size(), 1024);
swiotlb_adjust_size(min(swiotlb_default_pool_size(), size));
- swiotlb = true;
- swiotlb_flags |= SWIOTLB_ANY;
+ swiotlb_flags |= SWIOTLB_INIT_KMALLOC | SWIOTLB_ANY;
}
- swiotlb_init(swiotlb, swiotlb_flags);
+ swiotlb_init(swiotlb_flags);
print_vm_layout();
}
modified 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);
/* make sure bounce buffers are shared */
- swiotlb_init(true, SWIOTLB_VERBOSE | SWIOTLB_ANY);
+ swiotlb_init(SWIOTLB_VERBOSE | SWIOTLB_ANY);
swiotlb_update_mem_attributes();
}
modified arch/x86/kernel/pci-dma.c
@@ -44,8 +44,10 @@ static unsigned int x86_swiotlb_flags;
static void __init pci_swiotlb_detect(void)
{
/* don't initialize swiotlb if iommu=off (no_iommu=1) */
- if (!no_iommu && max_possible_pfn > MAX_DMA32_PFN)
+ if (!no_iommu && max_possible_pfn > MAX_DMA32_PFN) {
x86_swiotlb_enable = true;
+ x86_swiotlb_flags |= SWIOTLB_INIT_ADDRESSING_LIMIT;
+ }
/*
* Set swiotlb to 1 so that bounce buffers are allocated and used for
@@ -81,8 +83,10 @@ static void __init pci_xen_swiotlb_init(void)
if (!xen_swiotlb_enabled())
return;
x86_swiotlb_enable = true;
- x86_swiotlb_flags |= SWIOTLB_ANY;
- swiotlb_init_remap(true, x86_swiotlb_flags, xen_swiotlb_fixup);
+ /* Xen can use a SWIOTLB pool anywhere in directly mapped memory. */
+ x86_swiotlb_flags &= ~SWIOTLB_INIT_ADDRESSING_LIMIT;
+ x86_swiotlb_flags |= SWIOTLB_INIT_REMAP | SWIOTLB_ANY;
+ swiotlb_init_remap(x86_swiotlb_flags, xen_swiotlb_fixup);
dma_ops = &xen_swiotlb_dma_ops;
if (IS_ENABLED(CONFIG_PCI))
pci_request_acs();
@@ -103,7 +107,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);
}
static __init int iommu_setup(char *p)
@@ -149,8 +153,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 = true;
+ x86_swiotlb_flags |= SWIOTLB_INIT_ADDRESSING_LIMIT;
+ }
#endif
if (!strncmp(p, "pt", 2))
iommu_set_default_passthrough(true);
modified include/linux/swiotlb.h
@@ -16,6 +16,14 @@ struct scatterlist;
#define SWIOTLB_VERBOSE (1 << 0) /* verbose initialization */
#define SWIOTLB_ANY (1 << 1) /* allow any memory for the buffer */
+/* Initialize a pool for devices with limited DMA addressing. */
+#define SWIOTLB_INIT_ADDRESSING_LIMIT (1 << 2)
+/* Initialize a pool that requires architecture remapping. */
+#define SWIOTLB_INIT_REMAP (1 << 3)
+/* Initialize a pool for DMA to memory-encrypted host or guest memory. */
+#define SWIOTLB_INIT_MEM_ENCRYPT (1 << 4)
+/* Initialize a pool for unaligned kmalloc bouncing. */
+#define SWIOTLB_INIT_KMALLOC (1 << 5)
/*
* Maximum allowable number of contiguous slabs to map,
@@ -39,8 +47,8 @@ struct scatterlist;
#endif
unsigned long swiotlb_default_pool_size(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 +191,7 @@ static inline bool is_swiotlb_force_bounce(struct device *dev)
return mem && mem->force_bounce;
}
-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 +201,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 flags) +static inline void swiotlb_init(unsigned int flags)
{
}
modified kernel/dma/swiotlb.c
@@ -354,24 +354,15 @@ static void swiotlb_mark_pool_used(struct io_tlb_pool *pool)
void __init swiotlb_update_mem_attributes(void)
{
struct io_tlb_pool *mem = &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 = true;
- else
- io_tlb_default_mem.cc_shared = false;
if (!mem->nslabs || mem->late_alloc)
return;
- bytes = PAGE_ALIGN(mem->nslabs << IO_TLB_SHIFT);
if (io_tlb_default_mem.cc_shared) {
int ret;
+ unsigned long bytes;
+ bytes = PAGE_ALIGN(mem->nslabs << IO_TLB_SHIFT);
ret = set_memory_decrypted((unsigned long)mem->vaddr,
bytes >> PAGE_SHIFT);
if (ret) {
@@ -462,12 +453,32 @@ static void __init *swiotlb_memblock_alloc(unsigned long nslabs,
return tlb;
}
+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 (swiotlb_force_bounce)
+ return true;
+
+ return (flags & (SWIOTLB_INIT_ADDRESSING_LIMIT |
+ SWIOTLB_INIT_REMAP |
+ SWIOTLB_INIT_MEM_ENCRYPT |
+ SWIOTLB_INIT_KMALLOC));
+}
+
/*
* 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 = &io_tlb_default_mem.defpool;
unsigned long nslabs;
@@ -475,9 +486,12 @@ void __init swiotlb_init_remap(bool addressing_limit, unsigned int flags,
size_t alloc_size;
void *tlb;
- if (!addressing_limit && !swiotlb_force_bounce)
- return;
- if (swiotlb_force_disable)
+ if (cc_platform_has(CC_ATTR_MEM_ENCRYPT))
+ flags |= SWIOTLB_INIT_MEM_ENCRYPT;
+ if (swiotlb_kmalloc_needs_bounce())
+ flags |= SWIOTLB_INIT_KMALLOC;
+
+ if (!swiotlb_should_init(flags))
return;
io_tlb_default_mem.force_bounce = swiotlb_force_bounce;
@@ -491,6 +505,10 @@ void __init swiotlb_init_remap(bool addressing_limit, unsigned int flags,
io_tlb_default_mem.phys_limit = ARCH_LOW_ADDRESS_LIMIT;
#endif
+ /* if we have host or guest memory encryption */
+ if (cc_platform_has(CC_ATTR_MEM_ENCRYPT))
+ io_tlb_default_mem.cc_shared = true;
+
if (!default_nareas)
swiotlb_adjust_nareas(num_possible_cpus());
@@ -531,9 +549,9 @@ void __init swiotlb_init_remap(bool addressing_limit, unsigned int flags,
swiotlb_print_info();
}
-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);
}
/*
-aneesh
Marek Szyprowski
maintainerRe: [PATCH v6 6/8] dma: swiotlb: Centralize memory-encryption pool sizing
Quoted 113 lines · Aneesh Kumar K.V
Quoted 70 lines · Catalin Marinas
Quoted 50 lines · Aneesh Kumar K.V
Quoted 43 lines · Aneesh Kumar K.V
Quoted 32 lines · Will Deacon
Quoted 13 lines · Catalin Marinas
Quoted 5 lines · Will Deacon
Quoted 4 lines · Aneesh Kumar K.V (Arm)
(quoted diff) +0
-0@@ -496,7 +516,8 @@ swiotlb_select_pool_policy(unsigned int flags) if (swiotlb_force_disable) return SWIOTLB_POOL_NONE;Quoted 7 lines
Review swiotlb_select_pool_policy(unsigned int flags) · line 521
Quoted 4 lines
(quoted diff) +2
-1- if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) + if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT) && + !restricted_dma_pool_present) return SWIOTLB_POOL_CC_GUEST;I think this check on the restricted DMA pool is too general -- the pool could be tied to a specific DMA-capable peripheral and so treating its presence as a global property isn't right.
Quoted 4 lines
I agree it's a hack but that was the simplest way to avoid the pVMs getting a bounce buffer after this patch. More than happy to leave it out and reduce the buffer on cmdline or we come up with some better heuristics.
Hrm, that does mean that reverting just this part will regress pVMs because they'll suddenly be allocating a tonne more memory for an entirely unused swiotlb buffer. So I think I'd prefer to drop the entire series until this has been worked out properly.
Quoted 4 lines
Another option could be the arch code passing another flag that it doesn't want an encrypted pool (e.g. when running in a pKVM guest) but I don't particularly this either. The arch code doesn't know whether there's an alternative pool.
At that point, the default size may as well be driven by the
drivers/virt/cocodriver.Quoted 2 lines
That said, such heuristics should have been a separate patch to make it easier to review/drop.
Quoted 10 lines
I think the only right way to get a semi-accurate heuristic is to take into account the set of dma-capable devices that will use the swiotlb pool, but that's fiddly and should probably be tackled as a separate series. Maybe a simpler hack in that direction would be to take the
SWIOTLB_POOL_CC_GUESTif _any_ device is going to use swiotlb? You'll run into the usual problem of not being able to tell if a device is DMA-capable or not, but you could probably look for a global restricted DMA pool and, if that doesn't exist, check for per-device restricted pools on dma-coherent devices (since restricted DMA isn't supported by ACPI) as a reasonable approximation.Quoted 6 lines
So, something like this?
if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT) && swiotlb_cc_guest_needs_default_pool()) return SWIOTLB_POOL_CC_GUEST;Quoted 8 lines
Detecting a DMA-capable device is not straightforward, and if we get it wrong, we will enable
SWIOTLB_POOL_CC_GUESTunnecessarily. Would the code below be a reasonable approximation of what you suggested?Another option would be to make
swiotlb_cc_guest_needs_default_pool()a weak function that architectures can override. arm64 pKVM could then use a different scheme (for this patch series default to false). Would that be preferable?Even the rmem check for each device is still a hack that may bite us in the future (private devices for example would not need swiotlb). I'm thinking more and more of leaving the sizing an arch-specific decision, don't bother generalising it at all.
On pKVM vs CCA guests, there's really nothing specific here to pKVM guests. The only difference is that confidential guests that so far have run without a swiotlb buffer will regress if their memory is tight. For confidential guests without dedicated rmem (either CCA or pKVM), I think our options are either command line swiotlb sizing or dynamic swiotlb.
Quoted 5 lines
Could you respin your series while leaving out the generic sizing? IOW, no x86 code generalisation. We can discuss the best strategy on sizing later (I haven't checked how much of this series still makes sense without the generic sizing).
It would mostly consist of the first three cleanup patches, followed by three patches that replace the
addressing_limitargument with flags.#define
SWIOTLB_VERBOSE(1 << 0) /* verbose initialization */
/* Initialize a pool for devices with limited DMA addressing. */
#defineSWIOTLB_INIT_ADDRESSING_LIMIT(1 << 1)
/* Initialize a pool that requires architecture remapping. */
#defineSWIOTLB_INIT_REMAP(1 << 2)
/* Initialize a pool for DMA to memory-encrypted host or guest memory. */
#defineSWIOTLB_INIT_MEM_ENCRYPT(1 << 3)
/* Initialize a pool for unaligned kmalloc bouncing. */
#defineSWIOTLB_INIT_KMALLOC(1 << 4)
/* Do not initialize a pool unless SWIOTLB is explicitly required. */
#defineSWIOTLB_INIT_DEFAULT_OFF(1 << 5)This results in the large change below. I'm not sure we want to do this for no real benefit other than making
swiotlb_should_init()slightly easier to follow.static bool
__initswiotlb_should_init(unsigned int flags){ if (swiotlb_force_disable) return false; if (swiotlb_force_bounce) return true; if (flags & (SWIOTLB_INIT_REMAP | SWIOTLB_INIT_MEM_ENCRYPT))) return true; /* Explicit requirements override an architecture's default opt-out. */ if (flags & SWIOTLB_INIT_DEFAULT_OFF) return false; return flags & (SWIOTLB_INIT_ADDRESSING_LIMIT | SWIOTLB_INIT_KMALLOC); }
Quoted 4 lines
Marek,
Patch 3 is a fix, so you may want to take it even if we drop the rest of the series. Perhaps the first three patches could be taken together?
Okay, I will take only the first 3 patches to dma-mapping-for-next branch now and wait for the remaining patches until they gets sorted out.
Best regards
Signature · 2 lines
Marek Szyprowski, PhD Samsung R&D Institute Poland
Will Deacon
maintainerRe: [PATCH v6 6/8] dma: swiotlb: Centralize memory-encryption pool sizing
Quoted 6 lines · Marek Szyprowski
Quoted 2 lines · Aneesh Kumar K.V
Patch 3 is a fix, so you may want to take it even if we drop the rest of the series. Perhaps the first three patches could be taken together?
Okay, I will take only the first 3 patches to dma-mapping-for-next branch now and wait for the remaining patches until they gets sorted out.
Thanks, Marek.
Will
Re: [PATCH v6 6/8] dma: swiotlb: Centralize memory-encryption pool sizing
In reply to Aneesh Kumar K.VQuoted 122 lines · Aneesh Kumar K.V
Quoted 78 lines · Catalin Marinas
Quoted 57 lines · Aneesh Kumar K.V
Quoted 49 lines · Aneesh Kumar K.V
Quoted 37 lines · Will Deacon
Quoted 15 lines · Catalin Marinas
Quoted 5 lines · Will Deacon
Quoted 4 lines · Aneesh Kumar K.V (Arm)
(quoted diff) +0
-0@@ -496,7 +516,8 @@ swiotlb_select_pool_policy(unsigned int flags) if (swiotlb_force_disable) return SWIOTLB_POOL_NONE;Quoted 8 lines
Review swiotlb_select_pool_policy(unsigned int flags) · line 521
Quoted 4 lines
(quoted diff) +2
-1- if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) + if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT) && + !restricted_dma_pool_present) return SWIOTLB_POOL_CC_GUEST;I think this check on the restricted DMA pool is too general -- the pool could be tied to a specific DMA-capable peripheral and so treating its presence as a global property isn't right.
Quoted 4 lines
I agree it's a hack but that was the simplest way to avoid the pVMs getting a bounce buffer after this patch. More than happy to leave it out and reduce the buffer on cmdline or we come up with some better heuristics.
Hrm, that does mean that reverting just this part will regress pVMs because they'll suddenly be allocating a tonne more memory for an entirely unused swiotlb buffer. So I think I'd prefer to drop the entire series until this has been worked out properly.
Quoted 4 lines
Another option could be the arch code passing another flag that it doesn't want an encrypted pool (e.g. when running in a pKVM guest) but I don't particularly this either. The arch code doesn't know whether there's an alternative pool.
At that point, the default size may as well be driven by the
drivers/virt/cocodriver.Quoted 2 lines
That said, such heuristics should have been a separate patch to make it easier to review/drop.
Quoted 10 lines
I think the only right way to get a semi-accurate heuristic is to take into account the set of dma-capable devices that will use the swiotlb pool, but that's fiddly and should probably be tackled as a separate series. Maybe a simpler hack in that direction would be to take the
SWIOTLB_POOL_CC_GUESTif _any_ device is going to use swiotlb? You'll run into the usual problem of not being able to tell if a device is DMA-capable or not, but you could probably look for a global restricted DMA pool and, if that doesn't exist, check for per-device restricted pools on dma-coherent devices (since restricted DMA isn't supported by ACPI) as a reasonable approximation.Quoted 6 lines
So, something like this?
if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT) && swiotlb_cc_guest_needs_default_pool()) return SWIOTLB_POOL_CC_GUEST;Quoted 8 lines
Detecting a DMA-capable device is not straightforward, and if we get it wrong, we will enable
SWIOTLB_POOL_CC_GUESTunnecessarily. Would the code below be a reasonable approximation of what you suggested?Another option would be to make
swiotlb_cc_guest_needs_default_pool()a weak function that architectures can override. arm64 pKVM could then use a different scheme (for this patch series default to false). Would that be preferable?Even the rmem check for each device is still a hack that may bite us in the future (private devices for example would not need swiotlb). I'm thinking more and more of leaving the sizing an arch-specific decision, don't bother generalising it at all.
On pKVM vs CCA guests, there's really nothing specific here to pKVM guests. The only difference is that confidential guests that so far have run without a swiotlb buffer will regress if their memory is tight. For confidential guests without dedicated rmem (either CCA or pKVM), I think our options are either command line swiotlb sizing or dynamic swiotlb.
Quoted 5 lines
Could you respin your series while leaving out the generic sizing? IOW, no x86 code generalisation. We can discuss the best strategy on sizing later (I haven't checked how much of this series still makes sense without the generic sizing).
It would mostly consist of the first three cleanup patches, followed by three patches that replace the
addressing_limitargument with flags.#define
SWIOTLB_VERBOSE(1 << 0) /* verbose initialization */
/* Initialize a pool for devices with limited DMA addressing. */
#defineSWIOTLB_INIT_ADDRESSING_LIMIT(1 << 1)
/* Initialize a pool that requires architecture remapping. */
#defineSWIOTLB_INIT_REMAP(1 << 2)
/* Initialize a pool for DMA to memory-encrypted host or guest memory. */
#defineSWIOTLB_INIT_MEM_ENCRYPT(1 << 3)
/* Initialize a pool for unaligned kmalloc bouncing. */
#defineSWIOTLB_INIT_KMALLOC(1 << 4)
/* Do not initialize a pool unless SWIOTLB is explicitly required. */
#defineSWIOTLB_INIT_DEFAULT_OFF(1 << 5)This results in the large change below. I'm not sure we want to do this for no real benefit other than making
swiotlb_should_init()slightly easier to follow.static bool
__initswiotlb_should_init(unsigned int flags){ if (swiotlb_force_disable) return false; if (swiotlb_force_bounce) return true; if (flags & (SWIOTLB_INIT_REMAP | SWIOTLB_INIT_MEM_ENCRYPT))) return true; /* Explicit requirements override an architecture's default opt-out. */ if (flags & SWIOTLB_INIT_DEFAULT_OFF) return false; return flags & (SWIOTLB_INIT_ADDRESSING_LIMIT | SWIOTLB_INIT_KMALLOC); }
Quoted 1 line
[...]
Hi Aneesh,
I can reproduce the CCA regression discussed in this thread:
https://lore.kernel.org/all/[email protected]/#t
The guest runs out of SWIOTLB slots, causing disk I/O to fail and preventing the guest from booting.
I would like to test the fix on real CCA hardware. Could you please Cc me when you respin the series? I follow LKML, but I may still miss the posting by chance.
Thanks,
Kohei
Re: [PATCH v6 6/8] dma: swiotlb: Centralize memory-encryption pool sizing
Quoted 130 lines · Kohei Enju
Quoted 122 lines · Aneesh Kumar K.V
Quoted 78 lines · Catalin Marinas
Quoted 57 lines · Aneesh Kumar K.V
Quoted 49 lines · Aneesh Kumar K.V
Quoted 37 lines · Will Deacon
Quoted 15 lines · Catalin Marinas
Quoted 5 lines · Will Deacon
Quoted 4 lines · Aneesh Kumar K.V (Arm)
(quoted diff) +0
-0@@ -496,7 +516,8 @@ swiotlb_select_pool_policy(unsigned int flags) if (swiotlb_force_disable) return SWIOTLB_POOL_NONE;Quoted 8 lines
Review swiotlb_select_pool_policy(unsigned int flags) · line 521
Quoted 4 lines
(quoted diff) +2
-1- if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) + if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT) && + !restricted_dma_pool_present) return SWIOTLB_POOL_CC_GUEST;I think this check on the restricted DMA pool is too general -- the pool could be tied to a specific DMA-capable peripheral and so treating its presence as a global property isn't right.
Quoted 4 lines
I agree it's a hack but that was the simplest way to avoid the pVMs getting a bounce buffer after this patch. More than happy to leave it out and reduce the buffer on cmdline or we come up with some better heuristics.
Hrm, that does mean that reverting just this part will regress pVMs because they'll suddenly be allocating a tonne more memory for an entirely unused swiotlb buffer. So I think I'd prefer to drop the entire series until this has been worked out properly.
Quoted 4 lines
Another option could be the arch code passing another flag that it doesn't want an encrypted pool (e.g. when running in a pKVM guest) but I don't particularly this either. The arch code doesn't know whether there's an alternative pool.
At that point, the default size may as well be driven by the
drivers/virt/cocodriver.Quoted 2 lines
That said, such heuristics should have been a separate patch to make it easier to review/drop.
Quoted 10 lines
I think the only right way to get a semi-accurate heuristic is to take into account the set of dma-capable devices that will use the swiotlb pool, but that's fiddly and should probably be tackled as a separate series. Maybe a simpler hack in that direction would be to take the
SWIOTLB_POOL_CC_GUESTif _any_ device is going to use swiotlb? You'll run into the usual problem of not being able to tell if a device is DMA-capable or not, but you could probably look for a global restricted DMA pool and, if that doesn't exist, check for per-device restricted pools on dma-coherent devices (since restricted DMA isn't supported by ACPI) as a reasonable approximation.Quoted 6 lines
So, something like this?
if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT) && swiotlb_cc_guest_needs_default_pool()) return SWIOTLB_POOL_CC_GUEST;Quoted 8 lines
Detecting a DMA-capable device is not straightforward, and if we get it wrong, we will enable
SWIOTLB_POOL_CC_GUESTunnecessarily. Would the code below be a reasonable approximation of what you suggested?Another option would be to make
swiotlb_cc_guest_needs_default_pool()a weak function that architectures can override. arm64 pKVM could then use a different scheme (for this patch series default to false). Would that be preferable?Even the rmem check for each device is still a hack that may bite us in the future (private devices for example would not need swiotlb). I'm thinking more and more of leaving the sizing an arch-specific decision, don't bother generalising it at all.
On pKVM vs CCA guests, there's really nothing specific here to pKVM guests. The only difference is that confidential guests that so far have run without a swiotlb buffer will regress if their memory is tight. For confidential guests without dedicated rmem (either CCA or pKVM), I think our options are either command line swiotlb sizing or dynamic swiotlb.
Quoted 5 lines
Could you respin your series while leaving out the generic sizing? IOW, no x86 code generalisation. We can discuss the best strategy on sizing later (I haven't checked how much of this series still makes sense without the generic sizing).
It would mostly consist of the first three cleanup patches, followed by three patches that replace the
addressing_limitargument with flags.#define
SWIOTLB_VERBOSE(1 << 0) /* verbose initialization */
/* Initialize a pool for devices with limited DMA addressing. */
#defineSWIOTLB_INIT_ADDRESSING_LIMIT(1 << 1)
/* Initialize a pool that requires architecture remapping. */
#defineSWIOTLB_INIT_REMAP(1 << 2)
/* Initialize a pool for DMA to memory-encrypted host or guest memory. */
#defineSWIOTLB_INIT_MEM_ENCRYPT(1 << 3)
/* Initialize a pool for unaligned kmalloc bouncing. */
#defineSWIOTLB_INIT_KMALLOC(1 << 4)
/* Do not initialize a pool unless SWIOTLB is explicitly required. */
#defineSWIOTLB_INIT_DEFAULT_OFF(1 << 5)This results in the large change below. I'm not sure we want to do this for no real benefit other than making
swiotlb_should_init()slightly easier to follow.static bool
__initswiotlb_should_init(unsigned int flags){ if (swiotlb_force_disable) return false; if (swiotlb_force_bounce) return true; if (flags & (SWIOTLB_INIT_REMAP | SWIOTLB_INIT_MEM_ENCRYPT))) return true; /* Explicit requirements override an architecture's default opt-out. */ if (flags & SWIOTLB_INIT_DEFAULT_OFF) return false; return flags & (SWIOTLB_INIT_ADDRESSING_LIMIT | SWIOTLB_INIT_KMALLOC); }Quoted 1 line
[...]
Hi Aneesh,
I can reproduce the CCA regression discussed in this thread:
https://lore.kernel.org/all/[email protected]/#t
Quoted 7 lines
The guest runs out of SWIOTLB slots, causing disk I/O to fail and preventing the guest from booting.
I would like to test the fix on real CCA hardware. Could you please Cc me when you respin the series? I follow LKML, but I may still miss the posting by chance.
The conclusion was to either use CONFIG_SWIOTLB_DYNAMIC or swiotlb kernel command line option
-aneesh
Re: [PATCH v6 6/8] dma: swiotlb: Centralize memory-encryption pool sizing
Hi Aneesh,
On 11/01 09:47, Aneesh Kumar K.V wrote:
[...]
Quoted 9 lines
Quoted 9 lines
Hi Aneesh,
I can reproduce the CCA regression discussed in this thread:
https://lore.kernel.org/all/[email protected]/#tThe guest runs out of SWIOTLB slots, causing disk I/O to fail and preventing the guest from booting.
Quoted 7 lines
Quoted 4 lines
I would like to test the fix on real CCA hardware. Could you please Cc me when you respin the series? I follow LKML, but I may still miss the posting by chance.
The conclusion was to either use
CONFIG_SWIOTLB_DYNAMICor swiotlb kernel command line option
Thanks for the clarification.
After reading this whole thread, I agree that dynamic sizing would be appropriate.
However, currently some distributions do not enable CONFIG_SWIOTLB_DYNAMIC. Users of such distributions would therefore need to rebuild their kernels with the option enabled. This is not a practical solution for many users, particularly cloud users who use kernels provided by their distributions or cloud providers.
Specifying swiotlb= on the kernel command line is also not particularly user-friendly. It requires users or cloud providers to choose a fixed value in advance, without automatically taking into account properties of the VM, such as its memory size or whether it is a confidential guest.
I do not think the existing heuristic used for x86 CoCo guests is necessarily optimal, but a fixed swiotlb= value chosen by each user may be even less appropriate.
Overall, I would prefer the dynamic sizing approach. However, I believe the initial pool size still matters.
Also, as Catalin pointed out earlier in the following message:
https://lore.kernel.org/all/[email protected]/
the arm64 adjustment also reduces the target size used for dynamic pool allocation, since both the initial pool and dynamic allocation currently use default_nslabs.
I am testing the patch below to decouple the initial pool size from the dynamic allocation target. It adds swiotlb_adjust_initial_size() for callers that only want to reduce the initial allocation, while keeping the existing swiotlb_adjust_size() semantics for callers that want to adjust both sizes.
Thanks,
Kohei
--->8---
arch/arm64/mm/init.c +1 -1
@@ -349,7 +349,7 @@ void __init arch_mm_preinit(void)unsigned long size =DIV_ROUND_UP (memblock_phys_mem_size (),1024 ); -swiotlb_adjust_size (min (swiotlb_default_pool_size (), size)); +swiotlb_adjust_initial_size (min (swiotlb_default_pool_size (), size)); }swiotlb_init (true, flags);
arch/riscv/mm/init.c +1 -1
@@ -189,7 +189,7 @@ void __init arch_mm_preinit(void)*/ unsigned long size =DIV_ROUND_UP (memblock_phys_mem_size (),1024 ); -swiotlb_adjust_size (min (swiotlb_default_pool_size (), size)); +swiotlb_adjust_initial_size (min (swiotlb_default_pool_size (), size)); swiotlb = true; swiotlb_flags |=SWIOTLB_ANY ; }
include/linux/swiotlb.h +5 -0
@@ -190,6 +190,7 @@ size_t swiotlb_max_mapping_size(struct device *dev);bool is_swiotlb_allocated (void );bool is_swiotlb_active (struct device *dev);void __init swiotlb_adjust_size (unsigned long size); +void __init swiotlb_adjust_initial_size (unsigned long size);phys_addr_t default_swiotlb_base (void );phys_addr_t default_swiotlb_limit (void );#else
@@ -232,6 +233,10 @@ static inline void swiotlb_adjust_size(unsigned long size) { } +static inline void swiotlb_adjust_initial_size (unsigned long size) +{ +} +static inline phys_addr_t default_swiotlb_base (void ) {return 0 ;
kernel/dma/swiotlb.c +13 -2
@@ -99,6 +99,7 @@ static struct io_tlb_mem io_tlb_default_mem;#endif /* CONFIG_SWIOTLB_DYNAMIC */ static unsigned long default_nslabs =IO_TLB_DEFAULT_SIZE >>IO_TLB_SHIFT ; +static unsigned long dynamic_nslabs =IO_TLB_DEFAULT_SIZE >>IO_TLB_SHIFT ;static unsigned long default_nareas;static bool swiotlb_cmdline_size_set__initdata ;
@@ -152,6 +153,8 @@ static void swiotlb_adjust_nareas(unsigned int nareas) nareas =roundup_pow_of_two (nareas); default_nareas = nareas; + dynamic_nslabs = +swiotlb_calc_nslabs (dynamic_nslabs <<IO_TLB_SHIFT , nareas);pr_info ("area num %d.\n" , nareas); nslabs =swiotlb_calc_nslabs (default_nslabs <<IO_TLB_SHIFT , nareas);
@@ -254,6 +257,7 @@ setup_io_tlb_npages(char *str)/* avoid tail segment of size < IO_TLB_SEGSIZE */ default_nslabs =ALIGN (simple_strtoul (str, &str,0 ),IO_TLB_SEGSIZE ); + dynamic_nslabs = default_nslabs; swiotlb_cmdline_size_set = true; }if (*str ==',' )
@@ -290,7 +294,7 @@ unsigned long swiotlb_default_pool_size(void)return default_nslabs <<IO_TLB_SHIFT ; } -void __init swiotlb_adjust_size (unsigned long size) +void __init swiotlb_adjust_initial_size (unsigned long size) {/* * If swiotlb parameter has not been specified, give a chance to
@@ -305,6 +309,12 @@ void __init swiotlb_adjust_size(unsigned long size)pr_info ("SWIOTLB bounce buffer size adjusted to %luMB" , size >>20 ); } +void __init swiotlb_adjust_size (unsigned long size) +{ +swiotlb_adjust_initial_size (size); + dynamic_nslabs = default_nslabs; +} +void swiotlb_print_info (void ) {struct io_tlb_pool *mem = &io_tlb_default_mem.defpool;
@@ -507,6 +517,7 @@ void __init swiotlb_init_remap(bool addressing_limit, unsigned int flags,pr_info ("SWIOTLB bounce buffer size adjusted %lu -> %lu slabs" , default_nslabs, nslabs); default_nslabs = nslabs; + dynamic_nslabs = default_nslabs; } alloc_size =PAGE_ALIGN (array_size (sizeof (*mem->slots), nslabs));
@@ -889,7 +900,7 @@ static void swiotlb_dyn_alloc(struct work_struct *work) container_of(work, struct io_tlb_mem, dyn_alloc);struct io_tlb_pool *pool; - pool =swiotlb_alloc_pool (NULL , mem,IO_TLB_MIN_SLABS , default_nslabs, + pool =swiotlb_alloc_pool (NULL , mem,IO_TLB_MIN_SLABS , dynamic_nslabs, default_nareas, mem->phys_limit,GFP_KERNEL );if (!pool) {pr_warn_ratelimited ("Failed to allocate new pool" );
Marek Szyprowski
maintainerRe: [PATCH v6 6/8] dma: swiotlb: Centralize memory-encryption pool sizing
In reply to Will DeaconQuoted 14 lines · Will Deacon
Quoted 13 lines · Catalin Marinas
Quoted 12 lines · Will Deacon
kernel/dma/swiotlb.c swiotlb_select_pool_policy(unsigned int flags) · line 521
Quoted 8 lines · Aneesh Kumar K.V (Arm)
kernel/dma/swiotlb.c +2
-1@@ -496,7 +516,8 @@ swiotlb_select_pool_policy(unsigned int flags)if (swiotlb_force_disable)return SWIOTLB_POOL_NONE ; -if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT )) +if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT ) && + !restricted_dma_pool_present)return SWIOTLB_POOL_CC_GUEST ;I think this check on the restricted DMA pool is too general -- the pool could be tied to a specific DMA-capable peripheral and so treating its presence as a global property isn't right.
Quoted 8 lines
Quoted 4 lines
I agree it's a hack but that was the simplest way to avoid the pVMs getting a bounce buffer after this patch. More than happy to leave it out and reduce the buffer on cmdline or we come up with some better heuristics.
Hrm, that does mean that reverting just this part will regress pVMs because they'll suddenly be allocating a tonne more memory for an entirely unused swiotlb buffer. So I think I'd prefer to drop the entire series until this has been worked out properly.
I've dropped the entire series from dma-mapping-for-next. Aneesh, please respin it again and move the pKVM/restricted_dma_pool related code into the separate patch.
Best regards
Signature · 2 lines
Marek Szyprowski, PhD Samsung R&D Institute Poland
Re: [PATCH v6 6/8] dma: swiotlb: Centralize memory-encryption pool sizing
Quoted 19 lines · Marek Szyprowski
Quoted 18 lines · Will Deacon
Quoted 17 lines · Catalin Marinas
Quoted 5 lines · Will Deacon
Quoted 4 lines · Aneesh Kumar K.V (Arm)
kernel/dma/swiotlb.c +0
-0@@ -496,7 +516,8 @@ swiotlb_select_pool_policy(unsigned int flags)if (swiotlb_force_disable)return SWIOTLB_POOL_NONE ;Quoted 7 lines
kernel/dma/swiotlb.c swiotlb_select_pool_policy(unsigned int flags) · line 521
Quoted 4 lines
kernel/dma/swiotlb.c +2
-1-if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT )) +if (cc_platform_has (CC_ATTR_GUEST_MEM_ENCRYPT ) && + !restricted_dma_pool_present)return SWIOTLB_POOL_CC_GUEST ;I think this check on the restricted DMA pool is too general -- the pool could be tied to a specific DMA-capable peripheral and so treating its presence as a global property isn't right.
I agree it's a hack but that was the simplest way to avoid the pVMs getting a bounce buffer after this patch. More than happy to leave it out and reduce the buffer on cmdline or we come up with some better heuristics.
Quoted 8 lines
Quoted 4 lines
Hrm, that does mean that reverting just this part will regress pVMs because they'll suddenly be allocating a tonne more memory for an entirely unused swiotlb buffer. So I think I'd prefer to drop the entire series until this has been worked out properly.
I've dropped the entire series from dma-mapping-for-next. Aneesh, please respin it again and move the pKVM/restricted_dma_pool related code into the separate patch.
Once we agree on the correct way to detect the pKVM use case, I will resend the series.
-aneesh
Re: [PATCH v6 6/8] dma: swiotlb: Centralize memory-encryption pool sizing
In reply to Catalin MarinasQuoted 2 lines · Catalin Marinas
Quoted 1 line · Will Deacon
On Thu, Sep 24, 2026 at 11:37:54AM +0530, Aneesh Kumar K.V (Arm) wrote:
[ ... 22 lines skipped ... ]
Quoted 4 lines
That said, such heuristics should have been a separate patch to make it easier to review/drop.
I kept them in a single patch to avoid breaking bisection. Otherwise, an intermediate commit would allocate a swiotlb bounce buffer for pKVM.
-aneesh
PATCH v6 7/8 dma: swiotlb: Add an overridable architecture pool opt-out
In reply to Aneesh Kumar K.V (Arm)On x86, iommu=off historically prevented SWIOTLB initialization by not setting SWIOTLB_INIT_ADDRESSING_LIMIT. This overloads that flag: it controls both whether a pool is selected and where the pool is allocated. If another requirement, swiotlb=force selects a pool independently, omitting SWIOTLB_INIT_ADDRESSING_LIMIT may place it above the addressable range of devices which need bounce buffering.
Add SWIOTLB_INIT_DEFAULT_OFF to let an architecture opt out of normal pool initialization without discarding the pool placement constraints.
Unlike swiotlb_force_disable, which is set by swiotlb=noforce and unconditionally prevents pool initialization, the new flag is an architecture default. Explicit requirements such as memory encryption, architecture remapping, or swiotlb=force take precedence over it.
iommu=soft retains SWIOTLB_INIT_ADDRESSING_LIMIT because it requests software bounce buffering for devices whose DMA masks cannot address all system memory. Such devices must be able to reach the bounce pool.
Clear both flags for Xen because Xen explicitly requires a remapped swiotlb pool and may allocate it anywhere in directly mapped memory.
With no override, iommu=off disables both hardware IOMMU translation and swiotlb bouncing. Direct DMA remains available; mappings outside a device's addressable range fail instead of being bounced.
--- arch/x86/kernel/pci-dma.c | 11 ++++++++--- include/linux/swiotlb.h | 2 ++ kernel/dma/swiotlb.c | 10 ++++++++-- 3 files changed, 18 insertions(+), 5 deletions(-)
arch/x86/kernel/pci-dma.c +8 -3
@@ -44,9 +44,13 @@ static unsigned int x86_swiotlb_flags;static void __init pci_swiotlb_detect (void ) {/* don't initialize swiotlb if iommu=off (no_iommu=1) */ -if (!no_iommu && max_possible_pfn >MAX_DMA32_PFN ) { - x86_swiotlb_enable = true; +if (no_iommu) + x86_swiotlb_flags |=SWIOTLB_INIT_DEFAULT_OFF ; + +if (max_possible_pfn >MAX_DMA32_PFN ) { x86_swiotlb_flags |=SWIOTLB_INIT_ADDRESSING_LIMIT ; +if (!no_iommu) + x86_swiotlb_enable = true; }/*
@@ -84,7 +88,8 @@ static void __init pci_xen_swiotlb_init(void)return ; x86_swiotlb_enable = true;/* Xen can use a SWIOTLB pool anywhere in directly mapped memory. */ - x86_swiotlb_flags &= ~SWIOTLB_INIT_ADDRESSING_LIMIT ; + x86_swiotlb_flags &= ~(SWIOTLB_INIT_ADDRESSING_LIMIT | +SWIOTLB_INIT_DEFAULT_OFF ); x86_swiotlb_flags |=SWIOTLB_INIT_REMAP |SWIOTLB_ANY ;swiotlb_init_remap (x86_swiotlb_flags, xen_swiotlb_fixup); dma_ops = &xen_swiotlb_dma_ops;
include/linux/swiotlb.h +2 -0
@@ -20,6 +20,8 @@ struct scatterlist;#define SWIOTLB_INIT_ADDRESSING_LIMIT (1 << 2)/* Initialize a default-sized pool that requires architecture remapping. */ #define SWIOTLB_INIT_REMAP (1 << 3) +/* Do not initialize a pool unless SWIOTLB is explicitly required. */ +#define SWIOTLB_INIT_DEFAULT_OFF (1 << 4)/* * Maximum allowable number of contiguous slabs to map,
kernel/dma/swiotlb.c +8 -2
@@ -526,10 +526,16 @@ swiotlb_select_pool_policy(unsigned int flags)if (flags &SWIOTLB_INIT_REMAP )return SWIOTLB_POOL_DEFAULT ; -if (flags &SWIOTLB_INIT_ADDRESSING_LIMIT ) +if (swiotlb_force_bounce)return SWIOTLB_POOL_DEFAULT ; -if (swiotlb_force_bounce) +/* +* Explicit requirements above override an architecture's default opt-out. +*/ +if (flags &SWIOTLB_INIT_DEFAULT_OFF ) +return SWIOTLB_POOL_NONE ; + +if (flags &SWIOTLB_INIT_ADDRESSING_LIMIT )return SWIOTLB_POOL_DEFAULT ;if (swiotlb_kmalloc_needs_bounce ())
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH v6 7/8] dma: swiotlb: Add an overridable architecture pool opt-out
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 15 lines
On x86, iommu=off historically prevented SWIOTLB initialization by not setting
SWIOTLB_INIT_ADDRESSING_LIMIT. This overloads that flag: it controls both whether a pool is selected and where the pool is allocated. If another requirement, swiotlb=force selects a pool independently, omittingSWIOTLB_INIT_ADDRESSING_LIMITmay place it above the addressable range of devices which need bounce buffering.Add
SWIOTLB_INIT_DEFAULT_OFFto let an architecture opt out of normal pool initialization without discarding the pool placement constraints.Unlike
swiotlb_force_disable, which is set by swiotlb=noforce and unconditionally prevents pool initialization, the new flag is an architecture default. Explicit requirements such as memory encryption, architecture remapping, or swiotlb=force take precedence over it.
Quoted 6 lines
[ ... ]Cc "H. Peter Anvin" <[email protected]>Cc Marek Szyprowski <[email protected]>Cc Robin Murphy <[email protected]>Signed-off-by Aneesh Kumar K.V (Arm) <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=7
PATCH v6 8/8 dma: swiotlb: Remove SWIOTLB_ANY
In reply to Aneesh Kumar K.V (Arm)swiotlb pools are currently allocated below the architecture's low address limit by default. SWIOTLB_ANY overrides this and permits allocation anywhere in directly mapped memory.
SWIOTLB_INIT_ADDRESSING_LIMIT now explicitly identifies callers which need a pool that is reachable by devices with limited DMA addressing. Use it as the placement constraint and remove SWIOTLB_ANY.
This changes the default behavior for callers which do not set either flag. Previously, omitting SWIOTLB_ANY placed the default pool below the architecture's low address limit and also constrained dynamically allocated pools to the same range. After this change, omitting SWIOTLB_INIT_ADDRESSING_LIMIT permits both static and dynamic pools to use any directly mapped memory.
--- Documentation/core-api/swiotlb.rst | 8 ++++---- arch/powerpc/mm/mem.c | 6 ++++-- arch/riscv/mm/init.c | 16 ---------------- arch/s390/mm/init.c | 2 +- arch/x86/kernel/pci-dma.c | 2 +- include/linux/swiotlb.h | 7 +++---- kernel/dma/swiotlb.c | 17 ++++++----------- 7 files changed, 19 insertions(+), 39 deletions(-)
Documentation/core-api/swiotlb.rst +4 -4
@@ -148,10 +148,10 @@ may also be adjusted due to other conditions, such as running in a CoCo VM, as described above. If CONFIG_SWIOTLB_DYNAMIC is enabled, additional pools may be allocated later in the life of the system. Each pool must be a contiguous range of physical -memory. The default pool is allocated below the 4 GiB physical address line so -it works for devices that can only address 32-bits of physical memory (unless -architecture-specific code provides the SWIOTLB_ANY flag). In a CoCo VM, the -pool memory must be decrypted before swiotlb is used. +memory. The default pool is allocated below the architecture's low address +limit when it is needed for devices with limited DMA addressing. Otherwise, +it may be allocated anywhere in directly mapped memory. In a CoCo VM, the pool +memory must be decrypted before swiotlb is used. Each pool is divided into "slots" of size IO_TLB_SIZE, which is 2 KiB with current definitions. IO_TLB_SEGSIZE contiguous slots (128 slots) constitute
arch/powerpc/mm/mem.c +4 -2
@@ -295,9 +295,11 @@ void __init arch_mm_preinit(void)/* * 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. +* even if dma_capable() says otherwise. The hypervisor has +* no addressing limitation, so the buffer may be allocated +* anywhere. */ - ppc_swiotlb_flags |=SWIOTLB_ANY ; + ppc_swiotlb_flags &= ~SWIOTLB_INIT_ADDRESSING_LIMIT ; }/*
arch/riscv/mm/init.c +0 -16
@@ -165,27 +165,11 @@ static void print_vm_layout(void) { }void __init arch_mm_preinit (void ) { -bool swiotlb = max_pfn >PFN_DOWN (dma32_phys_limit) && -memblock_start_of_DRAM () < dma32_phys_limit;unsigned int swiotlb_flags =SWIOTLB_VERBOSE ;#ifdef CONFIG_FLATMEM BUG_ON (!mem_map);#endif /* CONFIG_FLATMEM */ -if (IS_ENABLED (CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC ) && !swiotlb && - dma_cache_alignment !=1 ) { -/* -* No 32-bit DMA bouncing needed (either all DRAM is within -* the 32-bit limit, or it all starts above it), but -* kmalloc() buffers whose sizes are not cache-line-aligned -* still require bouncing for non-coherent DMA. Use -* SWIOTLB_ANY so that the buffer can be allocated from high -* memory when DRAM starts above dma32_phys_limit. Allocate -* ~1 MB per 1 GB of RAM. -*/ - swiotlb_flags |=SWIOTLB_ANY ; - } -if ((max_pfn >PFN_DOWN (dma32_phys_limit)) && (memblock_start_of_DRAM () < dma32_phys_limit)) swiotlb_flags |=SWIOTLB_INIT_ADDRESSING_LIMIT ;
arch/s390/mm/init.c +1 -1
@@ -166,7 +166,7 @@ static void __init pv_init(void)virtio_set_mem_acc_cb (virtio_require_restricted_mem_acc);/* make sure bounce buffers are shared */ -swiotlb_init (SWIOTLB_VERBOSE |SWIOTLB_ANY ); +swiotlb_init (SWIOTLB_VERBOSE );swiotlb_update_mem_attributes (); }
arch/x86/kernel/pci-dma.c +1 -1
@@ -90,7 +90,7 @@ static void __init pci_xen_swiotlb_init(void)/* Xen can use a SWIOTLB pool anywhere in directly mapped memory. */ x86_swiotlb_flags &= ~(SWIOTLB_INIT_ADDRESSING_LIMIT |SWIOTLB_INIT_DEFAULT_OFF ); - x86_swiotlb_flags |=SWIOTLB_INIT_REMAP |SWIOTLB_ANY ; + x86_swiotlb_flags |=SWIOTLB_INIT_REMAP ;swiotlb_init_remap (x86_swiotlb_flags, xen_swiotlb_fixup); dma_ops = &xen_swiotlb_dma_ops;if (IS_ENABLED (CONFIG_PCI ))
include/linux/swiotlb.h +3 -4
@@ -15,13 +15,12 @@ struct page;struct scatterlist ;#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) +#define SWIOTLB_INIT_ADDRESSING_LIMIT (1 << 1)/* Initialize a default-sized pool that requires architecture remapping. */ -#define SWIOTLB_INIT_REMAP (1 << 3) +#define SWIOTLB_INIT_REMAP (1 << 2)/* Do not initialize a pool unless SWIOTLB is explicitly required. */ -#define SWIOTLB_INIT_DEFAULT_OFF (1 << 4) +#define SWIOTLB_INIT_DEFAULT_OFF (1 << 3)/* * Maximum allowable number of contiguous slabs to map,
kernel/dma/swiotlb.c +6 -11
@@ -437,15 +437,10 @@ static void __init *swiotlb_memblock_alloc(unsigned long nslabs,size_t bytes =PAGE_ALIGN (nslabs <<IO_TLB_SHIFT );void *tlb; -/* -* By default allocate the bounce buffer memory from low memory, but -* allow to pick a location everywhere for hypervisors with guest -* memory encryption. -*/ -if (flags &SWIOTLB_ANY ) - tlb =memblock_alloc (bytes,PAGE_SIZE ); -else +if (flags &SWIOTLB_INIT_ADDRESSING_LIMIT ) tlb =memblock_alloc_low (bytes,PAGE_SIZE ); +else + tlb =memblock_alloc (bytes,PAGE_SIZE );if (!tlb) { pr_warn("%s: Failed to allocate %zu bytes tlb structure\n",
@@ -567,10 +562,10 @@ void __init swiotlb_init_remap(unsigned int flags,#ifdef CONFIG_SWIOTLB_DYNAMIC if (!remap) io_tlb_default_mem.can_grow = true; -if (flags &SWIOTLB_ANY ) - io_tlb_default_mem.phys_limit =virt_to_phys (high_memory -1 ); -else +if (flags &SWIOTLB_INIT_ADDRESSING_LIMIT ) io_tlb_default_mem.phys_limit =ARCH_LOW_ADDRESS_LIMIT ; +else + io_tlb_default_mem.phys_limit =virt_to_phys (high_memory -1 );#endif /* if we have host or guest memory encryption */
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH v6 8/8] dma: swiotlb: Remove SWIOTLB_ANY
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 15 lines
swiotlb pools are currently allocated below the architecture's low address limit by default.
SWIOTLB_ANYoverrides this and permits allocation anywhere in directly mapped memory.
SWIOTLB_INIT_ADDRESSING_LIMITnow explicitly identifies callers which need a pool that is reachable by devices with limited DMA addressing. Use it as the placement constraint and removeSWIOTLB_ANY.This changes the default behavior for callers which do not set either flag. Previously, omitting
SWIOTLB_ANYplaced the default pool below the architecture's low address limit and also constrained dynamically allocated pools to the same range. After this change, omittingSWIOTLB_INIT_ADDRESSING_LIMITpermits both static and dynamic pools to use any directly mapped memory.
Quoted 6 lines
[ ... ]Cc "H. Peter Anvin" <[email protected]>Cc Marek Szyprowski <[email protected]>Cc Robin Murphy <[email protected]>Signed-off-by Aneesh Kumar K.V (Arm) <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=8
Marek Szyprowski
maintainerQuoted 18 lines · Aneesh Kumar K.V (Arm)
This series centralizes swiotlb default-pool selection and sizing, and simplifies the initialization flags used to describe pool placement.
The first patch replaces the addressing-limit argument with initialization flags and introduces explicit policies for the different reasons a default pool may be needed. Architectures now report DMA addressing constraints with
SWIOTLB_INIT_ADDRESSING_LIMIT, while the core selects the corresponding pool policy.The second patch moves the reduced sizing used when the pool is needed only for unaligned kmalloc bouncing from arm64 and RISC-V into the swiotlb core.
The third patch centralizes swiotlb sizing for memory-encrypted systems. It moves the existing x86 guest-sizing policy into the core. Host memory encryption retains the normal pool size, and a shared default pool is not selected solely for guest memory encryption when a restricted DMA pool is present.
Quoted 6 lines
The fourth patch removes
SWIOTLB_ANY. Pool placement is derived directly fromSWIOTLB_INIT_ADDRESSING_LIMIT: pools required for limited DMA addressing are allocated below the architecture's low address limit, while other pools may be allocated anywhere in directly mapped memory. Xen continues to request a pool explicitly withSWIOTLB_INIT_REMAPwithout imposing a low-address constraint.
I would like to give this patchset some tests in linux-next and merge this to v7.4-rc1, as this is important continuation of the code already merged to v7.3.
Any chance to get some more acks from arch maintainers (especially x86)? Unfortunately I had to reduce the CC list due to my smtp limits...
Quoted 14 lines
...
Documentation/core-api/swiotlb.rst | 8 +- arch/arm/mm/init.c | 6 +- arch/arm/xen/mm.c | 2 +- arch/arm64/mm/init.c | 14 +- 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 | 17 ++- arch/powerpc/platforms/pseries/svm.c | 10 -- arch/powerpc/sysdev/fsl_pci.c | 1 +
Quoted 8 lines
arch/riscv/mm/init.c | 24 +--- arch/s390/mm/init.c | 2 +- arch/x86/include/asm/crash_reserve.h | 4 +- arch/x86/kernel/pci-dma.c | 23 +++- arch/x86/mm/mem_encrypt.c | 24 ---- include/linux/swiotlb.h | 17 ++- kernel/dma/swiotlb.c | 193 +++++++++++++++++++-------- 19 files changed, 210 insertions(+), 147 deletions(-)
Best regards
Signature · 2 lines
Marek Szyprowski, PhD Samsung R&D Institute Poland
Quoted 18 lines · Aneesh Kumar K.V (Arm)
This series centralizes swiotlb default-pool selection and sizing, and simplifies the initialization flags used to describe pool placement.
The first patch replaces the addressing-limit argument with initialization flags and introduces explicit policies for the different reasons a default pool may be needed. Architectures now report DMA addressing constraints with
SWIOTLB_INIT_ADDRESSING_LIMIT, while the core selects the corresponding pool policy.The second patch moves the reduced sizing used when the pool is needed only for unaligned kmalloc bouncing from arm64 and RISC-V into the swiotlb core.
The third patch centralizes swiotlb sizing for memory-encrypted systems. It moves the existing x86 guest-sizing policy into the core. Host memory encryption retains the normal pool size, and a shared default pool is not selected solely for guest memory encryption when a restricted DMA pool is present.
Quoted 6 lines
The fourth patch removes
SWIOTLB_ANY. Pool placement is derived directly fromSWIOTLB_INIT_ADDRESSING_LIMIT: pools required for limited DMA addressing are allocated below the architecture's low address limit, while other pools may be allocated anywhere in directly mapped memory. Xen continues to request a pool explicitly withSWIOTLB_INIT_REMAPwithout imposing a low-address constraint.
I will give this patchset a chance in linux-next. If one feels that it still needs to be improved or sees any other reason why it shouldn't be merged, let me know asap.
Applied to dma-mapping-for-next.
Best regards
Signature · 2 lines
Marek Szyprowski, PhD Samsung R&D Institute Poland
Will Deacon
maintainerQuoted 27 lines · Marek Szyprowski
Quoted 18 lines · Aneesh Kumar K.V (Arm)
This series centralizes swiotlb default-pool selection and sizing, and simplifies the initialization flags used to describe pool placement.
The first patch replaces the addressing-limit argument with initialization flags and introduces explicit policies for the different reasons a default pool may be needed. Architectures now report DMA addressing constraints with
SWIOTLB_INIT_ADDRESSING_LIMIT, while the core selects the corresponding pool policy.The second patch moves the reduced sizing used when the pool is needed only for unaligned kmalloc bouncing from arm64 and RISC-V into the swiotlb core.
The third patch centralizes swiotlb sizing for memory-encrypted systems. It moves the existing x86 guest-sizing policy into the core. Host memory encryption retains the normal pool size, and a shared default pool is not selected solely for guest memory encryption when a restricted DMA pool is present.
Quoted 6 lines
The fourth patch removes
SWIOTLB_ANY. Pool placement is derived directly fromSWIOTLB_INIT_ADDRESSING_LIMIT: pools required for limited DMA addressing are allocated below the architecture's low address limit, while other pools may be allocated anywhere in directly mapped memory. Xen continues to request a pool explicitly withSWIOTLB_INIT_REMAPwithout imposing a low-address constraint.
Quoted 3 lines
I will give this patchset a chance in linux-next. If one feels that it still needs to be improved or sees any other reason why it shouldn't be merged, let me know asap.
I think the restricted-dma pool heuristic is horribly naive, so please drop that part for now.
Will