ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Unix/paranoia.cpp
Revision: 1.5
Committed: 2009-02-11T19:22:16Z (15 years, 9 months ago) by asvitkine
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +2 -2 lines
Log Message:
[Patch from Mike Sliczniak]

This first patch gets B2 and SS to build under Leopard and Tiger.

I tested this on a 32-bit intel 10.5.6 mac like so:

B2
./autogen.sh --disable-standalone-gui --enable-vosf --enable-sdl-video --enable-sdl-audio --enable-addressing=real --without-esd --without-gtk --without-mon --without-x

SS
./autogen.sh --disable-standalone-gui --enable-vosf -enable-sdl-video --disable-sdl-audio --enable-addressing=real --without-esd --without-gtk --without-mon --without-x --enable-jit

There is also a little tweak so that you can use sdl audio in SheepShaver when building for Mac OS X.

File Contents

# Content
1 /*
2 * paranoia.cpp - Check undocumented features of the underlying
3 * kernel that SheepShaver relies upon
4 *
5 * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 /*
23 * TODO
24 * - Check for nested signal handlers vs. sigaltstack()
25 */
26
27 #include <unistd.h>
28 #include <stdio.h>
29 #include <signal.h>
30 #include <errno.h>
31 #include <pthread.h>
32 #include <sys/types.h>
33 #include <sys/ucontext.h>
34
35 #include "sysdeps.h"
36 #include "sigregs.h"
37 #include "main.h"
38 #include "user_strings.h"
39
40 #define DEBUG 1
41 #include "debug.h"
42
43
44 // Constants
45 const uint32 SIG_STACK_SIZE = 0x10000; // Size of signal stack
46
47 // Prototypes
48 extern "C" void *get_sp(void);
49 extern "C" void *get_r2(void);
50 extern "C" void set_r2(void *);
51 extern "C" void *get_r13(void);
52 extern "C" void set_r13(void *);
53 extern void paranoia_check(void);
54 static void sigusr2_handler(int sig, siginfo_t *sip, void *scp);
55 static void *tick_func(void *);
56 static void *emul_func(void *);
57
58 // Global variables
59 static void *sig_stack = NULL;
60
61 static int err = 0;
62 static void *sig_sp = NULL;
63 static void *sig_r5 = NULL;
64 static int sig_sc_signal = 0;
65 static void *sig_sc_regs = NULL;
66 static uint32 sig_r2 = 0;
67
68 static pthread_t tick_thread;
69 static pthread_t emul_thread;
70 static volatile uint32 tick_thread_ready = 0;
71 static volatile uint32 emul_thread_regs[32] = { 0, };
72 static volatile uint32 &emul_thread_ready = emul_thread_regs[0];
73
74
75 void paranoia_check(void)
76 {
77 char str[256];
78
79 printf("Paranoia checks...\n");
80
81 // Create and install stack for signal handler
82 sig_stack = malloc(SIG_STACK_SIZE);
83 if (sig_stack == NULL) {
84 ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
85 exit(1);
86 }
87
88 stack_t old_stack;
89 stack_t new_stack;
90 new_stack.ss_sp = (char *)sig_stack;
91 new_stack.ss_flags = 0;
92 new_stack.ss_size = SIG_STACK_SIZE;
93 if (sigaltstack(&new_stack, &old_stack) < 0) {
94 sprintf(str, GetString(STR_SIGALTSTACK_ERR), strerror(errno));
95 ErrorAlert(str);
96 exit(1);
97 }
98
99 // Install SIGUSR2 signal handler
100 static struct sigaction old_action;
101 static struct sigaction sigusr2_action;
102 sigemptyset(&sigusr2_action.sa_mask);
103 sigusr2_action.sa_sigaction = sigusr2_handler;
104 sigusr2_action.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART;
105 if (sigaction(SIGUSR2, &sigusr2_action, &old_action) < 0) {
106 sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGUSR2", strerror(errno));
107 ErrorAlert(str);
108 exit(1);
109 }
110
111 // Start tick thread that will trigger only one SIGUSR2
112 pthread_create(&tick_thread, NULL, tick_func, NULL);
113
114 // Get my thread ID and execute MacOS thread function
115 emul_thread = pthread_self();
116 emul_func(NULL);
117
118 // Check error code
119 switch (err) {
120 case 1:
121 printf("FATAL: sigaltstack() doesn't seem to work (sp in signal handler was %p, expected %p..%p)\n", sig_sp, sig_stack, (uintptr)sig_stack + SIG_STACK_SIZE);
122 break;
123 case 2:
124 printf("FATAL: r5 in signal handler (%p) doesn't point to stack\n", sig_r5);
125 break;
126 case 3:
127 printf("FATAL: machine registers in signal handler (%p) doesn't point to stack\n", sig_sc_regs);
128 break;
129 case 4:
130 printf("FATAL: register file in signal handler is corrupted\n");
131 break;
132 }
133 if (err) {
134 printf("Maybe you need a different kernel?\n");
135 exit(1);
136 }
137
138 // Clean up
139 printf("...passed\n");
140 sigaction(SIGUSR2, &old_action, NULL);
141 sigaltstack(&old_stack, NULL);
142 free(sig_stack);
143 }
144
145 static void *tick_func(void *)
146 {
147 tick_thread_ready = true;
148
149 // Wait for emul thread to initialize
150 D(bug("[tick_thread] waiting for emul thread to initialize\n"));
151 while (!emul_thread_ready)
152 usleep(0);
153
154 // Trigger interrupt and terminate
155 D(bug("[tick_thread] trigger interrupt\n"));
156 pthread_kill(emul_thread, SIGUSR2);
157 return NULL;
158 }
159
160 static void *emul_func(void *)
161 {
162 // Wait for tick thread to initialize
163 D(bug("[emul_thread] waiting for tick thread to initialize\n"));
164 while (!tick_thread_ready)
165 usleep(0);
166
167 // Fill in register and wait for an interrupt from the tick thread
168 D(bug("[emul_thread] filling in registers and waiting for interrupt\n"));
169 #if defined(__APPLE__) && defined(__MACH__)
170 #define REG(n) "r" #n
171 #else
172 #define REG(n) #n
173 #endif
174 asm volatile ("stw " REG(2) ",2*4(%0)\n"
175 "mr " REG(2) ",%0\n"
176 #define SAVE_REG(n) \
177 "stw " REG(n) "," #n "*4(" REG(2) ")\n" \
178 "addi " REG(n) "," REG(2) ","#n"\n"
179 SAVE_REG(1)
180 SAVE_REG(3)
181 SAVE_REG(4)
182 SAVE_REG(5)
183 SAVE_REG(6)
184 SAVE_REG(7)
185 SAVE_REG(8)
186 SAVE_REG(9)
187 SAVE_REG(10)
188 SAVE_REG(11)
189 SAVE_REG(12)
190 SAVE_REG(13)
191 SAVE_REG(14)
192 SAVE_REG(15)
193 SAVE_REG(16)
194 SAVE_REG(17)
195 SAVE_REG(18)
196 SAVE_REG(19)
197 SAVE_REG(20)
198 SAVE_REG(21)
199 SAVE_REG(22)
200 SAVE_REG(23)
201 SAVE_REG(24)
202 SAVE_REG(25)
203 SAVE_REG(26)
204 SAVE_REG(27)
205 SAVE_REG(28)
206 SAVE_REG(29)
207 SAVE_REG(30)
208 SAVE_REG(31)
209 #undef SAVE_REG
210 " li " REG(0) ",1\n"
211 " stw " REG(0) ",0(" REG(2) ")\n" // regs[0] == emul_thread_ready
212 "0: lwz " REG(0) ",0(" REG(2) ")\n"
213 " cmpi 0," REG(0) ",0\n"
214 " bne+ 0b\n"
215 #define LOAD_REG(n) \
216 "lwz " REG(n) "," #n "*4(" REG(2) ")\n"
217 LOAD_REG(1)
218 LOAD_REG(3)
219 LOAD_REG(4)
220 LOAD_REG(5)
221 LOAD_REG(6)
222 LOAD_REG(7)
223 LOAD_REG(8)
224 LOAD_REG(9)
225 LOAD_REG(10)
226 LOAD_REG(11)
227 LOAD_REG(12)
228 LOAD_REG(13)
229 LOAD_REG(14)
230 LOAD_REG(15)
231 LOAD_REG(16)
232 LOAD_REG(17)
233 LOAD_REG(18)
234 LOAD_REG(19)
235 LOAD_REG(20)
236 LOAD_REG(21)
237 LOAD_REG(22)
238 LOAD_REG(23)
239 LOAD_REG(24)
240 LOAD_REG(25)
241 LOAD_REG(26)
242 LOAD_REG(27)
243 LOAD_REG(28)
244 LOAD_REG(29)
245 LOAD_REG(30)
246 LOAD_REG(31)
247 LOAD_REG(2)
248 #undef LOAD_REG
249 : : "r" ((uintptr)&emul_thread_regs[0]) : "r0");
250 #undef REG
251 }
252
253
254 void sigusr2_handler(int sig, siginfo_t *sip, void *scp)
255 {
256 machine_regs *r = MACHINE_REGISTERS(scp);
257
258 #ifdef SYSTEM_CLOBBERS_R2
259 // Restore pointer to Thread Local Storage
260 set_r2(TOC);
261 #endif
262
263 #ifdef SYSTEM_CLOBBERS_R13
264 // Restore pointer to .sdata section
265 set_r13(R13);
266 #endif
267
268 ucontext_t *ucp = (ucontext_t *)scp;
269 D(bug("SIGUSR2 caught\n"));
270
271 // Check whether sigaltstack works
272 sig_sp = get_sp();
273 if (sig_sp < sig_stack || sig_sp >= ((uint8 *)sig_stack + SIG_STACK_SIZE)) {
274 err = 1;
275 goto ret;
276 }
277
278 // Check whether r5 points to info on the stack
279 sig_r5 = ucp;
280 if (sig_r5 < sig_stack || sig_r5 >= ((uint8 *)sig_stack + SIG_STACK_SIZE)) {
281 err = 2;
282 goto ret;
283 }
284
285 // Check whether context regs points to info on the stack
286 sig_sc_regs = &r->gpr(0);
287 if (sig_sc_regs < sig_stack || sig_sc_regs >= ((uint8 *)sig_stack + SIG_STACK_SIZE)) {
288 err = 3;
289 goto ret;
290 }
291
292 // Check whether registers still hold the values we set them to
293 for (int n = 0; n < 32; n++) {
294 uint32 expected = (uintptr)&emul_thread_regs[0];
295 if (n == 0)
296 expected = 1;
297 else if (n != 2)
298 expected += n;
299 if (r->gpr(n) != expected) {
300 D(bug("Register corruption: r%d was %08x, expected %08x\n", n, r->gpr(n), expected));
301 err = 4;
302 goto ret;
303 }
304 }
305
306 ret:
307 // Tell emul_func() to exit
308 emul_thread_ready = false;
309 }
310
311
312 #ifdef TEST
313 void *TOC;
314 void *R13;
315
316 extern "C" void EmulOp(void *r, uint32 pc, int selector);
317 void EmulOp(void *r, uint32 pc, int selector)
318 {
319 }
320
321 extern "C" void check_load_invoc(uint32 type, int16 id, uint32 h);
322 void check_load_invoc(uint32 type, int16 id, uint32 h)
323 {
324 }
325
326 void ErrorAlert(const char *text)
327 {
328 printf(GetString(STR_SHELL_ERROR_PREFIX), text);
329 }
330
331 int main(void)
332 {
333 #ifdef SYSTEM_CLOBBERS_R2
334 // Get TOC pointer
335 TOC = get_r2();
336 #endif
337
338 #ifdef SYSTEM_CLOBBERS_R13
339 // Get r13 register
340 R13 = get_r13();
341 #endif
342
343 // Check some things
344 paranoia_check();
345 }
346 #endif