Virtualbox, come forzare una specifica CPU al guest


13

Ho un ospite XP in VirtualBox, Windows 8 host. L'ospite mostra il processore in modo trasparente come l'host (i5 2500k). Tuttavia, la maggior parte degli installatori non riconosce questi processori e non riesce a continuare a dichiarare il processore non supportato.

C'è un modo per ingannare l'ospite nel pensare che questo sia un vecchio processore? Se ricordo correttamente VMWare aveva una funzione di mascheramento della CPU, c'è qualcosa di simile in virtualbox?


Quale software stai installando che controlla il modello della CPU?
Darth Android

Controlli di Double Agent, Orca e Wix. Questo è per un progetto VB6 che stiamo cercando di far rivivere.
IUnknown

Risposte:


18

Informazioni su VirtualBox e CPUID

È necessario impostare il VBoxInternal/CPUM/HostCPUID extradata della macchina virtuale. Questo renderà VirtualBox rapporto risultati personalizzati per il CPUID istruzioni per l'ospite. A seconda del valore del registro EAX, questa istruzione restituisce informazioni sul processore - cose come fornitore, tipo, famiglia, stepping, marca, dimensione della cache, caratteristiche (MMX, SSE, SSE2, PAE, HTT), ecc. Più risultati maneggi, maggiori sono le possibilità di ingannare l'ospite.

Puoi usare il vboxmanage setextradata comando per configurare la macchina virtuale. Per esempio,

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

renderà CPUID restituire 50202952₍₁₆₎ nel registro EBX, quando chiamato con EAX impostato su 80000003₍₁₆₎. (D'ora in poi, i numeri esadecimali saranno scritti come 0xNN o NNh.)

Impostazione della stringa del fornitore della CPU

Se EAX è 0 (o 80000000h su AMD), CPUID restituisce il fornitore come una stringa ASCII nei registri EBX, EDX, ECX (notare l'ordine). Per una CPU AMD, assomigliano a questo:

| 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" |

(Preso da Specifica CPUID AMD , sottosezione "CPUID Fn0000_0000_E")

Se si concatenano EBX, EDX ed ECX, si otterrà AuthenticAMD.

Se hai Bash e le tradizionali utility Unix, puoi facilmente impostare il venditore con i seguenti comandi:

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

Impostazione della stringa del marchio della CPU

Se EAX è 80000002h, 80000003h, 80000004h, CPUID restituisce 16 caratteri ASCII della stringa del marchio nei registri EAX, EBX, ECX, EDX, per un totale di 3 * 16 = 48 caratteri; la stringa è terminato con un carattere nullo . Si noti che questa funzione è stata introdotta con i processori Pentium 4. Ecco come la stringa del marchio può apparire su un processore 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"           |
|-----------------|-----------------|------------------|

(Preso da Riferimento per la programmazione delle estensioni del set di istruzioni di Intel Architecture , sottosezione 2.9, "Istruzione CPUID", tabella 2-30. The è il carattere null (valore numerico 0).)

Se metti insieme i risultati, otterrai Intel(R) Pentium(R) 4 CPU 1500MHz☠.

Se hai Bash e le tradizionali utility Unix, puoi facilmente impostare il marchio con i seguenti comandi:

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

Se hai un prompt dei comandi di Windows, puoi impostare il marchio su Intel(R) Core(TM)2 CPU 6600 @ 2.40 GHz 1 correndo:

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

1 Il HostCPUID i valori sono stati presi dal rapporto bug di VirtualBox # 7865 .


Grazie. Ho rotto la mia VM con VERR_CFGM_INVALID_CHILD_PATH.
highmaintenance

1
sed deve essere usato con la bandiera G: 's/ //g'
highmaintenance

1
Che bella risposta! E con l'avvento delle CPU di Kaby Lake, questo è diventato improvvisamente più interessante a causa di una certa politica da parte di Redmond per non supportare Windows 7 su quelli ... Sembra che manchino le istruzioni su come impostare "EAX = 1: Processor Info e Feature Bits "poiché non sono stringhe semplici (con solo il marchio della CPU, CPU-Z riconosce ancora la CPU come KL); qualcuno lo sa?
sxc731

1
Per forums.virtualbox.org/viewtopic.php?f=2&t=77211#p359428 , potrebbe esserci un modo migliore (più sintetico, più supportato) di impostare questi valori.
Mark Amery

@ MarkAmery, grazie per il link. Funziona bene per il marchio, ma non così bene per il venditore perché il venditore non è impostato nel registro EAX e il --cpuid sottocomando richiede un valore per il registro EAX.
Cristian Ciupitu

5

Ecco un approccio che consente di mascherare la CPU host esattamente come una CPU specifica piuttosto che cercare di indovinare le impostazioni necessarie. Avrai bisogno di accedere a una macchina che esegue VirtualBox su quella CPU host in modo da poterne scaricare cpuid registri (è probabilmente meglio scegliere un'architettura che sia ragionevolmente simile a quella della CPU attuale come modello). Se non ne hai uno a portata di mano, puoi chiedere in giro (ho avuto successo su Reddit per esempio).

  1. Crea un file "modello" dalla CPU che desideri emulare:

    vboxmanage list hostcpuids > i7_6600U
    
  2. Sull'host di destinazione, assicurarsi che la VM che si desidera modificare non sia in esecuzione; si consiglia di fare un backup nel caso in cui.
  3. Eseguire il seguente script per caricare il file del modello ( i7_6600U qui) nella definizione della VBox VM ( my_vm_name Qui):

    #!/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. Ecco fatto, ora puoi eseguire la tua VM e goderti la CPU mascherata (nota: devi solo eseguire lo script sopra una volta).

Se hai mai bisogno di ripristinare il masquerade della CPU, puoi usare vboxmanage modifyvm $vm --cpuidremove $leaf per ciascuna delle foglie nel ciclo precedente ( man vboxmanage È tuo amico).

Ciò ha funzionato perfettamente per un paio di mesi per me, mascherando una CPU Kaby Lake (i7_7500U) come una Skylake (i7_6600U) su un host Ubuntu 17.04 con VBox 5.1.22. L'approccio dovrebbe funzionare su qualsiasi sistema operativo host, purché sia ​​possibile creare un equivalente del piccolo script bash sopra per quel sistema operativo.


Per quanto riguarda la parte "Impostazione della stringa del fornitore della CPU", ho un commento: è necessario assicurarsi di cambiare il nome del fornitore in "AuthenticAMD" sulla CPU AMD e "GenuineIntel" sulla CPU Intel. Se si utilizza "GenuineIntel" su una CPU AMD, la macchina virtuale si romperà molto probabilmente.
abulhol

Grazie mille per questo! Ha funzionato come un fascino sul mio Ryzen 7700K. Ho usato una vecchia motherboard AMD Socket SF2 per ottenere il CPUID eseguendo un LiveCD di Ubuntu, installando VirtualBox nell'ambiente live ed eseguendo il comando vboxmanage. Dal lato host, ho installato il sottosistema Windows per Linux in modo da poter eseguire un prompt Bash in Windows 10 ed eseguire lo script che hai condiviso. Ora sono in grado di ingannare il mio Windows 7 VM pensando che sto eseguendo un A8-5600K.
njbair

Sono contento che questo funzioni anche per te! Avrei dovuto chiarire che nulla di ciò richiede un host Linux; nemmeno raccogliendo il file "modello", tutto ciò di cui ha bisogno è VirtualBox in esecuzione su quella macchina. Lo script di bash può sembrare complicato, ma tutto ciò che fa è leggere le linee fuori dal file del modello, saltando le foglie in mezzo 0000000b e 00000017 (incluso) e eseguendoli uno ad uno attraverso vboxmanage modifyvm my_vm_name --cpuidset <line> quindi questo può essere fatto facilmente a mano dato che è un one-off.
sxc731

Niente da fare, ho installato WSL sul computer host e il LiveCD di Ubuntu era solo perché era il modo più veloce per avviare la vecchia scheda madre AMD.
njbair
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.