xref: /openbsd-src/regress/sys/arch/i386/f00f/f00f.c (revision 14c8f53dc5e2a7b1bb93b64606b28c16c4c164c9)
1*14c8f53dSbluhm /*	$OpenBSD: f00f.c,v 1.2 2018/05/21 23:34:20 bluhm Exp $	*/
2b3e44de5Sbluhm /*
3b3e44de5Sbluhm  * Copyright (c) 2018 Alexander Bluhm <bluhm@genua.de>
4b3e44de5Sbluhm  *
5b3e44de5Sbluhm  * Permission to use, copy, modify, and distribute this software for any
6b3e44de5Sbluhm  * purpose with or without fee is hereby granted, provided that the above
7b3e44de5Sbluhm  * copyright notice and this permission notice appear in all copies.
8b3e44de5Sbluhm  *
9b3e44de5Sbluhm  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10b3e44de5Sbluhm  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11b3e44de5Sbluhm  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12b3e44de5Sbluhm  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13b3e44de5Sbluhm  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14b3e44de5Sbluhm  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15b3e44de5Sbluhm  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16b3e44de5Sbluhm  */
17b3e44de5Sbluhm 
18b3e44de5Sbluhm /* Test the Pentium f00f bug workaround by executing 0xF0,0x0F,0xC7,0xC8. */
19b3e44de5Sbluhm 
20b3e44de5Sbluhm #include <err.h>
21b3e44de5Sbluhm #include <signal.h>
22b3e44de5Sbluhm #include <stdint.h>
23b3e44de5Sbluhm #include <stdio.h>
24b3e44de5Sbluhm #include <stdlib.h>
25b3e44de5Sbluhm #include <string.h>
26b3e44de5Sbluhm 
27b3e44de5Sbluhm void
handler(int sig,siginfo_t * sip,void * ctx)28b3e44de5Sbluhm handler(int sig, siginfo_t *sip, void *ctx)
29b3e44de5Sbluhm {
30b3e44de5Sbluhm 	printf("signo %d, code %d, errno %d\n",
31b3e44de5Sbluhm 	    sip->si_signo, sip->si_code, sip->si_errno);
32b3e44de5Sbluhm 	if (sig != SIGILL)
33b3e44de5Sbluhm 		errx(1, "expected SIGILL: %d", sig);
34b3e44de5Sbluhm 	printf("addr %p, trapno %d\n", sip->si_addr, sip->si_trapno);
35b3e44de5Sbluhm 	printf("instruction %.2x %.2x %.2x %.2x\n",
36b3e44de5Sbluhm 	    ((uint8_t *)sip->si_addr)[0],
37b3e44de5Sbluhm 	    ((uint8_t *)sip->si_addr)[1],
38b3e44de5Sbluhm 	    ((uint8_t *)sip->si_addr)[2],
39b3e44de5Sbluhm 	    ((uint8_t *)sip->si_addr)[3]);
40b3e44de5Sbluhm 	if (*((uint32_t *)sip->si_addr) != 0xc8c70ff0)
41b3e44de5Sbluhm 		errx(1, "expected instrcution f0 0f c7 c8");
42b3e44de5Sbluhm 
43b3e44de5Sbluhm 	exit(0);
44b3e44de5Sbluhm }
45b3e44de5Sbluhm 
46b3e44de5Sbluhm int
main(int argc,char * argv[])47b3e44de5Sbluhm main(int argc, char *argv[])
48b3e44de5Sbluhm {
49b3e44de5Sbluhm 	struct sigaction sa;
50b3e44de5Sbluhm 	uint64_t mem;
51b3e44de5Sbluhm 	uint32_t eax, ebx, ecx, edx;
52b3e44de5Sbluhm 
53b3e44de5Sbluhm 	mem = 0x0123456789abcdefLL;
54b3e44de5Sbluhm 	eax = 0x11111111;
55b3e44de5Sbluhm 	ebx = 0x22222222;
56b3e44de5Sbluhm 	ecx = 0x33333333;
57b3e44de5Sbluhm 	edx = 0x44444444;
58b3e44de5Sbluhm 
59b3e44de5Sbluhm 	/* First check that the cmpxchg8b instruction works as expected. */
60b3e44de5Sbluhm 	printf("mem %.16llx, edx:eax %.8x%8x, ecx:ebx %.8x%.8x\n",
61b3e44de5Sbluhm 	    mem, edx, eax, ecx, ebx);
62b3e44de5Sbluhm 	printf("cmpxchg8b mem, mem != edx:eax\n");
63b3e44de5Sbluhm 	asm volatile (
64b3e44de5Sbluhm 		"lock	cmpxchg8b %0"
65b3e44de5Sbluhm 		: "+m" (mem), "+a" (eax), "+b" (ebx), "+c" (ecx), "+d" (edx));
66b3e44de5Sbluhm 	printf("mem %.16llx, edx:eax %.8x%8x, ecx:ebx %.8x%.8x\n",
67b3e44de5Sbluhm 	    mem, edx, eax, ecx, ebx);
68b3e44de5Sbluhm 
69b3e44de5Sbluhm 	if (mem != 0x0123456789abcdefLL)
70b3e44de5Sbluhm 		errx(1, "expected mem 0x0123456789abcdef");
71b3e44de5Sbluhm 	if (edx != 0x01234567 || eax != 0x89abcdef)
72b3e44de5Sbluhm 		errx(1, "expected edx:eax 0x0123456789abcdef");
73b3e44de5Sbluhm 	if (ecx != 0x33333333 || ebx != 0x22222222)
74b3e44de5Sbluhm 		errx(1, "expected ecx:ebx 0x3333333322222222");
75b3e44de5Sbluhm 
76b3e44de5Sbluhm 	printf("cmpxchg8b mem, mem == edx:eax\n");
77b3e44de5Sbluhm 	asm volatile (
78b3e44de5Sbluhm 		"lock cmpxchg8b %0"
79b3e44de5Sbluhm 		: "+m" (mem), "+a" (eax), "+b" (ebx), "+c" (ecx), "+d" (edx));
80b3e44de5Sbluhm 	printf("mem %.16llx, edx:eax %.8x%8x, ecx:ebx %.8x%.8x\n",
81b3e44de5Sbluhm 	    mem, edx, eax, ecx, ebx);
82b3e44de5Sbluhm 
83b3e44de5Sbluhm 	if (mem != 0x3333333322222222LL)
84b3e44de5Sbluhm 		errx(1, "expected mem 0x3333333322222222");
85b3e44de5Sbluhm 	if (edx != 0x01234567 || eax != 0x89abcdef)
86b3e44de5Sbluhm 		errx(1, "expected edx:eax 0x0123456789abcdef");
87b3e44de5Sbluhm 	if (ecx != 0x33333333 || ebx != 0x22222222)
88b3e44de5Sbluhm 		errx(1, "expected ecx:ebx 0x3333333322222222");
89b3e44de5Sbluhm 
90b3e44de5Sbluhm 	/* An illegal instruction must be signalled to user land. */
91b3e44de5Sbluhm 	memset(&sa, 0 ,sizeof(sa));
92b3e44de5Sbluhm 	sa.sa_sigaction = handler;
93b3e44de5Sbluhm 	sa.sa_flags = SA_SIGINFO;
94b3e44de5Sbluhm 	if (sigaction(SIGILL, &sa, NULL) == -1)
95b3e44de5Sbluhm 		err(2, "sigaction");
96b3e44de5Sbluhm 
97b3e44de5Sbluhm 	/* Execute the cmpxchg8b instruction with invalid addressing mode. */
98b3e44de5Sbluhm 	printf("cmpxchg8b eax\n");
99b3e44de5Sbluhm 	asm volatile (
100b3e44de5Sbluhm 		".byte 0xF0,0x0F,0xC7,0xC8"
101b3e44de5Sbluhm 		: : : "%eax", "%ebx", "%ecx", "%edx");
102b3e44de5Sbluhm 	printf("mem %.16llx, edx:eax %.8x%8x, ecx:ebx %.8x%.8x\n",
103b3e44de5Sbluhm 	    mem, edx, eax, ecx, ebx);
104b3e44de5Sbluhm 
105b3e44de5Sbluhm 	/* Not reached, the processor hangs or the signal handler exits. */
106b3e44de5Sbluhm 	errx(1, "expected signal");
107b3e44de5Sbluhm }
108