2 * FreeBSD-os.c. Maybe could be just BSD-os.c
3 * From osf1-os.c,v 1.1 94/03/27 15:30:51 hallgren Exp $
5 * OS-dependent routines. This file (along with os.h) exports an
6 * OS-independent interface to the operating system VM facilities.
7 * Suprisingly, this interface looks a lot like the Mach interface
8 * (but simpler in some places). For some operating systems, a subset
9 * of these functions will have to be emulated.
11 * This is the OSF1 version. By Sean Hallgren.
12 * Much hacked by Paul Werkowski
13 * GENCGC support by Douglas Crosher, 1996, 1997.
15 * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/FreeBSD-os.c,v 1.38 2011/09/01 05:18:26 rtoy Exp $
21 #include <machine/npx.h>
25 #include "interrupt.h"
27 #include "internals.h"
39 vm_size_t os_vm_page_size;
42 os_init0(const char *argv[], const char *envp[])
46 os_init(const char *argv[], const char *envp[])
48 os_vm_page_size = getpagesize();
52 os_sigcontext_reg(ucontext_t *scp, int index)
58 rv = &scp->uc_mcontext.mc_eax;
61 rv = &scp->uc_mcontext.mc_ecx;
64 rv = &scp->uc_mcontext.mc_edx;
67 rv = &scp->uc_mcontext.mc_ebx;
70 rv = &scp->uc_mcontext.mc_esp;
73 rv = &scp->uc_mcontext.mc_ebp;
76 rv = &scp->uc_mcontext.mc_esi;
79 rv = &scp->uc_mcontext.mc_edi;
85 /* Pre-cast to (void *), to avoid the compiler warning:
86 * dereferencing type-punned pointer will break strict-aliasing rules
88 return (unsigned long *) (void *) rv;
92 os_sigcontext_pc(ucontext_t *scp)
94 return (unsigned long *) (void *) &scp->uc_mcontext.mc_eip;
98 os_sigcontext_fpu_reg(ucontext_t *scp, int index)
100 union savefpu *sv = (union savefpu *) scp->uc_mcontext.mc_fpstate;
101 int fpformat = scp->uc_mcontext.mc_fpformat;
102 unsigned char *reg = NULL;
107 reg = sv->sv_xmm.sv_fp[index].fp_acc.fp_bytes;
109 reg = sv->sv_xmm.sv_xmm[index - 8].xmm_bytes;
113 reg = sv->sv_87.sv_ac[index].fp_bytes;
115 case _MC_FPFMT_NODEV:
123 os_sigcontext_fpu_modes(ucontext_t *scp)
127 union savefpu *sv = (union savefpu *) scp->uc_mcontext.mc_fpstate;
128 int fpformat = scp->uc_mcontext.mc_fpformat;
129 struct env87 *env_87 = &sv->sv_87.sv_env;
130 struct envxmm *env_xmm = &sv->sv_xmm.sv_env;
134 if (fpformat == _MC_FPFMT_XMM) {
137 } else if (fpformat == _MC_FPFMT_387) {
138 cw = env_87->en_cw & 0xffff;
139 sw = env_87->en_sw & 0xffff;
140 } else { /* _MC_FPFMT_NODEV */
145 modes = ((cw & 0x3f) << 7) | (sw & 0x3f);
148 if (fpu_mode == SSE2) {
149 u_int32_t mxcsr = env_xmm->en_mxcsr;
151 DPRINTF(0, (stderr, "SSE2 modes = %08x\n", (int)mxcsr));
155 modes ^= (0x3f << 7);
160 os_validate(os_vm_address_t addr, os_vm_size_t len)
162 int flags = MAP_PRIVATE | MAP_ANON;
167 addr = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0);
169 if (addr == (os_vm_address_t) - 1) {
178 os_invalidate(os_vm_address_t addr, os_vm_size_t len)
180 if (munmap(addr, len) == -1)
185 os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
187 addr = mmap(addr, len, OS_VM_PROT_ALL,
188 MAP_PRIVATE | MAP_FILE | MAP_FIXED, fd, (off_t) offset);
190 if (addr == (os_vm_address_t) - 1)
197 os_flush_icache(os_vm_address_t address, os_vm_size_t length)
202 os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot)
204 if (mprotect(address, length, prot) == -1)
211 in_range_p(os_vm_address_t a, lispobj sbeg, size_t slen)
213 char *beg = (char *) sbeg;
214 char *end = (char *) sbeg + slen;
215 char *adr = (char *) a;
217 return adr >= beg && adr < end;
221 valid_addr(os_vm_address_t addr)
223 os_vm_address_t newaddr;
225 newaddr = os_trunc_to_page(addr);
227 if (in_range_p(addr, READ_ONLY_SPACE_START, read_only_space_size)
228 || in_range_p(addr, STATIC_SPACE_START, static_space_size)
229 || in_range_p(addr, DYNAMIC_0_SPACE_START, dynamic_space_size)
231 || in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size)
233 || in_range_p(addr, CONTROL_STACK_START, control_stack_size)
234 || in_range_p(addr, BINDING_STACK_START, binding_stack_size))
241 protection_violation_handler(HANDLER_ARGS)
244 if (os_control_stack_overflow(code->si_addr, context))
249 if (code->si_code == PROTECTION_VIOLATION_CODE) {
250 if (gc_write_barrier(code->si_addr)) {
256 interrupt_handle_now(signal, code, context);
260 * Restore the exception flags cleared by the kernel. These bits must
261 * be set for Lisp to determine which exception caused the signal. At
262 * present, there is no way to distinguish underflow exceptions from
263 * denormalized operand exceptions. An underflow exception is assumed
264 * if the subcode is FPE_FLTUND.
267 sigfpe_handler(HANDLER_ARGS)
269 ucontext_t *ucontext = (ucontext_t *) context;
270 union savefpu *sv = (union savefpu *) ucontext->uc_mcontext.mc_fpstate;
271 int fpformat = ucontext->uc_mcontext.mc_fpformat;
272 unsigned char trap = 0;
274 switch (code->si_code) {
275 case FPE_FLTDIV: /* ZE */
278 case FPE_FLTOVF: /* OE */
281 case FPE_FLTUND: /* DE or UE */
284 case FPE_FLTRES: /* PE */
287 case FPE_FLTINV: /* IE */
294 sv->sv_xmm.sv_env.en_sw |= trap;
297 sv->sv_87.sv_env.en_sw |= trap;
300 interrupt_handle_now(signal, code, context);
304 os_install_interrupt_handlers(void)
306 interrupt_install_low_level_handler(PROTECTION_VIOLATION_SIGNAL,
307 protection_violation_handler);
308 interrupt_install_low_level_handler(SIGFPE, sigfpe_handler);
312 os_dlsym(const char *sym_name, lispobj lib_list)
314 static void *program_handle;
317 program_handle = dlopen((void *) 0, RTLD_LAZY | RTLD_GLOBAL);
319 if (lib_list != NIL) {
320 lispobj lib_list_head;
322 for (lib_list_head = lib_list;
323 lib_list_head != NIL; lib_list_head = CONS(lib_list_head)->cdr) {
324 struct cons *lib_cons = CONS(CONS(lib_list_head)->car);
325 struct sap *dlhandle = (struct sap *)PTR(lib_cons->car);
326 void *sym_addr = dlsym((void *)dlhandle->pointer, sym_name);
332 return dlsym(program_handle, sym_name);
336 restore_fpu(ucontext_t *scp)
338 union savefpu *sv = (union savefpu *) scp->uc_mcontext.mc_fpstate;
339 int fpformat = scp->uc_mcontext.mc_fpformat;
340 struct env87 *env_87 = &sv->sv_87.sv_env;
341 struct envxmm *env_xmm = &sv->sv_xmm.sv_env;
344 if (fpformat == _MC_FPFMT_XMM) {
346 } else if (fpformat == _MC_FPFMT_387) {
347 cw = env_87->en_cw & 0xffff;
348 } else { /* _MC_FPFMT_NODEV */
351 DPRINTF(0, (stderr, "restore_fpu: cw = %08x\n", (int)cw));
352 __asm__ __volatile__ ("fldcw %0"::"m"(*&cw));
355 if (fpu_mode == SSE2) {
356 u_int32_t mxcsr = env_xmm->en_mxcsr;
358 DPRINTF(0, (stderr, "restore_fpu: mxcsr (raw) = %04x\n", mxcsr));
359 __asm__ __volatile__ ("ldmxcsr %0"::"m"(*&mxcsr));