Linux Environment Setup

Setting up QEMU + Linux 5.18 lab environment on Linux

Linux
한국어
← Back to DPAS Lab Guide

0. Prerequisites

Check Architecture and Virtualization Support

# Check architecture
uname -m   # Should be x86_64

# Check KVM hardware virtualization support
egrep -c '(vmx|svm)' /proc/cpuinfo   # 0 means KVM unavailable (e.g., nested VM in VirtualBox)

# Check if KVM module is loaded
lsmod | grep kvm

When KVM Is Not Available

If you are working inside a VirtualBox/VMware VM, nested KVM is required.

# VirtualBox: VM Settings > System > Acceleration > Enable "VT-x/AMD-V Nested Paging"
# VMware: Add the following to VMX file and restart
#   vhv.enable = "TRUE"

# Verify nested KVM is enabled
cat /sys/module/kvm_intel/parameters/nested   # Y means OK
cat /sys/module/kvm_amd/parameters/nested     # (for AMD)

If KVM is unavailable, remove -enable-kvm and run with software emulation (slow).

Step 1: Install QEMU

Ubuntu / Debian

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

Fedora / RHEL / CentOS Stream

sudo dnf install -y qemu-system-x86 qemu-img

Arch Linux

sudo pacman -S qemu-system-x86 qemu-img

Verify Installation

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

KVM Permission Setup

# Add current user to kvm group
sudo usermod -aG kvm $USER

# Re-login or apply immediately with newgrp
newgrp kvm

# Verify
ls -l /dev/kvm   # crw-rw----  group: kvm means OK

Step 2: Download Ubuntu 22.04 ISO

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

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

# Verify download
ls -lh ubuntu-22.04-server-amd64.iso

Step 3: Create Disk Images

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

# OS disk (for Ubuntu installation, 30GB, virtio-attached)
qemu-img create -f qcow2 ubuntu.qcow2 30G

# NVMe disk (for lab exercises, 16GB, raw format — raw required for O_DIRECT support)
qemu-img create -f raw nvme_disk.raw 16G

ls -lh *.qcow2 *.raw

Step 4: Install Ubuntu 22.04

cd ~/qemu-lab
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
Notes During Installation
  • Language/Keyboard/Network: keep defaults
  • OpenSSH server: must be selected (press spacebar to check)
  • Storage: When configuring LVM, allocate the entire disk (at least 20GB required for kernel build). The default only allocates half the disk, so after installation run sudo lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv && sudo resize2fs /dev/ubuntu-vg/ubuntu-lv to expand, or select "Custom storage layout" during installation to allocate the full size
  • Additional packages: none needed
  • After installation completes, select "Reboot Now" → press Ctrl+A X in the console to quit QEMU

Step 5: Boot VM After Installation (with NVMe)

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

After the VM finishes booting, connect via SSH:

ssh -p 2222 <username>@localhost
Note On first connection, type yes if a host key warning appears

Step 6: Inside Guest — Install Kernel 5.18

Proceed while connected to the guest VM via SSH.

Method A: Ubuntu Mainline PPA (Recommended, Fast)

# Install tools
sudo apt update
sudo apt install -y wget

# Download kernel packages (x86_64)
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

# Install
sudo dpkg -i /tmp/kernel/*.deb

# Verify GRUB and reboot
sudo reboot

After reboot, reconnect via SSH and verify the version:

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

Method B: Build from Source (When Custom Kernel 5.18.0-rc6-dpas-fast26 Is Needed)

Note Use this when a separate config file is provided in the course
# Install build dependencies
sudo apt install -y \
  build-essential libncurses-dev bison flex \
  libssl-dev libelf-dev bc pahole dwarves zstd

# Download source
cd ~
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

# Start from current kernel config
cp /boot/config-$(uname -r) .config
make olddefconfig

# Set localversion (optional)
echo "-dpas-fast26" > localversion

# Compile (parallel build with number of vCPUs)
make -j$(nproc) bindeb-pkg

# Install
sudo dpkg -i ../linux-image-*.deb ../linux-headers-*.deb
sudo reboot

Step 7: Verify NVMe Polling

ssh -p 2222 <username>@localhost

# Check kernel version
uname -r

# Verify NVMe device is recognized
lsblk | grep nvme

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

# Verify polling is enabled
cat /sys/block/nvme0n1/queue/io_poll        # 1
cat /sys/block/nvme0n1/queue/io_poll_delay  # -1 (adaptive)
# Install fio
sudo apt install -y fio

# Polling test
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

VM Start Script

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

Register Aliases

# Add to ~/.bashrc or ~/.zshrc
echo 'alias vm-start="~/qemu-lab/start-vm.sh"' >> ~/.bashrc
echo 'alias vm-ssh="ssh -p 2222 <username>@localhost"' >> ~/.bashrc
source ~/.bashrc

Background Execution (Daemon Mode)

# Start VM in background
~/qemu-lab/start-vm.sh -daemonize -pidfile ~/qemu-lab/vm.pid

# Stop VM
kill $(cat ~/qemu-lab/vm.pid)

Troubleshooting

SymptomCauseSolution
Could not access KVM kernel module: No such file or directoryKVM module not loaded or insufficient permissionssudo modprobe kvm_intel (or kvm_amd), sudo usermod -aG kvm $USER
permission denied /dev/kvmNot in kvm groupnewgrp kvm then retry
nvme0n1 device not found-device nvme option missingCheck QEMU launch command
io_poll value is 0Running kernel 5.19+Verify guest kernel 5.18 installation (uname -r)
Cannot select 5.18 in GRUBDefault kernel is a different versionSelect "Advanced options" → 5.18 in GRUB menu, or edit /etc/default/grub
SSH connection refusedopenssh-server not installedsudo apt install openssh-server then restart VM
Nested KVM not supportedVM-inside-VM environmentEnable nested virtualization in host hypervisor or remove -enable-kvm