Пример #1
0
/*===========================================================================*
 *				do_mmap			     		     *
 *===========================================================================*/
int do_mmap(message *m)
{
	int r, n;
	struct vmproc *vmp;
	vir_bytes addr = m->VMM_ADDR;
	struct vir_region *vr = NULL;
	int execpriv = 0;
	size_t len = (vir_bytes) m->VMM_LEN;

	/* RS and VFS can do slightly more special mmap() things */
	if(m->m_source == VFS_PROC_NR || m->m_source == RS_PROC_NR)
		execpriv = 1;

	if(m->VMM_FLAGS & MAP_THIRDPARTY) {
		if(!execpriv) return EPERM;
		if((r=vm_isokendpt(m->VMM_FORWHOM, &n)) != OK)
			return ESRCH;
	} else {
		/* regular mmap, i.e. for caller */
		if((r=vm_isokendpt(m->m_source, &n)) != OK) {
			panic("do_mmap: message from strange source: %d",
				m->m_source);
		}
	}

	vmp = &vmproc[n];

	if(m->VMM_FD == -1 || (m->VMM_FLAGS & MAP_ANON)) {
		/* actual memory in some form */
		mem_type_t *mt = NULL;

		if(m->VMM_FD != -1 || len <= 0) {
			printf("VM: mmap: fd %d, len 0x%x\n", m->VMM_FD, len);
			return EINVAL;
		}

		/* Contiguous phys memory has to be preallocated. */
		if((m->VMM_FLAGS & (MAP_CONTIG|MAP_PREALLOC)) == MAP_CONTIG) {
			return EINVAL;
		}

		if(m->VMM_FLAGS & MAP_CONTIG) {
			mt = &mem_type_anon_contig;
		} else	mt = &mem_type_anon;

		if(!(vr = mmap_region(vmp, addr, m->VMM_FLAGS, len,
			VR_WRITABLE | VR_ANON, mt, execpriv))) {
			return ENOMEM;
		}
	} else {
		return ENXIO;
	}

	/* Return mapping, as seen from process. */
	m->VMM_RETADDR = vr->vaddr;

	return OK;
}
Пример #2
0
/*===========================================================================*
 *				do_remap		     		     *
 *===========================================================================*/
PUBLIC int do_remap(message *m)
{
	int dn, sn;
	vir_bytes da, sa, startv;
	size_t size;
	struct vir_region *vr, *region;
	struct vmproc *dvmp, *svmp;
	int r;

	da = (vir_bytes) m->VMRE_DA;
	sa = (vir_bytes) m->VMRE_SA;
	size = m->VMRE_SIZE;

	if ((r = vm_isokendpt((endpoint_t) m->VMRE_D, &dn)) != OK)
		return EINVAL;
	if ((r = vm_isokendpt((endpoint_t) m->VMRE_S, &sn)) != OK)
		return EINVAL;

	dvmp = &vmproc[dn];
	svmp = &vmproc[sn];

	/* da is not translated by arch_vir2map(),
	 * it's handled a little differently,
	 * since in map_remap(), we have to know
	 * about whether the user needs to bind to
	 * THAT address or be chosen by the system.
	 */
	sa = arch_vir2map(svmp, sa);

	if (!(region = map_lookup(svmp, sa)))
		return EINVAL;

	if(region->vaddr != sa) {
		printf("VM: do_remap: not start of region.\n");
		return EFAULT;
	}

	if(!(region->flags & VR_SHARED)) {
		printf("VM: do_remap: not shared.\n");
		return EFAULT;
	}

	if (size % VM_PAGE_SIZE)  
		size += VM_PAGE_SIZE - size % VM_PAGE_SIZE;

	if(size != region->length) {
		printf("VM: do_remap: not size of region.\n");
		return EFAULT;
	}

	if ((r = map_remap(dvmp, da, size, region, &startv)) != OK)
		return r;

	m->VMRE_RETA = (char *) arch_map2vir(dvmp, startv);
	return OK;
}
Пример #3
0
/*===========================================================================*
 *				do_rs_update	     			     *
 *===========================================================================*/
int do_rs_update(message *m_ptr)
{
	endpoint_t src_e, dst_e, reply_e;
	int src_p, dst_p;
	struct vmproc *src_vmp, *dst_vmp;
	int r;

	src_e = m_ptr->VM_RS_SRC_ENDPT;
	dst_e = m_ptr->VM_RS_DST_ENDPT;

	/* Lookup slots for source and destination process. */
	if(vm_isokendpt(src_e, &src_p) != OK) {
		printf("do_rs_update: bad src endpoint %d\n", src_e);
		return EINVAL;
	}
	src_vmp = &vmproc[src_p];
	if(vm_isokendpt(dst_e, &dst_p) != OK) {
		printf("do_rs_update: bad dst endpoint %d\n", dst_e);
		return EINVAL;
	}
	dst_vmp = &vmproc[dst_p];

	/* Let the kernel do the update first. */
	r = sys_update(src_e, dst_e);
	if(r != OK) {
		return r;
	}

	/* Do the update in VM now. */
	r = swap_proc_slot(src_vmp, dst_vmp);
	if(r != OK) {
		return r;
	}
	r = swap_proc_dyn_data(src_vmp, dst_vmp);
	if(r != OK) {
		return r;
	}
	pt_bind(&src_vmp->vm_pt, src_vmp);
	pt_bind(&dst_vmp->vm_pt, dst_vmp);

	/* Reply, update-aware. */
	reply_e = m_ptr->m_source;
	if(reply_e == src_e) reply_e = dst_e;
	else if(reply_e == dst_e) reply_e = src_e;
	m_ptr->m_type = OK;
	r = send(reply_e, m_ptr);
	if(r != OK) {
		panic("send() error");
	}

	return SUSPEND;
}
/*===========================================================================*
 *				do_rs_set_priv				     *
 *===========================================================================*/
int do_rs_set_priv(message *m)
{
	int r, n, nr;
	struct vmproc *vmp;
	bitchunk_t call_mask[VM_CALL_MASK_SIZE], *call_mask_p;

	nr = m->VM_RS_NR;

	if ((r = vm_isokendpt(nr, &n)) != OK) {
		printf("do_rs_set_priv: bad endpoint %d\n", nr);
		return EINVAL;
	}

	vmp = &vmproc[n];

	if (m->VM_RS_BUF) {
		r = sys_datacopy(m->m_source, (vir_bytes) m->VM_RS_BUF, SELF,
			(vir_bytes) call_mask, sizeof(call_mask));
		if (r != OK)
			return r;
		call_mask_p = call_mask;
	} else {
		if (m->VM_RS_SYS) {
			printf("VM: do_rs_set_priv: sys procs don't share!\n");
			return EINVAL;
		}
		call_mask_p = NULL;
	}

	acl_set(vmp, call_mask_p, m->VM_RS_SYS);

	return OK;
}
Пример #5
0
/*===========================================================================*
 *				do_push_sig				     *
 *===========================================================================*/
PUBLIC int do_push_sig(message *msg)
{
	int r, n;
	endpoint_t ep;
	vir_bytes sp;
	struct vmproc *vmp;

	ep = msg->VMPS_ENDPOINT;

	if((r=vm_isokendpt(ep, &n)) != OK) {
		printf("VM: bogus endpoint %d from %d\n", ep, msg->m_source);
		return r;
	}
	vmp = &vmproc[n];

        if ((r=get_stack_ptr(ep, &sp)) != OK)
                vm_panic("couldn't get new stack pointer (for sig)",r);
	
	/* Save old SP for caller */
	msg->VMPS_OLD_SP = (char *) sp;
   
        /* Make room for the sigcontext and sigframe struct. */
        sp -= sizeof(struct sigcontext)
                                 + 3 * sizeof(char *) + 2 * sizeof(int);

        if ((r=adjust(vmp, vmp->vm_arch.vm_seg[D].mem_len, sp)) != OK) {
		printf("VM: do_push_sig: adjust() failed: %d\n", r);
		return r;
	}

	return OK;
}
Пример #6
0
int do_procctl(message *msg)
{
	endpoint_t proc;
	struct vmproc *vmp;

	if(vm_isokendpt(msg->VMPCTL_WHO, &proc) != OK) {
		printf("VM: bogus endpoint VM_PROCCTL %d\n",
			msg->VMPCTL_WHO);
		return EINVAL;
	}
	vmp = &vmproc[proc];

	switch(msg->VMPCTL_PARAM) {
		case VMPPARAM_CLEAR:
			if(msg->m_source != RS_PROC_NR
				&& msg->m_source != VFS_PROC_NR)
				return EPERM;
			free_proc(vmp);
			if(pt_new(&vmp->vm_pt) != OK)
				panic("VMPPARAM_CLEAR: pt_new failed");
			pt_bind(&vmp->vm_pt, vmp);
			return OK;
		default:
			return EINVAL;
	}


	return OK;
}
Пример #7
0
/*===========================================================================*
 *				do_exit					     *
 *===========================================================================*/
int do_exit(message *msg)
{
	int proc;
	struct vmproc *vmp;

SANITYCHECK(SCL_FUNCTIONS);

	if(vm_isokendpt(msg->VME_ENDPOINT, &proc) != OK) {
		printf("VM: bogus endpoint VM_EXIT %d\n", msg->VME_ENDPOINT);
		return EINVAL;
	}
	vmp = &vmproc[proc];

	if(!(vmp->vm_flags & VMF_EXITING)) {
		printf("VM: unannounced VM_EXIT %d\n", msg->VME_ENDPOINT);
		return EINVAL;
	}

	{
		/* Free pagetable and pages allocated by pt code. */
SANITYCHECK(SCL_DETAIL);
		free_proc(vmp);
SANITYCHECK(SCL_DETAIL);
	} 
SANITYCHECK(SCL_DETAIL);

	/* Reset process slot fields. */
	clear_proc(vmp);

SANITYCHECK(SCL_FUNCTIONS);
	return OK;
}
Пример #8
0
/*===========================================================================*
 *				do_unmap_phys		     		     *
 *===========================================================================*/
PUBLIC int do_unmap_phys(message *m)
{
	int r, n;
	struct vmproc *vmp;
	endpoint_t target;
	struct vir_region *region;

	target = m->VMUP_EP;
	if(target == SELF)
		target = m->m_source;

	if((r=vm_isokendpt(target, &n)) != OK)
		return EINVAL;

	vmp = &vmproc[n];

	if(!(region = map_lookup(vmp,
	  arch_vir2map(vmp, (vir_bytes) m->VMUM_ADDR)))) {
		return EINVAL;
	}

	if(!(region->flags & VR_DIRECT)) {
		return EINVAL;
	}

	if(map_unmap_region(vmp, region, region->length) != OK) {
		return EINVAL;
	}

	return OK;
}
Пример #9
0
/*===========================================================================*
 *                              do_vfs_reply                                 *
 *===========================================================================*/
int do_vfs_reply(message *m)
{
/* VFS has handled a VM request and VFS has replied. It must be the
 * active request.
 */
 	struct vfs_request_node *orignode = active;
 	vfs_callback_t req_callback;
	void *cbarg;
	int n;
	struct vmproc *vmp;

	assert(active);
	assert(active->req_id == m->VMV_REQID);

	/* the endpoint may have exited */
	if(vm_isokendpt(m->VMV_ENDPOINT, &n) != OK)
		vmp = NULL;
	else	vmp = &vmproc[n];

	req_callback = active->callback;
	cbarg = active->opaque;
	active = NULL;

	/* Invoke requested reply-callback within VM. */
	if(req_callback) req_callback(vmp, m, cbarg, orignode->reqstate);

	SLABFREE(orignode);

	/* Send the next request message if any and not re-activated. */
	if(first_queued && !active)
		activate();

	return SUSPEND;	/* don't reply to the reply */
}
Пример #10
0
/*===========================================================================*
 *				do_mmap			     		     *
 *===========================================================================*/
PUBLIC int do_mmap(message *m)
{
	int r, n;
	struct vmproc *vmp;
	int mfflags = 0;
	struct vir_region *vr = NULL;

	if((r=vm_isokendpt(m->m_source, &n)) != OK) {
		panic("do_mmap: message from strange source: %d", m->m_source);
	}

	vmp = &vmproc[n];

	if(!(vmp->vm_flags & VMF_HASPT))
		return ENXIO;

	if(m->VMM_FD == -1 || (m->VMM_FLAGS & MAP_ANON)) {
		int s;
		vir_bytes v;
		u32_t vrflags = VR_ANON | VR_WRITABLE;
		size_t len = (vir_bytes) m->VMM_LEN;

		if(m->VMM_FD != -1) {
			return EINVAL;
		}

		/* Contiguous phys memory has to be preallocated. */
		if((m->VMM_FLAGS & (MAP_CONTIG|MAP_PREALLOC)) == MAP_CONTIG) {
			return EINVAL;
		}

		if(m->VMM_FLAGS & MAP_PREALLOC) mfflags |= MF_PREALLOC;
		if(m->VMM_FLAGS & MAP_LOWER16M) vrflags |= VR_LOWER16MB;
		if(m->VMM_FLAGS & MAP_LOWER1M)  vrflags |= VR_LOWER1MB;
		if(m->VMM_FLAGS & MAP_ALIGN64K) vrflags |= VR_PHYS64K;
		if(m->VMM_FLAGS & MAP_SHARED) vrflags |= VR_SHARED;
		if(m->VMM_FLAGS & MAP_CONTIG) vrflags |= VR_CONTIG;

		if(len % VM_PAGE_SIZE)
			len += VM_PAGE_SIZE - (len % VM_PAGE_SIZE);

		if(!(vr = map_page_region(vmp,
			arch_vir2map(vmp,
				m->VMM_ADDR ? m->VMM_ADDR : vmp->vm_stacktop),
			VM_DATATOP, len, MAP_NONE, vrflags, mfflags))) {
			return ENOMEM;
		}
	} else {
		return ENOSYS;
	}

	/* Return mapping, as seen from process. */
	assert(vr);
	m->VMM_RETADDR = arch_map2vir(vmp, vr->vaddr);


	return OK;
}
Пример #11
0
/*===========================================================================*
 *                              do_munmap                                    *
 *===========================================================================*/
int do_munmap(message *m)
{
        int r, n;
        struct vmproc *vmp;
        vir_bytes addr, len, offset;
	struct vir_region *vr;
	endpoint_t target = SELF;

	if(m->m_type == VM_UNMAP_PHYS) {
		target = m->VMUP_EP;
	} else if(m->m_type == VM_SHM_UNMAP) {
		target = m->VMUN_ENDPT;
	}

	if(target == SELF)
		target = m->m_source;

        if((r=vm_isokendpt(target, &n)) != OK) {
                panic("do_mmap: message from strange source: %d", m->m_source);
        }
 
        vmp = &vmproc[n];

	if(m->m_type == VM_UNMAP_PHYS) {
		addr = (vir_bytes) m->VMUP_VADDR;
	} else if(m->m_type == VM_SHM_UNMAP) {
		addr = (vir_bytes) m->VMUN_ADDR;
	} else	addr = (vir_bytes) m->VMUM_ADDR;

        if(!(vr = map_lookup(vmp, addr, NULL))) {
                printf("VM: unmap: virtual address 0x%lx not found in %d\n",
                        addr, target);
                return EFAULT;
        }

	if(addr % VM_PAGE_SIZE)
		return EFAULT;
 
	if(m->m_type == VM_UNMAP_PHYS || m->m_type == VM_SHM_UNMAP) {
		len = vr->length;
	} else len = roundup(m->VMUM_LEN, VM_PAGE_SIZE);

	offset = addr - vr->vaddr;

	if(offset + len > vr->length) {
		printf("munmap: addr 0x%lx len 0x%lx spills out of region\n",
			addr, len);
		return EFAULT;
	}

	if(map_unmap_region(vmp, vr, offset, len) != OK)
		panic("do_munmap: map_unmap_region failed");

	return OK;
}
Пример #12
0
/*===========================================================================*
 *				do_watch_exit				     *
 *===========================================================================*/
PUBLIC int do_watch_exit(message *m)
{
	endpoint_t e = m->VM_WE_EP;
	struct vmproc *vmp;
	int p;
	if(vm_isokendpt(e, &p) != OK) return ESRCH;
	vmp = &vmproc[p];
	vmp->vm_flags |= VMF_WATCHEXIT;

	return OK;
}
Пример #13
0
/*===========================================================================*
 *				do_map_phys		     		     *
 *===========================================================================*/
PUBLIC int do_map_phys(message *m)
{
	int r, n;
	struct vmproc *vmp;
	endpoint_t target;
	struct vir_region *vr;
	vir_bytes len;
	phys_bytes startaddr;
	size_t offset;

	target = m->VMMP_EP;
	len = m->VMMP_LEN;

	if (len <= 0) return EINVAL;

	if(target == SELF)
		target = m->m_source;

	if((r=vm_isokendpt(target, &n)) != OK)
		return EINVAL;

	startaddr = (vir_bytes)m->VMMP_PHADDR;

	/* First check permission, then round range down/up. Caller can't
	 * help it if we can't map in lower than page granularity.
	 */
	if(map_perm_check(m->m_source, target, startaddr, len) != OK) {
		printf("VM: unauthorized mapping of 0x%lx by %d\n",
			startaddr, m->m_source);
		return EPERM;
	}

	vmp = &vmproc[n];

	if(!(vmp->vm_flags & VMF_HASPT))
		return ENXIO;

	offset = startaddr % VM_PAGE_SIZE;
	len += offset;
	startaddr -= offset;

	if(len % VM_PAGE_SIZE)
		len += VM_PAGE_SIZE - (len % VM_PAGE_SIZE);

	if(!(vr = map_page_region(vmp, arch_vir2map(vmp, vmp->vm_stacktop),
		VM_DATATOP, len, startaddr,
		VR_DIRECT | VR_NOPF | VR_WRITABLE, 0))) {
		return ENOMEM;
	}

	m->VMMP_VADDR_REPLY = (void *) (arch_map2vir(vmp, vr->vaddr) + offset);

	return OK;
}
Пример #14
0
/*===========================================================================*
 *				do_remap		     		     *
 *===========================================================================*/
int do_remap(kipc_msg_t *m)
{
	int d, dn, s, sn;
	vir_bytes da, sa, startv;
	size_t size;
	struct vir_region *vr, *region;
	struct vmproc *dvmp, *svmp;
	int r;

	d = m->VMRE_D;
	s = m->VMRE_S;
	da = (vir_bytes) m->VMRE_DA;
	sa = (vir_bytes) m->VMRE_SA;
	size = m->VMRE_SIZE;

	if ((r = vm_isokendpt(d, &dn)) != 0)
		return -EINVAL;
	if ((r = vm_isokendpt(s, &sn)) != 0)
		return -EINVAL;

	dvmp = &vmproc[dn];
	svmp = &vmproc[sn];

	/* da is not translated by arch_vir2map(),
	 * it's handled a little differently,
	 * since in map_remap(), we have to know
	 * about whether the user needs to bind to
	 * THAT address or be chosen by the system.
	 */
	sa = arch_vir2map(svmp, sa);

	if (!(region = map_lookup(svmp, sa)))
		return -EINVAL;

	if ((r = map_remap(dvmp, da, size, region, &startv)) != 0)
		return r;

	m->VMRE_RETA = (char *) arch_map2vir(dvmp, startv);
	return 0;
}
Пример #15
0
/*===========================================================================*
 *				do_map_phys		     		     *
 *===========================================================================*/
int do_map_phys(message *m)
{
	int r, n;
	struct vmproc *vmp;
	endpoint_t target;
	struct vir_region *vr;
	vir_bytes len;
	phys_bytes startaddr;
	size_t offset;

	target = m->m_lsys_vm_map_phys.ep;
	len = m->m_lsys_vm_map_phys.len;

	if (len <= 0) return EINVAL;

	if(target == SELF)
		target = m->m_source;

	if((r=vm_isokendpt(target, &n)) != OK)
		return EINVAL;

	startaddr = (vir_bytes)m->m_lsys_vm_map_phys.phaddr;

	/* First check permission, then round range down/up. Caller can't
	 * help it if we can't map in lower than page granularity.
	 */
	if(map_perm_check(m->m_source, target, startaddr, len) != OK) {
		printf("VM: unauthorized mapping of 0x%lx by %d\n",
			startaddr, m->m_source);
		return EPERM;
	}

	vmp = &vmproc[n];

	offset = startaddr % VM_PAGE_SIZE;
	len += offset;
	startaddr -= offset;

	if(len % VM_PAGE_SIZE)
		len += VM_PAGE_SIZE - (len % VM_PAGE_SIZE);

	if(!(vr = map_page_region(vmp, 0, VM_DATATOP, len, 
		VR_DIRECT | VR_WRITABLE, 0, &mem_type_directphys))) {
		return ENOMEM;
	}

	phys_setphys(vr, startaddr);

	m->m_lsys_vm_map_phys.reply = (void *) (vr->vaddr + offset);

	return OK;
}
Пример #16
0
int scall_mmap(kipc_msg_t *m)
{
	int err, n;
	struct vmproc *vmp;
	int mfflags = 0;
	struct vir_region *vr = NULL;

	if((err = vm_isokendpt(m->m_source, &n)) != 0) {
		vm_panic("do_mmap: message from strange source", m->m_source);
	}

	vmp = &vmproc[n];

	if(!(vmp->vm_flags & VMF_HASPT))
		return -ENXIO;

	if(m->VMM_FD == -1 || (m->VMM_FLAGS & MAP_ANONYMOUS)) {
		int s;
		vir_bytes v;
		u32_t vrflags = VR_ANON | VR_WRITABLE;
		size_t len = (vir_bytes) m->VMM_LEN;

		if(m->VMM_FD != -1) {
			return -EINVAL;
		}

		if(m->VMM_FLAGS & MAP_CONTIG) mfflags |= MF_CONTIG;
		if(m->VMM_FLAGS & MAP_PREALLOC) mfflags |= MF_PREALLOC;
		if(m->VMM_FLAGS & MAP_LOWER16M) vrflags |= VR_LOWER16MB;
		if(m->VMM_FLAGS & MAP_LOWER1M)  vrflags |= VR_LOWER1MB;
		if(m->VMM_FLAGS & MAP_ALIGN64K) vrflags |= VR_PHYS64K;
		if(m->VMM_FLAGS & MAP_SHARED) vrflags |= VR_SHARED;

		if(len % VM_PAGE_SIZE)
			len += VM_PAGE_SIZE - (len % VM_PAGE_SIZE);

		if(!(vr = map_page_region(vmp,
			arch_vir2map(vmp, m->VMM_ADDR ? m->VMM_ADDR : vmp->vm_stacktop),
			VM_DATATOP, len, MAP_NONE, vrflags, mfflags))) {
			return -ENOMEM;
		}
	} else {
		return -ENOSYS;
	}

	/* Return mapping, as seen from process. */
	vm_assert(vr);
	m->VMM_RETADDR = arch_map2vir(vmp, vr->vaddr);

	return m->VMM_RETADDR;
}
Пример #17
0
/*===========================================================================*
 *				do_brk					     *
 *===========================================================================*/
int do_brk(message *msg)
{
/* Perform the brk(addr) system call.
 * The parameter, 'addr' is the new virtual address in D space.
 */
	int proc;

	if(vm_isokendpt(msg->VMB_ENDPOINT, &proc) != OK) {
		printf("VM: bogus endpoint VM_BRK %d\n", msg->VMB_ENDPOINT);
		return EINVAL;
	}

	return real_brk(&vmproc[proc], (vir_bytes) msg->VMB_ADDR);
}
Пример #18
0
/*===========================================================================*
 *				do_notify_sig				     *
 *===========================================================================*/
PUBLIC int do_notify_sig(message *m)
{
	int i, avails = 0;
	endpoint_t ep = m->VM_NOTIFY_SIG_ENDPOINT;
	endpoint_t ipc_ep = m->VM_NOTIFY_SIG_IPC;
	int r;
	struct vmproc *vmp;
	int pslot;

	if(vm_isokendpt(ep, &pslot) != OK) return ESRCH;
	vmp = &vmproc[pslot];

	/* Only record the event if we've been asked to report it. */
	if(!(vmp->vm_flags & VMF_WATCHEXIT))
		return OK;

	for (i = 0; i < NR_PROCS; i++) {
		/* its signal is already here */
		if (!array[i].avail && array[i].ep == ep)
			goto out;
		if (array[i].avail)
			avails++;
	}
	if (!avails) {
		/* no slot for signals, unlikely */
		printf("VM: no slot for signals!\n");
		return ENOMEM;
	}

	for (i = 0; i < NR_PROCS; i++) {
		if (array[i].avail) {
			array[i].avail = 0;
			array[i].ep = ep;

			break;
		}
	}

out:
	/* only care when IPC server starts up,
	 * and bypass the process to be signal is IPC itself.
	 */
	if (ipc_ep != 0 && ep != ipc_ep) {
		r = notify(ipc_ep);
		if (r != OK)
			printf("VM: notify IPC error!\n");
	}
	return OK;
}
Пример #19
0
/*===========================================================================*
 *				do_willexit				     *
 *===========================================================================*/
int do_willexit(message *msg)
{
	int proc;
	struct vmproc *vmp;

	if(vm_isokendpt(msg->VMWE_ENDPOINT, &proc) != OK) {
		printf("VM: bogus endpoint VM_EXITING %d\n",
			msg->VMWE_ENDPOINT);
		return EINVAL;
	}
	vmp = &vmproc[proc];

	vmp->vm_flags |= VMF_EXITING;

	return OK;
}
/*===========================================================================*
 *				do_getrusage		     		     *
 *===========================================================================*/
int do_getrusage(message *m)
{
	int res, slot;
	struct vmproc *vmp;
	struct rusage r_usage;

	/* If the request is not from PM, it is coming directly from userland.
	 * This is an obsolete construction. In the future, userland programs
	 * should no longer be allowed to call vm_getrusage(2) directly at all.
	 * For backward compatibility, we simply return success for now.
	 */
	if (m->m_source != PM_PROC_NR)
		return OK;

	/* Get the process for which resource usage is requested. */
	if ((res = vm_isokendpt(m->m_lsys_vm_rusage.endpt, &slot)) != OK)
		return ESRCH;

	vmp = &vmproc[slot];

	/* We are going to change only a few fields, so copy in the rusage
	 * structure first. The structure is still in PM's address space at
	 * this point, so use the message source.
	 */
	if ((res = sys_datacopy(m->m_source, m->m_lsys_vm_rusage.addr,
		SELF, (vir_bytes) &r_usage, (vir_bytes) sizeof(r_usage))) < 0)
		return res;

	if (!m->m_lsys_vm_rusage.children) {
		r_usage.ru_maxrss = vmp->vm_total_max / 1024L; /* unit is KB */
		r_usage.ru_minflt = vmp->vm_minor_page_fault;
		r_usage.ru_majflt = vmp->vm_major_page_fault;
	} else {
		/* XXX TODO: return the fields for terminated, waited-for
		 * children of the given process. We currently do not have this
		 * information! In the future, rather than teaching VM about
		 * the process hierarchy, PM should probably tell VM at process
		 * exit time which other process should inherit its resource
		 * usage fields. For now, we assume PM clears the fields before
		 * making this call, so we don't zero the fields explicitly.
		 */
	}

	/* Copy out the resulting structure back to PM. */
	return sys_datacopy(SELF, (vir_bytes) &r_usage, m->m_source,
		m->m_lsys_vm_rusage.addr, (vir_bytes) sizeof(r_usage));
}
Пример #21
0
/*===========================================================================*
 *				do_vfs_reply			     	*
 *===========================================================================*/
PUBLIC int do_vfs_reply(message *m)
{
/* Reply to a request has been received from vfs. Handle it. First verify
 * and look up which process, identified by endpoint, this is about.
 * Then call the callback function that was registered when the request
 * was done. Return result to vfs.
 */
	endpoint_t ep;
	struct vmproc *vmp;
	int procno;
	callback_t cb;
	ep = m->VMV_ENDPOINT;
	if(vm_isokendpt(ep, &procno) != OK) {
		printf("VM:do_vfs_reply: reply %d about invalid endpoint %d\n",
			m->m_type, ep);
		vm_panic("do_vfs_reply: invalid endpoint from vfs", NO_NUM);
	}
	vmp = &vmproc[procno];
	if(!vmp->vm_callback) {
		printf("VM:do_vfs_reply: reply %d: endpoint %d not waiting\n",
			m->m_type, ep);
		vm_panic("do_vfs_reply: invalid endpoint from vfs", NO_NUM);
	}
	if(vmp->vm_callback_type != m->m_type) {
		printf("VM:do_vfs_reply: reply %d unexpected for endpoint %d\n"
		  " (expecting %d)\n", m->m_type, ep, vmp->vm_callback_type);
		vm_panic("do_vfs_reply: invalid reply from vfs", NO_NUM);
	}
	if(vmp->vm_flags & VMF_EXITING) {
		/* This is not fatal or impossible, but the callback
		 * function has to realize it shouldn't do any PM or
		 * VFS calls for this process.
		 */
		printf("VM:do_vfs_reply: reply %d for EXITING endpoint %d\n",
		  m->m_type, ep);
	}

	/* All desired callback state has been used, so save and reset
	 * the callback. This allows the callback to register another
	 * one.
	 */
	cb = vmp->vm_callback;
	vmp->vm_callback = NULL;
	cb(vmp, m);
	return SUSPEND;
}
Пример #22
0
static int getsrc(struct vir_region *region,
	struct vmproc **vmp, struct vir_region **r)
{
	int srcproc;

	if(region->def_memtype != &mem_type_shared) {
		printf("shared region hasn't shared type but %s.\n",
			region->def_memtype->name);
		return EINVAL;
	}

	if(!region->param.shared.ep || !region->param.shared.vaddr) {
		printf("shared region has not defined source region.\n");
		util_stacktrace();
		return EINVAL;
	}

        if(vm_isokendpt((endpoint_t) region->param.shared.ep, &srcproc) != OK) {
		printf("VM: shared memory with missing source process.\n");
		util_stacktrace();
                return EINVAL;
	}

	*vmp = &vmproc[srcproc];

	if(!(*r=map_lookup(*vmp, region->param.shared.vaddr, NULL))) {
		printf("VM: shared memory with missing vaddr 0x%lx.\n",
			region->param.shared.vaddr);
                return EINVAL;
	}

	if((*r)->def_memtype != &mem_type_anon) {
		printf("source region hasn't anon type but %s.\n",
			(*r)->def_memtype->name);
		return EINVAL;
	}

	if(region->param.shared.id != (*r)->id) {
		printf("source region has no matching id\n");
		return EINVAL;
	}

	return OK;
}
Пример #23
0
/*===========================================================================*
 *                              do_munmap                                    *
 *===========================================================================*/
int do_munmap(message *m)
{
        int r, n;
        struct vmproc *vmp;
        vir_bytes addr, len;
	endpoint_t target = SELF;

	if(m->m_type == VM_UNMAP_PHYS) {
		target = m->m_lsys_vm_unmap_phys.ep;
	} else if(m->m_type == VM_SHM_UNMAP) {
		target = m->m_lc_vm_shm_unmap.forwhom;
	}

	if(target == SELF)
		target = m->m_source;

        if((r=vm_isokendpt(target, &n)) != OK) {
                panic("do_mmap: message from strange source: %d", m->m_source);
        }
 
        vmp = &vmproc[n];

	if(m->m_type == VM_UNMAP_PHYS) {
		addr = (vir_bytes) m->m_lsys_vm_unmap_phys.vaddr;
	} else if(m->m_type == VM_SHM_UNMAP) {
		addr = (vir_bytes) m->m_lc_vm_shm_unmap.addr;
	} else	addr = (vir_bytes) m->VMUM_ADDR;

	if(addr % VM_PAGE_SIZE)
		return EFAULT;
 
	if(m->m_type == VM_UNMAP_PHYS || m->m_type == VM_SHM_UNMAP) {
		struct vir_region *vr;
	        if(!(vr = map_lookup(vmp, addr, NULL))) {
			printf("VM: unmap: address 0x%lx not found in %d\n",
	                       addr, target);
			sys_diagctl_stacktrace(target);
	                return EFAULT;
		}
		len = vr->length;
	} else len = roundup(m->VMUM_LEN, VM_PAGE_SIZE);

	return map_unmap_range(vmp, addr, len);
}
Пример #24
0
/*===========================================================================*
 *                              do_munmap                                    *
 *===========================================================================*/
PUBLIC int do_munmap(message *m)
{
        int r, n;
        struct vmproc *vmp;
        vir_bytes addr, len;
	struct vir_region *vr;
        
        if((r=vm_isokendpt(m->m_source, &n)) != OK) {
                panic("do_mmap: message from strange source: %d", m->m_source);
        }
 
        vmp = &vmproc[n];

	if(!(vmp->vm_flags & VMF_HASPT))
		return ENXIO;

	if(m->m_type == VM_MUNMAP) {
	        addr = (vir_bytes) arch_vir2map(vmp, (vir_bytes) m->VMUM_ADDR);
	} else if(m->m_type == VM_MUNMAP_TEXT) {
	        addr = (vir_bytes) arch_vir2map_text(vmp, (vir_bytes) m->VMUM_ADDR);
	} else {
		panic("do_munmap: strange type");
	}

        if(!(vr = map_lookup(vmp, addr))) {
                printf("VM: unmap: virtual address %p not found in %d\n",
                        m->VMUM_ADDR, vmp->vm_endpoint);
                return EFAULT;
        }
 
	len = m->VMUM_LEN;
	if (len % VM_PAGE_SIZE)
		len += VM_PAGE_SIZE - (len % VM_PAGE_SIZE);

        if(addr != vr->vaddr || len > vr->length || len < VM_PAGE_SIZE) {
                return EFAULT;
        }       

	if(map_unmap_region(vmp, vr, len) != OK)
		panic("do_munmap: map_unmap_region failed");

	return OK;
}
Пример #25
0
int scall_munmap(kipc_msg_t *m)
{
	int r, n;
	struct vmproc *vmp;
	vir_bytes addr, len;
	struct vir_region *vr;

	if((r = vm_isokendpt(m->m_source, &n)) != 0) {
		vm_panic("do_mmap: message from strange source", m->m_source);
	}

	vmp = &vmproc[n];

	if (!(vmp->vm_flags & VMF_HASPT))
		return -ENXIO;

	if (m->m_type == NNR_VM_MUNMAP) {
		addr = (vir_bytes) arch_vir2map(vmp, (vir_bytes) m->VMUM_ADDR);
	} else if(m->m_type == NNR_VM_MUNMAP_TEXT) {
		addr = (vir_bytes) arch_vir2map_text(vmp, (vir_bytes) m->VMUM_ADDR);
	} else {
		vm_panic("do_munmap: strange type", NO_NUM);
	}

	if (!(vr = map_lookup(vmp, addr))) {
		printk("VM: unmap: virtual address 0x%lx not found in %d\n",
			m->VMUM_ADDR, vmp->vm_endpoint);
		return -EFAULT;
	}

	len = m->VMUM_LEN;
	if (len % VM_PAGE_SIZE)
		len += VM_PAGE_SIZE - (len % VM_PAGE_SIZE);

	if (addr != vr->vaddr || len > vr->length || len < VM_PAGE_SIZE) {
		return -EFAULT;
	}

	if (map_unmap_region(vmp, vr, len) != 0)
		vm_panic("do_munmap: map_unmap_region failed", NO_NUM);

	return 0;
}
Пример #26
0
/*===========================================================================*
 *				do_rs_memctl	     			     *
 *===========================================================================*/
int do_rs_memctl(message *m_ptr)
{
	endpoint_t ep;
	int req, r, proc_nr;
	struct vmproc *vmp;

	ep = m_ptr->VM_RS_CTL_ENDPT;
	req = m_ptr->VM_RS_CTL_REQ;

	/* Lookup endpoint. */
	if ((r = vm_isokendpt(ep, &proc_nr)) != OK) {
		printf("do_rs_memctl: bad endpoint %d\n", ep);
		return EINVAL;
	}
	vmp = &vmproc[proc_nr];

	/* Process request. */
	switch(req)
	{
	case VM_RS_MEM_PIN:

		/* Do not perform VM_RS_MEM_PIN yet - it costs the full
		 * size of the RS stack (64MB by default) in memory,
		 * and it's needed for functionality that isn't complete /
		 * merged in current Minix (surviving VM crashes).
		 */

#if 0
		r = map_pin_memory(vmp);
		return r;
#else
		return OK;
#endif

	case VM_RS_MEM_MAKE_VM:
		r = rs_memctl_make_vm_instance(vmp);
		return r;
	default:
		printf("do_rs_memctl: bad request %d\n", req);
		return EINVAL;
	}
}
Пример #27
0
/*===========================================================================*
 *				do_rs_memctl	     			     *
 *===========================================================================*/
int do_rs_memctl(message *m_ptr)
{
	endpoint_t ep;
	int req, r, proc_nr;
	struct vmproc *vmp;

	ep = m_ptr->VM_RS_CTL_ENDPT;
	req = m_ptr->VM_RS_CTL_REQ;

	/* Lookup endpoint. */
	if ((r = vm_isokendpt(ep, &proc_nr)) != OK) {
		printf("do_rs_memctl: bad endpoint %d\n", ep);
		return EINVAL;
	}
	vmp = &vmproc[proc_nr];

	/* Process request. */
	switch(req)
	{
	case VM_RS_MEM_PIN:
		/* Only actually pin RS memory if VM can recover from crashes (saves memory). */
		if (num_vm_instances <= 1)
			return OK;
		r = map_pin_memory(vmp);
		return r;
	case VM_RS_MEM_MAKE_VM:
		r = rs_memctl_make_vm_instance(vmp);
		return r;
	case VM_RS_MEM_HEAP_PREALLOC:
		r = rs_memctl_heap_prealloc(vmp, (vir_bytes*) &m_ptr->VM_RS_CTL_ADDR, (size_t*) &m_ptr->VM_RS_CTL_LEN);
		return r;
	case VM_RS_MEM_MAP_PREALLOC:
		r = rs_memctl_map_prealloc(vmp, (vir_bytes*) &m_ptr->VM_RS_CTL_ADDR, (size_t*) &m_ptr->VM_RS_CTL_LEN);
		return r;
	case VM_RS_MEM_GET_PREALLOC_MAP:
		r = rs_memctl_get_prealloc_map(vmp, (vir_bytes*) &m_ptr->VM_RS_CTL_ADDR, (size_t*) &m_ptr->VM_RS_CTL_LEN);
		return r;
	default:
		printf("do_rs_memctl: bad request %d\n", req);
		return EINVAL;
	}
}
Пример #28
0
/*===========================================================================*
 *				do_get_refcount		     		     *
 *===========================================================================*/
int do_get_refcount(message *m)
{
	int r, n;
	struct vmproc *vmp;
	endpoint_t target;
	u8_t cnt;
	vir_bytes addr;

	target = m->m_lsys_vm_getref.endpt;
	addr = (vir_bytes) m->m_lsys_vm_getref.addr;

	if ((r = vm_isokendpt(target, &n)) != OK)
		return EINVAL;

	vmp = &vmproc[n];

	r = map_get_ref(vmp, addr, &cnt);

	m->m_lsys_vm_getref.retc = cnt;
	return r;
}
Пример #29
0
/*===========================================================================*
 *				do_get_phys		     		     *
 *===========================================================================*/
int do_get_phys(message *m)
{
	int r, n;
	struct vmproc *vmp;
	endpoint_t target;
	phys_bytes ret;
	vir_bytes addr;

	target = m->m_lc_vm_getphys.endpt;
	addr = (vir_bytes) m->m_lc_vm_getphys.addr;

	if ((r = vm_isokendpt(target, &n)) != OK)
		return EINVAL;

	vmp = &vmproc[n];

	r = map_get_phys(vmp, addr, &ret);

	m->m_lc_vm_getphys.ret_addr = (void *) ret;
	return r;
}
Пример #30
0
/*===========================================================================*
 *				do_get_refcount		     		     *
 *===========================================================================*/
int do_get_refcount(message *m)
{
	int r, n;
	struct vmproc *vmp;
	endpoint_t target;
	u8_t cnt;
	vir_bytes addr;

	target = m->VMREFCNT_ENDPT;
	addr = m->VMREFCNT_ADDR;

	if ((r = vm_isokendpt(target, &n)) != OK)
		return EINVAL;

	vmp = &vmproc[n];

	r = map_get_ref(vmp, addr, &cnt);

	m->VMREFCNT_RETC = cnt;
	return r;
}