2002-02-04 16:58:13 +00:00
|
|
|
/*
|
|
|
|
* main_unix.cpp - Emulation core, Unix implementation
|
|
|
|
*
|
2010-02-21 09:59:52 +00:00
|
|
|
* SheepShaver (C) Christian Bauer and Marc Hellwig
|
2002-02-04 16:58:13 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NOTES:
|
|
|
|
*
|
|
|
|
* See main_beos.cpp for a description of the three operating modes.
|
|
|
|
*
|
|
|
|
* In addition to that, we have to handle the fact that the MacOS ABI
|
|
|
|
* is slightly different from the SysV ABI used by Linux:
|
|
|
|
* - Stack frames are different (e.g. LR is stored in 8(r1) under
|
|
|
|
* MacOS, but in 4(r1) under Linux)
|
2005-02-27 21:52:06 +00:00
|
|
|
* - There is a pointer to Thread Local Storage (TLS) under Linux with
|
|
|
|
* recent enough glibc. This is r2 in 32-bit mode and r13 in
|
|
|
|
* 64-bit mode (PowerOpen/AIX ABI)
|
2002-02-04 16:58:13 +00:00
|
|
|
* - r13 is used as a small data pointer under Linux (but appearently
|
|
|
|
* it is not used this way? To be sure, we specify -msdata=none
|
|
|
|
* in the Makefile)
|
2005-02-27 21:52:06 +00:00
|
|
|
* - There are no TVECTs under Linux; function pointers point
|
|
|
|
* directly to the function code
|
2002-02-04 16:58:13 +00:00
|
|
|
* The Execute*() functions have to account for this. Additionally, we
|
|
|
|
* cannot simply call MacOS functions by getting their TVECT and jumping
|
|
|
|
* to it. Such calls are done via the call_macos*() functions in
|
|
|
|
* asm_linux.S that create a MacOS stack frame, load the TOC pointer
|
|
|
|
* and put the arguments into the right registers.
|
|
|
|
*
|
|
|
|
* As on the BeOS, we have to specify an alternate signal stack because
|
|
|
|
* interrupts (and, under Linux, Low Memory accesses) may occur when r1
|
|
|
|
* is pointing to the Kernel Data or to Low Memory. There is one
|
|
|
|
* problem, however, due to the alternate signal stack being global to
|
|
|
|
* all signal handlers. Consider the following scenario:
|
|
|
|
* - The main thread is executing some native PPC MacOS code in
|
|
|
|
* MODE_NATIVE, running on the MacOS stack (somewhere in the Mac RAM).
|
|
|
|
* - A SIGUSR2 interrupt occurs. The kernel switches to the signal
|
|
|
|
* stack and starts executing the SIGUSR2 signal handler.
|
|
|
|
* - The signal handler sees the MODE_NATIVE and calls ppc_interrupt()
|
|
|
|
* to handle a native interrupt.
|
|
|
|
* - ppc_interrupt() sets r1 to point to the Kernel Data and jumps to
|
|
|
|
* the nanokernel.
|
|
|
|
* - The nanokernel accesses a Low Memory global (most likely one of
|
|
|
|
* the XLMs), a SIGSEGV occurs.
|
|
|
|
* - The kernel sees that r1 does not point to the signal stack and
|
|
|
|
* switches to the signal stack again, thus overwriting the data that
|
|
|
|
* the SIGUSR2 handler put there.
|
|
|
|
* The same problem arises when calling ExecutePPC() inside the MODE_EMUL_OP
|
|
|
|
* interrupt handler.
|
|
|
|
*
|
|
|
|
* The solution is to set the signal stack to a second, "extra" stack
|
|
|
|
* inside the SIGUSR2 handler before entering the Nanokernel or calling
|
|
|
|
* ExecutePPC (or any function that might cause a mode switch). The signal
|
|
|
|
* stack is restored before exiting the SIGUSR2 handler.
|
|
|
|
*
|
2005-06-28 16:47:32 +00:00
|
|
|
* Note that POSIX standard says you can't modify the alternate
|
|
|
|
* signal stack while the process is executing on it. There is a
|
|
|
|
* hackaround though: we install a trampoline SIGUSR2 handler that
|
|
|
|
* sets up an alternate stack itself and calls the real handler.
|
|
|
|
* Then, when we call sigaltstack() there, we no longer get an EPERM,
|
|
|
|
* i.e. it now works.
|
2004-04-14 20:25:26 +00:00
|
|
|
*
|
2002-02-04 16:58:13 +00:00
|
|
|
* TODO:
|
|
|
|
* check if SIGSEGV handler works for all registers (including FP!)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#include <sys/ipc.h>
|
|
|
|
#include <sys/shm.h>
|
2009-07-23 19:12:51 +00:00
|
|
|
#include <sys/stat.h>
|
2002-02-04 16:58:13 +00:00
|
|
|
#include <signal.h>
|
|
|
|
|
|
|
|
#include "sysdeps.h"
|
|
|
|
#include "main.h"
|
|
|
|
#include "version.h"
|
|
|
|
#include "prefs.h"
|
|
|
|
#include "prefs_editor.h"
|
|
|
|
#include "cpu_emulation.h"
|
|
|
|
#include "emul_op.h"
|
|
|
|
#include "xlowmem.h"
|
|
|
|
#include "xpram.h"
|
|
|
|
#include "timer.h"
|
|
|
|
#include "adb.h"
|
|
|
|
#include "video.h"
|
|
|
|
#include "sys.h"
|
|
|
|
#include "macos_util.h"
|
|
|
|
#include "rom_patches.h"
|
|
|
|
#include "user_strings.h"
|
2003-05-13 16:59:57 +00:00
|
|
|
#include "vm_alloc.h"
|
2003-05-22 22:12:05 +00:00
|
|
|
#include "sigsegv.h"
|
2005-07-04 05:34:33 +00:00
|
|
|
#include "sigregs.h"
|
2006-05-01 22:33:34 +00:00
|
|
|
#include "rpc.h"
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
#define DEBUG 0
|
|
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
|
2004-07-03 10:39:07 +00:00
|
|
|
#ifdef HAVE_DIRENT_H
|
|
|
|
#include <dirent.h>
|
|
|
|
#endif
|
|
|
|
|
2004-06-24 15:37:26 +00:00
|
|
|
#ifdef USE_SDL
|
|
|
|
#include <SDL.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef USE_SDL_VIDEO
|
2002-02-04 16:58:13 +00:00
|
|
|
#include <X11/Xlib.h>
|
2004-06-24 15:37:26 +00:00
|
|
|
#endif
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
#ifdef ENABLE_GTK
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef ENABLE_XF86_DGA
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/Xutil.h>
|
2010-02-21 09:59:52 +00:00
|
|
|
#include <X11/extensions/Xxf86dga.h>
|
2002-02-04 16:58:13 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef ENABLE_MON
|
|
|
|
#include "mon.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2004-01-04 18:35:21 +00:00
|
|
|
// Enable emulation of unaligned lmw/stmw?
|
|
|
|
#define EMULATE_UNALIGNED_LOADSTORE_MULTIPLE 1
|
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
// Enable Execute68k() safety checks?
|
|
|
|
#define SAFE_EXEC_68K 0
|
|
|
|
|
|
|
|
// Interrupts in EMUL_OP mode?
|
|
|
|
#define INTERRUPTS_IN_EMUL_OP_MODE 1
|
|
|
|
|
|
|
|
// Interrupts in native mode?
|
|
|
|
#define INTERRUPTS_IN_NATIVE_MODE 1
|
|
|
|
|
|
|
|
|
|
|
|
// Constants
|
|
|
|
const char ROM_FILE_NAME[] = "ROM";
|
|
|
|
const char ROM_FILE_NAME2[] = "Mac OS ROM";
|
|
|
|
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
#if !REAL_ADDRESSING
|
2004-11-13 14:09:16 +00:00
|
|
|
// FIXME: needs to be >= 0x04000000
|
|
|
|
const uintptr RAM_BASE = 0x10000000; // Base address of RAM
|
|
|
|
#endif
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
const uintptr ROM_BASE = 0x40800000; // Base address of ROM
|
|
|
|
#if REAL_ADDRESSING
|
|
|
|
const uint32 ROM_ALIGNMENT = 0x100000; // ROM must be aligned to a 1MB boundary
|
|
|
|
#endif
|
2002-02-04 16:58:13 +00:00
|
|
|
const uint32 SIG_STACK_SIZE = 0x10000; // Size of signal stack
|
|
|
|
|
|
|
|
|
|
|
|
// Global variables (exported)
|
|
|
|
#if !EMULATED_PPC
|
2005-06-28 16:50:30 +00:00
|
|
|
void *TOC = NULL; // Pointer to Thread Local Storage (r2)
|
|
|
|
void *R13 = NULL; // Pointer to .sdata section (r13 under Linux)
|
2002-02-04 16:58:13 +00:00
|
|
|
#endif
|
|
|
|
uint32 RAMBase; // Base address of Mac RAM
|
|
|
|
uint32 RAMSize; // Size of Mac RAM
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
uint32 ROMBase; // Base address of Mac ROM
|
2002-02-04 16:58:13 +00:00
|
|
|
uint32 KernelDataAddr; // Address of Kernel Data
|
|
|
|
uint32 BootGlobsAddr; // Address of BootGlobs structure at top of Mac RAM
|
2004-05-31 09:04:44 +00:00
|
|
|
uint32 DRCacheAddr; // Address of DR Cache
|
2002-02-04 16:58:13 +00:00
|
|
|
uint32 PVR; // Theoretical PVR
|
|
|
|
int64 CPUClockSpeed; // Processor clock speed (Hz)
|
|
|
|
int64 BusClockSpeed; // Bus clock speed (Hz)
|
2004-07-03 10:39:07 +00:00
|
|
|
int64 TimebaseSpeed; // Timebase clock speed (Hz)
|
2004-11-13 14:09:16 +00:00
|
|
|
uint8 *RAMBaseHost; // Base address of Mac RAM (host address space)
|
|
|
|
uint8 *ROMBaseHost; // Base address of Mac ROM (host address space)
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Global variables
|
2004-06-24 15:37:26 +00:00
|
|
|
#ifndef USE_SDL_VIDEO
|
2003-10-26 07:54:02 +00:00
|
|
|
char *x_display_name = NULL; // X11 display name
|
2002-02-04 16:58:13 +00:00
|
|
|
Display *x_display = NULL; // X11 display handle
|
2003-12-31 18:16:55 +00:00
|
|
|
#ifdef X11_LOCK_TYPE
|
|
|
|
X11_LOCK_TYPE x_display_lock = X11_LOCK_INIT; // X11 display lock
|
|
|
|
#endif
|
2004-06-24 15:37:26 +00:00
|
|
|
#endif
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
static int zero_fd = 0; // FD of /dev/zero
|
|
|
|
static bool lm_area_mapped = false; // Flag: Low Memory area mmap()ped
|
|
|
|
static int kernel_area = -1; // SHM ID of Kernel Data area
|
|
|
|
static bool rom_area_mapped = false; // Flag: Mac ROM mmap()ped
|
|
|
|
static bool ram_area_mapped = false; // Flag: Mac RAM mmap()ped
|
2004-05-31 09:04:44 +00:00
|
|
|
static bool dr_cache_area_mapped = false; // Flag: Mac DR Cache mmap()ped
|
|
|
|
static bool dr_emulator_area_mapped = false;// Flag: Mac DR Emulator mmap()ped
|
2002-02-04 16:58:13 +00:00
|
|
|
static KernelData *kernel_data; // Pointer to Kernel Data
|
|
|
|
static EmulatorData *emulator_data;
|
|
|
|
|
|
|
|
static uint8 last_xpram[XPRAM_SIZE]; // Buffer for monitoring XPRAM changes
|
|
|
|
|
|
|
|
static bool nvram_thread_active = false; // Flag: NVRAM watchdog installed
|
2004-06-22 12:20:17 +00:00
|
|
|
static volatile bool nvram_thread_cancel; // Flag: Cancel NVRAM thread
|
2002-02-04 16:58:13 +00:00
|
|
|
static pthread_t nvram_thread; // NVRAM watchdog
|
|
|
|
static bool tick_thread_active = false; // Flag: MacOS thread installed
|
2004-06-22 12:20:17 +00:00
|
|
|
static volatile bool tick_thread_cancel; // Flag: Cancel 60Hz thread
|
2002-02-04 16:58:13 +00:00
|
|
|
static pthread_t tick_thread; // 60Hz thread
|
|
|
|
static pthread_t emul_thread; // MacOS thread
|
|
|
|
|
|
|
|
static bool ready_for_signals = false; // Handler installed, signals can be sent
|
|
|
|
static int64 num_segv = 0; // Number of handled SEGV signals
|
|
|
|
|
|
|
|
static struct sigaction sigusr2_action; // Interrupt signal (of emulator thread)
|
2003-12-05 13:37:56 +00:00
|
|
|
#if EMULATED_PPC
|
|
|
|
static uintptr sig_stack = 0; // Stack for PowerPC interrupt routine
|
|
|
|
#else
|
2002-02-04 16:58:13 +00:00
|
|
|
static struct sigaction sigsegv_action; // Data access exception signal (of emulator thread)
|
|
|
|
static struct sigaction sigill_action; // Illegal instruction signal (of emulator thread)
|
2009-02-11 19:23:53 +00:00
|
|
|
static stack_t sig_stack; // Stack for signal handlers
|
|
|
|
static stack_t extra_stack; // Stack for SIGSEGV inside interrupt handler
|
2002-02-04 16:58:13 +00:00
|
|
|
static bool emul_thread_fatal = false; // Flag: MacOS thread crashed, tick thread shall dump debug output
|
|
|
|
static sigregs sigsegv_regs; // Register dump when crashed
|
2004-01-04 18:35:21 +00:00
|
|
|
static const char *crash_reason = NULL; // Reason of the crash (SIGSEGV, SIGBUS, SIGILL)
|
2002-02-04 16:58:13 +00:00
|
|
|
#endif
|
|
|
|
|
2006-05-01 22:33:34 +00:00
|
|
|
static rpc_connection_t *gui_connection = NULL; // RPC connection to the GUI
|
|
|
|
static const char *gui_connection_path = NULL; // GUI connection identifier
|
|
|
|
|
2004-02-24 11:12:54 +00:00
|
|
|
uint32 SheepMem::page_size; // Size of a native page
|
2003-12-05 12:36:11 +00:00
|
|
|
uintptr SheepMem::zero_page = 0; // Address of ro page filled in with zeros
|
2003-12-04 17:26:38 +00:00
|
|
|
uintptr SheepMem::base = 0x60000000; // Address of SheepShaver data
|
2004-11-22 21:33:32 +00:00
|
|
|
uintptr SheepMem::proc; // Bottom address of SheepShave procedures
|
|
|
|
uintptr SheepMem::data; // Top of SheepShaver data (stack like storage)
|
2003-12-04 17:26:38 +00:00
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
// Prototypes
|
2004-11-22 21:33:32 +00:00
|
|
|
static bool kernel_data_init(void);
|
|
|
|
static void kernel_data_exit(void);
|
2002-02-04 16:58:13 +00:00
|
|
|
static void Quit(void);
|
|
|
|
static void *emul_func(void *arg);
|
|
|
|
static void *nvram_func(void *arg);
|
|
|
|
static void *tick_func(void *arg);
|
2003-09-29 15:46:09 +00:00
|
|
|
#if EMULATED_PPC
|
2003-11-03 21:28:32 +00:00
|
|
|
extern void emul_ppc(uint32 start);
|
|
|
|
extern void init_emul_ppc(void);
|
|
|
|
extern void exit_emul_ppc(void);
|
2007-12-30 09:18:40 +00:00
|
|
|
sigsegv_return_t sigsegv_handler(sigsegv_info_t *sip);
|
2003-09-29 15:46:09 +00:00
|
|
|
#else
|
2005-06-28 16:47:32 +00:00
|
|
|
extern "C" void sigusr2_handler_init(int sig, siginfo_t *sip, void *scp);
|
|
|
|
extern "C" void sigusr2_handler(int sig, siginfo_t *sip, void *scp);
|
2004-01-18 22:14:31 +00:00
|
|
|
static void sigsegv_handler(int sig, siginfo_t *sip, void *scp);
|
|
|
|
static void sigill_handler(int sig, siginfo_t *sip, void *scp);
|
2002-02-04 16:58:13 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
// From asm_linux.S
|
2003-10-26 09:14:14 +00:00
|
|
|
#if !EMULATED_PPC
|
2002-02-04 16:58:13 +00:00
|
|
|
extern "C" void *get_sp(void);
|
2005-02-27 21:52:06 +00:00
|
|
|
extern "C" void *get_r2(void);
|
|
|
|
extern "C" void set_r2(void *);
|
|
|
|
extern "C" void *get_r13(void);
|
|
|
|
extern "C" void set_r13(void *);
|
2005-01-30 21:25:24 +00:00
|
|
|
extern "C" void flush_icache_range(uint32 start, uint32 end);
|
2002-02-04 16:58:13 +00:00
|
|
|
extern "C" void jump_to_rom(uint32 entry, uint32 context);
|
|
|
|
extern "C" void quit_emulator(void);
|
|
|
|
extern "C" void execute_68k(uint32 pc, M68kRegisters *r);
|
|
|
|
extern "C" void ppc_interrupt(uint32 entry, uint32 kernel_data);
|
|
|
|
extern "C" int atomic_add(int *var, int v);
|
|
|
|
extern "C" int atomic_and(int *var, int v);
|
|
|
|
extern "C" int atomic_or(int *var, int v);
|
|
|
|
extern void paranoia_check(void);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2003-10-26 09:14:14 +00:00
|
|
|
#if EMULATED_PPC
|
2003-12-05 13:37:56 +00:00
|
|
|
/*
|
|
|
|
* Return signal stack base
|
|
|
|
*/
|
|
|
|
|
|
|
|
uintptr SignalStackBase(void)
|
|
|
|
{
|
|
|
|
return sig_stack + SIG_STACK_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-26 09:14:14 +00:00
|
|
|
/*
|
|
|
|
* Atomic operations
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if HAVE_SPINLOCKS
|
|
|
|
static spinlock_t atomic_ops_lock = SPIN_LOCK_UNLOCKED;
|
|
|
|
#else
|
|
|
|
#define spin_lock(LOCK)
|
|
|
|
#define spin_unlock(LOCK)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int atomic_add(int *var, int v)
|
|
|
|
{
|
|
|
|
spin_lock(&atomic_ops_lock);
|
|
|
|
int ret = *var;
|
|
|
|
*var += v;
|
|
|
|
spin_unlock(&atomic_ops_lock);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int atomic_and(int *var, int v)
|
|
|
|
{
|
|
|
|
spin_lock(&atomic_ops_lock);
|
|
|
|
int ret = *var;
|
|
|
|
*var &= v;
|
|
|
|
spin_unlock(&atomic_ops_lock);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int atomic_or(int *var, int v)
|
|
|
|
{
|
|
|
|
spin_lock(&atomic_ops_lock);
|
|
|
|
int ret = *var;
|
|
|
|
*var |= v;
|
|
|
|
spin_unlock(&atomic_ops_lock);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2004-11-22 21:33:32 +00:00
|
|
|
/*
|
|
|
|
* Memory management helpers
|
|
|
|
*/
|
|
|
|
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
static inline uint8 *vm_mac_acquire(uint32 size)
|
|
|
|
{
|
|
|
|
return (uint8 *)vm_acquire(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int vm_mac_acquire_fixed(uint32 addr, uint32 size)
|
2004-11-22 21:33:32 +00:00
|
|
|
{
|
|
|
|
return vm_acquire_fixed(Mac2HostAddr(addr), size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int vm_mac_release(uint32 addr, uint32 size)
|
|
|
|
{
|
|
|
|
return vm_release(Mac2HostAddr(addr), size);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
/*
|
|
|
|
* Main program
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void usage(const char *prg_name)
|
|
|
|
{
|
|
|
|
printf("Usage: %s [OPTION...]\n", prg_name);
|
|
|
|
printf("\nUnix options:\n");
|
|
|
|
printf(" --display STRING\n X display to use\n");
|
|
|
|
PrefsPrintUsage();
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
2009-07-23 19:12:51 +00:00
|
|
|
static bool valid_vmdir(const char *path)
|
|
|
|
{
|
|
|
|
const int suffix_len = sizeof(".sheepvm") - 1;
|
|
|
|
int len = strlen(path);
|
2009-08-18 02:36:59 +00:00
|
|
|
if (len && path[len - 1] == '/') // to support both ".sheepvm" and ".sheepvm/"
|
|
|
|
len--;
|
|
|
|
if (len > suffix_len && !strncmp(path + len - suffix_len, ".sheepvm", suffix_len)) {
|
2009-07-23 19:12:51 +00:00
|
|
|
struct stat d;
|
|
|
|
if (!stat(path, &d) && S_ISDIR(d.st_mode)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-12-28 23:17:29 +00:00
|
|
|
static void get_system_info(void)
|
|
|
|
{
|
|
|
|
#if !EMULATED_PPC
|
|
|
|
FILE *proc_file;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
PVR = 0x00040000; // Default: 604
|
|
|
|
CPUClockSpeed = 100000000; // Default: 100MHz
|
|
|
|
BusClockSpeed = 100000000; // Default: 100MHz
|
|
|
|
TimebaseSpeed = 25000000; // Default: 25MHz
|
|
|
|
|
|
|
|
#if EMULATED_PPC
|
|
|
|
PVR = 0x000c0000; // Default: 7400 (with AltiVec)
|
|
|
|
#elif defined(__APPLE__) && defined(__MACH__)
|
|
|
|
proc_file = popen("ioreg -c IOPlatformDevice", "r");
|
|
|
|
if (proc_file) {
|
|
|
|
char line[256];
|
|
|
|
bool powerpc_node = false;
|
|
|
|
while (fgets(line, sizeof(line) - 1, proc_file)) {
|
|
|
|
// Read line
|
|
|
|
int len = strlen(line);
|
|
|
|
if (len == 0)
|
|
|
|
continue;
|
|
|
|
line[len - 1] = 0;
|
|
|
|
|
|
|
|
// Parse line
|
|
|
|
if (strstr(line, "o PowerPC,"))
|
|
|
|
powerpc_node = true;
|
|
|
|
else if (powerpc_node) {
|
|
|
|
uint32 value;
|
|
|
|
char head[256];
|
|
|
|
if (sscanf(line, "%[ |]\"cpu-version\" = <%x>", head, &value) == 2)
|
|
|
|
PVR = value;
|
|
|
|
else if (sscanf(line, "%[ |]\"clock-frequency\" = <%x>", head, &value) == 2)
|
|
|
|
CPUClockSpeed = value;
|
|
|
|
else if (sscanf(line, "%[ |]\"bus-frequency\" = <%x>", head, &value) == 2)
|
|
|
|
BusClockSpeed = value;
|
|
|
|
else if (sscanf(line, "%[ |]\"timebase-frequency\" = <%x>", head, &value) == 2)
|
|
|
|
TimebaseSpeed = value;
|
|
|
|
else if (strchr(line, '}'))
|
|
|
|
powerpc_node = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose(proc_file);
|
|
|
|
} else {
|
2011-12-30 17:38:39 +00:00
|
|
|
char str[256];
|
2011-12-28 23:17:29 +00:00
|
|
|
sprintf(str, GetString(STR_PROC_CPUINFO_WARN), strerror(errno));
|
|
|
|
WarningAlert(str);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
proc_file = fopen("/proc/cpuinfo", "r");
|
|
|
|
if (proc_file) {
|
|
|
|
// CPU specs from Linux kernel
|
|
|
|
// TODO: make it more generic with features (e.g. AltiVec) and
|
|
|
|
// cache information and friends for NameRegistry
|
|
|
|
static const struct {
|
|
|
|
uint32 pvr_mask;
|
|
|
|
uint32 pvr_value;
|
|
|
|
const char *cpu_name;
|
|
|
|
}
|
|
|
|
cpu_specs[] = {
|
|
|
|
{ 0xffff0000, 0x00010000, "601" },
|
|
|
|
{ 0xffff0000, 0x00030000, "603" },
|
|
|
|
{ 0xffff0000, 0x00060000, "603e" },
|
|
|
|
{ 0xffff0000, 0x00070000, "603ev" },
|
|
|
|
{ 0xffff0000, 0x00040000, "604" },
|
|
|
|
{ 0xfffff000, 0x00090000, "604e" },
|
|
|
|
{ 0xffff0000, 0x00090000, "604r" },
|
|
|
|
{ 0xffff0000, 0x000a0000, "604ev" },
|
|
|
|
{ 0xffffffff, 0x00084202, "740/750" },
|
|
|
|
{ 0xfffff000, 0x00083000, "745/755" },
|
|
|
|
{ 0xfffffff0, 0x00080100, "750CX" },
|
|
|
|
{ 0xfffffff0, 0x00082200, "750CX" },
|
|
|
|
{ 0xfffffff0, 0x00082210, "750CXe" },
|
|
|
|
{ 0xffffff00, 0x70000100, "750FX" },
|
|
|
|
{ 0xffffffff, 0x70000200, "750FX" },
|
|
|
|
{ 0xffff0000, 0x70000000, "750FX" },
|
|
|
|
{ 0xffff0000, 0x70020000, "750GX" },
|
|
|
|
{ 0xffff0000, 0x00080000, "740/750" },
|
|
|
|
{ 0xffffffff, 0x000c1101, "7400 (1.1)" },
|
|
|
|
{ 0xffff0000, 0x000c0000, "7400" },
|
|
|
|
{ 0xffff0000, 0x800c0000, "7410" },
|
|
|
|
{ 0xffffffff, 0x80000200, "7450" },
|
|
|
|
{ 0xffffffff, 0x80000201, "7450" },
|
|
|
|
{ 0xffff0000, 0x80000000, "7450" },
|
|
|
|
{ 0xffffff00, 0x80010100, "7455" },
|
|
|
|
{ 0xffffffff, 0x80010200, "7455" },
|
|
|
|
{ 0xffff0000, 0x80010000, "7455" },
|
|
|
|
{ 0xffff0000, 0x80020000, "7457" },
|
|
|
|
{ 0xffff0000, 0x80030000, "7447A" },
|
|
|
|
{ 0xffff0000, 0x80040000, "7448" },
|
|
|
|
{ 0x7fff0000, 0x00810000, "82xx" },
|
|
|
|
{ 0x7fff0000, 0x00820000, "8280" },
|
|
|
|
{ 0xffff0000, 0x00400000, "Power3 (630)" },
|
|
|
|
{ 0xffff0000, 0x00410000, "Power3 (630+)" },
|
|
|
|
{ 0xffff0000, 0x00360000, "I-star" },
|
|
|
|
{ 0xffff0000, 0x00370000, "S-star" },
|
|
|
|
{ 0xffff0000, 0x00350000, "Power4" },
|
|
|
|
{ 0xffff0000, 0x00390000, "PPC970" },
|
|
|
|
{ 0xffff0000, 0x003c0000, "PPC970FX" },
|
|
|
|
{ 0xffff0000, 0x00440000, "PPC970MP" },
|
|
|
|
{ 0xffff0000, 0x003a0000, "POWER5 (gr)" },
|
|
|
|
{ 0xffff0000, 0x003b0000, "POWER5+ (gs)" },
|
|
|
|
{ 0xffff0000, 0x003e0000, "POWER6" },
|
|
|
|
{ 0xffff0000, 0x00700000, "Cell Broadband Engine" },
|
|
|
|
{ 0x7fff0000, 0x00900000, "PA6T" },
|
|
|
|
{ 0, 0, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
char line[256];
|
|
|
|
while(fgets(line, 255, proc_file)) {
|
|
|
|
// Read line
|
|
|
|
int len = strlen(line);
|
|
|
|
if (len == 0)
|
|
|
|
continue;
|
|
|
|
line[len-1] = 0;
|
|
|
|
|
|
|
|
// Parse line
|
|
|
|
int i;
|
|
|
|
float f;
|
|
|
|
char value[256];
|
|
|
|
if (sscanf(line, "cpu : %[^,]", value) == 1) {
|
|
|
|
// Search by name
|
|
|
|
const char *cpu_name = NULL;
|
|
|
|
for (int i = 0; cpu_specs[i].pvr_mask != 0; i++) {
|
|
|
|
if (strcmp(cpu_specs[i].cpu_name, value) == 0) {
|
|
|
|
cpu_name = cpu_specs[i].cpu_name;
|
|
|
|
PVR = cpu_specs[i].pvr_value;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cpu_name == NULL)
|
|
|
|
printf("WARNING: Unknown CPU type '%s', assuming 604\n", value);
|
|
|
|
else
|
|
|
|
printf("Found a PowerPC %s processor\n", cpu_name);
|
|
|
|
}
|
|
|
|
if (sscanf(line, "clock : %fMHz", &f) == 1)
|
|
|
|
CPUClockSpeed = BusClockSpeed = ((int64)f) * 1000000;
|
|
|
|
else if (sscanf(line, "clock : %dMHz", &i) == 1)
|
|
|
|
CPUClockSpeed = BusClockSpeed = i * 1000000;
|
|
|
|
}
|
|
|
|
fclose(proc_file);
|
|
|
|
} else {
|
|
|
|
sprintf(str, GetString(STR_PROC_CPUINFO_WARN), strerror(errno));
|
|
|
|
WarningAlert(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get actual bus frequency
|
|
|
|
proc_file = fopen("/proc/device-tree/clock-frequency", "r");
|
|
|
|
if (proc_file) {
|
|
|
|
union { uint8 b[4]; uint32 l; } value;
|
|
|
|
if (fread(value.b, sizeof(value), 1, proc_file) == 1)
|
|
|
|
BusClockSpeed = value.l;
|
|
|
|
fclose(proc_file);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get actual timebase frequency
|
|
|
|
TimebaseSpeed = BusClockSpeed / 4;
|
|
|
|
DIR *cpus_dir;
|
|
|
|
if ((cpus_dir = opendir("/proc/device-tree/cpus")) != NULL) {
|
|
|
|
struct dirent *cpu_entry;
|
|
|
|
while ((cpu_entry = readdir(cpus_dir)) != NULL) {
|
|
|
|
if (strstr(cpu_entry->d_name, "PowerPC,") == cpu_entry->d_name) {
|
|
|
|
char timebase_freq_node[256];
|
|
|
|
sprintf(timebase_freq_node, "/proc/device-tree/cpus/%s/timebase-frequency", cpu_entry->d_name);
|
|
|
|
proc_file = fopen(timebase_freq_node, "r");
|
|
|
|
if (proc_file) {
|
|
|
|
union { uint8 b[4]; uint32 l; } value;
|
|
|
|
if (fread(value.b, sizeof(value), 1, proc_file) == 1)
|
|
|
|
TimebaseSpeed = value.l;
|
|
|
|
fclose(proc_file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
closedir(cpus_dir);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Remap any newer G4/G5 processor to plain G4 for compatibility
|
|
|
|
switch (PVR >> 16) {
|
|
|
|
case 0x8000: // 7450
|
|
|
|
case 0x8001: // 7455
|
|
|
|
case 0x8002: // 7457
|
|
|
|
case 0x8003: // 7447A
|
|
|
|
case 0x8004: // 7448
|
|
|
|
case 0x0039: // 970
|
|
|
|
case 0x003c: // 970FX
|
|
|
|
case 0x0044: // 970MP
|
|
|
|
PVR = 0x000c0000; // 7400
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
D(bug("PVR: %08x (assumed)\n", PVR));
|
|
|
|
}
|
|
|
|
|
2011-12-28 23:24:30 +00:00
|
|
|
static bool load_mac_rom(void)
|
2002-02-04 16:58:13 +00:00
|
|
|
{
|
|
|
|
uint32 rom_size, actual;
|
|
|
|
uint8 *rom_tmp;
|
2011-12-28 23:24:30 +00:00
|
|
|
const char *rom_path = PrefsFindString("rom");
|
|
|
|
int rom_fd = open(rom_path && *rom_path ? rom_path : ROM_FILE_NAME, O_RDONLY);
|
|
|
|
if (rom_fd < 0) {
|
|
|
|
rom_fd = open(ROM_FILE_NAME2, O_RDONLY);
|
|
|
|
if (rom_fd < 0) {
|
|
|
|
ErrorAlert(GetString(STR_NO_ROM_FILE_ERR));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printf("%s", GetString(STR_READING_ROM_FILE));
|
|
|
|
rom_size = lseek(rom_fd, 0, SEEK_END);
|
|
|
|
lseek(rom_fd, 0, SEEK_SET);
|
|
|
|
rom_tmp = new uint8[ROM_SIZE];
|
|
|
|
actual = read(rom_fd, (void *)rom_tmp, ROM_SIZE);
|
|
|
|
close(rom_fd);
|
|
|
|
|
|
|
|
// Decode Mac ROM
|
|
|
|
if (!DecodeROM(rom_tmp, actual)) {
|
|
|
|
if (rom_size != 4*1024*1024) {
|
|
|
|
ErrorAlert(GetString(STR_ROM_SIZE_ERR));
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
ErrorAlert(GetString(STR_ROM_FILE_READ_ERR));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
delete[] rom_tmp;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-12-28 23:30:25 +00:00
|
|
|
static bool install_signal_handlers(void)
|
|
|
|
{
|
|
|
|
char str[256];
|
|
|
|
#if !EMULATED_PPC
|
|
|
|
// Create and install stacks for signal handlers
|
|
|
|
sig_stack.ss_sp = malloc(SIG_STACK_SIZE);
|
|
|
|
D(bug("Signal stack at %p\n", sig_stack.ss_sp));
|
|
|
|
if (sig_stack.ss_sp == NULL) {
|
|
|
|
ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sig_stack.ss_flags = 0;
|
|
|
|
sig_stack.ss_size = SIG_STACK_SIZE;
|
|
|
|
if (sigaltstack(&sig_stack, NULL) < 0) {
|
|
|
|
sprintf(str, GetString(STR_SIGALTSTACK_ERR), strerror(errno));
|
|
|
|
ErrorAlert(str);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
extra_stack.ss_sp = malloc(SIG_STACK_SIZE);
|
|
|
|
D(bug("Extra stack at %p\n", extra_stack.ss_sp));
|
|
|
|
if (extra_stack.ss_sp == NULL) {
|
|
|
|
ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
extra_stack.ss_flags = 0;
|
|
|
|
extra_stack.ss_size = SIG_STACK_SIZE;
|
|
|
|
|
|
|
|
// Install SIGSEGV and SIGBUS handlers
|
|
|
|
sigemptyset(&sigsegv_action.sa_mask); // Block interrupts during SEGV handling
|
|
|
|
sigaddset(&sigsegv_action.sa_mask, SIGUSR2);
|
|
|
|
sigsegv_action.sa_sigaction = sigsegv_handler;
|
|
|
|
sigsegv_action.sa_flags = SA_ONSTACK | SA_SIGINFO;
|
|
|
|
#ifdef HAVE_SIGNAL_SA_RESTORER
|
|
|
|
sigsegv_action.sa_restorer = NULL;
|
|
|
|
#endif
|
|
|
|
if (sigaction(SIGSEGV, &sigsegv_action, NULL) < 0) {
|
|
|
|
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGSEGV", strerror(errno));
|
|
|
|
ErrorAlert(str);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (sigaction(SIGBUS, &sigsegv_action, NULL) < 0) {
|
|
|
|
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGBUS", strerror(errno));
|
|
|
|
ErrorAlert(str);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
// Install SIGSEGV handler for CPU emulator
|
|
|
|
if (!sigsegv_install_handler(sigsegv_handler)) {
|
|
|
|
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGSEGV", strerror(errno));
|
|
|
|
ErrorAlert(str);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-12-28 23:33:04 +00:00
|
|
|
static bool init_sdl()
|
2011-12-28 23:24:30 +00:00
|
|
|
{
|
2011-12-28 23:33:04 +00:00
|
|
|
int sdl_flags = 0;
|
|
|
|
#ifdef USE_SDL_VIDEO
|
|
|
|
sdl_flags |= SDL_INIT_VIDEO;
|
|
|
|
#endif
|
|
|
|
#ifdef USE_SDL_AUDIO
|
|
|
|
sdl_flags |= SDL_INIT_AUDIO;
|
|
|
|
#endif
|
|
|
|
assert(sdl_flags != 0);
|
2002-02-04 16:58:13 +00:00
|
|
|
|
2007-08-27 21:45:13 +00:00
|
|
|
#ifdef USE_SDL_VIDEO
|
2008-06-22 20:30:12 +00:00
|
|
|
// Don't let SDL block the screensaver
|
2010-08-22 18:56:11 +00:00
|
|
|
setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", TRUE);
|
2008-06-22 20:30:12 +00:00
|
|
|
|
|
|
|
// Make SDL pass through command-clicks and option-clicks unaltered
|
2010-08-22 18:56:11 +00:00
|
|
|
setenv("SDL_HAS3BUTTONMOUSE", "1", TRUE);
|
2007-08-27 21:45:13 +00:00
|
|
|
#endif
|
|
|
|
|
2011-12-28 23:33:04 +00:00
|
|
|
if (SDL_Init(sdl_flags) == -1) {
|
|
|
|
char str[256];
|
|
|
|
sprintf(str, "Could not initialize SDL: %s.\n", SDL_GetError());
|
|
|
|
ErrorAlert(str);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
atexit(SDL_Quit);
|
|
|
|
|
|
|
|
// Don't let SDL catch SIGINT and SIGTERM signals
|
|
|
|
signal(SIGINT, SIG_DFL);
|
|
|
|
signal(SIGTERM, SIG_DFL);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
char str[256];
|
|
|
|
bool memory_mapped_from_zero, ram_rom_areas_contiguous;
|
|
|
|
const char *vmdir = NULL;
|
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
// Initialize variables
|
|
|
|
RAMBase = 0;
|
|
|
|
tzset();
|
|
|
|
|
|
|
|
// Print some info
|
|
|
|
printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
|
|
|
|
printf(" %s\n", GetString(STR_ABOUT_TEXT2));
|
|
|
|
|
|
|
|
#if !EMULATED_PPC
|
2005-02-27 21:52:06 +00:00
|
|
|
#ifdef SYSTEM_CLOBBERS_R2
|
2002-02-04 16:58:13 +00:00
|
|
|
// Get TOC pointer
|
2005-02-27 21:52:06 +00:00
|
|
|
TOC = get_r2();
|
|
|
|
#endif
|
|
|
|
#ifdef SYSTEM_CLOBBERS_R13
|
|
|
|
// Get r13 register
|
|
|
|
R13 = get_r13();
|
|
|
|
#endif
|
2002-02-04 16:58:13 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Parse command line arguments
|
|
|
|
for (int i=1; i<argc; i++) {
|
|
|
|
if (strcmp(argv[i], "--help") == 0) {
|
|
|
|
usage(argv[0]);
|
2004-06-24 15:37:26 +00:00
|
|
|
#ifndef USE_SDL_VIDEO
|
2002-02-04 16:58:13 +00:00
|
|
|
} else if (strcmp(argv[i], "--display") == 0) {
|
|
|
|
i++;
|
|
|
|
if (i < argc)
|
|
|
|
x_display_name = strdup(argv[i]);
|
2004-06-24 15:37:26 +00:00
|
|
|
#endif
|
2006-05-01 22:33:34 +00:00
|
|
|
} else if (strcmp(argv[i], "--gui-connection") == 0) {
|
|
|
|
argv[i++] = NULL;
|
|
|
|
if (i < argc) {
|
|
|
|
gui_connection_path = argv[i];
|
|
|
|
argv[i] = NULL;
|
|
|
|
}
|
2009-07-23 19:12:51 +00:00
|
|
|
} else if (valid_vmdir(argv[i])) {
|
|
|
|
vmdir = argv[i];
|
|
|
|
argv[i] = NULL;
|
|
|
|
printf("Using %s as vmdir.\n", vmdir);
|
|
|
|
if (chdir(vmdir)) {
|
|
|
|
printf("Failed to chdir to %s. Good bye.", vmdir);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
2006-05-01 22:33:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove processed arguments
|
|
|
|
for (int i=1; i<argc; i++) {
|
|
|
|
int k;
|
|
|
|
for (k=i; k<argc; k++)
|
|
|
|
if (argv[k] != NULL)
|
|
|
|
break;
|
|
|
|
if (k > i) {
|
|
|
|
k -= i;
|
|
|
|
for (int j=i+k; j<argc; j++)
|
|
|
|
argv[j-k] = argv[j];
|
|
|
|
argc -= k;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Connect to the external GUI
|
|
|
|
if (gui_connection_path) {
|
|
|
|
if ((gui_connection = rpc_init_client(gui_connection_path)) == NULL) {
|
|
|
|
fprintf(stderr, "Failed to initialize RPC client connection to the GUI\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef ENABLE_GTK
|
|
|
|
if (!gui_connection) {
|
|
|
|
// Init GTK
|
|
|
|
gtk_set_locale();
|
|
|
|
gtk_init(&argc, &argv);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Read preferences
|
2009-07-23 19:12:51 +00:00
|
|
|
PrefsInit(vmdir, argc, argv);
|
2006-05-01 22:33:34 +00:00
|
|
|
|
|
|
|
// Any command line arguments left?
|
|
|
|
for (int i=1; i<argc; i++) {
|
|
|
|
if (argv[i][0] == '-') {
|
2002-02-04 16:58:13 +00:00
|
|
|
fprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
|
|
|
|
usage(argv[0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-06-24 15:37:26 +00:00
|
|
|
#ifdef USE_SDL
|
|
|
|
// Initialize SDL system
|
2011-12-28 23:33:04 +00:00
|
|
|
if (!init_sdl())
|
2004-06-24 15:37:26 +00:00
|
|
|
goto quit;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef USE_SDL_VIDEO
|
2002-02-04 16:58:13 +00:00
|
|
|
// Open display
|
|
|
|
x_display = XOpenDisplay(x_display_name);
|
|
|
|
if (x_display == NULL) {
|
|
|
|
char str[256];
|
|
|
|
sprintf(str, GetString(STR_NO_XSERVER_ERR), XDisplayName(x_display_name));
|
|
|
|
ErrorAlert(str);
|
|
|
|
goto quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(ENABLE_XF86_DGA) && !defined(ENABLE_MON)
|
|
|
|
// Fork out, so we can return from fullscreen mode when things get ugly
|
|
|
|
XF86DGAForkApp(DefaultScreen(x_display));
|
|
|
|
#endif
|
2004-06-24 15:37:26 +00:00
|
|
|
#endif
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
#ifdef ENABLE_MON
|
|
|
|
// Initialize mon
|
|
|
|
mon_init();
|
|
|
|
#endif
|
|
|
|
|
2011-12-28 23:30:25 +00:00
|
|
|
// Install signal handlers
|
|
|
|
if (!install_signal_handlers())
|
2004-06-26 15:26:18 +00:00
|
|
|
goto quit;
|
|
|
|
|
|
|
|
// Initialize VM system
|
|
|
|
vm_init();
|
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
// Get system info
|
2011-12-28 23:17:29 +00:00
|
|
|
get_system_info();
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
// Init system routines
|
|
|
|
SysInit();
|
|
|
|
|
|
|
|
// Show preferences editor
|
|
|
|
if (!PrefsFindBool("nogui"))
|
|
|
|
if (!PrefsEditor())
|
|
|
|
goto quit;
|
|
|
|
|
|
|
|
#if !EMULATED_PPC
|
|
|
|
// Check some things
|
|
|
|
paranoia_check();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Open /dev/zero
|
|
|
|
zero_fd = open("/dev/zero", O_RDWR);
|
|
|
|
if (zero_fd < 0) {
|
|
|
|
sprintf(str, GetString(STR_NO_DEV_ZERO_ERR), strerror(errno));
|
|
|
|
ErrorAlert(str);
|
|
|
|
goto quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create areas for Kernel Data
|
2004-11-22 21:33:32 +00:00
|
|
|
if (!kernel_data_init())
|
2002-02-04 16:58:13 +00:00
|
|
|
goto quit;
|
2004-11-22 21:33:32 +00:00
|
|
|
kernel_data = (KernelData *)Mac2HostAddr(KERNEL_DATA_BASE);
|
2002-02-04 16:58:13 +00:00
|
|
|
emulator_data = &kernel_data->ed;
|
2003-12-04 17:26:38 +00:00
|
|
|
KernelDataAddr = KERNEL_DATA_BASE;
|
2004-11-13 14:09:16 +00:00
|
|
|
D(bug("Kernel Data at %p (%08x)\n", kernel_data, KERNEL_DATA_BASE));
|
|
|
|
D(bug("Emulator Data at %p (%08x)\n", emulator_data, KERNEL_DATA_BASE + offsetof(KernelData, ed)));
|
2002-02-04 16:58:13 +00:00
|
|
|
|
2004-05-31 09:04:44 +00:00
|
|
|
// Create area for DR Cache
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
if (vm_mac_acquire_fixed(DR_EMULATOR_BASE, DR_EMULATOR_SIZE) < 0) {
|
2004-05-31 09:04:44 +00:00
|
|
|
sprintf(str, GetString(STR_DR_EMULATOR_MMAP_ERR), strerror(errno));
|
|
|
|
ErrorAlert(str);
|
|
|
|
goto quit;
|
|
|
|
}
|
|
|
|
dr_emulator_area_mapped = true;
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
if (vm_mac_acquire_fixed(DR_CACHE_BASE, DR_CACHE_SIZE) < 0) {
|
2004-05-31 09:04:44 +00:00
|
|
|
sprintf(str, GetString(STR_DR_CACHE_MMAP_ERR), strerror(errno));
|
|
|
|
ErrorAlert(str);
|
|
|
|
goto quit;
|
|
|
|
}
|
|
|
|
dr_cache_area_mapped = true;
|
2004-05-31 10:55:42 +00:00
|
|
|
#if !EMULATED_PPC
|
|
|
|
if (vm_protect((char *)DR_CACHE_BASE, DR_CACHE_SIZE, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) {
|
|
|
|
sprintf(str, GetString(STR_DR_CACHE_MMAP_ERR), strerror(errno));
|
|
|
|
ErrorAlert(str);
|
|
|
|
goto quit;
|
|
|
|
}
|
|
|
|
#endif
|
2004-05-31 09:04:44 +00:00
|
|
|
DRCacheAddr = DR_CACHE_BASE;
|
|
|
|
D(bug("DR Cache at %p\n", DRCacheAddr));
|
|
|
|
|
2003-09-29 15:46:09 +00:00
|
|
|
// Create area for SheepShaver data
|
2003-12-04 17:26:38 +00:00
|
|
|
if (!SheepMem::Init()) {
|
2003-09-29 15:46:09 +00:00
|
|
|
sprintf(str, GetString(STR_SHEEP_MEM_MMAP_ERR), strerror(errno));
|
|
|
|
ErrorAlert(str);
|
|
|
|
goto quit;
|
|
|
|
}
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
// Create area for Mac RAM
|
|
|
|
RAMSize = PrefsFindInt32("ramsize");
|
|
|
|
if (RAMSize < 8*1024*1024) {
|
|
|
|
WarningAlert(GetString(STR_SMALL_RAM_WARN));
|
|
|
|
RAMSize = 8*1024*1024;
|
|
|
|
}
|
2006-05-06 10:42:51 +00:00
|
|
|
memory_mapped_from_zero = false;
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
ram_rom_areas_contiguous = false;
|
2006-05-06 10:42:51 +00:00
|
|
|
#if REAL_ADDRESSING && HAVE_LINKER_SCRIPT
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
if (vm_mac_acquire_fixed(0, RAMSize) == 0) {
|
2006-05-06 10:42:51 +00:00
|
|
|
D(bug("Could allocate RAM from 0x0000\n"));
|
|
|
|
RAMBase = 0;
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
RAMBaseHost = Mac2HostAddr(RAMBase);
|
2006-05-06 10:42:51 +00:00
|
|
|
memory_mapped_from_zero = true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (!memory_mapped_from_zero) {
|
|
|
|
#ifndef PAGEZERO_HACK
|
|
|
|
// Create Low Memory area (0x0000..0x3000)
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
if (vm_mac_acquire_fixed(0, 0x3000) < 0) {
|
2006-05-06 10:42:51 +00:00
|
|
|
sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
|
|
|
|
ErrorAlert(str);
|
|
|
|
goto quit;
|
|
|
|
}
|
|
|
|
lm_area_mapped = true;
|
|
|
|
#endif
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
#if REAL_ADDRESSING
|
|
|
|
// Allocate RAM at any address. Since ROM must be higher than RAM, allocate the RAM
|
|
|
|
// and ROM areas contiguously, plus a little extra to allow for ROM address alignment.
|
|
|
|
RAMBaseHost = vm_mac_acquire(RAMSize + ROM_AREA_SIZE + ROM_ALIGNMENT);
|
|
|
|
if (RAMBaseHost == VM_MAP_FAILED) {
|
|
|
|
sprintf(str, GetString(STR_RAM_ROM_MMAP_ERR), strerror(errno));
|
|
|
|
ErrorAlert(str);
|
|
|
|
goto quit;
|
|
|
|
}
|
|
|
|
RAMBase = Host2MacAddr(RAMBaseHost);
|
|
|
|
ROMBase = (RAMBase + RAMSize + ROM_ALIGNMENT -1) & -ROM_ALIGNMENT;
|
|
|
|
ROMBaseHost = Mac2HostAddr(ROMBase);
|
|
|
|
ram_rom_areas_contiguous = true;
|
|
|
|
#else
|
|
|
|
if (vm_mac_acquire_fixed(RAM_BASE, RAMSize) < 0) {
|
2006-05-06 10:42:51 +00:00
|
|
|
sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
|
|
|
|
ErrorAlert(str);
|
|
|
|
goto quit;
|
|
|
|
}
|
|
|
|
RAMBase = RAM_BASE;
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
RAMBaseHost = Mac2HostAddr(RAMBase);
|
|
|
|
#endif
|
2002-02-04 16:58:13 +00:00
|
|
|
}
|
2003-05-13 16:59:57 +00:00
|
|
|
#if !EMULATED_PPC
|
2004-11-13 14:09:16 +00:00
|
|
|
if (vm_protect(RAMBaseHost, RAMSize, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) {
|
2003-05-13 16:59:57 +00:00
|
|
|
sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
|
|
|
|
ErrorAlert(str);
|
|
|
|
goto quit;
|
|
|
|
}
|
|
|
|
#endif
|
2002-02-04 16:58:13 +00:00
|
|
|
ram_area_mapped = true;
|
2004-11-13 14:09:16 +00:00
|
|
|
D(bug("RAM area at %p (%08x)\n", RAMBaseHost, RAMBase));
|
2002-02-04 16:58:13 +00:00
|
|
|
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
if (RAMBase > KernelDataAddr) {
|
|
|
|
ErrorAlert(GetString(STR_RAM_AREA_TOO_HIGH_ERR));
|
|
|
|
goto quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create area for Mac ROM
|
|
|
|
if (!ram_rom_areas_contiguous) {
|
|
|
|
if (vm_mac_acquire_fixed(ROM_BASE, ROM_AREA_SIZE) < 0) {
|
|
|
|
sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno));
|
|
|
|
ErrorAlert(str);
|
|
|
|
goto quit;
|
|
|
|
}
|
|
|
|
ROMBase = ROM_BASE;
|
|
|
|
ROMBaseHost = Mac2HostAddr(ROMBase);
|
|
|
|
}
|
|
|
|
#if !EMULATED_PPC
|
|
|
|
if (vm_protect(ROMBaseHost, ROM_AREA_SIZE, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) {
|
|
|
|
sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno));
|
|
|
|
ErrorAlert(str);
|
|
|
|
goto quit;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
rom_area_mapped = true;
|
|
|
|
D(bug("ROM area at %p (%08x)\n", ROMBaseHost, ROMBase));
|
|
|
|
|
|
|
|
if (RAMBase > ROMBase) {
|
2002-02-04 16:58:13 +00:00
|
|
|
ErrorAlert(GetString(STR_RAM_HIGHER_THAN_ROM_ERR));
|
|
|
|
goto quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load Mac ROM
|
2011-12-28 23:24:30 +00:00
|
|
|
if (!load_mac_rom())
|
|
|
|
goto quit;
|
2002-02-04 16:58:13 +00:00
|
|
|
|
2005-01-30 21:19:07 +00:00
|
|
|
// Initialize everything
|
2009-07-23 19:12:51 +00:00
|
|
|
if (!InitAll(vmdir))
|
2003-12-04 17:26:38 +00:00
|
|
|
goto quit;
|
2005-01-30 21:19:07 +00:00
|
|
|
D(bug("Initialization complete\n"));
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
// Clear caches (as we loaded and patched code) and write protect ROM
|
|
|
|
#if !EMULATED_PPC
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
flush_icache_range(ROMBase, ROMBase + ROM_AREA_SIZE);
|
2002-02-04 16:58:13 +00:00
|
|
|
#endif
|
2004-11-13 14:09:16 +00:00
|
|
|
vm_protect(ROMBaseHost, ROM_AREA_SIZE, VM_PAGE_READ | VM_PAGE_EXECUTE);
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
// Start 60Hz thread
|
2004-06-22 12:20:17 +00:00
|
|
|
tick_thread_cancel = false;
|
2002-02-04 16:58:13 +00:00
|
|
|
tick_thread_active = (pthread_create(&tick_thread, NULL, tick_func, NULL) == 0);
|
|
|
|
D(bug("Tick thread installed (%ld)\n", tick_thread));
|
|
|
|
|
|
|
|
// Start NVRAM watchdog thread
|
|
|
|
memcpy(last_xpram, XPRAM, XPRAM_SIZE);
|
2004-06-22 12:20:17 +00:00
|
|
|
nvram_thread_cancel = false;
|
2002-02-04 16:58:13 +00:00
|
|
|
nvram_thread_active = (pthread_create(&nvram_thread, NULL, nvram_func, NULL) == 0);
|
|
|
|
D(bug("NVRAM thread installed (%ld)\n", nvram_thread));
|
|
|
|
|
|
|
|
#if !EMULATED_PPC
|
|
|
|
// Install SIGILL handler
|
|
|
|
sigemptyset(&sigill_action.sa_mask); // Block interrupts during ILL handling
|
|
|
|
sigaddset(&sigill_action.sa_mask, SIGUSR2);
|
2004-01-18 22:14:31 +00:00
|
|
|
sigill_action.sa_sigaction = sigill_handler;
|
|
|
|
sigill_action.sa_flags = SA_ONSTACK | SA_SIGINFO;
|
|
|
|
#ifdef HAVE_SIGNAL_SA_RESTORER
|
2002-02-04 16:58:13 +00:00
|
|
|
sigill_action.sa_restorer = NULL;
|
2004-01-18 22:14:31 +00:00
|
|
|
#endif
|
2002-02-04 16:58:13 +00:00
|
|
|
if (sigaction(SIGILL, &sigill_action, NULL) < 0) {
|
2006-05-01 22:33:34 +00:00
|
|
|
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGILL", strerror(errno));
|
2002-02-04 16:58:13 +00:00
|
|
|
ErrorAlert(str);
|
|
|
|
goto quit;
|
|
|
|
}
|
2003-09-07 14:33:54 +00:00
|
|
|
#endif
|
2002-02-04 16:58:13 +00:00
|
|
|
|
2004-01-18 22:14:31 +00:00
|
|
|
#if !EMULATED_PPC
|
2002-02-04 16:58:13 +00:00
|
|
|
// Install interrupt signal handler
|
|
|
|
sigemptyset(&sigusr2_action.sa_mask);
|
2005-06-28 16:47:32 +00:00
|
|
|
sigusr2_action.sa_sigaction = sigusr2_handler_init;
|
2004-01-18 22:14:31 +00:00
|
|
|
sigusr2_action.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO;
|
|
|
|
#ifdef HAVE_SIGNAL_SA_RESTORER
|
2002-02-04 16:58:13 +00:00
|
|
|
sigusr2_action.sa_restorer = NULL;
|
2004-01-18 22:14:31 +00:00
|
|
|
#endif
|
2002-02-04 16:58:13 +00:00
|
|
|
if (sigaction(SIGUSR2, &sigusr2_action, NULL) < 0) {
|
2006-05-01 22:33:34 +00:00
|
|
|
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGUSR2", strerror(errno));
|
2002-02-04 16:58:13 +00:00
|
|
|
ErrorAlert(str);
|
|
|
|
goto quit;
|
|
|
|
}
|
2004-01-18 22:14:31 +00:00
|
|
|
#endif
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
// Get my thread ID and execute MacOS thread function
|
|
|
|
emul_thread = pthread_self();
|
|
|
|
D(bug("MacOS thread is %ld\n", emul_thread));
|
|
|
|
emul_func(NULL);
|
|
|
|
|
|
|
|
quit:
|
|
|
|
Quit();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Cleanup and quit
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void Quit(void)
|
|
|
|
{
|
2003-11-03 21:28:32 +00:00
|
|
|
#if EMULATED_PPC
|
|
|
|
// Exit PowerPC emulation
|
|
|
|
exit_emul_ppc();
|
|
|
|
#endif
|
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
// Stop 60Hz thread
|
|
|
|
if (tick_thread_active) {
|
2004-06-22 12:20:17 +00:00
|
|
|
tick_thread_cancel = true;
|
2002-02-04 16:58:13 +00:00
|
|
|
pthread_cancel(tick_thread);
|
|
|
|
pthread_join(tick_thread, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stop NVRAM watchdog thread
|
|
|
|
if (nvram_thread_active) {
|
2004-06-22 12:20:17 +00:00
|
|
|
nvram_thread_cancel = true;
|
2002-02-04 16:58:13 +00:00
|
|
|
pthread_cancel(nvram_thread);
|
|
|
|
pthread_join(nvram_thread, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if !EMULATED_PPC
|
2004-01-04 18:35:21 +00:00
|
|
|
// Uninstall SIGSEGV and SIGBUS handlers
|
2002-02-04 16:58:13 +00:00
|
|
|
sigemptyset(&sigsegv_action.sa_mask);
|
|
|
|
sigsegv_action.sa_handler = SIG_DFL;
|
|
|
|
sigsegv_action.sa_flags = 0;
|
|
|
|
sigaction(SIGSEGV, &sigsegv_action, NULL);
|
2004-01-04 18:35:21 +00:00
|
|
|
sigaction(SIGBUS, &sigsegv_action, NULL);
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
// Uninstall SIGILL handler
|
|
|
|
sigemptyset(&sigill_action.sa_mask);
|
|
|
|
sigill_action.sa_handler = SIG_DFL;
|
|
|
|
sigill_action.sa_flags = 0;
|
|
|
|
sigaction(SIGILL, &sigill_action, NULL);
|
2004-04-14 20:25:26 +00:00
|
|
|
|
|
|
|
// Delete stacks for signal handlers
|
2005-06-28 16:47:32 +00:00
|
|
|
if (sig_stack.ss_sp)
|
|
|
|
free(sig_stack.ss_sp);
|
|
|
|
if (extra_stack.ss_sp)
|
|
|
|
free(extra_stack.ss_sp);
|
2002-02-04 16:58:13 +00:00
|
|
|
#endif
|
|
|
|
|
2005-01-30 21:19:07 +00:00
|
|
|
// Deinitialize everything
|
|
|
|
ExitAll();
|
2004-01-07 18:24:45 +00:00
|
|
|
|
2003-12-04 17:26:38 +00:00
|
|
|
// Delete SheepShaver globals
|
|
|
|
SheepMem::Exit();
|
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
// Delete RAM area
|
|
|
|
if (ram_area_mapped)
|
2006-05-06 10:42:51 +00:00
|
|
|
vm_mac_release(RAMBase, RAMSize);
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
// Delete ROM area
|
|
|
|
if (rom_area_mapped)
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
vm_mac_release(ROMBase, ROM_AREA_SIZE);
|
2002-02-04 16:58:13 +00:00
|
|
|
|
2004-05-31 09:04:44 +00:00
|
|
|
// Delete DR cache areas
|
|
|
|
if (dr_emulator_area_mapped)
|
2004-11-22 21:33:32 +00:00
|
|
|
vm_mac_release(DR_EMULATOR_BASE, DR_EMULATOR_SIZE);
|
2004-05-31 09:04:44 +00:00
|
|
|
if (dr_cache_area_mapped)
|
2004-11-22 21:33:32 +00:00
|
|
|
vm_mac_release(DR_CACHE_BASE, DR_CACHE_SIZE);
|
2004-05-31 09:04:44 +00:00
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
// Delete Kernel Data area
|
2004-11-22 21:33:32 +00:00
|
|
|
kernel_data_exit();
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
// Delete Low Memory area
|
|
|
|
if (lm_area_mapped)
|
2004-11-22 21:33:32 +00:00
|
|
|
vm_mac_release(0, 0x3000);
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
// Close /dev/zero
|
|
|
|
if (zero_fd > 0)
|
|
|
|
close(zero_fd);
|
|
|
|
|
|
|
|
// Exit system routines
|
|
|
|
SysExit();
|
|
|
|
|
|
|
|
// Exit preferences
|
|
|
|
PrefsExit();
|
|
|
|
|
|
|
|
#ifdef ENABLE_MON
|
|
|
|
// Exit mon
|
|
|
|
mon_exit();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Close X11 server connection
|
2004-06-24 15:37:26 +00:00
|
|
|
#ifndef USE_SDL_VIDEO
|
2002-02-04 16:58:13 +00:00
|
|
|
if (x_display)
|
|
|
|
XCloseDisplay(x_display);
|
2004-06-24 15:37:26 +00:00
|
|
|
#endif
|
2002-02-04 16:58:13 +00:00
|
|
|
|
2006-05-01 22:33:34 +00:00
|
|
|
// Notify GUI we are about to leave
|
|
|
|
if (gui_connection) {
|
|
|
|
if (rpc_method_invoke(gui_connection, RPC_METHOD_EXIT, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
|
|
|
|
rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID);
|
|
|
|
}
|
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-22 21:33:32 +00:00
|
|
|
/*
|
|
|
|
* Initialize Kernel Data segments
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool kernel_data_init(void)
|
|
|
|
{
|
2004-11-22 23:17:32 +00:00
|
|
|
char str[256];
|
2005-12-11 23:18:47 +00:00
|
|
|
uint32 kernel_area_size = (KERNEL_AREA_SIZE + SHMLBA - 1) & -SHMLBA;
|
|
|
|
|
|
|
|
kernel_area = shmget(IPC_PRIVATE, kernel_area_size, 0600);
|
2004-11-22 21:33:32 +00:00
|
|
|
if (kernel_area == -1) {
|
|
|
|
sprintf(str, GetString(STR_KD_SHMGET_ERR), strerror(errno));
|
|
|
|
ErrorAlert(str);
|
|
|
|
return false;
|
|
|
|
}
|
2005-12-11 23:18:47 +00:00
|
|
|
void *kernel_addr = Mac2HostAddr(KERNEL_DATA_BASE & -SHMLBA);
|
|
|
|
if (shmat(kernel_area, kernel_addr, 0) != kernel_addr) {
|
2004-11-22 21:33:32 +00:00
|
|
|
sprintf(str, GetString(STR_KD_SHMAT_ERR), strerror(errno));
|
|
|
|
ErrorAlert(str);
|
|
|
|
return false;
|
|
|
|
}
|
2005-12-11 23:18:47 +00:00
|
|
|
kernel_addr = Mac2HostAddr(KERNEL_DATA2_BASE & -SHMLBA);
|
|
|
|
if (shmat(kernel_area, kernel_addr, 0) != kernel_addr) {
|
2004-11-22 21:33:32 +00:00
|
|
|
sprintf(str, GetString(STR_KD2_SHMAT_ERR), strerror(errno));
|
|
|
|
ErrorAlert(str);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Deallocate Kernel Data segments
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void kernel_data_exit(void)
|
|
|
|
{
|
|
|
|
if (kernel_area >= 0) {
|
2005-12-11 23:18:47 +00:00
|
|
|
shmdt(Mac2HostAddr(KERNEL_DATA_BASE & -SHMLBA));
|
|
|
|
shmdt(Mac2HostAddr(KERNEL_DATA2_BASE & -SHMLBA));
|
2004-11-22 21:33:32 +00:00
|
|
|
shmctl(kernel_area, IPC_RMID, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
/*
|
|
|
|
* Jump into Mac ROM, start 680x0 emulator
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if EMULATED_PPC
|
|
|
|
void jump_to_rom(uint32 entry)
|
|
|
|
{
|
|
|
|
init_emul_ppc();
|
|
|
|
emul_ppc(entry);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Emulator thread function
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void *emul_func(void *arg)
|
|
|
|
{
|
|
|
|
// We're now ready to receive signals
|
|
|
|
ready_for_signals = true;
|
|
|
|
|
|
|
|
// Decrease priority, so more time-critical things like audio will work better
|
|
|
|
nice(1);
|
|
|
|
|
|
|
|
// Jump to ROM boot routine
|
|
|
|
D(bug("Jumping to ROM\n"));
|
|
|
|
#if EMULATED_PPC
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
jump_to_rom(ROMBase + 0x310000);
|
2002-02-04 16:58:13 +00:00
|
|
|
#else
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
jump_to_rom(ROMBase + 0x310000, (uint32)emulator_data);
|
2002-02-04 16:58:13 +00:00
|
|
|
#endif
|
|
|
|
D(bug("Returned from ROM\n"));
|
|
|
|
|
|
|
|
// We're no longer ready to receive signals
|
|
|
|
ready_for_signals = false;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if !EMULATED_PPC
|
|
|
|
/*
|
|
|
|
* Execute 68k subroutine (must be ended with RTS)
|
|
|
|
* This must only be called by the emul_thread when in EMUL_OP mode
|
|
|
|
* r->a[7] is unused, the routine runs on the caller's stack
|
|
|
|
*/
|
|
|
|
|
|
|
|
void Execute68k(uint32 pc, M68kRegisters *r)
|
|
|
|
{
|
|
|
|
#if SAFE_EXEC_68K
|
|
|
|
if (ReadMacInt32(XLM_RUN_MODE) != MODE_EMUL_OP)
|
|
|
|
printf("FATAL: Execute68k() not called from EMUL_OP mode\n");
|
|
|
|
if (!pthread_equal(pthread_self(), emul_thread))
|
|
|
|
printf("FATAL: Execute68k() not called from emul_thread\n");
|
|
|
|
#endif
|
|
|
|
execute_68k(pc, r);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Execute 68k A-Trap from EMUL_OP routine
|
|
|
|
* r->a[7] is unused, the routine runs on the caller's stack
|
|
|
|
*/
|
|
|
|
|
|
|
|
void Execute68kTrap(uint16 trap, M68kRegisters *r)
|
|
|
|
{
|
|
|
|
uint16 proc[2] = {trap, M68K_RTS};
|
|
|
|
Execute68k((uint32)proc, r);
|
|
|
|
}
|
2003-09-28 21:20:38 +00:00
|
|
|
#endif
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Quit emulator (cause return from jump_to_rom)
|
|
|
|
*/
|
|
|
|
|
|
|
|
void QuitEmulator(void)
|
|
|
|
{
|
|
|
|
#if EMULATED_PPC
|
|
|
|
Quit();
|
|
|
|
#else
|
|
|
|
quit_emulator();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Dump 68k registers
|
|
|
|
*/
|
|
|
|
|
|
|
|
void Dump68kRegs(M68kRegisters *r)
|
|
|
|
{
|
|
|
|
// Display 68k registers
|
|
|
|
for (int i=0; i<8; i++) {
|
|
|
|
printf("d%d: %08x", i, r->d[i]);
|
|
|
|
if (i == 3 || i == 7)
|
|
|
|
printf("\n");
|
|
|
|
else
|
|
|
|
printf(", ");
|
|
|
|
}
|
|
|
|
for (int i=0; i<8; i++) {
|
|
|
|
printf("a%d: %08x", i, r->a[i]);
|
|
|
|
if (i == 3 || i == 7)
|
|
|
|
printf("\n");
|
|
|
|
else
|
|
|
|
printf(", ");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make code executable
|
|
|
|
*/
|
|
|
|
|
2004-11-13 14:09:16 +00:00
|
|
|
void MakeExecutable(int dummy, uint32 start, uint32 length)
|
2002-02-04 16:58:13 +00:00
|
|
|
{
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
if ((start >= ROMBase) && (start < (ROMBase + ROM_SIZE)))
|
2002-02-04 16:58:13 +00:00
|
|
|
return;
|
2003-10-12 05:44:17 +00:00
|
|
|
#if EMULATED_PPC
|
2004-11-13 14:09:16 +00:00
|
|
|
FlushCodeCache(start, start + length);
|
2003-10-12 05:44:17 +00:00
|
|
|
#else
|
2005-01-30 21:25:24 +00:00
|
|
|
flush_icache_range(start, start + length);
|
2002-02-04 16:58:13 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NVRAM watchdog thread (saves NVRAM every minute)
|
|
|
|
*/
|
|
|
|
|
2004-06-22 12:20:17 +00:00
|
|
|
static void nvram_watchdog(void)
|
|
|
|
{
|
|
|
|
if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) {
|
|
|
|
memcpy(last_xpram, XPRAM, XPRAM_SIZE);
|
|
|
|
SaveXPRAM();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
static void *nvram_func(void *arg)
|
|
|
|
{
|
2004-06-22 12:20:17 +00:00
|
|
|
while (!nvram_thread_cancel) {
|
|
|
|
for (int i=0; i<60 && !nvram_thread_cancel; i++)
|
|
|
|
Delay_usec(999999); // Only wait 1 second so we quit promptly when nvram_thread_cancel becomes true
|
|
|
|
nvram_watchdog();
|
2002-02-04 16:58:13 +00:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 60Hz thread (really 60.15Hz)
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void *tick_func(void *arg)
|
|
|
|
{
|
|
|
|
int tick_counter = 0;
|
2004-06-22 12:20:17 +00:00
|
|
|
uint64 start = GetTicks_usec();
|
|
|
|
int64 ticks = 0;
|
|
|
|
uint64 next = GetTicks_usec();
|
2002-02-04 16:58:13 +00:00
|
|
|
|
2004-06-22 12:20:17 +00:00
|
|
|
while (!tick_thread_cancel) {
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
// Wait
|
2004-06-22 12:20:17 +00:00
|
|
|
next += 16625;
|
|
|
|
int64 delay = next - GetTicks_usec();
|
|
|
|
if (delay > 0)
|
|
|
|
Delay_usec(delay);
|
|
|
|
else if (delay < -16625)
|
|
|
|
next = GetTicks_usec();
|
|
|
|
ticks++;
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
#if !EMULATED_PPC
|
|
|
|
// Did we crash?
|
|
|
|
if (emul_thread_fatal) {
|
|
|
|
|
|
|
|
// Yes, dump registers
|
2004-01-18 22:14:31 +00:00
|
|
|
sigregs *r = &sigsegv_regs;
|
2002-02-04 16:58:13 +00:00
|
|
|
char str[256];
|
2004-01-04 18:35:21 +00:00
|
|
|
if (crash_reason == NULL)
|
|
|
|
crash_reason = "SIGSEGV";
|
|
|
|
sprintf(str, "%s\n"
|
2002-02-04 16:58:13 +00:00
|
|
|
" pc %08lx lr %08lx ctr %08lx msr %08lx\n"
|
|
|
|
" xer %08lx cr %08lx \n"
|
|
|
|
" r0 %08lx r1 %08lx r2 %08lx r3 %08lx\n"
|
|
|
|
" r4 %08lx r5 %08lx r6 %08lx r7 %08lx\n"
|
|
|
|
" r8 %08lx r9 %08lx r10 %08lx r11 %08lx\n"
|
|
|
|
" r12 %08lx r13 %08lx r14 %08lx r15 %08lx\n"
|
|
|
|
" r16 %08lx r17 %08lx r18 %08lx r19 %08lx\n"
|
|
|
|
" r20 %08lx r21 %08lx r22 %08lx r23 %08lx\n"
|
|
|
|
" r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n"
|
|
|
|
" r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n",
|
2004-01-04 18:35:21 +00:00
|
|
|
crash_reason,
|
2002-02-04 16:58:13 +00:00
|
|
|
r->nip, r->link, r->ctr, r->msr,
|
|
|
|
r->xer, r->ccr,
|
|
|
|
r->gpr[0], r->gpr[1], r->gpr[2], r->gpr[3],
|
|
|
|
r->gpr[4], r->gpr[5], r->gpr[6], r->gpr[7],
|
|
|
|
r->gpr[8], r->gpr[9], r->gpr[10], r->gpr[11],
|
|
|
|
r->gpr[12], r->gpr[13], r->gpr[14], r->gpr[15],
|
|
|
|
r->gpr[16], r->gpr[17], r->gpr[18], r->gpr[19],
|
|
|
|
r->gpr[20], r->gpr[21], r->gpr[22], r->gpr[23],
|
|
|
|
r->gpr[24], r->gpr[25], r->gpr[26], r->gpr[27],
|
|
|
|
r->gpr[28], r->gpr[29], r->gpr[30], r->gpr[31]);
|
|
|
|
printf(str);
|
|
|
|
VideoQuitFullScreen();
|
|
|
|
|
|
|
|
#ifdef ENABLE_MON
|
|
|
|
// Start up mon in real-mode
|
|
|
|
printf("Welcome to the sheep factory.\n");
|
|
|
|
char *arg[4] = {"mon", "-m", "-r", NULL};
|
|
|
|
mon(3, arg);
|
|
|
|
#endif
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Pseudo Mac 1Hz interrupt, update local time
|
|
|
|
if (++tick_counter > 60) {
|
|
|
|
tick_counter = 0;
|
|
|
|
WriteMacInt32(0x20c, TimerDateTime());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Trigger 60Hz interrupt
|
|
|
|
if (ReadMacInt32(XLM_IRQ_NEST) == 0) {
|
|
|
|
SetInterruptFlag(INTFLAG_VIA);
|
|
|
|
TriggerInterrupt();
|
|
|
|
}
|
|
|
|
}
|
2004-06-22 12:20:17 +00:00
|
|
|
|
|
|
|
uint64 end = GetTicks_usec();
|
2005-06-28 16:50:30 +00:00
|
|
|
D(bug("%lld ticks in %lld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
|
2002-02-04 16:58:13 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-02-21 15:12:12 +00:00
|
|
|
/*
|
|
|
|
* Pthread configuration
|
|
|
|
*/
|
|
|
|
|
|
|
|
void Set_pthread_attr(pthread_attr_t *attr, int priority)
|
|
|
|
{
|
2003-11-10 16:05:52 +00:00
|
|
|
#ifdef HAVE_PTHREADS
|
|
|
|
pthread_attr_init(attr);
|
|
|
|
#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
|
|
|
|
// Some of these only work for superuser
|
|
|
|
if (geteuid() == 0) {
|
|
|
|
pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
|
|
|
|
pthread_attr_setschedpolicy(attr, SCHED_FIFO);
|
|
|
|
struct sched_param fifo_param;
|
|
|
|
fifo_param.sched_priority = ((sched_get_priority_min(SCHED_FIFO) +
|
|
|
|
sched_get_priority_max(SCHED_FIFO)) / 2 +
|
|
|
|
priority);
|
|
|
|
pthread_attr_setschedparam(attr, &fifo_param);
|
|
|
|
}
|
|
|
|
if (pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM) != 0) {
|
|
|
|
#ifdef PTHREAD_SCOPE_BOUND_NP
|
|
|
|
// If system scope is not available (eg. we're not running
|
|
|
|
// with CAP_SCHED_MGT capability on an SGI box), try bound
|
|
|
|
// scope. It exposes pthread scheduling to the kernel,
|
|
|
|
// without setting realtime priority.
|
|
|
|
pthread_attr_setscope(attr, PTHREAD_SCOPE_BOUND_NP);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
2002-02-21 15:12:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
/*
|
|
|
|
* Mutexes
|
|
|
|
*/
|
|
|
|
|
2003-09-28 21:20:38 +00:00
|
|
|
#ifdef HAVE_PTHREADS
|
|
|
|
|
|
|
|
struct B2_mutex {
|
|
|
|
B2_mutex() {
|
|
|
|
pthread_mutexattr_t attr;
|
|
|
|
pthread_mutexattr_init(&attr);
|
|
|
|
// Initialize the mutex for priority inheritance --
|
|
|
|
// required for accurate timing.
|
2004-11-22 21:33:32 +00:00
|
|
|
#if defined(HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL) && !defined(__CYGWIN__)
|
2003-09-28 21:20:38 +00:00
|
|
|
pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
|
|
|
|
#endif
|
|
|
|
#if defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE) && defined(PTHREAD_MUTEX_NORMAL)
|
|
|
|
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED
|
|
|
|
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
|
|
|
|
#endif
|
|
|
|
pthread_mutex_init(&m, &attr);
|
|
|
|
pthread_mutexattr_destroy(&attr);
|
|
|
|
}
|
|
|
|
~B2_mutex() {
|
|
|
|
pthread_mutex_trylock(&m); // Make sure it's locked before
|
|
|
|
pthread_mutex_unlock(&m); // unlocking it.
|
|
|
|
pthread_mutex_destroy(&m);
|
|
|
|
}
|
|
|
|
pthread_mutex_t m;
|
|
|
|
};
|
|
|
|
|
|
|
|
B2_mutex *B2_create_mutex(void)
|
|
|
|
{
|
|
|
|
return new B2_mutex;
|
|
|
|
}
|
|
|
|
|
|
|
|
void B2_lock_mutex(B2_mutex *mutex)
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&mutex->m);
|
|
|
|
}
|
|
|
|
|
|
|
|
void B2_unlock_mutex(B2_mutex *mutex)
|
|
|
|
{
|
|
|
|
pthread_mutex_unlock(&mutex->m);
|
|
|
|
}
|
|
|
|
|
|
|
|
void B2_delete_mutex(B2_mutex *mutex)
|
|
|
|
{
|
|
|
|
delete mutex;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
struct B2_mutex {
|
|
|
|
int dummy;
|
|
|
|
};
|
|
|
|
|
|
|
|
B2_mutex *B2_create_mutex(void)
|
|
|
|
{
|
|
|
|
return new B2_mutex;
|
|
|
|
}
|
|
|
|
|
|
|
|
void B2_lock_mutex(B2_mutex *mutex)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void B2_unlock_mutex(B2_mutex *mutex)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void B2_delete_mutex(B2_mutex *mutex)
|
|
|
|
{
|
|
|
|
delete mutex;
|
|
|
|
}
|
|
|
|
|
2003-09-28 21:20:38 +00:00
|
|
|
#endif
|
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Trigger signal USR2 from another thread
|
|
|
|
*/
|
|
|
|
|
2004-05-20 12:33:58 +00:00
|
|
|
#if !EMULATED_PPC
|
2002-02-04 16:58:13 +00:00
|
|
|
void TriggerInterrupt(void)
|
|
|
|
{
|
2005-06-30 10:17:58 +00:00
|
|
|
if (ready_for_signals) {
|
|
|
|
idle_resume();
|
2002-02-04 16:58:13 +00:00
|
|
|
pthread_kill(emul_thread, SIGUSR2);
|
2005-06-30 10:17:58 +00:00
|
|
|
}
|
2002-02-04 16:58:13 +00:00
|
|
|
}
|
2003-09-28 21:20:38 +00:00
|
|
|
#endif
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Interrupt flags (must be handled atomically!)
|
|
|
|
*/
|
|
|
|
|
|
|
|
volatile uint32 InterruptFlags = 0;
|
|
|
|
|
|
|
|
void SetInterruptFlag(uint32 flag)
|
|
|
|
{
|
|
|
|
atomic_or((int *)&InterruptFlags, flag);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClearInterruptFlag(uint32 flag)
|
|
|
|
{
|
|
|
|
atomic_and((int *)&InterruptFlags, ~flag);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Disable interrupts
|
|
|
|
*/
|
|
|
|
|
|
|
|
void DisableInterrupt(void)
|
|
|
|
{
|
2004-06-22 17:10:08 +00:00
|
|
|
#if EMULATED_PPC
|
|
|
|
WriteMacInt32(XLM_IRQ_NEST, int32(ReadMacInt32(XLM_IRQ_NEST)) + 1);
|
|
|
|
#else
|
2003-09-28 21:20:38 +00:00
|
|
|
atomic_add((int *)XLM_IRQ_NEST, 1);
|
2004-06-22 17:10:08 +00:00
|
|
|
#endif
|
2002-02-04 16:58:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Enable interrupts
|
|
|
|
*/
|
|
|
|
|
|
|
|
void EnableInterrupt(void)
|
|
|
|
{
|
2004-06-22 17:10:08 +00:00
|
|
|
#if EMULATED_PPC
|
|
|
|
WriteMacInt32(XLM_IRQ_NEST, int32(ReadMacInt32(XLM_IRQ_NEST)) - 1);
|
|
|
|
#else
|
2003-09-28 21:20:38 +00:00
|
|
|
atomic_add((int *)XLM_IRQ_NEST, -1);
|
2004-06-22 17:10:08 +00:00
|
|
|
#endif
|
2002-02-04 16:58:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* USR2 handler
|
|
|
|
*/
|
|
|
|
|
2004-05-20 12:33:58 +00:00
|
|
|
#if !EMULATED_PPC
|
2005-06-28 16:47:32 +00:00
|
|
|
void sigusr2_handler(int sig, siginfo_t *sip, void *scp)
|
2002-02-04 16:58:13 +00:00
|
|
|
{
|
2004-01-18 22:14:31 +00:00
|
|
|
machine_regs *r = MACHINE_REGISTERS(scp);
|
2002-02-04 16:58:13 +00:00
|
|
|
|
2005-02-27 21:52:06 +00:00
|
|
|
#ifdef SYSTEM_CLOBBERS_R2
|
|
|
|
// Restore pointer to Thread Local Storage
|
|
|
|
set_r2(TOC);
|
|
|
|
#endif
|
|
|
|
#ifdef SYSTEM_CLOBBERS_R13
|
|
|
|
// Restore pointer to .sdata section
|
|
|
|
set_r13(R13);
|
|
|
|
#endif
|
|
|
|
|
2005-06-30 22:26:12 +00:00
|
|
|
#ifdef USE_SDL_VIDEO
|
|
|
|
// We must fill in the events queue in the same thread that did call SDL_SetVideoMode()
|
|
|
|
SDL_PumpEvents();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Do nothing if interrupts are disabled
|
|
|
|
if (*(int32 *)XLM_IRQ_NEST > 0)
|
|
|
|
return;
|
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
// Disable MacOS stack sniffer
|
|
|
|
WriteMacInt32(0x110, 0);
|
|
|
|
|
|
|
|
// Interrupt action depends on current run mode
|
|
|
|
switch (ReadMacInt32(XLM_RUN_MODE)) {
|
|
|
|
case MODE_68K:
|
|
|
|
// 68k emulator active, trigger 68k interrupt level 1
|
|
|
|
WriteMacInt16(ntohl(kernel_data->v[0x67c >> 2]), 1);
|
2004-01-18 22:14:31 +00:00
|
|
|
r->cr() |= ntohl(kernel_data->v[0x674 >> 2]);
|
2002-02-04 16:58:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
#if INTERRUPTS_IN_NATIVE_MODE
|
|
|
|
case MODE_NATIVE:
|
|
|
|
// 68k emulator inactive, in nanokernel?
|
2004-01-18 22:14:31 +00:00
|
|
|
if (r->gpr(1) != KernelDataAddr) {
|
2004-04-14 20:25:26 +00:00
|
|
|
|
2005-06-28 16:47:32 +00:00
|
|
|
// Set extra stack for SIGSEGV handler
|
|
|
|
sigaltstack(&extra_stack, NULL);
|
2004-04-14 20:25:26 +00:00
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
// Prepare for 68k interrupt level 1
|
|
|
|
WriteMacInt16(ntohl(kernel_data->v[0x67c >> 2]), 1);
|
|
|
|
WriteMacInt32(ntohl(kernel_data->v[0x658 >> 2]) + 0xdc, ReadMacInt32(ntohl(kernel_data->v[0x658 >> 2]) + 0xdc) | ntohl(kernel_data->v[0x674 >> 2]));
|
|
|
|
|
|
|
|
// Execute nanokernel interrupt routine (this will activate the 68k emulator)
|
2004-04-14 20:25:26 +00:00
|
|
|
DisableInterrupt();
|
2002-02-04 16:58:13 +00:00
|
|
|
if (ROMType == ROMTYPE_NEWWORLD)
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
ppc_interrupt(ROMBase + 0x312b1c, KernelDataAddr);
|
2002-02-04 16:58:13 +00:00
|
|
|
else
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
ppc_interrupt(ROMBase + 0x312a3c, KernelDataAddr);
|
2004-04-14 20:25:26 +00:00
|
|
|
|
2005-06-28 16:47:32 +00:00
|
|
|
// Reset normal stack
|
|
|
|
sigaltstack(&sig_stack, NULL);
|
2002-02-04 16:58:13 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if INTERRUPTS_IN_EMUL_OP_MODE
|
|
|
|
case MODE_EMUL_OP:
|
|
|
|
// 68k emulator active, within EMUL_OP routine, execute 68k interrupt routine directly when interrupt level is 0
|
|
|
|
if ((ReadMacInt32(XLM_68K_R25) & 7) == 0) {
|
|
|
|
|
|
|
|
// Set extra stack for SIGSEGV handler
|
2005-06-28 16:47:32 +00:00
|
|
|
sigaltstack(&extra_stack, NULL);
|
2002-02-04 16:58:13 +00:00
|
|
|
#if 1
|
|
|
|
// Execute full 68k interrupt routine
|
|
|
|
M68kRegisters r;
|
|
|
|
uint32 old_r25 = ReadMacInt32(XLM_68K_R25); // Save interrupt level
|
|
|
|
WriteMacInt32(XLM_68K_R25, 0x21); // Execute with interrupt level 1
|
|
|
|
static const uint16 proc[] = {
|
|
|
|
0x3f3c, 0x0000, // move.w #$0000,-(sp) (fake format word)
|
|
|
|
0x487a, 0x000a, // pea @1(pc) (return address)
|
|
|
|
0x40e7, // move sr,-(sp) (saved SR)
|
|
|
|
0x2078, 0x0064, // move.l $64,a0
|
|
|
|
0x4ed0, // jmp (a0)
|
|
|
|
M68K_RTS // @1
|
|
|
|
};
|
|
|
|
Execute68k((uint32)proc, &r);
|
|
|
|
WriteMacInt32(XLM_68K_R25, old_r25); // Restore interrupt level
|
|
|
|
#else
|
|
|
|
// Only update cursor
|
|
|
|
if (HasMacStarted()) {
|
|
|
|
if (InterruptFlags & INTFLAG_VIA) {
|
|
|
|
ClearInterruptFlag(INTFLAG_VIA);
|
|
|
|
ADBInterrupt();
|
2003-12-04 23:37:38 +00:00
|
|
|
ExecuteNative(NATIVE_VIDEO_VBL);
|
2002-02-04 16:58:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2005-06-28 16:47:32 +00:00
|
|
|
// Reset normal stack
|
|
|
|
sigaltstack(&sig_stack, NULL);
|
2002-02-04 16:58:13 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
2003-09-29 15:46:09 +00:00
|
|
|
#endif
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SIGSEGV handler
|
|
|
|
*/
|
|
|
|
|
2003-09-29 15:46:09 +00:00
|
|
|
#if !EMULATED_PPC
|
2004-01-18 22:14:31 +00:00
|
|
|
static void sigsegv_handler(int sig, siginfo_t *sip, void *scp)
|
2002-02-04 16:58:13 +00:00
|
|
|
{
|
2004-01-18 22:14:31 +00:00
|
|
|
machine_regs *r = MACHINE_REGISTERS(scp);
|
2003-05-22 22:12:05 +00:00
|
|
|
|
|
|
|
// Get effective address
|
2004-01-18 22:14:31 +00:00
|
|
|
uint32 addr = r->dar();
|
2003-05-22 22:12:05 +00:00
|
|
|
|
2005-02-27 21:52:06 +00:00
|
|
|
#ifdef SYSTEM_CLOBBERS_R2
|
|
|
|
// Restore pointer to Thread Local Storage
|
|
|
|
set_r2(TOC);
|
|
|
|
#endif
|
|
|
|
#ifdef SYSTEM_CLOBBERS_R13
|
|
|
|
// Restore pointer to .sdata section
|
|
|
|
set_r13(R13);
|
|
|
|
#endif
|
|
|
|
|
2003-05-22 22:12:05 +00:00
|
|
|
#if ENABLE_VOSF
|
2007-12-30 09:18:40 +00:00
|
|
|
// Handle screen fault
|
|
|
|
#if SIGSEGV_CHECK_VERSION(1,0,0)
|
|
|
|
sigsegv_info_t si;
|
|
|
|
si.addr = (sigsegv_address_t)addr;
|
|
|
|
si.pc = (sigsegv_address_t)r->pc();
|
|
|
|
#endif
|
|
|
|
extern bool Screen_fault_handler(sigsegv_info_t *sip);
|
|
|
|
if (Screen_fault_handler(&si))
|
2003-05-22 22:12:05 +00:00
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
num_segv++;
|
|
|
|
|
2004-05-31 10:02:20 +00:00
|
|
|
// Fault in Mac ROM or RAM or DR Cache?
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
bool mac_fault = (r->pc() >= ROMBase) && (r->pc() < (ROMBase + ROM_AREA_SIZE)) || (r->pc() >= RAMBase) && (r->pc() < (RAMBase + RAMSize)) || (r->pc() >= DR_CACHE_BASE && r->pc() < (DR_CACHE_BASE + DR_CACHE_SIZE));
|
2002-02-04 16:58:13 +00:00
|
|
|
if (mac_fault) {
|
|
|
|
|
|
|
|
// "VM settings" during MacOS 8 installation
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
if (r->pc() == ROMBase + 0x488160 && r->gpr(20) == 0xf8000000) {
|
2004-01-18 22:14:31 +00:00
|
|
|
r->pc() += 4;
|
|
|
|
r->gpr(8) = 0;
|
2002-02-04 16:58:13 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
// MacOS 8.5 installation
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
} else if (r->pc() == ROMBase + 0x488140 && r->gpr(16) == 0xf8000000) {
|
2004-01-18 22:14:31 +00:00
|
|
|
r->pc() += 4;
|
|
|
|
r->gpr(8) = 0;
|
2002-02-04 16:58:13 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
// MacOS 8 serial drivers on startup
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
} else if (r->pc() == ROMBase + 0x48e080 && (r->gpr(8) == 0xf3012002 || r->gpr(8) == 0xf3012000)) {
|
2004-01-18 22:14:31 +00:00
|
|
|
r->pc() += 4;
|
|
|
|
r->gpr(8) = 0;
|
2002-02-04 16:58:13 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
// MacOS 8.1 serial drivers on startup
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
} else if (r->pc() == ROMBase + 0x48c5e0 && (r->gpr(20) == 0xf3012002 || r->gpr(20) == 0xf3012000)) {
|
2004-01-18 22:14:31 +00:00
|
|
|
r->pc() += 4;
|
2002-02-04 16:58:13 +00:00
|
|
|
return;
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
} else if (r->pc() == ROMBase + 0x4a10a0 && (r->gpr(20) == 0xf3012002 || r->gpr(20) == 0xf3012000)) {
|
2004-01-18 22:14:31 +00:00
|
|
|
r->pc() += 4;
|
2002-02-04 16:58:13 +00:00
|
|
|
return;
|
2004-05-31 10:02:20 +00:00
|
|
|
|
|
|
|
// MacOS 8.6 serial drivers on startup (with DR Cache and OldWorld ROM)
|
|
|
|
} else if ((r->pc() - DR_CACHE_BASE) < DR_CACHE_SIZE && (r->gpr(16) == 0xf3012002 || r->gpr(16) == 0xf3012000)) {
|
|
|
|
r->pc() += 4;
|
|
|
|
return;
|
|
|
|
} else if ((r->pc() - DR_CACHE_BASE) < DR_CACHE_SIZE && (r->gpr(20) == 0xf3012002 || r->gpr(20) == 0xf3012000)) {
|
|
|
|
r->pc() += 4;
|
|
|
|
return;
|
2002-02-04 16:58:13 +00:00
|
|
|
}
|
|
|
|
|
2003-05-22 22:12:05 +00:00
|
|
|
// Get opcode and divide into fields
|
2004-01-18 22:14:31 +00:00
|
|
|
uint32 opcode = *((uint32 *)r->pc());
|
2003-05-22 22:12:05 +00:00
|
|
|
uint32 primop = opcode >> 26;
|
|
|
|
uint32 exop = (opcode >> 1) & 0x3ff;
|
|
|
|
uint32 ra = (opcode >> 16) & 0x1f;
|
|
|
|
uint32 rb = (opcode >> 11) & 0x1f;
|
|
|
|
uint32 rd = (opcode >> 21) & 0x1f;
|
|
|
|
int32 imm = (int16)(opcode & 0xffff);
|
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
// Analyze opcode
|
|
|
|
enum {
|
|
|
|
TYPE_UNKNOWN,
|
|
|
|
TYPE_LOAD,
|
|
|
|
TYPE_STORE
|
|
|
|
} transfer_type = TYPE_UNKNOWN;
|
|
|
|
enum {
|
|
|
|
SIZE_UNKNOWN,
|
|
|
|
SIZE_BYTE,
|
|
|
|
SIZE_HALFWORD,
|
|
|
|
SIZE_WORD
|
|
|
|
} transfer_size = SIZE_UNKNOWN;
|
|
|
|
enum {
|
|
|
|
MODE_UNKNOWN,
|
|
|
|
MODE_NORM,
|
|
|
|
MODE_U,
|
|
|
|
MODE_X,
|
|
|
|
MODE_UX
|
|
|
|
} addr_mode = MODE_UNKNOWN;
|
|
|
|
switch (primop) {
|
|
|
|
case 31:
|
|
|
|
switch (exop) {
|
|
|
|
case 23: // lwzx
|
|
|
|
transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
|
|
|
|
case 55: // lwzux
|
|
|
|
transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
|
|
|
|
case 87: // lbzx
|
|
|
|
transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break;
|
|
|
|
case 119: // lbzux
|
|
|
|
transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break;
|
|
|
|
case 151: // stwx
|
|
|
|
transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
|
|
|
|
case 183: // stwux
|
|
|
|
transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
|
|
|
|
case 215: // stbx
|
|
|
|
transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break;
|
|
|
|
case 247: // stbux
|
|
|
|
transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break;
|
|
|
|
case 279: // lhzx
|
|
|
|
transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break;
|
|
|
|
case 311: // lhzux
|
|
|
|
transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break;
|
|
|
|
case 343: // lhax
|
|
|
|
transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break;
|
|
|
|
case 375: // lhaux
|
|
|
|
transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break;
|
|
|
|
case 407: // sthx
|
|
|
|
transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break;
|
|
|
|
case 439: // sthux
|
|
|
|
transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 32: // lwz
|
|
|
|
transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
|
|
|
|
case 33: // lwzu
|
|
|
|
transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
|
|
|
|
case 34: // lbz
|
|
|
|
transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break;
|
|
|
|
case 35: // lbzu
|
|
|
|
transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break;
|
|
|
|
case 36: // stw
|
|
|
|
transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
|
|
|
|
case 37: // stwu
|
|
|
|
transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
|
|
|
|
case 38: // stb
|
|
|
|
transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break;
|
|
|
|
case 39: // stbu
|
|
|
|
transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break;
|
|
|
|
case 40: // lhz
|
|
|
|
transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break;
|
|
|
|
case 41: // lhzu
|
|
|
|
transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
|
|
|
|
case 42: // lha
|
|
|
|
transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break;
|
|
|
|
case 43: // lhau
|
|
|
|
transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
|
|
|
|
case 44: // sth
|
|
|
|
transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break;
|
|
|
|
case 45: // sthu
|
|
|
|
transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
|
2004-01-04 18:35:21 +00:00
|
|
|
#if EMULATE_UNALIGNED_LOADSTORE_MULTIPLE
|
|
|
|
case 46: // lmw
|
2004-01-18 22:22:28 +00:00
|
|
|
if ((addr % 4) != 0) {
|
|
|
|
uint32 ea = addr;
|
2004-01-18 22:14:31 +00:00
|
|
|
D(bug("WARNING: unaligned lmw to EA=%08x from IP=%08x\n", ea, r->pc()));
|
2004-01-04 18:35:21 +00:00
|
|
|
for (int i = rd; i <= 31; i++) {
|
2004-01-18 22:14:31 +00:00
|
|
|
r->gpr(i) = ReadMacInt32(ea);
|
2004-01-04 18:35:21 +00:00
|
|
|
ea += 4;
|
|
|
|
}
|
2004-01-18 22:14:31 +00:00
|
|
|
r->pc() += 4;
|
2004-01-04 18:35:21 +00:00
|
|
|
goto rti;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 47: // stmw
|
2004-01-18 22:22:28 +00:00
|
|
|
if ((addr % 4) != 0) {
|
|
|
|
uint32 ea = addr;
|
2004-01-18 22:14:31 +00:00
|
|
|
D(bug("WARNING: unaligned stmw to EA=%08x from IP=%08x\n", ea, r->pc()));
|
2004-01-04 18:35:21 +00:00
|
|
|
for (int i = rd; i <= 31; i++) {
|
2004-01-18 22:14:31 +00:00
|
|
|
WriteMacInt32(ea, r->gpr(i));
|
2004-01-04 18:35:21 +00:00
|
|
|
ea += 4;
|
|
|
|
}
|
2004-01-18 22:14:31 +00:00
|
|
|
r->pc() += 4;
|
2004-01-04 18:35:21 +00:00
|
|
|
goto rti;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
2002-02-04 16:58:13 +00:00
|
|
|
}
|
|
|
|
|
2004-02-24 11:12:54 +00:00
|
|
|
// Ignore ROM writes (including to the zero page, which is read-only)
|
|
|
|
if (transfer_type == TYPE_STORE &&
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
((addr >= ROMBase && addr < ROMBase + ROM_SIZE) ||
|
2004-02-24 11:12:54 +00:00
|
|
|
(addr >= SheepMem::ZeroPage() && addr < SheepMem::ZeroPage() + SheepMem::PageSize()))) {
|
2004-01-18 22:14:31 +00:00
|
|
|
// 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()));
|
2002-02-04 16:58:13 +00:00
|
|
|
if (addr_mode == MODE_U || addr_mode == MODE_UX)
|
2004-01-18 22:14:31 +00:00
|
|
|
r->gpr(ra) = addr;
|
|
|
|
r->pc() += 4;
|
2002-02-04 16:58:13 +00:00
|
|
|
goto rti;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ignore illegal memory accesses?
|
|
|
|
if (PrefsFindBool("ignoresegv")) {
|
|
|
|
if (addr_mode == MODE_U || addr_mode == MODE_UX)
|
2004-01-18 22:14:31 +00:00
|
|
|
r->gpr(ra) = addr;
|
2002-02-04 16:58:13 +00:00
|
|
|
if (transfer_type == TYPE_LOAD)
|
2004-01-18 22:14:31 +00:00
|
|
|
r->gpr(rd) = 0;
|
|
|
|
r->pc() += 4;
|
2002-02-04 16:58:13 +00:00
|
|
|
goto rti;
|
|
|
|
}
|
|
|
|
|
|
|
|
// In GUI mode, show error alert
|
|
|
|
if (!PrefsFindBool("nogui")) {
|
|
|
|
char str[256];
|
|
|
|
if (transfer_type == TYPE_LOAD || transfer_type == TYPE_STORE)
|
2004-01-18 22:14:31 +00:00
|
|
|
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));
|
2002-02-04 16:58:13 +00:00
|
|
|
else
|
2004-01-18 22:14:31 +00:00
|
|
|
sprintf(str, GetString(STR_UNKNOWN_SEGV_ERR), r->pc(), r->gpr(24), r->gpr(1), opcode);
|
2002-02-04 16:58:13 +00:00
|
|
|
ErrorAlert(str);
|
|
|
|
QuitEmulator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// For all other errors, jump into debugger (sort of...)
|
2004-01-04 18:35:21 +00:00
|
|
|
crash_reason = (sig == SIGBUS) ? "SIGBUS" : "SIGSEGV";
|
2002-02-04 16:58:13 +00:00
|
|
|
if (!ready_for_signals) {
|
2004-01-04 18:35:21 +00:00
|
|
|
printf("%s\n");
|
2004-01-18 22:14:31 +00:00
|
|
|
printf(" sigcontext %p, machine_regs %p\n", scp, r);
|
2002-02-04 16:58:13 +00:00
|
|
|
printf(
|
|
|
|
" pc %08lx lr %08lx ctr %08lx msr %08lx\n"
|
|
|
|
" xer %08lx cr %08lx \n"
|
|
|
|
" r0 %08lx r1 %08lx r2 %08lx r3 %08lx\n"
|
|
|
|
" r4 %08lx r5 %08lx r6 %08lx r7 %08lx\n"
|
|
|
|
" r8 %08lx r9 %08lx r10 %08lx r11 %08lx\n"
|
|
|
|
" r12 %08lx r13 %08lx r14 %08lx r15 %08lx\n"
|
|
|
|
" r16 %08lx r17 %08lx r18 %08lx r19 %08lx\n"
|
|
|
|
" r20 %08lx r21 %08lx r22 %08lx r23 %08lx\n"
|
|
|
|
" r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n"
|
|
|
|
" r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n",
|
2004-01-04 18:35:21 +00:00
|
|
|
crash_reason,
|
2004-01-18 22:14:31 +00:00
|
|
|
r->pc(), r->lr(), r->ctr(), r->msr(),
|
|
|
|
r->xer(), r->cr(),
|
|
|
|
r->gpr(0), r->gpr(1), r->gpr(2), r->gpr(3),
|
|
|
|
r->gpr(4), r->gpr(5), r->gpr(6), r->gpr(7),
|
|
|
|
r->gpr(8), r->gpr(9), r->gpr(10), r->gpr(11),
|
|
|
|
r->gpr(12), r->gpr(13), r->gpr(14), r->gpr(15),
|
|
|
|
r->gpr(16), r->gpr(17), r->gpr(18), r->gpr(19),
|
|
|
|
r->gpr(20), r->gpr(21), r->gpr(22), r->gpr(23),
|
|
|
|
r->gpr(24), r->gpr(25), r->gpr(26), r->gpr(27),
|
|
|
|
r->gpr(28), r->gpr(29), r->gpr(30), r->gpr(31));
|
2002-02-04 16:58:13 +00:00
|
|
|
exit(1);
|
|
|
|
QuitEmulator();
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
// We crashed. Save registers, tell tick thread and loop forever
|
2004-01-18 22:14:31 +00:00
|
|
|
build_sigregs(&sigsegv_regs, r);
|
2002-02-04 16:58:13 +00:00
|
|
|
emul_thread_fatal = true;
|
|
|
|
for (;;) ;
|
|
|
|
}
|
|
|
|
rti:;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SIGILL handler
|
|
|
|
*/
|
|
|
|
|
2004-01-18 22:14:31 +00:00
|
|
|
static void sigill_handler(int sig, siginfo_t *sip, void *scp)
|
2002-02-04 16:58:13 +00:00
|
|
|
{
|
2004-01-18 22:14:31 +00:00
|
|
|
machine_regs *r = MACHINE_REGISTERS(scp);
|
2002-02-04 16:58:13 +00:00
|
|
|
char str[256];
|
|
|
|
|
2005-02-27 21:52:06 +00:00
|
|
|
#ifdef SYSTEM_CLOBBERS_R2
|
|
|
|
// Restore pointer to Thread Local Storage
|
|
|
|
set_r2(TOC);
|
|
|
|
#endif
|
|
|
|
#ifdef SYSTEM_CLOBBERS_R13
|
|
|
|
// Restore pointer to .sdata section
|
|
|
|
set_r13(R13);
|
|
|
|
#endif
|
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
// Fault in Mac ROM or RAM?
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
bool mac_fault = (r->pc() >= ROMBase) && (r->pc() < (ROMBase + ROM_AREA_SIZE)) || (r->pc() >= RAMBase) && (r->pc() < (RAMBase + RAMSize));
|
2002-02-04 16:58:13 +00:00
|
|
|
if (mac_fault) {
|
|
|
|
|
|
|
|
// Get opcode and divide into fields
|
2004-01-18 22:14:31 +00:00
|
|
|
uint32 opcode = *((uint32 *)r->pc());
|
2002-02-04 16:58:13 +00:00
|
|
|
uint32 primop = opcode >> 26;
|
|
|
|
uint32 exop = (opcode >> 1) & 0x3ff;
|
|
|
|
uint32 ra = (opcode >> 16) & 0x1f;
|
|
|
|
uint32 rb = (opcode >> 11) & 0x1f;
|
|
|
|
uint32 rd = (opcode >> 21) & 0x1f;
|
|
|
|
int32 imm = (int16)(opcode & 0xffff);
|
|
|
|
|
|
|
|
switch (primop) {
|
|
|
|
case 9: // POWER instructions
|
|
|
|
case 22:
|
2004-01-18 22:14:31 +00:00
|
|
|
power_inst: sprintf(str, GetString(STR_POWER_INSTRUCTION_ERR), r->pc(), r->gpr(1), opcode);
|
2002-02-04 16:58:13 +00:00
|
|
|
ErrorAlert(str);
|
|
|
|
QuitEmulator();
|
|
|
|
return;
|
|
|
|
|
|
|
|
case 31:
|
|
|
|
switch (exop) {
|
|
|
|
case 83: // mfmsr
|
2004-01-18 22:14:31 +00:00
|
|
|
r->gpr(rd) = 0xf072;
|
|
|
|
r->pc() += 4;
|
2002-02-04 16:58:13 +00:00
|
|
|
goto rti;
|
|
|
|
|
|
|
|
case 210: // mtsr
|
|
|
|
case 242: // mtsrin
|
|
|
|
case 306: // tlbie
|
2004-01-18 22:14:31 +00:00
|
|
|
r->pc() += 4;
|
2002-02-04 16:58:13 +00:00
|
|
|
goto rti;
|
|
|
|
|
|
|
|
case 339: { // mfspr
|
|
|
|
int spr = ra | (rb << 5);
|
|
|
|
switch (spr) {
|
|
|
|
case 0: // MQ
|
|
|
|
case 22: // DEC
|
|
|
|
case 952: // MMCR0
|
|
|
|
case 953: // PMC1
|
|
|
|
case 954: // PMC2
|
|
|
|
case 955: // SIA
|
|
|
|
case 956: // MMCR1
|
|
|
|
case 957: // PMC3
|
|
|
|
case 958: // PMC4
|
|
|
|
case 959: // SDA
|
2004-01-18 22:14:31 +00:00
|
|
|
r->pc() += 4;
|
2002-02-04 16:58:13 +00:00
|
|
|
goto rti;
|
|
|
|
case 25: // SDR1
|
2004-01-18 22:14:31 +00:00
|
|
|
r->gpr(rd) = 0xdead001f;
|
|
|
|
r->pc() += 4;
|
2002-02-04 16:58:13 +00:00
|
|
|
goto rti;
|
|
|
|
case 287: // PVR
|
2004-01-18 22:14:31 +00:00
|
|
|
r->gpr(rd) = PVR;
|
|
|
|
r->pc() += 4;
|
2002-02-04 16:58:13 +00:00
|
|
|
goto rti;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 467: { // mtspr
|
|
|
|
int spr = ra | (rb << 5);
|
|
|
|
switch (spr) {
|
|
|
|
case 0: // MQ
|
|
|
|
case 22: // DEC
|
|
|
|
case 275: // SPRG3
|
|
|
|
case 528: // IBAT0U
|
|
|
|
case 529: // IBAT0L
|
|
|
|
case 530: // IBAT1U
|
|
|
|
case 531: // IBAT1L
|
|
|
|
case 532: // IBAT2U
|
|
|
|
case 533: // IBAT2L
|
|
|
|
case 534: // IBAT3U
|
|
|
|
case 535: // IBAT3L
|
|
|
|
case 536: // DBAT0U
|
|
|
|
case 537: // DBAT0L
|
|
|
|
case 538: // DBAT1U
|
|
|
|
case 539: // DBAT1L
|
|
|
|
case 540: // DBAT2U
|
|
|
|
case 541: // DBAT2L
|
|
|
|
case 542: // DBAT3U
|
|
|
|
case 543: // DBAT3L
|
|
|
|
case 952: // MMCR0
|
|
|
|
case 953: // PMC1
|
|
|
|
case 954: // PMC2
|
|
|
|
case 955: // SIA
|
|
|
|
case 956: // MMCR1
|
|
|
|
case 957: // PMC3
|
|
|
|
case 958: // PMC4
|
|
|
|
case 959: // SDA
|
2004-01-18 22:14:31 +00:00
|
|
|
r->pc() += 4;
|
2002-02-04 16:58:13 +00:00
|
|
|
goto rti;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 29: case 107: case 152: case 153: // POWER instructions
|
|
|
|
case 184: case 216: case 217: case 248:
|
|
|
|
case 264: case 277: case 331: case 360:
|
|
|
|
case 363: case 488: case 531: case 537:
|
|
|
|
case 541: case 664: case 665: case 696:
|
|
|
|
case 728: case 729: case 760: case 920:
|
|
|
|
case 921: case 952:
|
|
|
|
goto power_inst;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// In GUI mode, show error alert
|
|
|
|
if (!PrefsFindBool("nogui")) {
|
2004-01-18 22:14:31 +00:00
|
|
|
sprintf(str, GetString(STR_UNKNOWN_SEGV_ERR), r->pc(), r->gpr(24), r->gpr(1), opcode);
|
2002-02-04 16:58:13 +00:00
|
|
|
ErrorAlert(str);
|
|
|
|
QuitEmulator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// For all other errors, jump into debugger (sort of...)
|
2004-01-04 18:35:21 +00:00
|
|
|
crash_reason = "SIGILL";
|
2002-02-04 16:58:13 +00:00
|
|
|
if (!ready_for_signals) {
|
2004-01-04 18:35:21 +00:00
|
|
|
printf("%s\n");
|
2004-01-18 22:14:31 +00:00
|
|
|
printf(" sigcontext %p, machine_regs %p\n", scp, r);
|
2002-02-04 16:58:13 +00:00
|
|
|
printf(
|
|
|
|
" pc %08lx lr %08lx ctr %08lx msr %08lx\n"
|
|
|
|
" xer %08lx cr %08lx \n"
|
|
|
|
" r0 %08lx r1 %08lx r2 %08lx r3 %08lx\n"
|
|
|
|
" r4 %08lx r5 %08lx r6 %08lx r7 %08lx\n"
|
|
|
|
" r8 %08lx r9 %08lx r10 %08lx r11 %08lx\n"
|
|
|
|
" r12 %08lx r13 %08lx r14 %08lx r15 %08lx\n"
|
|
|
|
" r16 %08lx r17 %08lx r18 %08lx r19 %08lx\n"
|
|
|
|
" r20 %08lx r21 %08lx r22 %08lx r23 %08lx\n"
|
|
|
|
" r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n"
|
|
|
|
" r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n",
|
2004-01-04 18:35:21 +00:00
|
|
|
crash_reason,
|
2004-01-18 22:14:31 +00:00
|
|
|
r->pc(), r->lr(), r->ctr(), r->msr(),
|
|
|
|
r->xer(), r->cr(),
|
|
|
|
r->gpr(0), r->gpr(1), r->gpr(2), r->gpr(3),
|
|
|
|
r->gpr(4), r->gpr(5), r->gpr(6), r->gpr(7),
|
|
|
|
r->gpr(8), r->gpr(9), r->gpr(10), r->gpr(11),
|
|
|
|
r->gpr(12), r->gpr(13), r->gpr(14), r->gpr(15),
|
|
|
|
r->gpr(16), r->gpr(17), r->gpr(18), r->gpr(19),
|
|
|
|
r->gpr(20), r->gpr(21), r->gpr(22), r->gpr(23),
|
|
|
|
r->gpr(24), r->gpr(25), r->gpr(26), r->gpr(27),
|
|
|
|
r->gpr(28), r->gpr(29), r->gpr(30), r->gpr(31));
|
2002-02-04 16:58:13 +00:00
|
|
|
exit(1);
|
|
|
|
QuitEmulator();
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
// We crashed. Save registers, tell tick thread and loop forever
|
2004-01-18 22:14:31 +00:00
|
|
|
build_sigregs(&sigsegv_regs, r);
|
2002-02-04 16:58:13 +00:00
|
|
|
emul_thread_fatal = true;
|
|
|
|
for (;;) ;
|
|
|
|
}
|
|
|
|
rti:;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2003-12-04 17:26:38 +00:00
|
|
|
/*
|
|
|
|
* Helpers to share 32-bit addressable data with MacOS
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool SheepMem::Init(void)
|
|
|
|
{
|
2004-02-24 11:12:54 +00:00
|
|
|
// Size of a native page
|
|
|
|
page_size = getpagesize();
|
2003-12-05 13:37:56 +00:00
|
|
|
|
|
|
|
// Allocate SheepShaver globals
|
2004-11-22 21:33:32 +00:00
|
|
|
proc = base;
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
if (vm_mac_acquire_fixed(base, size) < 0)
|
2003-12-04 17:26:38 +00:00
|
|
|
return false;
|
2003-12-05 12:36:11 +00:00
|
|
|
|
2004-11-22 21:33:32 +00:00
|
|
|
// Allocate page with all bits set to 0, right in the middle
|
|
|
|
// This is also used to catch undesired overlaps between proc and data areas
|
|
|
|
zero_page = proc + (size / 2);
|
|
|
|
Mac_memset(zero_page, 0, page_size);
|
|
|
|
if (vm_protect(Mac2HostAddr(zero_page), page_size, VM_PAGE_READ) < 0)
|
2003-12-05 12:36:11 +00:00
|
|
|
return false;
|
|
|
|
|
2003-12-05 13:37:56 +00:00
|
|
|
#if EMULATED_PPC
|
|
|
|
// Allocate alternate stack for PowerPC interrupt routine
|
2004-11-22 21:33:32 +00:00
|
|
|
sig_stack = base + size;
|
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.
Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".
SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.
The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.
On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.
Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.
This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.
Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.
A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.
Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.
The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.
This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.
Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.
2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.
3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.
4. Changed and rearranged the allocation of RAM and ROM areas.
Before it worked like this:
- Allocate ROM area
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0, allocate at fixed address
We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:
- If can, attempt to allocate RAM at address zero
- If RAM not allocated at 0
if REAL addressing
allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
else (direct addressing)
allocate RAM at fixed address
- If ROM hasn't been allocated yet, allocate at fixed address
5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.
6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.
7. Change subsequent code from using constant ROM_BASE to variable ROMBase.
Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.
ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.
ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.
main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.
cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.
user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.
2009-08-18 18:26:11 +00:00
|
|
|
if (vm_mac_acquire_fixed(sig_stack, SIG_STACK_SIZE) < 0)
|
2003-12-05 13:37:56 +00:00
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
|
2004-11-22 21:33:32 +00:00
|
|
|
data = base + size;
|
2003-12-04 17:26:38 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SheepMem::Exit(void)
|
|
|
|
{
|
2004-11-22 21:33:32 +00:00
|
|
|
if (data) {
|
2003-12-05 13:37:56 +00:00
|
|
|
// Delete SheepShaver globals
|
2004-11-22 21:33:32 +00:00
|
|
|
vm_mac_release(base, size);
|
2003-12-05 13:37:56 +00:00
|
|
|
|
|
|
|
#if EMULATED_PPC
|
|
|
|
// Delete alternate stack for PowerPC interrupt routine
|
2004-11-22 21:33:32 +00:00
|
|
|
vm_mac_release(sig_stack, SIG_STACK_SIZE);
|
2003-12-05 13:37:56 +00:00
|
|
|
#endif
|
2003-12-05 12:36:11 +00:00
|
|
|
}
|
2003-12-04 17:26:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-02-04 16:58:13 +00:00
|
|
|
/*
|
|
|
|
* Display alert
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef ENABLE_GTK
|
|
|
|
static void dl_destroyed(void)
|
|
|
|
{
|
|
|
|
gtk_main_quit();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dl_quit(GtkWidget *dialog)
|
|
|
|
{
|
|
|
|
gtk_widget_destroy(dialog);
|
|
|
|
}
|
|
|
|
|
|
|
|
void display_alert(int title_id, int prefix_id, int button_id, const char *text)
|
|
|
|
{
|
|
|
|
char str[256];
|
|
|
|
sprintf(str, GetString(prefix_id), text);
|
|
|
|
|
|
|
|
GtkWidget *dialog = gtk_dialog_new();
|
|
|
|
gtk_window_set_title(GTK_WINDOW(dialog), GetString(title_id));
|
|
|
|
gtk_container_border_width(GTK_CONTAINER(dialog), 5);
|
|
|
|
gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150);
|
|
|
|
gtk_signal_connect(GTK_OBJECT(dialog), "destroy", GTK_SIGNAL_FUNC(dl_destroyed), NULL);
|
|
|
|
|
|
|
|
GtkWidget *label = gtk_label_new(str);
|
|
|
|
gtk_widget_show(label);
|
|
|
|
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0);
|
|
|
|
|
|
|
|
GtkWidget *button = gtk_button_new_with_label(GetString(button_id));
|
|
|
|
gtk_widget_show(button);
|
|
|
|
gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog));
|
|
|
|
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0);
|
|
|
|
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
|
|
|
|
gtk_widget_grab_default(button);
|
|
|
|
gtk_widget_show(dialog);
|
|
|
|
|
|
|
|
gtk_main();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Display error alert
|
|
|
|
*/
|
|
|
|
|
|
|
|
void ErrorAlert(const char *text)
|
|
|
|
{
|
2006-05-01 22:33:34 +00:00
|
|
|
if (gui_connection) {
|
|
|
|
if (rpc_method_invoke(gui_connection, RPC_METHOD_ERROR_ALERT, RPC_TYPE_STRING, text, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR &&
|
|
|
|
rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
|
|
|
|
return;
|
|
|
|
}
|
2004-06-24 15:37:26 +00:00
|
|
|
#if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO)
|
2002-02-04 16:58:13 +00:00
|
|
|
if (PrefsFindBool("nogui") || x_display == NULL) {
|
|
|
|
printf(GetString(STR_SHELL_ERROR_PREFIX), text);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
VideoQuitFullScreen();
|
|
|
|
display_alert(STR_ERROR_ALERT_TITLE, STR_GUI_ERROR_PREFIX, STR_QUIT_BUTTON, text);
|
|
|
|
#else
|
|
|
|
printf(GetString(STR_SHELL_ERROR_PREFIX), text);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Display warning alert
|
|
|
|
*/
|
|
|
|
|
|
|
|
void WarningAlert(const char *text)
|
|
|
|
{
|
2006-05-01 22:33:34 +00:00
|
|
|
if (gui_connection) {
|
|
|
|
if (rpc_method_invoke(gui_connection, RPC_METHOD_WARNING_ALERT, RPC_TYPE_STRING, text, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR &&
|
|
|
|
rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
|
|
|
|
return;
|
|
|
|
}
|
2004-06-24 15:37:26 +00:00
|
|
|
#if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO)
|
2002-02-04 16:58:13 +00:00
|
|
|
if (PrefsFindBool("nogui") || x_display == NULL) {
|
|
|
|
printf(GetString(STR_SHELL_WARNING_PREFIX), text);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
display_alert(STR_WARNING_ALERT_TITLE, STR_GUI_WARNING_PREFIX, STR_OK_BUTTON, text);
|
|
|
|
#else
|
|
|
|
printf(GetString(STR_SHELL_WARNING_PREFIX), text);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Display choice alert
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool ChoiceAlert(const char *text, const char *pos, const char *neg)
|
|
|
|
{
|
|
|
|
printf(GetString(STR_SHELL_WARNING_PREFIX), text);
|
|
|
|
return false; //!!
|
|
|
|
}
|