4 #include <minix/callnr.h>
6 #include <minix/config.h>
7 #include <minix/const.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>
26 #include <pagefaults.h>
34 /*===========================================================================*
36 *===========================================================================*/
37 char *pf_errstr(u32_t err
)
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");
50 /*===========================================================================*
52 *===========================================================================*/
53 PUBLIC
void do_pagefaults(void)
60 while((r
=arch_get_pagefault(&ep
, &addr
, &err
)) == OK
) {
61 struct vir_region
*region
;
63 int p
, wr
= PFERR_WRITE(err
);
65 if(vm_isokendpt(ep
, &p
) != OK
)
66 panic("do_pagefaults: endpoint wrong: %d", ep
);
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
);
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
);
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
);
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
);
129 /*===========================================================================*
131 *===========================================================================*/
132 PUBLIC
void do_memory(void)
134 endpoint_t who
, who_s
, requestor
;
135 vir_bytes mem
, mem_s
;
143 r
= sys_vmctl_get_memreq(&who
, &mem
, &len
, &wrflag
, &who_s
,
148 if(vm_isokendpt(who
, &p
) != OK
)
149 panic("do_memory: bad endpoint: %d", who
);
152 r
= handle_memory(vmp
, mem
, len
, wrflag
);
155 r
= map_memory(who_s
, who
, mem_s
, mem
, len
, -1);
158 r
= map_memory(who_s
, who
, mem_s
, mem
, len
, wrflag
);
161 r
= unmap_memory(who_s
, who
, mem_s
, mem
, len
, wrflag
);
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
;
178 /* Page-align memory and length. */
179 o
= mem
% VM_PAGE_SIZE
;
182 o
= len
% VM_PAGE_SIZE
;
183 if(o
> 0) len
+= VM_PAGE_SIZE
- o
;
187 if(!(region
= map_lookup(vmp
, mem
))) {
190 printf("VM: do_memory: memory doesn't exist\n");
193 } else if(!(region
->flags
& VR_WRITABLE
) && wrflag
) {
195 printf("VM: do_memory: write to unwritable map\n");
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
;
205 if(offset
+ sublen
> region
->length
)
206 sublen
= region
->length
- offset
;
208 r
= map_handle_memory(vmp
, region
, offset
,
217 printf("VM: memory range 0x%lx-0x%lx not available in %d\n",
218 arch_map2vir(vmp
, mem
), arch_map2vir(vmp
, mem
+len
),