ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Unix/main_unix.cpp
(Generate patch)

Comparing SheepShaver/src/Unix/main_unix.cpp (file contents):
Revision 1.70 by gbeauche, 2005-07-06T04:58:34Z vs.
Revision 1.82 by asvitkine, 2009-02-11T19:22:16Z

# Line 1 | Line 1
1   /*
2   *  main_unix.cpp - Emulation core, Unix implementation
3   *
4 < *  SheepShaver (C) 1997-2005 Christian Bauer and Marc Hellwig
4 > *  SheepShaver (C) 1997-2008 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
# Line 110 | Line 110
110   #include "vm_alloc.h"
111   #include "sigsegv.h"
112   #include "sigregs.h"
113 + #include "rpc.h"
114  
115   #define DEBUG 0
116   #include "debug.h"
# Line 224 | Line 225 | static uintptr sig_stack = 0;                          // Stac
225   #else
226   static struct sigaction sigsegv_action;         // Data access exception signal (of emulator thread)
227   static struct sigaction sigill_action;          // Illegal instruction signal (of emulator thread)
228 < static struct sigaltstack sig_stack;            // Stack for signal handlers
229 < static struct sigaltstack extra_stack;          // Stack for SIGSEGV inside interrupt handler
228 > static stack_t sig_stack;                                       // Stack for signal handlers
229 > static stack_t extra_stack;                                     // Stack for SIGSEGV inside interrupt handler
230   static bool emul_thread_fatal = false;          // Flag: MacOS thread crashed, tick thread shall dump debug output
231   static sigregs sigsegv_regs;                            // Register dump when crashed
232   static const char *crash_reason = NULL;         // Reason of the crash (SIGSEGV, SIGBUS, SIGILL)
233   #endif
234  
235 + static rpc_connection_t *gui_connection = NULL; // RPC connection to the GUI
236 + static const char *gui_connection_path = NULL;  // GUI connection identifier
237 +
238   uint32  SheepMem::page_size;                            // Size of a native page
239   uintptr SheepMem::zero_page = 0;                        // Address of ro page filled in with zeros
240   uintptr SheepMem::base = 0x60000000;            // Address of SheepShaver data
# Line 249 | Line 253 | static void *tick_func(void *arg);
253   extern void emul_ppc(uint32 start);
254   extern void init_emul_ppc(void);
255   extern void exit_emul_ppc(void);
256 < sigsegv_return_t sigsegv_handler(sigsegv_address_t, sigsegv_address_t);
256 > sigsegv_return_t sigsegv_handler(sigsegv_info_t *sip);
257   #else
258   extern "C" void sigusr2_handler_init(int sig, siginfo_t *sip, void *scp);
259   extern "C" void sigusr2_handler(int sig, siginfo_t *sip, void *scp);
# Line 365 | Line 369 | int main(int argc, char **argv)
369          uint32 rom_size, actual;
370          uint8 *rom_tmp;
371          time_t now, expire;
372 +        bool memory_mapped_from_zero;
373 +
374 + #ifdef USE_SDL_VIDEO
375 +        // Don't let SDL block the screensaver
376 +        putenv("SDL_VIDEO_ALLOW_SCREENSAVER=1");
377 +
378 +        // Make SDL pass through command-clicks and option-clicks unaltered
379 +        putenv("SDL_HAS3BUTTONMOUSE=1");
380 + #endif
381  
382          // Initialize variables
383          RAMBase = 0;
# Line 385 | Line 398 | int main(int argc, char **argv)
398   #endif
399   #endif
400  
388 #ifdef ENABLE_GTK
389        // Init GTK
390        gtk_set_locale();
391        gtk_init(&argc, &argv);
392 #endif
393
394        // Read preferences
395        PrefsInit(argc, argv);
396
401          // Parse command line arguments
402          for (int i=1; i<argc; i++) {
403                  if (strcmp(argv[i], "--help") == 0) {
# Line 404 | Line 408 | int main(int argc, char **argv)
408                          if (i < argc)
409                                  x_display_name = strdup(argv[i]);
410   #endif
411 <                } else if (argv[i][0] == '-') {
411 >                } else if (strcmp(argv[i], "--gui-connection") == 0) {
412 >                        argv[i++] = NULL;
413 >                        if (i < argc) {
414 >                                gui_connection_path = argv[i];
415 >                                argv[i] = NULL;
416 >                        }
417 >                }
418 >        }
419 >
420 >        // Remove processed arguments
421 >        for (int i=1; i<argc; i++) {
422 >                int k;
423 >                for (k=i; k<argc; k++)
424 >                        if (argv[k] != NULL)
425 >                                break;
426 >                if (k > i) {
427 >                        k -= i;
428 >                        for (int j=i+k; j<argc; j++)
429 >                                argv[j-k] = argv[j];
430 >                        argc -= k;
431 >                }
432 >        }
433 >
434 >        // Connect to the external GUI
435 >        if (gui_connection_path) {
436 >                if ((gui_connection = rpc_init_client(gui_connection_path)) == NULL) {
437 >                        fprintf(stderr, "Failed to initialize RPC client connection to the GUI\n");
438 >                        return 1;
439 >                }
440 >        }
441 >
442 > #ifdef ENABLE_GTK
443 >        if (!gui_connection) {
444 >                // Init GTK
445 >                gtk_set_locale();
446 >                gtk_init(&argc, &argv);
447 >        }
448 > #endif
449 >
450 >        // Read preferences
451 >        PrefsInit(argc, argv);
452 >
453 >        // Any command line arguments left?
454 >        for (int i=1; i<argc; i++) {
455 >                if (argv[i][0] == '-') {
456                          fprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
457                          usage(argv[0]);
458                  }
# Line 427 | Line 475 | int main(int argc, char **argv)
475                  goto quit;
476          }
477          atexit(SDL_Quit);
478 +
479 +        // Don't let SDL catch SIGINT and SIGTERM signals
480 +        signal(SIGINT, SIG_DFL);
481 +        signal(SIGTERM, SIG_DFL);
482   #endif
483  
484   #ifndef USE_SDL_VIDEO
# Line 485 | Line 537 | int main(int argc, char **argv)
537          sigsegv_action.sa_restorer = NULL;
538   #endif
539          if (sigaction(SIGSEGV, &sigsegv_action, NULL) < 0) {
540 <                sprintf(str, GetString(STR_SIGSEGV_INSTALL_ERR), strerror(errno));
540 >                sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGSEGV", strerror(errno));
541                  ErrorAlert(str);
542                  goto quit;
543          }
544          if (sigaction(SIGBUS, &sigsegv_action, NULL) < 0) {
545 <                sprintf(str, GetString(STR_SIGSEGV_INSTALL_ERR), strerror(errno));
545 >                sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGBUS", strerror(errno));
546                  ErrorAlert(str);
547                  goto quit;
548          }
549   #else
550          // Install SIGSEGV handler for CPU emulator
551          if (!sigsegv_install_handler(sigsegv_handler)) {
552 <                sprintf(str, GetString(STR_SIGSEGV_INSTALL_ERR), strerror(errno));
552 >                sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGSEGV", strerror(errno));
553                  ErrorAlert(str);
554                  goto quit;
555          }
# Line 589 | Line 641 | int main(int argc, char **argv)
641                          { 0xffff0000, 0x80010000, "7455" },
642                          { 0xffff0000, 0x80020000, "7457" },
643                          { 0xffff0000, 0x80030000, "7447A" },
644 +                        { 0xffff0000, 0x80040000, "7448" },
645                          { 0x7fff0000, 0x00810000, "82xx" },
646                          { 0x7fff0000, 0x00820000, "8280" },
647                          { 0xffff0000, 0x00400000, "Power3 (630)" },
# Line 597 | Line 650 | int main(int argc, char **argv)
650                          { 0xffff0000, 0x00370000, "S-star" },
651                          { 0xffff0000, 0x00350000, "Power4" },
652                          { 0xffff0000, 0x00390000, "PPC970" },
653 <                        { 0xffff0000, 0x003a0000, "POWER5" },
653 >                        { 0xffff0000, 0x003c0000, "PPC970FX" },
654 >                        { 0xffff0000, 0x003a0000, "POWER5 (gr)" },
655 >                        { 0xffff0000, 0x003b0000, "POWER5+ (gs)" },
656 >                        { 0xffff0000, 0x003e0000, "POWER6" },
657 >                        { 0xffff0000, 0x00700000, "Cell Broadband Engine" },
658 >                        { 0x7fff0000, 0x00900000, "PA6T" },
659                          { 0, 0, 0 }
660                  };
661  
# Line 611 | Line 669 | int main(int argc, char **argv)
669  
670                          // Parse line
671                          int i;
672 +                        float f;
673                          char value[256];
674 <                        if (sscanf(line, "cpu : %[0-9A-Za-a]", value) == 1) {
674 >                        if (sscanf(line, "cpu : %[^,]", value) == 1) {
675                                  // Search by name
676                                  const char *cpu_name = NULL;
677                                  for (int i = 0; cpu_specs[i].pvr_mask != 0; i++) {
# Line 627 | Line 686 | int main(int argc, char **argv)
686                                  else
687                                          printf("Found a PowerPC %s processor\n", cpu_name);
688                          }
689 <                        if (sscanf(line, "clock : %dMHz", &i) == 1)
689 >                        if (sscanf(line, "clock : %fMHz", &f) == 1)
690 >                                CPUClockSpeed = BusClockSpeed = ((int64)f) * 1000000;
691 >                        else if (sscanf(line, "clock : %dMHz", &i) == 1)
692                                  CPUClockSpeed = BusClockSpeed = i * 1000000;
693                  }
694                  fclose(proc_file);
# Line 672 | Line 733 | int main(int argc, char **argv)
733          case 0x8001:                            // 7455
734          case 0x8002:                            // 7457
735          case 0x8003:                            // 7447A
736 +        case 0x8004:                            // 7448
737          case 0x0039:                            //  970
738 +        case 0x003c:                            //  970FX
739                  PVR = 0x000c0000;               // 7400
740                  break;
741          }
# Line 699 | Line 762 | int main(int argc, char **argv)
762                  goto quit;
763          }
764  
702 #ifndef PAGEZERO_HACK
703        // Create Low Memory area (0x0000..0x3000)
704        if (vm_mac_acquire(0, 0x3000) < 0) {
705                sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
706                ErrorAlert(str);
707                goto quit;
708        }
709        lm_area_mapped = true;
710 #endif
711
765          // Create areas for Kernel Data
766          if (!kernel_data_init())
767                  goto quit;
# Line 771 | Line 824 | int main(int argc, char **argv)
824                  WarningAlert(GetString(STR_SMALL_RAM_WARN));
825                  RAMSize = 8*1024*1024;
826          }
827 <
828 <        if (vm_mac_acquire(RAM_BASE, RAMSize) < 0) {
829 <                sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
830 <                ErrorAlert(str);
831 <                goto quit;
827 >        memory_mapped_from_zero = false;
828 > #if REAL_ADDRESSING && HAVE_LINKER_SCRIPT
829 >        if (vm_mac_acquire(0, RAMSize) == 0) {
830 >                D(bug("Could allocate RAM from 0x0000\n"));
831 >                RAMBase = 0;
832 >                memory_mapped_from_zero = true;
833 >        }
834 > #endif
835 >        if (!memory_mapped_from_zero) {
836 > #ifndef PAGEZERO_HACK
837 >                // Create Low Memory area (0x0000..0x3000)
838 >                if (vm_mac_acquire(0, 0x3000) < 0) {
839 >                        sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
840 >                        ErrorAlert(str);
841 >                        goto quit;
842 >                }
843 >                lm_area_mapped = true;
844 > #endif
845 >                if (vm_mac_acquire(RAM_BASE, RAMSize) < 0) {
846 >                        sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
847 >                        ErrorAlert(str);
848 >                        goto quit;
849 >                }
850 >                RAMBase = RAM_BASE;
851          }
852 <        RAMBaseHost = Mac2HostAddr(RAM_BASE);
852 >        RAMBaseHost = Mac2HostAddr(RAMBase);
853   #if !EMULATED_PPC
854          if (vm_protect(RAMBaseHost, RAMSize, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) {
855                  sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
# Line 785 | Line 857 | int main(int argc, char **argv)
857                  goto quit;
858          }
859   #endif
788        RAMBase = RAM_BASE;
860          ram_area_mapped = true;
861          D(bug("RAM area at %p (%08x)\n", RAMBaseHost, RAMBase));
862  
# Line 855 | Line 926 | int main(int argc, char **argv)
926          sigill_action.sa_restorer = NULL;
927   #endif
928          if (sigaction(SIGILL, &sigill_action, NULL) < 0) {
929 <                sprintf(str, GetString(STR_SIGILL_INSTALL_ERR), strerror(errno));
929 >                sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGILL", strerror(errno));
930                  ErrorAlert(str);
931                  goto quit;
932          }
# Line 870 | Line 941 | int main(int argc, char **argv)
941          sigusr2_action.sa_restorer = NULL;
942   #endif
943          if (sigaction(SIGUSR2, &sigusr2_action, NULL) < 0) {
944 <                sprintf(str, GetString(STR_SIGUSR2_INSTALL_ERR), strerror(errno));
944 >                sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGUSR2", strerror(errno));
945                  ErrorAlert(str);
946                  goto quit;
947          }
# Line 941 | Line 1012 | static void Quit(void)
1012  
1013          // Delete RAM area
1014          if (ram_area_mapped)
1015 <                vm_mac_release(RAM_BASE, RAMSize);
1015 >                vm_mac_release(RAMBase, RAMSize);
1016  
1017          // Delete ROM area
1018          if (rom_area_mapped)
# Line 981 | Line 1052 | static void Quit(void)
1052                  XCloseDisplay(x_display);
1053   #endif
1054  
1055 +        // Notify GUI we are about to leave
1056 +        if (gui_connection) {
1057 +                if (rpc_method_invoke(gui_connection, RPC_METHOD_EXIT, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
1058 +                        rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID);
1059 +        }
1060 +
1061          exit(0);
1062   }
1063  
# Line 989 | Line 1066 | static void Quit(void)
1066   *  Initialize Kernel Data segments
1067   */
1068  
992 #if defined(__CYGWIN__)
993 #define WIN32_LEAN_AND_MEAN
994 #include <windows.h>
995
996 static HANDLE kernel_handle;                            // Shared memory handle for Kernel Data
997 static DWORD allocation_granule;                        // Minimum size of allocateable are (64K)
998 static DWORD kernel_area_size;                          // Size of Kernel Data area
999 #endif
1000
1069   static bool kernel_data_init(void)
1070   {
1071          char str[256];
1072 < #ifdef _WIN32
1073 <        SYSTEM_INFO si;
1074 <        GetSystemInfo(&si);
1007 <        allocation_granule = si.dwAllocationGranularity;
1008 <        kernel_area_size = (KERNEL_AREA_SIZE + allocation_granule - 1) & -allocation_granule;
1009 <
1010 <        char rcs[10];
1011 <        LPVOID kernel_addr;
1012 <        kernel_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, kernel_area_size, NULL);
1013 <        if (kernel_handle == NULL) {
1014 <                sprintf(rcs, "%d", GetLastError());
1015 <                sprintf(str, GetString(STR_KD_SHMGET_ERR), rcs);
1016 <                ErrorAlert(str);
1017 <                return false;
1018 <        }
1019 <        kernel_addr = (LPVOID)Mac2HostAddr(KERNEL_DATA_BASE & -allocation_granule);
1020 <        if (MapViewOfFileEx(kernel_handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, kernel_area_size, kernel_addr) != kernel_addr) {
1021 <                sprintf(rcs, "%d", GetLastError());
1022 <                sprintf(str, GetString(STR_KD_SHMAT_ERR), rcs);
1023 <                ErrorAlert(str);
1024 <                return false;
1025 <        }
1026 <        kernel_addr = (LPVOID)Mac2HostAddr(KERNEL_DATA2_BASE & -allocation_granule);
1027 <        if (MapViewOfFileEx(kernel_handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, kernel_area_size, kernel_addr) != kernel_addr) {
1028 <                sprintf(rcs, "%d", GetLastError());
1029 <                sprintf(str, GetString(STR_KD2_SHMAT_ERR), rcs);
1030 <                ErrorAlert(str);
1031 <                return false;
1032 <        }
1033 < #else
1034 <        kernel_area = shmget(IPC_PRIVATE, KERNEL_AREA_SIZE, 0600);
1072 >        uint32 kernel_area_size = (KERNEL_AREA_SIZE + SHMLBA - 1) & -SHMLBA;
1073 >
1074 >        kernel_area = shmget(IPC_PRIVATE, kernel_area_size, 0600);
1075          if (kernel_area == -1) {
1076                  sprintf(str, GetString(STR_KD_SHMGET_ERR), strerror(errno));
1077                  ErrorAlert(str);
1078                  return false;
1079          }
1080 <        if (shmat(kernel_area, Mac2HostAddr(KERNEL_DATA_BASE), 0) < 0) {
1080 >        void *kernel_addr = Mac2HostAddr(KERNEL_DATA_BASE & -SHMLBA);
1081 >        if (shmat(kernel_area, kernel_addr, 0) != kernel_addr) {
1082                  sprintf(str, GetString(STR_KD_SHMAT_ERR), strerror(errno));
1083                  ErrorAlert(str);
1084                  return false;
1085          }
1086 <        if (shmat(kernel_area, Mac2HostAddr(KERNEL_DATA2_BASE), 0) < 0) {
1086 >        kernel_addr = Mac2HostAddr(KERNEL_DATA2_BASE & -SHMLBA);
1087 >        if (shmat(kernel_area, kernel_addr, 0) != kernel_addr) {
1088                  sprintf(str, GetString(STR_KD2_SHMAT_ERR), strerror(errno));
1089                  ErrorAlert(str);
1090                  return false;
1091          }
1050 #endif
1092          return true;
1093   }
1094  
# Line 1058 | Line 1099 | static bool kernel_data_init(void)
1099  
1100   static void kernel_data_exit(void)
1101   {
1061 #ifdef _WIN32
1062        if (kernel_handle) {
1063                UnmapViewOfFile(Mac2HostAddr(KERNEL_DATA_BASE & -allocation_granule));
1064                UnmapViewOfFile(Mac2HostAddr(KERNEL_DATA2_BASE & -allocation_granule));
1065                CloseHandle(kernel_handle);
1066        }
1067 #else
1102          if (kernel_area >= 0) {
1103 <                shmdt(Mac2HostAddr(KERNEL_DATA_BASE));
1104 <                shmdt(Mac2HostAddr(KERNEL_DATA2_BASE));
1103 >                shmdt(Mac2HostAddr(KERNEL_DATA_BASE & -SHMLBA));
1104 >                shmdt(Mac2HostAddr(KERNEL_DATA2_BASE & -SHMLBA));
1105                  shmctl(kernel_area, IPC_RMID, NULL);
1106          }
1073 #endif
1107   }
1108  
1109  
# Line 1590 | Line 1623 | void sigusr2_handler(int sig, siginfo_t
1623   */
1624  
1625   #if !EMULATED_PPC
1626 + // XXX: don't redefine locally?
1627 + // Note: Original declaration is in sigsegv.cpp
1628 + // FIXME: If HAVE_MACH_EXCEPTIONS is set, sigsegv_info_t has a bunch of other
1629 + //        fields too! Let's hope Screen_fault_handler() doesn't use them...
1630 + struct sigsegv_info_t {
1631 +        sigsegv_address_t addr;
1632 +        sigsegv_address_t pc;
1633 + };
1634 +
1635   static void sigsegv_handler(int sig, siginfo_t *sip, void *scp)
1636   {
1637          machine_regs *r = MACHINE_REGISTERS(scp);
# Line 1607 | Line 1649 | static void sigsegv_handler(int sig, sig
1649   #endif
1650  
1651   #if ENABLE_VOSF
1652 <        // Handle screen fault.
1653 <        extern bool Screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction);
1654 <        if (Screen_fault_handler((sigsegv_address_t)addr, (sigsegv_address_t)r->pc()))
1652 >        // Handle screen fault
1653 > #if SIGSEGV_CHECK_VERSION(1,0,0)
1654 >        sigsegv_info_t si;
1655 >        si.addr = (sigsegv_address_t)addr;
1656 >        si.pc = (sigsegv_address_t)r->pc();
1657 > #endif
1658 >        extern bool Screen_fault_handler(sigsegv_info_t *sip);
1659 >        if (Screen_fault_handler(&si))
1660                  return;
1661   #endif
1662  
# Line 2117 | Line 2164 | void display_alert(int title_id, int pre
2164  
2165   void ErrorAlert(const char *text)
2166   {
2167 +        if (gui_connection) {
2168 +                if (rpc_method_invoke(gui_connection, RPC_METHOD_ERROR_ALERT, RPC_TYPE_STRING, text, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR &&
2169 +                        rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
2170 +                        return;
2171 +        }
2172   #if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO)
2173          if (PrefsFindBool("nogui") || x_display == NULL) {
2174                  printf(GetString(STR_SHELL_ERROR_PREFIX), text);
# Line 2136 | Line 2188 | void ErrorAlert(const char *text)
2188  
2189   void WarningAlert(const char *text)
2190   {
2191 +        if (gui_connection) {
2192 +                if (rpc_method_invoke(gui_connection, RPC_METHOD_WARNING_ALERT, RPC_TYPE_STRING, text, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR &&
2193 +                        rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
2194 +                        return;
2195 +        }
2196   #if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO)
2197          if (PrefsFindBool("nogui") || x_display == NULL) {
2198                  printf(GetString(STR_SHELL_WARNING_PREFIX), text);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines