Enable 33-bit memory addressing on 64-bit JIT capable platforms (e.g. x86-64).

This is useful to get rid of address offset sign extensions. It uses POSIX
shared memory to create aliased regions, fallback to usual sign-extension
way if shm_open et al. don't work (e.g. no /dev/shm mounted)
This commit is contained in:
gbeauche 2004-11-08 21:07:07 +00:00
parent 0ba075050c
commit e3c5f1769d
5 changed files with 218 additions and 10 deletions

View File

@ -126,6 +126,7 @@ fi
dnl Checks for libraries.
AC_CHECK_LIB(posix4, sem_init)
AC_CHECK_LIB(rt, timer_create)
AC_CHECK_LIB(rt, shm_open)
dnl Do we need SDL?
WANT_SDL=no
@ -702,6 +703,56 @@ AC_CACHE_CHECK([whether we can map Low Memory area 0x0000-0x2000],
]
)
dnl Check if we have POSIX shared memory support
AC_CACHE_CHECK([whether POSIX shared memory is working],
ac_cv_have_posix_shm, [
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_RUN([
#define HAVE_POSIX_SHM
#include "vm_alloc.cpp"
int main(void) { /* returns 0 if we have working POSIX shm */
if (vm_init() < 0) exit(2);
char *m1 = (char *)vm_acquire(32768, VM_MAP_DEFAULT | VM_MAP_33BIT);
if (m1 == VM_MAP_FAILED) exit(3);
vm_exit(); exit(0);
}
], ac_cv_have_posix_shm=yes, ac_cv_have_posix_shm=no,
dnl When cross-compiling, do not assume anything.
ac_cv_have_posix_shm="guessing no"
)
AC_LANG_RESTORE
]
)
AC_TRANSLATE_DEFINE(HAVE_POSIX_SHM, "$ac_cv_have_posix_shm",
[Define if your system supports POSIX shared memory.])
dnl Check if we have working 33-bit memory addressing
AC_CACHE_CHECK([whether 33-bit memory addressing is working],
ac_cv_have_33bit_addressing, [
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_RUN([
#define USE_33BIT_ADDRESSING 1
#include "vm_alloc.cpp"
int main(void) { /* returns 0 if we have working 33-bit addressing */
if (sizeof(void *) < 8) exit(1);
if (vm_init() < 0) exit(2);
char *m1 = (char *)vm_acquire(32768, VM_MAP_DEFAULT | VM_MAP_33BIT);
if (m1 == VM_MAP_FAILED) exit(3);
char *m2 = m1 + (1L << 32);
m1[0] = 0x12; if (m2[0] != 0x12) exit(4);
m2[0] = 0x34; if (m1[0] != 0x34) exit(5);
vm_exit(); exit(0);
}
], ac_cv_have_33bit_addressing=yes, ac_cv_have_33bit_addressing=no,
dnl When cross-compiling, do not assume anything.
ac_cv_have_33bit_addressing="guessing no"
)
AC_LANG_RESTORE
]
)
dnl Check signal handlers need to be reinstalled
AC_CACHE_CHECK([whether signal handlers need to be reinstalled],
ac_cv_signal_need_reinstall, [
@ -1028,6 +1079,7 @@ elif [[ "x$HAVE_GCC30" = "xyes" -a "x$HAVE_X86_64" = "xyes" ]]; then
DEFINES="$DEFINES -DX86_64_ASSEMBLY -DOPTIMIZED_FLAGS"
JITSRCS="cpuemu1_nf.cpp cpuemu2_nf.cpp cpuemu3_nf.cpp cpuemu4_nf.cpp cpuemu5_nf.cpp cpuemu6_nf.cpp cpuemu7_nf.cpp cpuemu8_nf.cpp $JITSRCS"
CAN_JIT=yes
WANT_33BIT_ADDRESSING=yes
fi
elif [[ "x$HAVE_GCC27" = "xyes" -a "x$HAVE_SPARC" = "xyes" -a "x$HAVE_GAS" = "xyes" ]]; then
dnl SPARC CPU
@ -1084,6 +1136,13 @@ else
JITSRCS=""
fi
dnl Use 33-bit memory addressing?
if [[ "$ac_cv_have_33bit_addressing:$WANT_33BIT_ADDRESSING" = "yes:yes" ]]; then
use_33bit_addressing=yes
fi
AC_TRANSLATE_DEFINE(USE_33BIT_ADDRESSING, "$use_33bit_addressing",
[Define to use 33-bit memory addressing on 64-bit JIT capable systems.])
dnl Utility macro used by next two tests.
dnl AC_EXAMINE_OBJECT(C source code,
dnl commands examining object file,

View File

@ -123,6 +123,7 @@ int CPUType;
bool CPUIs68060;
int FPUType;
bool TwentyFourBitAddressing;
bool ThirtyThreeBitAddressing = false;
// Global variables
@ -218,6 +219,21 @@ char *strdup(const char *s)
}
/*
* Map memory that can be accessed from the Mac side
*/
void *vm_acquire_mac(size_t size)
{
void *m = vm_acquire(size, VM_MAP_DEFAULT | VM_MAP_33BIT);
if (m == NULL) {
ThirtyThreeBitAddressing = false;
m = vm_acquire(size);
}
return m;
}
/*
* SIGSEGV handler
*/
@ -482,8 +498,12 @@ int main(int argc, char **argv)
else
#endif
{
RAMBaseHost = (uint8 *)vm_acquire(RAMSize);
ROMBaseHost = (uint8 *)vm_acquire(0x100000);
#ifdef USE_33BIT_ADDRESSING
// Speculatively enables 33-bit addressing
ThirtyThreeBitAddressing = true;
#endif
RAMBaseHost = (uint8 *)vm_acquire_mac(RAMSize);
ROMBaseHost = (uint8 *)vm_acquire_mac(0x100000);
if (RAMBaseHost == VM_MAP_FAILED || ROMBaseHost == VM_MAP_FAILED) {
ErrorAlert(STR_NO_MEM_ERR);
QuitEmulator();

View File

@ -192,6 +192,7 @@ static void *redraw_func(void *arg);
// From main_unix.cpp
extern char *x_display_name;
extern Display *x_display;
extern void *vm_acquire_mac(size_t size);
// From sys_unix.cpp
extern void SysMountFirstFloppy(void);
@ -730,7 +731,7 @@ driver_window::driver_window(X11_monitor_desc &m)
// Allocate memory for frame buffer (SIZE is extended to page-boundary)
the_host_buffer = the_buffer_copy;
the_buffer_size = page_extend((aligned_height + 2) * img->bytes_per_line);
the_buffer = (uint8 *)vm_acquire(the_buffer_size);
the_buffer = (uint8 *)vm_acquire_mac(the_buffer_size);
the_buffer_copy = (uint8 *)malloc(the_buffer_size);
D(bug("the_buffer = %p, the_buffer_copy = %p, the_host_buffer = %p\n", the_buffer, the_buffer_copy, the_host_buffer));
#else
@ -1126,7 +1127,7 @@ driver_fbdev::driver_fbdev(X11_monitor_desc &m) : driver_dga(m)
the_host_buffer = the_buffer;
the_buffer_size = page_extend((height + 2) * bytes_per_row);
the_buffer_copy = (uint8 *)malloc(the_buffer_size);
the_buffer = (uint8 *)vm_acquire(the_buffer_size);
the_buffer = (uint8 *)vm_acquire_mac(the_buffer_size);
}
#else
use_vosf = false;
@ -1266,7 +1267,7 @@ driver_xf86dga::driver_xf86dga(X11_monitor_desc &m)
the_host_buffer = the_buffer;
the_buffer_size = page_extend((height + 2) * bytes_per_row);
the_buffer_copy = (uint8 *)malloc(the_buffer_size);
the_buffer = (uint8 *)vm_acquire(the_buffer_size);
the_buffer = (uint8 *)vm_acquire_mac(the_buffer_size);
}
#else
use_vosf = false;

View File

@ -23,9 +23,15 @@
#include "config.h"
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
// TODO: Win32 VMs ?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "vm_alloc.h"
#ifdef HAVE_MACH_VM
@ -45,6 +51,12 @@
#ifndef MAP_32BIT
#define MAP_32BIT 0
#endif
#ifndef MAP_ANON
#define MAP_ANON 0
#endif
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS 0
#endif
#define MAP_EXTRA_FLAGS (MAP_32BIT)
@ -66,15 +78,83 @@ static char * next_address = (char *)MAP_BASE;
#define map_flags (MAP_ANONYMOUS | MAP_EXTRA_FLAGS)
#define zero_fd -1
#else
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#define map_flags (MAP_EXTRA_FLAGS)
static int zero_fd = -1;
#endif
#endif
#endif
/* Utility functions for POSIX SHM handling. */
#ifdef USE_33BIT_ADDRESSING
struct shm_range_t {
const char *file;
void *base;
unsigned int size;
shm_range_t *next;
};
static shm_range_t *shm_ranges = NULL;
static bool add_shm_range(const char *file, void *base, unsigned int size)
{
shm_range_t *r = (shm_range_t *)malloc(sizeof(shm_range_t));
if (r) {
r->file = file;
r->base = base;
r->size = size;
r->next = shm_ranges ? shm_ranges : NULL;
shm_ranges = r;
return true;
}
return false;
}
static shm_range_t *find_shm_range(void *base, unsigned int size)
{
for (shm_range_t *r = shm_ranges; r != NULL; r = r->next)
if (r->base == base && r->size == size)
return r;
return NULL;
}
static bool remove_shm_range(shm_range_t *r)
{
if (r) {
for (shm_range_t *p = shm_ranges; p != NULL; p = p->next) {
if (p->next == r) {
p->next = r->next;
free(r);
return true;
}
}
}
return false;
}
static bool remove_shm_range(void *base, unsigned int size)
{
remove_shm_range(find_shm_range(base, size));
}
#endif
/* Build a POSIX SHM memory segment file descriptor name. */
#ifdef USE_33BIT_ADDRESSING
static const char *build_shm_filename(void)
{
static int id = 0;
static char filename[PATH_MAX];
int ret = snprintf(filename, sizeof(filename), "/BasiliskII-%d-shm-%d", getpid(), id);
if (ret == -1 || ret >= sizeof(filename))
return NULL;
id++;
return filename;
}
#endif
/* Translate generic VM map flags to host values. */
#ifdef HAVE_MMAP_VM
@ -136,9 +216,29 @@ void * vm_acquire(size_t size, int options)
return VM_MAP_FAILED;
#else
#ifdef HAVE_MMAP_VM
const int extra_map_flags = translate_map_flags(options);
int fd = zero_fd;
int the_map_flags = translate_map_flags(options) | map_flags;
if ((addr = mmap((caddr_t)next_address, size, VM_PAGE_DEFAULT, extra_map_flags | map_flags, zero_fd, 0)) == (void *)MAP_FAILED)
#ifdef USE_33BIT_ADDRESSING
const char *shm_file = NULL;
if (sizeof(void *) == 8 && (options & VM_MAP_33BIT)) {
the_map_flags &= ~(MAP_PRIVATE | MAP_ANON | MAP_ANONYMOUS);
the_map_flags |= MAP_SHARED;
if ((shm_file = build_shm_filename()) == NULL)
return VM_MAP_FAILED;
if ((fd = shm_open(shm_file, O_RDWR | O_CREAT | O_EXCL, 0644)) < 0)
return VM_MAP_FAILED;
if (ftruncate(fd, size) < 0)
return VM_MAP_FAILED;
the_map_flags |= MAP_SHARED;
}
#endif
if ((addr = mmap((caddr_t)next_address, size, VM_PAGE_DEFAULT, the_map_flags, fd, 0)) == (void *)MAP_FAILED)
return VM_MAP_FAILED;
// Sanity checks for 64-bit platforms
@ -150,6 +250,18 @@ void * vm_acquire(size_t size, int options)
// Since I don't know the standard behavior of mmap(), zero-fill here
if (memset(addr, 0, size) != addr)
return VM_MAP_FAILED;
// Remap to 33-bit space
#ifdef USE_33BIT_ADDRESSING
if (sizeof(void *) == 8 && (options & VM_MAP_33BIT)) {
if (!add_shm_range(strdup(shm_file), addr, size))
return VM_MAP_FAILED;
if (mmap((char *)addr + (1L << 32), size, VM_PAGE_DEFAULT, the_map_flags | MAP_FIXED, fd, 0) == (void *)MAP_FAILED)
return VM_MAP_FAILED;
close(fd);
}
#endif
#else
if ((addr = calloc(size, 1)) == 0)
return VM_MAP_FAILED;
@ -220,6 +332,21 @@ int vm_release(void * addr, size_t size)
#ifdef HAVE_MMAP_VM
if (munmap((caddr_t)addr, size) != 0)
return -1;
#ifdef USE_33BIT_ADDRESSING
shm_range_t *r = find_shm_range(addr, size);
if (r) {
if (munmap((char *)r->base + (1L << 32), size) != 0)
return -1;
if (shm_unlink(r->file) < 0)
return -1;
free((char *)r->file);
if (!remove_shm_range(r))
return -1;
}
#endif
#else
free(addr);
#endif

View File

@ -52,6 +52,7 @@ extern "C" {
#define VM_MAP_PRIVATE 0x02
#define VM_MAP_FIXED 0x04
#define VM_MAP_32BIT 0x08
#define VM_MAP_33BIT 0x10
/* Default mapping options. */
#define VM_MAP_DEFAULT (VM_MAP_PRIVATE)