tools/testing/selftests/arm64/fp/za-ptrace.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/arm64/fp/za-ptrace.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/arm64/fp/za-ptrace.c
Extension
.c
Size
7955 bytes
Lines
369
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

if (*size < sz) {
			p = realloc(*buf, sz);
			if (!p) {
				errno = ENOMEM;
				goto error;
			}

			*buf = p;
			*size = sz;
		}

		iov.iov_base = *buf;
		iov.iov_len = sz;
		if (ptrace(PTRACE_GETREGSET, pid, NT_ARM_ZA, &iov))
			goto error;

		za = *buf;
		if (za->size <= sz)
			break;

		sz = za->size;
	}

	return za;

error:
	return NULL;
}

static int set_za(pid_t pid, const struct user_za_header *za)
{
	struct iovec iov;

	iov.iov_base = (void *)za;
	iov.iov_len = za->size;
	return ptrace(PTRACE_SETREGSET, pid, NT_ARM_ZA, &iov);
}

/* Validate attempting to set the specfied VL via ptrace */
static void ptrace_set_get_vl(pid_t child, unsigned int vl, bool *supported)
{
	struct user_za_header za;
	struct user_za_header *new_za = NULL;
	size_t new_za_size = 0;
	int ret, prctl_vl;

	*supported = false;

	/* Check if the VL is supported in this process */
	prctl_vl = prctl(PR_SME_SET_VL, vl);
	if (prctl_vl == -1)
		ksft_exit_fail_msg("prctl(PR_SME_SET_VL) failed: %s (%d)\n",
				   strerror(errno), errno);

	/* If the VL is not supported then a supported VL will be returned */
	*supported = (prctl_vl == vl);

	/* Set the VL by doing a set with no register payload */
	memset(&za, 0, sizeof(za));
	za.size = sizeof(za);
	za.vl = vl;
	ret = set_za(child, &za);
	if (ret != 0) {
		ksft_test_result_fail("Failed to set VL %u\n", vl);
		return;
	}

	/*
	 * Read back the new register state and verify that we have the
	 * same VL that we got from prctl() on ourselves.
	 */
	if (!get_za(child, (void **)&new_za, &new_za_size)) {
		ksft_test_result_fail("Failed to read VL %u\n", vl);
		return;
	}

	ksft_test_result(new_za->vl = prctl_vl, "Set VL %u\n", vl);

	free(new_za);
}

/* Validate attempting to set no ZA data and read it back */
static void ptrace_set_no_data(pid_t child, unsigned int vl)
{
	void *read_buf = NULL;
	struct user_za_header write_za;
	struct user_za_header *read_za;
	size_t read_za_size = 0;
	int ret;

Annotation

Implementation Notes