/[cmucl]/src/lisp/FreeBSD-os.c
ViewVC logotype

Contents of /src/lisp/FreeBSD-os.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.25 - (show annotations)
Sun Dec 7 03:14:21 2008 UTC (5 years, 4 months ago) by agoncharov
Branch: MAIN
Changes since 1.24: +26 -11 lines
File MIME type: text/plain
Get rid of the annoying gcc warning: "dereferencing type-punned
pointer will break strict-aliasing rules".
1 /*
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 $
4 *
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.
10 *
11 * This is the OSF1 version. By Sean Hallgren.
12 * Much hacked by Paul Werkowski
13 * GENCGC support by Douglas Crosher, 1996, 1997.
14 *
15 * $Header: /tiger/var/lib/cvsroots/cmucl/src/lisp/FreeBSD-os.c,v 1.25 2008/12/07 03:14:21 agoncharov Exp $
16 *
17 */
18
19 #include "os.h"
20 #include <sys/file.h>
21 #include <machine/npx.h>
22 #include <errno.h>
23 #include "arch.h"
24 #include "globals.h"
25 #include "interrupt.h"
26 #include "lispregs.h"
27 #include "internals.h"
28
29 #include <signal.h>
30 #include <dlfcn.h>
31 #include "validate.h"
32 #include <stdio.h>
33 #include <unistd.h>
34
35 #if defined GENCGC
36 #include "gencgc.h"
37 #endif
38
39 vm_size_t os_vm_page_size;
40
41
42 void
43 os_init(void)
44 {
45 os_vm_page_size = getpagesize();
46 }
47
48 unsigned long *
49 os_sigcontext_reg(ucontext_t *scp, int index)
50 {
51 __register_t *rv;
52 switch (index) {
53 case 0:
54 rv = &scp->uc_mcontext.mc_eax;
55 break;
56 case 2:
57 rv = &scp->uc_mcontext.mc_ecx;
58 break;
59 case 4:
60 rv = &scp->uc_mcontext.mc_edx;
61 break;
62 case 6:
63 rv = &scp->uc_mcontext.mc_ebx;
64 break;
65 case 8:
66 rv = &scp->uc_mcontext.mc_esp;
67 break;
68 case 10:
69 rv = &scp->uc_mcontext.mc_ebp;
70 break;
71 case 12:
72 rv = &scp->uc_mcontext.mc_esi;
73 break;
74 case 14:
75 rv = &scp->uc_mcontext.mc_edi;
76 break;
77 default:
78 rv = NULL;
79 }
80
81 /* Pre-cast to (void *), to avoid the compiler warning:
82 * FreeBSD-os.c:72: warning: dereferencing type-punned pointer will break strict-aliasing rules
83 */
84 return (unsigned long *) (void *) rv;
85 }
86
87 unsigned long *
88 os_sigcontext_pc(ucontext_t *scp)
89 {
90 return (unsigned long *) (void *) &scp->uc_mcontext.mc_eip;
91 }
92
93 unsigned char *
94 os_sigcontext_fpu_reg(ucontext_t *scp, int index)
95 {
96 union savefpu *sv = (union savefpu *) scp->uc_mcontext.mc_fpstate;
97 int fpformat = scp->uc_mcontext.mc_fpformat;
98 unsigned char *reg = NULL;
99
100 switch (fpformat) {
101 case _MC_FPFMT_XMM:
102 reg = sv->sv_xmm.sv_fp[index].fp_acc.fp_bytes;
103 break;
104 case _MC_FPFMT_387:
105 reg = sv->sv_87.sv_ac[index].fp_bytes;
106 break;
107 case _MC_FPFMT_NODEV:
108 reg = NULL;
109 break;
110 }
111 return reg;
112 }
113
114 unsigned long
115 os_sigcontext_fpu_modes(ucontext_t *scp)
116 {
117 union savefpu *sv = (union savefpu *) scp->uc_mcontext.mc_fpstate;
118 unsigned long modes;
119 int fpformat = scp->uc_mcontext.mc_fpformat;
120 unsigned short cw, sw;
121
122 if (fpformat == _MC_FPFMT_XMM) {
123 cw = sv->sv_xmm.sv_env.en_cw;
124 sw = sv->sv_xmm.sv_env.en_sw;
125 } else if (fpformat == _MC_FPFMT_387) {
126 cw = sv->sv_87.sv_env.en_cw & 0xffff;
127 sw = sv->sv_87.sv_env.en_sw & 0xffff;
128 } else { /* _MC_FPFMT_NODEV */
129 cw = 0;
130 sw = 0x3f;
131 }
132 modes = (sw & 0xff) << 16 | cw;
133 modes ^= 0x3f;
134 return modes;
135 }
136
137 os_vm_address_t os_validate(os_vm_address_t addr, os_vm_size_t len)
138 {
139 int flags = MAP_PRIVATE | MAP_ANON;
140
141 if (addr)
142 flags |= MAP_FIXED;
143
144 addr = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0);
145
146 if (addr == (os_vm_address_t) - 1) {
147 perror("mmap");
148 return NULL;
149 }
150
151 return addr;
152 }
153
154 void
155 os_invalidate(os_vm_address_t addr, os_vm_size_t len)
156 {
157 if (munmap(addr, len) == -1)
158 perror("munmap");
159 }
160
161 os_vm_address_t
162 os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
163 {
164 addr = mmap(addr, len, OS_VM_PROT_ALL,
165 MAP_PRIVATE | MAP_FILE | MAP_FIXED, fd, (off_t) offset);
166
167 if (addr == (os_vm_address_t) - 1)
168 perror("mmap");
169
170 return addr;
171 }
172
173 void
174 os_flush_icache(os_vm_address_t address, os_vm_size_t length)
175 {
176 }
177
178 void
179 os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot)
180 {
181 if (mprotect(address, length, prot) == -1)
182 perror("mprotect");
183 }
184
185
186
187 static boolean
188 in_range_p(os_vm_address_t a, lispobj sbeg, size_t slen)
189 {
190 char *beg = (char *) sbeg;
191 char *end = (char *) sbeg + slen;
192 char *adr = (char *) a;
193
194 return adr >= beg && adr < end;
195 }
196
197 boolean valid_addr(os_vm_address_t addr)
198 {
199 os_vm_address_t newaddr;
200
201 newaddr = os_trunc_to_page(addr);
202
203 if (in_range_p(addr, READ_ONLY_SPACE_START, READ_ONLY_SPACE_SIZE)
204 || in_range_p(addr, STATIC_SPACE_START, STATIC_SPACE_SIZE)
205 || in_range_p(addr, DYNAMIC_0_SPACE_START, dynamic_space_size)
206 #ifndef GENCGC
207 || in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size)
208 #endif
209 || in_range_p(addr, CONTROL_STACK_START, CONTROL_STACK_SIZE)
210 || in_range_p(addr, BINDING_STACK_START, BINDING_STACK_SIZE))
211 return TRUE;
212 return FALSE;
213 }
214
215
216 static void
217 sigbus_handler(int signal, siginfo_t *info, ucontext_t *context)
218 {
219 #ifdef RED_ZONE_HIT
220 if (os_control_stack_overflow(info->si_addr, context))
221 return;
222 #endif
223
224 #if defined GENCGC
225 if (info->si_code == PROTECTION_VIOLATION_CODE) {
226 if (gc_write_barrier(info->si_addr)) {
227 return;
228 }
229 }
230 #endif /* GENCGC */
231
232 interrupt_handle_now(signal, info, context);
233 }
234
235 /*
236 * Restore the exception flags cleared by the kernel. These bits must
237 * be set for Lisp to determine which exception caused the signal. At
238 * present, there is no way to distinguish underflow exceptions from
239 * denormalized operand exceptions. An underflow exception is assumed
240 * if the subcode is FPE_FLTUND.
241 */
242 static void
243 sigfpe_handler(int signal, siginfo_t *info, ucontext_t *context)
244 {
245 union savefpu *sv = (union savefpu *) context->uc_mcontext.mc_fpstate;
246 int fpformat = context->uc_mcontext.mc_fpformat;
247 int code = info->si_code;
248 unsigned char trap = 0;
249
250 switch (code) {
251 case FPE_FLTDIV: /* ZE */
252 trap = 0x04;
253 break;
254 case FPE_FLTOVF: /* OE */
255 trap = 0x08;
256 break;
257 case FPE_FLTUND: /* DE or UE */
258 trap = 0x10;
259 break;
260 case FPE_FLTRES: /* PE */
261 trap = 0x20;
262 break;
263 case FPE_FLTINV: /* IE */
264 trap = 0x01;
265 break;
266 }
267 switch (fpformat) {
268 case _MC_FPFMT_XMM:
269 sv->sv_xmm.sv_env.en_sw |= trap;
270 break;
271 case _MC_FPFMT_387:
272 sv->sv_87.sv_env.en_sw |= trap;
273 break;
274 }
275 interrupt_handle_now(signal, info, context);
276 }
277
278 void
279 os_install_interrupt_handlers(void)
280 {
281 interrupt_install_low_level_handler
282 (PROTECTION_VIOLATION_SIGNAL, sigbus_handler);
283 interrupt_install_low_level_handler(SIGFPE, sigfpe_handler);
284 }
285
286 void *
287 os_dlsym(const char *sym_name, lispobj lib_list)
288 {
289 if (lib_list != NIL) {
290 lispobj lib_list_head;
291
292 for (lib_list_head = lib_list;
293 lib_list_head != NIL; lib_list_head = CONS(lib_list_head)->cdr) {
294 struct cons *lib_cons = CONS(CONS(lib_list_head)->car);
295 struct sap *dlhandle = (struct sap *) PTR(lib_cons->car);
296 void *sym_addr = dlsym((void *) dlhandle->pointer, sym_name);
297
298 if (sym_addr)
299 return sym_addr;
300 }
301 }
302
303 return dlsym(RTLD_DEFAULT, sym_name);
304 }
305
306 void
307 restore_fpu(ucontext_t *scp)
308 {
309 union savefpu *sv = (union savefpu *) scp->uc_mcontext.mc_fpstate;
310 int fpformat = scp->uc_mcontext.mc_fpformat;
311 unsigned short cw;
312
313 if (fpformat == _MC_FPFMT_XMM) {
314 cw = sv->sv_xmm.sv_env.en_cw;
315 } else if (fpformat == _MC_FPFMT_387) {
316 cw = sv->sv_87.sv_env.en_cw & 0xffff;
317 } else { /* _MC_FPFMT_NODEV */
318 return;
319 }
320 __asm__ __volatile__ ("fldcw %0" : : "m" (*&cw));
321 }

  ViewVC Help
Powered by ViewVC 1.1.5