Clean up RCS ids
[projects/cmucl/cmucl.git] / src / lisp / mach-os.c
1 /*
2  * OS-dependent routines.  This file (along with os.h) exports an
3  * OS-independent interface to the operating system VM facilities.
4  * Suprisingly, this interface looks a lot like the Mach interface
5  * (but simpler in some places).  For some operating systems, a subset
6  * of these functions will have to be emulated.
7  *
8  * This is the Mach version.
9  *
10  */
11
12 #include <stdio.h>
13 #include <mach.h>
14 #include <sys/file.h>
15 #include <signal.h>
16 #include "os.h"
17 #include "arch.h"
18 #include "interrupt.h"
19
20 #define MAX_SEGS 32
21
22 static struct segment {
23     vm_address_t start;
24     vm_size_t length;
25 } addr_map[MAX_SEGS];
26 static int segments = -1;
27
28 vm_size_t os_vm_page_size;
29
30 #if defined(i386) || defined(parisc)
31 mach_port_t
32 task_self(void)
33 {
34     return mach_task_self();
35 }
36 #endif
37
38 void
39 os_init0(const char *argv[], const char *envp[])
40 {}
41
42 void
43 os_init(const char *argv[], const char *envp[])
44 {
45     os_vm_page_size = vm_page_size;
46 }
47
48 os_vm_address_t
49 os_validate(vm_address_t addr, vm_size_t len)
50 {
51     kern_return_t res;
52
53     res = vm_allocate(task_self(), &addr, len, addr == NULL);
54
55     if (res != KERN_SUCCESS)
56         return 0;
57
58     segments = -1;
59
60     vm_protect(task_self(), addr, len, FALSE,
61                VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
62
63     return addr;
64 }
65
66 void
67 os_invalidate(vm_address_t addr, vm_size_t len)
68 {
69     kern_return_t res;
70
71     res = vm_deallocate(task_self(), addr, len);
72
73     if (res != KERN_SUCCESS)
74         mach_error("Could not vm_allocate memory: ", res);
75
76     segments = -1;
77 }
78
79 vm_address_t
80 os_map(int fd, int offset, vm_address_t addr, vm_size_t len)
81 {
82     kern_return_t res;
83
84     res = map_fd(fd, offset, &addr, 0, len);
85
86     if (res != KERN_SUCCESS) {
87         char buf[256];
88
89         sprintf(buf, "Could not map_fd(%d, %d, 0x%08x, 0x%08x): ",
90                 fd, offset, addr, len);
91         mach_error(buf, res);
92
93         lseek(fd, offset, L_SET);
94         read(fd, addr, len);
95     }
96
97     segments = -1;
98
99     vm_protect(task_self(), addr, len, FALSE,
100                VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
101
102     return addr;
103 }
104
105 void
106 os_flush_icache(vm_address_t address, vm_size_t length)
107 {
108 #ifdef mips
109     vm_machine_attribute_val_t flush;
110     kern_return_t kr;
111
112     flush = MATTR_VAL_ICACHE_FLUSH;
113
114     kr = vm_machine_attribute(task_self(), address, length,
115                               MATTR_CACHE, &flush);
116     if (kr != KERN_SUCCESS)
117         mach_error("Could not flush the instruction cache", kr);
118 #endif
119 }
120
121 void
122 os_protect(vm_address_t address, vm_size_t length, vm_prot_t protection)
123 {
124     vm_protect(task_self(), address, length, FALSE, protection);
125 }
126
127 boolean
128 valid_addr(test)
129      vm_address_t test;
130 {
131     vm_address_t addr;
132     vm_size_t size;
133     int bullshit;
134     int curseg;
135
136     if (segments == -1) {
137         addr = 0;
138         curseg = 0;
139
140         while (1) {
141             if (vm_region
142                 (task_self(), &addr, &size, &bullshit, &bullshit, &bullshit,
143                  &bullshit, &bullshit, &bullshit) != KERN_SUCCESS)
144                 break;
145
146             if (curseg > 0
147                 && addr_map[curseg - 1].start + addr_map[curseg - 1].length ==
148                 addr) addr_map[curseg - 1].length += size;
149             else {
150                 addr_map[curseg].start = addr;
151                 addr_map[curseg].length = size;
152                 curseg++;
153             }
154
155             addr += size;
156         }
157
158         segments = curseg;
159     }
160
161     for (curseg = 0; curseg < segments; curseg++)
162         if (addr_map[curseg].start <= test
163             && test < addr_map[curseg].start + addr_map[curseg].length)
164             return TRUE;
165     return FALSE;
166 }
167
168 #ifndef ibmrt
169 static void
170 sigbus_handler(int signal, int code, struct sigcontext *context)
171 {
172     if (!interrupt_maybe_gc(signal, code, context))
173         interrupt_handle_now(signal, code, context);
174 }
175 #endif
176
177 void
178 os_install_interrupt_handlers(void)
179 {
180 #ifndef ibmrt
181     interrupt_install_low_level_handler(SIGBUS, sigbus_handler);
182 #endif
183 #ifdef mips
184     interrupt_install_low_level_handler(SIGSEGV, sigbus_handler);
185 #endif
186 }