ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/main.cpp
Revision: 1.7
Committed: 2009-08-18T18:26:10Z (14 years, 9 months ago) by asvitkine
Branch: MAIN
Changes since 1.6: +2 -2 lines
Log Message:
[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.

File Contents

# User Rev Content
1 gbeauche 1.1 /*
2     * main.cpp - ROM patches
3     *
4 gbeauche 1.5 * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig
5 gbeauche 1.1 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     #include "sysdeps.h"
22    
23     #include "main.h"
24     #include "version.h"
25     #include "prefs.h"
26     #include "prefs_editor.h"
27     #include "cpu_emulation.h"
28     #include "emul_op.h"
29     #include "xlowmem.h"
30     #include "xpram.h"
31     #include "timer.h"
32     #include "adb.h"
33     #include "sony.h"
34     #include "disk.h"
35     #include "cdrom.h"
36     #include "scsi.h"
37     #include "video.h"
38     #include "audio.h"
39     #include "ether.h"
40     #include "serial.h"
41     #include "clip.h"
42     #include "extfs.h"
43     #include "sys.h"
44     #include "macos_util.h"
45     #include "rom_patches.h"
46     #include "user_strings.h"
47     #include "vm_alloc.h"
48     #include "sigsegv.h"
49     #include "thunks.h"
50    
51     #define DEBUG 0
52     #include "debug.h"
53    
54     #ifdef ENABLE_MON
55     #include "mon.h"
56    
57     static uint32 sheepshaver_read_byte(uintptr adr)
58     {
59     return ReadMacInt8(adr);
60     }
61    
62     static void sheepshaver_write_byte(uintptr adr, uint32 b)
63     {
64     WriteMacInt8(adr, b);
65     }
66     #endif
67    
68    
69     /*
70     * Initialize everything, returns false on error
71     */
72    
73 asvitkine 1.6 bool InitAll(const char *vmdir)
74 gbeauche 1.1 {
75     // Load NVRAM
76 asvitkine 1.6 XPRAMInit(vmdir);
77 gbeauche 1.1
78     // Load XPRAM default values if signature not found
79     if (XPRAM[0x130c] != 0x4e || XPRAM[0x130d] != 0x75
80     || XPRAM[0x130e] != 0x4d || XPRAM[0x130f] != 0x63) {
81     D(bug("Loading XPRAM default values\n"));
82     memset(XPRAM + 0x1300, 0, 0x100);
83     XPRAM[0x130c] = 0x4e; // "NuMc" signature
84     XPRAM[0x130d] = 0x75;
85     XPRAM[0x130e] = 0x4d;
86     XPRAM[0x130f] = 0x63;
87     XPRAM[0x1301] = 0x80; // InternalWaitFlags = DynWait (don't wait for SCSI devices upon bootup)
88     XPRAM[0x1310] = 0xa8; // Standard PRAM values
89     XPRAM[0x1311] = 0x00;
90     XPRAM[0x1312] = 0x00;
91     XPRAM[0x1313] = 0x22;
92     XPRAM[0x1314] = 0xcc;
93     XPRAM[0x1315] = 0x0a;
94     XPRAM[0x1316] = 0xcc;
95     XPRAM[0x1317] = 0x0a;
96     XPRAM[0x131c] = 0x00;
97     XPRAM[0x131d] = 0x02;
98     XPRAM[0x131e] = 0x63;
99     XPRAM[0x131f] = 0x00;
100     XPRAM[0x1308] = 0x13;
101     XPRAM[0x1309] = 0x88;
102     XPRAM[0x130a] = 0x00;
103     XPRAM[0x130b] = 0xcc;
104     XPRAM[0x1376] = 0x00; // OSDefault = MacOS
105     XPRAM[0x1377] = 0x01;
106     }
107    
108     // Set boot volume
109     int16 i16 = PrefsFindInt32("bootdrive");
110     XPRAM[0x1378] = i16 >> 8;
111     XPRAM[0x1379] = i16 & 0xff;
112     i16 = PrefsFindInt32("bootdriver");
113     XPRAM[0x137a] = i16 >> 8;
114     XPRAM[0x137b] = i16 & 0xff;
115    
116     // Create BootGlobs at top of Mac memory
117     memset(RAMBaseHost + RAMSize - 4096, 0, 4096);
118     BootGlobsAddr = RAMBase + RAMSize - 0x1c;
119     WriteMacInt32(BootGlobsAddr - 5 * 4, RAMBase + RAMSize); // MemTop
120     WriteMacInt32(BootGlobsAddr + 0 * 4, RAMBase); // First RAM bank
121     WriteMacInt32(BootGlobsAddr + 1 * 4, RAMSize);
122     WriteMacInt32(BootGlobsAddr + 2 * 4, (uint32)-1); // End of bank table
123    
124     // Init thunks
125     if (!ThunksInit())
126     return false;
127    
128     // Init drivers
129     SonyInit();
130     DiskInit();
131     CDROMInit();
132     SCSIInit();
133    
134     // Init external file system
135     ExtFSInit();
136    
137     // Init ADB
138     ADBInit();
139    
140     // Init audio
141     AudioInit();
142    
143     // Init network
144     EtherInit();
145    
146     // Init serial ports
147     SerialInit();
148    
149     // Init Time Manager
150     TimerInit();
151    
152     // Init clipboard
153     ClipInit();
154    
155     // Init video
156     if (!VideoInit())
157     return false;
158    
159     // Install ROM patches
160     if (!PatchROM()) {
161     ErrorAlert(GetString(STR_UNSUPPORTED_ROM_TYPE_ERR));
162     return false;
163     }
164    
165     // Initialize Kernel Data
166     KernelData *kernel_data = (KernelData *)Mac2HostAddr(KERNEL_DATA_BASE);
167     memset(kernel_data, 0, sizeof(KernelData));
168     if (ROMType == ROMTYPE_NEWWORLD) {
169     uint32 of_dev_tree = SheepMem::Reserve(4 * sizeof(uint32));
170     Mac_memset(of_dev_tree, 0, 4 * sizeof(uint32));
171     uint32 vector_lookup_tbl = SheepMem::Reserve(128);
172     uint32 vector_mask_tbl = SheepMem::Reserve(64);
173     memset((uint8 *)kernel_data + 0xb80, 0x3d, 0x80);
174     Mac_memset(vector_lookup_tbl, 0, 128);
175     Mac_memset(vector_mask_tbl, 0, 64);
176 asvitkine 1.7 kernel_data->v[0xb80 >> 2] = htonl(ROMBase);
177 gbeauche 1.1 kernel_data->v[0xb84 >> 2] = htonl(of_dev_tree); // OF device tree base
178     kernel_data->v[0xb90 >> 2] = htonl(vector_lookup_tbl);
179     kernel_data->v[0xb94 >> 2] = htonl(vector_mask_tbl);
180 asvitkine 1.7 kernel_data->v[0xb98 >> 2] = htonl(ROMBase); // OpenPIC base
181 gbeauche 1.1 kernel_data->v[0xbb0 >> 2] = htonl(0); // ADB base
182     kernel_data->v[0xc20 >> 2] = htonl(RAMSize);
183     kernel_data->v[0xc24 >> 2] = htonl(RAMSize);
184     kernel_data->v[0xc30 >> 2] = htonl(RAMSize);
185     kernel_data->v[0xc34 >> 2] = htonl(RAMSize);
186     kernel_data->v[0xc38 >> 2] = htonl(0x00010020);
187     kernel_data->v[0xc3c >> 2] = htonl(0x00200001);
188     kernel_data->v[0xc40 >> 2] = htonl(0x00010000);
189     kernel_data->v[0xc50 >> 2] = htonl(RAMBase);
190     kernel_data->v[0xc54 >> 2] = htonl(RAMSize);
191     kernel_data->v[0xf60 >> 2] = htonl(PVR);
192     kernel_data->v[0xf64 >> 2] = htonl(CPUClockSpeed); // clock-frequency
193     kernel_data->v[0xf68 >> 2] = htonl(BusClockSpeed); // bus-frequency
194     kernel_data->v[0xf6c >> 2] = htonl(TimebaseSpeed); // timebase-frequency
195     } else if (ROMType == ROMTYPE_GOSSAMER) {
196     kernel_data->v[0xc80 >> 2] = htonl(RAMSize);
197     kernel_data->v[0xc84 >> 2] = htonl(RAMSize);
198     kernel_data->v[0xc90 >> 2] = htonl(RAMSize);
199     kernel_data->v[0xc94 >> 2] = htonl(RAMSize);
200     kernel_data->v[0xc98 >> 2] = htonl(0x00010020);
201     kernel_data->v[0xc9c >> 2] = htonl(0x00200001);
202     kernel_data->v[0xca0 >> 2] = htonl(0x00010000);
203     kernel_data->v[0xcb0 >> 2] = htonl(RAMBase);
204     kernel_data->v[0xcb4 >> 2] = htonl(RAMSize);
205     kernel_data->v[0xf60 >> 2] = htonl(PVR);
206     kernel_data->v[0xf64 >> 2] = htonl(CPUClockSpeed); // clock-frequency
207     kernel_data->v[0xf68 >> 2] = htonl(BusClockSpeed); // bus-frequency
208     kernel_data->v[0xf6c >> 2] = htonl(TimebaseSpeed); // timebase-frequency
209     } else {
210     kernel_data->v[0xc80 >> 2] = htonl(RAMSize);
211     kernel_data->v[0xc84 >> 2] = htonl(RAMSize);
212     kernel_data->v[0xc90 >> 2] = htonl(RAMSize);
213     kernel_data->v[0xc94 >> 2] = htonl(RAMSize);
214     kernel_data->v[0xc98 >> 2] = htonl(0x00010020);
215     kernel_data->v[0xc9c >> 2] = htonl(0x00200001);
216     kernel_data->v[0xca0 >> 2] = htonl(0x00010000);
217     kernel_data->v[0xcb0 >> 2] = htonl(RAMBase);
218     kernel_data->v[0xcb4 >> 2] = htonl(RAMSize);
219     kernel_data->v[0xf80 >> 2] = htonl(PVR);
220     kernel_data->v[0xf84 >> 2] = htonl(CPUClockSpeed); // clock-frequency
221     kernel_data->v[0xf88 >> 2] = htonl(BusClockSpeed); // bus-frequency
222     kernel_data->v[0xf8c >> 2] = htonl(TimebaseSpeed); // timebase-frequency
223     }
224    
225     // Initialize extra low memory
226     D(bug("Initializing Low Memory...\n"));
227     Mac_memset(0, 0, 0x3000);
228     WriteMacInt32(XLM_SIGNATURE, FOURCC('B','a','a','h')); // Signature to detect SheepShaver
229     WriteMacInt32(XLM_KERNEL_DATA, KernelDataAddr); // For trap replacement routines
230     WriteMacInt32(XLM_PVR, PVR); // Theoretical PVR
231     WriteMacInt32(XLM_BUS_CLOCK, BusClockSpeed); // For DriverServicesLib patch
232     WriteMacInt16(XLM_EXEC_RETURN_OPCODE, M68K_EXEC_RETURN); // For Execute68k() (RTS from the executed 68k code will jump here and end 68k mode)
233     WriteMacInt32(XLM_ZERO_PAGE, SheepMem::ZeroPage()); // Pointer to read-only page with all bits set to 0
234     #if !EMULATED_PPC
235 gbeauche 1.3 #ifdef SYSTEM_CLOBBERS_R2
236     WriteMacInt32(XLM_TOC, (uint32)TOC); // TOC pointer of emulator
237     #endif
238     #ifdef SYSTEM_CLOBBERS_R13
239     WriteMacInt32(XLM_R13, (uint32)R13); // TLS register
240     #endif
241 gbeauche 1.1 #endif
242 gbeauche 1.4
243     WriteMacInt32(XLM_ETHER_AO_GET_HWADDR, NativeFunction(NATIVE_ETHER_AO_GET_HWADDR)); // Low level ethernet driver functions
244     WriteMacInt32(XLM_ETHER_AO_ADD_MULTI, NativeFunction(NATIVE_ETHER_AO_ADD_MULTI));
245     WriteMacInt32(XLM_ETHER_AO_DEL_MULTI, NativeFunction(NATIVE_ETHER_AO_DEL_MULTI));
246     WriteMacInt32(XLM_ETHER_AO_SEND_PACKET, NativeFunction(NATIVE_ETHER_AO_SEND_PACKET));
247    
248 gbeauche 1.1 WriteMacInt32(XLM_ETHER_INIT, NativeFunction(NATIVE_ETHER_INIT)); // DLPI ethernet driver functions
249     WriteMacInt32(XLM_ETHER_TERM, NativeFunction(NATIVE_ETHER_TERM));
250     WriteMacInt32(XLM_ETHER_OPEN, NativeFunction(NATIVE_ETHER_OPEN));
251     WriteMacInt32(XLM_ETHER_CLOSE, NativeFunction(NATIVE_ETHER_CLOSE));
252     WriteMacInt32(XLM_ETHER_WPUT, NativeFunction(NATIVE_ETHER_WPUT));
253     WriteMacInt32(XLM_ETHER_RSRV, NativeFunction(NATIVE_ETHER_RSRV));
254     WriteMacInt32(XLM_VIDEO_DOIO, NativeFunction(NATIVE_VIDEO_DO_DRIVER_IO));
255     D(bug("Low Memory initialized\n"));
256    
257     #if ENABLE_MON
258     // Initialize mon
259     mon_init();
260     mon_read_byte = sheepshaver_read_byte;
261     mon_write_byte = sheepshaver_write_byte;
262     #endif
263    
264     return true;
265     }
266    
267    
268     /*
269     * Deinitialize everything
270     */
271    
272     void ExitAll(void)
273     {
274     #if ENABLE_MON
275     // Deinitialize mon
276     mon_exit();
277     #endif
278    
279     // Save NVRAM
280     XPRAMExit();
281    
282     // Exit clipboard
283     ClipExit();
284    
285     // Exit Time Manager
286     TimerExit();
287    
288     // Exit serial
289     SerialExit();
290    
291     // Exit network
292     EtherExit();
293    
294     // Exit audio
295     AudioExit();
296    
297     // Exit ADB
298     ADBExit();
299    
300     // Exit video
301     VideoExit();
302    
303     // Exit external file system
304     ExtFSExit();
305    
306     // Exit drivers
307     SCSIExit();
308     CDROMExit();
309     DiskExit();
310     SonyExit();
311    
312     // Delete thunks
313     ThunksExit();
314     }
315    
316    
317     /*
318     * Patch things after system startup (gets called by disk driver accRun routine)
319     */
320    
321     void PatchAfterStartup(void)
322     {
323     ExecuteNative(NATIVE_VIDEO_INSTALL_ACCEL);
324     InstallExtFS();
325     }