DPMI is Lutz's Baby. It's a really important part of the Emulator as far as we are concerned, since it will allow us to run so many more programs and, most importantly, bcc. This is the one thing that the WINE developers want that we haven't been able to give them.
If you think you can help .... "Away you Go!" (Sorry to those non-UK folks ... Thats a reference to a UK kids sports programme from my youth ... anyway ... enough of this banter. You'll be wanting to know that this is all about DPMI ...)
These are the functions defined in dosext/dpmi/dpmi.c.
This function is similar to the vm86() syscall in the kernel and switches to dpmi code.
This routine is used for running protected mode hardware interrupts and software interrupts 0x1c, 0x23 and 0x24. run_pm_int() switches to the locked protected mode stack and calls the handler. If no handler is installed the real mode interrupt routine is called.
This is the default CPU exception handler. Exceptions 0, 1, 2, 3, 4, 5 and 7 are reflected to real mode. All other exceptions are terminating the client (and may be dosemu too :-)).
This routine switches to the locked protected mode stack, disables interrupts and calls the DPMI client exception handler. If no handler is installed the default handler is called.
This is the brain of DPMI. All CPU exceptions are first reflected (from the signal handlers) to this code.
Exception from nonprivileged instructions INT XX, STI, CLI, HLT and from WINDOWS 3.1 are handled here.
All here unhandled exceptions are reflected to do_cpu_exception()
Note for cpu-emu: exceptions generated from the emulator are handled here. 'Real' system exceptions (e.g. from an emulator fault) are redirected to emu_dpmi_fault() in fullemu mode
We are caching ldt here for speed reasons and for Windows 3.1. I would love to have an readonly ldt-alias (located in the first 16MByte for use with 16-Bit descriptors (WIN-LDT)). This is on my wish list for the kernel hackers (Linus mainly) :-))))))).
DPMI is designed such that the stack change needs a task switch. We are doing it via an SIGSEGV - instead of one task switch we have now four :-(. Arrgh this is the point where I should start to include DPMI stuff in the kernel, but then we could include the rest of dosemu too. Would Linus love this? I don't :-((((. Anyway I would love to see first a working DPMI port, maybe we will later (with version 0.9 or similar :-)) start with it to get a really fast dos emulator...............
NOTE: Using DIRECT_DPMI_CONTEXT_SWITCH we avoid these 4 taskswitches actually doing 0. We don't need a 'physical' taskswitch (not having different TSS for us and DPMI), we only need a complete register (context) replacement. For back-switching, however, we need the sigcontext technique, so we build a proper sigcontext structure even for 'hand made taskswitch'. (Hans Lermen, June 1996)
dpmi_control is called only from dpmi_run when in_dpmi_dos_int==0
Hopefully the below LAR can serve as a replacement for the KERNEL_LDT, which we are abandoning now. Especially the 'accessed-bit' will get updated in the ldt-cache with the code below. Most DPMI-clients fortunately _are_ using LAR also to get this info, however, some do not. Some of those which do _not_, at least use the DPMI-GetDescriptor function, so this may solve the problem. (Hans Lermen, July 1996)
Here we handle all prefixes prior switching to the appropriate routines The exception CS:EIP will point to the first prefix that effects the the faulting instruction, hence, 0x65 0x66 is same as 0x66 0x65. So we collect all prefixes and remember them. - Hans Lermen
Should we really care for the Memory info?
We shouldn't return to dosemu code if IF=0, but it helps - WHY? */
we should not change registers for hardware interrupts */
Simulate Local Descriptor Table for MS-Windows 3.1 must be read only, so if krnl386.exe/krnl286.exe try to write to this table, we will bomb into sigsegv() and and emulate direct ldt access
These are the functions defined in dosext/dpmi/msdos.h.
This function is called before a protected mode client goes to real mode for DOS service. All protected mode selector is changed to real mode segment register. And if client\'s data buffer is above 1MB, necessary buffer copying is performed. This function returns 1 if it does not need to go to real mode, otherwise returns 0.
This function is called after return from real mode DOS service All real mode segment registers are changed to protected mode selectors And if client\'s data buffer is above 1MB, necessary buffer copying is performed.