| 195461c1 |
1 | /* |
| 2 | * OpenBSD-os.c. |
| 3 | * From FreeBSD-os.c 1.6 2000/10/24 13:32:30 dtc 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 | * Frobbed for OpenBSD by Pierre R. Mai, 2001. |
| 15 | * |
| 195461c1 |
16 | */ |
| 17 | |
| 18 | #include <stdio.h> |
| 19 | #include <sys/param.h> |
| 20 | #include <sys/file.h> |
| 21 | #include <errno.h> |
| 195461c1 |
22 | #include "os.h" |
| 23 | #include "arch.h" |
| 24 | #include "globals.h" |
| 25 | #include "interrupt.h" |
| 26 | #include "lispregs.h" |
| 27 | #include "internals.h" |
| 28 | |
| 29 | #include <sys/types.h> |
| 30 | #include <signal.h> |
| 31 | /* #include <sys/sysinfo.h> */ |
| 32 | #include <sys/proc.h> |
| 33 | #include "validate.h" |
| 34 | vm_size_t os_vm_page_size; |
| 35 | |
| 195461c1 |
36 | #if defined GENCGC |
| 37 | #include "gencgc.h" |
| 38 | #endif |
| 195461c1 |
39 | \f |
| 9a8c1c2f |
40 | |
| 41 | void |
| dafb9e03 |
42 | os_init0(const char *argv[], const char *envp[]) |
| 43 | {} |
| 44 | |
| 45 | void |
| 0f0aed07 |
46 | os_init(const char *argv[], const char *envp[]) |
| 195461c1 |
47 | { |
| 9a8c1c2f |
48 | os_vm_page_size = OS_VM_DEFAULT_PAGESIZE; |
| 195461c1 |
49 | } |
| 50 | |
| 3e4590e7 |
51 | int * |
| 9a8c1c2f |
52 | sc_reg(struct sigcontext *c, int offset) |
| 195461c1 |
53 | { |
| 9a8c1c2f |
54 | switch (offset) { |
| 55 | case 0: |
| 3e4590e7 |
56 | return &c->sc_eax; |
| 9a8c1c2f |
57 | case 2: |
| 3e4590e7 |
58 | return &c->sc_ecx; |
| 9a8c1c2f |
59 | case 4: |
| 3e4590e7 |
60 | return &c->sc_edx; |
| 9a8c1c2f |
61 | case 6: |
| 3e4590e7 |
62 | return &c->sc_ebx; |
| 9a8c1c2f |
63 | case 8: |
| 3e4590e7 |
64 | return &c->sc_esp; |
| 9a8c1c2f |
65 | case 10: |
| 3e4590e7 |
66 | return &c->sc_ebp; |
| 9a8c1c2f |
67 | case 12: |
| 3e4590e7 |
68 | return &c->sc_esi; |
| 9a8c1c2f |
69 | case 14: |
| 3e4590e7 |
70 | return &c->sc_edi; |
| 195461c1 |
71 | } |
| 3e4590e7 |
72 | return (int *) 0; |
| 195461c1 |
73 | } |
| 74 | |
| 9a8c1c2f |
75 | os_vm_address_t |
| 76 | os_validate(os_vm_address_t addr, os_vm_size_t len) |
| 195461c1 |
77 | { |
| 1e078503 |
78 | int flags = MAP_PRIVATE | MAP_ANON; |
| 195461c1 |
79 | |
| 9a8c1c2f |
80 | if (addr) |
| 81 | flags |= MAP_FIXED; |
| 195461c1 |
82 | |
| 9a8c1c2f |
83 | DPRINTF(0, (stderr, "os_validate %x %d => ", addr, len)); |
| 195461c1 |
84 | |
| 9a8c1c2f |
85 | addr = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0); |
| 195461c1 |
86 | |
| 9a8c1c2f |
87 | if (addr == (os_vm_address_t) - 1) { |
| 88 | perror("mmap"); |
| 89 | return NULL; |
| 195461c1 |
90 | } |
| 91 | |
| 9a8c1c2f |
92 | DPRINTF(0, (stderr, "%x\n", addr)); |
| 195461c1 |
93 | |
| 9a8c1c2f |
94 | return addr; |
| 195461c1 |
95 | } |
| 96 | |
| 9a8c1c2f |
97 | void |
| 98 | os_invalidate(os_vm_address_t addr, os_vm_size_t len) |
| 195461c1 |
99 | { |
| 9a8c1c2f |
100 | DPRINTF(0, (stderr, "os_invalidate %x %d\n", addr, len)); |
| 195461c1 |
101 | |
| 9a8c1c2f |
102 | if (munmap(addr, len) == -1) |
| 103 | perror("munmap"); |
| 195461c1 |
104 | } |
| 105 | |
| 9a8c1c2f |
106 | os_vm_address_t |
| 107 | os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len) |
| 195461c1 |
108 | { |
| 9a8c1c2f |
109 | addr = mmap(addr, len, |
| 110 | OS_VM_PROT_ALL, |
| 111 | MAP_PRIVATE | MAP_FILE | MAP_FIXED, fd, (off_t) offset); |
| 195461c1 |
112 | |
| 9a8c1c2f |
113 | if (addr == (os_vm_address_t) - 1) |
| 114 | perror("mmap"); |
| 195461c1 |
115 | |
| 9a8c1c2f |
116 | return addr; |
| 195461c1 |
117 | } |
| 118 | |
| 9a8c1c2f |
119 | void |
| 120 | os_flush_icache(os_vm_address_t address, os_vm_size_t length) |
| 195461c1 |
121 | { |
| 122 | } |
| 123 | |
| 9a8c1c2f |
124 | void |
| 125 | os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot) |
| 195461c1 |
126 | { |
| 9a8c1c2f |
127 | if (mprotect(address, length, prot) == -1) |
| 128 | perror("mprotect"); |
| 195461c1 |
129 | } |
| 195461c1 |
130 | \f |
| 131 | |
| 9a8c1c2f |
132 | |
| 133 | static boolean |
| 134 | in_range_p(os_vm_address_t a, lispobj sbeg, size_t slen) |
| 195461c1 |
135 | { |
| 9a8c1c2f |
136 | char *beg = (char *) sbeg; |
| 137 | char *end = (char *) sbeg + slen; |
| 138 | char *adr = (char *) a; |
| 139 | |
| 140 | return (adr >= beg && adr < end); |
| 195461c1 |
141 | } |
| 142 | |
| 9a8c1c2f |
143 | boolean |
| 144 | valid_addr(os_vm_address_t addr) |
| 195461c1 |
145 | { |
| 9a8c1c2f |
146 | int ret; |
| 147 | os_vm_address_t newaddr; |
| 148 | |
| 149 | newaddr = os_trunc_to_page(addr); |
| 150 | |
| 151 | if (in_range_p(addr, READ_ONLY_SPACE_START, READ_ONLY_SPACE_SIZE) |
| 152 | || in_range_p(addr, STATIC_SPACE_START, STATIC_SPACE_SIZE) |
| 153 | || in_range_p(addr, DYNAMIC_0_SPACE_START, dynamic_space_size) |
| 154 | || in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size) |
| 155 | || in_range_p(addr, CONTROL_STACK_START, CONTROL_STACK_SIZE) |
| 156 | || in_range_p(addr, BINDING_STACK_START, BINDING_STACK_SIZE)) |
| 157 | return TRUE; |
| 158 | return FALSE; |
| 195461c1 |
159 | } |
| 195461c1 |
160 | \f |
| 9a8c1c2f |
161 | |
| 162 | static void |
| 163 | sigsegv_handler(HANDLER_ARGS) |
| 195461c1 |
164 | { |
| 165 | #if defined GENCGC |
| 9a8c1c2f |
166 | caddr_t fault_addr = code->si_addr; |
| 195461c1 |
167 | |
| 168 | #if SIGSEGV_VERBOSE |
| 9a8c1c2f |
169 | fprintf(stderr, "Signal %d, fault_addr=%x, page_index=%d:\n", |
| 170 | signal, fault_addr, page_index); |
| 195461c1 |
171 | #endif |
| 172 | |
| 97083c55 |
173 | if (gc_write_barrier(code->si_addr)) |
| 9a8c1c2f |
174 | return; |
| 195461c1 |
175 | #endif |
| 176 | |
| 9a8c1c2f |
177 | SAVE_CONTEXT(); |
| 195461c1 |
178 | |
| 9a8c1c2f |
179 | DPRINTF(0, (stderr, "sigsegv:\n")); |
| 180 | interrupt_handle_now(signal, code, context); |
| 195461c1 |
181 | } |
| 182 | |
| 9a8c1c2f |
183 | static void |
| 184 | sigbus_handler(HANDLER_ARGS) |
| 195461c1 |
185 | { |
| 9a8c1c2f |
186 | SAVE_CONTEXT(); |
| 195461c1 |
187 | |
| 9a8c1c2f |
188 | DPRINTF(0, (stderr, "sigbus:\n")); |
| 189 | interrupt_handle_now(signal, code, context); |
| 195461c1 |
190 | } |
| 191 | |
| 9a8c1c2f |
192 | void |
| 193 | os_install_interrupt_handlers(void) |
| 195461c1 |
194 | { |
| 9a8c1c2f |
195 | interrupt_install_low_level_handler(SIGSEGV, sigsegv_handler); |
| 196 | interrupt_install_low_level_handler(SIGBUS, sigbus_handler); |
| 195461c1 |
197 | } |