KVM ও QEMU — kernel-ই hypervisor, userspace-ই বাকি সব হার্ডওয়্যার
KVM and QEMU: The Linux Hypervisor Stack
KVM একটা kernel module যা শুধু CPU আর memory virtualization দেয় ioctl দিয়ে; QEMU একটা userspace প্রোগ্রাম যা সবসময় device emulation করে আর CPU execution-এর জন্য হয় নিজস্ব software translator নাহয় KVM ব্যবহার করে — দুইটা মিলে গঠন করে আজকের Linux hypervisor stack, আর `ioctl(KVM_RUN)`-ই তাদের মাঝের একমাত্র সেতু।
আগে এটা বুঝি
hardware-virtualization লেসনে আমরা দেখেছি VT-x কী দেয় — একটা নতুন CPU mode-জোড়া, VMX root আর VMX non-root, একটা VMCS (Virtual Machine Control Structure) যেটা সেই দুই জগতের মধ্যেকার চুক্তি লিখে রাখে, আর VM-entry/VM-exit নামের দুইটা hardware-level ট্রানজিশন যা সেই চুক্তি প্রয়োগ করে। কিন্তু পুরো আলোচনাটা একটা প্রশ্ন ইচ্ছাকৃতভাবে এড়িয়ে গিয়েছিল — ঠিক কে বসে সেই VMX root mode-এ? কার কোড VMCS তৈরি করে, vmlaunch চালায়, guest-এর জন্য memory মাপে?
এই module-এর curriculum-এর driving question মনে করুন — “docker run লিখলে kernel-এ ঠিক কোন কোন syscall হয়?” আজকের লেসন সেই একই প্রশ্নের একটা পুরনো, আরও fundamental সংস্করণ ধরবে ভার্চুয়াল মেশিনের জগতে: qemu-system-x86_64 (বা libvirt-এর মাধ্যমে সেটাই) চালালে kernel-এ ঠিক কোন ioctl হয়?
উত্তরটা দুইটা আলাদা প্রজেক্টের গল্প, যারা একসাথে মিলে আজকের বাস্তব উত্তর গঠন করে —
- KVM (Kernel-based Virtual Machine) — Linux kernel-এর একটা module, যেটা
hardware-virtualizationলেসনের VMX root mode-এর কাজটা সরাসরি চলমান Linux kernel নিজেই করে ফেলে। কোনো আলাদা “hypervisor OS” নেই — আপনার রোজকার Linux kernel-ই, একটা module load করার পর, VMX root mode-এর বাসিন্দা হয়ে যায়। - QEMU — একটা সম্পূর্ণ, স্বাধীন, KVM-এর চেয়ে ৪ বছর পুরনো প্রজেক্ট, যেটা একটা সম্পূর্ণ কম্পিউটার software-এ emulate করতে পারে — CPU, disk, network card, graphics card, USB, BIOS — সব। QEMU একা, KVM ছাড়া, সম্পূর্ণ কার্যকর একটা emulator।
আজকের লেসনের কেন্দ্রীয় দাবি: এই দুইটা প্রজেক্ট, স্বাধীনভাবে ডিজাইন করা, একসাথে জোড়া লাগলে (QEMU KVM ব্যবহার করে CPU execution-এর জন্য) একটা চমৎকার division of labor তৈরি হয় — KVM CPU আর memory চালায়, QEMU বাকি সবকিছু চালায় — আর ঠিক মাঝখানে একটামাত্র syscall বসে থাকে যেটা এই পুরো সম্পর্কটার ভিত্তি: ioctl(vcpu_fd, KVM_RUN, ...)।
মূল ধারণা
KVM — Linux kernel-কে VMX root mode-এর বাসিন্দা বানানো
KVM আক্ষরিক অর্থেই একটা kernel module (kvm.ko প্লাস kvm-intel.ko বা kvm-amd.ko, vendor-নির্দিষ্ট)। এটা load হলে একটা character device তৈরি হয় — /dev/kvm — আর userspace-এর সাথে এর একমাত্র যোগাযোগের মাধ্যম হলো এই device-এর উপর ioctl() সিস্টেমকল। কোনো network protocol নেই, কোনো আলাদা daemon নেই (KVM নিজে কোনো process না) — শুধু একটা file descriptor আর তার উপর কয়েক ডজন সংজ্ঞায়িত ioctl command।
hardware-virtualization লেসনের ভাষায় বললে — KVM হলো সেই কোড যেটা VMCS তৈরি করে, তাতে guest-এর জন্য নিয়ম লেখে, আর vmlaunch/vmresume চালায়। KVM module load হওয়ার সাথে সাথেই চলমান Linux kernel VMX root mode গ্রহণ করে নেয় — kernel নিজেই এখন সেই “নিচের স্তর” যেটা আগের লেসনে বিমূর্তভাবে বর্ণনা করা হয়েছিল।
KVM কী প্রদান করে — আর কী করে না
এইটাই এই লেসনের সবচেয়ে গুরুত্বপূর্ণ বিভাজন-রেখা, তাই স্পষ্ট করে দুইটা তালিকায় লেখা যাক:
KVM যা প্রদান করে (শুধু এই দুইটা):
- CPU virtualization —
VMCSতৈরি ও পরিচালনা,VM-entry/VM-exitট্রানজিশন চালানো, guest register state সংরক্ষণ (hardware-virtualizationলেসনের পুরো যন্ত্রপাতি, বাস্তবে কোড হয়ে)। - Memory virtualization —
EPT(Extended Page Table) সেটআপ, guest-physical-থেকে host-physical ঠিকানা অনুবাদের দ্বিতীয় স্তর (hardware-virtualizationলেসনের EPT আলোচনার সরাসরি বাস্তবায়ন)।
KVM যা প্রদান করে না (এবং এটাই সবচেয়ে বেশি ভুল বোঝা হয়):
KVM কোনো ডিভাইস emulate করে না। কোনো ভার্চুয়াল disk controller নেই, কোনো ভার্চুয়াল network card নেই, কোনো ভার্চুয়াল graphics card নেই, কোনো BIOS/UEFI নেই। /dev/kvm একা খুলে একটা guest CPU রান করানো সম্ভব — কিন্তু সেই guest-এর কোনো disk-এ access নেই, কোনো keyboard/screen নেই, বুট করার মতো কোনো firmware নেই। এটা একটা primitive — একা অসম্পূর্ণ, কিন্তু একটা userspace প্রোগ্রামের (VMM — Virtual Machine Monitor) সাথে জোড়া লাগলেই সম্পূর্ণ VM হয়ে ওঠে।
সবচেয়ে সাধারণ সেই userspace VMM হলো QEMU — এবং এখান থেকেই দ্বিতীয় প্রজেক্টের গল্প শুরু।
QEMU — একা, সম্পূর্ণ, KVM ছাড়াই কার্যকর একটা emulator
QEMU-কে (Quick EMUlator) বোঝার সবচেয়ে গুরুত্বপূর্ণ প্রথম ধাপ — QEMU KVM-এর আগে থেকে ছিল (Fabrice Bellard প্রথম প্রকাশ করেন ২০০৩ সালে, KVM Linux kernel-এ merge হয় ২০০৭-এ) আর QEMU KVM ছাড়াও সম্পূর্ণ কার্যকর। QEMU-র মূল ইঞ্জিন TCG (Tiny Code Generator) — একটা dynamic binary translator যা guest-এর instruction-কে (যে ISA-ই হোক) ছোট ছোট block-এ ভেঙে host-এর native instruction-এ রূপান্তর করে, তারপর সেই translated code চালায়। এটা সম্পূর্ণ software — কোনো hardware virtualization support লাগে না, তাই যেকোনো host-এ যেকোনো guest ISA emulate করা যায়।
QEMU সবসময়, প্রতিটা মোডে, একটা কাজ করে — সম্পূর্ণ device emulation: ভার্চুয়াল disk controller (IDE, AHCI, বা virtio-blk), ভার্চুয়াল network card (e1000, rtl8139, বা virtio-net), ভার্চুয়াল graphics (VGA, virtio-gpu), USB controller, আর BIOS/UEFI firmware (SeaBIOS/OVMF) লোড করা। এই সব কোড সবসময় QEMU-র নিজস্ব, userspace, সাধারণ C কোড — ide.c, e1000.c, vga.c-র মতো ফাইলে লেখা, স্বাভাবিক ফাংশন কল দিয়ে চলে।
দুই মোড — QEMU-শুধু বনাম QEMU+KVM
CPU execution-এর জন্য QEMU-র দুইটা সম্পূর্ণ ভিন্ন উপায় আছে, আর -accel (বা পুরনো -enable-kvm) ফ্ল্যাগ ঠিক করে কোনটা ব্যবহার হবে:
| QEMU-শুধু (TCG) | QEMU + KVM | |
|---|---|---|
| CPU execution | software dynamic translation (TCG) | সরাসরি hardware — ioctl(KVM_RUN) দিয়ে VMX non-root mode |
| গতি | native-এর তুলনায় বহুগুণ ধীর (প্রতিটা instruction translate) | native-এর কাছাকাছি (guest code সরাসরি CPU-তে চলে) |
| Cross-architecture | সম্ভব — guest ISA ≠ host ISA (যেমন ARM-on-x86) | অসম্ভব — guest ISA অবশ্যই host ISA-র সমান হতে হবে |
| Device emulation | QEMU-তেই, userspace কোড | একই QEMU কোড, অপরিবর্তিত |
| প্রয়োজন | কিছুই না (যেকোনো host-এ চলে) | /dev/kvm অ্যাক্সেস, host CPU-তে VT-x/AMD-V সক্রিয় |
শেষ পর্যবেক্ষণটা সবচেয়ে গুরুত্বপূর্ণ — device model কোড দুই মোডেই হুবহু একই। ide.c-র ভেতরের কোড জানেই না CPU execution TCG দিয়ে হচ্ছে না KVM দিয়ে — সে শুধু একটা I/O access আসলে সেটা emulate করে। KVM যোগ করা মানে শুধু CPU execution engine বদলানো, device emulation architecture-এ কোনো পরিবর্তন নেই। এইটাই পরের অংশের ভিত্তি — কারণ device emulation যেভাবেই CPU চলুক, একই জায়গায়, একই খরচে ঘটে।
ভেতরে কী ঘটছে
ভেতরে কী ঘটছে — ঠিক কোন ioctl সিকোয়েন্স
QEMU যখন -enable-kvm-সহ একটা guest বুট করায়, নিচের ধাপগুলো (সরলীকৃত, কিন্তু ঠিক ক্রমে) ঘটে — প্রতিটাই /dev/kvm-এর উপর একটা ioctl() কল:
- open("/dev/kvm")একটা সাধারণ file descriptor — এখান থেকেই সব ioctl শুরু
- ioctl(KVM_CREATE_VM)একটা নতুন VM তৈরি — একটা নতুন vm_fd ফেরত দেয়, guest-এর জন্য একটা address space-এর প্রতিনিধিত্ব
- ioctl(vm_fd, KVM_SET_USER_MEMORY_REGION)QEMU নিজে mmap() করে একটা host memory অঞ্চল নেয় (guest RAM-এর জন্য), তারপর KVM-কে বলে দেয় — এই host ঠিকানাগুলোই guest-এর physical RAM; EPT সেটআপের কাঁচামাল
- ioctl(vm_fd, KVM_CREATE_VCPU)একটা vCPU তৈরি — নতুন vcpu_fd ফেরত দেয়; QEMU-র ভেতরে এর জন্য আলাদা একটা POSIX thread বরাদ্দ হয়
- ioctl(vcpu_fd, KVM_GET_VCPU_MMAP_SIZE) + mmap(vcpu_fd)kernel আর QEMU-র মধ্যে শেয়ার করা একটা struct kvm_run mmap হয় — exit reason, register data এখানে চলাচল করে, প্রতিবার copy করতে হয় না
- ioctl(vcpu_fd, KVM_SET_SREGS / KVM_SET_REGS)guest-এর প্রাথমিক register state সেট করা — segment register, instruction pointer, ইত্যাদি
- লুপ: ioctl(vcpu_fd, KVM_RUN)এই একটা কলই vmlaunch/vmresume চালায়, VMX non-root mode-এ প্রবেশ করে — guest code সরাসরি CPU-তে চলে, যতক্ষণ না KVM নিজে সামলাতে না-পারা একটা VM-exit ঘটে
লক্ষ্য করুন — শেষ ধাপ একটা লুপ, একবার না। প্রতিবার ioctl(KVM_RUN) কল ব্লক করে, guest CPU-তে সরাসরি চলে (kernel-এর ভেতরে vmlaunch/vmresume — এই সময় আর কোনো syscall হয় না, guest সরাসরি hardware-এ চলছে), যতক্ষণ পর্যন্ত না একটা VM-exit ঘটে যা KVM নিজে সামলাতে পারে না। তখন ioctl(KVM_RUN) কলটা ফেরত আসে — শেয়ার করা kvm_run struct-এ একটা exit_reason লেখা থাকে (KVM_EXIT_IO — port-mapped I/O, KVM_EXIT_MMIO — memory-mapped I/O, KVM_EXIT_HLT — guest hlt চালিয়েছে, ইত্যাদি)।
QEMU তখন exit_reason পরীক্ষা করে, নিজের device model কোড দিয়ে (যেমন ide.c-এর একটা ফাংশন) সেই I/O access emulate করে — port-এ লেখা মান ধরে রাখে, বা read-এর জন্য একটা মান বসিয়ে দেয় — তারপর আবার ioctl(vcpu_fd, KVM_RUN) কল করে। এই দ্বিতীয় কলটাই VM-entry — guest আবার VMX non-root mode-এ ঢোকে, ঠিক সেই instruction-এর পরে চালিয়ে যায় যেখানে থেমেছিল।
এই exit → handle → re-entry চক্রটাই পুরো লেসনের যান্ত্রিক হৃদয়। একটা guest যত বেশি device access করে, তত বেশিবার এই চক্র ঘোরে — আর প্রতিটা চক্র একটা userspace ↔ kernel context switch-এর দাম বহন করে।
উদাহরণ
সংখ্যায় — একটা device access-ভারী বাস্তব দৃশ্য
এই খরচটা concrete করতে, একটা পুরনো কিন্তু এখনও ব্যাপকভাবে ব্যবহৃত উদাহরণ নেওয়া যাক — একটা unmodified guest OS, একটা emulated legacy ATA/IDE disk controller-এর PIO (Programmed I/O) মোডে একটা সেক্টর (৫১২ বাইট) পড়ছে। PIO মোড ইচ্ছাকৃতভাবে বেছে নেওয়া হলো কারণ এটা “পুরোপুরি বাস্তব হার্ডওয়্যার নকল করা”-র সবচেয়ে চরম উদাহরণ — কোনো batching নেই, কোনো shared ring buffer নেই, শুধু individual port-এ individual instruction।
ATA PIO প্রোটোকল অনুযায়ী একটা সেক্টর read-এ guest driver-কে যা করতে হয়:
| ধাপ | Instruction | সংখ্যা |
|---|---|---|
| Drive/head সিলেক্ট | OUT (drive/head register) | ১ |
| Sector count সেট | OUT | ১ |
| LBA address (২৮-বিট, তিন byte) | OUT × ৩ | ৩ |
| Command জারি (READ SECTORS) | OUT | ১ |
| Status poll (BSY=0, DRQ=1 না হওয়া পর্যন্ত) | IN (status register) | ~৪ |
| ডেটা পড়া — ১৬-বিট শব্দ প্রতি একবার | IN (data port) × ২৫৬ | ২৫৬ |
| মোট | ২৬৬ |
৫১২ বাইট = ২৫৬টা ১৬-বিট শব্দ — আর ATA PIO মোডের ডিজাইনই এমন যে প্রতিটা শব্দের জন্য আলাদা IN instruction লাগে। VT-x-এ port-mapped I/O instruction (IN/OUT) ডিফল্টভাবে unconditionally trap হয় (I/O bitmap দিয়ে নির্বাচিতভাবে বাদ দেওয়া না থাকলে) — আর emulated legacy ATA controller-এর জন্য QEMU সেই bitmap trick ব্যবহার করে না, কারণ প্রতিটা access-ই তার device model-এর দরকার। ফলাফল: একটা মাত্র ৫১২-বাইট সেক্টর read ২৬৬টা আলাদা VM-exit ঘটায় — মানে ২৬৬টা আলাদা ioctl(KVM_RUN) রাউন্ড-ট্রিপ, শুধু একটা সেক্টর পড়তে।
যেখানে +1 প্রথম VM-entry-র জন্য (কোনো আগের exit ছাড়াই)। এই সূত্রটাই পরের অংশে সরাসরি একটা চালানো Python মডেলে রূপ নেবে।
guest: OUT drive/head ──► VM-exit(KVM_EXIT_IO) ──► QEMU ide.c handle ──► ioctl(KVM_RUN) ──► VM-entry
guest: OUT sector count ─► VM-exit ───────────────► QEMU ide.c handle ──► ioctl(KVM_RUN) ──► VM-entry
guest: OUT LBA (×৩) ─────► VM-exit ×৩ ────────────► QEMU ide.c handle ──► ioctl(KVM_RUN) ×৩
guest: OUT command ──────► VM-exit ───────────────► QEMU ide.c handle ──► ioctl(KVM_RUN) ──► VM-entry
guest: IN status (×৪) ───► VM-exit ×৪ ────────────► QEMU ide.c handle ──► ioctl(KVM_RUN) ×৪
guest: IN data word ─────► VM-exit ───────────────► QEMU ide.c handle ──► ioctl(KVM_RUN) ──► VM-entry
...২৫৬ বার পুনরাবৃত্তি...
মোট: ২৬৬ রাউন্ড-ট্রিপ / সেক্টরছবিতে
চার-স্তরের স্ট্যাক — আর libvirt কোথায় বসে
┌─────────────────────────────────────────────────────────────┐
│ Management layer (ঐচ্ছিক, কিন্তু বাস্তবে প্রায় সবসময়) │
│ virt-manager / oVirt / OpenStack Nova / virsh │
│ │ │
│ ▼ │
│ libvirtd (management API/daemon) │
│ VM lifecycle-এর ঘোষণামূলক (declarative) XML সংজ্ঞা, │
│ নিজে virtualize করে না — নিচের QEMU-কে সঠিক ফ্ল্যাগ দিয়ে │
│ চালায় ও তদারকি করে │
└──────────────────────────┬──────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ GUEST OS (unmodified — Linux, Windows, যা-ই হোক) │
└──────────────────────────┬──────────────────────────────────┘
│ IN/OUT, MMIO access
▼
┌─────────────────────────────────────────────────────────────┐
│ QEMU (userspace process) │
│ • device emulation — disk, NIC, VGA, USB, BIOS/UEFI │
│ • VM lifecycle — মেমরি বরাদ্দ, migration, snapshot │
│ • CPU execution driver — TCG (software) নাহয় KVM ioctl │
└──────────────────────────┬──────────────────────────────────┘
│ ioctl(KVM_RUN) / VM-exit ফেরত
▼
┌─────────────────────────────────────────────────────────────┐
│ KVM (Linux kernel module — /dev/kvm) │
│ • VMCS তৈরি ও পরিচালনা │
│ • VM-entry/VM-exit ট্রানজিশন চালানো (vmlaunch/vmresume) │
│ • EPT সেটআপ — memory virtualization │
│ ✕ device emulation নেই — ইচ্ছাকৃতভাবে │
└──────────────────────────┬──────────────────────────────────┘
│ VT-x / AMD-V hardware primitive
▼
┌─────────────────────────────────────────────────────────────┐
│ HARDWARE — CPU (VMX root/non-root), EPT/NPT, physical RAM │
└─────────────────────────────────────────────────────────────┘লক্ষ্য করুন — libvirt পুরো ছবিতে একটা বিশেষ ভূমিকায় বসে। এটা নিজে কোনো virtualization করে না — এটা একটা management API/daemon যা VM-কে একটা declarative XML হিসেবে বর্ণনা করে (কতগুলো vCPU, কত RAM, কোন disk image, কোন network), তারপর সেই বর্ণনা অনুযায়ী সঠিক qemu-system-x86_64 কমান্ড-লাইন ফ্ল্যাগ তৈরি করে QEMU-কে চালায় ও তদারকি করে। virt-manager (GUI), oVirt, আর OpenStack-এর Nova compute service — এরা প্রায় সবাই সরাসরি QEMU-র সাথে কথা না বলে libvirt-এর সাথে কথা বলে — libvirt-ই backend হিসেবে QEMU+KVM (বা Xen, বা LXC container) চালায়। এই লেসনের গভীরতায় libvirt না গিয়ে শুধু এর অবস্থানটা মনে রাখা যথেষ্ট — এটা orchestration স্তর, virtualization স্তর না।
নিজে চালিয়ে দেখুন
raw KVM ioctl API দিয়ে একটা ন্যূনতম guest — আপনার নিজের Linux মেশিনে
Guest machine code — মাত্র ১২ বাইট, x86-16 real mode-এ চলে:
0xba, 0xf8, 0x03, /* mov $0x3f8, %dx — serial port 0x3f8-এ ঠিকানা বসানো */
0x00, 0xd8, /* add %bl, %al — al = al + bl */
0x04, '0', /* add $'0', %al — al-কে ASCII digit বানানো */
0xee, /* out %al, (%dx) — port 0x3f8-এ byte লেখা → VM-exit! */
0xb0, '\n', /* mov $'\n', %al */
0xee, /* out %al, (%dx) — আবার VM-exit */
0xf4 /* hlt — শেষ, VM-exit (KVM_EXIT_HLT) */Host program-এর register setup: rax=2, rbx=2, rip=0x1000 (যেখানে উপরের কোড লোড করা), আর rflags=0x2 (x86-এ reserved bit)। তাহলে add %bl, %al হিসাব করে al = 2 + 2 = 4, তারপর add $'0', %al সেটাকে ASCII '4'-তে রূপান্তর করে।
Run-লুপের কেন্দ্রীয় অংশ (ioctl(vcpu_fd, KVM_RUN)-এর পরে exit_reason অনুযায়ী branch):
for (;;) {
ioctl(vcpu_fd, KVM_RUN, NULL);
switch (run->exit_reason) {
case KVM_EXIT_HLT:
puts("KVM_EXIT_HLT");
return 0;
case KVM_EXIT_IO:
if (run->io.direction == KVM_EXIT_IO_OUT &&
run->io.size == 1 && run->io.port == 0x3f8 &&
run->io.count == 1)
putchar(*(((char *)run) + run->io.data_offset));
else
errx(1, "unhandled KVM_EXIT_IO");
break;
default:
errx(1, "unhandled exit reason: %d", run->exit_reason);
}
}প্রত্যাশিত output (Triplett-এর প্রবন্ধ অনুযায়ী, real Linux + /dev/kvm-এ):
4
KVM_EXIT_HLTতিনটা জিনিস লক্ষ করুন এই ছোট্ট প্রোগ্রামে — (১) KVM_CREATE_VM → KVM_SET_USER_MEMORY_REGION → KVM_CREATE_VCPU → KVM_SET_SREGS/KVM_SET_REGS → লুপে KVM_RUN — ঠিক hood অংশের সেই সিকোয়েন্স, কোনো সংক্ষিপ্তকরণ ছাড়াই; (২) out %al, (%dx) instruction-টা দুইবার চলেছে (একবার '4'-এর জন্য, একবার '\n'-এর জন্য) — প্রতিবার আলাদা একটা KVM_EXIT_IO, আলাদা একটা userspace round-trip, ঠিক আগের অংশের ATA PIO উদাহরণের একই প্যাটার্নের ক্ষুদ্রতম সম্ভাব্য সংস্করণ; (৩) hlt-এ থামা মানে guest নিজেই স্বেচ্ছায় CPU ফেরত দিচ্ছে — QEMU-র মতো একটা বাস্তব VMM এখানে guest-কে shutdown/reboot হিসেবে বিবেচনা করত।
এই লেসনের পুরো hood অংশ — ioctl সিকোয়েন্স, KVM_EXIT_IO, VM-entry/VM-exit চক্র — কোনো abstraction না, প্রতিটা লাইন সরাসরি চালানো যায় এমন C কোড।
নিজে বানান
ioctl(KVM_RUN) Round-Trip গণনাকারী — device-emulation বনাম paravirtual batching
- উপরের ATA PIO টেবিল থেকে প্রতি সেক্টরে VM-exit সংখ্যা গণনা করার একটা ফাংশন লিখুন — select head, sector count, LBA byte, command, status poll, আর সবচেয়ে বড় খরচ ২৫৬টা word-read
- একটা দ্বিতীয় ফাংশন লিখুন যা একটা কাল্পনিক ব্যাচ-করা (batched) ডিভাইস মডেল করে — N সেক্টর একবারে, একটামাত্র "kick"-এ পাঠানো (এটাই পরের লেসনের virtio-blk-এর আগাম ইঙ্গিত)
- দুইটা মডেলেই ioctl(KVM_RUN) কলের সংখ্যা (= VM-exit + ১) হিসাব করুন, ১টা, ১০০টা, ১০,০০০টা, ১০ লাখ সেক্টরের জন্য
- একটা প্রকাশিত, রক্ষণশীল order-of-magnitude সংখ্যা (~১২০০ ন্যানোসেকেন্ড/round-trip, VT-x exit+entry-র প্রায়) ব্যবহার করে মোট overhead সময় আনুমানিক করুন
- ১০,০০০ সেক্টরে দুই মডেলের অনুপাত বের করুন — এই একটা সংখ্যাই পরের লেসনের পুরো যুক্তির প্রথম প্রমাণ
এই স্ক্রিপ্টটা আসলেই চালানো হয়েছে (এই sandbox macOS, /dev/kvm নেই বলে সরাসরি KVM কল করা যায়নি — কিন্তু এই গণনাটা কোনো kernel access লাগে না, তাই পুরোপুরি verify-করা, real output):
# kvm_qemu_iotrip.py
# Model: কতগুলো userspace round-trip (VM-exit -> QEMU device model handle
# -> VM-entry, অর্থাৎ আরেকটা ioctl(KVM_RUN) কল) একটা device-I/O-ভারী
# workload-এর লাগে — legacy ATA/IDE PIO (পূর্ণ device emulation) বনাম
# virtio-blk (paravirtual, batched)।
import math
def ata_pio_exits_per_sector(lba_bytes=3, status_polls=4):
select_drive_head = 1
sector_count = 1
lba_regs = lba_bytes
command = 1
polling = status_polls
data_words = 512 // 2 # ২৫৬ — প্রতি ১৬-বিট শব্দে একটা IN
return select_drive_head + sector_count + lba_regs + command + polling + data_words
def kvm_round_trips(n_sectors, exits_per_sector):
n_exits = n_sectors * exits_per_sector
ioctl_kvm_run_calls = n_exits + 1 # +১ প্রথম VM-entry-র জন্য
return n_exits, ioctl_kvm_run_calls
def virtio_round_trips(n_sectors, sectors_per_batch):
n_batches = math.ceil(n_sectors / sectors_per_batch)
n_exits = n_batches # এক "kick" (eventfd/MMIO doorbell) প্রতি ব্যাচে
ioctl_kvm_run_calls = n_exits + 1
return n_exits, ioctl_kvm_run_calls
EXIT_ENTRY_OVERHEAD_NS = 1200 # প্রকাশিত VT-x round-trip খরচের order-of-magnitude
if __name__ == "__main__":
exits_per_sector = ata_pio_exits_per_sector()
print(f"emulated ATA PIO: VM-exits per 512B sector = {exits_per_sector}")
print()
print("emulated ATA/IDE (PIO mode, full device emulation):")
for n_sectors in (1, 100, 10_000, 1_000_000):
n_exits, calls = kvm_round_trips(n_sectors, exits_per_sector)
total_ms = n_exits * EXIT_ENTRY_OVERHEAD_NS / 1e6
print(f" sectors={n_sectors:>9,} vm-exits={n_exits:>13,} "
f"ioctl(KVM_RUN) calls={calls:>13,} overhead~{total_ms:>10.2f} ms")
print()
print("virtio-blk (paravirtual, batch of 128 sectors/request):")
for n_sectors in (1, 100, 10_000, 1_000_000):
n_exits, calls = virtio_round_trips(n_sectors, 128)
total_ms = n_exits * EXIT_ENTRY_OVERHEAD_NS / 1e6
print(f" sectors={n_sectors:>9,} vm-exits={n_exits:>13,} "
f"ioctl(KVM_RUN) calls={calls:>13,} overhead~{total_ms:>10.4f} ms")
print()
n = 10_000
ata_exits, _ = kvm_round_trips(n, exits_per_sector)
vio_exits, _ = virtio_round_trips(n, 128)
print(f"at {n:,} sectors: {ata_exits/vio_exits:.1f}x fewer VM-exits with virtio batching "
f"({ata_exits:,} vs {vio_exits:,})")প্রকৃত, চালানো output (Python 3.9, এই sandbox-এ হুবহু এই কমান্ডে পাওয়া গেছে — কোনো hand-trace না):
emulated ATA PIO: VM-exits per 512B sector = 266
emulated ATA/IDE (PIO mode, full device emulation):
sectors= 1 vm-exits= 266 ioctl(KVM_RUN) calls= 267 overhead~ 0.32 ms
sectors= 100 vm-exits= 26,600 ioctl(KVM_RUN) calls= 26,601 overhead~ 31.92 ms
sectors= 10,000 vm-exits= 2,660,000 ioctl(KVM_RUN) calls= 2,660,001 overhead~ 3192.00 ms
sectors=1,000,000 vm-exits= 266,000,000 ioctl(KVM_RUN) calls= 266,000,001 overhead~ 319200.00 ms
virtio-blk (paravirtual, batch of 128 sectors/request):
sectors= 1 vm-exits= 1 ioctl(KVM_RUN) calls= 2 overhead~ 0.0012 ms
sectors= 100 vm-exits= 1 ioctl(KVM_RUN) calls= 2 overhead~ 0.0012 ms
sectors= 10,000 vm-exits= 79 ioctl(KVM_RUN) calls= 80 overhead~ 0.0948 ms
sectors=1,000,000 vm-exits= 7,813 ioctl(KVM_RUN) calls= 7,814 overhead~ 9.3756 ms
at 10,000 sectors: 33670.9x fewer VM-exits with virtio batching (2,660,000 vs 79)সংখ্যাগুলো নিজেরাই কথা বলছে — মাত্র ১০,০০০ সেক্টর (৫ মেগাবাইটেরও কম!) পড়তে emulated ATA PIO মোডে ২৬ লাখেরও বেশি VM-exit লাগে, শুধু exit/entry overhead-এই আনুমানিক ৩.২ সেকেন্ড — অথচ একই ডেটা batched virtio মডেলে মাত্র ৭৯টা exit, ০.১ মিলিসেকেন্ডেরও কম overhead। ৩৩,৬৭০ গুণ পার্থক্য, শুধু “কীভাবে ডেটা রিকোয়েস্ট ব্যাচ করা হয়েছে” তার কারণে — CPU নিজে ঠিক একই গতিতে চলছে দুই ক্ষেত্রেই (KVM-accelerated), পার্থক্যটা সম্পূর্ণ device-interaction প্যাটার্নে। এই একটা সংখ্যাই পরের লেসনের (paravirtualization) পুরো justification।
(EXIT_ENTRY_OVERHEAD_NS = 1200 একটা রক্ষণশীল, প্রকাশিত-সাহিত্য-ভিত্তিক order-of-magnitude ধরে নেওয়া মান — বাস্তব সংখ্যা CPU generation, mitigation (Spectre/Meltdown patch) সক্রিয় কি না, ইত্যাদির উপর নির্ভর করে কয়েকশ থেকে কয়েক হাজার ন্যানোসেকেন্ডের মধ্যে ওঠানামা করে; এখানে গুরুত্বপূর্ণ অনুপাতটা — একটা ধ্রুবক গুণিতক পাল্টালেও ৩৩,৬৭০× পার্থক্যের মাত্রা (order of magnitude) পাল্টাবে না।)
নিজে বাড়ান:
status_pollsবাড়িয়ে/কমিয়ে দেখুন — বাস্তব ATA controller-এ polling loop-এর দৈর্ঘ্য ডিভাইসের গতির উপর নির্ভর করে; এটা মোট overhead-এ কতটা প্রভাব ফেলে?sectors_per_batch(virtio-র batch size) ১ থেকে ৫১২ পর্যন্ত বদলে একটা গ্রাফ কল্পনা করুন — batch size বাড়ানোর diminishing return কোথায় শুরু হয়?- একটা তৃতীয় মডেল যোগ করুন — modern AHCI (native command queuing, PIO-র চেয়ে ভালো কিন্তু virtio-র চেয়ে খারাপ) কত exit/sector হতে পারে, ধরে নেওয়া অনুমানসহ যুক্তি দিন।
বাস্তব সিস্টেমে
বাস্তব জগতে KVM ও QEMU
-
Qumranet ও KVM-এর জন্ম (২০০৬-০৭)। KVM মূলত Qumranet নামের একটা ইসরায়েলি স্টার্টআপ ডেভেলপ করে, ২০০৬-এ প্রথম প্রকাশ, আর মাত্র কয়েক মাসের মধ্যেই Linux 2.6.20 (ফেব্রুয়ারি ২০০৭)-এ mainline kernel-এ merge হয় — একটা অস্বাভাবিক দ্রুত merge, যা দেখায় KVM-এর ডিজাইন (একটা ছোট kernel module, বিশাল আলাদা hypervisor কোডবেস না) কতটা elegant মনে হয়েছিল kernel maintainer-দের কাছে। Red Hat পরে ২০০৮-এ Qumranet কিনে নেয়; আজ KVM Red Hat-এর enterprise virtualization strategy-র কেন্দ্রে।
-
Firecracker (AWS, ২০১৮)। AWS Lambda আর Fargate-এর পেছনের microVM প্রযুক্তি। Firecracker QEMU ব্যবহার করে না — এটা সরাসরি
/dev/kvmioctl API-এর সাথে কথা বলে (Rust-এ লেখা), আর device emulation-এর জন্য শুধু কয়েকটা ন্যূনতম virtio ডিভাইস (block, net) সমর্থন করে — কোনো legacy ATA/VGA/USB emulation নেই। ফলাফল: একটা VM boot করতে ~১২৫ মিলিসেকেন্ডের কম, প্রতি VM-এর মেমরি overhead কয়েক মেগাবাইট মাত্র — QEMU-র পূর্ণাঙ্গ device model-এর তুলনায় বহুগুণ হালকা। এইটা এই লেসনের সবচেয়ে স্পষ্ট প্রমাণ যে QEMU আর KVM আলাদা, বদলযোগ্য — QEMU একমাত্র বিকল্প না, শুধু সবচেয়ে পরিচিত। -
crosvm ও cloud-hypervisor। Google-এর crosvm (ChromeOS/Android-এর Crostini Linux container-এর জন্য) আর Intel/community-চালিত cloud-hypervisor প্রজেক্ট — দুইটাই Firecracker-এর মতো, Rust-এ লেখা, QEMU-র বদলে সরাসরি KVM API ব্যবহার করা VMM। এই পুরো ecosystem-টাই প্রমাণ করে “device emulation কে করবে” প্রশ্নের একাধিক বৈধ উত্তর আছে — QEMU সবচেয়ে পুরনো ও পূর্ণাঙ্গ, কিন্তু একমাত্র না।
-
libvirt + virt-manager — desktop/server virtualization-এর ডি-ফ্যাক্টো স্ট্যান্ডার্ড। Fedora/RHEL-ভিত্তিক Linux distribution-এ
virt-managerGUI ব্যবহার করে VM তৈরি করলে, পর্দার আড়ালে libvirtd ঠিক এই লেসনের বর্ণিতqemu-system-x86_64 -enable-kvm ...কমান্ডই তৈরি করে চালায়। -
OpenStack Nova। বড় প্রাইভেট ক্লাউড ডেপ্লয়মেন্টে (OpenStack-ভিত্তিক), Nova compute service প্রতিটা physical host-এ libvirt-এর সাথে কথা বলে VM schedule করে — এই লেসনের চার-স্তরের ছবিটাই, শুধু শত শত সার্ভার জুড়ে বিস্তৃত।
-
Android Emulator। Linux host-এ Android Studio-র emulator KVM acceleration ব্যবহার করে (আর macOS/Windows-এ যথাক্রমে HVF/WHPX — একই ধারণার Apple/Microsoft সংস্করণ) — QEMU-ভিত্তিক, ঠিক এই লেসনের QEMU+KVM মডেল, ডেভেলপারের ল্যাপটপে প্রতিদিন চলছে, প্রায়ই কেউ খেয়ালও করে না।
যে ভুলগুলো সবাই করে
“KVM নিজেই একটা সম্পূর্ণ hypervisor — 'KVM চালানো' মানে একটা কার্যকর VM পাওয়া।”
ভুল, আর এই লেসনের সবচেয়ে গুরুত্বপূর্ণ বিভাজন-রেখা এখানেই। KVM একা শুধু /dev/kvm device আর কিছু ioctl প্রদান করে — CPU আর memory virtualization primitive, ব্যস। কোনো disk নেই, কোনো BIOS নেই, কোনো network card নেই। একা /dev/kvm খুলে, KVM_CREATE_VM/KVM_CREATE_VCPU কল করে একটা vCPU চালানো সম্ভব (experiment অংশের ১২-বাইট প্রোগ্রামের মতো) — কিন্তু সেটা একটা “VM” না, এটা একটা ন্যূনতম sandbox যেখানে raw machine code চলে। একটা প্রকৃত, বুট-করা-যায় এমন VM লাগে একটা userspace VMM (QEMU, Firecracker, crosvm — যেকোনো একটা) যেটা device emulation আর firmware প্রদান করে।
“QEMU+KVM মানে QEMU সবসময় ধীর software emulation করছে, শুধু KVM 'সাহায্য' করে।”
উল্টো — যখন KVM ব্যবহৃত হয়, CPU instruction execution সম্পূর্ণ native hardware গতিতে চলে (VMX non-root mode-এ সরাসরি, hardware-virtualization লেসনের core promise)। QEMU-র TCG software translator তখন সম্পূর্ণ নিষ্ক্রিয় থাকে CPU execution-এর জন্য। শুধুমাত্র device I/O (disk, network, graphics access) QEMU-র userspace কোডে emulate হয় — আর এইটা KVM ব্যবহার করুক বা না করুক, উভয় মোডেই সমান খরচ। তাই “QEMU ধীর” একটা অতি-সরলীকরণ — QEMU+KVM-এর CPU-bound workload প্রায় native-এর কাছাকাছি গতিতে চলে; শুধু device-I/O-ভারী workload-এ (এই লেসনের ATA PIO উদাহরণের মতো) পার্থক্য প্রকট হয়।
“QEMU-র cross-architecture emulation (যেমন ARM binary x86-এ চালানো) ক্ষমতাটা আসলে KVM-এর কৃতিত্ব — KVM 'বিভিন্ন CPU নকল করতে' সাহায্য করে।”
সম্পূর্ণ উল্টো সম্পর্ক। Cross-architecture emulation একচেটিয়াভাবে QEMU-র TCG (software dynamic translation)-এর ক্ষমতা — KVM-এর কোনো ভূমিকা নেই এখানে, বরং KVM ব্যবহার করলে cross-architecture emulation অসম্ভব হয়ে যায়। কারণ সহজ: KVM guest instruction-কে সরাসরি host CPU-তে চালায় (VMX non-root mode-এ) — তাই guest ISA অবশ্যই host ISA-র সাথে হুবহু মিলতে হবে (x86-64 guest শুধু x86-64 host-এ KVM-accelerated হতে পারে)। ভিন্ন ISA emulate করতে হলে (ARM-on-x86) instruction-বাই-instruction software translation ছাড়া উপায় নেই — অর্থাৎ TCG, KVM ছাড়া।
“libvirt হলো hypervisor — 'libvirt VM চালায়' মানে libvirt নিজেই virtualization করছে।”
Libvirt একটা management layer — VM-কে একটা declarative XML হিসেবে বর্ণনা করার, তারপর সঠিক backend (QEMU+KVM, Xen, LXC container, VMware — একাধিক driver সমর্থন করে) চালানোর একটা প্রমিত API/daemon। এটা নিজে কোনো VMCS তৈরি করে না, কোনো ioctl(KVM_RUN) কল করে না — এই সবকিছুই এখনও QEMU+KVM স্তরে ঘটে, libvirt শুধু সেই কমান্ড-লাইন তৈরি করে ও তদারকি করে। virt-manager-এর GUI থেকে একটা VM “চালানো” মানে পর্দার আড়ালে হুবহু এই লেসনের বর্ণিত পুরো ioctl সিকোয়েন্স ঘটা — libvirt শুধু সেই প্রক্রিয়া শুরু করার সুবিধাজনক একটা স্তর।
বুঝেছেন কি না দেখুন
1KVM ঠিক কী দুইটা জিনিস প্রদান করে, আর কোন তিনটা জিনিস প্রদান করে না?
স্মরণ
প্রদান করে: (১) CPU virtualization (VMCS তৈরি ও পরিচালনা, VM-entry/VM-exit ট্রানজিশন), (২) memory virtualization (EPT সেটআপ)। প্রদান করে না: disk controller emulation, network card emulation, graphics/BIOS emulation — এই সব device emulation সম্পূর্ণভাবে userspace VMM-এর (সাধারণত QEMU) দায়িত্ব।
2একজন সহকর্মী প্রস্তাব দিচ্ছেন — “disk I/O দ্রুত করতে KVM-এর ভেতরে সরাসরি একটা virtual disk controller emulate করার কোড যোগ করা উচিত, তাহলে আর QEMU পর্যন্ত VM-exit যেতে হবে না।” এই প্রস্তাবের ডিজাইন-ঝুঁকিটা কী?
যুক্তি
KVM একটা kernel module — এতে device emulation কোড যোগ করা মানে সেই কোড kernel space-এ চলবে, যেখানে একটা বাগ পুরো সিস্টেম crash (kernel panic) করতে পারে, নিরাপত্তা-ঝুঁকিও অনেক বেশি (kernel-এ privilege escalation)। QEMU-তে একই বাগ শুধু সেই একটা QEMU process crash করবে — বাকি host system অক্ষত থাকবে। এটাই মূল কারণ কেন KVM ইচ্ছাকৃতভাবে ন্যূনতম রাখা হয়েছে — device emulation-এর জটিল, বাগ-প্রবণ কোড userspace-এ (QEMU) রাখাই নিরাপদ ডিজাইন, পারফরম্যান্সের সামান্য খরচ সত্ত্বেও। (বাস্তবে কিছু performance-critical, ছোট device সত্যিই in-kernel accelerate করা হয় — যেমন ঐচ্ছিক in-kernel APIC/PIT — কিন্তু এগুলো ছোট, ভালোভাবে-অডিটেড ব্যতিক্রম, নিয়ম না।)
3Build অংশের মডেল অনুযায়ী, একটা প্রোগ্রাম emulated ATA PIO ডিস্ক থেকে ৫০০টা সেক্টর পড়ে। মোট কতগুলো VM-exit ঘটবে, আর কতগুলো ioctl(KVM_RUN) কল লাগবে? (ধরুন প্রতি সেক্টরে ২৬৬টা exit।)
প্রয়োগ
ioctl(KVM_RUN) কল লাগবে? (ধরুন প্রতি সেক্টরে ২৬৬টা exit।)VM-exit = ৫০০ × ২৬৬ = ১৩৩,০০০টা। ioctl(KVM_RUN) কল = ১৩৩,০০০ + ১ (প্রথম VM-entry-র জন্য) = ১৩৩,০০১টা। শুধু exit/entry overhead-এর হিসাবে (~১২০০ ন্যানোসেকেন্ড/round-trip ধরে): ১৩৩,০০০ × ১২০০ ns ≈ ১৫৯.৬ মিলিসেকেন্ড — শুধু context-switch overhead-এই, প্রকৃত ডেটা transfer বাদ দিয়ে।
4কেন QEMU+TCG দিয়ে একটা ARM binary x86 হোস্টে চালানো সম্ভব, কিন্তু QEMU+KVM দিয়ে অসম্ভব? এক বাক্যে যান্ত্রিক কারণ দিন।
যুক্তি
KVM guest instruction সরাসরি host CPU-তে চালায় (VMX non-root mode-এ hardware execution) — host CPU হার্ডওয়্যারগতভাবে শুধু তার নিজের ISA (x86-64) বোঝে, তাই guest ISA-ও x86-64 হতে হবে। TCG এর বদলে software-এ প্রতিটা instruction পড়ে-বুঝে-অনুবাদ করে — তাই guest ISA যা-ই হোক (ARM, RISC-V, MIPS), host-এর জন্য এটা শুধু ডেটা, hardware execution-এর প্রশ্নই আসে না।
5Experiment অংশের ১২-বাইট guest প্রোগ্রামে ঠিক কয়টা VM-exit ঘটবে, আর কেন?
প্রয়োগ
দুইটা KVM_EXIT_IO (দুইটা out %al, (%dx) instruction — একটা '4'-এর জন্য, একটা '\n'-এর জন্য) প্লাস একটা KVM_EXIT_HLT (hlt instruction-এ) — মোট তিনটা VM-exit। প্রতিটা out instruction port-mapped I/O access, VT-x-এ unconditionally trap হয় (কোনো I/O bitmap override না থাকলে); hlt-ও সবসময় trap হয় কারণ CPU-কে idle করার সিদ্ধান্ত VMM-এর হাতে থাকা দরকার (একটা VM অনির্দিষ্টকাল CPU আটকে রাখতে পারবে না)।
6আপনি একটা নতুন serverless platform বানাচ্ছেন যেখানে হাজার হাজার ছোট, স্বল্পস্থায়ী (কয়েক মিলিসেকেন্ড থেকে কয়েক সেকেন্ড) VM প্রতি সেকেন্ডে বুট করতে হবে। পূর্ণাঙ্গ QEMU (legacy ATA/VGA/USB device model-সহ) নাকি একটা Firecracker-ধাঁচের ন্যূনতম VMM (শুধু virtio-block/net, সরাসরি KVM ioctl) — কোনটা বাছবেন, আর এই লেসনের কোন দুইটা সংখ্যা/উদাহরণ আপনার সিদ্ধান্তকে সরাসরি সমর্থন করে?
ডিজাইন
Firecracker-ধাঁচের ন্যূনতম VMM বাছাই স্পষ্টভাবে সঠিক এখানে। কারণ: (১) boot দ্রুত হওয়া জরুরি — QEMU-র পূর্ণাঙ্গ device model (BIOS probe, legacy device enumeration) initialization overhead যোগ করে যা serverless-এর মিলিসেকেন্ড-স্কেল বাজেটে সহ্য করা কঠিন, যেখানে Firecracker-এর ~১২৫ ms boot time (realworld অংশ) স্পষ্টভাবে এই দাবি সমর্থন করে। (২) memory density — হাজার হাজার concurrent VM-এ প্রতিটার per-VM overhead গুরুত্বপূর্ণ; QEMU-র ভারী device model কোড প্রতিটা instance-এ বাড়তি মেমরি নেয়, Firecracker-এর ন্যূনতম footprint সেটা এড়ায়। (৩) build অংশের সংখ্যা সরাসরি প্রাসঙ্গিক — যদি এই VM-গুলো কোনো I/O করে, legacy device emulation-এর ২৬৬-exit/sector খরচ বনাম virtio-এর batched, কম-exit পথ — ৩৩,৬৭০× পার্থক্যটা সরাসরি latency budget-এ প্রভাব ফেলবে। Legacy ATA/VGA/USB সমর্থনের দরকারই নেই যখন guest নিজেই নিয়ন্ত্রিত (custom কার্নেল/rootfs), তাই সেই জটিলতা ফেলে দেওয়াই যুক্তিসঙ্গত।
এরপর কী
এরপর কী
আজ আমরা দেখলাম KVM+QEMU একটা unmodified guest OS-কে সম্পূর্ণ বিভ্রান্ত করে — guest ভাবে সে আসল ATA disk, আসল network card-এর সাথে কথা বলছে, কোনো cooperation ছাড়াই, শুধু faithful device emulation-এর জোরে। কিন্তু build অংশের সংখ্যা নির্মমভাবে স্পষ্ট — এই বিশ্বস্ততার দাম বিশাল। প্রতিটা disk read, প্রতিটা network packet, VM-exit সীমানা পার হয়ে userspace-এ যায়, প্রতিবারই একটা context-switch-এর খরচ বহন করে।
পরের লেসনে (paravirtualization) প্রশ্নটা উল্টে যাবে — যদি guest OS নিজে রাজি হয় সহযোগিতা করতে, প্রতারিত হওয়ার বদলে? যদি একটা ভার্চুয়াল disk controller “আসল ATA-র মতো” নকল করার চেষ্টা না করে, বরং একটা সম্পূর্ণ নতুন, virtualization-এর জন্যই ডিজাইন করা প্রোটোকল ব্যবহার করে — একটা shared ring buffer, batch করা রিকোয়েস্ট, একটা মাত্র “kick” প্রতি ব্যাচে? আজকের build অংশের virtio মডেলটাই সেই প্রশ্নের প্রথম ঝলক — পরের লেসনে সেটাই কেন্দ্রীয় বিষয় হয়ে পূর্ণ ব্যাখ্যা পাবে, virtio-র ring buffer গঠন, front-end/back-end driver split, আর ঠিক কীভাবে “guest agrees to cooperate” একটা বাস্তব, কোড-স্তরের চুক্তিতে রূপ নেয় তা-সহ।
আরও পড়ুন
- kvm: the Linux Virtual Machine Monitor — Avi Kivity, Yaniv Kamay, Dor Laor, Uri Lublin, Anthony Liguori — Ottawa Linux Symposium (OLS) 2007, Vol. 1 · KVM-এর মূল paper — Qumranet টিম ব্যাখ্যা করছে কেন Linux kernel-কেই hypervisor বানানো একটা আলাদা VMM লেখার চেয়ে ভালো সিদ্ধান্ত।
- QEMU, a Fast and Portable Dynamic Translator — Fabrice Bellard — USENIX Annual Technical Conference (FREENIX Track), 2005 · QEMU-র মূল paper — TCG (Tiny Code Generator)-এর ভিত্তি, cross-architecture dynamic binary translation-এর নকশা।
- Using the KVM API — Josh Triplett — LWN.net, সেপ্টেম্বর ২৯, ২০১৫ · raw ioctl API দিয়ে একটা ন্যূনতম guest চালানোর হাতে-কলমে গাইড — এই লেসনের experiment অংশের ভিত্তি।
- QEMU Documentation — System Emulation, Invocation, Accelerators — QEMU Project · device model, accelerator (KVM/TCG/HVF) নির্বাচন, আর `-enable-kvm`-এর মতো অপশনের প্রামাণ্য ডকুমেন্টেশন।