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
- MSI-X не настроен драйвером, события не приходят, проверка lspci -vvv Enable и dmesg;
- RCEC не привязан к устройствам, события через polling с задержкой, проверка Associated Endpoint List;
- rasdaemon не собран с поддержкой CXL, статистика пустая, пересборка с патчами или обновление пакета;
- очередь событий переполнена, устройство генерирует overflow, чтение через GET_EVENT_RECORDS быстрее;
- маскирование AER скрывает корректируемые ошибки, деградация не видна, проверка масок через lspci -vvv и снятие масок;
- события потеряны при переподключении устройства, повторное чтение event log после каждого подключения;
- привязка прерываний не по 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-узлов обрабатывает тысячи событий в сутки без участия человека, и единственная ручная операция остаётся замена железа в плановом окне.