diff --git a/include/minix/com.h b/include/minix/com.h index 219345c0a..6377c6845 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -356,13 +356,12 @@ #define CP_DST_ENDPT m5_i2 /* process to copy to */ #define CP_DST_ADDR m5_l2 /* address where data go to */ #define CP_NR_BYTES m5_l3 /* number of bytes to copy */ +#define CP_FLAGS m5_s2 /* number of bytes to copy */ + +#define CP_FLAG_TRY 0x01 /* do not transparently map */ #define UMAP_SEG m5_s1 -/* only used for backwards compatability */ -#define CP_SRC_SPACE_OBSOLETE m5_s1 /* T or D space (stack is also D) */ -#define CP_DST_SPACE_OBSOLETE m5_s2 /* T or D space (stack is also D) */ - /* Field names for SYS_VUMAP. */ #define VUMAP_ENDPT m10_i1 /* grant owner, or SELF for local addresses */ #define VUMAP_VADDR m10_l1 /* address of virtual (input) vector */ @@ -476,7 +475,6 @@ /* Field names for SYS_SAFECOPY* */ #define SCP_FROM_TO m2_i1 /* from/to whom? */ -#define SCP_SEG_OBSOLETE m2_i2 /* my own segment */ #define SCP_GID m2_i3 /* grant id */ #define SCP_OFFSET m2_l1 /* offset within grant */ #define SCP_ADDRESS m2_p1 /* my own address */ @@ -493,8 +491,6 @@ #define VSCP_VEC_ADDR m2_p1 /* start of vector */ #define VSCP_VEC_SIZE m2_l2 /* elements in vector */ -#define SMAP_SEG_OBSOLETE m2_p1 - /* Field names for SYS_SPROF, _CPROF, _PROFBUF. */ #define PROF_ACTION m7_i1 /* start/stop/reset/get */ #define PROF_MEM_SIZE m7_i2 /* available memory for data */ @@ -936,10 +932,14 @@ /* same args as VM_REMAP */ #define VM_PROCCTL (VM_RQ_BASE+45) -#define VMPCTL_PARAM m1_i1 -#define VMPCTL_WHO m1_i2 +#define VMPCTL_PARAM m9_l1 +#define VMPCTL_WHO m9_l2 +#define VMPCTL_M1 m9_l3 +#define VMPCTL_LEN m9_l4 +#define VMPCTL_FLAGS m9_l5 #define VMPPARAM_CLEAR 1 /* values for VMPCTL_PARAM */ +#define VMPPARAM_HANDLEMEM 2 #define VM_VFS_MMAP (VM_RQ_BASE+46) diff --git a/include/minix/const.h b/include/minix/const.h index f6da60b86..5131e9a00 100644 --- a/include/minix/const.h +++ b/include/minix/const.h @@ -53,8 +53,6 @@ #define SEGMENT_TYPE 0xFF00 /* bit mask to get segment type */ #define SEGMENT_INDEX 0x00FF /* bit mask to get segment index */ -#define D_OBSOLETE 1 /* proc[i].mem_map[D] is for data */ - #define PHYS_SEG 0x0400 /* flag indicating entire physical memory */ #define LOCAL_VM_SEG 0x1000 /* same as LOCAL_SEG, but with vm lookup */ diff --git a/include/minix/safecopies.h b/include/minix/safecopies.h index aa35fc502..4d9b4e2e8 100644 --- a/include/minix/safecopies.h +++ b/include/minix/safecopies.h @@ -56,6 +56,9 @@ struct vscp_vec { #define CPF_READ 0x000001 /* Granted process may read. */ #define CPF_WRITE 0x000002 /* Granted process may write. */ +/* Grant flags. */ +#define CPF_TRY 0x000010 /* Fail fast on unmapped memory. */ + /* Internal flags. */ #define CPF_USED 0x000100 /* Grant slot in use. */ #define CPF_DIRECT 0x000200 /* Grant from this process to another. */ diff --git a/include/minix/syslib.h b/include/minix/syslib.h index f2c004051..834e0ee65 100644 --- a/include/minix/syslib.h +++ b/include/minix/syslib.h @@ -123,14 +123,15 @@ int sys_vtimer(endpoint_t proc_nr, int which, clock_t *newval, clock_t int sys_irqctl(int request, int irq_vec, int policy, int *irq_hook_id); /* Shorthands for sys_vircopy() and sys_physcopy() system calls. */ -#define sys_datacopy sys_vircopy +#define sys_datacopy(p1, v1, p2, v2, len) sys_vircopy(p1, v1, p2, v2, len, 0) +#define sys_datacopy_try(p1, v1, p2, v2, len) sys_vircopy(p1, v1, p2, v2, len, CP_FLAG_TRY) int sys_vircopy(endpoint_t src_proc, vir_bytes src_v, - endpoint_t dst_proc, vir_bytes dst_vir, phys_bytes bytes); + endpoint_t dst_proc, vir_bytes dst_vir, phys_bytes bytes, int flags); #define sys_abscopy(src_phys, dst_phys, bytes) \ - sys_physcopy(NONE, src_phys, NONE, dst_phys, bytes) + sys_physcopy(NONE, src_phys, NONE, dst_phys, bytes, 0) int sys_physcopy(endpoint_t src_proc, vir_bytes src_vir, - endpoint_t dst_proc, vir_bytes dst_vir, phys_bytes bytes); + endpoint_t dst_proc, vir_bytes dst_vir, phys_bytes bytes, int flags); /* Grant-based copy functions. */ diff --git a/include/minix/vm.h b/include/minix/vm.h index f748aade4..6dd94cb0f 100644 --- a/include/minix/vm.h +++ b/include/minix/vm.h @@ -67,7 +67,8 @@ int vm_info_stats(struct vm_stats_info *vfi); int vm_info_usage(endpoint_t who, struct vm_usage_info *vui); int vm_info_region(endpoint_t who, struct vm_region_info *vri, int count, vir_bytes *next); -int vm_procctl(endpoint_t ep, int param); +int vm_procctl_clear(endpoint_t ep); +int vm_procctl_handlemem(endpoint_t ep, vir_bytes m1, vir_bytes m2, int wr); int vm_set_cacheblock(void *block, dev_t dev, off_t dev_offset, ino_t ino, off_t ino_offset, u32_t *flags, int blocksize); diff --git a/kernel/arch/earm/memory.c b/kernel/arch/earm/memory.c index ee77a71b8..e8648897c 100644 --- a/kernel/arch/earm/memory.c +++ b/kernel/arch/earm/memory.c @@ -398,7 +398,8 @@ size_t vm_lookup_range(const struct proc *proc, vir_bytes vir_addr, * vm_suspend * *===========================================================================*/ static void vm_suspend(struct proc *caller, const struct proc *target, - const vir_bytes linaddr, const vir_bytes len, const int type) + const vir_bytes linaddr, const vir_bytes len, const int type, + const int writeflag) { /* This range is not OK for this process. Set parameters * of the request and notify VM about the pending request. @@ -412,7 +413,7 @@ static void vm_suspend(struct proc *caller, const struct proc *target, caller->p_vmrequest.target = target->p_endpoint; caller->p_vmrequest.params.check.start = linaddr; caller->p_vmrequest.params.check.length = len; - caller->p_vmrequest.params.check.writeflag = 1; + caller->p_vmrequest.params.check.writeflag = writeflag; caller->p_vmrequest.type = type; /* Connect caller on vmrequest wait queue. */ @@ -426,7 +427,7 @@ static void vm_suspend(struct proc *caller, const struct proc *target, * vm_check_range * *===========================================================================*/ int vm_check_range(struct proc *caller, struct proc *target, - vir_bytes vir_addr, size_t bytes) + vir_bytes vir_addr, size_t bytes, int writeflag) { /* Public interface to vm_suspend(), for use by kernel calls. On behalf * of 'caller', call into VM to check linear virtual address range of @@ -442,7 +443,8 @@ int vm_check_range(struct proc *caller, struct proc *target, (r = caller->p_vmrequest.vmresult) != OK) return r; - vm_suspend(caller, target, vir_addr, bytes, VMSTYPE_KERNELCALL); + vm_suspend(caller, target, vir_addr, bytes, VMSTYPE_KERNELCALL, + writeflag); return VMSUSPEND; } @@ -520,7 +522,7 @@ int vm_memset(struct proc* caller, endpoint_t who, phys_bytes ph, int c, /* If a process pagefaults, VM may help out */ if (whoptr) { vm_suspend(caller, whoptr, ph, count, - VMSTYPE_KERNELCALL); + VMSTYPE_KERNELCALL, 1); assert(catch_pagefaults); catch_pagefaults = 0; return VMSUSPEND; @@ -589,6 +591,7 @@ int vmcheck; /* if nonzero, can return VMSUSPEND */ if((r=lin_lin_copy(procs[_SRC_], vir_addr[_SRC_]->offset, procs[_DST_], vir_addr[_DST_]->offset, bytes)) != OK) { + int writeflag; struct proc *target = NULL; phys_bytes lin; if(r != EFAULT_SRC && r != EFAULT_DST) @@ -600,9 +603,11 @@ int vmcheck; /* if nonzero, can return VMSUSPEND */ if(r == EFAULT_SRC) { lin = vir_addr[_SRC_]->offset; target = procs[_SRC_]; + writeflag = 0; } else if(r == EFAULT_DST) { lin = vir_addr[_DST_]->offset; target = procs[_DST_]; + writeflag = 1; } else { panic("r strange: %d", r); } @@ -610,7 +615,7 @@ int vmcheck; /* if nonzero, can return VMSUSPEND */ assert(caller); assert(target); - vm_suspend(caller, target, lin, bytes, VMSTYPE_KERNELCALL); + vm_suspend(caller, target, lin, bytes, VMSTYPE_KERNELCALL, writeflag); return VMSUSPEND; } diff --git a/kernel/arch/i386/do_sdevio.c b/kernel/arch/i386/do_sdevio.c index 23ea4fa24..4e5a5924c 100644 --- a/kernel/arch/i386/do_sdevio.c +++ b/kernel/arch/i386/do_sdevio.c @@ -72,7 +72,7 @@ int do_sdevio(struct proc * caller, message *m_ptr) count, req_dir == _DIO_INPUT ? CPF_WRITE : CPF_READ, (vir_bytes) m_ptr->DIO_OFFSET, - &newoffset, &newep) != OK) { + &newoffset, &newep, NULL) != OK) { printf("do_sdevio: verify_grant failed\n"); return EPERM; } diff --git a/kernel/arch/i386/memory.c b/kernel/arch/i386/memory.c index 24b866f0b..320dbe12f 100644 --- a/kernel/arch/i386/memory.c +++ b/kernel/arch/i386/memory.c @@ -421,7 +421,8 @@ size_t vm_lookup_range(const struct proc *proc, vir_bytes vir_addr, * vm_suspend * *===========================================================================*/ static void vm_suspend(struct proc *caller, const struct proc *target, - const vir_bytes linaddr, const vir_bytes len, const int type) + const vir_bytes linaddr, const vir_bytes len, const int type, + const int writeflag) { /* This range is not OK for this process. Set parameters * of the request and notify VM about the pending request. @@ -437,7 +438,7 @@ static void vm_suspend(struct proc *caller, const struct proc *target, caller->p_vmrequest.target = target->p_endpoint; caller->p_vmrequest.params.check.start = linaddr; caller->p_vmrequest.params.check.length = len; - caller->p_vmrequest.params.check.writeflag = 1; + caller->p_vmrequest.params.check.writeflag = writeflag; caller->p_vmrequest.type = type; /* Connect caller on vmrequest wait queue. */ @@ -451,7 +452,7 @@ static void vm_suspend(struct proc *caller, const struct proc *target, * vm_check_range * *===========================================================================*/ int vm_check_range(struct proc *caller, struct proc *target, - vir_bytes vir_addr, size_t bytes) + vir_bytes vir_addr, size_t bytes, int writeflag) { /* Public interface to vm_suspend(), for use by kernel calls. On behalf * of 'caller', call into VM to check linear virtual address range of @@ -467,7 +468,8 @@ int vm_check_range(struct proc *caller, struct proc *target, (r = caller->p_vmrequest.vmresult) != OK) return r; - vm_suspend(caller, target, vir_addr, bytes, VMSTYPE_KERNELCALL); + vm_suspend(caller, target, vir_addr, bytes, VMSTYPE_KERNELCALL, + writeflag); return VMSUSPEND; } @@ -619,7 +621,7 @@ int vm_memset(struct proc* caller, endpoint_t who, phys_bytes ph, int c, /* If a process pagefaults, VM may help out */ if (whoptr) { vm_suspend(caller, whoptr, ph, count, - VMSTYPE_KERNELCALL); + VMSTYPE_KERNELCALL, 1); assert(catch_pagefaults); catch_pagefaults = 0; return VMSUSPEND; @@ -688,6 +690,7 @@ int vmcheck; /* if nonzero, can return VMSUSPEND */ if((r=lin_lin_copy(procs[_SRC_], vir_addr[_SRC_]->offset, procs[_DST_], vir_addr[_DST_]->offset, bytes)) != OK) { + int writeflag; struct proc *target = NULL; phys_bytes lin; if(r != EFAULT_SRC && r != EFAULT_DST) @@ -699,9 +702,11 @@ int vmcheck; /* if nonzero, can return VMSUSPEND */ if(r == EFAULT_SRC) { lin = vir_addr[_SRC_]->offset; target = procs[_SRC_]; + writeflag = 0; } else if(r == EFAULT_DST) { lin = vir_addr[_DST_]->offset; target = procs[_DST_]; + writeflag = 1; } else { panic("r strange: %d", r); } @@ -709,7 +714,7 @@ int vmcheck; /* if nonzero, can return VMSUSPEND */ assert(caller); assert(target); - vm_suspend(caller, target, lin, bytes, VMSTYPE_KERNELCALL); + vm_suspend(caller, target, lin, bytes, VMSTYPE_KERNELCALL, writeflag); return VMSUSPEND; } diff --git a/kernel/proto.h b/kernel/proto.h index 22ce09521..0400d6772 100644 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -138,7 +138,7 @@ void hook_ipc_clear(struct proc *proc); /* system/do_safecopy.c */ int verify_grant(endpoint_t, endpoint_t, cp_grant_id_t, vir_bytes, int, - vir_bytes, vir_bytes *, endpoint_t *); + vir_bytes, vir_bytes *, endpoint_t *, u32_t *); /* system/do_diagctl.c */ int do_diagctl(struct proc * caller, message *m); @@ -211,7 +211,7 @@ int arch_phys_map_reply(int index, vir_bytes addr); reg_t arch_get_sp(struct proc *p); int arch_enable_paging(struct proc * caller); int vm_check_range(struct proc *caller, - struct proc *target, vir_bytes vir_addr, size_t bytes); + struct proc *target, vir_bytes vir_addr, size_t bytes, int writable); int copy_msg_from_user(message * user_mbuf, message * dst); int copy_msg_to_user(message * src, message * user_mbuf); diff --git a/kernel/system/do_copy.c b/kernel/system/do_copy.c index e40cdeb23..2fb61a2a4 100644 --- a/kernel/system/do_copy.c +++ b/kernel/system/do_copy.c @@ -10,7 +10,9 @@ */ #include "kernel/system.h" +#include "kernel/vm.h" #include +#include #if (USE_VIRCOPY || USE_PHYSCOPY) @@ -75,8 +77,16 @@ int do_copy(struct proc * caller, message * m_ptr) if (bytes != (phys_bytes) (vir_bytes) bytes) return(E2BIG); /* Now try to make the actual virtual copy. */ - return( virtual_copy_vmcheck(caller, &vir_addr[_SRC_], + if(m_ptr->CP_FLAGS & CP_FLAG_TRY) { + int r; + assert(caller->p_endpoint == VFS_PROC_NR); + r = virtual_copy(&vir_addr[_SRC_], &vir_addr[_DST_], bytes); + if(r == EFAULT_SRC || r == EFAULT_DST) return r = EFAULT; + return r; + } else { + return( virtual_copy_vmcheck(caller, &vir_addr[_SRC_], &vir_addr[_DST_], bytes) ); + } } #endif /* (USE_VIRCOPY || USE_PHYSCOPY) */ diff --git a/kernel/system/do_safecopy.c b/kernel/system/do_safecopy.c index 80d38fcb3..62cb6a7c0 100644 --- a/kernel/system/do_safecopy.c +++ b/kernel/system/do_safecopy.c @@ -17,6 +17,7 @@ #include "kernel/system.h" #include "kernel/kernel.h" +#include "kernel/vm.h" #define MAX_INDIRECT_DEPTH 5 /* up to how many indirect grants to follow? */ @@ -32,7 +33,7 @@ static int safecopy(struct proc *, endpoint_t, endpoint_t, * verify_grant * *===========================================================================*/ int verify_grant(granter, grantee, grant, bytes, access, - offset_in, offset_result, e_granter) + offset_in, offset_result, e_granter, flags) endpoint_t granter, grantee; /* copyee, copyer */ cp_grant_id_t grant; /* grant id */ vir_bytes bytes; /* copy size */ @@ -40,6 +41,7 @@ int access; /* direction (read/write) */ vir_bytes offset_in; /* copy offset within grant */ vir_bytes *offset_result; /* copy offset within virtual address space */ endpoint_t *e_granter; /* new granter (magic grants) */ +u32_t *flags; /* CPF_* */ { static cp_grant_t g; static int proc_nr; @@ -96,6 +98,8 @@ endpoint_t *e_granter; /* new granter (magic grants) */ return EPERM; } + if(flags) *flags = g.cp_flags; + /* Check validity. */ if((g.cp_flags & (CPF_USED | CPF_VALID)) != (CPF_USED | CPF_VALID)) { @@ -241,6 +245,7 @@ int access; /* CPF_READ for a copy from granter to grantee, CPF_WRITE endpoint_t new_granter, *src, *dst; struct proc *granter_p; int r; + u32_t flags; #if PERF_USE_COW_SAFECOPY vir_bytes size; #endif @@ -269,7 +274,7 @@ int access; /* CPF_READ for a copy from granter to grantee, CPF_WRITE /* Verify permission exists. */ if((r=verify_grant(granter, grantee, grantid, bytes, access, - g_offset, &v_offset, &new_granter)) != OK) { + g_offset, &v_offset, &new_granter, &flags)) != OK) { printf( "grant %d verify to copy %d->%d by %d failed: err %d\n", grantid, *src, *dst, grantee, r); @@ -298,6 +303,13 @@ int access; /* CPF_READ for a copy from granter to grantee, CPF_WRITE } /* Do the regular copy. */ + if(flags & CPF_TRY) { + int r; + /* Try copy without transparently faulting in pages. */ + r = virtual_copy(&v_src, &v_dst, bytes); + if(r == EFAULT_SRC || r == EFAULT_DST) return EFAULT; + return r; + } return virtual_copy_vmcheck(caller, &v_src, &v_dst, bytes); } diff --git a/kernel/system/do_safememset.c b/kernel/system/do_safememset.c index cdd127f85..0f9deda38 100644 --- a/kernel/system/do_safememset.c +++ b/kernel/system/do_safememset.c @@ -47,7 +47,7 @@ int do_safememset(struct proc *caller, message *m_ptr) { /* Verify permission exists, memset always requires CPF_WRITE */ r = verify_grant(dst_endpt, caller_endpt, grantid, len, CPF_WRITE, - g_offset, &v_offset, &new_granter); + g_offset, &v_offset, &new_granter, NULL); if (r != OK) { printf("safememset: grant %d verify failed %d", grantid, r); diff --git a/kernel/system/do_umap_remote.c b/kernel/system/do_umap_remote.c index 9d0b4065e..7e9c10fc1 100644 --- a/kernel/system/do_umap_remote.c +++ b/kernel/system/do_umap_remote.c @@ -64,7 +64,7 @@ int do_umap_remote(struct proc * caller, message * m_ptr) cp_grant_id_t grant = (cp_grant_id_t) offset; if(verify_grant(targetpr->p_endpoint, grantee, grant, count, - 0, 0, &newoffset, &newep) != OK) { + 0, 0, &newoffset, &newep, NULL) != OK) { printf("SYSTEM: do_umap: verify_grant in %s, grant %d, bytes 0x%lx, failed, caller %s\n", targetpr->p_name, offset, count, caller->p_name); proc_stacktrace(caller); return EFAULT; diff --git a/kernel/system/do_vumap.c b/kernel/system/do_vumap.c index 56bd635f4..e3fc3152b 100644 --- a/kernel/system/do_vumap.c +++ b/kernel/system/do_vumap.c @@ -78,7 +78,7 @@ int do_vumap(struct proc *caller, message *m_ptr) if (source != SELF) { r = verify_grant(source, endpt, vvec[i].vv_grant, size, access, - offset, &vir_addr, &granter); + offset, &vir_addr, &granter, NULL); if (r != OK) return r; } else { @@ -103,7 +103,7 @@ int do_vumap(struct proc *caller, message *m_ptr) /* This call may suspend the current call, or return an * error for a previous invocation. */ - return vm_check_range(caller, procp, vir_addr, size); + return vm_check_range(caller, procp, vir_addr, size, 1); } pvec[pcount].vp_addr = phys_addr; diff --git a/lib/libexec/exec_general.c b/lib/libexec/exec_general.c index 8b6367913..e590bf2dd 100644 --- a/lib/libexec/exec_general.c +++ b/lib/libexec/exec_general.c @@ -53,7 +53,7 @@ int libexec_alloc_mmap_ondemand(struct exec_info *execi, vir_bytes vaddr, size_t int libexec_clearproc_vm_procctl(struct exec_info *execi) { - return vm_procctl(execi->proc_e, VMPPARAM_CLEAR); + return vm_procctl_clear(execi->proc_e); } int libexec_clear_sys_memset(struct exec_info *execi, vir_bytes vaddr, size_t len) diff --git a/lib/libsys/safecopies.c b/lib/libsys/safecopies.c index 9342cf552..3cce51b48 100644 --- a/lib/libsys/safecopies.c +++ b/lib/libsys/safecopies.c @@ -16,7 +16,7 @@ #include #define ACCESS_CHECK(a) { \ - if((a) & ~(CPF_READ|CPF_WRITE)) { \ + if((a) & ~(CPF_READ|CPF_WRITE|CPF_TRY)) { \ errno = EINVAL; \ return -1; \ } \ diff --git a/lib/libsys/sys_physcopy.c b/lib/libsys/sys_physcopy.c index 3698332df..28fc890a8 100644 --- a/lib/libsys/sys_physcopy.c +++ b/lib/libsys/sys_physcopy.c @@ -1,11 +1,12 @@ #include "syslib.h" -int sys_physcopy(src_proc, src_vir, dst_proc, dst_vir, bytes) +int sys_physcopy(src_proc, src_vir, dst_proc, dst_vir, bytes, flags) endpoint_t src_proc; /* source process */ vir_bytes src_vir; /* source virtual address */ endpoint_t dst_proc; /* destination process */ vir_bytes dst_vir; /* destination virtual address */ phys_bytes bytes; /* how many bytes */ +int flags; /* copy flags */ { /* Transfer a block of data. The source and destination can each either be a * process number or SELF (to indicate own process number). Virtual addresses @@ -21,12 +22,7 @@ phys_bytes bytes; /* how many bytes */ copy_mess.CP_DST_ENDPT = dst_proc; copy_mess.CP_DST_ADDR = (long) dst_vir; copy_mess.CP_NR_BYTES = (long) bytes; - - /* provide backwards compatability arguments to old - * kernels based on process id's; NONE <=> physical - */ - copy_mess.CP_DST_SPACE_OBSOLETE = (dst_proc == NONE ? PHYS_SEG : D_OBSOLETE); - copy_mess.CP_SRC_SPACE_OBSOLETE = (src_proc == NONE ? PHYS_SEG : D_OBSOLETE); + copy_mess.CP_FLAGS = flags; return(_kernel_call(SYS_PHYSCOPY, ©_mess)); } diff --git a/lib/libsys/sys_safecopy.c b/lib/libsys/sys_safecopy.c index 4140b12a4..a9fae0edd 100644 --- a/lib/libsys/sys_safecopy.c +++ b/lib/libsys/sys_safecopy.c @@ -19,11 +19,6 @@ int sys_safecopyfrom(endpoint_t src_e, copy_mess.SCP_ADDRESS = (char *) address; copy_mess.SCP_BYTES = (long) bytes; - /* for older kernels that still need the 'seg' field - * provide the right value. - */ - copy_mess.SCP_SEG_OBSOLETE = D_OBSOLETE; - return(_kernel_call(SYS_SAFECOPYFROM, ©_mess)); } @@ -44,11 +39,6 @@ int sys_safecopyto(endpoint_t dst_e, copy_mess.SCP_ADDRESS = (char *) address; copy_mess.SCP_BYTES = (long) bytes; - /* for older kernels that still need the 'seg' field - * provide the right value. - */ - copy_mess.SCP_SEG_OBSOLETE = D_OBSOLETE; - return(_kernel_call(SYS_SAFECOPYTO, ©_mess)); } diff --git a/lib/libsys/sys_vircopy.c b/lib/libsys/sys_vircopy.c index 29e8d2c66..55a6b4a55 100644 --- a/lib/libsys/sys_vircopy.c +++ b/lib/libsys/sys_vircopy.c @@ -1,30 +1,28 @@ #include "syslib.h" int sys_vircopy(src_proc, src_vir, - dst_proc, dst_vir, bytes) + dst_proc, dst_vir, bytes, flags) endpoint_t src_proc; /* source process */ vir_bytes src_vir; /* source virtual address */ endpoint_t dst_proc; /* destination process */ vir_bytes dst_vir; /* destination virtual address */ phys_bytes bytes; /* how many bytes */ +int flags; /* copy flags */ { /* Transfer a block of data. The source and destination can each either be a - * process number or SELF (to indicate own process number). Virtual addresses - * are offsets within LOCAL_SEG (text, stack, data), or BIOS_SEG. + * process number or SELF (to indicate own process number). */ message copy_mess; if (bytes == 0L) return(OK); + memset(©_mess, 0, sizeof(copy_mess)); copy_mess.CP_SRC_ENDPT = src_proc; copy_mess.CP_SRC_ADDR = (long) src_vir; copy_mess.CP_DST_ENDPT = dst_proc; copy_mess.CP_DST_ADDR = (long) dst_vir; copy_mess.CP_NR_BYTES = (long) bytes; - - /* backwards compatability D segs */ - copy_mess.CP_DST_SPACE_OBSOLETE = D_OBSOLETE; - copy_mess.CP_SRC_SPACE_OBSOLETE = D_OBSOLETE; + copy_mess.CP_FLAGS = flags; return(_kernel_call(SYS_VIRCOPY, ©_mess)); } diff --git a/lib/libsys/vm_procctl.c b/lib/libsys/vm_procctl.c index dad82b9ce..84e1dba5c 100644 --- a/lib/libsys/vm_procctl.c +++ b/lib/libsys/vm_procctl.c @@ -5,9 +5,10 @@ #include /*===========================================================================* - * vm_exit * + * vm_procctl * *===========================================================================*/ -int vm_procctl(endpoint_t ep, int param) +static int vm_procctl(endpoint_t ep, int param, + vir_bytes m1, vir_bytes len, int flags) { message m; int result; @@ -16,8 +17,22 @@ int vm_procctl(endpoint_t ep, int param) m.VMPCTL_WHO = ep; m.VMPCTL_PARAM = param; + m.VMPCTL_M1 = m1; + m.VMPCTL_LEN = len; + m.VMPCTL_FLAGS = flags; result = _taskcall(VM_PROC_NR, VM_PROCCTL, &m); return(result); } +int vm_procctl_clear(endpoint_t ep) +{ + return vm_procctl(ep, VMPPARAM_CLEAR, 0, 0, 0); +} + +int vm_procctl_handlemem(endpoint_t ep, vir_bytes m1, vir_bytes len, + int writeflag) +{ + return vm_procctl(ep, VMPPARAM_HANDLEMEM, m1, len, writeflag); +} + diff --git a/servers/pm/misc.c b/servers/pm/misc.c index 0e409e018..fcdda46a2 100644 --- a/servers/pm/misc.c +++ b/servers/pm/misc.c @@ -92,7 +92,7 @@ int do_sysuname() /* Copy an uname string to the user. */ n = strlen(string) + 1; if (n > m_in.PM_SYSUNAME_LEN) n = m_in.PM_SYSUNAME_LEN; - r = sys_vircopy(SELF, (phys_bytes) string, + r = sys_datacopy(SELF, (phys_bytes) string, mp->mp_endpoint, (phys_bytes) m_in.PM_SYSUNAME_VALUE, (phys_bytes) n); if (r < 0) return(r); @@ -105,7 +105,7 @@ int do_sysuname() if (mp->mp_effuid != 0 || len == 0) return(EPERM); n = len < m_in.PM_SYSUNAME_LEN ? len : m_in.PM_SYSUNAME_LEN; if (n <= 0) return(EINVAL); - r = sys_vircopy(mp->mp_endpoint, (phys_bytes) m_in.PM_SYSUNAME_VALUE, + r = sys_datacopy(mp->mp_endpoint, (phys_bytes) m_in.PM_SYSUNAME_VALUE, SELF, (phys_bytes) tmp, (phys_bytes) n); if (r < 0) return(r); tmp[n-1] = 0; diff --git a/servers/pm/trace.c b/servers/pm/trace.c index 8644477c8..33c578440 100644 --- a/servers/pm/trace.c +++ b/servers/pm/trace.c @@ -175,11 +175,11 @@ int do_trace() if (req == T_GETRANGE) r = sys_vircopy(child->mp_endpoint, (vir_bytes) pr.pr_addr, who_e, (vir_bytes) pr.pr_ptr, - (phys_bytes) pr.pr_size); + (phys_bytes) pr.pr_size, 0); else r = sys_vircopy(who_e, (vir_bytes) pr.pr_ptr, child->mp_endpoint, (vir_bytes) pr.pr_addr, - (phys_bytes) pr.pr_size); + (phys_bytes) pr.pr_size, 0); if (r != OK) return(r); diff --git a/servers/rs/exec.c b/servers/rs/exec.c index b8215d270..09e0b9a0b 100644 --- a/servers/rs/exec.c +++ b/servers/rs/exec.c @@ -160,7 +160,7 @@ size_t seg_bytes /* how much is to be transferred? */ int r; if (off+seg_bytes > execi->hdr_len) return ENOEXEC; - if((r= sys_vircopy(SELF, ((vir_bytes)execi->hdr)+off, + if((r= sys_datacopy(SELF, ((vir_bytes)execi->hdr)+off, execi->proc_e, seg_addr, seg_bytes)) != OK) { printf("RS: exec read_seg: copy 0x%x bytes into %i at 0x%08lx failed: %i\n", seg_bytes, execi->proc_e, seg_addr, r); diff --git a/servers/rs/request.c b/servers/rs/request.c index a9480e624..9212998e4 100755 --- a/servers/rs/request.c +++ b/servers/rs/request.c @@ -913,7 +913,7 @@ message *m_ptr; return EINVAL; } - if((r=sys_vircopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_NAME, + if((r=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_NAME, SELF, (vir_bytes) namebuf, len)) != OK) { printf("RS: name copy failed\n"); return r; diff --git a/servers/vfs/comm.c b/servers/vfs/comm.c index 71e8fcaaa..663caebb2 100644 --- a/servers/vfs/comm.c +++ b/servers/vfs/comm.c @@ -1,27 +1,29 @@ #include "fs.h" #include #include +#include -static int sendmsg(struct vmnt *vmp, struct worker_thread *wp); +static int sendmsg(struct vmnt *vmp, endpoint_t dst, struct worker_thread *wp); static int queuemsg(struct vmnt *vmp); /*===========================================================================* * sendmsg * *===========================================================================*/ -static int sendmsg(struct vmnt *vmp, struct worker_thread *wp) +static int sendmsg(struct vmnt *vmp, endpoint_t dst, struct worker_thread *wp) { -/* This is the low level function that sends requests to FS processes. +/* This is the low level function that sends requests. + * Currently to FSes or VM. */ int r, transid; - vmp->m_comm.c_cur_reqs++; /* One more request awaiting a reply */ + if(vmp) vmp->m_comm.c_cur_reqs++; /* One more request awaiting a reply */ transid = wp->w_tid + VFS_TRANSID; - wp->w_fs_sendrec->m_type = TRNS_ADD_ID(wp->w_fs_sendrec->m_type, transid); - wp->w_task = vmp->m_fs_e; - if ((r = asynsend3(vmp->m_fs_e, wp->w_fs_sendrec, AMF_NOREPLY)) != OK) { + wp->w_sendrec->m_type = TRNS_ADD_ID(wp->w_sendrec->m_type, transid); + wp->w_task = dst; + if ((r = asynsend3(dst, wp->w_sendrec, AMF_NOREPLY)) != OK) { printf("VFS: sendmsg: error sending message. " - "FS_e: %d req_nr: %d err: %d\n", vmp->m_fs_e, - wp->w_fs_sendrec->m_type, r); + "dest: %d req_nr: %d err: %d\n", dst, + wp->w_sendrec->m_type, r); util_stacktrace(); return(r); } @@ -78,7 +80,7 @@ void fs_sendmore(struct vmnt *vmp) worker->w_next = NULL; sending--; assert(sending >= 0); - (void) sendmsg(vmp, worker); + (void) sendmsg(vmp, vmp->m_fs_e, worker); } /*===========================================================================* @@ -139,13 +141,13 @@ int fs_sendrec(endpoint_t fs_e, message *reqmp) } if (fs_e == fp->fp_endpoint) return(EDEADLK); - self->w_fs_sendrec = reqmp; /* Where to store request and reply */ + self->w_sendrec = reqmp; /* Where to store request and reply */ /* Find out whether we can send right away or have to enqueue */ if ( !(vmp->m_flags & VMNT_CALLBACK) && vmp->m_comm.c_cur_reqs < vmp->m_comm.c_max_reqs) { /* There's still room to send more and no proc is queued */ - r = sendmsg(vmp, self); + r = sendmsg(vmp, vmp->m_fs_e, self); } else { r = queuemsg(vmp); } @@ -158,6 +160,53 @@ int fs_sendrec(endpoint_t fs_e, message *reqmp) return(reqmp->m_type); } +/*===========================================================================* + * vm_sendrec * + *===========================================================================*/ +int vm_sendrec(message *reqmp) +{ + int r; + + assert(self); + assert(reqmp); + + self->w_sendrec = reqmp; /* Where to store request and reply */ + + r = sendmsg(NULL, VM_PROC_NR, self); + + self->w_next = NULL; /* End of list */ + + if (r != OK) return(r); + + worker_wait(); /* Yield execution until we've received the reply. */ + + return(reqmp->m_type); +} + + +/*===========================================================================* + * vm_vfs_procctl_handlemem * + *===========================================================================*/ +int vm_vfs_procctl_handlemem(endpoint_t ep, + vir_bytes mem, vir_bytes len, int flags) +{ + message m; + + /* main thread can not be suspended */ + if(!self) return EFAULT; + + memset(&m, 0, sizeof(m)); + + m.m_type = VM_PROCCTL; + m.VMPCTL_WHO = ep; + m.VMPCTL_PARAM = VMPPARAM_HANDLEMEM; + m.VMPCTL_M1 = mem; + m.VMPCTL_LEN = len; + m.VMPCTL_FLAGS = flags; + + return vm_sendrec(&m); +} + /*===========================================================================* * queuemsg * *===========================================================================*/ diff --git a/servers/vfs/coredump.c b/servers/vfs/coredump.c index a4068d14d..0de129240 100644 --- a/servers/vfs/coredump.c +++ b/servers/vfs/coredump.c @@ -303,7 +303,7 @@ static void dump_segments(struct filp *f, Elf_Phdr phdrs[], int phnum) for (off = 0; off < (off_t) len; off += CLICK_SIZE) { vir_bytes p = (vir_bytes) (seg_off + off); - r = sys_vircopy(fp->fp_endpoint, p, + r = sys_datacopy_try(fp->fp_endpoint, p, SELF, (vir_bytes) buf, (phys_bytes) CLICK_SIZE); diff --git a/servers/vfs/dmap.c b/servers/vfs/dmap.c index 6a411661c..b4cbe131a 100644 --- a/servers/vfs/dmap.c +++ b/servers/vfs/dmap.c @@ -129,7 +129,8 @@ int do_mapdriver(void) printf("VFS: do_mapdriver: label too long\n"); return(EINVAL); } - r = sys_vircopy(who_e, label_vir, SELF, (vir_bytes) label, label_len); + r = sys_vircopy(who_e, label_vir, SELF, (vir_bytes) label, label_len, + CP_FLAG_TRY); if (r != OK) { printf("VFS: do_mapdriver: sys_vircopy failed: %d\n", r); return(EINVAL); diff --git a/servers/vfs/exec.c b/servers/vfs/exec.c index ca12ddd28..14c36a172 100644 --- a/servers/vfs/exec.c +++ b/servers/vfs/exec.c @@ -228,7 +228,7 @@ int pm_exec(vir_bytes path, size_t path_len, vir_bytes frame, size_t frame_len, if (frame_len > ARG_MAX) FAILCHECK(ENOMEM); /* stack too big */ - r = sys_datacopy(fp->fp_endpoint, (vir_bytes) frame, SELF, (vir_bytes) mbuf, + r = sys_datacopy_wrapper(fp->fp_endpoint, (vir_bytes) frame, SELF, (vir_bytes) mbuf, (size_t) frame_len); if (r != OK) { /* can't fetch stack (e.g. bad virtual addr) */ printf("VFS: pm_exec: sys_datacopy failed\n"); @@ -362,7 +362,7 @@ int pm_exec(vir_bytes path, size_t path_len, vir_bytes frame, size_t frame_len, if(makestack) FAILCHECK(makestack(&execi, mbuf, &frame_len, &vsp)); /* Copy the stack from VFS to new core image. */ - FAILCHECK(sys_datacopy(SELF, (vir_bytes) mbuf, fp->fp_endpoint, + FAILCHECK(sys_datacopy_wrapper(SELF, (vir_bytes) mbuf, fp->fp_endpoint, (vir_bytes) vsp, (phys_bytes)frame_len)); /* Return new stack pointer to caller */ diff --git a/servers/vfs/lock.c b/servers/vfs/lock.c index 30fc30bc5..e9c63fcdd 100644 --- a/servers/vfs/lock.c +++ b/servers/vfs/lock.c @@ -31,7 +31,7 @@ int req; /* either F_SETLK or F_SETLKW */ struct file_lock *flp, *flp2, *empty; /* Fetch the flock structure from user space. */ - r = sys_datacopy(who_e, (vir_bytes) scratch(fp).io.io_buffer, VFS_PROC_NR, + r = sys_datacopy_wrapper(who_e, (vir_bytes) scratch(fp).io.io_buffer, VFS_PROC_NR, (vir_bytes) &flock, sizeof(flock)); if (r != OK) return(EINVAL); @@ -141,7 +141,7 @@ int req; /* either F_SETLK or F_SETLKW */ } /* Copy the flock structure back to the caller. */ - r = sys_datacopy(VFS_PROC_NR, (vir_bytes) &flock, who_e, + r = sys_datacopy_wrapper(VFS_PROC_NR, (vir_bytes) &flock, who_e, (vir_bytes) scratch(fp).io.io_buffer, sizeof(flock)); return(r); } diff --git a/servers/vfs/main.c b/servers/vfs/main.c index 1e0099767..e781a4997 100644 --- a/servers/vfs/main.c +++ b/servers/vfs/main.c @@ -35,7 +35,7 @@ EXTERN unsigned long calls_stats[NR_VFS_CALLS]; #endif /* Thread related prototypes */ -static void do_fs_reply(struct worker_thread *wp); +static void do_reply(struct worker_thread *wp); static void do_work(void); static void do_init_root(void); static void handle_work(void (*func)(void)); @@ -86,7 +86,7 @@ int main(void) continue; } m_in.m_type = TRNS_DEL_ID(m_in.m_type); - do_fs_reply(wp); + do_reply(wp); continue; } else if (who_e == PM_PROC_NR) { /* Calls from PM */ /* Special control messages from PM */ @@ -179,22 +179,22 @@ static void handle_work(void (*func)(void)) /*===========================================================================* - * do_fs_reply * + * do_reply * *===========================================================================*/ -static void do_fs_reply(struct worker_thread *wp) +static void do_reply(struct worker_thread *wp) { - struct vmnt *vmp; + struct vmnt *vmp = NULL; - if ((vmp = find_vmnt(who_e)) == NULL) + if(who_e != VM_PROC_NR && (vmp = find_vmnt(who_e)) == NULL) panic("Couldn't find vmnt for endpoint %d", who_e); if (wp->w_task != who_e) { - printf("VFS: expected %d to reply, not %d\n", wp->w_task, who_e); - return; + printf("VFS: tid %d: expected %d to reply, not %d\n", + wp->w_tid, wp->w_task, who_e); } - *wp->w_fs_sendrec = m_in; + *wp->w_sendrec = m_in; wp->w_task = NONE; - vmp->m_comm.c_cur_reqs--; /* We've got our reply, make room for others */ + if(vmp) vmp->m_comm.c_cur_reqs--; /* We've got our reply, make room for others */ worker_signal(wp); /* Continue this thread */ } diff --git a/servers/vfs/misc.c b/servers/vfs/misc.c index 7dcbb3276..d9548cbda 100644 --- a/servers/vfs/misc.c +++ b/servers/vfs/misc.c @@ -89,7 +89,7 @@ int do_getsysinfo(void) if (len != buf_size) return(EINVAL); - return sys_datacopy(SELF, src_addr, who_e, dst_addr, len); + return sys_datacopy_wrapper(SELF, src_addr, who_e, dst_addr, len); } /*===========================================================================* @@ -170,7 +170,7 @@ int do_fcntl(void) else if (!(f->filp_mode & W_BIT)) r = EBADF; else { /* Copy flock data from userspace. */ - r = sys_datacopy(who_e, (vir_bytes) scratch(fp).io.io_buffer, + r = sys_datacopy_wrapper(who_e, (vir_bytes) scratch(fp).io.io_buffer, SELF, (vir_bytes) &flock_arg, sizeof(flock_arg)); } @@ -709,7 +709,7 @@ gid_t *groups; rfp = &fproc[slot]; if (ngroups * sizeof(gid_t) > sizeof(rfp->fp_sgroups)) panic("VFS: pm_setgroups: too much data to copy"); - if (sys_datacopy(who_e, (vir_bytes) groups, SELF, (vir_bytes) rfp->fp_sgroups, + if (sys_datacopy_wrapper(who_e, (vir_bytes) groups, SELF, (vir_bytes) rfp->fp_sgroups, ngroups * sizeof(gid_t)) == OK) { rfp->fp_ngroups = ngroups; } else @@ -775,7 +775,7 @@ int do_svrctl(void) int r, s; /* Copy sysgetenv structure to VFS */ - if (sys_datacopy(who_e, ptr, SELF, (vir_bytes) &sysgetenv, + if (sys_datacopy_wrapper(who_e, ptr, SELF, (vir_bytes) &sysgetenv, sizeof(sysgetenv)) != OK) return(EFAULT); @@ -790,7 +790,7 @@ int do_svrctl(void) } /* Copy parameter "key" */ - if ((s = sys_datacopy(who_e, (vir_bytes) sysgetenv.key, + if ((s = sys_datacopy_wrapper(who_e, (vir_bytes) sysgetenv.key, SELF, (vir_bytes) search_key, sysgetenv.keylen)) != OK) return(s); @@ -800,7 +800,7 @@ int do_svrctl(void) if (svrctl == VFSSETPARAM) { if (!strcmp(search_key, "verbose")) { int verbose_val; - if ((s = sys_datacopy(who_e, + if ((s = sys_datacopy_wrapper(who_e, (vir_bytes) sysgetenv.val, SELF, (vir_bytes) &val, sysgetenv.vallen)) != OK) return(s); @@ -832,12 +832,12 @@ int do_svrctl(void) } if (r == OK) { - if ((s = sys_datacopy(SELF, + if ((s = sys_datacopy_wrapper(SELF, (vir_bytes) &sysgetenv, who_e, ptr, sizeof(sysgetenv))) != OK) return(s); if (sysgetenv.val != 0) { - if ((s = sys_datacopy(SELF, + if ((s = sys_datacopy_wrapper(SELF, (vir_bytes) small_buf, who_e, (vir_bytes) sysgetenv.val, sysgetenv.vallen)) != OK) @@ -875,7 +875,7 @@ int pm_dumpcore(int csig, vir_bytes exe_name) if (core_fd < 0) { r = core_fd; goto core_exit; } /* get process' name */ - r = sys_datacopy(PM_PROC_NR, exe_name, VFS_PROC_NR, (vir_bytes) proc_name, + r = sys_datacopy_wrapper(PM_PROC_NR, exe_name, VFS_PROC_NR, (vir_bytes) proc_name, PROC_NAME_LEN); if (r != OK) goto core_exit; proc_name[PROC_NAME_LEN - 1] = '\0'; @@ -943,7 +943,7 @@ int do_getrusage(void) int res; struct rusage r_usage; - if ((res = sys_datacopy(who_e, (vir_bytes) m_in.RU_RUSAGE_ADDR, SELF, + if ((res = sys_datacopy_wrapper(who_e, (vir_bytes) m_in.RU_RUSAGE_ADDR, SELF, (vir_bytes) &r_usage, (vir_bytes) sizeof(r_usage))) < 0) return res; @@ -953,6 +953,6 @@ int do_getrusage(void) r_usage.ru_idrss = fp->data_size; r_usage.ru_isrss = DEFAULT_STACK_LIMIT; - return sys_datacopy(SELF, (vir_bytes) &r_usage, who_e, + return sys_datacopy_wrapper(SELF, (vir_bytes) &r_usage, who_e, (vir_bytes) m_in.RU_RUSAGE_ADDR, (phys_bytes) sizeof(r_usage)); } diff --git a/servers/vfs/mount.c b/servers/vfs/mount.c index a97d1ea01..6d8ef411c 100644 --- a/servers/vfs/mount.c +++ b/servers/vfs/mount.c @@ -109,7 +109,7 @@ int do_mount(void) /* Get the label from the caller, and ask DS for the endpoint of the FS. */ if (label_len > sizeof(mount_label)) return EINVAL; - r = sys_datacopy(who_e, label, SELF, (vir_bytes) mount_label, + r = sys_datacopy_wrapper(who_e, label, SELF, (vir_bytes) mount_label, sizeof(mount_label)); if (r != OK) return(r); @@ -446,7 +446,7 @@ int do_umount(void) */ if (strlen(label) >= label_len) label[label_len-1] = 0; - return sys_datacopy(SELF, (vir_bytes) label, who_e, label_addr, + return sys_datacopy_wrapper(SELF, (vir_bytes) label, who_e, label_addr, strlen(label) + 1); } diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index 941072e07..cdf98fc59 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -24,8 +24,10 @@ struct job; int drv_sendrec(endpoint_t drv_e, message *reqm); void fs_cancel(struct vmnt *vmp); int fs_sendrec(endpoint_t fs_e, message *reqm); +int vm_sendrec(message *reqm); void fs_sendmore(struct vmnt *vmp); void send_work(void); +int vm_vfs_procctl_handlemem(endpoint_t ep, vir_bytes mem, vir_bytes len, int flags); /* device.c */ int cdev_open(dev_t dev, int flags); @@ -277,6 +279,8 @@ int copy_path(char *dest, size_t size); int fetch_name(vir_bytes path, size_t len, char *dest); int isokendpt_f(const char *f, int l, endpoint_t e, int *p, int ft); int in_group(struct fproc *rfp, gid_t grp); +int sys_datacopy_wrapper(endpoint_t src, vir_bytes srcv, endpoint_t dst, vir_bytes dstv, + size_t len); #define okendpt(e, p) isokendpt_f(__FILE__, __LINE__, (e), (p), 1) #define isokendpt(e, p) isokendpt_f(__FILE__, __LINE__, (e), (p), 0) diff --git a/servers/vfs/request.c b/servers/vfs/request.c index 09389dc1a..a68d2eea9 100644 --- a/servers/vfs/request.c +++ b/servers/vfs/request.c @@ -25,26 +25,18 @@ /*===========================================================================* - * req_breadwrite * + * req_breadwrite_actual * *===========================================================================*/ -int req_breadwrite( - endpoint_t fs_e, - endpoint_t user_e, - dev_t dev, - off_t pos, - unsigned int num_of_bytes, - vir_bytes user_addr, - int rw_flag, - off_t *new_pos, - unsigned int *cum_iop -) +static int req_breadwrite_actual(endpoint_t fs_e, endpoint_t user_e, dev_t dev, off_t pos, + unsigned int num_of_bytes, vir_bytes user_addr, int rw_flag, + off_t *new_pos, unsigned int *cum_iop, int cpflag) { int r; cp_grant_id_t grant_id; message m; grant_id = cpf_grant_magic(fs_e, user_e, user_addr, num_of_bytes, - (rw_flag == READING ? CPF_WRITE : CPF_READ)); + (rw_flag == READING ? CPF_WRITE : CPF_READ) | cpflag); if(grant_id == -1) panic("req_breadwrite: cpf_grant_magic failed"); @@ -67,6 +59,28 @@ int req_breadwrite( return(OK); } +int req_breadwrite(endpoint_t fs_e, endpoint_t user_e, dev_t dev, off_t pos, + unsigned int num_of_bytes, vir_bytes user_addr, int rw_flag, + off_t *new_pos, unsigned int *cum_iop) +{ + int r; + + r = req_breadwrite_actual(fs_e, user_e, dev, pos, num_of_bytes, + user_addr, rw_flag, new_pos, cum_iop, CPF_TRY); + + if(r == EFAULT) { + if((r=vm_vfs_procctl_handlemem(user_e, user_addr, num_of_bytes, + rw_flag == READING)) != OK) { + return r; + } + + r = req_breadwrite_actual(fs_e, user_e, dev, pos, num_of_bytes, + user_addr, rw_flag, new_pos, cum_iop, 0); + } + + return r; +} + /*===========================================================================* * req_bpeek * *===========================================================================*/ @@ -267,16 +281,17 @@ int req_ftrunc(endpoint_t fs_e, ino_t inode_nr, off_t start, off_t end) /*===========================================================================* - * req_getdents * + * req_getdents_actual * *===========================================================================*/ -int req_getdents( +static int req_getdents_actual( endpoint_t fs_e, ino_t inode_nr, off_t pos, char *buf, size_t size, off_t *new_pos, - int direct + int direct, + int cpflag ) { int r; @@ -291,7 +306,7 @@ int req_getdents( grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, size, CPF_WRITE); } else { grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, size, - CPF_WRITE); + CPF_WRITE | cpflag); } if (grant_id < 0) @@ -319,6 +334,36 @@ int req_getdents( return(r); } +/*===========================================================================* + * req_getdents * + *===========================================================================*/ +int req_getdents( + endpoint_t fs_e, + ino_t inode_nr, + off_t pos, + char *buf, + size_t size, + off_t *new_pos, + int direct) +{ + int r; + + r = req_getdents_actual(fs_e, inode_nr, pos, buf, size, new_pos, + direct, CPF_TRY); + + if(r == EFAULT && !direct) { + if((r=vm_vfs_procctl_handlemem(who_e, (vir_bytes) buf, + size, 1)) != OK) { + return r; + } + + r = req_getdents_actual(fs_e, inode_nr, pos, buf, size, + new_pos, direct, 0); + } + + return r; +} + /*===========================================================================* * req_inhibread * *===========================================================================*/ @@ -665,15 +710,12 @@ int count; /*===========================================================================* - * req_rdlink * + * req_rdlink_actual * *===========================================================================*/ -int req_rdlink(fs_e, inode_nr, proc_e, buf, len, direct) -endpoint_t fs_e; -ino_t inode_nr; -endpoint_t proc_e; -vir_bytes buf; -size_t len; -int direct; /* set to 1 to use direct grants instead of magic grants */ +static int req_rdlink_actual(endpoint_t fs_e, ino_t inode_nr, + endpoint_t proc_e, vir_bytes buf, size_t len, + int direct, /* set to 1 to use direct grants instead of magic grants */ + int cpflag) { message m; int r; @@ -682,7 +724,7 @@ int direct; /* set to 1 to use direct grants instead of magic grants */ if (direct) { grant_id = cpf_grant_direct(fs_e, buf, len, CPF_WRITE); } else { - grant_id = cpf_grant_magic(fs_e, proc_e, buf, len, CPF_WRITE); + grant_id = cpf_grant_magic(fs_e, proc_e, buf, len, CPF_WRITE | cpflag); } if (grant_id == -1) panic("req_rdlink: cpf_grant_magic failed"); @@ -702,6 +744,30 @@ int direct; /* set to 1 to use direct grants instead of magic grants */ return(r); } +/*===========================================================================* + * req_rdlink * + *===========================================================================*/ +int req_rdlink(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, + vir_bytes buf, size_t len, + int direct /* set to 1 to use direct grants instead of magic grants */ +) +{ + int r; + + r = req_rdlink_actual(fs_e, inode_nr, proc_e, buf, len, direct, + CPF_TRY); + + if(r == EFAULT && !direct) { + if((r=vm_vfs_procctl_handlemem(proc_e, buf, len, 1)) != OK) { + return r; + } + + r = req_rdlink_actual(fs_e, inode_nr, proc_e, buf, len, + direct, 0); + } + + return r; +} /*===========================================================================* * req_readsuper * @@ -758,18 +824,12 @@ int req_readsuper( /*===========================================================================* - * req_readwrite * + * req_readwrite_actual * *===========================================================================*/ -int req_readwrite( -endpoint_t fs_e, -ino_t inode_nr, -off_t pos, -int rw_flag, -endpoint_t user_e, -vir_bytes user_addr, -unsigned int num_of_bytes, -off_t *new_posp, -unsigned int *cum_iop) +static int req_readwrite_actual(endpoint_t fs_e, ino_t inode_nr, off_t pos, + int rw_flag, endpoint_t user_e, vir_bytes user_addr, + unsigned int num_of_bytes, off_t *new_posp, unsigned int *cum_iop, + int cpflag) { struct vmnt *vmp; int r; @@ -779,7 +839,7 @@ unsigned int *cum_iop) vmp = find_vmnt(fs_e); grant_id = cpf_grant_magic(fs_e, user_e, user_addr, num_of_bytes, - (rw_flag==READING ? CPF_WRITE:CPF_READ)); + (rw_flag==READING ? CPF_WRITE:CPF_READ) | cpflag); if (grant_id == -1) panic("req_readwrite: cpf_grant_magic failed"); @@ -806,6 +866,31 @@ unsigned int *cum_iop) return(r); } +/*===========================================================================* + * req_readwrite * + *===========================================================================*/ +int req_readwrite(endpoint_t fs_e, ino_t inode_nr, off_t pos, + int rw_flag, endpoint_t user_e, vir_bytes user_addr, + unsigned int num_of_bytes, off_t *new_posp, unsigned int *cum_iop) +{ + int r; + + r = req_readwrite_actual(fs_e, inode_nr, pos, rw_flag, user_e, + user_addr, num_of_bytes, new_posp, cum_iop, CPF_TRY); + + if(r == EFAULT) { + if((r=vm_vfs_procctl_handlemem(user_e, (vir_bytes) user_addr, num_of_bytes, + rw_flag == READING)) != OK) { + return r; + } + + r = req_readwrite_actual(fs_e, inode_nr, pos, rw_flag, user_e, + user_addr, num_of_bytes, new_posp, cum_iop, 0); + } + + return r; +} + /*===========================================================================* * req_peek * *===========================================================================*/ @@ -905,9 +990,9 @@ char *lastc; /*===========================================================================* - * req_slink * + * req_slink_actual * *===========================================================================*/ -int req_slink( +static int req_slink_actual( endpoint_t fs_e, ino_t inode_nr, char *lastc, @@ -915,7 +1000,8 @@ int req_slink( vir_bytes path_addr, size_t path_length, uid_t uid, - gid_t gid + gid_t gid, + int cpflag ) { int r; @@ -928,7 +1014,9 @@ int req_slink( if (gid_name == GRANT_INVALID) panic("req_slink: cpf_grant_direct failed"); - gid_buf = cpf_grant_magic(fs_e, proc_e, path_addr, path_length, CPF_READ); + gid_buf = cpf_grant_magic(fs_e, proc_e, path_addr, path_length, + CPF_READ | cpflag); + if (gid_buf == GRANT_INVALID) { cpf_revoke(gid_name); panic("req_slink: cpf_grant_magic failed"); @@ -952,18 +1040,51 @@ int req_slink( return(r); } +/*===========================================================================* + * req_slink * + *===========================================================================*/ +int req_slink( + endpoint_t fs_e, + ino_t inode_nr, + char *lastc, + endpoint_t proc_e, + vir_bytes path_addr, + size_t path_length, + uid_t uid, + gid_t gid +) +{ + int r; + + r = req_slink_actual(fs_e, inode_nr, lastc, proc_e, path_addr, + path_length, uid, gid, CPF_TRY); + + if(r == EFAULT) { + if((r=vm_vfs_procctl_handlemem(proc_e, (vir_bytes) path_addr, + path_length, 0)) != OK) { + return r; + } + + r = req_slink_actual(fs_e, inode_nr, lastc, proc_e, path_addr, + path_length, uid, gid, 0); + } + + return r; +} /*===========================================================================* - * req_stat * + * req_stat_actual * *===========================================================================*/ -int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, vir_bytes buf) +int req_stat_actual(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, + vir_bytes buf, int cpflag) { cp_grant_id_t grant_id; int r; message m; /* Grant FS access to copy straight into user provided buffer */ - grant_id = cpf_grant_magic(fs_e, proc_e, buf, sizeof(struct stat), CPF_WRITE); + grant_id = cpf_grant_magic(fs_e, proc_e, buf, sizeof(struct stat), + CPF_WRITE | cpflag); if (grant_id < 0) panic("req_stat: cpf_grant_* failed"); @@ -981,6 +1102,28 @@ int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, vir_bytes buf) } +/*===========================================================================* + * req_stat * + *===========================================================================*/ +int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, + vir_bytes buf) +{ + int r; + + r = req_stat_actual(fs_e, inode_nr, proc_e, buf, CPF_TRY); + + if(r == EFAULT) { + if((r=vm_vfs_procctl_handlemem(proc_e, (vir_bytes) buf, + sizeof(struct stat), 1)) != OK) { + return r; + } + + r = req_stat_actual(fs_e, inode_nr, proc_e, buf, 0); + } + + return r; +} + /*===========================================================================* * req_sync * *===========================================================================*/ diff --git a/servers/vfs/select.c b/servers/vfs/select.c index 537e4d879..945be2cf8 100644 --- a/servers/vfs/select.c +++ b/servers/vfs/select.c @@ -126,7 +126,7 @@ int do_select(void) /* Did the process set a timeout value? If so, retrieve it. */ if (vtimeout != 0) { do_timeout = 1; - r = sys_vircopy(who_e, (vir_bytes) vtimeout, SELF, + r = sys_datacopy_wrapper(who_e, (vir_bytes) vtimeout, SELF, (vir_bytes) &timeout, sizeof(timeout)); if (r != OK) { se->requestor = NULL; @@ -535,7 +535,7 @@ static int copy_fdsets(struct selectentry *se, int nfds, int direction) src_fds = (direction == FROM_PROC) ? se->vir_readfds : &se->ready_readfds; dst_fds = (direction == FROM_PROC) ? &se->readfds : se->vir_readfds; if (se->vir_readfds) { - r = sys_vircopy(src_e, (vir_bytes) src_fds, dst_e, + r = sys_datacopy_wrapper(src_e, (vir_bytes) src_fds, dst_e, (vir_bytes) dst_fds, fd_setsize); if (r != OK) return(r); } @@ -544,7 +544,7 @@ static int copy_fdsets(struct selectentry *se, int nfds, int direction) src_fds = (direction == FROM_PROC) ? se->vir_writefds : &se->ready_writefds; dst_fds = (direction == FROM_PROC) ? &se->writefds : se->vir_writefds; if (se->vir_writefds) { - r = sys_vircopy(src_e, (vir_bytes) src_fds, dst_e, + r = sys_datacopy_wrapper(src_e, (vir_bytes) src_fds, dst_e, (vir_bytes) dst_fds, fd_setsize); if (r != OK) return(r); } @@ -553,7 +553,7 @@ static int copy_fdsets(struct selectentry *se, int nfds, int direction) src_fds = (direction == FROM_PROC) ? se->vir_errorfds : &se->ready_errorfds; dst_fds = (direction == FROM_PROC) ? &se->errorfds : se->vir_errorfds; if (se->vir_errorfds) { - r = sys_vircopy(src_e, (vir_bytes) src_fds, dst_e, + r = sys_datacopy_wrapper(src_e, (vir_bytes) src_fds, dst_e, (vir_bytes) dst_fds, fd_setsize); if (r != OK) return(r); } diff --git a/servers/vfs/stadir.c b/servers/vfs/stadir.c index 971fc6830..b8dfc087f 100644 --- a/servers/vfs/stadir.c +++ b/servers/vfs/stadir.c @@ -284,7 +284,8 @@ static int fill_statvfs(struct vmnt *vmp, endpoint_t endpt, vir_bytes buf_addr, strlcpy(buf.f_mntonname, vmp->m_mount_path, sizeof(buf.f_mntonname)); strlcpy(buf.f_mntfromname, vmp->m_mount_dev, sizeof(buf.f_mntfromname)); - return sys_datacopy(SELF, (vir_bytes) &buf, endpt, buf_addr, sizeof(buf)); + return sys_datacopy_wrapper(SELF, (vir_bytes) &buf, + endpt, buf_addr, sizeof(buf)); } /*===========================================================================* diff --git a/servers/vfs/threads.h b/servers/vfs/threads.h index 6758cd123..b4a30689d 100644 --- a/servers/vfs/threads.h +++ b/servers/vfs/threads.h @@ -31,7 +31,7 @@ struct worker_thread { message w_m_in; message w_m_out; int w_err_code; - message *w_fs_sendrec; + message *w_sendrec; message *w_drv_sendrec; endpoint_t w_task; struct dmap *w_dmap; diff --git a/servers/vfs/utility.c b/servers/vfs/utility.c index b3437edbe..4f4e4ed49 100644 --- a/servers/vfs/utility.c +++ b/servers/vfs/utility.c @@ -75,7 +75,7 @@ int fetch_name(vir_bytes path, size_t len, char *dest) } /* String is not contained in the message. Get it from user space. */ - r = sys_datacopy(who_e, path, VFS_PROC_NR, (vir_bytes) dest, len); + r = sys_datacopy_wrapper(who_e, path, VFS_PROC_NR, (vir_bytes) dest, len); if (r != OK) { err_code = EINVAL; return(r); @@ -164,3 +164,52 @@ int in_group(struct fproc *rfp, gid_t grp) return(EINVAL); } + +/*===========================================================================* + * sys_datacopy_wrapper * + *===========================================================================*/ +int sys_datacopy_wrapper(endpoint_t src, vir_bytes srcv, + endpoint_t dst, vir_bytes dstv, size_t len) +{ + /* Safe function to copy data from or to a user buffer. + * VFS has to be a bit more careful as a regular copy + * might trigger VFS action needed by VM while it's + * blocked on the kernel call. This wrapper tries the + * copy, invokes VM itself asynchronously if necessary, + * then tries the copy again. + * + * This function assumes it's between VFS and a user process, + * and therefore one of the endpoints is SELF (VFS). + */ + int r; + endpoint_t them = NONE; + vir_bytes themv = -1; + int writable = -1; + + r = sys_datacopy_try(src, srcv, dst, dstv, len); + + if(src == VFS_PROC_NR) src = SELF; + if(dst == VFS_PROC_NR) dst = SELF; + + assert(src == SELF || dst == SELF); + + if(src == SELF) { them = dst; themv = dstv; writable = 1; } + if(dst == SELF) { them = src; themv = srcv; writable = 0; } + + assert(writable >= 0); + assert(them != SELF); + + if(r == EFAULT) { + /* The copy has failed with EFAULT, this means the kernel has + * given up but it might not be a legitimate error. Ask VM. + */ + if((r=vm_vfs_procctl_handlemem(them, themv, len, writable)) != OK) { + return r; + } + + r = sys_datacopy_try(src, srcv, dst, dstv, len); + } + + return r; +} + diff --git a/servers/vfs/vnode.c b/servers/vfs/vnode.c index 438c057ba..a45b3d885 100644 --- a/servers/vfs/vnode.c +++ b/servers/vfs/vnode.c @@ -47,7 +47,7 @@ void check_vnode_locks_by_me(struct fproc *rfp) for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) { if (tll_locked_by_me(&vp->v_lock)) { - panic("Thread %d still holds vnode lock on vp %x call_nr=%d\n", + panic("Thread %d still holds vnode lock on vp %p call_nr=%d\n", mthread_self(), vp, job_call_nr); } } diff --git a/servers/vfs/worker.c b/servers/vfs/worker.c index 8c1f0d771..fe026a6f2 100644 --- a/servers/vfs/worker.c +++ b/servers/vfs/worker.c @@ -37,6 +37,7 @@ void worker_init(void) wp->w_fp = NULL; /* Mark not in use */ wp->w_next = NULL; + wp->w_task = NONE; if (mutex_init(&wp->w_event_mutex, NULL) != 0) panic("failed to initialize mutex"); if (cond_init(&wp->w_event, NULL) != 0) @@ -397,8 +398,8 @@ void worker_stop(struct worker_thread *worker) /* This thread is communicating with a driver or file server */ if (worker->w_drv_sendrec != NULL) { /* Driver */ worker->w_drv_sendrec->m_type = EIO; - } else if (worker->w_fs_sendrec != NULL) { /* FS */ - worker->w_fs_sendrec->m_type = EIO; + } else if (worker->w_sendrec != NULL) { /* FS */ + worker->w_sendrec->m_type = EIO; } else { panic("reply storage consistency error"); /* Oh dear */ } diff --git a/servers/vm/alloc.c b/servers/vm/alloc.c index 2f1ea32fe..3ba55bdeb 100644 --- a/servers/vm/alloc.c +++ b/servers/vm/alloc.c @@ -46,7 +46,7 @@ static phys_bytes alloc_pages(int pages, int flags); #if SANITYCHECKS struct { int used; - char *file; + const char *file; int line; } pagemap[NUMBER_PHYSICAL_PAGES]; #endif @@ -335,7 +335,7 @@ void mem_init(struct memory *chunks) } #if SANITYCHECKS -void mem_sanitycheck(char *file, int line) +void mem_sanitycheck(const char *file, int line) { int i; for(i = 0; i < NUMBER_PHYSICAL_PAGES; i++) { @@ -506,7 +506,7 @@ void usedpages_reset(void) /*===========================================================================* * usedpages_add * *===========================================================================*/ -int usedpages_add_f(phys_bytes addr, phys_bytes len, char *file, int line) +int usedpages_add_f(phys_bytes addr, phys_bytes len, const char *file, int line) { u32_t pagestart, pages; @@ -525,7 +525,6 @@ int usedpages_add_f(phys_bytes addr, phys_bytes len, char *file, int line) assert(pagestart > 0); assert(pagestart < NUMBER_PHYSICAL_PAGES); thisaddr = pagestart * VM_PAGE_SIZE; - assert(pagestart >= 0); assert(pagestart < NUMBER_PHYSICAL_PAGES); if(pagemap[pagestart].used) { static int warnings = 0; diff --git a/servers/vm/exit.c b/servers/vm/exit.c index ea829d7a6..a62a7d490 100644 --- a/servers/vm/exit.c +++ b/servers/vm/exit.c @@ -111,13 +111,13 @@ int do_willexit(message *msg) return OK; } -int do_procctl(message *msg) +int do_procctl(message *msg, int transid) { endpoint_t proc; struct vmproc *vmp; if(vm_isokendpt(msg->VMPCTL_WHO, &proc) != OK) { - printf("VM: bogus endpoint VM_PROCCTL %d\n", + printf("VM: bogus endpoint VM_PROCCTL %ld\n", msg->VMPCTL_WHO); return EINVAL; } @@ -133,11 +133,21 @@ int do_procctl(message *msg) panic("VMPPARAM_CLEAR: pt_new failed"); pt_bind(&vmp->vm_pt, vmp); return OK; + case VMPPARAM_HANDLEMEM: + { + if(msg->m_source != VFS_PROC_NR) + return EPERM; + + handle_memory_start(vmp, msg->VMPCTL_M1, + msg->VMPCTL_LEN, msg->VMPCTL_FLAGS, + VFS_PROC_NR, VFS_PROC_NR, transid, 1); + + return SUSPEND; + } default: return EINVAL; } - return OK; } diff --git a/servers/vm/fork.c b/servers/vm/fork.c index 50d9ea4bd..806fe38a9 100644 --- a/servers/vm/fork.c +++ b/servers/vm/fork.c @@ -101,10 +101,10 @@ int do_fork(message *msg) * and its return value needn't be checked. */ vir = msgaddr; - if (handle_memory(vmc, vir, sizeof(message), 1, NULL, 0, 0) != OK) + if (handle_memory_once(vmc, vir, sizeof(message), 1) != OK) panic("do_fork: handle_memory for child failed\n"); vir = msgaddr; - if (handle_memory(vmp, vir, sizeof(message), 1, NULL, 0, 0) != OK) + if (handle_memory_once(vmp, vir, sizeof(message), 1) != OK) panic("do_fork: handle_memory for parent failed\n"); } diff --git a/servers/vm/glo.h b/servers/vm/glo.h index 880aca934..d4c1e71b1 100644 --- a/servers/vm/glo.h +++ b/servers/vm/glo.h @@ -25,7 +25,7 @@ EXTERN kinfo_t kernel_boot_info; EXTERN int nocheck; EXTERN int incheck; EXTERN int sc_lastline; -EXTERN char *sc_lastfile; +EXTERN const char *sc_lastfile; #endif extern struct minix_kerninfo *_minix_kerninfo; diff --git a/servers/vm/main.c b/servers/vm/main.c index 9a926e027..8fbb769d2 100644 --- a/servers/vm/main.c +++ b/servers/vm/main.c @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -90,7 +91,8 @@ int main(void) /* This is VM's main loop. */ while (TRUE) { int r, c; - int type, param; + int type; + int transid = 0; /* VFS transid if any */ SANITYCHECK(SCL_TOP); if(missing_spares > 0) { @@ -109,13 +111,22 @@ int main(void) if(vm_isokendpt(who_e, &caller_slot) != OK) panic("invalid caller %d", who_e); - type = param = msg.m_type; - type &= 0x0000FFFF; - param >>= 16; + /* We depend on this being false for the initialized value. */ + assert(!IS_VFS_FS_TRANSID(transid)); + + type = msg.m_type; c = CALLNUMBER(type); result = ENOSYS; /* Out of range or restricted calls return this. */ - - if(msg.m_type == RS_INIT && msg.m_source == RS_PROC_NR) { + + transid = TRNS_GET_ID(msg.m_type); + + if((msg.m_source == VFS_PROC_NR) && IS_VFS_FS_TRANSID(transid)) { + /* If it's a request from VFS, it might have a transaction id. */ + msg.m_type = TRNS_DEL_ID(msg.m_type); + + /* Calls that use the transid */ + result = do_procctl(&msg, transid); + } else if(msg.m_type == RS_INIT && msg.m_source == RS_PROC_NR) { result = do_rs_init(&msg); } else if (msg.m_type == VM_PAGEFAULT) { if (!IPC_STATUS_FLAGS_TEST(rcv_sts, IPC_FLG_MSG_FROM_KERNEL)) { @@ -147,6 +158,9 @@ int main(void) */ if(result != SUSPEND) { msg.m_type = result; + + assert(!IS_VFS_FS_TRANSID(transid)); + if((r=ipc_send(who_e, &msg)) != OK) { printf("VM: couldn't send %d to %d (err %d)\n", msg.m_type, who_e, r); @@ -223,7 +237,7 @@ static int libexec_copy_physcopy(struct exec_info *execi, end = ei->ip->start_addr + ei->ip->len; assert(ei->ip->start_addr + off + len <= end); return sys_physcopy(NONE, ei->ip->start_addr + off, - execi->proc_e, vaddr, len); + execi->proc_e, vaddr, len, 0); } static void boot_alloc(struct exec_info *execi, off_t vaddr, @@ -279,7 +293,7 @@ static void exec_bootproc(struct vmproc *vmp, struct boot_image *ip) panic("VM: pt_bind failed"); if(sys_physcopy(NONE, ip->start_addr, SELF, - (vir_bytes) hdr, sizeof(hdr)) != OK) + (vir_bytes) hdr, sizeof(hdr), 0) != OK) panic("can't look at boot proc header"); execi->stack_high = kernel_boot_info.user_sp; @@ -320,7 +334,7 @@ static void exec_bootproc(struct vmproc *vmp, struct boot_image *ip) minix_stack_fill(path, argc, argv, envc, envp, frame_size, frame, &vsp, &psp); - if(handle_memory(vmp, vsp, frame_size, 1, NULL, NULL, 0) != OK) + if(handle_memory_once(vmp, vsp, frame_size, 1) != OK) panic("vm: could not map stack for boot process %s (ep=%d)\n", execi->progname, vmp->vm_endpoint); @@ -338,6 +352,15 @@ static void exec_bootproc(struct vmproc *vmp, struct boot_image *ip) panic("VMCTL_BOOTINHIBIT_CLEAR failed"); } +static int do_procctl_notrans(message *msg) +{ + int transid = 0; + + assert(!IS_VFS_FS_TRANSID(transid)); + + return do_procctl(msg, transid); +} + void init_vm(void) { int s, i; @@ -459,6 +482,8 @@ void init_vm(void) CALLMAP(VM_WILLEXIT, do_willexit); CALLMAP(VM_NOTIFY_SIG, do_notify_sig); + CALLMAP(VM_PROCCTL, do_procctl_notrans); + /* Calls from VFS. */ CALLMAP(VM_VFS_REPLY, do_vfs_reply); CALLMAP(VM_VFS_MMAP, do_vfs_mmap); @@ -468,9 +493,6 @@ void init_vm(void) CALLMAP(VM_RS_UPDATE, do_rs_update); CALLMAP(VM_RS_MEMCTL, do_rs_memctl); - /* Calls from RS/VFS */ - CALLMAP(VM_PROCCTL, do_procctl); - /* Generic calls. */ CALLMAP(VM_REMAP, do_remap); CALLMAP(VM_REMAP_RO, do_remap); diff --git a/servers/vm/mem_anon.c b/servers/vm/mem_anon.c index 68a7813e9..172e30ed9 100644 --- a/servers/vm/mem_anon.c +++ b/servers/vm/mem_anon.c @@ -24,7 +24,7 @@ static int anon_unreference(struct phys_region *pr); static int anon_pagefault(struct vmproc *vmp, struct vir_region *region, struct phys_region *ph, int write, vfs_callback_t cb, void *state, int len, int *io); -static int anon_sanitycheck(struct phys_region *pr, char *file, int line); +static int anon_sanitycheck(struct phys_region *pr, const char *file, int line); static int anon_writable(struct phys_region *pr); static int anon_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l); static u32_t anon_regionid(struct vir_region *region); @@ -87,8 +87,7 @@ static int anon_pagefault(struct vmproc *vmp, struct vir_region *region, } if(ph->ph->refcount < 2 || !write) { - printf("anon_pagefault: %d refcount, %d write - not handling pagefault\n", - ph->ph->refcount, write); + /* memory is ready already */ return OK; } @@ -97,7 +96,7 @@ static int anon_pagefault(struct vmproc *vmp, struct vir_region *region, return mem_cow(region, ph, new_page_cl, new_page); } -static int anon_sanitycheck(struct phys_region *pr, char *file, int line) +static int anon_sanitycheck(struct phys_region *pr, const char *file, int line) { MYASSERT(usedpages_add(pr->ph->phys, VM_PAGE_SIZE) == OK); return OK; diff --git a/servers/vm/mem_anon_contig.c b/servers/vm/mem_anon_contig.c index 4b09ec52f..d2f063df1 100644 --- a/servers/vm/mem_anon_contig.c +++ b/servers/vm/mem_anon_contig.c @@ -13,7 +13,7 @@ static int anon_contig_unreference(struct phys_region *pr); static int anon_contig_pagefault(struct vmproc *vmp, struct vir_region *region, struct phys_region *ph, int write, vfs_callback_t cb, void *state, int len, int *io); -static int anon_contig_sanitycheck(struct phys_region *pr, char *file, int line); +static int anon_contig_sanitycheck(struct phys_region *pr, const char *file, int line); static int anon_contig_writable(struct phys_region *pr); static int anon_contig_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l); static int anon_contig_new(struct vir_region *vr); @@ -111,7 +111,7 @@ static int anon_contig_unreference(struct phys_region *pr) return mem_type_anon.ev_unreference(pr); } -static int anon_contig_sanitycheck(struct phys_region *pr, char *file, int line) +static int anon_contig_sanitycheck(struct phys_region *pr, const char *file, int line) { return mem_type_anon.ev_sanitycheck(pr, file, line); } diff --git a/servers/vm/mem_cache.c b/servers/vm/mem_cache.c index 7c501cf52..b61ac939e 100644 --- a/servers/vm/mem_cache.c +++ b/servers/vm/mem_cache.c @@ -27,7 +27,7 @@ static int cache_reference(struct phys_region *pr, struct phys_region *pr2); static int cache_unreference(struct phys_region *pr); -static int cache_sanitycheck(struct phys_region *pr, char *file, int line); +static int cache_sanitycheck(struct phys_region *pr, const char *file, int line); static int cache_writable(struct phys_region *pr); static int cache_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l); static int cache_pagefault(struct vmproc *vmp, struct vir_region *region, @@ -65,7 +65,7 @@ static int cache_unreference(struct phys_region *pr) return mem_type_anon.ev_unreference(pr); } -static int cache_sanitycheck(struct phys_region *pr, char *file, int line) +static int cache_sanitycheck(struct phys_region *pr, const char *file, int line) { MYASSERT(usedpages_add(pr->ph->phys, VM_PAGE_SIZE) == OK); return OK; diff --git a/servers/vm/mem_file.c b/servers/vm/mem_file.c index 2588cdbea..ef25cff55 100644 --- a/servers/vm/mem_file.c +++ b/servers/vm/mem_file.c @@ -20,7 +20,7 @@ static int mappedfile_unreference(struct phys_region *pr); static int mappedfile_pagefault(struct vmproc *vmp, struct vir_region *region, struct phys_region *ph, int write, vfs_callback_t callback, void *state, int len, int *io); -static int mappedfile_sanitycheck(struct phys_region *pr, char *file, int line); +static int mappedfile_sanitycheck(struct phys_region *pr, const char *file, int line); static int mappedfile_writable(struct phys_region *pr); static int mappedfile_copy(struct vir_region *vr, struct vir_region *newvr); static int mappedfile_lowshrink(struct vir_region *vr, vir_bytes len); @@ -124,7 +124,9 @@ static int mappedfile_pagefault(struct vmproc *vmp, struct vir_region *region, } if(!cb) { +#if 0 printf("VM: mem_file: no callback, returning EFAULT\n"); +#endif sys_diagctl_stacktrace(vmp->vm_endpoint); return EFAULT; } @@ -139,14 +141,16 @@ static int mappedfile_pagefault(struct vmproc *vmp, struct vir_region *region, } if(!write) { +#if 0 printf("mappedfile_pagefault: nonwrite fault?\n"); - return EFAULT; +#endif + return OK; } return cow_block(vmp, region, ph, 0); } -static int mappedfile_sanitycheck(struct phys_region *pr, char *file, int line) +static int mappedfile_sanitycheck(struct phys_region *pr, const char *file, int line) { MYASSERT(usedpages_add(pr->ph->phys, VM_PAGE_SIZE) == OK); return OK; diff --git a/servers/vm/mem_shared.c b/servers/vm/mem_shared.c index 19239b09f..d51029111 100644 --- a/servers/vm/mem_shared.c +++ b/servers/vm/mem_shared.c @@ -17,7 +17,7 @@ static int shared_unreference(struct phys_region *pr); static int shared_pagefault(struct vmproc *vmp, struct vir_region *region, struct phys_region *ph, int write, vfs_callback_t cb, void *state, int len, int *io); -static int shared_sanitycheck(struct phys_region *pr, char *file, int line); +static int shared_sanitycheck(struct phys_region *pr, const char *file, int line); static int shared_writable(struct phys_region *pr); static void shared_delete(struct vir_region *region); static u32_t shared_regionid(struct vir_region *region); @@ -149,7 +149,7 @@ static int shared_pagefault(struct vmproc *vmp, struct vir_region *region, return OK; } -static int shared_sanitycheck(struct phys_region *pr, char *file, int line) +static int shared_sanitycheck(struct phys_region *pr, const char *file, int line) { return OK; } diff --git a/servers/vm/memtype.h b/servers/vm/memtype.h index a8c14dce9..a7edaa3a5 100644 --- a/servers/vm/memtype.h +++ b/servers/vm/memtype.h @@ -22,7 +22,7 @@ typedef struct mem_type { void (*ev_split)(struct vmproc *vmp, struct vir_region *vr, struct vir_region *r1, struct vir_region *r2); int (*writable)(struct phys_region *pr); - int (*ev_sanitycheck)(struct phys_region *pr, char *file, int line); + int (*ev_sanitycheck)(struct phys_region *pr, const char *file, int line); int (*ev_copy)(struct vir_region *vr, struct vir_region *newvr); int (*ev_lowshrink)(struct vir_region *vr, vir_bytes len); u32_t (*regionid)(struct vir_region *vr); diff --git a/servers/vm/pagefaults.c b/servers/vm/pagefaults.c index 95e1142cc..ed1f0a476 100644 --- a/servers/vm/pagefaults.c +++ b/servers/vm/pagefaults.c @@ -14,6 +14,9 @@ #include #include #include +#include + +#include #include #include @@ -28,6 +31,29 @@ #include "util.h" #include "region.h" +struct pf_state { + endpoint_t ep; + vir_bytes vaddr; + u32_t err; +}; + +struct hm_state { + endpoint_t caller; /* KERNEL or process? if NONE, no callback */ + endpoint_t requestor; /* on behalf of whom? */ + int transid; /* VFS transaction id if valid */ + struct vmproc *vmp; /* target address space */ + vir_bytes mem, len; /* memory range */ + int wrflag; /* must it be writable or not */ + int valid; /* sanity check */ + int vfs_avail; /* may vfs be called to satisfy this range? */ +#define VALID 0xc0ff1 +}; + +static void handle_memory_continue(struct vmproc *vmp, message *m, + void *arg, void *statearg); +static int handle_memory_step(struct hm_state *hmstate); +static void handle_memory_final(struct hm_state *state, int result); + /*===========================================================================* * pf_errstr * *===========================================================================*/ @@ -44,23 +70,9 @@ char *pf_errstr(u32_t err) return buf; } -struct pf_state { - endpoint_t ep; - vir_bytes vaddr; - u32_t err; -}; - -struct hm_state { - endpoint_t requestor; - struct vmproc *vmp; - vir_bytes mem; - vir_bytes len; - int wrflag; -}; - static void pf_cont(struct vmproc *vmp, message *m, void *arg, void *statearg); -static void hm_cont(struct vmproc *vmp, message *m, void *arg, void *statearg); +static void handle_memory_continue(struct vmproc *vmp, message *m, void *arg, void *statearg); static void handle_pagefault(endpoint_t ep, vir_bytes addr, u32_t err, int retry) { @@ -156,25 +168,65 @@ static void pf_cont(struct vmproc *vmp, message *m, handle_pagefault(state->ep, state->vaddr, state->err, 1); } -static void hm_cont(struct vmproc *vmp, message *m, +static void handle_memory_continue(struct vmproc *vmp, message *m, void *arg, void *statearg) { int r; struct hm_state *state = statearg; - printf("hm_cont: result %d\n", m->VMV_RESULT); - r = handle_memory(vmp, state->mem, state->len, state->wrflag, - hm_cont, &state, sizeof(state)); - if(r == SUSPEND) { - printf("VM: hm_cont: damnit: hm_cont: more SUSPEND\n"); + assert(state); + assert(state->caller != NONE); + assert(state->valid == VALID); + + if(m->VMV_RESULT != OK) { + printf("VM: handle_memory_continue: vfs request failed\n"); + handle_memory_final(state, m->VMV_RESULT); return; } - printf("VM: hm_cont: ok, result %d, requestor %d\n", r, state->requestor); + r = handle_memory_step(state); - if(sys_vmctl(state->requestor, VMCTL_MEMREQ_REPLY, r) != OK) - panic("hm_cont: sys_vmctl failed: %d", r); + assert(state->valid == VALID); - printf("MEMREQ_REPLY sent\n"); + if(r == SUSPEND) { + return; + } + + assert(state->valid == VALID); + + handle_memory_final(state, r); +} + +static void handle_memory_final(struct hm_state *state, int result) +{ + int r; + + assert(state); + assert(state->valid == VALID); + + if(state->caller == KERNEL) { + if((r=sys_vmctl(state->requestor, VMCTL_MEMREQ_REPLY, result)) != OK) + panic("handle_memory_continue: sys_vmctl failed: %d", r); + } else if(state->caller != NONE) { + /* Send a reply msg */ + message msg; + memset(&msg, 0, sizeof(msg)); + msg.m_type = result; + + if(IS_VFS_FS_TRANSID(state->transid)) { + assert(state->caller == VFS_PROC_NR); + /* If a transaction ID was set, reset it */ + msg.m_type = TRNS_ADD_ID(msg.m_type, state->transid); + } + + if(asynsend3(state->caller, &msg, 0) != OK) { + panic("handle_memory_final: asynsend3 failed"); + } + + assert(state->valid == VALID); + + /* fail fast if anyone tries to access this state again */ + memset(state, 0, sizeof(*state)); + } } /*===========================================================================* @@ -185,6 +237,52 @@ void do_pagefaults(message *m) handle_pagefault(m->m_source, m->VPF_ADDR, m->VPF_FLAGS, 0); } +int handle_memory_once(struct vmproc *vmp, vir_bytes mem, vir_bytes len, + int wrflag) +{ + int r; + r = handle_memory_start(vmp, mem, len, wrflag, NONE, NONE, 0, 0); + assert(r != SUSPEND); + return r; +} + +int handle_memory_start(struct vmproc *vmp, vir_bytes mem, vir_bytes len, + int wrflag, endpoint_t caller, endpoint_t requestor, int transid, + int vfs_avail) +{ + int r; + struct hm_state state; + vir_bytes o; + + if((o = mem % PAGE_SIZE)) { + mem -= o; + len += o; + } + + len = roundup(len, PAGE_SIZE); + + state.vmp = vmp; + state.mem = mem; + state.len = len; + state.wrflag = wrflag; + state.requestor = requestor; + state.caller = caller; + state.transid = transid; + state.valid = VALID; + state.vfs_avail = vfs_avail; + + r = handle_memory_step(&state); + + if(r == SUSPEND) { + assert(caller != NONE); + assert(vfs_avail); + } else { + handle_memory_final(&state, r); + } + + return r; +} + /*===========================================================================* * do_memory * *===========================================================================*/ @@ -205,21 +303,21 @@ void do_memory(void) switch(r) { case VMPTYPE_CHECK: { - struct hm_state state; + int transid = 0; + int vfs_avail; if(vm_isokendpt(who, &p) != OK) panic("do_memory: bad endpoint: %d", who); vmp = &vmproc[p]; + assert(!IS_VFS_FS_TRANSID(transid)); - state.vmp = vmp; - state.mem = mem; - state.len = len; - state.wrflag = wrflag; - state.requestor = requestor; + /* is VFS blocked? */ + if(requestor == VFS_PROC_NR) vfs_avail = 0; + else vfs_avail = 1; - r = handle_memory(vmp, mem, len, - wrflag, hm_cont, &state, sizeof(state)); + handle_memory_start(vmp, mem, len, wrflag, + KERNEL, requestor, transid, vfs_avail); break; } @@ -227,69 +325,56 @@ void do_memory(void) default: return; } - - if(r != SUSPEND) { - if(sys_vmctl(requestor, VMCTL_MEMREQ_REPLY, r) != OK) - panic("do_memory: sys_vmctl failed: %d", r); - } } } -int handle_memory(struct vmproc *vmp, vir_bytes mem, vir_bytes len, int wrflag, - vfs_callback_t callback, void *state, int statelen) +static int handle_memory_step(struct hm_state *hmstate) { struct vir_region *region; - vir_bytes o; - struct hm_state *hmstate = (struct hm_state *) state; /* Page-align memory and length. */ - o = mem % VM_PAGE_SIZE; - mem -= o; - len += o; - o = len % VM_PAGE_SIZE; - if(o > 0) len += VM_PAGE_SIZE - o; + assert(hmstate); + assert(hmstate->valid == VALID); + assert(!(hmstate->mem % VM_PAGE_SIZE)); + assert(!(hmstate->len % VM_PAGE_SIZE)); - while(len > 0) { + while(hmstate->len > 0) { int r; - if(!(region = map_lookup(vmp, mem, NULL))) { + if(!(region = map_lookup(hmstate->vmp, hmstate->mem, NULL))) { #if VERBOSE - map_printmap(vmp); + map_printmap(hmstate->vmp); printf("VM: do_memory: memory doesn't exist\n"); #endif - r = EFAULT; - } else if(!(region->flags & VR_WRITABLE) && wrflag) { + return EFAULT; + } else if(!(region->flags & VR_WRITABLE) && hmstate->wrflag) { #if VERBOSE printf("VM: do_memory: write to unwritable map\n"); #endif - r = EFAULT; + return EFAULT; } else { vir_bytes offset, sublen; - assert(region->vaddr <= mem); + assert(region->vaddr <= hmstate->mem); assert(!(region->vaddr % VM_PAGE_SIZE)); - offset = mem - region->vaddr; - sublen = len; + offset = hmstate->mem - region->vaddr; + sublen = hmstate->len; if(offset + sublen > region->length) sublen = region->length - offset; - if(hmstate && hmstate->requestor == VFS_PROC_NR - && region->def_memtype == &mem_type_mappedfile) { - r = map_handle_memory(vmp, region, offset, - sublen, wrflag, NULL, NULL, 0); + if((region->def_memtype == &mem_type_mappedfile && + !hmstate->vfs_avail) || hmstate->caller == NONE) { + r = map_handle_memory(hmstate->vmp, region, offset, + sublen, hmstate->wrflag, NULL, NULL, 0); + assert(r != SUSPEND); } else { - r = map_handle_memory(vmp, region, offset, - sublen, wrflag, callback, state, sizeof(state)); + r = map_handle_memory(hmstate->vmp, region, offset, + sublen, hmstate->wrflag, handle_memory_continue, + hmstate, sizeof(*hmstate)); } - len -= sublen; - mem += sublen; - } - - if(r != OK) { -#if VERBOSE - printf("VM: memory range 0x%lx-0x%lx not available in %d\n", - mem, mem+len, vmp->vm_endpoint); -#endif - return r; + if(r != OK) return r; + + hmstate->len -= sublen; + hmstate->mem += sublen; } } diff --git a/servers/vm/pagetable.c b/servers/vm/pagetable.c index 489249626..e0fe60af2 100644 --- a/servers/vm/pagetable.c +++ b/servers/vm/pagetable.c @@ -65,12 +65,15 @@ struct vmproc *vmprocess = &vmproc[VM_PROC_NR]; # define SPAREPAGES 150 # define STATIC_SPAREPAGES 140 #else -static u32_t global_bit = 0; # define SPAREPAGES 20 # define STATIC_SPAREPAGES 15 #endif /* __arm__ */ #endif +#ifdef __i386__ +static u32_t global_bit = 0; +#endif + #define SPAREPAGEDIRS 1 #define STATIC_SPAREPAGEDIRS 1 @@ -115,7 +118,7 @@ static char static_sparepagedirs[ARCH_PAGEDIR_SIZE*STATIC_SPAREPAGEDIRS + ARCH_P /*===========================================================================* * pt_sanitycheck * *===========================================================================*/ -void pt_sanitycheck(pt_t *pt, char *file, int line) +void pt_sanitycheck(pt_t *pt, const char *file, int line) { /* Basic pt sanity check. */ int slot; @@ -1234,10 +1237,10 @@ void pt_init(void) panic("VM: sys_vmctl_get_pdbr failed"); #if defined(__i386__) if(sys_vircopy(NONE, mypdbr, SELF, - (vir_bytes) currentpagedir, VM_PAGE_SIZE) != OK) + (vir_bytes) currentpagedir, VM_PAGE_SIZE, 0) != OK) #elif defined(__arm__) if(sys_vircopy(NONE, myttbr, SELF, - (vir_bytes) currentpagedir, ARCH_PAGEDIR_SIZE) != OK) + (vir_bytes) currentpagedir, ARCH_PAGEDIR_SIZE, 0) != OK) #endif panic("VM: sys_vircopy failed"); diff --git a/servers/vm/proto.h b/servers/vm/proto.h index 869bfc8a9..0ad9998cf 100644 --- a/servers/vm/proto.h +++ b/servers/vm/proto.h @@ -28,12 +28,12 @@ void *reservedqueue_new(int, int, int, int); int reservedqueue_alloc(void *, phys_bytes *, void **); void reservedqueue_add(void *, void *, phys_bytes); void alloc_cycle(void); -void mem_sanitycheck(char *file, int line); +void mem_sanitycheck(const char *file, int line); phys_clicks alloc_mem(phys_clicks clicks, u32_t flags); void memstats(int *nodes, int *pages, int *largest); void printmemstats(void); void usedpages_reset(void); -int usedpages_add_f(phys_bytes phys, phys_bytes len, char *file, int +int usedpages_add_f(phys_bytes phys, phys_bytes len, const char *file, int line); void free_mem(phys_clicks base, phys_clicks clicks); void mem_add_total_pages(int pages); @@ -54,7 +54,7 @@ int do_getrusage(message *m); void clear_proc(struct vmproc *vmp); int do_exit(message *msg); int do_willexit(message *msg); -int do_procctl(message *msg); +int do_procctl(message *msg, int transid); void free_proc(struct vmproc *vmp); /* fork.c */ @@ -84,8 +84,11 @@ int do_vfs_mmap(message *m); void do_pagefaults(message *m); void do_memory(void); char *pf_errstr(u32_t err); -int handle_memory(struct vmproc *vmp, vir_bytes mem, vir_bytes len, int - wrflag, vfs_callback_t cb, void *state, int statelen); +int handle_memory_start(struct vmproc *vmp, vir_bytes mem, vir_bytes len, + int wrflag, endpoint_t caller, endpoint_t requestor, int transid, + int vfs_avail); +int handle_memory_once(struct vmproc *vmp, vir_bytes mem, vir_bytes len, + int wrflag); /* $(ARCH)/pagetable.c */ void pt_init(void); @@ -115,21 +118,21 @@ int get_vm_self_pages(void); int pt_writable(struct vmproc *vmp, vir_bytes v); #if SANITYCHECKS -void pt_sanitycheck(pt_t *pt, char *file, int line); +void pt_sanitycheck(pt_t *pt, const char *file, int line); #endif /* slaballoc.c */ void *slaballoc(int bytes); void slabfree(void *mem, int bytes); void slabstats(void); -void slab_sanitycheck(char *file, int line); +void slab_sanitycheck(const char *file, int line); #define SLABALLOC(var) (var = slaballoc(sizeof(*var))) #define SLABFREE(ptr) do { slabfree(ptr, sizeof(*(ptr))); (ptr) = NULL; } while(0) #if SANITYCHECKS void slabunlock(void *mem, int bytes); void slablock(void *mem, int bytes); -int slabsane_f(char *file, int line, void *mem, int bytes); +int slabsane_f(const char *file, int line, void *mem, int bytes); #endif /* region.c */ @@ -184,7 +187,7 @@ int get_region_info(struct vmproc *vmp, struct vm_region_info *vri, int int copy_abs2region(phys_bytes abs, struct vir_region *destregion, phys_bytes offset, phys_bytes len); #if SANITYCHECKS -void map_sanitycheck(char *file, int line); +void map_sanitycheck(const char *file, int line); #endif /* rs.c */ diff --git a/servers/vm/region.c b/servers/vm/region.c index 7450fd844..507407d67 100644 --- a/servers/vm/region.c +++ b/servers/vm/region.c @@ -165,7 +165,7 @@ static int map_sanitycheck_pt(struct vmproc *vmp, /*===========================================================================* * map_sanitycheck * *===========================================================================*/ -void map_sanitycheck(char *file, int line) +void map_sanitycheck(const char *file, int line) { struct vmproc *vmp; @@ -723,7 +723,9 @@ int map_pf(struct vmproc *vmp, } if(r != OK) { +#if 0 printf("map_pf: pagefault in %s failed\n", ph->memtype->name); +#endif if(ph) pb_unreferenced(region, ph, 1); return r; @@ -812,7 +814,7 @@ struct vir_region *map_copy_region(struct vmproc *vmp, struct vir_region *vr) struct phys_region *ph; int r; #if SANITYCHECKS - int cr; + unsigned int cr; cr = physregions(vr); #endif vir_bytes p; diff --git a/servers/vm/sanitycheck.h b/servers/vm/sanitycheck.h index a2993ce5f..f353d9b3a 100644 --- a/servers/vm/sanitycheck.h +++ b/servers/vm/sanitycheck.h @@ -16,7 +16,7 @@ printf("VM:%s:%d: %s failed (last sanity check %s:%d)\n", file, line, #c, sc_lastfile, sc_lastline); \ panic("sanity check failed"); } } while(0) -#define SLABSANITYCHECK(l) if(_minix_kerninfo && 0) { \ +#define SLABSANITYCHECK(l) if(_minix_kerninfo) { \ slab_sanitycheck(__FILE__, __LINE__); } #define SANITYCHECK(l) if(!nocheck && _minix_kerninfo && 0) { \ diff --git a/servers/vm/slaballoc.c b/servers/vm/slaballoc.c index 61a7ff849..6b19e61f5 100644 --- a/servers/vm/slaballoc.c +++ b/servers/vm/slaballoc.c @@ -190,7 +190,7 @@ static struct slabdata *newslabdata(void) /*===========================================================================* * checklist * *===========================================================================*/ -static int checklist(char *file, int line, +static int checklist(const char *file, int line, struct slabheader *s, int bytes) { struct slabdata *n = s->list_head; @@ -225,7 +225,7 @@ static int checklist(char *file, int line, /*===========================================================================* * void slab_sanitycheck * *===========================================================================*/ -void slab_sanitycheck(char *file, int line) +void slab_sanitycheck(const char *file, int line) { int s; for(s = 0; s < SLABSIZES; s++) { @@ -236,7 +236,7 @@ void slab_sanitycheck(char *file, int line) /*===========================================================================* * int slabsane * *===========================================================================*/ -int slabsane_f(char *file, int line, void *mem, int bytes) +int slabsane_f(const char *file, int line, void *mem, int bytes) { struct slabheader *s; struct slabdata *f; diff --git a/servers/vm/utility.c b/servers/vm/utility.c index c59462d49..aa00c95ba 100644 --- a/servers/vm/utility.c +++ b/servers/vm/utility.c @@ -170,7 +170,7 @@ int do_info(message *m) * deadlock. Note that no memory mapping can be undone without the * involvement of VM, so we are safe until we're done. */ - r = handle_memory(vmp, ptr, size, 1 /*wrflag*/, NULL, NULL, 0); + r = handle_memory_once(vmp, ptr, size, 1 /*wrflag*/); if (r != OK) return r; /* Now that we know the copy out will succeed, perform the actual copy