diff options
| author | Mark Brown <broonie@kernel.org> | 2026-08-21 13:55:39 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-08-21 13:55:39 +0100 |
| commit | 6def83e89a6f662cd95776a19db4770b5fcb9a94 (patch) | |
| tree | e81a7e18e54c993a0595a0f3a910d81f3a6128cd /include | |
| parent | a4a7cdb265854960429cda79b53eb350f32ed17d (diff) | |
| parent | 42311aa29e20fdc0157746143c108b08b268f5cb (diff) | |
| download | linux-next-6def83e89a6f662cd95776a19db4770b5fcb9a94.tar.gz linux-next-6def83e89a6f662cd95776a19db4770b5fcb9a94.zip | |
Merge branch 'dma-mapping-for-next' of https://git.kernel.org/pub/scm/linux/kernel/git/mszyprowski/linux.git
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/dma-direct.h | 20 | ||||
| -rw-r--r-- | include/linux/dma-map-ops.h | 3 | ||||
| -rw-r--r-- | include/linux/dma-mapping.h | 8 | ||||
| -rw-r--r-- | include/linux/swiotlb.h | 41 | ||||
| -rw-r--r-- | include/trace/events/dma.h | 3 |
5 files changed, 59 insertions, 16 deletions
diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h index c249912456f9..daa31a1adf7b 100644 --- a/include/linux/dma-direct.h +++ b/include/linux/dma-direct.h @@ -77,6 +77,10 @@ static inline dma_addr_t dma_range_map_max(const struct bus_dma_region *map) #ifndef phys_to_dma_unencrypted #define phys_to_dma_unencrypted phys_to_dma #endif + +#ifndef phys_to_dma_encrypted +#define phys_to_dma_encrypted phys_to_dma +#endif #else static inline dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr) { @@ -90,6 +94,12 @@ static inline dma_addr_t phys_to_dma_unencrypted(struct device *dev, { return dma_addr_unencrypted(__phys_to_dma(dev, paddr)); } + +static inline dma_addr_t phys_to_dma_encrypted(struct device *dev, + phys_addr_t paddr) +{ + return dma_addr_encrypted(__phys_to_dma(dev, paddr)); +} /* * If memory encryption is supported, phys_to_dma will set the memory encryption * bit in the DMA address, and dma_to_phys will clear it. @@ -125,12 +135,20 @@ static inline bool force_dma_unencrypted(struct device *dev) #endif /* CONFIG_ARCH_HAS_FORCE_DMA_UNENCRYPTED */ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size, - bool is_ram) + bool is_ram, unsigned long attrs) { dma_addr_t end = addr + size - 1; if (addr == DMA_MAPPING_ERROR) return false; + /* + * The DMA address was derived from encrypted RAM, but this device + * requires unencrypted DMA addresses. Treat it as not DMA-capable + * so the caller can fall back to a suitable SWIOTLB pool. + */ + if (!(attrs & DMA_ATTR_CC_SHARED) && force_dma_unencrypted(dev)) + return false; + if (is_ram && !IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) && min(addr, end) < phys_to_dma(dev, PFN_PHYS(min_low_pfn))) return false; diff --git a/include/linux/dma-map-ops.h b/include/linux/dma-map-ops.h index bcb5b5428aea..8fae2b7deb20 100644 --- a/include/linux/dma-map-ops.h +++ b/include/linux/dma-map-ops.h @@ -212,9 +212,10 @@ void *dma_common_pages_remap(struct page **pages, size_t size, pgprot_t prot, void dma_common_free_remap(void *cpu_addr, size_t size); struct page *dma_alloc_from_pool(struct device *dev, size_t size, - void **cpu_addr, gfp_t flags, + void **cpu_addr, gfp_t flags, unsigned long attrs, bool (*phys_addr_ok)(struct device *, phys_addr_t, size_t)); bool dma_free_from_pool(struct device *dev, void *start, size_t size); +bool dma_free_from_pool_page(struct device *dev, struct page *page, size_t size); int dma_direct_set_offset(struct device *dev, phys_addr_t cpu_start, dma_addr_t dma_start, u64 size); diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index cc0823a99cfd..a3e880649fa4 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -104,6 +104,14 @@ #define DMA_ATTR_CC_SHARED (1UL << 13) /* + * __DMA_ATTR_ALLOC_CC_SHARED: Internal DMA-mapping attribute used by + * allocation paths that create shared (decrypted) backing pages for + * confidential computing guests. Drivers must not pass this attribute to + * dma_alloc_attrs(). + */ +#define __DMA_ATTR_ALLOC_CC_SHARED (1UL << 14) + +/* * A dma_addr_t can hold any valid DMA or bus address for the platform. It can * be given to a device to use as a DMA source or target. It is specific to a * given device and there may be a translation between the CPU physical address diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h index 3dae0f592063..2a421241b980 100644 --- a/include/linux/swiotlb.h +++ b/include/linux/swiotlb.h @@ -15,8 +15,7 @@ struct page; struct scatterlist; #define SWIOTLB_VERBOSE (1 << 0) /* verbose initialization */ -#define SWIOTLB_FORCE (1 << 1) /* force bounce buffering */ -#define SWIOTLB_ANY (1 << 2) /* allow any memory for the buffer */ +#define SWIOTLB_ANY (1 << 1) /* allow any memory for the buffer */ /* * Maximum allowable number of contiguous slabs to map, @@ -32,8 +31,12 @@ struct scatterlist; #define IO_TLB_SHIFT 11 #define IO_TLB_SIZE (1 << IO_TLB_SHIFT) -/* default to 64MB */ -#define IO_TLB_DEFAULT_SIZE (64UL<<20) +/* compile-time default; overridable via CONFIG_SWIOTLB_DEFAULT_SIZE_MB */ +#ifdef CONFIG_SWIOTLB +#define IO_TLB_DEFAULT_SIZE ((unsigned long)CONFIG_SWIOTLB_DEFAULT_SIZE_MB << 20) +#else +#define IO_TLB_DEFAULT_SIZE (64UL << 20) +#endif unsigned long swiotlb_size_or_default(void); void __init swiotlb_init_remap(bool addressing_limit, unsigned int flags, @@ -64,8 +67,9 @@ extern void __init swiotlb_update_mem_attributes(void); * @areas: Array of memory area descriptors. * @slots: Array of slot descriptors. * @node: Member of the IO TLB memory pool list. - * @rcu: RCU head for swiotlb_dyn_free(). + * @dyn_free: RCU work item used to free the pool from process context. * @transient: %true if transient memory pool. + * @cc_shared: %true if the pool memory is shared for confidential computing. */ struct io_tlb_pool { phys_addr_t start; @@ -79,8 +83,9 @@ struct io_tlb_pool { struct io_tlb_slot *slots; #ifdef CONFIG_SWIOTLB_DYNAMIC struct list_head node; - struct rcu_head rcu; + struct rcu_work dyn_free; bool transient; + bool cc_shared; #endif }; @@ -92,16 +97,17 @@ struct io_tlb_pool { * @debugfs: The dentry to debugfs. * @force_bounce: %true if swiotlb bouncing is forced * @for_alloc: %true if the pool is used for memory allocation + * @cc_shared: %true if the pool memory is shared for confidential computing. * @can_grow: %true if more pools can be allocated dynamically. * @phys_limit: Maximum allowed physical address. * @lock: Lock to synchronize changes to the list. * @pools: List of IO TLB memory pool descriptors (if dynamic). * @dyn_alloc: Dynamic IO TLB pool allocation work. * @total_used: The total number of slots in the pool that are currently used - * across all areas. Used only for calculating used_hiwater in - * debugfs. - * @used_hiwater: The high water mark for total_used. Used only for reporting - * in debugfs. + * across all areas. Used only for calculating used_hiwater via boot + * parameter swiotlb=track_hiwater and exposed via debugfs. + * @used_hiwater: The high water mark for total_used. Can be enabled at boot + * time via swiotlb=track_hiwater and exposed via debugfs. * @transient_nslabs: The total number of slots in all transient pools that * are currently used across all areas. */ @@ -111,6 +117,7 @@ struct io_tlb_mem { struct dentry *debugfs; bool force_bounce; bool for_alloc; + bool cc_shared; #ifdef CONFIG_SWIOTLB_DYNAMIC bool can_grow; u64 phys_limit; @@ -238,7 +245,7 @@ static inline phys_addr_t default_swiotlb_limit(void) phys_addr_t swiotlb_tbl_map_single(struct device *hwdev, phys_addr_t phys, size_t mapping_size, unsigned int alloc_aligned_mask, - enum dma_data_direction dir, unsigned long attrs); + enum dma_data_direction dir, unsigned long *attrs); dma_addr_t swiotlb_map(struct device *dev, phys_addr_t phys, size_t size, enum dma_data_direction dir, unsigned long attrs); @@ -282,15 +289,19 @@ static inline void swiotlb_sync_single_for_cpu(struct device *dev, extern void swiotlb_print_info(void); #ifdef CONFIG_DMA_RESTRICTED_POOL -struct page *swiotlb_alloc(struct device *dev, size_t size); +struct page *swiotlb_alloc(struct device *dev, size_t size, + unsigned long attrs); bool swiotlb_free(struct device *dev, struct page *page, size_t size); +void swiotlb_free_from_pool(struct device *dev, + phys_addr_t tlb_addr, struct io_tlb_pool *pool); static inline bool is_swiotlb_for_alloc(struct device *dev) { return dev->dma_io_tlb_mem->for_alloc; } #else -static inline struct page *swiotlb_alloc(struct device *dev, size_t size) +static inline struct page *swiotlb_alloc(struct device *dev, size_t size, + unsigned long attrs) { return NULL; } @@ -299,6 +310,10 @@ static inline bool swiotlb_free(struct device *dev, struct page *page, { return false; } +static inline void swiotlb_free_from_pool(struct device *dev, + phys_addr_t tlb_addr, struct io_tlb_pool *pool) +{ +} static inline bool is_swiotlb_for_alloc(struct device *dev) { return false; diff --git a/include/trace/events/dma.h b/include/trace/events/dma.h index 31c9ddf72c9d..9df02c1511de 100644 --- a/include/trace/events/dma.h +++ b/include/trace/events/dma.h @@ -35,7 +35,8 @@ TRACE_DEFINE_ENUM(DMA_NONE); { DMA_ATTR_MMIO, "MMIO" }, \ { DMA_ATTR_DEBUGGING_IGNORE_CACHELINES, "CACHELINES_OVERLAP" }, \ { DMA_ATTR_REQUIRE_COHERENT, "REQUIRE_COHERENT" }, \ - { DMA_ATTR_CC_SHARED, "CC_SHARED" }) + { DMA_ATTR_CC_SHARED, "CC_SHARED" }, \ + { __DMA_ATTR_ALLOC_CC_SHARED, "ALLOC_CC_SHARED" }) DECLARE_EVENT_CLASS(dma_map, TP_PROTO(struct device *dev, phys_addr_t phys_addr, dma_addr_t dma_addr, |
