Я действительно удивлен, что никто не ответил на этот вопрос, поэтому здесь мы переходим к ответу, не относящемуся к Linux (у меня недостаточно знаний о самом ядре Linux, чтобы быть более конкретным) ...
Отслеживание кэша просто говорит контроллеру DMA отправлять запросы на аннулирование кэша всем процессорам для памяти, в которую осуществляется DMA. Это, очевидно, увеличивает нагрузку на шину когерентности кэша и особенно плохо масштабируется с дополнительными процессорами, поскольку не все процессоры будут иметь соединение с одним скачком с контроллером DMA, выдающим анализатор. Следовательно, простой ответ на вопрос «когда безопасно отключить отслеживание кэша» заключается в том, что когда DMA-память либо не существует ни в одном из кэшей ЦП, ИЛИ ее строки кэша помечены как недействительные. Другими словами, любая попытка чтения из области DMAed всегда приводит к чтению из основной памяти.
Итак, как вы гарантируете, что чтение из области DMAed всегда будет идти в основную память?
Раньше, до того, как у нас появились такие необычные функции, как отслеживание DMA-кэша, мы использовали для конвейеризации память DMA, выполняя ее через серию разбитых этапов следующим образом:
Этап 1: добавить «грязную» область памяти DMA в список «грязных и нуждающихся в очистке» памяти DMA.
Этап 2: В следующий раз, когда устройство прерывает работу со свежими данными DMA, выдайте асинхронный локальный кэш ЦП, аннулирующий для сегментов DMA в списке «грязный и подлежащий очистке» для всех ЦП, которые могут обращаться к этим блокам (часто каждый CPU запускает свои собственные списки, состоящие из блоков локальной памяти). Переместить указанные сегменты в «чистый» список.
Этап 3: следующее прерывание DMA (которое, конечно, вы уверены, что не произойдет до завершения предыдущего аннулирования кэша), возьмите новую область из «чистого» списка и сообщите устройству, что его следующий DMA должен войти в тот. Утилизируйте любые грязные блоки.
Стадия 4: повтор.
Насколько это больше работы, у него есть несколько основных преимуществ. Во-первых, вы можете привязать обработку DMA к одному ЦП (обычно к первичному ЦП0) или к одному узлу SMP, что означает, что только один ЦП / узел должен беспокоиться о недействительности кэша. Во-вторых, вы предоставляете подсистеме памяти гораздо больше возможностей для скрытия задержек памяти, распределяя операции с течением времени и распределяя нагрузку на шину когерентности кэша. Ключом к производительности, как правило, является попытка заставить любой DMA происходить на CPU как можно ближе к соответствующему контроллеру DMA и в памяти как можно ближе к этому CPU.
Если вы всегда передаете недавно DMAed в память пользовательскому пространству и / или другим процессорам, просто вставьте свежую полученную память в начало конвейера аннулирования асинхронного кэша. Некоторые ОС (не уверенны в Linux) имеют оптимизированную подпрограмму для предварительного упорядочения обнуленной памяти, поэтому ОС в основном обнуляет память в фоновом режиме и поддерживает быстрый кэш-память вокруг - это позволит вам поддерживать новые запросы памяти ниже этого кешируемого объема, поскольку обнуление памяти очень медленно Я не знаю ни одной платформы, созданной за последние десять лет, которая использует обнуление аппаратной разгрузки памяти, поэтому вы должны предположить, что вся свежая память может содержать действительные строки кэша, которые необходимо аннулировать.
Я ценю, что это отвечает только на половину вашего вопроса, но это лучше, чем ничего. Удачи!
Найл