Geoff Chappell - Software Analyst
This article was x86-specific when written about Windows Vista. It never has got properly attended to for later versions or for 64-bit Windows, despite continuing interest and occasional attempts. Use with caution. If you need more up-to-date information, try getting it from Microsoft.
The MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED bug check reports that one processor differs too much from others.
The summary that Microsoft offers to programmers through the !analyze debugger extension command is:
The system has multiple processors, but they are asymmetric in relation to one another. In order to be symmetric all processors must be of the same type and level. For example, trying to mix a Pentium level processor with an 80486 would cause this bug check.
The MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED bug check can occur in all known versions, i.e., 3.10 and higher.
The MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED bug check is documented. Even today, 7th July 2020, Microsoft’s documentation says this bug check has no parameters.
Microsoft’s documentation was correct when it was written. Before version 4.0, this bug check does indeed have no parameters. Even then, the documentation’s “all processors must be of the same type and level” was at best a general intention. The last version for which it is explicitly true is 3.10. It requires that all processors have exactly the same CpuType, meaning roughly what the Intel literature refers to as the family, in their KPRCB and that either all have a numeric coprocessor or none have. Versions 3.50 and 3.51 make a point of accepting processors from different families except to reject any multi-processor configuration that includes an 80386. This provision is dropped from later versions, which reject even a lone 80386 (and raise the UNSUPPORTED_PROCESSOR bug check without multi-processor implications being yet an issue).
In version 4.0, the kernel changed completely to matching processors not by their “type and level”, as documented, but by the presence or absence of particular features. Access to a numeric coprocessor remains as one feature to test for and require agreement on. Most others are determined from the cpuid instruction, especially from the feature flags that are returned in edx from cpuid leaf 1. Beware, though, that feature identification can get complex, with special cases for such things as vendors, models and steppings—which are all ignored for the rest of this note!
Much as the early versions accept a mixture of families, later versions can work with some mixtures of features. This perhaps requires some explanation. Windows has long been documented as being designed for symmetric multiprocessor (SMP) systems. This is often expressed as meaning that all processors must be identical, but this is correct only very roughly. What the kernel requires is not that all the processors be identical but that they can all be used identically.
The kernel can tolerate some differences by the simple expedient of working to the lowest capability. If a feature is not supported on all processors, it simply doesn’t get used for any. For some features, however, the kernel’s support for the feature, or its accommodation of the feature’s absence, is already relied on for the boot processor by the time the kernel starts other processors. If reconfiguring for a difference would be impossible, difficult or too much trouble, then the difference is fatal and is reported as bug check 0x3E.
In versions 4.0 to 6.1 inclusive, reporting what it is that differs too much between the processors is relatively straightforward. The first feature that is noticed to be fatally different between processors is indicated by the 1st bug-check parameter:
Bug Check Code: | MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED (0x3E) |
1st Parameter: | 0x00000010 for difference in PGE support (4.0
and higher); 0x00000040 for difference in MTRR support (5.0 and higher); 0x00000080 for difference in CX8 support (4.0 and higher); 0x00000387 for difference in whether numerical coprocessor is present (4.0 to 6.1); 0x00000400 for difference in PAT support (5.0 and higher); 0x00000800 for difference in FXSR support (5.0 and higher) or value of mxcsr (5.1 and higher); 0x00002000 for difference in SSE support (5.0 and higher); 0x00040000 for difference in CLFSH support (6.0 and higher); 0x20000000 for difference in Execute-Disable support (some 5.1, some 5.2, and 6.0 and higher) |
2nd Parameter: | expected mxcsr value, if difference is in
value of mxcsr (5.1 and higher); 0, otherwise |
3rd Parameter: | rejected mxcsr value, if difference is in
value of mxcsr (5.1 and higher); 0, otherwise |
4th Parameter: | 0 |
The “some versions” of 5.1 and 5.2 start with Windows XP SP2 and Windows Server 2003 SP1, respectively.
The order in which differences are noticed perhaps does not matter. As it happens, the features that are noticed first allow for no mix-and-match. They must either be present for all processors or for none:
For FXSR support, the mxcsr register must be consistent across all processors. When inconsistent, the expected and rejected values are given as the 2nd and 3rd bug-check parameters.
For most features, the rule is that if the boot processor has the feature, then so must all other processors:
For MTRR support, the Model-Specific Register (MSR) MTRRcap (0xFE) must be consistent across all processors. Inconsistency of the model-specific register MTRRdefType (0x2FF) is tested but tolerated, albeit with a complaint to the debugger even in the free build:
KiInitializeMTRR: MTRR_MSR_DEFAULT is not consistent between processors.
If the boot processor supports CLFLUSH, then not only must all processors support the instruction, they must all have the same line size (which cpuid leaf 1 returns in bits 8 to 15 of ebx).
Version 6.2 adds
Bug Check Code: | MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED (0x3E) |
1st Parameter: | address of KPRCB |
2nd Parameter: | number of processors in package |
3rd Parameter: | number of cores per physical processor |
4th Parameter: | number of logical processors per core |
Versions 4.0 and 5.0 have code to raise this bug check for mis-matched CX8 support even while initialising for the boot processor, i.e., without yet knowing whether a second processor exists, let alone whether it has CX8 support. In version 4.0 before Windows NT 4.0 SP6, this allows the occurrence of this bug check even on machines that have only one processor.
This curious effect arises because (in these early builds only) the kernel tests for CX8 support in two different ways. A first test, applied only to the boot processor, is very rough and ready. It asks only whether the CPUID bit in the eflags register can be changed, as assurance that there is a cpuid instruction, and then whether the CX8 bit is set in the cpuid feature flags. A later test, applied to each processor in turn, including the boot processor, does not recognise the CX8 bit if either of the following is true:
If the boot processor has CX8 support according to the first test but not the second, then the boot processor is rejected for its supposed contribution to an unsupported multiprocessor configuration.
Evidently this did have real-world occurrence in the late 1990s for users of processors whose manufacturer was not Intel, AMD or Cyrix. In the Knowledge Base article CMPXCHG8B CPUs in Non-Intel/AMD x86 Compatibles Not Supported (apparently long removed from Microsoft’s website), Microsoft is at best disingenuous in suggesting that the first test is only a rough guess from the processor’s “type”, which a second test must “verify” by querying for “specific features”: both tests are specifically for the CX8 feature; what’s specific about one but not the other is to test for particular manufacturers. Whoever wrote the text of Microsoft’s article surely knew this, as did whatever manager approved the text for publication.
Though Windows NT 4.0 SP4 fixed this part of the second test, it left the other for two more service packs. This likely did not have real-world occurrence at the time. It perhaps can’t even have been seen internally at Microsoft at the time. It will instead have shown years later when processors that have a cpuid leaf higher than 3 finally became available and programmers, testers and the merely curious tried to run Windows NT 4.0 (except for its last service pack) on their new processors.
TO BE DONE?