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
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

# User Rev Content
1 gbeauche 1.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     }