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
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
# 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
# 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
# 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ı
/* 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
# 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ı
# 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
# 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
/* 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ı
#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
# 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
#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
# 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
/* 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
# 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ı
| Özellik | ARM (AArch64) | x86-64 |
|---|---|---|
| Hypervisor katmanı | EL2 (donanım desteği) | VMX (Intel VT-x) / SVM (AMD-V) |
| IOMMU | ARM SMMU (SMMUv2/v3) | Intel VT-d / AMD-Vi |
| Interrupt controller | ARM GICv2/v3/v4 | LAPIC / IOAPIC / MSI |
| Timer | ARM Generic Timer (arch_timer) | HPET / TSC / LAPIC timer |
| Config dosyaları | configs/arm64/ | configs/x86/ |
| Entry point | header.S (AArch64) | header.S (x86-64) |
| Console type | IMX / PL011 / 8250 | 8250 UART / VUART |
ARM GIC konfigürasyonu
/* 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
/* 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
BeagleBone Black root cell config
/* 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
#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ü
# 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ı