#!/usr/bin/env bash # # build-kernel.sh - Build an optimized microVM kernel for Volt # # This script downloads and builds a minimal Linux kernel configured # specifically for fast-booting microVMs with KVM virtualization. # # Requirements: # - gcc, make, flex, bison, libelf-dev, libssl-dev # - ~2GB disk space, ~10 min build time # # Output: kernels/vmlinux (uncompressed kernel for direct boot) set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" BUILD_DIR="${PROJECT_DIR}/.build/kernel" OUTPUT_DIR="${PROJECT_DIR}/kernels" # Kernel version - LTS for stability KERNEL_VERSION="${KERNEL_VERSION:-6.6.51}" KERNEL_MAJOR="${KERNEL_VERSION%%.*}" KERNEL_URL="https://cdn.kernel.org/pub/linux/kernel/v${KERNEL_MAJOR}.x/linux-${KERNEL_VERSION}.tar.xz" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color log() { echo -e "${GREEN}[+]${NC} $*"; } warn() { echo -e "${YELLOW}[!]${NC} $*"; } error() { echo -e "${RED}[✗]${NC} $*"; exit 1; } check_dependencies() { log "Checking build dependencies..." local deps=(gcc make flex bison bc perl) local missing=() for dep in "${deps[@]}"; do if ! command -v "$dep" &>/dev/null; then missing+=("$dep") fi done if [[ ${#missing[@]} -gt 0 ]]; then error "Missing dependencies: ${missing[*]}" fi # Check for headers if [[ ! -f /usr/include/libelf.h ]] && [[ ! -f /usr/include/elfutils/libelf.h ]]; then warn "libelf-dev might be missing (needed for BTF)" fi } download_kernel() { log "Downloading Linux kernel ${KERNEL_VERSION}..." mkdir -p "$BUILD_DIR" cd "$BUILD_DIR" if [[ -d "linux-${KERNEL_VERSION}" ]]; then log "Kernel source already exists, skipping download" return fi local tarball="linux-${KERNEL_VERSION}.tar.xz" if [[ ! -f "$tarball" ]]; then curl -L -o "$tarball" "$KERNEL_URL" fi log "Extracting kernel source..." tar xf "$tarball" } create_config() { log "Creating minimal microVM kernel config..." cd "${BUILD_DIR}/linux-${KERNEL_VERSION}" # Start with a minimal config make allnoconfig # Apply microVM-specific options cat >> .config << 'EOF' # Basic system CONFIG_64BIT=y CONFIG_SMP=y CONFIG_NR_CPUS=128 CONFIG_PREEMPT_VOLUNTARY=y CONFIG_HIGH_RES_TIMERS=y CONFIG_NO_HZ_IDLE=y CONFIG_HZ_100=y # PVH boot support (direct kernel boot) CONFIG_PVH=y CONFIG_XEN_PVH=y # KVM guest support CONFIG_HYPERVISOR_GUEST=y CONFIG_PARAVIRT=y CONFIG_KVM_GUEST=y CONFIG_PARAVIRT_CLOCK=y CONFIG_PARAVIRT_SPINLOCKS=y # Memory CONFIG_MEMORY_HOTPLUG=y CONFIG_MEMORY_BALLOON=y CONFIG_VIRTIO_BALLOON=y CONFIG_BALLOON_COMPACTION=y # Block devices CONFIG_BLOCK=y CONFIG_BLK_DEV=y CONFIG_VIRTIO_BLK=y # Networking CONFIG_NET=y CONFIG_PACKET=y CONFIG_INET=y CONFIG_VIRTIO_NET=y CONFIG_VHOST_NET=y # VirtIO core CONFIG_VIRTIO=y CONFIG_VIRTIO_MMIO=y CONFIG_VIRTIO_PCI=y CONFIG_VIRTIO_PCI_LEGACY=n CONFIG_VIRTIO_CONSOLE=y # Filesystems CONFIG_EXT4_FS=y CONFIG_PROC_FS=y CONFIG_SYSFS=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_TMPFS=y CONFIG_SQUASHFS=y CONFIG_SQUASHFS_ZSTD=y # TTY/Serial (for console) CONFIG_TTY=y CONFIG_VT=n CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=4 CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # Minimal character devices CONFIG_UNIX98_PTYS=y CONFIG_DEVMEM=y # Init CONFIG_BINFMT_ELF=y CONFIG_BINFMT_SCRIPT=y # Crypto (minimal for boot) CONFIG_CRYPTO=y CONFIG_CRYPTO_CRC32C_INTEL=y # Disable unnecessary features CONFIG_MODULES=n CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_DEBUG_INFO=n CONFIG_KALLSYMS=n CONFIG_FTRACE=n CONFIG_PROFILING=n CONFIG_DEBUG_KERNEL=n # 9P for host filesystem sharing CONFIG_NET_9P=y CONFIG_NET_9P_VIRTIO=y CONFIG_9P_FS=y # Compression support for initrd CONFIG_RD_GZIP=y CONFIG_RD_ZSTD=y # Disable legacy/unused CONFIG_USB_SUPPORT=n CONFIG_SOUND=n CONFIG_INPUT=n CONFIG_SERIO=n CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_VIRTIO=y CONFIG_DRM=n CONFIG_FB=n CONFIG_AGP=n CONFIG_ACPI=n CONFIG_PNP=n CONFIG_WIRELESS=n CONFIG_WLAN=n CONFIG_RFKILL=n CONFIG_BLUETOOTH=n CONFIG_I2C=n CONFIG_SPI=n CONFIG_HWMON=n CONFIG_THERMAL=n CONFIG_WATCHDOG=n CONFIG_MD=n CONFIG_BT=n CONFIG_NFS_FS=n CONFIG_CIFS=n CONFIG_SECURITY=n CONFIG_AUDIT=n EOF # Resolve any conflicts make olddefconfig } build_kernel() { log "Building kernel (this may take 5-15 minutes)..." cd "${BUILD_DIR}/linux-${KERNEL_VERSION}" # Parallel build using all cores local jobs jobs=$(nproc) make -j"$jobs" vmlinux # Copy output mkdir -p "$OUTPUT_DIR" cp vmlinux "${OUTPUT_DIR}/vmlinux" # Create a symlink to the versioned kernel ln -sf vmlinux "${OUTPUT_DIR}/vmlinux-${KERNEL_VERSION}" } show_stats() { local kernel="${OUTPUT_DIR}/vmlinux" if [[ -f "$kernel" ]]; then log "Kernel built successfully!" echo "" echo " Path: $kernel" echo " Size: $(du -h "$kernel" | cut -f1)" echo " Kernel version: ${KERNEL_VERSION}" echo "" echo "To use with Volt:" echo " volt-vmm --kernel ${kernel} --rootfs ..." else error "Kernel build failed - vmlinux not found" fi } # Main main() { log "Building Volt microVM kernel v${KERNEL_VERSION}" echo "" check_dependencies download_kernel create_config build_kernel show_stats } main "$@"