Virtualbox, làm thế nào để buộc một CPU cụ thể cho khách


13

Tôi có một khách XP trong VirtualBox, máy chủ windows 8. Khách hiển thị bộ xử lý trong suốt giống như máy chủ (i5 2500k). Tuy nhiên, hầu hết các trình cài đặt không nhận ra bộ xử lý này và không tiếp tục nêu rõ bộ xử lý không được hỗ trợ.

Có cách nào để đánh lừa khách nghĩ rằng đây là bộ xử lý cũ? Nếu tôi nhớ lại chính xác VMWare có tính năng mặt nạ CPU, có gì tương tự trong hộp ảo không?


Phần mềm nào bạn đang cài đặt để kiểm tra mô hình CPU?
Darth Android

Điều khiển tác nhân kép, Orca và Wix. Đây là một dự án VB6 mà chúng tôi đang cố gắng hồi sinh.
IUn Unknown

Câu trả lời:


18

Khái niệm cơ bản về VirtualBox và CPUID

Bạn cần thiết lập VBoxInternal/CPUM/HostCPUIDextradata của máy ảo. Điều này sẽ làm cho VirtualBox báo cáo kết quả tùy chỉnh cho hướng dẫn CPUID cho khách. Tùy thuộc vào giá trị của thanh ghi EAX, hướng dẫn này trả về thông tin về bộ xử lý - những thứ như nhà cung cấp, loại, gia đình, bước, thương hiệu, kích thước bộ đệm, tính năng (MMX, SSE, SSE2, PAE, HTT), v.v. bạn mangle, cơ hội đánh lừa khách càng cao.

Bạn có thể sử dụng vboxmanage setextradatalệnh để cấu hình máy ảo. Ví dụ,

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

sẽ khiến CPUID trả về 50202952₍₁₆₎ trong thanh ghi EBX, khi được gọi với EAX được đặt thành 80000003₍₁₆₎. (Từ giờ trở đi, các số thập lục phân sẽ được viết là 0xNN hoặc NNh.)

Đặt chuỗi nhà cung cấp CPU

Nếu EAX bằng 0 (hoặc 80000000h trên AMD), CPUID trả về nhà cung cấp dưới dạng chuỗi ASCII trong các thanh ghi EBX, EDX, ECX (thông báo đơn hàng). Đối với CPU AMD, chúng trông như thế này:

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

(Lấy từ Đặc tả CPUID của AMD , tiểu mục "CPUID Fn0000_0000_E")

Nếu bạn kết hợp EBX, EDX và ECX, bạn sẽ nhận được AuthenticAMD.

Nếu bạn có Bash và các tiện ích Unix truyền thống, bạn có thể dễ dàng đặt nhà cung cấp với các lệnh sau:

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

Đặt chuỗi thương hiệu CPU

Nếu EAX là 80000002h, 80000003h, 80000004h, CPUID trả về 16 ký tự ASCII của chuỗi thương hiệu trong các thanh ghi EAX, EBX, ECX, EDX, tổng cộng 3 * 16 = 48 ký tự; chuỗi được kết thúc bằng một ký tự null . Lưu ý rằng tính năng này đã được giới thiệu với bộ xử lý Pentium 4. Đây là cách chuỗi thương hiệu có thể nhìn trên bộ xử lý 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"           |
|-----------------|-----------------|------------------|

(Lấy từ Tài liệu tham khảo lập trình mở rộng tập hợp kiến ​​trúc Intel , tiểu mục 2.9, "Hướng dẫn CPUID", bảng 2-30. Là ký tự null (giá trị số 0).)

Nếu bạn đặt kết quả cùng nhau, bạn sẽ nhận được Intel(R) Pentium(R) 4 CPU 1500MHz☠.

Nếu bạn có Bash và các tiện ích Unix truyền thống, bạn có thể dễ dàng đặt thương hiệu bằng các lệnh sau:

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

Nếu bạn có dấu nhắc lệnh của Windows, bạn có thể đặt nhãn hiệu thành Intel(R) Core(TM)2 CPU 6600 @ 2.40 GHz1 bằng cách chạy:

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

Máy tính: Intel (R) Core (TM) 2 CPU 6600 @ 2.40 GHz

1 Các HostCPUIDgiá trị được lấy từ báo cáo lỗi VirtualBox # 7865 .


Cảm ơn. Máy ảo của tôi bị hỏng với VERR_CFGM_INVALID_CHILD_PATH.
Ben Sinclair

1
sed phải được sử dụng với cờ G:'s/ //g'
Ben Sinclair

1
Thật là một câu trả lời tuyệt vời! Và với sự ra đời của CPU Kaby Lake, điều này đột nhiên trở nên thú vị nhất do một chính sách nhất định từ Redmond để không hỗ trợ Windows 7 trên những thứ đó ... Có vẻ như tất cả những gì còn thiếu là hướng dẫn về cách đặt "EAX = 1: Thông tin bộ xử lý và các bit tính năng "vì chúng không phải là các chuỗi đơn giản (chỉ với nhãn hiệu CPU, CPU-Z vẫn nhận ra CPU là KL); có ai biết?
sxc731

1
Trên mỗi forum.virtualbox.org/viewtopic.php?f=2&t=77211#p359428 , có thể có cách tốt hơn (ngắn gọn hơn, được hỗ trợ nhiều hơn) để đặt các giá trị này.
Đánh dấu Amery

@MarkAmery, cảm ơn vì đường link. Nó hoạt động tốt cho thương hiệu, nhưng không tốt cho nhà cung cấp vì nhà cung cấp không được đặt trong thanh ghi EAX và --cpuidtiểu ban yêu cầu một giá trị cho thanh ghi EAX.
Cristian Ciupitu

5

Đây là một cách tiếp cận cho phép giả mạo CPU chủ chính xác như một CPU cụ thể thay vì cố gắng đoán thứ hai các cài đặt cần thiết. Bạn sẽ cần quyền truy cập vào một máy chạy VirtualBox trên CPU chủ đó để bạn có thể kết xuất các cpuidthanh ghi của nó (có lẽ tốt nhất là chọn một kiến ​​trúc tương tự như mô hình thực tế của CPU làm mô hình). Nếu bạn không có một tay, bạn có thể hỏi xung quanh (ví dụ như tôi đã thành công trên Reddit).

  1. Tạo tệp "mô hình" từ CPU mà bạn muốn mô phỏng:

    vboxmanage list hostcpuids > i7_6600U
    
  2. Trên máy chủ đích, đảm bảo VM bạn muốn sửa đổi không chạy; bạn có thể muốn có một bản sao lưu chỉ trong trường hợp.
  3. Chạy đoạn mã sau để tải tệp mô hình ( i7_6600Utại đây) vào định nghĩa của VBox VM ( my_vm_nametại đây):

    #!/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. Thế là xong, giờ bạn có thể chạy VM của mình và tận hưởng CPU được giả mạo (lưu ý: bạn chỉ cần chạy đoạn script trên một lần).

Nếu bạn cần phải khôi phục CPU giả trang, bạn có thể sử dụng vboxmanage modifyvm $vm --cpuidremove $leafcho mỗi lá trong vòng lặp trên ( man vboxmanagelà bạn của bạn).

Điều này đã hoạt động hoàn hảo trong một vài tháng đối với tôi, giả mạo CPU Kaby Lake (i7_7500U) dưới dạng Skylake (i7_6600U) trên máy chủ Ubuntu 17.04 chạy VBox 5.1.22. Cách tiếp cận sẽ hoạt động trên bất kỳ HĐH máy chủ nào, miễn là bạn có thể tạo một mã tương đương với tập lệnh bash nhỏ ở trên cho HĐH đó.


Về phần "Đặt chuỗi nhà cung cấp CPU", tôi có một nhận xét: Bạn phải đảm bảo thay đổi tên nhà cung cấp thành "AuthenticAMD" trên CPU AMD và "GenuineIntel" trên CPU Intel. Nếu bạn sử dụng "GenuineIntel" trên CPU AMD, máy ảo sẽ rất có thể bị hỏng.
abulhol

Cảm ơn rất nhiều cho việc này! Nó hoạt động như một bùa mê trên Ryzen 7700K của tôi. Tôi đã sử dụng bo mạch chủ AMD Socket SF2 cũ để lấy CPUID bằng cách chạy Ubuntu LiveCD, cài đặt VirtualBox trong môi trường trực tiếp và chạy lệnh vboxmanage. Về phía máy chủ, tôi đã cài đặt Hệ thống con Windows cho Linux để tôi có thể chạy dấu nhắc Bash trong Windows 10 và chạy tập lệnh mà bạn đã chia sẻ. Bây giờ tôi có thể lừa Windows 7 VM của tôi nghĩ rằng tôi đang chạy một chiếc A8-5600K.
njbair

Vui mừng điều này làm việc cho bạn quá! Tôi nên làm rõ rằng không ai trong số này yêu cầu máy chủ Linux; thậm chí không thu thập tệp "mô hình", tất cả những gì nó cần là VirtualBox đang chạy trên máy đó. Tập lệnh bash có thể trông phức tạp nhưng tất cả những gì nó làm là đọc các dòng ra khỏi tệp mô hình, bỏ qua các lá giữa 0000000b00000017(bao gồm) và chạy từng cái một vboxmanage modifyvm my_vm_name --cpuidset <line>để chúng có thể dễ dàng thực hiện bằng tay một lần.
sxc731

Không có vấn đề gì, dù sao tôi cũng đã cài đặt WSL trên máy chủ và Ubuntu LiveCD chỉ vì đó là cách nhanh nhất để quay bo mạch chủ AMD cũ.
njbair
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.