Xen & Jailhouse
TEKNİK REHBER GÖMÜLÜ LİNUX JAILHOUSE 2026

Jailhouse
Static Partitioning Hypervisor

Linux üzerinde çalışan static partitioning hypervisor. Root cell, non-root cell, IVSHMEM IPC, bare-metal inmate ve BeagleBone Black pratik kurulumu.

00 Jailhouse konsepti

Jailhouse, Siemens tarafından geliştirilen ve gömülü sistemler için tasarlanmış bir Linux partitioning hypervisor'ıdır. "Hücre" metaforu üzerine kuruludur: her yazılım bileşeni kendi hücresinde izole çalışır.

Static partitioning nedir?

Geleneksel hypervisor'lar (KVM, Xen) dinamik kaynak yönetimi yapar — VM'ler oluşturulup silinebilir, bellek balon sürücüsüyle değişebilir. Jailhouse ise statik: sistem başlamadan önce tüm kaynaklar (CPU, bellek, MMIO, IRQ) sabit olarak hücrelere atanır. Runtime'da değişmez.

Başlangıç (Linux çalışıyor):
┌────────────────────────────────────────┐
│  Linux (root cell candidate)           │
│  CPU 0-3, RAM 0x80000000-0xFFFFFFFF    │
└────────────────────────────────────────┘

jailhouse enable root-cell.cell komutu:
┌───────────────────────┬────────────────┐
│  Root Cell (Linux)    │ Non-root Cell  │
│  CPU 0-1, RAM         │ CPU 2-3, RAM   │
│  0x80000000-0xBFFFFFFF│ 0xC0000000-    │
│                       │ 0xFFFFFFFF     │
└───────────────────────┴────────────────┘
        ↑ Jailhouse Hypervisor (EL2) ↑
    

Jailhouse'un tasarım felsefesi

Minimal hypervisor kodu~20.000 satır — küçük TCB (Trusted Computing Base) — sertifikasyon kolaylığı
Linux'tan yararlanmaRoot cell Linux sürücü ekosistemini kullanır — yeniden yazmaya gerek yok
Statik konfigürasyonRuntime dinamizm yok — öngörülebilir, deterministik davranış
Bare-metal inmateNon-root cell'de tam bare-metal program yazılabilir — RTOS veya custom firmware

Bu bölümde

  • Static partitioning: tüm kaynaklar boot'tan önce sabit atanır
  • Root cell: Linux — donanım sürücülerine erişir, Jailhouse'u yönetir
  • Non-root cell: RTOS veya bare-metal — izole edilmiş bölme
  • ~20KB kod tabanı — güvenlik sertifikasyonu için kritik avantaj

01 Kurulum — kernel patch & jailhouse tool

Jailhouse kurulumu üç bileşen gerektirir: uyumlu Linux kernel, Jailhouse kernel modülü ve kullanıcı alanı yönetim aracı.

Kernel gereksinimleri

bash — Kernel konfigürasyon gereksinimleri
# Jailhouse için kernel konfigürasyonu
# ARM64 için:
CONFIG_ARM64=y
CONFIG_ARM_SMMU=y         # SMMU desteği (IOMMU)
CONFIG_ARM_SMMU_V3=y      # SMMUv3 (i.MX8, ARM Cortex-A)
CONFIG_VFIO=y             # PCI passthrough
CONFIG_VFIO_PCI=y
CONFIG_VFIO_IOMMU_TYPE1=y
CONFIG_IOMMU_API=y

# Jailhouse modülü için
CONFIG_KALLSYMS_ALL=y
CONFIG_STRICT_MODULE_RWX=n   # bazı dağıtımlarda gerekli

# EFI stub (EL2 için boot)
CONFIG_EFI=y

# PCI MSI (x86 için)
CONFIG_PCI_MSI=y

# Kernel komut satırında EL2 zorunlu
# mem=3G — kalan bellek Jailhouse/inmate için boş bırakılır

Jailhouse kaynak kodu ve derleme

bash — Jailhouse derleme (ARM64)
# Kaynak kodu indir
git clone https://github.com/siemens/jailhouse.git
cd jailhouse
git checkout v0.12

# Çapraz derleme ortamı
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
export KDIR=/path/to/kernel/source

# Derleme
make KDIR=$KDIR

# Çıktı dosyaları
# driver/jailhouse.ko  — kernel modülü
# tools/jailhouse      — yönetim aracı
# hypervisor/jailhouse.bin — hypervisor binary

# Kurulum
make KDIR=$KDIR DESTDIR=/target install

# Hedef cihaza kopyala
scp driver/jailhouse.ko root@192.168.1.100:/lib/modules/$(uname -r)/
scp tools/jailhouse root@192.168.1.100:/usr/sbin/
scp hypervisor/jailhouse.bin root@192.168.1.100:/lib/firmware/

Hedef cihazda ilk kurulum

bash — Hedef cihazda Jailhouse başlatma
# Kernel modülünü yükle
modprobe jailhouse
# [  12.345678] jailhouse: loading out-of-tree module...
# [  12.345890] jailhouse: Initialized

# /dev/jailhouse kontrol et
ls -la /dev/jailhouse
# crw------- 1 root root 10, 63 ... /dev/jailhouse

# Jailhouse version
jailhouse --version
# Jailhouse v0.12

Bu bölümde

  • Kernel: CONFIG_ARM_SMMU, CONFIG_VFIO, CONFIG_IOMMU_API zorunlu
  • 3 bileşen: jailhouse.ko + jailhouse tool + jailhouse.bin
  • KDIR: kernel kaynak dizini — modül kernel sürümüyle eşleşmeli
  • /dev/jailhouse: kullanıcı alanı arayüzü

02 Cell konfigürasyon dosyası

Jailhouse'da her hücre (cell) bir C struct dosyasıyla tanımlanır. Bu dosya derlenerek binary .cell formatına dönüştürülür. Konfigürasyon donanıma özgüdür ve memory map'i, CPU atamasını, MMIO bölgelerini ve IRQ'ları belirtir.

Cell config dosyası yapısı

C — cell config temel yapısı
/* configs/arm64/myboard-root.c */
#include <jailhouse/types.h>
#include <jailhouse/cell-config.h>

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

struct {
    struct jailhouse_system header;
    __u64 cpus[1];
    struct jailhouse_memory mem_regions[8];
    struct jailhouse_irqchip irqchips[1];
    struct jailhouse_pci_device pci_devices[2];
} __attribute__((packed)) config = {

    .header = {
        .signature = JAILHOUSE_SYSTEM_SIGNATURE,
        .revision = JAILHOUSE_CONFIG_REVISION,
        .flags = JAILHOUSE_SYS_VIRTUAL_DEBUG_CONSOLE,
        .hypervisor_memory = {
            .phys_start = 0xfc000000,  /* hypervisor için ayrılan RAM */
            .size       = 0x04000000,  /* 64MB */
        },
        .debug_console = {
            .address = 0x30880000,     /* UART3 base (i.MX8) */
            .size    = 0x1000,
            .type    = JAILHOUSE_CON_TYPE_IMX,
            .flags   = JAILHOUSE_CON_ACCESS_MMIO |
                       JAILHOUSE_CON_REGDIST_4,
        },
        .platform_info = {
            .arm = {
                .gic_version = 3,
                .gicd_base   = 0x38800000,  /* GIC Distributor */
                .gicr_base   = 0x38880000,  /* GIC Redistributor */
                .maintenance_irq = 25,
            },
        },
        .root_cell = {
            .name = "imx8mp-root",
            .num_cpus = ARRAY_SIZE(config.cpus),
            .num_memory_regions = ARRAY_SIZE(config.mem_regions),
            .num_irqchips = ARRAY_SIZE(config.irqchips),
            .num_pci_devices = ARRAY_SIZE(config.pci_devices),
        },
    },

    .cpus = { 0xf },  /* CPU 0-3 (4 çekirdek) root cell'de */

    .mem_regions = {
        /* UART3 MMIO */
        {
            .phys_start = 0x30880000,
            .virt_start = 0x30880000,
            .size       = 0x10000,
            .flags      = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
                          JAILHOUSE_MEM_IO | JAILHOUSE_MEM_IO_32,
        },
        /* RAM — Linux için */
        {
            .phys_start = 0x40000000,
            .virt_start = 0x40000000,
            .size       = 0xbc000000,  /* ~3GB */
            .flags      = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
                          JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_DMA,
        },
        /* Jailhouse hypervisor alanı (eşlenmez) */
        {
            .phys_start = 0xfc000000,
            .virt_start = 0xfc000000,
            .size       = 0x04000000,
            .flags      = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE,
        },
    },
};

Cell config derleme

bash — .cell binary derleme
# Jailhouse kaynak içindeki konfigürasyonu derle
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- \
     KDIR=$KDIR configs

# Çıktı: configs/arm64/imx8mp-evk.cell
ls configs/arm64/*.cell
# configs/arm64/imx8mp-evk.cell
# configs/arm64/imx8mp-evk-inmate-demo.cell

# Alternatif: tek dosyayı derle
aarch64-linux-gnu-gcc -I include/jailhouse \
    -DJAILHOUSE_CONFIG_REVISION=13 \
    -c configs/arm64/imx8mp-evk.c -o /tmp/imx8mp-evk.o
aarch64-linux-gnu-objcopy -O binary /tmp/imx8mp-evk.o \
    /tmp/imx8mp-evk.cell

Bu bölümde

  • Cell config: C struct — memory_regions, cpus, irqchips, pci_devices
  • hypervisor_memory: Jailhouse için ayrılan RAM bölgesi
  • debug_console: UART MMIO adresi — konsol çıktısı için
  • .cell binary: C struct → objcopy → binary dönüşüm

03 Jailhouse komutları

Jailhouse kullanıcı alanı aracı, cell yaşam döngüsünü yönetir. Root cell Linux içinden çalışır ve /dev/jailhouse üzerinden hypervisor ile iletişim kurar.

Temel komut sırası

bash — Jailhouse komut referansı
# 1. Jailhouse'u etkinleştir (root cell config ile)
jailhouse enable /lib/firmware/imx8mp-evk.cell
# [  25.123456] Created Jailhouse cell "imx8mp-root"
# [  25.123789] Jailhouse activated

# 2. Non-root cell oluştur
jailhouse cell create /lib/firmware/imx8mp-inmate-demo.cell
# [  26.234567] Created Jailhouse cell "inmate-demo"

# 3. Cell'e image yükle
jailhouse cell load inmate-demo /lib/firmware/led-blink.bin
# Loaded image into cell "inmate-demo"

# 4. Cell'i başlat
jailhouse cell start inmate-demo
# [  27.345678] Started cell "inmate-demo"

# 5. Cell durumunu kontrol et
jailhouse cell list
# ID      Name           State    Assigned CPUs    Failed CPUs
#  0      imx8mp-root    running  0-1              
#  1      inmate-demo    running  2                

# 6. Cell durdur
jailhouse cell shutdown inmate-demo
jailhouse cell destroy inmate-demo

# 7. Jailhouse'u devre dışı bırak
jailhouse disable
# [  60.789012] Jailhouse deactivated

# Yardımcı komutlar
jailhouse hardware check    # platform uyumluluğu
jailhouse cell stats inmate-demo  # CPU istatistikleri
jailhouse console            # Jailhouse log çıktısı

Cell load ile birden fazla image

bash — Çoklu image yükleme
# Linux inmate için kernel + initrd + DTB
jailhouse cell load linux-inmate \
    /boot/Image -a 0x80000000 \
    /boot/initramfs.cpio.gz -a 0x82000000 \
    /boot/linux-inmate.dtb -a 0x84000000

# -a flag: yükleme adresi
# Bare-metal için sadece binary
jailhouse cell load bare-metal-cell /lib/firmware/rtos.bin

Bu bölümde

  • jailhouse enable: hypervisor aktif → Linux root cell'e alınır
  • cell create → load → start: non-root cell yaşam döngüsü
  • cell list: çalışan cell'lerin CPU ve durum özeti
  • jailhouse disable: tüm cell'ler durdurulur, Linux tek başına devam eder

04 IVSHMEM — Inter-VM Shared Memory

IVSHMEM (Inter-VM Shared Memory), Jailhouse cell'leri arasında hızlı iletişim sağlar. Paylaşılan bir bellek bölgesi ve bildirim mekanizması (doorbell interrupt) üzerine kuruludur.

IVSHMEM mimarisi

Root Cell (Linux)          Non-root Cell (RTOS/Linux)
    ↕                              ↕
shmem_region[0]      ←→     shmem_region[0]
(0xF0000000, 4MB)           (aynı fiziksel adres)
    ↕ doorbell IRQ              ↕ doorbell IRQ
    ↕                              ↕
IVSHMEM PCI device          IVSHMEM registers
    

Root cell'de IVSHMEM konfigürasyonu

C — IVSHMEM cell config (root cell)
/* Root cell config içinde IVSHMEM bölgesi */
.mem_regions = {
    /* ... diğer bölgeler ... */

    /* IVSHMEM paylaşımlı bellek (non-root cell'e de atanır) */
    {
        .phys_start = 0xF0000000,
        .virt_start = 0xF0000000,
        .size       = 0x00400000,  /* 4MB paylaşımlı RAM */
        .flags      = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
                      JAILHOUSE_MEM_ROOTSHARED,
    },
},
.pci_devices = {
    {
        .type        = JAILHOUSE_PCI_TYPE_IVSHMEM,
        .domain      = 0,
        .bdf         = 0x0e << 3,  /* bus:dev:func */
        .bar_mask    = JAILHOUSE_IVSHMEM_BAR_MASK_INTX,
        .shmem_regions_start = 0,  /* mem_regions indeksi */
        .shmem_dev_id = 0,
        .shmem_peers  = 2,         /* 2 peer: root + inmate */
        .shmem_protocol = JAILHOUSE_SHMEM_PROTO_UNDEFINED,
    },
},

Linux'ta IVSHMEM kullanımı

C — Linux IVSHMEM okuma/yazma
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

#define SHMEM_PHYS  0xF0000000
#define SHMEM_SIZE  0x400000   /* 4MB */

int main(void)
{
    int fd = open("/dev/mem", O_RDWR | O_SYNC);
    if (fd < 0) { perror("open"); return 1; }

    volatile uint32_t *shmem = mmap(NULL, SHMEM_SIZE,
        PROT_READ | PROT_WRITE, MAP_SHARED, fd, SHMEM_PHYS);
    if (shmem == MAP_FAILED) { perror("mmap"); return 1; }

    /* RTOS'tan gelen heartbeat oku */
    while (1) {
        uint32_t heartbeat = shmem[0];
        uint32_t status    = shmem[1];
        printf("Heartbeat: %u, Status: 0x%08x\n", heartbeat, status);
        sleep(1);
    }

    munmap((void*)shmem, SHMEM_SIZE);
    close(fd);
    return 0;
}

IVSHMEM üzerinde doorbell interrupt

bash — ivshmem-net sürücüsü (Linux)
# ivshmem-net sürücüsü — ağ protokolü üzerinden IPC
modprobe ivshmem-net
ip link show
# eth1: ... ivshmem_net

# IVSHMEM üzerinden ping
ip addr add 10.0.0.1/24 dev eth1
ip link set eth1 up
ping 10.0.0.2  # inmate tarafı

# jailhouse-demo paketi — Python üst katman
# /usr/share/jailhouse/tools/jailhouse-cell-demo.sh

Bu bölümde

  • IVSHMEM: paylaşılan fiziksel bellek + doorbell IRQ — en hızlı IPC
  • ROOTSHARED flag: bellek bölgesi birden fazla cell'e eşlenir
  • /dev/mem + mmap: Linux'tan IVSHMEM erişimi
  • ivshmem-net: ağ protokolü stacked IVSHMEM üzerinde

05 Bare-metal inmate

Jailhouse'un en güçlü özelliklerinden biri, non-root cell'de tamamen bare-metal kod çalıştırabilmektir. OS gerekmez — doğrudan donanım erişimi, minimum gecikme.

Bare-metal inmate yapısı

inmate.c (uygulama kodu)
    + inmates/lib/arm64/inmate.lds (linker script)
    + inmates/lib/arm64/header.S (entry point)
    + inmates/lib/printk.c (UART debug)
    = inmate.bin (flat binary)
    

Minimal bare-metal inmate

C — minimal bare-metal inmate
#include <inmate.h>
#include <inmates/lib/arm64/sysregs.h>

/* GPIO veya MMIO doğrudan erişim */
#define GPIO1_BASE   0x30200000UL
#define GPIO_DR      0x00  /* Data Register */
#define GPIO_GDIR    0x04  /* Direction Register */
#define LED_PIN      (1 << 10)  /* GPIO1_IO10 */

static volatile uint32_t *gpio1 = (volatile uint32_t *)GPIO1_BASE;

static void gpio_set_output(uint32_t pin)
{
    gpio1[GPIO_GDIR / 4] |= pin;
}

static void gpio_toggle(uint32_t pin)
{
    gpio1[GPIO_DR / 4] ^= pin;
}

static void udelay(unsigned long us)
{
    /* ARM64 systimer tabanlı gecikme */
    unsigned long freq = read_sysreg(cntfrq_el0);
    unsigned long start = read_sysreg(cntpct_el0);
    unsigned long ticks = (freq / 1000000) * us;
    while ((read_sysreg(cntpct_el0) - start) < ticks)
        ;
}

void inmate_main(void)
{
    printk("Jailhouse bare-metal inmate starting!\n");
    printk("GPIO base: 0x%lx\n", (unsigned long)GPIO1_BASE);

    gpio_set_output(LED_PIN);

    while (1) {
        gpio_toggle(LED_PIN);
        printk("LED toggle\n");
        udelay(500000);  /* 500ms */
    }
}

Inmate derleme

bash — bare-metal inmate derleme
# Jailhouse inmates dizininde
cd /path/to/jailhouse

# Inmate derle
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- \
     KDIR=$KDIR \
     inmates/demos/arm64/led-demo.bin

# Veya kendi inmate'ini ekle: inmates/demos/arm64/led-demo.c
# inmates/Makefile'a ekle:
# demos-$(CONFIG_ARM64) += led-demo

# Çıktı kontrol
ls -la inmates/demos/arm64/led-demo.bin
# -rw-r--r-- 1 user user 4096 ... led-demo.bin

# ARM64 binary dump — doğrulama
aarch64-linux-gnu-objdump -D inmates/demos/arm64/led-demo.elf | head -40

Bu bölümde

  • Bare-metal inmate: OS yok — doğrudan MMIO/GPIO erişimi
  • inmate_main(): entry point — header.S tarafından çağrılır
  • printk(): Jailhouse inmate debug UART çıktısı
  • ARM64 systimer: udelay için donanım sayacı

06 Linux inmate

Non-root cell'de minimal bir Linux sistemi çalıştırmak mümkündür. Root cell Linux'tan farklı olarak bu Linux, kısıtlı kaynaklara ve ayrı bir network namespace'e sahiptir.

Linux inmate cell konfigürasyonu

C — Linux inmate cell config
/* configs/arm64/imx8mp-linux-inmate.c */
struct {
    struct jailhouse_cell_desc header;
    __u64 cpus[1];
    struct jailhouse_memory mem_regions[4];
    struct jailhouse_irqchip irqchips[1];
} __attribute__((packed)) config = {
    .header = {
        .signature = JAILHOUSE_CELL_DESC_SIGNATURE,
        .revision  = JAILHOUSE_CONFIG_REVISION,
        .name      = "linux-inmate",
        .flags     = JAILHOUSE_CELL_PASSIVE_COMMREG,
        .cpu_set_size = sizeof(config.cpus),
        .num_memory_regions = ARRAY_SIZE(config.mem_regions),
        .num_irqchips = ARRAY_SIZE(config.irqchips),
        .vpci_irq_base = 108,  /* sanal PCI IRQ başlangıcı */
    },

    /* CPU 2-3 bu cell'e ait */
    .cpus = { 0xc },  /* bit mask: CPU 2=0x4, CPU 3=0x8, toplam 0xc */

    .mem_regions = {
        /* RAM — Linux inmate için 256MB */
        {
            .phys_start = 0xC0000000,
            .virt_start = 0x40000000,  /* guest sanal adres */
            .size       = 0x10000000,  /* 256MB */
            .flags      = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
                          JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_LOADABLE,
        },
        /* UART4 (inmate'e atanan UART) */
        {
            .phys_start = 0x30890000,
            .virt_start = 0x30890000,
            .size       = 0x10000,
            .flags      = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
                          JAILHOUSE_MEM_IO | JAILHOUSE_MEM_IO_32,
        },
        /* IVSHMEM paylaşımlı bellek */
        {
            .phys_start = 0xF0000000,
            .virt_start = 0xF0000000,
            .size       = 0x00400000,
            .flags      = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
                          JAILHOUSE_MEM_ROOTSHARED,
        },
    },
};

Linux inmate için minimal kernel konfigürasyonu

bash — Linux inmate kernel derleme
# Jailhouse Linux inmate için minimal defconfig
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- \
     jailhouse_defconfig

# Kritik konfigürasyonlar
# CONFIG_JAILHOUSE_GUEST=y  — inmate desteği
# CONFIG_PCI=y              — IVSHMEM için
# CONFIG_PCI_MMCONFIG=y
# CONFIG_SERIAL_IMX=y       — UART4 sürücüsü

# Kernel derle
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc) Image

# Minimal initramfs oluştur (busybox)
mkdir -p /tmp/initramfs/{bin,dev,proc,sys}
cp /usr/bin/busybox /tmp/initramfs/bin/
ln -s busybox /tmp/initramfs/bin/sh
cat > /tmp/initramfs/init << 'EOF'
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
echo "Linux inmate booted!"
exec /bin/sh
EOF
chmod +x /tmp/initramfs/init
cd /tmp/initramfs
find . | cpio -o -H newc | gzip > /tmp/initramfs.cpio.gz

Bu bölümde

  • Linux inmate: ayrı CPU + RAM bölmesi — tam Linux çekirdeği
  • JAILHOUSE_CELL_PASSIVE_COMMREG: root cell ile senkronizasyon
  • virt_start ≠ phys_start: Stage-2 adres çevirisi ile remapping
  • CONFIG_JAILHOUSE_GUEST: inmate Linux için zorunlu kernel seçeneği

07 ARM vs x86 platform farkları

Jailhouse hem ARM hem x86 destekler ancak her platformun donanım özellikleri farklı konfigürasyon gerektirir.

Platform karşılaştırması

ÖzellikARM (AArch64)x86-64
Hypervisor katmanıEL2 (donanım desteği)VMX (Intel VT-x) / SVM (AMD-V)
IOMMUARM SMMU (SMMUv2/v3)Intel VT-d / AMD-Vi
Interrupt controllerARM GICv2/v3/v4LAPIC / IOAPIC / MSI
TimerARM Generic Timer (arch_timer)HPET / TSC / LAPIC timer
Config dosyalarıconfigs/arm64/configs/x86/
Entry pointheader.S (AArch64)header.S (x86-64)
Console typeIMX / PL011 / 82508250 UART / VUART

ARM GIC konfigürasyonu

C — ARM GIC irqchip config
/* ARM GICv3 irqchip konfigürasyonu */
.irqchips = {
    {
        .address  = 0x38800000,  /* GICD base — Distributor */
        .pin_base = 32,          /* SPI başlangıcı (0-31 SGI/PPI) */
        .pin_bitmap = {
            0xffffffff,          /* SPI 32-63 */
            0xffffffff,          /* SPI 64-95 */
            0xffffffff,          /* SPI 96-127 */
            0xffffffff,          /* SPI 128-159 */
        },
    },
},

/* platform_info.arm için GIC adresleri */
.platform_info = {
    .arm = {
        .gic_version     = 3,
        .gicd_base       = 0x38800000,
        .gicr_base       = 0x38880000,  /* Redistributor */
        .maintenance_irq = 25,          /* PPI 9 (25 = 16+9) */
    },
},

x86 VUART — sanal UART

C — x86 VUART konfigürasyonu
/* x86: sanal UART (port I/O tabanlı) */
.debug_console = {
    .address = 0x3F8,    /* COM1 port I/O adresi */
    .size    = 0x8,
    .type    = JAILHOUSE_CON_TYPE_8250,
    .flags   = JAILHOUSE_CON_ACCESS_PIO,  /* PIO — ARM'da MMIO */
},

/* ARM için MMIO UART */
.debug_console = { */
/*   .address = 0x30880000, */  /* MMIO */
/*   .type    = JAILHOUSE_CON_TYPE_IMX, */
/*   .flags   = JAILHOUSE_CON_ACCESS_MMIO, */
/* }, */

Bu bölümde

  • ARM: EL2 + SMMU + GICv3 — AArch64 spesifik konfigürasyon
  • x86: VT-x + VT-d + LAPIC/IOAPIC — PIO vs MMIO farkı
  • configs/arm64/ vs configs/x86/: platform dizinleri
  • ARM maintenance_irq: PPI 9 (25) — VGIC maintenance interrupt

08 Pratik: BeagleBone Black LED blink inmate

BeagleBone Black (AM335x, ARM Cortex-A8) üzerinde Jailhouse ile bare-metal LED blink inmate kurulumu. Root cell Linux çalışırken non-root cell'de LED yanıp söner.

BeagleBone Black donanım özellikleri

SoCTI AM335x — ARM Cortex-A8, tek çekirdek, 1GHz
RAM512MB DDR3 — root cell: 384MB, inmate: 128MB
LEDUSR0-USR3 — GPIO1_21, GPIO1_22, GPIO1_23, GPIO1_24
NotAM335x tek çekirdek — CPU paylaşımı yerine hypervisor time-slicing kullanılır

BeagleBone Black root cell config

C — bbb-root-cell.c (kısaltılmış)
/* BeagleBone Black root cell konfigürasyonu */
.header = {
    .signature = JAILHOUSE_SYSTEM_SIGNATURE,
    .revision  = JAILHOUSE_CONFIG_REVISION,
    .hypervisor_memory = {
        .phys_start = 0x7c000000,  /* 512MB - 64MB */
        .size       = 0x04000000,  /* 64MB hypervisor */
    },
    .debug_console = {
        .address = 0x44e09000,     /* UART0 base */
        .size    = 0x1000,
        .type    = JAILHOUSE_CON_TYPE_8250,
        .flags   = JAILHOUSE_CON_ACCESS_MMIO |
                   JAILHOUSE_CON_REGDIST_4,
    },
    .platform_info.arm = {
        .gicd_base       = 0x48241000,
        .gicc_base       = 0x48240100,
        .gic_version     = 2,
        .maintenance_irq = 25,
    },
},
.cpus = { 0x1 },  /* Tek CPU — AM335x */

LED blink inmate kodu

C — bbb-led-demo.c
#include <inmate.h>

/* AM335x GPIO1 */
#define GPIO1_BASE        0x4804C000UL
#define GPIO_OE           0x134  /* Output Enable (0=output) */
#define GPIO_DATAOUT      0x13C  /* Data Out */
#define GPIO_CLEARDATAOUT 0x190  /* Clear bit */
#define GPIO_SETDATAOUT   0x194  /* Set bit */

/* USR LEDs: GPIO1_21 - GPIO1_24 */
#define LED_MASK  (0xF << 21)

static volatile uint32_t *gpio1 = (volatile uint32_t *)GPIO1_BASE;

static inline void gpio_write(uint32_t offset, uint32_t val)
{
    gpio1[offset / 4] = val;
}

static inline uint32_t gpio_read(uint32_t offset)
{
    return gpio1[offset / 4];
}

void inmate_main(void)
{
    uint32_t oe;

    printk("BBB LED blink inmate starting\n");

    /* GPIO1 çıkış olarak ayarla */
    oe = gpio_read(GPIO_OE);
    oe &= ~LED_MASK;  /* 0 = output */
    gpio_write(GPIO_OE, oe);

    printk("GPIO1 OE configured: 0x%08x\n", gpio_read(GPIO_OE));

    uint32_t pattern = 0;
    while (1) {
        /* Chase pattern: her döngüde bir LED kayar */
        gpio_write(GPIO_CLEARDATAOUT, LED_MASK);
        gpio_write(GPIO_SETDATAOUT, 1 << (21 + (pattern % 4)));
        pattern++;

        printk("LED pattern: %u\n", pattern % 4);

        /* ~250ms gecikme (ARM926 @1GHz yaklaşık) */
        delay_us(250000);
    }
}

Tam test prosedürü

bash — BBB Jailhouse test adımları
# 1. Dosyaları BBB'ye kopyala
scp bbb-root-cell.cell root@192.168.7.2:/lib/firmware/
scp bbb-inmate-demo.cell root@192.168.7.2:/lib/firmware/
scp bbb-led-demo.bin root@192.168.7.2:/lib/firmware/
scp jailhouse.ko root@192.168.7.2:/lib/modules/$(uname -r)/extra/

# 2. BBB'de modül yükle
ssh root@192.168.7.2
depmod -a
modprobe jailhouse

# 3. Jailhouse etkinleştir
jailhouse enable /lib/firmware/bbb-root-cell.cell
# Created Jailhouse cell "bbb-root"

# 4. Inmate cell oluştur ve başlat
jailhouse cell create /lib/firmware/bbb-inmate-demo.cell
jailhouse cell load inmate-demo /lib/firmware/bbb-led-demo.bin
jailhouse cell start inmate-demo
# Started cell "inmate-demo"
# (USR LED'ler yanıp sönmeye başlar)

# 5. Inmate konsol çıktısı
jailhouse console
# BBB LED blink inmate starting
# GPIO1 OE configured: 0xFE1FFFFF
# LED pattern: 0
# LED pattern: 1
# ...

# 6. Root cell Linux çalışmaya devam ediyor
jailhouse cell list
# ID    Name           State    Assigned CPUs
#  0    bbb-root       running  0
#  1    inmate-demo    running  0 (time-sliced)

Bu bölümde

  • AM335x: tek çekirdek — hypervisor time-slicing ile paylaşım
  • GPIO1 SETDATAOUT/CLEARDATAOUT: atomic LED kontrolü
  • jailhouse console: inmate'in printk çıktısını root cell'den izle
  • LED chase pattern: 4 LED sırayla yakılır — inmate çalışıyor kanıtı