ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Unix/main_unix.cpp
Revision: 1.31
Committed: 2004-02-24T11:12:52Z (20 years, 3 months ago) by gbeauche
Branch: MAIN
Changes since 1.30: +7 -5 lines
Log Message:
Make SheepShaver work with OS 8.6 out-of-the-box with no extra patch for
the time being. i.e. ignore writes to the zero page when faking SCSIGlobals

File Contents

# Content
1 /*
2 * main_unix.cpp - Emulation core, Unix implementation
3 *
4 * SheepShaver (C) 1997-2004 Christian Bauer and Marc Hellwig
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 /*
22 * NOTES:
23 *
24 * See main_beos.cpp for a description of the three operating modes.
25 *
26 * In addition to that, we have to handle the fact that the MacOS ABI
27 * is slightly different from the SysV ABI used by Linux:
28 * - Stack frames are different (e.g. LR is stored in 8(r1) under
29 * MacOS, but in 4(r1) under Linux)
30 * - There is no TOC under Linux; r2 is free for the user
31 * - r13 is used as a small data pointer under Linux (but appearently
32 * it is not used this way? To be sure, we specify -msdata=none
33 * in the Makefile)
34 * - As there is no TOC, there are also no TVECTs under Linux;
35 * function pointers point directly to the function code
36 * The Execute*() functions have to account for this. Additionally, we
37 * cannot simply call MacOS functions by getting their TVECT and jumping
38 * to it. Such calls are done via the call_macos*() functions in
39 * asm_linux.S that create a MacOS stack frame, load the TOC pointer
40 * and put the arguments into the right registers.
41 *
42 * As on the BeOS, we have to specify an alternate signal stack because
43 * interrupts (and, under Linux, Low Memory accesses) may occur when r1
44 * is pointing to the Kernel Data or to Low Memory. There is one
45 * problem, however, due to the alternate signal stack being global to
46 * all signal handlers. Consider the following scenario:
47 * - The main thread is executing some native PPC MacOS code in
48 * MODE_NATIVE, running on the MacOS stack (somewhere in the Mac RAM).
49 * - A SIGUSR2 interrupt occurs. The kernel switches to the signal
50 * stack and starts executing the SIGUSR2 signal handler.
51 * - The signal handler sees the MODE_NATIVE and calls ppc_interrupt()
52 * to handle a native interrupt.
53 * - ppc_interrupt() sets r1 to point to the Kernel Data and jumps to
54 * the nanokernel.
55 * - The nanokernel accesses a Low Memory global (most likely one of
56 * the XLMs), a SIGSEGV occurs.
57 * - The kernel sees that r1 does not point to the signal stack and
58 * switches to the signal stack again, thus overwriting the data that
59 * the SIGUSR2 handler put there.
60 * The same problem arises when calling ExecutePPC() inside the MODE_EMUL_OP
61 * interrupt handler.
62 *
63 * The solution is to set the signal stack to a second, "extra" stack
64 * inside the SIGUSR2 handler before entering the Nanokernel or calling
65 * ExecutePPC (or any function that might cause a mode switch). The signal
66 * stack is restored before exiting the SIGUSR2 handler.
67 *
68 * TODO:
69 * check if SIGSEGV handler works for all registers (including FP!)
70 */
71
72 #include <unistd.h>
73 #include <fcntl.h>
74 #include <time.h>
75 #include <errno.h>
76 #include <stdio.h>
77 #include <stdlib.h>
78 #include <string.h>
79 #include <pthread.h>
80 #include <sys/mman.h>
81 #include <sys/ipc.h>
82 #include <sys/shm.h>
83 #include <signal.h>
84
85 #include "sysdeps.h"
86 #include "main.h"
87 #include "version.h"
88 #include "prefs.h"
89 #include "prefs_editor.h"
90 #include "cpu_emulation.h"
91 #include "emul_op.h"
92 #include "xlowmem.h"
93 #include "xpram.h"
94 #include "timer.h"
95 #include "adb.h"
96 #include "sony.h"
97 #include "disk.h"
98 #include "cdrom.h"
99 #include "scsi.h"
100 #include "video.h"
101 #include "audio.h"
102 #include "ether.h"
103 #include "serial.h"
104 #include "clip.h"
105 #include "extfs.h"
106 #include "sys.h"
107 #include "macos_util.h"
108 #include "rom_patches.h"
109 #include "user_strings.h"
110 #include "vm_alloc.h"
111 #include "sigsegv.h"
112 #include "thunks.h"
113
114 #define DEBUG 0
115 #include "debug.h"
116
117
118 #include <X11/Xlib.h>
119
120 #ifdef ENABLE_GTK
121 #include <gtk/gtk.h>
122 #endif
123
124 #ifdef ENABLE_XF86_DGA
125 #include <X11/Xlib.h>
126 #include <X11/Xutil.h>
127 #include <X11/extensions/xf86dga.h>
128 #endif
129
130 #ifdef ENABLE_MON
131 #include "mon.h"
132 #endif
133
134
135 // Enable emulation of unaligned lmw/stmw?
136 #define EMULATE_UNALIGNED_LOADSTORE_MULTIPLE 1
137
138 // Enable Execute68k() safety checks?
139 #define SAFE_EXEC_68K 0
140
141 // Interrupts in EMUL_OP mode?
142 #define INTERRUPTS_IN_EMUL_OP_MODE 1
143
144 // Interrupts in native mode?
145 #define INTERRUPTS_IN_NATIVE_MODE 1
146
147
148 // Constants
149 const char ROM_FILE_NAME[] = "ROM";
150 const char ROM_FILE_NAME2[] = "Mac OS ROM";
151
152 const uintptr RAM_BASE = 0x20000000; // Base address of RAM
153 const uint32 SIG_STACK_SIZE = 0x10000; // Size of signal stack
154
155
156 #if !EMULATED_PPC
157 struct sigregs {
158 uint32 nip;
159 uint32 link;
160 uint32 ctr;
161 uint32 msr;
162 uint32 xer;
163 uint32 ccr;
164 uint32 gpr[32];
165 };
166
167 #if defined(__linux__)
168 #include <sys/ucontext.h>
169 #define MACHINE_REGISTERS(scp) ((machine_regs *)(((ucontext_t *)scp)->uc_mcontext.regs))
170
171 struct machine_regs : public pt_regs
172 {
173 u_long & cr() { return pt_regs::ccr; }
174 uint32 cr() const { return pt_regs::ccr; }
175 uint32 lr() const { return pt_regs::link; }
176 uint32 ctr() const { return pt_regs::ctr; }
177 uint32 xer() const { return pt_regs::xer; }
178 uint32 msr() const { return pt_regs::msr; }
179 uint32 dar() const { return pt_regs::dar; }
180 u_long & pc() { return pt_regs::nip; }
181 uint32 pc() const { return pt_regs::nip; }
182 u_long & gpr(int i) { return pt_regs::gpr[i]; }
183 uint32 gpr(int i) const { return pt_regs::gpr[i]; }
184 };
185 #endif
186
187 #if defined(__APPLE__) && defined(__MACH__)
188 #include <sys/signal.h>
189 extern "C" int sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss);
190
191 #include <sys/ucontext.h>
192 #define MACHINE_REGISTERS(scp) ((machine_regs *)(((ucontext_t *)scp)->uc_mcontext))
193
194 struct machine_regs : public mcontext
195 {
196 uint32 & cr() { return ss.cr; }
197 uint32 cr() const { return ss.cr; }
198 uint32 lr() const { return ss.lr; }
199 uint32 ctr() const { return ss.ctr; }
200 uint32 xer() const { return ss.xer; }
201 uint32 msr() const { return ss.srr1; }
202 uint32 dar() const { return es.dar; }
203 uint32 & pc() { return ss.srr0; }
204 uint32 pc() const { return ss.srr0; }
205 uint32 & gpr(int i) { return (&ss.r0)[i]; }
206 uint32 gpr(int i) const { return (&ss.r0)[i]; }
207 };
208 #endif
209
210 static void build_sigregs(sigregs *srp, machine_regs *mrp)
211 {
212 srp->nip = mrp->pc();
213 srp->link = mrp->lr();
214 srp->ctr = mrp->ctr();
215 srp->msr = mrp->msr();
216 srp->xer = mrp->xer();
217 srp->ccr = mrp->cr();
218 for (int i = 0; i < 32; i++)
219 srp->gpr[i] = mrp->gpr(i);
220 }
221 #endif
222
223
224 // Global variables (exported)
225 #if !EMULATED_PPC
226 void *TOC; // Small data pointer (r13)
227 #endif
228 uint32 RAMBase; // Base address of Mac RAM
229 uint32 RAMSize; // Size of Mac RAM
230 uint32 KernelDataAddr; // Address of Kernel Data
231 uint32 BootGlobsAddr; // Address of BootGlobs structure at top of Mac RAM
232 uint32 PVR; // Theoretical PVR
233 int64 CPUClockSpeed; // Processor clock speed (Hz)
234 int64 BusClockSpeed; // Bus clock speed (Hz)
235
236
237 // Global variables
238 char *x_display_name = NULL; // X11 display name
239 Display *x_display = NULL; // X11 display handle
240 #ifdef X11_LOCK_TYPE
241 X11_LOCK_TYPE x_display_lock = X11_LOCK_INIT; // X11 display lock
242 #endif
243
244 static int zero_fd = 0; // FD of /dev/zero
245 static bool lm_area_mapped = false; // Flag: Low Memory area mmap()ped
246 static int kernel_area = -1; // SHM ID of Kernel Data area
247 static bool rom_area_mapped = false; // Flag: Mac ROM mmap()ped
248 static bool ram_area_mapped = false; // Flag: Mac RAM mmap()ped
249 static KernelData *kernel_data; // Pointer to Kernel Data
250 static EmulatorData *emulator_data;
251
252 static uint8 last_xpram[XPRAM_SIZE]; // Buffer for monitoring XPRAM changes
253
254 static bool nvram_thread_active = false; // Flag: NVRAM watchdog installed
255 static pthread_t nvram_thread; // NVRAM watchdog
256 static bool tick_thread_active = false; // Flag: MacOS thread installed
257 static pthread_t tick_thread; // 60Hz thread
258 static pthread_t emul_thread; // MacOS thread
259
260 static bool ready_for_signals = false; // Handler installed, signals can be sent
261 static int64 num_segv = 0; // Number of handled SEGV signals
262
263 static struct sigaction sigusr2_action; // Interrupt signal (of emulator thread)
264 #if EMULATED_PPC
265 static uintptr sig_stack = 0; // Stack for PowerPC interrupt routine
266 #else
267 static struct sigaction sigsegv_action; // Data access exception signal (of emulator thread)
268 static struct sigaction sigill_action; // Illegal instruction signal (of emulator thread)
269 static void *sig_stack = NULL; // Stack for signal handlers
270 static void *extra_stack = NULL; // Stack for SIGSEGV inside interrupt handler
271 static bool emul_thread_fatal = false; // Flag: MacOS thread crashed, tick thread shall dump debug output
272 static sigregs sigsegv_regs; // Register dump when crashed
273 static const char *crash_reason = NULL; // Reason of the crash (SIGSEGV, SIGBUS, SIGILL)
274 #endif
275
276 uint32 SheepMem::page_size; // Size of a native page
277 uintptr SheepMem::zero_page = 0; // Address of ro page filled in with zeros
278 uintptr SheepMem::base = 0x60000000; // Address of SheepShaver data
279 uintptr SheepMem::top = 0; // Top of SheepShaver data (stack like storage)
280
281
282 // Prototypes
283 static void Quit(void);
284 static void *emul_func(void *arg);
285 static void *nvram_func(void *arg);
286 static void *tick_func(void *arg);
287 #if EMULATED_PPC
288 static void sigusr2_handler(int sig);
289 extern void emul_ppc(uint32 start);
290 extern void init_emul_ppc(void);
291 extern void exit_emul_ppc(void);
292 #else
293 static void sigusr2_handler(int sig, siginfo_t *sip, void *scp);
294 static void sigsegv_handler(int sig, siginfo_t *sip, void *scp);
295 static void sigill_handler(int sig, siginfo_t *sip, void *scp);
296 #endif
297
298
299 // From asm_linux.S
300 #if !EMULATED_PPC
301 extern "C" void *get_toc(void);
302 extern "C" void *get_sp(void);
303 extern "C" void flush_icache_range(void *start, void *end);
304 extern "C" void jump_to_rom(uint32 entry, uint32 context);
305 extern "C" void quit_emulator(void);
306 extern "C" void execute_68k(uint32 pc, M68kRegisters *r);
307 extern "C" void ppc_interrupt(uint32 entry, uint32 kernel_data);
308 extern "C" int atomic_add(int *var, int v);
309 extern "C" int atomic_and(int *var, int v);
310 extern "C" int atomic_or(int *var, int v);
311 extern void paranoia_check(void);
312 #endif
313
314
315 #if EMULATED_PPC
316 /*
317 * Return signal stack base
318 */
319
320 uintptr SignalStackBase(void)
321 {
322 return sig_stack + SIG_STACK_SIZE;
323 }
324
325
326 /*
327 * Atomic operations
328 */
329
330 #if HAVE_SPINLOCKS
331 static spinlock_t atomic_ops_lock = SPIN_LOCK_UNLOCKED;
332 #else
333 #define spin_lock(LOCK)
334 #define spin_unlock(LOCK)
335 #endif
336
337 int atomic_add(int *var, int v)
338 {
339 spin_lock(&atomic_ops_lock);
340 int ret = *var;
341 *var += v;
342 spin_unlock(&atomic_ops_lock);
343 return ret;
344 }
345
346 int atomic_and(int *var, int v)
347 {
348 spin_lock(&atomic_ops_lock);
349 int ret = *var;
350 *var &= v;
351 spin_unlock(&atomic_ops_lock);
352 return ret;
353 }
354
355 int atomic_or(int *var, int v)
356 {
357 spin_lock(&atomic_ops_lock);
358 int ret = *var;
359 *var |= v;
360 spin_unlock(&atomic_ops_lock);
361 return ret;
362 }
363 #endif
364
365
366 /*
367 * Main program
368 */
369
370 static void usage(const char *prg_name)
371 {
372 printf("Usage: %s [OPTION...]\n", prg_name);
373 printf("\nUnix options:\n");
374 printf(" --display STRING\n X display to use\n");
375 PrefsPrintUsage();
376 exit(0);
377 }
378
379 int main(int argc, char **argv)
380 {
381 char str[256];
382 uint32 *boot_globs;
383 int16 i16;
384 int rom_fd;
385 FILE *proc_file;
386 const char *rom_path;
387 uint32 rom_size, actual;
388 uint8 *rom_tmp;
389 time_t now, expire;
390
391 // Initialize variables
392 RAMBase = 0;
393 tzset();
394
395 // Print some info
396 printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
397 printf(" %s\n", GetString(STR_ABOUT_TEXT2));
398
399 #if !EMULATED_PPC
400 // Get TOC pointer
401 TOC = get_toc();
402 #endif
403
404 #ifdef ENABLE_GTK
405 // Init GTK
406 gtk_set_locale();
407 gtk_init(&argc, &argv);
408 #endif
409
410 // Read preferences
411 PrefsInit(argc, argv);
412
413 // Parse command line arguments
414 for (int i=1; i<argc; i++) {
415 if (strcmp(argv[i], "--help") == 0) {
416 usage(argv[0]);
417 } else if (strcmp(argv[i], "--display") == 0) {
418 i++;
419 if (i < argc)
420 x_display_name = strdup(argv[i]);
421 } else if (argv[i][0] == '-') {
422 fprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
423 usage(argv[0]);
424 }
425 }
426
427 // Open display
428 x_display = XOpenDisplay(x_display_name);
429 if (x_display == NULL) {
430 char str[256];
431 sprintf(str, GetString(STR_NO_XSERVER_ERR), XDisplayName(x_display_name));
432 ErrorAlert(str);
433 goto quit;
434 }
435
436 #if defined(ENABLE_XF86_DGA) && !defined(ENABLE_MON)
437 // Fork out, so we can return from fullscreen mode when things get ugly
438 XF86DGAForkApp(DefaultScreen(x_display));
439 #endif
440
441 #ifdef ENABLE_MON
442 // Initialize mon
443 mon_init();
444 #endif
445
446 // Get system info
447 PVR = 0x00040000; // Default: 604
448 CPUClockSpeed = 100000000; // Default: 100MHz
449 BusClockSpeed = 100000000; // Default: 100MHz
450 #if EMULATED_PPC
451 PVR = 0x000c0000; // Default: 7400 (with AltiVec)
452 #else
453 proc_file = fopen("/proc/cpuinfo", "r");
454 if (proc_file) {
455 char line[256];
456 while(fgets(line, 255, proc_file)) {
457 // Read line
458 int len = strlen(line);
459 if (len == 0)
460 continue;
461 line[len-1] = 0;
462
463 // Parse line
464 int i;
465 char value[256];
466 if (sscanf(line, "cpu : %[0-9A-Za-a]", value) == 1) {
467 if (strcmp(value, "601") == 0)
468 PVR = 0x00010000;
469 else if (strcmp(value, "603") == 0)
470 PVR = 0x00030000;
471 else if (strcmp(value, "604") == 0)
472 PVR = 0x00040000;
473 else if (strcmp(value, "603e") == 0)
474 PVR = 0x00060000;
475 else if (strcmp(value, "603ev") == 0)
476 PVR = 0x00070000;
477 else if (strcmp(value, "604e") == 0)
478 PVR = 0x00090000;
479 else if (strcmp(value, "604ev5") == 0)
480 PVR = 0x000a0000;
481 else if (strcmp(value, "750") == 0)
482 PVR = 0x00080000;
483 else if (strcmp(value, "821") == 0)
484 PVR = 0x00320000;
485 else if (strcmp(value, "860") == 0)
486 PVR = 0x00500000;
487 else if (strcmp(value, "7400") == 0)
488 PVR = 0x000c0000;
489 else if (strcmp(value, "7410") == 0)
490 PVR = 0x800c0000;
491 else
492 printf("WARNING: Unknown CPU type '%s', assuming 604\n", value);
493 }
494 if (sscanf(line, "clock : %dMHz", &i) == 1)
495 CPUClockSpeed = BusClockSpeed = i * 1000000;
496 }
497 fclose(proc_file);
498 } else {
499 sprintf(str, GetString(STR_PROC_CPUINFO_WARN), strerror(errno));
500 WarningAlert(str);
501 }
502 #endif
503 D(bug("PVR: %08x (assumed)\n", PVR));
504
505 // Init system routines
506 SysInit();
507
508 // Show preferences editor
509 if (!PrefsFindBool("nogui"))
510 if (!PrefsEditor())
511 goto quit;
512
513 #if !EMULATED_PPC
514 // Check some things
515 paranoia_check();
516 #endif
517
518 // Open /dev/zero
519 zero_fd = open("/dev/zero", O_RDWR);
520 if (zero_fd < 0) {
521 sprintf(str, GetString(STR_NO_DEV_ZERO_ERR), strerror(errno));
522 ErrorAlert(str);
523 goto quit;
524 }
525
526 #ifndef PAGEZERO_HACK
527 // Create Low Memory area (0x0000..0x3000)
528 if (vm_acquire_fixed((char *)0, 0x3000) < 0) {
529 sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
530 ErrorAlert(str);
531 goto quit;
532 }
533 lm_area_mapped = true;
534 #endif
535
536 // Create areas for Kernel Data
537 kernel_area = shmget(IPC_PRIVATE, KERNEL_AREA_SIZE, 0600);
538 if (kernel_area == -1) {
539 sprintf(str, GetString(STR_KD_SHMGET_ERR), strerror(errno));
540 ErrorAlert(str);
541 goto quit;
542 }
543 if (shmat(kernel_area, (void *)KERNEL_DATA_BASE, 0) < 0) {
544 sprintf(str, GetString(STR_KD_SHMAT_ERR), strerror(errno));
545 ErrorAlert(str);
546 goto quit;
547 }
548 if (shmat(kernel_area, (void *)KERNEL_DATA2_BASE, 0) < 0) {
549 sprintf(str, GetString(STR_KD2_SHMAT_ERR), strerror(errno));
550 ErrorAlert(str);
551 goto quit;
552 }
553 kernel_data = (KernelData *)KERNEL_DATA_BASE;
554 emulator_data = &kernel_data->ed;
555 KernelDataAddr = KERNEL_DATA_BASE;
556 D(bug("Kernel Data at %p, Emulator Data at %p\n", kernel_data, emulator_data));
557
558 // Create area for SheepShaver data
559 if (!SheepMem::Init()) {
560 sprintf(str, GetString(STR_SHEEP_MEM_MMAP_ERR), strerror(errno));
561 ErrorAlert(str);
562 goto quit;
563 }
564
565 // Create area for Mac ROM
566 if (vm_acquire_fixed((char *)ROM_BASE, ROM_AREA_SIZE) < 0) {
567 sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno));
568 ErrorAlert(str);
569 goto quit;
570 }
571 #if !EMULATED_PPC
572 if (vm_protect((char *)ROM_BASE, ROM_AREA_SIZE, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) {
573 sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno));
574 ErrorAlert(str);
575 goto quit;
576 }
577 #endif
578 rom_area_mapped = true;
579 D(bug("ROM area at %08x\n", ROM_BASE));
580
581 // Create area for Mac RAM
582 RAMSize = PrefsFindInt32("ramsize");
583 if (RAMSize < 8*1024*1024) {
584 WarningAlert(GetString(STR_SMALL_RAM_WARN));
585 RAMSize = 8*1024*1024;
586 }
587
588 if (vm_acquire_fixed((char *)RAM_BASE, RAMSize) < 0) {
589 sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
590 ErrorAlert(str);
591 goto quit;
592 }
593 #if !EMULATED_PPC
594 if (vm_protect((char *)RAM_BASE, RAMSize, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) {
595 sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
596 ErrorAlert(str);
597 goto quit;
598 }
599 #endif
600 RAMBase = RAM_BASE;
601 ram_area_mapped = true;
602 D(bug("RAM area at %08x\n", RAMBase));
603
604 if (RAMBase > ROM_BASE) {
605 ErrorAlert(GetString(STR_RAM_HIGHER_THAN_ROM_ERR));
606 goto quit;
607 }
608
609 // Load Mac ROM
610 rom_path = PrefsFindString("rom");
611 rom_fd = open(rom_path ? rom_path : ROM_FILE_NAME, O_RDONLY);
612 if (rom_fd < 0) {
613 rom_fd = open(rom_path ? rom_path : ROM_FILE_NAME2, O_RDONLY);
614 if (rom_fd < 0) {
615 ErrorAlert(GetString(STR_NO_ROM_FILE_ERR));
616 goto quit;
617 }
618 }
619 printf(GetString(STR_READING_ROM_FILE));
620 rom_size = lseek(rom_fd, 0, SEEK_END);
621 lseek(rom_fd, 0, SEEK_SET);
622 rom_tmp = new uint8[ROM_SIZE];
623 actual = read(rom_fd, (void *)rom_tmp, ROM_SIZE);
624 close(rom_fd);
625
626 // Decode Mac ROM
627 if (!DecodeROM(rom_tmp, actual)) {
628 if (rom_size != 4*1024*1024) {
629 ErrorAlert(GetString(STR_ROM_SIZE_ERR));
630 goto quit;
631 } else {
632 ErrorAlert(GetString(STR_ROM_FILE_READ_ERR));
633 goto quit;
634 }
635 }
636 delete[] rom_tmp;
637
638 // Load NVRAM
639 XPRAMInit();
640
641 // Set boot volume
642 i16 = PrefsFindInt32("bootdrive");
643 XPRAM[0x1378] = i16 >> 8;
644 XPRAM[0x1379] = i16 & 0xff;
645 i16 = PrefsFindInt32("bootdriver");
646 XPRAM[0x137a] = i16 >> 8;
647 XPRAM[0x137b] = i16 & 0xff;
648
649 // Create BootGlobs at top of Mac memory
650 memset((void *)(RAMBase + RAMSize - 4096), 0, 4096);
651 BootGlobsAddr = RAMBase + RAMSize - 0x1c;
652 boot_globs = (uint32 *)BootGlobsAddr;
653 boot_globs[-5] = htonl(RAMBase + RAMSize); // MemTop
654 boot_globs[0] = htonl(RAMBase); // First RAM bank
655 boot_globs[1] = htonl(RAMSize);
656 boot_globs[2] = htonl((uint32)-1); // End of bank table
657
658 // Init thunks
659 if (!ThunksInit())
660 goto quit;
661
662 // Init drivers
663 SonyInit();
664 DiskInit();
665 CDROMInit();
666 SCSIInit();
667
668 // Init external file system
669 ExtFSInit();
670
671 // Init ADB
672 ADBInit();
673
674 // Init audio
675 AudioInit();
676
677 // Init network
678 EtherInit();
679
680 // Init serial ports
681 SerialInit();
682
683 // Init Time Manager
684 TimerInit();
685
686 // Init clipboard
687 ClipInit();
688
689 // Init video
690 if (!VideoInit())
691 goto quit;
692
693 // Install ROM patches
694 if (!PatchROM()) {
695 ErrorAlert(GetString(STR_UNSUPPORTED_ROM_TYPE_ERR));
696 goto quit;
697 }
698
699 // Clear caches (as we loaded and patched code) and write protect ROM
700 #if !EMULATED_PPC
701 MakeExecutable(0, (void *)ROM_BASE, ROM_AREA_SIZE);
702 #endif
703 vm_protect((char *)ROM_BASE, ROM_AREA_SIZE, VM_PAGE_READ | VM_PAGE_EXECUTE);
704
705 // Initialize Kernel Data
706 memset(kernel_data, 0, sizeof(KernelData));
707 if (ROMType == ROMTYPE_NEWWORLD) {
708 uintptr of_dev_tree = SheepMem::Reserve(4 * sizeof(uint32));
709 memset((void *)of_dev_tree, 0, 4 * sizeof(uint32));
710 uintptr vector_lookup_tbl = SheepMem::Reserve(128);
711 uintptr vector_mask_tbl = SheepMem::Reserve(64);
712 memset((uint8 *)kernel_data + 0xb80, 0x3d, 0x80);
713 memset((void *)vector_lookup_tbl, 0, 128);
714 memset((void *)vector_mask_tbl, 0, 64);
715 kernel_data->v[0xb80 >> 2] = htonl(ROM_BASE);
716 kernel_data->v[0xb84 >> 2] = htonl(of_dev_tree); // OF device tree base
717 kernel_data->v[0xb90 >> 2] = htonl(vector_lookup_tbl);
718 kernel_data->v[0xb94 >> 2] = htonl(vector_mask_tbl);
719 kernel_data->v[0xb98 >> 2] = htonl(ROM_BASE); // OpenPIC base
720 kernel_data->v[0xbb0 >> 2] = htonl(0); // ADB base
721 kernel_data->v[0xc20 >> 2] = htonl(RAMSize);
722 kernel_data->v[0xc24 >> 2] = htonl(RAMSize);
723 kernel_data->v[0xc30 >> 2] = htonl(RAMSize);
724 kernel_data->v[0xc34 >> 2] = htonl(RAMSize);
725 kernel_data->v[0xc38 >> 2] = htonl(0x00010020);
726 kernel_data->v[0xc3c >> 2] = htonl(0x00200001);
727 kernel_data->v[0xc40 >> 2] = htonl(0x00010000);
728 kernel_data->v[0xc50 >> 2] = htonl(RAMBase);
729 kernel_data->v[0xc54 >> 2] = htonl(RAMSize);
730 kernel_data->v[0xf60 >> 2] = htonl(PVR);
731 kernel_data->v[0xf64 >> 2] = htonl(CPUClockSpeed);
732 kernel_data->v[0xf68 >> 2] = htonl(BusClockSpeed);
733 kernel_data->v[0xf6c >> 2] = htonl(CPUClockSpeed);
734 } else {
735 kernel_data->v[0xc80 >> 2] = htonl(RAMSize);
736 kernel_data->v[0xc84 >> 2] = htonl(RAMSize);
737 kernel_data->v[0xc90 >> 2] = htonl(RAMSize);
738 kernel_data->v[0xc94 >> 2] = htonl(RAMSize);
739 kernel_data->v[0xc98 >> 2] = htonl(0x00010020);
740 kernel_data->v[0xc9c >> 2] = htonl(0x00200001);
741 kernel_data->v[0xca0 >> 2] = htonl(0x00010000);
742 kernel_data->v[0xcb0 >> 2] = htonl(RAMBase);
743 kernel_data->v[0xcb4 >> 2] = htonl(RAMSize);
744 kernel_data->v[0xf80 >> 2] = htonl(PVR);
745 kernel_data->v[0xf84 >> 2] = htonl(CPUClockSpeed);
746 kernel_data->v[0xf88 >> 2] = htonl(BusClockSpeed);
747 kernel_data->v[0xf8c >> 2] = htonl(CPUClockSpeed);
748 }
749
750 // Initialize extra low memory
751 D(bug("Initializing Low Memory...\n"));
752 memset(NULL, 0, 0x3000);
753 WriteMacInt32(XLM_SIGNATURE, FOURCC('B','a','a','h')); // Signature to detect SheepShaver
754 WriteMacInt32(XLM_KERNEL_DATA, KernelDataAddr); // For trap replacement routines
755 WriteMacInt32(XLM_PVR, PVR); // Theoretical PVR
756 WriteMacInt32(XLM_BUS_CLOCK, BusClockSpeed); // For DriverServicesLib patch
757 WriteMacInt16(XLM_EXEC_RETURN_OPCODE, M68K_EXEC_RETURN); // For Execute68k() (RTS from the executed 68k code will jump here and end 68k mode)
758 WriteMacInt32(XLM_ZERO_PAGE, SheepMem::ZeroPage()); // Pointer to read-only page with all bits set to 0
759 #if !EMULATED_PPC
760 WriteMacInt32(XLM_TOC, (uint32)TOC); // TOC pointer of emulator
761 #endif
762 WriteMacInt32(XLM_ETHER_INIT, NativeFunction(NATIVE_ETHER_INIT)); // DLPI ethernet driver functions
763 WriteMacInt32(XLM_ETHER_TERM, NativeFunction(NATIVE_ETHER_TERM));
764 WriteMacInt32(XLM_ETHER_OPEN, NativeFunction(NATIVE_ETHER_OPEN));
765 WriteMacInt32(XLM_ETHER_CLOSE, NativeFunction(NATIVE_ETHER_CLOSE));
766 WriteMacInt32(XLM_ETHER_WPUT, NativeFunction(NATIVE_ETHER_WPUT));
767 WriteMacInt32(XLM_ETHER_RSRV, NativeFunction(NATIVE_ETHER_RSRV));
768 WriteMacInt32(XLM_VIDEO_DOIO, NativeFunction(NATIVE_VIDEO_DO_DRIVER_IO));
769 D(bug("Low Memory initialized\n"));
770
771 // Start 60Hz thread
772 tick_thread_active = (pthread_create(&tick_thread, NULL, tick_func, NULL) == 0);
773 D(bug("Tick thread installed (%ld)\n", tick_thread));
774
775 // Start NVRAM watchdog thread
776 memcpy(last_xpram, XPRAM, XPRAM_SIZE);
777 nvram_thread_active = (pthread_create(&nvram_thread, NULL, nvram_func, NULL) == 0);
778 D(bug("NVRAM thread installed (%ld)\n", nvram_thread));
779
780 #if !EMULATED_PPC
781 // Create and install stacks for signal handlers
782 sig_stack = malloc(SIG_STACK_SIZE);
783 D(bug("Signal stack at %p\n", sig_stack));
784 if (sig_stack == NULL) {
785 ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
786 goto quit;
787 }
788 extra_stack = malloc(SIG_STACK_SIZE);
789 D(bug("Extra stack at %p\n", extra_stack));
790 if (extra_stack == NULL) {
791 ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
792 goto quit;
793 }
794 struct sigaltstack new_stack;
795 new_stack.ss_sp = sig_stack;
796 new_stack.ss_flags = 0;
797 new_stack.ss_size = SIG_STACK_SIZE;
798 if (sigaltstack(&new_stack, NULL) < 0) {
799 sprintf(str, GetString(STR_SIGALTSTACK_ERR), strerror(errno));
800 ErrorAlert(str);
801 goto quit;
802 }
803 #endif
804
805 #if !EMULATED_PPC
806 // Install SIGSEGV and SIGBUS handlers
807 sigemptyset(&sigsegv_action.sa_mask); // Block interrupts during SEGV handling
808 sigaddset(&sigsegv_action.sa_mask, SIGUSR2);
809 sigsegv_action.sa_sigaction = sigsegv_handler;
810 sigsegv_action.sa_flags = SA_ONSTACK | SA_SIGINFO;
811 #ifdef HAVE_SIGNAL_SA_RESTORER
812 sigsegv_action.sa_restorer = NULL;
813 #endif
814 if (sigaction(SIGSEGV, &sigsegv_action, NULL) < 0) {
815 sprintf(str, GetString(STR_SIGSEGV_INSTALL_ERR), strerror(errno));
816 ErrorAlert(str);
817 goto quit;
818 }
819 if (sigaction(SIGBUS, &sigsegv_action, NULL) < 0) {
820 sprintf(str, GetString(STR_SIGSEGV_INSTALL_ERR), strerror(errno));
821 ErrorAlert(str);
822 goto quit;
823 }
824
825 // Install SIGILL handler
826 sigemptyset(&sigill_action.sa_mask); // Block interrupts during ILL handling
827 sigaddset(&sigill_action.sa_mask, SIGUSR2);
828 sigill_action.sa_sigaction = sigill_handler;
829 sigill_action.sa_flags = SA_ONSTACK | SA_SIGINFO;
830 #ifdef HAVE_SIGNAL_SA_RESTORER
831 sigill_action.sa_restorer = NULL;
832 #endif
833 if (sigaction(SIGILL, &sigill_action, NULL) < 0) {
834 sprintf(str, GetString(STR_SIGILL_INSTALL_ERR), strerror(errno));
835 ErrorAlert(str);
836 goto quit;
837 }
838 #endif
839
840 #if !EMULATED_PPC
841 // Install interrupt signal handler
842 sigemptyset(&sigusr2_action.sa_mask);
843 sigusr2_action.sa_sigaction = sigusr2_handler;
844 sigusr2_action.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO;
845 #ifdef HAVE_SIGNAL_SA_RESTORER
846 sigusr2_action.sa_restorer = NULL;
847 #endif
848 if (sigaction(SIGUSR2, &sigusr2_action, NULL) < 0) {
849 sprintf(str, GetString(STR_SIGUSR2_INSTALL_ERR), strerror(errno));
850 ErrorAlert(str);
851 goto quit;
852 }
853 #endif
854
855 // Get my thread ID and execute MacOS thread function
856 emul_thread = pthread_self();
857 D(bug("MacOS thread is %ld\n", emul_thread));
858 emul_func(NULL);
859
860 quit:
861 Quit();
862 return 0;
863 }
864
865
866 /*
867 * Cleanup and quit
868 */
869
870 static void Quit(void)
871 {
872 #if EMULATED_PPC
873 // Exit PowerPC emulation
874 exit_emul_ppc();
875 #endif
876
877 // Stop 60Hz thread
878 if (tick_thread_active) {
879 pthread_cancel(tick_thread);
880 pthread_join(tick_thread, NULL);
881 }
882
883 // Stop NVRAM watchdog thread
884 if (nvram_thread_active) {
885 pthread_cancel(nvram_thread);
886 pthread_join(nvram_thread, NULL);
887 }
888
889 #if !EMULATED_PPC
890 // Uninstall SIGSEGV and SIGBUS handlers
891 sigemptyset(&sigsegv_action.sa_mask);
892 sigsegv_action.sa_handler = SIG_DFL;
893 sigsegv_action.sa_flags = 0;
894 sigaction(SIGSEGV, &sigsegv_action, NULL);
895 sigaction(SIGBUS, &sigsegv_action, NULL);
896
897 // Uninstall SIGILL handler
898 sigemptyset(&sigill_action.sa_mask);
899 sigill_action.sa_handler = SIG_DFL;
900 sigill_action.sa_flags = 0;
901 sigaction(SIGILL, &sigill_action, NULL);
902 #endif
903
904 // Save NVRAM
905 XPRAMExit();
906
907 // Exit clipboard
908 ClipExit();
909
910 // Exit Time Manager
911 TimerExit();
912
913 // Exit serial
914 SerialExit();
915
916 // Exit network
917 EtherExit();
918
919 // Exit audio
920 AudioExit();
921
922 // Exit ADB
923 ADBExit();
924
925 // Exit video
926 VideoExit();
927
928 // Exit external file system
929 ExtFSExit();
930
931 // Exit drivers
932 SCSIExit();
933 CDROMExit();
934 DiskExit();
935 SonyExit();
936
937 // Delete thunks
938 ThunksExit();
939
940 // Delete SheepShaver globals
941 SheepMem::Exit();
942
943 // Delete RAM area
944 if (ram_area_mapped)
945 vm_release((char *)RAM_BASE, RAMSize);
946
947 // Delete ROM area
948 if (rom_area_mapped)
949 vm_release((char *)ROM_BASE, ROM_AREA_SIZE);
950
951 // Delete Kernel Data area
952 if (kernel_area >= 0) {
953 shmdt((void *)KERNEL_DATA_BASE);
954 shmdt((void *)KERNEL_DATA2_BASE);
955 shmctl(kernel_area, IPC_RMID, NULL);
956 }
957
958 // Delete Low Memory area
959 if (lm_area_mapped)
960 munmap((char *)0x0000, 0x3000);
961
962 // Close /dev/zero
963 if (zero_fd > 0)
964 close(zero_fd);
965
966 // Exit system routines
967 SysExit();
968
969 // Exit preferences
970 PrefsExit();
971
972 #ifdef ENABLE_MON
973 // Exit mon
974 mon_exit();
975 #endif
976
977 // Close X11 server connection
978 if (x_display)
979 XCloseDisplay(x_display);
980
981 exit(0);
982 }
983
984
985 /*
986 * Jump into Mac ROM, start 680x0 emulator
987 */
988
989 #if EMULATED_PPC
990 void jump_to_rom(uint32 entry)
991 {
992 init_emul_ppc();
993 emul_ppc(entry);
994 }
995 #endif
996
997
998 /*
999 * Emulator thread function
1000 */
1001
1002 static void *emul_func(void *arg)
1003 {
1004 // We're now ready to receive signals
1005 ready_for_signals = true;
1006
1007 // Decrease priority, so more time-critical things like audio will work better
1008 nice(1);
1009
1010 // Jump to ROM boot routine
1011 D(bug("Jumping to ROM\n"));
1012 #if EMULATED_PPC
1013 jump_to_rom(ROM_BASE + 0x310000);
1014 #else
1015 jump_to_rom(ROM_BASE + 0x310000, (uint32)emulator_data);
1016 #endif
1017 D(bug("Returned from ROM\n"));
1018
1019 // We're no longer ready to receive signals
1020 ready_for_signals = false;
1021 return NULL;
1022 }
1023
1024
1025 #if !EMULATED_PPC
1026 /*
1027 * Execute 68k subroutine (must be ended with RTS)
1028 * This must only be called by the emul_thread when in EMUL_OP mode
1029 * r->a[7] is unused, the routine runs on the caller's stack
1030 */
1031
1032 void Execute68k(uint32 pc, M68kRegisters *r)
1033 {
1034 #if SAFE_EXEC_68K
1035 if (ReadMacInt32(XLM_RUN_MODE) != MODE_EMUL_OP)
1036 printf("FATAL: Execute68k() not called from EMUL_OP mode\n");
1037 if (!pthread_equal(pthread_self(), emul_thread))
1038 printf("FATAL: Execute68k() not called from emul_thread\n");
1039 #endif
1040 execute_68k(pc, r);
1041 }
1042
1043
1044 /*
1045 * Execute 68k A-Trap from EMUL_OP routine
1046 * r->a[7] is unused, the routine runs on the caller's stack
1047 */
1048
1049 void Execute68kTrap(uint16 trap, M68kRegisters *r)
1050 {
1051 uint16 proc[2] = {trap, M68K_RTS};
1052 Execute68k((uint32)proc, r);
1053 }
1054 #endif
1055
1056
1057 /*
1058 * Quit emulator (cause return from jump_to_rom)
1059 */
1060
1061 void QuitEmulator(void)
1062 {
1063 #if EMULATED_PPC
1064 Quit();
1065 #else
1066 quit_emulator();
1067 #endif
1068 }
1069
1070
1071 /*
1072 * Pause/resume emulator
1073 */
1074
1075 void PauseEmulator(void)
1076 {
1077 pthread_kill(emul_thread, SIGSTOP);
1078 }
1079
1080 void ResumeEmulator(void)
1081 {
1082 pthread_kill(emul_thread, SIGCONT);
1083 }
1084
1085
1086 /*
1087 * Dump 68k registers
1088 */
1089
1090 void Dump68kRegs(M68kRegisters *r)
1091 {
1092 // Display 68k registers
1093 for (int i=0; i<8; i++) {
1094 printf("d%d: %08x", i, r->d[i]);
1095 if (i == 3 || i == 7)
1096 printf("\n");
1097 else
1098 printf(", ");
1099 }
1100 for (int i=0; i<8; i++) {
1101 printf("a%d: %08x", i, r->a[i]);
1102 if (i == 3 || i == 7)
1103 printf("\n");
1104 else
1105 printf(", ");
1106 }
1107 }
1108
1109
1110 /*
1111 * Make code executable
1112 */
1113
1114 void MakeExecutable(int dummy, void *start, uint32 length)
1115 {
1116 if (((uintptr)start >= ROM_BASE) && ((uintptr)start < (ROM_BASE + ROM_SIZE)))
1117 return;
1118 #if EMULATED_PPC
1119 FlushCodeCache((uintptr)start, (uintptr)start + length);
1120 #else
1121 flush_icache_range(start, (void *)((uintptr)start + length));
1122 #endif
1123 }
1124
1125
1126 /*
1127 * Patch things after system startup (gets called by disk driver accRun routine)
1128 */
1129
1130 void PatchAfterStartup(void)
1131 {
1132 ExecuteNative(NATIVE_VIDEO_INSTALL_ACCEL);
1133 InstallExtFS();
1134 }
1135
1136
1137 /*
1138 * NVRAM watchdog thread (saves NVRAM every minute)
1139 */
1140
1141 static void *nvram_func(void *arg)
1142 {
1143 struct timespec req = {60, 0}; // 1 minute
1144
1145 for (;;) {
1146 pthread_testcancel();
1147 nanosleep(&req, NULL);
1148 pthread_testcancel();
1149 if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) {
1150 memcpy(last_xpram, XPRAM, XPRAM_SIZE);
1151 SaveXPRAM();
1152 }
1153 }
1154 return NULL;
1155 }
1156
1157
1158 /*
1159 * 60Hz thread (really 60.15Hz)
1160 */
1161
1162 static void *tick_func(void *arg)
1163 {
1164 int tick_counter = 0;
1165 struct timespec req = {0, 16625000};
1166
1167 for (;;) {
1168
1169 // Wait
1170 nanosleep(&req, NULL);
1171
1172 #if !EMULATED_PPC
1173 // Did we crash?
1174 if (emul_thread_fatal) {
1175
1176 // Yes, dump registers
1177 sigregs *r = &sigsegv_regs;
1178 char str[256];
1179 if (crash_reason == NULL)
1180 crash_reason = "SIGSEGV";
1181 sprintf(str, "%s\n"
1182 " pc %08lx lr %08lx ctr %08lx msr %08lx\n"
1183 " xer %08lx cr %08lx \n"
1184 " r0 %08lx r1 %08lx r2 %08lx r3 %08lx\n"
1185 " r4 %08lx r5 %08lx r6 %08lx r7 %08lx\n"
1186 " r8 %08lx r9 %08lx r10 %08lx r11 %08lx\n"
1187 " r12 %08lx r13 %08lx r14 %08lx r15 %08lx\n"
1188 " r16 %08lx r17 %08lx r18 %08lx r19 %08lx\n"
1189 " r20 %08lx r21 %08lx r22 %08lx r23 %08lx\n"
1190 " r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n"
1191 " r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n",
1192 crash_reason,
1193 r->nip, r->link, r->ctr, r->msr,
1194 r->xer, r->ccr,
1195 r->gpr[0], r->gpr[1], r->gpr[2], r->gpr[3],
1196 r->gpr[4], r->gpr[5], r->gpr[6], r->gpr[7],
1197 r->gpr[8], r->gpr[9], r->gpr[10], r->gpr[11],
1198 r->gpr[12], r->gpr[13], r->gpr[14], r->gpr[15],
1199 r->gpr[16], r->gpr[17], r->gpr[18], r->gpr[19],
1200 r->gpr[20], r->gpr[21], r->gpr[22], r->gpr[23],
1201 r->gpr[24], r->gpr[25], r->gpr[26], r->gpr[27],
1202 r->gpr[28], r->gpr[29], r->gpr[30], r->gpr[31]);
1203 printf(str);
1204 VideoQuitFullScreen();
1205
1206 #ifdef ENABLE_MON
1207 // Start up mon in real-mode
1208 printf("Welcome to the sheep factory.\n");
1209 char *arg[4] = {"mon", "-m", "-r", NULL};
1210 mon(3, arg);
1211 #endif
1212 return NULL;
1213 }
1214 #endif
1215
1216 // Pseudo Mac 1Hz interrupt, update local time
1217 if (++tick_counter > 60) {
1218 tick_counter = 0;
1219 WriteMacInt32(0x20c, TimerDateTime());
1220 }
1221
1222 // Trigger 60Hz interrupt
1223 if (ReadMacInt32(XLM_IRQ_NEST) == 0) {
1224 SetInterruptFlag(INTFLAG_VIA);
1225 TriggerInterrupt();
1226 }
1227 }
1228 return NULL;
1229 }
1230
1231
1232 /*
1233 * Pthread configuration
1234 */
1235
1236 void Set_pthread_attr(pthread_attr_t *attr, int priority)
1237 {
1238 #ifdef HAVE_PTHREADS
1239 pthread_attr_init(attr);
1240 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
1241 // Some of these only work for superuser
1242 if (geteuid() == 0) {
1243 pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
1244 pthread_attr_setschedpolicy(attr, SCHED_FIFO);
1245 struct sched_param fifo_param;
1246 fifo_param.sched_priority = ((sched_get_priority_min(SCHED_FIFO) +
1247 sched_get_priority_max(SCHED_FIFO)) / 2 +
1248 priority);
1249 pthread_attr_setschedparam(attr, &fifo_param);
1250 }
1251 if (pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM) != 0) {
1252 #ifdef PTHREAD_SCOPE_BOUND_NP
1253 // If system scope is not available (eg. we're not running
1254 // with CAP_SCHED_MGT capability on an SGI box), try bound
1255 // scope. It exposes pthread scheduling to the kernel,
1256 // without setting realtime priority.
1257 pthread_attr_setscope(attr, PTHREAD_SCOPE_BOUND_NP);
1258 #endif
1259 }
1260 #endif
1261 #endif
1262 }
1263
1264
1265 /*
1266 * Mutexes
1267 */
1268
1269 #ifdef HAVE_PTHREADS
1270
1271 struct B2_mutex {
1272 B2_mutex() {
1273 pthread_mutexattr_t attr;
1274 pthread_mutexattr_init(&attr);
1275 // Initialize the mutex for priority inheritance --
1276 // required for accurate timing.
1277 #ifdef HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL
1278 pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
1279 #endif
1280 #if defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE) && defined(PTHREAD_MUTEX_NORMAL)
1281 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
1282 #endif
1283 #ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED
1284 pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
1285 #endif
1286 pthread_mutex_init(&m, &attr);
1287 pthread_mutexattr_destroy(&attr);
1288 }
1289 ~B2_mutex() {
1290 pthread_mutex_trylock(&m); // Make sure it's locked before
1291 pthread_mutex_unlock(&m); // unlocking it.
1292 pthread_mutex_destroy(&m);
1293 }
1294 pthread_mutex_t m;
1295 };
1296
1297 B2_mutex *B2_create_mutex(void)
1298 {
1299 return new B2_mutex;
1300 }
1301
1302 void B2_lock_mutex(B2_mutex *mutex)
1303 {
1304 pthread_mutex_lock(&mutex->m);
1305 }
1306
1307 void B2_unlock_mutex(B2_mutex *mutex)
1308 {
1309 pthread_mutex_unlock(&mutex->m);
1310 }
1311
1312 void B2_delete_mutex(B2_mutex *mutex)
1313 {
1314 delete mutex;
1315 }
1316
1317 #else
1318
1319 struct B2_mutex {
1320 int dummy;
1321 };
1322
1323 B2_mutex *B2_create_mutex(void)
1324 {
1325 return new B2_mutex;
1326 }
1327
1328 void B2_lock_mutex(B2_mutex *mutex)
1329 {
1330 }
1331
1332 void B2_unlock_mutex(B2_mutex *mutex)
1333 {
1334 }
1335
1336 void B2_delete_mutex(B2_mutex *mutex)
1337 {
1338 delete mutex;
1339 }
1340
1341 #endif
1342
1343
1344 /*
1345 * Trigger signal USR2 from another thread
1346 */
1347
1348 #if !EMULATED_PPC || ASYNC_IRQ
1349 void TriggerInterrupt(void)
1350 {
1351 if (ready_for_signals)
1352 pthread_kill(emul_thread, SIGUSR2);
1353 }
1354 #endif
1355
1356
1357 /*
1358 * Interrupt flags (must be handled atomically!)
1359 */
1360
1361 volatile uint32 InterruptFlags = 0;
1362
1363 void SetInterruptFlag(uint32 flag)
1364 {
1365 atomic_or((int *)&InterruptFlags, flag);
1366 }
1367
1368 void ClearInterruptFlag(uint32 flag)
1369 {
1370 atomic_and((int *)&InterruptFlags, ~flag);
1371 }
1372
1373
1374 /*
1375 * Disable interrupts
1376 */
1377
1378 void DisableInterrupt(void)
1379 {
1380 atomic_add((int *)XLM_IRQ_NEST, 1);
1381 }
1382
1383
1384 /*
1385 * Enable interrupts
1386 */
1387
1388 void EnableInterrupt(void)
1389 {
1390 atomic_add((int *)XLM_IRQ_NEST, -1);
1391 }
1392
1393
1394 /*
1395 * USR2 handler
1396 */
1397
1398 #if EMULATED_PPC
1399 static void sigusr2_handler(int sig)
1400 {
1401 #if ASYNC_IRQ
1402 extern void HandleInterrupt(void);
1403 HandleInterrupt();
1404 #endif
1405 }
1406 #else
1407 static void sigusr2_handler(int sig, siginfo_t *sip, void *scp)
1408 {
1409 machine_regs *r = MACHINE_REGISTERS(scp);
1410
1411 // Do nothing if interrupts are disabled
1412 if (*(int32 *)XLM_IRQ_NEST > 0)
1413 return;
1414
1415 // Disable MacOS stack sniffer
1416 WriteMacInt32(0x110, 0);
1417
1418 // Interrupt action depends on current run mode
1419 switch (ReadMacInt32(XLM_RUN_MODE)) {
1420 case MODE_68K:
1421 // 68k emulator active, trigger 68k interrupt level 1
1422 WriteMacInt16(ntohl(kernel_data->v[0x67c >> 2]), 1);
1423 r->cr() |= ntohl(kernel_data->v[0x674 >> 2]);
1424 break;
1425
1426 #if INTERRUPTS_IN_NATIVE_MODE
1427 case MODE_NATIVE:
1428 // 68k emulator inactive, in nanokernel?
1429 if (r->gpr(1) != KernelDataAddr) {
1430 // Prepare for 68k interrupt level 1
1431 WriteMacInt16(ntohl(kernel_data->v[0x67c >> 2]), 1);
1432 WriteMacInt32(ntohl(kernel_data->v[0x658 >> 2]) + 0xdc, ReadMacInt32(ntohl(kernel_data->v[0x658 >> 2]) + 0xdc) | ntohl(kernel_data->v[0x674 >> 2]));
1433
1434 // Execute nanokernel interrupt routine (this will activate the 68k emulator)
1435 atomic_add((int32 *)XLM_IRQ_NEST, 1);
1436 if (ROMType == ROMTYPE_NEWWORLD)
1437 ppc_interrupt(ROM_BASE + 0x312b1c, KernelDataAddr);
1438 else
1439 ppc_interrupt(ROM_BASE + 0x312a3c, KernelDataAddr);
1440 }
1441 break;
1442 #endif
1443
1444 #if INTERRUPTS_IN_EMUL_OP_MODE
1445 case MODE_EMUL_OP:
1446 // 68k emulator active, within EMUL_OP routine, execute 68k interrupt routine directly when interrupt level is 0
1447 if ((ReadMacInt32(XLM_68K_R25) & 7) == 0) {
1448
1449 // Set extra stack for SIGSEGV handler
1450 struct sigaltstack new_stack;
1451 new_stack.ss_sp = extra_stack;
1452 new_stack.ss_flags = 0;
1453 new_stack.ss_size = SIG_STACK_SIZE;
1454 sigaltstack(&new_stack, NULL);
1455 #if 1
1456 // Execute full 68k interrupt routine
1457 M68kRegisters r;
1458 uint32 old_r25 = ReadMacInt32(XLM_68K_R25); // Save interrupt level
1459 WriteMacInt32(XLM_68K_R25, 0x21); // Execute with interrupt level 1
1460 static const uint16 proc[] = {
1461 0x3f3c, 0x0000, // move.w #$0000,-(sp) (fake format word)
1462 0x487a, 0x000a, // pea @1(pc) (return address)
1463 0x40e7, // move sr,-(sp) (saved SR)
1464 0x2078, 0x0064, // move.l $64,a0
1465 0x4ed0, // jmp (a0)
1466 M68K_RTS // @1
1467 };
1468 Execute68k((uint32)proc, &r);
1469 WriteMacInt32(XLM_68K_R25, old_r25); // Restore interrupt level
1470 #else
1471 // Only update cursor
1472 if (HasMacStarted()) {
1473 if (InterruptFlags & INTFLAG_VIA) {
1474 ClearInterruptFlag(INTFLAG_VIA);
1475 ADBInterrupt();
1476 ExecuteNative(NATIVE_VIDEO_VBL);
1477 }
1478 }
1479 #endif
1480 // Reset normal signal stack
1481 new_stack.ss_sp = sig_stack;
1482 new_stack.ss_flags = 0;
1483 new_stack.ss_size = SIG_STACK_SIZE;
1484 sigaltstack(&new_stack, NULL);
1485 }
1486 break;
1487 #endif
1488 }
1489 }
1490 #endif
1491
1492
1493 /*
1494 * SIGSEGV handler
1495 */
1496
1497 #if !EMULATED_PPC
1498 static void sigsegv_handler(int sig, siginfo_t *sip, void *scp)
1499 {
1500 machine_regs *r = MACHINE_REGISTERS(scp);
1501
1502 // Get effective address
1503 uint32 addr = r->dar();
1504
1505 #if ENABLE_VOSF
1506 // Handle screen fault.
1507 extern bool Screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction);
1508 if (Screen_fault_handler((sigsegv_address_t)addr, (sigsegv_address_t)r->pc()))
1509 return;
1510 #endif
1511
1512 num_segv++;
1513
1514 // Fault in Mac ROM or RAM?
1515 bool mac_fault = (r->pc() >= ROM_BASE) && (r->pc() < (ROM_BASE + ROM_AREA_SIZE)) || (r->pc() >= RAMBase) && (r->pc() < (RAMBase + RAMSize));
1516 if (mac_fault) {
1517
1518 // "VM settings" during MacOS 8 installation
1519 if (r->pc() == ROM_BASE + 0x488160 && r->gpr(20) == 0xf8000000) {
1520 r->pc() += 4;
1521 r->gpr(8) = 0;
1522 return;
1523
1524 // MacOS 8.5 installation
1525 } else if (r->pc() == ROM_BASE + 0x488140 && r->gpr(16) == 0xf8000000) {
1526 r->pc() += 4;
1527 r->gpr(8) = 0;
1528 return;
1529
1530 // MacOS 8 serial drivers on startup
1531 } else if (r->pc() == ROM_BASE + 0x48e080 && (r->gpr(8) == 0xf3012002 || r->gpr(8) == 0xf3012000)) {
1532 r->pc() += 4;
1533 r->gpr(8) = 0;
1534 return;
1535
1536 // MacOS 8.1 serial drivers on startup
1537 } else if (r->pc() == ROM_BASE + 0x48c5e0 && (r->gpr(20) == 0xf3012002 || r->gpr(20) == 0xf3012000)) {
1538 r->pc() += 4;
1539 return;
1540 } else if (r->pc() == ROM_BASE + 0x4a10a0 && (r->gpr(20) == 0xf3012002 || r->gpr(20) == 0xf3012000)) {
1541 r->pc() += 4;
1542 return;
1543 }
1544
1545 // Get opcode and divide into fields
1546 uint32 opcode = *((uint32 *)r->pc());
1547 uint32 primop = opcode >> 26;
1548 uint32 exop = (opcode >> 1) & 0x3ff;
1549 uint32 ra = (opcode >> 16) & 0x1f;
1550 uint32 rb = (opcode >> 11) & 0x1f;
1551 uint32 rd = (opcode >> 21) & 0x1f;
1552 int32 imm = (int16)(opcode & 0xffff);
1553
1554 // Analyze opcode
1555 enum {
1556 TYPE_UNKNOWN,
1557 TYPE_LOAD,
1558 TYPE_STORE
1559 } transfer_type = TYPE_UNKNOWN;
1560 enum {
1561 SIZE_UNKNOWN,
1562 SIZE_BYTE,
1563 SIZE_HALFWORD,
1564 SIZE_WORD
1565 } transfer_size = SIZE_UNKNOWN;
1566 enum {
1567 MODE_UNKNOWN,
1568 MODE_NORM,
1569 MODE_U,
1570 MODE_X,
1571 MODE_UX
1572 } addr_mode = MODE_UNKNOWN;
1573 switch (primop) {
1574 case 31:
1575 switch (exop) {
1576 case 23: // lwzx
1577 transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
1578 case 55: // lwzux
1579 transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
1580 case 87: // lbzx
1581 transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break;
1582 case 119: // lbzux
1583 transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break;
1584 case 151: // stwx
1585 transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
1586 case 183: // stwux
1587 transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
1588 case 215: // stbx
1589 transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break;
1590 case 247: // stbux
1591 transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break;
1592 case 279: // lhzx
1593 transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break;
1594 case 311: // lhzux
1595 transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break;
1596 case 343: // lhax
1597 transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break;
1598 case 375: // lhaux
1599 transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break;
1600 case 407: // sthx
1601 transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break;
1602 case 439: // sthux
1603 transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break;
1604 }
1605 break;
1606
1607 case 32: // lwz
1608 transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
1609 case 33: // lwzu
1610 transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
1611 case 34: // lbz
1612 transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break;
1613 case 35: // lbzu
1614 transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break;
1615 case 36: // stw
1616 transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
1617 case 37: // stwu
1618 transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
1619 case 38: // stb
1620 transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break;
1621 case 39: // stbu
1622 transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break;
1623 case 40: // lhz
1624 transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break;
1625 case 41: // lhzu
1626 transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
1627 case 42: // lha
1628 transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break;
1629 case 43: // lhau
1630 transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
1631 case 44: // sth
1632 transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break;
1633 case 45: // sthu
1634 transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
1635 #if EMULATE_UNALIGNED_LOADSTORE_MULTIPLE
1636 case 46: // lmw
1637 if ((addr % 4) != 0) {
1638 uint32 ea = addr;
1639 D(bug("WARNING: unaligned lmw to EA=%08x from IP=%08x\n", ea, r->pc()));
1640 for (int i = rd; i <= 31; i++) {
1641 r->gpr(i) = ReadMacInt32(ea);
1642 ea += 4;
1643 }
1644 r->pc() += 4;
1645 goto rti;
1646 }
1647 break;
1648 case 47: // stmw
1649 if ((addr % 4) != 0) {
1650 uint32 ea = addr;
1651 D(bug("WARNING: unaligned stmw to EA=%08x from IP=%08x\n", ea, r->pc()));
1652 for (int i = rd; i <= 31; i++) {
1653 WriteMacInt32(ea, r->gpr(i));
1654 ea += 4;
1655 }
1656 r->pc() += 4;
1657 goto rti;
1658 }
1659 break;
1660 #endif
1661 }
1662
1663 // Ignore ROM writes (including to the zero page, which is read-only)
1664 if (transfer_type == TYPE_STORE &&
1665 ((addr >= ROM_BASE && addr < ROM_BASE + ROM_SIZE) ||
1666 (addr >= SheepMem::ZeroPage() && addr < SheepMem::ZeroPage() + SheepMem::PageSize()))) {
1667 // D(bug("WARNING: %s write access to ROM at %08lx, pc %08lx\n", transfer_size == SIZE_BYTE ? "Byte" : transfer_size == SIZE_HALFWORD ? "Halfword" : "Word", addr, r->pc()));
1668 if (addr_mode == MODE_U || addr_mode == MODE_UX)
1669 r->gpr(ra) = addr;
1670 r->pc() += 4;
1671 goto rti;
1672 }
1673
1674 // Ignore illegal memory accesses?
1675 if (PrefsFindBool("ignoresegv")) {
1676 if (addr_mode == MODE_U || addr_mode == MODE_UX)
1677 r->gpr(ra) = addr;
1678 if (transfer_type == TYPE_LOAD)
1679 r->gpr(rd) = 0;
1680 r->pc() += 4;
1681 goto rti;
1682 }
1683
1684 // In GUI mode, show error alert
1685 if (!PrefsFindBool("nogui")) {
1686 char str[256];
1687 if (transfer_type == TYPE_LOAD || transfer_type == TYPE_STORE)
1688 sprintf(str, GetString(STR_MEM_ACCESS_ERR), transfer_size == SIZE_BYTE ? "byte" : transfer_size == SIZE_HALFWORD ? "halfword" : "word", transfer_type == TYPE_LOAD ? GetString(STR_MEM_ACCESS_READ) : GetString(STR_MEM_ACCESS_WRITE), addr, r->pc(), r->gpr(24), r->gpr(1));
1689 else
1690 sprintf(str, GetString(STR_UNKNOWN_SEGV_ERR), r->pc(), r->gpr(24), r->gpr(1), opcode);
1691 ErrorAlert(str);
1692 QuitEmulator();
1693 return;
1694 }
1695 }
1696
1697 // For all other errors, jump into debugger (sort of...)
1698 crash_reason = (sig == SIGBUS) ? "SIGBUS" : "SIGSEGV";
1699 if (!ready_for_signals) {
1700 printf("%s\n");
1701 printf(" sigcontext %p, machine_regs %p\n", scp, r);
1702 printf(
1703 " pc %08lx lr %08lx ctr %08lx msr %08lx\n"
1704 " xer %08lx cr %08lx \n"
1705 " r0 %08lx r1 %08lx r2 %08lx r3 %08lx\n"
1706 " r4 %08lx r5 %08lx r6 %08lx r7 %08lx\n"
1707 " r8 %08lx r9 %08lx r10 %08lx r11 %08lx\n"
1708 " r12 %08lx r13 %08lx r14 %08lx r15 %08lx\n"
1709 " r16 %08lx r17 %08lx r18 %08lx r19 %08lx\n"
1710 " r20 %08lx r21 %08lx r22 %08lx r23 %08lx\n"
1711 " r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n"
1712 " r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n",
1713 crash_reason,
1714 r->pc(), r->lr(), r->ctr(), r->msr(),
1715 r->xer(), r->cr(),
1716 r->gpr(0), r->gpr(1), r->gpr(2), r->gpr(3),
1717 r->gpr(4), r->gpr(5), r->gpr(6), r->gpr(7),
1718 r->gpr(8), r->gpr(9), r->gpr(10), r->gpr(11),
1719 r->gpr(12), r->gpr(13), r->gpr(14), r->gpr(15),
1720 r->gpr(16), r->gpr(17), r->gpr(18), r->gpr(19),
1721 r->gpr(20), r->gpr(21), r->gpr(22), r->gpr(23),
1722 r->gpr(24), r->gpr(25), r->gpr(26), r->gpr(27),
1723 r->gpr(28), r->gpr(29), r->gpr(30), r->gpr(31));
1724 exit(1);
1725 QuitEmulator();
1726 return;
1727 } else {
1728 // We crashed. Save registers, tell tick thread and loop forever
1729 build_sigregs(&sigsegv_regs, r);
1730 emul_thread_fatal = true;
1731 for (;;) ;
1732 }
1733 rti:;
1734 }
1735
1736
1737 /*
1738 * SIGILL handler
1739 */
1740
1741 static void sigill_handler(int sig, siginfo_t *sip, void *scp)
1742 {
1743 machine_regs *r = MACHINE_REGISTERS(scp);
1744 char str[256];
1745
1746 // Fault in Mac ROM or RAM?
1747 bool mac_fault = (r->pc() >= ROM_BASE) && (r->pc() < (ROM_BASE + ROM_AREA_SIZE)) || (r->pc() >= RAMBase) && (r->pc() < (RAMBase + RAMSize));
1748 if (mac_fault) {
1749
1750 // Get opcode and divide into fields
1751 uint32 opcode = *((uint32 *)r->pc());
1752 uint32 primop = opcode >> 26;
1753 uint32 exop = (opcode >> 1) & 0x3ff;
1754 uint32 ra = (opcode >> 16) & 0x1f;
1755 uint32 rb = (opcode >> 11) & 0x1f;
1756 uint32 rd = (opcode >> 21) & 0x1f;
1757 int32 imm = (int16)(opcode & 0xffff);
1758
1759 switch (primop) {
1760 case 9: // POWER instructions
1761 case 22:
1762 power_inst: sprintf(str, GetString(STR_POWER_INSTRUCTION_ERR), r->pc(), r->gpr(1), opcode);
1763 ErrorAlert(str);
1764 QuitEmulator();
1765 return;
1766
1767 case 31:
1768 switch (exop) {
1769 case 83: // mfmsr
1770 r->gpr(rd) = 0xf072;
1771 r->pc() += 4;
1772 goto rti;
1773
1774 case 210: // mtsr
1775 case 242: // mtsrin
1776 case 306: // tlbie
1777 r->pc() += 4;
1778 goto rti;
1779
1780 case 339: { // mfspr
1781 int spr = ra | (rb << 5);
1782 switch (spr) {
1783 case 0: // MQ
1784 case 22: // DEC
1785 case 952: // MMCR0
1786 case 953: // PMC1
1787 case 954: // PMC2
1788 case 955: // SIA
1789 case 956: // MMCR1
1790 case 957: // PMC3
1791 case 958: // PMC4
1792 case 959: // SDA
1793 r->pc() += 4;
1794 goto rti;
1795 case 25: // SDR1
1796 r->gpr(rd) = 0xdead001f;
1797 r->pc() += 4;
1798 goto rti;
1799 case 287: // PVR
1800 r->gpr(rd) = PVR;
1801 r->pc() += 4;
1802 goto rti;
1803 }
1804 break;
1805 }
1806
1807 case 467: { // mtspr
1808 int spr = ra | (rb << 5);
1809 switch (spr) {
1810 case 0: // MQ
1811 case 22: // DEC
1812 case 275: // SPRG3
1813 case 528: // IBAT0U
1814 case 529: // IBAT0L
1815 case 530: // IBAT1U
1816 case 531: // IBAT1L
1817 case 532: // IBAT2U
1818 case 533: // IBAT2L
1819 case 534: // IBAT3U
1820 case 535: // IBAT3L
1821 case 536: // DBAT0U
1822 case 537: // DBAT0L
1823 case 538: // DBAT1U
1824 case 539: // DBAT1L
1825 case 540: // DBAT2U
1826 case 541: // DBAT2L
1827 case 542: // DBAT3U
1828 case 543: // DBAT3L
1829 case 952: // MMCR0
1830 case 953: // PMC1
1831 case 954: // PMC2
1832 case 955: // SIA
1833 case 956: // MMCR1
1834 case 957: // PMC3
1835 case 958: // PMC4
1836 case 959: // SDA
1837 r->pc() += 4;
1838 goto rti;
1839 }
1840 break;
1841 }
1842
1843 case 29: case 107: case 152: case 153: // POWER instructions
1844 case 184: case 216: case 217: case 248:
1845 case 264: case 277: case 331: case 360:
1846 case 363: case 488: case 531: case 537:
1847 case 541: case 664: case 665: case 696:
1848 case 728: case 729: case 760: case 920:
1849 case 921: case 952:
1850 goto power_inst;
1851 }
1852 }
1853
1854 // In GUI mode, show error alert
1855 if (!PrefsFindBool("nogui")) {
1856 sprintf(str, GetString(STR_UNKNOWN_SEGV_ERR), r->pc(), r->gpr(24), r->gpr(1), opcode);
1857 ErrorAlert(str);
1858 QuitEmulator();
1859 return;
1860 }
1861 }
1862
1863 // For all other errors, jump into debugger (sort of...)
1864 crash_reason = "SIGILL";
1865 if (!ready_for_signals) {
1866 printf("%s\n");
1867 printf(" sigcontext %p, machine_regs %p\n", scp, r);
1868 printf(
1869 " pc %08lx lr %08lx ctr %08lx msr %08lx\n"
1870 " xer %08lx cr %08lx \n"
1871 " r0 %08lx r1 %08lx r2 %08lx r3 %08lx\n"
1872 " r4 %08lx r5 %08lx r6 %08lx r7 %08lx\n"
1873 " r8 %08lx r9 %08lx r10 %08lx r11 %08lx\n"
1874 " r12 %08lx r13 %08lx r14 %08lx r15 %08lx\n"
1875 " r16 %08lx r17 %08lx r18 %08lx r19 %08lx\n"
1876 " r20 %08lx r21 %08lx r22 %08lx r23 %08lx\n"
1877 " r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n"
1878 " r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n",
1879 crash_reason,
1880 r->pc(), r->lr(), r->ctr(), r->msr(),
1881 r->xer(), r->cr(),
1882 r->gpr(0), r->gpr(1), r->gpr(2), r->gpr(3),
1883 r->gpr(4), r->gpr(5), r->gpr(6), r->gpr(7),
1884 r->gpr(8), r->gpr(9), r->gpr(10), r->gpr(11),
1885 r->gpr(12), r->gpr(13), r->gpr(14), r->gpr(15),
1886 r->gpr(16), r->gpr(17), r->gpr(18), r->gpr(19),
1887 r->gpr(20), r->gpr(21), r->gpr(22), r->gpr(23),
1888 r->gpr(24), r->gpr(25), r->gpr(26), r->gpr(27),
1889 r->gpr(28), r->gpr(29), r->gpr(30), r->gpr(31));
1890 exit(1);
1891 QuitEmulator();
1892 return;
1893 } else {
1894 // We crashed. Save registers, tell tick thread and loop forever
1895 build_sigregs(&sigsegv_regs, r);
1896 emul_thread_fatal = true;
1897 for (;;) ;
1898 }
1899 rti:;
1900 }
1901 #endif
1902
1903
1904 /*
1905 * Helpers to share 32-bit addressable data with MacOS
1906 */
1907
1908 bool SheepMem::Init(void)
1909 {
1910 // Size of a native page
1911 page_size = getpagesize();
1912
1913 // Allocate SheepShaver globals
1914 if (vm_acquire_fixed((char *)base, size) < 0)
1915 return false;
1916
1917 // Allocate page with all bits set to 0
1918 zero_page = base + size;
1919 if (vm_acquire_fixed((char *)zero_page, page_size) < 0)
1920 return false;
1921 memset((char *)zero_page, 0, page_size);
1922 if (vm_protect((char *)zero_page, page_size, VM_PAGE_READ) < 0)
1923 return false;
1924
1925 #if EMULATED_PPC
1926 // Allocate alternate stack for PowerPC interrupt routine
1927 sig_stack = zero_page + page_size;
1928 if (vm_acquire_fixed((char *)sig_stack, SIG_STACK_SIZE) < 0)
1929 return false;
1930 #endif
1931
1932 top = base + size;
1933 return true;
1934 }
1935
1936 void SheepMem::Exit(void)
1937 {
1938 if (top) {
1939 // Delete SheepShaver globals
1940 vm_release((void *)base, size);
1941
1942 // Delete zero page
1943 vm_release((void *)zero_page, page_size);
1944
1945 #if EMULATED_PPC
1946 // Delete alternate stack for PowerPC interrupt routine
1947 vm_release((void *)sig_stack, SIG_STACK_SIZE);
1948 #endif
1949 }
1950 }
1951
1952
1953 /*
1954 * Display alert
1955 */
1956
1957 #ifdef ENABLE_GTK
1958 static void dl_destroyed(void)
1959 {
1960 gtk_main_quit();
1961 }
1962
1963 static void dl_quit(GtkWidget *dialog)
1964 {
1965 gtk_widget_destroy(dialog);
1966 }
1967
1968 void display_alert(int title_id, int prefix_id, int button_id, const char *text)
1969 {
1970 char str[256];
1971 sprintf(str, GetString(prefix_id), text);
1972
1973 GtkWidget *dialog = gtk_dialog_new();
1974 gtk_window_set_title(GTK_WINDOW(dialog), GetString(title_id));
1975 gtk_container_border_width(GTK_CONTAINER(dialog), 5);
1976 gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150);
1977 gtk_signal_connect(GTK_OBJECT(dialog), "destroy", GTK_SIGNAL_FUNC(dl_destroyed), NULL);
1978
1979 GtkWidget *label = gtk_label_new(str);
1980 gtk_widget_show(label);
1981 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0);
1982
1983 GtkWidget *button = gtk_button_new_with_label(GetString(button_id));
1984 gtk_widget_show(button);
1985 gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog));
1986 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0);
1987 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1988 gtk_widget_grab_default(button);
1989 gtk_widget_show(dialog);
1990
1991 gtk_main();
1992 }
1993 #endif
1994
1995
1996 /*
1997 * Display error alert
1998 */
1999
2000 void ErrorAlert(const char *text)
2001 {
2002 #ifdef ENABLE_GTK
2003 if (PrefsFindBool("nogui") || x_display == NULL) {
2004 printf(GetString(STR_SHELL_ERROR_PREFIX), text);
2005 return;
2006 }
2007 VideoQuitFullScreen();
2008 display_alert(STR_ERROR_ALERT_TITLE, STR_GUI_ERROR_PREFIX, STR_QUIT_BUTTON, text);
2009 #else
2010 printf(GetString(STR_SHELL_ERROR_PREFIX), text);
2011 #endif
2012 }
2013
2014
2015 /*
2016 * Display warning alert
2017 */
2018
2019 void WarningAlert(const char *text)
2020 {
2021 #ifdef ENABLE_GTK
2022 if (PrefsFindBool("nogui") || x_display == NULL) {
2023 printf(GetString(STR_SHELL_WARNING_PREFIX), text);
2024 return;
2025 }
2026 display_alert(STR_WARNING_ALERT_TITLE, STR_GUI_WARNING_PREFIX, STR_OK_BUTTON, text);
2027 #else
2028 printf(GetString(STR_SHELL_WARNING_PREFIX), text);
2029 #endif
2030 }
2031
2032
2033 /*
2034 * Display choice alert
2035 */
2036
2037 bool ChoiceAlert(const char *text, const char *pos, const char *neg)
2038 {
2039 printf(GetString(STR_SHELL_WARNING_PREFIX), text);
2040 return false; //!!
2041 }