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.2 by cebix, 2002-02-21T15:12:12Z vs.
Revision 1.22 by gbeauche, 2004-01-04T05:45:50Z

# Line 107 | Line 107
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"
# Line 143 | Line 146
146   const char ROM_FILE_NAME[] = "ROM";
147   const char ROM_FILE_NAME2[] = "Mac OS ROM";
148  
149 < const uint32 ROM_AREA_SIZE = 0x500000;          // Size of ROM area
147 < const uint32 ROM_END = ROM_BASE + ROM_SIZE;     // End of ROM
148 <
149 < const uint32 KERNEL_DATA_BASE = 0x68ffe000;     // Address of Kernel Data
150 < const uint32 KERNEL_DATA2_BASE = 0x5fffe000;    // Alternate address of Kernel Data
151 < const uint32 KERNEL_AREA_SIZE = 0x2000;         // Size of Kernel Data area
152 <
149 > const uintptr RAM_BASE = 0x20000000;            // Base address of RAM
150   const uint32 SIG_STACK_SIZE = 0x10000;          // Size of signal stack
151  
152  
156 // 68k Emulator Data
157 struct EmulatorData {
158        uint32  v[0x400];      
159 };
160
161
162 // Kernel Data
163 struct KernelData {
164        uint32  v[0x400];
165        EmulatorData ed;
166 };
167
168
153   #if !EMULATED_PPC
154   // Structure in which registers are saved in a signal handler;
155   // sigcontext->regs points to it
# Line 197 | Line 181 | int64 BusClockSpeed;   // Bus clock speed
181  
182  
183   // Global variables
184 < static char *x_display_name = NULL;                     // X11 display name
184 > char *x_display_name = NULL;                            // X11 display name
185   Display *x_display = NULL;                                      // X11 display handle
186 + #ifdef X11_LOCK_TYPE
187 + X11_LOCK_TYPE x_display_lock = X11_LOCK_INIT; // X11 display lock
188 + #endif
189  
190   static int zero_fd = 0;                                         // FD of /dev/zero
191   static bool lm_area_mapped = false;                     // Flag: Low Memory area mmap()ped
192   static int kernel_area = -1;                            // SHM ID of Kernel Data area
193   static bool rom_area_mapped = false;            // Flag: Mac ROM mmap()ped
194   static bool ram_area_mapped = false;            // Flag: Mac RAM mmap()ped
208 static void *mmap_RAMBase = NULL;                       // Base address of mmap()ed RAM area
195   static KernelData *kernel_data;                         // Pointer to Kernel Data
196   static EmulatorData *emulator_data;
197  
# Line 220 | Line 206 | static pthread_t emul_thread;                          // MacO
206   static bool ready_for_signals = false;          // Handler installed, signals can be sent
207   static int64 num_segv = 0;                                      // Number of handled SEGV signals
208  
223 #if !EMULATED_PPC
209   static struct sigaction sigusr2_action;         // Interrupt signal (of emulator thread)
210 + #if EMULATED_PPC
211 + static uintptr sig_stack = 0;                           // Stack for PowerPC interrupt routine
212 + #else
213   static struct sigaction sigsegv_action;         // Data access exception signal (of emulator thread)
214   static struct sigaction sigill_action;          // Illegal instruction signal (of emulator thread)
215   static void *sig_stack = NULL;                          // Stack for signal handlers
# Line 230 | Line 218 | static bool emul_thread_fatal = false;
218   static sigregs sigsegv_regs;                            // Register dump when crashed
219   #endif
220  
221 + uintptr SheepMem::zero_page = 0;                        // Address of ro page filled in with zeros
222 + uintptr SheepMem::base = 0x60000000;            // Address of SheepShaver data
223 + uintptr SheepMem::top = 0;                                      // Top of SheepShaver data (stack like storage)
224 +
225  
226   // Prototypes
227   static void Quit(void);
228   static void *emul_func(void *arg);
229   static void *nvram_func(void *arg);
230   static void *tick_func(void *arg);
231 < #if !EMULATED_PPC
231 > #if EMULATED_PPC
232 > static void sigusr2_handler(int sig);
233 > extern void emul_ppc(uint32 start);
234 > extern void init_emul_ppc(void);
235 > extern void exit_emul_ppc(void);
236 > #else
237   static void sigusr2_handler(int sig, sigcontext_struct *sc);
238   static void sigsegv_handler(int sig, sigcontext_struct *sc);
239   static void sigill_handler(int sig, sigcontext_struct *sc);
# Line 244 | Line 241 | static void sigill_handler(int sig, sigc
241  
242  
243   // From asm_linux.S
244 < #if EMULATED_PPC
248 < extern int atomic_add(int *var, int v);
249 < extern int atomic_and(int *var, int v);
250 < extern int atomic_or(int *var, int v);
251 < #else
244 > #if !EMULATED_PPC
245   extern "C" void *get_toc(void);
246   extern "C" void *get_sp(void);
247   extern "C" void flush_icache_range(void *start, void *end);
# Line 263 | Line 256 | extern void paranoia_check(void);
256   #endif
257  
258  
259 < // Decode LZSS data
260 < static void decode_lzss(const uint8 *src, uint8 *dest, int size)
259 > #if EMULATED_PPC
260 > /*
261 > *  Return signal stack base
262 > */
263 >
264 > uintptr SignalStackBase(void)
265   {
266 <        char dict[0x1000];
267 <        int run_mask = 0, dict_idx = 0xfee;
268 <        for (;;) {
269 <                if (run_mask < 0x100) {
270 <                        // Start new run
271 <                        if (--size < 0)
272 <                                break;
273 <                        run_mask = *src++ | 0xff00;
274 <                }
275 <                bool bit = run_mask & 1;
276 <                run_mask >>= 1;
277 <                if (bit) {
278 <                        // Verbatim copy
279 <                        if (--size < 0)
280 <                                break;
281 <                        int c = *src++;
282 <                        dict[dict_idx++] = c;
283 <                        *dest++ = c;
284 <                        dict_idx &= 0xfff;
285 <                } else {
286 <                        // Copy from dictionary
287 <                        if (--size < 0)
288 <                                break;
289 <                        int idx = *src++;
290 <                        if (--size < 0)
291 <                                break;
292 <                        int cnt = *src++;
293 <                        idx |= (cnt << 4) & 0xf00;
294 <                        cnt = (cnt & 0x0f) + 3;
295 <                        while (cnt--) {
296 <                                char c = dict[idx++];
297 <                                dict[dict_idx++] = c;
298 <                                *dest++ = c;
299 <                                idx &= 0xfff;
300 <                                dict_idx &= 0xfff;
301 <                        }
302 <                }
303 <        }
266 >        return sig_stack + SIG_STACK_SIZE;
267 > }
268 >
269 >
270 > /*
271 > *  Atomic operations
272 > */
273 >
274 > #if HAVE_SPINLOCKS
275 > static spinlock_t atomic_ops_lock = SPIN_LOCK_UNLOCKED;
276 > #else
277 > #define spin_lock(LOCK)
278 > #define spin_unlock(LOCK)
279 > #endif
280 >
281 > int atomic_add(int *var, int v)
282 > {
283 >        spin_lock(&atomic_ops_lock);
284 >        int ret = *var;
285 >        *var += v;
286 >        spin_unlock(&atomic_ops_lock);
287 >        return ret;
288 > }
289 >
290 > int atomic_and(int *var, int v)
291 > {
292 >        spin_lock(&atomic_ops_lock);
293 >        int ret = *var;
294 >        *var &= v;
295 >        spin_unlock(&atomic_ops_lock);
296 >        return ret;
297 > }
298 >
299 > int atomic_or(int *var, int v)
300 > {
301 >        spin_lock(&atomic_ops_lock);
302 >        int ret = *var;
303 >        *var |= v;
304 >        spin_unlock(&atomic_ops_lock);
305 >        return ret;
306   }
307 + #endif
308  
309  
310   /*
# Line 325 | Line 325 | int main(int argc, char **argv)
325          char str[256];
326          uint32 *boot_globs;
327          int16 i16;
328        int drive, driver;
328          int rom_fd;
329          FILE *proc_file;
330          const char *rom_path;
# Line 335 | Line 334 | int main(int argc, char **argv)
334  
335          // Initialize variables
336          RAMBase = 0;
338        mmap_RAMBase = NULL;
337          tzset();
338  
339          // Print some info
# Line 464 | Line 462 | int main(int argc, char **argv)
462          }
463  
464          // Create Low Memory area (0x0000..0x3000)
465 <        if (mmap((char *)0x0000, 0x3000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) {
465 >        if (vm_acquire_fixed((char *)0, 0x3000) < 0) {
466                  sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
467                  ErrorAlert(str);
468                  goto quit;
# Line 488 | Line 486 | int main(int argc, char **argv)
486                  ErrorAlert(str);
487                  goto quit;
488          }
489 <        kernel_data = (KernelData *)0x68ffe000;
489 >        kernel_data = (KernelData *)KERNEL_DATA_BASE;
490          emulator_data = &kernel_data->ed;
491 <        KernelDataAddr = (uint32)kernel_data;
491 >        KernelDataAddr = KERNEL_DATA_BASE;
492          D(bug("Kernel Data at %p, Emulator Data at %p\n", kernel_data, emulator_data));
493  
494 +        // Create area for SheepShaver data
495 +        if (!SheepMem::Init()) {
496 +                sprintf(str, GetString(STR_SHEEP_MEM_MMAP_ERR), strerror(errno));
497 +                ErrorAlert(str);
498 +                goto quit;
499 +        }
500 +
501          // Create area for Mac ROM
502 <        if (mmap((char *)ROM_BASE, ROM_AREA_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) {
502 >        if (vm_acquire_fixed((char *)ROM_BASE, ROM_AREA_SIZE) < 0) {
503                  sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno));
504                  ErrorAlert(str);
505                  goto quit;
506          }
507 + #if !EMULATED_PPC || defined(__powerpc__)
508 +        if (vm_protect((char *)ROM_BASE, ROM_AREA_SIZE, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) {
509 +                sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno));
510 +                ErrorAlert(str);
511 +                goto quit;
512 +        }
513 + #endif
514          rom_area_mapped = true;
515          D(bug("ROM area at %08x\n", ROM_BASE));
516  
# Line 509 | Line 521 | int main(int argc, char **argv)
521                  RAMSize = 8*1024*1024;
522          }
523  
524 <        mmap_RAMBase = mmap((void *)0x20000000, RAMSize, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0);
513 <        if (mmap_RAMBase == (void *)-1) {
524 >        if (vm_acquire_fixed((char *)RAM_BASE, RAMSize) < 0) {
525                  sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
526                  ErrorAlert(str);
527                  goto quit;
528          }
529 <        RAMBase = (uint32)mmap_RAMBase;
529 > #if !EMULATED_PPC
530 >        if (vm_protect((char *)RAM_BASE, RAMSize, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) {
531 >                sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
532 >                ErrorAlert(str);
533 >                goto quit;
534 >        }
535 > #endif
536 >        RAMBase = RAM_BASE;
537          ram_area_mapped = true;
538          D(bug("RAM area at %08x\n", RAMBase));
539  
# Line 540 | Line 558 | int main(int argc, char **argv)
558          rom_tmp = new uint8[ROM_SIZE];
559          actual = read(rom_fd, (void *)rom_tmp, ROM_SIZE);
560          close(rom_fd);
561 <        if (actual == ROM_SIZE) {
562 <                // Plain ROM image
563 <                memcpy((void *)ROM_BASE, rom_tmp, ROM_SIZE);
564 <                delete[] rom_tmp;
547 <        } else {
548 <                if (strncmp((char *)rom_tmp, "<CHRP-BOOT>", 11) == 0) {
549 <                        // CHRP compressed ROM image
550 <                        D(bug("CHRP ROM image\n"));
551 <                        uint32 lzss_offset, lzss_size;
552 <
553 <                        char *s = strstr((char *)rom_tmp, "constant lzss-offset");
554 <                        if (s == NULL) {
555 <                                ErrorAlert(GetString(STR_ROM_SIZE_ERR));
556 <                                goto quit;
557 <                        }
558 <                        s -= 7;
559 <                        if (sscanf(s, "%06x", &lzss_offset) != 1) {
560 <                                ErrorAlert(GetString(STR_ROM_SIZE_ERR));
561 <                                goto quit;
562 <                        }
563 <                        s = strstr((char *)rom_tmp, "constant lzss-size");
564 <                        if (s == NULL) {
565 <                                ErrorAlert(GetString(STR_ROM_SIZE_ERR));
566 <                                goto quit;
567 <                        }
568 <                        s -= 7;
569 <                        if (sscanf(s, "%06x", &lzss_size) != 1) {
570 <                                ErrorAlert(GetString(STR_ROM_SIZE_ERR));
571 <                                goto quit;
572 <                        }
573 <                        D(bug("Offset of compressed data: %08x\n", lzss_offset));
574 <                        D(bug("Size of compressed data: %08x\n", lzss_size));
575 <
576 <                        D(bug("Uncompressing ROM...\n"));
577 <                        decode_lzss(rom_tmp + lzss_offset, (uint8 *)ROM_BASE, lzss_size);
578 <                        delete[] rom_tmp;
579 <                } else if (rom_size != 4*1024*1024) {
561 >        
562 >        // Decode Mac ROM
563 >        if (!DecodeROM(rom_tmp, actual)) {
564 >                if (rom_size != 4*1024*1024) {
565                          ErrorAlert(GetString(STR_ROM_SIZE_ERR));
566                          goto quit;
567                  } else {
# Line 584 | Line 569 | int main(int argc, char **argv)
569                          goto quit;
570                  }
571          }
572 +        delete[] rom_tmp;
573  
574          // Load NVRAM
575          XPRAMInit();
576  
577          // Set boot volume
578 <        drive = PrefsFindInt32("bootdrive");
578 >        i16 = PrefsFindInt32("bootdrive");
579          XPRAM[0x1378] = i16 >> 8;
580          XPRAM[0x1379] = i16 & 0xff;
581 <        driver = PrefsFindInt32("bootdriver");
581 >        i16 = PrefsFindInt32("bootdriver");
582          XPRAM[0x137a] = i16 >> 8;
583          XPRAM[0x137b] = i16 & 0xff;
584  
# Line 605 | Line 591 | int main(int argc, char **argv)
591          boot_globs[1] = htonl(RAMSize);
592          boot_globs[2] = htonl((uint32)-1);                      // End of bank table
593  
594 +        // Init thunks
595 +        if (!ThunksInit())
596 +                goto quit;
597 +
598          // Init drivers
599          SonyInit();
600          DiskInit();
# Line 614 | Line 604 | int main(int argc, char **argv)
604          // Init external file system
605          ExtFSInit();
606  
607 +        // Init ADB
608 +        ADBInit();
609 +
610          // Init audio
611          AudioInit();
612  
# Line 643 | Line 636 | int main(int argc, char **argv)
636   #if !EMULATED_PPC
637          MakeExecutable(0, (void *)ROM_BASE, ROM_AREA_SIZE);
638   #endif
639 <        mprotect((char *)ROM_BASE, ROM_AREA_SIZE, PROT_EXEC | PROT_READ);
639 >        vm_protect((char *)ROM_BASE, ROM_AREA_SIZE, VM_PAGE_READ | VM_PAGE_EXECUTE);
640  
641          // Initialize Kernel Data
642          memset(kernel_data, 0, sizeof(KernelData));
643          if (ROMType == ROMTYPE_NEWWORLD) {
644 <                static uint32 of_dev_tree[4] = {0, 0, 0, 0};
645 <                static uint8 vector_lookup_tbl[128];
646 <                static uint8 vector_mask_tbl[64];
644 >                uintptr of_dev_tree = SheepMem::Reserve(4 * sizeof(uint32));
645 >                memset((void *)of_dev_tree, 0, 4 * sizeof(uint32));
646 >                uintptr vector_lookup_tbl = SheepMem::Reserve(128);
647 >                uintptr vector_mask_tbl = SheepMem::Reserve(64);
648                  memset((uint8 *)kernel_data + 0xb80, 0x3d, 0x80);
649 <                memset(vector_lookup_tbl, 0, 128);
650 <                memset(vector_mask_tbl, 0, 64);
649 >                memset((void *)vector_lookup_tbl, 0, 128);
650 >                memset((void *)vector_mask_tbl, 0, 64);
651                  kernel_data->v[0xb80 >> 2] = htonl(ROM_BASE);
652 <                kernel_data->v[0xb84 >> 2] = htonl((uint32)of_dev_tree);        // OF device tree base
653 <                kernel_data->v[0xb90 >> 2] = htonl((uint32)vector_lookup_tbl);
654 <                kernel_data->v[0xb94 >> 2] = htonl((uint32)vector_mask_tbl);
652 >                kernel_data->v[0xb84 >> 2] = htonl(of_dev_tree);                        // OF device tree base
653 >                kernel_data->v[0xb90 >> 2] = htonl(vector_lookup_tbl);
654 >                kernel_data->v[0xb94 >> 2] = htonl(vector_mask_tbl);
655                  kernel_data->v[0xb98 >> 2] = htonl(ROM_BASE);                           // OpenPIC base
656                  kernel_data->v[0xbb0 >> 2] = htonl(0);                                          // ADB base
657                  kernel_data->v[0xc20 >> 2] = htonl(RAMSize);
# Line 693 | Line 687 | int main(int argc, char **argv)
687          D(bug("Initializing Low Memory...\n"));
688          memset(NULL, 0, 0x3000);
689          WriteMacInt32(XLM_SIGNATURE, FOURCC('B','a','a','h'));                  // Signature to detect SheepShaver
690 <        WriteMacInt32(XLM_KERNEL_DATA, (uint32)kernel_data);                    // For trap replacement routines
690 >        WriteMacInt32(XLM_KERNEL_DATA, KernelDataAddr);                                 // For trap replacement routines
691          WriteMacInt32(XLM_PVR, PVR);                                                                    // Theoretical PVR
692          WriteMacInt32(XLM_BUS_CLOCK, BusClockSpeed);                                    // For DriverServicesLib patch
693          WriteMacInt16(XLM_EXEC_RETURN_OPCODE, M68K_EXEC_RETURN);                // For Execute68k() (RTS from the executed 68k code will jump here and end 68k mode)
694 +        WriteMacInt32(XLM_ZERO_PAGE, SheepMem::ZeroPage());                             // Pointer to read-only page with all bits set to 0
695   #if !EMULATED_PPC
696 <        WriteMacInt32(XLM_TOC, (uint32)TOC);                                                    // TOC pointer of emulator
702 <        WriteMacInt32(XLM_ETHER_INIT, (uint32)InitStreamModule);                // DLPI ethernet driver functions
703 <        WriteMacInt32(XLM_ETHER_TERM, (uint32)TerminateStreamModule);
704 <        WriteMacInt32(XLM_ETHER_OPEN, (uint32)ether_open);
705 <        WriteMacInt32(XLM_ETHER_CLOSE, (uint32)ether_close);
706 <        WriteMacInt32(XLM_ETHER_WPUT, (uint32)ether_wput);
707 <        WriteMacInt32(XLM_ETHER_RSRV, (uint32)ether_rsrv);
708 <        WriteMacInt32(XLM_VIDEO_DOIO, (uint32)VideoDoDriverIO);
696 >        WriteMacInt32(XLM_TOC, (uint32)TOC);                                                            // TOC pointer of emulator
697   #endif
698 +        WriteMacInt32(XLM_ETHER_INIT, NativeFunction(NATIVE_ETHER_INIT));       // DLPI ethernet driver functions
699 +        WriteMacInt32(XLM_ETHER_TERM, NativeFunction(NATIVE_ETHER_TERM));
700 +        WriteMacInt32(XLM_ETHER_OPEN, NativeFunction(NATIVE_ETHER_OPEN));
701 +        WriteMacInt32(XLM_ETHER_CLOSE, NativeFunction(NATIVE_ETHER_CLOSE));
702 +        WriteMacInt32(XLM_ETHER_WPUT, NativeFunction(NATIVE_ETHER_WPUT));
703 +        WriteMacInt32(XLM_ETHER_RSRV, NativeFunction(NATIVE_ETHER_RSRV));
704 +        WriteMacInt32(XLM_VIDEO_DOIO, NativeFunction(NATIVE_VIDEO_DO_DRIVER_IO));
705          D(bug("Low Memory initialized\n"));
706  
707          // Start 60Hz thread
# Line 767 | Line 762 | int main(int argc, char **argv)
762                  ErrorAlert(str);
763                  goto quit;
764          }
765 + #endif
766  
767          // Install interrupt signal handler
768          sigemptyset(&sigusr2_action.sa_mask);
769          sigusr2_action.sa_handler = (__sighandler_t)sigusr2_handler;
770 +        sigusr2_action.sa_flags = 0;
771 + #if !EMULATED_PPC
772          sigusr2_action.sa_flags = SA_ONSTACK | SA_RESTART;
773 + #endif
774          sigusr2_action.sa_restorer = NULL;
775          if (sigaction(SIGUSR2, &sigusr2_action, NULL) < 0) {
776                  sprintf(str, GetString(STR_SIGUSR2_INSTALL_ERR), strerror(errno));
777                  ErrorAlert(str);
778                  goto quit;
779          }
781 #endif
780  
781          // Get my thread ID and execute MacOS thread function
782          emul_thread = pthread_self();
# Line 797 | Line 795 | quit:
795  
796   static void Quit(void)
797   {
798 + #if EMULATED_PPC
799 +        // Exit PowerPC emulation
800 +        exit_emul_ppc();
801 + #endif
802 +
803          // Stop 60Hz thread
804          if (tick_thread_active) {
805                  pthread_cancel(tick_thread);
# Line 841 | Line 844 | static void Quit(void)
844          // Exit audio
845          AudioExit();
846  
847 +        // Exit ADB
848 +        ADBExit();
849 +
850          // Exit video
851          VideoExit();
852  
# Line 853 | Line 859 | static void Quit(void)
859          DiskExit();
860          SonyExit();
861  
862 +        // Delete SheepShaver globals
863 +        SheepMem::Exit();
864 +
865          // Delete RAM area
866          if (ram_area_mapped)
867 <                munmap(mmap_RAMBase, RAMSize);
867 >                vm_release((char *)RAM_BASE, RAMSize);
868  
869          // Delete ROM area
870          if (rom_area_mapped)
871 <                munmap((char *)ROM_BASE, ROM_AREA_SIZE);
871 >                vm_release((char *)ROM_BASE, ROM_AREA_SIZE);
872  
873          // Delete Kernel Data area
874          if (kernel_area >= 0) {
# Line 900 | Line 909 | static void Quit(void)
909   */
910  
911   #if EMULATED_PPC
903 extern void emul_ppc(uint32 start);
904 extern void init_emul_ppc(void);
912   void jump_to_rom(uint32 entry)
913   {
914          init_emul_ppc();
# Line 970 | Line 977 | void Execute68kTrap(uint16 trap, M68kReg
977  
978  
979   /*
973 *  Execute PPC code from EMUL_OP routine (real mode switch)
974 */
975
976 void ExecutePPC(void (*func)())
977 {
978        uint32 tvect[2] = {(uint32)func, 0};    // Fake TVECT
979        RoutineDescriptor desc = BUILD_PPC_ROUTINE_DESCRIPTOR(0, tvect);
980        M68kRegisters r;
981        Execute68k((uint32)&desc, &r);
982 }
983
984
985 /*
980   *  Quit emulator (cause return from jump_to_rom)
981   */
982  
# Line 1041 | Line 1035 | void Dump68kRegs(M68kRegisters *r)
1035  
1036   void MakeExecutable(int dummy, void *start, uint32 length)
1037   {
1038 < #if !EMULATED_PPC
1045 <        if (((uint32)start >= ROM_BASE) && ((uint32)start < (ROM_BASE + ROM_SIZE)))
1038 >        if (((uintptr)start >= ROM_BASE) && ((uintptr)start < (ROM_BASE + ROM_SIZE)))
1039                  return;
1040 <        flush_icache_range(start, (void *)((uint32)start + length));
1040 > #if EMULATED_PPC
1041 >        FlushCodeCache((uintptr)start, (uintptr)start + length);
1042 > #else
1043 >        flush_icache_range(start, (void *)((uintptr)start + length));
1044   #endif
1045   }
1046  
# Line 1055 | Line 1051 | void MakeExecutable(int dummy, void *sta
1051  
1052   void PatchAfterStartup(void)
1053   {
1054 <        ExecutePPC(VideoInstallAccel);
1054 >        ExecuteNative(NATIVE_VIDEO_INSTALL_ACCEL);
1055          InstallExtFS();
1056   }
1057  
# Line 1158 | Line 1154 | static void *tick_func(void *arg)
1154  
1155   void Set_pthread_attr(pthread_attr_t *attr, int priority)
1156   {
1157 <        // nothing to do
1157 > #ifdef HAVE_PTHREADS
1158 >        pthread_attr_init(attr);
1159 > #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
1160 >        // Some of these only work for superuser
1161 >        if (geteuid() == 0) {
1162 >                pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
1163 >                pthread_attr_setschedpolicy(attr, SCHED_FIFO);
1164 >                struct sched_param fifo_param;
1165 >                fifo_param.sched_priority = ((sched_get_priority_min(SCHED_FIFO) +
1166 >                                              sched_get_priority_max(SCHED_FIFO)) / 2 +
1167 >                                             priority);
1168 >                pthread_attr_setschedparam(attr, &fifo_param);
1169 >        }
1170 >        if (pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM) != 0) {
1171 > #ifdef PTHREAD_SCOPE_BOUND_NP
1172 >            // If system scope is not available (eg. we're not running
1173 >            // with CAP_SCHED_MGT capability on an SGI box), try bound
1174 >            // scope.  It exposes pthread scheduling to the kernel,
1175 >            // without setting realtime priority.
1176 >            pthread_attr_setscope(attr, PTHREAD_SCOPE_BOUND_NP);
1177 > #endif
1178 >        }
1179 > #endif
1180 > #endif
1181   }
1182  
1183  
# Line 1166 | Line 1185 | void Set_pthread_attr(pthread_attr_t *at
1185   *  Mutexes
1186   */
1187  
1188 + #ifdef HAVE_PTHREADS
1189 +
1190 + struct B2_mutex {
1191 +        B2_mutex() {
1192 +            pthread_mutexattr_t attr;
1193 +            pthread_mutexattr_init(&attr);
1194 +            // Initialize the mutex for priority inheritance --
1195 +            // required for accurate timing.
1196 + #ifdef HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL
1197 +            pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
1198 + #endif
1199 + #if defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE) && defined(PTHREAD_MUTEX_NORMAL)
1200 +            pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
1201 + #endif
1202 + #ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED
1203 +            pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
1204 + #endif
1205 +            pthread_mutex_init(&m, &attr);
1206 +            pthread_mutexattr_destroy(&attr);
1207 +        }
1208 +        ~B2_mutex() {
1209 +            pthread_mutex_trylock(&m); // Make sure it's locked before
1210 +            pthread_mutex_unlock(&m);  // unlocking it.
1211 +            pthread_mutex_destroy(&m);
1212 +        }
1213 +        pthread_mutex_t m;
1214 + };
1215 +
1216 + B2_mutex *B2_create_mutex(void)
1217 + {
1218 +        return new B2_mutex;
1219 + }
1220 +
1221 + void B2_lock_mutex(B2_mutex *mutex)
1222 + {
1223 +        pthread_mutex_lock(&mutex->m);
1224 + }
1225 +
1226 + void B2_unlock_mutex(B2_mutex *mutex)
1227 + {
1228 +        pthread_mutex_unlock(&mutex->m);
1229 + }
1230 +
1231 + void B2_delete_mutex(B2_mutex *mutex)
1232 + {
1233 +        delete mutex;
1234 + }
1235 +
1236 + #else
1237 +
1238   struct B2_mutex {
1239          int dummy;
1240   };
# Line 1188 | Line 1257 | void B2_delete_mutex(B2_mutex *mutex)
1257          delete mutex;
1258   }
1259  
1260 + #endif
1261 +
1262  
1263   /*
1264   *  Trigger signal USR2 from another thread
1265   */
1266  
1267 + #if !EMULATED_PPC || ASYNC_IRQ
1268   void TriggerInterrupt(void)
1269   {
1198 #if EMULATED_PPC
1199        WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1);
1200 #else
1201 #if 0
1202        WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1);
1203 #else
1270          if (ready_for_signals)
1271                  pthread_kill(emul_thread, SIGUSR2);
1206 #endif
1207 #endif
1272   }
1273 + #endif
1274  
1275  
1276   /*
# Line 1245 | Line 1310 | void EnableInterrupt(void)
1310   }
1311  
1312  
1248 #if !EMULATED_PPC
1313   /*
1314   *  USR2 handler
1315   */
1316  
1317 + #if EMULATED_PPC
1318 + static void sigusr2_handler(int sig)
1319 + {
1320 + #if ASYNC_IRQ
1321 +        extern void HandleInterrupt(void);
1322 +        HandleInterrupt();
1323 + #endif
1324 + }
1325 + #else
1326   static void sigusr2_handler(int sig, sigcontext_struct *sc)
1327   {
1328          pt_regs *r = sc->regs;
# Line 1319 | Line 1392 | static void sigusr2_handler(int sig, sig
1392                                          if (InterruptFlags & INTFLAG_VIA) {
1393                                                  ClearInterruptFlag(INTFLAG_VIA);
1394                                                  ADBInterrupt();
1395 <                                                ExecutePPC(VideoVBL);
1395 >                                                ExecuteNative(NATIVE_VIDEO_VBL);
1396                                          }
1397                                  }
1398   #endif
# Line 1331 | Line 1404 | static void sigusr2_handler(int sig, sig
1404                          }
1405                          break;
1406   #endif
1334
1407          }
1408   }
1409 + #endif
1410  
1411  
1412   /*
1413   *  SIGSEGV handler
1414   */
1415  
1416 + #if !EMULATED_PPC
1417   static void sigsegv_handler(int sig, sigcontext_struct *sc)
1418   {
1419          pt_regs *r = sc->regs;
1420 +
1421 +        // Get effective address
1422 +        uint32 addr = r->dar;
1423 +        
1424 + #if ENABLE_VOSF
1425 +        // Handle screen fault.
1426 +        extern bool Screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction);
1427 +        if (Screen_fault_handler((sigsegv_address_t)addr, (sigsegv_address_t)r->nip))
1428 +                return;
1429 + #endif
1430 +
1431          num_segv++;
1432  
1433          // Fault in Mac ROM or RAM?
1434          bool mac_fault = (r->nip >= ROM_BASE) && (r->nip < (ROM_BASE + ROM_AREA_SIZE)) || (r->nip >= RAMBase) && (r->nip < (RAMBase + RAMSize));
1435          if (mac_fault) {
1436  
1352                // Get opcode and divide into fields
1353                uint32 opcode = *((uint32 *)r->nip);
1354                uint32 primop = opcode >> 26;
1355                uint32 exop = (opcode >> 1) & 0x3ff;
1356                uint32 ra = (opcode >> 16) & 0x1f;
1357                uint32 rb = (opcode >> 11) & 0x1f;
1358                uint32 rd = (opcode >> 21) & 0x1f;
1359                int32 imm = (int16)(opcode & 0xffff);
1360
1437                  // "VM settings" during MacOS 8 installation
1438                  if (r->nip == ROM_BASE + 0x488160 && r->gpr[20] == 0xf8000000) {
1439                          r->nip += 4;
# Line 1385 | Line 1461 | static void sigsegv_handler(int sig, sig
1461                          return;
1462                  }
1463  
1464 +                // Get opcode and divide into fields
1465 +                uint32 opcode = *((uint32 *)r->nip);
1466 +                uint32 primop = opcode >> 26;
1467 +                uint32 exop = (opcode >> 1) & 0x3ff;
1468 +                uint32 ra = (opcode >> 16) & 0x1f;
1469 +                uint32 rb = (opcode >> 11) & 0x1f;
1470 +                uint32 rd = (opcode >> 21) & 0x1f;
1471 +                int32 imm = (int16)(opcode & 0xffff);
1472 +
1473                  // Analyze opcode
1474                  enum {
1475                          TYPE_UNKNOWN,
# Line 1468 | Line 1553 | static void sigsegv_handler(int sig, sig
1553                                  transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
1554                  }
1555          
1471                // Calculate effective address
1472                uint32 addr = 0;
1473                switch (addr_mode) {
1474                        case MODE_X:
1475                        case MODE_UX:
1476                                if (ra == 0)
1477                                        addr = r->gpr[rb];
1478                                else
1479                                        addr = r->gpr[ra] + r->gpr[rb];
1480                                break;
1481                        case MODE_NORM:
1482                        case MODE_U:
1483                                if (ra == 0)
1484                                        addr = (int32)(int16)imm;
1485                                else
1486                                        addr = r->gpr[ra] + (int32)(int16)imm;
1487                                break;
1488                        default:
1489                                break;
1490                }
1491
1556                  // Ignore ROM writes
1557                  if (transfer_type == TYPE_STORE && addr >= ROM_BASE && addr < ROM_BASE + ROM_SIZE) {
1558   //                      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->nip));
# Line 1725 | Line 1789 | rti:;
1789  
1790  
1791   /*
1792 + *  Helpers to share 32-bit addressable data with MacOS
1793 + */
1794 +
1795 + bool SheepMem::Init(void)
1796 + {
1797 +        const int page_size = getpagesize();
1798 +
1799 +        // Allocate SheepShaver globals
1800 +        if (vm_acquire_fixed((char *)base, size) < 0)
1801 +                return false;
1802 +
1803 +        // Allocate page with all bits set to 0
1804 +        zero_page = base + size;
1805 +        if (vm_acquire_fixed((char *)zero_page, page_size) < 0)
1806 +                return false;
1807 +        memset((char *)zero_page, 0, page_size);
1808 +        if (vm_protect((char *)zero_page, page_size, VM_PAGE_READ) < 0)
1809 +                return false;
1810 +
1811 + #if EMULATED_PPC
1812 +        // Allocate alternate stack for PowerPC interrupt routine
1813 +        sig_stack = zero_page + page_size;
1814 +        if (vm_acquire_fixed((char *)sig_stack, SIG_STACK_SIZE) < 0)
1815 +                return false;
1816 + #endif
1817 +
1818 +        top = base + size;
1819 +        return true;
1820 + }
1821 +
1822 + void SheepMem::Exit(void)
1823 + {
1824 +        if (top) {
1825 +                const int page_size = getpagesize();
1826 +
1827 +                // Delete SheepShaver globals
1828 +                vm_release((void *)base, size);
1829 +
1830 +                // Delete zero page
1831 +                vm_release((void *)zero_page, page_size);
1832 +
1833 + #if EMULATED_PPC
1834 +                // Delete alternate stack for PowerPC interrupt routine
1835 +                vm_release((void *)sig_stack, SIG_STACK_SIZE);
1836 + #endif
1837 +        }
1838 + }
1839 +
1840 +
1841 + /*
1842   *  Display alert
1843   */
1844  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines