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>
27 #include <pagefaults.h>
35 /*===========================================================================*
37 *===========================================================================*/
38 char *pf_errstr(u32_t err
)
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");
51 /*===========================================================================*
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
;
62 struct vir_region
*region
;
64 int p
, wr
= PFERR_WRITE(err
);
66 if(vm_isokendpt(ep
, &p
) != OK
)
67 panic("do_pagefaults: endpoint wrong: %d", ep
);
70 assert(vmp
->vm_flags
& VMF_INUSE
);
72 /* See if address is valid at all. */
73 if(!(region
= map_lookup(vmp
, addr
, NULL
))) {
75 printf("VM: pagefault: SIGSEGV %d protected addr 0x%x; %s\n",
76 ep
, addr
, pf_errstr(err
));
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
);
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
);
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
);
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 /*===========================================================================*
125 *===========================================================================*/
128 endpoint_t who
, who_s
, requestor
;
129 vir_bytes mem
, mem_s
;
137 r
= sys_vmctl_get_memreq(&who
, &mem
, &len
, &wrflag
, &who_s
,
142 if(vm_isokendpt(who
, &p
) != OK
)
143 panic("do_memory: bad endpoint: %d", who
);
146 r
= handle_memory(vmp
, mem
, len
, wrflag
);
149 r
= map_memory(who_s
, who
, mem_s
, mem
, len
, -1);
152 r
= map_memory(who_s
, who
, mem_s
, mem
, len
, wrflag
);
155 r
= unmap_memory(who_s
, who
, mem_s
, mem
, len
, wrflag
);
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
;
171 /* Page-align memory and length. */
172 o
= mem
% VM_PAGE_SIZE
;
175 o
= len
% VM_PAGE_SIZE
;
176 if(o
> 0) len
+= VM_PAGE_SIZE
- o
;
180 if(!(region
= map_lookup(vmp
, mem
, NULL
))) {
183 printf("VM: do_memory: memory doesn't exist\n");
186 } else if(!(region
->flags
& VR_WRITABLE
) && wrflag
) {
188 printf("VM: do_memory: write to unwritable map\n");
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
;
198 if(offset
+ sublen
> region
->length
)
199 sublen
= region
->length
- offset
;
201 r
= map_handle_memory(vmp
, region
, offset
,
210 printf("VM: memory range 0x%lx-0x%lx not available in %d\n",
211 mem
, mem
+len
, vmp
->vm_endpoint
);