1333534Skib/*-
2333534Skib * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3333534Skib *
4333534Skib * Copyright (c) 2018 The FreeBSD Foundation
5333534Skib * All rights reserved.
6333534Skib *
7333534Skib * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
8333534Skib * under sponsorship from the FreeBSD Foundation.
9333534Skib *
10333534Skib * Redistribution and use in source and binary forms, with or without
11333534Skib * modification, are permitted provided that the following conditions
12333534Skib * are met:
13333534Skib * 1. Redistributions of source code must retain the above copyright
14333534Skib *    notice, this list of conditions and the following disclaimer.
15333534Skib * 2. Redistributions in binary form must reproduce the above copyright
16333534Skib *    notice, this list of conditions and the following disclaimer in the
17333534Skib *    documentation and/or other materials provided with the distribution.
18333534Skib *
19333534Skib * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20333534Skib * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21333534Skib * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22333534Skib * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23333534Skib * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24333534Skib * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25333534Skib * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26333534Skib * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27333534Skib * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28333534Skib * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29333534Skib * SUCH DAMAGE.
30333534Skib */
31333534Skib
32333534Skib#include <sys/cdefs.h>
33333534Skib__FBSDID("$FreeBSD: stable/11/tools/test/vm86/vm86_test.c 333534 2018-05-12 11:53:49Z kib $");
34333534Skib/* $Id: vm86_test.c,v 1.10 2018/05/12 11:35:58 kostik Exp kostik $ */
35333534Skib
36333534Skib#include <sys/param.h>
37333534Skib#include <sys/mman.h>
38333534Skib#include <sys/ucontext.h>
39333534Skib
40333534Skib#include <machine/cpufunc.h>
41333534Skib#include <machine/psl.h>
42333534Skib#include <machine/sysarch.h>
43333534Skib#include <machine/vm86.h>
44333534Skib
45333534Skib#include <err.h>
46333534Skib#include <signal.h>
47333534Skib#include <stdio.h>
48333534Skib#include <stdlib.h>
49333534Skib#include <string.h>
50333534Skib
51333534Skibstatic u_int gs;
52333534Skib
53333534Skibstatic void
54333534Skibsig_handler(int signo, siginfo_t *si __unused, void *ucp)
55333534Skib{
56333534Skib	ucontext_t *uc;
57333534Skib	mcontext_t *mc;
58333534Skib
59333534Skib	uc = ucp;
60333534Skib	mc = &uc->uc_mcontext;
61333534Skib
62333534Skib	/*
63333534Skib	 * Reload pointer to the TLS base, so that malloc inside
64333534Skib	 * printf() works.
65333534Skib	 */
66333534Skib	load_gs(gs);
67333534Skib
68333534Skib	printf("sig %d %%eax %#x %%ecx %#x %%eip %#x\n", signo,
69333534Skib	    mc->mc_eax, mc->mc_ecx, mc->mc_eip);
70333534Skib	exit(0);
71333534Skib}
72333534Skib
73333534Skibextern char vm86_code_start[], vm86_code_end[];
74333534Skib
75333534Skibint
76333534Skibmain(void)
77333534Skib{
78333534Skib	ucontext_t uc;
79333534Skib	struct sigaction sa;
80333534Skib	struct vm86_init_args va;
81333534Skib	stack_t ssa;
82333534Skib	char *vm86_code;
83333534Skib
84333534Skib	gs = rgs();
85333534Skib
86333534Skib	memset(&ssa, 0, sizeof(ssa));
87333534Skib	ssa.ss_size = PAGE_SIZE * 128;
88333534Skib	ssa.ss_sp = mmap(NULL, ssa.ss_size, PROT_READ | PROT_WRITE |
89333534Skib	    PROT_EXEC, MAP_ANON, -1, 0);
90333534Skib	if (ssa.ss_sp == MAP_FAILED)
91333534Skib		err(1, "mmap sigstack");
92333534Skib	if (sigaltstack(&ssa, NULL) == -1)
93333534Skib		err(1, "sigaltstack");
94333534Skib
95333534Skib	memset(&sa, 0, sizeof(sa));
96333534Skib	sa.sa_sigaction = sig_handler;
97333534Skib	sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
98333534Skib	if (sigaction(SIGBUS, &sa, NULL) == -1)
99333534Skib		err(1, "sigaction SIGBUS");
100333534Skib	if (sigaction(SIGSEGV, &sa, NULL) == -1)
101333534Skib		err(1, "sigaction SIGSEGV");
102333534Skib	if (sigaction(SIGILL, &sa, NULL) == -1)
103333534Skib		err(1, "sigaction SIGILL");
104333534Skib
105333534Skib	vm86_code = mmap((void *)0x10000, PAGE_SIZE, PROT_READ | PROT_WRITE |
106333534Skib	    PROT_EXEC, MAP_ANON | MAP_FIXED, -1, 0);
107333534Skib	if (vm86_code == MAP_FAILED)
108333534Skib		err(1, "mmap");
109333534Skib	memcpy(vm86_code, vm86_code_start, vm86_code_end - vm86_code_start);
110333534Skib
111333534Skib	memset(&va, 0, sizeof(va));
112333534Skib	if (i386_vm86(VM86_INIT, &va) == -1)
113333534Skib		err(1, "VM86_INIT");
114333534Skib
115333534Skib	memset(&uc, 0, sizeof(uc));
116333534Skib	uc.uc_mcontext.mc_ecx = 0x2345;
117333534Skib	uc.uc_mcontext.mc_eflags = PSL_VM | PSL_USER;
118333534Skib	uc.uc_mcontext.mc_cs = uc.uc_mcontext.mc_ds = uc.uc_mcontext.mc_es =
119333534Skib	    uc.uc_mcontext.mc_ss = (uintptr_t)vm86_code >> 4;
120333534Skib	uc.uc_mcontext.mc_esp = 0xfffe;
121333534Skib	sigreturn(&uc);
122333534Skib}
123