I think I know what the problem is.
Believe it or not, those DOS device drivers enter protected mode, load
some segment registers with a 32-bit data segment, and return to real
mode.
The result is that the code segment still is the same, but the data
segment register's limit is 4GB. This is done because it is faster.
This works fine with Bochs itself, but I'm guessing Plex86 uses v86
mode. It's not compatible with v86 mode, because in that mode, the
segment registers always have a limit compatible with real mode.
This means either the code needs to be emulated, OR, it needs to be run
in 16-bit protected mode, in which case, if all segment registers in the
GDT have a DPL < 3, then, since in v86 mode CPL = 3, a fault will be
generated on ALL segment register loads. The code segment can be made to
fault by clearing the readable attribute in it. THen segment register
loads need to be emulated (the faults will be self-trapping), and, if
the code is run in the non-guest memory space (I haven't checked the
sources and I can't get DocBook to work because I'm trying to get a job
and am working on personal projects...), then CS needs to be emulated.
This can be done by replacing the CS segment override with DS: and then,
making the DS descriptor correspond to the v86 mode DS, unless a segment
override is done; in that case, just replace the segment override with
DS: in the code, and then make the DS descriptor correspond to the v86
mode CS for the duration of the instruction: I'd set TF.
Anyways, this way this so-called "big real mode", "unreal mode", "flat
real mode", and whatever else it is called, that DOS uses, can be
implemented.
Note that reloading a segment register in real mode does NOT exit big
real mode: it's only protected mode where reloading a segment register
updates the hidden part of the segment register. Once entering big real
mode, DOS can be sure it stays there until a program is executed. This
is bad a problem for 32-bit TSRs, but in general there's no problem if
the TSRs support VCPI (DJGPP TSRs do support VCPI because they are DPMI
compliant and CWSDPMI supports VCPI).
Also, if that is all too much work, this is what can also be done: hook
interrupt 0Ch which I believe is the pseudo-exception that gets
generated when v86 mode tries to write past 0xFFFF:0xFFFF, the same way
real mode does when "big real mode" is NOT enabled; then, make the
interrupt 0Ch exception handler emulate the instruction. That's the
cheesy way. I think VMWare did that. VMWare sucks. I like Plex because,
by being open-source, it has extensive capabilities to simplefy software
development and debugging.
BTW, I'm making a little Mini-OS, like the kind Kevin mentioned in his
paper. Non-complient OSes will run at PL3. I'll enable PVI when the OS
running thinks its CPL is <= IOPL, and clear it when that is not the
case. It won't be as good as Plex, but it will suit my purposes. I'll
then make Linux and FreeBSD 'compliant'. Only one 'non-compliant' OS
will be able to run at a time, but many 'compliant' systems can run at a
time. This is because I don't want to emulate EVERYTHING, including my
S3 video card. Comeon, that's just silly. VGA emulation, OK, but SVGA?
Huhgh.
There will be lots of caveats: for example, SGDT and SIDT will be
allowed to run and will not return the values loaded by LGDT and LIDT
(which fault). However, one caveat will NOT exist: SMSW in v86 mode will
report that bit 0 of CR0 is clear (it will fake real mode). Also it will
do what I explained above, simulating real mode via 16-bit protected
mode, when necessary. Pretty much everything will run at full speed, but
everything will run at PL3 and this has some caveats like SGDT, SIDT. I
can make all segment register reloads fault, including CS segment
register reloads: to do this, just load CS and then clear the present
bit for CS in the GDT via paging.. I wont use hardware task switching,
but for exception handling to work correctly, I will do an LTR
instruction (so that it can find SS0 and ESP0). I have figured out how
to make VERR and VERW generate a fault, but SGDT and SIDT will just be
caveats.
WS: "Anyways, I must appologize for that VGABIOS thing. I really reverse
engineered an existing VGA BIOS to make it, and, hence, can't really
show it to you guys. Want to know something freaky? After reverse
engineering the Win9x boot sector, via Bochs (I got it to work under
DJGPP in DOS), guess what I found out? For FAT12/FAT16 disks (not
FAT32), the boot sector FIRST checks all the root directory entries for
JO.SYS, and THEN, if none is found, THEN checks for IO.SYS. Wierd
shit!!! There are 10 bytes that are added to the boot sector to make
this happen, and they are DEFINITELY there on purpose. Methinks those
other security flaws (internet...) are there on purpose too."
WS/ws
Wolfgang Schwotzer wrote:
>
> Some days ago I had a look on plex86. It's amazing to see DOS booting
> just in a separate dos window within linux!
>
> Playing around with the config.sys I got repeatedly exceptions.
> On a real DOS PC the floopy still boots fine.
>
> The config.sys starts with:
>
> DOS=HIGH,UMB
> SWITCHES=/F
> BREAK=ON
> DEVICE=HIMEM.SYS
> DEVICE=EMM386.EXE
> ...
>
> it produces the following logfile:
>
> Processing command-line options
> Opening VM (/dev/plex86)
> Processing config file ../conf/msdos...
> Allocating 16MB of physical memory in VM
> Mapping virtualized physical memory into monitor
> Zeroing virtualized physical memory
> Mapping monitor print buffer into user mem.
> bochs: ips = 1000000
> unmapped_c::init: IGNORING unmapped ports
> bochs: [cmos] Setting initial clock to: Tue Jan 30 22:33:33 2001
> bochs: bx_options.floppy_command_delay = 500
> vga construct static
> bochs: font_width = 8
> bochs: font_height = 16
> bochs: default_depth = 16
> bochs: waiting for MapNotify
> bochs: MapNotify found.
> bochs: vga: interval=200000
> vga init called
> bochs: TTY not used, serial port is not connected
> ROM: loading image '../bios/BIOS-plex86-current' @ 0xf0000 (65536 bytes)
> ROM: loading image '../bios/VGABIOS-elpin-2.40' @ 0xc0000 (32768 bytes)
> Setting prescan depth to 2
> prescan on
> Processed 63 lines of config file '../conf/msdos'
> Initializing plugins
> Running VM
> bochs: timer0 period set to 18 hz
> bochs: CMOS: write reg 14h: value = 05h
> bochs: vga: io write: 3cf: reg 05: value = 10h
> bochs: vga: io write: 3da: ignoring: feature ctrl & vert sync
> bochs: *** io read 3c5 case 1: sequencer clocking mode
> bochs: vga: io write 3c0: address mode reg=16
> bochs: vga: io write 3c0: address mode reg=17
> bochs: vga: io write 3c0: address mode reg=18
> bochs: vga: io write 3c0: address mode reg=19
> bochs: vga: io write 3c0: address mode reg=20
> bochs: *** io read 3c5 case 1: sequencer clocking mode
> bochs: vga: io write: 3cf: reg 05: value = 10h
> bochs: *** io read 3c5 case 1: sequencer clocking mode
> floppy io: cylinder request != current cylinder
> floppy io: cylinder request != current cylinder
> floppy io: cylinder request != current cylinder
> floppy io: cylinder request != current cylinder
> floppy io: cylinder request != current cylinder
> floppy io: cylinder request != current cylinder
> bochs: vga: io write: 3cf: reg 05: value = 10h
> bochs: vga: io write: 3da: ignoring: feature ctrl & vert sync
> bochs: *** io read 3c5 case 1: sequencer clocking mode
> bochs: vga: io write 3c0: address mode reg=16
> bochs: vga: io write 3c0: address mode reg=17
> bochs: vga: io write 3c0: address mode reg=18
> bochs: vga: io write 3c0: address mode reg=19
> bochs: vga: io write 3c0: address mode reg=20
> bochs: *** io read 3c5 case 1: sequencer clocking mode
> bochs: vga: io write: 3cf: reg 05: value = 10h
> bochs: *** io read 3c5 case 1: sequencer clocking mode
> floppy io: cylinder request != current cylinder
> floppy io: cylinder request != current cylinder
> floppy io: cylinder request != current cylinder
> floppy io: cylinder request != current cylinder
> ::write_virtual_checks EXCEPTION: seg=0 0:100000 + 4
>
>
> floppy io: cylinder request != current cylinder
> floppy io: cylinder request != current cylinder
> floppy io: cylinder request != current cylinder
> floppy io: cylinder request != current cylinder
> floppy io: cylinder request != current cylinder
> floppy io: cylinder request != current cylinder
> floppy io: cylinder request != current cylinder
> floppy io: cylinder request != current cylinder
> floppy io: cylinder request != current cylinder
> floppy io: cylinder request != current cylinder
> ::read_virtual_checks EXCEPTION: seg=0 F4C:A6D0 + 2
>
> ::read_virtual_checks EXCEPTION: seg=0 F4C:A6D0 + 2
>
> ::read_virtual_checks EXCEPTION: seg=0 F4C:A6D0 + 2
>
> ::read_virtual_checks EXCEPTION: seg=0 F4C:A6D0 + 2
>
> ::read_virtual_checks EXCEPTION: seg=0 F4C:A6D0 + 2
>
> ::read_virtual_checks EXCEPTION: seg=0 F4C:A6D0 + 2
>
> ::read_virtual_checks EXCEPTION: seg=0 F4C:A6D0 + 2
>
> ....
>
> bochs: panic, POWER button turned off.
> Shutting down plugins
> bochs: Note: X11: bx_gui_c::exit() not implemented yet.
> Unmapping guest physical memory.
> Unmapping monitor print buffer.
> Tearing down VM
> Closing VM
>
>
> System config:
>
> Linux 2.2.18
> AMD Atlon 900 MHz
> 128MB RAM
> Current CVS sources
>
> Any ideas?
>
> --
> Sent through GMX FreeMail - http://www.gmx.net