| 3489d6bc |
1 | /* |
| 3489d6bc |
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 IRIX version. By Sean Hallgren. |
| 9 | * |
| 10 | */ |
| 11 | |
| 12 | #include <stdio.h> |
| 13 | #include <sys/file.h> |
| 14 | #include <errno.h> |
| c6d5b32f |
15 | #include <signal.h> |
| 3489d6bc |
16 | #include "os.h" |
| 17 | #include "arch.h" |
| 18 | #include "interrupt.h" |
| 19 | #include "lispregs.h" |
| 20 | #include <sys/types.h> |
| 21 | #include <sys/sysinfo.h> |
| 22 | #include <sys/proc.h> |
| 23 | |
| 24 | /* #define DEBUG */ |
| 25 | |
| 9a8c1c2f |
26 | os_vm_size_t os_vm_page_size = (-1); |
| 3489d6bc |
27 | |
| 28 | int zero_fd; |
| 29 | |
| 30 | void |
| dafb9e03 |
31 | os_init0(const char *argv[], const char *envp[]) |
| 32 | {} |
| 33 | |
| 34 | void |
| 0f0aed07 |
35 | os_init(const char *argv[], const char *envp[]) |
| 3489d6bc |
36 | { |
| 9a8c1c2f |
37 | zero_fd = open("/dev/zero", O_RDONLY); |
| 38 | os_vm_page_size = getpagesize(); |
| 3489d6bc |
39 | } |
| 40 | |
| 9a8c1c2f |
41 | os_vm_address_t os_validate(os_vm_address_t addr, os_vm_size_t len) |
| 3489d6bc |
42 | { |
| 9a8c1c2f |
43 | int flags = MAP_PRIVATE | MAP_AUTORESRV; |
| 3489d6bc |
44 | |
| 45 | #ifdef DEBUG |
| 9a8c1c2f |
46 | printf("os_validate: addr = %x, len = %x\n", addr, len); |
| 3489d6bc |
47 | #endif |
| 48 | |
| 9a8c1c2f |
49 | if (addr) |
| 50 | flags |= MAP_FIXED; |
| 3489d6bc |
51 | |
| 9a8c1c2f |
52 | if ((addr = mmap(addr, len, OS_VM_PROT_ALL, flags, zero_fd, 0)) == |
| 53 | (os_vm_address_t) - 1) |
| 54 | perror("mmap"); |
| 3489d6bc |
55 | |
| 9a8c1c2f |
56 | return addr; |
| 3489d6bc |
57 | } |
| 58 | |
| 59 | void |
| 60 | os_invalidate(os_vm_address_t addr, os_vm_size_t len) |
| 61 | { |
| 62 | #ifdef DEBUG |
| 9a8c1c2f |
63 | printf("os_invalidate: addr = %x, len = %x\n", addr, len); |
| 3489d6bc |
64 | #endif |
| 65 | |
| 9a8c1c2f |
66 | if (munmap(addr, len) == -1) |
| 67 | perror("munmap"); |
| 3489d6bc |
68 | } |
| 69 | |
| 70 | os_vm_address_t |
| 71 | os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len) |
| 72 | { |
| 73 | #ifdef DEBUG |
| 9a8c1c2f |
74 | printf("os_map: fd = %d, offset = %d, addr = %x, len = %x\n", fd, offset, |
| 75 | addr, len); |
| 3489d6bc |
76 | #endif |
| 77 | |
| 9a8c1c2f |
78 | if ((addr = mmap(addr, len, OS_VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, fd, |
| 79 | (off_t) offset)) == (os_vm_address_t) - 1) |
| 80 | perror("mmap"); |
| 81 | |
| 82 | return addr; |
| 3489d6bc |
83 | } |
| 84 | |
| 85 | void |
| 86 | sanctify_for_execution(os_vm_address_t addr, os_vm_size_t len) |
| 87 | { |
| 9a8c1c2f |
88 | char *end_addr = addr + len; |
| 89 | |
| 90 | addr = os_trunc_to_page(addr); |
| 91 | len = end_addr - addr; |
| 3489d6bc |
92 | |
| 9a8c1c2f |
93 | if (mprotect(addr, len, OS_VM_PROT_ALL) == -1) |
| 94 | perror("mprotect"); |
| 3489d6bc |
95 | } |
| 96 | |
| 97 | void |
| 98 | os_flush_icache(os_vm_address_t address, os_vm_size_t length) |
| 99 | { |
| 9a8c1c2f |
100 | sanctify_for_execution(address, length); |
| 3489d6bc |
101 | } |
| 102 | |
| 103 | void |
| 104 | os_protect(os_vm_address_t addr, os_vm_size_t len, os_vm_prot_t prot) |
| 105 | { |
| 9a8c1c2f |
106 | if (mprotect(addr, len, prot) == -1) |
| 107 | perror("mprotect"); |
| 3489d6bc |
108 | } |
| 109 | |
| 9a8c1c2f |
110 | boolean valid_addr(os_vm_address_t addr) |
| 3489d6bc |
111 | { |
| 112 | } |
| 113 | |
| 114 | static void |
| 115 | sigbus_handler(int signal, int code, struct sigcontext *context) |
| 116 | { |
| 9a8c1c2f |
117 | if (!interrupt_maybe_gc(signal, code, context)) |
| 118 | interrupt_handle_now(signal, code, context); |
| 3489d6bc |
119 | } |
| 120 | |
| 121 | static void |
| 122 | sigsegv_handler(int signal, int code, struct sigcontext *context) |
| 123 | { |
| 9a8c1c2f |
124 | if (!interrupt_maybe_gc(signal, code, context)) |
| 125 | interrupt_handle_now(signal, code, context); |
| 3489d6bc |
126 | } |
| 127 | |
| 9a8c1c2f |
128 | void |
| 3489d6bc |
129 | os_install_interrupt_handlers(void) |
| 130 | { |
| 9a8c1c2f |
131 | interrupt_install_low_level_handler(SIGSEGV, sigsegv_handler); |
| 132 | interrupt_install_low_level_handler(SIGBUS, sigbus_handler); |
| 3489d6bc |
133 | } |