tools/testing/selftests/x86/iopl.c

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

File Facts

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

// SPDX-License-Identifier: GPL-2.0
/*
 * iopl.c - Test case for a Linux on Xen 64-bit bug
 * Copyright (c) 2015 Andrew Lutomirski
 */

#define _GNU_SOURCE
#include <err.h>
#include <stdio.h>
#include <stdint.h>
#include <signal.h>
#include <setjmp.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdbool.h>
#include <sched.h>
#include <sys/io.h>

#include "helpers.h"

static int nerrs = 0;

static jmp_buf jmpbuf;

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

static bool try_outb(unsigned short port)
{
	sethandler(SIGSEGV, sigsegv, SA_RESETHAND);
	if (sigsetjmp(jmpbuf, 1) != 0) {
		return false;
	} else {
		asm volatile ("outb %%al, %w[port]"
			      : : [port] "Nd" (port), "a" (0));
		return true;
	}
	clearhandler(SIGSEGV);
}

static void expect_ok_outb(unsigned short port)
{
	if (!try_outb(port)) {
		printf("[FAIL]\toutb to 0x%02hx failed\n", port);
		exit(1);
	}

	printf("[OK]\toutb to 0x%02hx worked\n", port);
}

static void expect_gp_outb(unsigned short port)
{
	if (try_outb(port)) {
		printf("[FAIL]\toutb to 0x%02hx worked\n", port);
		nerrs++;
	}

	printf("[OK]\toutb to 0x%02hx failed\n", port);
}

#define RET_FAULTED	0
#define RET_FAIL	1
#define RET_EMUL	2

static int try_cli(void)
{
	unsigned long flags;

	sethandler(SIGSEGV, sigsegv, SA_RESETHAND);
	if (sigsetjmp(jmpbuf, 1) != 0) {
		return RET_FAULTED;
	} else {
		asm volatile("cli; pushf; pop %[flags]"
				: [flags] "=rm" (flags));

		/* X86_FLAGS_IF */
		if (!(flags & (1 << 9)))
			return RET_FAIL;
		else
			return RET_EMUL;
	}
	clearhandler(SIGSEGV);
}

Annotation

Implementation Notes