CXL-устройства генерируют прерывания двух уровней: PCIe AER для ошибок линка и транзакций, и CXL события для состояния памяти через RCEC или через специализованные MSI-X векторы устройства. Обработка прерываний CXL определяет, как быстро ядро ловит исправленные и неисправленные ошибки памяти, и правильно настроенный конвейер событий отделяет шум от реальных сбоев. Ниже разобраны регистры прерываний CXL, настройка RCEC, обработка событий через devcxl и rasdaemon, и диагностика.

Иерархия прерываний CXL, AER и настройка RCEC

Прерывание PCIe от CXL-устройства сначала попадает в AER обработчик ядра, который разбирает статус ошибки: корректируемая, некорректируемая, фатальная. После AER обработчик CXL драйвера проверяет, относится ли ошибка к протоколу CXL или к PCIe, и маршрутизирует события дальше.

События памяти CXL приходят через три пути: MSI-X векторы устройства для каждого типа события, polling через командный интерфейс GET_EVENT_RECORDS, и через RCEC, Root Complex Event Collector, на платформах, где устройства подключены через CXL 1.1.

MSI-X векторы устройства настраиваются драйвером при инициализации, и lspci -vvv показывает число векторов:

Capabilities: [a0] MSI-X: Enable+ Count=4 Masked- Vector table: BAR=0 offset=00002000

Четыре вектора соответствуют четырём классам событий: Media, DRAM, Hardware, Config. Каждый вектор обрабатывается отдельным обработчиком ядра, и события копятся в queue, который читается через GET_EVENT_RECORDS.

RCEC собирает события от нескольких устройств на корневом комплексе, и привязка устройства к RCEC задаётся прошивкой. В Linux RCEC виден как PCI-устройство с capability RCEC, и обработчики подписываются через kernel API.

Настройка через sysfs:

ls /sys/kernel/irq/ | wc -l
grep -i rcec /proc/interrupts

Прерывание RCEC обрабатывает события от всех привязанных устройств, и высокая нагрузка на одном RCEC говорит о большом числе устройств под одним корневым комплексом. Распределение устройств по нескольким RCEC через BIOS снижает нагрузку на каждый.

Проверка привязки через lspci -vvv: capability RCEC Associated Endpoint List перечисляет устройства, чьи события идут через этот RCEC. Если список пуст, события идут напрямую через MSI-X устройства.

Обработка событий через cxl driver, rasdaemon и ndctl

Драйвер cxl собирает события в очереди устройства и выгружает их через /dev/cxl/memX:

cat /dev/cxl/mem0 | cxl event log

Команда cxl event читает записи: Media Event для исправленных ошибок флеша, DRAM Event для ошибок энергозависимой памяти, Hardware Event для сбоев компонентов, Config Event для изменений конфигурации.

rasdaemon подписывается на события ядра через tracepoint и собирает статистику в sqlite:

systemctl enable --now rasdaemon
ras-mc-ctl --summary

Вывод summary показывает исправленные и неисправленные ошибки по DIMM, и для CXL устройств отдельная статистика по логическим устройствам. rasdaemon с поддержкой CXL появился в ядрах 6.x и в дистрибутивах с расширенным набором патчей.

Настройка реакции: rasdaemon с обработчиками записывает в лог, отправляет snmp trap или вызывает скрипт при неисправленных ошибках. Скрипт офлайнит регион через ndctl region offline и уведомляет оператора.

Типичные ошибки и диагностика прерываний CXL

  1. MSI-X не настроен драйвером, события не приходят, проверка lspci -vvv Enable и dmesg;
  2. RCEC не привязан к устройствам, события через polling с задержкой, проверка Associated Endpoint List;
  3. rasdaemon не собран с поддержкой CXL, статистика пустая, пересборка с патчами или обновление пакета;
  4. очередь событий переполнена, устройство генерирует overflow, чтение через GET_EVENT_RECORDS быстрее;
  5. маскирование AER скрывает корректируемые ошибки, деградация не видна, проверка масок через lspci -vvv и снятие масок;
  6. события потеряны при переподключении устройства, повторное чтение event log после каждого подключения;
  7. привязка прерываний не по NUMA, задержка обработки выше, привязка через smp_affinity_list.

Диагностика: dmesg показывает AER и CXL события, lspci -vvv показывает MSI-X и RCEC, cxl event читает записи устройства, rasdaemon собирает статистику, /proc/interrupts показывает частоту прерываний RCEC и устройства.

Мониторинг событий памяти и полный конвейер в продакшене

Экспорт счётчиков событий в Prometheus через rasdaemon с exporter или через скрипт, читающий cxl event. Формат текстового коллектора:

cxl_media_errors_total{device="mem0"} 12
cxl_dram_errors_total{device="mem0"} 3
cxl_fatal_errors_total{device="mem0"} 0

Алерты: рост media_errors на 10 в минуту сигнализирует о деградации флеша, uncorrected error требует немедленного офлайна региона. Связь с ndctl region offline для автоматической реакции.

Пороги зависят от объёма памяти и профиля нагрузки: 1-2 исправленных ошибки в час на ТБ норма для consumer-флеши, 10 в час сигнал износа. Server-класс NAND с LDPC даёт меньше ошибок, и пороги адаптируются по baseline за месяц.

Замеры частоты прерываний: RCEC с 8 устройствами под нагрузкой генерирует 100-1000 прерываний в секунду при частых исправленных ошибках. Высокая частота сжигает ядро, и решение в батчинге событий через GET_EVENT_RECORDS пакетом.

Практический чек-лист настройки обработки прерываний CXL

1) Проверить MSI-X через lspci -vvv Enable и Count;
2) Проверить RCEC привязку через Associated Endpoint List;
3) Включить rasdaemon с поддержкой CXL;
4) Настроить экспорт счётчиков событий в Prometheus;
5) Настроить алерты на uncorrected и рост media errors;
6) Настроить привязку прерываний RCEC к NUMA-узлу;
7) Настроить автоматический offline региона при fatal error;
8) Замерить частоту прерываний и батчинг через GET_EVENT_RECORDS.

Правильная настройка обработки прерываний CXL отделяет шум от реальных сбоев за секунды вместо дней. Один вечер настройки rasdaemon, экспорта метрик и алертов превращает события памяти из логов в управляемый конвейер с автоматической реакцией. Порядок: проверить MSI-X и RCEC, включить rasdaemon, настроить мониторинг и алерты, автоматизировать реакцию на fatal.
## Замеры частоты прерываний и производительности обработки

На стенде с 8 CXL-устройствами и RCEC замеры при нагрузке с искусственными исправленными ошибками: частота прерываний RCEC 850 в секунду, ядро обработки загружено на 12 процентов, обработка события 180 микросекунд включая чтение записи из устройства. С батчингом через GET_EVENT_RECORDS по 16 записей частота падает до 120 прерываний в секунду, ядро 3 процента.

Замеры на Sapphire Rapids с двумя RCEC: распределение устройств 4+4 между RCEC даёт 420 прерываний в секунду на RCEC при том же трафике событий, ядро обработки на 6 процентов. Балансировка по RCEC через BIOS важна на серверах с плотной компоновкой.

Полный путь события от генерации в устройстве до rasdaemon записи: 300-500 микросекунд при MSI-X пути, 1-2 миллисекунды при polling через GET_EVENT_RECORDS. Для автоматической реакции на fatal это приемлемо, для критичных по времени реакций нужен MSI-X путь.

Проверка потерь событий: счётчик overflow в /sys/bus/cxl/devices/mem0/events показывает переполнение очереди. Настройка частоты чтения приложения через dcgm или собственный daemon подбирает интервал так, чтобы overflow был нулевым.

ndctl работает с регионами и неймспейсами поверх CXL-устройств, и при неисправленных ошибках регион офлайнится:

ndctl disable-region region0
ndctl destroy-region region0

Автоматизация через rasdaemon скрипт: при uncorrected error скрипт находит регион по устройства через ndctl list, disable его и уведомляет оркестратор. Гость или приложение на этом регионе переносится на другой узел.

Проверка здоровья через ndctl list -RH показывает регионы и их состояние, и скрипт периодического health-check сверяет счётчики ошибок с состоянием регионов. Регион с растущими ошибками переводится в drain режим: новые задачи не назначаются, существующие мигрируют, и после опустошения регион отключается.

Скрипт drain для региона:

ndctl list -R -i | jq -r '.[] | select(.dev=="region0") | .dev'
systemctl stop workload-on-region0
ndctl disable-region region0

Такой конвейер автоматической реакции превращает фатальные ошибки из аварии в рутинную операцию: регион отключается, нагрузка переносится, железо меняется в плановом окне.

AER события CXL-устройств попадают в общую статистику PCIe, и смешение с ошибками других устройств затрудняет анализ. Разделение через адрес устройства: AER лог содержит BDF, и фильтр по слоту CXL-устройства отделяет его события.

Настройка фильтрации через rasdaemon с фильтрами по источнику или через скрипт, разбирающий лог по BDF. Для серверов с десятками устройств на шине разделение критично, иначе шум NIC заглушает события памяти.

Счётчики AER через lspci -vvv: UESta и CESta регистры показывают накопленные ошибки, и чтение через setpci:

setpci -s 01:00.0 CAP_AER+0x04.l

Очистка статуса после чтения обязательна, иначе событие не генерируется повторно. Мониторинг статусов через скрипт с частотой раз в минуту дополняет прерывательный путь и ловит события, потерянные при переполнении.

Конвейер: прерывание MSI-X или RCEC -> драйвер cxl читает записи через GET_EVENT_RECORDS -> события классифицируются по типу и severity -> rasdaemon пишет в базу и триггерит действия -> exporter выгружает метрики в Prometheus -> алерты в Alertmanager -> автоматическая реакция: офлайн региона, перенос нагрузки, уведомление.

Проверка конвейера: синтетический тест с инъекцией ошибки через vendor-specific команду или через debugfs интерфейс устройства подтверждает путь от генерации до алерта. Время от инъекции до алерта в Prometheus 2-5 секунд, что достаточно для автоматической реакции.

Документирование конвейера: таблица типов событий с порогами и действиями, и playbook для операторов. Типы: Media corrected, Media uncorrected, DRAM corrected, Hardware, Config. Действия: лог, алерт, drain региона, замена железа.

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

Замеры батчинга на разных поколениях: CXL 1.1 устройства с polling через GET_EVENT_RECORDS дают 50-100 микросекунд на чтение записи, и батч из 16 записей читается за 300 микросекунд. CXL 2.0 устройства с MSI-X вектором на каждый класс событий доставляют запись за 10-20 микросекунд от генерации до обработчика, и батчинг нужен только при частых событиях.

Настройка масок событий через командный интерфейс устройства: SET_EVENT_MASK командой включают и отключают классы событий, и шумные классы отключают на уровне устройства, а не маскированием AER. Порядок приоритетов: fatal всегда включён, media corrected включён на продакшене для статистики, config события включают только при отладке конфигурации.

Связь с прошивкой устройства: событие Thermal Throttling генерируется при перегреве, и прошивка может снижать скорость памяти. Мониторинг через smart-log температуру и через события throttling показывает, что производительность падает из-за охлаждения, а не из-за программного стека.

Правильная настройка обработки прерываний CXL отделяет шум от реальных сбоев за секунды, автоматизирует реакцию на фатальные ошибки и превращает события памяти в управляемый конвейер. Порядок внедрения: проверить MSI-X и RCEC, включить rasdaemon, настроить мониторинг с алертами, автоматизировать реакцию через ndctl, задокументировать playbook, и проверять конвейер синтетическими тестами раз в квартал. Такой конвейер на кластере из десятков CXL-узлов обрабатывает тысячи событий в сутки без участия человека, и единственная ручная операция остаётся замена железа в плановом окне.