c68d753bfb2f5969d6fa70a181b9f14b97356b56
2 Linux Real Mode Interface - A library of DPMI-like functions for Linux.
4 Copyright (C) 1998 by Josh Vanderhoof
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
14 The above copyright notice and this permission notice shall be
15 included in all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 IN NO EVENT SHALL JOSH VANDERHOOF BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 OTHER DEALINGS IN THE SOFTWARE.
26 #if defined(__i386__) && (defined(__linux__) || defined(__NetBSD__) \
27 || defined(__FreeBSD__) || defined(__OpenBSD__))
32 #if defined(__linux__)
41 #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
43 #include <sys/param.h>
46 #include <machine/psl.h>
47 #include <machine/vm86.h>
48 #include <machine/sysarch.h>
50 #endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */
52 #if defined(__FreeBSD__)
53 #include <sys/ucontext.h>
56 #include <sys/types.h>
64 /* 2.6.26+ kernels don't define the legacy masks. */
65 #if defined(__linux__) && !defined(TF_MASK)
66 #define TF_MASK X86_EFLAGS_TF
67 #define IF_MASK X86_EFLAGS_IF
68 #define VIF_MASK X86_EFLAGS_VIF
69 #define IOPL_MASK X86_EFLAGS_IOPL
72 #define REAL_MEM_BASE ((void *)0x10000)
73 #define REAL_MEM_SIZE 0x40000
74 #define REAL_MEM_BLOCKS 0x100
77 unsigned int size
: 20;
78 unsigned int free
: 1;
84 struct mem_block blocks
[REAL_MEM_BLOCKS
];
88 read_file(char *name
, void *p
, size_t n
)
92 fd
= open(name
, O_RDONLY
);
99 if (read(fd
, p
, n
) != n
) {
111 map_file(void *start
, size_t length
, int prot
, int flags
, char *name
, long offset
)
116 fd
= open(name
, (flags
& MAP_SHARED
) ? O_RDWR
: O_RDONLY
);
123 m
= mmap(start
, length
, prot
, flags
, fd
, offset
);
125 if (m
== (void *)-1) {
141 if (!map_file((void *)REAL_MEM_BASE
, REAL_MEM_SIZE
,
142 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
143 MAP_FIXED
| MAP_PRIVATE
, "/dev/zero", 0))
148 mem_info
.blocks
[0].size
= REAL_MEM_SIZE
;
149 mem_info
.blocks
[0].free
= 1;
155 real_mem_deinit(void)
157 if (mem_info
.ready
) {
158 munmap((void *)REAL_MEM_BASE
, REAL_MEM_SIZE
);
168 mem_info
.blocks
+ i
+ 1,
170 (mem_info
.count
- i
) * sizeof(struct mem_block
));
182 mem_info
.blocks
+ i
+ 1,
183 (mem_info
.count
- i
) * sizeof(struct mem_block
));
187 LRMI_alloc_real(int size
)
190 char *r
= (char *)REAL_MEM_BASE
;
195 if (mem_info
.count
== REAL_MEM_BLOCKS
)
198 size
= (size
+ 15) & ~15;
200 for (i
= 0; i
< mem_info
.count
; i
++) {
201 if (mem_info
.blocks
[i
].free
&& size
< mem_info
.blocks
[i
].size
) {
204 mem_info
.blocks
[i
].size
= size
;
205 mem_info
.blocks
[i
].free
= 0;
206 mem_info
.blocks
[i
+ 1].size
-= size
;
211 r
+= mem_info
.blocks
[i
].size
;
219 LRMI_free_real(void *m
)
222 char *r
= (char *)REAL_MEM_BASE
;
228 while (m
!= (void *)r
) {
229 r
+= mem_info
.blocks
[i
].size
;
231 if (i
== mem_info
.count
)
235 mem_info
.blocks
[i
].free
= 1;
237 if (i
+ 1 < mem_info
.count
&& mem_info
.blocks
[i
+ 1].free
) {
238 mem_info
.blocks
[i
].size
+= mem_info
.blocks
[i
+ 1].size
;
242 if (i
- 1 >= 0 && mem_info
.blocks
[i
- 1].free
) {
243 mem_info
.blocks
[i
- 1].size
+= mem_info
.blocks
[i
].size
;
249 #if defined(__linux__)
250 #define DEFAULT_VM86_FLAGS (IF_MASK | IOPL_MASK)
251 #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
252 #define DEFAULT_VM86_FLAGS (PSL_I | PSL_IOPL)
253 #define TF_MASK PSL_T
254 #define VIF_MASK PSL_VIF
256 #define DEFAULT_STACK_SIZE 0x1000
257 #define RETURN_TO_32_INT 255
259 #if defined(__linux__)
260 #define CONTEXT_REGS context.vm.regs
262 #elif defined(__NetBSD__) || defined(__OpenBSD__)
263 #define CONTEXT_REGS context.vm.substr.regs
264 #define REG(x) vmsc.sc_ ## x
265 #elif defined(__FreeBSD__)
266 #define CONTEXT_REGS context.vm.uc
267 #define REG(x) uc_mcontext.mc_ ## x
272 unsigned short ret_seg
, ret_off
;
273 unsigned short stack_seg
, stack_off
;
274 #if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__)
275 struct vm86_struct vm
;
276 #elif defined(__FreeBSD__)
278 struct vm86_init_args init
;
282 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
285 void *old_sighandler
;
292 set_bit(unsigned int bit
, void *array
)
294 unsigned char *a
= array
;
296 a
[bit
/ 8] |= (1 << (bit
% 8));
300 static inline unsigned int
303 return *(unsigned short *)(i
* 4 + 2);
307 static inline unsigned int
310 return *(unsigned short *)(i
* 4);
315 pushw(unsigned short i
)
317 CONTEXT_REGS
.REG(esp
) -= 2;
318 *(unsigned short *)(((unsigned int)CONTEXT_REGS
.REG(ss
) << 4) +
319 CONTEXT_REGS
.REG(esp
)) = i
;
331 if (!real_mem_init())
335 Map the Interrupt Vectors (0x0 - 0x400) + BIOS data (0x400 - 0x502)
336 and the ROM (0xa0000 - 0x100000)
340 * v86d: map the IVTBDA area as shared, see note in v86_mem.c for
343 if (!map_file((void *)0, 0x502,
344 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
345 MAP_FIXED
| MAP_SHARED
, "/dev/mem", 0)) {
350 if (!map_file((void *)0xa0000, 0x100000 - 0xa0000,
351 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
352 MAP_FIXED
| MAP_SHARED
, "/dev/mem", 0xa0000)) {
353 munmap((void *)0, 0x502);
361 m
= LRMI_alloc_real(DEFAULT_STACK_SIZE
);
363 context
.stack_seg
= (unsigned int)m
>> 4;
364 context
.stack_off
= DEFAULT_STACK_SIZE
;
367 Allocate the return to 32 bit routine
369 m
= LRMI_alloc_real(2);
371 context
.ret_seg
= (unsigned int)m
>> 4;
372 context
.ret_off
= (unsigned int)m
& 0xf;
374 ((unsigned char *)m
)[0] = 0xcd; /* int opcode */
375 ((unsigned char *)m
)[1] = RETURN_TO_32_INT
;
377 memset(&context
.vm
, 0, sizeof(context
.vm
));
380 Enable kernel emulation of all ints except RETURN_TO_32_INT
382 #if defined(__linux__)
383 memset(&context
.vm
.int_revectored
, 0, sizeof(context
.vm
.int_revectored
));
384 set_bit(RETURN_TO_32_INT
, &context
.vm
.int_revectored
);
385 #elif defined(__NetBSD__) || defined(__OpenBSD__)
386 set_bit(RETURN_TO_32_INT
, &context
.vm
.int_byuser
);
387 #elif defined(__FreeBSD__)
388 set_bit(RETURN_TO_32_INT
, &context
.vm
.init
.int_map
);
398 set_regs(struct LRMI_regs
*r
)
400 CONTEXT_REGS
.REG(edi
) = r
->edi
;
401 CONTEXT_REGS
.REG(esi
) = r
->esi
;
402 CONTEXT_REGS
.REG(ebp
) = r
->ebp
;
403 CONTEXT_REGS
.REG(ebx
) = r
->ebx
;
404 CONTEXT_REGS
.REG(edx
) = r
->edx
;
405 CONTEXT_REGS
.REG(ecx
) = r
->ecx
;
406 CONTEXT_REGS
.REG(eax
) = r
->eax
;
407 CONTEXT_REGS
.REG(eflags
) = DEFAULT_VM86_FLAGS
;
408 CONTEXT_REGS
.REG(es
) = r
->es
;
409 CONTEXT_REGS
.REG(ds
) = r
->ds
;
410 CONTEXT_REGS
.REG(fs
) = r
->fs
;
411 CONTEXT_REGS
.REG(gs
) = r
->gs
;
416 get_regs(struct LRMI_regs
*r
)
418 r
->edi
= CONTEXT_REGS
.REG(edi
);
419 r
->esi
= CONTEXT_REGS
.REG(esi
);
420 r
->ebp
= CONTEXT_REGS
.REG(ebp
);
421 r
->ebx
= CONTEXT_REGS
.REG(ebx
);
422 r
->edx
= CONTEXT_REGS
.REG(edx
);
423 r
->ecx
= CONTEXT_REGS
.REG(ecx
);
424 r
->eax
= CONTEXT_REGS
.REG(eax
);
425 r
->flags
= CONTEXT_REGS
.REG(eflags
);
426 r
->es
= CONTEXT_REGS
.REG(es
);
427 r
->ds
= CONTEXT_REGS
.REG(ds
);
428 r
->fs
= CONTEXT_REGS
.REG(fs
);
429 r
->gs
= CONTEXT_REGS
.REG(gs
);
432 #define DIRECTION_FLAG (1 << 10)
435 CSEG
= 0x2e, SSEG
= 0x36, DSEG
= 0x3e,
436 ESEG
= 0x26, FSEG
= 0x64, GSEG
= 0x65,
442 unsigned int edx
, edi
;
444 edx
= CONTEXT_REGS
.REG(edx
) & 0xffff;
445 edi
= CONTEXT_REGS
.REG(edi
) & 0xffff;
446 edi
+= (unsigned int)CONTEXT_REGS
.REG(es
) << 4;
448 if (CONTEXT_REGS
.REG(eflags
) & DIRECTION_FLAG
) {
450 asm volatile ("std; insl; cld"
451 : "=D" (edi
) : "d" (edx
), "0" (edi
));
453 asm volatile ("std; insw; cld"
454 : "=D" (edi
) : "d" (edx
), "0" (edi
));
456 asm volatile ("std; insb; cld"
457 : "=D" (edi
) : "d" (edx
), "0" (edi
));
460 asm volatile ("cld; insl"
461 : "=D" (edi
) : "d" (edx
), "0" (edi
));
463 asm volatile ("cld; insw"
464 : "=D" (edi
) : "d" (edx
), "0" (edi
));
466 asm volatile ("cld; insb"
467 : "=D" (edi
) : "d" (edx
), "0" (edi
));
470 edi
-= (unsigned int)CONTEXT_REGS
.REG(es
) << 4;
472 CONTEXT_REGS
.REG(edi
) &= 0xffff0000;
473 CONTEXT_REGS
.REG(edi
) |= edi
& 0xffff;
481 cx
= CONTEXT_REGS
.REG(ecx
) & 0xffff;
486 CONTEXT_REGS
.REG(ecx
) &= 0xffff0000;
490 em_outs(int size
, int seg
)
492 unsigned int edx
, esi
, base
;
494 edx
= CONTEXT_REGS
.REG(edx
) & 0xffff;
495 esi
= CONTEXT_REGS
.REG(esi
) & 0xffff;
498 case CSEG
: base
= CONTEXT_REGS
.REG(cs
); break;
499 case SSEG
: base
= CONTEXT_REGS
.REG(ss
); break;
500 case ESEG
: base
= CONTEXT_REGS
.REG(es
); break;
501 case FSEG
: base
= CONTEXT_REGS
.REG(fs
); break;
502 case GSEG
: base
= CONTEXT_REGS
.REG(gs
); break;
504 case DSEG
: base
= CONTEXT_REGS
.REG(ds
); break;
509 if (CONTEXT_REGS
.REG(eflags
) & DIRECTION_FLAG
) {
511 asm volatile ("std; outsl; cld"
512 : "=S" (esi
) : "d" (edx
), "0" (esi
));
514 asm volatile ("std; outsw; cld"
515 : "=S" (esi
) : "d" (edx
), "0" (esi
));
517 asm volatile ("std; outsb; cld"
518 : "=S" (esi
) : "d" (edx
), "0" (esi
));
521 asm volatile ("cld; outsl"
522 : "=S" (esi
) : "d" (edx
), "0" (esi
));
524 asm volatile ("cld; outsw"
525 : "=S" (esi
) : "d" (edx
), "0" (esi
));
527 asm volatile ("cld; outsb"
528 : "=S" (esi
) : "d" (edx
), "0" (esi
));
533 CONTEXT_REGS
.REG(esi
) &= 0xffff0000;
534 CONTEXT_REGS
.REG(esi
) |= esi
& 0xffff;
538 em_rep_outs(int size
, int seg
)
542 cx
= CONTEXT_REGS
.REG(ecx
) & 0xffff;
547 CONTEXT_REGS
.REG(ecx
) &= 0xffff0000;
551 em_inbl(unsigned char literal
)
553 asm volatile ("inb %w1, %b0"
554 : "=a" (CONTEXT_REGS
.REG(eax
))
555 : "d" (literal
), "0" (CONTEXT_REGS
.REG(eax
)));
561 asm volatile ("inb %w1, %b0"
562 : "=a" (CONTEXT_REGS
.REG(eax
))
563 : "d" (CONTEXT_REGS
.REG(edx
)), "0" (CONTEXT_REGS
.REG(eax
)));
569 asm volatile ("inw %w1, %w0"
570 : "=a" (CONTEXT_REGS
.REG(eax
))
571 : "d" (CONTEXT_REGS
.REG(edx
)), "0" (CONTEXT_REGS
.REG(eax
)));
577 asm volatile ("inl %w1, %0"
578 : "=a" (CONTEXT_REGS
.REG(eax
))
579 : "d" (CONTEXT_REGS
.REG(edx
)));
583 em_outbl(unsigned char literal
)
585 asm volatile ("outb %b0, %w1"
586 : : "a" (CONTEXT_REGS
.REG(eax
)),
593 asm volatile ("outb %b0, %w1"
594 : : "a" (CONTEXT_REGS
.REG(eax
)),
595 "d" (CONTEXT_REGS
.REG(edx
)));
601 asm volatile ("outw %w0, %w1"
602 : : "a" (CONTEXT_REGS
.REG(eax
)),
603 "d" (CONTEXT_REGS
.REG(edx
)));
609 asm volatile ("outl %0, %w1"
610 : : "a" (CONTEXT_REGS
.REG(eax
)),
611 "d" (CONTEXT_REGS
.REG(edx
)));
620 unsigned int size
: 1;
621 unsigned int rep
: 1;
622 } prefix
= { DSEG
, 0, 0 };
625 insn
= (unsigned char *)((unsigned int)CONTEXT_REGS
.REG(cs
) << 4);
626 insn
+= CONTEXT_REGS
.REG(eip
);
629 if (insn
[i
] == 0x66) {
630 prefix
.size
= 1 - prefix
.size
;
632 } else if (insn
[i
] == 0xf3) {
635 } else if (insn
[i
] == CSEG
|| insn
[i
] == SSEG
636 || insn
[i
] == DSEG
|| insn
[i
] == ESEG
637 || insn
[i
] == FSEG
|| insn
[i
] == GSEG
) {
638 prefix
.seg
= insn
[i
];
640 } else if (insn
[i
] == 0xf0 || insn
[i
] == 0xf2
641 || insn
[i
] == 0x67) {
642 /* these prefixes are just ignored */
644 } else if (insn
[i
] == 0x6c) {
651 } else if (insn
[i
] == 0x6d) {
665 } else if (insn
[i
] == 0x6e) {
667 em_rep_outs(1, prefix
.seg
);
669 em_outs(1, prefix
.seg
);
672 } else if (insn
[i
] == 0x6f) {
675 em_rep_outs(4, prefix
.seg
);
677 em_rep_outs(2, prefix
.seg
);
680 em_outs(4, prefix
.seg
);
682 em_outs(2, prefix
.seg
);
686 } else if (insn
[i
] == 0xe4) {
687 em_inbl(insn
[i
+ 1]);
690 } else if (insn
[i
] == 0xec) {
694 } else if (insn
[i
] == 0xed) {
701 } else if (insn
[i
] == 0xe6) {
702 em_outbl(insn
[i
+ 1]);
705 } else if (insn
[i
] == 0xee) {
709 } else if (insn
[i
] == 0xef) {
721 CONTEXT_REGS
.REG(eip
) += i
;
726 #if defined(__linux__)
728 I don't know how to make sure I get the right vm86() from libc.
729 The one I want is syscall # 113 (vm86old() in libc 5, vm86() in glibc)
730 which should be declared as "int vm86(struct vm86_struct *);" in
733 This just does syscall 113 with inline asm, which should work
734 for both libc's (I hope).
736 #if !defined(USE_LIBC_VM86)
738 lrmi_vm86(struct vm86_struct
*vm
)
748 : "0" (113), "r" (vm
));
753 : "0" (113), "b" (vm
));
758 #define lrmi_vm86 vm86
760 #endif /* __linux__ */
770 fputs("vm86() failed\n", stderr
);
771 fprintf(stderr
, "return = 0x%x\n", vret
);
772 fprintf(stderr
, "eax = 0x%08x\n", CONTEXT_REGS
.REG(eax
));
773 fprintf(stderr
, "ebx = 0x%08x\n", CONTEXT_REGS
.REG(ebx
));
774 fprintf(stderr
, "ecx = 0x%08x\n", CONTEXT_REGS
.REG(ecx
));
775 fprintf(stderr
, "edx = 0x%08x\n", CONTEXT_REGS
.REG(edx
));
776 fprintf(stderr
, "esi = 0x%08x\n", CONTEXT_REGS
.REG(esi
));
777 fprintf(stderr
, "edi = 0x%08x\n", CONTEXT_REGS
.REG(edi
));
778 fprintf(stderr
, "ebp = 0x%08x\n", CONTEXT_REGS
.REG(ebp
));
779 fprintf(stderr
, "eip = 0x%08x\n", CONTEXT_REGS
.REG(eip
));
780 fprintf(stderr
, "cs = 0x%04x\n", CONTEXT_REGS
.REG(cs
));
781 fprintf(stderr
, "esp = 0x%08x\n", CONTEXT_REGS
.REG(esp
));
782 fprintf(stderr
, "ss = 0x%04x\n", CONTEXT_REGS
.REG(ss
));
783 fprintf(stderr
, "ds = 0x%04x\n", CONTEXT_REGS
.REG(ds
));
784 fprintf(stderr
, "es = 0x%04x\n", CONTEXT_REGS
.REG(es
));
785 fprintf(stderr
, "fs = 0x%04x\n", CONTEXT_REGS
.REG(fs
));
786 fprintf(stderr
, "gs = 0x%04x\n", CONTEXT_REGS
.REG(gs
));
787 fprintf(stderr
, "eflags = 0x%08x\n", CONTEXT_REGS
.REG(eflags
));
789 fputs("cs:ip = [ ", stderr
);
791 p
= (unsigned char *)((CONTEXT_REGS
.REG(cs
) << 4) + (CONTEXT_REGS
.REG(eip
) & 0xffff));
793 for (i
= 0; i
< 16; ++i
)
794 fprintf(stderr
, "%02x ", (unsigned int)p
[i
]);
796 fputs("]\n", stderr
);
801 #if defined(__linux__)
806 sigset_t all_sigs
, old_sigs
;
807 unsigned long old_gs
, old_fs
;
810 // FIXME: may apply this to BSD equivalents?
811 sigfillset(&all_sigs
);
812 sigprocmask(SIG_SETMASK
, &all_sigs
, &old_sigs
);
813 asm volatile ("mov %%gs, %0" : "=rm" (old_gs
));
814 asm volatile ("mov %%fs, %0" : "=rm" (old_fs
));
815 vret
= lrmi_vm86(&context
.vm
);
816 asm volatile ("mov %0, %%gs" :: "rm" (old_gs
));
817 asm volatile ("mov %0, %%fs" :: "rm" (old_fs
));
818 sigprocmask(SIG_SETMASK
, &old_sigs
, NULL
);
820 if (VM86_TYPE(vret
) == VM86_INTx
) {
821 unsigned int v
= VM86_ARG(vret
);
823 if (v
== RETURN_TO_32_INT
)
826 pushw(CONTEXT_REGS
.REG(eflags
));
827 pushw(CONTEXT_REGS
.REG(cs
));
828 pushw(CONTEXT_REGS
.REG(eip
));
830 CONTEXT_REGS
.REG(cs
) = get_int_seg(v
);
831 CONTEXT_REGS
.REG(eip
) = get_int_off(v
);
832 CONTEXT_REGS
.REG(eflags
) &= ~(VIF_MASK
| TF_MASK
);
837 if (VM86_TYPE(vret
) != VM86_UNKNOWN
)
848 #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
849 #if defined(__NetBSD__) || defined(__OpenBSD__)
851 vm86_callback(int sig
, int code
, struct sigcontext
*sc
)
853 /* Sync our context with what the kernel develivered to us. */
854 memcpy(&CONTEXT_REGS
, sc
, sizeof(*sc
));
856 switch (VM86_TYPE(code
)) {
859 unsigned int v
= VM86_ARG(code
);
861 if (v
== RETURN_TO_32_INT
) {
863 longjmp(context
.env
, 1);
866 pushw(CONTEXT_REGS
.REG(eflags
));
867 pushw(CONTEXT_REGS
.REG(cs
));
868 pushw(CONTEXT_REGS
.REG(eip
));
870 CONTEXT_REGS
.REG(cs
) = get_int_seg(v
);
871 CONTEXT_REGS
.REG(eip
) = get_int_off(v
);
872 CONTEXT_REGS
.REG(eflags
) &= ~(VIF_MASK
| TF_MASK
);
878 if (emulate() == 0) {
881 longjmp(context
.env
, 1);
888 longjmp(context
.env
, 1);
892 /* ...and sync our context back to the kernel. */
893 memcpy(sc
, &CONTEXT_REGS
, sizeof(*sc
));
895 #elif defined(__FreeBSD__)
897 vm86_callback(int sig
, int code
, struct sigcontext
*sc
)
901 /* Sync our context with what the kernel develivered to us. */
902 memcpy(&CONTEXT_REGS
, sc
, sizeof(*sc
));
905 /* XXX probably need to call original signal handler here */
908 longjmp(context
.env
, 1);
911 addr
= (unsigned char *)((CONTEXT_REGS
.REG(cs
) << 4) +
912 CONTEXT_REGS
.REG(eip
));
914 if (addr
[0] == 0xcd) { /* int opcode */
915 if (addr
[1] == RETURN_TO_32_INT
) {
917 longjmp(context
.env
, 1);
920 pushw(CONTEXT_REGS
.REG(eflags
));
921 pushw(CONTEXT_REGS
.REG(cs
));
922 pushw(CONTEXT_REGS
.REG(eip
));
924 CONTEXT_REGS
.REG(cs
) = get_int_seg(addr
[1]);
925 CONTEXT_REGS
.REG(eip
) = get_int_off(addr
[1]);
926 CONTEXT_REGS
.REG(eflags
) &= ~(VIF_MASK
| TF_MASK
);
928 if (emulate() == 0) {
930 longjmp(context
.env
, 1);
934 /* ...and sync our context back to the kernel. */
935 memcpy(sc
, &CONTEXT_REGS
, sizeof(*sc
));
937 #endif /* __FreeBSD__ */
942 if (context
.old_sighandler
) {
944 fprintf(stderr
, "run_vm86: callback already installed\n");
949 #if defined(__NetBSD__) || defined(__OpenBSD__)
950 context
.old_sighandler
= signal(SIGURG
, (void (*)(int))vm86_callback
);
951 #elif defined(__FreeBSD__)
952 context
.old_sighandler
= signal(SIGBUS
, (void (*)(int))vm86_callback
);
955 if (context
.old_sighandler
== (void *)-1) {
956 context
.old_sighandler
= NULL
;
958 fprintf(stderr
, "run_vm86: cannot install callback\n");
963 if (setjmp(context
.env
)) {
964 #if defined(__NetBSD__) || defined(__OpenBSD__)
965 (void) signal(SIGURG
, context
.old_sighandler
);
966 #elif defined(__FreeBSD__)
967 (void) signal(SIGBUS
, context
.old_sighandler
);
969 context
.old_sighandler
= NULL
;
973 debug_info(context
.vret
);
977 #if defined(__NetBSD__) || defined(__OpenBSD__)
978 if (i386_vm86(&context
.vm
) == -1)
980 #elif defined(__FreeBSD__)
981 if (i386_vm86(VM86_INIT
, &context
.vm
.init
))
984 CONTEXT_REGS
.REG(eflags
) |= PSL_VM
| PSL_VIF
;
985 sigreturn(&context
.vm
.uc
);
986 #endif /* __FreeBSD__ */
991 #endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */
994 LRMI_call(struct LRMI_regs
*r
)
998 memset(&CONTEXT_REGS
, 0, sizeof(CONTEXT_REGS
));
1002 CONTEXT_REGS
.REG(cs
) = r
->cs
;
1003 CONTEXT_REGS
.REG(eip
) = r
->ip
;
1005 if (r
->ss
== 0 && r
->sp
== 0) {
1006 CONTEXT_REGS
.REG(ss
) = context
.stack_seg
;
1007 CONTEXT_REGS
.REG(esp
) = context
.stack_off
;
1009 CONTEXT_REGS
.REG(ss
) = r
->ss
;
1010 CONTEXT_REGS
.REG(esp
) = r
->sp
;
1013 pushw(context
.ret_seg
);
1014 pushw(context
.ret_off
);
1025 LRMI_int(int i
, struct LRMI_regs
*r
)
1028 unsigned int seg
, off
;
1030 seg
= get_int_seg(i
);
1031 off
= get_int_off(i
);
1034 If the interrupt is in regular memory, it's probably
1035 still pointing at a dos TSR (which is now gone).
1037 if (seg
< 0xa000 || (seg
<< 4) + off
>= 0x100000) {
1039 fprintf(stderr
, "Int 0x%x is not in rom (%04x:%04x)\n", i
, seg
, off
);
1044 memset(&CONTEXT_REGS
, 0, sizeof(CONTEXT_REGS
));
1048 CONTEXT_REGS
.REG(cs
) = seg
;
1049 CONTEXT_REGS
.REG(eip
) = off
;
1051 if (r
->ss
== 0 && r
->sp
== 0) {
1052 CONTEXT_REGS
.REG(ss
) = context
.stack_seg
;
1053 CONTEXT_REGS
.REG(esp
) = context
.stack_off
;
1055 CONTEXT_REGS
.REG(ss
) = r
->ss
;
1056 CONTEXT_REGS
.REG(esp
) = r
->sp
;
1059 pushw(DEFAULT_VM86_FLAGS
);
1060 pushw(context
.ret_seg
);
1061 pushw(context
.ret_off
);
1070 #else /* (__linux__ || __NetBSD__ || __FreeBSD__ || __OpenBSD__) && __i386__ */
1071 #warning "LRMI is not supported on your system!"