Undocumented RDTSC

The other day I wrote a simple DOS program which used the RDTSC instruction in order to obtain precise time measurements (of how long it takes a PS/2 keyboard to send data; more about that some other time). The 16-bit DOS program worked fine in a VM running PC DOS 2000, as well as in NTVDM on Windows running on a system with a Core 2 class CPU. But when I tried running it on an old IBM ThinkPad 760XL laptop with a 166 MHz Pentium MMX processor running PC DOS 2000, it just hung when executing RDTSC. Unless I disabled EMM386, and then it worked fine.

That was a bit of a mystery. The Pentium MMX does obviously support the RDTSC instruction. The only troublesome possibility would be if perhaps someone set the CR4.TSD bit (the Time Stamp Disable bit) which would cause RDTSC (and RDTSCP on newer CPUs which support it) to #GP fault outside of ring 0. But old EMM386 does not even touch CR4, and at any rate the same program with the same EMM386 version worked on a newer CPU. Could the ThinkPad’s BIOS be setting CR4.TSD?

A quick experiment showed that no, the ThinkPad’s BIOS does not set CR4.TSD. But unless CR4.TSD is set, the Intel SDM clearly documents RDTSC to work in V86 mode without any problem! Given that RDTSC only works on registers, it essentially cannot fail.

And yet it did on the Pentium MMX. Okay, clearly something is amiss. What did Intel’s Pentium documentation say? Let’s check the original Pentium Processor Family Developer’s Manual, Volume 3: Architecture and Programming Manual (Intel document order number 241430-004, 1995). RDTSC is documented on page 25-264.

Wow, look at that: Virtual 8086 Mode Exceptions: #GP(0) if instruction execution is attempted! That would certainly explain why RDTSC refuses to work on the Pentium CPU with EMM386. Intel completely fails to document this behavior in the current SDM, which is supposed to cover the Pentium. Good thing the old documentation survived.

So what is going on? Not surprisingly, I’m not the only one who noticed this oddity recently, although in that case the author incorrectly concluded that it’s somehow related to a specific EMM386 version, rather than the CPU model (to be fair, EMM386 could handle RDTSC in V86 mode, but clearly EMM386 versions at least from the mid-1990s don’t).

Fortunately, this problem was noticed in the old days as well, and there’s an explanation for the strange misbehavior. According to unverified but very plausible information, Intel’s design was to have RDTSC working in V86 mode, which really makes perfect sense. But due to a misunderstanding, RDTSC cannot be used in V86 mode on the Pentium.  Whatever the real reason, the Pentium documentation does accurately describe the actual behavior.

On the Pentium Pro (and all subsequent Intel CPUs), RDTSC works as originally intended and can be used in V86 mode (subject to CR4.TSD). Since the current SDM evolved from the Pentium Pro/Pentium II documentation, the Pentium behavior was forgotten and left out (it’s not mentioned in the Pentium Pro documentation because users were expected to look at the separate Pentium documentation).

In the original 1993 Pentium documentation, RDTSC was documented in the infamous Appendix H, so it’s difficult to check exactly what the documentation said.

It is notable that the AMD K5/5k86 is documented to behave like the Intel Pentium (RDTSC always faults in V86 mode). The behavior of AMD K6 and K7 CPUs is not entirely clear. All AMD64 processors are documented to behave the same as modern Intel processors, i.e. RDTSC is supported in V86 mode.

Cyrix introduced RDTSC in the 6x86MX processor (1997). Cyrix documentation implies that RDTSC should be usable in V86 mode. IDT likewise makes no mention that RDTSC should be unusable in V86 mode.

Conclusion: The RDTSC instruction cannot be used in V86 mode on a set of older processors which includes the Intel Pentium (but not Pentium Pro and later), AMD K5, and possibly some other processors. On modern CPUs this restriction does not exist.

This entry was posted in Documentation, Intel, Pentium. Bookmark the permalink.

15 Responses to Undocumented RDTSC

  1. Yuhong Bao says:

    I think old EMM386 did handle RDMSR.

  2. Michal Necasek says:

    Yes, that occurred to me too. So maybe reading MSR 10h can be used as an alternative.

  3. Yuhong Bao says:

    I wonder what was the first version of EMM386 that did it though.

  4. dosfan says:

    EMM386 4.48 (MS-DOS 6.2 and PC DOS 6.3)

  5. techfury90 says:

    Interesting. I should throw together a test case and see if NEC’s fork of EMM386 supported it. It has some very different options from regular EMM386, particularly support for exclusions in two different memory map modes for “high resolution” systems.

  6. Rugxulo says:

    Try JEMM386 on the laptop, and see what happens.

  7. dosfan says:


    Are you referring to the PC98 version of EMM386 ? Theoretically it should have been derived from the standard MS-DOS version of EMM386. Granted PC98 hardware is different from PC hardware but the GP handler code should be the same.

    By the way do you have older PC98 software ? If so then could you check if MS-DOS 2.25 ran on that platform ? Supposedly MS-DOS 2.25 was done for some Far East OEM.

  8. Michal Necasek says:

    I’ll let someone else do that. The result is not really relevant to me, what matters for me is that on a Pentium CPU, RDTSC can’t be expected to be usable in V86 mode. If that works in some specific configurations that’s great, but unfortunately doesn’t help me much.

  9. techfury90 says:

    dosfan- Yes, the PC-98 one. I have some older versions of DOS. Mainly 3.x, but I have two revisions of Epson-branded 2.11 and NEC’s 2.11 (the initial public PC-98 DOS release from 1983: note that DOS was actually ported after the PC-9801 went on sale)

    At one point, I theorized that the Epson 2.11 release may have really been 2.25 under the covers since it wasn’t released until 1988. That was proven false when I tracked it down. I believe Michal said that most of the extant information relating to 2.25 hints that it would have been a Korean-market release (presence of the word Hangul in documentation et al), and I’m inclined to agree. I cannot find any conclusive evidence of any Japanese OEM using it, they all used 2.11 (initial release with Japanese support) or 3.x. However, it appears that at least some versions of PC-98 DOS (at least 3.3 and later, earlier has not been tested but Japanese sources say 3.2 doesn’t have it) have the DBCS lead byte table function that was added in 2.25. However, none of the official documentation from ASCII/MS or NEC makes any reference to this function. I was actually unable to find any Japanese primary source that mentions that function as well, at least sifting through about a dozen dead tree/PDF sources. So, I’m pretty sure Korea is where one needs to be looking for 2.25.

  10. dosfan says:


    You are correct, INT 21h function 63h was originally called “Hongeul” (there’s an old DOS 3.1 “SYSTEM3.DOC” which mentions this) but this was changed to ECS_Call in later versions. How big was the South Korean PC market in the mid-80s ? I’m starting to wonder if MS-DOS 2.25 was ever released since there seems to be no evidence that it did.

  11. dosfan says:

    Back to RDTSC, I vaguely remember reading something about RDTSC not working in V86 mode on the Pentium being an error. The whole point of having a separate opcode to read the TSC was for it to be usable regardless of CPL as opposed to RDMSR/WRMSR.

  12. techfury90 says:

    That’s the mystery. I suspect it was actually released, but didn’t sell many copies. As I understand things, 2.25 would have been released sometime around 1984-1985. There is evidence that Korean OEMs like Samsung and GoldStar (present-day LG) started producing PCs around this time, and they were being exported to the US around the same time.

    We do know that they had special video cards designed around Korean text support, as later versions of Korean DOS used them, eventually switching over to software-based support using VESA graphics modes. My knowledge stops right here, however. I can only read and write English, German, and Japanese, so sifting through Korean sources is sadly pretty much out of the picture for the most part.

    Regarding the size of the market: I think that might be an explanation for why we have not seen 2.25. I do not have figures for the Korean market, but it seems to have “started” in the mid-1980s, right around the time of 2.25’s theoretical release. It is important to consider a few facts, however: in the 1980s, South Korea was still a (rapidly) developing economy. I doubt consumer disposable income had risen to appropriate levels for PCs to be affordable to the average citizen at this point. I just looked for numbers and found a 1987 NY Times article that states that at the time, South Korean household incomes were an eighth of that of US or Japanese households, on average. Obviously, this is not the case anymore, but would explain the rarity of 2.25: not many copies were sold except to business users, almost certainly.

  13. MiaM says:

    Samsung and Goldstar (LG = Lucky Goldstar, btw) certainly produced semiconductors in the second half of the 80’s. I remember building electronic stuff in the late 80’s and got Samsung and Goldstar parts from a locally well renowned distributor. But that was simpler parts like voltage regulators, 74xx logic and so on. Hundai however made atleast SRAMs at about that time. So they probably had most of the technology to make PC’s without importing that much stuff, thus it seems likely that they actually started making PC’s.

    But I wounder how important language support in DOS were?

  14. techfury90 says:

    Leading Edge Model D is the proof in the pudding: Daewoo manufactured it in South Korea for Leading Edge and it was launched in the US in 1985.

    It would be interesting to see how the South Korean semiconductor business got started. If it’s anything like most of their electronics industry and heavy industry in general, I suspect they had considerable amounts of help from the Japanese semiconductor manufacturers. Example: Kia cars were originally license-built Mazdas. Samsung TVs? Product of a 1970 partnership with NEC to acquire CRT technology. The list goes on and on; I suspect they probably sold them all the equipment and designs necessary.

    WRT language support: I truly don’t know. Nor am I exactly certain how many parts of DBCS support in CJK variants of DOS comes from DOS inasmuch as the OEM extensions left and right.

    On the PC-98, we have a driver called KKCFUNC.SYS that provides an API that is then used by your FEP/IME (front end processor/input method editor, common choices are NECAI, ATOK, and VJE) to hook into the console input routines and such. The FEP handles the actual input, but KKCFUNC provides the API they hook onto. As I understand it, it’s totally different on DOS/V and (at least later versions of) Korean DOS: they have all sorts of display driver/font stuff that PC-98 users didn’t have, as the PC-98’s character ROM contains the complete JIS character set, and the display hardware fully supports mixed 1/2 byte characters.

    The other thing, now that I think of it: DOS on the PC-98 doesn’t actually have much in the way of DBCS functions. Every PC-98 programming book has an entire chapter on dealing with DBCS strings and conversions between the different encoding schemes.

  15. Michal Necasek says:

    DOS still needs to handle file names, and at a minimum it needs to not freak out when presented with DBCS characters. It’s true that the OS as such does very little when it comes to inputting and displaying the characters.

    FWIW, Japan was one of the first foreign countries Microsoft was interested in, that goes back at least to the early 1980s and is the reason for things like MSX.

    Korea has much in common with Japan (just don’t tell either of them…) and the way the government supports industry is similar in both countries. I’d be shocked if, like in Japan, the semicon industry in Korea wasn’t part of gigantic conglomerates from the earliest days.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.