PCIe & DMA
TEKNİK REHBER PCIe & DMA DONANIM 2026

IOMMU & SMMU
DMA Koruması

DMA saldırılarını anla ve önle. Intel VT-d, AMD-Vi ve ARM SMMU-v3 ile cihaz izolasyonu. Linux IOMMU subsystem, VFIO ve KVM PCIe passthrough.

00 IOMMU nedir? — DMA saldırısı ve izolasyon

IOMMU (Input-Output Memory Management Unit), PCIe ve diğer I/O cihazlarının sistem belleğine erişimini kontrol eden donanım birimidir. CPU'nun MMU'su ne işe yarıyorsa, IOMMU da I/O cihazları için aynı işlevi görür.

DMA saldırısı — neden IOMMU gerekli?

IOMMU olmayan bir sistemde, PCIe cihazı herhangi bir fiziksel adrese DMA yapabilir. Bu durum ciddi güvenlik riskleri doğurur:

  IOMMU OLMADAN (tehlikeli):

  Kötü niyetli PCIe cihazı (örn. truva atı USB-PCIe dongle):
  ┌────────────────────────────────────────────────────────┐
  │  DMA isteği: adres=0x100000, len=4096                  │
  │  → Kernel kod bölgesini okur/değiştirir!               │
  │  → SSH anahtarını, bellek içeriğini çalar              │
  │  → /dev/mem yerine doğrudan DMA ile çekirdek bypass    │
  └────────────────────────────────────────────────────────┘

  IOMMU İLE (güvenli):
  ┌────────────────────────────────────────────────────────┐
  │  Cihaz DMA isteği: adres=0x100000                      │
  │  IOMMU: bu IOVA için eşleme var mı?                    │
  │    → Eşleme yok → ATE (Access Translation Error)       │
  │    → PCIe UR (Unsupported Request) yanıtı              │
  │    → dmesg: IOMMU fault: device 01:00.0                │
  └────────────────────────────────────────────────────────┘
    

IOMMU temel kavramları

IOVA (I/O Virtual Address)Cihazın kullandığı adres; gerçek fiziksel adres değil; IOMMU çevirir
IOMMU DomainBir sayfa tablosu; bir veya daha fazla cihaza atanabilir
IOMMU GroupAynı trust sınırında olan cihazlar; grup başına bir domain zorunlu
ACS (Access Control Services)PCIe özelliği: Switch içindeki P2P (peer-to-peer) DMA'yı kontrol eder
ATS (Address Translation Services)PCIe özelliği: cihaz kendi IOVA→PA çevirisini yapabilir (performans)

IOMMU olmayan sistem riski

Thunderbolt, PCIe hot-plug, USB4 gibi kullanıcı tarafından takılabilen cihazlara sahip sistemlerde IOMMU kritiktir. "Evil maid" saldırısı: masaüstü bilgisayar kilitliyken takılan bir PCIe cihazı, IOMMU olmadan RAM'i okuyabilir.

Bu bölümde

  • IOMMU: I/O cihazlarının DMA erişimini sayfa tablosu ile denetler
  • IOVA: cihazın gördüğü adres; IOMMU → PA çevirisi; haritasız erişim engellenir
  • DMA saldırısı: IOMMU olmadan herhangi bir PCIe cihazı tüm RAM'e erişebilir
  • IOMMU group: izolasyon birimi; bir grubun tamamı aynı domain'e bağlanmalı

01 Intel VT-d ve AMD-Vi

Intel VT-d (Virtualization Technology for Directed I/O) ve AMD-Vi, x86 platformlarındaki IOMMU uygulamalarıdır. ACPI DMAR tablosu üzerinden keşfedilir.

Intel VT-d mimarisi

  ┌─────────────────────────────────────────────────────────────┐
  │                    Intel VT-d                               │
  │                                                             │
  │  PCIe Bus  →  [Remapping Hardware Unit]  →  System RAM     │
  │                        │                                    │
  │                        ▼                                    │
  │              Root Entry Table (RET)                         │
  │              (Bus 0-255 için 256 entry)                     │
  │                        │                                    │
  │                    Context Entry                            │
  │              (Device:Function için)                         │
  │                        │                                    │
  │                  IOMMU Page Table                           │
  │              (IOVA → PA çevirisi, 4/2/1 KB page)           │
  └─────────────────────────────────────────────────────────────┘
    
bash — Intel VT-d etkinleştirme ve doğrulama
# BIOS/UEFI'de VT-d etkinleştirdikten sonra:

# Kernel parametreleri (/etc/default/grub)
# GRUB_CMDLINE_LINUX="intel_iommu=on iommu=strict"
# iommu=strict: her DMA haritası kaldırıldığında TLB flush (güvenli)
# iommu=pt:    passthrough (güvenlik kapalı, max performans)

sudo update-grub
sudo reboot

# Doğrulama
dmesg | grep -i iommu | head -10
# DMAR: IOMMU enabled
# DMAR-IR: Enabled IRQ remapping in x2apic mode

cat /sys/class/iommu/dmar0/intel-iommu/cap
# Capability flags: SAGAW (address width), SLTS, etc.

# DMAR (DMA Remapping) tablosunu oku
sudo acpidump -n DMAR | acpixtract -l
sudo iasl -d DMAR.dat

AMD-Vi

AMD IOMMU (IVRS tablosu, AMD-Vi), Intel VT-d'ye benzer işlevsellik sunar. Kernel parametresi: amd_iommu=on. AMD platformlarda PCIe cihazları IVHD (I/O Virtualization Hardware Definition) tablosu üzerinden IOMMU'ya bağlanır.

ÖzellikIntel VT-dAMD-Vi
ACPI tablosuDMARIVRS
Kernel parametresiintel_iommu=onamd_iommu=on
IRQ remappingVT-d IRAMD-Vi IR
Sayfa boyutları4KB, 2MB, 1GB4KB, 2MB, 1GB
Nested translationSLAT (nested)PPR (Peripheral Page Request)

Bu bölümde

  • VT-d: DMAR ACPI tablosu → Root Entry → Context Entry → IOMMU page table
  • intel_iommu=on: VT-d etkinleştirir; iommu=strict: her unmap'te TLB flush
  • AMD-Vi: IVRS tablosu; amd_iommu=on; VT-d ile işlevsel eşdeğer
  • Sayfa boyutu: 4KB (minimum), 2MB (büyük sayfa, TLB verimli), 1GB (dev sayfa)

02 ARM SMMU-v3 — stream ID ve context bank

ARM Systems MMU (SMMU), ARM SoC'larındaki IOMMU uygulamasıdır. SMMU-v3, PCIe ve diğer I/O master'lar için iki aşamalı sayfa tablosu çevirisi sağlar.

SMMU-v3 mimarisi

  ┌───────────────────────────────────────────────────────────────┐
  │                      ARM SMMU-v3                              │
  │                                                               │
  │  I/O Device  ──(StreamID)──▶  Stream Table  ──▶  Context     │
  │  (PCIe BDF,                  (STE: Stream    Bank / CD       │
  │   DMA master ID)              Table Entry)   (sayfa tablosu) │
  │                                                               │
  │  Stage 1: VA → IPA (guest OS sayfa tablosu, VMID ile)        │
  │  Stage 2: IPA → PA  (hypervisor sayfa tablosu, VMID ile)     │
  │                                                               │
  │  PCIe BDF → RequestID → StreamID → STE → Stage1 + Stage2    │
  └───────────────────────────────────────────────────────────────┘
    

StreamID ve RequestID

RequestID: PCIe'de BDF (Bus:Device:Function) — TLP header'dan alınır. StreamID: SMMU'nun gördüğü ID; RequestID → StreamID dönüşümü platform yapılandırmasına bağlı. Her StreamID için SMMU'da bir Stream Table Entry (STE) bulunur.

bash — SMMU-v3 Linux ile doğrulama
# ARM64 kernel: SMMU DT node örneği (device tree)
# smmu: iommu@09000000 {
#     compatible = "arm,smmu-v3";
#     reg = <0x0 0x09000000 0x0 0x800000>;
#     interrupts = <...>;
#     #iommu-cells = <1>;
# };
#
# PCIe EP'nin SMMU'ya bağlanması:
# pcie: pcie@... {
#     iommus = <&smmu STREAMID>;
# };

# Kernel parametreleri
# arm-smmu-v3.disable_bypass=1  — haritasız DMA'yı engelle
# iommu.strict=1                — strict TLB invalidation

# SMMU cihazını gör
dmesg | grep -i smmu
# arm-smmu-v3 9000000.iommu: probing hardware
# arm-smmu-v3 9000000.iommu: SMMU-v3 with 128-bit IDS

# Bağlı gruplar
ls /sys/kernel/iommu_groups/
ls /sys/kernel/iommu_groups/0/devices/

Stage 1 ve Stage 2 çevirisi

AşamaGirdiÇıktıKullanım
Stage 1 (S1)IOVA (cihaz adresi)IPA (Intermediate Physical)Native Linux DMA API
Stage 2 (S2)IPA (Guest fiziksel)PA (gerçek fiziksel)Sanallaştırma (hypervisor)
S1 + S2 (nested)IOVA → IPA → PAPAVM içindeki PCIe passthrough

Bu bölümde

  • SMMU-v3: ARM SoC için IOMMU; PCIe RequestID → StreamID → STE → sayfa tablosu
  • Stage 1: cihaz IOVA → fiziksel adres (native Linux kullanımı)
  • Stage 2: guest fiziksel → gerçek fiziksel (hypervisor, KVM)
  • disable_bypass=1: haritasız DMA isteği faulta düşer — zorunlu güvenlik ayarı

03 Linux IOMMU subsystem

Linux IOMMU subsystem, farklı donanım uygulamalarını (VT-d, AMD-Vi, SMMU) tek bir API arkasında soyutlar. Sürücüler iommu_ops üzerinden donanımdan bağımsız çalışır.

IOMMU subsystem katmanları

  Kullanıcı alanı (VFIO)
       │
  ┌────▼─────────────────────────────────┐
  │        Linux IOMMU Core API          │
  │  iommu_domain_alloc()                │
  │  iommu_attach_device()               │
  │  iommu_map()  /  iommu_unmap()       │
  └────┬─────────────────────────────────┘
       │   iommu_ops (driver-specific)
  ┌────▼───────────────────────────────────────┐
  │  intel-iommu.c │ amd-iommu.c │ arm-smmu.c  │
  └────────────────────────────────────────────┘
       │
  Hardware (VT-d / AMD-Vi / SMMU)
    
C — Linux IOMMU API (kernel sürücü tarafı)
#include <linux/iommu.h>

/* ── IOMMU domain oluşturma ───────────────────────────────── */
static struct iommu_domain *create_dma_domain(struct device *dev)
{
    struct iommu_domain *domain;

    /*
     * Domain türleri:
     *   IOMMU_DOMAIN_DMA:      DMA API için genel domain
     *   IOMMU_DOMAIN_IDENTITY: passthrough (PA==IOVA)
     *   IOMMU_DOMAIN_UNMANAGED: sürücü elle yönetir (VFIO için)
     *   IOMMU_DOMAIN_BLOCKED:  tüm DMA engellenir
     */
    domain = iommu_domain_alloc(dev->bus);
    if (!domain) {
        dev_err(dev, "iommu_domain_alloc başarısız\n");
        return NULL;
    }

    return domain;
}

/* ── Cihazı domain'e bağla ────────────────────────────────── */
static int attach_to_domain(struct iommu_domain *domain,
                              struct device *dev)
{
    int ret = iommu_attach_device(domain, dev);
    if (ret)
        pr_err("iommu_attach_device hata: %d\n", ret);
    return ret;
}

/* ── IOVA → PA haritası kur ──────────────────────────────── */
static int map_iova(struct iommu_domain *domain,
                    unsigned long iova, phys_addr_t pa,
                    size_t size)
{
    int prot = IOMMU_READ | IOMMU_WRITE;  /* | IOMMU_NOEXEC */
    int ret = iommu_map(domain, iova, pa, size, prot, GFP_KERNEL);
    if (ret)
        pr_err("iommu_map(0x%lx→0x%llx, %zu): %d\n",
               iova, (u64)pa, size, ret);
    return ret;
}

/* ── Haritayı kaldır ─────────────────────────────────────── */
static void unmap_iova(struct iommu_domain *domain,
                        unsigned long iova, size_t size)
{
    size_t unmapped = iommu_unmap(domain, iova, size);
    if (unmapped != size)
        pr_warn("iommu_unmap: beklenen %zu, gerçek %zu\n",
                size, unmapped);
}

/* ── IOVA → PA çeviri kontrolü ───────────────────────────── */
static phys_addr_t translate_iova(struct iommu_domain *domain,
                                   unsigned long iova)
{
    phys_addr_t pa = iommu_iova_to_phys(domain, iova);
    pr_debug("IOVA 0x%lx → PA 0x%llx\n", iova, (u64)pa);
    return pa;
}

Bu bölümde

  • iommu_domain: sayfa tablosu kapsayıcısı; IOMMU_DOMAIN_DMA genel kullanım için
  • iommu_attach_device(): cihazı domain'e bağlar; tüm DMA bu domain sayfa tablosundan geçer
  • iommu_map(): IOVA → PA eşlemesi kur; prot: READ, WRITE, NOEXEC bayrakları
  • DMA API sürücü çağrıları (dma_map_single vb.) arka planda iommu_map kullanır

04 IOMMU groups ve /sys/kernel/iommu_groups

IOMMU group, PCIe topolojisi veya donanım kısıtları nedeniyle birlikte yönetilmesi zorunlu cihazlar kümesidir. Bir grubu VFIO'ya atamak için gruptaki tüm cihazların VFIO'ya bağlanması gerekir.

Grup oluşma nedenleri

PCIe ACS (Access Control Services) yoksa, bir Switch arkasındaki tüm cihazlar birbirinin DMA trafiğine erişebilir — bunlar tek grup oluşturur. ACS etkinse her cihaz kendi grubunu alabilir. Root Port doğrudan bağlı Endpoint genellikle tek başına bir grupta olur.

bash — IOMMU group analizi
# Tüm IOMMU gruplarını ve içindeki cihazları listele
for d in /sys/kernel/iommu_groups/*/devices/*; do
    group=$(echo "$d" | cut -d/ -f5)
    bdf=$(basename "$d")
    name=$(lspci -s "$bdf" 2>/dev/null | cut -d: -f3-)
    printf "Group %-4s  %s  %s\n" "$group" "$bdf" "$name"
done | sort -n

# Tipik çıktı:
# Group 0    00:00.0  Host bridge: Intel ...  
# Group 1    00:1d.0  PCI bridge: Intel ...   
# Group 2    01:00.0  Non-Volatile memory: Samsung ...
# Group 3    02:00.0  Ethernet: Realtek ...   

# Bir grubun tüm cihazlarını gör
ls /sys/kernel/iommu_groups/2/devices/

# ACS desteği kontrolü
sudo lspci -vvv | grep -A5 "Access Control"
# Access Control Services: ACSCap: SrcValid+ TransBlk+ ReqRedir+ ... 
# → ACS mevcut: her downstream port izole edilebilir

# Grup-1 cihaz sayısı: birden fazlaysa VFIO passthrough için hepsini bağlamalısın
ls /sys/kernel/iommu_groups/1/devices/ | wc -l

IOMMU group ve VM passthrough ilişkisi

  İYİ (single-device group): ACS mevcut
  ┌──────────────┐    ┌──────────────┐
  │ Group 5      │    │ Group 6      │
  │ 02:00.0 NIC  │    │ 03:00.0 NVMe │
  └──────────────┘    └──────────────┘
  → Sadece NIC'i VM'e ver; NVMe host'ta kalır

  KÖTÜ (multi-device group): ACS yok, switch arkası
  ┌─────────────────────────────────────┐
  │ Group 7                             │
  │ 04:00.0 NIC                         │
  │ 04:01.0 Sound card                  │
  │ 04:02.0 USB controller              │
  └─────────────────────────────────────┘
  → VM'e NIC vermek için Sound + USB'yi de VM'e vermek zorunda
  → Veya: acs_override kernel patch (güvenlik kaybı)
    

Bu bölümde

  • IOMMU group: trust sınırı — gruptaki cihazlar birbirini etkileyebilir
  • ACS olmayan switch: tüm downstream cihazlar tek grup; passthrough sınırlaması
  • /sys/kernel/iommu_groups/N/devices/: grup üyelerini listeler
  • VFIO passthrough için: grup içindeki tüm cihazlar VFIO'ya bağlanmalı

05 VFIO — userspace device access

VFIO (Virtual Function I/O), PCIe cihazlarına kullanıcı alanından güvenli erişim sağlar. IOMMU koruması altında, cihaz doğrudan bir VM'e veya DPDK gibi kullanıcı alanı sürücülerine atanır.

VFIO mimarisi

  Kullanıcı Alanı (QEMU, DPDK):
    /dev/vfio/N  →  ioctl(VFIO_IOMMU_MAP_DMA)  →  DMA harita kur
    /dev/vfio/N  →  ioctl(VFIO_DEVICE_GET_REGION_INFO) → BAR okuma
    /dev/vfio/N  →  ioctl(VFIO_DEVICE_GET_IRQ_INFO)    → IRQ yapılandır

  Kernel:
    vfio.ko  →  vfio_iommu_type1.ko  →  Linux IOMMU API
                      │
              IOMMU Domain (UNMANAGED)
                      │
              IOMMU hardware (VT-d / SMMU)
    
bash — VFIO kurulumu ve cihaz bağlama
# 1. IOMMU etkin olduğunu doğrula
dmesg | grep -E "IOMMU|DMAR|SMMU"

# 2. Hedef cihazı belirle
lspci -nn
# 02:00.0 Ethernet [0200]: Realtek RTL8111/8168/8411 [10ec:8168]

# 3. IOMMU grubunu kontrol et
ls /sys/kernel/iommu_groups/3/devices/
# 0000:02:00.0  ← tek cihaz, iyi

# 4. Mevcut sürücüyü ayır
echo 0000:02:00.0 | sudo tee /sys/bus/pci/devices/0000:02:00.0/driver/unbind

# 5. VFIO modüllerini yükle
sudo modprobe vfio
sudo modprobe vfio_pci

# 6. Cihazı VFIO'ya bağla
echo "10ec 8168" | sudo tee /sys/bus/pci/drivers/vfio-pci/new_id

# Alternatif: vfio-pci doğrudan bind
echo 0000:02:00.0 | sudo tee /sys/bus/pci/drivers/vfio-pci/bind

# 7. /dev/vfio/ oluşturulduğunu doğrula
ls -la /dev/vfio/
# crw-rw-rw- 1 root vfio ...  /dev/vfio/3
# crw-rw-rw- 1 root root ...  /dev/vfio/vfio
C — VFIO userspace erişimi (DMA haritası)
#include <linux/vfio.h>
#include <sys/ioctl.h>

int vfio_setup(int group_id)
{
    int container, group, device_fd;

    /* VFIO container */
    container = open("/dev/vfio/vfio", O_RDWR);
    ioctl(container, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU);

    /* IOMMU group'u aç */
    char path[64];
    snprintf(path, sizeof(path), "/dev/vfio/%d", group_id);
    group = open(path, O_RDWR);
    ioctl(group, VFIO_GROUP_SET_CONTAINER, &container);

    /* Cihazı aç */
    device_fd = ioctl(group, VFIO_GROUP_GET_DEVICE_FD, "0000:02:00.0");

    /* BAR bilgisini al */
    struct vfio_region_info reg = {
        .argsz = sizeof(reg),
        .index = VFIO_PCI_BAR0_REGION_INDEX,
    };
    ioctl(device_fd, VFIO_DEVICE_GET_REGION_INFO, ®);
    printf("BAR0: offset=0x%llx size=0x%llx\n",
           reg.offset, reg.size);

    /* DMA haritası kur (QEMU bunu yapar) */
    struct vfio_iommu_type1_dma_map dma = {
        .argsz = sizeof(dma),
        .flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE,
        .vaddr = (uintptr_t)mmap(NULL, 4096, PROT_READ|PROT_WRITE,
                                  MAP_PRIVATE|MAP_ANONYMOUS, -1, 0),
        .iova  = 0x10000,   /* cihaza görünecek adres */
        .size  = 4096,
    };
    ioctl(container, VFIO_IOMMU_MAP_DMA, &dma);

    return device_fd;
}

Bu bölümde

  • VFIO: IOMMU korumalı kullanıcı alanı cihaz erişimi; güvenli DMA passthrough
  • Container → Group → Device hiyerarşisi; her grup tek container'a bağlanır
  • VFIO_IOMMU_MAP_DMA: kullanıcı belleği için IOMMU haritası kur → cihaz bu IOVA'ya DMA yapabilir
  • DPDK, QEMU, SPDK: performans kritik userspace sürücüler VFIO kullanır

06 IOMMU ve KVM/QEMU — PCIe passthrough

PCIe passthrough (assigned device), bir PCIe cihazını doğrudan sanal makineye atar. IOMMU, VM'nin cihazın DMA'sından korunmasını sağlar; cihaz sanki fiziksel olarak VM'in kendisindeymiş gibi çalışır.

Passthrough mekanizması

  Host Linux (KVM/QEMU)
  ┌─────────────────────────────────────────────────────────────┐
  │  QEMU proses                                                │
  │  ├── vCPU thread'leri                                       │
  │  └── VFIO device thread                                     │
  │         │                                                   │
  │         ▼                                                   │
  │  /dev/vfio/3  ──▶  vfio_iommu  ──▶  IOMMU (VT-d)          │
  │                                          │                  │
  │                                    PCIe 02:00.0 NIC        │
  └─────────────────────────────────────────────────────────────┘

  Sanal Makine (Guest OS):
  ├── Guest kernel: NIC'i "gerçek donanım" olarak görür
  ├── Guest DMA → IOMMU Stage-2 → Host PA → NIC
  └── IRQ: VFIO interrupt forwarding → kvm_irqfd → Guest IRQ
    
bash — QEMU PCIe passthrough komutu
# QEMU ile PCIe NIC passthrough (vfio-pci)
qemu-system-x86_64 \
    -enable-kvm \
    -cpu host \
    -m 4G \
    -drive file=vm.qcow2,format=qcow2 \
    \
    # IOMMU modeli (Guest'in IOMMU görmesi için)
    -machine q35,accel=kvm \
    -device intel-iommu,intremap=on,caching-mode=on \
    \
    # PCIe cihazı passthrough
    -device vfio-pci,host=02:00.0,multifunction=on \
    \
    -nographic \
    -serial mon:stdio

# Guest'te doğrulama
# lspci -k → sürücü: r8169 veya e1000e (gerçek hardware sürücüsü)
# ethtool eth0 → Speed: 1000baseT/Full (gerçek hız)
# iperf3 → host-to-guest: ~940 Mbps (bare metal yakın performans)

vIOMMU: Guest'e IOMMU sunmak

Guest OS IOMMU kullanmak istiyorsa (örn. VFIO içinde VFIO), QEMU'da vIOMMU emülasyonu etkinleştirilir. -device intel-iommu veya -device virtio-iommu-pci ile guest'e sanal IOMMU sunulur.

Bu bölümde

  • PCIe passthrough: cihaz doğrudan VM'e; bare metal yakın performans
  • IOMMU: VM DMA'sını izole eder; bir VM diğerinin belleğine veya host'a DMA yapamaz
  • q35 + intel-iommu: QEMU'da IOMMU destekli passthrough için gerekli platform
  • vIOMMU: nested VM veya guest DPDK için guest'e sanal IOMMU sunumu

07 Pratik: VFIO ile PCIe NIC'i sanal makineye doğrudan atama

Adım adım: Intel VT-d etkin sistemde Realtek NIC'i VFIO ile ayır, QEMU VM'ine ata ve guest Ubuntu'da çalıştır.

bash — tam passthrough kurulum betiği
#!/bin/bash
# nic_passthrough_setup.sh — PCIe NIC'i VM'e atama
set -euo pipefail

NIC_BDF="0000:02:00.0"       # lspci'den al
NIC_VENDOR_DEV="10ec:8168"   # lspci -nn'den al

echo "=== 1. IOMMU etkin mi? ==="
if ! dmesg | grep -qi "IOMMU enabled"; then
    echo "HATA: IOMMU etkin değil!"
    echo "GRUB: intel_iommu=on veya amd_iommu=on ekle"
    exit 1
fi
echo "OK: IOMMU etkin"

echo "=== 2. IOMMU group ==="
GROUP=$(readlink /sys/bus/pci/devices/$NIC_BDF/iommu_group | \
        sed 's|.*/||')
echo "NIC IOMMU group: $GROUP"
DEVICES=$(ls /sys/kernel/iommu_groups/$GROUP/devices/)
echo "Gruptaki cihazlar: $DEVICES"
COUNT=$(echo "$DEVICES" | wc -w)
if [ "$COUNT" -gt 1 ]; then
    echo "UYARI: Grupta $COUNT cihaz var — hepsini VFIO'ya bağlamalısın!"
fi

echo "=== 3. Mevcut sürücüyü ayır ==="
DRIVER=$(readlink /sys/bus/pci/devices/$NIC_BDF/driver 2>/dev/null | \
         sed 's|.*/||' || echo "none")
echo "Mevcut sürücü: $DRIVER"
if [ "$DRIVER" != "none" ] && [ "$DRIVER" != "vfio-pci" ]; then
    echo "$NIC_BDF" | sudo tee /sys/bus/pci/drivers/$DRIVER/unbind
    echo "Ayrıldı: $DRIVER"
fi

echo "=== 4. VFIO modülleri ==="
sudo modprobe vfio vfio_iommu_type1 vfio_pci

echo "=== 5. VFIO'ya bağla ==="
echo "$NIC_VENDOR_DEV" | sudo tee /sys/bus/pci/drivers/vfio-pci/new_id \
    2>/dev/null || true

if [ ! -e /sys/bus/pci/devices/$NIC_BDF/driver ]; then
    echo "$NIC_BDF" | sudo tee /sys/bus/pci/drivers/vfio-pci/bind
fi

echo "=== 6. Doğrulama ==="
readlink /sys/bus/pci/devices/$NIC_BDF/driver
ls -la /dev/vfio/

echo ""
echo "=== VM başlatma komutu ==="
cat <<'EOF'
qemu-system-x86_64 \
  -enable-kvm -cpu host -m 2G \
  -drive file=ubuntu.qcow2,format=qcow2 \
  -machine q35,accel=kvm \
  -device intel-iommu \
  -device vfio-pci,host=02:00.0 \
  -nographic -serial mon:stdio
EOF
bash — guest doğrulama ve performans testi
# Guest OS içinde (Ubuntu)

# NIC tanındı mı?
lspci -k
# 00:03.0 Ethernet: Realtek RTL8111/8168
#         Kernel driver in use: r8169

# IP adresi al
sudo dhclient eth0

# Performans testi: host ↔ guest iperf3
# Host'ta:
iperf3 -s
# Guest'te:
iperf3 -c 192.168.1.1 -t 10
# [ ID] Interval      Transfer     Bandwidth
# [  5]  0.00-10.00   1.11 GBytes  953 Mbits/sec
# → 953 Mbps: bare metal yakın (overhead yok)

# Karşılaştırma: virtio-net (QEMU emüle)
# [  5]  0.00-10.00   0.91 GBytes  784 Mbits/sec
# → virtio-net 17% daha yavaş — passthrough'un avantajı

Bu bölümde

  • IOMMU group kontrolü: tek cihazlı group → passthrough için ideal; çok cihazlı → hepsini VFIO'ya bağla
  • vfio-pci modülü: mevcut sürücüyü ayır, cihazı VFIO'ya bağla, /dev/vfio/N oluşur
  • Performans: vfio-pci passthrough, virtio-net'ten %15-20 daha yüksek throughput
  • Güvenlik: IOMMU etkin passthrough — VM host belleğine DMA yapamaz