1 /* The kernel call implemented in this file:
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
10 #include "../system.h"
13 #include <minix/type.h>
15 /*===========================================================================*
17 *===========================================================================*/
18 PUBLIC
int do_vmctl(struct proc
* caller
, message
* m_ptr
)
21 endpoint_t ep
= m_ptr
->SVMCTL_WHO
;
22 struct proc
*p
, *rp
, *target
;
25 if(ep
== SELF
) { ep
= m_ptr
->m_source
; }
27 if(!isokendpt(ep
, &proc_nr
)) {
28 kprintf("do_vmctl: unexpected endpoint %d from VM\n", ep
);
32 p
= proc_addr(proc_nr
);
34 switch(m_ptr
->SVMCTL_PARAM
) {
35 case VMCTL_CLEAR_PAGEFAULT
:
36 RTS_LOCK_UNSET(p
, RTS_PAGEFAULT
);
38 case VMCTL_MEMREQ_GET
:
39 /* Send VM the information about the memory request. */
42 vmassert(RTS_ISSET(rp
, RTS_VMREQUEST
));
45 printf("kernel: vm request sent by: %s / %d about %d; 0x%lx-0x%lx, wr %d, stack: %s ",
46 rp
->p_name
, rp
->p_endpoint
, rp
->p_vmrequest
.who
,
47 rp
->p_vmrequest
.start
,
48 rp
->p_vmrequest
.start
+ rp
->p_vmrequest
.length
,
49 rp
->p_vmrequest
.writeflag
, rp
->p_vmrequest
.stacktrace
);
50 printf("type %d\n", rp
->p_vmrequest
.type
);
54 okendpt(rp
->p_vmrequest
.who
, &proc_nr
);
55 target
= proc_addr(proc_nr
);
57 if(!RTS_ISSET(target
, RTS_VMREQTARGET
)) {
58 printf("set stack: %s\n", rp
->p_vmrequest
.stacktrace
);
59 minix_panic("RTS_VMREQTARGET not set for target",
65 /* Reply with request fields. */
66 switch(rp
->p_vmrequest
.req_type
) {
68 m_ptr
->SVMCTL_MRG_TARGET
=
69 rp
->p_vmrequest
.target
;
70 m_ptr
->SVMCTL_MRG_ADDR
=
71 rp
->p_vmrequest
.params
.check
.start
;
72 m_ptr
->SVMCTL_MRG_LENGTH
=
73 rp
->p_vmrequest
.params
.check
.length
;
74 m_ptr
->SVMCTL_MRG_FLAG
=
75 rp
->p_vmrequest
.params
.check
.writeflag
;
76 m_ptr
->SVMCTL_MRG_REQUESTOR
=
77 (void *) rp
->p_endpoint
;
82 m_ptr
->SVMCTL_MRG_TARGET
=
83 rp
->p_vmrequest
.target
;
84 m_ptr
->SVMCTL_MRG_ADDR
=
85 rp
->p_vmrequest
.params
.map
.vir_d
;
86 m_ptr
->SVMCTL_MRG_EP2
=
87 rp
->p_vmrequest
.params
.map
.ep_s
;
88 m_ptr
->SVMCTL_MRG_ADDR2
=
89 rp
->p_vmrequest
.params
.map
.vir_s
;
90 m_ptr
->SVMCTL_MRG_LENGTH
=
91 rp
->p_vmrequest
.params
.map
.length
;
92 m_ptr
->SVMCTL_MRG_FLAG
=
93 rp
->p_vmrequest
.params
.map
.writeflag
;
94 m_ptr
->SVMCTL_MRG_REQUESTOR
=
95 (void *) rp
->p_endpoint
;
98 minix_panic("VMREQUEST wrong type", NO_NUM
);
101 rp
->p_vmrequest
.vmresult
= VMSUSPEND
;
103 /* Remove from request chain. */
104 vmrequest
= vmrequest
->p_vmrequest
.nextrequestor
;
106 return rp
->p_vmrequest
.req_type
;
107 case VMCTL_MEMREQ_REPLY
:
108 vmassert(RTS_ISSET(p
, RTS_VMREQUEST
));
109 vmassert(p
->p_vmrequest
.vmresult
== VMSUSPEND
);
110 okendpt(p
->p_vmrequest
.target
, &proc_nr
);
111 target
= proc_addr(proc_nr
);
112 p
->p_vmrequest
.vmresult
= m_ptr
->SVMCTL_VALUE
;
113 vmassert(p
->p_vmrequest
.vmresult
!= VMSUSPEND
);
115 if(p
->p_vmrequest
.vmresult
!= OK
)
116 kprintf("SYSTEM: VM replied %d to mem request\n",
117 p
->p_vmrequest
.vmresult
);
119 printf("memreq reply: vm request sent by: %s / %d about %d; 0x%lx-0x%lx, wr %d, stack: %s ",
120 p
->p_name
, p
->p_endpoint
, p
->p_vmrequest
.who
,
121 p
->p_vmrequest
.start
,
122 p
->p_vmrequest
.start
+ p
->p_vmrequest
.length
,
123 p
->p_vmrequest
.writeflag
, p
->p_vmrequest
.stacktrace
);
124 printf("type %d\n", p
->p_vmrequest
.type
);
127 vmassert(RTS_ISSET(target
, RTS_VMREQTARGET
));
128 RTS_LOCK_UNSET(target
, RTS_VMREQTARGET
);
130 switch(p
->p_vmrequest
.type
) {
131 case VMSTYPE_KERNELCALL
:
132 /* Put on restart chain. */
133 p
->p_vmrequest
.nextrestart
= vmrestart
;
136 case VMSTYPE_DELIVERMSG
:
137 vmassert(p
->p_misc_flags
& MF_DELIVERMSG
);
138 vmassert(p
== target
);
139 vmassert(RTS_ISSET(p
, RTS_VMREQUEST
));
140 RTS_LOCK_UNSET(p
, RTS_VMREQUEST
);
143 vmassert(RTS_ISSET(p
, RTS_VMREQUEST
));
144 RTS_LOCK_UNSET(p
, RTS_VMREQUEST
);
148 printf("suspended with stack: %s\n",
149 p
->p_vmrequest
.stacktrace
);
151 minix_panic("strange request type",
152 p
->p_vmrequest
.type
);
156 case VMCTL_ENABLE_PAGING
:
158 * system task must not get preempted while switching to paging,
159 * interrupt handling is not safe
163 minix_panic("do_vmctl: paging already enabled", NO_NUM
);
166 minix_panic("do_vmctl: paging enabling failed", NO_NUM
);
167 vmassert(p
->p_delivermsg_lin
==
168 umap_local(p
, D
, p
->p_delivermsg_vir
, sizeof(message
)));
169 if ((err
= arch_enable_paging()) != OK
) {
173 if(newmap(caller
, p
, (struct mem_map
*) m_ptr
->SVMCTL_VALUE
) != OK
)
174 minix_panic("do_vmctl: newmap failed", NO_NUM
);
176 vmassert(p
->p_delivermsg_lin
);
179 case VMCTL_KERN_PHYSMAP
:
181 int i
= m_ptr
->SVMCTL_VALUE
;
182 return arch_phys_map(i
,
183 (phys_bytes
*) &m_ptr
->SVMCTL_MAP_PHYS_ADDR
,
184 (phys_bytes
*) &m_ptr
->SVMCTL_MAP_PHYS_LEN
,
185 &m_ptr
->SVMCTL_MAP_FLAGS
);
187 case VMCTL_KERN_MAP_REPLY
:
189 return arch_phys_map_reply(m_ptr
->SVMCTL_VALUE
,
190 (vir_bytes
) m_ptr
->SVMCTL_MAP_VIR_ADDR
);
194 /* Try architecture-specific vmctls. */
195 return arch_do_vmctl(m_ptr
, p
);