Кеш - сброс и аннулирование операции
У меня есть несколько вопросов по операциям синхронизации кэша.
Invalidate: перед тем, как процессор попытается прочитать часть памяти, обновленную устройством, соответствующая память должна быть аннулирована.
Очистка: перед тем, как устройство прочитает часть памяти, обновленную ЦП, ЦП должен сбросить (запись также правильна?) Содержимое из кэша в память, чтобы устройство считывало содержимое из памяти с обновленным содержимым.
Если сброс не выполняется, он может считывать ненужные данные, присутствующие в памяти, так как память все еще не обновляется содержимым, записанным в кэш.
Пожалуйста, подтвердите, правильно ли мое понимание выше?
Когда вы хотите объединить и сброс, и аннулирование? Я слышал, что во время игры с дескрипторами управления устройством нам нужно синхронизировать, комбинируя сброс и аннулирование. Почему так?
Нужно ли нам следовать такой последовательности, как flush с последующим аннулированием?
Есть ли сценарий, в котором недействительным после флеш будет полезно?
2 ответа
Flush записывает содержимое кеша в основную память, а invalidate помечает строки кеша как недействительные, поэтому последующие чтения идут в основную память.
Я думаю, что вы бы объединили сброс и аннулирование, если бы устройство обновляло блок памяти: очистка гарантировала бы, что устройство имело самое последнее содержимое, а аннулирование затем гарантировало бы, что когда устройство завершит работу, ЦП будет читать новое содержимое из памяти.
Пожалуйста, подтвердите, правильно ли мое понимание выше?
Обычно вы абсолютно правы, но есть камни, которые могут споткнуться. Вы не указали платформу HW. Если мы не говорим о маленьких встроенных контроллерах, упакованных с SRAM, рассмотрим следующее. Процессоры с MMU поддерживают различные атрибуты памяти для обычной памяти DDR и памяти драйвера (связанной с HW). Последний не кешируется, поэтому нет проблем с очисткой / аннулированием.
Когда вы хотите объединить и сброс, и аннулирование? Я слышал, что во время игры с дескрипторами управления устройством нам нужно синхронизировать, комбинируя сброс и аннулирование. Почему так?
Поскольку DMA упоминается в тегах, существует несколько сценариев (при условии, что буфер HW является не кешируемой памятью устройства):
- DMA передает данные из памяти DDR в буфер HW.
- DMA передает данные из буфера HW в DDR (HW получил данные и хочет сделать их доступными для CPU)
- Передача DMA из DDR в другой регион DDR.
- Буфер DDR должен быть очищен перед DMA. Буфер драйвера не кешируется, поэтому нет необходимости в аннулировании.
- Буфер DDR должен быть аннулирован до или после (смотрите
NOTE
ниже для подробностей) Передача DMA для предотвращения использования ЦПУ "старых" данных из кэша. Очистка буфера HW избыточна. - Буфер 'Source' должен быть очищен, буфер 'Destination' должен быть признан недействительным. Таким образом, действительные данные находятся в памяти для DMA перед передачей, и CPU не берет "грязь" из кэша после того, как DMA сделал свою работу.
NOTE
Очевидно, что "источник" должен быть сброшен перед DMAing. Тем не менее остается вопрос, когда признать недействительным. Технически это происходит до того, как CPU попытается получить доступ к данным "Destination", и может быть до или после DMA (мы должны убедиться, что DMA завершил работу). Аннулирование IRL после DMAing может привести к проблеме. Обратитесь к Сбросить / Неверный диапазон по виртуальному адресу; ARMv8; Cache;
Как вы могли видеть, аннулирование для этой конкретной платформы должно быть сделано до DMAing. Также несуразный код BSP для устройства ARMv7 Я нашел рекомендацию аннулировать буфер назначения перед передачей DMA.
Нужно ли нам следовать такой последовательности, как flush с последующим аннулированием?
Предполагая, что исходный и целевой буферы не пересекаются друг с другом, нет никаких зависимостей. Вы могли бы flush-invalidate
или же invalidate-flush
,
Есть ли сценарий, в котором недействительным после флеш будет полезно?
Не думай так.