panic() cleanup.
[minix.git] / servers / vm / pagefaults.c
blobcccbed4f74c3e0f6e447f63f5d916b08682784c9
2 #define _SYSTEM 1
4 #include <minix/callnr.h>
5 #include <minix/com.h>
6 #include <minix/config.h>
7 #include <minix/const.h>
8 #include <minix/ds.h>
9 #include <minix/endpoint.h>
10 #include <minix/keymap.h>
11 #include <minix/minlib.h>
12 #include <minix/type.h>
13 #include <minix/ipc.h>
14 #include <minix/sysutil.h>
15 #include <minix/syslib.h>
16 #include <minix/safecopies.h>
17 #include <minix/bitmap.h>
19 #include <errno.h>
20 #include <string.h>
21 #include <env.h>
22 #include <stdio.h>
23 #include <fcntl.h>
24 #include <signal.h>
26 #include <pagefaults.h>
28 #include "glo.h"
29 #include "proto.h"
30 #include "memory.h"
31 #include "util.h"
32 #include "region.h"
34 /*===========================================================================*
35 * pf_errstr *
36 *===========================================================================*/
37 char *pf_errstr(u32_t err)
39 static char buf[100];
41 sprintf(buf, "err 0x%lx ", err);
42 if(PFERR_NOPAGE(err)) strcat(buf, "nopage ");
43 if(PFERR_PROT(err)) strcat(buf, "protection ");
44 if(PFERR_WRITE(err)) strcat(buf, "write");
45 if(PFERR_READ(err)) strcat(buf, "read");
47 return buf;
50 /*===========================================================================*
51 * do_pagefaults *
52 *===========================================================================*/
53 PUBLIC void do_pagefaults(void)
55 endpoint_t ep;
56 u32_t addr, err;
57 struct vmproc *vmp;
58 int r, s;
60 while((r=arch_get_pagefault(&ep, &addr, &err)) == OK) {
61 struct vir_region *region;
62 vir_bytes offset;
63 int p, wr = PFERR_WRITE(err);
65 if(vm_isokendpt(ep, &p) != OK)
66 panic("do_pagefaults: endpoint wrong: %d", ep);
68 vmp = &vmproc[p];
69 vm_assert(vmp->vm_flags & VMF_INUSE);
71 /* See if address is valid at all. */
72 if(!(region = map_lookup(vmp, addr))) {
73 vm_assert(PFERR_NOPAGE(err));
74 printf("VM: pagefault: SIGSEGV %d bad addr 0x%lx %s\n",
75 ep, arch_map2vir(vmp, addr), pf_errstr(err));
76 sys_sysctl_stacktrace(vmp->vm_endpoint);
77 if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK)
78 panic("sys_kill failed: %d", s);
79 if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, r)) != OK)
80 panic("do_pagefaults: sys_vmctl failed: %d", ep);
81 continue;
84 /* Make sure this isn't a region that isn't supposed
85 * to cause pagefaults.
87 vm_assert(!(region->flags & VR_NOPF));
89 /* We do not allow shared memory to cause pagefaults.
90 * These pages have to be pre-allocated.
92 vm_assert(!(region->flags & VR_SHARED));
94 /* If process was writing, see if it's writable. */
95 if(!(region->flags & VR_WRITABLE) && wr) {
96 printf("VM: pagefault: SIGSEGV %d ro map 0x%lx %s\n",
97 ep, arch_map2vir(vmp, addr), pf_errstr(err));
98 sys_sysctl_stacktrace(vmp->vm_endpoint);
99 if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK)
100 panic("sys_kill failed: %d", s);
101 if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, r)) != OK)
102 panic("do_pagefaults: sys_vmctl failed: %d", ep);
103 continue;
106 vm_assert(addr >= region->vaddr);
107 offset = addr - region->vaddr;
109 /* Access is allowed; handle it. */
110 if((r=map_pf(vmp, region, offset, wr)) != OK) {
111 printf("VM: pagefault: SIGSEGV %d pagefault not handled\n", ep);
112 sys_sysctl_stacktrace(vmp->vm_endpoint);
113 if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK)
114 panic("sys_kill failed: %d", s);
115 if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, r)) != OK)
116 panic("do_pagefaults: sys_vmctl failed: %d", ep);
117 continue;
120 /* Pagefault is handled, so now reactivate the process. */
121 if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, r)) != OK)
122 panic("do_pagefaults: sys_vmctl failed: %d", ep);
126 return;
129 /*===========================================================================*
130 * do_memory *
131 *===========================================================================*/
132 PUBLIC void do_memory(void)
134 endpoint_t who, who_s, requestor;
135 vir_bytes mem, mem_s;
136 vir_bytes len;
137 int wrflag;
139 while(1) {
140 int p, r = OK;
141 struct vmproc *vmp;
143 r = sys_vmctl_get_memreq(&who, &mem, &len, &wrflag, &who_s,
144 &mem_s, &requestor);
146 switch(r) {
147 case VMPTYPE_CHECK:
148 if(vm_isokendpt(who, &p) != OK)
149 panic("do_memory: bad endpoint: %d", who);
150 vmp = &vmproc[p];
152 r = handle_memory(vmp, mem, len, wrflag);
153 break;
154 case VMPTYPE_COWMAP:
155 r = map_memory(who_s, who, mem_s, mem, len, -1);
156 break;
157 case VMPTYPE_SMAP:
158 r = map_memory(who_s, who, mem_s, mem, len, wrflag);
159 break;
160 case VMPTYPE_SUNMAP:
161 r = unmap_memory(who_s, who, mem_s, mem, len, wrflag);
162 break;
163 default:
164 return;
167 if(sys_vmctl(requestor, VMCTL_MEMREQ_REPLY, r) != OK)
168 panic("do_memory: sys_vmctl failed: %d", r);
172 int handle_memory(struct vmproc *vmp, vir_bytes mem, vir_bytes len, int wrflag)
174 struct vir_region *region;
175 vir_bytes o;
176 vir_bytes v;
178 /* Page-align memory and length. */
179 o = mem % VM_PAGE_SIZE;
180 mem -= o;
181 len += o;
182 o = len % VM_PAGE_SIZE;
183 if(o > 0) len += VM_PAGE_SIZE - o;
185 while(len > 0) {
186 int r;
187 if(!(region = map_lookup(vmp, mem))) {
188 #if VERBOSE
189 map_printmap(vmp);
190 printf("VM: do_memory: memory doesn't exist\n");
191 #endif
192 r = EFAULT;
193 } else if(!(region->flags & VR_WRITABLE) && wrflag) {
194 #if VERBOSE
195 printf("VM: do_memory: write to unwritable map\n");
196 #endif
197 r = EFAULT;
198 } else {
199 vir_bytes offset, sublen;
200 vm_assert(region->vaddr <= mem);
201 vm_assert(!(region->flags & VR_NOPF));
202 vm_assert(!(region->vaddr % VM_PAGE_SIZE));
203 offset = mem - region->vaddr;
204 sublen = len;
205 if(offset + sublen > region->length)
206 sublen = region->length - offset;
208 r = map_handle_memory(vmp, region, offset,
209 sublen, wrflag);
211 len -= sublen;
212 mem += sublen;
215 if(r != OK) {
216 #if VERBOSE
217 printf("VM: memory range 0x%lx-0x%lx not available in %d\n",
218 arch_map2vir(vmp, mem), arch_map2vir(vmp, mem+len),
219 vmp->vm_endpoint);
220 #endif
221 return r;
225 return OK;