Windows Environment Setup

Setting up a QEMU + Linux 5.18 lab environment on Windows

Windows
한국어
← Back to DPAS Lab Guide

0. Prerequisites

System Requirements

Checking Virtualization Support

Task Manager → Performance → CPU → Confirm Virtualization: Enabled

Or in PowerShell:

Get-ComputerInfo -Property HyperVisorPresent, HyperVRequirementVirtualizationFirmwareEnabled

Choosing Between Two Methods

MethodCharacteristicsRecommended For
Method 1: WSL2 + QEMULinux command-line environment, KVM acceleration supportStudents with development experience (recommended)
Method 2: Windows Native QEMURun directly in Windows environmentEnvironments without WSL2

Method 1: WSL2 + QEMU (Recommended)

Running QEMU inside WSL2 allows you to use KVM acceleration for better performance.

1-1. Installing WSL2

Run PowerShell as Administrator:

wsl --install

After rebooting, complete the Ubuntu 22.04 setup (enter username/password).

If WSL1 is already installed, upgrade to WSL2:

wsl --set-default-version 2
wsl --set-version Ubuntu 2

Verify the version:

wsl --list --verbose
# NAME      STATE   VERSION
# Ubuntu    Running 2          ← Must be 2

1-2. Checking KVM Inside WSL2

Open a WSL2 terminal (Ubuntu):

# Check if KVM device exists
ls /dev/kvm
# If missing: Enable "Virtual Machine Platform" in Windows Features (see below)

If /dev/kvm is not present:

# In PowerShell as Administrator
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
dism.exe /online /enable-feature /featurename:Microsoft-Hyper-V /all /norestart

Reboot and restart WSL2:

wsl --shutdown
wsl

1-3. Installing QEMU in WSL2

sudo apt update
sudo apt install -y qemu-system-x86 qemu-utils

qemu-system-x86_64 --version

1-4. Next Steps

All subsequent steps are performed in the WSL2 terminal. Follow the same steps as the Linux guide (setup-linux.md) starting from step 2.

mkdir -p ~/qemu-lab && cd ~/qemu-lab

# Download ISO
wget -O ubuntu-22.04-server-amd64.iso \
  https://releases.ubuntu.com/22.04/ubuntu-22.04.5-live-server-amd64.iso

# Create disk images (OS on virtio, test disk on NVMe — separate)
qemu-img create -f qcow2 ubuntu.qcow2 30G
qemu-img create -f raw nvme_disk.raw 16G
Why Separate Disks? During the lab, we repeatedly rmmod/insmod the NVMe driver. If the OS resides on an NVMe device, removing the driver will freeze the system. Therefore, the OS goes on a virtio disk (/dev/vda) and the test disk goes on the NVMe device (/dev/nvme0n1).

Install Ubuntu:

qemu-system-x86_64 \
  -m 4G -smp 4 \
  -enable-kvm \
  -drive file=ubuntu.qcow2,if=virtio,format=qcow2 \
  -cdrom ubuntu-22.04-server-amd64.iso \
  -boot d \
  -net nic -net user,hostfwd=tcp::2222-:22 \
  -nographic

Boot with NVMe after installation:

qemu-system-x86_64 \
  -m 4G -smp 4 \
  -enable-kvm \
  -drive file=ubuntu.qcow2,if=virtio,format=qcow2 \
  -drive file=nvme_disk.raw,id=nvm,if=none,format=raw \
  -device nvme,id=nvme0,serial=deadbeef \
  -device nvme-ns,drive=nvm,bus=nvme0,nsid=1,logical_block_size=512,physical_block_size=512 \
  -net nic -net user,hostfwd=tcp::2222-:22 \
  -nographic

SSH connection:

ssh -p 2222 <username>@localhost

Kernel 5.18 installation and NVMe verification are the same as Step 8 and Step 9.

Method 2: Windows Native QEMU

Run QEMU directly on Windows without WSL2. WHPX (Windows Hypervisor Platform) is used for acceleration.

2-1. Enabling Windows Features

Run PowerShell as Administrator:

# Enable Windows Hypervisor Platform (for WHPX acceleration)
dism.exe /online /enable-feature /featurename:HypervisorPlatform /all /norestart

# Enable Hyper-V
dism.exe /online /enable-feature /featurename:Microsoft-Hyper-V-All /all /norestart

Verify after rebooting:

Get-WindowsOptionalFeature -Online -FeatureName HypervisorPlatform | Select-Object State
# State: Enabled

2-2. Installing QEMU

Option A: Using Scoop (Recommended)

# Install Scoop (if not installed)
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
irm get.scoop.sh | iex

# Install QEMU
scoop install qemu

Option B: Using Chocolatey

# Install Chocolatey (if not installed, Administrator PowerShell)
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))

# Install QEMU
choco install qemu

Option C: Official Installer

Download the latest Windows installer from https://www.qemu.org/download/#windows and install.

Example installation path: C:\Program Files\qemu

Add to PATH (PowerShell):

$env:PATH += ";C:\Program Files\qemu"
# Permanent registration
[System.Environment]::SetEnvironmentVariable("PATH", $env:PATH, "Machine")

Verify installation:

qemu-system-x86_64 --version
qemu-img --version

2-3. Download Ubuntu 22.04 ISO

PowerShell:

mkdir $HOME\qemu-lab
cd $HOME\qemu-lab

# PowerShell 7+ or use curl
curl.exe -L -o ubuntu-22.04-server-amd64.iso `
  https://releases.ubuntu.com/22.04/ubuntu-22.04.5-live-server-amd64.iso

Or download directly via browser and move to C:\Users\<username>\qemu-lab\.

2-4. Creating Disk Images

Why Separate Disks? During the lab, we repeatedly rmmod/insmod the NVMe driver. If the OS resides on an NVMe device, removing the driver will freeze the system. Therefore, the OS goes on a virtio disk (/dev/vda) and the test disk goes on the NVMe device (/dev/nvme0n1).
cd $HOME\qemu-lab

qemu-img create -f qcow2 ubuntu.qcow2 30G
qemu-img create -f raw nvme_disk.raw 16G

2-5. Installing Ubuntu

cd $HOME\qemu-lab

qemu-system-x86_64 `
  -m 4G -smp 4 `
  -accel whpx `
  -drive file=ubuntu.qcow2,if=virtio,format=qcow2 `
  -cdrom ubuntu-22.04-server-amd64.iso `
  -boot d `
  -net nic -net user,hostfwd=tcp::2222-:22 `
  -nographic
If WHPX Acceleration Is Unavailable If an error occurs, replace -accel whpx with -accel tcg (software emulation, slower)
Notes for Ubuntu Installation
  • OpenSSH server must be selected
  • Storage: When configuring LVM, set it to use the entire disk (at least 20GB needed for kernel build). The default allocates only half the disk, so after installation expand with sudo lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv && sudo resize2fs /dev/ubuntu-vg/ubuntu-lv
  • After installation is complete, exit QEMU with Ctrl+A X

2-6. Booting the VM After Installation (with NVMe)

cd $HOME\qemu-lab

qemu-system-x86_64 `
  -m 4G -smp 4 `
  -accel whpx `
  -drive file=ubuntu.qcow2,if=virtio,format=qcow2 `
  -drive file=nvme_disk.raw,id=nvm,if=none,format=raw `
  -device nvme,id=nvme0,serial=deadbeef `
  -device nvme-ns,drive=nvm,bus=nvme0,nsid=1,logical_block_size=512,physical_block_size=512 `
  -net nic -net user,hostfwd=tcp::2222-:22 `
  -nographic

2-7. SSH Connection

Windows 10/11 comes with a built-in OpenSSH client.

ssh -p 2222 <username>@localhost

If SSH is not available:

# Install OpenSSH client (Administrator PowerShell)
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0

Or use PuTTY:

Step 8: Inside the Guest — Installing Kernel 5.18

(Common to both Method 1 and Method 2 — proceed inside the Guest VM after SSH connection)

Option A: Ubuntu Mainline PPA (Recommended)

sudo apt update && sudo apt install -y wget

KVER=5.18.0-051800
mkdir -p /tmp/kernel && cd /tmp/kernel

wget \
  https://kernel.ubuntu.com/mainline/v5.18/amd64/linux-image-unsigned-${KVER}-generic_${KVER}.202205222030_amd64.deb \
  https://kernel.ubuntu.com/mainline/v5.18/amd64/linux-modules-${KVER}-generic_${KVER}.202205222030_amd64.deb \
  https://kernel.ubuntu.com/mainline/v5.18/amd64/linux-headers-${KVER}-generic_${KVER}.202205222030_amd64.deb \
  https://kernel.ubuntu.com/mainline/v5.18/amd64/linux-headers-${KVER}_${KVER}.202205222030_all.deb

sudo dpkg -i /tmp/kernel/*.deb
sudo reboot

After reconnecting, verify:

ssh -p 2222 <username>@localhost
uname -r
# 5.18.0-051800-generic

Option B: Build from Source

sudo apt install -y build-essential libncurses-dev bison flex \
  libssl-dev libelf-dev bc pahole dwarves zstd

wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.18-rc6.tar.xz
tar xf linux-5.18-rc6.tar.xz && cd linux-5.18-rc6

cp /boot/config-$(uname -r) .config
make olddefconfig
echo "-dpas-fast26" > localversion

make -j$(nproc) bindeb-pkg
sudo dpkg -i ../linux-image-*.deb ../linux-headers-*.deb
sudo reboot

Step 9: Verifying NVMe Polling

uname -r
lsblk | grep nvme

# Enable poll_queues (reload nvme module)
sudo rmmod nvme
sudo modprobe nvme poll_queues=2

cat /sys/block/nvme0n1/queue/io_poll        # 1
cat /sys/block/nvme0n1/queue/io_poll_delay  # -1

sudo apt install -y fio
sudo fio --name=poll_test --filename=/dev/nvme0n1 \
  --ioengine=io_uring --hipri=1 \
  --rw=randread --bs=4k --direct=1 \
  --iodepth=1 --numjobs=1 --runtime=10

Convenience Scripts

Method 1 (WSL2): start-vm.sh

In the WSL2 terminal:

cat > ~/qemu-lab/start-vm.sh << 'EOF'
#!/bin/bash
cd ~/qemu-lab
qemu-system-x86_64 \
  -m 4G -smp 4 \
  -enable-kvm \
  -drive file=ubuntu.qcow2,if=virtio,format=qcow2 \
  -drive file=nvme_disk.raw,id=nvm,if=none,format=raw \
  -device nvme,id=nvme0,serial=deadbeef \
  -device nvme-ns,drive=nvm,bus=nvme0,nsid=1,logical_block_size=512,physical_block_size=512 \
  -net nic -net user,hostfwd=tcp::2222-:22 \
  -nographic "$@"
EOF
chmod +x ~/qemu-lab/start-vm.sh

Method 2 (Native): start-vm.ps1

# $HOME\qemu-lab\start-vm.ps1
$QEMU_LAB = "$HOME\qemu-lab"
qemu-system-x86_64 `
  -m 4G -smp 4 `
  -accel whpx `
  -drive "file=$QEMU_LAB\ubuntu.qcow2,if=virtio,format=qcow2" `
  -drive "file=$QEMU_LAB\nvme_disk.raw,id=nvm,if=none,format=raw" `
  -device nvme,id=nvme0,serial=deadbeef `
  -device nvme-ns,drive=nvm,bus=nvme0,nsid=1,logical_block_size=512,physical_block_size=512 `
  -net nic -net user,hostfwd=tcp::2222-:22 `
  -nographic

Run:

.\start-vm.ps1
# If ExecutionPolicy error: Set-ExecutionPolicy -Scope CurrentUser RemoteSigned

Troubleshooting

SymptomCauseSolution
WHPX: Failed to initializeWindows Hypervisor Platform not enabledEnable HypervisorPlatform feature via Administrator PowerShell and reboot
WHPX not supportedConflict with Hyper-V or unsupported hardwareSwitch to -accel tcg (slower)
qemu-system-x86_64: command not foundPATH not configuredAdd QEMU installation path to PATH
PowerShell line continuation errorSpace after backtick (`)Ensure no spaces/tabs after the backtick (`)
SSH Connection refusedVM still bootingWait 30-60 seconds and retry
nvme0n1 not foundMissing -device nvmeCheck the QEMU launch command
io_poll value is 0Guest kernel 5.19+Check uname -r, reinstall kernel 5.18
/dev/kvm missing in WSL2Hyper-V not enabledEnable HypervisorPlatform and Microsoft-Hyper-V features
PuTTY Connection timed outPort forwarding errorVerify hostfwd=tcp::2222-:22 in QEMU, check Windows Firewall