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.8 by gbeauche, 2003-09-29T15:46:07Z vs.
Revision 1.20 by gbeauche, 2003-12-05T13:37:54Z

# Line 109 | Line 109
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 145 | Line 146
146   const char ROM_FILE_NAME[] = "ROM";
147   const char ROM_FILE_NAME2[] = "Mac OS ROM";
148  
149 < const uint32 RAM_BASE = 0x20000000;                     // Base address of RAM
149 > const uintptr RAM_BASE = 0x20000000;            // Base address of RAM
150   const uint32 SIG_STACK_SIZE = 0x10000;          // Size of signal stack
151  
152  
# Line 172 | Line 173 | void *TOC;                             // Small data pointer (r13
173   #endif
174   uint32 RAMBase;                 // Base address of Mac RAM
175   uint32 RAMSize;                 // Size of Mac RAM
175 uint32 SheepStack1Base; // SheepShaver first alternate stack base
176 uint32 SheepStack2Base; // SheepShaver second alternate stack base
177 uint32 SheepThunksBase; // SheepShaver thunks base
176   uint32 KernelDataAddr;  // Address of Kernel Data
177   uint32 BootGlobsAddr;   // Address of BootGlobs structure at top of Mac RAM
178   uint32 PVR;                             // Theoretical PVR
# Line 183 | 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  
187   static int zero_fd = 0;                                         // FD of /dev/zero
190 static bool sheep_area_mapped = false;          // Flag: SheepShaver data area mmap()ed
188   static bool lm_area_mapped = false;                     // Flag: Low Memory area mmap()ped
189   static int kernel_area = -1;                            // SHM ID of Kernel Data area
190   static bool rom_area_mapped = false;            // Flag: Mac ROM mmap()ped
# Line 207 | Line 204 | static bool ready_for_signals = false;
204   static int64 num_segv = 0;                                      // Number of handled SEGV signals
205  
206   static struct sigaction sigusr2_action;         // Interrupt signal (of emulator thread)
207 < #if !EMULATED_PPC
207 > #if EMULATED_PPC
208 > static uintptr sig_stack = 0;                           // Stack for PowerPC interrupt routine
209 > #else
210   static struct sigaction sigsegv_action;         // Data access exception signal (of emulator thread)
211   static struct sigaction sigill_action;          // Illegal instruction signal (of emulator thread)
212   static void *sig_stack = NULL;                          // Stack for signal handlers
# Line 216 | Line 215 | static bool emul_thread_fatal = false;
215   static sigregs sigsegv_regs;                            // Register dump when crashed
216   #endif
217  
218 + uintptr SheepMem::zero_page = 0;                        // Address of ro page filled in with zeros
219 + uintptr SheepMem::base = 0x60000000;            // Address of SheepShaver data
220 + uintptr SheepMem::top = 0;                                      // Top of SheepShaver data (stack like storage)
221 +
222  
223   // Prototypes
224   static void Quit(void);
# Line 224 | Line 227 | static void *nvram_func(void *arg);
227   static void *tick_func(void *arg);
228   #if EMULATED_PPC
229   static void sigusr2_handler(int sig);
230 + extern void emul_ppc(uint32 start);
231 + extern void init_emul_ppc(void);
232 + extern void exit_emul_ppc(void);
233   #else
234   static void sigusr2_handler(int sig, sigcontext_struct *sc);
235   static void sigsegv_handler(int sig, sigcontext_struct *sc);
# Line 232 | Line 238 | static void sigill_handler(int sig, sigc
238  
239  
240   // From asm_linux.S
241 < #if EMULATED_PPC
236 < extern int atomic_add(int *var, int v);
237 < extern int atomic_and(int *var, int v);
238 < extern int atomic_or(int *var, int v);
239 < #else
241 > #if !EMULATED_PPC
242   extern "C" void *get_toc(void);
243   extern "C" void *get_sp(void);
244   extern "C" void flush_icache_range(void *start, void *end);
# Line 251 | Line 253 | extern void paranoia_check(void);
253   #endif
254  
255  
256 + #if EMULATED_PPC
257 + /*
258 + *  Return signal stack base
259 + */
260 +
261 + uintptr SignalStackBase(void)
262 + {
263 +        return sig_stack + SIG_STACK_SIZE;
264 + }
265 +
266 +
267 + /*
268 + *  Atomic operations
269 + */
270 +
271 + #if HAVE_SPINLOCKS
272 + static spinlock_t atomic_ops_lock = SPIN_LOCK_UNLOCKED;
273 + #else
274 + #define spin_lock(LOCK)
275 + #define spin_unlock(LOCK)
276 + #endif
277 +
278 + int atomic_add(int *var, int v)
279 + {
280 +        spin_lock(&atomic_ops_lock);
281 +        int ret = *var;
282 +        *var += v;
283 +        spin_unlock(&atomic_ops_lock);
284 +        return ret;
285 + }
286 +
287 + int atomic_and(int *var, int v)
288 + {
289 +        spin_lock(&atomic_ops_lock);
290 +        int ret = *var;
291 +        *var &= v;
292 +        spin_unlock(&atomic_ops_lock);
293 +        return ret;
294 + }
295 +
296 + int atomic_or(int *var, int v)
297 + {
298 +        spin_lock(&atomic_ops_lock);
299 +        int ret = *var;
300 +        *var |= v;
301 +        spin_unlock(&atomic_ops_lock);
302 +        return ret;
303 + }
304 + #endif
305 +
306 +
307   /*
308   *  Main program
309   */
# Line 269 | Line 322 | int main(int argc, char **argv)
322          char str[256];
323          uint32 *boot_globs;
324          int16 i16;
272        int drive, driver;
325          int rom_fd;
326          FILE *proc_file;
327          const char *rom_path;
# Line 431 | Line 483 | int main(int argc, char **argv)
483                  ErrorAlert(str);
484                  goto quit;
485          }
486 <        kernel_data = (KernelData *)0x68ffe000;
486 >        kernel_data = (KernelData *)KERNEL_DATA_BASE;
487          emulator_data = &kernel_data->ed;
488 <        KernelDataAddr = (uint32)kernel_data;
488 >        KernelDataAddr = KERNEL_DATA_BASE;
489          D(bug("Kernel Data at %p, Emulator Data at %p\n", kernel_data, emulator_data));
490  
491          // Create area for SheepShaver data
492 <        if (vm_acquire_fixed((char *)SHEEP_BASE, SHEEP_SIZE) < 0) {
492 >        if (!SheepMem::Init()) {
493                  sprintf(str, GetString(STR_SHEEP_MEM_MMAP_ERR), strerror(errno));
494                  ErrorAlert(str);
495                  goto quit;
496          }
445        SheepStack1Base = SHEEP_BASE + 0x10000;
446        SheepStack2Base = SheepStack1Base + 0x10000;
447        SheepThunksBase = SheepStack2Base + 0x1000;
448        sheep_area_mapped = true;
497  
498          // Create area for Mac ROM
499          if (vm_acquire_fixed((char *)ROM_BASE, ROM_AREA_SIZE) < 0) {
# Line 524 | Line 572 | int main(int argc, char **argv)
572          XPRAMInit();
573  
574          // Set boot volume
575 <        drive = PrefsFindInt32("bootdrive");
575 >        i16 = PrefsFindInt32("bootdrive");
576          XPRAM[0x1378] = i16 >> 8;
577          XPRAM[0x1379] = i16 & 0xff;
578 <        driver = PrefsFindInt32("bootdriver");
578 >        i16 = PrefsFindInt32("bootdriver");
579          XPRAM[0x137a] = i16 >> 8;
580          XPRAM[0x137b] = i16 & 0xff;
581  
# Line 540 | Line 588 | int main(int argc, char **argv)
588          boot_globs[1] = htonl(RAMSize);
589          boot_globs[2] = htonl((uint32)-1);                      // End of bank table
590  
591 +        // Init thunks
592 +        if (!ThunksInit())
593 +                goto quit;
594 +
595          // Init drivers
596          SonyInit();
597          DiskInit();
# Line 583 | Line 635 | int main(int argc, char **argv)
635          // Initialize Kernel Data
636          memset(kernel_data, 0, sizeof(KernelData));
637          if (ROMType == ROMTYPE_NEWWORLD) {
638 <                static uint32 of_dev_tree[4] = {0, 0, 0, 0};
639 <                static uint8 vector_lookup_tbl[128];
640 <                static uint8 vector_mask_tbl[64];
638 >                uintptr of_dev_tree = SheepMem::Reserve(4 * sizeof(uint32));
639 >                memset((void *)of_dev_tree, 0, 4 * sizeof(uint32));
640 >                uintptr vector_lookup_tbl = SheepMem::Reserve(128);
641 >                uintptr vector_mask_tbl = SheepMem::Reserve(64);
642                  memset((uint8 *)kernel_data + 0xb80, 0x3d, 0x80);
643 <                memset(vector_lookup_tbl, 0, 128);
644 <                memset(vector_mask_tbl, 0, 64);
643 >                memset((void *)vector_lookup_tbl, 0, 128);
644 >                memset((void *)vector_mask_tbl, 0, 64);
645                  kernel_data->v[0xb80 >> 2] = htonl(ROM_BASE);
646 <                kernel_data->v[0xb84 >> 2] = htonl((uint32)of_dev_tree);        // OF device tree base
647 <                kernel_data->v[0xb90 >> 2] = htonl((uint32)vector_lookup_tbl);
648 <                kernel_data->v[0xb94 >> 2] = htonl((uint32)vector_mask_tbl);
646 >                kernel_data->v[0xb84 >> 2] = htonl(of_dev_tree);                        // OF device tree base
647 >                kernel_data->v[0xb90 >> 2] = htonl(vector_lookup_tbl);
648 >                kernel_data->v[0xb94 >> 2] = htonl(vector_mask_tbl);
649                  kernel_data->v[0xb98 >> 2] = htonl(ROM_BASE);                           // OpenPIC base
650                  kernel_data->v[0xbb0 >> 2] = htonl(0);                                          // ADB base
651                  kernel_data->v[0xc20 >> 2] = htonl(RAMSize);
# Line 628 | Line 681 | int main(int argc, char **argv)
681          D(bug("Initializing Low Memory...\n"));
682          memset(NULL, 0, 0x3000);
683          WriteMacInt32(XLM_SIGNATURE, FOURCC('B','a','a','h'));                  // Signature to detect SheepShaver
684 <        WriteMacInt32(XLM_KERNEL_DATA, (uint32)kernel_data);                    // For trap replacement routines
684 >        WriteMacInt32(XLM_KERNEL_DATA, KernelDataAddr);                                 // For trap replacement routines
685          WriteMacInt32(XLM_PVR, PVR);                                                                    // Theoretical PVR
686          WriteMacInt32(XLM_BUS_CLOCK, BusClockSpeed);                                    // For DriverServicesLib patch
687          WriteMacInt16(XLM_EXEC_RETURN_OPCODE, M68K_EXEC_RETURN);                // For Execute68k() (RTS from the executed 68k code will jump here and end 68k mode)
688 < #if EMULATED_PPC
689 <        WriteMacInt32(XLM_ETHER_INIT, POWERPC_NATIVE_OP_FUNC(NATIVE_ETHER_INIT));
690 <        WriteMacInt32(XLM_ETHER_TERM, POWERPC_NATIVE_OP_FUNC(NATIVE_ETHER_TERM));
638 <        WriteMacInt32(XLM_ETHER_OPEN, POWERPC_NATIVE_OP_FUNC(NATIVE_ETHER_OPEN));
639 <        WriteMacInt32(XLM_ETHER_CLOSE, POWERPC_NATIVE_OP_FUNC(NATIVE_ETHER_CLOSE));
640 <        WriteMacInt32(XLM_ETHER_WPUT, POWERPC_NATIVE_OP_FUNC(NATIVE_ETHER_WPUT));
641 <        WriteMacInt32(XLM_ETHER_RSRV, POWERPC_NATIVE_OP_FUNC(NATIVE_ETHER_RSRV));
642 <        WriteMacInt32(XLM_VIDEO_DOIO, POWERPC_NATIVE_OP_FUNC(NATIVE_VIDEO_DO_DRIVER_IO));
643 < #else
644 <        WriteMacInt32(XLM_TOC, (uint32)TOC);                                                    // TOC pointer of emulator
645 <        WriteMacInt32(XLM_ETHER_INIT, (uint32)InitStreamModule);                // DLPI ethernet driver functions
646 <        WriteMacInt32(XLM_ETHER_TERM, (uint32)TerminateStreamModule);
647 <        WriteMacInt32(XLM_ETHER_OPEN, (uint32)ether_open);
648 <        WriteMacInt32(XLM_ETHER_CLOSE, (uint32)ether_close);
649 <        WriteMacInt32(XLM_ETHER_WPUT, (uint32)ether_wput);
650 <        WriteMacInt32(XLM_ETHER_RSRV, (uint32)ether_rsrv);
651 <        WriteMacInt32(XLM_VIDEO_DOIO, (uint32)VideoDoDriverIO);
688 >        WriteMacInt32(XLM_ZERO_PAGE, SheepMem::ZeroPage());                             // Pointer to read-only page with all bits set to 0
689 > #if !EMULATED_PPC
690 >        WriteMacInt32(XLM_TOC, (uint32)TOC);                                                            // TOC pointer of emulator
691   #endif
692 +        WriteMacInt32(XLM_ETHER_INIT, NativeFunction(NATIVE_ETHER_INIT));       // DLPI ethernet driver functions
693 +        WriteMacInt32(XLM_ETHER_TERM, NativeFunction(NATIVE_ETHER_TERM));
694 +        WriteMacInt32(XLM_ETHER_OPEN, NativeFunction(NATIVE_ETHER_OPEN));
695 +        WriteMacInt32(XLM_ETHER_CLOSE, NativeFunction(NATIVE_ETHER_CLOSE));
696 +        WriteMacInt32(XLM_ETHER_WPUT, NativeFunction(NATIVE_ETHER_WPUT));
697 +        WriteMacInt32(XLM_ETHER_RSRV, NativeFunction(NATIVE_ETHER_RSRV));
698 +        WriteMacInt32(XLM_VIDEO_DOIO, NativeFunction(NATIVE_VIDEO_DO_DRIVER_IO));
699          D(bug("Low Memory initialized\n"));
700  
701          // Start 60Hz thread
# Line 743 | Line 789 | quit:
789  
790   static void Quit(void)
791   {
792 + #if EMULATED_PPC
793 +        // Exit PowerPC emulation
794 +        exit_emul_ppc();
795 + #endif
796 +
797          // Stop 60Hz thread
798          if (tick_thread_active) {
799                  pthread_cancel(tick_thread);
# Line 799 | Line 850 | static void Quit(void)
850          DiskExit();
851          SonyExit();
852  
853 +        // Delete SheepShaver globals
854 +        SheepMem::Exit();
855 +
856          // Delete RAM area
857          if (ram_area_mapped)
858                  vm_release((char *)RAM_BASE, RAMSize);
# Line 846 | Line 900 | static void Quit(void)
900   */
901  
902   #if EMULATED_PPC
849 extern void emul_ppc(uint32 start);
850 extern void init_emul_ppc(void);
903   void jump_to_rom(uint32 entry)
904   {
905          init_emul_ppc();
# Line 912 | Line 964 | void Execute68kTrap(uint16 trap, M68kReg
964          uint16 proc[2] = {trap, M68K_RTS};
965          Execute68k((uint32)proc, r);
966   }
915
916
917 /*
918 *  Execute PPC code from EMUL_OP routine (real mode switch)
919 */
920
921 void ExecutePPC(void (*func)())
922 {
923        uint32 tvect[2] = {(uint32)func, 0};    // Fake TVECT
924        RoutineDescriptor desc = BUILD_PPC_ROUTINE_DESCRIPTOR(0, tvect);
925        M68kRegisters r;
926        Execute68k((uint32)&desc, &r);
927 }
967   #endif
968  
969  
# Line 987 | Line 1026 | void Dump68kRegs(M68kRegisters *r)
1026  
1027   void MakeExecutable(int dummy, void *start, uint32 length)
1028   {
1029 < #if !EMULATED_PPC
991 <        if (((uint32)start >= ROM_BASE) && ((uint32)start < (ROM_BASE + ROM_SIZE)))
1029 >        if (((uintptr)start >= ROM_BASE) && ((uintptr)start < (ROM_BASE + ROM_SIZE)))
1030                  return;
1031 <        flush_icache_range(start, (void *)((uint32)start + length));
1031 > #if EMULATED_PPC
1032 >        FlushCodeCache((uintptr)start, (uintptr)start + length);
1033 > #else
1034 >        flush_icache_range(start, (void *)((uintptr)start + length));
1035   #endif
1036   }
1037  
# Line 1001 | Line 1042 | void MakeExecutable(int dummy, void *sta
1042  
1043   void PatchAfterStartup(void)
1044   {
1004 #if EMULATED_PPC
1045          ExecuteNative(NATIVE_VIDEO_INSTALL_ACCEL);
1006 #else
1007        ExecutePPC(VideoInstallAccel);
1008 #endif
1046          InstallExtFS();
1047   }
1048  
# Line 1108 | Line 1145 | static void *tick_func(void *arg)
1145  
1146   void Set_pthread_attr(pthread_attr_t *attr, int priority)
1147   {
1148 <        // nothing to do
1148 > #ifdef HAVE_PTHREADS
1149 >        pthread_attr_init(attr);
1150 > #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
1151 >        // Some of these only work for superuser
1152 >        if (geteuid() == 0) {
1153 >                pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
1154 >                pthread_attr_setschedpolicy(attr, SCHED_FIFO);
1155 >                struct sched_param fifo_param;
1156 >                fifo_param.sched_priority = ((sched_get_priority_min(SCHED_FIFO) +
1157 >                                              sched_get_priority_max(SCHED_FIFO)) / 2 +
1158 >                                             priority);
1159 >                pthread_attr_setschedparam(attr, &fifo_param);
1160 >        }
1161 >        if (pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM) != 0) {
1162 > #ifdef PTHREAD_SCOPE_BOUND_NP
1163 >            // If system scope is not available (eg. we're not running
1164 >            // with CAP_SCHED_MGT capability on an SGI box), try bound
1165 >            // scope.  It exposes pthread scheduling to the kernel,
1166 >            // without setting realtime priority.
1167 >            pthread_attr_setscope(attr, PTHREAD_SCOPE_BOUND_NP);
1168 > #endif
1169 >        }
1170 > #endif
1171 > #endif
1172   }
1173  
1174  
# Line 1323 | Line 1383 | static void sigusr2_handler(int sig, sig
1383                                          if (InterruptFlags & INTFLAG_VIA) {
1384                                                  ClearInterruptFlag(INTFLAG_VIA);
1385                                                  ADBInterrupt();
1386 <                                                ExecutePPC(VideoVBL);
1386 >                                                ExecuteNative(NATIVE_VIDEO_VBL);
1387                                          }
1388                                  }
1389   #endif
# Line 1720 | Line 1780 | rti:;
1780  
1781  
1782   /*
1783 + *  Helpers to share 32-bit addressable data with MacOS
1784 + */
1785 +
1786 + bool SheepMem::Init(void)
1787 + {
1788 +        const int page_size = getpagesize();
1789 +
1790 +        // Allocate SheepShaver globals
1791 +        if (vm_acquire_fixed((char *)base, size) < 0)
1792 +                return false;
1793 +
1794 +        // Allocate page with all bits set to 0
1795 +        zero_page = base + size;
1796 +        if (vm_acquire_fixed((char *)zero_page, page_size) < 0)
1797 +                return false;
1798 +        memset((char *)zero_page, 0, page_size);
1799 +        if (vm_protect((char *)zero_page, page_size, VM_PAGE_READ) < 0)
1800 +                return false;
1801 +
1802 + #if EMULATED_PPC
1803 +        // Allocate alternate stack for PowerPC interrupt routine
1804 +        sig_stack = zero_page + page_size;
1805 +        if (vm_acquire_fixed((char *)sig_stack, SIG_STACK_SIZE) < 0)
1806 +                return false;
1807 + #endif
1808 +
1809 +        top = base + size;
1810 +        return true;
1811 + }
1812 +
1813 + void SheepMem::Exit(void)
1814 + {
1815 +        if (top) {
1816 +                const int page_size = getpagesize();
1817 +
1818 +                // Delete SheepShaver globals
1819 +                vm_release((void *)base, size);
1820 +
1821 +                // Delete zero page
1822 +                vm_release((void *)zero_page, page_size);
1823 +
1824 + #if EMULATED_PPC
1825 +                // Delete alternate stack for PowerPC interrupt routine
1826 +                vm_release((void *)sig_stack, SIG_STACK_SIZE);
1827 + #endif
1828 +        }
1829 + }
1830 +
1831 +
1832 + /*
1833   *  Display alert
1834   */
1835  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines