#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 */
/* 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 */
#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 */
/* 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)
#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 */
#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. */
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. */
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);
* 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.
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. */
* 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
(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;
}
/* 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;
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)
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);
}
assert(caller);
assert(target);
- vm_suspend(caller, target, lin, bytes, VMSTYPE_KERNELCALL);
+ vm_suspend(caller, target, lin, bytes, VMSTYPE_KERNELCALL, writeflag);
return VMSUSPEND;
}
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;
}
* 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.
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. */
* 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
(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;
}
/* 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;
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)
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);
}
assert(caller);
assert(target);
- vm_suspend(caller, target, lin, bytes, VMSTYPE_KERNELCALL);
+ vm_suspend(caller, target, lin, bytes, VMSTYPE_KERNELCALL, writeflag);
return VMSUSPEND;
}
/* 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);
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);
*/
#include "kernel/system.h"
+#include "kernel/vm.h"
#include <minix/type.h>
+#include <assert.h>
#if (USE_VIRCOPY || USE_PHYSCOPY)
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) */
#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? */
* 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 */
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;
return EPERM;
}
+ if(flags) *flags = g.cp_flags;
+
/* Check validity. */
if((g.cp_flags & (CPF_USED | CPF_VALID)) !=
(CPF_USED | CPF_VALID)) {
endpoint_t new_granter, *src, *dst;
struct proc *granter_p;
int r;
+ u32_t flags;
#if PERF_USE_COW_SAFECOPY
vir_bytes size;
#endif
/* 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);
}
/* 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);
}
/* 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);
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;
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 {
/* 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;
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)
#include <string.h>
#define ACCESS_CHECK(a) { \
- if((a) & ~(CPF_READ|CPF_WRITE)) { \
+ if((a) & ~(CPF_READ|CPF_WRITE|CPF_TRY)) { \
errno = EINVAL; \
return -1; \
} \
#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
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));
}
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));
}
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));
}
#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));
}
#include <string.h>
/*===========================================================================*
- * 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;
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);
+}
+
/* 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);
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;
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);
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);
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;
#include "fs.h"
#include <minix/vfsif.h>
#include <assert.h>
+#include <string.h>
-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);
}
worker->w_next = NULL;
sending--;
assert(sending >= 0);
- (void) sendmsg(vmp, worker);
+ (void) sendmsg(vmp, vmp->m_fs_e, worker);
}
/*===========================================================================*
}
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);
}
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 *
*===========================================================================*/
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);
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);
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");
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 */
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);
}
/* 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);
}
#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));
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 */
/*===========================================================================*
- * 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 */
}
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);
}
/*===========================================================================*
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));
}
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
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);
}
/* 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);
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);
}
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)
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';
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;
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));
}
/* 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);
*/
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);
}
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);
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)
/*===========================================================================*
- * 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");
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 *
*===========================================================================*/
/*===========================================================================*
- * 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;
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)
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 *
*===========================================================================*/
/*===========================================================================*
- * 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;
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");
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 *
/*===========================================================================*
- * 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;
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");
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 *
*===========================================================================*/
/*===========================================================================*
- * req_slink *
+ * req_slink_actual *
*===========================================================================*/
-int req_slink(
+static int req_slink_actual(
endpoint_t fs_e,
ino_t inode_nr,
char *lastc,
vir_bytes path_addr,
size_t path_length,
uid_t uid,
- gid_t gid
+ gid_t gid,
+ int cpflag
)
{
int r;
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");
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");
}
+/*===========================================================================*
+ * 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 *
*===========================================================================*/
/* 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;
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);
}
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);
}
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);
}
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));
}
/*===========================================================================*
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;
}
/* 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);
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;
+}
+
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);
}
}
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)
/* 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 */
}
#if SANITYCHECKS
struct {
int used;
- char *file;
+ const char *file;
int line;
} pagemap[NUMBER_PHYSICAL_PAGES];
#endif
}
#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++) {
/*===========================================================================*
* 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;
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;
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;
}
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;
}
* 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");
}
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;
#include <minix/const.h>
#include <minix/bitmap.h>
#include <minix/rs.h>
+#include <minix/vfsif.h>
#include <sys/exec.h>
/* 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) {
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)) {
*/
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);
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,
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;
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);
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;
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);
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);
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);
}
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;
}
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;
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);
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);
}
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,
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;
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);
}
if(!cb) {
+#if 0
printf("VM: mem_file: no callback, returning EFAULT\n");
+#endif
sys_diagctl_stacktrace(vmp->vm_endpoint);
return EFAULT;
}
}
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;
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);
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;
}
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);
#include <minix/syslib.h>
#include <minix/safecopies.h>
#include <minix/bitmap.h>
+#include <minix/vfsif.h>
+
+#include <machine/vmparam.h>
#include <errno.h>
#include <string.h>
#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 *
*===========================================================================*/
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)
{
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));
+ }
}
/*===========================================================================*
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 *
*===========================================================================*/
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;
}
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;
}
}
# 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
/*===========================================================================*
* 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;
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");
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);
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 */
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);
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 */
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 */
/*===========================================================================*
* map_sanitycheck *
*===========================================================================*/
-void map_sanitycheck(char *file, int line)
+void map_sanitycheck(const char *file, int line)
{
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;
struct phys_region *ph;
int r;
#if SANITYCHECKS
- int cr;
+ unsigned int cr;
cr = physregions(vr);
#endif
vir_bytes p;
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) { \
/*===========================================================================*
* 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;
/*===========================================================================*
* 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++) {
/*===========================================================================*
* 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;
* 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