From 565f13088f773c2c01108b3f6989394528c8ded5 Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Thu, 16 Jan 2014 14:22:13 +0100 Subject: [PATCH] make vfs & filesystems use failable copying Change the kernel to add features to vircopy and safecopies so that transparent copy fixing won't happen to avoid deadlocks, and such copies fail with EFAULT. Transparently making copying work from filesystems (as normally done by the kernel & VM when copying fails because of missing/readonly memory) is problematic as it can happen that, for file-mapped ranges, that that same filesystem that is blocked on the copy request is needed to satisfy the memory range, leading to deadlock. Dito for VFS itself, if done with a blocking call. This change makes the copying done from a filesystem fail in such cases with EFAULT by VFS adding the CPF_TRY flag to the grants. If a FS call fails with EFAULT, VFS will then request the range to be made available to VM after the FS is unblocked, allowing it to be used to satisfy the range if need be in another VFS thread. Similarly, for datacopies that VFS itself does, it uses the failable vircopy variant and callers use a wrapper that talk to VM if necessary to get the copy to work. . kernel: add CPF_TRY flag to safecopies . kernel: only request writable ranges to VM for the target buffer when copying fails . do copying in VFS TRY-first . some fixes in VM to build SANITYCHECK mode . add regression test for the cases where - a FS system call needs memory mapped in a process that the FS itself must map. - such a range covers more than one file-mapped region. . add 'try' mode to vircopy, physcopy . add flags field to copy kernel call messages . if CP_FLAG_TRY is set, do not transparently try to fix memory ranges . for use by VFS when accessing user buffers to avoid deadlock . remove some obsolete backwards compatability assignments . VFS: let thread scheduling work for VM requests too Allows VFS to make calls to VM while suspending and resuming the currently running thread. Does currently not work for the main thread. . VM: add fix memory range call for use by VFS Change-Id: I295794269cea51a3163519a9cfe5901301d90b32 --- include/minix/com.h | 18 +-- include/minix/const.h | 2 - include/minix/safecopies.h | 3 + include/minix/syslib.h | 9 +- include/minix/vm.h | 3 +- kernel/arch/earm/memory.c | 17 ++- kernel/arch/i386/do_sdevio.c | 2 +- kernel/arch/i386/memory.c | 17 ++- kernel/proto.h | 4 +- kernel/system/do_copy.c | 12 +- kernel/system/do_safecopy.c | 16 ++- kernel/system/do_safememset.c | 2 +- kernel/system/do_umap_remote.c | 2 +- kernel/system/do_vumap.c | 4 +- lib/libexec/exec_general.c | 2 +- lib/libsys/safecopies.c | 2 +- lib/libsys/sys_physcopy.c | 10 +- lib/libsys/sys_safecopy.c | 10 -- lib/libsys/sys_vircopy.c | 12 +- lib/libsys/vm_procctl.c | 19 ++- servers/pm/misc.c | 4 +- servers/pm/trace.c | 4 +- servers/rs/exec.c | 2 +- servers/rs/request.c | 2 +- servers/vfs/comm.c | 73 +++++++++-- servers/vfs/coredump.c | 2 +- servers/vfs/dmap.c | 3 +- servers/vfs/exec.c | 4 +- servers/vfs/lock.c | 4 +- servers/vfs/main.c | 20 +-- servers/vfs/misc.c | 22 ++-- servers/vfs/mount.c | 4 +- servers/vfs/proto.h | 4 + servers/vfs/request.c | 233 ++++++++++++++++++++++++++------- servers/vfs/select.c | 8 +- servers/vfs/stadir.c | 3 +- servers/vfs/threads.h | 2 +- servers/vfs/utility.c | 51 +++++++- servers/vfs/vnode.c | 2 +- servers/vfs/worker.c | 5 +- servers/vm/alloc.c | 7 +- servers/vm/exit.c | 16 ++- servers/vm/fork.c | 4 +- servers/vm/glo.h | 2 +- servers/vm/main.c | 46 +++++-- servers/vm/mem_anon.c | 7 +- servers/vm/mem_anon_contig.c | 4 +- servers/vm/mem_cache.c | 4 +- servers/vm/mem_file.c | 10 +- servers/vm/mem_shared.c | 4 +- servers/vm/memtype.h | 2 +- servers/vm/pagefaults.c | 227 ++++++++++++++++++++++---------- servers/vm/pagetable.c | 11 +- servers/vm/proto.h | 21 +-- servers/vm/region.c | 6 +- servers/vm/sanitycheck.h | 2 +- servers/vm/slaballoc.c | 6 +- servers/vm/utility.c | 2 +- 58 files changed, 704 insertions(+), 295 deletions(-) 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,12 +356,11 @@ #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 UMAP_SEG m5_s1 +#define CP_FLAG_TRY 0x01 /* do not transparently map */ -/* 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) */ +#define UMAP_SEG m5_s1 /* Field names for SYS_VUMAP. */ #define VUMAP_ENDPT m10_i1 /* grant owner, or SELF for local addresses */ @@ -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)); + 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; + } + + r = handle_memory_step(state); + + assert(state->valid == VALID); + if(r == SUSPEND) { - printf("VM: hm_cont: damnit: hm_cont: more SUSPEND\n"); return; } - printf("VM: hm_cont: ok, result %d, requestor %d\n", r, state->requestor); + 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"); + } - 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"); + /* 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 -- 2.44.0