Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

В архитектуре x86 инструкция CPUID (идентифицируемая кодом CPUID операции ) является дополнительной инструкцией процессора (ее имя происходит от CPU IDentification), позволяя программному обеспечению обнаруживать детали процессора. Он был представлен Intel в 1993 году с выпуском процессоров 486 с улучшенными процессорами Pentium и 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 [ править ]

Код CPUIDоперации - 0Fh, A2h (как два байта или A20Fh как одно слово ).

В языке ассемблера , то 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 системы. По состоянию на июль 2014 года основные действительные отпуска продолжаются до 14 часов, но информация, возвращаемая некоторыми листами, не раскрывается в общедоступной документации, т. Е. Они «зарезервированы».

Некоторые из недавно добавленных листьев также имеют подчиненные листья, которые выбираются через регистр ECX перед вызовом CPUID.

EAX = 0: наивысший функциональный параметр и идентификатор производителя [ редактировать ]

Это возвращает строку идентификатора производителя процессора - двенадцатисимвольную строку ASCII, хранящуюся в EBX, EDX, ECX (в указанном порядке). Самый высокий базовый параметр вызова (наибольшее значение, которое может быть установлено в EAX перед вызовом CPUID) возвращается в EAX.

Вот список процессоров и самая высокая реализованная функция.

Ниже приведены известные строки идентификатора производителя процессора:

  • "AMD лучше!"  - раннее инженерные образцы AMD K5 процессор
  • «AuthenticAMD»  - AMD
  • "CentaurHauls"  - IDT WinChip / Centaur (включая некоторые процессоры VIA)
  • «CyrixInstead»  - Cyrix / ранняя STMicroelectronics и IBM
  • «GenuineIntel»  - Intel
  • «TransmetaCPU»  - Transmeta
  • «ПодлинныйTMx86»  - Transmeta
  • "Geode by NSC"  - National Semiconductor
  • «NexGenDriven»  - NexGen
  • "RiseRiseRise"  - Восход
  • «SiS SiS SiS»  - SiS
  • «UMC UMC UMC»  - UMC
  • «ВИА ВИА ВИА»  - ВИА
  • "Vortex86 SoC"  - DM&P Vortex
  • «Шанхай»  - Чжаосинь
  • «HygonGenuine»  - Хигон
  • «МАШИНА Е2К»  - МЦСТ Эльбрус.

Следующие строки идентификаторов используются программными ядрами ЦП с открытым исходным кодом :

  • "GenuineAO486"  - процессор ao486 [5]
  • "GenuineIntel"  - ядро ​​v586 [6] (идентично строке Intel ID)

Ниже приведены известные строки идентификаторов виртуальных машин:

  • «бхиве бхиве»  - бхиве
  • «КВМКВМКВМ»  - КВМ
  • «TCGTCGTCGTCG»  - QEMU
  • «Microsoft Hv»  - Microsoft Hyper-V или Windows Virtual PC.
  • "lrpepyh vr"  - параллели (возможно, это должно быть "prl hyperv", но оно закодировано как "lrpepyh vr" из-за несовпадения порядка байтов )
  • «VMwareVMware»  - VMware
  • "XenVMMXenVMM"  - Xen HVM
  • "ACRNACRNACRN"  - Проект ACRN
  • "QNXQVMBSQG"  - гипервизор QNX
  • «VirtualApple»  - Apple Rosetta
  • «GenuineIntel»  - Apple Rosetta 2 [7]

Например, для процессора GenuineIntel значения, возвращаемые в EBX, равны 0x756e6547, EDX - 0x49656e69, а ECX - 0x6c65746e. Следующий код написан на GNU Assembler для архитектуры x86-64 и отображает строку идентификатора поставщика, а также самый высокий параметр вызова, который реализует ЦП.

.данныеs0: .asciz "CPUID:% x \ n" s1: .asciz "Наибольший номер реализованной базовой функции:% i \ n" s2: .asciz "Идентификатор поставщика:% .12s \ n".текст.align 32 .globl mainОсновной: pushq % RBP MOVQ % RSP , % RBP SubQ $ 16 , % RSPmovl $ 1 , % eax cpuidmovq $ s0 , % rdi movl % eax , % esi xorl % eax , % eax вызов printfpushq % rbx  // -fPICxorl % eax , % eax cpuidmovl % ebx , 0 ( % rsp ) movl % edx , 4 ( % rsp ) movl % ecx , 8 ( % rsp )popq % rbx  // -fPICmovq $ s1 , % rdi movl % eax , % esi xorl % eax , % eax вызов printfmovq $ s2 , % rdi movq % rsp , % rsi xorl % eax , % eax вызов printfmovq % rbp , % rsp popq % rbp // ret movl $ 1 , % eax int $ 0x80

EAX = 1: информация о процессоре и биты функций [ править ]

Это возвращает информацию о степпинге , модели и семействе ЦП в регистре EAX (также называемом сигнатурой ЦП), флаги функций в регистрах EDX и ECX и дополнительную информацию о функциях в регистре EBX. [8]

  • Идентификатор шага - это номер версии продукта, присвоенный из-за исправленных ошибок или других изменений.
  • Фактическая модель процессора определяется полями Модель, Расширенный идентификатор модели и Идентификатор семейства. Если поле идентификатора семейства равно 6 или 15, модель равна сумме поля расширенного идентификатора модели, сдвинутого влево на 4 бита, и поля модели. В противном случае модель равна значению поля Модель.
  • Фактическое семейство процессоров выводится из полей «Идентификатор семейства» и «Идентификатор расширенного семейства». Если поле «Идентификатор семьи» равно 15, семейство равно сумме полей «Идентификатор расширенной семьи» и «Идентификатор семьи». В противном случае семейство равно значению поля Family ID.
  • Значение поля «Тип процессора» приведено в таблице ниже.

Информация о процессоре и флаги функций зависят от производителя, но обычно значения Intel используются другими производителями для совместимости.

Зарезервированные поля должны быть замаскированы перед их использованием для идентификации процессора.

EAX = 2: информация о кэше и дескрипторе TLB [ править ]

Это возвращает список дескрипторов, указывающих возможности кеширования и TLB в регистрах EAX, EBX, ECX и EDX.

EAX = 3: серийный номер процессора [ править ]

Это возвращает серийный номер процессора. Серийный номер процессора был введен в Intel Pentium III , но из соображений конфиденциальности эта функция больше не реализована в более поздних моделях (бит функции PSN всегда сброшен). Процессоры Transmeta Efficeon и Crusoe также предоставляют эту функцию. Однако процессоры AMD не поддерживают эту функцию ни в каких моделях процессоров.

Для процессоров Intel Pentium III серийный номер возвращается в регистрах EDX: ECX. Для процессоров Transmeta Efficeon он возвращается в регистрах EBX: EAX. А для процессоров Transmeta Crusoe он возвращается только в регистре EBX.

Обратите внимание, что для работы функция серийного номера процессора должна быть включена в настройках BIOS .

EAX = 4 и EAX = Bh: топология потока / ядра и кеш-памяти Intel [ править ]

Эти два листа используются для топологии процессора (поток, ядро, пакет) и перечисления иерархии кеша в многоядерных (и гиперпоточных) процессорах Intel. [14] По состоянию на 2013 год AMD не использует эти листья, но имеет альтернативные способы выполнения перечисления ядер. [15]

В отличие от большинства других листьев CPUID, лист Bh будет возвращать разные значения в EDX в зависимости от того, на каком логическом процессоре выполняется инструкция CPUID; значение, возвращаемое в EDX, на самом деле является идентификатором x2APIC логического процессора. Однако пространство идентификаторов x2APIC не отображается постоянно на логические процессоры; в отображении могут быть пробелы, что означает, что некоторые промежуточные идентификаторы x2APIC не обязательно соответствуют какому-либо логическому процессору. Дополнительная информация для сопоставления идентификаторов x2APIC с ядрами предоставляется в других регистрах. Хотя лист Bh имеет подчиненные листы (выбранные ECX, как описано ниже), на значение, возвращаемое в EDX, влияет только логический процессор, на котором выполняется инструкция, но не подчиненный лист.

Топология процессора (ов), представленная листом Bh, является иерархической, но со странной оговоркой, что порядок (логических) уровней в этой иерархии не обязательно соответствует порядку в физической иерархии ( SMT/ ядро ​​/ пакет). Однако каждый логический уровень может быть запрошен как подуровень ECX (листа Bh) на предмет его соответствия «типу уровня», который может быть либо SMT, либо основным, либо «недействительным». Пространство идентификаторов уровня начинается с 0 и является непрерывным, что означает, что если идентификатор уровня недопустим, все идентификаторы более высокого уровня также будут недопустимыми. Тип уровня возвращается в битах 15:08 ECX, а количество логических процессоров на запрошенном уровне возвращается в EBX. Наконец, связь между этими уровнями и идентификаторами x2APIC возвращается в EAX [4: 0] как количество битов, на которое должен быть сдвинут идентификатор x2APIC, чтобы получить уникальный идентификатор на следующем уровне.

Например, двухъядерный процессор Westmere с поддержкой гиперпоточности.(таким образом, имея в общей сложности два ядра и четыре потока) может иметь идентификаторы x2APIC 0, 1, 4 и 5 для своих четырех логических процессоров. Leaf Bh (= EAX), subbleaf 0 (= ECX) CPUID может, например, возвращать 100h в ECX, что означает, что уровень 0 описывает уровень SMT (гиперпоточность) и возвращает 2 в EBX, потому что есть два логических процессора (блоки SMT) на физическое ядро. Значение, возвращаемое в EAX для этого 0-подуровня, должно быть в этом случае 1, потому что сдвиг вышеупомянутых идентификаторов x2APIC вправо на один бит дает уникальный номер ядра (на следующем уровне иерархии идентификаторов уровней) и стирает идентификатор SMT. бит внутри каждого ядра. Более простой способ интерпретировать эту информацию заключается в том, что последний бит (бит номер 0) идентификатора x2APIC идентифицирует модуль SMT / гиперпоточности внутри каждого ядра в нашем примере.Переход к subbleaf 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.это означает, что это уровень типа ядра, и 4 в EBX, потому что в пакете 4 логических процессора; Возвращаемый EAX может иметь любое значение больше 3, потому что так случается, что бит номер 2 используется для идентификации ядра в идентификаторе x2APIC. Обратите внимание, что бит номер 1 идентификатора x2APIC не используется в этом примере. Однако EAX, возвращаемый на этом уровне, вполне может быть равен 4 (и это так на Clarkdale Core i3 5x0), потому что это также дает уникальный идентификатор на уровне пакета (= 0, очевидно) при смещении идентификатора x2APIC на 4 бита. Наконец, вы можете задаться вопросом, что может сказать нам лист EAX = 4, чего мы еще не выяснили. В EAX [31:26] он возвращает биты маски APIC.это означает, что это уровень типа ядра, и 4 в EBX, потому что в пакете 4 логических процессора; Возвращаемый EAX может иметь любое значение больше 3, потому что так случается, что бит номер 2 используется для идентификации ядра в идентификаторе x2APIC. Обратите внимание, что бит номер 1 идентификатора x2APIC не используется в этом примере. Однако EAX, возвращаемый на этом уровне, вполне может быть равен 4 (и это так на Clarkdale Core i3 5x0), потому что это также дает уникальный идентификатор на уровне пакета (= 0, очевидно) при смещении идентификатора x2APIC на 4 бита. Наконец, вы можете задаться вопросом, что может сказать нам лист EAX = 4, чего мы еще не выяснили. В EAX [31:26] он возвращает биты маски APIC.потому что так случилось, что бит номер 2 используется для идентификации ядра в идентификаторе x2APIC. Обратите внимание, что бит номер 1 идентификатора x2APIC не используется в этом примере. Однако EAX, возвращаемый на этом уровне, вполне может быть равен 4 (и это так на Clarkdale Core i3 5x0), потому что это также дает уникальный идентификатор на уровне пакета (= 0, очевидно) при смещении идентификатора x2APIC на 4 бита. Наконец, вы можете задаться вопросом, что может сказать нам лист EAX = 4, чего мы еще не выяснили. В EAX [31:26] он возвращает биты маски APIC.потому что так случилось, что бит номер 2 используется для идентификации ядра в идентификаторе x2APIC. Обратите внимание, что бит номер 1 идентификатора x2APIC не используется в этом примере. Однако EAX, возвращаемый на этом уровне, вполне может быть равен 4 (и это так на Clarkdale Core i3 5x0), потому что это также дает уникальный идентификатор на уровне пакета (= 0, очевидно) при смещении идентификатора x2APIC на 4 бита. Наконец, вы можете задаться вопросом, что может сказать нам лист EAX = 4, чего мы еще не выяснили. В EAX [31:26] он возвращает биты маски APIC.Вы можете задаться вопросом, что может сказать нам лист EAX = 4, чего мы еще не выяснили. В EAX [31:26] он возвращает биты маски APIC.Вы можете задаться вопросом, что может сказать нам лист 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.

Помните, что более старые версии заметки о приложении Intel 485 содержат некоторую вводящую в заблуждение информацию, особенно в отношении идентификации и подсчета ядер в многоядерном процессоре; [16] ошибки из-за неправильной интерпретации этой информации были даже включены в пример кода Microsoft для использования cpuid, даже для выпуска Visual Studio 2013 г. [17], а также на странице sandpile.org для CPUID, [18] но Intel Пример кода для определения топологии процессора [14] имеет правильную интерпретацию, а текущее руководство Intel Software Developer's Manual содержит более ясный язык. Кросс-платформенный производственный код (с открытым исходным кодом) [19] от Wildfire Games также реализует правильную интерпретацию документации Intel.

Примеры обнаружения топологии с участием более старых (до 2010 г.) процессоров Intel, в которых отсутствует x2APIC (таким образом, не реализуется лист EAX = Bh), приведены в презентации Intel 2010 г. [20] Помните, что использование этого старого метода обнаружения на процессорах Intel 2010 года и более новых может привести к завышению количества ядер и логических процессоров, поскольку старый метод обнаружения предполагает, что в пространстве идентификаторов APIC нет пробелов, и это предположение нарушается некоторыми новыми процессорами. (начиная с серии Core i3 5x0), но эти новые процессоры также поставляются с x2APIC, поэтому их топология может быть правильно определена с помощью листового метода EAX = Bh.

EAX = 6: Управление температурой и питанием [ править ]

EAX = 7, ECX = 0: Расширенные функции [ править ]

Это возвращает флаги расширенных функций в EBX, ECX и EDX. Возвращает максимальное значение ECX для EAX = 7 в EAX.

EAX = 7, ECX = 1: Расширенные функции [ править ]

Это возвращает расширенные флаги функций в EAX.


EAX = 80000000h: реализация максимальной расширенной функции [ править ]

Самый высокий параметр вызова возвращается в EAX.

EAX = 80000001h: расширенная информация о процессоре и биты функций [ править ]

Это возвращает расширенные флаги функций в EDX и ECX.

Флаги функций AMD следующие: [23] [24]

EAX = 80000002h, 80000003h, 80000004h: Строка бренда процессора [ править ]

Они возвращают строку бренда процессора в EAX, EBX, ECX и EDX. CPUIDдолжен выдаваться с каждым параметром в последовательности, чтобы получить всю строку марки процессора ASCII с завершающим 48 байтовым символом в конце. [26] Необходимо , чтобы проверить, присутствует ли в CPU функция путем выдачи CPUIDс EAX = 80000000hпервой и проверки , если возвращаемое значение больше или равно 80000004h.

#include  <cpuid.h>  // предоставляется GCC#include  <stdio.h>#include  <stdint.h>int  main ( void )  {    бренд uint32_t  [ 12 ];   if  ( ! __get_cpuid_max ( 0x80000004 ,  NULL ))  {  fprintf ( stderr ,  «Функция не реализована.» );  возврат  2 ;  }   __get_cpuid ( 0x80000002 ,  марка + 0x0 ,  марка + 0x1 ,  марка + 0x2 ,  марка + 0x3 );  __get_cpuid ( 0x80000003 ,  марка + 0x4 ,  марка + 0x5 ,  марка + 0x6 ,  марка + 0x7 );  __get_cpuid ( 0x80000004 ,  марка + 0x8 ,  марка + 0x9 , марка + 0xa ,  марка + 0xb );    printf ( "Бренд:% s \ n " ,  бренд ); }

EAX = 80000005h: идентификаторы кэша L1 и TLB [ править ]

Эта функция содержит характеристики кэша L1 и TLB процессора.

EAX = 80000006h: Расширенные функции кэша второго уровня [ править ]

Возвращает подробную информацию о кэше L2 в ECX, включая размер строки в байтах (биты 07-00), тип ассоциативности (закодирован 4-битным полем; биты 15-12) и размер кеша в килобайтах (биты 31-16). .

#include  <cpuid.h>  // предоставляется GCC#include  <stdio.h>#include  <stdint.h>int  main ( void )  {  uint32_t  eax ,  ebx ,  ecx ,  edx ;    if  ( __get_cpuid ( 0x80000006 ,  & eax ,  & ebx ,  & ecx ,  & edx ))  {        printf ( "Размер строки:% d B, тип сопоставления:% d; Размер кеша:% d КБ. \ n " ,  ecx  &  0xff ,  ( ecx  >>  12 )  &  0x07 , ( ecx  >>  16 )  &  0xffff );  возврат  0 ;  }  else  {  fputs ( stderr ,  «ЦП не поддерживает 0x80000006» );  возврат  2 ;  } }

EAX = 80000007h: расширенная информация об управлении питанием [ править ]

Эта функция предоставляет идентификаторы расширенных функций управления питанием. Бит 8 EDX указывает на поддержку инвариантного TSC.

EAX = 80000008h: размеры виртуального и физического адреса [ редактировать ]

Возвращает наибольший размер виртуального и физического адреса в EAX.

  • Биты 07-00: # Биты физического адреса.
  • Биты 15-8: # Биты линейного адреса.
  • Биты 31-16: зарезервировано = 0.

Он может использоваться гипервизором в системе виртуальной машины для сообщения о размерах физических / виртуальных адресов, возможных для виртуального ЦП.

EBX используется для функций :

  • Бит 0: CLZERO, очистить строку кэша с адресом в RAX.
  • Бит 4: RDPRU, чтение MPERF или APERF из кольца 3.
  • Бит 8: MCOMMIT, фиксация сохраненных данных в памяти. Для разделения памяти и получения ошибок ECC.
  • Бит 9: WBNOINVD, обратная запись и не делать кеш недействительным.

ECX обеспечивает количество ядер.

  • Биты 07-00: # Физические ядра минус один.
  • Биты 11-8: зарезервировано = 0.
  • Биты 15–12: биты идентификатора #APIC. 2 в этой степени будет физическим числом ядер, если оно не равно нулю.
  • Биты 17-16: размер счетчика отметок времени производительности.
  • Биты 31-18: зарезервировано = 0.

EDX предоставляет информацию, специфичную для RDPRU (максимально допустимый идентификатор регистра) в 31-16. Текущее число по состоянию на Zen 2 - 1 для MPERF и APERF.

EAX = 8FFFFFFFh: пасхальное яйцо AMD [ править ]

Специально для процессоров AMD K7 и K8, это возвращает строку «IT'S HAMMER TIME» в EAX, EBX, ECX и EDX, [27] ссылку на песню MC Hammer U Can't Touch This .

Использование CPUID из языков высокого уровня [ править ]

Встроенная сборка [ править ]

Эту информацию легко получить и на других языках. Например, приведенный ниже код C для gcc выводит первые пять значений, возвращаемых cpuid:

#include  <stdio.h>/ * Работает в 32- и 64-битных системах. См. [[Встроенный ассемблер # В реальных компиляторах]] за советами по чтению этого кода. * / int  main () {  / * Четыре регистра не нужно инициализировать, так как процессор будет писать поверх них. * /  int  инфо-тип ,  a ,  b ,  c ,  d ; for  ( инфо-тип  =  0 ;  инфо-  тип <  5 ;  инфо-  тип ++ )  {  __asm__ ( "cpuid"            :  "= a"  ( a ),  "= b"  ( b ),  "= c"  ( c ),  "= d"  ( г )  // Выходные переменные. EAX -> a и наоборот  :  "0"  ( инфо-тип ));  // Поместите инфо-тип в EAX.  printf  ( "Тип информации% x \ n EAX:% x \ n EBX:% x \ nECX:% x \ n EDX:% x \ n " ,  инфо-тип ,  a ,  b ,  c ,  d );  } возврат  0 ; }

В компиляторах MSVC и Borland / Embarcadero C (bcc32) встроенная ассемблерная информация неявно указана в инструкциях:

#include  <stdio.h>int  main () {  беззнаковый  int  InfoType  =  0 ;  беззнаковые  int  a ,  b ,  c ,  d ;  __asm  {  / * Сделай звонок. * /  mov  EAX ,  InfoType ;  cpuid ;  / * Сохраняем результаты. * /  mov  a ,  EAX ;  mov  b ,  EBX ;  mov  c ,  ECX ;  mov  d ,  EDX ;  }  printf ( "InfoType% x \ n EAX:% x \ n EBX:% x \ n ECX:% x \ n EDX:% x \ n " ,  InfoType ,  a ,  b ,  c ,  d );  возврат  0 ; }

Если какая-либо версия была написана на простом ассемблере, программист должен вручную сохранить результаты EAX, EBX, ECX и EDX в другом месте, если он хочет продолжать использовать значения.

Функции оболочки [ править ]

GCC также предоставляет заголовок, вызываемый <cpuid.h>в системах с CPUID. Это __cpuidмакрос, расширяющийся до встроенной сборки. Типичное использование:

#include  <cpuid.h>#include  <stdio.h>int main  ( void ) {  int  a ,  b ,  c ,  d ;  __cpuid  ( 0  / * строка поставщика * / ,  a ,  b ,  c ,  d );  printf  ( "EAX:% x \ n EBX:% x \ n ECX:% x \ n EDX:% x \ n " ,  a ,  b ,  c ,  d );  возврат  0 ; }

Но если кто-то запросит расширенную функцию, отсутствующую в этом процессоре, они не заметят и могут получить случайные, неожиданные результаты. Более безопасная версия также предоставляется в формате <cpuid.h>. Он проверяет наличие расширенных функций и выполняет еще несколько проверок безопасности. Выходные значения передаются не с использованием параметров макроса, подобных ссылкам, а с использованием более обычных указателей.

#include  <cpuid.h>#include  <stdio.h>int main  ( void ) {  int  a ,  b ,  c ,  d ;  if  ( ! __get_cpuid  ( 0x81234567  / * не существует, но предполагается, что он существует * / ,  & a a ,  & b ,  & c ,  & d ))  {  fprintf  ( stderr ,  "Предупреждение: запрос CPUID 0x81234567 недействителен! \ n " );  }  printf ( "EAX:% x \ n EBX:% x \ nECX:% x \ n EDX:% x \ n " ,  a ,  b ,  c ,  d );  return  0 ; }

Обратите внимание на амперсанды &a, &b, &c, &dи условное выражение. Если __get_cpuidвызов получит правильный запрос, он вернет ненулевое значение, если не удастся - ноль. [28]

Компилятор Microsoft Visual C имеет встроенную функцию, __cpuid()поэтому инструкция cpuid может быть встроена без использования встроенной сборки, что удобно, поскольку версия MSVC для x86-64 вообще не допускает встроенную сборку. Та же программа для MSVC будет:

#include  <iostream>#include  <intrin.h>int  main () {  int  cpuInfo [ 4 ]; для  ( int  a  =  0 ;  a  <  5 ;  a ++ )  {  __cpuid ( cpuInfo ,  a );  std :: cout  <<  "Код"  <<  a  <<  "дает"  <<  cpuInfo [ 0 ]  <<  ","  <<  cpuInfo [ 1 ]  <<  ","  <<  cpuInfo [ 2 ]  <<  ", "  << cpuInfo [ 3]  <<  '\ n' ;  } возврат  0 ; }

Многие интерпретируемые или скомпилированные языки сценариев могут использовать CPUID через библиотеку FFI . Одна из таких реализаций демонстрирует использование модуля Ruby FFI для выполнения языка ассемблера, который включает код операции CPUID.

Информация о процессоре вне x86 [ править ]

Некоторые архитектуры ЦП, отличные от x86, также предоставляют определенные формы структурированной информации о возможностях процессора, обычно в виде набора специальных регистров:

  • Архитектура ARM имеет CPUIDрегистр сопроцессора, для доступа к которому требуется уровень EL1 или выше. [29]
  • В Z IBM System процессоры мэйнфреймов имеют магазин CPU ID ( STIDPинструкция) , так как в 1983 году IBM 4381 [30] для запроса процессор ID. [31]
  • В процессорах мэйнфреймов IBM System z также есть инструкция « Сохранить список возможностей» ( STFLE), в которой перечислены установленные аппаратные функции. [31]
  • Архитектура MIPS32 / 64 определяет обязательную идентификацию процессора ( PrId) и серию последовательно соединенных регистров конфигурации . [32]
  • Процессор PowerPC имеет 32-битный регистр версии процессора ( PVR), предназначенный только для чтения, который определяет используемую модель процессора. Инструкция требует уровня доступа супервизора. [33]

Семейства микросхем DSP и транспьютерных микросхем практически не учитывают инструкции, несмотря на то, что имеют (в относительном выражении) множество вариаций в дизайне. Могут присутствовать альтернативные способы идентификации кремния; например, DSP от Texas Instruments содержат набор регистров на основе памяти для каждого функционального блока, который начинается с идентификаторов, определяющих тип и модель блока, его версию ASIC и функции, выбранные на этапе проектирования, и продолжается с управлением и данными для конкретного блока регистры. Доступ к этим областям осуществляется простым использованием существующих инструкций загрузки и сохранения; таким образом, для таких устройств нет необходимости расширять набор регистров для целей идентификации устройства. [цитата необходима ]

См. Также [ править ]

  • CPU-Z , утилита Windows, которая используется CPUIDдля определения различных системных настроек.
  • Spectre (уязвимость безопасности)
  • Спекулятивный обход хранилища (SSB)
  • / proc / cpuinfo , текстовый файл, созданный некоторыми системами, содержащий некоторую информацию о CPUID.

Ссылки [ править ]

  1. ^ "Руководство разработчика программного обеспечения для архитектур Intel 64 и IA-32" (PDF) . Intel.com . Проверено 11 апреля 2013 .
  2. ^ «Обнаружение процессоров Intel - Знание поколения системного ЦП» . Rcollins.org . Проверено 11 апреля 2013 .
  3. ^ "LXR linux-old / arch / i386 / kernel / head.S" . Lxr.linux.no. Архивировано из оригинала на 2012-07-13 . Проверено 11 апреля 2013 .
  4. ^ «CPUID, EAX = 4 - Странные результаты (решено)» . Software.intel.com . Проверено 10 июля 2014 .
  5. ^ "ao486 инструкция CPUID" .
  6. ^ "v586: 586 совместимое программное ядро ​​для FPGA" .
  7. ^ https://cpufun.substack.com/p/fun-with-timers-and-cpuid
  8. ^ "Глава 3 Справочник по набору команд, AL" (PDF) . Руководство разработчика программного обеспечения для архитектур Intel® 64 и IA-32 . Корпорация Intel. 2018-12-20 . Проверено 20 декабря 2018 .
  9. ^ http://bochs.sourceforge.net/techspec/24161821.pdf
  10. ^ Huggahalli, Рам; Айер, Рави; Тетрик, Скотт (2005). «Прямой доступ к кэш-памяти для высокоскоростного сетевого ввода-вывода». Новости компьютерной архитектуры ACM SIGARCH . 33 (2): 50–59. DOI : 10.1145 / 1080695.1069976 . CiteSeerX : 10.1.1.91.957 .
  11. ^ Дреппер, Ульрих (2007), Что каждый программист должен знать о памяти , CiteSeerX : 10.1.1.91.957
  12. ^ «Механизмы определения того, работает ли программное обеспечение на виртуальной машине VMware» . База знаний VMware . VMWare . 2015-05-01. Процессоры Intel и AMD зарезервировали бит 31 ECX листа CPUID 0x1 в качестве бита присутствия гипервизора. Этот бит позволяет гипервизорам сообщать о своем присутствии гостевой операционной системе. Гипервизоры устанавливают этот бит, а физические процессоры (все существующие и будущие процессоры) устанавливают этот бит в ноль. Гостевые операционные системы могут проверить бит 31, чтобы определить, работают ли они внутри виртуальной машины.
  13. ^ Kataria, Alok; Хехт, Дэн (2008-10-01). "Предложение интерфейса CPUID гипервизора" . LKML Архив на lore.kernel.org. Архивировано 15 марта 2019 года. Бит 31 ECX листа CPUID 0x1. Этот бит зарезервирован Intel и AMD для использования гипервизорами и указывает на наличие гипервизора. Виртуальные ЦП (гипервизоры) устанавливают этот бит в 1, а физические ЦП (все существующие и будущие ЦП) устанавливают этот бит в ноль. Этот бит может проверяться гостевым программным обеспечением, чтобы определить, работают ли они внутри виртуальной машины.
  14. ↑ a b Ши Куо (27 января 2012 г.). «Перечень топологии процессора с архитектурой Intel® 64» .
  15. ^ «Перечисление процессоров и ядер с использованием CPUID | AMD» . Developer.amd.com. Архивировано из оригинала на 2014-07-14 . Проверено 10 июля 2014 .
  16. ^ "Процессоры Sandybridge сообщают неверный номер ядра?" . Software.intel.com. 2012-12-29 . Проверено 10 июля 2014 .
  17. ^ "cpuid, __cpuidex" . Msdn.microsoft.com. 2014-06-20 . Проверено 10 июля 2014 .
  18. ^ "Архитектура x86 - CPUID" . sandpile.org . Проверено 10 июля 2014 .
  19. ^ "topology.cpp в ps / trunk / source / lib / sysdep / arch / x86_x64 - Wildfire Games" . Trac.wildfiregames.com. 2011-12-27 . Проверено 10 июля 2014 .
  20. ^ Технология Hyper-Threading и обнаружение многоядерных процессоров
  21. ^ a b c d "Снижение риска по стороннему каналу спекулятивного исполнения" (PDF) . Редакция 2.0. Intel . Май 2018 [январь 2018]. Номер документа: 336996-002 . Проверено 26 мая 2018 .
  22. ^ "Серия патчей IBRS [LWN.net]" .
  23. ^ Спецификация CPUID (PDF) , AMD , сентябрь 2010 г. , получено 2 апреля 2013 г.
  24. ^ Исходный код ядра Linux
  25. ^ Спецификация облегченного профилирования (PDF) , AMD , август 2010 г. , получено 3 апреля 2013 г.
  26. ^ «Идентификация процессора Intel® и инструкция CPUID» (PDF) . Download.intel.com. 2012-03-06 . Проверено 11 апреля 2013 .
  27. ^ Ферри, Питер. «Атаки на эмуляторы виртуальных машин» (PDF) . symantec.com . Symantec Advanced Threat Research. Архивировано из оригинального (PDF) 07.02.2007 . Проверено 15 марта 2017 года .
  28. ^ https://github.com/gcc-mirror/gcc/blob/master/gcc/config/i386/cpuid.h
  29. ^ "Информационный центр ARM" . Infocenter.arm.com . Проверено 11 апреля 2013 .
  30. ^ «Коды версий процессора и константы SRM» . Архивировано из оригинала на 2014-09-08 . Проверено 8 сентября 2014 .
  31. ^ a b «Техническое руководство по IBM System z10 Enterprise Class» (PDF) .
  32. ^ «Архитектура MIPS32 для программистов, Том III: Архитектура привилегированных ресурсов MIPS32» (PDF) . MIPS Technologies, Inc. 12 марта 2001 г.
  33. ^ «Архитектура операционной среды PowerPC, книга III» (PDF) .

Дальнейшее чтение [ править ]

  • «Расширение косвенного управления ветвями технологии AMD64» (PDF) (Белая книга). Редакция 4.10.18. Advanced Micro Devices, Inc. (AMD). 2018. Архивировано (PDF) из оригинала 09.05.2018 . Проверено 9 мая 2018 .

Внешние ссылки [ править ]

  • Идентификация процессора Intel и инструкция CPUID (примечание по приложению 485), последняя опубликованная версия. Утверждается, что он будет включен в Руководство разработчика программного обеспечения для архитектур Intel® 64 и IA-32 в 2013 году , но по состоянию на июль 2014 года руководство по-прежнему предлагает читателю примечание 485.
    • Содержит информацию , которая может быть и легко неверно истолковано , хотя, в частности , в отношении идентификации топологии процессора .
    • Большие руководства Intel имеют тенденцию отставать от документа Intel ISA, доступного в верхней части этой страницы , который обновляется даже для процессоров, еще не общедоступных, и, следовательно, обычно содержит больше битов CPUID. Например, на момент написания книги ISA (ревизия 19, датированная маем 2014 г.) бит CLFLUSHOPT задокументирован на листе 7, но большие руководства, хотя и явно более современные (ревизия 51, датированная июнем 2014 г.), не содержат не упоминаю об этом.
  • Руководство программиста по архитектуре AMD64, том 3: Общие и системные инструкции
  • cpuid.exe, инструмент командной строки с открытым исходным кодом для Windows, доступный в SysTools.zip . Пример: cpuid -v отображает значение каждого флага функции CPUID.
  • instlatx64 - сборник дампов данных о задержке инструкций x86 / x64, задержке памяти и CPUID