[PATCH 1/6] generic_pt: allow missing sw bit in DMA_INCOHERENT case
From: Daniel Drake <hidden>
Date: 2026-07-12 21:19:43
Also in:
linux-devicetree, linux-iommu, lkml
Subsystem:
iommu subsystem, the rest · Maintainers:
Joerg Roedel, Will Deacon, Linus Torvalds
When working with a iommu with PT_FEAT_DMA_INCOHERENT set, generic_pt will attempt to use a spare "SW" bit in the hardware page tables to denote when a thread has flushed the CPU cache after modifying an entry. This means that other threads know that they are not working with cached/unflushed data, if they come across the same entry. In the case where no SW bit is available, two things happen: 1. __map_range() defensively flushes every time it reads the PT. This ensures all data that may have just been manipulated by another thread gets flushed and made iommu-visible immediately. 2. An undefined reference to __pt_no_sw_bit() is created, causing a linker error in order to alert the developer that they are going to suffer a performance penalty in the previous point. The BCM2712 IOMMU appears to be the first device supported by generic_pt that hits this case. The prod to check for sw bits is appreciated, but in this case there are no known bits that can be used, so we need to acknowledge and accept the performance penalty without a linker error. Adding an empty __pt_no_sw_bit() symbol to iommu_bcm2712 would be problematic because if a second IOMMU were to have the same constraint, this would result in a symbol clash in the global namespace. Also, the kunit build creates and builds a 2nd variant of the same code and hits this exact collision. Add an opt-in PT_SW_BIT_NOT_PRESENT flag to avoid this. This prevents the undefined reference from being created, allowing drivers like bcm2712 to acknowledge the situation and accept the performance penalty of the defensive flushing. Signed-off-by: Daniel Drake <redacted> --- drivers/iommu/generic_pt/pt_fmt_defaults.h | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/drivers/iommu/generic_pt/pt_fmt_defaults.h b/drivers/iommu/generic_pt/pt_fmt_defaults.h
index 69fb7c2314ca..cc57106c87d1 100644
--- a/drivers/iommu/generic_pt/pt_fmt_defaults.h
+++ b/drivers/iommu/generic_pt/pt_fmt_defaults.h@@ -249,7 +249,20 @@ static inline unsigned int pt_max_sw_bit(struct pt_common *common) return 0; } +/* + * In the DMA_INCOHERENT case, if no SW bit has been defined, produce a linker + * error (undefined symbol __pt_no_sw_bit) to alert the developer that they + * will suffer a performance penalty due to defensive flushing. The driver + * can either implement pt_sw_bit (if supported by the hardware) for optimal + * performance, or otherwise set PT_SW_BIT_NOT_PRESENT to acknowledge the + * performance penalty. + */ +#ifdef PT_SW_BIT_NOT_PRESENT +static inline void __pt_no_sw_bit(void) {} +#else extern void __pt_no_sw_bit(void); +#endif + static inline bool pt_test_sw_bit_acquire(struct pt_state *pts, unsigned int bitnr) {
--
2.55.0