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