mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-10-13 17:48:10 +08:00

movement code resolved one of the BSODs that can happen during the setup phase. It turns out the other crash, related to the dynamic core, can be overcome if you're patient and willing to run the setup phase with core=normal (it takes a LONG time though!). Added document on what DOSBox did wrong and why it affected Windows NT 3.1 and Windows ME the way it did.
96 lines
6.1 KiB
Plaintext
96 lines
6.1 KiB
Plaintext
Assumptions made in DOSBox that caused crashes in Windows NT and Windows ME.
|
|
|
|
You may remember on the forums or from the build log my complaint that in
|
|
Windows NT 3.1, moving the mouse caused an immediate system crash.
|
|
|
|
Well, one day, I noticed that at the BOOTLDR screen, the protected mode
|
|
memory manager would also report a page fault on mouse movement. Even if
|
|
BIOS PS/2 emulation was turned off. Even if the AUX port was turned off.
|
|
|
|
At some point a value that showed up in the page fault dump jumped out
|
|
at me: Linear address 0x449 AKA the "current video mode" value of the BIOS
|
|
data area.
|
|
|
|
Now what did that have to do with the mouse?
|
|
|
|
It turns out that when DOSBox processes mouse movement from the SDL library,
|
|
it calls INT10_SetCurMode() to ensure that the CurMode pointer reflects the
|
|
current (BIOS) video mode so that INT 33h emulation can properly map the
|
|
mouse cursor. One of the things it does is read the BIOS data area using
|
|
real_readb(). Now, real_readb() like most memory I/O functions in DOSBox
|
|
are beholden to the emulated page tables, so if the page is NOT PRESENT,
|
|
that action causes a page fault instead! This is why moving the mouse, even
|
|
when AUX emulation and INT 15h mouse emulation were disabled, caused Windows
|
|
NT to crash!
|
|
|
|
So it was at this point I made several key modifications to DOSBox: When
|
|
booting a guest OS, it disables INT 33h emulation entirely (INT 33h is an
|
|
API provided by DOS or DOS TSRs and is never expected to be there at boot
|
|
time). Then, I modified the mouse movement handler to call INT10_SetCurMode()
|
|
if and only if emulating INT 33h.
|
|
|
|
Having made these modifications, Windows NT is now able to boot into it's
|
|
graphical desktop without crashing, and the mouse cursor is usable.
|
|
|
|
Apparently this fix also resolved one of the major BSOD crashes at setup time
|
|
in Windows ME. The initial System Configuration setup phase no longer BSODs
|
|
with a hung mouse cursor (but it still crashes DOSBox at some point when the
|
|
dynamic core issues a floating point instruction that causes a page fault).
|
|
|
|
To explain why Windows NT and ME had this problem while DOSBox was able to
|
|
get away with doing this in Windows 3.1, 95, and 98, you need to understand
|
|
how these Windows environments mapped the page tables, which I learned from
|
|
testing that region of memory with my experimental DOSLIB and DOSLIB2 code
|
|
on Hackipedia.org.
|
|
|
|
Linear address mapping (first 64KB of virtual memory) and how it's mapped:
|
|
|
|
Environment | 0x0000-0xFFFF are mapped as | Comments
|
|
---------------------+-----------------------------+----------------------
|
|
Windows 3.0 | Read/write |
|
|
| |
|
|
Windows 3.1 | Read/write | Win32s 32-bit subsystem catches NULL pointer errors
|
|
| | regardless by creating 32-bit code & data segment
|
|
| | with base=0xFFFF0000 and limit=0xFFFFFFFF in other
|
|
| | words shifting virtual vs. linear up by 64KB to
|
|
| | help cover it up.
|
|
| |
|
|
Windows 95 | Read/write | Apparently Win95 removed the 64KB offset for Win32
|
|
Windows 95 SP1 | | programs. Both Win16 and Win32 can address VMA 0
|
|
Windows 95 OSR1 | | as valid memory! In other words, NULL is a valid
|
|
| | pointer in Win32, and it's even writeable! Yikes!
|
|
| |
|
|
Windows 95 OSR2 | Read only | Finally, writing to NULL causes an exception as it
|
|
Windows 98 | | should in Win32 land. But reading through a NULL
|
|
Windows 98 SE | | pointer still works.
|
|
| |
|
|
Windows ME | Not present | Finally, right at the end of the 9x line, Microsoft
|
|
| | got around to making sure NULL reads or writes cause
|
|
| | an exception (like they would in any normal OS). But
|
|
| | the restriction is apparently only applied to Win32.
|
|
| | Win16 can still read linear memory address 0.
|
|
|
|
NOTE: Despite linear memory 0x0000-0xFFFF being read/write, Win16 applications will crash as expected
|
|
dereferencing a NULL pointer because in Win16, a NULL pointer 0x0000:0x0000 (segment=0 offset=0)
|
|
contains an invalid segment value. BUT, if the same program were to allocate a protected mode
|
|
selector that refers to linear memory address 0x00000000, that pointer would be readable/writeable
|
|
without any exceptions whatsoever.
|
|
|
|
So when DOSBox's mouse movement code issues real_readb(0x40,0x49), it works it's way through the OS
|
|
page tables and can cause a page fault. The only reason it didn't in Win 3.1 and 9x was because those
|
|
versions of Windows were DOS-oriented and left the mapping open for performance reasons. And with
|
|
Windows 98, DOSBox reading the BIOS data area doesn't clash with Win98's write protecting the pages.
|
|
It's not until Windows ME maps out the page entirely that DOSBox has a problem with causing page
|
|
faults in the way described.
|
|
|
|
Also stating the obvious: Windows NT doesn't map anything down there at all 99% of the time (the exception
|
|
being the NTVDM.EXE process for virtual 8086 mode), which is why moving the mouse caused the crash.
|
|
|
|
In Windows ME, this problem made itself obvious when, after installing itself, it boots up
|
|
for the first time and runs the Setup phase of setting up the Control Panel, Programs on the
|
|
start menu, etc. and then finally, the System Configuration phase. Prior to the bugfix, this
|
|
phase would eventually get to a driver load or test that causes a BSOD, one that's obviously
|
|
related to the mouse. You can hit ENTER to recover from the BSOD, but the cursor will no longer
|
|
respond to movement (the setup phase at that point will be stuck as well).
|
|
|