Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/*
* NetBSD-os.c.
* From OpenBSD-os.c 1.1 2001/12/06 19:15:44 pmai Exp
* From FreeBSD-os.c 1.6 2000/10/24 13:32:30 dtc 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.
* Frobbed for OpenBSD by Pierre R. Mai, 2001.
* Frobbed for NetBSD by Pierre R. Mai, 2002.
*
* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/NetBSD-os.c,v 1.1 2002/01/28 20:19:39 pmai Exp $
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/file.h>
#include <errno.h>
#include "./signal.h"
#include "os.h"
#include "arch.h"
#include "globals.h"
#include "interrupt.h"
#include "lispregs.h"
#include "internals.h"
#include <sys/types.h>
#include <signal.h>
/* #include <sys/sysinfo.h> */
#include <sys/proc.h>
#include "validate.h"
size_t os_vm_page_size;
#define DPRINTF(t,a) {if (t) fprintf a;}
#if defined GENCGC
#include "gencgc.h"
#endif
void os_init(void)
{
os_vm_page_size = OS_VM_DEFAULT_PAGESIZE;
}
int sc_reg(struct sigcontext *c, int offset)
{
switch(offset)
{
case 0: return c->sc_eax;
case 2: return c->sc_ecx;
case 4: return c->sc_edx;
case 6: return c->sc_ebx;
case 8: return c->sc_esp;
case 10: return c->sc_ebp;
case 12: return c->sc_esi;
case 14: return c->sc_edi;
}
return 0;
}
void os_save_context(void)
{
/*
* Called from interrupt handlers so C stuff knows things set in Lisp.
*/
}
void os_set_context(void)
{
}
os_vm_address_t os_validate(os_vm_address_t addr, os_vm_size_t len)
{
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
/*
* NetBSD 1.5.2 seems to insist on each mmap being less than 128MB.
* So we mmap in 64MB steps. This is probably inefficient, but the
* missing CR2 reporting in signal handlers already ensures that
* NetBSD/x86 is not a suitable platform for CMU CL as it stands.
*/
if (addr)
flags |= MAP_FIXED;
else
flags |= MAP_VARIABLE;
DPRINTF(0, (stderr, "os_validate %x %d =>", addr, len));
if (addr)
{
os_vm_address_t curaddr=addr;
while (len>0)
{
os_vm_address_t resaddr;
int curlen=MIN(64*1024*1024,len);
resaddr = mmap(curaddr, curlen, OS_VM_PROT_ALL, flags, -1, 0);
if (resaddr == (os_vm_address_t) -1)
{
perror("mmap");
while (curaddr>addr)
{
curaddr-=64*1024*1024;
munmap(curaddr,64*1024*1024);
}
return NULL;
}
DPRINTF(0, (stderr, " %x", resaddr));
curaddr+=curlen;
len-=curlen;
}
DPRINTF(0, (stderr, "\n"));
}
else
{
addr = mmap(0, len, OS_VM_PROT_ALL, flags, -1, 0);
if (addr == (os_vm_address_t) -1)
{
perror("mmap");
return NULL;
}
DPRINTF(0, (stderr, " %x\n", addr));
}
return addr;
}
void os_invalidate(os_vm_address_t addr, os_vm_size_t len)
{
DPRINTF(0, (stderr, "os_invalidate %x %d\n", addr, len));
if (munmap(addr, len) == -1)
perror("munmap");
}
os_vm_address_t 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");
return addr;
}
void os_flush_icache(os_vm_address_t address, os_vm_size_t length)
{
}
void 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");
}
static boolean 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)
{
int ret;
os_vm_address_t newaddr;
newaddr = os_trunc_to_page(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;
}
static void sigsegv_handler(HANDLER_ARGS)
{
/*
* Since NetBSD on x86 currently provides no way to get the faulting
* memory address (i.e. the contents of the CR2 register), the page
* protection mechanism of the generational GC currently can't be
* used (see gengc.c), hence we don't neet to do anything here.
*
* See OpenBSD-os.c for details of what should be here, once NetBSD
* provides siginfo_t.
*/
SAVE_CONTEXT();
DPRINTF(0, (stderr, "sigsegv:\n"));
interrupt_handle_now(signal, code, context);
}
static void sigbus_handler(HANDLER_ARGS)
{
SAVE_CONTEXT();
DPRINTF(0, (stderr, "sigbus:\n"));
interrupt_handle_now(signal, code, context);
}
void os_install_interrupt_handlers(void)
{
interrupt_install_low_level_handler(SIGSEGV, sigsegv_handler);
interrupt_install_low_level_handler(SIGBUS, sigbus_handler);
}