|
Erratum Technical Description Updated Nov. 20 1997
Problem: The CMPXCHG8B
instruction compares an 8 byte value in EDX and EAX with an 8 byte value in memory (the
destination operand). The only valid destination operands for this instruction are memory
operands. If the destination operand is a register the processor should generate an
invalid opcode exception, execution of the CMPXCHG8B instruction should be halted and the
processor should execute the invalid opcode exception handler. This erratum occurs if the
LOCK prefix is used with the CMPXCHG8B instruction with an (invalid) register destination
operand. In this case, the processor may not start execution of the invalid opcode
exception handler because the bus is locked. This results in a system hang.
Implication: If an (invalid) register destination
operand is used with the CMPXCHG8B instruction and the LOCK prefix, the system may hang.
No memory data is corrupted and the user can perform a system reset to return to normal
operation. Note that the specific invalid code sequence necessary for this erratum to
occur is not normally generated in the course of programming nor is such a sequence
generated by commercially available software.
This erratum only applies to Pentium®
processors, Pentium processors with MMX™ technology, Pentium OverDrive®
processors and Pentium OverDrive processors with MMX technology. Pentium Pro processors,
Pentium II Processors and i486™ and earlier processors are not affected.
Workaround: There are two workarounds for this erratum for
protected mode operating systems. Both workarounds generate a page fault when the invalid
opcode exception occurs. In both cases, the page fault will be serviced before the invalid
opcode exception and thus prevent the lock condition from occurring. The implementation
details will differ depending on the operating system. Use one of the following:
- The first part of this workaround sets the first 7 entries (0-6) of the Interrupt
Descriptor Table (IDT) in a non-writeable page. When the invalid opcode exception
(exception 6) occurs due to the locked CMPXCHG8B instruction with an invalid register
destination (and only then), the processor will generate a page fault if it does not have
write access to the page containing entry 6 of the IDT. The second part of this workaround
modifies the page fault handler to recognize and correctly dispatch the invalid opcode
exceptions that are now routed through the page fault handler.
Part I, IDT page access
- Mark the page containing the first seven entries (0-6) of the IDT as read only by
setting bit 1 of the page table entry to zero. Also set CR0.WP (bit 16) to 1. Now when the
invalid opcode exception occurs on the locked CMPXCHG8B instruction, the processor will
trigger a page fault since it does not have write access to the page containing entry 6 of
the IDT. This page fault prevents the bus lock condition and gives the OS complete control
to process the invalid operand exception as appropriate. Note that exception 6 is the
invalid opcode exception, so with this scheme an OS has complete control of any program
executing an invalid CMPXCHG8B instruction.
- Optional: If updates to entries 7-255 of the IDT occur during the course of normal
operation, page faults should be avoided on writes to these IDT entries. These page faults
can be avoided by aligning the IDT across a 4KB page boundary such that the first seven
entries (0-6) of the IDT are on the first read only page and the remaining entries are on
a read/writeable page.
Part II, Page Fault
Handler Modifications
- Modify the page fault handler to calculate which exception caused the page fault using
the fault address in CR2. If the error code on the stack indicates the exception occurred
from ring 0 and if the address corresponds to the invalid opcode exception, then pop the
error code off the stack and jump to the invalid opcode exception handler. Otherwise
continue with the normal page fault handler.
OR
- This workaround has two parts. First, the Interrupt Descriptor Table (IDT) is aligned
such that any invalid opcode exception will cause a page fault (due to the page not being
present). Second, the page fault handler is modified to recognize and correctly dispatch
the invalid opcode exception and certain other exceptions that are now routed through the
page fault handler.
Part I, IDT Alignment:
- Align the Interrupt Descriptor Table (IDT) such that it spans a 4KB page boundary by
placing the first entry starting 56 bytes from the end of the first 4KB page. This places
the first seven entries (0-6) on the first 4KB page, and the remaining entries on the
second page.
- The page containing the first seven entries of the IDT must not have a mapping in the OS
page tables. This will cause any of exceptions 0-6 to generate a page not present fault. A
page fault prevents the bus lock condition and gives the OS complete control to process
these exceptions as appropriate. Note that exception 6 is the invalid opcode exception, so
with this scheme an OS has complete control of any program executing an invalid CMPXCHG8B
instruction.
Part II, Page Fault Handler Modifications:
- Recognize accesses to the first page of the IDT by testing the fault address in CR2.
Page not present faults on other addresses can be processed normally.
- For page not present faults on the first page of the IDT, the OS must recognize and
dispatch the exception which caused the page not present fault. Before proceeding, test
the fault address in CR2 to determine if it is in the address range corresponding to
exceptions 0-6.
- Calculate which exception caused the page not present fault from the fault address in
CR2.
- Depending on the operating system, certain privilege level checks may be required, along
with adjustments to the interrupt stack.
- Jump to the normal handler for the appropriate exception.
Both workarounds should only be implemented on Intel processors that return Family=5
via the CPUID instruction.
75/90/100/120/133/150/166/200 MHz Pentium®
Processors and 120/133/150/166/200/233 MHz Pentium Processors with MMX™ Technology
|
No. |
B1 |
B3 |
B5 |
C2 |
mA1 |
cB1 |
mcB1 |
cC0 |
mA4 |
mcC0 |
E0 |
xA3 |
mxA3 |
xB1 |
mxB1 |
myA0 |
ERRATA |
| 81 |
X |
X |
X |
X |
X |
X |
X |
X |
X |
X |
X |
X |
X |
X |
X |
X |
Invalid operand
with locked CMPXCHG8B instruction |
|
60 MHz and 66 MHz Pentium® Processors
|
No. |
B1 |
C1 |
D1 |
ERRATA |
| 52 |
X |
X |
X |
Invalid operand
with locked CMPXCHG8B instruction |
|
63/83/120/125/133/150/166 MHz Pentium®
OverDrive® Processors and 125/150/166/180/200 MHz Pentium OverDrive Processors
with MMX™ Technology
|
No. |
B1 |
B2 |
C0 |
tA0 |
aC0 |
oxA3 |
oxB1 |
ERRATA |
| 70 |
X |
X |
X |
X |
X |
X |
X |
Invalid operand
with locked CMPXCHG8B instruction |
|
This applies to:
|