PROJECT := ariel TARGET := aarch64-none-elf BUILD := build HV_ELF := $(BUILD)/hypervisor.elf HV_BIN := $(BUILD)/hypervisor.bin GUEST_ELF := $(BUILD)/guest/diag.elf GUEST_BIN := $(BUILD)/guest/diag.bin MAP := $(BUILD)/hypervisor.map OBJDUMP := $(BUILD)/hypervisor.objdump READELF := $(BUILD)/hypervisor.readelf DIST := dist RELEASE_DIR := $(DIST)/$(PROJECT)-qemu-virt-aarch64 RELEASE_TAR := $(DIST)/$(PROJECT)-qemu-virt-aarch64.tar.gz CC := clang LD := ld.lld OBJCOPY := llvm-objcopy OBJDUMP_TOOL := llvm-objdump READELF_TOOL := llvm-readelf PYTHON ?= python3 QEMU ?= qemu-system-aarch64 QEMU_RAM ?= 1G comma := , LINUX_DIR ?= /tmp/ariel-linux LINUX_IMAGE_URL ?= http://deb.debian.org/debian/dists/bookworm/main/installer-arm64/current/images/netboot/debian-installer/arm64/linux LINUX_INITRD_URL ?= http://deb.debian.org/debian/dists/bookworm/main/installer-arm64/current/images/netboot/debian-installer/arm64/initrd.gz LINUX_INITRD_BYTES := $(if $(LINUX_INITRD),$(shell stat -c %s "$(LINUX_INITRD)" 2>/dev/null),) LINUX_INITRD_SIZE := $(if $(LINUX_INITRD),$(if $(LINUX_INITRD_BYTES),$(LINUX_INITRD_BYTES),0),0) LINUX_INITRD_DEVICE := $(if $(LINUX_INITRD),-device loader$(comma)file=$(LINUX_INITRD)$(comma)addr=0x46000000$(comma)force-raw=on,) COMMON_CFLAGS := --target=$(TARGET) -std=c11 -ffreestanding -fno-builtin \ -fno-stack-protector -fno-unwind-tables -fno-asynchronous-unwind-tables \ -fno-exceptions -mgeneral-regs-only -mstrict-align -Wall -Wextra -Werror \ -Wconversion -Wsign-conversion -Wmissing-prototypes -Wstrict-prototypes \ -Iinclude -I. EXTRA_CFLAGS ?= HV_CFLAGS := $(COMMON_CFLAGS) -O2 -g -D__HYPERVISOR__ $(EXTRA_CFLAGS) GUEST_CFLAGS := $(COMMON_CFLAGS) -O2 -g -D__GUEST__ ASFLAGS := --target=$(TARGET) -g -Iinclude -I. LDFLAGS := -nostdlib -static --fatal-warnings HV_C_SRCS := \ arch/aarch64/arch.c \ core/main.c core/el2_mmu.c core/fdt.c core/guest_loader.c core/image.c core/log.c core/mmio_policy.c core/panic.c core/policy.c core/psci.c core/selftest.c \ core/string.c core/sysreg.c core/trap.c core/vcpu.c core/monitor.c \ drivers/gicv3.c drivers/pl011.c drivers/timer.c \ mm/allocator.c mm/stage2.c HV_S_SRCS := arch/aarch64/entry.S arch/aarch64/vectors.S arch/aarch64/vcpu.S arch/aarch64/guest_blob.S GUEST_C_SRCS := guest/main.c GUEST_S_SRCS := guest/start.S HV_OBJS := $(HV_C_SRCS:%.c=$(BUILD)/%.o) $(HV_S_SRCS:%.S=$(BUILD)/%.o) GUEST_OBJS := $(GUEST_C_SRCS:%.c=$(BUILD)/%.o) $(GUEST_S_SRCS:%.S=$(BUILD)/%.o) .PHONY: all clean run run-linux linux-artifacts test-linux-smoke test-diagnostic-smoke test-host test ci release debug objdump readelf all: $(HV_ELF) $(HV_BIN) $(OBJDUMP) $(READELF) $(BUILD): mkdir -p $(BUILD) $(BUILD)/guest/%.o: guest/%.c mkdir -p $(dir $@) $(CC) $(GUEST_CFLAGS) -c $< -o $@ $(BUILD)/%.o: %.c mkdir -p $(dir $@) $(CC) $(HV_CFLAGS) -c $< -o $@ $(BUILD)/%.o: %.S mkdir -p $(dir $@) $(CC) $(ASFLAGS) -c $< -o $@ $(BUILD)/arch/aarch64/guest_blob.o: arch/aarch64/guest_blob.S $(GUEST_BIN) mkdir -p $(dir $@) $(CC) $(ASFLAGS) -c $< -o $@ $(GUEST_ELF): $(GUEST_OBJS) guest/linker.ld mkdir -p $(dir $@) $(LD) $(LDFLAGS) -T guest/linker.ld $(GUEST_OBJS) -o $@ $(GUEST_BIN): $(GUEST_ELF) $(OBJCOPY) -O binary $< $@ $(HV_ELF): $(HV_OBJS) linker.ld mkdir -p $(dir $@) $(LD) $(LDFLAGS) -T linker.ld -Map=$(MAP) $(HV_OBJS) -o $@ $(HV_BIN): $(HV_ELF) $(OBJCOPY) -O binary $< $@ $(OBJDUMP): $(HV_ELF) $(OBJDUMP_TOOL) -d -S $< > $@ $(READELF): $(HV_ELF) $(READELF_TOOL) -a $< > $@ run: $(HV_ELF) $(QEMU) -M virt,virtualization=on,gic-version=3 -cpu cortex-a57 -m $(QEMU_RAM) \ -nographic -serial mon:stdio -kernel $(HV_ELF) run-linux: @if [ -z "$(LINUX_IMAGE)" ] || [ -z "$(LINUX_DTB)" ]; then \ echo "usage: make run-linux LINUX_IMAGE=/path/Image LINUX_DTB=/path/qemu-virt.dtb [LINUX_INITRD=/path/initrd]"; \ echo "builds a Linux-profile hypervisor and loads Image+DTB into guest RAM"; \ else \ $(MAKE) -B BUILD=build-linux EXTRA_CFLAGS="-DCONFIG_BOOT_LINUX=1 -DCONFIG_LINUX_INITRD_SIZE=$(LINUX_INITRD_SIZE)ull" all && \ $(QEMU) -M virt,virtualization=on,gic-version=3 -cpu cortex-a57 -m $(QEMU_RAM) \ -nographic -serial mon:stdio -kernel build-linux/hypervisor.elf \ -device loader,file=$(LINUX_IMAGE),addr=0x42000000,force-raw=on \ -device loader,file=$(LINUX_DTB),addr=0x71e00000,force-raw=on \ $(LINUX_INITRD_DEVICE); \ fi linux-artifacts: mkdir -p $(LINUX_DIR) $(QEMU) -M virt,virtualization=on,gic-version=3,dumpdtb=$(LINUX_DIR)/virt.dtb -cpu cortex-a57 -m $(QEMU_RAM) -nographic curl -L --fail --show-error --output $(LINUX_DIR)/debian-arm64-linux $(LINUX_IMAGE_URL) curl -L --fail --show-error --output $(LINUX_DIR)/debian-arm64-initrd.gz $(LINUX_INITRD_URL) test-linux-smoke: linux-artifacts bash -o pipefail -c 'timeout 180s $(MAKE) run-linux LINUX_IMAGE=$(LINUX_DIR)/debian-arm64-linux LINUX_DTB=$(LINUX_DIR)/virt.dtb LINUX_INITRD=$(LINUX_DIR)/debian-arm64-initrd.gz 2>&1 | tee $(LINUX_DIR)/linux-smoke.log; status=$${PIPESTATUS[0]}; test $$status -eq 0 -o $$status -eq 124' grep -q 'Booting Linux on physical CPU' $(LINUX_DIR)/linux-smoke.log grep -q 'Kernel command line: console=ttyAMA0 earlycon' $(LINUX_DIR)/linux-smoke.log grep -q 'CPU: All CPU(s) started at EL1' $(LINUX_DIR)/linux-smoke.log grep -q 'Trying to unpack rootfs image as initramfs' $(LINUX_DIR)/linux-smoke.log grep -q 'Freeing initrd memory' $(LINUX_DIR)/linux-smoke.log grep -q 'Run /init as init process' $(LINUX_DIR)/linux-smoke.log ! grep -q 'Initramfs unpacking failed' $(LINUX_DIR)/linux-smoke.log ! grep -q 'Kernel panic' $(LINUX_DIR)/linux-smoke.log test-diagnostic-smoke: $(HV_ELF) bash -o pipefail -c 'printf "status\n" | timeout 14s $(MAKE) run 2>&1 | tee $(BUILD)/diagnostic-smoke.log; status=$${PIPESTATUS[1]}; test $$status -eq 0 -o $$status -eq 124' grep -q 'ariel qemu-virt-aarch64' $(BUILD)/diagnostic-smoke.log grep -q 'guest: diagnostic guest: requested hv id' $(BUILD)/diagnostic-smoke.log grep -q 'monitor entered reason=guest requested pause' $(BUILD)/diagnostic-smoke.log ! grep -q 'panic:' $(BUILD)/diagnostic-smoke.log test-host: mkdir -p build-host $(CC) -std=c11 -Wall -Wextra -Werror -Iinclude tests/host/test_hv_types.c -o build-host/test_hv_types build-host/test_hv_types $(CC) -std=c11 -Wall -Wextra -Werror -Iinclude tests/host/test_hv_interval.c -o build-host/test_hv_interval build-host/test_hv_interval $(CC) -std=c11 -Wall -Wextra -Werror -Iinclude tests/host/test_qemu_virt.c -o build-host/test_qemu_virt build-host/test_qemu_virt $(CC) -std=c11 -Wall -Wextra -Werror -Iinclude tests/host/test_hvc_abi.c -o build-host/test_hvc_abi build-host/test_hvc_abi $(CC) -std=c11 -Wall -Wextra -Werror -Iinclude tests/host/test_sysreg_key.c core/sysreg.c core/string.c -o build-host/test_sysreg_key build-host/test_sysreg_key $(PYTHON) tests/test_log_decode.py $(PYTHON) scripts/verify_topology.py $(PYTHON) scripts/check_release.py test: all test-host test-diagnostic-smoke ci: clean release release: test scripts/release.sh debug: $(HV_ELF) @echo "gdb command: gdb-multiarch $(HV_ELF) -ex 'target remote :1234'" $(QEMU) -M virt,virtualization=on,gic-version=3 -cpu cortex-a57 -m $(QEMU_RAM) \ -nographic -serial mon:stdio -S -gdb tcp::1234 -kernel $(HV_ELF) objdump: $(OBJDUMP) readelf: $(READELF) clean: rm -rf $(BUILD)