FUCK
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
# Linux 6.6 LTS for UTSM Dual-Kernel Architecture
|
||||
|
||||
## Overview
|
||||
|
||||
This directory contains the Linux 6.6 LTS configuration and build scripts for the
|
||||
UTSM + Linux dual-kernel architecture. Linux runs as a VMX non-root guest under
|
||||
the UTSM hypervisor (VMX root).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **WSL** (Windows Subsystem for Linux) with Ubuntu 22.04+ installed
|
||||
```powersShell
|
||||
wsl --install -d Ubuntu-22.04
|
||||
```
|
||||
- Build dependencies (inside WSL):
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install -y build-essential bc flex bison libelf-dev libssl-dev cpio gzip git
|
||||
```
|
||||
- ~3GB free disk space
|
||||
|
||||
## Building Linux
|
||||
|
||||
### 1. From WSL
|
||||
|
||||
```bash
|
||||
# Navigate to the project (adjust path for your WSL mount)
|
||||
cd /mnt/d/Code/Deshab/CODE/linux
|
||||
|
||||
# Make the build script executable
|
||||
chmod +x build.sh
|
||||
|
||||
# Run the build (clones Linux 6.6 LTS, configures, builds)
|
||||
./build.sh
|
||||
```
|
||||
|
||||
The build will:
|
||||
1. Clone Linux 6.6 LTS source to `CODE/linux/src/`
|
||||
2. Apply UTSM patches from `CODE/linux/patches/` (if any)
|
||||
3. Configure with `configs/utsm_x86_64_defconfig`
|
||||
4. Build `bzImage`
|
||||
5. Copy to `SYSTEM/boot/linux-bzImage`
|
||||
6. Build initramfs if `CODE/linux/initramfs/` exists
|
||||
|
||||
### 2. Enable in Limine
|
||||
|
||||
After building, uncomment the Linux module entries in `SYSTEM/limine/limine.conf`:
|
||||
|
||||
```
|
||||
module_path: boot():/boot/linux-bzImage
|
||||
module_cmdline: linux:bzImage
|
||||
module_path: boot():/boot/linux-initrd.img
|
||||
module_cmdline: linux:initrd
|
||||
```
|
||||
|
||||
### 3. Rebuild the disk image
|
||||
|
||||
```PowerShell
|
||||
cd d:\Code\Deshab
|
||||
.\build.bat
|
||||
```
|
||||
|
||||
### 4. Test with QEMU
|
||||
|
||||
**Note:** VMX requires hardware virtualization support. QEMU's TCG (software
|
||||
emulation) does NOT support VMX instructions. To test the VMX path:
|
||||
|
||||
- **Real hardware**: Boot on an Intel machine with VT-x enabled in BIOS
|
||||
- **QEMU with WHPX**: `qemu-system-x86_64 -accel whpx -cpu max` (may not expose
|
||||
nested VMX to the guest)
|
||||
- **QEMU with KVM** (Linux host only): `qemu-system-x86_64 -enable-kvm -cpu host`
|
||||
|
||||
Without VMX, UTSM gracefully falls back to the normal DSK boot flow.
|
||||
|
||||
## Configuration Details
|
||||
|
||||
The `utsm_x86_64_defconfig` enables:
|
||||
- 64-bit kernel with SMP support
|
||||
- Serial console (8250/16550 at 0x3F8, 115200 baud)
|
||||
- virtio: console, block, net, fs (for UTSM host backends)
|
||||
- ext4, FAT, tmpfs, proc, sysfs filesystems
|
||||
- No module loading (all drivers built-in for Phase 1)
|
||||
- No EFI stub (UTSM uses custom VMX boot protocol)
|
||||
- Debug info and printk timestamps
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
CODE/linux/
|
||||
├── configs/
|
||||
│ └── utsm_x86_64_defconfig # Kernel configuration
|
||||
├── patches/ # UTSM-specific kernel patches
|
||||
│ ├── utsm-hcall.patch # /dev/utsm hypercall driver (Phase 1.3)
|
||||
│ ├── utsm-ipc.patch # Shared memory IPC driver (Phase 1.3)
|
||||
│ └── utsm-virtio.patch # virtio enhancements (Phase 1.4+)
|
||||
├── initramfs/ # Minimal initramfs contents (optional)
|
||||
├── build.sh # Build script (run in WSL/Linux)
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## Boot Flow
|
||||
|
||||
```
|
||||
Limine (UEFI)
|
||||
→ utsm.elf (VMX root)
|
||||
→ vmm_init() + vmm_self_test()
|
||||
→ linux_loader_init() (parse bzImage, set up boot_params, EPT)
|
||||
→ linux_launch() (VMCS config + vmlaunch)
|
||||
→ Linux 6.6 startup_64 (VMX non-root)
|
||||
→ Serial console output
|
||||
→ virtio-console ↔ UTSM
|
||||
→ virtio-fs mount /utsm
|
||||
→ User space (init/shell)
|
||||
```
|
||||
@@ -0,0 +1,134 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Build Linux 6.6 LTS bzImage for UTSM dual-kernel guest.
|
||||
#
|
||||
# Prerequisites:
|
||||
# - Linux build environment (WSL, native Linux, or Docker)
|
||||
# - gcc, make, bc, flex, bison, libelf-dev, libssl-dev
|
||||
# - ~3GB free disk space
|
||||
#
|
||||
# Usage:
|
||||
# cd CODE/linux
|
||||
# ./build.sh
|
||||
#
|
||||
# Output:
|
||||
# - SYSTEM/boot/linux-bzImage (kernel image)
|
||||
# - SYSTEM/boot/linux-initrd.img (minimal initramfs, if initramfs/ exists)
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
LINUX_SRC="${LINUX_SRC:-$SCRIPT_DIR/src}"
|
||||
OUTPUT_DIR="$PROJECT_ROOT/SYSTEM/boot"
|
||||
CONFIG_FILE="$SCRIPT_DIR/configs/utsm_x86_64_defconfig"
|
||||
INITRAMFS_DIR="$SCRIPT_DIR/initramfs"
|
||||
|
||||
echo "[build] Linux kernel build for UTSM"
|
||||
echo "[build] Project root: $PROJECT_ROOT"
|
||||
echo "[build] Linux source: $LINUX_SRC"
|
||||
|
||||
# 1. Clone Linux 6.6 LTS if not present
|
||||
if [ ! -d "$LINUX_SRC" ]; then
|
||||
echo "[build] Cloning Linux 6.6 LTS..."
|
||||
git clone --depth 1 --branch v6.6 \
|
||||
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git \
|
||||
"$LINUX_SRC"
|
||||
fi
|
||||
|
||||
cd "$LINUX_SRC"
|
||||
|
||||
# 2. Apply UTSM patches if any
|
||||
PATCH_DIR="$SCRIPT_DIR/patches"
|
||||
if [ -d "$PATCH_DIR" ] && [ "$(ls -A $PATCH_DIR 2>/dev/null)" ]; then
|
||||
echo "[build] Applying UTSM patches..."
|
||||
|
||||
# 2a. Apply .patch files (if any)
|
||||
for patch in "$PATCH_DIR"/*.patch; do
|
||||
if [ -f "$patch" ]; then
|
||||
echo "[build] applying $(basename $patch)"
|
||||
git apply --check "$patch" 2>/dev/null && git apply "$patch" || \
|
||||
echo "[build] WARNING: $patch already applied or failed"
|
||||
fi
|
||||
done
|
||||
|
||||
# 2b. Install UTSM driver source files into drivers/utsm/
|
||||
UTSM_DRV_DIR="$LINUX_SRC/drivers/utsm"
|
||||
echo "[build] installing UTSM driver into drivers/utsm/"
|
||||
mkdir -p "$UTSM_DRV_DIR/include"
|
||||
|
||||
# Copy driver source, Kconfig, and Makefile
|
||||
cp "$PATCH_DIR/utsm_hcall.c" "$UTSM_DRV_DIR/utsm_hcall.c"
|
||||
cp "$PATCH_DIR/utsm_Kconfig" "$UTSM_DRV_DIR/Kconfig"
|
||||
cp "$PATCH_DIR/utsm_Makefile" "$UTSM_DRV_DIR/Makefile"
|
||||
|
||||
# Copy shared IPC protocol header (included by both UTSM and Linux)
|
||||
cp "$PROJECT_ROOT/CODE/utsm-ipc/ipc_proto.h" "$UTSM_DRV_DIR/include/ipc_proto.h"
|
||||
|
||||
# Add UTSM to drivers/Kconfig (if not already present)
|
||||
if ! grep -q "drivers/utsm/Kconfig" "$LINUX_SRC/drivers/Kconfig"; then
|
||||
echo '[build] adding source "drivers/utsm/Kconfig" to drivers/Kconfig'
|
||||
echo 'source "drivers/utsm/Kconfig"' >> "$LINUX_SRC/drivers/Kconfig"
|
||||
fi
|
||||
|
||||
# Add UTSM to drivers/Makefile (if not already present)
|
||||
if ! grep -q "CONFIG_UTSM_HCALL" "$LINUX_SRC/drivers/Makefile"; then
|
||||
echo '[build] adding obj-$(CONFIG_UTSM_HCALL) += utsm/ to drivers/Makefile'
|
||||
echo 'obj-$(CONFIG_UTSM_HCALL) += utsm/' >> "$LINUX_SRC/drivers/Makefile"
|
||||
fi
|
||||
|
||||
echo "[build] UTSM driver installed:"
|
||||
echo "[build] $UTSM_DRV_DIR/utsm_hcall.c"
|
||||
echo "[build] $UTSM_DRV_DIR/Kconfig"
|
||||
echo "[build] $UTSM_DRV_DIR/Makefile"
|
||||
echo "[build] $UTSM_DRV_DIR/include/ipc_proto.h"
|
||||
fi
|
||||
|
||||
# 3. Configure
|
||||
echo "[build] Configuring kernel..."
|
||||
cp "$CONFIG_FILE" .config
|
||||
make olddefconfig
|
||||
|
||||
# 4. Build bzImage
|
||||
echo "[build] Building bzImage (this may take 10-30 minutes)..."
|
||||
make -j"$(nproc)" bzImage
|
||||
|
||||
# 5. Copy bzImage to SYSTEM/boot/
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
cp arch/x86/boot/bzImage "$OUTPUT_DIR/linux-bzImage"
|
||||
echo "[build] bzImage: $OUTPUT_DIR/linux-bzImage ($(du -h $OUTPUT_DIR/linux-bzImage | cut -f1))"
|
||||
|
||||
# 6. Build initramfs if initramfs/ directory exists
|
||||
if [ -d "$INITRAMFS_DIR" ]; then
|
||||
echo "[build] Building initramfs..."
|
||||
# Create a minimal initramfs with busybox or a simple init
|
||||
INITRAMFS_TMP="$SCRIPT_DIR/initramfs.tmp"
|
||||
rm -rf "$INITRAMFS_TMP"
|
||||
mkdir -p "$INITRAMFS_TMP"
|
||||
|
||||
# Copy initramfs contents
|
||||
cp -a "$INITRAMFS_DIR"/* "$INITRAMFS_TMP"/
|
||||
|
||||
# Create init script if not present
|
||||
if [ ! -f "$INITRAMFS_TMP/init" ]; then
|
||||
cat > "$INITRAMFS_TMP/init" <<'INITEOF'
|
||||
#!/bin/sh
|
||||
mount -t proc none /proc
|
||||
mount -t sysfs none /sys
|
||||
mount -t devtmpfs none /dev
|
||||
echo "[utsm-linux] Boot complete"
|
||||
echo "[utsm-linux] Console ready on /dev/hvc0 (virtio-console)"
|
||||
exec /bin/sh
|
||||
INITEOF
|
||||
chmod +x "$INITRAMFS_TMP/init"
|
||||
fi
|
||||
|
||||
# Pack initramfs
|
||||
cd "$INITRAMFS_TMP"
|
||||
find . | cpio -H newc -o | gzip -9 > "$OUTPUT_DIR/linux-initrd.img"
|
||||
echo "[build] initrd: $OUTPUT_DIR/linux-initrd.img ($(du -h $OUTPUT_DIR/linux-initrd.img | cut -f1))"
|
||||
cd "$LINUX_SRC"
|
||||
fi
|
||||
|
||||
echo "[build] Done. Copy linux-bzImage (and linux-initrd.img) to your FAT32 image."
|
||||
echo "[build] Limine will load them as boot modules for UTSM."
|
||||
@@ -0,0 +1,231 @@
|
||||
#
|
||||
# Linux 6.6 LTS minimal config for UTSM dual-kernel guest
|
||||
#
|
||||
# Build: make utsm_x86_64_defconfig && make -j$(nproc) bzImage
|
||||
#
|
||||
# Key design choices:
|
||||
# - 64-bit only (CONFIG_64BIT=y)
|
||||
# - Serial console (8250/16550 at 0x3F8)
|
||||
# - virtio: console, block, net, fs (for UTSM host backends)
|
||||
# - EFI stub disabled (UTSM uses custom VMX boot, not EFI)
|
||||
# - Built-in drivers (no module loading needed for Phase 1)
|
||||
# - No SMP (single CPU for Phase 1 simplicity)
|
||||
# - printk to serial for debugging
|
||||
|
||||
CONFIG_64BIT=y
|
||||
CONFIG_X86_64=y
|
||||
CONFIG_X86=y
|
||||
CONFIG_INSTRUCTION_DECODER=y
|
||||
CONFIG_OUTPUT_FORMAT="elf64-x86-64"
|
||||
CONFIG_ARCH_MMAP_RND_BITS_MIN=28
|
||||
CONFIG_ARCH_MMAP_RND_BITS_MAX=32
|
||||
CONFIG_GENERIC_ISA_DMA=y
|
||||
CONFIG_GENERIC_BUG=y
|
||||
CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
|
||||
CONFIG_GENERIC_HWEIGHT=y
|
||||
CONFIG_ARCH_MMAP_RND_BITS=28
|
||||
CONFIG_SMP=y
|
||||
CONFIG_NR_CPUS=4
|
||||
CONFIG_X86_64_SMP=y
|
||||
CONFIG_SCHED_MC=y
|
||||
CONFIG_SCHED_SMT=y
|
||||
|
||||
# Processor type
|
||||
CONFIG_MK8=y
|
||||
CONFIG_X86_CPU=y
|
||||
CONFIG_X86_L1_CACHE_SHIFT=6
|
||||
CONFIG_X86_TSC=y
|
||||
CONFIG_X86_CMPXCHG64=y
|
||||
CONFIG_X86_CMOV=y
|
||||
CONFIG_X86_MINIMUM_CPU_FAMILY=64
|
||||
CONFIG_PROCESSOR_SELECT=y
|
||||
CONFIG_CPU_SUP_INTEL=y
|
||||
CONFIG_CPU_SUP_AMD=y
|
||||
CONFIG_CPU_SUP_CENTAUR=y
|
||||
CONFIG_HPET_TIMER=y
|
||||
CONFIG_HPET_EMULATE_RTC=y
|
||||
CONFIG_DMI=y
|
||||
|
||||
# Memory
|
||||
CONFIG_PHYS_ADDR_T_64BIT=y
|
||||
CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
|
||||
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
|
||||
CONFIG_DIRECT_GBPAGES=y
|
||||
CONFIG_ARCH_SPARSEMEM_ENABLE=y
|
||||
CONFIG_ARCH_SPARSEMEM_DEFAULT=y
|
||||
CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
|
||||
CONFIG_X86_PMEM_LEGACY_DEVICE=y
|
||||
CONFIG_X86_PMEM_LEGACY=y
|
||||
CONFIG_X86_CHECK_BIOS_CORRUPTION=y
|
||||
CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y
|
||||
CONFIG_X86_RESERVE_LOW=64
|
||||
CONFIG_MTRR=y
|
||||
CONFIG_MTRR_SANITIZER=y
|
||||
CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0
|
||||
CONFIG_X86_PAT=y
|
||||
CONFIG_ARCH_USES_PG_UNCACHED=y
|
||||
CONFIG_ARCH_RANDOM=y
|
||||
CONFIG_X86_SMAP=y
|
||||
CONFIG_X86_INTEL_UMIP=y
|
||||
CONFIG_X86_UMIP=y
|
||||
|
||||
# Power management (minimal)
|
||||
CONFIG_PM=y
|
||||
CONFIG_PM_CLK=y
|
||||
|
||||
# Bus options
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCI_DIRECT=y
|
||||
CONFIG_PCI_MMCONFIG=y
|
||||
CONFIG_PCI_DOMAINS=y
|
||||
CONFIG_PCI_MSI=y
|
||||
CONFIG_PCI_MSI_IRQ_DOMAIN=y
|
||||
CONFIG_PCI_LABEL=y
|
||||
CONFIG_ISA_DMA_API=y
|
||||
CONFIG_AMD_NB=y
|
||||
|
||||
#Executable file formats
|
||||
CONFIG_BINFMT_ELF=y
|
||||
CONFIG_BINFMT_SCRIPT=y
|
||||
CONFIG_BINFMT_MISC=y
|
||||
|
||||
# Networking
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
CONFIG_UNIX=y
|
||||
CONFIG_INET=y
|
||||
CONFIG_IP_MULTICAST=y
|
||||
CONFIG_IP_ADVANCED_ROUTER=y
|
||||
CONFIG_IP_PNP=y
|
||||
CONFIG_IP_PNP_DHCP=y
|
||||
CONFIG_SYN_COOKIES=y
|
||||
CONFIG_TCP_CONG_CUBIC=y
|
||||
|
||||
# Device Drivers
|
||||
# Serial console (critical: UTSM captures serial output)
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_PCI=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=4
|
||||
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
|
||||
CONFIG_SERIAL_CORE=y
|
||||
CONFIG_SERIAL_CORE_CONSOLE=y
|
||||
CONFIG_EARLY_PRINTK=y
|
||||
CONFIG_EARLY_PRINTK_SERIAL=y
|
||||
|
||||
# PCI host bridge
|
||||
CONFIG_PCI_HOST_GENERIC=y
|
||||
|
||||
# virtio (critical: UTSM provides virtio backends)
|
||||
CONFIG_VIRTIO=y
|
||||
CONFIG_VIRTIO_PCI=y
|
||||
CONFIG_VIRTIO_PCI_LEGACY=y
|
||||
CONFIG_VIRTIO_BALLOON=y
|
||||
CONFIG_VIRTIO_INPUT=y
|
||||
CONFIG_VIRTIO_MMIO=y
|
||||
CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
|
||||
|
||||
# virtio console (Phase 1.4: UTSM↔Linux console)
|
||||
CONFIG_VIRTIO_CONSOLE=y
|
||||
CONFIG_HW_RANDOM=y
|
||||
CONFIG_HW_RANDOM_VIRTIO=y
|
||||
|
||||
# UTSM dual-kernel hypercall and IPC driver (Phase 1.3)
|
||||
CONFIG_UTSM_HCALL=y
|
||||
|
||||
# virtio block (Phase 2: block device)
|
||||
CONFIG_VIRTIO_BLK=y
|
||||
CONFIG_VIRTIO_BLK_SCSI=y
|
||||
|
||||
# virtio net (Phase 2: network)
|
||||
CONFIG_VIRTIO_NET=y
|
||||
|
||||
# virtio-fs (Phase 1.5: shared filesystem)
|
||||
CONFIG_VIRTIO_FS=y
|
||||
CONFIG_FUSE_FS=y
|
||||
|
||||
# Filesystems
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_EXT4_USE_FOR_EXT2=y
|
||||
CONFIG_FAT_FS=y
|
||||
CONFIG_VFAT_FS=y
|
||||
CONFIG_FAT_DEFAULT_CODEPAGE=437
|
||||
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
|
||||
CONFIG_TMPFS=y
|
||||
CONFIG_PROC_FS=y
|
||||
CONFIG_PROC_SYSCTL=y
|
||||
CONFIG_SYSFS=y
|
||||
CONFIG_DEVTMPFS=y
|
||||
CONFIG_DEVTMPFS_MOUNT=y
|
||||
|
||||
# Block devices
|
||||
CONFIG_BLK_DEV=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
|
||||
# Input (minimal)
|
||||
CONFIG_INPUT=y
|
||||
CONFIG_INPUT_KEYBOARD=y
|
||||
|
||||
# RTC
|
||||
CONFIG_RTC_LIB=y
|
||||
CONFIG_RTC_CLASS=y
|
||||
CONFIG_RTC_HCTOSYS=y
|
||||
CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
|
||||
|
||||
# PNP/ACPI (minimal for QEMU)
|
||||
CONFIG_ACPI=y
|
||||
CONFIG_ACPI_AC=y
|
||||
CONFIG_ACPI_BUTTON=y
|
||||
CONFIG_ACPI_FAN=y
|
||||
CONFIG_ACPI_PROCESSOR=y
|
||||
CONFIG_ACPI_THERMAL=y
|
||||
|
||||
# File systems
|
||||
CONFIG_FHANDLE=y
|
||||
|
||||
# Kernel hacking
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_PRINTK_TIME=y
|
||||
CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7
|
||||
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_FRAME_WARN=2048
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
CONFIG_DEBUG_RODATA=y
|
||||
CONFIG_DEBUG_SET_MODULE_RONX=y
|
||||
CONFIG_DEBUG_WX=y
|
||||
|
||||
# Security (minimal)
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITYFS=y
|
||||
|
||||
# Crypto (minimal)
|
||||
CONFIG_CRYPTO=y
|
||||
CONFIG_CRYPTO_CRC32C=y
|
||||
CONFIG_CRYPTO_SHA256=y
|
||||
|
||||
# Library routines
|
||||
CONFIG_CRC16=y
|
||||
CONFIG_CRC32=y
|
||||
CONFIG_ZLIB_INFLATE=y
|
||||
CONFIG_ZLIB_DEFLATE=y
|
||||
CONFIG_LZO_COMPRESS=y
|
||||
CONFIG_LZO_DECOMPRESS=y
|
||||
CONFIG_XZ_DEC=y
|
||||
CONFIG_XZ_DEC_X86=y
|
||||
|
||||
# Initramfs
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_INITRAMFS_SOURCE=""
|
||||
|
||||
# No module support (build everything in for Phase 1)
|
||||
# CONFIG_MODULES is not set
|
||||
|
||||
# No EFI stub (UTSM uses custom VMX boot)
|
||||
# CONFIG_EFI_STUB is not set
|
||||
# CONFIG_EFI is not set
|
||||
|
||||
# Boot protocol
|
||||
CONFIG_EARLY_PRINTK_SERIAL=y
|
||||
@@ -0,0 +1,33 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# UTSM dual-kernel hypercall driver configuration
|
||||
#
|
||||
|
||||
config UTSM_HCALL
|
||||
tristate "UTSM dual-kernel hypercall and IPC driver"
|
||||
default y
|
||||
help
|
||||
This driver enables communication between the Linux guest and
|
||||
the UTSM monitor kernel in the Deshab dual-kernel architecture.
|
||||
|
||||
When loaded, it:
|
||||
- Probes for the UTSM monitor via a VMCALL PING hypercall
|
||||
- Maps the IPC shared memory ring buffer
|
||||
- Registers /dev/utsm for userspace IPC message passing
|
||||
|
||||
If running on bare metal or a non-UTSM hypervisor, the driver
|
||||
loads in passive mode (no /dev/utsm registered).
|
||||
|
||||
If unsure, say Y for UTSM guest builds, N otherwise.
|
||||
|
||||
config UTSM_EARLY_CONSOLE
|
||||
bool "Redirect kernel printk to UTSM serial console"
|
||||
depends on UTSM_HCALL
|
||||
default n
|
||||
help
|
||||
Redirects Linux kernel console output to the UTSM monitor's
|
||||
serial port via UTSM_HCALL_CONSOLE_WRITE hypercalls. Useful
|
||||
for early boot debugging when the guest's own serial is not
|
||||
configured.
|
||||
|
||||
If unsure, say N.
|
||||
@@ -0,0 +1,10 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# UTSM dual-kernel driver Makefile
|
||||
#
|
||||
|
||||
obj-$(CONFIG_UTSM_HCALL) += utsm_hcall.o
|
||||
|
||||
# Include the shared IPC protocol header from CODE/utsm-ipc/
|
||||
# This path is set up by build.sh when copying files into the source tree
|
||||
ccflags-y += -I$(src)/include
|
||||
@@ -0,0 +1,369 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* UTSM hypercall driver — Linux guest side.
|
||||
*
|
||||
* Provides:
|
||||
* 1. VMCALL hypercall interface to communicate with the UTSM monitor kernel
|
||||
* 2. /dev/utsm character device for userspace IPC message passing
|
||||
* 3. Shared memory ring buffer mapping (queried via UTSM_HCALL_SHM_INFO)
|
||||
*
|
||||
* The driver is platform-agnostic: it probes for UTSM by issuing a PING
|
||||
* hypercall at init. If UTSM is not present (e.g. running on bare metal
|
||||
* or a different hypervisor), the driver exits gracefully.
|
||||
*
|
||||
* Build: configured via CONFIG_UTSM_HCALL (built-in or module).
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
/* Shared IPC protocol header (included via build.sh -I flag) */
|
||||
#include <ipc_proto.h>
|
||||
|
||||
#define UTSM_DEV_NAME "utsm"
|
||||
|
||||
/* ===== Hypercall ABI =====
|
||||
*
|
||||
* Linux calls VMCALL with:
|
||||
* RAX = UTSM_HCALL_MAGIC | op
|
||||
* RDI = arg0, RSI = arg1, RDX = arg2
|
||||
*
|
||||
* UTSM handles the VMCALL VM-Exit and returns:
|
||||
* RAX = return value
|
||||
*
|
||||
* Since we run in the guest, the VMCALL instruction triggers a VM-Exit
|
||||
* to UTSM. The inline assembly must use the same register conventions.
|
||||
*/
|
||||
|
||||
static inline long utsm_hcall(u64 op, u64 a0, u64 a1, u64 a2)
|
||||
{
|
||||
long ret;
|
||||
register u64 rax asm("rax") = UTSM_HCALL_MAGIC | op;
|
||||
register u64 rdi asm("rdi") = a0;
|
||||
register u64 rsi asm("rsi") = a1;
|
||||
register u64 rdx asm("rdx") = a2;
|
||||
|
||||
asm volatile("vmcall"
|
||||
: "+r"(rax)
|
||||
: "r"(rdi), "r"(rsi), "r"(rdx)
|
||||
: "memory");
|
||||
|
||||
return (long)rax;
|
||||
}
|
||||
|
||||
static inline long utsm_hcall_ping(void)
|
||||
{
|
||||
return utsm_hcall(UTSM_HCALL_PING, 0, 0, 0);
|
||||
}
|
||||
|
||||
static inline long utsm_hcall_hello(void)
|
||||
{
|
||||
return utsm_hcall(UTSM_HCALL_HELLO, 0, 0, 0);
|
||||
}
|
||||
|
||||
static inline long utsm_hcall_shm_info(u64 *gpa_out, u64 *size_out)
|
||||
{
|
||||
u64 gpa = 0, size = 0;
|
||||
long ret;
|
||||
|
||||
/* Pass stack addresses (GVA=GPA due to identity mapping in early boot).
|
||||
* UTSM translates GPA→HPA via EPT walk and writes the values there. */
|
||||
ret = utsm_hcall(UTSM_HCALL_SHM_INFO, (u64)&gpa, (u64)&size, 0);
|
||||
if (ret == 0) {
|
||||
*gpa_out = gpa;
|
||||
*size_out = size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline long utsm_hcall_console_write(const char *buf, u64 len)
|
||||
{
|
||||
return utsm_hcall(UTSM_HCALL_CONSOLE_WRITE, (u64)buf, len, 0);
|
||||
}
|
||||
|
||||
/* ===== Shared memory state ===== */
|
||||
|
||||
static struct utsm_ipc_shm *g_shm; /* kernel virtual address of SHM */
|
||||
static u64 g_shm_gpa; /* guest physical address of SHM */
|
||||
static u64 g_shm_size; /* size of SHM region */
|
||||
static int g_utsm_present; /* 1 = UTSM detected */
|
||||
static int g_shm_mapped;
|
||||
|
||||
/* ===== /dev/utsm character device ===== */
|
||||
|
||||
static ssize_t utsm_dev_write(struct file *f, const char __user *buf,
|
||||
size_t len, loff_t *off)
|
||||
{
|
||||
struct utsm_ipc_msg msg;
|
||||
size_t copy_len;
|
||||
ssize_t ret;
|
||||
|
||||
if (!g_shm_mapped)
|
||||
return -ENODEV;
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
/* Cap data to inline message size */
|
||||
copy_len = min_t(size_t, len, UTSM_IPC_MSG_DATA_SIZE);
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.type = UTSM_MSG_DATA;
|
||||
msg.data_len = (u32)copy_len;
|
||||
|
||||
if (copy_from_user(msg.data, buf, copy_len)) {
|
||||
pr_err("[utsm] copy_from_user failed\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Enqueue into linux_to_utsm ring (Linux produces, UTSM consumes) */
|
||||
if (utsm_ipc_ring_push(&g_shm->linux_to_utsm, &msg) != 0) {
|
||||
pr_warn("[utsm] linux_to_utsm ring full\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
ret = (ssize_t)copy_len;
|
||||
|
||||
/* Also relay the data to the UTSM serial console via hypercall.
|
||||
* This gives immediate visibility into Linux userspace output. */
|
||||
if (copy_len > 0) {
|
||||
char kbuf[UTSM_IPC_MSG_DATA_SIZE + 1];
|
||||
memcpy(kbuf, msg.data, copy_len);
|
||||
kbuf[copy_len] = '\0';
|
||||
utsm_hcall_console_write(kbuf, copy_len);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t utsm_dev_read(struct file *f, char __user *buf,
|
||||
size_t len, loff_t *off)
|
||||
{
|
||||
struct utsm_ipc_msg msg;
|
||||
|
||||
if (!g_shm_mapped)
|
||||
return -ENODEV;
|
||||
|
||||
/* Dequeue from utsm_to_linux ring (UTSM produces, Linux consumes) */
|
||||
if (utsm_ipc_ring_pop(&g_shm->utsm_to_linux, &msg) != 0) {
|
||||
/* No message available */
|
||||
return -EAGAIN; /* Non-blocking; userspace can poll */
|
||||
}
|
||||
|
||||
if (msg.data_len == 0)
|
||||
return 0;
|
||||
|
||||
if (len < msg.data_len)
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_to_user(buf, msg.data, msg.data_len))
|
||||
return -EFAULT;
|
||||
|
||||
return (ssize_t)msg.data_len;
|
||||
}
|
||||
|
||||
static const struct file_operations utsm_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.write = utsm_dev_write,
|
||||
.read = utsm_dev_read,
|
||||
};
|
||||
|
||||
static struct miscdevice utsm_miscdev = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = UTSM_DEV_NAME,
|
||||
.fops = &utsm_fops,
|
||||
.mode = 0666,
|
||||
};
|
||||
|
||||
/* ===== Early console redirect (optional) =====
|
||||
*
|
||||
* Redirect kernel printk output to UTSM serial console via hypercall.
|
||||
* This is useful for debugging when the guest's own serial is not set up.
|
||||
* Currently disabled; can be enabled via CONFIG_UTSM_EARLY_CONSOLE.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_UTSM_EARLY_CONSOLE
|
||||
static void utsm_console_write(struct console *con, const char *s, unsigned int n)
|
||||
{
|
||||
if (g_utsm_present) {
|
||||
char buf[256];
|
||||
unsigned int chunk;
|
||||
|
||||
while (n > 0) {
|
||||
chunk = min_t(unsigned int, n, sizeof(buf) - 1);
|
||||
memcpy(buf, s, chunk);
|
||||
buf[chunk] = '\0';
|
||||
utsm_hcall_console_write(buf, chunk);
|
||||
s += chunk;
|
||||
n -= chunk;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct console utsm_console = {
|
||||
.name = "utsmcon",
|
||||
.write = utsm_console_write,
|
||||
.flags = CON_PRINTBUFFER | CON_ENABLED,
|
||||
.index = -1,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* ===== Initialization ===== */
|
||||
|
||||
/* Forward declaration: used by init before /dev/utsm is registered */
|
||||
static inline int ipc_shm_send_to_utsm(u32 type, const void *data, u32 len);
|
||||
|
||||
static int __init utsm_hcall_init(void)
|
||||
{
|
||||
long ping_ret;
|
||||
u64 shm_gpa = 0, shm_size = 0;
|
||||
int ret;
|
||||
|
||||
pr_info("[utsm] probing for UTSM monitor...\n");
|
||||
|
||||
/* 1. Ping UTSM to verify it's present */
|
||||
ping_ret = utsm_hcall_ping();
|
||||
if (ping_ret != 0x504F4E47) { /* "PONG" */
|
||||
pr_info("[utsm] UTSM not detected (ping returned 0x%lx)\n", ping_ret);
|
||||
pr_info("[utsm] Driver loaded in passive mode (no /dev/utsm)\n");
|
||||
return 0; /* Not an error: we might be running on bare metal */
|
||||
}
|
||||
|
||||
g_utsm_present = 1;
|
||||
pr_info("[utsm] UTSM monitor detected (PONG=0x%lx)\n", ping_ret);
|
||||
|
||||
/* 2. Say hello */
|
||||
utsm_hcall_hello();
|
||||
|
||||
/* 3. Query shared memory info */
|
||||
ret = utsm_hcall_shm_info(&shm_gpa, &shm_size);
|
||||
if (ret != 0) {
|
||||
pr_err("[utsm] SHM_INFO hypercall failed: %ld\n", ret);
|
||||
goto err_no_shm;
|
||||
}
|
||||
|
||||
pr_info("[utsm] shared memory: gpa=0x%llx size=%llu KB\n",
|
||||
shm_gpa, shm_size / 1024);
|
||||
|
||||
if (shm_gpa == 0 || shm_size == 0) {
|
||||
pr_err("[utsm] invalid SHM info\n");
|
||||
goto err_no_shm;
|
||||
}
|
||||
|
||||
/* 4. Map the shared memory region.
|
||||
* The GPA is a physical address from Linux's perspective.
|
||||
* Use ioremap_cache for cacheable memory (the SHM region is
|
||||
* configured as WB in EPT). */
|
||||
g_shm = (struct utsm_ipc_shm *)ioremap_cache(shm_gpa, shm_size);
|
||||
if (!g_shm) {
|
||||
pr_err("[utsm] failed to ioremap SHM at 0x%llx\n", shm_gpa);
|
||||
goto err_ioremap;
|
||||
}
|
||||
|
||||
g_shm_gpa = shm_gpa;
|
||||
g_shm_size = shm_size;
|
||||
g_shm_mapped = 1;
|
||||
|
||||
/* 5. Verify SHM header */
|
||||
if (g_shm->header.magic != UTSM_IPC_MAGIC) {
|
||||
pr_err("[utsm] SHM magic mismatch: 0x%llx\n", g_shm->header.magic);
|
||||
goto err_bad_magic;
|
||||
}
|
||||
|
||||
pr_info("[utsm] SHM header: magic=OK version=%u utsm_ready=%u\n",
|
||||
g_shm->header.version, g_shm->header.utsm_ready);
|
||||
|
||||
/* 6. Set linux_ready flag */
|
||||
g_shm->header.linux_ready = 1;
|
||||
mb(); /* Ensure visible to UTSM */
|
||||
|
||||
/* 7. Register /dev/utsm */
|
||||
ret = misc_register(&utsm_miscdev);
|
||||
if (ret) {
|
||||
pr_err("[utsm] misc_register failed: %d\n", ret);
|
||||
goto err_misc;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UTSM_EARLY_CONSOLE
|
||||
register_console(&utsm_console);
|
||||
#endif
|
||||
|
||||
pr_info("[utsm] /dev/%s registered (IPC ready)\n", UTSM_DEV_NAME);
|
||||
|
||||
/* 8. Send a HELLO message via the ring buffer */
|
||||
{
|
||||
const char *hello_msg = "Linux booted OK";
|
||||
ipc_shm_send_to_utsm(UTSM_MSG_DATA, hello_msg, 15);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_misc:
|
||||
g_shm->header.linux_ready = 0;
|
||||
err_bad_magic:
|
||||
iounmap(g_shm);
|
||||
g_shm = NULL;
|
||||
g_shm_mapped = 0;
|
||||
err_ioremap:
|
||||
err_no_shm:
|
||||
g_utsm_present = 0;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Helper to send a message (used by init before /dev/utsm is available) */
|
||||
static inline int ipc_shm_send_to_utsm(u32 type, const void *data, u32 len)
|
||||
{
|
||||
struct utsm_ipc_msg msg;
|
||||
|
||||
if (!g_shm_mapped || !g_shm)
|
||||
return -1;
|
||||
|
||||
if (len > UTSM_IPC_MSG_DATA_SIZE)
|
||||
len = UTSM_IPC_MSG_DATA_SIZE;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.type = type;
|
||||
msg.data_len = len;
|
||||
if (data && len > 0)
|
||||
memcpy(msg.data, data, len);
|
||||
|
||||
return utsm_ipc_ring_push(&g_shm->linux_to_utsm, &msg);
|
||||
}
|
||||
|
||||
static void __exit utsm_hcall_exit(void)
|
||||
{
|
||||
if (g_shm_mapped) {
|
||||
/* Clear linux_ready flag */
|
||||
g_shm->header.linux_ready = 0;
|
||||
mb();
|
||||
|
||||
/* Send shutdown notification */
|
||||
ipc_shm_send_to_utsm(UTSM_MSG_SHUTDOWN, NULL, 0);
|
||||
|
||||
misc_deregister(&utsm_miscdev);
|
||||
|
||||
#ifdef CONFIG_UTSM_EARLY_CONSOLE
|
||||
unregister_console(&utsm_console);
|
||||
#endif
|
||||
|
||||
iounmap(g_shm);
|
||||
g_shm = NULL;
|
||||
g_shm_mapped = 0;
|
||||
}
|
||||
|
||||
pr_info("[utsm] driver unloaded\n");
|
||||
}
|
||||
|
||||
module_init(utsm_hcall_init);
|
||||
module_exit(utsm_hcall_exit);
|
||||
|
||||
MODULE_AUTHOR("Deshab Project");
|
||||
MODULE_DESCRIPTION("UTSM dual-kernel hypercall and IPC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
Reference in New Issue
Block a user