mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	riscv: selftests: Add signal handling vector tests
Add two tests to check vector save/restore when a signal is received during a vector routine. One test ensures that a value is not clobbered during signal handling. The other verifies that vector registers modified in the signal handler are properly reflected when the signal handling is complete. Signed-off-by: Charlie Jenkins <charlie@rivosinc.com> Reviewed-by: Björn Töpel <bjorn@rivosinc.com> Reviewed-by: Andy Chiu <andy.chiu@sifive.com> Tested-by: Andy Chiu <andy.chiu@sifive.com> Link: https://lore.kernel.org/r/20240403-vector_sigreturn_tests-v1-1-2e68b7a3b8d7@rivosinc.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
		
							parent
							
								
									4c6c002042
								
							
						
					
					
						commit
						9d5328eeb1
					
				
					 4 changed files with 96 additions and 1 deletions
				
			
		| 
						 | 
				
			
			@ -5,7 +5,7 @@
 | 
			
		|||
ARCH ?= $(shell uname -m 2>/dev/null || echo not)
 | 
			
		||||
 | 
			
		||||
ifneq (,$(filter $(ARCH),riscv))
 | 
			
		||||
RISCV_SUBTARGETS ?= hwprobe vector mm
 | 
			
		||||
RISCV_SUBTARGETS ?= hwprobe vector mm sigreturn
 | 
			
		||||
else
 | 
			
		||||
RISCV_SUBTARGETS :=
 | 
			
		||||
endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								tools/testing/selftests/riscv/sigreturn/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tools/testing/selftests/riscv/sigreturn/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
sigreturn
 | 
			
		||||
							
								
								
									
										12
									
								
								tools/testing/selftests/riscv/sigreturn/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								tools/testing/selftests/riscv/sigreturn/Makefile
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
# SPDX-License-Identifier: GPL-2.0
 | 
			
		||||
# Copyright (C) 2021 ARM Limited
 | 
			
		||||
# Originally tools/testing/arm64/abi/Makefile
 | 
			
		||||
 | 
			
		||||
CFLAGS += -I$(top_srcdir)/tools/include
 | 
			
		||||
 | 
			
		||||
TEST_GEN_PROGS := sigreturn
 | 
			
		||||
 | 
			
		||||
include ../../lib.mk
 | 
			
		||||
 | 
			
		||||
$(OUTPUT)/sigreturn: sigreturn.c
 | 
			
		||||
	$(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^
 | 
			
		||||
							
								
								
									
										82
									
								
								tools/testing/selftests/riscv/sigreturn/sigreturn.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								tools/testing/selftests/riscv/sigreturn/sigreturn.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,82 @@
 | 
			
		|||
// SPDX-License-Identifier: GPL-2.0-only
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <ucontext.h>
 | 
			
		||||
#include <linux/ptrace.h>
 | 
			
		||||
#include "../../kselftest_harness.h"
 | 
			
		||||
 | 
			
		||||
#define RISCV_V_MAGIC		0x53465457
 | 
			
		||||
#define DEFAULT_VALUE		2
 | 
			
		||||
#define SIGNAL_HANDLER_OVERRIDE	3
 | 
			
		||||
 | 
			
		||||
static void simple_handle(int sig_no, siginfo_t *info, void *vcontext)
 | 
			
		||||
{
 | 
			
		||||
	ucontext_t *context = vcontext;
 | 
			
		||||
 | 
			
		||||
	context->uc_mcontext.__gregs[REG_PC] = context->uc_mcontext.__gregs[REG_PC] + 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void vector_override(int sig_no, siginfo_t *info, void *vcontext)
 | 
			
		||||
{
 | 
			
		||||
	ucontext_t *context = vcontext;
 | 
			
		||||
 | 
			
		||||
	// vector state
 | 
			
		||||
	struct __riscv_extra_ext_header *ext;
 | 
			
		||||
	struct __riscv_v_ext_state *v_ext_state;
 | 
			
		||||
 | 
			
		||||
	/* Find the vector context. */
 | 
			
		||||
	ext = (void *)(&context->uc_mcontext.__fpregs);
 | 
			
		||||
	if (ext->hdr.magic != RISCV_V_MAGIC) {
 | 
			
		||||
		fprintf(stderr, "bad vector magic: %x\n", ext->hdr.magic);
 | 
			
		||||
		abort();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v_ext_state = (void *)((char *)(ext) + sizeof(*ext));
 | 
			
		||||
 | 
			
		||||
	*(int *)v_ext_state->datap = SIGNAL_HANDLER_OVERRIDE;
 | 
			
		||||
 | 
			
		||||
	context->uc_mcontext.__gregs[REG_PC] = context->uc_mcontext.__gregs[REG_PC] + 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int vector_sigreturn(int data, void (*handler)(int, siginfo_t *, void *))
 | 
			
		||||
{
 | 
			
		||||
	int after_sigreturn;
 | 
			
		||||
	struct sigaction sig_action = {
 | 
			
		||||
		.sa_sigaction = handler,
 | 
			
		||||
		.sa_flags = SA_SIGINFO
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	sigaction(SIGSEGV, &sig_action, 0);
 | 
			
		||||
 | 
			
		||||
	asm(".option push				\n\
 | 
			
		||||
		.option		arch, +v		\n\
 | 
			
		||||
		vsetivli	x0, 1, e32, ta, ma	\n\
 | 
			
		||||
		vmv.s.x		v0, %1			\n\
 | 
			
		||||
		# Generate SIGSEGV			\n\
 | 
			
		||||
		lw		a0, 0(x0)		\n\
 | 
			
		||||
		vmv.x.s		%0, v0			\n\
 | 
			
		||||
		.option pop" : "=r" (after_sigreturn) : "r" (data));
 | 
			
		||||
 | 
			
		||||
	return after_sigreturn;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(vector_restore)
 | 
			
		||||
{
 | 
			
		||||
	int result;
 | 
			
		||||
 | 
			
		||||
	result = vector_sigreturn(DEFAULT_VALUE, &simple_handle);
 | 
			
		||||
 | 
			
		||||
	EXPECT_EQ(DEFAULT_VALUE, result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(vector_restore_signal_handler_override)
 | 
			
		||||
{
 | 
			
		||||
	int result;
 | 
			
		||||
 | 
			
		||||
	result = vector_sigreturn(DEFAULT_VALUE, &vector_override);
 | 
			
		||||
 | 
			
		||||
	EXPECT_EQ(SIGNAL_HANDLER_OVERRIDE, result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_HARNESS_MAIN
 | 
			
		||||
		Loading…
	
		Reference in a new issue