Hello. Patrick J. LoPresti wrote: >> The only good thing here is that the amount of progs that works on >> 486 but not on 386 is very minor... > But how annoying when you run into one :-). I really don't think it is a major advantage to have an ability to pass the first stage of NT install... :)
OKey, I have found the bug. According to this: http://support.intel.com/design/intarch/techinfo/Pentium/instrefi.htm#89126 AC is cleared by an INT instruction executed in real mode. As this flag resides in the higher word of eflags, it is not saved on stack so it gets lost. Two attached patches implements that functionality. Then you can safely remove the "BUG" stuff I think. I have failed to find any docs on how the hardware interrupts affects the AC flag but I guess they don't, otherwise it can be used only when IF is not set. ID flag is not affected so I guess it gets cleared together with AC by mistake. > Couldn't you just tell people to use $_cpu=(80386) as a workaround? > That would have the side-effect of protecting the AC bit, wouldn't it? Yes, it would. And not, it is not a side-effect, this is the main and almost only difference with 80486 in dosemu. >> Furthermore somehow it happens that if the signal was received while >> AC is set, dosemu itself executes with AC set and crashs somewhere >> in glibc functions due to exception 0x11. > Is that not a bug in the emulator design? I mean, shouldn't *all* of > the emulator's state be isolated from the emulated machine's? Right, this is a main design problem of dosemu which is that the DPMI code is executed in the same address space with dosemu. vm86 is separated however. So DPMI code can do everything and if dosemu have root privs, it can be easily exploited by DPMI code. > Would you accept such a patch? It is not me who accepting patches here, this is what the project coordinators/maintainers does. Visit dosemu.sourceforge.net and www.sf.net/projects/dosemu to find out who is responsible.
--- src/include/cpu.h Wed Jun 26 21:58:32 2002 +++ src/include/cpu.h Sat Jul 27 23:12:23 2002 @@ -198,6 +198,10 @@ #define set_TF() (_EFLAGS |= TF) #define clear_TF() (_EFLAGS &= ~TF) #define isset_TF() ((_EFLAGS & TF) != 0) + /* alignment flag */ +#define set_AC() (_EFLAGS |= AC) +#define clear_AC() (_EFLAGS &= ~AC) +#define isset_AC() ((_EFLAGS & AC) != 0) /* Virtual Interrupt Pending flag */ #define set_VIP() (_EFLAGS |= VIP) #define clear_VIP() (_EFLAGS &= ~VIP) --- src/emu-i386/do_vm86.c Fri Jul 26 21:16:46 2002 +++ src/emu-i386/do_vm86.c Sun Jul 28 00:06:46 2002 @@ -506,6 +506,14 @@ pic_iret(); break; case VM86_INTx: + /* + * AC flag gets cleared by the INT instruction and is not restored + * by IRET because it resides in the higher word of eflags and + * hence not saved in the stack. + * However we can't clear it in real_run_int() et al because + * it is not cleared by hardware interrupts (???) + */ + clear_AC(); #ifdef USE_MHPDBG mhp_debug(DBG_INTx + (VM86_ARG(retval) << 8), 0, 0); #endif --- src/dosext/dpmi/dpmi.c Sun Jun 23 23:42:23 2002 +++ src/dosext/dpmi/dpmi.c Sun Jul 28 00:07:35 2002 @@ -2240,6 +2227,14 @@ pic_iret(); break; case VM86_INTx: + /* + * AC flag gets cleared by the INT instruction and is not restored + * by IRET because it resides in the higher word of eflags and + * hence not saved in the stack. + * However we can't clear it in real_run_int() et al because + * it is not cleared by hardware interrupts (???) + */ + clear_AC(); #ifdef X86_EMULATOR D_printf("DPMI: Return from vm86() for interrupt\n"); #endif
--- linux/arch/i386/kernel/vm86.c Sat Jul 27 13:12:38 2002 +++ linux/arch/i386/kernel/vm86.c Sat Jul 27 23:56:27 2002 @@ -317,6 +317,11 @@ regs->eflags &= ~TF_MASK; } +static inline void clear_AC(struct kernel_vm86_regs * regs) +{ + regs->eflags &= ~AC_MASK; +} + /* It is correct to call set_IF(regs) from the set_vflags_* * functions. However someone forgot to call clear_IF(regs) * in the opposite case. @@ -471,6 +476,7 @@ IP(regs) = segoffs & 0xffff; clear_TF(regs); clear_IF(regs); + clear_AC(regs); return; cannot_handle: