xref: /minix3/minix/servers/vm/exit.c (revision 5f6c420586374d552d4a81aa129ada5aa46b797d)
1433d6423SLionel Sambuc 
2433d6423SLionel Sambuc #define _SYSTEM 1
3433d6423SLionel Sambuc 
4433d6423SLionel Sambuc #include <minix/callnr.h>
5433d6423SLionel Sambuc #include <minix/com.h>
6433d6423SLionel Sambuc #include <minix/config.h>
7433d6423SLionel Sambuc #include <minix/const.h>
8433d6423SLionel Sambuc #include <minix/ds.h>
9433d6423SLionel Sambuc #include <minix/endpoint.h>
10433d6423SLionel Sambuc #include <minix/minlib.h>
11433d6423SLionel Sambuc #include <minix/type.h>
12433d6423SLionel Sambuc #include <minix/ipc.h>
13433d6423SLionel Sambuc #include <minix/sysutil.h>
14433d6423SLionel Sambuc #include <minix/syslib.h>
15433d6423SLionel Sambuc #include <minix/bitmap.h>
16433d6423SLionel Sambuc 
17433d6423SLionel Sambuc #include <errno.h>
18433d6423SLionel Sambuc #include <assert.h>
19433d6423SLionel Sambuc 
20433d6423SLionel Sambuc #include "glo.h"
21433d6423SLionel Sambuc #include "proto.h"
22433d6423SLionel Sambuc #include "util.h"
23433d6423SLionel Sambuc #include "sanitycheck.h"
24433d6423SLionel Sambuc 
reset_vm_rusage(struct vmproc * vmp)25433d6423SLionel Sambuc static void reset_vm_rusage(struct vmproc *vmp)
26433d6423SLionel Sambuc {
27433d6423SLionel Sambuc 	vmp->vm_total = 0;
28433d6423SLionel Sambuc 	vmp->vm_total_max = 0;
29433d6423SLionel Sambuc 	vmp->vm_minor_page_fault = 0;
30433d6423SLionel Sambuc 	vmp->vm_major_page_fault = 0;
31433d6423SLionel Sambuc }
32433d6423SLionel Sambuc 
free_proc(struct vmproc * vmp)33433d6423SLionel Sambuc void free_proc(struct vmproc *vmp)
34433d6423SLionel Sambuc {
35433d6423SLionel Sambuc 	map_free_proc(vmp);
36433d6423SLionel Sambuc 	pt_free(&vmp->vm_pt);
37433d6423SLionel Sambuc 	region_init(&vmp->vm_regions_avl);
38433d6423SLionel Sambuc #if VMSTATS
39433d6423SLionel Sambuc 	vmp->vm_bytecopies = 0;
40433d6423SLionel Sambuc #endif
41433d6423SLionel Sambuc 	vmp->vm_region_top = 0;
42433d6423SLionel Sambuc 	reset_vm_rusage(vmp);
43433d6423SLionel Sambuc }
44433d6423SLionel Sambuc 
clear_proc(struct vmproc * vmp)45433d6423SLionel Sambuc void clear_proc(struct vmproc *vmp)
46433d6423SLionel Sambuc {
47433d6423SLionel Sambuc 	region_init(&vmp->vm_regions_avl);
48433d6423SLionel Sambuc 	acl_clear(vmp);
49433d6423SLionel Sambuc 	vmp->vm_flags = 0;		/* Clear INUSE, so slot is free. */
50433d6423SLionel Sambuc #if VMSTATS
51433d6423SLionel Sambuc 	vmp->vm_bytecopies = 0;
52433d6423SLionel Sambuc #endif
53433d6423SLionel Sambuc 	vmp->vm_region_top = 0;
54433d6423SLionel Sambuc 	reset_vm_rusage(vmp);
55433d6423SLionel Sambuc }
56433d6423SLionel Sambuc 
57433d6423SLionel Sambuc /*===========================================================================*
58433d6423SLionel Sambuc  *				do_exit					     *
59433d6423SLionel Sambuc  *===========================================================================*/
do_exit(message * msg)60433d6423SLionel Sambuc int do_exit(message *msg)
61433d6423SLionel Sambuc {
62433d6423SLionel Sambuc 	int proc;
63433d6423SLionel Sambuc 	struct vmproc *vmp;
64433d6423SLionel Sambuc 
65433d6423SLionel Sambuc SANITYCHECK(SCL_FUNCTIONS);
66433d6423SLionel Sambuc 
67433d6423SLionel Sambuc 	if(vm_isokendpt(msg->VME_ENDPOINT, &proc) != OK) {
68433d6423SLionel Sambuc 		printf("VM: bogus endpoint VM_EXIT %d\n", msg->VME_ENDPOINT);
69433d6423SLionel Sambuc 		return EINVAL;
70433d6423SLionel Sambuc 	}
71433d6423SLionel Sambuc 	vmp = &vmproc[proc];
72433d6423SLionel Sambuc 
73433d6423SLionel Sambuc 	if(!(vmp->vm_flags & VMF_EXITING)) {
74433d6423SLionel Sambuc 		printf("VM: unannounced VM_EXIT %d\n", msg->VME_ENDPOINT);
75433d6423SLionel Sambuc 		return EINVAL;
76433d6423SLionel Sambuc 	}
77*63483e02SCristiano Giuffrida 	if(vmp->vm_flags & VMF_VM_INSTANCE) {
78*63483e02SCristiano Giuffrida 	    vmp->vm_flags &= ~VMF_VM_INSTANCE;
79*63483e02SCristiano Giuffrida 	    num_vm_instances--;
80*63483e02SCristiano Giuffrida 	}
81433d6423SLionel Sambuc 
82433d6423SLionel Sambuc 	{
83433d6423SLionel Sambuc 		/* Free pagetable and pages allocated by pt code. */
84433d6423SLionel Sambuc SANITYCHECK(SCL_DETAIL);
85433d6423SLionel Sambuc 		free_proc(vmp);
86433d6423SLionel Sambuc SANITYCHECK(SCL_DETAIL);
87433d6423SLionel Sambuc 	}
88433d6423SLionel Sambuc SANITYCHECK(SCL_DETAIL);
89433d6423SLionel Sambuc 
90433d6423SLionel Sambuc 	/* Reset process slot fields. */
91433d6423SLionel Sambuc 	clear_proc(vmp);
92433d6423SLionel Sambuc 
93433d6423SLionel Sambuc SANITYCHECK(SCL_FUNCTIONS);
94433d6423SLionel Sambuc 	return OK;
95433d6423SLionel Sambuc }
96433d6423SLionel Sambuc 
97433d6423SLionel Sambuc /*===========================================================================*
98433d6423SLionel Sambuc  *				do_willexit				     *
99433d6423SLionel Sambuc  *===========================================================================*/
do_willexit(message * msg)100433d6423SLionel Sambuc int do_willexit(message *msg)
101433d6423SLionel Sambuc {
102433d6423SLionel Sambuc 	int proc;
103433d6423SLionel Sambuc 	struct vmproc *vmp;
104433d6423SLionel Sambuc 
105433d6423SLionel Sambuc 	if(vm_isokendpt(msg->VMWE_ENDPOINT, &proc) != OK) {
106433d6423SLionel Sambuc 		printf("VM: bogus endpoint VM_EXITING %d\n",
107433d6423SLionel Sambuc 			msg->VMWE_ENDPOINT);
108433d6423SLionel Sambuc 		return EINVAL;
109433d6423SLionel Sambuc 	}
110433d6423SLionel Sambuc 	vmp = &vmproc[proc];
111433d6423SLionel Sambuc 
112433d6423SLionel Sambuc 	vmp->vm_flags |= VMF_EXITING;
113433d6423SLionel Sambuc 
114433d6423SLionel Sambuc 	return OK;
115433d6423SLionel Sambuc }
116433d6423SLionel Sambuc 
do_procctl(message * msg,int transid)117433d6423SLionel Sambuc int do_procctl(message *msg, int transid)
118433d6423SLionel Sambuc {
119433d6423SLionel Sambuc 	endpoint_t proc;
120433d6423SLionel Sambuc 	struct vmproc *vmp;
121433d6423SLionel Sambuc 
122433d6423SLionel Sambuc 	if(vm_isokendpt(msg->VMPCTL_WHO, &proc) != OK) {
123433d6423SLionel Sambuc 		printf("VM: bogus endpoint VM_PROCCTL %ld\n",
124433d6423SLionel Sambuc 			msg->VMPCTL_WHO);
125433d6423SLionel Sambuc 		return EINVAL;
126433d6423SLionel Sambuc 	}
127433d6423SLionel Sambuc 	vmp = &vmproc[proc];
128433d6423SLionel Sambuc 
129433d6423SLionel Sambuc 	switch(msg->VMPCTL_PARAM) {
130433d6423SLionel Sambuc 		case VMPPARAM_CLEAR:
131433d6423SLionel Sambuc 			if(msg->m_source != RS_PROC_NR
132433d6423SLionel Sambuc 				&& msg->m_source != VFS_PROC_NR)
133433d6423SLionel Sambuc 				return EPERM;
134433d6423SLionel Sambuc 			free_proc(vmp);
135433d6423SLionel Sambuc 			if(pt_new(&vmp->vm_pt) != OK)
136433d6423SLionel Sambuc 				panic("VMPPARAM_CLEAR: pt_new failed");
137433d6423SLionel Sambuc 			pt_bind(&vmp->vm_pt, vmp);
138433d6423SLionel Sambuc 			return OK;
139433d6423SLionel Sambuc 		case VMPPARAM_HANDLEMEM:
140433d6423SLionel Sambuc 		{
141433d6423SLionel Sambuc 			if(msg->m_source != VFS_PROC_NR)
142433d6423SLionel Sambuc 				return EPERM;
143433d6423SLionel Sambuc 
144433d6423SLionel Sambuc                         handle_memory_start(vmp, msg->VMPCTL_M1,
145433d6423SLionel Sambuc 				msg->VMPCTL_LEN, msg->VMPCTL_FLAGS,
146433d6423SLionel Sambuc                                 VFS_PROC_NR, VFS_PROC_NR, transid, 1);
147433d6423SLionel Sambuc 
148433d6423SLionel Sambuc 			return SUSPEND;
149433d6423SLionel Sambuc 		}
150433d6423SLionel Sambuc 		default:
151433d6423SLionel Sambuc 			return EINVAL;
152433d6423SLionel Sambuc 	}
153433d6423SLionel Sambuc 
154433d6423SLionel Sambuc 	return OK;
155433d6423SLionel Sambuc }
156433d6423SLionel Sambuc 
157