Messages in this thread Patch in this message | | | Date | Fri, 7 May 1999 09:51:56 -0700 (PDT) | From | Jiuming Luo <> | Subject | Bug Fixing: CPU exception handling routine |
| |
System information
The CPU type is Pentium II 300MHz. The total hardware memory size is 64M bytes. The dosemu.conf lines are normal(unchanged), except the following variables:
$_rawkeyboard = (1) $_cpu = "80586" $_xms = (32768) $_ems = (0) $_console = (1) $_graphics = (1) $_vmemsize = (4096) $_chipset = "trident" $_hdimage = "/dev/hda1 /dev/hdc1"
The /dev/hda1 is a DOS partition and contains Windows 98. Linux kernel version is 2.2.7. DOSEmu version is 0.99.11.
Bug Description
Now, run DOSEmu, press F8 key to access Win98 startup menu.
Then choose "Safe mode command prompt only".
At the dos prompt, type DEBUG and press Enter. Then type the
letter "A" and press Enter to Assemble something. And then
enter the following lines:
cli cli cli nop nop nop
Press an additional Enter to leave the "A" command.
Now type the letter "T" ( single step Trace command ) and
press Enter. O! O! O! Oh! FOUR instructions passed ( other
than ONE instruction )---- the IP register (the program
counter) points to the 5th instruction "NOP".
Similarly, you can try to trace the following:
pushf pushf pushf popf pushf cli sti popf pushf nop
Set IP to point to the first "pushf", then enter "T" command.
You will find that all instructions are executed, and the SP
(stack pointer) and the stack contain the right values. That is
dangerous, especially when the last instruction is not "nop" !
Note that in real mode DOS or even in Win98's DOS Box, there is
no such problem.
##################################################################
Fixing
It seems that this bug is related to Linux kernel. I have re-written
the kernel function 'handle_vm86_faults()' and rebuilt the kernel.
No conflicts encountered so far.
The only change is the addition of DOS debugger trap support.
Note that inside the new function, the 'ip' variable is used as a temp
variable.
'diff -u ' differences between the old ( ver. 2.2.7 ) and the new:
--- linux-2.2.7/arch/i386/kernel/vm86.c Wed Dec 2 03:28:24 1998 +++ linux-n.e.w/arch/i386/kernel/vm86.c Fri May 7 03:44:40 1999 @@ -460,11 +460,14 @@ #define CHECK_IF_IN_TRAP \ if (VMPI.vm86dbg_active && VMPI.vm86dbg_TFpendig) \ - pushw(ssp,sp,popw(ssp,sp) | TF_MASK); + pushw(ssp,sp,popw(ssp,sp) | TF_MASK); \ + ip = regs->eflags & TF_MASK + #define VM86_FAULT_RETURN \ if (VMPI.force_return_for_pic && (VEFLAGS & IF_MASK)) \ return_to_32bit(regs, VM86_PICRETURN); \ - return; + if (ip) return_to_32bit(regs, VM86_TRAP + (1 << 8)); \ + return csp = (unsigned char *) (regs->cs << 4); ssp = (unsigned char *) (regs->ss << 4); @@ -481,6 +484,7 @@ case 0x9c: SP(regs) -= 4; IP(regs) += 2; + ip = regs->eflags & TF_MASK; pushl(ssp, sp, get_vflags(regs)); VM86_FAULT_RETURN; @@ -488,7 +492,7 @@ case 0x9d: SP(regs) += 4; IP(regs) += 2; - CHECK_IF_IN_TRAP + CHECK_IF_IN_TRAP; set_vflags_long(popl(ssp, sp), regs); VM86_FAULT_RETURN; @@ -497,9 +501,24 @@ SP(regs) += 12; IP(regs) = (unsigned short)popl(ssp, sp); regs->cs = (unsigned short)popl(ssp, sp); - CHECK_IF_IN_TRAP + CHECK_IF_IN_TRAP; set_vflags_long(popl(ssp, sp), regs); VM86_FAULT_RETURN; + + /* cli, sti ---- only for test purpose */ + /*--------------------------------------- + case 0xfa: + IP(regs) += 2; + ip = regs->eflags & TF_MASK; + clear_IF(regs); + VM86_FAULT_RETURN; + case 0xfb: + IP(regs) += 2; + ip = regs->eflags & TF_MASK; + set_IF(regs); + VM86_FAULT_RETURN; + ---------------------------------------*/ + /* need this to avoid a fallthrough */ default: return_to_32bit(regs, VM86_UNKNOWN); @@ -509,6 +528,7 @@ case 0x9c: SP(regs) -= 2; IP(regs)++; + ip = regs->eflags & TF_MASK; pushw(ssp, sp, get_vflags(regs)); VM86_FAULT_RETURN; @@ -516,7 +536,7 @@ case 0x9d: SP(regs) += 2; IP(regs)++; - CHECK_IF_IN_TRAP + CHECK_IF_IN_TRAP; set_vflags_short(popw(ssp, sp), regs); VM86_FAULT_RETURN; @@ -537,13 +557,14 @@ SP(regs) += 6; IP(regs) = popw(ssp, sp); regs->cs = popw(ssp, sp); - CHECK_IF_IN_TRAP + CHECK_IF_IN_TRAP; set_vflags_short(popw(ssp, sp), regs); VM86_FAULT_RETURN; /* cli */ case 0xfa: IP(regs)++; + ip = regs->eflags & TF_MASK; clear_IF(regs); VM86_FAULT_RETURN; @@ -556,12 +577,15 @@ */ case 0xfb: IP(regs)++; + ip = regs->eflags & TF_MASK; set_IF(regs); VM86_FAULT_RETURN; default: return_to_32bit(regs, VM86_UNKNOWN); } +#undef CHECK_IF_IN_TRAP +#undef VM86_FAULT_RETURN } /* ---------------- vm86 special IRQ passing stuff ----------------- */
##################################################################
Description of another case
Also under DOSEMU, try to run "td.exe" and "td32.exe" (two utilities of Borland C++ 5.02). Both will crash with the following information:
ERROR: unexpected CPU exception 0x06 errorcode: 0x00000000 while in vm86 (DOS) Program=sigsegv.c, Line=250
_________________________________________________________ Do You Yahoo!? Get your free @yahoo.com address at http://mail.yahoo.com
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |