Finding bugs in 8086-80386 emulation core?

Emulation of old PCs, PC hardware, or PC peripherals.

Re: Finding bugs in 8086-80386 emulation core?

Postby superfury » 2017-8-24 @ 05:24

That's odd: it shouldn't work according to 80286/386 documentation: it will fetch past 0xFFFF(0x10000), causing a #GP fault?
superfury
Oldbie
 
Posts: 1824
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: Finding bugs in 8086-80386 emulation core?

Postby Jepael » 2017-8-24 @ 20:33

superfury wrote:That's odd: it shouldn't work according to 80286/386 documentation: it will fetch past 0xFFFF(0x10000), causing a #GP fault?


I don't know if that's possible on a 286 for a multitude of reasons.

1) IP is 16-bit
2) LIMIT = 65535 max, so offset in IP cannot be larger than LIMIT
3) Prefetcher can never cause a code segment limit violation
4) So a program must try to actually execute past end of the code segment (but as IP wraps around it's still within limits).
5) even if jumped to cs:0xFFFF, prefetcher would prefetch a byte from odd address so it would not again cause #GP as it does not load a word from 0xFFFF.

On 386 it should have caused a #GP, maybe it was handled by EMM386 V86 monitor?
Jepael
Oldbie
 
Posts: 1078
Joined: 2005-6-15 @ 19:28
Location: Finland

Re: Finding bugs in 8086-80386 emulation core?

Postby superfury » 2017-8-24 @ 23:19

That's my thoughts exactly. And the limit can be broken by lowering the limit of the descriptor to <64K on a 80286. That will fault the Prefetch and should make it stop prefetching? It should be possible to verify on a real CPU trying to make it prefetch into VRAM by using Video Write Mode 1(VRAM to VRAM transfer) or comparable read-sensitive VRAM operation. If it changes the VRAM results in that mode, it is prefetching into VRAM(ignoring the limit). If it doesn't, prefetch stops at the limit of the descriptor(at the first fault location). Just read back the VRAM that's modified when that VRAM is read and compare in mode 0 with a random pattern on the lower VRAM from the Real-mode #GP handler.

Don't have a real 2/386, though. Can any of you verify that?
superfury
Oldbie
 
Posts: 1824
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: Finding bugs in 8086-80386 emulation core?

Postby vladstamate » 2017-8-25 @ 14:45

superfury wrote:Don't have a real 2/386, though. Can any of you verify that?

Don't mind trying it for you on either a 286 or 386. However the code you describe while not very complicated is not trivial to write either. It requires

0) a VGA card
1) set up protected mode (different in 286 vs 386)
2) set up 16bit segment type (for 386)
3) set up all the segment descriptors ( you need the one in VRAM as well as the code segment)
4) Set up VGA to have video write mode 1
5) set up a GP handler that reads from VRAM and does some CMPSB code
6) Have a way to report all this out (how? can you still use INT 21h to print stuff out in protected mode?)

However if we had a program like this (a framework for entering PM and doing tests) we could definitely use it for other purposes in testing emulators.
User avatar
vladstamate
Oldbie
 
Posts: 566
Joined: 2015-8-23 @ 01:43

Re: Finding bugs in 8086-80386 emulation core?

Postby superfury » 2017-8-25 @ 21:04

1) You could just set up 16-bit protected mode, which should be the same on both(leaving the 80286 undocumented bits cleared).
2) VRAM isn't needed: can be done from real mode after resetting.
4) Just a few register writes before entering the NOP-filled segment. All but post-GP can be done from (un)real mode.
5) The #GP handler can simply save the interesting data from VRAM to a safe location and reset the CPU to real mode, then report the results after returning from the reset(the BIOS should support that?). No protected mode is required, as it's a pseudo-GP handler in real mode(limit broken in (un)real mode should do that too, it doesn't magicallty enter protected mode).

That should roughly be it(unless I've made some mistake answering those questions).
superfury
Oldbie
 
Posts: 1824
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: Finding bugs in 8086-80386 emulation core?

Postby superfury » 2017-9-05 @ 08:16

I've just fixed a bug in the 8042 PS/2 controller, where the 0xDD and 0xDF commands had their meanings switched(0xDD disabled the A20 line, while 0xDF enabled it, which is supposed to be reversed).

Now the first protected mode(PIQ flush) JMP tries to load the descriptor from it's correct address in physical memory(segment 0x110, offset 0x09BB as the JMP(opcode 0xEA) implies).
The descriptor address resolves to address 0x00110110. It passes through the A20 line unmodified(which is corrected now).

It then resolves into the modified memory bank of physical memory B0110 by the memory controller itself(which applies the A0000-FFFFF bank to be removed in physical memory, removing the memory of that area, effectively moving the 1MB+ memory back to the A0000 address(thus moving the UMA to the end of physical memory). So the memory remapping works without problems.

The descriptor that's loaded contains only 0x00 bytes, thus causes a #NP(Not Present) fault(return point 1170:09B6). Thus interrupt 0xB is started.
The 0xB interrupt handler resolves to address 0x120058 in linear memory(IDT is at 0x120000).
The interrupt handler is also an empty handler(filled with 0x00 bytes). Thus another #NP is faulted, which resolves to a Double fault interrupt.
The Double fault handler also isn't present, which causes the CPU to triple fault, resetting the CPU and rebooting the machine.

Anyone knows why the GDT/IDT aren't pointing to valid tables? Why are they empty?

Is the #NP being faulted when the present bit isn't set correct?

Edit: I've just logged the entire 1MB+ memory accesses when runnning WIN.COM(of Windows 3.0) on the Compaq Deskpro 386 machine emulation. The only 0x0012XXXX addresses popping up in the log are the reads from RAM just before the triple fault(the invalid 00120058-"5F and 00120040-"47, all containing 0x00 data). The GDT entry that's loaded into CS(selector 0x0110) is at 0x110110-0x110117, which also contains 0x00 values.

The entire log of 0x100000+ memory accesses booting Windows 3.0:
https://www.dropbox.com/s/gdbxztoumfrt1 ... 9.zip?dl=0

So that means a problem in HIMEM.SYS moving data to high memory?
superfury
Oldbie
 
Posts: 1824
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: Finding bugs in 8086-80386 emulation core?

Postby superfury » 2017-9-05 @ 10:26

I've enabled the /testmem:ON parameter on MS-DOS 6.22's HIMEM.SYS. It now tells me it detects unreliable memory at address 0x100000h. So there's a protected mode/extended memory problem here? The A20 line should be enabled, thus not causing problems. But placing a breakpoint on the protected-mode segment loading(loading a segment descriptor) doesn't get triggered? So it's not even entering protected mode to test the extended memory and use the proper extended memory DS/ES mapping? Maybe a problem in real mode segment exceptions past 0xFFFF(which SHOULD be triggered)?
superfury
Oldbie
 
Posts: 1824
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: Finding bugs in 8086-80386 emulation core?

Postby superfury » 2017-9-05 @ 12:50

I've tried to compare the program flow of the MS-DOS 6.22 HIMEM.SYS with the one at http://cd.textfiles.com/1stcanadian/uti ... /himem.asm , but for some reason it doesn't match?

debugger.log
Full debugger log with a segment filter on the logged program.
(256.58 KiB) Downloaded 2 times


Can anyone see what's going wrong? It also doesn't seem to enter protected mode in any way, according to the breakpoints I've set in the emulator?
superfury
Oldbie
 
Posts: 1824
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: Finding bugs in 8086-80386 emulation core?

Postby superfury » 2017-9-05 @ 15:39

I've made a log of the 80386 emulation (@16MHz) running the HIMEM.SYS that's with MS-DOS 6.22(from the virtual hard disk). Somehow it doesn't seem to enter protected mode for the extended memory area test at all before giving up on the 0x100000 address, giving an error saying that the RAM is faulty?

The log(when extracted) is pretty large, though(about 18GB in total, 598MB compressed with 7-zip), so I'm uploading that one externally:
https://www.dropbox.com/s/cdanx9bl5a1ds ... 14.7z?dl=0

Can anyone see why the HIMEM.SYS is failing? Why is it erroring on the 1MB+ HMA?
superfury
Oldbie
 
Posts: 1824
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: Finding bugs in 8086-80386 emulation core?

Postby peterferrie » 2017-9-05 @ 19:29

himem uses unreal mode for testing memory. The only time that it ever enters protected mode is to load the selectors before returning to real mode to do everything else, including memory copies.
peterferrie
Oldbie
 
Posts: 575
Joined: 2008-5-08 @ 21:54

Re: Finding bugs in 8086-80386 emulation core?

Postby superfury » 2017-9-05 @ 21:00

That's strange then: Megarace runs in unreal mode as well(afaik), but runs fine.

When putting breakpoints on UniPCemu's segment descriptor loading, I see it being loaded many times during BIOS POST, but not when executing HIMEM.SYS while booting. And I literally mean not a single descriptor being loaded or fault being raised(protection faults, not looking at normal faults(INT 6-0)) before it gives up and tells the user(through the VGA) that the memory at 0x100000 is faulty.

Why isn't the #GP it would use when accessing the HMA(offset 0x100000) being triggered? Are the offsets being calculated correctly(e.g. ESI/EDI being loaded correctly)? The earlier dump(two posts back) did show it setting up data at DS:AAA, but that isn't any interrupt in the IVT afaik? What's going wrong?
superfury
Oldbie
 
Posts: 1824
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: Finding bugs in 8086-80386 emulation core?

Postby superfury » 2017-9-07 @ 12:20

I've just tried to run this freeware tool: Extended Memory Test V3.0, from https://archive.org/details/msdos_TESTEXT3_shareware to verify XMS memory emulation.

When I try to start it it tells me that it needs a mono/color video card capable of 80x25, even though a VGA is installed? The same happens with the ET3000/ET4000 cards.
superfury
Oldbie
 
Posts: 1824
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: Finding bugs in 8086-80386 emulation core?

Postby superfury » 2017-9-07 @ 14:39

Also just tried the Windows 95 setup again. It keeps returning to and raising Bound Exceptions, which return to the Bound Instruction, infinitely faulting? Anyone has an idea why that might be happening?

Edit: The bound instruction compares 0x4778 with bounds between 0(low bound) and 0(high bound)? That cannot be right? So an array with zero size? Or the instruction that fills it isn't writing it's data back properly?

Edit: The offset of the BOUND data is 0x10AA0? Is that correct? It's then truncated to be a correct 16-bits offset(0AA0h)? Or is that incorrect behaviour? Or is this only truncated on 80(1)86 CPUs? What about 80286 CPUs and 80386+ CPUs?

BP=C2B2h and DI=477Ah, DISP8=74h. Thus BP+DI+DISP8=C2B2+477A+74=10AA0. That offset is truncated to 16-bits to get 0AA0 as the effective offset. The segment is 0x1BFD. So the offset that contains the comparing offsets is 1CA70? And the second word is at 0x1CA72? The entire four bytes contain 0x00000000. So it generates a Bounds Check fault, infinitely faulting the setup, as the faults handler returns to the BOUND instruction itself.

Why is this happening? Are the values in BP and DI incorrect? It looks like that's true, seeing as the BP+DI add up to past the 16-bit offset? Anyone knows how these values are calculated within the Windows 95 setup?
superfury
Oldbie
 
Posts: 1824
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: Finding bugs in 8086-80386 emulation core?

Postby superfury » 2017-9-12 @ 14:01

Just tried HIMEM.SYS again. Now it triple faults because of an interrupt (double faults->triple faults because of a NULL IDT) after faulting on a PUSH AX with a non-present SS descriptor(causing #GP)?

That shouldn't be possible, does it?
Edit: Perhaps a invalid 80286 LOADALL? Normal loading of the NULL segment prevents this?
superfury
Oldbie
 
Posts: 1824
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: Finding bugs in 8086-80386 emulation core?

Postby superfury » 2017-9-12 @ 19:38

Indeed, the 80286 had a LOADALL union/struct alignment and size issue. The LOADALL now runs properly(is even called twice), but then hangs during the HIMEM.SYS due to an #UD 80386+ 0F opcode 82h? Which is a 80386+ jcc instruction? It's the MS-DOS 6.22 HIMEM.SYS I'm testing memory with(/testmem:on)?

Is there a CPU requirement for the 6.22 HIMEM.SYS?
superfury
Oldbie
 
Posts: 1824
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: Finding bugs in 8086-80386 emulation core?

Postby Jepael » 2017-9-12 @ 23:01

superfury wrote:Is there a CPU requirement for the 6.22 HIMEM.SYS?


It should detect CPU and use 286 or 386 specific functions based on detected CPU.
Jepael
Oldbie
 
Posts: 1078
Joined: 2005-6-15 @ 19:28
Location: Finland

Re: Finding bugs in 8086-80386 emulation core?

Postby superfury » 2017-9-13 @ 09:09

So it's incorrectly detecting the CPU? Is it known how the CPU is detected with HIMEM.SYS? It does use the 80286-only LOADALL instruction(opcode 0F05), so it's probably detecting the 80286? Then why is it trying to execute an 80386+ 0F instruction during the memory testing?

Edit: Currently implementing the 80386 variants of the 80286 cycle timings from the manual ( https://pdos.csail.mit.edu/6.828/2006/r ... 86/c17.htm ). I've currently added and modified the 80386 records up to the equivalent of Page 3-50 of the 80286 manual's timings(adding to and modifying(a copy of the 80286) timings records for 80386 timings). So still gotten the new 80386 instructions, processor state(HLT, STI etc., as well as stuff like LMSW, MOV CRn etc.) instructions, some 5 logic instructions(AND,TEST,OR,XOR,NOT), string instructions, IN/OUT instructions(still need to extend the exception handling to support it's specific IOPL timings) and control transfer(JMP, Jcc) and BOUND. All other instructions are properly converted to use 80386 timings already:D
superfury
Oldbie
 
Posts: 1824
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: Finding bugs in 8086-80386 emulation core?

Postby superfury » 2017-9-14 @ 12:51

Implemented the 80386 string instruction timings(except INS/OUTS instructions), Page 2-52, Page 2-53, Page 2-54, disabled interrupt task switch timings(to be reimplemented on the 80386 task switching itself) and LSL only in byte granularity(still need to do page granularity, requiring slight instruction modification to detect).

The timings reported by MIPS are getting more accurate, but strangely enough, the integer instruction timings are still only 50%? The integer instruction should have been modified to run at the correct cycle counts?

433-80386 emulation getting more cycle-accurate_integer and processor control and jump instructions implemented.jpg
MIPS report within the current commit's 80386 core.
superfury
Oldbie
 
Posts: 1824
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: Finding bugs in 8086-80386 emulation core?

Postby superfury » 2017-9-14 @ 17:55

I've just tried debugging the x86 modr/m addressing mode by placing a breakpoint at the point the 32-bit modr/m decoding is handled. Even when booting and running HIMEM.SYS' 1MB+ memory check(which SHOULD use unreal mode afaik?), no 32-bit address decoding is used? I see the 32-bit decoder being called, but since the address size is 16-bit, it redirects itself to the 16-bit decoder(the same in reverse happens when a 16-bit decoder is called while the address size is 32-bit)? The address size is dependent only on the Default bit(in the CS segment descriptor) and the address size override(whether it's used or not for the current instruction).

I see this happening once, and only while running HIMEM.SYS, after which it gives up on addressing saying that the 1MB address is broken(it's validation failed)? It's decoded instead as an 16-bit address(r/m), with 32-bit register(reg)? It has an operand size(66h) and ES(26) override. It's opcode 8B(MOVW reg,r/m). It decodes a a [SI] address. Thus decoding as address 25F:5A4A.

The next instance is opcode 89h(MOV r/m32,reg32), r/m16 being [BP+00FC]? This results in the address 25F:5A36. Next is 25F:5A36 again. The 25F:5A50. This goes on and on. I never see ANY access using a 32-bit r/m address? Also the code segment is never triggered to use a 32-bit default bit? Is HIMEM.SYS even entering protected mode?

Edit: Strangely enough, I don't even see it raise a #GP fault when checking memory(which I also assume it's trying to check the 1MB address?)?
superfury
Oldbie
 
Posts: 1824
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: Finding bugs in 8086-80386 emulation core?

Postby superfury » 2017-9-18 @ 18:32

I've just finished implementing all 80386 instructions in UniPCemu's cycle-information. :D

The timings are now a lot closer, but for some reason some parts(like integer math) are still too slow, according to MIPS(two are very close, at x1.01 and x1.00)?

433-80386 timings fully implemented in the timing table.jpg
80386 timings fully implemented in the 286+ timings table.


Although, the 80386 0F instruction core itself still needs some adjusting to fully use the BIU for all memory accesses(which will slow it down some more, due to memory accesses currently taking 0 cycles for those instructions). Otherwise, it's theoretically fully cycle accurate(except for protected mode stuff like descriptor loading from memory etc., paging itself and task switching, which still operates without the BIU(although task switching should be relatively easily implemented, due to it being seperated from normal instructions already, within it's own EU unit, essentially)).
superfury
Oldbie
 
Posts: 1824
Joined: 2014-3-08 @ 11:25
Location: Netherlands

PreviousNext

Return to PC Emulation

Who is online

Users browsing this forum: No registered users and 1 guest