some coverity fixes.
[minix.git] / servers / vm / pagefaults.c
blobf0d1feec66724c6e43737333bbebb23fb5fcdbcd
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>
25 #include <assert.h>
27 #include <pagefaults.h>
29 #include "glo.h"
30 #include "proto.h"
31 #include "memory.h"
32 #include "util.h"
33 #include "region.h"
35 /*===========================================================================*
36 * pf_errstr *
37 *===========================================================================*/
38 char *pf_errstr(u32_t err)
40 static char buf[100];
42 sprintf(buf, "err 0x%lx ", (long)err);
43 if(PFERR_NOPAGE(err)) strcat(buf, "nopage ");
44 if(PFERR_PROT(err)) strcat(buf, "protection ");
45 if(PFERR_WRITE(err)) strcat(buf, "write");
46 if(PFERR_READ(err)) strcat(buf, "read");
48 return buf;
51 /*===========================================================================*
52 * do_pagefaults *
53 *===========================================================================*/
54 void do_pagefaults(message *m)
56 endpoint_t ep = m->m_source;
57 u32_t addr = m->VPF_ADDR;
58 u32_t err = m->VPF_FLAGS;
59 struct vmproc *vmp;
60 int s;
62 struct vir_region *region;
63 vir_bytes offset;
64 int p, wr = PFERR_WRITE(err);
66 if(vm_isokendpt(ep, &p) != OK)
67 panic("do_pagefaults: endpoint wrong: %d", ep);
69 vmp = &vmproc[p];
70 assert(vmp->vm_flags & VMF_INUSE);
72 /* See if address is valid at all. */
73 if(!(region = map_lookup(vmp, addr, NULL))) {
74 if(PFERR_PROT(err)) {
75 printf("VM: pagefault: SIGSEGV %d protected addr 0x%x; %s\n",
76 ep, addr, pf_errstr(err));
77 } else {
78 assert(PFERR_NOPAGE(err));
79 printf("VM: pagefault: SIGSEGV %d bad addr 0x%x; %s\n",
80 ep, addr, pf_errstr(err));
82 if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK)
83 panic("sys_kill failed: %d", s);
84 if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, 0 /*unused*/)) != OK)
85 panic("do_pagefaults: sys_vmctl failed: %d", ep);
86 return;
89 /* Make sure this isn't a region that isn't supposed
90 * to cause pagefaults.
92 assert(!(region->flags & VR_NOPF));
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%x %s\n",
97 ep, addr, pf_errstr(err));
98 if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK)
99 panic("sys_kill failed: %d", s);
100 if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, 0 /*unused*/)) != OK)
101 panic("do_pagefaults: sys_vmctl failed: %d", ep);
102 return;
105 assert(addr >= region->vaddr);
106 offset = addr - region->vaddr;
108 /* Access is allowed; handle it. */
109 if((map_pf(vmp, region, offset, wr)) != OK) {
110 printf("VM: pagefault: SIGSEGV %d pagefault not handled\n", ep);
111 if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK)
112 panic("sys_kill failed: %d", s);
113 if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, 0 /*unused*/)) != OK)
114 panic("do_pagefaults: sys_vmctl failed: %d", ep);
115 return;
118 /* Pagefault is handled, so now reactivate the process. */
119 if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, 0 /*unused*/)) != OK)
120 panic("do_pagefaults: sys_vmctl failed: %d", ep);
123 /*===========================================================================*
124 * do_memory *
125 *===========================================================================*/
126 void do_memory(void)
128 endpoint_t who, who_s, requestor;
129 vir_bytes mem, mem_s;
130 vir_bytes len;
131 int wrflag;
133 while(1) {
134 int p, r = OK;
135 struct vmproc *vmp;
137 r = sys_vmctl_get_memreq(&who, &mem, &len, &wrflag, &who_s,
138 &mem_s, &requestor);
140 switch(r) {
141 case VMPTYPE_CHECK:
142 if(vm_isokendpt(who, &p) != OK)
143 panic("do_memory: bad endpoint: %d", who);
144 vmp = &vmproc[p];
146 r = handle_memory(vmp, mem, len, wrflag);
147 break;
148 case VMPTYPE_COWMAP:
149 r = map_memory(who_s, who, mem_s, mem, len, -1);
150 break;
151 case VMPTYPE_SMAP:
152 r = map_memory(who_s, who, mem_s, mem, len, wrflag);
153 break;
154 case VMPTYPE_SUNMAP:
155 r = unmap_memory(who_s, who, mem_s, mem, len, wrflag);
156 break;
157 default:
158 return;
161 if(sys_vmctl(requestor, VMCTL_MEMREQ_REPLY, r) != OK)
162 panic("do_memory: sys_vmctl failed: %d", r);
166 int handle_memory(struct vmproc *vmp, vir_bytes mem, vir_bytes len, int wrflag)
168 struct vir_region *region;
169 vir_bytes o;
171 /* Page-align memory and length. */
172 o = mem % VM_PAGE_SIZE;
173 mem -= o;
174 len += o;
175 o = len % VM_PAGE_SIZE;
176 if(o > 0) len += VM_PAGE_SIZE - o;
178 while(len > 0) {
179 int r;
180 if(!(region = map_lookup(vmp, mem, NULL))) {
181 #if VERBOSE
182 map_printmap(vmp);
183 printf("VM: do_memory: memory doesn't exist\n");
184 #endif
185 r = EFAULT;
186 } else if(!(region->flags & VR_WRITABLE) && wrflag) {
187 #if VERBOSE
188 printf("VM: do_memory: write to unwritable map\n");
189 #endif
190 r = EFAULT;
191 } else {
192 vir_bytes offset, sublen;
193 assert(region->vaddr <= mem);
194 assert(!(region->flags & VR_NOPF));
195 assert(!(region->vaddr % VM_PAGE_SIZE));
196 offset = mem - region->vaddr;
197 sublen = len;
198 if(offset + sublen > region->length)
199 sublen = region->length - offset;
201 r = map_handle_memory(vmp, region, offset,
202 sublen, wrflag);
204 len -= sublen;
205 mem += sublen;
208 if(r != OK) {
209 #if VERBOSE
210 printf("VM: memory range 0x%lx-0x%lx not available in %d\n",
211 mem, mem+len, vmp->vm_endpoint);
212 #endif
213 return r;
217 return OK;