Now that all the Linux specifics have been factored out of the load
programs that fp-stress uses and we have a simple VMM we can build
versions for running with that VMM.  Provide an asm-utils-kvm.S with
startup code that's easier in the guest and implementations of the
functions that the programs call, writing output to the fixed address
expected by the VMM and using PSCI to shut down on error.

The programs are built into flat binaries to simplify the VMM, this is a
bit more Makefile effort but it's all fairly standard for bare metal
programming.

We install single instruction BRK handlers for all exceptions with the
expectation that the VMM will trap BRKs and log exception state, we do
not expect to trigger any exceptions in normal operation.

We log the current EL to help with diagnostics.

Since we're constantly reading and writing the contents of the floating
point registers to and from memory there is fairly heavy memory traffic.
We do not currently turn the MMU on so on hardware the number of
iterations a test does will be very much lower that that seen on the
host, this can be addressed in future.

Signed-off-by: Mark Brown <[email protected]>
---
 tools/testing/selftests/arm64/fp/.gitignore        |  3 +
 tools/testing/selftests/arm64/fp/Makefile          | 40 +++++++++-
 tools/testing/selftests/arm64/fp/asm-utils-kvm.S   | 86 ++++++++++++++++++++++
 .../testing/selftests/arm64/fp/fp-stress-kvm.lds.S | 58 +++++++++++++++
 4 files changed, 186 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/arm64/fp/.gitignore 
b/tools/testing/selftests/arm64/fp/.gitignore
index 229a5c65b65f..7a788b23ae76 100644
--- a/tools/testing/selftests/arm64/fp/.gitignore
+++ b/tools/testing/selftests/arm64/fp/.gitignore
@@ -1,6 +1,7 @@
 fp-pidbench
 fp-ptrace
 fp-stress
+fp-stress-kvm.lds
 fp-stress-vmm
 fpsimd-test
 kernel-test
@@ -17,3 +18,5 @@ za-ptrace
 za-test
 zt-ptrace
 zt-test
+*-kvm.bin
+*-kvm.elf
diff --git a/tools/testing/selftests/arm64/fp/Makefile 
b/tools/testing/selftests/arm64/fp/Makefile
index 3c4e17a34776..5322cb66f0a9 100644
--- a/tools/testing/selftests/arm64/fp/Makefile
+++ b/tools/testing/selftests/arm64/fp/Makefile
@@ -21,17 +21,41 @@ TEST_GEN_PROGS_EXTENDED := fp-pidbench fp-stress-vmm 
fpsimd-test \
        zt-test \
        vlset
 TEST_PROGS_EXTENDED := fpsimd-stress sve-stress ssve-stress za-stress
+TEST_GEN_FILES := \
+       fpsimd-test-kvm.bin \
+       sve-test-kvm.bin \
+       ssve-test-kvm.bin \
+       za-test-kvm.bin \
+       zt-test-kvm.bin
 
 EXTRA_CLEAN += $(OUTPUT)/asm-utils.o $(OUTPUT)/asm-utils-linux.o \
-       $(OUTPUT)/rdvl.o $(OUTPUT)/za-fork-asm.o
+       $(OUTPUT)/rdvl.o $(OUTPUT)/za-fork-asm.o \
+       $(patsubst %.bin,%.elf,$(TEST_GEN_FILES)) \
+       $(KVM_LDS)
 
 ASM_UTILS_LINUX := $(OUTPUT)/asm-utils.o $(OUTPUT)/asm-utils-linux.o
+ASM_UTILS_KVM := asm-utils.S asm-utils-kvm.S
+
+OBJCOPY ?= $(CROSS_COMPILE)objcopy
 
 # For sysreg definitons
 ARCH_INCLUDES := $(KHDR_INCLUDES) -I$(top_srcdir)/tools/arch/arm64/include \
        -I$(top_srcdir)/tools/include \
        -I$(top_srcdir)/tools/include/generated
 
+# The guests run with no OS under them at all, link them as flat binaries
+# with the link script placing them where fp-stress-vmm puts their RAM.
+KVM_LDS := $(OUTPUT)/fp-stress-kvm.lds
+KVM_LDFLAGS := -nostdlib -static $(ARCH_INCLUDES) -D__ASSEMBLY__ \
+       -Wl,-T,$(KVM_LDS)
+
+# Supported/required from GNU ld 2.39, not confirmed LLD but after 22.1.2
+COMMA=,
+KVM_LDFLAGS += $(call try-run,$(LD) --warn-rwx-segments 
-v,-Wl$(COMMA)--warn-rwx-segments)
+
+$(KVM_LDS): fp-stress-kvm.lds.S fp-stress-vmm.h
+       $(CC) -E -P -x c $< -o $@
+
 $(OUTPUT)/fp-stress-vmm: CFLAGS += $(ARCH_INCLUDES)
 
 # Build with nolibc to avoid effects due to libc's clone() support
@@ -61,4 +85,18 @@ $(OUTPUT)/zt-ptrace: zt-ptrace.c
 $(OUTPUT)/zt-test: zt-test.S $(ASM_UTILS_LINUX)
        $(CC) -nostdlib $^ -o $@
 
+$(OUTPUT)/fpsimd-test-kvm.elf: fpsimd-test.S $(ASM_UTILS_KVM) $(KVM_LDS)
+       $(CC) $(KVM_LDFLAGS) $(filter %.S,$^) -o $@
+$(OUTPUT)/sve-test-kvm.elf: sve-test.S $(ASM_UTILS_KVM) $(KVM_LDS)
+       $(CC) $(KVM_LDFLAGS) $(filter %.S,$^) -o $@
+$(OUTPUT)/ssve-test-kvm.elf: sve-test.S $(ASM_UTILS_KVM) $(KVM_LDS)
+       $(CC) -DSSVE $(KVM_LDFLAGS) $(filter %.S,$^) -o $@
+$(OUTPUT)/za-test-kvm.elf: za-test.S $(ASM_UTILS_KVM) $(KVM_LDS)
+       $(CC) $(KVM_LDFLAGS) $(filter %.S,$^) -o $@
+$(OUTPUT)/zt-test-kvm.elf: zt-test.S $(ASM_UTILS_KVM) $(KVM_LDS)
+       $(CC) $(KVM_LDFLAGS) $(filter %.S,$^) -o $@
+
+$(OUTPUT)/%-kvm.bin: $(OUTPUT)/%-kvm.elf
+       $(OBJCOPY) -O binary $< $@
+
 include ../../lib.mk
diff --git a/tools/testing/selftests/arm64/fp/asm-utils-kvm.S 
b/tools/testing/selftests/arm64/fp/asm-utils-kvm.S
new file mode 100644
index 000000000000..422d6425ab56
--- /dev/null
+++ b/tools/testing/selftests/arm64/fp/asm-utils-kvm.S
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Utility functions for assembly code programs run under fp-stress-vmm.
+//
+// Copyright 2026, Arm Ltd
+
+#include <asm/sysreg.h>
+
+#include "assembler.h"
+#include "asm-offsets.h"
+#include "fp-stress-vmm.h"
+
+#define PSCI_0_2_FN_SYSTEM_OFF         0x84000008
+
+// Print a single character x0 to the console
+// Clobbers x1
+function putc
+       movz    x1, #(CONSOLE_BASE >> 16), lsl #16
+       strb    w0, [x1]
+       ret
+endfunction
+.globl putc
+
+// Print a \0 terminated string starting at address x0 to the console.
+// Doesn't use putc as a slight optimisation.
+// Clobbers x0-x3
+function puts
+       mov     x2, x0
+       movz    x3, #(CONSOLE_BASE >> 16), lsl #16
+
+0:     ldrb    w0, [x2], #1
+       cbz     w0, 1f
+       strb    w0, [x3]
+       b       0b
+
+1:     ret
+endfunction
+.globl puts
+
+// Report errors to the host by shutting down, there is no other reason one
+// of these test programs should exit.
+function exit_error
+       movz    x0, #(PSCI_0_2_FN_SYSTEM_OFF >> 16), lsl #16
+       movk    x0, #(PSCI_0_2_FN_SYSTEM_OFF & 0xffff)
+       hvc     #0
+
+0:     b       0b              // PSCI should not have returned
+endfunction
+.globl exit_error
+
+// Exception vectors.  We have no handlers for anything so each entry
+// just BRKs with its own number.
+       .balign 2048
+vectors:
+       .irp    vector, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+       .balign 0x80
+       brk     #\vector
+       .endr
+
+// Main program entry point.
+//
+// The VMM starts us at the very start of the image so the link script
+// places .text.boot first.
+       .section .text.boot, "ax"
+.globl _start
+function _start
+       // Vectors that report any exception we take to the VMM.
+       adr     x0, vectors
+       msr     VBAR_EL1, x0
+
+       // The VMM sizes our RAM as the image plus GUEST_EXTRA_RAM, put the
+       // stack at the top of that so it grows down away from the image.
+       ldr     x0, =_end
+       ldr     x1, =GUEST_EXTRA_RAM
+       add     x0, x0, x1
+       and     x0, x0, #~15
+       mov     sp, x0
+
+       // Log the current EL for diagnostic purposes.
+       puts    "EL:\t\tEL"
+       mrs     x0, CurrentEL
+       ubfx    x0, x0, #2, #2
+       bl      putdecn
+
+       b       main
+endfunction
diff --git a/tools/testing/selftests/arm64/fp/fp-stress-kvm.lds.S 
b/tools/testing/selftests/arm64/fp/fp-stress-kvm.lds.S
new file mode 100644
index 000000000000..f1d44f0ae49c
--- /dev/null
+++ b/tools/testing/selftests/arm64/fp/fp-stress-kvm.lds.S
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Link script for the flat binary builds of the fp-stress loads which run
+ * as guests under fp-stress-vmm.
+ *
+ * The VMM loads the image at the start of the guest RAM and starts the
+ * guest there so the startup code has to be first in the image, it is in
+ * .text.boot for that.
+ */
+
+#include "fp-stress-vmm.h"
+
+OUTPUT_ARCH(aarch64)
+ENTRY(_start)
+
+SECTIONS
+{
+       . = GUEST_RAM_BASE;
+
+       .text : {
+               *(.text.boot)
+               *(.text)
+               *(.text.*)
+       }
+
+       .rodata : {
+               *(.rodata)
+               *(.rodata.*)
+       }
+
+       .data : {
+               *(.data)
+               *(.data.*)
+       }
+
+       .bss : {
+               *(.bss)
+               *(.bss.*)
+               *(COMMON)
+       }
+
+       . = ALIGN(16);
+       _end = .;
+
+       /DISCARD/ : {
+               *(.note*)
+               *(.comment)
+               *(.eh_frame*)
+       }
+}
+
+/*
+ * The VMM sizes the guest RAM from the size of the image file and the
+ * guest puts its stack immediately above _end, anything allocated but not
+ * present in the file would leave the two disagreeing about where the RAM
+ * ends.
+ */
+ASSERT(SIZEOF(.bss) == 0, "fp-stress guests must not have a .bss")

-- 
2.47.3


Reply via email to