На каждой платформе AMD рядом с большими ядрами Zen трудится крошечный сопроцессор, о котором вспоминают, когда что-то перестаёт работать. В графиках загрузки его нет, но именно он выдаёт ключи шифрования памяти, обслуживает fTPM и управляет конфиденциальными виртуальными машинами. Речь о Platform Security Processor, сокращённо PSP, который в Linux представлен модулем ядра ccp. Разберём, как увидеть эту подсистему глазами операционной системы, что она забирает из бюджета производительности и как измерить её вклад командами от lspci и dmesg до openssl speed и perf.
Кто на самом деле шифрует память и держит ключи на платформах AMD
PSP представляет собой 32-битный контроллер семейства ARM Cortex-A5, распаянный в кристалл вместе с вычислительными ядрами. У него собственная прошивка, обновляемая вместе с BIOS через блоки AGESA, и набор обязанностей: fTPM, ключи шифрования памяти, команды SEV для гипервизора, доверенная среда TEE, защищённое хранилище и аппаратный генератор случайных чисел. Само шифрование выполняет контроллер памяти: в SME и SEV используется AES с ключом 128 бит в режиме XTS, а PSP лишь создаёт ключи и ведёт жизненный цикл гостей.
Тонкости видны уже в параметрах запуска виртуальной машины. У 48-битной физической адресации бит шифрования C занимает позицию 47, поэтому для SEV фигурирует cbitpos=47, а в свежих примерах для SEV-SNP, где адресное пространство шире, фигурирует cbitpos=51. Поддержка SEV определяется через CPUID функции 0x8000001f: бит 1 в регистре EAX говорит о наличии технологии, а значение ECX показывает, сколько шифрованных гостей платформа держит одновременно. Каждому гостю выдаётся ASID в диапазоне от 1 до этого максимума, потому что ключ шифрования связан именно с ним. На старте всё выглядит незаметно, но у этой тихой подсистемы есть свой характер, и дальше станет видно, где он проявляется.
Модуль ccp в ядре Linux и его след в dmesg и sysfs
За PSP в ядре отвечает связка модулей: базовый ccp, разгрузочная надстройка ccp_crypto и полностью встроенные в базовый модуль части psp и sev. Найдём устройство на шине:
lspci -nn | grep -i -e "Security" -e "1022:1456" -e "1022:1486"
sudo dmesg | grep -i -e ccp -e psp -e sev
lsmod | grep ccp
sudo modprobe ccp
Идентификаторы зависят от поколения кристалла: 0x1456 принадлежит Zen первого поколения и серверным Naples, 0x1486 замечен на Matisse, 0x15DF на APU, 0x14CA на Zen 3, а 0x1537 достался старым кристаллам с третьей версией движка. Типичная строка lspci выглядит так:
0b:00.1 Co-processor [1080]: Advanced Micro Devices, Inc. [AMD] Family 17h (Models 70h-7fh) Platform Security Processor [1022:1486]
После загрузки драйвера dmesg показывает читаемую телеметрию. Драйвер пишет строки вида "psp enabled" и "sev enabled", сообщает версию прошивочного API строкой "SEV API:1.51 build:21", а если шифрование памяти выключено в BIOS, честно признаётся: "SEV: memory encryption not enabled by BIOS", а после обновления BIOS сообщает "SEV firmware updated from 1.50.0 to 1.51.0". Драйвер запрашивает два вектора MSI-X и 48-битную маску DMA, при отказе падая до 32 бит.
Состояние подсистемы читается из sysfs. В каталоге устройства лежат файлы bootloader_version и tee_version с версиями загрузчика и доверенной среды, управление SEV идёт через символьный узел /dev/sev, а аппаратный генератор случайных чисел виден как hwrng с именем ccp-0-rng:
cat /sys/bus/pci/devices/0000:0b:00.1/bootloader_version
ls -l /dev/sev
cat /sys/class/hwrng/hwrng0/rng_available
Если ядро собрано с опцией CRYPTO_DEV_CCP_DEBUGFS, появляется каталог /sys/kernel/debug/ccp с файлами info и stats, где видна статистика операций. Полный список параметров показывает modinfo: у ccp это nqueues и max_devs, у части sev таймауты psp_cmd_timeout и psp_probe_timeout и путь init_ex_path к файлу инициализации прошивки. Подсистема, которую никто не конфигурирует годами, на деле имеет ряд ручек, и часть из них прямо влияет на скорость.
Криптографическая разгрузка ccp_crypto и когда она оправдана
Надстройка ccp_crypto регистрирует в криптографическом фреймворке ядра варианты ecb-aes-ccp, cbc-aes-ccp, ctr-aes-ccp, xts-aes-ccp, gcm-aes-ccp, cmac-aes-ccp, des3-ccp, sha1-ccp вплоть до sha512-ccp, их HMAC-обёртки и rsa-ccp с модулями до 16 КБ на новых движках. Все они регистрируются с приоритетом 300, а очередь запросов вмещает до 100 команд. Проверить, зарегистрированы ли варианты ccp, проще всего по файлу /proc/crypto:
grep -c ccp /proc/crypto
grep -B4 "xts-aes-ccp" /proc/crypto
Кому достанется работа, решает приоритетная гонка криптографического API среди всех зарегистрированных вариантов. Поэтому честный замер здесь делается сравнением до и после:
sudo cryptsetup benchmark
sudo rmmod ccp_crypto
sudo cryptsetup benchmark
sudo modprobe ccp_crypto
На CPU с инструкциями AES-NI программные варианты AES обычно выигрывают у сопроцессора: команда AES на большом ядре Zen быстрее, чем пересылка данных в крошечный движок. Ориентиром служит userspace-замер openssl, который опирается только на инструкции центрального процессора и ccp не касается:
openssl speed -evp aes-256-xts
openssl speed -evp aes-128-xts -multi $(nproc)
На Ryzen поколения Zen 3 одиночный поток выдаёт на AES-256-XTS порядка четырёх гигабайт в секунду, и это верхняя планка для сравнения с результатом cryptsetup. Если с загруженным ccp_crypto бенчмарк проседает в разы, ядро выбирает сопроцессор там, где он медленнее, и разгрузку лучше отключить точечно. Для этого у модуля есть параметры aes_disable, sha_disable, des3_disable и rsa_disable, задаваемые строкой options ccp_crypto sha_disable=1 в файле /etc/modprobe.d/ccp-crypto.conf. Настоящая ценность разгрузки проявляется, когда больших ядер мало и их хочется освободить, и на встроенных ARM64-кристаллах вроде Opteron A1100, где драйвер ccp собирается ради такого случая. Для массового десктопа с AES-NI честный ответ чаще звучит как "не трогайте, просто не мешайте", и умение проверить это за пять минут дорогого стоит.
fTPM в Linux, от устройств в /dev до прошивочных сюрпризов
Прошивка fTPM исполняется на том же сопроцессоре, а операционная система видит её как ACPI-устройство с идентификатором MSFT0101, с которым работает драйвер tpm_crb. Современное ядро создаёт два узла: /dev/tpm0 для прямых команд и /dev/tpmrm0 для менеджера ресурсов, который управляет параллельным доступом из разных служб:
ls -l /dev/tpm*
sudo dmesg | grep -i tpm
tpm2_getcap properties-fixed | head -20
tpm2_pcrread sha256:0
Версию прошивки подсказывают строки FIRMWARE_VERSION в выводе tpm2_getcap properties-fixed. Цена операций здесь принципиально иная: каждая команда проходит через шину к 32-битному ARM-контроллеру, поэтому цикл из пятидесяти чтений PCR на типичном Ryzen занимает несколько секунд, что даёт десятки миллисекунд на вызов вместе с накладными расходами утилиты. Для дискового шифрования с запечатыванием ключей в PCR это неважно, операция выполняется один раз при монтировании, и systemd-cryptenroll с параметром --tpm2-device=/dev/tpmrm0 начиная с systemd 248 делает её почти прозрачной. А вот если приложение дёргает TPM постоянно, задержки складываются в ощутимый налог.
С fTPM связан громкий инцидент, показывающий цену этой подсистемы. В 2022 году AMD подтвердила, что прошивка fTPM на части платформ Ryzen вызывает периодические паузы длиной до секунды в играх и бенчмарках, и выпустила исправление в AGESA 1.2.0.7. Мораль простая: если система использует fTPM, обновления BIOS не косметика, а способ сохранить плавность. При сомнениях стоит сравнить поведение с дискретным TPM-модулем или отключить fTPM в BIOS, если запечатывание ключей не нужно. Мало кто ожидает от микропрошивки TPM влияния на частоту кадров, но именно такие сюрпризы делают тему PSP интересной.
SEV и цена конфиденциальных виртуальных машин
Самая тяжёлая нагрузка на PSP приходит вместе с SEV. Готовность хоста проверяется в два действия:
cat /sys/module/kvm_amd/parameters/sev
cat /sys/module/kvm_amd/parameters/sev_es
История поддержки в основных ядрах выглядит так: SEV для хоста появился в 4.16 в 2018 году, гостевая поддержка SEV-ES в 5.10 в 2020 году, серверная часть SEV-SNP в 6.9 в 2024 году, а QEMU умеет SEV начиная с версии 2.12. Запуск конфиденциального гостя в современных версиях QEMU задаётся объектом sev-guest:
qemu-system-x86_64 \
-machine q35,confidential-guest-support=sev0 \
-object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1
Добавление policy=0x5 превращает гостя в SEV-ES, а для SNP используется объект sev-snp-guest с cbitpos=51. Обратная сторона конфиденциальности измерима. При старте гостя гипервизор шифрует всю его память командами LAUNCH_UPDATE_DATA, поэтому время запуска растёт пропорционально объёму RAM: гость с восемью гигабайтами стартует заметно дольше обычного. После старта шифрование выполняет контроллер памяти, вычислительные задачи почти не замечают разницы, а тесты, интенсивно работающие с большими массивами данных, проседают сильнее, поскольку часть пропускной способности памяти уходит на AES. В SEV-ES состояние регистров виртуального процессора зашифровано, чувствительные выходы из гостя обрабатываются через механизм #VC и разделяемый буфер GHCB, что добавляет ловушек и задержек, а гипервизор лишается инструментов: SEV-ES не поддерживает SMM и перезагрузку и требует внутриядерного irqchip. Живая миграция через команды SEND_START, SEND_UPDATE_DATA и SEND_FINISH перешифровывает весь объём памяти и потому идёт медленнее обычной. Число одновременных гостей ограничено значением из CPUID, на платформах EPYC речь идёт о сотнях виртуальных машин. Замер прост: поднять две идентичные виртуальные машины, обычную и конфиденциальную, и прогнать внутри одинаковый набор из openssl speed, fio и вычислительно плотного теста. По опыту независимых измерений, разница в чистых вычислениях укладывается в единицы процентов, а память-зависимые тесты теряют заметно больше, и этот разброс решает, подходит ли SEV конкретной нагрузке.
Методика замеров, которая показывает честную картину
Цифры о подсистемах, которые почти не отражаются в привычных графиках, легко получить искажёнными, поэтому методика здесь важнее любого отдельного теста. Первый шаг, зафиксировать частоты:
sudo cpupower frequency-set -g performance
Второй шаг, разложить замеры по уровням. Уровень инструкций процессора показывает openssl, уровень ядра показывает cryptsetup benchmark, уровень диска показывает fio поверх LUKS-контейнера, а вклад сопроцессора в загрузку CPU оценивает perf:
sudo perf stat -e cycles,instructions,cache-misses openssl speed -evp aes-256-xts 2>&1 | tail -6
sudo fio --name=crypttest --filename=/dev/mapper/cryptdisk --rw=write --bs=1M --direct=1 --numjobs=4 --runtime=30 --time_based --group_reporting
Третий шаг, парность. Каждый замер выполняется трижды с выгрузкой и загрузкой ccp_crypto между сериями, чтобы разница отражала драйвер, а не нагрев или кэш. Для прошивочной части тем же шаблоном измеряется цикл чтений PCR, для SEV сравниваются обычный и конфиденциальный гости на одном железе. Результаты сводятся в таблицу из трёх столбцов: тест, без ccp, с ccp. Протокол занимает полчаса и даёт больше пользы, чем абстрактный бенчмарк с чужого железа, потому что поведение подсистемы зависит от конкретного кристалла, версии AGESA и даже от версии ядра, где приоритеты алгоритмов периодически пересматриваются. Честно говоря, дешевизна протокола удивляет: сложная на вид тема измеряется тремя знакомыми командами.
Практические рекомендации и настройка платформы
Набор действий, который стоит прогнать на любой AMD-платформе под Linux, укладывается в короткий список:
- Найти устройство через lspci -nn по идентификаторам 1022 и прочитать bootloader_version и строки "SEV API" в dmesg;
- Сравнить cryptsetup benchmark с загруженным и выгруженным ccp_crypto и в случае просадки задать точечные параметры aes_disable или sha_disable в /etc/modprobe.d;
- Если fTPM используется, обновить BIOS до прошивки с исправлением пауз и проверить версию через tpm2_getcap properties-fixed;
- Для SEV-хоста заранее оценить время старта гостя и память-зависимые бенчмарки, а миграцию планировать с запасом на перешифровку;
- Повторить полную серию замеров после каждого обновления ядра или BIOS, поскольку приоритеты и прошивки меняют баланс.
Подсистема продолжает расти: в исходниках ядра рядом с классическими файлами драйвера появились модули sev-dev-tsm и sev-dev-tio для доверенного ввода-вывода PCIe-устройств в связке с SNP, и это обещает PSP ещё больше обязанностей. Вполне вероятно, что через пару обновлений сегодняшние неочевидные эффекты станут заметнее, а те, кто однажды прогнал протокол по своей платформе, получат запасные цифры для сравнения. Тихий сопроцессор перестаёт быть чёрным ящиком в тот момент, когда на него смотрят глазами lspci, dmesg и perf, и его производительность становится управляемой величиной, а не сюрпризом.