1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2021 Tintri by DDN, Inc. All rights reserved.
14  */
15 
16 /*
17  * Test that the stack is aligned to expected values.
18  */
19 
20 #include <stdio.h>
21 #include <pthread.h>
22 #include <thread.h>
23 #include <door.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <ucontext.h>
27 
28 #include <sys/stack.h>
29 
30 /*
31  * The introduction of SSE led to the IA32 ABI changing the required stack
32  * alignment from 4 bytes to 16 bytes. Compilers assume this when using SSE.
33  */
34 #if defined(__i386)
35 #undef STACK_ALIGN
36 #define	STACK_ALIGN 16
37 #endif
38 
39 #define	ALIGN_ERR_IMPL(align, text)				\
40 	"stack was not aligned to " #align " on " text "\n"
41 #define	ALIGN_ERR_HELP(align, text) ALIGN_ERR_IMPL(align, text)
42 #define	ALIGN_ERR(text) ALIGN_ERR_HELP(STACK_ALIGN, text)
43 
44 #define	STACK_SIZE 16*1024
45 
46 typedef struct test_ctx {
47 	void (*func)(uintptr_t, char *);
48 	char *text;
49 } test_ctx_t;
50 
51 extern void get_stack_at_entry(test_ctx_t *);
52 
53 void
54 teststack(uintptr_t stack, char *arg)
55 {
56 	if ((stack & (STACK_ALIGN - 1)) != 0) {
57 		fprintf(stderr, ALIGN_ERR("%s"), (char *)arg);
58 		exit(1);
59 	}
60 }
61 
62 void
63 initmain(uintptr_t stack)
64 {
65 	teststack(stack, "section .init");
66 }
67 
68 void
69 initarray(uintptr_t stack)
70 {
71 	teststack(stack, "section .init_array");
72 }
73 
74 void
75 doorstack(uintptr_t stack, char *arg)
76 {
77 	teststack(stack, arg);
78 	(void) door_return(NULL, 0, NULL, 0);
79 }
80 
81 char door_arg[] = "DOOR ARG";
82 
83 int
84 main(int argc, char *argv[])
85 {
86 #if defined(__sparc)
87 	/*
88 	 * This hasn't been implemented for SPARC, so skip.
89 	 */
90 	fprintf(stderr, "No SPARC implementation of get_stack_at_entry\n");
91 	return (3);
92 #else
93 	door_arg_t da = {
94 	    .data_ptr = (void *)door_arg,
95 	    .data_size = sizeof (door_arg)
96 	};
97 	test_ctx_t arg = {
98 	    .func = teststack,
99 	    .text = "pthread_create()"
100 	};
101 	ucontext_t back, uc;
102 	pthread_t tid;
103 	int door_fd, rc;
104 
105 	if (pthread_create(&tid, NULL,
106 	    (void *(*)(void *))(uintptr_t)get_stack_at_entry, &arg) != 0) {
107 		perror("pthread_create() failed:");
108 		exit(-2);
109 	}
110 	(void) pthread_join(tid, NULL);
111 
112 	arg.text = "thr_create()";
113 
114 	if (thr_create(NULL, 0,
115 	    (void *(*)(void *))(uintptr_t)get_stack_at_entry,
116 	    &arg, 0, &tid) != 0) {
117 		perror("thr_create() failed:");
118 		exit(-3);
119 	}
120 	(void) thr_join(tid, NULL, NULL);
121 
122 	if (getcontext(&uc) < 0) {
123 		perror("getcontext() failed");
124 		exit(-4);
125 	}
126 
127 	uc.uc_link = &back;
128 	uc.uc_stack.ss_size = STACK_SIZE;
129 	uc.uc_stack.ss_flags = 0;
130 	if ((uc.uc_stack.ss_sp = malloc(STACK_SIZE)) == NULL) {
131 		perror("failed to allocate stack");
132 		exit(-5);
133 	}
134 
135 	arg.text = "swapcontext()";
136 	makecontext(&uc, (void (*)(void *))get_stack_at_entry, 1, &arg);
137 	if (swapcontext(&back, &uc) < 0) {
138 		perror("swapcontext() failed");
139 		exit(-6);
140 	}
141 
142 	arg.func = doorstack;
143 	arg.text = "door_call()";
144 
145 	if ((door_fd = door_create(
146 	    (door_server_procedure_t *)(uintptr_t)get_stack_at_entry,
147 	    &arg, 0)) < 0) {
148 		perror("failed to create door");
149 		exit(-7);
150 	}
151 
152 	rc = door_call(door_fd, &da);
153 
154 	if (rc < 0) {
155 		perror("door call #1 failed");
156 		exit(-8);
157 	}
158 
159 	da.data_size += 5;
160 	rc = door_call(door_fd, &da);
161 
162 	if (rc < 0) {
163 		perror("door call #2 failed");
164 		exit(-9);
165 	}
166 
167 	(void) close(door_fd);
168 
169 	return (0);
170 #endif
171 }
172