tools/testing/selftests/arm64/mte/mte_common_util.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/arm64/mte/mte_common_util.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/arm64/mte/mte_common_util.c
Extension
.c
Size
11307 bytes
Lines
426
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 (si->si_code == SEGV_MTEAERR) {
			if (cur_mte_cxt.trig_si_code == si->si_code)
				cur_mte_cxt.fault_valid = true;
			else
				ksft_print_msg("Got unexpected SEGV_MTEAERR at pc=%llx, fault addr=%lx\n",
					       ((ucontext_t *)uc)->uc_mcontext.pc,
					       addr);
			return;
		}
		/* Compare the context for precise error */
		else if (si->si_code == SEGV_MTESERR) {
			if ((!mtefar_support && si_atag) || (si_atag != MT_FETCH_ATAG(cur_mte_cxt.trig_addr))) {
				ksft_print_msg("Invalid MTE synchronous exception caught for address tag! si_tag=%x, si_atag: %x\n", si_tag, si_atag);
				exit(KSFT_FAIL);
			}

			if (cur_mte_cxt.trig_si_code == si->si_code &&
			    ((cur_mte_cxt.trig_range >= 0 &&
			      addr >= MT_CLEAR_TAGS(cur_mte_cxt.trig_addr) &&
			      addr <= (MT_CLEAR_TAGS(cur_mte_cxt.trig_addr) + cur_mte_cxt.trig_range)) ||
			     (cur_mte_cxt.trig_range < 0 &&
			      addr <= MT_CLEAR_TAGS(cur_mte_cxt.trig_addr) &&
			      addr >= (MT_CLEAR_TAGS(cur_mte_cxt.trig_addr) + cur_mte_cxt.trig_range)))) {
				cur_mte_cxt.fault_valid = true;
				/* Adjust the pc by 4 */
				((ucontext_t *)uc)->uc_mcontext.pc += 4;
			} else {
				ksft_print_msg("Invalid MTE synchronous exception caught!\n");
				exit(1);
			}
		} else {
			ksft_print_msg("Unknown SIGSEGV exception caught!\n");
			exit(1);
		}
	} else if (signum == SIGBUS) {
		ksft_print_msg("INFO: SIGBUS signal at pc=%llx, fault addr=%lx, si_code=%x\n",
				((ucontext_t *)uc)->uc_mcontext.pc, addr, si->si_code);
		if ((cur_mte_cxt.trig_range >= 0 &&
		     addr >= MT_CLEAR_TAGS(cur_mte_cxt.trig_addr) &&
		     addr <= (MT_CLEAR_TAGS(cur_mte_cxt.trig_addr) + cur_mte_cxt.trig_range)) ||
		    (cur_mte_cxt.trig_range < 0 &&
		     addr <= MT_CLEAR_TAGS(cur_mte_cxt.trig_addr) &&
		     addr >= (MT_CLEAR_TAGS(cur_mte_cxt.trig_addr) + cur_mte_cxt.trig_range))) {
			cur_mte_cxt.fault_valid = true;
			/* Adjust the pc by 4 */
			((ucontext_t *)uc)->uc_mcontext.pc += 4;
		}
	}
}

void mte_register_signal(int signal, void (*handler)(int, siginfo_t *, void *),
			 bool export_tags)
{
	struct sigaction sa;

	sa.sa_sigaction = handler;
	sa.sa_flags = SA_SIGINFO;

	if (export_tags && signal == SIGSEGV)
		sa.sa_flags |= SA_EXPOSE_TAGBITS;

	sigemptyset(&sa.sa_mask);
	sigaction(signal, &sa, NULL);
}

void mte_wait_after_trig(void)
{
	sched_yield();
}

void *mte_insert_tags(void *ptr, size_t size)
{
	void *tag_ptr;
	int align_size;

	if (!ptr || (unsigned long)(ptr) & MT_ALIGN_GRANULE) {
		ksft_print_msg("FAIL: Addr=%p: invalid\n", ptr);
		return NULL;
	}
	align_size = MT_ALIGN_UP(size);
	tag_ptr = mte_insert_random_tag(ptr);
	mte_set_tag_address_range(tag_ptr, align_size);
	return tag_ptr;
}

void mte_clear_tags(void *ptr, size_t size)
{
	if (!ptr || (unsigned long)(ptr) & MT_ALIGN_GRANULE) {
		ksft_print_msg("FAIL: Addr=%p: invalid\n", ptr);
		return;

Annotation

Implementation Notes