3.1.7 branch.
[minix.git] / kernel / system / do_vmctl.c
blobc5fdbd865f8810eaa091be2673ba3d623b871c55
1 /* The kernel call implemented in this file:
2 * m_type: SYS_VMCTL
4 * The parameters for this kernel call are:
5 * SVMCTL_WHO which process
6 * SVMCTL_PARAM set this setting (VMCTL_*)
7 * SVMCTL_VALUE to this value
8 */
10 #include "kernel/system.h"
11 #include "kernel/vm.h"
12 #include "kernel/debug.h"
13 #include <assert.h>
14 #include <minix/type.h>
16 /*===========================================================================*
17 * do_vmctl *
18 *===========================================================================*/
19 PUBLIC int do_vmctl(struct proc * caller, message * m_ptr)
21 int proc_nr;
22 endpoint_t ep = m_ptr->SVMCTL_WHO;
23 struct proc *p, *rp, *target;
25 if(ep == SELF) { ep = caller->p_endpoint; }
27 if(!isokendpt(ep, &proc_nr)) {
28 printf("do_vmctl: unexpected endpoint %d from VM\n", ep);
29 return EINVAL;
32 p = proc_addr(proc_nr);
34 switch(m_ptr->SVMCTL_PARAM) {
35 case VMCTL_CLEAR_PAGEFAULT:
36 assert(RTS_ISSET(p,RTS_PAGEFAULT));
37 RTS_UNSET(p, RTS_PAGEFAULT);
38 return OK;
39 case VMCTL_MEMREQ_GET:
40 /* Send VM the information about the memory request. */
41 if(!(rp = vmrequest))
42 return ESRCH;
43 assert(RTS_ISSET(rp, RTS_VMREQUEST));
45 okendpt(rp->p_vmrequest.target, &proc_nr);
46 target = proc_addr(proc_nr);
48 /* Reply with request fields. */
49 switch(rp->p_vmrequest.req_type) {
50 case VMPTYPE_CHECK:
51 m_ptr->SVMCTL_MRG_TARGET =
52 rp->p_vmrequest.target;
53 m_ptr->SVMCTL_MRG_ADDR =
54 rp->p_vmrequest.params.check.start;
55 m_ptr->SVMCTL_MRG_LENGTH =
56 rp->p_vmrequest.params.check.length;
57 m_ptr->SVMCTL_MRG_FLAG =
58 rp->p_vmrequest.params.check.writeflag;
59 m_ptr->SVMCTL_MRG_REQUESTOR =
60 (void *) rp->p_endpoint;
61 break;
62 case VMPTYPE_SMAP:
63 case VMPTYPE_SUNMAP:
64 case VMPTYPE_COWMAP:
65 assert(RTS_ISSET(target,RTS_VMREQTARGET));
66 RTS_UNSET(target, RTS_VMREQTARGET);
67 m_ptr->SVMCTL_MRG_TARGET =
68 rp->p_vmrequest.target;
69 m_ptr->SVMCTL_MRG_ADDR =
70 rp->p_vmrequest.params.map.vir_d;
71 m_ptr->SVMCTL_MRG_EP2 =
72 rp->p_vmrequest.params.map.ep_s;
73 m_ptr->SVMCTL_MRG_ADDR2 =
74 rp->p_vmrequest.params.map.vir_s;
75 m_ptr->SVMCTL_MRG_LENGTH =
76 rp->p_vmrequest.params.map.length;
77 m_ptr->SVMCTL_MRG_FLAG =
78 rp->p_vmrequest.params.map.writeflag;
79 m_ptr->SVMCTL_MRG_REQUESTOR =
80 (void *) rp->p_endpoint;
81 break;
82 default:
83 panic("VMREQUEST wrong type");
86 rp->p_vmrequest.vmresult = VMSUSPEND;
88 /* Remove from request chain. */
89 vmrequest = vmrequest->p_vmrequest.nextrequestor;
91 return rp->p_vmrequest.req_type;
92 case VMCTL_MEMREQ_REPLY:
93 assert(RTS_ISSET(p, RTS_VMREQUEST));
94 assert(p->p_vmrequest.vmresult == VMSUSPEND);
95 okendpt(p->p_vmrequest.target, &proc_nr);
96 target = proc_addr(proc_nr);
97 p->p_vmrequest.vmresult = m_ptr->SVMCTL_VALUE;
98 assert(p->p_vmrequest.vmresult != VMSUSPEND);
100 switch(p->p_vmrequest.type) {
101 case VMSTYPE_KERNELCALL:
103 * we will have to resume execution of the kernel call
104 * as soon the scheduler picks up this process again
106 p->p_misc_flags |= MF_KCALL_RESUME;
107 break;
108 case VMSTYPE_DELIVERMSG:
109 assert(p->p_misc_flags & MF_DELIVERMSG);
110 assert(p == target);
111 assert(RTS_ISSET(p, RTS_VMREQUEST));
112 break;
113 case VMSTYPE_MAP:
114 assert(RTS_ISSET(p, RTS_VMREQUEST));
115 break;
116 default:
117 panic("strange request type: %d",p->p_vmrequest.type);
120 RTS_UNSET(p, RTS_VMREQUEST);
121 return OK;
123 case VMCTL_ENABLE_PAGING:
124 if(vm_running)
125 panic("do_vmctl: paging already enabled");
126 vm_init(p);
127 if(!vm_running)
128 panic("do_vmctl: paging enabling failed");
129 return arch_enable_paging(caller, m_ptr);
130 case VMCTL_KERN_PHYSMAP:
132 int i = m_ptr->SVMCTL_VALUE;
133 return arch_phys_map(i,
134 (phys_bytes *) &m_ptr->SVMCTL_MAP_PHYS_ADDR,
135 (phys_bytes *) &m_ptr->SVMCTL_MAP_PHYS_LEN,
136 &m_ptr->SVMCTL_MAP_FLAGS);
138 case VMCTL_KERN_MAP_REPLY:
140 return arch_phys_map_reply(m_ptr->SVMCTL_VALUE,
141 (vir_bytes) m_ptr->SVMCTL_MAP_VIR_ADDR);
145 /* Try architecture-specific vmctls. */
146 return arch_do_vmctl(m_ptr, p);