Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Documentation/core-api/swiotlb.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 5 additions & 1 deletion arch/arm/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 3 additions & 11 deletions arch/arm64/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,18 +340,10 @@ 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_size_or_default(), size));
}
if (max_pfn > PFN_DOWN(arm64_dma_phys_limit))
flags |= SWIOTLB_INIT_ADDRESSING_LIMIT;

swiotlb_init(true, flags);
swiotlb_init(flags);

/*
* Check boundaries twice: Some fundamental inconsistencies can be
Expand Down
2 changes: 1 addition & 1 deletion arch/loongarch/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down
2 changes: 1 addition & 1 deletion arch/mips/cavium-octeon/dma-octeon.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
2 changes: 1 addition & 1 deletion arch/mips/loongson64/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
2 changes: 1 addition & 1 deletion arch/mips/sibyte/common/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@

void __init plat_swiotlb_setup(void)
{
swiotlb_init(true, SWIOTLB_VERBOSE);
swiotlb_init(SWIOTLB_VERBOSE | SWIOTLB_INIT_ADDRESSING_LIMIT);
}
4 changes: 3 additions & 1 deletion arch/powerpc/kernel/dma-swiotlb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
17 changes: 16 additions & 1 deletion arch/powerpc/mm/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,21 @@ 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. The hypervisor has
* no addressing limitation, so the buffer may be allocated
* anywhere.
*/
ppc_swiotlb_flags &= ~SWIOTLB_INIT_ADDRESSING_LIMIT;
}

/*
* Some platforms (e.g. 85xx) limit DMA-able memory way below
* 4G. We force memblock to bottom-up mode to ensure that the
Expand All @@ -295,7 +310,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();
Expand Down
10 changes: 0 additions & 10 deletions arch/powerpc/platforms/pseries/svm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/sysdev/fsl_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
24 changes: 4 additions & 20 deletions arch/riscv/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,32 +165,16 @@ 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.
*/
unsigned long size =
DIV_ROUND_UP(memblock_phys_mem_size(), 1024);
swiotlb_adjust_size(min(swiotlb_size_or_default(), size));
swiotlb = true;
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;

swiotlb_init(swiotlb, swiotlb_flags);
swiotlb_init(swiotlb_flags);

print_vm_layout();
}
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_update_mem_attributes();
}

Expand Down
4 changes: 2 additions & 2 deletions arch/x86/include/asm/crash_reserve.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
unsigned long __init swiotlb_adjusted_size(void);

#ifdef CONFIG_X86_32
# define CRASH_ADDR_LOW_MAX SZ_512M
Expand All @@ -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_adjusted_size() + (8UL << 20), 256UL << 20);
#else
return 0;
#endif
Expand Down
2 changes: 2 additions & 0 deletions arch/x86/include/asm/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ extern bool amd_iommu_snp_en;

#ifdef CONFIG_SWIOTLB
extern bool x86_swiotlb_enable;
extern unsigned int x86_swiotlb_flags;
#else
#define x86_swiotlb_enable false
#define x86_swiotlb_flags 0
#endif

/* 10 seconds */
Expand Down
1 change: 1 addition & 0 deletions arch/x86/kernel/amd_gart_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,7 @@ int __init gart_iommu_init(void)
dma_ops = &gart_dma_ops;
x86_platform.iommu_shutdown = gart_iommu_shutdown;
x86_swiotlb_enable = false;
x86_swiotlb_flags = 0;

return 0;
}
Expand Down
19 changes: 12 additions & 7 deletions arch/x86/kernel/pci-dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ int iommu_detected __read_mostly = 0;

#ifdef CONFIG_SWIOTLB
bool x86_swiotlb_enable;
static unsigned int x86_swiotlb_flags;
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
Expand All @@ -66,7 +68,6 @@ static void __init pci_swiotlb_detect(void)
static inline void __init pci_swiotlb_detect(void)
{
}
#define x86_swiotlb_flags 0
#endif /* CONFIG_SWIOTLB */

#ifdef CONFIG_SWIOTLB_XEN
Expand All @@ -81,8 +82,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_init_remap(x86_swiotlb_flags, xen_swiotlb_fixup);
dma_ops = &xen_swiotlb_dma_ops;
if (IS_ENABLED(CONFIG_PCI))
pci_request_acs();
Expand All @@ -103,7 +106,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)
Expand Down Expand Up @@ -149,8 +152,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);
Expand Down
24 changes: 0 additions & 24 deletions arch/x86/mm/mem_encrypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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().
Expand All @@ -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);
}
19 changes: 14 additions & 5 deletions include/linux/swiotlb.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ 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 << 1)
/* Initialize a default-sized pool that requires architecture remapping. */
#define SWIOTLB_INIT_REMAP (1 << 2)

/*
* Maximum allowable number of contiguous slabs to map,
Expand All @@ -39,8 +42,8 @@ struct scatterlist;
#endif

unsigned long swiotlb_size_or_default(void);
void __init swiotlb_init_remap(bool addressing_limit, unsigned int flags,
int (*remap)(void *tlb, unsigned long nslabs));
void __init swiotlb_init_remap(unsigned int flags,
int (*remap)(void *tlb, unsigned long nslabs));
int swiotlb_init_late(size_t size, gfp_t gfp_mask,
int (*remap)(void *tlb, unsigned long nslabs));
extern void __init swiotlb_update_mem_attributes(void);
Expand Down Expand Up @@ -183,17 +186,18 @@ 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);
bool is_swiotlb_allocated(void);
bool is_swiotlb_active(struct device *dev);
unsigned long __init swiotlb_adjusted_size(void);
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)
{
}

Expand Down Expand Up @@ -228,6 +232,11 @@ static inline bool is_swiotlb_active(struct device *dev)
return false;
}

static inline unsigned long __init swiotlb_adjusted_size(void)
{
return 0;
}

static inline void swiotlb_adjust_size(unsigned long size)
{
}
Expand Down
Loading