P2V Windows 11
v1.2.22
Progress
Build StepsRequired Hardware
PHYSICAL-TO-VIRTUAL BUILD DOCUMENTATION

Build Steps

Simple Windows 11 Pro physical-to-virtual migration to Proxmox VE 9.2 on the same PC.

IMPORTANT: Use two different external devices. The migration drive keeps this guide, saved state, and the VHDX. The Proxmox installer USB is separate and will be erased.

WORKFLOW: Do everything in Windows on the source PC. Use the second PC only after Proxmox is installed.

RECOMMENDED STORAGE: Install Proxmox on a second internal SSD/NVMe and leave the original Windows drive intact. This gives you a firmware-level fallback/dual-boot path and avoids erasing the original Windows installation.

SAVE STATE: After every step, click Export saved state. Save it to the migration drive. After STEP 017, save it on the second PC.

Start on the source PC

STEP 000 — Put the guide on the migration drive

DO: On the source PC:

  1. Plug in the external migration drive.
  2. Copy the documentation ZIP to it.
  3. Extract the ZIP on the migration drive.
  4. Open p2v-windows-11\docs\index.html.
  5. Keep the ZIP as a fallback copy.

STOP CHECK: The guide is open from the migration drive.

SAVE STATE: Export saved state to the migration drive.

STEP 000a

Record the source PC

STEP 001 — Make sure a local admin works

DO: If you already have a local administrator with a known password, use it and skip the commands below.

Otherwise open Terminal (Admin) and run:

net user P2VAdmin * /add
net localgroup Administrators P2VAdmin /add

Sign out once. Confirm P2VAdmin can sign in. Then return to your normal account.

STOP CHECK: A local administrator with a known password works.

SAVE STATE: Export saved state to the migration drive.

STEP 001a

STEP 002 — Record the PC name and network

DO: Open PowerShell and run:

$o = ipconfig /all | Out-String
$o
$o | Set-Clipboard

Paste the command output here.

Detected configuration

STOP CHECK: The source hostname, IPv4 address, gateway, and subnet are detected.

SAVE STATE: Export saved state to the migration drive.

STEP 002a

Prepare Windows

STEP 003 — Update and back up Windows

DO:

  1. Finish Windows Update.
  2. Reboot if requested.
  3. Back up anything important to storage other than the internal disk.

STOP CHECK: Windows is updated and important files are backed up.

SAVE STATE: Export saved state to the migration drive.

STEP 003a

STEP 004 — Check Windows, activation, and firmware

DO:

  1. Open Settings → System → Activation.
  2. Confirm the edition is Windows 11 Pro and Windows is activated.
  3. If activation uses a digital license, recommended: confirm it is linked to your Microsoft account before the P2V. If you use a product key instead, make sure you know how you will reactivate Windows after the virtual hardware change.
  4. Run:
$o = Get-ComputerInfo | Select WindowsProductName,WindowsVersion,OsBuildNumber,OsArchitecture,BiosFirmwareType,CsManufacturer,CsModel | Format-List | Out-String
$d = Get-Partition -DriveLetter C | Get-Disk | Select Number,FriendlyName,PartitionStyle | Format-List | Out-String
$o = $o + "`r`n" + $d
$o
$o | Set-Clipboard

Paste the command output here.

Detected configuration

STOP CHECK: Windows 11 Pro is activated, UEFI is detected, and the Windows system disk uses GPT. If you rely on a digital license, it is linked to your Microsoft account or you have another known reactivation method.

SAVE STATE: Export saved state to the migration drive.

STEP 004a

STEP 005 — Decrypt BitLocker

DO: Run:

manage-bde -status C:

If C: is encrypted, run Terminal (Admin):

manage-bde -off C:

Wait until C: shows Fully Decrypted / 0%.

STOP CHECK: C: is fully decrypted.

SAVE STATE: Export saved state to the migration drive.

STEP 005a

STEP 006 — Clean Windows

DO:

  1. Settings → System → Storage → Temporary files → remove what you do not need.
  2. Run Terminal (Admin):
powercfg /h off
DISM /Online /Cleanup-Image /StartComponentCleanup

STOP CHECK: Cleanup is complete and hibernation is off.

SAVE STATE: Export saved state to the migration drive.

STEP 006a

STEP 007 — Shrink C:

DO: Run:

$p = Get-Partition -DriveLetter C
$s = Get-PartitionSupportedSize -DriveLetter C
$v = Get-Volume C
$o = @(
  "CurrentPartitionGB=$([math]::Round($p.Size / 1GB,1))"
  "MinimumSupportedGB=$([math]::Ceiling($s.SizeMin / 1GB))"
  "UsedGB=$([math]::Round(($v.Size-$v.SizeRemaining) / 1GB,1))"
  "FreeGB=$([math]::Round($v.SizeRemaining / 1GB,1))"
) -join "`n"
$o
$o | Set-Clipboard

Paste the sizing output here.

Detected configuration

C: target

Open diskmgmt.msc → right-click C: → Shrink Volume → enter {{WINDOWS_SHRINK_AMOUNT_MB}} MB.

Do not change EFI or Recovery partitions.

After the shrink finishes, record the actual final C: partition size:

$v = Get-Volume -DriveLetter C
$p = Get-Partition -DriveLetter C
$o = @(
  "PostShrinkCGB=$([math]::Round($p.Size / 1GB,1))"
  "PostShrinkFreeGB=$([math]::Round($v.SizeRemaining / 1GB,1))"
) -join "`n"
$o
$o | Set-Clipboard

Paste the final C: sizing output here.

Detected configuration

Final recorded C: size: {{WINDOWS_C_AFTER_GB}} GB. This value is saved with the documentation state and will be used later to check Proxmox storage capacity.

STOP CHECK: C: is smaller, the final size is recorded, and Windows still has comfortable free space.

SAVE STATE: Export saved state to the migration drive.

STEP 007a

STEP 008 — Install VirtIO drivers

DO: Mount the VirtIO Windows ISO. Enter its drive letter.

VirtIO ISO

Run:

{{VIRTIO_ISO_DRIVE}}\virtio-win-guest-tools.exe

Then run Terminal (Admin):

pnputil /add-driver {{VIRTIO_ISO_DRIVE}}\vioscsi\w11\amd64\*.inf /subdirs
pnputil /add-driver {{VIRTIO_ISO_DRIVE}}\NetKVM\w11\amd64\*.inf /subdirs

STOP CHECK: VirtIO guest tools, storage driver, and network driver are installed/staged.

SAVE STATE: Export saved state to the migration drive.

STEP 008a

STEP 009 — Final Windows check

DO: Reboot. Sign in normally. Open Device Manager and check for unexpected errors.

STOP CHECK: Windows boots normally.

SAVE STATE: Export saved state to the migration drive.

STEP 009a

Create the VHDX

STEP 010 — Choose the Proxmox IP

DO: Open your router's DHCP settings. Enter the DHCP range and choose a free Proxmox address outside it.

Proxmox network

STOP CHECK: {{PROXMOX_IP}} is free, inside {{NETWORK_CIDR}}, and outside the DHCP range.

SAVE STATE: Export saved state to the migration drive.

STEP 010a

STEP 011 — Confirm the migration drive

DO: Keep the migration drive plugged into the source PC. Enter its drive letter.

VHDX destination

The VHDX name is the source hostname in uppercase:

{{VHDX_WINDOWS_PATH}}

STOP CHECK: The path is the migration-drive root, for example E:\SOURCE-PC.vhdx.

SAVE STATE: Export saved state to the migration drive.

STEP 011a

STEP 012 — Create the VHDX

DO: Open Disk2vhd as Administrator.

  1. Select the Windows disk's EFI/System, C:, and Recovery volumes.
  2. Check Use Vhdx.
  3. Save to {{VHDX_WINDOWS_PATH}}.
  4. Click Create.

If Volume Shadow Copy makes Disk2vhd crash, turn it off, close other apps, and run the capture again.

STOP CHECK: {{VHDX_WINDOWS_PATH}} exists and has a plausible size.

SAVE STATE: Export saved state to the migration drive.

STEP 012a

STEP 013 — Hash the VHDX

DO: Run:

$o = Get-FileHash '{{VHDX_WINDOWS_PATH}}' -Algorithm SHA256 | Format-List Algorithm,Hash,Path | Out-String
$o
$o | Set-Clipboard

Paste the hash output here.

Detected configuration

STOP CHECK: The VHDX path and SHA-256 are saved.

SAVE STATE: Export saved state to the migration drive.

STEP 013a

Install Proxmox VE 9.2

STEP 014 — Create the Proxmox installer USB

DO: On the source PC:

  1. Plug in a second USB flash drive.
  2. Download the Proxmox VE 9.2 ISO.
  3. Use Rufus or another ISO writer to write the ISO to the installer USB.
  4. Do not select the migration drive.

STOP CHECK: The installer USB and migration drive are different devices.

SAVE STATE: Export saved state to the migration drive.

STEP 014a

STEP 015 — Prepare the Proxmox target and boot installer

DO:

  1. Export saved state one more time.
  2. Safely eject and unplug the migration drive.
  3. Choose the Proxmox target-disk path:
  • Recommended — lowest data-loss risk: shut down the PC, install a second internal SSD/NVMe large enough for Proxmox and the imported Windows VM, and leave the original Windows drive intact. For the safest install, temporarily disconnect the original Windows drive while Proxmox is being installed.
  • Single-disk fallback: reuse the original Windows disk only if you accept that it will be erased and your VHDX plus important-file backup are already safe on other storage.
  1. Leave only the Proxmox installer USB attached externally.
  2. From Terminal (Admin) reboot into UEFI/BIOS by entering the following command:
shutdown.exe /r /fw /t 1
  1. Enable CPU virtualization if needed.
  2. Boot the Proxmox installer USB.

STOP CHECK: The Proxmox installer starts, the migration drive is unplugged, and you know exactly which internal disk will receive Proxmox.

SAVE STATE: Already exported before reboot.

STEP 015a

STEP 016 — Install Proxmox

DO: Install Proxmox VE 9.2 to the selected target disk.

Recommended two-disk path: select the new secondary SSD/NVMe. Do not select or format the original Windows disk.

Single-disk fallback: selecting the original Windows disk will erase the physical Windows installation.

Use:

Hostname:  {{PROXMOX_HOSTNAME}}
Address:   {{PROXMOX_IP_CIDR}}
Gateway:   {{DEFAULT_GATEWAY}}
DNS:       {{PRIMARY_DNS}}

WARNING: The disk selected in the Proxmox installer will be erased.

After installation:

  1. Remove the installer USB and boot Proxmox.
  2. If you temporarily disconnected the original Windows drive, shut Proxmox down, reconnect that drive, and keep the Proxmox disk first in firmware boot order.
  3. Boot Proxmox again. The untouched Windows disk can remain available as a firmware boot-menu fallback. Do not add, format, or modify that physical Windows disk from Proxmox during this migration.

STOP CHECK: The console shows https://{{PROXMOX_IP}}:8006/. On the recommended two-disk path, the original Windows drive is still intact and Proxmox boots from the secondary SSD/NVMe.

SAVE STATE: Complete this after reopening the guide in STEP 017.

STEP 016a

STEP 017 — Move to the second PC

DO: Now use the second PC for the first time.

  1. Plug the migration drive into the second PC.
  2. Copy the extracted documentation folder to the second PC.
  3. Open docs\index.html from that local copy.
  4. Click Import saved state and load the latest JSON from the migration drive.
  5. Open https://{{PROXMOX_IP}}:8006/ and sign in as root.

STOP CHECK: The guide and Proxmox web UI are open on the second PC.

SAVE STATE: Export saved state on the second PC.

STEP 017a

STEP 018 — Consolidate Proxmox storage into local

DO: Replace the default local-lvm thin pool with one larger local storage pool for this standalone P2V host.

Why we are doing this: Proxmox normally splits a single disk into local (a directory used for ISOs, backups, and templates) and local-lvm (LVM-thin storage used for VM disks). For this guide, that split adds unnecessary complexity and can leave free space stranded in the wrong pool. We will remove local-lvm, give its unused space to the root filesystem, and allow local to store VM disks too. This gives the machine one shared pool of free space for the Proxmox host files and the Windows VM.

Tradeoffs: This is a simplicity-first layout for a standalone host. You give up LVM-thin's separate VM-storage pool and its block-level thin-provisioning/snapshot behavior. VM disks stored on local use file-based storage instead. Because the Proxmox root filesystem and VM disks now share the same free space, a VM or backup that fills local can also fill the host filesystem. Keep free-space headroom and monitor usage. In a larger cluster, shared storage such as Ceph may be a better design instead of either local layout.

First confirm the expected default layout:

pveversion
ip -4 addr show vmbr0
pvesm status
lvs
findmnt -no FSTYPE /

STOP: Continue only if local-lvm is the default pve/data thin pool and there are no VM or container disks stored on it. This guide performs this change before importing the Windows VM.

Remove the Proxmox storage definition and the empty thin pool, then expand pve/root into all free space:

pvesm remove local-lvm
lvremove -y /dev/pve/data
lvextend -l +100%FREE /dev/pve/root
resize2fs /dev/mapper/pve-root
pvesm set local --content iso,vztmpl,backup,images,rootdir,snippets

resize2fs is correct for the default ext4 installation used by this guide. If findmnt -no FSTYPE / did not report ext4, stop instead of running the resize commands.

Verify the result:

pvesm status
lvs
df -h /

Copy the complete output from those three commands and save it below. The analyzer stores the final local/root capacity and free space in the documentation state.

Paste the final storage output here.

Detected configuration

Capacity check for the Windows VHDX import

  • Final Windows C: partition recorded after shrinking: {{WINDOWS_C_AFTER_GB}} GB
  • Final Proxmox local/root size: {{PVE_ROOT_SIZE_AFTER}}
  • Final Proxmox local/root free space: {{PVE_ROOT_FREE_AFTER}}

For a simple conservative check, the free space on local should be greater than the final C: partition size before importing the VHDX.

local-lvm and pve/data should be gone. local should now have most of the Proxmox disk available and be allowed to store VM disks.

HARD STOP: If {{PVE_ROOT_FREE_AFTER}} is not comfortably larger than the recorded {{WINDOWS_C_AFTER_GB}} GB C: partition, do not import the VHDX yet. Free space or use a larger Proxmox disk first.

STOP CHECK: Proxmox is 9.2.x, vmbr0 has {{PROXMOX_IP_CIDR}}, local-lvm is gone, pve/data is gone, the final free space is saved, and local has enough capacity for the recorded Windows C: size plus headroom.

SAVE STATE: Export saved state on the second PC.

STEP 018a

STEP 019 — Confirm the Windows fallback disk

DO: Confirm your rollback path before importing Windows.

If you used the recommended second SSD/NVMe, run:

lsblk -o NAME,SIZE,MODEL,FSTYPE,MOUNTPOINTS

Identify:

  • the disk that contains Proxmox;
  • the untouched original Windows disk.

Leave the original Windows disk alone. It is your physical fallback and can be selected from the PC's firmware boot menu if you need to return to the original installation.

If you used the single-disk path, the physical Windows installation has already been erased; your rollback path is the migration-drive VHDX plus your separate file backup.

STOP CHECK: You can clearly identify your Proxmox disk and your rollback path. On the recommended two-disk path, the original Windows disk has not been modified.

SAVE STATE: Export saved state on the second PC.

STEP 019a

Import Windows

STEP 020 — Mount and verify the migration VHDX

DO:

  1. Export saved state on the second PC.
  2. Copy the documentation folder with saved state from the migration drive to the second PC local disk.
  3. Safely eject the migration drive from the second PC.
  4. Plug it into the Proxmox PC.
  5. In Node → Shell, run:
lsblk -f

Enter the migration-drive partition, for example sdb1.

Migration drive on Proxmox

Mount it and find the VHDX:

mkdir -p /mnt/p2v
mount /dev/{{PVE_EXTERNAL_PARTITION}} /mnt/p2v
find /mnt/p2v -maxdepth 2 -type f -iname '*.vhdx'

VHDX on Proxmox

Before importing the disk, verify the copy that Proxmox can actually read:

sha256sum '{{PVE_VHDX_PATH}}'

Compare that value with the SHA-256 saved in STEP 013:

{{VHDX_SHA256}}

HARD STOP: If the hashes do not match exactly, do not import the VHDX. Recheck the selected file and migration drive first.

STOP CHECK: {{PVE_VHDX_PATH}} points to the expected VHDX and its SHA-256 matches {{VHDX_SHA256}}.

SAVE STATE: Export saved state on the second PC.

STEP 020a

STEP 021 — Create the Windows VM

DO: In Proxmox click Create VM.

Use:

  • OS: Do not use any media
  • Machine: q35
  • BIOS: OVMF (UEFI)
  • EFI Disk: local + Pre-Enrolled Keys
  • TPM: 2.0 on local
  • SCSI Controller: VirtIO SCSI single
  • CPU: host
  • Network: VirtIO on vmbr0
  • QEMU Guest Agent: enabled

Remove the placeholder disk. Do not start the VM.

Windows VM

STOP CHECK: The empty VM exists with OVMF, TPM 2.0, VirtIO NIC, and VirtIO SCSI.

SAVE STATE: Export saved state on the second PC.

STEP 021a

STEP 022 — Import the VHDX

DO: In Node → Shell, run:

qm importdisk {{VM_ID}} '{{PVE_VHDX_PATH}}' local

Wait for 100% and a successful import message.

STOP CHECK: The Windows disk appears under the VM as Unused Disk.

SAVE STATE: Export saved state on the second PC.

STEP 022a

STEP 023 — Attach the disk and boot Windows

DO:

  1. VM → Hardware → Unused Disk → Edit/Add → attach as SATA.
  2. Put SATA first in Boot Order.
  3. Start the VM.
  4. Open Console and sign in.

Windows will not boot initially on SCSI. After first boot, add a small temporary SCSI disk, then move the Windows disk back to SCSI.

STOP CHECK: Windows boots from SCSI0.

SAVE STATE: Export saved state on the second PC.

STEP 023a

Finish and back up

STEP 024 — Check VirtIO and Guest Agent

DO: In the Windows VM, confirm:

  • VirtIO network works.
  • Windows disk is on VirtIO SCSI.
  • QEMU Guest Agent service is running.

STOP CHECK: Network, storage, and Guest Agent work.

SAVE STATE: Export saved state on the second PC.

STEP 024a

STEP 025 — Check the Windows VM network

DO: In the Windows VM console, run:

ipconfig

Enter the VM IPv4 address below.

Windows VM

STOP CHECK: Windows and Proxmox have different IP addresses and both are reachable from the second PC.

SAVE STATE: Export saved state on the second PC.

STEP 025a

STEP 026 — Remove the temporary admin and finish Windows

DO:

  1. Sign in with your normal Windows account.
  2. Confirm it works and has the access you expect.
  3. Run Windows Update.
  4. Check Settings → System → Activation. If Windows is no longer activated, use Troubleshoot → I changed hardware on this device recently with the Microsoft account linked in STEP 004, or enter the valid product key for this Windows license.
  5. Another option is to check if the OEM Windows key is embedded in firmware. Enter the following command into proxmox shell as root:
strings /sys/firmware/acpi/tables/MSDM

Inside the Windows 11 VM, open PowerShell as Administrator and run:

slmgr /ipk YOUR-KEY

If you created P2VAdmin in STEP 001, open Terminal (Admin) and remove it:

net user P2VAdmin /delete

Do not remove an administrator account that existed before this guide.

STOP CHECK: Windows works normally, activation is confirmed or its reactivation path is known, and the temporary P2VAdmin account is removed if this guide created it.

SAVE STATE: Export saved state on the second PC.

STEP 026a

STEP 027 — Back up the VM

DO: Create a full Proxmox backup to storage outside the internal system disk.

Keep the original VHDX until the backup is tested.

Final record:

Item Value
Source PC {{SOURCE_COMPUTER_NAME}}
Source Windows {{WINDOWS_PRODUCT_NAME}} build {{WINDOWS_BUILD}}
Firmware {{SOURCE_BIOS_MODE}}
Proxmox {{PROXMOX_HOSTNAME}} · {{PROXMOX_IP_CIDR}}
VM {{VM_ID}} · {{VM_NAME}}
VM IP {{WINDOWS_VM_IP}}
VHDX {{VHDX_WINDOWS_PATH}}
VHDX SHA-256 {{VHDX_SHA256}}

To backup to the same migration drive (same USB VHDX is stored) use the following instructions:

Note: There's an assumption the backup USB is an external drive formatted as NTFS filesystem.

From {{PROXMOX_HOSTNAME}} > shell, enter the following command until findmnt /mnt/p2v doesn't return any output:

umount /mnt/p2v
umount /mnt/p2v
umount /mnt/p2v
umount /mnt/p2v
findmnt /mnt/p2v

Recreate /mnt/p2v directory and mount again with read/write permissionsby entering the following command:

mkdir -p /mnt/p2v
mount -t ntfs3 -o rw /dev/{{PVE_EXTERNAL_PARTITION}}  /mnt/p2v

Open Datacenter > Storage > Add > Directory

ID: USB Directory: /mnt/p2v Content: Backup

Under {{PROXMOX_HOSTNAME}} > {{VM_NAME}} > Backup > Backup now

Storage: USB > Backup

Once Complete you can restore from your backup by selecting "USB ({{PROXMOX_HOSTNAME}}) > Backups > vzdump > Restore

STOP CHECK: A tested external VM backup exists and the original VHDX is still available.

SAVE STATE: Export the final saved state on the second PC.

STEP 027a

Optional: EliteDesk 800 G3 / Intel HD 530 physical console

OPTIONAL / HARDWARE-SPECIFIC: Stop here if you only need the Windows VM through the Proxmox console or remote access. This phase is specifically for an HP EliteDesk 800 G3 with Skylake / Intel HD Graphics 530 using the onboard DisplayPort. Do not copy these ROM or machine-model instructions to a different iGPU generation without validating them first.

HARD STOP: Before assigning the iGPU, the Proxmox Web UI and a successful SSH login from the second PC must both work. Keep SSH available. Physical iGPU passthrough can remove or disrupt the Proxmox host's local monitor output.

STEP 028 — Prove remote access and save rollback

DO: From the second PC:

  1. Open https://{{PROXMOX_IP}}:8006 and confirm the Proxmox Web UI loads.
  2. Open PowerShell and run:
ssh root@{{PROXMOX_IP}}
  1. After SSH connects, run:
hostname
qm status {{VM_ID}}
  1. Keep this SSH window open.
  2. Shut down the Windows VM cleanly.
  3. In SSH, save the current VM configuration:
qm stop {{VM_ID}}
qm config {{VM_ID}} | tee /root/vm-{{VM_ID}}-before-igd.txt
cp /etc/pve/qemu-server/{{VM_ID}}.conf /root/{{VM_ID}}.conf.before-igd

STOP CHECK: The Web UI works from the second PC, SSH is connected and still available, the VM is stopped, and /root/{{VM_ID}}.conf.before-igd exists.

SAVE STATE: Export saved state on the second PC.

STEP 028a

STEP 029 — Verify IOMMU and identify the HD 530

DO: In the open Proxmox SSH session, run:

dmesg | grep -Ei 'DMAR|IOMMU'
lspci -nnk | grep -A4 -Ei 'VGA compatible controller|Display controller'
pvesh get /nodes/$(hostname)/hardware/pci --pci-class-blacklist ""
grep -R "disable_vga=1" /etc/modprobe.d /etc/default/grub 2>/dev/null || true

Find the Intel HD Graphics 530 / Skylake entry. Record its full PCI address and vendor:device ID. Do not assume the address, even though 0000:00:02.0 is common.

Intel iGPU

Check its IOMMU group:

readlink -f /sys/bus/pci/devices/{{IGPU_PCI}}/iommu_group
ls -l /sys/bus/pci/devices/{{IGPU_PCI}}/iommu_group/devices

On Proxmox VE 9, do not add old intel_iommu=on instructions by default. If no DMAR/IOMMU is active, stop and enable Intel VT-d in the EliteDesk firmware first.

If the grep command finds disable_vga=1, stop and remove that setting before continuing; it conflicts with legacy IGD passthrough.

STOP CHECK: IOMMU is active, {{IGPU_PCI}} is the Intel HD 530, its IOMMU group is acceptable, and disable_vga=1 is not configured.

SAVE STATE: Export saved state on the second PC.

STEP 029a

STEP 030 — Get the Skylake IGD ROM

DO: This ZIP does not bundle third-party Intel firmware. On the second PC, open the community project below and use its release/checksum information:

https://github.com/LongQT-sea/intel-igpu-passthru

For the EliteDesk 800 G3 / Skylake HD 530, use:

SKL_CML_GOPv9_igd.rom

Universal_noGOP_igd.rom is a last-resort fallback, not the normal Skylake choice.

Rename the selected Skylake ROM to igd.rom, then copy it to Proxmox:

scp .\igd.rom root@{{PROXMOX_IP}}:/usr/share/kvm/igd.rom

Back in SSH, verify the file and compare its SHA-256 with the checksum published by the ROM project's release page:

ls -lh /usr/share/kvm/igd.rom
sha256sum /usr/share/kvm/igd.rom

STOP CHECK: /usr/share/kvm/igd.rom is the Skylake SKL_CML_GOPv9_igd.rom file and its checksum matches the project's published checksum.

SAVE STATE: Export saved state on the second PC.

STEP 030a

STEP 031 — Switch the VM to legacy Intel IGD mode

DO: This guide created the VM as q35 in STEP 021. QEMU legacy IGD requires the i440fx machine family, IGD at guest 00:02.0, no competing virtual VGA device, and a valid ROM.

Configure the stopped VM:

qm stop {{VM_ID}}
qm set {{VM_ID}} --machine pc
qm set {{VM_ID}} --vga none
qm set {{VM_ID}} --bios ovmf
qm set {{VM_ID}} --hostpci0 {{IGPU_PCI}},legacy-igd=1,romfile=igd.rom
qm config {{VM_ID}}

Do not add pcie=1 to the legacy IGD device.

Do not blacklist i915 yet. Current Proxmox/iGPU guidance does not require the old blanket VFIO preparation for this path; blacklist i915 is kept only as a troubleshooting fallback if it is actually needed.

The original q35 configuration is preserved in /root/{{VM_ID}}.conf.before-igd.

STOP CHECK: qm config {{VM_ID}} shows machine: pc, bios: ovmf, vga: none, and hostpci0 with legacy-igd=1,romfile=igd.rom.

SAVE STATE: Export saved state on the second PC.

STEP 032 — Test the iGPU before changing host drivers

DO: Connect a monitor to an onboard EliteDesk DisplayPort and start Windows from SSH:

qm start {{VM_ID}}

Watch the physical monitor. With the recommended GOP ROM, display output may appear early in VM startup. If Windows loads before the display appears, wait for the Intel graphics driver to initialize.

From SSH, confirm the VM remains running:

qm status {{VM_ID}}

At this point, do not blacklist i915 just because the host driver is present. If the physical display works, leave the host configuration alone.

If the VM immediately fails to start, Windows reports Code 43, or the DisplayPort remains black after Windows should be loaded, go to STEP 035 for diagnostics before changing host-driver binding.

When the display test is complete, shut the VM down from SSH before assigning the physical USB ports:

qm shutdown {{VM_ID}}

STOP CHECK: The iGPU passthrough starts without requiring a permanent i915 blacklist, or you have captured the failure and will use STEP 035.

SAVE STATE: Export saved state on the second PC.

STEP 033 — Pass through only the keyboard and mouse USB ports

DO: Keep the keyboard and mouse connected to the two EliteDesk USB ports you want Windows to own. In SSH, run:

lsusb
lsusb -t

Unplug and reconnect one device at a time to identify the physical port path for each port, such as 1-3 or 1-3.2.

Physical USB ports

Assign only those ports:

qm set {{VM_ID}} --usb0 host={{USB_KEYBOARD_PORT}}
qm set {{VM_ID}} --usb1 host={{USB_MOUSE_PORT}}
qm config {{VM_ID}}

This leaves the rest of the EliteDesk USB controller available to Proxmox.

STOP CHECK: qm config {{VM_ID}} shows only the selected keyboard and mouse physical USB ports under usb0 and usb1.

SAVE STATE: Export saved state on the second PC.

STEP 034 — Verify the physical Windows console

DO: Start the VM from SSH:

qm start {{VM_ID}}

Then confirm:

  1. Windows appears on the onboard EliteDesk DisplayPort.
  2. The keyboard and mouse work when connected to the two selected physical USB ports.
  3. Device Manager → Display adapters shows Intel HD Graphics 530 without Code 43.
  4. If Windows uses Microsoft Basic Display Adapter, install the appropriate Intel graphics driver or let Windows Update supply it, then reboot the VM.
  5. The Proxmox built-in VM console can be blank because vga: none is intentional.

If one onboard DisplayPort remains black after Windows finishes loading, test the other onboard DisplayPort before changing the VM configuration.

STOP CHECK: The Windows desktop is visible on the EliteDesk DisplayPort, Intel HD 530 has no Code 43, and the selected physical keyboard/mouse ports control the VM.

SAVE STATE: Export saved state on the second PC.

STEP 035 — Diagnose, use the VFIO fallback only if needed, or recover

DO: If the VM will not boot correctly, Windows shows Code 43, the physical display stays black, or the iGPU is unreliable, stay on the second PC and use SSH.

First collect diagnostics:

qm status {{VM_ID}}
qm config {{VM_ID}}
lspci -nnk -s {{IGPU_PCI}}
journalctl -b | grep -Ei 'vfio|IOMMU|DMAR|i915'

Optional VFIO/i915 fallback

Use this only after the normal legacy-IGD configuration has failed or the iGPU project guidance indicates the host i915 driver is preventing reliable output/resolution. This will usually remove the Proxmox host's local video console after reboot.

qm stop {{VM_ID}}
cat >/etc/modules-load.d/p2v-igd-vfio.conf <<'EOF'
vfio
vfio_iommu_type1
vfio_pci
EOF

cat >/etc/modprobe.d/p2v-igd-vfio.conf <<'EOF'
blacklist i915
options vfio-pci ids={{IGPU_PCI_ID}}
EOF

update-initramfs -u -k all
reboot

After Proxmox returns, reconnect with SSH and verify:

lspci -nnk -s {{IGPU_PCI}}

If you used the fallback, Kernel driver in use: vfio-pci is expected. Retry the VM.

Restore the original VM and host iGPU

To return the VM to its pre-passthrough q35 configuration and remove the optional host-driver fallback:

qm stop {{VM_ID}}
cp /root/{{VM_ID}}.conf.before-igd /etc/pve/qemu-server/{{VM_ID}}.conf
rm -f /etc/modprobe.d/p2v-igd-vfio.conf
rm -f /etc/modules-load.d/p2v-igd-vfio.conf
update-initramfs -u -k all
reboot

After reboot, verify the original VM configuration is restored. If you used the VFIO fallback, lspci -nnk -s {{IGPU_PCI}} should show i915 again when the host reclaims the iGPU.

STOP CHECK: Either the physical-console passthrough works, or the original q35 VM configuration and normal Proxmox iGPU ownership have been restored.

SAVE STATE: Export the final saved state on the second PC.