Атомарность небольших записей PCIE TLP
Существуют ли какие-либо гарантии того, как карта для хоста записи с устройства PCIe, нацеленного на обычную память, реализована с точки зрения программного процесса, когда одна запись TLP полностью содержится в одной строке кэша ЦП?
Меня интересует случай, когда мое устройство может записать некоторое количество слов данных, за которыми следует байт, чтобы указать, что структура теперь действительна (например, завершение события), например:
struct PCIE_COMPLETION_T {
uint64_t data_a;
uint64_t data_b;
uint64_t data_c;
uint64_t data_d;
uint8_t valid;
} alignas(SYSTEM_CACHE_LINE_SIZE);
Могу ли я использовать один TLP для написания этой структуры, чтобы, когда программное обеспечение видит, что действительный член изменяется на 1 (который был предварительно очищен до нуля программным обеспечением), тогда другие члены данных также будут отражать значения, которые я написал, а не предыдущее значение?
В настоящее время я выполняю 2 записи, сначала записываю данные, а затем помечаю их как действительные, что не имеет никаких явных условий гонки, но, конечно, добавляет нежелательные накладные расходы.
Самый актуальный вопрос, который я могу увидеть на этом сайте, кажется, это атомарно ли запись на шине PCIe? хотя это, по-видимому, связано с относительным порядком TLP.
Просматривая спецификацию PCIe 3.0, я не нашел ничего, что бы явно отражало мои опасения, я не думаю, что мне особенно нужен AtomicOps. Учитывая, что меня беспокоит только взаимодействие с системами x86-64, я также покопался в руководстве по архитектуре Intel, но не нашел более ясного.
Инстинктивно кажется, что такая запись должна восприниматься атомарно - тем более, что это называется транзакцией, - но в равной степени я не могу найти много документации, явно подтверждающей это мнение (и я тоже совершенно уверен, что мне нужно посмотреть, возможно, поставщик процессора?). Мне также интересно, можно ли распространить такую схему на несколько строк кэша - т.е. если действительный находится на второй строке кэша, записанной из той же транзакции TLP, могу ли я быть уверен, что первая будет воспринята не позже второй?
1 ответ
Запись может быть разбита на более мелкие единицы, размером с двойные слова, но если это так, то они должны выполняться в порядке возрастания адресов.
Версия 4 PCIe, раздел 2.4.3:
Если одна транзакция записи, содержащая несколько DW и сброс бита ослабленного упорядочивания, принимается завершителем, наблюдаемое упорядочение обновлений в местоположениях в буфере данных завершителя должно быть в порядке возрастания адресов. Эта семантика требуется в случае, если мост PCI или PCI-X на пути объединяет несколько транзакций записи в одну. Однако наблюдаемая детализация обновлений буфера данных Completer выходит за рамки данной спецификации.
Хотя это и не требуется данной спецификацией, настоятельно рекомендуется, чтобы хост-платформы гарантировали, что, когда запись PCI Express обновляет память хоста, степень детализации обновления, наблюдаемая центральным процессором, не будет меньше, чем DW.
В качестве примера порядка обновлений и степени детализации, если запрашивающий записывает QW в память хоста, в некоторых случаях центральный ЦП, считывающий эту QW из памяти хоста, может наблюдать, как первый DW обновлен, а второй DW содержит старое значение.
У меня нет копии версии 3, но я подозреваю, что этот язык также находится в этой версии. Чтобы помочь вам найти его, раздел 2.4 - "Порядок транзакций", а раздел 2.4.3 - "Порядок обновления и степень детализации, обеспечиваемые транзакцией записи".