VOGONS


First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

When I try to run Windows 3.0 in Standard Mode on UniPCemu's 80386 emulation, I see it do something strange(it's an endless loop with invalid return point, seeing as the call instruction keeps retriggering infinitely until stack will overflow) at 51:FE1 in plain protected mode. It keeps returning to the same instruction(through RETF, which returns to the E8 (near) CALL opcode)? The subroutine substracts 2 from ESP and then starts doing some stack operations after emulating a ENTER instruction, finally popping BP (and restoring the previously saved DS on the stack before returning using RETF). I see the stack keeps decreasing more and more(which will eventually overflow, causing a stack fault).

Anyone knows anything about this odd routine?

Edit: Trying to load EMM386.SYS NOEMS and running Windows 3.0 in 386 enhanced mode(default afaik) causes it to infinitely fault because Paging is disabled and the TSS descriptor is pointing to an invalid location(0x80002XXX range, which isn't in physical memory)?
Edit: I see it's enabling Paging when starting Windows 3.0 in 386 Enhanced mode, but then clearing the upper 16 bits of CR0, disabling Paging, at instruction address 8:2F8? Why would it disable, only to crash immediately after?

I'm using a required file(WinA20.386) which was downloaded from http://www.filewatcher.com/m/WINA20.386.9354-0.html

Last edited by superfury on 2017-12-29, 16:53. Edited 5 times in total.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 1 of 18, by Jo22

User metadata
Rank l33t++
Rank
l33t++

Hi! Even though this isn't my special subject, I'd recommend to read that post at OS/2 Museum.
It's quite interesting, even if it may not related to your issue:
http://www.os2museum.com/wp/sgdtsidt-fiction-and-reality/

Not sure, if this is of any relevance, but I believe Windows 3.0 behaves different than Windows 3.1 in several cases, as well.
For example, on Win 3.0, using the /2 switch seems to actually run the 16-Bit Protected Mode kernal.

On Windows 3.1, it always runs the 32-Bit kernal, if possible (except on 286es, of course).
Here, the /S or /2 parameters just force Windows to not load VXDs and to not use paging.
(As far as I remember. I posted this at Re: Is there a win3x EGA driver that supports more than 640x350 resolution?)

PS:I'm a lousy programmer, so please forgive my ignorance. 😅

"Time, it seems, doesn't flow. For some it's fast, for some it's slow.
In what to one race is no time at all, another race can rise and fall..." - The Minstrel

//My video channel//

Reply 2 of 18, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just modified EMM386.SYS to use the parameter ON in CONFIG.SYS to force it on. Now, when it executes a normal protected-mode IRET eventually(probably to restore MS-DOS in Virtual 8086 mode or a task switch), it will load CS with a NULL descriptor? Three words are POPped off the stack: Flags(0x2AA), CS(0x0000) and IP(0xBBF). This causes the driver to give error code #13 and reboot into the BIOS. Why are those strange 16-bit values on the stack?

The current location of the crash is at B8:BBD?

Edit: It almost seems that it's supposed to use 32-bit stack POPs instead of 16-bit ones? That would result in better values(32-bit operand size is used)?

Edit: Having modified IRET to use the operand size instead of CS segment default causes it to perform a proper IRET into Virtual 8086 mode(FLAGS=0x23000, CS=2AA, IP=BBF, DS=2AA,ES=2AA,FS=2AA,GS,SS=9047.

After that, it reboots(triple fault)?
Edit: The triple fault happens on the very first INT 21h(MS-DOS interrupt being fired)? Shouldn't that be a #GP fault instead? Apparently, IOPL==3?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 3 of 18, by superfury

User metadata
Rank l33t++
Rank
l33t++

The INT 21h call from V86 mode causes a #NP due to the descriptor's present bit being 0(entire descriptor is filled with zeroes). That causes another fault due to it not existing, thus double faulting. Then the double fault handler doesn't exist, thus triple faulting, rebooting the system? Is that normal once EMM386.SYS(Windows 3.0 one) enters V86 mode? IOPL==3. Anyone knows something about this? Jepael?

Just looked at http://wiki.osdev.org/Interrupt_Descriptor_Table . It says that non-present IDT entries cause a #GP fault instead of a #NP fault? Is #NP even used at the IDT entry stage?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 4 of 18, by superfury

User metadata
Rank l33t++
Rank
l33t++

The problem now is the following: The INT 21h causes a #GP because it isn't present. That #GP IDT entry is found, but it's DPL is 0, while CPL is 3. Since DPL<CPL, while servicing the external interrupt(bit 1 of error code is set due to it being a fault), it will cause another #GP fault, causing the interrupt to fire into the double fault, then into triple fault? But that isn't supposed to happen somehow(since it's firing a #GP which is actually the Virtual Machine Monitor starting)? What happens in a real 80386?

Edit: After a bit of modifying the interrupt sequence, it now successfully switches to the CPL-0 stack. Then it tries to push the segment registers, which fails and causes a double>triple fault(Remember, it's already a #GP fault handler running, so another stack fault causes a Double Fault, which triple faults due to not being present).

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 5 of 18, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just looked at the SS descriptor that it's switched to: it has a limit of 0x17F, while being a normal data segment(0x92 attribute)? Thus it'll fail on the first PUSH, which decreases SP from 0 to 0xFFFF and tries to write there. Why is the ESP register set up to become 0 on PL0? Why not 0x180? Or is the segment a top-down one, incorrectly setup?

Edit: This is the current protected-mode functionality:
Core protected mode: https://bitbucket.org/superfury/unipcemu/src/ … ion.c?at=master
Task switching routine: https://bitbucket.org/superfury/unipcemu/src/ … ing.c?at=master
Interrupts(real mode)/IRET/NMI: https://bitbucket.org/superfury/unipcemu/src/ … pts.c?at=master
BIU memory/execution phase support:
https://bitbucket.org/superfury/unipcemu/src/ … ion.c?at=master

Anyone can see something going wrong or missing?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 6 of 18, by superfury

User metadata
Rank l33t++
Rank
l33t++

After some little adjustments on loading NULL DS/ES/FS/GS descriptors(allowing for the clearing of DS-GS switching from Virtual 8086 mode to Privilege Level 0 monitor) and fixing the wrong offsets of the SS(0)/ESP(0) to be correct when firing interrupts(wrong base offsets and Privilege level shifts), it now starts up the monitor correctly 😁

Now it crashes somehow with a EMM386 #12 error?

Edit: After fixing another bug(checking popping 12 dwords instead of 6 dwords off the stack for faults when executing IRET to Virtual 8086 mode), I now see it switching back and forth between the VMM and Virtual 8086 mode! 😁 Although, it eventually(after displaying data from EMM386.SYS on the screen) crashes once again with an EMM386 exception #13?

Edit: The last I see of the EMM386.SYS on the MS-DOS prompt is the message "EMM386 Active", after which an IRET eventually is executed, which executes a protected-mode IRET into an invalid CS descriptor?

Edit: Looking at the other values popped during the IRET, it seems fishy: it's a 32-bit IRET, popping:
EIP=FFFF1695
CS=02AA
EFLAGS=0000FCC8

So it looks like it's trying to return to the Virtual 8086 mode program(which used segment 02AA for many of it's segment register states), but the high EFLAGS is cleared for some odd reason?

It seems (oddly enough) to be an interrupt 21h causing a fault? But it shouldn't do that(earlier calls went through correctly)?

A log of EMM386.SYS running (final #GP fault seems to be the INT 21h call that goes wrong, at line 1487691?): https://www.dropbox.com/s/4pkhsz4nyorh7ep/deb … 3_1425.zip?dl=0

Edit: Are those INT 16h calls the cause of the problem? It seems to run fine until that point(it's showing the result of MS-DOS running EMM386, which uses MS-DOS interrupt calls to do it's printing work)?

Edit: I've enabled a simple special log term in the logging(which is logged when the invalid return is fired):
https://www.dropbox.com/s/a4syfyuv6c207gn/deb … 1425_2.zip?dl=0

Search for the term "PlainPMReturnGoneWrong!" (without quotes) for the place where the invalid IRET occurs. Looking for the previous INT at that point seems to be an INT 2F instruction?

Filename
UniPCemu_invalid2Fcall_EMM386.txt
File size
127.51 KiB
Downloads
39 downloads
File comment
Invalid 2F call from the full log, which goes wrong.
File license
Fair use/fair dealing exception

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 7 of 18, by superfury

User metadata
Rank l33t++
Rank
l33t++

After some debugging, I notice that the special error code of -2(used with plain INT/INTO/INT3 instructions) gets pushed on stack, causing the Virtual 8086 monitor to detect it as a valid fault. Disabling the push on the stack causes it to continue on to the next driver:D

Now the VIDE-CDD.SYS crashes(and triple faults it seems) the CPU into rebooting(probably due to using I/O ports not allowed in the Virtual 8086 machine)?

Edit: The cause seems to be a 8-bit IN instruction reading port 240E(stored in DX)? This causes a #GP(00000028), which faults again (#GP(0000006B)), double faulting, which causes a #GP again, triple faulting.

Edit: Having improved it somewhat, it now seems to be infinitely writing some port, which is delegated to the Virtual 8086 monitor, which handles it and returns, while the driver(VIDE-CDD) seems to hang?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 8 of 18, by superfury

User metadata
Rank l33t++
Rank
l33t++

I see it keeps reading port 20h and acessing port 2XXXh whuch traps to the VM monitor? VIDE-CDD.SYS seems to have completed it's detection of the drives(and succeeded). It now seems to hang on the port OUT faulting(because of i/o rights fault to the unknown port)?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 9 of 18, by superfury

User metadata
Rank l33t++
Rank
l33t++

After stepping through the code, I notice the V86 monitor is executing a loop, while ECX contains a ridiculously(0x2XXXXXXX loaded in ECX) large loop, causing the CPU to appear hanging?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 10 of 18, by superfury

User metadata
Rank l33t++
Rank
l33t++

One little question: some #SS and #GP faults say #SS(0) and #GP(0) in the 80386 user reference, but that would mean the EXT bit is cleared. But the EXT bit is supposed to be set for exceptions(these cases) and external interrupts? So is it supposed to be set or cleared with the #SS(0) and #GP(0) in the 80386 user reference?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 11 of 18, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just modified the #GP(0) and #SS(0) (as well as #NP for non-present descriptors of data segmemts that are allowed to be loaded with cleared value(e.g. mov es,0)) to be according to the manual. Booting works, until reaching virtual 8086 mode address 2AA:DCA9, which tries to access an offset(32-bit address size override) that causes a segment limit violation(#GP(0)). I also see writes by the BIOS from segment F000 to ports 0x84 and 0x85(DMA Page registers) faulting between the itherations of the above fault? Is that a conflict with the HIMEM.SYS driver? Or is that something else going wrong? The EMM386.SYS already finished installing and VIDE-CDD.SYS detected the hardware. So it might be (just before) loading MSCDEX.EXE that's faulting for some odd reason?

Anyone? Jepael?

The port that´s being accessed by a INSB instruction is port 240E? Anyone knows anything about this I/O port?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 12 of 18, by vladstamate

User metadata
Rank Oldbie
Rank
Oldbie
superfury wrote:

The port that´s being accessed by a INSB instruction is port 240E? Anyone knows anything about this I/O port?

Who is doing the INSB? The BIOS or DOS? According to Bochs' port list that is:

2400-24FF ----	available for EISA slot 2

So maybe it is just trying to detect if it is anything there?

YouTube channel: https://www.youtube.com/channel/UC7HbC_nq8t1S9l7qGYL0mTA
Collection: http://www.digiloguemuseum.com/index.html
Emulator: https://sites.google.com/site/capex86/
Raytracer: https://sites.google.com/site/opaqueraytracer/

Reply 13 of 18, by superfury

User metadata
Rank l33t++
Rank
l33t++

Well, somewhere directly after that(probably first DMA I/O port being accessed and faulting because of the TSS blocking the ports by default(all cleared entries afaik)), it starts the Virtual 8086 monitor, which somehow goes REALLY WRONG and somehow corrupts some/most registers with invalid values(I see most registers filled with large 32-bit quantities, sometimes even as early as entering the monitor from Virtual 8086 mode(Directly after the interrupt has completed???). It's executing a ridiculously large loop of 0x2XXXXXXX entires for some odd reason(ECX contains the value 0x2XXXXXXX(XXXXXXXX being some random-like number))? It's using a LOOP instruction to count down using that counter, locking the Virtual 8086 monitor into a big loop that will finish in a long long period(the CPU running at 16MHz, so not so many loops/second).

The INSB is done either by MS-DOS or one of the drivers(don't know about the Compaq Deskpro 386 accessing that port?). I know segment 2AAh contains the EMM386.SYS driver of Windows 3.0(which should have already completed it's basic setup, having already run the VIDE-CDD.SYS device driver). The next program that should run to the old config.sys(just upgraded it to MS-DOS 6.22 for easier configuration switching(without having to convert my 2GB back and forth between it's small sfdimg disk image format(only 100MB) and it's full static image format(flat disk image)).

I did notice some oddities with the FDC when trying to install MS-DOS 6.22(using a simple "SYS c:" and copying the remaining files manually to the C:\MSDOS directory using WinImage): at odd moments, the IBM AT BIOS seems to not detect the FDC as being ready anymore(requiring multiple (R)etries to transfer the OS to the hard disk image). Eventually it succeeds copying the system files, though. Immediately after that, I've modified my config.sys and autoexec.bat to add a simple boot menu allowing me to switch between IBM XT, AT and Compaq Deskpro 386 configurations(instead of having to continuously change the harddisk image itself to do that:S ). So far it seems to be working without many problems(although it seems to have large hard disk delays for some odd reason now, but that could be due to the hard disk emulation itself.
I've adjusted the FDC a bit to allow improved detection of the 40-track vs 80-track drives(keeping a virtual head to detect track 0 with seperate, which doesn't move past 40 tracks or 80 tracks depending on the disk image). That way the seek-to-track48 and backtrack-to-track 0 will properly detect the 40-track drives(40 track drives give track0 at physical track 0/reported track 8, while 80-track drives will give track 0 at track 0(as it does move past track 40 when executing the pulses). But oddly enough, the AT BIOS seems to issue the SEEK to track 48 and then completely gives up? The SEEKING bit in the MSR is set properly(cleared when completed seeking to the FDC's idea of track 48), but when it's completing the seek(the same way as a recalibrate, roughly, but can be in two directions: towards higher cylinders or lower cylinders, using virtual step pulses(timer timing out each simulated 'pulse')) the IBM AT BIOS has already given the 601-Diskette error?

Looking at the config.sys/autoexec.bat, I notice that the point it's going wrong seems to be the MS-DOS 6.22 mouse.com executing? It's called as "mouse /Y"? The program after that is MSCDEX for CD-ROM support, but it doesn't get that far it seems? Or it's something within MS-DOS itself(IO.SYS/MSDOS.SYS) that's going wrong?

I've also added a slight delay when issuing the hard disk IRQs(of 2us, compared to the ATAPI 20us(also when finishing an ATAPI command)) to allow the driver/BIOS to set some flag before checking the response from the hard disk, but I still see the HDD BIOS(XT-IDE Universal BIOS) waiting for the disk IRQ when it's seems to have completed the Read Multiple(up to 0x80 sectors) command? This seems to happen at least directly after detecting the hard disks(It's reporting them correctly after the ATA IDENTIFY command has been issued)?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 14 of 18, by superfury

User metadata
Rank l33t++
Rank
l33t++

One thing I notice now, after modifying and simplifying the EMM386 parameters and MS-DOS 6.22(Previously 5.0a)/EMM386(.EXE from MS-DOS 6.22 instead of the .SYS from Windows 3.0) being loaded in the correct format(UniPCemu compatible geometry, only NOEMS parameter), that it seems to crash. It now gives me an #UD exception(or error code #06 as EMM386 calls it), because of an invalid locked HLT instruction (LOCK HLT instruction, which is invalid) at the Virtual Machine Monitor segment, EIP=6667h? Although 6667h sounds fishy: 66h 67h are the combined opcode prefixes for 16-bit address and data(e.g. the VMM trying to access something the 8086-way?)

Anyone? It's coming from the EMM386 driver it seems(as MS-DOS wouldn't use segment 23h afaik)? Real mode segment 2AAh was the EMM386 real mode continuation, but I don't know if that's still the case with EMM386.EXE(as opposed to the Windows 3.0 .SYS variant)?

The fault seems to occur at 48:6667, within the Virtual 8086 monitor installed by EMM386? According to my debugger, it's the third time it gets to that location, before jumping to the incorrect location specified in ECX? I've also added support for Virtual 8086 mode Pseudo protection fault interrupts(instead of pushing 0 on the stack of the Virtual 8086 monitor, it now pushes no error code, allowing for the Virtual 8086 monitor to see that and handle it accordingly(as an interrupt without error code)).

Pressing enter on the error code #06, causes the execution to get to the same execution point twice before rebooting?

The invalid jump seems to be:
CALL word CS:[00006100+ECX*2]

Is that even correct? I see it's using a address-size override(67h) and CS: override(2E) and then the instruction(complete instruction: 672EFF144D00610000). But shouldn't that be a 16-bit address instead, seeing as the Virtual 8086 monitor should be a 32-bit program? According to the loaded CS segment descriptor it's indeed a 16-bit program? So it's overriding to 32-bit address size(which it is doing properly) and 16-bit operand size?
Why would a Virtual 8086 monitor operate in 16-bit mode? Isn't it supposed to be in 32-bit mode usually?

Edit: Just looked at the very first Virtual 8086 mode call: it's descriptor is actually a 16-bit code segment descriptor that's being used? Why not 32-bit?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 15 of 18, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've implemented the pseudo V86 (int 12/13h) for #GP(0) and #SS(0). It's still reaching the LOCK HLT? Anyone?

Current CPU emulation: https://bitbucket.org/superfury/unipcemu/src/ … /cpu/?at=master

Anyone can see what's going wrong?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 16 of 18, by superfury

User metadata
Rank l33t++
Rank
l33t++

One thing I notice when the invalid jump happens is that ECX contains 0xFF? It contains 0x06 all other times, which runs fine, but 0xFF is probably out of some table's range? It's also an unalligned address, so probably some invalid jump anyway? It seems to happen between the last device driver(VIDE-CDD.SYS(when loaded) or EMM386.EXE(which is loaded before that)) and the start of COMMAND.COM(and/or autoexec.bat)? Stepping though using the MS-DOS 6.22 F8 option tells me it crashes directly after the last device driver that's loaded(either EMM386.EXE or VIDE-CDD.SYS). I do see that the problem happens somewhere within the V86 monitor(segment 0048) that's loaded by EMM386.EXE(from MS-DOS 6.22)? So why does it crash? Why does ECX contain 0xFF(instead of a valid value)?

Edit: Just tried to load the DLX Linux(10meg version from bochs.sourceforge.net at http://bochs.sourceforge.net/guestos/dlxlinux4.tar.gz ) 10MB disk image. It tries to load an invalid sector(in the 100MB range), which shouldn't exist on the disk image(it's only 10MB after all) from the boot loader? Anyone knows what the cause might be? It reports: "L 04 04" etc.
Edit: Looking again it's the Linux 4-meg image, but the disk image is actually 100MB large? It tries to read sector number 0x71C69, which is at 238MB, but the disk image is only 112MB?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 17 of 18, by superfury

User metadata
Rank l33t++
Rank
l33t++

It's strange that after all the VM monitor is crashing. The test386.asm testsuite (https://github.com/barotto/test386.asm) checks out correctly, so basic operation should be flawless(at least math instructions). Basic jumps should also work(since they're so simple). Protected mode stuff should also basically work(since I see it running until the crash in the monitor after switching back and forth to/from V86/protected mode). No exceptions are thrown from the VM monitor, until reaching the #UD fault. It seems to go right the first few times reaching that point(ECX=06h), but at the crash time ECX=FFh? Anyone can think of a possible cause of the problem?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 18 of 18, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just tried the Supersoft/Landmark AT BIOS again(using 80286 cycle-accurate emulation). It seems to work, except (after fixing CGA/MDA memory to be shadowed and copied back on VGA memory mode changes, fixing CGA memory bugs it reported, while increasing CGA/MDA compatibility) the U keyboard chip, CMOS RAM test and Protected mode test? All other tests check out without errors.

Edit: The faulty #GP exception seems to occur after an IRET instruction?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io