tools/testing/selftests/arm64/signal/test_signals_utils.h

Source file repositories/reference/linux-study-clean/tools/testing/selftests/arm64/signal/test_signals_utils.h

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/arm64/signal/test_signals_utils.h
Extension
.h
Size
6653 bytes
Lines
204
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

#ifndef __TEST_SIGNALS_UTILS_H__
#define __TEST_SIGNALS_UTILS_H__

#include <assert.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

#include <linux/compiler.h>

#include "test_signals.h"

int test_init(struct tdescr *td);
int test_setup(struct tdescr *td);
void test_cleanup(struct tdescr *td);
int test_run(struct tdescr *td);
void test_result(struct tdescr *td);

#ifndef __NR_prctl
#define __NR_prctl 167
#endif

/*
 * The prctl takes 1 argument but we need to ensure that the other
 * values passed in registers to the syscall are zero since the kernel
 * validates them.
 */
#define gcs_set_state(state)					\
	({								\
		register long _num  __asm__ ("x8") = __NR_prctl;	\
		register long _arg1 __asm__ ("x0") =  PR_SET_SHADOW_STACK_STATUS; \
		register long _arg2 __asm__ ("x1") = (long)(state);	\
		register long _arg3 __asm__ ("x2") = 0;			\
		register long _arg4 __asm__ ("x3") = 0;			\
		register long _arg5 __asm__ ("x4") = 0;			\
	                                                                      \
		__asm__  volatile (					\
			"svc #0\n"					\
			: "=r"(_arg1)					\
			: "r"(_arg1), "r"(_arg2),			\
			  "r"(_arg3), "r"(_arg4),			\
			  "r"(_arg5), "r"(_num)				\
			: "memory", "cc"				\
			);						\
		_arg1;							\
	})

static inline __attribute__((always_inline)) uint64_t get_gcspr_el0(void)
{
	uint64_t val;

	asm volatile("mrs %0, S3_3_C2_C5_1" : "=r" (val));

	return val;
}

#define SYS_POR_EL0 "S3_3_C10_C2_4"

static inline uint64_t get_por_el0(void)
{
	uint64_t val;

	asm volatile("mrs %0, " SYS_POR_EL0 "\n" : "=r"(val));

	return val;
}

static inline void set_por_el0(uint64_t val)
{
	asm volatile("msr " SYS_POR_EL0 ", %0\n" :: "r"(val));
}

static inline bool feats_ok(struct tdescr *td)
{
	if (td->feats_incompatible & td->feats_supported)
		return false;
	return (td->feats_required & td->feats_supported) == td->feats_required;
}

/*
 * Obtaining a valid and full-blown ucontext_t from userspace is tricky:
 * libc getcontext does() not save all the regs and messes with some of
 * them (pstate value in particular is not reliable).
 *
 * Here we use a service signal to grab the ucontext_t from inside a
 * dedicated signal handler, since there, it is populated by Kernel
 * itself in setup_sigframe(). The grabbed context is then stored and
 * made available in td->live_uc.
 *
 * As service-signal is used a SIGTRAP induced by a 'brk' instruction,

Annotation

Implementation Notes