tests/tcg/aarch64: Add gcsss
Validate stack switching and recursion depth. Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20251008215613.300150-74-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
8f278acdce
commit
af0bd678df
3 changed files with 84 additions and 1 deletions
|
|
@ -76,7 +76,7 @@ $(SME_TESTS): CFLAGS += $(CROSS_AS_HAS_ARMV9_SME)
|
|||
endif
|
||||
|
||||
# GCS Tests
|
||||
GCS_TESTS += gcsstr gcspushm
|
||||
GCS_TESTS += gcsstr gcspushm gcsss
|
||||
AARCH64_TESTS += $(GCS_TESTS)
|
||||
$(GCS_TESTS): gcs.h
|
||||
|
||||
|
|
|
|||
|
|
@ -69,3 +69,12 @@
|
|||
|
||||
#define gcspr() \
|
||||
({ uint64_t *r; asm volatile("mrs %0, s3_3_c2_c5_1" : "=r"(r)); r; })
|
||||
|
||||
#define gcsss1(val) \
|
||||
do { \
|
||||
asm volatile("sys #3, c7, c7, #2, %0" : : "r"(val) : "memory"); \
|
||||
} while (0)
|
||||
|
||||
#define gcsss2() \
|
||||
({ uint64_t *r; \
|
||||
asm volatile("sysl %0, #3, c7, c7, #3" : "=r"(r) : : "memory"); r; })
|
||||
|
|
|
|||
74
tests/tcg/aarch64/gcsss.c
Normal file
74
tests/tcg/aarch64/gcsss.c
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "gcs.h"
|
||||
|
||||
#define IN_PROGRESS(X) ((uint64_t)(X) | 5)
|
||||
#define CAP(X) (((uint64_t)(X) & ~0xfff) + 1)
|
||||
|
||||
static uint64_t * __attribute__((noinline)) recurse(size_t index)
|
||||
{
|
||||
if (index == 0) {
|
||||
return gcspr();
|
||||
}
|
||||
return recurse(index - 1);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
void *tmp;
|
||||
uint64_t *alt_stack, *alt_cap;
|
||||
uint64_t *orig_pr, *orig_cap;
|
||||
uint64_t *bottom;
|
||||
size_t pagesize = getpagesize();
|
||||
size_t words;
|
||||
|
||||
enable_gcs(0);
|
||||
orig_pr = gcspr();
|
||||
|
||||
/* Allocate a guard page before and after. */
|
||||
tmp = mmap(0, 3 * pagesize, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
assert(tmp != MAP_FAILED);
|
||||
|
||||
/* map_shadow_stack won't replace existing mappings */
|
||||
munmap(tmp + pagesize, pagesize);
|
||||
|
||||
/* Allocate a new stack between the guards. */
|
||||
alt_stack = (uint64_t *)
|
||||
syscall(__NR_map_shadow_stack, tmp + pagesize, pagesize,
|
||||
SHADOW_STACK_SET_TOKEN);
|
||||
assert(alt_stack == tmp + pagesize);
|
||||
|
||||
words = pagesize / 8;
|
||||
alt_cap = alt_stack + words - 1;
|
||||
|
||||
/* SHADOW_STACK_SET_TOKEN set the cap. */
|
||||
assert(*alt_cap == CAP(alt_cap));
|
||||
|
||||
/* Swap to the alt stack, one step at a time. */
|
||||
gcsss1(alt_cap);
|
||||
|
||||
assert(gcspr() == alt_cap);
|
||||
assert(*alt_cap == IN_PROGRESS(orig_pr));
|
||||
|
||||
orig_cap = gcsss2();
|
||||
|
||||
assert(orig_cap == orig_pr - 1);
|
||||
assert(*orig_cap == CAP(orig_cap));
|
||||
assert(gcspr() == alt_stack + words);
|
||||
|
||||
/* We should be able to use the whole stack. */
|
||||
bottom = recurse(words - 1);
|
||||
assert(bottom == alt_stack);
|
||||
|
||||
/* We should be back where we started. */
|
||||
assert(gcspr() == alt_stack + words);
|
||||
|
||||
/* Swap back to the original stack. */
|
||||
gcsss1(orig_cap);
|
||||
tmp = gcsss2();
|
||||
|
||||
assert(gcspr() == orig_pr);
|
||||
assert(tmp == alt_cap);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue