This source file includes following definitions.
- is_bitset
- fast_intxx
- vm86_return
- vm86_gpfault
- i386_vm86
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/signalvar.h>
43 #include <sys/kernel.h>
44 #include <sys/proc.h>
45 #include <sys/user.h>
46 #include <sys/exec.h>
47 #include <sys/buf.h>
48 #include <sys/reboot.h>
49 #include <sys/conf.h>
50 #include <sys/file.h>
51 #include <sys/malloc.h>
52 #include <sys/mbuf.h>
53 #include <sys/msgbuf.h>
54 #include <sys/mount.h>
55 #include <sys/vnode.h>
56 #include <sys/device.h>
57 #include <sys/sysctl.h>
58 #include <sys/syscallargs.h>
59 #ifdef SYSVMSG
60 #include <sys/msg.h>
61 #endif
62 #ifdef SYSVSEM
63 #include <sys/sem.h>
64 #endif
65 #ifdef SYSVSHM
66 #include <sys/shm.h>
67 #endif
68
69 #include <sys/ktrace.h>
70 #include <machine/sysarch.h>
71 #include <machine/vm86.h>
72
73 static void fast_intxx(struct proc *, int);
74 static __inline int is_bitset(int, caddr_t);
75
76 #define CS(tf) (*(u_short *)&tf->tf_cs)
77 #define IP(tf) (*(u_short *)&tf->tf_eip)
78 #define SS(tf) (*(u_short *)&tf->tf_ss)
79 #define SP(tf) (*(u_short *)&tf->tf_esp)
80
81
82 #define putword(base, ptr, val) \
83 __asm__ __volatile__( \
84 "decw %w0\n\t" \
85 "movb %h2,0(%1,%0)\n\t" \
86 "decw %w0\n\t" \
87 "movb %b2,0(%1,%0)" \
88 : "=r" (ptr) \
89 : "r" (base), "q" (val), "0" (ptr))
90
91 #define putdword(base, ptr, val) \
92 __asm__ __volatile__( \
93 "rorl $16,%2\n\t" \
94 "decw %w0\n\t" \
95 "movb %h2,0(%1,%0)\n\t" \
96 "decw %w0\n\t" \
97 "movb %b2,0(%1,%0)\n\t" \
98 "rorl $16,%2\n\t" \
99 "decw %w0\n\t" \
100 "movb %h2,0(%1,%0)\n\t" \
101 "decw %w0\n\t" \
102 "movb %b2,0(%1,%0)" \
103 : "=r" (ptr) \
104 : "r" (base), "q" (val), "0" (ptr))
105
106 #define getbyte(base, ptr) \
107 ({ unsigned long __res; \
108 __asm__ __volatile__( \
109 "movb 0(%1,%0),%b2\n\t" \
110 "incw %w0" \
111 : "=r" (ptr), "=r" (base), "=q" (__res) \
112 : "0" (ptr), "1" (base), "2" (0)); \
113 __res; })
114
115 #define getword(base, ptr) \
116 ({ unsigned long __res; \
117 __asm__ __volatile__( \
118 "movb 0(%1,%0),%b2\n\t" \
119 "incw %w0\n\t" \
120 "movb 0(%1,%0),%h2\n\t" \
121 "incw %w0" \
122 : "=r" (ptr), "=r" (base), "=q" (__res) \
123 : "0" (ptr), "1" (base), "2" (0)); \
124 __res; })
125
126 #define getdword(base, ptr) \
127 ({ unsigned long __res; \
128 __asm__ __volatile__( \
129 "movb 0(%1,%0),%b2\n\t" \
130 "incw %w0\n\t" \
131 "movb 0(%1,%0),%h2\n\t" \
132 "incw %w0\n\t" \
133 "rorl $16,%2\n\t" \
134 "movb 0(%1,%0),%b2\n\t" \
135 "incw %w0\n\t" \
136 "movb 0(%1,%0),%h2\n\t" \
137 "incw %w0\n\t" \
138 "rorl $16,%2" \
139 : "=r" (ptr), "=r" (base), "=q" (__res) \
140 : "0" (ptr), "1" (base)); \
141 __res; })
142
143
144 static __inline int
145 is_bitset(int nr, caddr_t bitmap)
146 {
147 u_int byte;
148
149 bitmap += nr / NBBY;
150 nr = nr % NBBY;
151 copyin(bitmap, &byte, sizeof(u_char));
152
153 __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
154 :"=r" (nr)
155 :"r" (byte),"r" (nr));
156 return (nr);
157 }
158
159
160 #define V86_AH(regs) (((u_char *)&((regs)->tf_eax))[1])
161 #define V86_AL(regs) (((u_char *)&((regs)->tf_eax))[0])
162
163 static void
164 fast_intxx(struct proc *p, int intrno)
165 {
166 struct trapframe *tf = p->p_md.md_regs;
167
168
169
170
171
172 struct vm86_struct *u_vm86p;
173 struct { u_short ip, cs; } ihand;
174
175 u_long ss, sp;
176
177
178
179
180
181
182 u_vm86p = (struct vm86_struct *)p->p_addr->u_pcb.vm86_userp;
183
184
185
186
187
188 if (is_bitset(intrno, &u_vm86p->int_byuser[0]))
189 goto vector;
190
191
192
193
194
195
196 if (intrno == 0x21 && is_bitset(V86_AH(tf), &u_vm86p->int21_byuser[0]))
197 goto vector;
198
199
200
201
202
203 if (copyin((caddr_t)(intrno * sizeof(ihand)), &ihand, sizeof(ihand)))
204 goto bad;
205
206
207
208
209
210 ss = SS(tf) << 4;
211 sp = SP(tf);
212
213 putword(ss, sp, get_vflags_short(p));
214 putword(ss, sp, CS(tf));
215 putword(ss, sp, IP(tf));
216 SP(tf) = sp;
217
218 IP(tf) = ihand.ip;
219 CS(tf) = ihand.cs;
220
221 return;
222
223 vector:
224 vm86_return(p, VM86_MAKEVAL(VM86_INTx, intrno));
225 return;
226
227 bad:
228 vm86_return(p, VM86_UNKNOWN);
229 return;
230 }
231
232 void
233 vm86_return(struct proc *p, int retval)
234 {
235 union sigval sv;
236
237
238
239
240
241
242 if (p->p_sigmask & sigmask(SIGURG)) {
243 #ifdef DIAGNOSTIC
244 printf("pid %d killed on VM86 protocol screwup (SIGURG blocked)\n",
245 p->p_pid);
246 #endif
247 sigexit(p, SIGILL);
248
249 }
250 sv.sival_int = 0;
251 trapsignal(p, SIGURG, retval, 0, sv);
252 }
253
254 #define CLI 0xFA
255 #define STI 0xFB
256 #define INTxx 0xCD
257 #define INTO 0xCE
258 #define IRET 0xCF
259 #define OPSIZ 0x66
260 #define INT3 0xCC
261 #define LOCK 0xF0
262 #define PUSHF 0x9C
263 #define POPF 0x9D
264
265
266
267
268
269
270 void
271 vm86_gpfault(struct proc *p, int type)
272 {
273 struct trapframe *tf = p->p_md.md_regs;
274 union sigval sv;
275
276
277
278
279
280
281 u_long cs, ip, ss, sp;
282 u_char tmpbyte;
283 int trace;
284
285 cs = CS(tf) << 4;
286 ip = IP(tf);
287 ss = SS(tf) << 4;
288 sp = SP(tf);
289
290 trace = tf->tf_eflags & PSL_T;
291
292
293
294
295
296 tmpbyte = getbyte(cs, ip);
297 IP(tf) = ip;
298 switch (tmpbyte) {
299 case CLI:
300
301 clr_vif(p);
302 break;
303
304 case STI:
305
306
307
308
309 set_vif(p);
310 break;
311
312 case INTxx:
313
314 tmpbyte = getbyte(cs, ip);
315 IP(tf) = ip;
316 fast_intxx(p, tmpbyte);
317 break;
318
319 case INTO:
320 if (tf->tf_eflags & PSL_V)
321 fast_intxx(p, 4);
322 break;
323
324 case PUSHF:
325 putword(ss, sp, get_vflags_short(p));
326 SP(tf) = sp;
327 break;
328
329 case IRET:
330 IP(tf) = getword(ss, sp);
331 CS(tf) = getword(ss, sp);
332 case POPF:
333 set_vflags_short(p, getword(ss, sp));
334 SP(tf) = sp;
335 break;
336
337 case OPSIZ:
338 tmpbyte = getbyte(cs, ip);
339 IP(tf) = ip;
340 switch (tmpbyte) {
341 case PUSHF:
342 putdword(ss, sp, get_vflags(p) & ~PSL_VM);
343 SP(tf) = sp;
344 break;
345
346 case IRET:
347 IP(tf) = getdword(ss, sp);
348 CS(tf) = getdword(ss, sp);
349 case POPF:
350 set_vflags(p, getdword(ss, sp) | PSL_VM);
351 SP(tf) = sp;
352 break;
353
354 default:
355 IP(tf) -= 2;
356 goto bad;
357 }
358 break;
359
360 case LOCK:
361 default:
362 IP(tf) -= 1;
363 goto bad;
364 }
365
366 if (trace && tf->tf_eflags & PSL_VM) {
367 sv.sival_int = 0;
368 trapsignal(p, SIGTRAP, T_TRCTRAP, TRAP_TRACE, sv);
369 }
370 return;
371
372 bad:
373 vm86_return(p, VM86_UNKNOWN);
374 return;
375 }
376
377 int
378 i386_vm86(struct proc *p, char *args, register_t *retval)
379 {
380 struct trapframe *tf = p->p_md.md_regs;
381 struct pcb *pcb = &p->p_addr->u_pcb;
382 struct vm86_kern vm86s;
383 int error;
384
385 error = copyin(args, &vm86s, sizeof(vm86s));
386 if (error)
387 return (error);
388
389 pcb->vm86_userp = (void *)args;
390
391
392
393
394
395 switch (vm86s.ss_cpu_type) {
396 case VCPU_086:
397 case VCPU_186:
398 case VCPU_286:
399 pcb->vm86_flagmask = PSL_ID|PSL_AC|PSL_NT|PSL_IOPL;
400 break;
401 case VCPU_386:
402 pcb->vm86_flagmask = PSL_ID|PSL_AC;
403 break;
404 case VCPU_486:
405 pcb->vm86_flagmask = PSL_ID;
406 break;
407 case VCPU_586:
408 pcb->vm86_flagmask = 0;
409 break;
410 default:
411 return (EINVAL);
412 }
413
414 #define DOVREG(reg) tf->tf_vm86_##reg = (u_short) vm86s.regs.vmsc.sc_##reg
415 #define DOREG(reg) tf->tf_##reg = (u_short) vm86s.regs.vmsc.sc_##reg
416
417 DOVREG(ds);
418 DOVREG(es);
419 DOVREG(fs);
420 DOVREG(gs);
421 DOREG(edi);
422 DOREG(esi);
423 DOREG(ebp);
424 DOREG(eax);
425 DOREG(ebx);
426 DOREG(ecx);
427 DOREG(edx);
428 DOREG(eip);
429 DOREG(cs);
430 DOREG(esp);
431 DOREG(ss);
432
433 #undef DOVREG
434 #undef DOREG
435
436
437 p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
438
439 set_vflags(p, vm86s.regs.vmsc.sc_eflags | PSL_VM);
440
441 return (EJUSTRETURN);
442 }