Что такое идентификатор процессора

Обновлено: 06.07.2024

Современные процессоры имеют весьма внушительный набор команд. Общее их кол-во можно подсчитать открыв том(2) Интеловского мануала "Instruction Set Referense" . На различных площадках народ сильно преувеличивает утверждая, будто число опкодов давно перевалило за тысячу. Чтобы-уж наверняка и ради собственного интереса, я скопировал из оглавления указанной доки в блокнот весь перечень, и к своему удивлению на выходе получил всего 632 строки текста, в каждой из которых одна инструкция. Судя по-всему, на данный момент именно такой объём полностью удовлетворяет нашим требованиям, иначе монархи из Intel не упустили-бы возможности записать на свой счёт очередной новый опкод. Из всего этого листа, в данной статье предлагаю рассмотреть одну из интересных инструкций под названием CPUID, которая призвана идентифицировать бортовой процессор CPU.


1. Основная идея

При включении машины, системный BIOS/EFI должен каким-либо образом опознать установленный на материнской плате CPU, чтобы настроить под него чипсет и всё остальное. Нужно сказать, что на первом витке эволюции вплоть до древних 16-битных процессоров i80286 в этом не было необходимости, поскольку архитектура компьютера была примитивной, с довольно устойчивым состоянием. Но тут пришёл 32-битный процессор нового поколения i80386, который мог работать как в 16, так и в 32-битном защищённом режиме. Здесь-то и всплыла проблема. Инженеры Intel с присущим им оптимизмом решили её просто – они жёстко запрограммировали проц, чтобы на старте он возвращал свою "половую" принадлежность в регистровой паре EСX:EDX. Но дальше-больше..

Инструкцию CPUID принёс с собой следующий процессор i80486, когда благодаря механизму PAE (Physical Address Extension, расширение физического адреса) 32-битному CPU стало доступно сразу три ступени памяти, разрядностью 16, 32 и 36-бит. Теперь, биосу требовался паспорт процессора, иначе он просто не мог должным образом настроить ответственные за распределение ОЗУ регистры чипсета. Так возникла необходимость в идентификации CPU, что вынудило Intel включить в набор команд инструкцию CPUID. Первая его спецификация от Intel датируется 1993-годом.

Если говорить об инструкциях в целом, то каждая из них является совокупностью микрокоманд. Когда инструкция простая (типа INC, ADD, SUB и т.д.), для неё достаточно одной микрокоманды, а если сложная – она собирается из нескольких таких команд. На этапе изготовления процессора, производитель зашивает в специально предназначенную для этих целей встроенную ROM-память весь поддерживаемый набор микрокоманд, из которых в конечном счёте и собираются разнообразные инструкции. Блок процессора под названием "микро-секвенсер" (microsequencer) считывает микрокоманды из хранилища ROM, и по-требованию передаёт их в декодер инструкций. Таким образом, чтобы включить в набор команд процессора какую-нибудь новую инструкцию, в большинстве случаях производителю достаточно добавить лишь пару ключевых микрокоманд.

На этапе производства процессора отследить все его ошибки невозможно, что влечёт за собой различные хард-глюки. По этой причине, производитель предусматривает обновление микро-кодов уже при эксплуатации готового продукта. Обновы всегда кратны 2Кб и их можно найти на сайтах Intel и AMD. Включённый в пакет прошивальщик сначала идентифицирует бортовой CPU, и если его модель/степпинг/ревизия совпадает с прошивкой, то заливает обновлённые микро-коды не в ROM процессора, а в системный BIOS, от куда проц потом их и стягивает. Intel давно уже практикует рассылку своих обновлений всем производителям биосов, чтобы они включали их в свой код. В конечном итоге, поддержка биосами современных процессоров определяется в первую очередь наличием соответствующей прошивки.

На уровне-же микроархитектуры CPUID устроена так, что помимо прочего, в постоянную память ROM производитель закладывает порядка 30-ти основных листов с детальной информацией о своём продукте, и некоторое кол-во (под)листов. В документации эти листы назвали "Leaf" , а подлисты "Subleaf" . Перед тем-как вызвать инструкцию CPUID, мы должны предварительно указать номер конкретного листа в регистре EAX, и если этот лист имеет вложенный (под)лист, то его номер занести ещё и в регистр ECX. На программном уровне, запрос каждого из листов представляет собой отдельную функцию, о чём прямым текстом и сообщается в спецификации CPUID.

В таблице ниже я перечислил все доступные мне функции и их назначения. К сожалению, в наличии оказалась только спека от 2012-года, и более свежих данных мне так и не удалось выудить из сети (если кто поделится, буду благодарен). Причём действительна представленная табличка только для процессоров Intel, поскольку у AMD нумерация функций совсем иная. Как по мне, так двум этим гигантам пора-бы уже не выносить нам мозг, а "выпить за мировую", чтобы согласовывать между собой хотя-бы такие элементарные вещи. Ан-нет.. нужно чтобы всё было через известное место. В силу того, что на обеих моих машинах (бук и стационар) установлены процессоры Intel, всё нижесказанное будет относиться исключительно к продуктам Intel.

CPUID_func.jpg


Обратите внимание, что вложенные подлисты имеют только функции EAX=04,07,0В и 0Dh (выделены красным). Например если мы запросим инструкцию CPUID.EAX=4:ECX=0 , то в регистрах EAX,EBX,ECX,EDX процессор вернёт нам информацию о своём кэше L1. Теперь, чтобы получить характеристики кэша L2, мы должны повторно вызвать CPUID.EAX=4 , только на этот раз сменить номер (под)листа на ECX=1. Соответственно для кэша L3 будет уже EAX=4:ECX=2 , и т.д. в том-же духе. Вне зависимости от разрядности процессора 32 или 64-бит, CPUID всегда возвращает информацию в первые четыре регистра общего назначения EAX,EBX,ECX,EDX. Надеюсь суть вы уловили, и вооружившись спекой можно теперь смело пробираться вглубь.

Спецификация CPUID для процессоров INTEL (2012 год)
Спецификация CPUID для процессоров AMD (2010 год)

2. Стандартные функции

Начнём по-порядку и рассмотрим на конкретных примерах, какого рода информацию возвращают все функции CPUID. В некоторых случаях, это поможет осуществить направленные на конкретный процессор атаки, ну или просто идентифицировать его, чтобы пустить код по нужной ветке. К примеру если мы написали приложение с использованием современных инструкций SSE4 или AVX, то это приложение может попасть на платформу, процессор которой вообще не поддерживает данный тип инструкций. Значит перед запуском софта нужно обязательно позвать CPUID и проверить в нём нужные биты. В любом случае знания всегда идут на шаг впереди их отсутствия, а потому профит по-любому будет.


2.0. Функция EAX=0. (Vendor-ID, and Largest Standard Function)

Данная функция возвращает в EAX общее число поддерживаемых процессором стандартных функций, и в остальные три регистра сбрасывает строку с именем производителя. Для Intel и AMD эта строка будет иметь вид "GenuineIntel" и "AuthenticAMD" соответственно. На процессоре своего стационара я получил всего 14 указанных в таблице выше функций, при этом 0x08 и 0x0C находятся в резерве. А вот на буке с 64-битным процессором счётчик показывает уже 25 поддерживаемых функций, но как говорилось выше спеки на него нет. Пример вызова функции выглядит так:

eax_0.jpg

2.1. Функция EAX =1. (Feature Information)

Очередная функция возвращает характерные особенности бортового процессора, где можно будет найти его: Family/Model/Stepping , идентификатор текущего контролёра прерываний APIC, макс.кол-во поддерживаемых ядер (не путать с реальным кол-вом), размер линейки кэш-памяти, и в 64-битах регистровой пары ECX:EDX разнообразные свойства, типа поддержка инструкций SSE4/AVX, гипер-трейдинг HT, x2APIC, RDRAND и многое другое (см.спецификацию). Чтобы вывести все эти 64 типа информации на консоль, придётся чекать их биты по отдельности например инструкцией BT (bit-test), как в примере ниже. Если тестируемый бит взведён, инструкция взводит флаг процессора(CF):

eax_1.jpg


Как видно из листа "FeatureFlags" , мой бородатый проц не знаком с инструкциями SSE4/AVX, а лишь поддерживает макс.SSSE3. Имеет встроенный датчик температуры "TermalMonitor2" (TM2), в режиме энергосбережения может сохранять в специальной область памяти значения всех регистров CPU/FPU (xsave/fxsave соответственно), при переходе в ядро вместо устаревшего SYSCALL использует SYSENTER , способен очищать линейки кэша L1 при помощи инструкции CLFLUSH , и прочее. Описание всех этих аббревиатур имеется в спецификации, так-что курите её.


2.2. Функция EAX =2. (Cache Descriptors)

Каждый дескриптор кэша имеет размер 1-байт, и является закодированным значением определённой строки. На всякий-пожарный, я оформил все эти строки в виде таблички, и сохранил их в инклуд (см.скрепку в подвале статьи). Поскольку результат мы получим в четырёх 4-байтных регистрах EAX,EBX,ECX,EDX, итого получается 4х4=16 байт. Тогда общее кол-во дескрипторов будет 15, без учёта регистра-счётчика(AL). Если дескриптор имеет значение нуль, значит он пустой и не используется.

Теперь, для разбора дескрипторов последовательно перемещаемся от самого старшего байта всех регистров вниз, к младшему их байту (ну или наоборот). Код реализации парсинга дескрипторов и фрагмент таблицы из спецификации представлены ниже:

eax_2.jpg

Однако кроме кэша данных, в процессоре имеется ещё и кэш для хранения адресов страниц виртуальной памяти, к которым он обращался последний раз. Этот кэш назвали TLB, или "Translation Lookaside Buffer" (буфер ассоциативной трансляции). Проблема в том, что для доступа к памяти ОЗУ, транслятор контролёра памяти (в процессоре) сначала должен преобразовать текущий адрес из виртуального в физический, на что может уйти до 100-тактов процессора. По современным меркам, это чистой воды расточительство, поэтому один раз преобразовав вирт.адрес, процессор запоминает его в своём кэше TLB. Как показала практика, такой алго даёт существенный прирост скорости при чтении данных из оперативной памяти.


2.3. Функция EAX=3. (Processor Serial Number)

Если процессор фирменный и благополучно прошёл все надзорные инстанции, производитель может записать в него серийный номер продукта. Но в наше время это скорее исключение, чем правило, и лично мне такие пока не встречались.


2.4. Функция EAX=4. (Deterministic Cache Parameters)

Функция CPUID.EAX=4 имеет подлист, поэтому вызывать её нужно с регистром ECX. Как и функция EAX=2, она возвращает информацию о кэшах процессора L1,2,3, только без кэшей TLB. Индекс в регистре ECX указывает, о каком кэше следует возвращать информацию. Чтобы получить информацию о кэшах всех уровней, мы должны вызывать её в цикле, пока в битах EAX[4:0] не получим нуль. Порядок возврата кэшей не регламентируется и может быть изменен по усмотрению Intel. Это означает, что при вызове функции с ECX=0 мы можем получить инфу например о кэше L3 и т.д. Бонусом, индекс(0) в регистре ECX возвращает ещё и кол-во ядер процессора, в старших битах EAX[31:26].

Вызов этой функции, в регистре EBX возвращает информацию об ассоциативности кэшей, кол-ве блоков "Way", и числу записей "Sets". Используя эти данные можно вычислить и размер кэша, который не возвращает функция CPUID.EAX=4 в явном виде. Спецификация предлагает нам такую формулу для этих целей:

Ниже представлен возможный вариант вывода результата этой функции на консоль. Здесь я при первом вызове получаю кол-во ядер, и дальше в цикле зову эту функцию с инкрементом счётчика в ECX, чтобы получить инфу о кэшах всех уровней:

eax_4.jpg


Здесь стоит отметить, что для хранения информации о кэшах, современные процессоры 64-бит используют только данную функцию CPUID.EAX=4 , полностью игнорируя ранее рассмотренную CPUID.EAX=2 , которая возвращает дескрипторы кэшей. В этом случае, при вызове EAX=2 на выходе получаем 0xFF вместо дескрипторов, что означает см.функцию EAX=4. Вот фрагмент из описания функции CPUID.EAX=2 с дескриптором 0xFF :

eax_4_1.jpg


3. Расширенные функции

Остальные стандартные функции не представляют особого интереса, и при желании вы можете по-экспериментировать с ними сами. А вот рассмотреть набор расширенных функций CPUID вполне себе стоит. Во времена своего младенчества, Intel и AMD разделили инструкцию CPUID пополам. Чтобы хоть как-то отличаться от Intel, инженеры AMD забрали себе старшую половину функций, начиная с 0x80000000. Однако позже всё утряслось и теперь обоим производителям принадлежит весь диапазон, хотя и нумерация по назначению абсолютно разная.

3.0. Функция EAX=8000_0000h (Largest Extended Function)

Эта функция особо не напрягается, и возвращает в единственный регистр EAX общее число поддерживаемых расширенных функций. На обоих своих процессорах я получаю значение EAX=8.

3.1. Функция EAX=8000_0001h (Extended Feature Bits)

Очередная функция возвращает в регистр EDX флаги расширенных возможностей процессора.

eax_8001.jpg


Посмотрим на флаг "XD bit" .
В документации AMD этот бит называется NX, от слова "No eXecution" , а Intel обозвала его XD – "eXecution Disable" . Это самый старший бит(64) в записях виртуальных страниц PTE (Page Table Entry), который предотвращает исполнение данных. Для более детального ознакомления с ним отправляю вас к статье "DEP и ASLR – игра без правил" , где ему была посвящена одна глава. Как видно из скрина, мой древний проц поддерживает и его, и архитектуру Intel-64, хотя в упор не видит гигантских виртуальных страниц размером 1Gb (по-умолчанию 4Кб), и не знаком с современной инструкций генератора рандома RDTSCP . Для перехода в ядро при вызовах API-функций инструкция SYSCALL уже давно не юзается даже процессорами Pentium, и ей на смену пришла свежая SYSENTER .


3.2. Функции EAX=8000_0002/3/4 (Processor Brand String)

Цепочка этих трёх функций возвращает имя процессора, как его окрестил производитель. Под строку брэнда производитель резервирует 48 байт во-встроенной памяти ROM, поэтому чтобы получить её полностью, нужно вызвать эти функции последовательно 3-раза. При каждом запросе в регистры EAX,EBX,ECX,EDX будет возвращаться новая информация, поэтому не забываем сохранять её в выделенный буфер. В примере ниже я поместил счётчик цикла в переменную "count", и на каждой итерации увеличиваю номер функции в EAX:

eax_8002.jpg


3.3. Функция EAX=8000_0006h (Extended L2 Cache Features)

Ещё одна функция для сбора информации о кэше, только теперь исключительно об общем L2. Прямым текстом сообщает его размер и длину линейки, и в закодированном виде ассоциативность (мне лень было декодировать). Бьёт без промаха точно в цель на любых процессорах Intel, хоть 32, хоть 64-бит.

eax_8006.jpg

3.4. Функция EAX=8000_0008h (Virtual & Physical Address Sizes)

4. Пример кода для сбора информации CPUID

В заключении приведу готовый пример кода, который соберёт всю представленную выше информацию.

Result.jpg

Опыты выше показали, что CPUID изначально не способен возвратить некоторую информацию. К примеру в нём нет данных типа: кодовое имя ядра, порог рабочих напряжений, тип сокета, потребляемая мощность, и значение производственного тех.процесса. Судя по всему, софт на подобии CPU-Z хранит это всё в своих таблицах, которые программисты скурпулёзно собирают ручками. Базы подобного рода пишутся исходя из значений "Family/Model/Stepping", предоставляемые нам функцией CPUID.EAX=1 . В любом случае, теперь мы знаем, на что способен "зверь" под названием CPUID, и будем делать соответствующие выводы.

В скрепке можно найти инклуд с описанием дескрипторов кэшей, и исполняемый файл для тестов. Всем удачи, пока!

В первой части я рассказал о необходимости идентификации расширений, присутствующих на конкретном процессоре. Это нужно для того, чтобы исполняющийся код (операционная система, компилятор или пользовательское приложение) смог надёжно определить, какие возможности аппаратуры он может задействовать. Также в предыдущей статье я сравнил несколько популярных архитектур центральных процессоров общего назначения. Возможности по идентификации между ними сильно разнятся: некоторые предоставляют полную информацию о расширениях ISA, тогда как другие ограничиваются парой чисел для различения вендора и ревизии.
В этой части я расскажу об одной инструкции архитектуры Intel IA-32 — CPUID, введённой специально для перечисления декларируемых процессором расширений. Немного о том, что было до её появления, что она умеет сообщать, какие неожиданности могут поджидать и какой софт позволяет интерпретировать её вывод.



Источник изображения: [1]

История

Как я уже утверждал в первой части, присутствует следующая тенденция: чем более «встраиваемая» природа у процессора, тем меньше возможностей для идентификации заложено в его архитектуру. Создатели встраиваемых систем почему-то не волнуются о переносимости двоичного кода.

Не являлся исключением и Intel 8086 — микропроцессор 1970-х годов, выросший из «калькуляторной» серии 8008, 8080, 8085. Изначально в него не было заложено никаких средств идентификации.
Начиная с 808386 сведения о модели, степпинге и семействе стали сообщаться в регистре EDX сразу после перезагрузки (получения сигнала RESET). Инструкция CPUID, кодируемая байтами 0x0f 0xa2, была введена в процессорах 80486. Наличие CPUID можно было распознать по возможности записи в бит 21 регистра флагов. Для поддержки работы на более старых ЦПУ приходилось идти на очень изощрённые методы для того, чтобы различать процессоры серий от 8086 до 80386.

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

Интерфейс

Для системного программиста работа по идентификации некоторого расширения обычно заключается в установке входных значений в регистрах EAX (лист, англ. leaf) и ECX (подлист, англ. subleaf), исполнению CPUID и прочтению результата в четырёх регистрах: EAX, EBX, ECX, EDX. Отдельные битовые поля выходных регистров будут содержать информацию о значениях связанных с ними архитектурных параметров конкретного ядра процессора.

Все валидные сочетания входных листов-подлистов и четвёрок регистров на выходе формируют таблицу CPUID. Для современных процессоров она содержит около двух десятков строк по четыре 32-битных столбца.
Я не буду расписывать детально все официально описанные поля этой таблицы. Интересующиеся всегда могут найти их в Intel SDM [1] (рекомендую запастись терпением — около 40 страниц текста только про CPUID). Болеее того, для уже заявленных, но ещё не выпущенных в физических продуктах расширений ISA соответствующие им новые поля CPUID могут быть найдены в [3]. Вместо этого я классифицирую информацию, которую можно извлечь из вывода этой инструкции. Для обозначения битовых полей таблицы я буду использовать принятую для этого нотацию: CPUID.leaf.subleaf.reg[bitstart:bitend]. Например, CPUID.0.EBX[31:0] — это биты с 0 по 31 выходного регистра EBX после исполнения CPUID, которая на вход получила лист 0 (EAX = 0); подлист (входное значение ECX) игнорируется, поэтому он не указан.

Регионы листов

Неподдерживаемые значения входных EAX и ECX не приводят к возникновению исключений, а вместо этого возвращают нули во всех четырёх регистрах, либо «мусор» (значения другого листа согласно спецификации). Допустимые же сочетания листов и подлистов образуют три непрерывных региона.


  • Обычный регион — все листы с номерами, начиная с нулевого и до максимального значения, равного CPUID.0.EAX[31:0]. Номер максимального листа постоянно растёт и уже давно перевалил за десятку.
  • Расширенный регион — все листы, начиная с 0x80000000 и до максимального значения, равного CPUID.0x80000000.EAX[31:0]. Довольно долгое время это максимальное значение остаётся равным 0x80000008. Я не нашёл документальных доказательств, но у меня есть чувство, что само появление диапазона расширенных листов связанно с введением компанией AMD 64-битного расширения архитектуры IA-32.
  • Диапазон листов 0x40000000-0x4fffffff считается зарезервированным; обещается, что возвращаемые для него CPUID значения всегда будут равны нулю. Однако это не мешает некоторым использовать его для своих нужд. Например, виртуальные машины KVM возвращают в листе 0x40000000 четвёрку чисел [0, 0x4b4d564b, 0x564b4d56, 0x4d].

  • CPUID.1.ECX[0] — SSE3 — векторные инструкции.
  • CPUID.1.ECX[9] — SSSE3 — другие векторные инструкции.
  • CPUID.1.ECX[7] — EIST — Enhanced Intel SpeedStep®, динамическое изменение частоты процессора.
  • CPUID.1.EDX[25] — SSE — ещё векторные инструкции.
  • CPUID.1.EDX[26] — SSE2 — снова векторные инструкции.
  • CPUID.6.EAX[1] — Intel Turbo Boost, оверклокинг «из коробки».
  • CPUID.7.0.EBX[4] — Hardware Lock Elision, CPUID.7.0.EBX[11] — Restricted Transactional Memory — два расширения от Intel для поддержки транзакционной памяти.
  • CPUID.0x80000001.ECX[5] — LZCNT, инструкция для подсчёта числа старших нулевых бит, похожая (даже слишком) на BSR.
Brand String

Конечно же, ни один вендор не упустит возможности увековечить своё имя в идентификационных данных своего продукта. Причём желательно сделать это не просто в виде числа, а впечатать ASCII-строку (хорошо хоть, что не Unicode).
В IA-32 CPUID текст можно найти минимум в двух группах листов. CPUID.0.EBX, ECX, EDX содержат 12 байт ASCII-строки, специфичной для каждого вендора. Для Intel это, конечно же, «GenuineIntel». А три листа CPUID.0x80000002–0x80000004 предоставляют аж 48 байт для кодирования в ASCII так называемой Brand String. Именно её видно при распечатке cat /proc/cpuinfo в Linux. И, хотя формат её более-менее стандартизован: «вендор марка серия CPU @ частота», я настоятельно не рекомендую по её содержимому принимать решения в программном коде. Слишком значительно её содержимое может варьироваться: частота может быть указана в МГц или в ГГц (а в реальности быть совсем иной из-за динамической подстройки), пробелы могут менять положение, а симулятор или виртуальная машина могут подставить туда вообще что угодно. Вся информация из brand string может быть найдена программно более надёжными способами.

Информация о кэшах, такая как их тип, количество, ёмкость, геометрия, разделяемость между ядрами полезна для тюнинга высокопроизводительного математического софта, например, библиотек BLAS (basic linear algebra system).
Изначально конфигурацию кэшей описывал лист 2. Спроектировали его не очень дальновидно. Формат кодирования информации в нём был выбран не самый гибкий, он не смог в будущем поддержать постоянные изменения в объёме и конфигурации нескольких уровней кэшей. В настоящее время использование информации из листа 2 не рекомендуется, там могут стоять 0xFF-ки.
Судя по тому, что лист 0x80000006 входит в расширенный диапазон (хотя я не уверен, документальных доказательств пока что не нашёл), он был добавлен не Intel. С помощью него была сделана попытка информацию листа 2 дополнить данными о строении кэшей, которые потребовались разработчикам софта. При этом опять же не было намерения предоставить пространство для роста.
Лист 4 — последнее и пока что наиболее гибкое представление данных о кэшах. Цена этому — добавление концепции подлистов, кодируемых в ECX. Каждый подлист описывает один кэш: данных, кода или совмещённый, определяет его уровень, ёмкость и т.д. Хватит ли четвёртого листа надолго — поживём, увидим.

Топология
  • SMT — уровень гипер-потока, сущности, содержащей индивидуальное архитектурное состояние (регистры), но потенциально разделяющей исполнительные устройства с другими потоками (в составе одного ядра).
  • Ядро (core) — сущность, содержащая индивидуальный набор вычислительных устройств (сумматоров, умножителей и т.д.). Одно ядро может иметь в себе один, два (у ЦПУ с HyperThreading) или четыре (у Xeon Phi) гипер-потока.
  • Пакет (пэкадж, package) — собственно железка целиком, покупаемая в магазине и вставляемая в разъём (сокет) на матплате. Имеет на себе как минимум одно ядро. В многопроцессорных серверных системах может быть несколько пэкаджей.
Изменяемые поля
  • Бит 18 регистра CR4 влияет на CPUID.1:ECX.OSXSAVE[27], обозначающий поддержку инструкции XSAVE.
  • Поля регистра IA32_MISC_ENABLE влияют сразу на несколько полей CPUID: бит 3 — на поля TM1 и TM2, бит 16 — на поле EIST, бит 34 — на поле XD (execution disable) и т.д.
  • Включение бита 22 регистра IA32_MISC_ENABLE вообще «отрезает» все листы таблиц CPUID старше третьего (видимо, это было сделано для совместимости с Windows NT4, не зря этот бит так и называется — NT4).
Разное

В этой секции я собрал прочие интересные моменты, связанные с историей и работой команды CPUID.

Processor Serial Number

Во времена Pentium III каждый процессор получил уникальный серийный номер, содержавшийся в CPUID.3.ECX и CPUID.3.EDX [7]. Легко представить, насколько такая фича была бы удобна для нужд защиты ПО от копирования. Однако в 1999 году Европейское сообщество запротестовало, разумно опасаясь, что подобная функциональность повредит приватности пользователей таких систем. Уже в Intel Pentium IV серийный номер был убран, сейчас лист 3 возвращает нули.

Вендоры и CPUID

Очень интересная таблица [5] повествует о том, что хранят (или в прошлом хранили) в разных листах CPUID разные вендоры. Например, описывается некий mystery level 0x8fffffff, в котором процессоры AMD K8 возвращали строку IT'S HAMMER TIME.

Agner Fog о войнах ISA

История появления расширений набора инструкций IA-32 в условиях конкурентной борьбы нескольких компаний [4]. Добавление новых инструкций всегда влияло на CPUID, и не всегда все могли договориться о том, как это сделать правильно.

Они испортили CPUID! IA32_BIOS_SIGN_ID

Инструкция CPUID всегда нравилась мне лаконичностью своего интерфейса и отсутствием неожиданностей в работе: один регистр на входе и четыре на выходе. В её работе нет генерации исключений, нет обращений к памяти, нет чтения/модификации регистра флагов, на неё не влияют префиксы, она работает во всех режимах процессора. По сравнению с зоопарком CISC-команд IA-32 это был почти идеал.
… пока не оказалось, что иногда на вход необходимо подать два регистра для кодирования листа и подлиста. Окей, не так всё хорошо. Ну хотя бы выходные регистры заранее известны и всегда изменяются…
И тут оказалось, что иногда CPUID изменяет ещё один регистр — а именно IA32_BIOS_SIGN_ID, — и сохраняет в нём сигнатуру текущей программы микрокода процессора. Происходит это, если до этого было произведено обновление прошивки процессора. По каким-то причинам информация об этой процедуре была раскидана по мануалу [1] на тысячу страниц, и потому она ускользала от меня очень долго.

Интересуют методы через которые можно получить id процессора средствами c++.


12.1k 12 12 золотых знаков 37 37 серебряных знаков 68 68 бронзовых знаков


средствами c++ - никак, используйте интринсики или соотв. библиотеки @avp Задача состоит в получение данных от клиента для бана. Нужны любые уникальные данные о компьютере которые записываются в бд. Из наших наблюдений у людей с взломанной виндой совпадают айди матери и cpu. По этому ищем другие пути. Мак адрес должен быть уникален, но у некоторых юзеров встречаются ошибки с ACCESS_VIOLATION.

Не каждый процессор возвращает в CPUID уникальный серийный номер. Чтобы уникально идентифицировать компьютер, имеет смысл использовать составной аппаратный идентификатор, состоящий из нескольких значений, например:

  • CPUID
  • SMBIOS System UUID
  • Серийный номер системника
  • Серийный номер материнской платы

Все эти значения можно программно получить из таблицы SMBIOS. MAC-адреса сетевых интерфейсов, конечно, тоже можно добавить, но следует помнить, что компьютер может иметь несколько сетевых интерфейсов, нельзя просто взять первый попавшийся - он может быть виртуальным.

Пример для Windows (код для чтения таблицы SMBIOS взят из проекта sysinv):


19.7k 6 6 золотых знаков 33 33 серебряных знака 76 76 бронзовых знаков

Попробуйте через команду cpuid. Полная инструкция :

Может быть там есть, что вы ищете. Пример :

4.2. Forming the 96-bit Processor Serial Number The 96-bit processor serial number is the concatenation of three 32-bit entities. To access the most significant 32-bits of the processor serial number the program should set the EAX register parameter value to “1” and then execute the CPUID instruction as follows: MOV EAX, 01H CPUID After execution of the CPUID instruction, the EAX register contains the Processor Signature. The Processor Signature comprises the most significant 32-bits of the processor serial number. The value in EAX should be saved prior to gathering the remaining 64-bits of the processor serial number. To access the remaining 64-bits of the processor serial number the program should set the EAX register parameter value to “3” and then execute the CPUID instruction as follows: MOV EAX, 03H CPUID After execution of the CPUID instruction, the EDX register contains the middle 32-bits, and the ECX register contains the least significant 32-bits of the processor serial number. Software may then concatenate the saved Processor Signature, EDX, and ECX before returning the complete 96-bit processor serial number. Processor serial number should be displayed as 6 groups of 4 hex nibbles (Ex. XXXX-XXXX-XXXX-XXXXXXXX-XXXX where X represents a hex digit). Alpha hex characters should be displayed as capital letters.

Судя по приватности запрос с EAX=0x03 всегда возвращает ноль. Пользуйтесь всей другой доступной информацией. Иногда люди пользуются виртуальными компьютерами. Так-что запрос идентичности не очень получиться у вас.

Данная программа сообщает сведения о процессоре Intel®, в частности, название и номер процессора Intel®, а также показывает, поддерживает ли процессор HD-графику Intel®.

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

В программе есть три раздела: Частота процессора, Процессорные технологии и CPUID

ПО для идентификации процессоров Intel

Какая информация отображается на вкладке «ЧАСТОТА ПРОЦЕССОРА»?

  • Ожидаемая и отображаемая частота
  • Информация о кэш-памяти
  • Количество ядер и вычислительных потоков

Вкладка «Частота процессора»

Какая информация отображается на вкладке «ТЕХНОЛОГИИ ПРОЦЕССОРА»?

Информация о поддержке технологий и наборов команд Intel® Virtualization, Intel® Hyper-Threading, Enhanced Intel SpeedStep® , Intel® AES New Instructions, Intel® Advanced Vector Extensions, Intel® Internet Streaming SIMD Extensions (SSE), Execute Disable Bit Enhanced halt state и архитектуры Intel® 64

Вкладка «Технологии процессора»

Какая информация отображается на вкладке «ДАННЫЕ CPUID»?

  • Тип процессора, семейство, модель, степпинг и CPUID
  • Информация о кэш-памяти
  • Название графического контроллера

вкладка CPUID

Как сохранить информацию о процессоре с помощью этой программы?

В меню «Файл» нажмите «Сохранить», выберите папку и нажмите «ОК». Текстовый файл будет сохранен в выбранной вами папке.

Существует ли версия ПО для идентификации процессоров Intel® для Linux*?

Нет, у этой программы нет версии для Linux*.

Какие поддерживаются версии операционной системы (ОС) Windows*?

Какие процессоры Intel® поддерживает ПО для идентификации процессоров Intel®?

Читайте также: