CPUIDの変更方法

VirtualBoxを使用するとゲストOSに対してホストPCと異なるCPUID値を与えることができる。
たとえば、SSE2を未サポートにしたり、CPU名称を変更したりできる。
以下 VirtualBox Version 5.0.8 r 103449での動作について解説する。
CPUIDの変更はVBoxManageコマンドを使用する。
VBoxManage modifyvm 名前 --cpuidset ファンクション番号 EAX EBX ECX EDX
名前はOracle VM VirtualBox マネージャーで表示されている名称を入力する。
ファンクション番号は変更したいCPUIDのファンクション番号、EAX~EDXはCPUID命令が出力する各レジスタの値を16進数で記述する。
サポートするファンクション番号の範囲は、基本ファンクションがファンクション0のEAXレジスタ、拡張ファンクションがファンクション0x80000000のEAXレジスタで設定する。
CPUIDの値を初期値に戻すときは、以下の様に入力する
VBoxManage modifyvm 名前 --cpuidremoveall
コマンドは、VirtualBoxがインストールフォルダー(通常は、C:¥Program Files¥Oracle¥VirtualBox)に存在するので、カレントディレクトリを変更するか、 環境変数PATHにパスを通すかバッチファイルの場合、環境変数VBOX_MSI_INSTALL_PATHが使える。
マルチブート環境はインストールがCドライブとは限らないので、環境変数を使用すると便利である。 環境変数VBOX_MSI_INSTALL_PATHはVirtualBoxがインストールされている場合に定義され、インストールフォルダーを示している。(通常は、C:¥Program Files¥Oracle¥VirtualBox¥が定義されている)
環境変数の前後に%を入れるとバッチファイルで環境変数の値を参照できる。インストールフォルダーは通常Program Filesの下である。Program Filesの様に途中で空白があると、コマンド名がProgramと解釈されてしまうので、以下の様に全体をダブルコーテーションでくくる。
"%VBOX_MSI_INSTALL_PATH%VBoxManage" modifyvm 名前 --cpuidset ファンクション番号 EAX EBX ECX EDX
以下に仮想環境の名前がWindows Vistaの場合にCPUの名称のみをAMD Athlon 64 3200+に変更する場合のバッチファイルの記述例を示す。
これを実行すると仮想環境Windows VistaのCPUの名称がAthlon 64 3200+となる。 同じ名前を何回も記述しなくても良い様に環境変数VM_NAMEに名前を定義し各行で参照している。
set VM_NAME="Windows Vista"
"%VBOX_MSI_INSTALL_PATH%VBoxManage" modifyvm %VM_NAME% --cpuidset 80000000 80000004 68747541 444D4163 69746E65
"%VBOX_MSI_INSTALL_PATH%VBoxManage" modifyvm %VM_NAME% --cpuidset 80000002 20444D41 6C687441 74286E6F 3620296D
"%VBOX_MSI_INSTALL_PATH%VBoxManage" modifyvm %VM_NAME% --cpuidset 80000003 72502034 7365636F 20726F73 30303233
"%VBOX_MSI_INSTALL_PATH%VBoxManage" modifyvm %VM_NAME% --cpuidset 80000004 0000002B 00000000 00000000 00000000
set VM_NAME=
pause
実行は作成したバッチファイルをダブルクリックをすればよい。
pauseはバッチファイルが一瞬で実行され実行結果が分からなくなるので、キー入力があるまでバッチファイルで起動されたコマンドプロンプトを閉じないようにするためである。 上記の内容のバッチファイルを仮想環境を停止した状態で実行し仮想環境を起動すると下図のようにIntel入ってるPC(Intel Core i7-3820)で実行しているにもかかわらずゲストOSではIntel入っていない(AMD Athlon(tm) 64 Processor 3200+)になる。
下図のWindows Vistaのログインユーザー名は着色してわからないようにしています。


バッチファイルでCPU名に対応しているのが赤で示した部分です。
以下の様にアスキーコードで4文字(4byte)ずつリトルエンディアンで記述します。すなわち4文字単位で文字順を逆にしアスキーコードを16進数で記述すればOKです。文字列の最後は00である必要があります。
最大で00を含めて48文字となります。
  D M A  l h t A  t ) n o   6  ) m
20444D41 6C687441 74286E6F 3620296D
r P   4  s e c o    r o s  0 0 2 3
72502034 7365636F 20726F73 30303233
      +
0000002B 00000000 00000000 00000000
アスキーコード表
0 1 2 3 4 5 6 7 8 9 A B C D E F
2 ! " # $ % & ' ( ) * + , - . /
3 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
4 @ A B C D E F G H I J K L M N O
5 P Q R S T U V W X Y Z [ \ ] ^ _
6 ` a b c d e f g h i j k l m n o
7 p q r s t u v w x y z { | } ~ 
A  
B ソ
C
D
仮想環境なので意味はありませんが、8088、Z80、6809、Xeon、Crusoe TM5600,Pentium 5 10GHzなどCPU名や人名などアスキー文字(Windows Vistaでは半角カタカナも正常動作した)に限られますが変更できます。
各種CPUのCPUIDの値を調べる場合は以下のページが便利です。
http://users.atw.hu/instlatx64/ リンク先のCPUID Dumpをクリックすると各CPUのCPUIDが参照できます。
またCPUIDのファンクションについてはIntelのデーターシートの他以下のリンク先を参照しました。
http://sandpile.org/x86/cpuid.htm
以下にいくつかのCPU用のバッチファイルを用意しています。ダウンロードし仮想環境名を変更して実行するとCPUIDが変更できます。

CPUIDの変更の影響

ゲストOSにおいて変更したCPUIDがどのように影響するか調べた。
ここではCPU i7-3820で動作するVirtualBoxのゲストOSがWindows Vistaであり、割り当てCPU数が4の場合のゲストマシーンのCPUIDを変更した場合の動作について示す。
ホストCPUの仕様
CPU ホストCPU
構成 キャッシュ(1コア当り) ファンクション最大
コア スレッド(1コア当り) L1 Inst L1 Data L2 L3 L4 基本 拡張
i7-3820 3.60GHz 4 2 32k 32k 256k 2560k 0x0d 0x08

CPUIDの変更によるゲストOSへの影響一覧
CPU シミュレーションされるCPU ゲストCPU
構成 キャッシュ(1コア当り) ファンクション最大 構成 キャッシュ(1コア当り)
コア スレッド(1コア当り) L1 Inst L1 Data L2 L3 L4 基本 拡張 ソケット コア スレッド(1コア当り) L1 Inst L1 Data L2 L3 L4
Celeron 2.00GHz 1 1 12kμ 8k 128k 0x02 0x04 1 4 1 12kμ 8k 128k
Pentium4 3.40GHz 1 2 12kμ 16k 2048k 0x06 0x08 1 4 1 16k 16k 256k 10240k
PentiumD 3.40GHz 2 1 12kμ 16k 2048k 0x06 0x08 1 4 1 16k 16k 256k 10240k
Core2 6320 1.86GHz 2 1 32k 32k 2048k 0x0a 0x08 1 4 1 16k 32k 256k 10240k
Core2 Q8200 2.33GHz 4 1 32k 32k 1024k 0x0a 0x08 1 4 1 16k 32k 256k 10240k
i7 CPU 870 2.93GHz 4 2 32k 32k 256k 2048k 0x0b 0x08 1 4 1 16k 32k 256k 10240k
i7-4770 3.40GHz 4 2 32k 32k 256k 2048k 0x0d 0x08 1 4 1 16k 32k 256k 10240k
i3-2100 3.10GHz 2 2 32k 32k 256k 1536k 0x0d 0x08 1 4 1 16k 32k 256k 10240k
i7-2600 3.40GHz 4 2 32k 32k 256k 2048k 0x0d 0x08 1 4 1 16k 32k 256k 10240k
i7-5775C 3.30GHz 4 2 32k 32k 256k 1536k 32768k 0x14 0x08 1 4 1 16k 32k 256k 10240k
i7-6700K 4.00GHz 4 2 32k 32k 256k 2048k 0x16 0x08 1 4 1 16k 32k 256k 10240k
i5-2400 3.10GHz 4 1 32k 32k 256k 1536k 0x0d 0x08 1 4 1 16k 32k 256k 10240k
Atom D2701 2.13GHz 2 2 32k 24k 512k 0x0a 0x08 1 4 1 16k 24k 256k 10240k
Pentium2 450MHz 1 1 16k 16k 512k 0x02 1 4 1 16k 16k 512k
MMX Pentium 1 1 16k 16k 0x01 1 4 1 16k 16k

ホストCPUの仕様
CPU ホストCPU
構成 キャッシュ(1コア当り) ファンクション最大
コア スレッド(1コア当り) L1 Inst L1 Data L2 L3 L4 基本 拡張
i3 M370 2.40GHz 2 2 32k 32k 256k 1536k 0x0b 0x08

CPUIDの変更によるゲストOSへの影響一覧
CPU シミュレーションされるCPU ゲストCPU
構成 キャッシュ(1コア当り) ファンクション最大 構成 キャッシュ(1コア当り)
コア スレッド(1コア当り) L1 Inst L1 Data L2 L3 L4 基本 拡張 ソケット コア スレッド(1コア当り) L1 Inst L1 Data L2 L3 L4
Celeron 2.00GHz 1 1 12kμ 8k 128k 0x02 0x04 1 4 1 12kμ 8k 128k
i7 CPU 870 2.93GHz 4 2 32k 32k 256k 2048k 0x0b 0x08 1 4 1 32k 32k 256k 3072k
Core2 6320 1.86GHz 2 1 32k 32k 2048k 0x0a 0x08 1 4 1 32k 32k 256k 3072k
Core2 Q8200 2.33GHz 4 1 32k 32k 1024k 0x0a 0x08 1 4 1 32k 32k 256k 3072k
i3-2100 3.10GHz 2 2 32k 32k 256k 1536k 0x0d 0x08 1 4 1 32k 32k 256k 3072k
i7-2600 3.40GHz 4 2 32k 32k 256k 2048k 0x0d 0x08 1 4 1 32k 32k 256k 3072k
i7-4770 3.40GHz 4 2 32k 32k 256k 2048k 0x0d 0x08 1 4 1 32k 32k 256k 3072k
※ファンクション最大の基本は基本ファンクションで指定できる最大値を示す。
※ファンクション最大の拡張は拡張ファンクションで指定できる最大値から0x80000000を引いた値を示す。(例えばCeleron 2.00GHzでは0x80000000+0x04=0x80000004が指定できる最大値となる。)記載なき場合は拡張ファンクションを使用できないことを示す。
以上よりCPUIDの基本ファンクションが4以上をサポートしている場合は、L2以降はホストCPUのCPUIDがそのまま反映されそれにゲストCPU数が影響している。
CPUIDの基本ファンクションが4以上をサポートしているPentium4系についてはL1キャッシュも影響を受けている。
i7-3820がホストCPUの場合、CPUIDのファンクション1の結果、ハイパースレッドがON(EDXのビット28が1)で基本ファンクションが4以上をサポートしている場合、L1命令キャッシュが半分の容量となる。
ゲストOSではCPUIDでPentium2相当にしてもハイパースレッドがONとなっていた。
VBoxManage modifyvmコマンドによりゲストCPUのCPUIDの変更は基本ファンクションでは0xb以降はエラーとなり無視されるが、0xb以降が必要な場合は、VirtualBoxが自動的にCPUID値を提供している。またホストCPUがサポートしているファンクション以上のCPUIDが使用できている。(ホストCPUの基本ファンクションが0xbまででもCPUID値で0x14とすればゲストでは0x14まで使用できる可能性がある。)
ホストCPUがサポートしている機能であればCPUIDで使用可能としていればゲストCPUでも使用できる。ホストCPUがサポートしていない機能は、VirtualBoxがCPUID値を修正して未サポートとしている。(ホストでAVX2が未サポートであればCPUIDでAVX2をONしてもゲストCPUでは未サポートとなる)
ブランド情報(ストリング、ID等)およびプロセッサのステッピング、モデル、ファミリー等は設定したCPU値が反映される。
CPUID値でハイパースレッドをONにしコアあたりのスレッド数を2にしてもハイパースレッドがONの1コア当り1スレッドのCPUに変換される。
したがってゲストOSに割り当てるCPU数が同じであればPentium4とPentiumDおよびCore2DuoとCore2Quadやi3~i7は同一となる。
VirtualBoxでは物理パッケージが複数個存在する設定はできないようなので1つの物理パッケージの中のコア数が変化することになる。)
従って、マルチコアCPUが存在しない世代のCPUであれば本来複数ソケットとなるはずがマルチコアとしてエミュレーションされることとなる。