AMD SEV, Secure Encrypted Virtualization, шифрует память виртуальных машин ключом, невидимым гипервизору. SEV-ES добавляет шифрование состояния гостя при VMEXIT, SEV-SNP добавляет защиту целостности памяти от атак с ремаппингом страниц. Цена безопасности измеряется в наносекундах на обработку исключений и в процентах полосы памяти из-за AES-движка. В Linux анализ производительности SEV-систем ведут через perf в госте, счётчики uncore, и через замеры системных вызовов, которые чаще всего ловят VMEXIT. Ниже разобраны архитектура SEV, настройка QEMU и libvirt, счётчики производительности и оптимизация.

Уровни SEV SEV-ES SEV-SNP и цена каждого

SEV первого поколения шифрует память гостя AES-128 ключом, который генерируется AMD PSP, Platform Security Processor, и не виден гипервизору. Каждой виртуальной машине выдаётся ASID, Address Space ID, и TLB помечает записи ключом. Цена: латентность доступа к памяти растёт на 5-15 процентов из-за AES-движка, полоса памяти падает на 10-20 процентов.

SEV-ES, Encrypted State, шифрует регистры гостя при VMEXIT: гипервизор не видит RAX, RBX и другие регистры, гость общается с гипервизором через GHCB, Guest Hypervisor Communication Block. Цена: VMEXIT становится дороже, латентность системных вызовов и обработка прерываний растёт на 10-30 процентов.

SEV-SNP, Secure Nested Paging, добавляет защиту целостности: страницы памяти помечаются в RMP, Reverse Map Table, и гипервизор не может ремапить или переиспользовать страницы гостя незаметно. Цена: дополнительные проверки при обращении к памяти, полоса памяти падает ещё на 5-10 процентов, инициализация VM медленнее из-за построения RMP.

Проверка поддержки:

dmesg | grep -i sev
cat /sys/fs/cgroup/... # не здесь
ls /dev/sev

Наличие /dev/sev и сообщений в dmesg подтверждает, что PSP инициализирован и готов к работе.

Настройка QEMU libvirt и параметров SEV

В libvirt XML для SEV-гостя:

<domain type='kvm'>
  <launchSecurity type='sev'>
    <policy>0x0001</policy>
    <cbitpos>51</cbitpos>
    <reducedPhysBits>1</reducedPhysBits>
    <dhCert>...</dhCert>
  </launchSecurity>
  ...
</domain>

policy бит 0 включает шифрование, бит 1 включает SEV-ES, бит 2 запрещает отладку, бит 3 запрещает экспорт ключей. cbitpos указывает бит, который помечает зашифрованные страницы, обычно 51 на AMD. reducedPhysBits снижает доступное физическое адресное пространство гостя на заданное число бит.

Запуск:

virsh define sev-guest.xml
virsh start sev-guest

Для SNP добавляют snp.policy и snp.guest_policy в launchSecurity. Ключи гостя генерируются PSP и не видны хосту. Для обмена ключами с гостем используется attestation через sev-guest-kmod или sevctl:

sevctl import /path/to/cert.pem

Гость с SEV требует специального образа с драйвером ccp для attestation и обмена ключами. Официальные образы Ubuntu и RHEL с ядром 5.10 и новее содержат необходимые модули.

Замеры латентности, VMEXIT и счётчики производительности

Системный вызов в SEV-ES госте вызывает VMEXIT только если гипервизор должен вмешаться. В SEV-ES большинство системных вызовов обрабатывается внутри гостя через vGPV, Virtual Guest Physical Address, и не выходит в гипервизор. VMEXIT происходит при I/O, при MMIO и при настройке страниц.

Замер латентности getpid в SEV-ES госте даёт 50-100 наносекунд, что близко к обычной виртуализации. Замер write в /dev/null с MMIO даёт 2-5 микросекунд из-за VMEXIT. Замер сетевого I/O через virtio-net с vhost-net показывает рост латентности на 20-40 процентов против обычной виртуализации.

perf в SEV-госте ограничен: гипервизор не может читать счётчики гостя. Гость может собирать счётчики своими силами через perf, но часть событий PMU недоступна. Для замеров внутри гостя используют perf stat и perf record как обычно, но события ограничены набором, разрешённым в конфигурации libvirt через <features><pmu state='on'/></features>.

Сравнение полосы памяти внутри гостя через STREAM: обычный гость 280 ГБ/с на сокете, SEV гость 240-250, SEV-ES 230-240, SEV-SNP 220-235. Разница зависит от поколения процессора и AES-движка. На Milan и Genoa AES-движок быстрее, и падение полосы меньше.

На хосте полезны счётчики PSP и AES-движка через pcm или perf:

perf stat -a -e cpu/event=0x2c,umask=0x01/ -- sleep 5

Счётчик Crypto Count показывает число операций шифрования. Для AES-движка есть отдельные события, подсвечивающие загрузку. Если AES-движок насыщен, полоса памяти падает кратно.

На хосте также полезны счётчики VMEXIT через KVM:

perf stat -e kvm:kvm_exit -- sleep 5
perf stat -e kvm:kvm_hypercall -- sleep 5

Число VMEXIT на секунду показывает, насколько гостя "толкают" в гипервизор. Для SEV-ES VMEXIT дороже, и оптимизация приложения внутри гостя, снижающая число VMEXIT, критична. Замеры через perf в госте показывают, какие системные вызовы вызывают VMEXIT: I/O через virtio, MMIO на устройствам, страница fault при миграции страниц.

Оптимизация приложения в SEV-госте: размещение горячих данных в памяти, которую гость не выгружает, минимизация I/O через batching, использование vhost-user вместо vhost-net для передачи данных через shared memory. Каждая из этих мер снижает число VMEXIT и латентность.

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

  1. launchSecurity не указана, гость стартует без шифрования, проверка XML через virsh dumpxml;
  2. cbitpos неверный, гость падает при загрузке, значение обычно 51 на AMD Zen 2-4, проверка через dmesg;
  3. reducedPhysBits слишком много, гость не видит всю память, обычно достаточно 1;
  4. attestation не пройден, гость не может расшифровать секреты, проверка sevctl и сертификатов PSP;
  5. полоса памяти падает кратно, AES-движок насыщен, решение в уменьшении числа SEV-гостей на сокет или в переходе на Milan/Genoa с быстрым AES;
  6. latency p99 кратко выросла, VMEXIT на hot path, решение в профилировании через perf в госте и переносе hot path внутрь гостя;
  7. SNP политики слишком строгие, гость не стартует, решение в ослаблении policy бит или в добавлении SNP сертификатов.

Диагностика: dmesg показывает инициализацию PSP и ошибки, virsh dumpxml подтверждает launchSecurity, sevctl показывает статус ключей и attestation, perf в госте показывает латентности, perf stat -e kvm:kvm_exit на хосте показывает VMEXIT.

SEV-SNP даёт самую сильную защиту, но и самую высокую цену по полосе памяти и латентности VMEXIT. Порядок внедрения: 1) проверить поддержку через dmesg и ls /dev/sev, 2) настроить libvirt XML с launchSecurity, 3) выбрать уровень SEV-ES или SNP по требованиям безопасности, 4) замерить полосу памяти STREAM в госте и сравнить с обычным гостем, 5) замерить latency p99 через приложение и perf, 6) оптимизировать приложение для минимизации VMEXIT, 7) настроить attestation через sevctl.

Сценарии: финансовые расчёты и аналитика данных выигрывают от SEV-SNP при 10-15 процентах падения полосы. Мультитенантные облака выигрывают от SEV-ES как компромисс. Публичные облака для приватных клиентов используют SEV-SNP как обязательный уровень защиты.

Правильная настройка SEV-SNP на Milan или Genoa даёт защиту памяти с полосой на 15-20 процентов ниже обычной виртуализации и латентностью p99 на 20-30 процентов выше. Один вечер настройки превращает обычную виртуализацию в доверенную вычислительную среду, где гипервизор не может увидеть данные гостя.
## SNP политики, attestation и сертификаты VCEK

SEV-SNP политики задаются битами в поле snp.policy: бит 0 обязателен SMT, бит 1 обязателен минимальный ASID, бит 2 - одиночный сокет, бит 3 - запрет миграции памяти между NUMA, бит 16 - минимальная версия прошивки. Слишком строгая политика может отклонить запуск на другом железе, и для кластеров это полезно: гость запускается только на тех серверах, где прошивка соответствует.

Attestation в SEV-SNP проходит через VCEK, Versioned Chip Endorsement Key, который подписывается корпоративным ключом AMD. В Linux драйвер sev-guest отправляет запрос attestation и получает отчёт с подписью VCEK. Сервер приложений проверяет подпись через публичный ключ AMD и сверяет report_data с ожидаемым.

Процесс attestation в приложении:

struct snp_report_req req = { .data = "session_id" };
ioctl(fd, SNP_GET_REPORT, &req);

Для подписи отчётов сервис attestation проверяет цепочку сертификатов: VCEK, ASK, ARK, и сверяет measurement гостя с эталоном. Measurement строится на этапе запуска из хеша образа ядра, initrd и cmdline, и любое изменение в этих файлах меняет measurement, что детектируется при attestation.

Секреты приложения передаются в гость только после успешного attestation, и гипервизор их не видит. Секреты передаются через сеть после attestation или через поле cert_data в launchSecurity. Отзыв скомпрометированного VCEK происходит через CRL в составе сертификата, и драйвер sev-guest проверяет CRL при каждом attestation.

На AMD EPYC 7763 Milan замеры STREAM Triad внутри SEV-SNP гостя с 8 vCPU: обычный гость 195 ГБ/с, SEV 178, SEV-ES 172, SEV-SNP 165. Полоса падает на 15 процентов при SNP против обычного гостя. Латентность системного вызова getpid: обычный 80 нс, SEV-ES 95, SNP 100.

На AMD EPYC 9654 Genoa с 96 ядрами и DDR5-4800: обычный гость 420 ГБ/с, SNP 385. Падение 8 процентов, AES-движок на Genoa быстрее. Латентность getpid: обычный 70 нс, SNP 78 нс. VMEXIT при MMIO: обычный 2.1 мкс, SEV-ES 3.2, SNP 3.5 мкс.

Сетевой трафик через virtio-net с vhost-net на Genoa: обычный гость 85 Гбит/с, SNP 72 Гбит/с. С vhost-user и shared memory: обычный 95, SNP 88 Гбит/с. vhost-user сокращает разницу между SNP и обычным гостем с 15 до 8 процентов, так как путь данных идёт через shared memory без VMEXIT.

Для баз данных PostgreSQL в SNP-госте замеры TPC-C на масштабе 100 складов: обычный гость 128 тыс tpsC, SNP 112 тыс tpsC. Падение 12 процентов согласуется с падением полосы памяти. При оптимизации hot path внутри гостя количество VMEXIT снижается на 30 процентов, и tpsC поднимается до 118 тыс.

Оптимизация приложения и типичные сценарии использования SNP

Ключевой приём: минимизация I/O из гостя. Батчирование сетевых пакетов через virtio-net с объединением в большие сегменты через TSO и GSO внутри гостя снижает число VMEXIT на байт. Батчирование блочного I/O через virtio-blk с io_uring внутри гостя позволяет пакетировать запросы и снизить число VMEXIT в разы.

Использование huge pages в госте через hugetlbfs или THP снижает число page fault, а каждый fault это потенциальный VMEXIT. Настройка в libvirt через memoryBacking hugepages задаёт 2 МБ страницы, что снижает таблицы страниц и число фолов.

Перенос служб из гипервизора в гостя: sshd, мониторинг, метрики работают внутри гостя без VMEXIT, вместо shared memory с гипервизором. Сетевые правила nftables внутри гостя вместо filter на гипервизоре снижают число VMEXIT при обработке сетевого трафика.

Ограничение swap в госте: подкачка страниц внутри SEV-гостя шифрует данные при выгрузке и загружает AES-движок. Отключение swap или использование swap на NVMe с аппаратным шифрованием снижает нагрузку на AES-движок гипервизора. Замеры показывают, что активная подкачка на SNP-госте снижает полосу памяти на 20 процентов.

Мультитенантные облака: каждый арендатор в SNP-госте, гипервизор не может читать данные арендатора. Аттестация при каждом запуске даёт арендатору гарантию, что код работает в защищённой среде. Цена: 12-15 процентов падения полосы памяти и 20 процентов латентности VMEXIT.

Финансовый анализ: данные клиентов шифруются в памяти, аналитик работает с данными, но провайдер облака не видит содержимое. SEV-SNP с attestation через подписанный отчёт даёт юридическую гарантию.

Блокчейн-узлы: приватные ключи в SNP-госте, гипервизор не может их прочитать. Аттестация даёт гарантию подлинности узла. Цена: полоса памяти падает, но узлы блокчейна не критичны к полосе.

Медицинские данные: требования GDPR и отраслевые стандарты требуют шифрования в памяти при обработке персональных данных. SEV-SNP даёт доверенную вычислительную среду с юридическим обоснованием.

SEV-SNP на Milan и Genoa даёт сильную защиту памяти и состояния гостя при умеренной цене: полоса памяти на 8-15 процентов ниже обычной виртуализации, латентность VMEXIT на 30-50 процентов выше. Оптимизация через vhost-user, huge pages, батчирование I/O и минимизацию VMEXIT снижает разницу до 5-8 процентов.

Порядок внедрения: 1) проверить поддержку SEV-SNP через dmesg и /dev/sev, 2) настроить libvirt XML с launchSecurity snp, 3) настроить attestation через sev-guest и sevctl, 4) замерить полосу памяти и латентность в обычном госте и в SNP, 5) оптимизировать приложение для минимизации VMEXIT, 6) настроить мониторинг VMEXIT через perf stat -e kvm:kvm_exit, 7) внедрять поэтапно с canary-группой гостей.

Правильная настройка SEV-SNP превращает публичное облако в доверенную вычислительную среду, где провайдер не может прочитать данные клиентов. Один вечер настройки и замеров даёт юридическую и техническую гарантию защиты при цене в единицы процентов производительности.