As previously mentioned, IBM’s OS/2 1.0 and 1.1 used the 286 LOADALL instruction, even on 386 and later processors which do not support it. This was typically solved by BIOS emulation. Now there’s more information about how OS/2 uses LOADALL.
Tracing OS/2 showed that LOADALL was used to implement the PhysToVirt DevHlp (Device Helper) API. The PhysToVirt function was documented in the OS/2 DDK; its function was to create a virtual address mapping for a (contiguous) buffer in physical memory.
PhysToVirt was used by device drivers when they needed to map physical memory. This might be memory on a device or a buffer in system memory provided by caller. Since the driver might execute in the context of any process, it was not necessarily able to use “normal” pointers. PhysToVirt created a temporary mapping (selector) pointing to the given physical memory. The documentation naturally made no mention of LOADALL, but it provided a very clear hint. The relevant paragraph is worth quoting in full:
“The device driver must not enable interrupts or change the returned segment register (ES or DS) before it has finished using the returned value. The value returned in the segment register has no physical meaning, so the caller of PhysToVirt should have no reason to examine it. While the pointer(s) generated by PhsToVirt are in use, the device driver may call only for another PhysToVirt. It may not call any other DevHlp routines, since they may not preserve the special ES/DS values.”
This text fairly clearly explains (without explicitly spelling it out) that the selector value did not correspond to the selector base and reloading the selector would change the base. Such situation is more or less completely unnecessary in protected mode (a temporary GDT selector would do the job), but it would have been very useful in real mode if the selector was obtained through LOADALL or a temporary switch to protected mode (386+ only, obviously).
The PhysToVirt documentation cautions that the API might switch to protected mode, but that does not appear to actually happen. Perhaps this was an earlier specification, or it might happen in specific cases.
With both OS/2 1.0 and 1.1, LOADALL was very often used if the DOS session was active and there was any disk transfer in the background (triggered by a concurrently executing OS/2 session), at least with a non-busmastering device such as a standard AT fixed disk drive.
The disk driver source code is available in the OS/2 DDK and there is a PhysToVirt call (through a wrapper called PhysToVirtESDI) right before executing REP INSW to read from a WD1003 style data port. What’s of course not visible in the DDK is that the PhysToVirt call might execute LOADALL and continue executing in real mode but with a “magic” ES selector. On a 386+, the same effect could be achieved through documented means.
Again, it’s not clear whether IBM’s OS/2 1.0 and 1.1 intentionally used LOADALL on 386 systems. It would not happen on IBM’s ABIOS-based (PS/2) 386s.
Early LOADALL Users
OS/2 was not the first user of LOADALL. It’s not clear who was, but there is very good evidence (in the Windows 2.x BAK, for example) that Microsoft used LOADALL as early as 1986. It’s also apparent from source code comments that Microsoft was given preferential treatment and received LOADALL documentation from Intel.
IBM on the other hand never wrote code to use LOADALL. IBM’s VDISK.SYS strictly used the BIOS interface for extended memory copying. Newer software then generally used XMS and let HIMEM.SYS deal with LOADALL and similar trickery.
Microsoft used LOADALL in RAMDRIVE.SYS (a clone of IBM’s VDISK.SYS) as well as SMARTDRV.SYS which had been cloned from RAMDRIVE. Note that HIMEM.SYS was comparatively speaking a latecomer. SMARTDRV development started in May 1986, and RAMDRIVE is even older, dating back to May 1985 (part of Microsoft’s effort to create a shrink-wrapped PC DOS equivalent). On the other hand, the development of HIMEM.SYS only started in April 1988.
LOADALL Refinements
Later users of LOADALL refined the use of LOADALL to allow interrupts during memory copies. As the OS/2 DDK documentation cautions, an interrupt is highly likely to destroy the magic selector created by LOADALL, and if the memory copy were continued after completing the interrupt, it would lead to uncontrolled memory corruption. How did Microsoft avoid that?
The trick was to make sure that an interrupt handler would not only destroy the magic selector but also change CS in a controlled fashion. The LOADALL caller (HIMEM.SYS, for instance) would change the base for ES and/or DS selector, but it would also set up CS such that the base didn’t change while the selector value did. If an interrupt occurred, the execution would not return to the interrupted instruction but rather fall into a “safety net” that would restart the memory copy again.
For example, if (real mode) CS was initially 1234h and the corresponding base was 12340h, after LOADALL the base would remain 12340h but the selector value might be changed to 1235h. If an interrupt occurred, the IRET would force CS to be reloaded under real mode rules, and the CS base would change to 12350h. The safety net code would execute LOADALL again and continue the memory copy.
More or less the same method would also be applicable to 386+ processors which can switch to protected mode, reload segment selectors and bases, and return back to real mode. However, the 386 version of HIMEM.SYS used a much more straightforward method which relied on extending the selector limits (big real mode), and an interrupt in the middle of a memory copy would simply trigger an exception that could be handled and the copy continued.
LOADALL is a prime example of an undocumented feature which was so frequently relied upon by major software that it became an integral part of the architecture. A 286 clone without LOADALL support would be seriously incompatible with MS-DOS as well as with OS/2, which would likely make it extremely difficult to sell.
When you say “A 286 clone”, do you mean a 286 CPU clone or a 286 PC clone? Because a 286 PC clone has LOADALL support just because it has a 286, hasn’t it?
A different thing is a 386 PC clone which should have BIOS support for the 286 LOADALL, as you told in previous LOADALL article.
I meant a 286 processor clone, yes. Not just a 286-based PC clone using a 100% Intel-compatible CPU.
Any idea as to how many programs used the 286 LOADALL ? As far as I know the following programs used it:
* HIMEM.SYS – started using LOADALL sometime after the publicly released version 2.03 (which used INT 15h function 87h)
* RAMDRIVE.SYS – pre-XMS versions prior to its inclusion with DOS 5
* SMARTDRV.SYS – pre-XMS versions prior to its inclusion with DOS 5 (the later SMARTDRV.EXE never used LOADALL)
* OS/2 1.x
Also as far as I know no software ever used the 386 LOADALL (0Fh 07h) since there was no need to do so.
I did some checking and discovered that HIMEM.SYS 2.04 dated 08/17/88 is the first version to use LOADALL. It’s probably no coincidence that HIMEM.SYS version 2.03 dated 08/09/88 which does not use LOADALL is the only version of HIMEM that Microsoft publicly released source code for.
It’s more complicated than that. The revision log in HIMEM.SYS 2.04 lists (among others):
2.03 - Added 286 LoadAll and 386 Big Mode MoveBlock 8/04/88
- Removed 286 LoadAll for publication 8/10/88
2.04 - Restored 286 LoadAll 8/11/88
I don’t know if any 2.03 versions with LOADALL included made it outside Microsoft.
The only use of 386 LOADALL I’ve seen was a 286 LOADALL emulator TSR written by Robert Collins (with documented instructions it’s not quite possible to emulate all aspects of 286 LOADALL). I’m not sure if all 386s even supported LOADALL. But yes, with the ability to switch from protected back to real mode, the rationale for using LOADALL wasn’t there anymore.
I wonder what the impetus was for BIOSes to emulate 286 LOADALL ? HIMEM.SYS didn’t need this since all versions which used LOADALL also used big real mode on 32-bit CPUs. RAMDRIVE.SYS and SMARTDRV.SYS don’t seem important enough to merit it and at least for RAMDRIVE.SYS, DOS 3.3 and later versions had 386 detection and used INT 15h function 87h instead. Perhaps it was done to support OS/2 1.x and Windows 2.1x (specifically Windows/286 which I believe also used LOADALL).
Right, it can’t have been HIMEM.SYS. Knowing when the emulation was first added would narrow down the list of suspect. If the emulation was added only after OS/2 1.0 showed up, I’d suspect OS/2 as the reason. Otherwise it could have been RAMDRIVE or SMARTDRV, or possibly some 3rd party software.
386 LOADALL was also used when AMD and IBM (I think) tried to sell chips with ICE mode enabled and rename it “SMM” mode. I think Intel sued them for trademark violation over this.
You’re right, it would be interesting to see if the early Compaq Deskpro 386s had LOADALL emulation given this timeline:
MS-DOS 3.2 RAMDRIVE.SYS – Jul 1986
Compaq Deskpro 386 – Sep 1986
Compaq Deskpro 386/20 – Oct 1987
OS/2 1.0 – Dec 1987
Windows 2.1 – May 1988
HIMEM 2.04 – Aug 1988
Early versions of RAMDRIVE and SMARTDRV which used LOADALL appeared in 1986 though I can’t see BIOSes being updated just for them especially since later versions (circa 1987) detected the 386.
At least Award Bioses v4.51 and 6.00 support 286 LOADALL emulation and 286 triple fault handler for OS/2 1.0 operation.
Checked in source code (bundled with some rare bios engineering chinese books).
This omits the early adopter of LOADALL in DRI’s Concurrent DOS 286 and FlexOS 286 from 1985 and 1986. It requires E2 stepping 286 which has the changed LOADALL instruction to run 8086 applications in protected mode. Check out Chapter 3 of the Supplement for iAPX286 Computers which devotes 16 pages to how to run five different DOS applications in this emulation. Three of those five have various errors with Lotus 1-2-3 and Personal Editor (a bonus sixth tested application) crashing with the shipping 1.3 release.
Then there were programs like AboveDisc and possibly Extender. Extender seems to have tried something similar to FlexOS and run 1-2-3 v2 in Protected Mode to increase memory available to 960kB. Got a bit of attention and a full page article in InfoWorld back in 1985 before seeming to vanish.
There was a lot of LOADALL using software before the 386 was introduced and FlexOS seemed well on its way to being the defacto standard for Point-of-Sales systems thanks to IBM’s use of it. More might be answered with the discovery of the fabled Intel 15 page whitepaper on LOADALL which the few articles on LOADALL refer to in roundabout ways. I don’t have a copy.
Not sure what you mean by a triple fault handler?
I see: http://bitsavers.org/pdf/digitalResearch/flexos/FlexOS_Suppliment_For_iAPX286_Computers_Nov86.pdf There’s definitely a lot of interesting history in Concurrent DOS and FlexOS.
I guess the question is whether the early LOADALL users were still around by the time 386s showed up. And if they used LOADALL in a way that can be easily emulated.
I assume a “triple fault handler” would be the bit in the BIOS that checks to see if the machine is restarting or if it’s a return-from-pmode CPU reset either from a triple fault or the keyboard controller. Slightly off-topic, does anyone know of any software that actually uses 16-bit TSSs for anything other than error handling? OS/2 1.x uses them but only for NMI and DF handling.
Award 4.51 PG BIOS is from the late 1990s, by that point all major BIOSes emulated LOADALL. The question is when BIOSes first started to do so and for what software. Phoenix BIOSes were emulating LOADALL in 1991 and there’s evidence that they were doing so as far back as Jan 1988.
“triple fault handler” ?!? Surely you mean double fault handler.
It has been said that lots of software used the 286 LOADALL but this doesn’t seem like “lots”:
* HIMEM.SYS 2.04 and later (which also has 386 detection so doesn’t really count)
* RAMDRIVE.SYS โ pre-XMS versions prior to its inclusion with DOS 5
* SMARTDRV.SYS โ pre-XMS versions prior to its inclusion with DOS 5 (the later SMARTDRV.EXE never used LOADALL)
* OS/2 1.0 and 1.1 (apparently 1.2 and 1.3 has proper 386 detection)
* Windows 2.1x (Windows/286)
* AboveDisc
I was refering to the mechanism to return a 286 CPU back to real mode by resetting the CPU but returning to program execution skipping all the POST code (method called EXC9HDLR by Award).
Sorry for the mistake
That mechanism has been with us ever since the original PC/AT (1984)… it’s a generic warm boot mechanism and a triple fault is just one way to trigger it. A KBC-initiated reset works much the same, though it’s slower (the KBC is not a particularly fast microcontroller). At any rate, this is just basic PC/AT compatibility. LOADALL emulation is something not found in IBM BIOSes of the era. Actually I should check if newer ISA-based IBM systems do it…
Yes, “triple fault handler” seems to have been a slightly odd way of referring to the reset/warm boot POST handling.
Some ancient DOS extender might have used 16-bit TSSs (maybe). Perhaps 286 XENIX. Really just guessing though ๐ AFAIK more or less everyone discovered that task switching “by hand” is faster than using the hardware mechanism, so task switches were relegated to NMIs and #DFs where a task switch is required for correct function.
Actually I know for a fact that the prehistoric Ergo 286 DOS extender used a task switch to the current TSS to populate the TSS. It can be found in Borland’s Turbo Debugger 286 (TD286.EXE). Not sure if this counts as “use”, but it will at least always be executed.
TD286 sounds interesting, I’ll have to check it out. Except by forcing a DF in OS/2 I haven’t really been able to test the TSS code I wrote in MESS and that’s why I’m interested (XENIX 286 and Netware 2 both work in MESS and never triggered the log message I put in that prints whenever a task switch via TSS occurs).
It might be interesting to see if the BIOS for 386 systems that were not intended for use with 286 software still had 286 LOADALL compatibility. Sun’s 386i would be an example.
The number of LOADALL applications needs to include all the DOS developers who planned on having programs that ran in protected mode without the complexity of switching to a different OS or creating what became DOS extenders. Even if some programs never shipped in a form using LOADALL, if major application publishers were considering the use of LOADALL in 1985, 386 BIOSes would have to be designed to incorporate support for 286 LOADALL. It takes more than a year to design a BIOS.
I have wondered if Intel showed LOADALL to various companies in the hopes of getting extended memory to be used (and selling RAM cards) or some engineer realized that LOADALL could almost create a virtual 86 session and was just trying to get feedback for the better implementation that arrived with the 386. Had to be started by Intel because it seems unlikely that all those companies would just simultaneously notice the same undocumented instruction having a bunch of useful features. Intel did do multiple respins of the 286 trying to adjust LOADALL to DRI’s requirements which is unusual for an undocumented instruction.
More than likely an engineer realized that LOADALL could be used to access extended memory from real mode since the hidden segment descriptor caches could be altered to point to any address. Remember that the true purpose of LOADALL was to support an ICE. Also Intel did provide companies like Microsoft with a 15-page secret document describing LOADALL around 1985.
I find it hard to believe that Intel changed LOADALL for DRI. I have never read anything about there being multiple respins of LOADALL. Once they released the confidential document to companies they probably wouldn’t change things, particularly after software started using LOADALL. Also DRI simply wasn’t that important, Microsoft and IBM, yes but not DRI.
dosfan: Check out InfoWorld May 13, 1985 (pages 17-18) and August 26, 1985 (page 21) for evidence of Intel modifying 286 in response to DRI’s issues which resulted in the E-1 and E-2 steppings. I would have copied out the relevant Intel spokesman quote except it is a bit long and selecting text doesn’t seem to work with the online issues. I can’t find the reference that those steppings incorporated changes to LOADALL. Now, my searches instead turn up Compaq and MS patents involving the usage of LOADALL or emulating LOADALL which while interesting aren’t relevant to Intel steppings.
So Intel fixed some 286 bugs, without seeing the actual errata it is just an assumption that they had anything to do with LOADALL. Also fixing bugs isn’t the same as altering the operation of an instruction. There is only one known 286 LOADALL functionality.
I don’t think Sun386i had a BIOS at all? Or did it? I’ve never seen one of those beastsโฆ too bad as it was a rare non-PC x86-based workstation.
It seems fairly certain that LOADALL was designed as a debugging feature, but I also suspect that Intel initiated its use, or at least blessed it. I spoke to one 286 DOS extender author who said that he didn’t want to use LOADALL because as a small company they couldn’t guarantee LOADALL would be and continue to be supported in all 286 CPUs. Microsoft clearly had a different opinion, but Microsoft also received LOADALL documentation from Intel.
All that said, LOADALL was not required in order to implement a 286 DOS extender, although it was more efficient than the alternative.
TD286 was what I needed, thanks. It also uses LOADALL so Borland may have also had access to the Intel doc but on 286’s only so it doesn’t need any BIOS emulation for 386+.
It would have been Ergo/Eclipse/A.I. Architects, the authors of the DOS extender. I doubt Borland had anything to do with it. Interesting nonetheless!
http://www.pcjs.org/pubs/pc/reference/intel/80286/
That’s been there for months now ๐
Pingback: 386 LOADALL | OS/2 Museum
Pingback: A Brief History of Unreal Mode | OS/2 Museum