Use vm_acquire/vm_acquire_fixed/vm_release API. Prepare use of SIGSEGV

handlers and instruction skippers. Fix test prior to including posix_sem.cpp.
This commit is contained in:
gbeauche 2003-05-13 16:59:57 +00:00
parent 61e40b3e55
commit 94ec8c82ca
4 changed files with 335 additions and 9 deletions

View File

@ -57,6 +57,8 @@ links:
Unix/audio_oss_esd.cpp Unix/extfs_unix.cpp Unix/serial_unix.cpp \
Unix/sshpty.h Unix/sshpty.c Unix/strlcpy.h Unix/strlcpy.c \
Unix/sys_unix.cpp Unix/timer_unix.cpp Unix/xpram_unix.cpp \
Unix/sigsegv.h Unix/sigsegv.cpp Unix/vm_alloc.h Unix/vm_alloc.cpp \
Unix/posix_sem.cpp \
Unix/Linux/scsi_linux.cpp Unix/Linux/NetDriver'; \
PREFIX="`pwd`/"; case $(B2_TOPDIR) in /*) PREFIX="";; esac; \
for i in $$list; do \

View File

@ -32,6 +32,7 @@ SRCS = main_unix.cpp ../prefs.cpp ../prefs_items.cpp prefs_unix.cpp sys_unix.cpp
Linux/scsi_linux.cpp ../video.cpp video_x.cpp ../audio.cpp audio_oss_esd.cpp ../ether.cpp \
Linux/ether_linux.cpp ../serial.cpp serial_unix.cpp ../extfs.cpp extfs_unix.cpp \
about_window_unix.cpp ../user_strings.cpp user_strings_unix.cpp \
vm_alloc.cpp sigsegv.cpp \
sshpty.c strlcpy.c $(SYSSRCS)
APP = SheepShaver

View File

@ -82,7 +82,7 @@ fi
dnl If POSIX.4 semaphores are not available, we emulate them with pthread mutexes.
SEMSRC=
AC_CHECK_FUNCS(sem_init, , [
if [[ "x$HAVE_PTHREADS" = "xyes" ]]; then
if test "x$HAVE_PTHREADS" = "xyes"; then
SEMSRC=posix_sem.cpp
fi
])
@ -140,7 +140,7 @@ fi
dnl Checks for header files.
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(unistd.h fcntl.h sys/time.h)
AC_CHECK_HEADERS(unistd.h fcntl.h sys/time.h sys/mman.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_BIGENDIAN
@ -150,16 +150,22 @@ AC_CHECK_SIZEOF(short, 2)
AC_CHECK_SIZEOF(int, 4)
AC_CHECK_SIZEOF(long, 4)
AC_CHECK_SIZEOF(long long, 8)
AC_CHECK_SIZEOF(float, 4)
AC_CHECK_SIZEOF(double, 8)
AC_CHECK_SIZEOF(void *, 4)
AC_TYPE_OFF_T
AC_CHECK_TYPE(loff_t, off_t)
AC_TYPE_SIZE_T
AC_TYPE_SIGNAL
AC_HEADER_TIME
AC_STRUCT_TM
dnl Checks for library functions.
AC_CHECK_FUNCS(strdup cfmakeraw)
AC_CHECK_FUNCS(nanosleep clock_gettime timer_create)
AC_CHECK_FUNCS(sigaction signal)
AC_CHECK_FUNCS(mmap mprotect munmap)
AC_CHECK_FUNCS(vm_allocate vm_deallocate vm_protect)
dnl Select system-dependant sources.
if [[ "x$HAVE_PPC" = "xyes" ]]; then
@ -169,6 +175,308 @@ else
fi
SYSSRCS="$SYSSRCS $SEMSRCS $UISRCS $MONSRCS"
dnl Define a macro that translates a yesno-variable into a C macro definition
dnl to be put into the config.h file
dnl $1 -- the macro to define
dnl $2 -- the value to translate
dnl $3 -- template name
AC_DEFUN(AC_TRANSLATE_DEFINE, [
if [[ "x$2" = "xyes" -o "x$2" = "xguessing yes" ]]; then
AC_DEFINE($1, 1, $3)
fi
])
dnl Various checks if the system supports vm_allocate() and the like functions.
have_mach_vm=no
if [[ "x$ac_cv_func_vm_allocate" = "xyes" -a "x$ac_cv_func_vm_deallocate" = "xyes" -a \
"x$ac_cv_func_vm_protect" = "xyes" ]]; then
have_mach_vm=yes
fi
AC_TRANSLATE_DEFINE(HAVE_MACH_VM, "$have_mach_vm",
[Define if your system has a working vm_allocate()-based memory allocator.])
dnl Check that vm_allocate(), vm_protect() work
if [[ "x$have_mach_vm" = "xyes" ]]; then
AC_CACHE_CHECK([whether vm_protect works],
ac_cv_vm_protect_works, [
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
ac_cv_vm_protect_works=yes
dnl First the tests that should segfault
for test_def in NONE_READ NONE_WRITE READ_WRITE; do
AC_TRY_RUN([
#define CONFIGURE_TEST_VM_MAP
#define TEST_VM_PROT_$test_def
#include "vm_alloc.cpp"
], ac_cv_vm_protect_works=no, rm -f core,
dnl When cross-compiling, do not assume anything
ac_cv_vm_protect_works="guessing no"
)
done
AC_TRY_RUN([
#define CONFIGURE_TEST_VM_MAP
#define TEST_VM_PROT_RDWR_WRITE
#include "vm_alloc.cpp"
], , ac_cv_vm_protect_works=no,
dnl When cross-compiling, do not assume anything
ac_cv_vm_protect_works="guessing no"
)
AC_LANG_RESTORE
]
)
dnl Remove support for vm_allocate() if vm_protect() does not work
if [[ "x$have_mach_vm" = "xyes" ]]; then
case $ac_cv_vm_protect_works in
*yes) have_mach_vm=yes;;
*no) have_mach_vm=no;;
esac
fi
AC_TRANSLATE_DEFINE(HAVE_MACH_VM, "$have_mach_vm",
[Define if your system has a working vm_allocate()-based memory allocator.])
fi dnl HAVE_MACH_VM
dnl Various checks if the system supports mmap() and the like functions.
dnl ... and Mach memory allocators are not supported
have_mmap_vm=no
if [[ "x$ac_cv_func_mmap" = "xyes" -a "x$ac_cv_func_munmap" = "xyes" -a \
"x$ac_cv_func_mprotect" = "xyes" ]]; then
if [[ "x$have_mach_vm" = "xno" ]]; then
have_mmap_vm=yes
fi
fi
AC_TRANSLATE_DEFINE(HAVE_MMAP_VM, "$have_mmap_vm",
[Define if your system has a working mmap()-based memory allocator.])
dnl Check that mmap() and associated functions work.
if [[ "x$have_mmap_vm" = "xyes" ]]; then
dnl Check if we have a working anonymous mmap()
AC_CACHE_CHECK([whether mmap supports MAP_ANON],
ac_cv_mmap_anon, [
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_RUN([
#define HAVE_MMAP_ANON
#define CONFIGURE_TEST_VM_MAP
#define TEST_VM_MMAP_ANON
#include "vm_alloc.cpp"
], ac_cv_mmap_anon=yes, ac_cv_mmap_anon=no,
dnl When cross-compiling, do not assume anything.
ac_cv_mmap_anon="guessing no"
)
AC_LANG_RESTORE
]
)
AC_TRANSLATE_DEFINE(HAVE_MMAP_ANON, "$ac_cv_mmap_anon",
[Define if <sys/mman.h> defines MAP_ANON and mmap()'ing with MAP_ANON works.])
AC_CACHE_CHECK([whether mmap supports MAP_ANONYMOUS],
ac_cv_mmap_anonymous, [
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_RUN([
#define HAVE_MMAP_ANONYMOUS
#define CONFIGURE_TEST_VM_MAP
#define TEST_VM_MMAP_ANON
#include "vm_alloc.cpp"
], ac_cv_mmap_anonymous=yes, ac_cv_mmap_anonymous=no,
dnl When cross-compiling, do not assume anything.
ac_cv_mmap_anonymous="guessing no"
)
AC_LANG_RESTORE
]
)
AC_TRANSLATE_DEFINE(HAVE_MMAP_ANONYMOUS, "$ac_cv_mmap_anonymous",
[Define if <sys/mman.h> defines MAP_ANONYMOUS and mmap()'ing with MAP_ANONYMOUS works.])
AC_CACHE_CHECK([whether mprotect works],
ac_cv_mprotect_works, [
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
ac_cv_mprotect_works=yes
dnl First the tests that should segfault
for test_def in NONE_READ NONE_WRITE READ_WRITE; do
AC_TRY_RUN([
#define CONFIGURE_TEST_VM_MAP
#define TEST_VM_PROT_$test_def
#include "vm_alloc.cpp"
], ac_cv_mprotect_works=no, rm -f core,
dnl When cross-compiling, do not assume anything
ac_cv_mprotect_works="guessing no"
)
done
AC_TRY_RUN([
#define CONFIGURE_TEST_VM_MAP
#define TEST_VM_PROT_RDWR_WRITE
#include "vm_alloc.cpp"
], , ac_cv_mprotect_works=no,
dnl When cross-compiling, do not assume anything
ac_cv_mprotect_works="guessing no"
)
AC_LANG_RESTORE
]
)
dnl Remove support for mmap() if mprotect() does not work
if [[ "x$have_mmap_vm" = "xyes" ]]; then
case $ac_cv_mprotect_works in
*yes) have_mmap_vm=yes;;
*no) have_mmap_vm=no;;
esac
fi
AC_TRANSLATE_DEFINE(HAVE_MMAP_VM, $have_mmap_vm,
[Define if your system has a working mmap()-based memory allocator.])
fi dnl HAVE_MMAP_VM
dnl Check if we can mmap 0x2000 bytes from 0x0000
AC_CACHE_CHECK([whether we can map Low Memory area 0x0000-0x2000],
ac_cv_can_map_lm, [
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_RUN([
#include "vm_alloc.cpp"
int main(void) { /* returns 0 if we could map the lowmem globals */
volatile char * lm = 0;
if (vm_init() < 0) exit(1);
if (vm_acquire_fixed(0, 0x2000) < 0) exit(1);
lm[0] = 'z';
if (vm_release((char *)lm, 0x2000) < 0) exit(1);
vm_exit(); exit(0);
}
], ac_cv_can_map_lm=yes, ac_cv_can_map_lm=no,
dnl When cross-compiling, do not assume anything.
ac_cv_can_map_lm="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, [
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_RUN([
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <signal.h>
static int handled_signal = 0;
RETSIGTYPE sigusr1_handler(int) { handled_signal++; }
int main(void) { /* returns 0 if signals need not to be reinstalled */
signal(SIGUSR1, sigusr1_handler); raise(SIGUSR1); raise(SIGUSR1);
exit(handled_signal == 2);
}
], ac_cv_signal_need_reinstall=yes, ac_cv_signal_need_reinstall=no,
dnl When cross-compiling, do not assume anything.
ac_cv_signal_need_reinstall="guessing yes"
)
AC_LANG_RESTORE
]
)
AC_TRANSLATE_DEFINE(SIGNAL_NEED_REINSTALL, "$ac_cv_signal_need_reinstall",
[Define if your system requires signals to be reinstalled.])
dnl Check if sigaction handlers need to be reinstalled
AC_CACHE_CHECK([whether sigaction handlers need to be reinstalled],
ac_cv_sigaction_need_reinstall, [
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_RUN([
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <signal.h>
static int handled_signal = 0;
RETSIGTYPE sigusr1_handler(int) { handled_signal++; }
typedef RETSIGTYPE (*signal_handler)(int);
static signal_handler mysignal(int sig, signal_handler handler) {
struct sigaction old_sa;
struct sigaction new_sa;
new_sa.sa_handler = handler;
return ((sigaction(sig,&new_sa,&old_sa) < 0) ? SIG_IGN : old_sa.sa_handler);
}
int main(void) { /* returns 0 if signals need not to be reinstalled */
mysignal(SIGUSR1, sigusr1_handler); raise(SIGUSR1); raise(SIGUSR1);
exit(handled_signal == 2);
}
], ac_cv_sigaction_need_reinstall=yes, ac_cv_sigaction_need_reinstall=no,
dnl When cross-compiling, do not assume anything.
ac_cv_sigaction_need_reinstall="guessing yes"
)
AC_LANG_RESTORE
]
)
AC_TRANSLATE_DEFINE(SIGACTION_NEED_REINSTALL, "$ac_cv_sigaction_need_reinstall",
[Define if your system requires sigactions to be reinstalled.])
dnl Check if extended signals are supported.
AC_CACHE_CHECK([whether your system supports extended signal handlers],
ac_cv_have_extended_signals, [
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_RUN([
#define HAVE_SIGINFO_T 1
#define CONFIGURE_TEST_SIGSEGV_RECOVERY
#include "vm_alloc.cpp"
#include "sigsegv.cpp"
], ac_cv_have_extended_signals=yes, ac_cv_have_extended_signals=no,
dnl When cross-compiling, do not assume anything.
ac_cv_have_extended_signals=no
)
AC_LANG_RESTORE
]
)
AC_TRANSLATE_DEFINE(HAVE_SIGINFO_T, "$ac_cv_have_extended_signals",
[Define if your system support extended signals.])
dnl Otherwise, check for subterfuges.
if [[ "x$ac_cv_have_extended_signals" = "xno" ]]; then
AC_CACHE_CHECK([whether we then have a subterfuge for your system],
ac_cv_have_sigcontext_hack, [
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_RUN([
#define HAVE_SIGCONTEXT_SUBTERFUGE 1
#define CONFIGURE_TEST_SIGSEGV_RECOVERY
#include "vm_alloc.cpp"
#include "sigsegv.cpp"
], ac_cv_have_sigcontext_hack=yes, ac_cv_have_sigcontext_hack=no,
dnl When cross-compiling, do not assume anything.
ac_cv_have_sigcontext_hack=no
)
AC_LANG_RESTORE
])
AC_TRANSLATE_DEFINE(HAVE_SIGCONTEXT_SUBTERFUGE, "$ac_cv_have_sigcontext_hack",
[Define if we know a hack to replace siginfo_t->si_addr member.])
fi
dnl Check if we can ignore the fault (instruction skipping in SIGSEGV handler)
AC_CACHE_CHECK([whether we can skip instruction in SIGSEGV handler],
ac_cv_have_skip_instruction, [
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_RUN([
#define HAVE_SIGSEGV_SKIP_INSTRUCTION 1
#define CONFIGURE_TEST_SIGSEGV_RECOVERY
#include "vm_alloc.cpp"
#include "sigsegv.cpp"
], ac_cv_have_skip_instruction=yes, ac_cv_have_skip_instruction=no,
dnl When cross-compiling, do not assume anything.
ac_cv_have_skip_instruction=no
)
AC_LANG_RESTORE
]
)
AC_TRANSLATE_DEFINE(HAVE_SIGSEGV_SKIP_INSTRUCTION, "$ac_cv_have_skip_instruction",
[Define if we can ignore the fault (instruction skipping in SIGSEGV handler).])
dnl Generate Makefile.
AC_SUBST(SYSSRCS)
AC_OUTPUT(Makefile)

View File

@ -107,6 +107,7 @@
#include "macos_util.h"
#include "rom_patches.h"
#include "user_strings.h"
#include "vm_alloc.h"
#define DEBUG 0
#include "debug.h"
@ -420,7 +421,7 @@ int main(int argc, char **argv)
}
// Create Low Memory area (0x0000..0x3000)
if (mmap((char *)0x0000, 0x3000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) {
if (vm_acquire_fixed((char *)0, 0x3000) < 0) {
sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
ErrorAlert(str);
goto quit;
@ -450,11 +451,18 @@ int main(int argc, char **argv)
D(bug("Kernel Data at %p, Emulator Data at %p\n", kernel_data, emulator_data));
// Create area for Mac ROM
if (mmap((char *)ROM_BASE, ROM_AREA_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) {
if (vm_acquire_fixed((char *)ROM_BASE, ROM_AREA_SIZE) < 0) {
sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno));
ErrorAlert(str);
goto quit;
}
#if !EMULATED_PPC
if (vm_protect((char *)ROM_BASE, 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 %08x\n", ROM_BASE));
@ -465,12 +473,19 @@ int main(int argc, char **argv)
RAMSize = 8*1024*1024;
}
mmap_RAMBase = mmap((void *)0x20000000, RAMSize, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0);
if (mmap_RAMBase == (void *)-1) {
mmap_RAMBase = (void *)0x20000000;
if (vm_acquire_fixed(mmap_RAMBase, RAMSize) < 0) {
sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
ErrorAlert(str);
goto quit;
}
#if !EMULATED_PPC
if (vm_protect(mmap_RAMBase, RAMSize, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) {
sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
ErrorAlert(str);
goto quit;
}
#endif
RAMBase = (uint32)mmap_RAMBase;
ram_area_mapped = true;
D(bug("RAM area at %08x\n", RAMBase));
@ -567,7 +582,7 @@ int main(int argc, char **argv)
#if !EMULATED_PPC
MakeExecutable(0, (void *)ROM_BASE, ROM_AREA_SIZE);
#endif
mprotect((char *)ROM_BASE, ROM_AREA_SIZE, PROT_EXEC | PROT_READ);
vm_protect((char *)ROM_BASE, ROM_AREA_SIZE, VM_PAGE_READ | VM_PAGE_EXECUTE);
// Initialize Kernel Data
memset(kernel_data, 0, sizeof(KernelData));
@ -779,11 +794,11 @@ static void Quit(void)
// Delete RAM area
if (ram_area_mapped)
munmap(mmap_RAMBase, RAMSize);
vm_release(mmap_RAMBase, RAMSize);
// Delete ROM area
if (rom_area_mapped)
munmap((char *)ROM_BASE, ROM_AREA_SIZE);
vm_release((char *)ROM_BASE, ROM_AREA_SIZE);
// Delete Kernel Data area
if (kernel_area >= 0) {