tar: use utime() to restore timestamps
[minix.git] / servers / vm / pagefaults.c
blobacc497562ac5493d3cd92d3f96d6f682fff79b7e
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 "glo.h"
28 #include "proto.h"
29 #include "util.h"
30 #include "region.h"
32 /*===========================================================================*
33 * pf_errstr *
34 *===========================================================================*/
35 char *pf_errstr(u32_t err)
37 static char buf[100];
39 sprintf(buf, "err 0x%lx ", (long)err);
40 if(PFERR_NOPAGE(err)) strcat(buf, "nopage ");
41 if(PFERR_PROT(err)) strcat(buf, "protection ");
42 if(PFERR_WRITE(err)) strcat(buf, "write");
43 if(PFERR_READ(err)) strcat(buf, "read");
45 return buf;
48 /*===========================================================================*
49 * do_pagefaults *
50 *===========================================================================*/
51 void do_pagefaults(message *m)
53 endpoint_t ep = m->m_source;
54 u32_t addr = m->VPF_ADDR;
55 u32_t err = m->VPF_FLAGS;
56 struct vmproc *vmp;
57 int s;
59 struct vir_region *region;
60 vir_bytes offset;
61 int p, wr = PFERR_WRITE(err);
63 if(vm_isokendpt(ep, &p) != OK)
64 panic("do_pagefaults: endpoint wrong: %d", ep);
66 vmp = &vmproc[p];
67 assert(vmp->vm_flags & VMF_INUSE);
69 /* See if address is valid at all. */
70 if(!(region = map_lookup(vmp, addr, NULL))) {
71 if(PFERR_PROT(err)) {
72 printf("VM: pagefault: SIGSEGV %d protected addr 0x%x; %s\n",
73 ep, addr, pf_errstr(err));
74 } else {
75 assert(PFERR_NOPAGE(err));
76 printf("VM: pagefault: SIGSEGV %d bad addr 0x%x; %s\n",
77 ep, addr, pf_errstr(err));
78 sys_sysctl_stacktrace(ep);
80 if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK)
81 panic("sys_kill failed: %d", s);
82 if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, 0 /*unused*/)) != OK)
83 panic("do_pagefaults: sys_vmctl failed: %d", ep);
84 return;
87 /* If process was writing, see if it's writable. */
88 if(!(region->flags & VR_WRITABLE) && wr) {
89 printf("VM: pagefault: SIGSEGV %d ro map 0x%x %s\n",
90 ep, addr, pf_errstr(err));
91 if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK)
92 panic("sys_kill failed: %d", s);
93 if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, 0 /*unused*/)) != OK)
94 panic("do_pagefaults: sys_vmctl failed: %d", ep);
95 return;
98 assert(addr >= region->vaddr);
99 offset = addr - region->vaddr;
101 /* Access is allowed; handle it. */
102 if((map_pf(vmp, region, offset, wr)) != OK) {
103 printf("VM: pagefault: SIGSEGV %d pagefault not handled\n", ep);
104 if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK)
105 panic("sys_kill failed: %d", s);
106 if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, 0 /*unused*/)) != OK)
107 panic("do_pagefaults: sys_vmctl failed: %d", ep);
108 return;
111 /* Pagefault is handled, so now reactivate the process. */
112 if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, 0 /*unused*/)) != OK)
113 panic("do_pagefaults: sys_vmctl failed: %d", ep);
116 /*===========================================================================*
117 * do_memory *
118 *===========================================================================*/
119 void do_memory(void)
121 endpoint_t who, who_s, requestor;
122 vir_bytes mem, mem_s;
123 vir_bytes len;
124 int wrflag;
126 while(1) {
127 int p, r = OK;
128 struct vmproc *vmp;
130 r = sys_vmctl_get_memreq(&who, &mem, &len, &wrflag, &who_s,
131 &mem_s, &requestor);
133 switch(r) {
134 case VMPTYPE_CHECK:
135 if(vm_isokendpt(who, &p) != OK)
136 panic("do_memory: bad endpoint: %d", who);
137 vmp = &vmproc[p];
139 r = handle_memory(vmp, mem, len, wrflag);
140 break;
141 default:
142 return;
145 if(sys_vmctl(requestor, VMCTL_MEMREQ_REPLY, r) != OK)
146 panic("do_memory: sys_vmctl failed: %d", r);
150 int handle_memory(struct vmproc *vmp, vir_bytes mem, vir_bytes len, int wrflag)
152 struct vir_region *region;
153 vir_bytes o;
155 /* Page-align memory and length. */
156 o = mem % VM_PAGE_SIZE;
157 mem -= o;
158 len += o;
159 o = len % VM_PAGE_SIZE;
160 if(o > 0) len += VM_PAGE_SIZE - o;
162 while(len > 0) {
163 int r;
164 if(!(region = map_lookup(vmp, mem, NULL))) {
165 #if VERBOSE
166 map_printmap(vmp);
167 printf("VM: do_memory: memory doesn't exist\n");
168 #endif
169 r = EFAULT;
170 } else if(!(region->flags & VR_WRITABLE) && wrflag) {
171 #if VERBOSE
172 printf("VM: do_memory: write to unwritable map\n");
173 #endif
174 r = EFAULT;
175 } else {
176 vir_bytes offset, sublen;
177 assert(region->vaddr <= mem);
178 assert(!(region->vaddr % VM_PAGE_SIZE));
179 offset = mem - region->vaddr;
180 sublen = len;
181 if(offset + sublen > region->length)
182 sublen = region->length - offset;
184 r = map_handle_memory(vmp, region, offset,
185 sublen, wrflag);
187 len -= sublen;
188 mem += sublen;
191 if(r != OK) {
192 #if VERBOSE
193 printf("VM: memory range 0x%lx-0x%lx not available in %d\n",
194 mem, mem+len, vmp->vm_endpoint);
195 #endif
196 return r;
200 return OK;