linux/tools/testing/selftests/arm64/gcs/gcs-util.h
Mark Brown a505a52b4e kselftest/arm64: Add a GCS test program built with the system libc
There are things like threads which nolibc struggles with which we want
to add coverage for, and the ABI allows us to test most of these even if
libc itself does not understand GCS so add a test application built
using the system libc.

Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Tested-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20241001-arm64-gcs-v13-35-222b78d87eee@kernel.org
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2024-10-04 12:04:44 +01:00

100 lines
1.9 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2023 ARM Limited.
*/
#ifndef GCS_UTIL_H
#define GCS_UTIL_H
#include <stdbool.h>
#ifndef __NR_map_shadow_stack
#define __NR_map_shadow_stack 453
#endif
#ifndef __NR_prctl
#define __NR_prctl 167
#endif
#ifndef NT_ARM_GCS
#define NT_ARM_GCS 0x410
struct user_gcs {
__u64 features_enabled;
__u64 features_locked;
__u64 gcspr_el0;
};
#endif
/* Shadow Stack/Guarded Control Stack interface */
#define PR_GET_SHADOW_STACK_STATUS 74
#define PR_SET_SHADOW_STACK_STATUS 75
#define PR_LOCK_SHADOW_STACK_STATUS 76
# define PR_SHADOW_STACK_ENABLE (1UL << 0)
# define PR_SHADOW_STACK_WRITE (1UL << 1)
# define PR_SHADOW_STACK_PUSH (1UL << 2)
#define PR_SHADOW_STACK_ALL_MODES \
PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_WRITE | PR_SHADOW_STACK_PUSH
#define SHADOW_STACK_SET_TOKEN (1ULL << 0) /* Set up a restore token in the shadow stack */
#define SHADOW_STACK_SET_MARKER (1ULL << 1) /* Set up a top of stack merker in the shadow stack */
#define GCS_CAP_ADDR_MASK (0xfffffffffffff000UL)
#define GCS_CAP_TOKEN_MASK (0x0000000000000fffUL)
#define GCS_CAP_VALID_TOKEN 1
#define GCS_CAP_IN_PROGRESS_TOKEN 5
#define GCS_CAP(x) (((unsigned long)(x) & GCS_CAP_ADDR_MASK) | \
GCS_CAP_VALID_TOKEN)
static inline unsigned long *get_gcspr(void)
{
unsigned long *gcspr;
asm volatile(
"mrs %0, S3_3_C2_C5_1"
: "=r" (gcspr)
:
: "cc");
return gcspr;
}
static inline void __attribute__((always_inline)) gcsss1(unsigned long *Xt)
{
asm volatile (
"sys #3, C7, C7, #2, %0\n"
:
: "rZ" (Xt)
: "memory");
}
static inline unsigned long __attribute__((always_inline)) *gcsss2(void)
{
unsigned long *Xt;
asm volatile(
"SYSL %0, #3, C7, C7, #3\n"
: "=r" (Xt)
:
: "memory");
return Xt;
}
static inline bool chkfeat_gcs(void)
{
register long val __asm__ ("x16") = 1;
/* CHKFEAT x16 */
asm volatile(
"hint #0x28\n"
: "=r" (val)
: "r" (val));
return val != 1;
}
#endif