xref: /freebsd/tools/test/stress2/misc/ldt.sh (revision 02e9120893770924227138ba49df1edb3896112a)
1#!/bin/sh
2
3#
4# Copyright (c) 2009 Peter Holm <pho@FreeBSD.org>
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# SUCH DAMAGE.
27#
28
29# Test the amd64 implementation of:
30# 1. Per-process private ldt and corresponding i386 arch syscalls.
31# 2. Per-process private io permission bitmap and corresponding
32#    i386 arch syscalls.
33# 3. Sigcontext
34
35# The tests must be compiled on i386 and run on amd64
36
37# All tests by kib@
38
39[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
40
41. ../default.cfg
42
43cd /tmp
44if [ "`uname -p`" = "i386" ]; then
45	cat > ldt.c <<EOF
46/* \$Id: ldt.c,v 1.8 2008/11/01 21:14:59 kostik Exp kostik \$ */
47
48#include <sys/param.h>
49#include <sys/types.h>
50#include <sys/wait.h>
51#include <machine/segments.h>
52#include <machine/sysarch.h>
53#include <errno.h>
54#include <inttypes.h>
55#include <signal.h>
56#include <stdio.h>
57#include <string.h>
58#include <unistd.h>
59
60char stack[64 * 1024];
61
62char a[1];
63
64int
65s2ds(int sel)
66{
67
68	return (LSEL(sel, SEL_UPL));
69}
70
71unsigned char
72readbyte(int sel, int offset)
73{
74	unsigned char res;
75
76	__asm__ volatile(
77	    "\tpushl	%%es\n"
78	    "\tmovl	%1,%%es\n"
79	    "\tmovb	%%es:(%2),%0\n"
80	    "\tpopl	%%es\n"
81	    : "=r"(res) : "r"(s2ds(sel)), "r"(offset));
82
83	return (res);
84}
85
86void
87writebyte(int sel, int offset, unsigned char val)
88{
89
90	__asm__ volatile(
91	    "\tpushl	%%es\n"
92	    "\tmovl	%0,%%es\n"
93	    "\tmovb	%2,%%es:(%1)\n"
94	    "\tpopl	%%es\n"
95	    : : "r"(s2ds(sel)), "r"(offset), "r"(val) : "memory");
96}
97
98int
99alloc_sel(char *base, size_t len, int type, int p)
100{
101	int sel;
102	union descriptor descs[1], descsk[1];
103	uintptr_t pb;
104
105	memset(descs, 0, sizeof(descs));
106	if (len > PAGE_SIZE) {
107		len = roundup(len, PAGE_SIZE);
108		len /= PAGE_SIZE;
109		descs[0].sd.sd_lolimit = len & 0xffff;
110		descs[0].sd.sd_hilimit = (len >> 16) & 0xf;
111		descs[0].sd.sd_gran = 1;
112	} else {
113		descs[0].sd.sd_lolimit = len;
114		descs[0].sd.sd_hilimit = 0;
115		descs[0].sd.sd_gran = 0;
116	}
117	pb = (uintptr_t)base;
118	descs[0].sd.sd_lobase = pb & 0xffffff;
119	descs[0].sd.sd_hibase = (pb >> 24) & 0xff;
120	descs[0].sd.sd_type = type;
121	descs[0].sd.sd_dpl = SEL_UPL;
122	descs[0].sd.sd_p = p;
123	descs[0].sd.sd_def32 = 1;
124
125	if ((sel = i386_set_ldt(LDT_AUTO_ALLOC, descs, 1)) == -1)
126		fprintf(stderr, "i386_set_ldt: %s\n", strerror(errno));
127	else if (i386_get_ldt(sel, descsk, 1) == -1) {
128		fprintf(stderr, "i386_get_ldt: %s\n", strerror(errno));
129		sel = -1;
130	} else if (memcmp(descs, descsk, sizeof(descs)) != 0) {
131		fprintf(stderr, "descs != descsk\n");
132		sel = -1;
133	} else
134		fprintf(stderr, "selector %d\n", sel);
135
136	return (sel);
137}
138
139int
140test1(int tnum, int sel)
141{
142	unsigned char ar;
143
144	writebyte(sel, 0, '1');
145	ar = readbyte(sel, 0);
146	if (ar == '1')
147		fprintf(stderr, "test %d.1 ok\n", tnum);
148	else
149		fprintf(stderr, "test%d.1 failed, ar %x\n", tnum, ar);
150	writebyte(sel, 0, '2');
151	ar = readbyte(sel, 0);
152	if (ar == '2')
153		fprintf(stderr, "test %d.2 ok\n", tnum);
154	else
155		fprintf(stderr, "test%d.2 failed, ar %x\n", tnum, ar);
156	return (sel);
157}
158
159int
160test2_func(void *arg)
161{
162	int *sel;
163
164	sel = arg;
165	test1(2, *sel);
166	rfork(0);
167	test1(3, *sel);
168	return (0);
169}
170
171void
172test2(int sel)
173{
174	pid_t r;
175	int status;
176
177	r = rfork_thread(RFPROC | RFMEM, stack + sizeof(stack),
178	    test2_func, &sel);
179	if (r == -1) {
180		fprintf(stderr, "rfork(RFPROC): %s\n", strerror(errno));
181		return;
182	} else {
183		waitpid(r, &status, 0);
184		if (WIFSIGNALED(status)) {
185			fprintf(stderr, "test2: child terminated by %s\n",
186			    strsignal(WTERMSIG(status)));
187		}
188	}
189}
190
191int
192main(int argc, char *argv[])
193{
194	int sel;
195
196	sel = alloc_sel(a, 1, SDT_MEMRWA, 1);
197	if (sel == -1)
198		return (1);
199
200	test1(1, sel);
201	test2(sel);
202	return (0);
203}
204EOF
205	cc -o ldt_static_i386 -Wall -static ldt.c
206	rm ldt.c
207
208	cat > ioperm.c <<EOF
209/* \$Id: ioperm.c,v 1.3 2008/11/02 15:43:33 kostik Exp \$ */
210
211#include <machine/sysarch.h>
212#include <errno.h>
213#include <signal.h>
214#include <stdio.h>
215#include <stdlib.h>
216#include <string.h>
217
218static const unsigned int port_num = 0x130;
219
220unsigned char
221inb(unsigned int port)
222{
223	unsigned char data;
224
225	__asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
226	return (data);
227}
228
229void
230sigbus_handler(int signo)
231{
232
233	fprintf(stderr, "Got SIGBUS\n");
234	exit(0);
235}
236
237int
238main(int argc, char *argv[])
239{
240	struct sigaction sa;
241	unsigned int length1;
242	int enable1;
243
244	if (i386_get_ioperm(port_num, &length1, &enable1) == -1) {
245		fprintf(stderr, "get 1: %s\n", strerror(errno));
246		return (1);
247	}
248	if (length1 != 0 && enable1 != 0) {
249		fprintf(stderr, "enable1: enabled\n");
250		return (1);
251	}
252	if (i386_set_ioperm(port_num, 1, 1) == -1) {
253		fprintf(stderr, "set 1: %s\n", strerror(errno));
254		return (1);
255	}
256	inb(port_num);
257	if (i386_set_ioperm(port_num, 1, 0) == -1) {
258		fprintf(stderr, "set 2: %s\n", strerror(errno));
259		return (1);
260	}
261	if (i386_get_ioperm(port_num, &length1, &enable1) == -1) {
262		fprintf(stderr, "get 1: %s\n", strerror(errno));
263		return (1);
264	}
265	if (enable1 != 0) {
266		fprintf(stderr, "enable2: enabled\n");
267		return (1);
268	}
269	fprintf(stderr, "And now we should get SIGBUS\n");
270	memset(&sa, 0, sizeof(sa));
271	sa.sa_handler = sigbus_handler;
272	if (sigaction(SIGBUS, &sa, NULL) == -1) {
273		fprintf(stderr, "sigaction(SIGBUS): %s\n", strerror(errno));
274		return (1);
275	}
276	inb(port_num);
277
278	return (0);
279}
280EOF
281	cc -o ioperm_static_i386 -Wall -static ioperm.c
282	rm ioperm.c
283
284	cat > fault.c <<EOF
285/* \$Id: fault.c,v 1.5 2008/10/28 17:39:16 kostik Exp \$ */
286
287#include <sys/types.h>
288#include <sys/ucontext.h>
289#include <errno.h>
290#include <signal.h>
291#include <stdio.h>
292#include <string.h>
293#include <unistd.h>
294
295extern char *fault_instr;
296int run;
297
298void
299sigsegv_sigaction(int signo, siginfo_t *si, void *c)
300{
301	ucontext_t *uc;
302	mcontext_t *mc;
303
304	uc = c;
305	mc = &uc->uc_mcontext;
306	printf("SIGSEGV run %d err %x ds %x ss %x es %x fs %x gs %x\n",
307	    run, mc->mc_err, mc->mc_ds, mc->mc_ss, mc->mc_es, mc->mc_fs,
308	    mc->mc_gs);
309	switch (run) {
310	case 0:
311		mc->mc_ds = 0x1111;
312		break;
313	case 1:
314		mc->mc_es = 0x1111;
315		break;
316	case 2:
317		mc->mc_fs = 0x1111;
318		break;
319	case 3:
320		mc->mc_gs = 0x1111;
321		break;
322	case 4:
323		mc->mc_ss = 0x1111;
324		break;
325	case 5:
326		_exit(11);
327	}
328	run++;
329}
330
331void
332fault(void)
333{
334
335	__asm__ volatile(".globl\tfault_instr;fault_instr:\ttestl\t\$0,0\n");
336}
337
338int
339main(int argc, char *argv[])
340{
341	struct sigaction sa;
342
343	memset(&sa, 0, sizeof(sa));
344	sa.sa_sigaction = sigsegv_sigaction;
345	sa.sa_flags = SA_SIGINFO;
346	if (sigaction(SIGSEGV, &sa, NULL) == -1) {
347		fprintf(stderr, "sigaction: %s\n", strerror(errno));
348		return (1);
349	}
350	if (sigaction(SIGBUS, &sa, NULL) == -1) {
351		fprintf(stderr, "sigaction: %s\n", strerror(errno));
352		return (1);
353	}
354
355	fault();
356
357	return (0);
358}
359EOF
360	cc -o fault_static_i386 -Wall -static fault.c
361	rm fault.c
362fi
363
364if [ "`uname -p`" = "amd64" ]; then
365	[ -x ldt_static_i386 ]    && ./ldt_static_i386
366	[ -x ioperm_static_i386 ] && ./ioperm_static_i386
367	[ -x fault_static_i386 ]  && { ./fault_static_i386; rm fault_static_i386.core; }
368fi
369exit 0
370