web-dev-qa-db-ja.com

Virtualbox、特定のCPUをゲストに強制する方法

私はXPゲストを持っています。Windows8ホスト。ゲストはホスト(i5 2500k)と透過的に同じプロセッサを表示します。しかし、ほとんどのインストーラはこのプロセッサを認識せず、失敗しますサポートされていないプロセッサの説明を続けます。

これを古いプロセッサだとゲストをだます方法はありますか? VMWareにCPUマスキング機能があったことを正しく思い出せば、virtualboxにも同様の機能はありますか?

16
IUnknown

VirtualBoxとCPUIDの基本

仮想マシンの_VBoxInternal/CPUM/HostCPUID_エクストラデータを設定する必要があります。これにより、ゲストへの [〜#〜] cpuid [〜#〜] 命令のVirtualBoxレポートカスタム結果が作成されます。 EAXレジスターの値に応じて、この命令はプロセッサーに関する情報(ベンダー、タイプ、ファミリー、ステッピング、ブランド、キャッシュサイズ、機能(MMX、SSE、SSE2、PAE、HTT)など)を返します。より多くの結果マングルすると、ゲストをだます可能性が高くなります。

_vboxmanage setextradata_ コマンドを使用して、仮想マシンを構成できます。例えば、

_vboxmanage setextradata WinXP VBoxInternal/CPUM/HostCPUID/80000003/ebx 0x50202952
_

eAXを80000003に設定して呼び出された場合、CPUIDはEBXレジスタに50202952を返します。 (これ以降、16進数は0xNNまたはNNhとして書き込まれます。)

CPUベンダー文字列の設定

EAXが0(またはAMDでは80000000h)の場合、CPUIDはベンダーをASCII文字列レジスタEBX、EDX、ECX(順序に注意)として返します)。AMDCPUの場合、次のようになります。 :

_| Register | Value      | Description                    |
|----------|------------|--------------------------------|
| EBX      | 6874_7541h | The ASCII characters "h t u A" |
| ECX      | 444D_4163h | The ASCII characters "D M A c" |
| EDX      | 6974_6E65h | The ASCII characters "i t n e" |
_

AMD CPUID仕様 から取得、サブセクション「CPUID Fn0000_0000_E」)

EBX、EDX、ECXを連結すると、AuthenticAMDが得られます。

Bashと従来のUnixユーティリティがある場合は、次のコマンドでベンダーを簡単に設定できます。

_vm='WinXP'  # UUID works as well
# The vendor string needs to have 12 characters!
vendor='AuthenticAMD'
if [ ${#vendor} -ne 12 ]; then
    exit 1
fi
ascii2hex() { echo -n 0x; od -A n --endian little -t x4 | sed 's/ //g'; }

registers=(ebx edx ecx)
for (( i=0; i<${#vendor}; i+=4 )); do
    register=${registers[$(($i/4))]}
    value=`echo -n "${vendor:$i:4}" | ascii2hex`
    # set value to an empty string to reset the CPUID, i.e.
    # value=""
    for eax in 00000000 80000000; do
        key=VBoxInternal/CPUM/HostCPUID/${eax}/${register}
        vboxmanage setextradata "$vm" $key $value
    done
done
_

CPUブランド文字列の設定

EAXが80000002h、80000003h、80000004hの場合、CPUIDはブランドストリングの16 ASCII文字をレジスターEAX、EBX、ECX、EDX、合計3 * 16 = 48文字で返します;文字列は- null文字で終了 。この機能はPentium 4プロセッサで導入されたことに注意してください。これは、Pentium 4プロセッサでブランド文字列がどのように見えるかを示しています。

_| EAX Input Value | Return Values   | ASCII Equivalent |
|-----------------|-----------------|------------------|
| 80000002h       | EAX = 20202020h | "    "           |
|                 | EBX = 20202020h | "    "           |
|                 | ECX = 20202020h | "    "           |
|                 | EDX = 6E492020h | "nI  "           |
|-----------------|-----------------|------------------|
| 80000003h       | EAX = 286C6574h | "(let"           |
|                 | EBX = 50202952h | "P )R"           |
|                 | ECX = 69746E65h | "itne"           |
|                 | EDX = 52286D75h | "R(mu"           |
|-----------------|-----------------|------------------|
| 80000004h       | EAX = 20342029h | " 4 )"           |
|                 | EBX = 20555043h | " UPC"           |
|                 | ECX = 30303531h | "0051"           |
|                 | EDX = 007A484Dh | "☠zHM"           |
|-----------------|-----------------|------------------|
_

インテルアーキテクチャインストラクションセットエクステンションプログラミングリファレンス 、サブセクション2.9、「CPUIDインストラクション」、表2-30から取得。☠は null文字 (数値0)です。)

結果をまとめると、Intel(R) Pentium(R) 4 CPU 1500MHz☠になります。

Bashと従来のUnixユーティリティがある場合は、次のコマンドでブランドを簡単に設定できます。

_vm='WinXP'  # UUID works as well
# The brand string needs to have 47 characters!
# The null terminator is added automatically
brand='              Intel(R) Pentium(R) 4 CPU 1500MHz'
if [ ${#brand} -ne 47 ]; then
    exit 1
fi
ascii2hex() { echo -n 0x; od -A n --endian little -t x4 | sed 's/ //g'; }

eax_values=(80000002 80000003 80000004)
registers=(edx ecx ebx eax)
for (( i=0; i<${#brand}; i+=4 )); do
    eax=${eax_values[$((${i} / 4 / 4))]}
    register=${registers[$((${i} / 4 % 4 ))]}
    key=VBoxInternal/CPUM/HostCPUID/${eax}/${register}
    value=`echo -n "${brand:$i:4}" | ascii2hex`
    # set value to an empty string to reset the CPUID, i.e.
    # value=""
    vboxmanage setextradata "$vm" $key $value
done
_

Windowsコマンドプロンプトがある場合は、ブランドをIntel(R) Core(TM)2 CPU 6600 @ 2.40 GHzに設定できます。1 実行することにより:

_set vm=your-vm-name-or-uuid
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000002/eax 0x65746e49
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000002/ebx 0x2952286c
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000002/ecx 0x726f4320
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000002/edx 0x4d542865
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000003/eax 0x43203229
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000003/ebx 0x20205550
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000003/ecx 0x20202020
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000003/edx 0x20202020
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000004/eax 0x30303636
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000004/ebx 0x20402020
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000004/ecx 0x30342e32
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000004/edx 0x007a4847
_

Computer: Intel(R) Core(TM)2 CPU 6600 @ 2.40 GHz

1HostCPUIDの値は、VirtualBoxバグレポート #7865 から取得されました。

20

次に、必要な設定を推測するのではなく、ホストCPUを特定のCPUとして正確に偽装できる方法を示します。そのホストCPUでVirtualBoxを実行しているマシンにアクセスする必要があるので、そのcpuidレジスタをダンプできます(モデルとしての実際のCPUのアーキテクチャにかなり類似しているアーキテクチャを選択することがおそらく最善です)。手元にない場合は、質問してみてください(たとえば、私はRedditで成功しました)。

  1. エミュレートしたいCPUから「モデル」ファイルを作成します。

    vboxmanage list hostcpuids > i7_6600U
    
  2. ターゲットホストで、変更したいVM=が実行されていないことを確認してください。念のため、バックアップを取ることをお勧めします。
  3. 次のスクリプトを実行して、モデルファイル(i7_6600U here)をVBoxの定義にロードしますVM(my_vm_name here):

    #!/bin/bash
    vm=my_vm_name
    model_file=i7_6600U
    
    egrep -e '^[[:digit:]abcdef]{8} ' $model_file |
    while read -r line; do
        leaf="0x`echo $line | cut -f1 -d' '`"
        # VBox doesn't like applying leaves between the below boundaries so skip those:
        if [[ $leaf -lt 0x0b || $leaf -gt 0x17 ]]; then
            echo "Applying: $line"
            vboxmanage modifyvm $vm --cpuidset $line
        fi
    done
    
  4. これで終わりです。VMを実行して、マスカレードされたCPUを楽しむことができます(注:上記のスクリプトを実行する必要があるのは1回だけです)。

CPUマスカレードをロールバックする必要がある場合は、上記のループの各リーフに対してvboxmanage modifyvm $vm --cpuidremove $leafを使用できます(man vboxmanageはあなたの友達です)。

これは、私にとって数か月間問題なく機能しており、Kaby Lake CPU(i7_7500U)を、VBox 5.1.22を実行するUbuntu 17.04ホスト上のSkylake CPU(i7_6600U)に見せかけています。上記の小さなbashスクリプトと同等のOSを作成できれば、このアプローチはどのホストOSでも機能するはずです。

6
sxc731