Как запросы конфигурации MMIO, IO и PCI маршрутизируются и обрабатываются ОС в системе NUMA? - программирование

Как запросы конфигурации MMIO, IO и PCI маршрутизируются и обрабатываются ОС в системе NUMA?

TL; DR

Как запросы конфигурации MMIO, IO и PCI направляются на нужный узел в системе NUMA?
У каждого узла есть "таблица маршрутизации", но у меня сложилось впечатление, что ОС, как предполагается, не знает об этом.
Как ОС может переназначить устройства, если она не может изменить "таблицу маршрутизации"?


Для правильного знакомства с "таблицей маршрутизации", то есть декодерами исходного адреса (SAD), см. Декодирование физических адресов в Intel Xeon. ЦП v3/v4: дополнительная таблица данных.

Сначала я попытаюсь подытожить то, что я собрал из бумаг и едва документированных таблиц. К сожалению, это еще больше усугубит вопрос и может не иметь всех частей.

Когда запрос выходит из LLC 1, необходимо выяснить, куда его направить.

На процессорах рабочих станций целевыми объектами являются либо DRAM, либо один корневой порт PCIe/интегрированное устройство, либо интерфейс DMI.
Uncore может легко определить, принадлежит ли запрос памяти к DRAM благодаря регистрам iMC 2 или одному из корневого порта PCIe 3/встроенному устройству, и в конечном итоге откатится к DMI.
Это, конечно, также включает MMIO и практически идентично для ввода-вывода с отображением портов (которое пропускает только проверку DRAM).
Запросы конфигурации PCI (CFG) маршрутизируются согласно спецификации с единственным предупреждением, что запросы CFG на шине 0, не предназначенные для интегрированных устройств, отправляются по интерфейсу DMI 4.

На ЦП сервера целевой адрес может быть вне сокета.
Таблица используется для поиска идентификатора узла (NID) 5. Эта таблица называется SAD.

Фактически, SAD состоит из двух декодеров: декодера DRAM (который использует таблицу) и декодера IO 6 (который состоит в основном из фиксированных диапазонов и разрешающих битов, но также должен содержать таблицы).
При необходимости IO-декодер переопределяет декодер DRAM.

Декодер DRAM работает со списком диапазонов, каждый из которых связан со списком целевых NID 7. Если запрос конфигурации памяти, MMIO или PCIe (MMCFG) совпадает с диапазоном, uncore отправит запрос по пути QPI/UPI выбранной цели (неясно, может ли SAD предназначаться для самого узла-запросчика).
Декодер ввода-вывода работает либо с разрешающими битами для фиксированных диапазонов с фиксированными целями (например, вернуть устаревшие окна BIOS на "BIOS NID"), либо с переменным диапазоном, где часть адреса используется для индексации списка целей.

Назначения портов ввода-вывода с сопоставлением портов ищутся в таблице, обозначенной как IO[yyy].
Назначения ввода-вывода MMCFG ищутся в таблице с именем PCI[zzz].
Пункты назначения CFG повторно используют таблицу PCI[zzz].
Здесь yyy и zzz обозначают индексную функцию, то есть часть адреса запроса (zzz - номер шины для CFG).

Все это имеет смысл для меня, но эти таблицы не задокументированы в таблице данных, поэтому такой символ, как PCI[zzz], может фактически означать что-то совершенно другое.


Хотя документации по этим декодерам практически нет, этого достаточно для примитивной ментальной модели.

Мне все еще неясно, используются ли SAD даже для запросов, предназначенных для локальных ресурсов, или они используются только для исходящих запросов.
Это будет важно позже.

Предположим, что когда запрос покидает LLC, SAD используются для маршрутизации его к компоненту (в конечном итоге в том же сокете), а затем он обрабатывается аналогично случаю рабочей станции 8.

Пока аппаратная конфигурация не изменена, SAD может быть настроен микропрограммным обеспечением, а ОС может быть полностью независимой от них.
Но что произойдет, если ОС переназначит устройство PCIe, которое находится за локальным каналом PCIe узла?

Чтобы запрос MMIO достиг такого устройства, он должен сначала достичь узла устройства (поскольку это единственная связь с остальной частью системы), но это может произойти, только если SAD правильно переконфигурированы.
Переконфигурирование SAD может потребоваться даже для запросов, исходящих из того же узла, что и устройство 9.
Но предполагается, что ОС не знает о SAD или нет?

У меня есть несколько возможных ответов:

  1. SAD не используются для доступа к локальным ресурсам, и ОС ограничивает доступ к локальному вводу-выводу только процессам (или ядру), работающим в родительском узле. Это исключает необходимость перенастройки SAD.
  2. Микропрограмма конфигурирует SAD так, чтобы каждый узел имел часть адресного пространства (скажем, 2 k/N, где k - размер физического адресного пространства, а N - номер узла) и сообщает об этом в таблице SRAT ACPI., (но не является ли SRAT необязательным?) 10 Затем ОС распределяет ресурсы MMIO только внутри каждой части памяти узла. Это может привести к неоптимальному использованию памяти.
  3. SAD - это оптимизация, если неядерный не знает, куда направить запрос, он будет передавать его по ссылкам QPI/UPI до тех пор, пока он не будет принят узлом.
  4. Все выше не так.

1, например. из-за пропуска или из-за того, что UC.

2, например, TOUM для максимального физического адреса, который может быть восстановлен посредством DRAM, хотя это не непрерывный блок.

3 Это мост PCI-PCI (P2P), имеющий регистры для установки окон ввода-вывода, памяти с предварительной выборкой и без предварительной выборки.

4 Вот почему устройства PCH появляются на шине 0. ЦП сервера имеют две "внутренние" шины, и их номера могут быть изменены.

5 Идентификатор узла состоит из номера сокета и неосновного идентификатора компонента. Я знаю, что uncore-компонент, который может быть целью (после перевода имени из номенклатуры "box"): первый или второй Home agent (iMC), системный агент и ссылка DMI.

6 Таблица IO-декодера разделена на IOS (IO Small декодер) и IOL (IO Large декодер). Это отражает аппаратные возможности двух таблиц, при этом IOS почти фиксирована, а IOL - CAM. С обоими обращаются параллельно с таблицей DRAM, IOS переопределяет IOL, если оба совпадают.

7 Диапазон автоматически перемежается (то есть подразделяется) между всеми восемью целями. Чтобы использовать менее восьми целей, могут использоваться повторяющиеся записи (например, все установленные на одни и те же цели совпадают с отсутствием чередования).

8 Интересно, что произойдет, если SAD направит запрос к неосновному компоненту (скажем, iMC), но за пределами его исправленного диапазона? Я предполагаю, что это отброшено.

9 См. жирную часть выше, я не знаю, как SAD работает с запросами, ориентированными на локальные ресурсы.

10 Linux подделывает узел NUMA на машинах UMA. В моем ящике количество памяти, выделенной узлу, включает MMIO (почти 10 ГБ, выделенных против 8 ГБ или DRAM). Кажется, весь диапазон, возвращаемый E8020, используется.

4b9b3361

Ответ 1

Основной проблемой здесь является то, что ВСЕ таблицы данных, например, Xeon D-1500 vol2, e7 v2 vol2 не показывает регистры конфигурации CBo, которые, скорее всего, содержат конфигурацию целевого списка SAD.

В этом ответе используются элементы из таблицы данных Xeon 7500 (для соединения с остальной частью системы используются кольцо и Rbox), но в этом ответе говорится о системе, архитектура кольцевой шины которой напоминает IvB-EX Xeon e7 v2 (в которой используется 2 кольца), но также относится к Haswell-EX (который использует 4 кольца для соединения между двумя) и далее. Я предполагаю, что каждое кольцо - это 32 * 4 snoop, data, request, Подтверждающее кольцо (я точно знаю, что это на Nehalem-EX и SnB).

Xeon e7 v2:

На заднем фронте сигнала сброса пакет мгновенно определяет NodeID и смежные NodeID, ID кластера x2APIC и идентификаторы APIC логического процессора (до SnB на настольных процессорах он использовал для выборки сигналов MCH на входных контактах, чтобы сделать это; я не уверен насчет мультисокета начиная с SnB). После этого кэши и TLB сбрасываются, ядра выполняют BIST, а затем происходит алгоритм инициализации MP с несколькими гнездами MP initialisation algorithm occurs. Xeon D-1500 vol2 показывает регистр CPUNODEID; Я не уверен, какое поведение возникает при изменении этого сброса в отношении транзакций в полете. Изменяются ли целевые списки SAD посредством автоматически сгенерированных записей, когда CPUNODEID изменяется на других ядрах, или это вызывает обработчик SMI, или это задача программиста? ИДК. Предположительно, все агенты должны были быть отключены, чтобы остановить их доступ к Cbo, прежде чем можно будет изменить конфигурацию SAD.

Кеширующий агент

Каждый сокет имеет кеширующий агент и домашний агент (или 2 центра сертификации и 2 центра сертификации на MCC/HCC). Функциональность агента кэширования хэшируется по адресам в срезах Cbo. Сопоставление устанавливается во время загрузки, потому что это когда режим отслеживания установлен. На Haswell-EX режим отслеживания можно переключать в BIOS между режимами без отслеживания, home snoop, ранний snoop, source snoop, HS w. Каталог + OSB + HitME кеш или ХПК, в зависимости от процессора; хотя мне еще предстоит увидеть какие-либо таблицы данных с регистрами конфигурации PCIe, относящиеся к режимам слежения. Я не уверен, какое поведение возникает для транзакций в полете, когда это изменяется после сброса. Когда ядро отключено BIOS, оно не влияет на Cbos, которые продолжают функционировать. Агент кэширования был отдельным компонентом в Nehalem-EX (см. таблицу данных 7500), но в более поздних архитектурах он используется для ссылки на Cbos в целом. COD (Cluster on Die), представленный на Haswell-EP, разбивает кеширующий агент на 2 на сокет.

СВО

В каждом слое кеша есть поле кеша, которое является контроллером и агентом между LLC и остальной частью системы, в основном контроллером LLC. Cbo содержит таблицу запросов, которая содержит все ожидающие транзакции. Cbo поддерживает три типа транзакций: 1. Запросы, инициированные ядром /IIO 2. Внешние отслеживания Intel QPI 3. Высвобождение емкости LLC. С каждой транзакцией связана запись в ТЗ. Запись TOR содержит информацию, требуемую Cbo для уникальной идентификации запроса (например, адрес и тип транзакции) и элементы состояния, необходимые для отслеживания текущего статуса транзакции.

Запросы Core/PCIe хешируются по адресу, чтобы выбрать Cbo для перевода и поместить запрос в кольцо. Ядро знает, в каком направлении на кольце отправлять запрос наименьшей задержки, поэтому оно будет знать о хэш-карте и том, какой Cbo является целью, и ожидает вакансии в кольце для размещения транзакции.

Исходные запросы ядра используют интерфейс пакета IDI. IDI (Intra-Die-Interconnect) показан на Broadwell-EX. Диаграмма подразумевает, что ядра отвечают только на пакеты IDI, а CBos отвечают на QPI и IDI (но это немного неправильно, потому что ядра действительно используют QPI для блокировок, прерываний и специальных циклов; для этого нет кодов операций IDI). Коды операций Xeon e7 v2 показаны в Таблица 2-18 и коды операций QPI в Таблица 2-218. Это также препятствует тому, чтобы IIO запрашивал адрес перед его декодированием, поскольку он принимает только коды операций QPI. Ubox/IIO/PMU/PCU совместно используют интерфейс для единой остановки, а Ubox/IIO совместно используют интерфейс с DMI.

Когда появляется вакансия, он гарантирует, что полярность кольца будет такой же, как и у целевого Cbo, и помещает 32-байтовый флип в кольцо в том же цикле. Я хотел бы представить, что заголовок канального уровня IDI flit содержит идентификатор источника, dest и ID транзакции, что позволяет разделять транзакции более высокого уровня и поступать несмежно по мере появления свободных пробелов в кольце, и поэтому он знает, следует ли продолжать буферизация транзакции и удаление флита с ринга. (Кольцевой IDI/QPI отличается от QPI, который не имеет источника/приемника канального уровня, потому что QPI является двухточечным; также QPI имеет только 80-битный переход, который легко найти диаграмму; не относится к заголовкам кольцевой шины ) (также мы предполагаем, что Phit = Flit, когда кольцо движется со скоростью 1 цикл на остановку). Cbo реализует схему кредитования/дебетования канального уровня QPI для каждого пункта назначения, чтобы остановить переполнение буфера. Этот запрос, вероятно, будет нуждаться только в 1 такте, но выборки строки кэша потребуют 3. Cbo декодирует, когда он видит соответствующий код операции и адрес в диапазоне адресов, который ему был назначен. Теперь он должен декодировать адрес, чтобы посмотреть, что с ним делать.

Внутри Cbo запросы проходят через SAD одновременно с выделением их в TOR и отправляются в LLC. Типы сообщений не-LLC проходят через SAD, когда они также выделяются в TOR. SAD получает адрес, адресное пространство, код операции и некоторые другие детали транзакции. Чтобы помочь уменьшить количество записей декодера, требуемых для различных мощностей DRAM, адресный декодер имеет несколько опций чередования, а на Xeon 7500 разделен на 3 декодера с приоритетом от наивысшего к низшему:

• I/O маленький (IOS) декодер

• I/O большой (IOL) декодер

• DRAM декодер

Каждый из этих декодеров представлен адресом и доступен параллельно. Адреса, которые соответствуют записи в одном из декодеров, заставляют декодер искать и генерировать атрибут памяти QPI и NodeID. Для одного декодера разрешено только одно совпадение. Совпадения адресов в декодере с более высоким приоритетом переопределяют одновременные совпадения в декодерах с более низким приоритетом (обратите внимание, что Xeon e7 v2 имеет "декодер чередования" исключительно для MMCFG и традиционный декодер для устаревших диапазонов, отдельно от основного декодера ввода/вывода).

Декодеры ввода/вывода

Здесь представлено 8 целевых списков: PCI [], MIOU [], MIOL [], FWH [], APIC [], IOH [], CPU [], IO []. Они, наряду с некоторыми записями декодера ввода/вывода, должны конфигурироваться через CSR под устройством Cbo; BIOS должен знать эту информацию. Они будут помечены как что-то вроде PCI_TARGET_LIST, APIC_TARGET_LIST и т.д., А его тело будет выглядеть как SAD_INTERLEAVE_LIST на Xeon 3400, за исключением того, что будет разрешено 3 бита на индекс. Локальные регистры Cfg, которые являются просто фиксированной областью MMIO, которая отображает локальные регистры конфигурации PCIe, имеют только одну цель - локальный сокет и не нуждаются в каком-либо списке целей (он всегда будет направляться в Ubox, поэтому NodeID будет локальным Ubox на 7500).

Семейство продуктов Intel Xeon E7 v2 реализует 4-битный NodeID (NID). Семейство продуктов Intel Xeon E7 v2 может поддерживать до 2 HA в каждом сокете. HA в том же сокете будут различаться по NID [2]. В тех случаях, когда целью является только 3 бита, NID [2] предполагается равным нулю. Следовательно, ID сокета будет NID [3,1: 0]. Процессор Intel® Xeon® серии 7500 реализует 5 бит и может поддерживать до четырех сокетов (выбирается NID [3: 2], когда NID [8] равен нулю). Внутри каждого разъема находятся четыре устройства (NID [1: 0]): набор микросхем Intel® 7500 (00), B0/S0 (01), Ubox (10), B1/S1 (11). B0/S0 и B1/S1 - это два набора HA (Bbox) и CA (Sbox).

E7 v2 имеет только 3 бита NodeID, что означает, что он может поддерживать до 8 сокетов и 2 HA на сокет. Однако в руководстве E7 v2 говорится, что размер списка чередования равен 8, что может означать, что поддерживаются только 4 сокета, если у них есть 2 HA (конечно?). Я полагаю, что если сокет имеет 2 HA (MCC, HCC), он все равно будет иметь 2 отдельных NodeID для каждого независимо от того, находится ли он в режиме COD или нет. COD изменяет только хэш Cbo, чтобы у Cbo в обоих кластерах был собственный адрес, чтобы уменьшить задержку кэша (поэтому, если он имеет HA, то он рассматривается как 2 узла в одном узле NUMA; но COD делает его 2 узлами NUMA - запрос к другому NID будет получен другим HA, а не ссылкой QPI). Насколько я могу судить, COD - это скорее оптимизация NUCA, поскольку базовая база чередования DRAM внутри сокетов на [6: 4] остается неизменной, если есть 2 HA независимо от режима COD; COD только уменьшает задержку кэша, уменьшая количество переходов в слайс LLC. Режим COD показывает, что объем памяти, адресуемой каждым узлом, равен половине, но он уже наполовину из-за различий целей списка чередования, различающих HA.

Это парафраз списка декодеров ввода/вывода, который появляется. Таблица включает в себя записи IOS и IOL декодера. Атрибут, например CFG - это выходной класс кода операции, из которого будет выбран код операции.

DRAM декодер

На Xeon 7500 декодер DRAM состоит из двух массивов, массива CAM и массива полезной нагрузки. Декодер DRAM имеет 20 записей в каждом массиве. Массив CAM имеет специальную логику сравнения для вычисления того, является ли адрес меньше или равен пределу области каждой записи, чтобы учесть любой размер области, кратный 256 МБ. Биты адреса ограничения области [43:28] сохраняются в массиве CAM записи (то есть гранулярность 256 МБ). Массив полезной нагрузки (tgtlist – attr) имеет 42 бита на запись.

Вы ожидаете увидеть 20 64-битных (зарезервированных 6 битов) конфигурационных регистров для этих записей декодера, но с момента введения CBos в качестве агента кэширования ни одна таблица данных не отображает их регистры конфигурации; Я не уверен, почему это все не отображается в таблице данных, когда, например, регистры Ubox показаны; Я предполагаю, что OEM-производители UEFI BIOS информированы о правильных смещениях регистра. Поэтому для демонстрации я буду использовать регистры Xeon 3400. На Xeon 5500 вы можете установить 8 правил для каждого сокета, которые будут использоваться в качестве записей декодера.

Вы устанавливаете PA [39:26] для соответствия в [19: 6] и метод генерации индекса в SAD_DRAM_RULE_0, а затем в SAD_INTERLEAVE_LIST_0 вы помещаете список целей. Нет доступных таблиц конфигурации SAD, показывающих, что более 2 сокетов не зарезервированы. Было бы интересно увидеть таблицу данных конфигурации PCIe Xeon 7500, в которой говорится о чередовании 8 узлов. Xeon 5500 - это Nehalem-EP (Gainestown), так что, вероятно, правильно, что есть только 2 розетки. Я ожидаю, что он будет 3 бита на 7500. Я не могу думать, почему конфигурация SAD и конфигурация записи декодирования DRAM не будут установлены одинаково для всех сокетов.

Чередование для 8 сокетов выполняется на [8: 6] адреса, и они удаляются из адреса, отправленного в HA, поскольку они неявны.


Есть 2 типа запросов:

Непоследовательные запросы

Некогерентные запросы - это либо обращения к данным, которые сопоставляются с некогерентным адресным пространством (например, MMIO), либо это не запросы памяти, такие как чтение/запись ввода-вывода, прерывания/события и т.д. Когда запросы NC обращаются к памяти ЧПУ, они отправляются в Cbo в соответствии с хешем адреса точно так же, как и согласованные запросы. Запросы NC, не предназначенные для памяти, всегда отправляются в Cbo, который подключен к ядру, которое генерирует запрос.

MMIO

Запрос MMIO принимается Cbo (предположительно в том же цикле, в котором он отправляется, когда он находится на одной и той же остановке), и он передается через декодер I/O и DRAM, сохраняется в TOR, но не отправляется в секцию LLC, если код операции IDI не кэшируется, который ядро отправляет в зависимости от типа памяти в чтении PAT/MTRR при доступе L1, например UC/USWC. (Я не уверен, что используется для чтения MMIO, либо PRd, PCIRdCur или PCINSRd). Он будет совпадать в записи декодера ввода/вывода для одной из областей MMIO. На некоторых процессорах будет 8 IOAPIC (не на Xeon 7500, потому что он говорит об ICH/IOH и его Beckton (Nehalem-EX), так что это самая первая реализация кольцевой шины, но когда PCH был представлен на SnB, он встроен в чип в модуле IIO). Yyy в FECX_ (yyyx) XXXh (поэтому бит [15:13]) будет использоваться для индексации в таблице APIC [] для NodeID. Это означает, что в смежном регионе 64 КБ на каждую IOAPIC приходится 8 КБ. SAD выводит NodeID и код операции для использования. Запрос будет отправлен с NodeID текущего пакета и кодом операции QPI NcRd (поскольку SAD выдает этот NodeID. IIO декодирует запрос на NodeID текущего пакета, кода операции и диапазона адресов.

Кроме того, есть 2 области MMIOL и MMIOH для баров MMIO, которые должны быть установлены. Для каждого гнезда MMIOLL + MMIOLU по 256 МБ. В таблице данных 7500 говорится, что MMIOH требует отдельных записей декодера ввода/вывода для каждого сокета. Предположительно, эти и соответствующие биты включения/выключения будут настраиваться в Cbo CSR

Что касается конфигурационного пространства PCIe, общая схема многоузловой памяти выглядит следующим образом:

Существует субрегион SCA_PCIE, который занимает первые 8 МБ пространства конфигурации 256 МБ, которое должно находиться в области 256 МБ ниже 4 ГБ. Когда доступ PCINSRd находится в диапазоне локальных адресов сгущения (сгущение 1 МБ на сокет), нормальное декодирование PCIe отменяется, а NodeID принимается за PhysicalAddr [22:20]. Обратите внимание, что 1MiB - это шина 0 (32 dev * 8 func). Таким образом, по сути, шина 0 каждого сокета видна всем декодерам таким образом; Таким образом, на шине 0,1,2..7 начинается 8 доменов. Некоторые процессоры имеют регистр CPUBUSNO. Я предполагаю, что это должно быть запрограммировано, чтобы соответствовать этому. Похоже, что устройства IIO + PCH могут иметь отдельный номер шины. Затем NodeID будет помещен в транзакцию QPI с кодом операции NcCfgRd и назначением NodeID, а скачки помещены в кольцо запроса; это тогда будет поглощено связью QPI, которая распознает этот диапазон NID, и однажды на целевом сокете, это будет направлено в Ubox, который выполнит чтение конфигурации; Ubox имеет уникальный NodeID на 7500, поэтому он будет перенаправлен на него без проблем; если он не имеет уникального NodeID, он будет декодироваться на основе кода операции и NodeID одного из HA в пакете. В пакете QPI Cbo может вставлять NodeID запрашивающей стороны, идентификатор CBo запрашивающей стороны и идентификатор транзакции; Ubox буферизирует и отслеживает транзакцию (я полагаю, отправляет подтверждение обратно в кольцо подтверждения) и отправит результаты (успех/сбой) исходному NodeID в пакете QPI в кольце данных, как только обработка будет завершена, и она будет перемещена. вернуться по ссылке QPI. CBo завершает транзакцию и возвращает пакет IDI в Ядро в кольце данных.

Если адрес находится за пределами области 8 МБ, но находится в конфигурационном пространстве 256 PCIe, то он будет соответствовать 2-й верхней записи в списке декодеров ввода/вывода. Биты zzz (очевидно, бит 27-25) используются для индексации в списке целей для выбора узла. Что это значит? хорошо мы знаем, что это явно 3 верхних бита номера автобуса. Это предполагает, что, предполагая, что index = socket no в списке перемежения, распределение сокетов 0 начнется на шине 8 (с шиной 0 в качестве шины 0), сокет 1 начнется как шина 32 (с шиной 0 в качестве шины 1), сокет 2 в шина 64 (с шиной 0 как шина 2), розетка 3 на 96 (с шиной 0 на шину 3). Похоже, что PCI [zzz] означает: индексировать в целевой список PCI, чтобы выбрать NodeID и дать запросу опкод класса атрибута (NcCfgRd/Wr на основе данных TOR). BIOS должен будет прочитать этот регистр конфигурации, чтобы ввести правильные номера подчиненных устройств для мостов PCI-PCI на портах PCIe.

На декодере ввода/вывода также есть записи LclCSR (Local Config), Glb CSR IOH (IOH Cfg), Glbl CPU CSR (CPU Cfg), lcl clump CSR (Local Clump CPU Config). Это фиксированные псевдонимы MMIO для доступа к регистрам конфигурационных пространств (CSR) PCIe без использования PCIEXBAR.

IO

Все сокеты имеют фиксированные порты ввода-вывода и порты, которые можно установить в BAR с индикатором пространства памяти, установленным в пространство ввода-вывода.

Запрос ввода-вывода получен Cbo, и он ищется в таблице ввода-вывода. Кажется, что в списке IDI нет отдельного кода операции ввода-вывода, поэтому, возможно, он также использует PCINSWr, но устанавливает бит в пакете.

Запросом ввода-вывода может быть IO-PCIE или IO-SCA или не-PCIe-IO. Если адрес совпадает с шаблоном в нижней строке и установлен бит ввода-вывода и адрес CF8/CFC, то в адрес вставляются 4 нуля [11: 8] (ядро может выдавать только 8 бит индекса регистра), делая номер функции CONFIG_ADDRESS LSB начинается с бита 12, а не с 8, а номер шины MSB - с бита 27, и теперь он сравнивается с 3-м нижним рядом. Если верхние 5 битов шины совпадают, то NodeID определяется [22:20], и NcCfgRd/Wr отправляется этому NodeID. Если это не CF8/CFC, то NodeID назначения определяется путем поиска записи в списке целей с использованием IO_Addr [15:13] - так, 3 самых значимых бита порта IO. Это означает, что каждый сокет имеет 8 КБ пространства ввода/вывода, и переменный ввод/вывод должен быть установлен в диапазоне для сокета. Для фиксированного доступа к вводу/выводу, если вы сделаете 3 старших бита битами сокета, то теоретически они могут быть удалены Cbo при совпадении; поэтому для доступа к 20h на сокете 1 вы должны использовать 2020h.

Другой

Основные выданные запросы, которые могут соответствовать записям декодера по коду операции: • IntA, Lock, SplitLock, Unlock, SpCyc, DbgWr, IntPriUp, IntLog, IntPhy, EOI, FERR, Quiesce (я предполагаю, что им нужны записи декодера, поскольку ядро не знает целевой идентификатор узла и должен быть запрограммирован). Они размещены в техническом задании, но не отправлены в LLC. SplitLock используется, когда операция аппаратной блокировки пересекает 2 строки кэша. Раньше блокировка направлялась Cbo на Ubox, чтобы успокоить всех агентов для выполнения атомарной операции, но это ненужные накладные расходы, поскольку это может быть реализовано в протоколе согласованности кэша. Таким образом, либо блокировка теперь взята Cbo, и она делает недействительными другие копии и отвечает, и ядро не может прочитать строку до этого момента (вероятно, в LLC есть индикатор, что линия заблокирована в ядре, указанном в фильтре snoop), и есть новый код операции для главной блокировки. Либо блокировка по-прежнему используется в качестве главной блокировки, а блокировка x86 теперь реализована в кэше L1, отказываясь отвечать до тех пор, пока блокировка не будет удалена.

Согласованные запросы

Связные запросы - это запросы доступа к адресу памяти, который сопоставлен с последовательным адресным пространством. Они обычно используются для передачи данных с детализацией строки кэша и/или для изменения состояния строки кэша. Наиболее распространенными согласованными запросами являются чтение данных и кода, RFO, ItoM и выселение с обратной записью (WbMtoI)/обратная запись (MbMtoE) в LLC (только включающий кэш). Связанные запросы обслуживаются Cbo, который содержит срез LLC для указанного адреса, определенного функцией хеширования.

Если адрес декодируется в область DRAM, а срез кэша последнего уровня, присоединенный к этому Cbo, указывает, что ядру в сокете принадлежит линия (для последовательного чтения), запрос отслеживается на этом локальном ядре (это, очевидно, говорит о включительно L3 с битами фильтра отслеживания в срезе LLC по доступам из других ядер; обратите внимание, что на межсетевом соединении сервера SKL (не настольном, поскольку он все еще использует кольцо), L3 не включительно; в кеше включительно, если он действителен в 2 ядрах, тогда копия LLC действительна).

Если строка не находится в кэше (предположим, что используется режим HS с кешем Directory + OSB + HitME), то агент кэширования, который запрашивает строку кэша, не передает отслеживания. Вместо этого он направляет запрос в HA в домашнем узле, который затем отправляет отслеживания другим агентам кэширования, которые могут владеть линией. Пересылка на домашний узел добавляет задержку. Однако HA может реализовать каталог для повышения производительности. Haswell-EP также включает в себя кэши каталогов для ускорения поиска в каталоге. Однако при наличии только 14 КиБ на HA эти кэши очень малы. Поэтому в кэше HitMe хранятся только те строки кэша, которые часто передаются между узлами. Кэш каталога хранит 8-битные векторы, которые указывают, какие из 8 узлов имеют копии строки кэша. Когда запрос поступает на домашний узел, проверяется кэш каталога. Если он содержит запись для запрошенной строки, отслеживания отправляются, как указано в кэше каталога. Если запрос отсутствует в кэше каталога, HA извлекает из адреса в памяти и считывает биты каталога и отправляет отслеживания соответственно, если он изменен в некотором сокете (HA поддерживает 2-битный каталог, который хранится с каждой строкой кэша в DRAM Биты ECC. Каталог используется для фильтрации отслеживаний на удаленных сокетах или контроллерах узлов, при успешном ответе отслеживания он выделяет запись в кэше каталога; COD также сначала отслеживает кэш каталога, а затем каталог, поэтому я не знаю, что происходит с 4 сокетами в COD. только с 2 битами каталога - возможно, он может действовать как номер сокета, а не как маска, и может указывать на присутствие в 1 из 4 широковещательных доменов; HA может отправлять по одному пакету каждому узлу в указанном сокете) или напрямую отправляет данные, которые он выбрал из памяти, если никакие отслеживания не требуются и не выделяет запись. [3]

В E7 v2 HA реализован буфер памяти на 128 входов (домашний трекер) и трекер на 512 входов (резервный трекер). Все сообщения домашнего канала, поступающие на HA, будут проходить через BT (если BT включен). BT поддерживает набор FIFO для упорядочения запросов, ожидающих входа в HT, так что запись HT выделяется для самого старого ожидающего запроса, когда он становится доступным. Он также имеет буфер данных домашнего агента (набор буферов данных для передачи данных между кольцом и контроллером памяти. Он имеет 128 записей, по одной для каждого Home Tracker). HA должен декодировать соответствующий канал DRAM с адреса. Этот процесс называется "декодирование целевого адреса". Правила TAD для каждого HA будут настраиваться через CSR; правила состоят из соответствующего диапазона памяти и затем режима чередования, то есть [8: 6] усеченного адреса для индексации в списке каналов DRAM. Поскольку TAD содержит соответствующий диапазон адресов, он позволяет восстановить память для украденных диапазонов I/O-декодера: настройте декодер SAD DRAM для декодирования определенного диапазона восстановления и настройте его в записи TAD. (Процессоры рабочих станций используют TOLUD и REMAPBASE и т. Д.; установка этих регистров изменяет декодеры Cbo, которые читают с них). После того как целевой канал декодирован, запрос пересылается в соответствующий BGF (генератор пузырьков fifo). При чтении данные будут возвращены из iMC и отправлены в HADB. При записи данные будут загружены из кольца в HADB и отправлены в iMC. IMC на процессорах сервера подключается к 2 портам SMI2 на сокет для переходных плат с обычно 12 модулями DIMM и масштабируемым буфером памяти (например, Jordan Creek). HA отправляет данные обратно запрашивающему идентификатору CBo + NodeID + TX ID.

ItoM - это то место, где ядро должно записывать в строку, но оно находится в состоянии S и требует состояния E и, следовательно, другие копии должны быть признаны недействительными (я понятия не имею, почему это не называется StoE), и где RFO не владеет строкой, но запрашивает ее в состоянии E (делает недействительными другие ядра). Доктор Маккальпин дает полный обзор RFO здесь.

Нет совпадения

Если адрес не соответствует ни одному диапазону или соответствует адресной дыре (несуществующий атрибут памяти), целью по умолчанию является сокет Ubox, и сообщение кодируется как код операции NcRdPtl или NcWrPtl с нулевой длиной или все нулевые байты разрешают соответственно. Ubox обрабатывает сообщение как ошибку, ошибки могут быть настроены на возврат ответа об ошибке или нормальное завершение (возвращение всех данных для чтения или предотвращение обновления данных для записи) с или без MCA. Этот механизм используется для предотвращения внешнего незаконного доступа во время некоторых последовательностей инициализации. Агент кэширования серии 7500 не будет выдавать MCA при доступе к области адреса SAD, помеченной как несуществующая память (NXM), если доступ не является хранилищем с атрибутом памяти обратной записи (WB).


Нумерация шин на классических коммутационных схемах PCIe очень неправильная. Мой GPU фактически находится на шине 1 (как и на порте PCIe). Похоже, что встроенные коммутаторы PCIe невидимы для программного обеспечения, а порт просто выглядит как один мост контроллера PCIe/PCI-PCI на шине 0, а устройство, подключенное к порту точка-точка, появляется на новой шине № (Ethernet контроллер на шине 2 и контроллер WLAN на шине 3).

В действительности мост PCI-PCI-1 не может существовать, поскольку для него требуется подчиненная шина, которой нет в моей системе. Либо он не существует в моей системе и имеет 2 встроенных моста PCI-PCI, как это:

Или же он существует, но имеет регистры, невидимые для программиста, которые изменяются в зависимости от содержимого подчиненных мостов PCI-PCI и подчиненной шины no, которые должны быть равны 0 (а не 1 на диаграмме) (что не будет испортить маршрутизацию, имея 2 одинаковых номера шины, потому что интерфейс на противоположной стороне не был бы шиной 0, а напрямую подключен к логике PCH, поэтому для устройств всегда будет происходить транзакция, исходящая из моста 1 PCI-PCI как если бы это был корневой комплекс, не имеющий ничего, кроме этого). Эта диаграмма представляет очень вводящего в заблуждение PCH; Интерфейс PCIe не так чист, как этот, он разбивается и сопрягается чипсетом, где это необходимо (слишком дорого, чтобы иметь все встроенные мосты и контроллеры PCH в качестве отдельных устройств PCIe "точка-точка" на портах).

Похоже, что процессор и PCH функционируют как отдельные физические устройства PCIe. CPUBUSNO (1) усложняет вещи. Ubox перехватывает NcCfgRd/NcCfgWr. Если номер шины равен CPUBUSNO (0) или CPUBUSNO (1) ниже определенного номера устройства, он будет обрабатывать запрос напрямую. Если он находится на CPUBUSNO (1), а номер устройства выше определенного номера устройства или номера шины> CPUBUSNO (1), то он направляет TLP на интерфейс DMI. Так как CPUBUSNO (1) может измениться, потенциально номер шины удаляется при отправке на PCH, если шина no = CPUBUSNO (1). Если номер шины не указан, PCH декодирует его как доступ к одному из интегрированных устройств с этой функцией/номер устройства. Все не-cfg MMIO (NcRd/Wr) без NID или NID одного из HA в локальном пакете будут декодироваться с помощью. Декларированные адреса DRAM (RdData) будут приняты HA с правильным NID и сопоставлены с записями TAD

Что касается горячего подключения процессора, я понятия не имею. Связь QPI выдает SMI IntLog на кольце, когда он обнаруживает текущий поток? Как утверждается RESET #? Сокет автоматически генерирует идентификатор NodeID/APIC, как и при загрузке, но что, если APICID/CPUNODEID были изменены программным обеспечением на других сокетах? Как сокет узнает, что не проходит инициализацию MP? Как обработчик SMI знает NodeID, который был назначен? Он не может предполагать, что NodeID = ID сокета, так как CPUNODEID мог быть ранее изменен для конфликта на другом сокете. Даже когда он знает NodeID и помещает его в SAD своего текущего сокета и тестирует пространство конфигурации для корневой шины, чтобы определить, доступен ли он для записи, если NodeID не существует, что происходит с транзакцией? Может быть, у него есть TTL на ринге, и агент генерирует ошибку, если он обнаруживает флит с 0?

Дополнительные ресурсы

Такого рода вопросы могут подойти на форуме Intel Intel forum

https://www.alisaler.com/dell-xps-15-9550-aam00-la-c361p-schematic/  (здесь есть много бесплатных компонентных схем, включая выводы процессора, SuperIO, PCH). В качестве альтернативы можно искать изображения в Google, например. Блок-схема Sandy Bridge. Обратите внимание, что на этом DB21 нет никаких выводов SMI/LINT this SnB (но есть на Penryn). Это совпадает с перемещением IOAPIC в IIO, поэтому мы знаем, что INTR теперь эмулируется IIO. Это говорит о том, что контакты LINT/SMI больше не существуют (помните, руководство x2APIC - Nehalem 2008). Это означает, что NMI/SMI могут поступать только через DMI на TLP эмуляции PCIe и доставляются IIO в кольцо.

https://eprint.iacr.org/2016/086.pdf  (рассказывает о SAD, процессе загрузки UEFI, алгоритмах выбора MP/BSP, помощи микрокодов, PMH и т.д.)