Virtualbox, как заставить конкретный процессор для гостя

14

У меня гость XP в VirtualBox, хост Windows 8. Гость показывает процессор прозрачно так же, как хост (i5 2500k). Однако большинство установщиков не распознают эти процессоры и не могут продолжить указывать неподдерживаемый процессор.

Есть ли способ обмануть гостя, думая, что это старый процессор? Если я правильно помню, у VMWare была функция маскировки процессора, есть ли что-то похожее в virtualbox?

IUnknown
источник
Какое программное обеспечение вы устанавливаете, чтобы проверить модель процессора?
Дарт Андроид
Двойной агент управления, Orca и Wix. Это для проекта VB6, который мы пытаемся возродить.
Неизвестно

Ответы:

19

Основы VirtualBox и CPUID

Вам необходимо установить VBoxInternal/CPUM/HostCPUIDдополнительные данные виртуальной машины. Это заставит VirtualBox сообщать гостю о пользовательских результатах для инструкции CPUID . В зависимости от значения регистра EAX, эта инструкция возвращает информацию о процессоре - такие как поставщик, тип, семейство, степпинг, бренд, размер кэша, функции (MMX, SSE, SSE2, PAE, HTT) и т. Д. Чем больше результатов ты будешь калечить, тем выше шансы одурачить гостя.

Вы можете использовать vboxmanage setextradataкоманду для настройки виртуальной машины. Например,

vboxmanage setextradata WinXP VBoxInternal/CPUM/HostCPUID/80000003/ebx 0x50202952

заставит CPUID возвращать 50202952₍₁₆₎ в регистр EBX при вызове с EAX, установленным в 80000003₍₁₆₎. (С этого момента шестнадцатеричные числа будут записываться как 0xNN или NNh.)

Установка строки поставщика ЦП

Если EAX равен 0 (или 80000000h для AMD), CPUID возвращает поставщика в виде строки ASCII в регистрах EBX, EDX, ECX (обратите внимание на порядок). Для процессора AMD они выглядят так:

| 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

Установка строки марки процессора

Если EAX равен 80000002h, 80000003h, 80000004h, CPUID возвращает 16 символов ASCII строки бренда в регистрах EAX, EBX, ECX, EDX, всего 3 * 16 = 48 символов; строка заканчивается нулевым символом . Обратите внимание, что эта функция была введена с процессорами 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"           |
|-----------------|-----------------|------------------|

(Взято из Справочника по программированию расширений набора команд архитектуры Intel , подраздел 2.9, «Инструкция CPUID», таблица 2-30. ☠ - нулевой символ (числовое значение 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 GHz1 , запустив:

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

Компьютер: Intel (R) Core (TM) 2, процессор 6600 @ 2,40 ГГц

1 В HostCPUIDзначении было взято из VirtualBox Сообщения об ошибке # 7865 .

Кристиан Чиупиту
источник
Благодарю. У меня сломалась виртуальная машина с VERR_CFGM_INVALID_CHILD_PATH.
Бен Синклер
1
sed должен использоваться с флагом G:'s/ //g'
Бен Синклер
1
Какой отличный ответ! И с появлением процессоров Kaby Lake, это внезапно стало наиболее интересным из-за определенной политики Redmond не поддерживать Windows 7 на этих ... Кажется, что все, что не хватает, это инструкции о том, как установить "EAX = 1: Информация о процессоре и функциональные биты », поскольку они не являются простыми строками (при использовании только марки ЦП CPU-Z по-прежнему распознает ЦП как KL); кто-нибудь знает?
sxc731
1
Согласно forums.virtualbox.org/viewtopic.php?f=2&t=77211#p359428 , может быть лучший (более краткий, более поддерживаемый) способ установки этих значений.
Марк Эмери
@MarkAmery, спасибо за ссылку. Это хорошо работает для бренда, но не так хорошо для продавца, потому что поставщик не задан в регистре EAX, а --cpuidподкоманда требует значения для регистра EAX.
Кристиан Чиупиту
5

Вот подход, который позволяет маскировать центральный процессор именно под конкретный процессор, а не пытаться угадать необходимые настройки. Вам понадобится доступ к машине с VirtualBox на этом хост-процессоре, чтобы вы могли выгружать его cpuidрегистры (вероятно, лучше выбрать архитектуру, которая достаточно похожа на модель вашего фактического ЦП в качестве модели). Если у вас нет руки, вы можете поспрашивать (например, у меня был успех на Reddit).

  1. Создайте файл модели из процессора, который вы хотите эмулировать:

    vboxmanage list hostcpuids > i7_6600U
    
  2. На целевом хосте убедитесь, что виртуальная машина, которую вы хотите изменить, не работает; Вы можете сделать резервную копию на всякий случай.
  3. Запустите следующий скрипт, чтобы загрузить файл модели ( i7_6600Uздесь) в определение вашей виртуальной машины VBox ( my_vm_nameздесь):

    #!/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. Вот и все, теперь вы можете запустить свою виртуальную машину и наслаждаться маскарадным процессором (примечание: вам нужно запустить вышеупомянутый скрипт только один раз).

Если вам когда-нибудь понадобится откатить маскарад ЦП, вы можете использовать vboxmanage modifyvm $vm --cpuidremove $leafдля каждого из листьев в вышеуказанном цикле ( man vboxmanageэто ваш друг).

Для меня это работало безупречно в течение нескольких месяцев, маскируя процессор Kaby Lake (i7_7500U) под Skylake (i7_6600U) на хосте Ubuntu 17.04 с VBox 5.1.22. Подход должен работать на любой хост-ОС, при условии, что вы можете создать эквивалент маленького скрипта bash выше для этой ОС.

sxc731
источник
Что касается части «Установка строки поставщика ЦП», у меня есть комментарий: Вы должны обязательно изменить имя поставщика на «AuthenticAMD» на процессоре AMD и «GenuineIntel» на процессоре Intel. Если вы используете «GenuineIntel» на процессоре AMD, виртуальная машина очень вероятно сломается.
Абулхол
Большое спасибо за это! Это работает как шарм на моем Ryzen 7700K. Я использовал старую материнскую плату AMD Socket SF2, чтобы получить CPUID, запустив Ubuntu LiveCD, установив VirtualBox в реальной среде и выполнив команду vboxmanage. На стороне хоста я установил подсистему Windows для Linux, чтобы я мог запустить приглашение Bash в Windows 10 и запустить сценарий, которым вы поделились. Теперь я могу обмануть свою виртуальную машину Windows 7, заставив ее думать, что у меня A8-5600K.
njbair
Рад, что это работает и для вас! Я должен был уточнить, что ничего из этого не требует хоста Linux; даже не собирая файл "model", все, что ему нужно, это VirtualBox, работающий на этой машине. Сценарий bash может показаться сложным, но все, что он делает, это читает строки из файла модели, пропуская листья между 0000000bи 00000017(включительно) и пропуская их один за другим, vboxmanage modifyvm my_vm_name --cpuidset <line>так что это можно легко сделать вручную, так как он одноразовый.
sxc731
Не важно, у меня на хост-компьютере был установлен WSL, а Ubuntu LiveCD был просто потому, что это был самый быстрый способ раскрутить старую материнскую плату AMD.
njbair