flycast/core/linux/common.cpp

208 lines
4.9 KiB
C++
Raw Normal View History

2015-05-16 08:23:31 +00:00
#include "types.h"
2013-12-19 17:10:14 +00:00
2021-07-12 18:14:21 +00:00
#if defined(__unix__) || defined(__APPLE__) || defined(__SWITCH__)
2020-04-26 08:03:57 +00:00
#if defined(__APPLE__)
#define _XOPEN_SOURCE 1
#define __USE_GNU 1
#include <TargetConditionals.h>
#endif
2019-09-07 12:37:39 +00:00
#include <csignal>
2013-12-19 17:10:14 +00:00
#include <sys/time.h>
#if defined(__linux__) && !defined(__ANDROID__)
2015-07-08 08:15:37 +00:00
#include <sys/personality.h>
#include <dlfcn.h>
2015-07-08 08:15:37 +00:00
#endif
2013-12-19 17:10:14 +00:00
#include <unistd.h>
#include "hw/sh4/dyna/blockmanager.h"
#include "oslib/host_context.h"
2013-12-19 17:10:14 +00:00
#include "hw/sh4/dyna/ngen.h"
2021-07-12 18:14:21 +00:00
#ifdef __SWITCH__
#include <ucontext.h>
extern "C" char __start__;
2021-07-12 18:14:21 +00:00
#define siginfo_t switch_siginfo_t
#endif // __SWITCH__
#if !defined(TARGET_NO_EXCEPTIONS)
2013-12-19 17:10:14 +00:00
bool VramLockedWrite(u8* address);
bool BM_LockedWrite(u8* address);
void context_from_segfault(host_context_t* hctx, void* segfault_ctx);
void context_to_segfault(host_context_t* hctx, void* segfault_ctx);
2020-04-26 08:03:57 +00:00
#if defined(__APPLE__)
2015-05-16 08:04:30 +00:00
void sigill_handler(int sn, siginfo_t * si, void *segfault_ctx) {
host_context_t ctx;
2015-05-16 08:04:30 +00:00
context_from_segfault(&ctx, segfault_ctx);
unat pc = (unat)ctx.pc;
bool dyna_cde = (pc>(unat)CodeCache) && (pc<(unat)(CodeCache + CODE_SIZE + TEMP_CODE_SIZE));
ERROR_LOG(COMMON, "SIGILL @ %lx -> %p was not in vram, dynacode:%d", pc, si->si_addr, dyna_cde);
//printf("PC is used here %08X\n", pc);
kill(getpid(), SIGABRT);
}
#endif
void fault_handler (int sn, siginfo_t * si, void *segfault_ctx)
2013-12-19 17:10:14 +00:00
{
// code protection in RAM
2019-06-19 20:55:47 +00:00
if (bm_RamWriteAccess(si->si_addr))
return;
// texture protection in VRAM
if (VramLockedWrite((u8*)si->si_addr))
return;
// FPCB jump table protection
if (BM_LockedWrite((u8*)si->si_addr))
2013-12-19 17:10:14 +00:00
return;
#if FEAT_SHREC == DYNAREC_JIT
// fast mem access rewriting
host_context_t ctx;
context_from_segfault(&ctx, segfault_ctx);
bool dyna_cde = ((unat)CC_RX2RW(ctx.pc) >= (unat)CodeCache) && ((unat)CC_RX2RW(ctx.pc) < (unat)(CodeCache + CODE_SIZE + TEMP_CODE_SIZE));
if (dyna_cde && ngen_Rewrite(ctx, si->si_addr))
2013-12-19 17:10:14 +00:00
{
context_to_segfault(&ctx, segfault_ctx);
return;
2013-12-19 17:10:14 +00:00
}
#endif
ERROR_LOG(COMMON, "SIGSEGV @ %p -> %p was not in vram, dynacode:%d", (void *)ctx.pc, si->si_addr, dyna_cde);
2021-07-12 18:14:21 +00:00
#ifdef __SWITCH__
MemoryInfo meminfo;
u32 pageinfo;
svcQueryMemory(&meminfo, &pageinfo, (u64)&__start__);
ERROR_LOG(COMMON, ".text base: %p", meminfo.addr);
2021-07-12 18:14:21 +00:00
#endif // __SWITCH__
die("segfault");
signal(SIGSEGV, SIG_DFL);
2013-12-19 17:10:14 +00:00
}
#undef HOST_CTX_READY
2013-12-19 17:10:14 +00:00
void os_InstallFaultHandler()
2013-12-19 17:10:14 +00:00
{
2021-07-12 18:14:21 +00:00
#ifndef __SWITCH__
struct sigaction act, segv_oact;
memset(&act, 0, sizeof(act));
act.sa_sigaction = fault_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &act, &segv_oact);
#endif
2020-04-26 08:03:57 +00:00
#if defined(__APPLE__)
//this is broken on osx/ios/mach in general
sigaction(SIGBUS, &act, &segv_oact);
act.sa_sigaction = sigill_handler;
sigaction(SIGILL, &act, &segv_oact);
#endif
2013-12-19 17:10:14 +00:00
}
void os_UninstallFaultHandler()
{
#ifndef __SWITCH__
struct sigaction act{};
act.sa_handler = SIG_DFL;
sigemptyset(&act.sa_mask);
sigaction(SIGSEGV, &act, nullptr);
#endif
#if defined(__APPLE__)
sigaction(SIGBUS, &act, nullptr);
sigaction(SIGILL, &act, nullptr);
#endif
}
#else // !defined(TARGET_NO_EXCEPTIONS)
void os_InstallFaultHandler()
{
}
void os_UninstallFaultHandler()
{
}
#endif // !defined(TARGET_NO_EXCEPTIONS)
2013-12-19 17:10:14 +00:00
double os_GetSeconds()
{
timeval a;
gettimeofday (&a,0);
static u64 tvs_base=a.tv_sec;
return a.tv_sec-tvs_base+a.tv_usec/1000000.0;
}
#ifdef TARGET_IPHONE
void os_DebugBreak() {
__asm__("trap");
}
2021-03-13 10:37:13 +00:00
#elif !defined(__unix__)
2014-09-30 09:00:46 +00:00
void os_DebugBreak()
{
__builtin_trap();
}
#endif
2013-12-19 17:10:14 +00:00
void enable_runfast()
{
#if HOST_CPU==CPU_ARM && !defined(ARMCC)
static const unsigned int x = 0x04086060;
static const unsigned int y = 0x03000000;
int r;
asm volatile (
"fmrx %0, fpscr \n\t" //r0 = FPSCR
"and %0, %0, %1 \n\t" //r0 = r0 & 0x04086060
"orr %0, %0, %2 \n\t" //r0 = r0 | 0x03000000
"fmxr fpscr, %0 \n\t" //FPSCR = r0
: "=r"(r)
: "r"(x), "r"(y)
);
DEBUG_LOG(BOOT, "ARM VFP-Run Fast (NFP) enabled !");
2013-12-19 17:10:14 +00:00
#endif
}
2015-07-07 14:20:14 +00:00
void linux_fix_personality() {
#if defined(__linux__) && !defined(__ANDROID__)
DEBUG_LOG(BOOT, "Personality: %08X", personality(0xFFFFFFFF));
personality(~READ_IMPLIES_EXEC & personality(0xFFFFFFFF));
DEBUG_LOG(BOOT, "Updated personality: %08X", personality(0xFFFFFFFF));
#endif
2015-07-07 14:20:14 +00:00
}
void linux_rpi2_init() {
#if !defined(TARGET_BSD) && !defined(__ANDROID__) && defined(TARGET_VIDEOCORE)
2015-07-07 14:20:14 +00:00
void* handle;
void (*rpi_bcm_init)(void);
handle = dlopen("libbcm_host.so", RTLD_LAZY);
if (handle) {
DEBUG_LOG(BOOT, "found libbcm_host");
2015-07-07 14:20:14 +00:00
*(void**) (&rpi_bcm_init) = dlsym(handle, "bcm_host_init");
if (rpi_bcm_init) {
DEBUG_LOG(BOOT, "rpi2: bcm_init");
2015-07-07 14:20:14 +00:00
rpi_bcm_init();
}
}
#endif
2015-07-07 14:20:14 +00:00
}
2013-12-19 17:10:14 +00:00
void common_linux_setup()
{
2015-07-07 14:20:14 +00:00
linux_fix_personality();
linux_rpi2_init();
2013-12-19 17:10:14 +00:00
enable_runfast();
os_InstallFaultHandler();
2013-12-19 17:10:14 +00:00
signal(SIGINT, exit);
DEBUG_LOG(BOOT, "Linux paging: %ld %08X %08X", sysconf(_SC_PAGESIZE), PAGE_SIZE, PAGE_MASK);
2013-12-19 17:10:14 +00:00
verify(PAGE_MASK==(sysconf(_SC_PAGESIZE)-1));
}
#endif