VOGONS


First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've been running the latest test386.asm commit against UniPCemu's improved protection and instruction emulation, but now I strangely see it crashing on the very first or second paging test?

It's never done that, as far as I can remember?

Perhaps the cause is somewhere else? I see the instruction causing the Page Fault trying to move 0xDEADBEEF into the memory at logical address 49F000?

Anyone knows why said problem occurs?

Edit: Turning on the DEBUG constant(set to 1), I get in my logs(UniPCemu itself adds the timestamp in front of it):

00:05:01:78.02720: P SUPER W,   SUPER W,   SUPER R, #PF 

So the problem is a non-present access somehow, which it doesn't like?

Edit: Just found a little bug that made the Paging unit think there were writes to memory when there were actually only reads(due to the new paging vs segmentation check being split).
Edit: Said bugfix seems to have fixed said checks. They are passing correctly now. 😁

Now the next check(12h segmentation checks?) fails.
Edit: Whoops. The segmentation checks that check for read/write/execute permissions to fault or not when accessing it's contents(e.g. CS:xxxx, checking the xxxx read/write against the descriptor) wasn't properly protected against the new bits that were added(the same problem as with the paging unit above). Thus reads/writes/executes were incorrectly throwing and not throwing faults.

Now it progresses onward to the next text, which(guess what) fails(test 1Ah in this case).

Attachments

  • Filename
    debugger_test386_pagefault.zip
    File size
    259.17 KiB
    Downloads
    33 downloads
    File comment
    test386.asm POST 11h running and erroring out on Page fault tests.
    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 1 of 6, by superfury

User metadata
Rank l33t++
Rank
l33t++

It now seems to fail on ENTER 1,0 not page faulting, as far as the comment just before it tells? But no page fault is thrown? It's logical address is 21000h(at SS:E$P=17:1000)?

Edit: When loading the PDE and PTE, they are loaded as 2027(PDE) and 21007(PTE). Those are both user-level privileges, with full write access and being present? But the PTE should have been updated immediately before that with:

	updPageFlags 0x1000|(TEST_BASE>>12), PTE_SUPER_W

So it should have become a supervisor page? But somehow it isn't a supervisor page?

Edit: The enter instruction itself references said address as:
PDE=2027
PTE=21007

So clearly, the PTE flags aren't updated correctly.
So 9475(EIP with DEBUG set to 1) onwards isn't doing it's job correctly(making the PTE flags supervisor, writable).

Anyone can see what's going wrong?
Assembler generated ROM of test386.asm assembly output(segment 10h in running):

Filename
test386.lst.txt
File size
1.68 MiB
Downloads
34 downloads
File license
Fair use/fair dealing exception

Code running:

Filename
debugger_test386_missingenter_pagefault.zip
File size
11.58 KiB
Downloads
34 downloads
File license
Fair use/fair dealing exception

$dit: Luckily the L*S instruction disassembly is just incorrect, not updating the modrm parameter disassembly correctly due to getting 0 instead of 16/32 on it's second parameter(operand size for modr/m disassembly). %he instruction executes correctly, as can be seen by the resultant register values and segment desceiptor loaded(pointing segment to 1000h(the PDBR base address).

Edit: It's updating the entry at logical and physical location 2080h(seems to be direct-mapped?)...
Edit: Looking at the page table initialozation, I can see that 0x1000 has the PDE, whkle 0x2000 has the only PTE(only 1MB mapped).
The PDE is correctly pointing to the PTE at 0x2000, so that's fine.
Now it's updating the PTE at 2080, so the 80h/4=20h PTE(logical memory 0x20000). So the table update works fine, it properly updates the entry for 0x20000?

But wasn't the enter instruction trying to use 21000(20000+1000) for it's PUSH EBP? ESP was 1004, decremented to 1000h for the pushed EBP. That address is written. Then, it just substracts 1 from ESP(bringing ESP to the changed page) and finishing the instruction? Said location isn't accessed or checked against paging, is it?

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

Reply 2 of 6, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just added the paging check for writes to the byte at SS:[SP] after ENTER finishes on 80386+. Now test386.asm continues to EE again1 😁

Also noticed missing EBP state save durimg faults. Now EBP is properly restored during ENTER faulting.

Edit: All tests are passing without errors, including EE. So the only problems left are with protected mode itself?

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

Reply 3 of 6, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just found a bug in the BIU TLB: it was handling TLB translation requests for writes as reads instead. Although that shouldn't cause huge problems(since it's cached as writes already during earlier stages). But it's still incorrect.

Edit: Yay:/ Now the TLB translation hangs because of infinite TLB fetches on a kernel privilege write access? (W=0, U=0, D=1 when written into the TLB, W=1, U=0, D=1 when trying to tranzlate(which fails, repeating the TLB fetch)).

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

Reply 4 of 6, by superfury

User metadata
Rank l33t++
Rank
l33t++

After fixing the CPL checks to work properly, I now see test386.asm crashing on some strange stuff: it tries to execute a non-faulting test:

   384                              <1> .write_nofault:
385 0000766F C70500F04900EFBEAD- <1> mov [TESTPAGE_LIN], dword 0xdeadbeef
385 00007678 DE <1>
386 00007679 EB00 <1> jmp .continue
387 <1>
388 <1> .continue:
389 <1>
390 <1> ; if the fault happened in user mode switch back to ring0
391 0000767B F7C204000000 <1> test edx, PF_USER
392 00007681 7408 <1> jz .verify_bits
393 00007683 E876AAFFFF <1> call switchToRing0
394 00007688 5A <1> pop edx ; restore edx
395 00007689 59 <1> pop ecx ; restore ecx
396 0000768A 5E <1> pop esi ; restore esi

But the PDE(0x3005) and PTE(9F005) are both user-level, read-only, present pages. Thus the resulting privileges are: user privilege, read-only. The present bit faults first, so that passes it's test. Then it checks the read-only user privilege against CPL(0) and access(a write). CPL(supervisor) isn't checked against anything else than the U/S bit(which passes always in Supervisor mode). Then the read-only attribute is verified against the access(a write), which page faults(which shouldn't happen according to the source code)???

Anyone? What effect does the privilege level have on the read-only user privilege pages?

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

Reply 5 of 6, by superfury

User metadata
Rank l33t++
Rank
l33t++

Thinking about it, I can find the problematic one looking at the last reported EAX,EBX,EDX registers at 0010:7639.

The last one that's reported is test PDE=5,PTE=5,PF=82. So that's matching the following row:

   212 000074C0 050582              <1> db	PTE_USER_R,   PTE_USER_R,   PF_NOFAULT|PF_WRITE

But that's saying that a write to an user-mode page doesn't fault when executing a write? That doesn't match documentation, which says user-mode pages DO fault on writes when the combined rights are read-only?

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

Reply 6 of 6, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just tried Windows 3.0 with only HIMEM loaded on the 80386 emulation in real mode(/r switch). It errors out to hang with a Divide error now?
Edit: Turns out Windows 3.0 was just corrupted due to old CPU bugs when installing it. After reinstalling, it runs like a charm again(real mode checked only).
Standard mode gives the loading screen, then a permanent black screen(Black Screen of Death?)?

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