]>
git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/hwinfo/src/int10/i10_v86.c
2 * Copyright 1999 Egbert Eich
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the authors not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. The authors makes no representations
11 * about the suitability of this software for any purpose. It is provided
12 * "as is" without express or implied warranty.
14 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
25 #include <asm/unistd.h>
31 #include "vm86_struct.h"
35 #include "AsmMacros.h"
37 extern int emu_vm86(struct vm86_struct
*vm
, unsigned debug
);
39 #define INT2PTR(a) ((a) + (unsigned char *) 0)
41 void log_err(char *format
, ...) __attribute__ ((format (printf
, 1, 2)));
43 struct vm86_struct vm86s
;
45 static int vm86_GP_fault(void);
46 static int vm86_do_int(int num
);
48 static int vm86_rep(struct vm86_struct
*ptr
);
50 void log_registers(void);
52 #define CPU_REG(x) (vm86s.regs.x)
53 #define CPU_REG_LW(reg) (*((CARD16 *)&CPU_REG(reg)))
54 #define CPU_REG_HW(reg) (*((CARD16 *)&CPU_REG(reg) + 1))
55 #define CPU_REG_LB(reg) (*(CARD8 *)&CPU_REG(e##reg))
56 #define SEG_ADR(type, seg, reg) type((CPU_REG_LW(seg) << 4) + CPU_REG_LW(e##reg) + (unsigned char *) 0)
64 P
.inb
= (CARD8(*)(CARD16
))inb
;
65 P
.inw
= (CARD16(*)(CARD16
))inw
;
66 P
.inl
= (CARD32(*)(CARD16
))inl
;
67 P
.outb
= (void(*)(CARD16
,CARD8
))outb
;
68 P
.outw
= (void(*)(CARD16
,CARD16
))outw
;
69 P
.outl
= (void(*)(CARD16
,CARD32
))outl
;
74 setup_vm86(unsigned long bios_start
, i86biosRegsPtr regs
)
79 vm86s
.flags
= VM86_SCREEN_BITMAP
;
81 vm86s
.screen_bitmap
= 0;
82 vm86s
.cpu_type
= CPU_586
;
83 memset(&vm86s
.int_revectored
, 0xff,sizeof(vm86s
.int_revectored
)) ;
84 memset(&vm86s
.int21_revectored
, 0xff,sizeof(vm86s
.int21_revectored
)) ;
86 eip
= bios_start
& 0xFFFF;
87 cs
= (bios_start
& 0xFF0000) >> 4;
89 CPU_REG(eax
) = regs
->ax
;
90 CPU_REG(ebx
) = regs
->bx
;
91 CPU_REG(ecx
) = regs
->cx
;
92 CPU_REG(edx
) = regs
->dx
;
94 CPU_REG(edi
) = regs
->di
;
99 CPU_REG(ss
) = 0x30; /* This is the standard pc bios stack */
100 CPU_REG(es
) = regs
->es
;
101 CPU_REG(ds
) = 0x40; /* standard pc ds */
104 CPU_REG(eflags
) |= (VIF_MASK
| VIP_MASK
);
108 collect_bios_regs(i86biosRegsPtr regs
)
110 regs
->ax
= CPU_REG(eax
);
111 regs
->bx
= CPU_REG(ebx
);
112 regs
->cx
= CPU_REG(ecx
);
113 regs
->dx
= CPU_REG(edx
);
114 regs
->es
= CPU_REG(es
);
115 regs
->ds
= CPU_REG(ds
);
116 regs
->di
= CPU_REG(edi
);
117 regs
->si
= CPU_REG(esi
);
120 static int do_vm86(int cpuemu
)
130 retval
= emu_vm86(&vm86s
, cpuemu
& 2);
133 retval
= vm86_rep(&vm86s
);
136 retval
= emu_vm86(&vm86s
, cpuemu
& 2);
139 switch (VM86_TYPE(retval
)) {
141 if (!vm86_GP_fault())
145 log_err("vm86_sti :-((\n");
149 if (!vm86_do_int(VM86_ARG(retval
))) {
150 log_err("Unknown vm86_int: %X\n",VM86_ARG(retval
));
154 /* I'm not sure yet what to do if we can handle ints */
157 log_err("VBE: received a signal!\n");
161 log_err("unknown type(0x%x)=0x%x\n",
162 VM86_ARG(retval
),VM86_TYPE(retval
));
171 do_x86(unsigned long bios_start
, i86biosRegsPtr regs
, int cpuemu
)
173 setup_vm86(bios_start
, regs
);
174 while(do_vm86(cpuemu
)) {};
175 collect_bios_regs(regs
);
178 /* get the linear address */
179 #define LIN_PREF_SI ((pref_seg << 4) + CPU_REG_LW(esi))
181 #define LWECX (prefix66 ^ prefix67 ? CPU_REG(ecx) : CPU_REG_LW(ecx))
182 #define SET_LWECX_ZERO (prefix66 ^ prefix67 ? (CPU_REG(ecx) = 0) : (CPU_REG_LW(ecx) = 0))
187 unsigned char *csp
, *lina
;
190 int done
,is_rep
,prefix66
,prefix67
;
193 csp
= lina
= SEG_ADR((unsigned char *), cs
, ip
);
195 printf("exception: \n");
200 prefix66
= prefix67
= 0;
203 /* eat up prefixes */
207 case 0x66: /* operand prefix */ prefix66
=1; break;
208 case 0x67: /* address prefix */ prefix67
=1; break;
209 case 0x2e: /* CS */ pref_seg
=CPU_REG(cs
); break;
210 case 0x3e: /* DS */ pref_seg
=CPU_REG(ds
); break;
211 case 0x26: /* ES */ pref_seg
=CPU_REG(es
); break;
212 case 0x36: /* SS */ pref_seg
=CPU_REG(ss
); break;
213 case 0x65: /* GS */ pref_seg
=CPU_REG(gs
); break;
214 case 0x64: /* FS */ pref_seg
=CPU_REG(fs
); break;
215 case 0xf2: /* repnz */
216 case 0xf3: /* rep */ is_rep
=1; break;
220 csp
--; /* oops one too many */
221 org_eip
= CPU_REG(eip
);
222 CPU_REG_LW(eip
) += (csp
- lina
);
226 case 0x6c: /* insb */
227 /* NOTE: ES can't be overwritten; prefixes 66,67 should use esi,edi,ecx
228 * but is anyone using extended regs in real mode? */
229 /* WARNING: no test for DI wrapping! */
230 CPU_REG_LW(edi
) += port_rep_inb(CPU_REG_LW(edx
),
231 SEG_ADR((CARD8
*),es
,di
),
232 CPU_REG_LW(eflags
)&DF
,
234 if (is_rep
) SET_LWECX_ZERO
;
238 case 0x6d: /* (rep) insw / insd */
239 /* NOTE: ES can't be overwritten */
240 /* WARNING: no test for _DI wrapping! */
242 CPU_REG_LW(edi
) += port_rep_inl(CPU_REG_LW(edx
),
243 SEG_ADR((CARD32
*),es
,di
),
244 CPU_REG_LW(eflags
)&DF
,
248 CPU_REG_LW(edi
) += port_rep_inw(CPU_REG_LW(edx
),
249 SEG_ADR((CARD16
*),es
,di
),
250 CPU_REG_LW(eflags
)&DF
,
253 if (is_rep
) SET_LWECX_ZERO
;
257 case 0x6e: /* (rep) outsb */
258 if (pref_seg
< 0) pref_seg
= CPU_REG_LW(ds
);
259 /* WARNING: no test for _SI wrapping! */
260 CPU_REG_LW(esi
) += port_rep_outb(CPU_REG_LW(edx
),(CARD8
*)INT2PTR(LIN_PREF_SI
),
261 CPU_REG_LW(eflags
)&DF
,
263 if (is_rep
) SET_LWECX_ZERO
;
267 case 0x6f: /* (rep) outsw / outsd */
268 if (pref_seg
< 0) pref_seg
= CPU_REG_LW(ds
);
269 /* WARNING: no test for _SI wrapping! */
271 CPU_REG_LW(esi
) += port_rep_outl(CPU_REG_LW(edx
),
272 (CARD32
*)INT2PTR(LIN_PREF_SI
),
273 CPU_REG_LW(eflags
)&DF
,
277 CPU_REG_LW(esi
) += port_rep_outw(CPU_REG_LW(edx
),
278 (CARD16
*)INT2PTR(LIN_PREF_SI
),
279 CPU_REG_LW(eflags
)&DF
,
282 if (is_rep
) SET_LWECX_ZERO
;
286 case 0xe5: /* inw xx, inl xx */
287 if (prefix66
) CPU_REG(eax
) = P
.inl((int) csp
[1]);
288 else CPU_REG_LW(eax
) = P
.inw((int) csp
[1]);
289 CPU_REG_LW(eip
) += 2;
291 case 0xe4: /* inb xx */
292 CPU_REG_LW(eax
) &= ~(CARD32
)0xff;
293 CPU_REG_LB(ax
) |= P
.inb((int) csp
[1]);
294 CPU_REG_LW(eip
) += 2;
296 case 0xed: /* inw dx, inl dx */
297 if (prefix66
) CPU_REG(eax
) = P
.inl(CPU_REG_LW(edx
));
298 else CPU_REG_LW(eax
) = P
.inw(CPU_REG_LW(edx
));
299 CPU_REG_LW(eip
) += 1;
301 case 0xec: /* inb dx */
302 CPU_REG_LW(eax
) &= ~(CARD32
)0xff;
303 CPU_REG_LB(ax
) |= P
.inb(CPU_REG_LW(edx
));
304 CPU_REG_LW(eip
) += 1;
307 case 0xe7: /* outw xx */
308 if (prefix66
) P
.outl((int)csp
[1], CPU_REG(eax
));
309 else P
.outw((int)csp
[1], CPU_REG_LW(eax
));
310 CPU_REG_LW(eip
) += 2;
312 case 0xe6: /* outb xx */
313 P
.outb((int) csp
[1], CPU_REG_LB(ax
));
314 CPU_REG_LW(eip
) += 2;
316 case 0xef: /* outw dx */
317 if (prefix66
) P
.outl(CPU_REG_LW(edx
), CPU_REG(eax
));
318 else P
.outw(CPU_REG_LW(edx
), CPU_REG_LW(eax
));
319 CPU_REG_LW(eip
) += 1;
321 case 0xee: /* outb dx */
322 P
.outb(CPU_REG_LW(edx
), CPU_REG_LB(ax
));
323 CPU_REG_LW(eip
) += 1;
328 printf("hlt at %p\n", lina
);
333 log_err("CPU 0x0f Trap at eip=0x%lx\n",CPU_REG(eip
));
337 case 0xf0: /* lock */
339 log_err("unknown reason for exception\n");
342 log_err("cannot continue\n");
344 } /* end of switch() */
354 /* try to run bios interrupt */
356 /* if not installed fall back */
357 #define COPY(x) regs.x = CPU_REG(x)
358 #define COPY_R(x) CPU_REG(x) = regs.x
377 if (!(val
= int_handler(num
,®s
)))
378 if (!(val
= run_bios_int(num
,®s
)))
406 vm86_rep(struct vm86_struct
*ptr
)
411 /* stay away from %ebx */
412 __asm__
__volatile__("push %%ebx\n\tmov %%ecx,%%ebx\n\tpush %%gs\n\tint $0x80\n\tpop %%gs\n\tpop %%ebx\n"
413 :"=a" (__res
):"a" ((int)113),
414 "c" ((struct vm86_struct
*)ptr
));
428 #define pushw(base, ptr, val) \
429 __asm__ __volatile__( \
431 "movb %h2,(%1,%0)\n\t" \
435 : "r" (base), "q" (val), "0" (ptr))
439 #define pushw(base, ptr, val) { \
440 ptr = ((ptr) - 1) & 0xffff; \
441 *((unsigned char *)(base) + (ptr)) = (val) >> 8; \
442 ptr = ((ptr) - 1) & 0xffff; \
443 *((unsigned char *)(base) + (ptr)) = (val); \
449 run_bios_int(int num
, struct regs86
*regs
)
456 static int firsttime
= 1;
458 /* check if bios vector is initialized */
459 if (((CARD16
*)0)[(num
<<1)+1] == 0x0000) { /* SYS_BIOS_SEG ?*/
470 ssp
= (CARD16
*)INT2PTR(CPU_REG(ss
)<<4);
471 sp
= (CARD32
) CPU_REG_LW(esp
);
473 eflags
= regs
->eflags
;
474 eflags
= ((eflags
& VIF_MASK
) != 0)
475 ? (eflags
| IF_MASK
) : (eflags
& ~(CARD32
) IF_MASK
);
476 pushw(ssp
, sp
, eflags
);
477 pushw(ssp
, sp
, regs
->cs
);
478 pushw(ssp
, sp
, (CARD16
)regs
->eip
);
480 regs
->cs
= ((CARD16
*) 0)[(num
<< 1) + 1];
481 regs
->eip
= (regs
->eip
& 0xFFFF0000) | ((CARD16
*) 0)[num
<< 1];
485 regs
->eflags
= regs
->eflags
486 & ~(VIF_MASK
| TF_MASK
| IF_MASK
| NT_MASK
);
493 return ((CARD32
*)0)[num
];
499 return (CPU_REG(cs
) << 4) + CPU_REG(eip
);
505 " eax %08x, ebx %08x, ecx %08x, edx %08x\n"
506 " esi %08x, edi %08x, ebp %08x, esp %08x\n"
507 " ds %04x, es %04x, fs %04x, gs %04x, ss %04x\n"
508 " cs:eip %04x:%08x\n",
509 (unsigned) CPU_REG(eax
), (unsigned) CPU_REG(ebx
), (unsigned) CPU_REG(ecx
), (unsigned) CPU_REG(edx
),
510 (unsigned) CPU_REG(esi
), (unsigned) CPU_REG(edi
), (unsigned) CPU_REG(ebp
), (unsigned) CPU_REG(esp
),
511 (unsigned) CPU_REG(ds
), (unsigned) CPU_REG(es
),
512 (unsigned) CPU_REG(fs
), (unsigned) CPU_REG(gs
), (unsigned) CPU_REG(ss
),
513 (unsigned) CPU_REG(cs
), (unsigned) CPU_REG(eip
)