Mercurial > mplayer.hg
annotate osdep/lrmi.c @ 11434:5084f09ba20e
Fix pthread & lrmi segfault issue. ("Oleg I. Vdovikin" <vdovikin@jscc.ru>)
author | ranma |
---|---|
date | Tue, 11 Nov 2003 10:39:36 +0000 |
parents | 608666e629b2 |
children | 22f8732b5d97 |
rev | line source |
---|---|
2212 | 1 /* |
2 Linux Real Mode Interface - A library of DPMI-like functions for Linux. | |
3 | |
4 Copyright (C) 1998 by Josh Vanderhoof | |
5 | |
6 You are free to distribute and modify this file, as long as you | |
7 do not remove this copyright notice and clearly label modified | |
8 versions as being modified. | |
9 | |
10 This software has NO WARRANTY. Use it at your own risk. | |
11 Original location: http://cvs.debian.org/lrmi/ | |
12 */ | |
13 | |
11434
5084f09ba20e
Fix pthread & lrmi segfault issue. ("Oleg I. Vdovikin" <vdovikin@jscc.ru>)
ranma
parents:
10857
diff
changeset
|
14 #include <signal.h> |
2212 | 15 #include <stdio.h> |
16 #include <string.h> | |
17 #include <sys/io.h> | |
18 #include <asm/vm86.h> | |
19 | |
20 #ifdef USE_LIBC_VM86 | |
21 #include <sys/vm86.h> | |
22 #endif | |
23 | |
24 #include <sys/types.h> | |
25 #include <sys/stat.h> | |
26 #include <sys/mman.h> | |
27 #include <unistd.h> | |
28 #include <fcntl.h> | |
29 | |
30 #include "lrmi.h" | |
31 | |
32 #define REAL_MEM_BASE ((void *)0x10000) | |
33 #define REAL_MEM_SIZE 0x10000 | |
34 #define REAL_MEM_BLOCKS 0x100 | |
35 | |
36 struct mem_block | |
37 { | |
38 unsigned int size : 20; | |
39 unsigned int free : 1; | |
40 }; | |
41 | |
42 static struct | |
43 { | |
44 int ready; | |
45 int count; | |
46 struct mem_block blocks[REAL_MEM_BLOCKS]; | |
10857 | 47 } mem_info = { .ready = 0, }; |
2212 | 48 |
49 static int | |
50 real_mem_init(void) | |
51 { | |
52 void *m; | |
53 int fd_zero; | |
54 | |
55 if (mem_info.ready) | |
56 return 1; | |
57 | |
58 fd_zero = open("/dev/zero", O_RDONLY); | |
59 if (fd_zero == -1) | |
60 { | |
61 perror("open /dev/zero"); | |
62 return 0; | |
63 } | |
64 | |
65 m = mmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE, | |
66 PROT_READ | PROT_WRITE | PROT_EXEC, | |
67 MAP_FIXED | MAP_PRIVATE, fd_zero, 0); | |
68 | |
69 if (m == (void *)-1) | |
70 { | |
71 perror("mmap /dev/zero"); | |
72 close(fd_zero); | |
73 return 0; | |
74 } | |
75 | |
76 mem_info.ready = 1; | |
77 mem_info.count = 1; | |
78 mem_info.blocks[0].size = REAL_MEM_SIZE; | |
79 mem_info.blocks[0].free = 1; | |
80 | |
81 return 1; | |
82 } | |
83 | |
84 | |
85 static void | |
86 insert_block(int i) | |
87 { | |
88 memmove( | |
89 mem_info.blocks + i + 1, | |
90 mem_info.blocks + i, | |
91 (mem_info.count - i) * sizeof(struct mem_block)); | |
92 | |
93 mem_info.count++; | |
94 } | |
95 | |
96 static void | |
97 delete_block(int i) | |
98 { | |
99 mem_info.count--; | |
100 | |
101 memmove( | |
102 mem_info.blocks + i, | |
103 mem_info.blocks + i + 1, | |
104 (mem_info.count - i) * sizeof(struct mem_block)); | |
105 } | |
106 | |
107 void * | |
108 LRMI_alloc_real(int size) | |
109 { | |
110 int i; | |
111 char *r = (char *)REAL_MEM_BASE; | |
112 | |
113 if (!mem_info.ready) | |
114 return NULL; | |
115 | |
116 if (mem_info.count == REAL_MEM_BLOCKS) | |
117 return NULL; | |
118 | |
119 size = (size + 15) & ~15; | |
120 | |
121 for (i = 0; i < mem_info.count; i++) | |
122 { | |
123 if (mem_info.blocks[i].free && size < mem_info.blocks[i].size) | |
124 { | |
125 insert_block(i); | |
126 | |
127 mem_info.blocks[i].size = size; | |
128 mem_info.blocks[i].free = 0; | |
129 mem_info.blocks[i + 1].size -= size; | |
130 | |
131 return (void *)r; | |
132 } | |
133 | |
134 r += mem_info.blocks[i].size; | |
135 } | |
136 | |
137 return NULL; | |
138 } | |
139 | |
140 | |
141 void | |
142 LRMI_free_real(void *m) | |
143 { | |
144 int i; | |
145 char *r = (char *)REAL_MEM_BASE; | |
146 | |
147 if (!mem_info.ready) | |
148 return; | |
149 | |
150 i = 0; | |
151 while (m != (void *)r) | |
152 { | |
153 r += mem_info.blocks[i].size; | |
154 i++; | |
155 if (i == mem_info.count) | |
156 return; | |
157 } | |
158 | |
159 mem_info.blocks[i].free = 1; | |
160 | |
161 if (i + 1 < mem_info.count && mem_info.blocks[i + 1].free) | |
162 { | |
163 mem_info.blocks[i].size += mem_info.blocks[i + 1].size; | |
164 delete_block(i + 1); | |
165 } | |
166 | |
167 if (i - 1 >= 0 && mem_info.blocks[i - 1].free) | |
168 { | |
169 mem_info.blocks[i - 1].size += mem_info.blocks[i].size; | |
170 delete_block(i); | |
171 } | |
172 } | |
173 | |
174 | |
175 #define DEFAULT_VM86_FLAGS (IF_MASK | IOPL_MASK) | |
176 #define DEFAULT_STACK_SIZE 0x1000 | |
177 #define RETURN_TO_32_INT 255 | |
178 | |
179 static struct | |
180 { | |
181 int ready; | |
182 unsigned short ret_seg, ret_off; | |
183 unsigned short stack_seg, stack_off; | |
184 struct vm86_struct vm; | |
10857 | 185 } context = { .ready = 0, }; |
2212 | 186 |
187 | |
188 static inline void | |
189 set_bit(unsigned int bit, void *array) | |
190 { | |
191 unsigned char *a = array; | |
192 | |
193 a[bit / 8] |= (1 << (bit % 8)); | |
194 } | |
195 | |
196 | |
197 static inline unsigned int | |
198 get_int_seg(int i) | |
199 { | |
200 return *(unsigned short *)(i * 4 + 2); | |
201 } | |
202 | |
203 | |
204 static inline unsigned int | |
205 get_int_off(int i) | |
206 { | |
207 return *(unsigned short *)(i * 4); | |
208 } | |
209 | |
210 | |
211 static inline void | |
212 pushw(unsigned short i) | |
213 { | |
214 struct vm86_regs *r = &context.vm.regs; | |
215 r->esp -= 2; | |
216 *(unsigned short *)(((unsigned int)r->ss << 4) + r->esp) = i; | |
217 } | |
218 | |
219 | |
220 int | |
221 LRMI_init(void) | |
222 { | |
223 void *m; | |
224 int fd_mem; | |
225 | |
226 if (context.ready) | |
227 return 1; | |
228 | |
229 if (!real_mem_init()) | |
230 return 0; | |
231 | |
232 /* | |
233 Map the Interrupt Vectors (0x0 - 0x400) + BIOS data (0x400 - 0x502) | |
234 and the ROM (0xa0000 - 0x100000) | |
235 */ | |
236 fd_mem = open("/dev/mem", O_RDWR); | |
237 | |
238 if (fd_mem == -1) | |
239 { | |
240 perror("open /dev/mem"); | |
241 return 0; | |
242 } | |
243 | |
244 m = mmap((void *)0, 0x502, | |
245 PROT_READ | PROT_WRITE | PROT_EXEC, | |
246 MAP_FIXED | MAP_PRIVATE, fd_mem, 0); | |
247 | |
248 if (m == (void *)-1) | |
249 { | |
250 perror("mmap /dev/mem"); | |
251 return 0; | |
252 } | |
253 | |
254 m = mmap((void *)0xa0000, 0x100000 - 0xa0000, | |
255 PROT_READ | PROT_WRITE, | |
256 MAP_FIXED | MAP_SHARED, fd_mem, 0xa0000); | |
257 | |
258 if (m == (void *)-1) | |
259 { | |
260 perror("mmap /dev/mem"); | |
261 return 0; | |
262 } | |
263 | |
264 | |
265 /* | |
266 Allocate a stack | |
267 */ | |
268 m = LRMI_alloc_real(DEFAULT_STACK_SIZE); | |
269 | |
270 context.stack_seg = (unsigned int)m >> 4; | |
271 context.stack_off = DEFAULT_STACK_SIZE; | |
272 | |
273 /* | |
274 Allocate the return to 32 bit routine | |
275 */ | |
276 m = LRMI_alloc_real(2); | |
277 | |
278 context.ret_seg = (unsigned int)m >> 4; | |
279 context.ret_off = (unsigned int)m & 0xf; | |
280 | |
281 ((unsigned char *)m)[0] = 0xcd; /* int opcode */ | |
282 ((unsigned char *)m)[1] = RETURN_TO_32_INT; | |
283 | |
284 memset(&context.vm, 0, sizeof(context.vm)); | |
285 | |
286 /* | |
287 Enable kernel emulation of all ints except RETURN_TO_32_INT | |
288 */ | |
289 memset(&context.vm.int_revectored, 0, sizeof(context.vm.int_revectored)); | |
290 set_bit(RETURN_TO_32_INT, &context.vm.int_revectored); | |
291 | |
292 context.ready = 1; | |
293 | |
294 return 1; | |
295 } | |
296 | |
297 | |
298 static void | |
299 set_regs(struct LRMI_regs *r) | |
300 { | |
301 context.vm.regs.edi = r->edi; | |
302 context.vm.regs.esi = r->esi; | |
303 context.vm.regs.ebp = r->ebp; | |
304 context.vm.regs.ebx = r->ebx; | |
305 context.vm.regs.edx = r->edx; | |
306 context.vm.regs.ecx = r->ecx; | |
307 context.vm.regs.eax = r->eax; | |
308 context.vm.regs.eflags = DEFAULT_VM86_FLAGS; | |
309 context.vm.regs.es = r->es; | |
310 context.vm.regs.ds = r->ds; | |
311 context.vm.regs.fs = r->fs; | |
312 context.vm.regs.gs = r->gs; | |
313 } | |
314 | |
315 | |
316 static void | |
317 get_regs(struct LRMI_regs *r) | |
318 { | |
319 r->edi = context.vm.regs.edi; | |
320 r->esi = context.vm.regs.esi; | |
321 r->ebp = context.vm.regs.ebp; | |
322 r->ebx = context.vm.regs.ebx; | |
323 r->edx = context.vm.regs.edx; | |
324 r->ecx = context.vm.regs.ecx; | |
325 r->eax = context.vm.regs.eax; | |
326 r->flags = context.vm.regs.eflags; | |
327 r->es = context.vm.regs.es; | |
328 r->ds = context.vm.regs.ds; | |
329 r->fs = context.vm.regs.fs; | |
330 r->gs = context.vm.regs.gs; | |
331 } | |
332 | |
333 #define DIRECTION_FLAG (1 << 10) | |
334 | |
335 static void | |
336 em_ins(int size) | |
337 { | |
338 unsigned int edx, edi; | |
339 | |
340 edx = context.vm.regs.edx & 0xffff; | |
341 edi = context.vm.regs.edi & 0xffff; | |
342 edi += (unsigned int)context.vm.regs.ds << 4; | |
343 | |
344 if (context.vm.regs.eflags & DIRECTION_FLAG) | |
345 { | |
346 if (size == 4) | |
347 asm volatile ("std; insl; cld" | |
348 : "=D" (edi) : "d" (edx), "0" (edi)); | |
349 else if (size == 2) | |
350 asm volatile ("std; insw; cld" | |
351 : "=D" (edi) : "d" (edx), "0" (edi)); | |
352 else | |
353 asm volatile ("std; insb; cld" | |
354 : "=D" (edi) : "d" (edx), "0" (edi)); | |
355 } | |
356 else | |
357 { | |
358 if (size == 4) | |
359 asm volatile ("cld; insl" | |
360 : "=D" (edi) : "d" (edx), "0" (edi)); | |
361 else if (size == 2) | |
362 asm volatile ("cld; insw" | |
363 : "=D" (edi) : "d" (edx), "0" (edi)); | |
364 else | |
365 asm volatile ("cld; insb" | |
366 : "=D" (edi) : "d" (edx), "0" (edi)); | |
367 } | |
368 | |
369 edi -= (unsigned int)context.vm.regs.ds << 4; | |
370 | |
371 context.vm.regs.edi &= 0xffff0000; | |
372 context.vm.regs.edi |= edi & 0xffff; | |
373 } | |
374 | |
375 static void | |
376 em_rep_ins(int size) | |
377 { | |
378 unsigned int ecx, edx, edi; | |
379 | |
380 ecx = context.vm.regs.ecx & 0xffff; | |
381 edx = context.vm.regs.edx & 0xffff; | |
382 edi = context.vm.regs.edi & 0xffff; | |
383 edi += (unsigned int)context.vm.regs.ds << 4; | |
384 | |
385 if (context.vm.regs.eflags & DIRECTION_FLAG) | |
386 { | |
387 if (size == 4) | |
388 asm volatile ("std; rep; insl; cld" | |
389 : "=D" (edi), "=c" (ecx) | |
390 : "d" (edx), "0" (edi), "1" (ecx)); | |
391 else if (size == 2) | |
392 asm volatile ("std; rep; insw; cld" | |
393 : "=D" (edi), "=c" (ecx) | |
394 : "d" (edx), "0" (edi), "1" (ecx)); | |
395 else | |
396 asm volatile ("std; rep; insb; cld" | |
397 : "=D" (edi), "=c" (ecx) | |
398 : "d" (edx), "0" (edi), "1" (ecx)); | |
399 } | |
400 else | |
401 { | |
402 if (size == 4) | |
403 asm volatile ("cld; rep; insl" | |
404 : "=D" (edi), "=c" (ecx) | |
405 : "d" (edx), "0" (edi), "1" (ecx)); | |
406 else if (size == 2) | |
407 asm volatile ("cld; rep; insw" | |
408 : "=D" (edi), "=c" (ecx) | |
409 : "d" (edx), "0" (edi), "1" (ecx)); | |
410 else | |
411 asm volatile ("cld; rep; insb" | |
412 : "=D" (edi), "=c" (ecx) | |
413 : "d" (edx), "0" (edi), "1" (ecx)); | |
414 } | |
415 | |
416 edi -= (unsigned int)context.vm.regs.ds << 4; | |
417 | |
418 context.vm.regs.edi &= 0xffff0000; | |
419 context.vm.regs.edi |= edi & 0xffff; | |
420 | |
421 context.vm.regs.ecx &= 0xffff0000; | |
422 context.vm.regs.ecx |= ecx & 0xffff; | |
423 } | |
424 | |
425 static void | |
426 em_outs(int size) | |
427 { | |
428 unsigned int edx, esi; | |
429 | |
430 edx = context.vm.regs.edx & 0xffff; | |
431 esi = context.vm.regs.esi & 0xffff; | |
432 esi += (unsigned int)context.vm.regs.ds << 4; | |
433 | |
434 if (context.vm.regs.eflags & DIRECTION_FLAG) | |
435 { | |
436 if (size == 4) | |
437 asm volatile ("std; outsl; cld" | |
438 : "=S" (esi) : "d" (edx), "0" (esi)); | |
439 else if (size == 2) | |
440 asm volatile ("std; outsw; cld" | |
441 : "=S" (esi) : "d" (edx), "0" (esi)); | |
442 else | |
443 asm volatile ("std; outsb; cld" | |
444 : "=S" (esi) : "d" (edx), "0" (esi)); | |
445 } | |
446 else | |
447 { | |
448 if (size == 4) | |
449 asm volatile ("cld; outsl" | |
450 : "=S" (esi) : "d" (edx), "0" (esi)); | |
451 else if (size == 2) | |
452 asm volatile ("cld; outsw" | |
453 : "=S" (esi) : "d" (edx), "0" (esi)); | |
454 else | |
455 asm volatile ("cld; outsb" | |
456 : "=S" (esi) : "d" (edx), "0" (esi)); | |
457 } | |
458 | |
459 esi -= (unsigned int)context.vm.regs.ds << 4; | |
460 | |
461 context.vm.regs.esi &= 0xffff0000; | |
462 context.vm.regs.esi |= esi & 0xffff; | |
463 } | |
464 | |
465 static void | |
466 em_rep_outs(int size) | |
467 { | |
468 unsigned int ecx, edx, esi; | |
469 | |
470 ecx = context.vm.regs.ecx & 0xffff; | |
471 edx = context.vm.regs.edx & 0xffff; | |
472 esi = context.vm.regs.esi & 0xffff; | |
473 esi += (unsigned int)context.vm.regs.ds << 4; | |
474 | |
475 if (context.vm.regs.eflags & DIRECTION_FLAG) | |
476 { | |
477 if (size == 4) | |
478 asm volatile ("std; rep; outsl; cld" | |
479 : "=S" (esi), "=c" (ecx) | |
480 : "d" (edx), "0" (esi), "1" (ecx)); | |
481 else if (size == 2) | |
482 asm volatile ("std; rep; outsw; cld" | |
483 : "=S" (esi), "=c" (ecx) | |
484 : "d" (edx), "0" (esi), "1" (ecx)); | |
485 else | |
486 asm volatile ("std; rep; outsb; cld" | |
487 : "=S" (esi), "=c" (ecx) | |
488 : "d" (edx), "0" (esi), "1" (ecx)); | |
489 } | |
490 else | |
491 { | |
492 if (size == 4) | |
493 asm volatile ("cld; rep; outsl" | |
494 : "=S" (esi), "=c" (ecx) | |
495 : "d" (edx), "0" (esi), "1" (ecx)); | |
496 else if (size == 2) | |
497 asm volatile ("cld; rep; outsw" | |
498 : "=S" (esi), "=c" (ecx) | |
499 : "d" (edx), "0" (esi), "1" (ecx)); | |
500 else | |
501 asm volatile ("cld; rep; outsb" | |
502 : "=S" (esi), "=c" (ecx) | |
503 : "d" (edx), "0" (esi), "1" (ecx)); | |
504 } | |
505 | |
506 esi -= (unsigned int)context.vm.regs.ds << 4; | |
507 | |
508 context.vm.regs.esi &= 0xffff0000; | |
509 context.vm.regs.esi |= esi & 0xffff; | |
510 | |
511 context.vm.regs.ecx &= 0xffff0000; | |
512 context.vm.regs.ecx |= ecx & 0xffff; | |
513 } | |
514 | |
515 static void | |
516 em_inbl(unsigned char literal) | |
517 { | |
518 context.vm.regs.eax = inb(literal) & 0xff; | |
519 } | |
520 | |
521 static void | |
522 em_inb(void) | |
523 { | |
524 asm volatile ("inb (%w1), %b0" | |
525 : "=a" (context.vm.regs.eax) | |
526 : "d" (context.vm.regs.edx), "0" (context.vm.regs.eax)); | |
527 } | |
528 | |
529 static void | |
530 em_inw(void) | |
531 { | |
532 asm volatile ("inw (%w1), %w0" | |
533 : "=a" (context.vm.regs.eax) | |
534 : "d" (context.vm.regs.edx), "0" (context.vm.regs.eax)); | |
535 } | |
536 | |
537 static void | |
538 em_inl(void) | |
539 { | |
540 asm volatile ("inl (%w1), %0" | |
541 : "=a" (context.vm.regs.eax) | |
542 : "d" (context.vm.regs.edx)); | |
543 } | |
544 | |
545 static void | |
546 em_outbl(unsigned char literal) | |
547 { | |
548 outb(context.vm.regs.eax & 0xff, literal); | |
549 } | |
550 | |
551 static void | |
552 em_outb(void) | |
553 { | |
554 asm volatile ("outb %b0, (%w1)" | |
555 : : "a" (context.vm.regs.eax), | |
556 "d" (context.vm.regs.edx)); | |
557 } | |
558 | |
559 static void | |
560 em_outw(void) | |
561 { | |
562 asm volatile ("outw %w0, (%w1)" | |
563 : : "a" (context.vm.regs.eax), | |
564 "d" (context.vm.regs.edx)); | |
565 } | |
566 | |
567 static void | |
568 em_outl(void) | |
569 { | |
570 asm volatile ("outl %0, (%w1)" | |
571 : : "a" (context.vm.regs.eax), | |
572 "d" (context.vm.regs.edx)); | |
573 } | |
574 | |
575 static int | |
576 emulate(void) | |
577 { | |
578 unsigned char *insn; | |
579 struct | |
580 { | |
581 unsigned int size : 1; | |
582 unsigned int rep : 1; | |
583 } prefix = { 0, 0 }; | |
584 int i = 0; | |
585 | |
586 insn = (unsigned char *)((unsigned int)context.vm.regs.cs << 4); | |
587 insn += context.vm.regs.eip; | |
588 | |
589 while (1) | |
590 { | |
591 if (insn[i] == 0x66) | |
592 { | |
593 prefix.size = 1 - prefix.size; | |
594 i++; | |
595 } | |
596 else if (insn[i] == 0xf3) | |
597 { | |
598 prefix.rep = 1; | |
599 i++; | |
600 } | |
601 else if (insn[i] == 0xf0 || insn[i] == 0xf2 | |
602 || insn[i] == 0x26 || insn[i] == 0x2e | |
603 || insn[i] == 0x36 || insn[i] == 0x3e | |
604 || insn[i] == 0x64 || insn[i] == 0x65 | |
605 || insn[i] == 0x67) | |
606 { | |
607 /* these prefixes are just ignored */ | |
608 i++; | |
609 } | |
610 else if (insn[i] == 0x6c) | |
611 { | |
612 if (prefix.rep) | |
613 em_rep_ins(1); | |
614 else | |
615 em_ins(1); | |
616 i++; | |
617 break; | |
618 } | |
619 else if (insn[i] == 0x6d) | |
620 { | |
621 if (prefix.rep) | |
622 { | |
623 if (prefix.size) | |
624 em_rep_ins(4); | |
625 else | |
626 em_rep_ins(2); | |
627 } | |
628 else | |
629 { | |
630 if (prefix.size) | |
631 em_ins(4); | |
632 else | |
633 em_ins(2); | |
634 } | |
635 i++; | |
636 break; | |
637 } | |
638 else if (insn[i] == 0x6e) | |
639 { | |
640 if (prefix.rep) | |
641 em_rep_outs(1); | |
642 else | |
643 em_outs(1); | |
644 i++; | |
645 break; | |
646 } | |
647 else if (insn[i] == 0x6f) | |
648 { | |
649 if (prefix.rep) | |
650 { | |
651 if (prefix.size) | |
652 em_rep_outs(4); | |
653 else | |
654 em_rep_outs(2); | |
655 } | |
656 else | |
657 { | |
658 if (prefix.size) | |
659 em_outs(4); | |
660 else | |
661 em_outs(2); | |
662 } | |
663 i++; | |
664 break; | |
665 } | |
666 else if (insn[i] == 0xe4) | |
667 { | |
668 em_inbl(insn[i + 1]); | |
669 i += 2; | |
670 break; | |
671 } | |
672 else if (insn[i] == 0xe6) | |
673 { | |
674 em_outbl(insn[i + 1]); | |
675 i += 2; | |
676 break; | |
677 } | |
678 else if (insn[i] == 0xec) | |
679 { | |
680 em_inb(); | |
681 i++; | |
682 break; | |
683 } | |
684 else if (insn[i] == 0xed) | |
685 { | |
686 if (prefix.size) | |
687 em_inl(); | |
688 else | |
689 em_inw(); | |
690 i++; | |
691 break; | |
692 } | |
693 else if (insn[i] == 0xee) | |
694 { | |
695 em_outb(); | |
696 i++; | |
697 break; | |
698 } | |
699 else if (insn[i] == 0xef) | |
700 { | |
701 if (prefix.size) | |
702 em_outl(); | |
703 else | |
704 em_outw(); | |
705 | |
706 i++; | |
707 break; | |
708 } | |
709 else | |
710 return 0; | |
711 } | |
712 | |
713 context.vm.regs.eip += i; | |
714 return 1; | |
715 } | |
716 | |
717 | |
718 /* | |
719 I don't know how to make sure I get the right vm86() from libc. | |
720 The one I want is syscall # 113 (vm86old() in libc 5, vm86() in glibc) | |
721 which should be declared as "int vm86(struct vm86_struct *);" in | |
722 <sys/vm86.h>. | |
723 | |
724 This just does syscall 113 with inline asm, which should work | |
725 for both libc's (I hope). | |
726 */ | |
727 #if !defined(USE_LIBC_VM86) | |
728 static int | |
729 lrmi_vm86(struct vm86_struct *vm) | |
730 { | |
731 int r; | |
732 #ifdef __PIC__ | |
733 asm volatile ( | |
734 "pushl %%ebx\n\t" | |
735 "movl %2, %%ebx\n\t" | |
736 "int $0x80\n\t" | |
737 "popl %%ebx" | |
738 : "=a" (r) | |
739 : "0" (113), "r" (vm)); | |
740 #else | |
741 asm volatile ( | |
742 "int $0x80" | |
743 : "=a" (r) | |
744 : "0" (113), "b" (vm)); | |
745 #endif | |
746 return r; | |
747 } | |
748 #else | |
749 #define lrmi_vm86 vm86 | |
750 #endif | |
751 | |
752 | |
753 static void | |
754 debug_info(int vret) | |
755 { | |
756 int i; | |
757 unsigned char *p; | |
758 | |
759 fputs("vm86() failed\n", stderr); | |
760 fprintf(stderr, "return = 0x%x\n", vret); | |
761 fprintf(stderr, "eax = 0x%08lx\n", context.vm.regs.eax); | |
762 fprintf(stderr, "ebx = 0x%08lx\n", context.vm.regs.ebx); | |
763 fprintf(stderr, "ecx = 0x%08lx\n", context.vm.regs.ecx); | |
764 fprintf(stderr, "edx = 0x%08lx\n", context.vm.regs.edx); | |
765 fprintf(stderr, "esi = 0x%08lx\n", context.vm.regs.esi); | |
766 fprintf(stderr, "edi = 0x%08lx\n", context.vm.regs.edi); | |
767 fprintf(stderr, "ebp = 0x%08lx\n", context.vm.regs.ebp); | |
768 fprintf(stderr, "eip = 0x%08lx\n", context.vm.regs.eip); | |
769 fprintf(stderr, "cs = 0x%04x\n", context.vm.regs.cs); | |
770 fprintf(stderr, "esp = 0x%08lx\n", context.vm.regs.esp); | |
771 fprintf(stderr, "ss = 0x%04x\n", context.vm.regs.ss); | |
772 fprintf(stderr, "ds = 0x%04x\n", context.vm.regs.ds); | |
773 fprintf(stderr, "es = 0x%04x\n", context.vm.regs.es); | |
774 fprintf(stderr, "fs = 0x%04x\n", context.vm.regs.fs); | |
775 fprintf(stderr, "gs = 0x%04x\n", context.vm.regs.gs); | |
776 fprintf(stderr, "eflags = 0x%08lx\n", context.vm.regs.eflags); | |
777 | |
778 fputs("cs:ip = [ ", stderr); | |
779 | |
780 p = (unsigned char *)((context.vm.regs.cs << 4) + (context.vm.regs.eip & 0xffff)); | |
781 | |
782 for (i = 0; i < 16; ++i) | |
783 fprintf(stderr, "%02x ", (unsigned int)p[i]); | |
784 | |
785 fputs("]\n", stderr); | |
786 } | |
787 | |
788 | |
789 static int | |
790 run_vm86(void) | |
791 { | |
792 unsigned int vret; | |
11434
5084f09ba20e
Fix pthread & lrmi segfault issue. ("Oleg I. Vdovikin" <vdovikin@jscc.ru>)
ranma
parents:
10857
diff
changeset
|
793 sigset_t allsigs, cursigs; |
5084f09ba20e
Fix pthread & lrmi segfault issue. ("Oleg I. Vdovikin" <vdovikin@jscc.ru>)
ranma
parents:
10857
diff
changeset
|
794 unsigned long oldgs; |
2212 | 795 |
796 while (1) | |
797 { | |
11434
5084f09ba20e
Fix pthread & lrmi segfault issue. ("Oleg I. Vdovikin" <vdovikin@jscc.ru>)
ranma
parents:
10857
diff
changeset
|
798 sigfillset(&allsigs); |
5084f09ba20e
Fix pthread & lrmi segfault issue. ("Oleg I. Vdovikin" <vdovikin@jscc.ru>)
ranma
parents:
10857
diff
changeset
|
799 sigprocmask(SIG_SETMASK, &allsigs, &cursigs); |
5084f09ba20e
Fix pthread & lrmi segfault issue. ("Oleg I. Vdovikin" <vdovikin@jscc.ru>)
ranma
parents:
10857
diff
changeset
|
800 asm volatile ("movl %%gs, %0" : "=g" (oldgs)); |
2212 | 801 vret = lrmi_vm86(&context.vm); |
11434
5084f09ba20e
Fix pthread & lrmi segfault issue. ("Oleg I. Vdovikin" <vdovikin@jscc.ru>)
ranma
parents:
10857
diff
changeset
|
802 asm volatile ("movl %0, %%gs" :: "g" (oldgs)); |
5084f09ba20e
Fix pthread & lrmi segfault issue. ("Oleg I. Vdovikin" <vdovikin@jscc.ru>)
ranma
parents:
10857
diff
changeset
|
803 sigprocmask(SIG_SETMASK, &cursigs, NULL); |
2212 | 804 |
805 if (VM86_TYPE(vret) == VM86_INTx) | |
806 { | |
807 unsigned int v = VM86_ARG(vret); | |
808 | |
809 if (v == RETURN_TO_32_INT) | |
810 return 1; | |
811 | |
812 pushw(context.vm.regs.eflags); | |
813 pushw(context.vm.regs.cs); | |
814 pushw(context.vm.regs.eip); | |
815 | |
816 context.vm.regs.cs = get_int_seg(v); | |
817 context.vm.regs.eip = get_int_off(v); | |
818 context.vm.regs.eflags &= ~(VIF_MASK | TF_MASK); | |
819 | |
820 continue; | |
821 } | |
822 | |
823 if (VM86_TYPE(vret) != VM86_UNKNOWN) | |
824 break; | |
825 | |
826 if (!emulate()) | |
827 break; | |
828 } | |
829 | |
830 #ifdef ORIGINAL_LRMI_CODE_THAT_GOT_IFDEFED_OUT | |
831 debug_info(vret); | |
832 #endif | |
833 return 0; | |
834 } | |
835 | |
836 | |
837 int | |
838 LRMI_call(struct LRMI_regs *r) | |
839 { | |
840 unsigned int vret; | |
841 | |
842 memset(&context.vm.regs, 0, sizeof(context.vm.regs)); | |
843 | |
844 set_regs(r); | |
845 | |
846 context.vm.regs.cs = r->cs; | |
847 context.vm.regs.eip = r->ip; | |
848 | |
849 if (r->ss == 0 && r->sp == 0) | |
850 { | |
851 context.vm.regs.ss = context.stack_seg; | |
852 context.vm.regs.esp = context.stack_off; | |
853 } | |
854 else | |
855 { | |
856 context.vm.regs.ss = r->ss; | |
857 context.vm.regs.esp = r->sp; | |
858 } | |
859 | |
860 pushw(context.ret_seg); | |
861 pushw(context.ret_off); | |
862 | |
863 vret = run_vm86(); | |
864 | |
865 get_regs(r); | |
866 | |
867 return vret; | |
868 } | |
869 | |
870 | |
871 int | |
872 LRMI_int(int i, struct LRMI_regs *r) | |
873 { | |
874 unsigned int vret; | |
875 unsigned int seg, off; | |
876 | |
877 seg = get_int_seg(i); | |
878 off = get_int_off(i); | |
879 | |
880 /* | |
881 If the interrupt is in regular memory, it's probably | |
882 still pointing at a dos TSR (which is now gone). | |
883 */ | |
884 if (seg < 0xa000 || (seg << 4) + off >= 0x100000) | |
885 { | |
886 #ifdef ORIGINAL_LRMI_CODE_THAT_GOT_IFDEFED_OUT | |
887 fprintf(stderr, "Int 0x%x is not in rom (%04x:%04x)\n", i, seg, off); | |
888 #endif | |
889 return 0; | |
890 } | |
891 | |
892 memset(&context.vm.regs, 0, sizeof(context.vm.regs)); | |
893 | |
894 set_regs(r); | |
895 | |
896 context.vm.regs.cs = seg; | |
897 context.vm.regs.eip = off; | |
898 | |
899 if (r->ss == 0 && r->sp == 0) | |
900 { | |
901 context.vm.regs.ss = context.stack_seg; | |
902 context.vm.regs.esp = context.stack_off; | |
903 } | |
904 else | |
905 { | |
906 context.vm.regs.ss = r->ss; | |
907 context.vm.regs.esp = r->sp; | |
908 } | |
909 | |
910 pushw(DEFAULT_VM86_FLAGS); | |
911 pushw(context.ret_seg); | |
912 pushw(context.ret_off); | |
913 | |
914 vret = run_vm86(); | |
915 | |
916 get_regs(r); | |
917 | |
918 return vret; | |
919 } | |
920 |