335 |
|
uint32 SheepMem::page_size; // Size of a native page |
336 |
|
uintptr SheepMem::zero_page = 0; // Address of ro page filled in with zeros |
337 |
|
uintptr SheepMem::base = 0x60000000; // Address of SheepShaver data |
338 |
< |
uintptr SheepMem::top = 0; // Top of SheepShaver data (stack like storage) |
338 |
> |
uintptr SheepMem::proc; // Bottom address of SheepShave procedures |
339 |
> |
uintptr SheepMem::data; // Top of SheepShaver data (stack like storage) |
340 |
|
|
341 |
|
|
342 |
|
// Prototypes |
343 |
+ |
static bool kernel_data_init(void); |
344 |
+ |
static void kernel_data_exit(void); |
345 |
|
static void Quit(void); |
346 |
|
static void *emul_func(void *arg); |
347 |
|
static void *nvram_func(void *arg); |
426 |
|
|
427 |
|
|
428 |
|
/* |
429 |
+ |
* Memory management helpers |
430 |
+ |
*/ |
431 |
+ |
|
432 |
+ |
static inline int vm_mac_acquire(uint32 addr, uint32 size) |
433 |
+ |
{ |
434 |
+ |
return vm_acquire_fixed(Mac2HostAddr(addr), size); |
435 |
+ |
} |
436 |
+ |
|
437 |
+ |
static inline int vm_mac_release(uint32 addr, uint32 size) |
438 |
+ |
{ |
439 |
+ |
return vm_release(Mac2HostAddr(addr), size); |
440 |
+ |
} |
441 |
+ |
|
442 |
+ |
|
443 |
+ |
/* |
444 |
|
* Main program |
445 |
|
*/ |
446 |
|
|
787 |
|
|
788 |
|
#ifndef PAGEZERO_HACK |
789 |
|
// Create Low Memory area (0x0000..0x3000) |
790 |
< |
if (vm_acquire_fixed((char *)NATMEM_OFFSET, 0x3000) < 0) { |
790 |
> |
if (vm_mac_acquire(0, 0x3000) < 0) { |
791 |
|
sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno)); |
792 |
|
ErrorAlert(str); |
793 |
|
goto quit; |
796 |
|
#endif |
797 |
|
|
798 |
|
// Create areas for Kernel Data |
799 |
< |
kernel_area = shmget(IPC_PRIVATE, KERNEL_AREA_SIZE, 0600); |
782 |
< |
if (kernel_area == -1) { |
783 |
< |
sprintf(str, GetString(STR_KD_SHMGET_ERR), strerror(errno)); |
784 |
< |
ErrorAlert(str); |
785 |
< |
goto quit; |
786 |
< |
} |
787 |
< |
if (shmat(kernel_area, (void *)(KERNEL_DATA_BASE + NATMEM_OFFSET), 0) < 0) { |
788 |
< |
sprintf(str, GetString(STR_KD_SHMAT_ERR), strerror(errno)); |
789 |
< |
ErrorAlert(str); |
790 |
< |
goto quit; |
791 |
< |
} |
792 |
< |
if (shmat(kernel_area, (void *)(KERNEL_DATA2_BASE + NATMEM_OFFSET), 0) < 0) { |
793 |
< |
sprintf(str, GetString(STR_KD2_SHMAT_ERR), strerror(errno)); |
794 |
< |
ErrorAlert(str); |
799 |
> |
if (!kernel_data_init()) |
800 |
|
goto quit; |
801 |
< |
} |
797 |
< |
kernel_data = (KernelData *)(KERNEL_DATA_BASE + NATMEM_OFFSET); |
801 |
> |
kernel_data = (KernelData *)Mac2HostAddr(KERNEL_DATA_BASE); |
802 |
|
emulator_data = &kernel_data->ed; |
803 |
|
KernelDataAddr = KERNEL_DATA_BASE; |
804 |
|
D(bug("Kernel Data at %p (%08x)\n", kernel_data, KERNEL_DATA_BASE)); |
805 |
|
D(bug("Emulator Data at %p (%08x)\n", emulator_data, KERNEL_DATA_BASE + offsetof(KernelData, ed))); |
806 |
|
|
807 |
|
// Create area for DR Cache |
808 |
< |
if (vm_acquire_fixed((void *)(DR_EMULATOR_BASE + NATMEM_OFFSET), DR_EMULATOR_SIZE) < 0) { |
808 |
> |
if (vm_mac_acquire(DR_EMULATOR_BASE, DR_EMULATOR_SIZE) < 0) { |
809 |
|
sprintf(str, GetString(STR_DR_EMULATOR_MMAP_ERR), strerror(errno)); |
810 |
|
ErrorAlert(str); |
811 |
|
goto quit; |
812 |
|
} |
813 |
|
dr_emulator_area_mapped = true; |
814 |
< |
if (vm_acquire_fixed((void *)(DR_CACHE_BASE + NATMEM_OFFSET), DR_CACHE_SIZE) < 0) { |
814 |
> |
if (vm_mac_acquire(DR_CACHE_BASE, DR_CACHE_SIZE) < 0) { |
815 |
|
sprintf(str, GetString(STR_DR_CACHE_MMAP_ERR), strerror(errno)); |
816 |
|
ErrorAlert(str); |
817 |
|
goto quit; |
835 |
|
} |
836 |
|
|
837 |
|
// Create area for Mac ROM |
838 |
< |
ROMBaseHost = (uint8 *)(ROM_BASE + NATMEM_OFFSET); |
835 |
< |
if (vm_acquire_fixed(ROMBaseHost, ROM_AREA_SIZE) < 0) { |
838 |
> |
if (vm_mac_acquire(ROM_BASE, ROM_AREA_SIZE) < 0) { |
839 |
|
sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno)); |
840 |
|
ErrorAlert(str); |
841 |
|
goto quit; |
842 |
|
} |
843 |
+ |
ROMBaseHost = Mac2HostAddr(ROM_BASE); |
844 |
|
#if !EMULATED_PPC |
845 |
|
if (vm_protect(ROMBaseHost, ROM_AREA_SIZE, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) { |
846 |
|
sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno)); |
858 |
|
RAMSize = 8*1024*1024; |
859 |
|
} |
860 |
|
|
861 |
< |
RAMBaseHost = (uint8 *)(RAM_BASE + NATMEM_OFFSET); |
858 |
< |
if (vm_acquire_fixed(RAMBaseHost, RAMSize) < 0) { |
861 |
> |
if (vm_mac_acquire(RAM_BASE, RAMSize) < 0) { |
862 |
|
sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno)); |
863 |
|
ErrorAlert(str); |
864 |
|
goto quit; |
865 |
|
} |
866 |
+ |
RAMBaseHost = Mac2HostAddr(RAM_BASE); |
867 |
|
#if !EMULATED_PPC |
868 |
|
if (vm_protect(RAMBaseHost, RAMSize, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) { |
869 |
|
sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno)); |
1212 |
|
|
1213 |
|
// Delete RAM area |
1214 |
|
if (ram_area_mapped) |
1215 |
< |
vm_release(RAMBaseHost, RAMSize); |
1215 |
> |
vm_mac_release(RAM_BASE, RAMSize); |
1216 |
|
|
1217 |
|
// Delete ROM area |
1218 |
|
if (rom_area_mapped) |
1219 |
< |
vm_release(ROMBaseHost, ROM_AREA_SIZE); |
1219 |
> |
vm_mac_release(ROM_BASE, ROM_AREA_SIZE); |
1220 |
|
|
1221 |
|
// Delete DR cache areas |
1222 |
|
if (dr_emulator_area_mapped) |
1223 |
< |
vm_release((void *)(DR_EMULATOR_BASE + NATMEM_OFFSET), DR_EMULATOR_SIZE); |
1223 |
> |
vm_mac_release(DR_EMULATOR_BASE, DR_EMULATOR_SIZE); |
1224 |
|
if (dr_cache_area_mapped) |
1225 |
< |
vm_release((void *)(DR_CACHE_BASE + NATMEM_OFFSET), DR_CACHE_SIZE); |
1225 |
> |
vm_mac_release(DR_CACHE_BASE, DR_CACHE_SIZE); |
1226 |
|
|
1227 |
|
// Delete Kernel Data area |
1228 |
< |
if (kernel_area >= 0) { |
1225 |
< |
shmdt((void *)(KERNEL_DATA_BASE + NATMEM_OFFSET)); |
1226 |
< |
shmdt((void *)(KERNEL_DATA2_BASE + NATMEM_OFFSET)); |
1227 |
< |
shmctl(kernel_area, IPC_RMID, NULL); |
1228 |
< |
} |
1228 |
> |
kernel_data_exit(); |
1229 |
|
|
1230 |
|
// Delete Low Memory area |
1231 |
|
if (lm_area_mapped) |
1232 |
< |
vm_release((void *)NATMEM_OFFSET, 0x3000); |
1232 |
> |
vm_mac_release(0, 0x3000); |
1233 |
|
|
1234 |
|
// Close /dev/zero |
1235 |
|
if (zero_fd > 0) |
1257 |
|
|
1258 |
|
|
1259 |
|
/* |
1260 |
+ |
* Initialize Kernel Data segments |
1261 |
+ |
*/ |
1262 |
+ |
|
1263 |
+ |
#if defined(__CYGWIN__) |
1264 |
+ |
#define WIN32_LEAN_AND_MEAN |
1265 |
+ |
#include <windows.h> |
1266 |
+ |
|
1267 |
+ |
static HANDLE kernel_handle; // Shared memory handle for Kernel Data |
1268 |
+ |
static DWORD allocation_granule; // Minimum size of allocateable are (64K) |
1269 |
+ |
static DWORD kernel_area_size; // Size of Kernel Data area |
1270 |
+ |
#endif |
1271 |
+ |
|
1272 |
+ |
static bool kernel_data_init(void) |
1273 |
+ |
{ |
1274 |
+ |
#ifdef _WIN32 |
1275 |
+ |
SYSTEM_INFO si; |
1276 |
+ |
GetSystemInfo(&si); |
1277 |
+ |
allocation_granule = si.dwAllocationGranularity; |
1278 |
+ |
kernel_area_size = (KERNEL_AREA_SIZE + allocation_granule - 1) & -allocation_granule; |
1279 |
+ |
|
1280 |
+ |
char rcs[10]; |
1281 |
+ |
char str[256]; |
1282 |
+ |
LPVOID kernel_addr; |
1283 |
+ |
kernel_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, kernel_area_size, NULL); |
1284 |
+ |
if (kernel_handle == NULL) { |
1285 |
+ |
sprintf(rcs, "%d", GetLastError()); |
1286 |
+ |
sprintf(str, GetString(STR_KD_SHMGET_ERR), rcs); |
1287 |
+ |
ErrorAlert(str); |
1288 |
+ |
return false; |
1289 |
+ |
} |
1290 |
+ |
kernel_addr = (LPVOID)Mac2HostAddr(KERNEL_DATA_BASE & -allocation_granule); |
1291 |
+ |
if (MapViewOfFileEx(kernel_handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, kernel_area_size, kernel_addr) != kernel_addr) { |
1292 |
+ |
sprintf(rcs, "%d", GetLastError()); |
1293 |
+ |
sprintf(str, GetString(STR_KD_SHMAT_ERR), rcs); |
1294 |
+ |
ErrorAlert(str); |
1295 |
+ |
return false; |
1296 |
+ |
} |
1297 |
+ |
kernel_addr = (LPVOID)Mac2HostAddr(KERNEL_DATA2_BASE & -allocation_granule); |
1298 |
+ |
if (MapViewOfFileEx(kernel_handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, kernel_area_size, kernel_addr) != kernel_addr) { |
1299 |
+ |
sprintf(rcs, "%d", GetLastError()); |
1300 |
+ |
sprintf(str, GetString(STR_KD2_SHMAT_ERR), rcs); |
1301 |
+ |
ErrorAlert(str); |
1302 |
+ |
return false; |
1303 |
+ |
} |
1304 |
+ |
#else |
1305 |
+ |
kernel_area = shmget(IPC_PRIVATE, KERNEL_AREA_SIZE, 0600); |
1306 |
+ |
if (kernel_area == -1) { |
1307 |
+ |
sprintf(str, GetString(STR_KD_SHMGET_ERR), strerror(errno)); |
1308 |
+ |
ErrorAlert(str); |
1309 |
+ |
return false; |
1310 |
+ |
} |
1311 |
+ |
if (shmat(kernel_area, Mac2HostAddr(KERNEL_DATA_BASE), 0) < 0) { |
1312 |
+ |
sprintf(str, GetString(STR_KD_SHMAT_ERR), strerror(errno)); |
1313 |
+ |
ErrorAlert(str); |
1314 |
+ |
return false; |
1315 |
+ |
} |
1316 |
+ |
if (shmat(kernel_area, Mac2HostAddr(KERNEL_DATA2_BASE), 0) < 0) { |
1317 |
+ |
sprintf(str, GetString(STR_KD2_SHMAT_ERR), strerror(errno)); |
1318 |
+ |
ErrorAlert(str); |
1319 |
+ |
return false; |
1320 |
+ |
} |
1321 |
+ |
#endif |
1322 |
+ |
return true; |
1323 |
+ |
} |
1324 |
+ |
|
1325 |
+ |
|
1326 |
+ |
/* |
1327 |
+ |
* Deallocate Kernel Data segments |
1328 |
+ |
*/ |
1329 |
+ |
|
1330 |
+ |
static void kernel_data_exit(void) |
1331 |
+ |
{ |
1332 |
+ |
#ifdef _WIN32 |
1333 |
+ |
if (kernel_handle) { |
1334 |
+ |
UnmapViewOfFile(Mac2HostAddr(KERNEL_DATA_BASE & -allocation_granule)); |
1335 |
+ |
UnmapViewOfFile(Mac2HostAddr(KERNEL_DATA2_BASE & -allocation_granule)); |
1336 |
+ |
CloseHandle(kernel_handle); |
1337 |
+ |
} |
1338 |
+ |
#else |
1339 |
+ |
if (kernel_area >= 0) { |
1340 |
+ |
shmdt(Mac2HostAddr(KERNEL_DATA_BASE)); |
1341 |
+ |
shmdt(Mac2HostAddr(KERNEL_DATA2_BASE)); |
1342 |
+ |
shmctl(kernel_area, IPC_RMID, NULL); |
1343 |
+ |
} |
1344 |
+ |
#endif |
1345 |
+ |
} |
1346 |
+ |
|
1347 |
+ |
|
1348 |
+ |
/* |
1349 |
|
* Jump into Mac ROM, start 680x0 emulator |
1350 |
|
*/ |
1351 |
|
|
1650 |
|
pthread_mutexattr_init(&attr); |
1651 |
|
// Initialize the mutex for priority inheritance -- |
1652 |
|
// required for accurate timing. |
1653 |
< |
#ifdef HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL |
1653 |
> |
#if defined(HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL) && !defined(__CYGWIN__) |
1654 |
|
pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT); |
1655 |
|
#endif |
1656 |
|
#if defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE) && defined(PTHREAD_MUTEX_NORMAL) |
2300 |
|
page_size = getpagesize(); |
2301 |
|
|
2302 |
|
// Allocate SheepShaver globals |
2303 |
< |
if (vm_acquire_fixed((char *)(base + NATMEM_OFFSET), size) < 0) |
2303 |
> |
proc = base; |
2304 |
> |
if (vm_mac_acquire(base, size) < 0) |
2305 |
|
return false; |
2306 |
|
|
2307 |
< |
// Allocate page with all bits set to 0 |
2308 |
< |
zero_page = base + size; |
2309 |
< |
uint8 *zero_page_host = (uint8 *)zero_page + NATMEM_OFFSET; |
2310 |
< |
if (vm_acquire_fixed(zero_page_host, page_size) < 0) |
2311 |
< |
return false; |
2222 |
< |
memset(zero_page_host, 0, page_size); |
2223 |
< |
if (vm_protect(zero_page_host, page_size, VM_PAGE_READ) < 0) |
2307 |
> |
// Allocate page with all bits set to 0, right in the middle |
2308 |
> |
// This is also used to catch undesired overlaps between proc and data areas |
2309 |
> |
zero_page = proc + (size / 2); |
2310 |
> |
Mac_memset(zero_page, 0, page_size); |
2311 |
> |
if (vm_protect(Mac2HostAddr(zero_page), page_size, VM_PAGE_READ) < 0) |
2312 |
|
return false; |
2313 |
|
|
2314 |
|
#if EMULATED_PPC |
2315 |
|
// Allocate alternate stack for PowerPC interrupt routine |
2316 |
< |
sig_stack = zero_page + page_size; |
2317 |
< |
if (vm_acquire_fixed((char *)(sig_stack + NATMEM_OFFSET), SIG_STACK_SIZE) < 0) |
2316 |
> |
sig_stack = base + size; |
2317 |
> |
if (vm_mac_acquire(sig_stack, SIG_STACK_SIZE) < 0) |
2318 |
|
return false; |
2319 |
|
#endif |
2320 |
|
|
2321 |
< |
top = base + size; |
2321 |
> |
data = base + size; |
2322 |
|
return true; |
2323 |
|
} |
2324 |
|
|
2325 |
|
void SheepMem::Exit(void) |
2326 |
|
{ |
2327 |
< |
if (top) { |
2327 |
> |
if (data) { |
2328 |
|
// Delete SheepShaver globals |
2329 |
< |
vm_release((void *)(base + NATMEM_OFFSET), size); |
2242 |
< |
|
2243 |
< |
// Delete zero page |
2244 |
< |
vm_release((void *)(zero_page + NATMEM_OFFSET), page_size); |
2329 |
> |
vm_mac_release(base, size); |
2330 |
|
|
2331 |
|
#if EMULATED_PPC |
2332 |
|
// Delete alternate stack for PowerPC interrupt routine |
2333 |
< |
vm_release((void *)(sig_stack + NATMEM_OFFSET), SIG_STACK_SIZE); |
2333 |
> |
vm_mac_release(sig_stack, SIG_STACK_SIZE); |
2334 |
|
#endif |
2335 |
|
} |
2336 |
|
} |