Newer
Older
* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/mach-os.c,v 1.3 1992/09/16 22:26:53 wlott Exp $
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
*
* 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 Mach version.
*
*/
#include <stdio.h>
#include <mach.h>
#include <sys/file.h>
#include "./signal.h"
#include "os.h"
#include "arch.h"
#include "interrupt.h"
#define MAX_SEGS 32
static struct segment {
vm_address_t start;
vm_size_t length;
} addr_map[MAX_SEGS];
static int segments = -1;
vm_size_t os_vm_page_size;
#if defined(i386) || defined(parisc)
mach_port_t task_self()
{
return mach_task_self();
}
#endif
void os_init()
{
os_vm_page_size = vm_page_size;
}
os_vm_address_t os_validate(vm_address_t addr, vm_size_t len)
{
kern_return_t res;
res = vm_allocate(task_self(), &addr, len, addr==NULL);
if (res != KERN_SUCCESS)
return 0;
segments = -1;
vm_protect(task_self(), addr, len, FALSE,
VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
return addr;
}
void os_invalidate(vm_address_t addr, vm_size_t len)
{
kern_return_t res;
res = vm_deallocate(task_self(), addr, len);
if (res != KERN_SUCCESS)
mach_error("Could not vm_allocate memory: ", res);
segments = -1;
}
vm_address_t os_map(int fd, int offset, vm_address_t addr, vm_size_t len)
{
kern_return_t res;
res = map_fd(fd, offset, &addr, 0, len);
if (res != KERN_SUCCESS) {
char buf[256];
sprintf(buf, "Could not map_fd(%d, %d, 0x%08x, 0x%08x): ",
fd, offset, addr, len);
mach_error(buf, res);
lseek(fd, offset, L_SET);
read(fd, addr, len);
}
segments = -1;
vm_protect(task_self(), addr, len, FALSE,
VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
return addr;
}
void os_flush_icache(vm_address_t address, vm_size_t length)
{
#ifdef mips
vm_machine_attribute_val_t flush;
kern_return_t kr;
flush = MATTR_VAL_ICACHE_FLUSH;
kr = vm_machine_attribute(task_self(), address, length,
MATTR_CACHE, &flush);
if (kr != KERN_SUCCESS)
mach_error("Could not flush the instruction cache", kr);
#endif
}
void os_protect(vm_address_t address, vm_size_t length, vm_prot_t protection)
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
{
vm_protect(task_self(), address, length, FALSE, protection);
}
boolean valid_addr(test)
vm_address_t test;
{
vm_address_t addr;
vm_size_t size;
int bullshit;
int curseg;
if (segments == -1) {
addr = 0;
curseg = 0;
while (1) {
if (vm_region(task_self(), &addr, &size, &bullshit, &bullshit, &bullshit, &bullshit, &bullshit, &bullshit) != KERN_SUCCESS)
break;
if (curseg > 0 && addr_map[curseg-1].start + addr_map[curseg-1].length == addr)
addr_map[curseg-1].length += size;
else {
addr_map[curseg].start = addr;
addr_map[curseg].length = size;
curseg++;
}
addr += size;
}
segments = curseg;
}
for (curseg = 0; curseg < segments; curseg++)
if (addr_map[curseg].start <= test && test < addr_map[curseg].start + addr_map[curseg].length)
return TRUE;
return FALSE;
}
#ifndef ibmrt
static void sigbus_handler(int signal, int code, struct sigcontext *context)
{
if(!interrupt_maybe_gc(signal, code, context))
interrupt_handle_now(signal, code, context);
}
#endif
void os_install_interrupt_handlers(void)
{
#ifndef ibmrt
interrupt_install_low_level_handler(SIGBUS,sigbus_handler);
#endif
#ifdef mips
interrupt_install_low_level_handler(SIGSEGV,sigbus_handler);
#endif
}