tools/testing/selftests/x86/ldt_gdt.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/x86/ldt_gdt.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/x86/ldt_gdt.c
Extension
.c
Size
22553 bytes
Lines
918
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

struct fake_ksigaction {
	void *handler;  /* the real type is nasty */
	unsigned long sa_flags;
	void (*sa_restorer)(void);
	unsigned char sigset[8];
};

static void fix_sa_restorer(int sig)
{
	struct fake_ksigaction ksa;

	if (syscall(SYS_rt_sigaction, sig, NULL, &ksa, 8) == 0) {
		/*
		 * glibc has a nasty bug: it sometimes writes garbage to
		 * sa_restorer.  This interacts quite badly with anything
		 * that fiddles with SS because it can trigger legacy
		 * stack switching.  Patch it up.  See:
		 *
		 * https://sourceware.org/bugzilla/show_bug.cgi?id=21269
		 */
		if (!(ksa.sa_flags & SA_RESTORER) && ksa.sa_restorer) {
			ksa.sa_restorer = NULL;
			if (syscall(SYS_rt_sigaction, sig, &ksa, NULL,
				    sizeof(ksa.sigset)) != 0)
				err(1, "rt_sigaction");
		}
	}
}
#else
static void fix_sa_restorer(int sig)
{
	/* 64-bit glibc works fine. */
}
#endif

static jmp_buf jmpbuf;

static void sigsegv(int sig, siginfo_t *info, void *ctx_void)
{
	siglongjmp(jmpbuf, 1);
}

static void do_multicpu_tests(void)
{
	cpu_set_t cpuset;
	pthread_t thread;
	int failures = 0, iters = 5, i;
	unsigned short orig_ss;

	CPU_ZERO(&cpuset);
	CPU_SET(1, &cpuset);
	if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) {
		printf("[SKIP]\tCannot set affinity to CPU 1\n");
		return;
	}

	CPU_ZERO(&cpuset);
	CPU_SET(0, &cpuset);
	if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) {
		printf("[SKIP]\tCannot set affinity to CPU 0\n");
		return;
	}

	sethandler(SIGSEGV, sigsegv, 0);
	fix_sa_restorer(SIGSEGV);
#ifdef __i386__
	/* True 32-bit kernels send SIGILL instead of SIGSEGV on IRET faults. */
	sethandler(SIGILL, sigsegv, 0);
	fix_sa_restorer(SIGILL);
#endif

	printf("[RUN]\tCross-CPU LDT invalidation\n");

	if (pthread_create(&thread, 0, threadproc, 0) != 0)
		err(1, "pthread_create");

	asm volatile ("mov %%ss, %0" : "=rm" (orig_ss));

	for (i = 0; i < 5; i++) {
		if (sigsetjmp(jmpbuf, 1) != 0)
			continue;

		/* Make sure the thread is ready after the last test. */
		while (ftx != 0)
			;

		struct user_desc desc = {
			.entry_number    = 0,
			.base_addr       = 0,
			.limit           = 0xfffff,

Annotation

Implementation Notes