Обнаружение функции AVX с использованием SIGILL против ЦП
Я пытаюсь определить эффективный метод определения доступности AVX и AVX2 на процессорах Intel и AMD. Я был немного удивлен, узнав, что он ближе к SSE и XSAVE, когда читал Руководство по разработке программного обеспечения Intel, том I (УПРАВЛЕНИЕ СОСТОЯНИЕМ С ИСПОЛЬЗОВАНИЕМ XSAVE FEATURE SET, стр. 310).
Корпорация Intel публикует некоторый код для определения доступности AVX при включенном AVX? Код показан ниже, и это не слишком больно. Проблема в том, что Visual Studio - это болевая точка, потому что нам нужно переместить код из файлов C/C++ ind в файлы ASM для X64.
Другие, кажется, принимают SIGILL
подход к обнаружению доступности AVX. Или они невольно используют SIGILL
метод. Смотрите, например, SIGILL по инструкции AVX.
Мой вопрос, безопасно ли использовать SIGILL
метод определения доступности AVX? Здесь "безопасный" означает, что инструкция AVX не будет генерировать SIGILL
когда процессор и ОС поддерживают AVX; и это сгенерирует SIGILL
иначе.
Приведенный ниже код предназначен для 32-разрядных машин и из блога Intel. Включен ли AVX? Меня беспокоит манипулирование управляющими регистрами. Чтение и запись некоторых управляющих регистров X86 и ARM иногда требуют привилегий суперпользователя / администратора. Это причина, по которой я предпочитаю SIGILL
(и избегайте контрольных регистров).
; int isAvxSupported();
isAvxSupported proc
xor eax, eax
cpuid
cmp eax, 1 ; does CPUID support eax = 1?
jb not_supported
mov eax, 1
cpuid
and ecx, 018000000h ; check 27 bit (OS uses XSAVE/XRSTOR)
cmp ecx, 018000000h ; and 28 (AVX supported by CPU)
jne not_supported
xor ecx, ecx ; XFEATURE_ENABLED_MASK/XCR0 register number = 0
xgetbv ; XFEATURE_ENABLED_MASK register is in edx:eax
and eax, 110b
cmp eax, 110b ; check the AVX registers restore at context switch
jne not_supported
supported:
mov eax, 1
ret
not_supported:
xor eax, eax
ret
isAvxSupported endp
1 ответ
Сначала немного теории.
Для использования инструкций AVX необходимо выполнить несколько условий:
CR4.OSXSAVE[bit 18]
должно быть 1.
Этот флаг устанавливается ОС, чтобы сигнализировать процессору, что он поддерживаетxsave
расширения.xsave
расширения - единственный способ сохранить состояние AVX (fxsave
не сохраняетymm
регистры) и таким образом ОС должна их поддерживать.XCR0.SSE[bit 1]
а такжеXCR0.AVX[bit 2]
должно быть 1.
Эти флаги устанавливаются ОС для сигнализации процессору о том, что он поддерживает сохранение и восстановление состояний SSE и AVX (черезxsave
).CPUID.1:ECX.AVX[bit 28] = 1
Конечно, процессор должен поддерживать расширения AVX в первую очередь.
Все эти регистры читаются в режиме пользователя, но для CR4
,
К счастью, немного CR4.OSXSAVE
отражается в CPUID.1:ECX.OSXSAVE[bit 27]
и, таким образом, вся информация доступна в режиме пользователя. Никакие привилегированные инструкции не участвуют.
Для использования расширений AVX оба оборудования (CPUID.1:ECX.AVX
а также CPUID.1:ECX.XSAVE
) и ОС (CPUID.1:ECX.OSXSAVE
, XCR0.SSE
а также XCR0.AVX
) поддержка должна присутствовать.
Поскольку ОС сигнализирует о своей поддержке xsave
только при наличии аппаратной поддержки тестирование первого достаточно.
Для расширений AVX, тестирование CPUID.1:ECX.AVX
все еще рекомендуется, так как ОС может установить XCR0.AVX
даже если AVX не поддерживается.
Это приводит к использованию официального и настоятельно рекомендуемого алгоритма Intel:
который является тем же самым, который Вы отправили.
Отлов исключений для определения поддержки расширений AVX также будет гарантирован, если вы гарантируете, что обнаруженное исключение - #UD.
Например, выполнив vzeroall
единственными возможными исключениями являются #UD и #NM.
Первый бросается только тогда, когда:
Если XCR0[2:1] ≠ '11b'.
Если CR4.OSXSAVE[бит 18]=0.
Если CPUID.01H.ECX.AVX[бит 28]=0.
Если VEX.vvvv ≠ 1111B.
Таким образом, если у вас нет испорченного ассемблера / компилятора, это в точности соответствует условиям, указанным в начале.
Последнее выбрано как оптимизация для сохранения состояния AVX и, как таковое, не доступно для программ пользовательского режима ОС.
Тем самым ловить SIGILL
на vzeroall
или подобное также будет делать.