1433d6423SLionel Sambuc 2433d6423SLionel Sambuc #define _SYSTEM 1 3433d6423SLionel Sambuc 4433d6423SLionel Sambuc #include <minix/callnr.h> 5433d6423SLionel Sambuc #include <minix/com.h> 6433d6423SLionel Sambuc #include <minix/config.h> 7433d6423SLionel Sambuc #include <minix/const.h> 8433d6423SLionel Sambuc #include <minix/ds.h> 9433d6423SLionel Sambuc #include <minix/endpoint.h> 10433d6423SLionel Sambuc #include <minix/minlib.h> 11433d6423SLionel Sambuc #include <minix/type.h> 12433d6423SLionel Sambuc #include <minix/ipc.h> 13433d6423SLionel Sambuc #include <minix/sysutil.h> 14433d6423SLionel Sambuc #include <minix/syslib.h> 15433d6423SLionel Sambuc #include <minix/safecopies.h> 16433d6423SLionel Sambuc #include <minix/bitmap.h> 17433d6423SLionel Sambuc #include <minix/vfsif.h> 18433d6423SLionel Sambuc 19433d6423SLionel Sambuc #include <machine/vmparam.h> 20433d6423SLionel Sambuc 21433d6423SLionel Sambuc #include <errno.h> 22433d6423SLionel Sambuc #include <string.h> 23433d6423SLionel Sambuc #include <env.h> 24433d6423SLionel Sambuc #include <stdio.h> 25433d6423SLionel Sambuc #include <fcntl.h> 26433d6423SLionel Sambuc #include <signal.h> 27433d6423SLionel Sambuc #include <assert.h> 28433d6423SLionel Sambuc 29433d6423SLionel Sambuc #include "glo.h" 30433d6423SLionel Sambuc #include "proto.h" 31433d6423SLionel Sambuc #include "util.h" 32433d6423SLionel Sambuc #include "region.h" 33433d6423SLionel Sambuc 34433d6423SLionel Sambuc struct pf_state { 35433d6423SLionel Sambuc endpoint_t ep; 36433d6423SLionel Sambuc vir_bytes vaddr; 37433d6423SLionel Sambuc u32_t err; 38433d6423SLionel Sambuc }; 39433d6423SLionel Sambuc 40433d6423SLionel Sambuc struct hm_state { 41433d6423SLionel Sambuc endpoint_t caller; /* KERNEL or process? if NONE, no callback */ 42433d6423SLionel Sambuc endpoint_t requestor; /* on behalf of whom? */ 43433d6423SLionel Sambuc int transid; /* VFS transaction id if valid */ 44433d6423SLionel Sambuc struct vmproc *vmp; /* target address space */ 45433d6423SLionel Sambuc vir_bytes mem, len; /* memory range */ 46433d6423SLionel Sambuc int wrflag; /* must it be writable or not */ 47433d6423SLionel Sambuc int valid; /* sanity check */ 48433d6423SLionel Sambuc int vfs_avail; /* may vfs be called to satisfy this range? */ 49433d6423SLionel Sambuc #define VALID 0xc0ff1 50433d6423SLionel Sambuc }; 51433d6423SLionel Sambuc 52433d6423SLionel Sambuc static void handle_memory_continue(struct vmproc *vmp, message *m, 53433d6423SLionel Sambuc void *arg, void *statearg); 54*f202792eSDavid van Moolenbroek static int handle_memory_step(struct hm_state *hmstate, int retry); 55433d6423SLionel Sambuc static void handle_memory_final(struct hm_state *state, int result); 56433d6423SLionel Sambuc 57433d6423SLionel Sambuc /*===========================================================================* 58433d6423SLionel Sambuc * pf_errstr * 59433d6423SLionel Sambuc *===========================================================================*/ 60433d6423SLionel Sambuc char *pf_errstr(u32_t err) 61433d6423SLionel Sambuc { 62433d6423SLionel Sambuc static char buf[100]; 63433d6423SLionel Sambuc 64433d6423SLionel Sambuc sprintf(buf, "err 0x%lx ", (long)err); 65433d6423SLionel Sambuc if(PFERR_NOPAGE(err)) strcat(buf, "nopage "); 66433d6423SLionel Sambuc if(PFERR_PROT(err)) strcat(buf, "protection "); 67433d6423SLionel Sambuc if(PFERR_WRITE(err)) strcat(buf, "write"); 68433d6423SLionel Sambuc if(PFERR_READ(err)) strcat(buf, "read"); 69433d6423SLionel Sambuc 70433d6423SLionel Sambuc return buf; 71433d6423SLionel Sambuc } 72433d6423SLionel Sambuc 73433d6423SLionel Sambuc static void pf_cont(struct vmproc *vmp, message *m, void *arg, void *statearg); 74433d6423SLionel Sambuc 75433d6423SLionel Sambuc static void handle_memory_continue(struct vmproc *vmp, message *m, void *arg, void *statearg); 76433d6423SLionel Sambuc 77433d6423SLionel Sambuc static void handle_pagefault(endpoint_t ep, vir_bytes addr, u32_t err, int retry) 78433d6423SLionel Sambuc { 79433d6423SLionel Sambuc struct vmproc *vmp; 80433d6423SLionel Sambuc int s, result; 81433d6423SLionel Sambuc struct vir_region *region; 82433d6423SLionel Sambuc vir_bytes offset; 83433d6423SLionel Sambuc int p, wr = PFERR_WRITE(err); 84433d6423SLionel Sambuc int io = 0; 85433d6423SLionel Sambuc 86433d6423SLionel Sambuc if(vm_isokendpt(ep, &p) != OK) 87433d6423SLionel Sambuc panic("handle_pagefault: endpoint wrong: %d", ep); 88433d6423SLionel Sambuc 89433d6423SLionel Sambuc vmp = &vmproc[p]; 90433d6423SLionel Sambuc assert(vmp->vm_flags & VMF_INUSE); 91433d6423SLionel Sambuc 92433d6423SLionel Sambuc /* See if address is valid at all. */ 93433d6423SLionel Sambuc if(!(region = map_lookup(vmp, addr, NULL))) { 94433d6423SLionel Sambuc if(PFERR_PROT(err)) { 95433d6423SLionel Sambuc printf("VM: pagefault: SIGSEGV %d protected addr 0x%lx; %s\n", 96433d6423SLionel Sambuc ep, addr, pf_errstr(err)); 97433d6423SLionel Sambuc } else { 98433d6423SLionel Sambuc assert(PFERR_NOPAGE(err)); 99433d6423SLionel Sambuc printf("VM: pagefault: SIGSEGV %d bad addr 0x%lx; %s\n", 100433d6423SLionel Sambuc ep, addr, pf_errstr(err)); 101433d6423SLionel Sambuc sys_diagctl_stacktrace(ep); 102433d6423SLionel Sambuc } 103433d6423SLionel Sambuc if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK) 104433d6423SLionel Sambuc panic("sys_kill failed: %d", s); 105433d6423SLionel Sambuc if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, 0 /*unused*/)) != OK) 106433d6423SLionel Sambuc panic("do_pagefaults: sys_vmctl failed: %d", ep); 107433d6423SLionel Sambuc return; 108433d6423SLionel Sambuc } 109433d6423SLionel Sambuc 110433d6423SLionel Sambuc /* If process was writing, see if it's writable. */ 111433d6423SLionel Sambuc if(!(region->flags & VR_WRITABLE) && wr) { 112433d6423SLionel Sambuc printf("VM: pagefault: SIGSEGV %d ro map 0x%lx %s\n", 113433d6423SLionel Sambuc ep, addr, pf_errstr(err)); 114433d6423SLionel Sambuc if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK) 115433d6423SLionel Sambuc panic("sys_kill failed: %d", s); 116433d6423SLionel Sambuc if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, 0 /*unused*/)) != OK) 117433d6423SLionel Sambuc panic("do_pagefaults: sys_vmctl failed: %d", ep); 118433d6423SLionel Sambuc return; 119433d6423SLionel Sambuc } 120433d6423SLionel Sambuc 121433d6423SLionel Sambuc assert(addr >= region->vaddr); 122433d6423SLionel Sambuc offset = addr - region->vaddr; 123433d6423SLionel Sambuc 124433d6423SLionel Sambuc /* Access is allowed; handle it. */ 125433d6423SLionel Sambuc if(retry) { 126433d6423SLionel Sambuc result = map_pf(vmp, region, offset, wr, NULL, NULL, 0, &io); 127433d6423SLionel Sambuc assert(result != SUSPEND); 128433d6423SLionel Sambuc } else { 129433d6423SLionel Sambuc struct pf_state state; 130433d6423SLionel Sambuc state.ep = ep; 131433d6423SLionel Sambuc state.vaddr = addr; 132433d6423SLionel Sambuc state.err = err; 133433d6423SLionel Sambuc result = map_pf(vmp, region, offset, wr, pf_cont, 134433d6423SLionel Sambuc &state, sizeof(state), &io); 135433d6423SLionel Sambuc } 136433d6423SLionel Sambuc if (io) 137433d6423SLionel Sambuc vmp->vm_major_page_fault++; 138433d6423SLionel Sambuc else 139433d6423SLionel Sambuc vmp->vm_minor_page_fault++; 140433d6423SLionel Sambuc 141433d6423SLionel Sambuc if(result == SUSPEND) { 142433d6423SLionel Sambuc return; 143433d6423SLionel Sambuc } 144433d6423SLionel Sambuc 145433d6423SLionel Sambuc if(result != OK) { 146433d6423SLionel Sambuc printf("VM: pagefault: SIGSEGV %d pagefault not handled\n", ep); 147433d6423SLionel Sambuc if((s=sys_kill(ep, SIGSEGV)) != OK) 148433d6423SLionel Sambuc panic("sys_kill failed: %d", s); 149433d6423SLionel Sambuc if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, 0 /*unused*/)) != OK) 150433d6423SLionel Sambuc panic("do_pagefaults: sys_vmctl failed: %d", ep); 151433d6423SLionel Sambuc return; 152433d6423SLionel Sambuc } 153433d6423SLionel Sambuc 154433d6423SLionel Sambuc pt_clearmapcache(); 155433d6423SLionel Sambuc 156433d6423SLionel Sambuc /* Pagefault is handled, so now reactivate the process. */ 157433d6423SLionel Sambuc if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, 0 /*unused*/)) != OK) 158433d6423SLionel Sambuc panic("do_pagefaults: sys_vmctl failed: %d", ep); 159433d6423SLionel Sambuc } 160433d6423SLionel Sambuc 161433d6423SLionel Sambuc 162433d6423SLionel Sambuc static void pf_cont(struct vmproc *vmp, message *m, 163433d6423SLionel Sambuc void *arg, void *statearg) 164433d6423SLionel Sambuc { 165433d6423SLionel Sambuc struct pf_state *state = statearg; 166433d6423SLionel Sambuc int p; 167433d6423SLionel Sambuc if(vm_isokendpt(state->ep, &p) != OK) return; /* signal */ 168433d6423SLionel Sambuc handle_pagefault(state->ep, state->vaddr, state->err, 1); 169433d6423SLionel Sambuc } 170433d6423SLionel Sambuc 171433d6423SLionel Sambuc static void handle_memory_continue(struct vmproc *vmp, message *m, 172433d6423SLionel Sambuc void *arg, void *statearg) 173433d6423SLionel Sambuc { 174433d6423SLionel Sambuc int r; 175433d6423SLionel Sambuc struct hm_state *state = statearg; 176433d6423SLionel Sambuc assert(state); 177433d6423SLionel Sambuc assert(state->caller != NONE); 178433d6423SLionel Sambuc assert(state->valid == VALID); 179433d6423SLionel Sambuc 180433d6423SLionel Sambuc if(m->VMV_RESULT != OK) { 181433d6423SLionel Sambuc printf("VM: handle_memory_continue: vfs request failed\n"); 182433d6423SLionel Sambuc handle_memory_final(state, m->VMV_RESULT); 183433d6423SLionel Sambuc return; 184433d6423SLionel Sambuc } 185433d6423SLionel Sambuc 186*f202792eSDavid van Moolenbroek r = handle_memory_step(state, TRUE /*retry*/); 187433d6423SLionel Sambuc 188433d6423SLionel Sambuc assert(state->valid == VALID); 189433d6423SLionel Sambuc 190433d6423SLionel Sambuc if(r == SUSPEND) { 191433d6423SLionel Sambuc return; 192433d6423SLionel Sambuc } 193433d6423SLionel Sambuc 194433d6423SLionel Sambuc assert(state->valid == VALID); 195433d6423SLionel Sambuc 196433d6423SLionel Sambuc handle_memory_final(state, r); 197433d6423SLionel Sambuc } 198433d6423SLionel Sambuc 199433d6423SLionel Sambuc static void handle_memory_final(struct hm_state *state, int result) 200433d6423SLionel Sambuc { 201433d6423SLionel Sambuc int r; 202433d6423SLionel Sambuc 203433d6423SLionel Sambuc assert(state); 204433d6423SLionel Sambuc assert(state->valid == VALID); 205433d6423SLionel Sambuc 206433d6423SLionel Sambuc if(state->caller == KERNEL) { 207433d6423SLionel Sambuc if((r=sys_vmctl(state->requestor, VMCTL_MEMREQ_REPLY, result)) != OK) 208433d6423SLionel Sambuc panic("handle_memory_continue: sys_vmctl failed: %d", r); 209433d6423SLionel Sambuc } else if(state->caller != NONE) { 210433d6423SLionel Sambuc /* Send a reply msg */ 211433d6423SLionel Sambuc message msg; 212433d6423SLionel Sambuc memset(&msg, 0, sizeof(msg)); 213433d6423SLionel Sambuc msg.m_type = result; 214433d6423SLionel Sambuc 215433d6423SLionel Sambuc if(IS_VFS_FS_TRANSID(state->transid)) { 216433d6423SLionel Sambuc assert(state->caller == VFS_PROC_NR); 217433d6423SLionel Sambuc /* If a transaction ID was set, reset it */ 218433d6423SLionel Sambuc msg.m_type = TRNS_ADD_ID(msg.m_type, state->transid); 219433d6423SLionel Sambuc } 220433d6423SLionel Sambuc 221433d6423SLionel Sambuc if(asynsend3(state->caller, &msg, 0) != OK) { 222433d6423SLionel Sambuc panic("handle_memory_final: asynsend3 failed"); 223433d6423SLionel Sambuc } 224433d6423SLionel Sambuc 225433d6423SLionel Sambuc assert(state->valid == VALID); 226433d6423SLionel Sambuc 227433d6423SLionel Sambuc /* fail fast if anyone tries to access this state again */ 228433d6423SLionel Sambuc memset(state, 0, sizeof(*state)); 229433d6423SLionel Sambuc } 230433d6423SLionel Sambuc } 231433d6423SLionel Sambuc 232433d6423SLionel Sambuc /*===========================================================================* 233433d6423SLionel Sambuc * do_pagefaults * 234433d6423SLionel Sambuc *===========================================================================*/ 235433d6423SLionel Sambuc void do_pagefaults(message *m) 236433d6423SLionel Sambuc { 237433d6423SLionel Sambuc handle_pagefault(m->m_source, m->VPF_ADDR, m->VPF_FLAGS, 0); 238433d6423SLionel Sambuc } 239433d6423SLionel Sambuc 240433d6423SLionel Sambuc int handle_memory_once(struct vmproc *vmp, vir_bytes mem, vir_bytes len, 241433d6423SLionel Sambuc int wrflag) 242433d6423SLionel Sambuc { 243433d6423SLionel Sambuc int r; 244433d6423SLionel Sambuc r = handle_memory_start(vmp, mem, len, wrflag, NONE, NONE, 0, 0); 245433d6423SLionel Sambuc assert(r != SUSPEND); 246433d6423SLionel Sambuc return r; 247433d6423SLionel Sambuc } 248433d6423SLionel Sambuc 249433d6423SLionel Sambuc int handle_memory_start(struct vmproc *vmp, vir_bytes mem, vir_bytes len, 250433d6423SLionel Sambuc int wrflag, endpoint_t caller, endpoint_t requestor, int transid, 251433d6423SLionel Sambuc int vfs_avail) 252433d6423SLionel Sambuc { 253433d6423SLionel Sambuc int r; 254433d6423SLionel Sambuc struct hm_state state; 255433d6423SLionel Sambuc vir_bytes o; 256433d6423SLionel Sambuc 257433d6423SLionel Sambuc if((o = mem % PAGE_SIZE)) { 258433d6423SLionel Sambuc mem -= o; 259433d6423SLionel Sambuc len += o; 260433d6423SLionel Sambuc } 261433d6423SLionel Sambuc 262433d6423SLionel Sambuc len = roundup(len, PAGE_SIZE); 263433d6423SLionel Sambuc 264433d6423SLionel Sambuc state.vmp = vmp; 265433d6423SLionel Sambuc state.mem = mem; 266433d6423SLionel Sambuc state.len = len; 267433d6423SLionel Sambuc state.wrflag = wrflag; 268433d6423SLionel Sambuc state.requestor = requestor; 269433d6423SLionel Sambuc state.caller = caller; 270433d6423SLionel Sambuc state.transid = transid; 271433d6423SLionel Sambuc state.valid = VALID; 272433d6423SLionel Sambuc state.vfs_avail = vfs_avail; 273433d6423SLionel Sambuc 274*f202792eSDavid van Moolenbroek r = handle_memory_step(&state, FALSE /*retry*/); 275433d6423SLionel Sambuc 276433d6423SLionel Sambuc if(r == SUSPEND) { 277433d6423SLionel Sambuc assert(caller != NONE); 278433d6423SLionel Sambuc assert(vfs_avail); 279433d6423SLionel Sambuc } else { 280433d6423SLionel Sambuc handle_memory_final(&state, r); 281433d6423SLionel Sambuc } 282433d6423SLionel Sambuc 283433d6423SLionel Sambuc return r; 284433d6423SLionel Sambuc } 285433d6423SLionel Sambuc 286433d6423SLionel Sambuc /*===========================================================================* 287433d6423SLionel Sambuc * do_memory * 288433d6423SLionel Sambuc *===========================================================================*/ 289433d6423SLionel Sambuc void do_memory(void) 290433d6423SLionel Sambuc { 291433d6423SLionel Sambuc endpoint_t who, who_s, requestor; 292433d6423SLionel Sambuc vir_bytes mem, mem_s; 293433d6423SLionel Sambuc vir_bytes len; 294433d6423SLionel Sambuc int wrflag; 295433d6423SLionel Sambuc 296433d6423SLionel Sambuc while(1) { 297433d6423SLionel Sambuc int p, r = OK; 298433d6423SLionel Sambuc struct vmproc *vmp; 299433d6423SLionel Sambuc 300433d6423SLionel Sambuc r = sys_vmctl_get_memreq(&who, &mem, &len, &wrflag, &who_s, 301433d6423SLionel Sambuc &mem_s, &requestor); 302433d6423SLionel Sambuc 303433d6423SLionel Sambuc switch(r) { 304433d6423SLionel Sambuc case VMPTYPE_CHECK: 305433d6423SLionel Sambuc { 306433d6423SLionel Sambuc int transid = 0; 307433d6423SLionel Sambuc int vfs_avail; 308433d6423SLionel Sambuc 309433d6423SLionel Sambuc if(vm_isokendpt(who, &p) != OK) 310433d6423SLionel Sambuc panic("do_memory: bad endpoint: %d", who); 311433d6423SLionel Sambuc vmp = &vmproc[p]; 312433d6423SLionel Sambuc 313433d6423SLionel Sambuc assert(!IS_VFS_FS_TRANSID(transid)); 314433d6423SLionel Sambuc 315433d6423SLionel Sambuc /* is VFS blocked? */ 316433d6423SLionel Sambuc if(requestor == VFS_PROC_NR) vfs_avail = 0; 317433d6423SLionel Sambuc else vfs_avail = 1; 318433d6423SLionel Sambuc 319433d6423SLionel Sambuc handle_memory_start(vmp, mem, len, wrflag, 320433d6423SLionel Sambuc KERNEL, requestor, transid, vfs_avail); 321433d6423SLionel Sambuc 322433d6423SLionel Sambuc break; 323433d6423SLionel Sambuc } 324433d6423SLionel Sambuc 325433d6423SLionel Sambuc default: 326433d6423SLionel Sambuc return; 327433d6423SLionel Sambuc } 328433d6423SLionel Sambuc } 329433d6423SLionel Sambuc } 330433d6423SLionel Sambuc 331*f202792eSDavid van Moolenbroek static int handle_memory_step(struct hm_state *hmstate, int retry) 332433d6423SLionel Sambuc { 333433d6423SLionel Sambuc struct vir_region *region; 334*f202792eSDavid van Moolenbroek vir_bytes offset, length, sublen; 335*f202792eSDavid van Moolenbroek int r; 336433d6423SLionel Sambuc 337433d6423SLionel Sambuc /* Page-align memory and length. */ 338433d6423SLionel Sambuc assert(hmstate); 339433d6423SLionel Sambuc assert(hmstate->valid == VALID); 340433d6423SLionel Sambuc assert(!(hmstate->mem % VM_PAGE_SIZE)); 341433d6423SLionel Sambuc assert(!(hmstate->len % VM_PAGE_SIZE)); 342433d6423SLionel Sambuc 343433d6423SLionel Sambuc while(hmstate->len > 0) { 344433d6423SLionel Sambuc if(!(region = map_lookup(hmstate->vmp, hmstate->mem, NULL))) { 345433d6423SLionel Sambuc #if VERBOSE 346433d6423SLionel Sambuc map_printmap(hmstate->vmp); 347433d6423SLionel Sambuc printf("VM: do_memory: memory doesn't exist\n"); 348433d6423SLionel Sambuc #endif 349433d6423SLionel Sambuc return EFAULT; 350433d6423SLionel Sambuc } else if(!(region->flags & VR_WRITABLE) && hmstate->wrflag) { 351433d6423SLionel Sambuc #if VERBOSE 352433d6423SLionel Sambuc printf("VM: do_memory: write to unwritable map\n"); 353433d6423SLionel Sambuc #endif 354433d6423SLionel Sambuc return EFAULT; 355*f202792eSDavid van Moolenbroek } 356*f202792eSDavid van Moolenbroek 357433d6423SLionel Sambuc assert(region->vaddr <= hmstate->mem); 358433d6423SLionel Sambuc assert(!(region->vaddr % VM_PAGE_SIZE)); 359433d6423SLionel Sambuc offset = hmstate->mem - region->vaddr; 360*f202792eSDavid van Moolenbroek length = hmstate->len; 361*f202792eSDavid van Moolenbroek if (offset + length > region->length) 362*f202792eSDavid van Moolenbroek length = region->length - offset; 363433d6423SLionel Sambuc 364*f202792eSDavid van Moolenbroek /* 365*f202792eSDavid van Moolenbroek * Handle one page at a time. While it seems beneficial to 366*f202792eSDavid van Moolenbroek * handle multiple pages in one go, the opposite is true: 367*f202792eSDavid van Moolenbroek * map_handle_memory will handle one page at a time anyway, and 368*f202792eSDavid van Moolenbroek * if we give it the whole range multiple times, it will have 369*f202792eSDavid van Moolenbroek * to recheck pages it already handled. In addition, in order 370*f202792eSDavid van Moolenbroek * to handle one-shot pages, we need to know whether we are 371*f202792eSDavid van Moolenbroek * retrying a single page, and that is not possible if this is 372*f202792eSDavid van Moolenbroek * hidden in map_handle_memory. 373*f202792eSDavid van Moolenbroek */ 374*f202792eSDavid van Moolenbroek while (length > 0) { 375*f202792eSDavid van Moolenbroek sublen = VM_PAGE_SIZE; 376*f202792eSDavid van Moolenbroek 377*f202792eSDavid van Moolenbroek assert(sublen <= length); 378*f202792eSDavid van Moolenbroek assert(offset + sublen <= region->length); 379*f202792eSDavid van Moolenbroek 380*f202792eSDavid van Moolenbroek /* 381*f202792eSDavid van Moolenbroek * Upon the second try for this range, do not allow 382*f202792eSDavid van Moolenbroek * calling into VFS again. This prevents eternal loops 383*f202792eSDavid van Moolenbroek * in case the FS messes up, and allows one-shot pages 384*f202792eSDavid van Moolenbroek * to be mapped in on the second call. 385*f202792eSDavid van Moolenbroek */ 386433d6423SLionel Sambuc if((region->def_memtype == &mem_type_mappedfile && 387*f202792eSDavid van Moolenbroek (!hmstate->vfs_avail || retry)) || 388*f202792eSDavid van Moolenbroek hmstate->caller == NONE) { 389*f202792eSDavid van Moolenbroek r = map_handle_memory(hmstate->vmp, region, 390*f202792eSDavid van Moolenbroek offset, sublen, hmstate->wrflag, NULL, 391*f202792eSDavid van Moolenbroek NULL, 0); 392433d6423SLionel Sambuc assert(r != SUSPEND); 393433d6423SLionel Sambuc } else { 394*f202792eSDavid van Moolenbroek r = map_handle_memory(hmstate->vmp, region, 395*f202792eSDavid van Moolenbroek offset, sublen, hmstate->wrflag, 396*f202792eSDavid van Moolenbroek handle_memory_continue, hmstate, 397*f202792eSDavid van Moolenbroek sizeof(*hmstate)); 398433d6423SLionel Sambuc } 399433d6423SLionel Sambuc 400433d6423SLionel Sambuc if(r != OK) return r; 401433d6423SLionel Sambuc 402433d6423SLionel Sambuc hmstate->len -= sublen; 403433d6423SLionel Sambuc hmstate->mem += sublen; 404*f202792eSDavid van Moolenbroek 405*f202792eSDavid van Moolenbroek offset += sublen; 406*f202792eSDavid van Moolenbroek length -= sublen; 407*f202792eSDavid van Moolenbroek retry = FALSE; 408433d6423SLionel Sambuc } 409433d6423SLionel Sambuc } 410433d6423SLionel Sambuc 411433d6423SLionel Sambuc return OK; 412433d6423SLionel Sambuc } 413433d6423SLionel Sambuc 414