Newer
Older
/*
* FreeBSD-os.c. Maybe could be just BSD-os.c
* From osf1-os.c,v 1.1 94/03/27 15:30:51 hallgren Exp $
*
* OS-dependent routines. This file (along with os.h) exports an
* OS-independent interface to the operating system VM facilities.
* Suprisingly, this interface looks a lot like the Mach interface
* (but simpler in some places). For some operating systems, a subset
* of these functions will have to be emulated.
*
* This is the OSF1 version. By Sean Hallgren.
* Much hacked by Paul Werkowski
* GENCGC support by Douglas Crosher, 1996, 1997.
*
#include "os.h"
#include <machine/npx.h>
#include <errno.h>
#include "arch.h"
#include "globals.h"
#include "interrupt.h"
#include "lispregs.h"
#include "internals.h"
#include <stdio.h>
#include <unistd.h>
#if defined GENCGC
#include "gencgc.h"
#endif
vm_size_t os_vm_page_size;
void
os_init0(const char *argv[], const char *envp[])
{}
os_vm_page_size = getpagesize();
unsigned long *
os_sigcontext_reg(ucontext_t *scp, int index)
{
__register_t *rv;
switch (index) {
/* Pre-cast to (void *), to avoid the compiler warning:
* dereferencing type-punned pointer will break strict-aliasing rules
return (unsigned long *) (void *) rv;
}
unsigned long *
os_sigcontext_pc(ucontext_t *scp)
{
return (unsigned long *) (void *) &scp->uc_mcontext.mc_eip;
}
unsigned char *
os_sigcontext_fpu_reg(ucontext_t *scp, int index)
{
union savefpu *sv = (union savefpu *) scp->uc_mcontext.mc_fpstate;
int fpformat = scp->uc_mcontext.mc_fpformat;
unsigned char *reg = NULL;
switch (fpformat) {
if (index < 8) {
reg = sv->sv_xmm.sv_fp[index].fp_acc.fp_bytes;
} else {
reg = sv->sv_xmm.sv_xmm[index - 8].xmm_bytes;
}
break;
case _MC_FPFMT_387:
reg = sv->sv_87.sv_ac[index].fp_bytes;
break;
case _MC_FPFMT_NODEV:
reg = NULL;
break;
return reg;
}
unsigned int
os_sigcontext_fpu_modes(ucontext_t *scp)
{
unsigned int modes;
union savefpu *sv = (union savefpu *) scp->uc_mcontext.mc_fpstate;
int fpformat = scp->uc_mcontext.mc_fpformat;
struct env87 *env_87 = &sv->sv_87.sv_env;
struct envxmm *env_xmm = &sv->sv_xmm.sv_env;
u_int16_t cw;
u_int16_t sw;
if (fpformat == _MC_FPFMT_XMM) {
} else if (fpformat == _MC_FPFMT_387) {
cw = env_87->en_cw & 0xffff;
sw = env_87->en_sw & 0xffff;
} else { /* _MC_FPFMT_NODEV */
cw = 0;
sw = 0x3f;
}
modes = ((cw & 0x3f) << 7) | (sw & 0x3f);
#ifdef FEATURE_SSE2
u_int32_t mxcsr = env_xmm->en_mxcsr;
DPRINTF(0, (stderr, "SSE2 modes = %08x\n", (int)mxcsr));
return modes;
os_vm_address_t
os_validate(os_vm_address_t addr, os_vm_size_t len)
if (addr)
flags |= MAP_FIXED;
addr = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0);
if (addr == (os_vm_address_t) - 1) {
perror("mmap");
return NULL;
os_invalidate(os_vm_address_t addr, os_vm_size_t len)
if (munmap(addr, len) == -1)
perror("munmap");
os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
addr = mmap(addr, len, OS_VM_PROT_ALL,
MAP_PRIVATE | MAP_FILE | MAP_FIXED, fd, (off_t) offset);
if (addr == (os_vm_address_t) - 1)
perror("mmap");
os_flush_icache(os_vm_address_t address, os_vm_size_t length)
os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot)
if (mprotect(address, length, prot) == -1)
perror("mprotect");
in_range_p(os_vm_address_t a, lispobj sbeg, size_t slen)
char *beg = (char *) sbeg;
char *end = (char *) sbeg + slen;
char *adr = (char *) a;
return adr >= beg && adr < end;
boolean
valid_addr(os_vm_address_t addr)
if (in_range_p(addr, READ_ONLY_SPACE_START, read_only_space_size)
|| in_range_p(addr, STATIC_SPACE_START, static_space_size)
|| in_range_p(addr, DYNAMIC_0_SPACE_START, dynamic_space_size)
|| in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size)
|| in_range_p(addr, CONTROL_STACK_START, control_stack_size)
|| in_range_p(addr, BINDING_STACK_START, binding_stack_size))
return TRUE;
return FALSE;
protection_violation_handler(HANDLER_ARGS)
if (os_control_stack_overflow(code->si_addr, context))
if (code->si_code == PROTECTION_VIOLATION_CODE) {
if (gc_write_barrier(code->si_addr)) {
interrupt_handle_now(signal, code, context);
/*
* Restore the exception flags cleared by the kernel. These bits must
* be set for Lisp to determine which exception caused the signal. At
* present, there is no way to distinguish underflow exceptions from
* denormalized operand exceptions. An underflow exception is assumed
* if the subcode is FPE_FLTUND.
*/
static void
sigfpe_handler(HANDLER_ARGS)
ucontext_t *ucontext = (ucontext_t *) context;
union savefpu *sv = (union savefpu *) ucontext->uc_mcontext.mc_fpstate;
int fpformat = ucontext->uc_mcontext.mc_fpformat;
unsigned char trap = 0;
switch (code->si_code) {
case FPE_FLTDIV: /* ZE */
trap = 0x04;
break;
trap = 0x08;
break;
case FPE_FLTUND: /* DE or UE */
trap = 0x10;
break;
trap = 0x20;
break;
trap = 0x01;
break;
}
switch (fpformat) {
case _MC_FPFMT_XMM:
sv->sv_xmm.sv_env.en_sw |= trap;
break;
sv->sv_87.sv_env.en_sw |= trap;
break;
}
interrupt_handle_now(signal, code, context);
os_install_interrupt_handlers(void)
interrupt_install_low_level_handler(PROTECTION_VIOLATION_SIGNAL,
protection_violation_handler);
interrupt_install_low_level_handler(SIGFPE, sigfpe_handler);
os_dlsym(const char *sym_name, lispobj lib_list)
static void *program_handle;
if (!program_handle)
program_handle = dlopen((void *) 0, RTLD_LAZY | RTLD_GLOBAL);
if (lib_list != NIL) {
lispobj lib_list_head;
for (lib_list_head = lib_list;
lib_list_head != NIL; lib_list_head = CONS(lib_list_head)->cdr) {
struct cons *lib_cons = CONS(CONS(lib_list_head)->car);
struct sap *dlhandle = (struct sap *)PTR(lib_cons->car);
void *sym_addr = dlsym((void *)dlhandle->pointer, sym_name);
if (sym_addr)
return sym_addr;
return dlsym(program_handle, sym_name);
void
restore_fpu(ucontext_t *scp)
{
union savefpu *sv = (union savefpu *) scp->uc_mcontext.mc_fpstate;
int fpformat = scp->uc_mcontext.mc_fpformat;
struct env87 *env_87 = &sv->sv_87.sv_env;
struct envxmm *env_xmm = &sv->sv_xmm.sv_env;
u_int16_t cw;
if (fpformat == _MC_FPFMT_XMM) {
} else if (fpformat == _MC_FPFMT_387) {
} else { /* _MC_FPFMT_NODEV */
return;
}
DPRINTF(0, (stderr, "restore_fpu: cw = %08x\n", (int)cw));
__asm__ __volatile__ ("fldcw %0"::"m"(*&cw));
if (fpu_mode == SSE2) {
u_int32_t mxcsr = env_xmm->en_mxcsr;
DPRINTF(0, (stderr, "restore_fpu: mxcsr (raw) = %04x\n", mxcsr));
__asm__ __volatile__ ("ldmxcsr %0"::"m"(*&mxcsr));