ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Unix/NetBSD/paranoia.cpp
Revision: 1.2
Committed: 2005-07-04T06:09:59Z (19 years, 4 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +0 -0 lines
State: FILE REMOVED
Error occurred while calculating annotation data.
Log Message:
New paranoia checks that better match was SheepShaver is doing with threads
and sigaltstack(). At least, this time we force use of threads and also
alter r1 to see whether the current threading model relies on it or not.

File Contents

# Content
1 /*
2 * paranoia.cpp - Check undocumented features of the NetBSD kernel that
3 * SheepShaver relies upon
4 *
5 * SheepShaver (C) 1997-2005 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 #include <unistd.h>
23 #include <stdio.h>
24 #include <signal.h>
25 #include <errno.h>
26 #include <sys/ucontext.h>
27
28 #include "sysdeps.h"
29 #include "main.h"
30 #include "user_strings.h"
31
32 #define DEBUG 1
33 #include "debug.h"
34
35
36 // Constants
37 const int SIG_IRQ = SIGUSR2; // Signal to trigger on interrupt
38 const uint32 SIG_STACK_SIZE = 0x10000; // Size of signal stack
39
40 // Prototypes
41 extern "C" void *get_sp(void);
42 extern "C" void set_r2(uint32 val);
43 extern void paranoia_check(void);
44 static void sigusr2_handler(int sig, siginfo_t *sip, void *scp);
45
46 // Global variables
47 static void *sig_stack = NULL;
48
49 static int err = 0;
50 static void *sig_sp = NULL;
51 static void *sig_r4 = NULL;
52 static void *sig_sc_regs = NULL;
53 static uint32 sig_r2 = 0;
54
55
56 void paranoia_check(void)
57 {
58 char str[256];
59
60 D(bug("Paranoia checks...\n"));
61
62 // Create and install stack for signal handler
63 sig_stack = malloc(SIG_STACK_SIZE);
64 if (sig_stack == NULL) {
65 ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
66 exit(1);
67 }
68
69 struct sigaltstack old_stack;
70 struct sigaltstack new_stack;
71 new_stack.ss_sp = sig_stack;
72 new_stack.ss_flags = 0;
73 new_stack.ss_size = SIG_STACK_SIZE;
74 if (sigaltstack(&new_stack, &old_stack) < 0) {
75 sprintf(str, GetString(STR_SIGALTSTACK_ERR), strerror(errno));
76 ErrorAlert(str);
77 exit(1);
78 }
79
80 // Install SIG_IRQ signal handler
81 static struct sigaction old_action;
82 static struct sigaction sigusr2_action;
83 sigemptyset(&sigusr2_action.sa_mask);
84 sigusr2_action.sa_sigaction = sigusr2_handler;
85 sigusr2_action.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART;
86 if (sigaction(SIG_IRQ, &sigusr2_action, &old_action) < 0) {
87 sprintf(str, GetString(STR_SIGUSR2_INSTALL_ERR), strerror(errno));
88 ErrorAlert(str);
89 exit(1);
90 }
91
92 // Raise SIG_IRQ
93 set_r2(0xaffebad5);
94 raise(SIG_IRQ);
95
96 // Check error code
97 switch (err) {
98 case 1:
99 printf("FATAL: sigaltstack() doesn't seem to work (sp in signal handler was %08lx, expected %08lx..%08lx)\n", (uint32)sig_sp, (uint32)sig_stack, (uint32)sig_stack + SIG_STACK_SIZE);
100 break;
101 case 2:
102 printf("FATAL: r4 in signal handler (%08lx) doesn't point to stack\n", (uint32)sig_r4);
103 break;
104 case 4:
105 printf("FATAL: sc->regs in signal handler (%08lx) doesn't point to stack\n", (uint32)sig_sc_regs);
106 break;
107 case 5:
108 printf("FATAL: sc->regs->gpr[2] in signal handler (%08lx) doesn't have expected value (%08x)\n", (uint32)sig_r2, 0xaffebad5);
109 break;
110 }
111 if (err) {
112 printf("Maybe you need a different kernel?\n");
113 exit(1);
114 }
115
116 // Clean up
117 D(bug("...passed\n"));
118 sigaction(SIG_IRQ, &old_action, NULL);
119 sigaltstack(&old_stack, NULL);
120 free(sig_stack);
121 }
122
123 static void sigusr2_handler(int sig, siginfo_t *sip, void *scp)
124 {
125 ucontext_t *ucp = (ucontext_t *)scp;
126 D(bug("SIGUSR2 handler caught\n"));
127
128 // Check whether sigaltstack works
129 D(bug(" check whether sigaltstack() works\n"));
130 sig_sp = get_sp();
131 if (sig_sp < sig_stack || sig_sp >= ((uint8 *)sig_stack + SIG_STACK_SIZE)) {
132 err = 1;
133 return;
134 }
135
136 // Check whether r4 points to info on the stack
137 D(bug(" check whether r4 points to info on the stack\n"));
138 sig_r4 = ucp;
139 if (sig_r4 < sig_stack || sig_r4 >= ((uint8 *)sig_stack + SIG_STACK_SIZE)) {
140 err = 2;
141 return;
142 }
143
144 // Check whether context regs points to info on the stack
145 D(bug(" check whether context regs points to info on the stack\n"));
146 sig_sc_regs = ucp->uc_mcontext.__gregs;
147 if (sig_sc_regs < sig_stack || sig_sc_regs >= ((uint8 *)sig_stack + SIG_STACK_SIZE)) {
148 err = 4;
149 return;
150 }
151
152 // Check whether r2 still holds the value we set it to
153 D(bug(" check whether r2 still holds the value we set it to\n"));
154 sig_r2 = ucp->uc_mcontext.__gregs[_REG_R2];
155 if (sig_r2 != 0xaffebad5) {
156 err = 5;
157 return;
158 }
159 }