tools/testing/selftests/arm64/abi/syscall-abi.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/arm64/abi/syscall-abi.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/arm64/abi/syscall-abi.c
Extension
.c
Size
13263 bytes
Lines
566
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: syscall or user/kernel boundary
Status
core 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

if (gpr_in[i] != gpr_out[i]) {
			ksft_print_msg("%s SVE VL %d mismatch in GPR %d: %lx != %lx\n",
				       cfg->name, sve_vl, i,
				       gpr_in[i], gpr_out[i]);
			errors++;
		}
	}

	return errors;
}

#define NUM_FPR 32
uint64_t fpr_in[NUM_FPR * 2];
uint64_t fpr_out[NUM_FPR * 2];
uint64_t fpr_zero[NUM_FPR * 2];

static void setup_fpr(struct syscall_cfg *cfg, int sve_vl, int sme_vl,
		      uint64_t svcr)
{
	fill_random(fpr_in, sizeof(fpr_in));
	memset(fpr_out, 0, sizeof(fpr_out));
}

static int check_fpr(struct syscall_cfg *cfg, int sve_vl, int sme_vl,
		     uint64_t svcr)
{
	int errors = 0;
	int i;

	if (!sve_vl && !(svcr & SVCR_SM_MASK)) {
		for (i = 0; i < ARRAY_SIZE(fpr_in); i++) {
			if (fpr_in[i] != fpr_out[i]) {
				ksft_print_msg("%s Q%d/%d mismatch %lx != %lx\n",
					       cfg->name,
					       i / 2, i % 2,
					       fpr_in[i], fpr_out[i]);
				errors++;
			}
		}
	}

	/*
	 * In streaming mode the whole register set should be cleared
	 * by the transition out of streaming mode.
	 */
	if (svcr & SVCR_SM_MASK) {
		if (memcmp(fpr_zero, fpr_out, sizeof(fpr_out)) != 0) {
			ksft_print_msg("%s FPSIMD registers non-zero exiting SM\n",
				       cfg->name);
			errors++;
		}
	}

	return errors;
}

#define SVE_Z_SHARED_BYTES (128 / 8)

static uint8_t z_zero[__SVE_ZREG_SIZE(ARCH_SVE_VQ_MAX)];
uint8_t z_in[SVE_NUM_ZREGS * __SVE_ZREG_SIZE(ARCH_SVE_VQ_MAX)];
uint8_t z_out[SVE_NUM_ZREGS * __SVE_ZREG_SIZE(ARCH_SVE_VQ_MAX)];

static void setup_z(struct syscall_cfg *cfg, int sve_vl, int sme_vl,
		    uint64_t svcr)
{
	fill_random(z_in, sizeof(z_in));
	fill_random(z_out, sizeof(z_out));
}

static int check_z(struct syscall_cfg *cfg, int sve_vl, int sme_vl,
		   uint64_t svcr)
{
	size_t reg_size = sve_vl;
	int errors = 0;
	int i;

	if (!sve_vl)
		return 0;

	for (i = 0; i < SVE_NUM_ZREGS; i++) {
		uint8_t *in = &z_in[reg_size * i];
		uint8_t *out = &z_out[reg_size * i];

		if (svcr & SVCR_SM_MASK) {
			/*
			 * In streaming mode the whole register should
			 * be cleared by the transition out of
			 * streaming mode.
			 */
			if (memcmp(z_zero, out, reg_size) != 0) {

Annotation

Implementation Notes