В архитектуре x86 инструкция CPUID (идентифицированная CPUID
кодом операции ) является дополнительной инструкцией процессора (ее название происходит от идентификации ЦП ), позволяющей программному обеспечению обнаруживать подробную информацию о процессоре. Он был представлен Intel в 1993 году с выпуском процессоров Pentium и 486 с усовершенствованной версией SL . [1]
Программа может использовать для определения типа процессора и того, реализованы CPUID
ли такие функции, как MMX / SSE .
До того, как инструкция стала общедоступной CPUID
, программисты писали эзотерический машинный код , который использовал незначительные различия в поведении ЦП, чтобы определить марку и модель процессора. [2] [3] С появлением процессора 80386 EDX при сбросе указывал версию, но ее можно было прочитать только после сброса, и у приложений не было стандартного способа чтения значения.
За пределами семейства x86 разработчикам в большинстве случаев по-прежнему приходится использовать эзотерические процессы (включая синхронизацию инструкций или триггеры сбоев ЦП) для определения имеющихся изменений в конструкции ЦП.
В семействе Motorola 680x0, где никогда не было CPUID
никаких инструкций, некоторые конкретные инструкции требовали повышенных привилегий. Их можно использовать для различения различных членов семейства процессоров. В Motorola 68010 команда MOVE из SR стала привилегированной. Это заметное изменение инструкций (и конечного автомата) позволило 68010 соответствовать требованиям виртуализации Попека и Голдберга . Поскольку 68000 предлагал непривилегированный MOVE от SR, два разных ЦП можно было отличить по срабатыванию состояния ошибки ЦП.
Хотя CPUID
инструкция специфична для архитектуры x86, другие архитектуры (например, ARM) часто предоставляют встроенные регистры, которые можно читать заданными способами для получения информации того же типа, что и инструкция x86 CPUID
.
Код CPUID
операции 0F A2
: .
На языке ассемблера инструкция CPUID
не принимает никаких параметров, поскольку CPUID
неявно использует регистр EAX для определения основной категории возвращаемой информации. В современной терминологии Intel это называется листом CPUID. CPUID
следует вызывать EAX = 0
первым, так как при этом в регистре EAX будет сохранен самый высокий параметр вызова EAX (лист), который реализует ЦП.
Для получения расширенной информации о функции CPUID
следует вызывать ее с установленным старшим битом EAX. Чтобы определить наивысший параметр вызова расширенной функции, вызовите CPUID
с помощью EAX = 80000000h
.
CPUID оставляет больше 3, но меньше 80000000 и доступен только тогда, когда регистры конкретной модели имеют IA32_MISC_ENABLE.BOOT_NT4 [бит 22] = 0 (что так по умолчанию). Как следует из названия, Windows NT 4.0 до SP6 не загружалась должным образом, если этот бит не был установлен, [4] но более поздним версиям Windows он не нужен, поэтому базовые листья, превышающие 4, можно считать видимыми в текущих системах Windows. По состоянию на сентябрь 2023 года [обновлять]базовый срок действия отпусков увеличивается до 20 часов, но информация, возвращаемая некоторыми отпусками, не раскрывается в общедоступной документации, т.е. они «зарезервированы».
Некоторые из недавно добавленных листьев также имеют подлисты, которые выбираются через регистр ECX перед вызовом CPUID
.
Возвращает строку идентификатора производителя ЦП — двенадцатизначную строку ASCII, хранящуюся в EBX, EDX, ECX (именно в этом порядке). CPUID
В EAX возвращается самый высокий базовый параметр вызова (наибольшее значение, которое может быть установлено EAX перед вызовом ).
Вот список процессоров и реализованных функций.
Ниже приведены известные строки идентификатора производителя процессора:
"AMDisbetter!"
– ранние инженерные образцы процессора AMD K5"AuthenticAMD"
– АМД"CentaurHauls"
– IDT WinChip/ Centaur (включая некоторые процессоры VIA и Zhaoxin)"CyrixInstead"
– Cyrix / ранние компании STMicroelectronics и IBM"GenuineIntel"
– Интел"GenuineIotel"
— Интел (редко) [5]"TransmetaCPU"
– Трансмета"GenuineTMx86"
– Трансмета"Geode by NSC"
– Национальный полупроводник"NexGenDriven"
– НексГен"RiseRiseRise"
- Рост"SiS SiS SiS "
– СиС"UMC UMC UMC "
– УМС"VIA VIA VIA "
- С ПОМОЩЬЮ"Vortex86 SoC"
— ДМ&П Вортекс86" Shanghai "
- Чжаосинь"HygonGenuine"
- Хайгон"Genuine RDC"
– RDC Semiconductor Co. Ltd. [6]"E2K MACHINE"
– МЦСТ Эльбрус [7]Ниже приведены строки идентификаторов, используемые программными ядрами ЦП с открытым исходным кодом :
"GenuineAO486"
— ЦП ao486 (старый) [8] [9]"MiSTer AO486"
— ЦП ao486 (новый) [10] [9]"GenuineIntel"
– ядро v586 [11] (идентично строке идентификатора Intel)Ниже приведены известные строки идентификаторов виртуальных машин:
"bhyve bhyve "
- да"KVMKVMKVM\0\0\0"
– KVM , \0 обозначает символ ASCII NUL."TCGTCGTCGTCG"
– КЕМУ"Microsoft Hv"
– Microsoft Hyper-V или Windows Virtual PC"MicrosoftXTA"
– Microsoft x86-ARM [12]" lrpepyh vr"
– Параллели (возможно , это должно быть «prl Hyperv», но оно кодируется как «lrpepyh vr» из-за несоответствия порядка байтов )"VMwareVMware"
– VMware"XenVMMXenVMM"
— Зен ХВМ"ACRNACRNACRN"
– Проект АКРН" QNXQVMBSQG "
— Гипервизор QNX"GenuineIntel"
– Apple Розетта 2 [13]"VirtualApple"
– Новые версии Apple Rosetta 2Например, на процессоре GenuineIntel значения, возвращаемые в EBX, — это 0x756e6547, EDX — 0x49656e69, а ECX — 0x6c65746e. В следующем примере кода отображается строка идентификатора поставщика, а также наивысший вызывающий параметр, реализуемый ЦП.
.intel_syntax без префикса .текст.m0: .string "ЦП: %x\n" .m1: .string "Наибольший реализованный номер базовой функции: %i\n" .m2: .string "Идентификатор поставщика: %s\n" .globl основной основной:нажмите r12 мов eax , 1 суб рсп , 16 идентификатор процессора lea rdi , .m0 [ rip ] mov esi , eax вызвать printfперемещение eax , 0 идентификатор процессораlea rdi , .m1 [ rip ] mov esi , eax мов r12d , edx мов ebp , ecx вызвать printf мов 3 [ rsp ], ebx Леа Рси , 3 [ RSP ] lea rdi , .m2 [ рип ] мов 7 [ рсп ], r12d мов 11 [ рсп ], ebp вызвать printfдобавить рсп , 16 поп р12 в отставку .section .note.GNU - стек , "" , @ progbits
На некоторых процессорах можно изменить строку идентификатора производителя, сообщаемую CPUID.(EAX=0), путем записи новой строки идентификатора в определенные MSR ( регистры, зависящие от модели ) с помощью WRMSR
инструкции. Это использовалось на процессорах сторонних производителей для включения функций и оптимизаций, которые были отключены в программном обеспечении для процессоров, которые не возвращают GenuineIntel
строку идентификатора. [14] Известно, что процессоры, обладающие такими MSR, включают:
Это возвращает информацию о шагах , модели и семействе ЦП в регистре EAX (также называемом сигнатурой ЦП ), флаги функций в регистрах EDX и ECX, а также дополнительную информацию о функциях в регистре EBX. [21]
По состоянию на октябрь 2023 года известны следующие идентификаторы семейства процессоров x86: [23]
CPUID
инструкцию, однако он возвращает идентификатор семейства 3h
в значении сброса EDX.8h
Информация о процессоре и флаги функций зависят от производителя, но обычно значения Intel используются другими производителями в целях совместимости.
CPUID
с конечным индексом (EAX) больше 0 может оставить EBX и ECX неизмененными, сохранив свои старые значения. По этой причине рекомендуется обнулить EBX и ECX перед выполнением CPUID
с конечным индексом 1.К процессорам, демонстрирующим такое поведение, относятся Cyrix MII [37] и IDT WinChip 2. [38]
CentaurHauls
и GenuineTMx86
) RiseRiseRise
инструкция CMPXCHG8B
всегда поддерживается, однако бит функции для инструкции может быть не установлен. Это обходной путь ошибки в Windows NT. [39]AuthenticAMD
семейство 5, модель 0) бит 9 EDX использовался для обозначения поддержки PGE. Начиная с модели K5 Model 1, это было перенесено в бит 13. [40]GenuineIntel
семейство 6, модель 1) бит 11 EDX недействителен — бит, который он установил, но инструкции SYSENTER
и SYSEXIT
не поддерживаются на Pentium Pro. [42]FCMOV
и FCOMI
инструкции доступны только в том случае, если имеется встроенный FPU x87 (обозначается битом 0 EDX).119h
( BBL_CR_CTL
) значение 1. В результате CPUID.(EAX=1):EDX[бит 18] вернет 0.В старой документации этот бит часто указывается как флаг « Технологии Hyper-Threading » [47] . Однако, хотя этот флаг является обязательным условием для поддержки Hyper-Threading, сам по себе он не указывает на поддержку Hyper-Threading и имеет был установлен на многих процессорах, которые не поддерживают какую-либо технологию многопоточности. [48]
Зарезервированные поля следует замаскировать перед их использованием в целях идентификации процессора.
Это возвращает список дескрипторов, указывающих возможности кэша и TLB в регистрах EAX, EBX, ECX и EDX.
На процессорах, поддерживающих этот лист, вызов CPUID
с EAX=2 приведет к тому, что нижний байт EAX будет установлен в значение, 01h
а оставшиеся 15 байтов EAX/EBX/ECX/EDX будут заполнены 15 дескрипторами, по одному байту каждый. Эти дескрипторы предоставляют информацию о кэшах процессора, TLB и предварительной выборке. Обычно это один кэш или TLB для каждого дескриптора, но некоторые значения дескриптора также предоставляют другую информацию - в частности, 00h
используется для пустого дескриптора, FFh
указывает, что лист не содержит допустимой информации о кэше и что вместо него следует использовать лист 4h. и FEh
указывает, что лист не содержит допустимой информации TLB и что вместо него следует использовать лист 18h. Дескрипторы могут появляться в любом порядке.
Для каждого из четырех регистров (EAX,EBX,ECX,EDX), если установлен бит 31, не следует считать, что регистр содержит действительные дескрипторы (например, на Itanium в режиме IA-32 CPUID(EAX=2) возвращает 80000000h
в EDX — это следует интерпретировать как означающее, что EDX не содержит достоверной информации, а не то, что он содержит кэш L2 объемом 512 КБ.)
В таблице ниже для известных значений дескриптора представлено сокращенное описание кэша или TLB, указанного этим значением дескриптора (или другой информации, если это применимо). В таблице используются суффиксы:
10h
, 15h
, 1Ah
, 88h
, 89h
, 8Ah
, 90h
, 96h
, 9Bh
документированы только для режима работы IA-32 Itanium . [52]26h
27h
28h
81h
81h
39h-3Eh
перечислены 73h
в версии 36 Intel AP-485, [53] , но были удалены из более поздней документации Intel, хотя некоторые из них использовались в процессорах Intel (например, 39h
в процессорах Celeron на базе «Willamette-128» [ 54] ).49h
указывает на кэш-память 3-го уровня на GenuineIntel
процессорах семейства 0Fh Model 6 (Xeon на базе Pentium 4) и кэш-память 2-го уровня на других процессорах.4Fh
. Процессоры, использующие этот дескриптор (Intel Atom «Bonnell» [55] ), указаны в другом месте как имеющие полностью ассоциативную ITLB с 32 элементами. [56]CyrixInstead
и Geode by NSC
) дескрипторы 70h
имеют 80h
другое значение: [57]70h
указывает общий TLB с 32 записями и четырьмя ассоциативными наборами инструкций и данными с размером страницы 4 КБ.80h
указывает общий кэш инструкций + данных L1 объемом 16 КБ с четырехсторонней ассоциативностью наборов и размером строки кэша 16 байт.76h
указан как кэш L2 размером 1 МБ в версии 37 Intel AP-485, [58] , но как инструкция TLB в версии 38 и во всей более поздней документации Intel.77h
, 7Eh
, 8Dh
документированы только для режима работы IA-32 Itanium 2 . [60]B1h
емкость TLB составляет 8 элементов при использовании страниц по 2 МБ, но уменьшается до 4 элементов при использовании страниц по 4 МБ.Это вернет серийный номер процессора. Серийный номер процессора был введен в Intel Pentium III , но из соображений конфиденциальности эта функция больше не реализована в более поздних моделях (бит функции PSN всегда сброшен). Процессоры Transmeta Efficeon и Crusoe также обеспечивают эту функцию. Однако процессоры AMD не реализуют эту функцию ни в одной модели процессоров.
Для процессоров Intel Pentium III серийный номер возвращается в регистрах EDX:ECX. Для процессоров Transmeta Efficeon он возвращается в регистрах EBX:EAX. А для процессоров Transmeta Crusoe оно возвращается только в регистре EBX.
Обратите внимание, что для работы функция серийного номера процессора должна быть включена в настройках BIOS .
Эти два листа используются для топологии процессора (поток, ядро, пакет) и перечисления иерархии кэша в многоядерных (и гиперпоточных) процессорах Intel. [64] По состоянию на 2013 год [обновлять]AMD не использует эти листья, но имеет альтернативные способы выполнения нумерации ядер. [65]
В отличие от большинства других листьев CPUID, лист Bh будет возвращать разные значения в EDX в зависимости от того, на каком логическом процессоре выполняется инструкция CPUID; значение, возвращаемое в EDX, на самом деле является идентификатором x2APIC логического процессора. Однако пространство идентификаторов x2APIC не отображается постоянно на логические процессоры; в сопоставлении могут быть пробелы, а это означает, что некоторые промежуточные идентификаторы x2APIC не обязательно соответствуют какому-либо логическому процессору. Дополнительная информация для сопоставления идентификаторов x2APIC с ядрами предоставляется в других регистрах. Хотя лист Bh имеет подлисты (выбираемые ECX, как описано ниже), на значение, возвращаемое в EDX, влияет только логический процессор, на котором выполняется инструкция, но не подлист.
Топология процессора(ов), представленная листом Bh, является иерархической, но со странной оговоркой, что порядок (логических) уровней в этой иерархии не обязательно соответствует порядку в физической иерархии ( SMT /core/package). . Однако каждый логический уровень может быть запрошен как подлист ECX (листа Bh) на предмет его соответствия «типу уровня», который может быть SMT, ядром или «недействительным». Пространство идентификатора уровня начинается с 0 и является непрерывным. Это означает, что если идентификатор уровня недействителен, все идентификаторы более высоких уровней также будут недействительны. Тип уровня возвращается в битах 15:08 ECX, а количество логических процессоров на запрошенном уровне возвращается в EBX. Наконец, связь между этими уровнями и идентификаторами x2APIC возвращается в EAX[4:0] как количество битов, на которое идентификатор x2APIC должен быть сдвинут, чтобы получить уникальный идентификатор на следующем уровне.
Например, двухъядерный процессор Westmere , поддерживающий гиперпоточность (то есть имеющий в общей сложности два ядра и четыре потока), может иметь идентификаторы x2APIC 0, 1, 4 и 5 для своих четырех логических процессоров. Лист Bh (=EAX), подлист 0 (=ECX) CPUID может, например, возвращать 100h в ECX, что означает, что уровень 0 описывает уровень SMT (гиперпоточность) и возвращать 2 в EBX, поскольку имеется два логических процессора (модуля SMT). на каждое физическое ядро. Значение, возвращаемое в EAX для этого 0-подлиста, в этом случае должно быть равно 1, поскольку сдвиг вышеупомянутых идентификаторов x2APIC вправо на один бит дает уникальный номер ядра (на следующем уровне иерархии идентификаторов уровней) и стирает идентификатор SMT. бит внутри каждого ядра. Более простой способ интерпретировать эту информацию заключается в том, что последний бит (бит номер 0) идентификатора x2APIC идентифицирует блок SMT/гиперпоточности внутри каждого ядра в нашем примере. Переход к подлисту 1 (путем повторного вызова CPUID с EAX=Bh и ECX=1) может, например, вернуть 201h в ECX, что означает, что это уровень типа ядра, и 4 в EBX, поскольку в подлисте 4 логических процессора. упаковка; Возвращенный EAX может иметь любое значение больше 3, поскольку так получилось, что бит номер 2 используется для идентификации ядра в идентификаторе x2APIC. Обратите внимание, что бит номер 1 идентификатора x2APIC в этом примере не используется. Однако значение EAX, возвращаемое на этом уровне, вполне может быть равно 4 (и это происходит на Clarkdale Core i3 5x0), поскольку это также дает уникальный идентификатор на уровне пакета (очевидно, = 0) при сдвиге идентификатора x2APIC на 4 бита. Наконец, вы можете задаться вопросом, что может сказать нам лист EAX=4, чего мы еще не выяснили. В EAX[31:26] он возвращает биты маски APIC, зарезервированные для пакета; в нашем примере это будет 111b, поскольку биты от 0 до 2 используются для идентификации логических процессоров внутри этого пакета, но бит 1 также зарезервирован, хотя и не используется как часть схемы идентификации логического процессора. Другими словами, идентификаторы APIC от 0 до 7 зарезервированы для пакета, даже если половина этих значений не сопоставлена логическому процессору.
Иерархия кэша процессора исследуется путем рассмотрения подлистов листа 4. Идентификаторы APIC также используются в этой иерархии для передачи информации о том, как различные уровни кэша совместно используются модулями и ядрами SMT. Продолжая наш пример, кэш L2, который используется совместно модулями SMT одного и того же ядра, но не между физическими ядрами на Westmere, обозначается EAX[26:14], установленным в 1, а информация о том, что кэш L3 является общим для всего пакета указывается установкой этих битов в (по крайней мере) 111b. Детали кэша, включая тип, размер и ассоциативность кэша, передаются через другие регистры на листе 4.
Помните, что более старые версии примечания 485 к приложению Intel содержат некоторую вводящую в заблуждение информацию, особенно в отношении идентификации и подсчета ядер в многоядерном процессоре; [66] ошибки, связанные с неправильной интерпретацией этой информации, были даже включены в пример кода Microsoft для использования CPUID, даже для версии Visual Studio 2013 года, [67] , а также на странице sandpile.org для CPUID, [68], но Intel пример кода для определения топологии процессора [64] имеет правильную интерпретацию, а в текущем Руководстве разработчика программного обеспечения Intel написан более понятный язык. Кроссплатформенный производственный код (с открытым исходным кодом) [69] от Wildfire Games также реализует правильную интерпретацию документации Intel.
Примеры обнаружения топологии с использованием старых процессоров Intel (до 2010 года), в которых отсутствует x2APIC (поэтому не реализуется лист EAX=Bh), приведены в презентации Intel за 2010 год. [70] Помните, что использование этого старого метода обнаружения на процессорах Intel 2010 года выпуска и новее может привести к завышению количества ядер и логических процессоров, поскольку старый метод обнаружения предполагает отсутствие пробелов в пространстве идентификаторов APIC, а это предположение нарушается некоторыми новыми процессорами. (начиная с серии Core i3 5x0), но эти новые процессоры также поставляются с x2APIC, поэтому их топологию можно правильно определить с помощью листового метода EAX=Bh.
Это возвращает функциональные биты в регистре EAX и дополнительную информацию в регистрах EBX, ECX и EDX.
IA32_HWP_REQUEST
MSR на процессорах, которые его поддерживают, необходимо установить бит 0 в FAST_UNCORE_MSRS_CTL
( 657h
) MSR.Это возвращает флаги расширенных функций в EBX, ECX и EDX. Возвращает максимальное значение ECX для EAX=7 в EAX.
Это возвращает флаги расширенных функций во всех четырех регистрах.
Это возвращает флаги расширенных функций в EDX.
EAX, EBX и ECX зарезервированы.
Этот лист используется для перечисления функций XSAVE и компонентов состояния.
Расширение набора команд XSAVE предназначено для сохранения/восстановления расширенного состояния ЦП (обычно с целью переключения контекста ) таким образом, чтобы его можно было расширить для охвата новых расширений набора команд, при этом коду переключения контекста ОС не нужно понимать специфику новые расширения. Это делается путем определения серии компонентов состояния , каждый из которых имеет размер и смещение в пределах заданной области сохранения, и каждый соответствует подмножеству состояния, необходимого для того или иного расширения ЦП. Лист EAX=0Dh
CPUID используется для предоставления информации о том, какие компоненты состояния поддерживает ЦП и каковы их размеры/смещения, чтобы ОС могла зарезервировать необходимый объем пространства и установить соответствующие биты включения.
Компоненты состояния можно разделить на две группы: состояние пользователя (элементы состояния, видимые приложению, например векторные регистры AVX-512 ) и состояние супервизора (элементы состояния, которые влияют на приложение, но не являются непосредственно пользователем). видимый, например, конфигурация прерываний пользовательского режима). Элементы состояния пользователя активируются путем установки связанных с ними битов в XCR0
регистре управления, а элементы состояния супервизора включаются путем установки связанных с ними битов в IA32_XSS
( 0DA0h
) MSR - указанные элементы состояния затем становятся компонентами состояния, которые можно сохранить. и восстановлен с помощью XSAVE
/ XRSTOR
семейства инструкций.
Таким образом механизм XSAVE может обрабатывать до 63 компонентов состояния. Компоненты состояния 0 и 1 ( x87 и SSE соответственно) имеют фиксированные смещения и размеры — для компонентов состояния от 2 до 62 их размеры, смещения и несколько дополнительных флагов можно запросить, выполнив с помощью CPUID
и EAX=0Dh
установив ECX
индекс состояния. -компонент. Это вернет следующие элементы в EAX, EBX и ECX (при этом EDX зарезервирован):
Попытка запросить неподдерживаемый компонент состояния таким образом приводит к тому, что EAX,EBX,ECX и EDX устанавливаются в 0.
Подлисты 0 и 1 CPUID
листа 0Dh
используются для предоставления информации о функциях:
По состоянию на июль 2023 года архитектурно определены следующие компоненты состояния XSAVE:
XCR0
жестко привязан к 1, поэтому инструкции XSAVE всегда поддерживают сохранение/восстановление состояния x87.XCR0
и IA32_XSS
бит 63 зарезервирован специально для расширения битового вектора - это исключает существование компонента состояния 63.На этом листе представлена информация о поддерживаемых возможностях функции Intel Software Guard Extensions (SGX). Лист предоставляет несколько подлистов, выбранных с помощью ECX.
Подлист 0 предоставляет информацию о поддерживаемых конечных функциях SGX в EAX и максимальных поддерживаемых размерах анклава SGX в EDX; ECX зарезервирован. EBX предоставляет битовую карту, которая может быть установлена в поле MISCSELECT в SECS (структура управления анклавом SGX) — это поле используется для управления информацией, записываемой в область MISC SSA (область состояния сохранения SGX), когда AEX (SGX Save State Area) происходит асинхронный выход из анклава).
Подлист 1 предоставляет битовую карту, биты которой могут быть установлены в 128-битном поле ATTRIBUTES SECS в EDX:ECX:EBX:EAX (это относится к копии SECS, используемой в качестве входных данных для конечной ENCLS[ECREATE]
функции). Старшие 64 бита (заданные в EDX:ECX) представляют собой битовую карту, биты которой могут быть установлены в XFRM (маска запроса X-функции) — эта маска представляет собой битовую маску того, какие компоненты состояния процессора (см. лист 0Dh) будут сохранены. в SSA в случае AEX; он имеет ту же структуру, что и XCR0
регистр управления. Остальные биты задаются в EAX и EBX следующим образом:
ENCLS[EINIT]
. Этот бит должен быть равен 0 в копии SECS, которая передается в качестве входных данных для ENCLS[CREATE]
.Подлисты 2 и выше используются для предоставления информации о том, какие области физической памяти доступны для использования в качестве разделов EPC (кэш страниц анклава) в SGX.
На этом подлисте представлена информация о функциях трассировки процессоров Intel (также известной как трассировка инструкций в реальном времени).
Значение, возвращаемое в EAX, представляет собой индекс самого высокого подлиста, поддерживаемого для CPUID с EAX=14h. EBX и ECX предоставляют флаги функций, EDX зарезервирован.
В этом листе представлена информация о функциях AES Key Locker в EAX, EBX и ECX. EDX зарезервирован.
Это возвращает максимально поддерживаемый подлист в EAX и информацию о функциях AVX10 в EBX. [82] (ECX и EDX зарезервированы.)
В EAX возвращается самый высокий вызывающий параметр.
EBX/ECX/EDX возвращают строку идентификатора производителя (такую же, как EAX=0) на процессорах AMD, но не на процессорах Intel.
Это возвращает флаги расширенных функций в EDX и ECX.
Многие из битов EDX
(биты с 0 по 9, с 12 по 17, 23 и 24) являются дубликатами EDX
листа EAX=1
— эти биты выделены светло-желтым цветом. (Эти дублированные биты присутствуют в процессорах AMD, но не в процессорах Intel.)
Флаги функций AMD следующие: [86] [87]
SYSCALL
/ SYSRET
допустимо только для процессоров AuthenticAMD
семейства 5 Model 7 ( AMD K6 , 250 нм «Little Foot») — для всех остальных процессоров вместо этого следует использовать бит 11 EDX.Эти инструкции были впервые представлены в модели 7 [88] — бит CPUID, обозначающий их поддержку, был перенесен [89] в бит 11 EDX, начиная с модели 8 ( AMD K6-2 ).
SYSCALL
/ SYSRET
устанавливается только в том случае, если CPUID
инструкция выполняется в 64-битном режиме. [90]FCMOV
).AuthenticAMD
семейства 6 - этот бит в сочетании с сигнатурой процессора и скоростью FSB используется для идентификации процессоров как многопроцессорных или имеющих торговую марку Sempron . [95]Они возвращают строку бренда процессора в EAX, EBX, ECX и EDX. CPUID
должен вводиться с каждым параметром последовательно, чтобы получить всю 48-байтовую строку торговой марки процессора ASCII. [98] Необходимо проверить, присутствует ли эта функция в ЦП, выдав сначала CPUID
команду EAX = 80000000h
и проверив, не меньше ли возвращаемое значение 80000004h
.
В документации Intel/AMD строка указана как завершающаяся нулем , однако это не всегда так (например, DM&P Vortex86DX3 и AMD Ryzen 7 6800HS, как известно, возвращают строки бренда, не заканчивающиеся нулем, в листьях 80000002h
- 80000004h
[99] [100 ] ] ), и программное обеспечение не должно полагаться на него.
#include <stdio.h> #include <string.h> #include <cpuid.h> int main () { unsigned int regs [ 12 ]; char str [ sizeof ( regs ) + 1 ]; __cpuid ( 0x80000000 , regs [ 0 ], regs [ 1 ], regs [ 2 ], regs [ 3 ]); if ( regs [ 0 ] < 0x80000004 ) возвращает 1 ; __cpuid ( 0x80000002 , regs [ 0 ], regs [ 1 ], regs [ 2 ], regs [ 3 ]); __cpuid ( 0x80000003 , regs [ 4 ], regs [ 5 ], regs [ 6 ], regs [ 7 ]); __cpuid ( 0x80000004 , regs [ 8 ], regs [ 9 ], regs [ 10 ], regs [ 11 ]); memcpy ( str , regs , sizeof ( regs )); str [ sizeof ( regs )] = '\0' ; printf ( "%s \n " , str ); вернуть 0 ; }
Эта функция содержит характеристики кэша L1 процессора и TLB.
Возвращает сведения о кэше L2 в ECX, включая размер строки в байтах (биты 07–00), тип ассоциативности (кодируется 4-битным полем; биты 15–12) и размер кэша в КБ (биты 31–16). .
#include <stdio.h> #include <cpuid.h> int main () { unsigned int eax , ebx , ecx , edx ; беззнаковый int lsize , assoc , кэш ; __cpuid ( 0x80000006 , eax , ebx , ecx , edx ); lsize = ecx & 0xff ; assoc = ( ecx >> 12 ) & 0x07 ; кэш = ( ecx >> 16 ) & 0xffff ; printf ( "Размер строки: %d B, Тип ассоциированного объекта: %d, Размер кэша: %d КБ. \n " , lsize , ассоциированный , кэш ); вернуть 0 ; }
Эта функция предоставляет информацию об управлении питанием, отчетах о питании и возможностях RAS ( надежность, доступность и удобство обслуживания ) ЦП.
AuthenticAMD
семейства 0Fh Model 14h [104] (90-нм Athlon64/Opteron) и присутствует во всех более поздних процессорах AMD, за исключением тех, у которых установлен флаг no_efer_lmsle.Этот лист возвращает информацию о функциях AMD SVM ( безопасной виртуальной машины ) в EAX, EBX и EDX.
В более поздней документации AMD, такой как #25481 «Спецификация CPUID» версии 2.18 [107] и более поздних, этот бит указан только как зарезервированный.
В версии 2.30 [108] и более поздних версиях указан другой бит, зарезервированный для использования гипервизором: CPUID.(EAX=1):ECX[бит 31].
В версии 2.28 № 25481 этот бит указан как «Ssse3Sse5Dis» [110] - в версии 2.34 он указан как удаленный из спецификации версии 2.32 под именем «SseIsa10Compat». [111]
Некоторые модели процессоров AMD для CPUID с EAX=8FFFFFFFh
возвращают строку пасхального яйца в EAX, EBX, ECX и EDX. [115] [116] Известные струны пасхальных яиц включают:
Возвращает индекс самого высокого листа Centaur в EAX. Если возвращаемое значение в EAX меньше C0000001h
, то расширенные листья Centaur не поддерживаются.
Присутствует в процессорах VIA и Zhaoxin .
В процессорах IDT WinChip ( CentaurHauls
семейство 5) расширенные листья C0000001h-C0000005h
не кодируют какие-либо специфичные для Centaur функции, а вместо этого являются псевдонимами листьев 80000001h-80000005h
. [118]
Этот лист возвращает информацию о функциях Centaur (в основном через PadLock ) в EDX. [119] [120] (EAX, EBX и ECX зарезервированы.)
CentaurHauls
и Antaur ( только семейство 6, модель 9) [121] биты 0,1,4,5 используются по-другому:0x110A
) присутствует.FEMMS
инструкция (код операции 0F 0E
).Эту информацию легко получить и на других языках. Например, приведенный ниже код C для gcc печатает первые пять значений, возвращаемых cpuid:
#include <stdio.h> #include <cpuid.h> int main () { unsigned int i , eax , ebx , ecx , edx ; for ( я знак равно 0 ; я < 5 ; я ++ ) { __cpuid ( я , eax , ebx , ecx , edx ); printf ( "InfoType %x \n EAX: %x \n EBX: %x \n ECX: %x \n EDX: %x \n " , i , eax , ebx , ecx , edx ); } вернуть 0 ; }
В встроенной ассемблерной сборке MSVC и Borland/Embarcadero C (bcc32) информация о затирании неявно содержится в инструкциях:
#include <stdio.h> int main () { unsigned int a , b , c , d , я знак равно 0 ; __asm { /* Выполняем вызов. */ mov EAX , я ; идентификатор процессора ; /* Сохраняем результаты. */ mov a , EAX ; мов б , EBX ; мов с , ECX ; мов д , EDX ; } printf ( "InfoType %x \n EAX: %x \n EBX: %x \n ECX: %x \n EDX: %x \n " , i , a , b , c , d ); вернуть 0 ; }
Если какая-либо версия была написана на простом языке ассемблера, программист должен вручную сохранить результаты EAX, EBX, ECX и EDX в другом месте, если он хочет продолжать использовать значения.
GCC также предоставляет заголовок, вызываемый <cpuid.h>
в системах с CPUID. Это __cpuid
макрос, расширяемый до встроенной сборки. Типичное использование будет:
#include <stdio.h> #include <cpuid.h> int main () { unsigned int eax , ebx , ecx , edx ; __cpuid ( 0 /* строка поставщика */ , eax , ebx , ecx , edx ); printf ( "EAX: %x \n EBX: %x \n ECX: %x \n EDX: %x \n " , eax , ebx , ecx , edx ); вернуть 0 ; }
Но если кто-то запросит расширенную функцию, отсутствующую в этом процессоре, он этого не заметит и может получить случайные, неожиданные результаты. Более безопасная версия также доступна в формате <cpuid.h>
. Он проверяет наличие расширенных функций и выполняет еще несколько проверок безопасности. Выходные значения передаются не с использованием параметров макроса, подобных ссылкам, а с использованием более традиционных указателей.
#include <stdio.h> #include <cpuid.h> int main () { unsigned int eax , ebx , ecx , edx ; /* 0x81234567 не существует, но предположим, что он существует */ if ( ! __get_cpuid ( 0x81234567 , & eax , & ebx , & ecx , & edx )) { printf ( "Внимание: запрос CPUID 0x81234567 недействителен! \n " ); вернуть 1 ; } printf ( "EAX: %x \n EBX: %x \n ECX: %x \n EDX: %x \n " , eax , ebx , ecx , edx ); вернуть 0 ; }
Обратите внимание на амперсанды &a, &b, &c, &d
и условный оператор. Если __get_cpuid
вызов получит правильный запрос, он вернет ненулевое значение, в случае неудачи — ноль. [122]
Компилятор Microsoft Visual C имеет встроенную функцию __cpuid()
, поэтому инструкцию cpuid можно внедрить без использования встроенной ассемблера, что удобно, поскольку версия MSVC x86-64 вообще не поддерживает встроенную ассемблерную сборку. Та же программа для MSVC будет:
#include <stdio.h> #ifdef __MSVC__ #include <intrin.h> #endif int main () { unsigned int regs [ 4 ]; интервал я ; for ( я знак равно 0 ; я < 4 ; я ++ ) { __cpuid ( regs , я ); printf ( "Код %d дает %d, %d, %d, %d" , regs [ 0 ], regs [ 1 ], regs [ 2 ], regs [ 3 ]); } вернуть 0 ; }
Многие интерпретируемые или скомпилированные языки сценариев способны использовать CPUID через библиотеку FFI . Одна из таких реализаций демонстрирует использование модуля Ruby FFI для выполнения языка ассемблера, который включает код операции CPUID.
.NET 5 и более поздние версии предоставляют этот System.Runtime.Intrinsics.X86.X86base.CpuId
метод. Например, приведенный ниже код C# выводит марку процессора, если он поддерживает инструкцию CPUID:
используя System.Runtime.InteropServices ; используя System.Runtime.Intrinsics.X86 ; используя System.Text ; пространство имен X86CPUID { класс CPUBrandString { public static void Main ( строка [] args ) { if ( ! X86Base . IsSupported ) { Console . WriteLine ( "Ваш процессор не поддерживает инструкцию CPUID." ); } else { Span <int> raw = stackalloc int [ 12 ] ; ( сырой [ 0 ], необработанный [ 1 ], необработанный [ 2 ], необработанный [ 3 ]) = X86Base . CpuId ( не проверено (( int ) 0 x80000002 ), 0 ); ( сырой [ 4 ], необработанный [ 5 ], необработанный [ 6 ], необработанный [ 7 ]) = X86Base . CpuId ( не проверено (( int ) 0 x80000003 ), 0 ); ( сырой [ 8 ], необработанный [ 9 ], необработанный [ 10 ], необработанный [ 11 ]) = X86Base . CpuId ( не проверено (( int ) 0 x80000004 ), 0 ); Span < байт > байт = MemoryMarshal . AsBytes ( необработанный ); строка бренда = Кодировка . UTF8 . GetString ( байты ). Подрезать (); Консоль . WriteLine ( торговая марка ); } } } }
Некоторые архитектуры ЦП, отличные от x86, также предоставляют определенные формы структурированной информации о возможностях процессора, обычно в виде набора специальных регистров:
CPUID
регистр сопроцессора, для доступа к которому требуется уровень исключения EL1 или выше. [123]STIDP
1983 года [124] для запроса идентификатора процессора. [125]STFLE
), в которой перечислены установленные аппаратные функции. [125]PrId
) и ряд регистров конфигурации, подключенных последовательно . [126]PVR
), идентифицирующий используемую модель процессора. Инструкция требует уровня доступа супервизора. [127]Семейства DSP и транспьютерных микросхем не восприняли эту инструкцию каким-либо заметным образом, несмотря на (в относительном выражении) столько же вариаций конструкции. Могут существовать альтернативные способы идентификации кремния; например, DSP от Texas Instruments содержат набор регистров в памяти для каждого функционального блока, который начинается с идентификаторов, определяющих тип и модель блока, версию его конструкции ASIC и функции, выбранные на этапе проектирования, и продолжается контролем и данными для конкретного блока. регистры. Доступ к этим областям осуществляется простым использованием существующих инструкций загрузки и сохранения; таким образом, для таких устройств нет необходимости расширять набор регистров для целей идентификации устройства. [ нужна цитата ]
CPUID
для определения различных системных настроек.Процессоры Intel и AMD зарезервировали бит 31 ECX листа CPUID 0x1 в качестве бита присутствия гипервизора.
Этот бит позволяет гипервизорам сообщать о своем присутствии гостевой операционной системе.
Гипервизоры устанавливают этот бит, а физические процессоры (все существующие и будущие процессоры) устанавливают этот бит в ноль.
Гостевые операционные системы могут проверять бит 31, чтобы определить, работают ли они внутри виртуальной машины.
Бит 31 ECX листа CPUID 0x1.
Этот бит зарезервирован Intel и AMD для использования гипервизорами и указывает на наличие гипервизора.
Виртуальные процессоры (гипервизоры) устанавливают этот бит в 1, а физические процессоры (все существующие и будущие процессоры) устанавливают этот бит в ноль.
Этот бит может быть проверен гостевым программным обеспечением, чтобы определить, работают ли они внутри виртуальной машины.
15.2.2 Гостевой режим. Вход в этот новый режим процессора осуществляется с помощью инструкции VMRUN.
В гостевом режиме поведение некоторых инструкций x86 меняется для облегчения виртуализации.
Номера функций CPUID 4000_0000h-4000_00FFh зарезервированы для использования программным обеспечением.
Гипервизоры могут использовать эти номера функций для предоставления интерфейса для передачи информации от гипервизора гостю.
Это похоже на извлечение информации о физическом процессоре с помощью CPUID.
Гипервизоры используют бит CPUID Fn 400000[FF:00] для обозначения виртуальной платформы.
Бит функции CPUID Fn0000_0001_ECX[31] зарезервирован для использования гипервизорами для обозначения присутствия гипервизора.
Гипервизоры устанавливают этот бит в 1, а физические процессоры устанавливают этот бит в ноль.
Этот бит может быть проверен гостевым программным обеспечением, чтобы определить, работают ли они внутри виртуальной машины.
8FFFFFFFh
. Проверено 22 декабря 2022 г.