[1]logo[2]ASUS[3]eMail Please [4]visit my sponsor. ______________________________________________________________________ microcode update feature © 1996-1997 by Christian Ludloff. Last [5]updated on Tuesday, 22-Jul-97 02:22:55 EDT. The entire sandpile.org website can be [6]searched for keywords, or for phrases. Please, use your browsers [[7]BACK] button or shortcut key to go to the previous page! ______________________________________________________________________ Introduction This page does shed light on the so-called microcode update feature, which is supported by many modern microprocessors. First, some reasons why this page does exist will be explained. Then a brief [8]overview on what microcode is, what it is used for, and why it is useful to be able to update it, will be given. Also, the page will look back at the [9]history, and the [10]roots of the feature, describe some [11]variations, and -- last but not least -- it will give an outlook from [12]today into the [13]future, discussing a few interesting [14]questions. This material has been collected over the past few months, whereas some of the sources can be traced back until as early as 1992. One reason, why this page does exist, was a short [15]article, which appeared in the [16]EE Times on June 30th 1997, written by Alexander Wolfe. In this article he claimed that "...Intel plans to make a high-profile public announcement [in July 1997] that it has developed a technology to quickly fix bugs that crop up in its microprocessors without having to recall the chips." To set the record straight from the beginning -- [17]Intel did neither invent, nor did they patent [as of writing this] such a technology. The truth is, that they are just another vendor, who is using it, and that [as of writing this] nobody has a patent on this technology. A quick research, using a powerful [18]patent database, did not show any issued patents, which would explicitly describe the microcode update feature, but rather it resulted in various microcode related patents. Another fact is, that Intel didn't just recently add such technology to their processors. It has been around since late 1995, when Intel had introduced their PentiumPro processor. Just by reading the PentiumPro processor BIOS writer's guide, v2.01 dated February 1996, one can confirm that the feature does exist, although it is named "BIOS update feature". (Click [19]here for a huge list of manuals.) The only problem is, that -- except for how updates are loaded -- no information, and no updates are available from Intel. To make something else clear from the beginning -- this page is not intended to put Intel under fire, or continue the [20]Appendix H saga (of Intel, [21]hiding useful information), as it might seem to some readers after the above two paragraphs. Instead -- since no other resource on the Internet has done this so far -- it is intended to give an informative background, so that a reader can draw his/her own conclusions. Now, that this is clear, a short explanation of what microcode is, should follow. Overview Although other devices may contain microcode too, only microprocessors will be looked at here. These microprocessors -- especially 80x86 parts -- often use two main methods, of how they implement instructions. Simple instructions are hard-wired, which allows a very high performance. Complex instructions are described by some sort of a small program, which controls the microprocessor units. This program's code is refered to as microcode, which is stored inside the chip. Although writing microcode is similar to other programming, it is much more an art, and requires a very deep knowledge about the target microprocessor. Thus, only a few people practice this art, and usually they stick with their jobs for a long time. Often writing microcode resembles programming a parallel computer, as each of the microcode instructions is supposed to make use of the microprocessor's units as effectively, as possible. For details just talk to one of the microcoders. :-) When a microprocessor design is finalized, the microcode is translated into a binary data block, which is then hard-wired into the chip. If such a chip does execute a complex instruction, it will look up the microcode, and execute it, to control its units. The difference to the hard-wired and simple instructions is, that a hard-wired microcode is generated based on some sort of a program. By contrast, eg. some simple adding functionality is based on standard [22]VHDL libraries. Following the above explanation it becomes clear, that microcode may contain bugs. While manufacturing bugs, which would cause that the wrong binary data seems to be stored in the microcode storage array, can be detected by checksums, other bugs which come into life because of an error during the final translation, and of course those bugs which come from mistakes, the microcoder made, are not only much more common, but also much harder to detect, and much more difficult to avoid. That makes it clear, why it would be nice to be able to correct such bugs with an easy-to-use, simple, and not too expensive method. The microcode update feature is, what gets used to fulfill these needs. Instead of having microcode in a read-only storage array (the historical microcode ROM), microprocessors allow to modify the microcode. Either the entire microcode gets loaded during the startup process, or it can be loaded later and override all, or parts of the built-in hard-wired microcode. A nice side effect of being able to update microcode is, that you may be able to enhance the existing functionality, optimize it, or even add completely new functionality, as permitted by the existing microprocessor hardware. Another short introduction to microcode and microcode updates, is given by [23]IBM. They provide this feature, and updates, for their RS/6000 platform. Hey, Intel & Co -- let IBM be a good example for how this business does work! History Although the microcode update feature is probably older than that, some of the earliest references to it, can be found in documents from [24]DEC, all dated 1992. The [25]first one is about the Alpha microprocessor ("A 200 MHz 64bit dual issue CMOS microprocessor", 217 KB), the [26]second one is about the roots of [27]FX!32 ("Binary translation", 100 KB), and the [28]third one is about the Alpha development ("Using simulation to develop and port software", 76 KB). The first document describes on page 7, how the Alpha microprocessor loads some block of binary data from a read-only memory into its instruction cache, before it does begin to execute instructions. "When the chip is reset, the first action is to read from a serial read-only memory (SROM) into the I-cache via a private three-wire port. The CPU is then enabled and the program counter (PC) is forced to 0. [...] This initial set of instructions is used to write the bus control registers inside the CPU chip to set the cache timing and to test the chip and module from the CPU out." The second document claims on page 2, that RISC microprocessors do not have any microcode. As their name implies, they use some reduced instruction set, which is simple, and can be hard-wired for performance reasons. "[...] since RISC architectures do not have a microcoded hardware layer underlying the visible machine architecture." The third document describes on page 2, how the Alpha microprocessor was simulated on a VAX 8800 machine, and how additional VAX microcode was used to speed up this simulation. It mentions updateable VAX microcode. "The [...] microcode occupies 93 percent of the total 1,024 words of the user-writable control store." With that, DEC might be able to claim to be one of the first companies, to have used the microcode update feature technology. This may even put new oil into the flames of the fire, caused by the recent lawsuit, DEC has filed against Intel, claiming patent infringements. (An interesting [29]article (137 KB) about that lawsuit has been published by the [30]Microprocessor Report in June 1997.) But that is another story, which doesn't really belong here. Roots Another player has been NexGen, a small 80x86 company, which has [31]merged with [32]AMD in 1995. NexGen introduced their Nx586 microprocessor in 1994 as a competitor to Intel's Pentium. Although the chip was neither pin, nor fully binary compatible, it offered about equal performance, for less money. Due to its proprietary pinout only two boards, one VLB and one PCI, both supplied by NexGen, were available -- which at that time helped to doom this part from the beginning. Since NexGen had started to design their CPU as an 80386 competitor, but faced delays, the final outcome was a chip, running as fast as a Pentium, but looking like an 80386 to software. In example the Nx586 did not support the alignment checking feature, which allows to cause an exception (AC#) on unaligned data. This feature is enabled by setting the AC bit in the [33]EFLAGS register (after the AM bit in the Control Register [34]CR0 has been set). Now Intel comes in again... Because they provided a CPU detection algorithm, which checked for an 80486 microprocessor by trying to toggle the EFLAGS.AC bit, most programs did follow the Intel algorithm, and thus identified the Nx586 as an 80386 microprocessor. Not only does the algorithm violate Intel's own rule, not to rely on any undefined bits -- and for pre-80486 microprocessors EFLAGS.AC is not defined --, but also many programs did refuse to work with the Nx586 due to that stupid mistake. Always be paranoid, Intel! :-) Another problem was, that the Pentium had introduced a new instruction, [35]CPUID, which assists software in a simple identification of the microprocessor. Programs started to use CPUID, and failed on the Nx586, again. But luckily NexGen had implemented the soon to be very useful microcode update feature into their Nx586! That way they were able to fix several problems which came from bad CPU detection algorithms. (Read [36]here for one of the better ones.) From AMD's website you can [37]download toolboxes for the NexGen Nx586 VLB, or PCI board. These toolboxes contains four interesting little programs: IDON, IDOFF, EXTON, and EXTOFF. To see what these programs do, check these dis-assembly listings: IDON.COM IDOFF.COM 0000: BE0EB0 mov si,B00E 0003: B003 mov al,03 0005: B44C mov ah,4C 0007: 0F55 ??? 0000: BE0EB0 mov si,B00E 0003: B004 mov al,04 0005: B44C mov ah,4C 0007: 0F55 ??? EXTON.EXE EXTOFF.EXE 0212: B80400 mov ax,0004 0215: 8ED8 mov ds,ax 0217: 8EC0 mov es,ax 0219: BE00B0 mov si,B000 021C: 0F55 ??? 021E: 66C1EA10 shr edx,10 0222: 80FA33 cmp dl,33 0225: 7515 jne wrong_BIOS 0227: 80FE77 cmp dh,77 022A: 7210 jb wrong_BIOS 022C: 80FE7A cmp dh,7A 022F: 770B ja wrong_BIOS 0231: B005 mov al,05 0233: B101 mov cl,01 0235: BE0EB0 mov si,B00E 0238: 0F55 ??? 0212: B80400 mov ax,0004 0215: 8ED8 mov ds,ax 0217: 8EC0 mov es,ax 0219: BE00B0 mov si,B000 021C: 0F55 ??? 021E: 66C1EA10 shr edx,10 0222: 80FA33 cmp dl,33 0225: 7515 jne wrong_BIOS 0227: 80FE77 cmp dh,77 022A: 7210 jb wrong_BIOS 022C: 80FE7A cmp dh,7A 022F: 770B ja wrong_BIOS 0231: B005 mov al,05 0233: B100 mov cl,00 0235: BE0EB0 mov si,B00E 0238: 0F55 ??? notes: These are only fragments. Reserved opcodes are marked red. Any differences between the files are marked with bold text. The opcode 0Fh 55h is reserved. The 2-byte opcode [38]map shows, that even todays MMX instructions still make no use of this particular opcode. So NexGen's choice of a "special opcode" was a lucky choice. Since no further documentation about this opcode is available, one must guess, what this opcode could stand for. A very hot guess is of course, that it does affect the way, the Nx586 works, and behaves. In addition, rumors claim, that it could be part of some sort of a microcode update feature. These rumors, combined with the fact, that detecting the external cache size in a NexGen Nx586-based system never returns a 100% reliable result, lead to some very interesting conclusion: The Nx586 is capable of microcode updates, and it does store the necessary data in a write protected portion of its external L2 cache. You may ask now, why the slow L2 cache would be used for that, rather than the much faster L1 cache. Well, there is an explanation. First of all the L1 cache is pretty small. Using a larger portion of it to hold the microcode update would dramatically decrease the overall performance. Second, the Nx586 did include a proprietary L2 cache controller, which was one of the reasons for its incompatible pinout. This provided the Nx586 with a very fast interface to its external L2 cache. And third, only NexGen supplied the motherboards for the Nx586, as mentioned earlier. Both available models always contained 256 KB of L2 cache. With these facts, and the knowledge that most of the microcode update would not be used too often, NexGen probably made the good decision, to store some sort of a microcode update in a write protected portion of the external L2 cache. And the 0Fh 55h opcode was part of the control mechanism for it. Depending on register values, the processor executed certain functions. As it can be seen above, one function returns the BIOS version, while others control the microprocessor behavior (EFLAGS.AC, EFLAGS.ID, and CPUID). Since NexGen never provided an in-circuit emulation (ICE) tool for the Nx586, nor a logic analyzer for its proprietary bus, and since the Nx586 died out a while ago, further research remains to those, who still are interested in more details. Maybe some of all these former NexGen workers, which now build microprocessors for AMD, are in a position, to release the missing information. Or is anyone really concerned, that this is still vital information? Come on... Variations Another 80x86 microprocessor, known to support some microcode update-like feature, is the 6x86 processor, designed by [39]Cyrix, and manufactured by [40]IBM. Once this microprocessor faced a totally different problem than the Nx586, which may lead to trouble with any Intel clone -- it just was too fast. In particular, the LOOP instruction executes in only one clock cycle on the 6x86, while eg. a Pentium takes 5 or 6 clocks. This started to cause problems with badly designed programs. These programs used LOOP instruction for delay loops, and thus became useless when running on the 6x86 microprocessor. Since the 6x86 market share was not big enough to have the programs fixed -- the [41]well-known problem of older 6x86s with WinNT 4.0 and the writeback caching made that pretty clear, didn't it? -- Cyrix and IBM had to come up with some other solution. Luckily, the 6x86 did include quite some (undocumented) feature control through CCRs, and so a workaround was born: [42]PIPELOOP.EXE (4 KB). Instead of a long dis-assembly listing, pseudo-code is given below. It is assumed, that the reader is familiar with the CCRs, and their usage. If not, then all the required details can be found [43]here. PIPELOOP.EXE (slowed) PIPELOOP.EXE (normal) CCR3.MAPEN=0001b DBR0.bit7=0 DBR1=B8h DBR2=7Fh DBR3=00h DOR=E2h (opcode for LOOP) CCR3.MAPEN=0000b CCR3.MAPEN=0001b DBR1=00h DBR2=00h DBR3=00h DOR=00h (cleared opcode) CCR3.MAPEN=0000b notes: Accessing CCR3.MAPEN enables and disables access to the full CCR range. While DOR gets loaded with the first byte of the LOOP instruction opcode ([44]E2h), DBR1..3 get loaded with some sort of control data. Whenever the LOOP instruction is executed, this control information ensures a slowdown, probably by partially, or fully serializing the 6x86 microprocessor. Later versions of the 6x86 include a bit, CCR5.SLOP, which has the same effect as the above sequences: it does slow down the LOOP instruction (when set). Although the 6x86 microprocessor probably uses a hard-wired LOOP instruction, rather than a microcoded one, this example makes clear, why a microcode update feature is very useful, and where its limitations lie. If, in example, a basic adding functionality has been hard-wired, containing a bug, then nothing but a new mask revision would fix the problem. But for many other problems a microcode update feature, combined with other control accessibility to the core, can help to fix problems without chip exchanges. Today After the above explanations, it should be clear, that Intel hasn't invented the microcode update feature. But what about the claim, that the feature has been added to the Intel microprocessors just recently? To answer that question, one must remember the PentiumPro BIOS writer's guide, mentioned earlier. It contains technical information, describing Intel's implementation of the microcode update feature, and it is dated early 1996. Doesn't that time stamp alone cry out "not recently"? As described in chapter 8 of the PentiumPro BIOS writer's guide, the microcode update is stored in a 2,048 byte long block of data, whereas Intel claims that "No executable code resides within the update." -- a claim which is not entirely true. Although the data is encrypted -- "The encryption scheme also guards against tampering of the update data and provides a means for determining the authenticity of any given [...] update." -- it does contain some code which later, inside the chip, is executed: microcode. Furthermore, Intel claims that "The data within the update is [...] designed such that it is rejected by any stepping of the processor other than its intended recipient. Thus, a given [...] Update is associated with a particular family, model, and stepping of the processor as returned by the CPUID instruction." In fact the data contains quite some revision information -- refer to the layout of the data block below --, which is checked by the loading mechanism, described later. bits and description offset 31 24 23 16 15 8 7 0 header revision #1 +000h update revision #2 +004h month day year #3 +008h reserved type family model step #4 +00Ch checksum #5 +010h loader revision #6 +014h reserved #7 +018h ... +02Ch update data #8 +030h ... +7FCh notes description #1 update block header version number (defines layout, currently 00000001h) #2 unique update version number, basis for the MSR 8Bh (see below) #3 update creation date (BCD format, eg. 07181995h for July 18th 1995) #4 target processor's [45]CPUID type, family, model, and stepping (must match) #5 if the sum of all 512 doublewords is zero, then the update is (probably) okay #6 required update loader version (must match, currently 00000001h) #7 reserved for future expansions #8 update block data (microcode) To load a microcode update, the following procedure is required/recommended. First, the loader must store the 2,048 byte microcode update block in memory. It must ensure that this memory can be accessed in the current operating mode, eg. that neither segmentation, nor paging protection will cause any problems. No particular alignment is required. Then it must check the header revision. Only if it is equal to 00000001h, the format, given above, is valid. As a next step the loader must query the CPUID information of the used microprocessor, and compare it to the CPUID information, stored in the microcode update block header. In multi-processor environments this must be done for the target microprocessor, as different versions of the same microprocessor might be used in one system. This check must include a test of the [46]MSR 8Bh value (the update signature, see below), to ensure that the microcode update is newer than a possibly already loaded microcode update. Finally, the loader must check, whether the microcode update is authentic, by calculating the checksum, and comparing it to zero. Only after all these steps, the loader can load EAX with the linear base address of the update block data (not the header!), EDX with zero, and execute a [47]WRMSR instruction, using MSR 79h. Although the update is possible in any microprocessor mode, the WRMSR is a privileged instruction, and thus requires real mode, or protected mode CPL=0. After the microprocessor has executed the WRMSR instruction, the loader should check, whether the microcode update was loaded into the chip. This can be done by using the above mentioned MSR 8Bh. When [48]CPUID level #1 is queried, in addition to the regular output, MSR 8Bh will be loaded with the update revision (see above, offset +004h), if any microcode update is currently active. If MSR 8Bh is not changed by such a CPUID, then no microcode update has been loaded (or loading one has failed). That way, MSR 8Bh and the update revision value can be used, to confirm a successful microcode update, or to check, whether a microcode update is required. (If MSR 8Bh returns a higher value, than stored in some microcode update block, then a newer block already has been loaded earlier, and no further update loading is required.) To remove microcode updates, a [49]RESET is required (but not just an INIT!). Also, it is guaranteed that the microprocessor executes without microcode updates, and rejects wrong updates. All the above information comes from chapter 8 of the PentiumPro BIOS writer's guide. In addition, this document contains the (long) description of an API, based on INT 15h, which is supposed to be used by BIOS vendors, to implement the above functionality. Details can be obtained by reading the BIOS writer's guide, using Intel's PentiumPro processor BIOS reference kit, or by browsing through the famous [50]DOS interrupt list, maintained by Ralf Brown. BTW, many people have been wondering about the very large transistor count of the P6 core, used in the PentiumPro and PentiumII microprocessors, as well as the Pentium with MMX technology processor core, when compared to a classic Pentium core. A microcode update must be stored somewhere in the chip, and one bit of RAM requires more transistors than a ROM bit. The mentioned processors support microcode updates, and thus include a storage array for them, in addition to their microcode ROM. Future One thing is for sure: most new microprocessors will implement a microcode update feature. But there might be more potential, hidden in this technology. In example, take a look at this [51]announcement from International Meta Systems ([52]IMS). If you look up the [53]patent, which is metioned there, then you will see, that the same microprocessor could be configured to execute several different instruction sets, just by loading a different microcode. A potential limitation is, that only one microcode can be active at a time. This prevents executing two instruction sets, as it is supposed to be possible with eg. [54]IA64 and Merced. On the other hand, there are quite some 80x86 emulations on the market by now -- click [55]here for links -- which would allow an interesting combination: For full performance a microprocessor could be used with a special microcode update, while for the occasional use of some different instruction set an emulation would be good enough. Questions It has been asked, whether the well-known [56]Pentium FDIV bug could have been fixed that way. Well, even if the Pentium would have had some microcode update feature (which it did not), the problem, caused by wrong entries in a hard-wired data table for the SRT division algorithm (more [57]details, 200 KB), could only have been fixed, if this table would have been updateable too. It could be very interesting to compare the extra costs for a microcode update feature to the costs of Intel's Pentium exchange program. Also, it has been asked, whether the well-known [58]PentiumPro and [59]PentiumII FIST bug could be fixed that way. According to Intel's [60]documentation (750 KB) the FIST instruction is not complex, but broken into four simple µOPs. Thus it is unlikely, that microcode is used for FIST itself. But since the bug occurs when an exception is caused, and the Performance Monitoring [61]event list for both the PentiumPro and PentiumII contains an event named "microcode handled floating point exception cases", it might be possible. Finally, it has been asked, whether it would be possible to create your own version of microcode, which could in example be optimized, or even add more functionality, eg. new instructions. This question can be answered with a no. To create such a microcode some would need information about the interna of the target microprocessor, which exceed the level of all known documentation. The only possible way is, if those, who originally created the microprocessor, do create the microcode updates. [INLINE] Another issue which was brought up in a follow-up [62]article in the [63]EE Times, also written by Alexander Wolfe, dated July 10th 1997, is the possibility of faked microcode updates. Someone could modify the data block, and adapt the checksums, so that an update looks authentic. Although encryption is supposed to avoid that, and probably other protection mechanisms are used by the vendor, but will never be publically documented, nor even ever mentioned, this scenario is possible. [INLINE] The most likely result when trying to load a faked update, which nevertheless looks authentic to the user, or the microcode loader, is that the microprocessor refuses to active such an update after loading it, due to the above mentioned security checks. In the rare occasion of a faked update, which would pass all these undocumented tests, the result would be a hang in most cases, but a slight chance of modified microprocessor operation remains. Conclusion: Not only would it be very foolish, if a vendor releases all the details about the used microcode, since such a vendor would give valuable information away to its competitors, but also disclosing such information may lead customers to their own experiments, which, as soon as they fail, would be blamed on the vendor. The microcode update feature is only powerful, and does help, if it is used appropriately, in example through vendor-provided updates. As mentioned above, IBM is a good [64]example here. I hope, that you did enjoy the above thoughts, as I enjoyed writing them down. If you should have any questions or comments, then please, let me know by dropping me an [65]eMail. [INLINE] & [INLINE] 07/20/97 Update The sandpile.org website is proud to provide you with microcode updates for the Intel PentiumPro and PentiumII processors, even before Intel itself is doing so. Recently I came accross a [66]public FTP site, where I found the appropriate files. Both, a version 2.0, dated September 1996, as well as the brand new version 3.2, dated June 1997, are available for a free download from there. Since the help file doesn't claim anything like "confidential", you can download the packages directly from here too. version release date download size file (WWW) file (FTP) 2.0 09/96 57.937 [67]UPDATE20.ZIP [68]UPDATE20.ZIP 3.2 06/97 63.872 [69]UPDATE32.ZIP [70]UPDATE32.ZIP ______________________________________________________________________ [71][LINK] This website has been accessed 306998 times since November 20th 1996. According to daily provided server logs 2377476 hits did occur until yesterday. References 1. http://www.sandpile.org/misc/addanad.shtml 2. http://www.asus.com.tw/ 3. http://www.sandpile.org/misc/mail.shtml 4. http://www.asus.com.tw/ 5. http://www.sandpile.org/misc/news.shtml 6. http://www.sandpile.org/misc/search.shtml 7. http://www.sandpile.org/80x86/overview.shtml 8. http://www.sandpile.org/80x86/mcupdate.shtml#overview 9. http://www.sandpile.org/80x86/mcupdate.shtml#history 10. http://www.sandpile.org/80x86/mcupdate.shtml#roots 11. http://www.sandpile.org/80x86/mcupdate.shtml#variations 12. http://www.sandpile.org/80x86/mcupdate.shtml#today 13. http://www.sandpile.org/80x86/mcupdate.shtml#future 14. http://www.sandpile.org/80x86/mcupdate.shtml#questions 15. http://www.techweb.com/se/directlink.cgi?EET19970630S0007 16. http://www.techweb.com/eet/ 17. http://www.intel.com/ 18. http://patent.womplex.ibm.com/ 19. http://www.sandpile.org/80x86/manuals.shtml 20. http://www.sandpile.org/80x86/appendix.shtml 21. http://techweb.cmp.com/eet/column1/wintel12.html 22. http://www.vhdl.org/ 23. http://www.austin.ibm.com/support/micro/help.html 24. http://www.dec.com/ 25. http://www.dec.com/info/DTJ802/DTJ802PF.PDF 26. http://www.dec.com/info/DTJ809/DTJ809PF.PDF 27. http://www.service.digital.com/FX32/ 28. http://www.dec.com/info/DTJ812/DTJ812PF.PDF 29. http://www.chipanalyst.com/mpr/patents/LAWSUIT.PDF 30. http://www.chipanalyst.com/ 31. http://www.amd.com/news/corppr/9619.html 32. http://www.amd.com/ 33. http://www.sandpile.org/80x86/ia32/eflags.shtml 34. http://www.sandpile.org/80x86/ia32/crx.shtml 35. http://www.sandpile.org/80x86/cpuid.shtml 36. http://www.sandpile.org/80x86/nexgen.shtml 37. http://www.amd.com/products/cpg/nx586/support/toolbox.html 38. http://www.sandpile.org/80x86/opcodes2.shtml 39. http://www.cyrix.com/ 40. http://www.chips.ibm.com/ 41. http://www.alternativecpu.com/ 42. ftp://ftp.cyrix.com/TECH/PIPELOOP.EXE 43. http://www.sandpile.org/80x86/ccr.shtml 44. http://www.sandpile.org/80x86/opcodes1.shtml 45. http://www.sandpile.org/80x86/cpuid.shtml#level1 46. http://www.sandpile.org/80x86/msr_p6.shtml 47. http://www.sandpile.org/80x86/wrmsr.shtml 48. http://www.sandpile.org/80x86/cpuid.shtml#level1 49. http://www.sandpile.org/80x86/reset.shtml 50. http://www.cs.cmu.edu/afs/cs.cmu.edu/user/ralf/pub/WWW/ 51. http://www.imes.com/page4.html 52. http://www.imes.com/ 53. http://patent.womplex.ibm.com/details?patent_number=5574927 54. http://www.sandpile.org/80x86/ia64/index.shtml 55. http://www.sandpile.org/80x86/80x86.shtml 56. http://www.sandpile.org/80x86/bugs_p5.shtml 57. ftp://download.intel.com/enduser_reseller/overdrive_processors/FPUWP.PDF 58. http://www.sandpile.org/80x86/bugs_p6.shtml 59. http://www.sandpile.org/80x86/bugs_p2.shtml 60. ftp://download.intel.com/design/pentiumii/manuals/24281603.pdf 61. http://www.sandpile.org/80x86/ev_p6.shtml 62. http://www.techweb.com/se/directlink.cgi?EET19970714S0016 63. http://www.techweb.com/eet/ 64. http://www.austin.ibm.com/support/micro/ 65. http://www.sandpile.org/misc/mail.shtml 66. ftp://ftp.einsteinscomputer.com/pub/intel/p6/ 67. http://www.sandpile.org/80x86/mcupdate/update20.zip 68. ftp://ftp.sandpile.org/mcupdate/update20.zip 69. http://www.sandpile.org/80x86/mcupdate/update32.zip 70. ftp://ftp.sandpile.org/mcupdate/update32.zip 71. http://www.sandpile.org/80x86/index.shtml