Intel 64 and IA-32 Architectures. Software Developer’s Manual (Collection, 2023) - page 4

 

  Index      Manuals     Intel 64 and IA-32 Architectures. Software Developer’s Manual (Collection, 2023)

 

Search            copyright infringement  

 

   

 

   

 

Content      ..     2      3      4      5     ..

 

 

 

Intel 64 and IA-32 Architectures. Software Developer’s Manual (Collection, 2023) - page 4

 

 

SYSTEM ARCHITECTURE OVERVIEW
Table 2-3. Summary of System Instructions (Contd.)
Useful to
Protected from
Instruction
Description
Application?
Application?
NOTES:
1. Useful to application programs running at a CPL of 1 or 2.
2. The TSD and PCE flags in control register CR4 control access to these instructions by application programs running at a CPL of 3.
3. These instructions were introduced into the IA-32 Architecture with the Pentium processor.
4. This instruction was introduced into the IA-32 Architecture with the Pentium Pro processor and the Pentium processor with MMX technol-
ogy.
5. This instruction is not supported in 64-bit mode.
6. Application uses XGETBV to query which set of processor extended states are enabled.
7. RDTSCP is introduced in Intel Core i7 processor.
2.8.1
Loading and Storing System Registers
The GDTR, LDTR, IDTR, and TR registers each have a load and store instruction for loading data into and storing
data from the register:
LGDT (Load GDTR Register) - Loads the GDT base address and limit from memory into the GDTR register.
SGDT (Store GDTR Register) - Stores the GDT base address and limit from the GDTR register into memory.
LIDT (Load IDTR Register) - Loads the IDT base address and limit from memory into the IDTR register.
SIDT (Store IDTR Register) - Stores the IDT base address and limit from the IDTR register into memory.
LLDT (Load LDTR Register) - Loads the LDT segment selector and segment descriptor from memory into
the LDTR. (The segment selector operand can also be located in a general-purpose register.)
SLDT (Store LDTR Register) - Stores the LDT segment selector from the LDTR register into memory or a
general-purpose register.
LTR (Load Task Register) - Loads segment selector and segment descriptor for a TSS from memory into the
task register. (The segment selector operand can also be located in a general-purpose register.)
STR (Store Task Register) - Stores the segment selector for the current task TSS from the task register into
memory or a general-purpose register.
The LMSW (load machine status word) and SMSW (store machine status word) instructions operate on bits 0
through 15 of control register CR0. These instructions are provided for compatibility with the 16-bit Intel 286
processor. Programs written to run on 32-bit IA-32 processors should not use these instructions. Instead, they
should access the control register CR0 using the MOV CR instruction.
The CLTS (clear TS flag in CR0) instruction is provided for use in handling a device-not-available exception (#NM)
that occurs when the processor attempts to execute a floating-point instruction when the TS flag is set. This
instruction allows the TS flag to be cleared after the x87 FPU context has been saved, preventing further #NM
exceptions. See Section 2.5, “Control Registers,” for more information on the TS flag.
The control registers (CR0, CR1, CR2, CR3, CR4, and CR8) are loaded using the MOV instruction. The instruction
loads a control register from a general-purpose register or stores the content of a control register in a general-
purpose register.
2.8.2
Verifying of Access Privileges
The processor provides several instructions for examining segment selectors and segment descriptors to determine
if access to their associated segments is allowed. These instructions duplicate some of the automatic access rights
and type checking done by the processor, thus allowing operating-system or executive software to prevent excep-
tions from being generated.
The ARPL (adjust RPL) instruction adjusts the RPL (requestor privilege level) of a segment selector to match that of
the program or procedure that supplied the segment selector. See Section 5.10.4, “Checking Caller Access Privi-
leges (ARPL Instruction),” for a detailed explanation of the function and use of this instruction. Note that ARPL is
not supported in 64-bit mode.
2-24
Vol. 3A
SYSTEM ARCHITECTURE OVERVIEW
The LAR (load access rights) instruction verifies the accessibility of a specified segment and loads access rights
information from the segment’s segment descriptor into a general-purpose register. Software can then examine
the access rights to determine if the segment type is compatible with its intended use. See Section 5.10.1,
“Checking Access Rights (LAR Instruction),” for a detailed explanation of the function and use of this instruction.
The LSL (load segment limit) instruction verifies the accessibility of a specified segment and loads the segment
limit from the segment’s segment descriptor into a general-purpose register. Software can then compare the
segment limit with an offset into the segment to determine whether the offset lies within the segment. See Section
5.10.3, “Checking That the Pointer Offset Is Within Limits (LSL Instruction),” for a detailed explanation of the func-
tion and use of this instruction.
The VERR (verify for reading) and VERW (verify for writing) instructions verify if a selected segment is readable or
writable, respectively, at a given CPL. See Section 5.10.2, “Checking Read/Write Rights (VERR and VERW Instruc-
tions),” for a detailed explanation of the function and use of these instructions.
2.8.3
Loading and Storing Debug Registers
Internal debugging facilities in the processor are controlled by a set of 8 debug registers (DR0-DR7). The MOV
instruction allows setup data to be loaded to and stored from these registers.
On processors that support Intel 64 architecture, debug registers DR0-DR7 are 64 bits. In 32-bit modes and
compatibility mode, writes to a debug register fill the upper 32 bits with zeros. Reads return the lower 32 bits. In
64-bit mode, the upper 32 bits of DR6-DR7 are reserved and must be written with zeros. Writing one to any of the
upper 32 bits causes an exception, #GP(0).
In 64-bit mode, MOV DRn instructions read or write all 64 bits of a debug register (operand-size prefixes are
ignored). All 64 bits of DR0-DR3 are writable by software. However, MOV DRn instructions do not check that
addresses written to DR0-DR3 are in the limits of the implementation. Address matching is supported only on valid
addresses generated by the processor implementation.
2.8.4
Invalidating Caches and TLBs
The processor provides several instructions for use in explicitly invalidating its caches and TLB entries. The INVD
(invalidate cache with no writeback) instruction invalidates all data and instruction entries in the internal caches
and sends a signal to the external caches indicating that they should also be invalidated.
The WBINVD (invalidate cache with writeback) instruction performs the same function as the INVD instruction,
except that it writes back modified lines in its internal caches to memory before it invalidates the caches. After
invalidating the caches local to the executing logical processor or processor core, WBINVD signals caches higher in
the cache hierarchy (caches shared with the invalidating logical processor or core) to write back any data they have
in modified state at the time of instruction execution and to invalidate their contents.
Note, non-shared caches may not be written back nor invalidated. In Figure 2-10 below, if code executing on either
LP0 or LP1 were to execute a WBINVD, the shared L1 and L2 for LP0/LP1 will be written back and invalidated as will
the shared L3. However, the L1 and L2 caches not shared with LP0 and LP1 will not be written back nor invalidated.
Vol. 3A
2-25
SYSTEM ARCHITECTURE OVERVIEW
Not Written back and
not Invalidated
Logical Processors
LP0
LP1
LP2
LP3
LP4
LP5
LP6
LP7
L1 & L2 Cache
Written back
& Invalidated
Execution Engine
L3 Cache
Written back and Invalidated
Uncore
QPI
DDR3
Figure 2-10. WBINVD Invalidation of Shared and Non-Shared Cache Hierarchy
The INVLPG (invalidate TLB entry) instruction invalidates (flushes) the TLB entry for a specified page.
2.8.5
Controlling the Processor
The HLT (halt processor) instruction stops the processor until an enabled interrupt (such as NMI or SMI, which are
normally enabled), a debug exception, the BINIT# signal, the INIT# signal, or the RESET# signal is received. The
processor generates a special bus cycle to indicate that the halt mode has been entered.
Hardware may respond to this signal in a number of ways. An indicator light on the front panel may be turned on.
An NMI interrupt for recording diagnostic information may be generated. Reset initialization may be invoked (note
that the BINIT# pin was introduced with the Pentium Pro processor). If any non-wake events are pending during
shutdown, they will be handled after the wake event from shutdown is processed (for example, A20M# interrupts).
The LOCK prefix invokes a locked (atomic) read-modify-write operation when modifying a memory operand. This
mechanism is used to allow reliable communications between processors in multiprocessor systems, as described
below:
In the Pentium processor and earlier IA-32 processors, the LOCK prefix causes the processor to assert the
LOCK# signal during the instruction. This always causes an explicit bus lock to occur.
In the Pentium 4, Intel Xeon, and P6 family processors, the locking operation is handled with either a cache lock
or bus lock. If a memory access is cacheable and affects only a single cache line, a cache lock is invoked and
the system bus and the actual memory location in system memory are not locked during the operation. Here,
other Pentium 4, Intel Xeon, or P6 family processors on the bus write-back any modified data and invalidate
their caches as necessary to maintain system memory coherency. If the memory access is not cacheable
and/or it crosses a cache line boundary, the processor’s LOCK# signal is asserted and the processor does not
respond to requests for bus control during the locked operation.
The RSM (return from SMM) instruction restores the processor (from a context dump) to the state it was in prior to
a system management mode (SMM) interrupt.
2.8.6
Reading Performance-Monitoring and Time-Stamp Counters
The RDPMC (read performance-monitoring counter) and RDTSC (read time-stamp counter) instructions allow
application programs to read the processor’s performance-monitoring and time-stamp counters, respectively.
Processors based on Intel NetBurst® microarchitecture have eighteen 40-bit performance-monitoring counters; P6
family processors have two 40-bit counters. Intel Atom® processors and most of the processors based on the Intel
Core microarchitecture support two types of performance monitoring counters: programmable performance coun-
ters similar to those available in the P6 family, and three fixed-function performance monitoring counters. Details
2-26
Vol. 3A
SYSTEM ARCHITECTURE OVERVIEW
of programmable and fixed-function performance monitoring counters for each processor generation are described
in Chapter 20, “Performance Monitoring.”
The programmable performance counters can support counting either the occurrence or duration of events. Events
that can be monitored on programmable counters generally are model specific (except for architectural perfor-
mance events enumerated by CPUID leaf 0AH); they may include the number of instructions decoded, interrupts
received, or the number of cache loads. Individual counters can be set up to monitor different events. Use the
system instruction WRMSR to set up values in one of the IA32_PERFEVTSELx MSR, in one of the 45 ESCRs and one
of the 18 CCCR MSRs (for Pentium 4 and Intel Xeon processors); or in the PerfEvtSel0 or the PerfEvtSel1 MSR (for
the P6 family processors). The RDPMC instruction loads the current count from the selected counter into the
EDX:EAX registers.
Fixed-function performance counters record only specific events that are defined at: https://perfmon-
events.intel.com/, and the width/number of fixed-function counters are enumerated by CPUID leaf 0AH.
The time-stamp counter is a model-specific 64-bit counter that is reset to zero each time the processor is reset. If
not reset, the counter will increment ~9.5 x 1016 times per year when the processor is operating at a clock rate
of 3GHz. At this clock frequency, it would take over 190 years for the counter to wrap around. The RDTSC
instruction loads the current count of the time-stamp counter into the EDX:EAX registers.
See Section 20.1, “Performance Monitoring Overview,” and Section 18.17, “Time-Stamp Counter,” for more infor-
mation about the performance monitoring and time-stamp counters.
The RDTSC instruction was introduced into the IA-32 architecture with the Pentium processor. The RDPMC instruc-
tion was introduced into the IA-32 architecture with the Pentium Pro processor and the Pentium processor with
MMX technology. Earlier Pentium processors have two performance-monitoring counters, but they can be read only
with the RDMSR instruction, and only at privilege level 0.
2.8.6.1
Reading Counters in 64-Bit Mode
In 64-bit mode, RDTSC operates the same as in protected mode. The count in the time-stamp counter is stored in
EDX:EAX (or RDX[31:0]:RAX[31:0] with RDX[63:32]:RAX[63:32] cleared).
RDPMC requires an index to specify the offset of the performance-monitoring counter. In 64-bit mode for Pentium
4 or Intel Xeon processor families, the index is specified in ECX[30:0]. The current count of the performance-moni-
toring counter is stored in EDX:EAX (or RDX[31:0]:RAX[31:0] with RDX[63:32]:RAX[63:32] cleared).
2.8.7
Reading and Writing Model-Specific Registers
The RDMSR (read model-specific register) and WRMSR (write model-specific register) instructions allow a
processor’s 64-bit model-specific registers (MSRs) to be read and written, respectively. The MSR to be read or
written is specified by the value in the ECX register.
RDMSR reads the value from the specified MSR to the EDX:EAX registers; WRMSR writes the value in the EDX:EAX
registers to the specified MSR. RDMSR and WRMSR were introduced into the IA-32 architecture with the Pentium
processor.
See Section 10.4, “Model-Specific Registers (MSRs),” for more information.
2.8.7.1
Reading and Writing Model-Specific Registers in 64-Bit Mode
RDMSR and WRMSR require an index to specify the address of an MSR. In 64-bit mode, the index is 32 bits; it is
specified using ECX.
2.8.8
Enabling Processor Extended States
The XSETBV instruction is required to enable OS support of individual processor extended states in XCR0 (see
Section 2.6).
Vol. 3A
2-27
SYSTEM ARCHITECTURE OVERVIEW
2-28
Vol. 3A
10.Updates to Chapter 9, Volume 3A
Change bars and violet text show changes to Chapter 9 of the Intel® 64 and IA-32 Architectures Software
Developer’s Manual, Volume 3A: System Programming Guide, Part 1.
------------------------------------------------------------------------------------------
Changes to this chapter:
• Added a statement to Section 9.1.2.3, “Features to Disable Bus Locks,” to indicate processor behavior when
both bus lock features are enabled.
Intel® 64 and IA-32 Architectures Software Developer’s Manual Documentation Changes
13
CHAPTER 9
MULTIPLE-PROCESSOR MANAGEMENT
The Intel 64 and IA-32 architectures provide mechanisms for managing and improving the performance of multiple
processors connected to the same system bus. These include:
Bus locking and/or cache coherency management for performing atomic operations on system memory.
Serializing instructions.
An advance programmable interrupt controller (APIC) located on the processor chip (see Chapter 11,
“Advanced Programmable Interrupt Controller (APIC)”). This feature was introduced by the Pentium processor.
A second-level cache (level 2, L2). For the Pentium 4, Intel Xeon, and P6 family processors, the L2 cache is
included in the processor package and is tightly coupled to the processor. For the Pentium and Intel486
processors, pins are provided to support an external L2 cache.
A third-level cache (level 3, L3). For Intel Xeon processors, the L3 cache is included in the processor package
and is tightly coupled to the processor.
Intel Hyper-Threading Technology. This extension to the Intel 64 and IA-32 architectures enables a single
processor core to execute two or more threads concurrently (see Section 9.5, “Intel® Hyper-Threading
Technology and Intel® Multi-Core Technology”).
These mechanisms are particularly useful in symmetric-multiprocessing (SMP) systems. However, they can also be
used when an Intel 64 or IA-32 processor and a special-purpose processor (such as a communications, graphics,
or video processor) share the system bus.
These multiprocessing mechanisms have the following characteristics:
To maintain system memory coherency - When two or more processors are attempting simultaneously to
access the same address in system memory, some communication mechanism or memory access protocol
must be available to promote data coherency and, in some instances, to allow one processor to temporarily lock
a memory location.
To maintain cache consistency - When one processor accesses data cached on another processor, it must not
receive incorrect data. If it modifies data, all other processors that access that data must receive the modified
data.
To allow predictable ordering of writes to memory - In some circumstances, it is important that memory writes
be observed externally in precisely the same order as programmed.
To distribute interrupt handling among a group of processors - When several processors are operating in a
system in parallel, it is useful to have a centralized mechanism for receiving interrupts and distributing them to
available processors for servicing.
To increase system performance by exploiting the multi-threaded and multi-process nature of contemporary
operating systems and applications.
The caching mechanism and cache consistency of Intel 64 and IA-32 processors are discussed in Chapter 12. The
APIC architecture is described in Chapter 11. Bus and memory locking, serializing instructions, memory ordering,
and Intel Hyper-Threading Technology are discussed in the following sections.
9.1
LOCKED ATOMIC OPERATIONS
The 32-bit IA-32 processors support locked atomic operations on locations in system memory. These operations
are typically used to manage shared data structures (such as semaphores, segment descriptors, system segments,
or page tables) in which two or more processors may try simultaneously to modify the same field or flag. The
processor uses three interdependent mechanisms for carrying out locked atomic operations:
Guaranteed atomic operations.
Bus locking, using the LOCK# signal and the LOCK instruction prefix.
Vol. 3A
9-1
MULTIPLE-PROCESSOR MANAGEMENT
Cache coherency protocols that ensure that atomic operations can be carried out on cached data structures
(cache lock); this mechanism is present in the Pentium 4, Intel Xeon, and P6 family processors.
These mechanisms are interdependent in the following ways. Certain basic memory transactions (such as reading
or writing a byte in system memory) are always guaranteed to be handled atomically. That is, once started, the
processor guarantees that the operation will be completed before another processor or bus agent is allowed access
to the memory location. The processor also supports bus locking for performing selected memory operations (such
as a read-modify-write operation in a shared area of memory) that typically need to be handled atomically, but are
not automatically handled this way. Because frequently used memory locations are often cached in a processor’s L1
or L2 caches, atomic operations can often be carried out inside a processor’s caches without asserting the bus lock.
Here the processor’s cache coherency protocols ensure that other processors that are caching the same memory
locations are managed properly while atomic operations are performed on cached memory locations.
NOTE
Where there are contested lock accesses, software may need to implement algorithms that ensure
fair access to resources in order to prevent lock starvation. The hardware provides no resource that
guarantees fairness to participating agents. It is the responsibility of software to manage the
fairness of semaphores and exclusive locking functions.
The mechanisms for handling locked atomic operations have evolved with the complexity of IA-32 processors. More
recent IA-32 processors (such as the Pentium 4, Intel Xeon, and P6 family processors) and Intel 64 provide a more
refined locking mechanism than earlier processors. These mechanisms are described in the following sections.
9.1.1
Guaranteed Atomic Operations
The Intel486 processor (and newer processors since) guarantees that the following basic memory operations will
always be carried out atomically:
Reading or writing a byte.
Reading or writing a word aligned on a 16-bit boundary.
Reading or writing a doubleword aligned on a 32-bit boundary.
The Pentium processor (and newer processors since) guarantees that the following additional memory operations
will always be carried out atomically:
Reading or writing a quadword aligned on a 64-bit boundary.
16-bit accesses to uncached memory locations that fit within a 32-bit data bus.
The P6 family processors (and newer processors since) guarantee that the following additional memory operation
will always be carried out atomically:
Unaligned 16-, 32-, and 64-bit accesses to cached memory that fit within a cache line.
Processors that enumerate support for Intel® AVX (by setting the feature flag CPUID.01H:ECX.AVX[bit 28]) guar-
antee that the 16-byte memory operations performed by the following instructions will always be carried out atom-
ically:
MOVAPD, MOVAPS, and MOVDQA.
VMOVAPD, VMOVAPS, and VMOVDQA when encoded with VEX.128.
VMOVAPD, VMOVAPS, VMOVDQA32, and VMOVDQA64 when encoded with EVEX.128 and k0 (masking
disabled).
(Note that these instructions require the linear addresses of their memory operands to be 16-byte aligned.)
Accesses to cacheable memory that are split across cache lines and page boundaries are not guaranteed to be
atomic by the Intel Core 2 Duo, Intel Atom, Intel Core Duo, Pentium M, Pentium 4, Intel Xeon, P6 family, Pentium,
and Intel486 processors. The Intel Core 2 Duo, Intel Atom, Intel Core Duo, Pentium M, Pentium 4, Intel Xeon, and
P6 family processors provide bus control signals that permit external memory subsystems to make split accesses
atomic; however, nonaligned data accesses will seriously impact the performance of the processor and should be
avoided.
9-2
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
Except as noted above, an x87 instruction or an SSE instruction that accesses data larger than a quadword may be
implemented using multiple memory accesses. If such an instruction stores to memory, some of the accesses may
complete (writing to memory) while another causes the operation to fault for architectural reasons (e.g., due an
page-table entry that is marked “not present”). In this case, the effects of the completed accesses may be visible
to software even though the overall instruction caused a fault. If TLB invalidation has been delayed (see Section
4.10.4.4), such page faults may occur even if all accesses are to the same page.
9.1.2
Bus Locking
Intel 64 and IA-32 processors provide a LOCK# signal that is asserted automatically during certain critical memory
operations to lock the system bus or equivalent link. Assertion of this signal is called a bus lock. While this output
signal is asserted, requests from other processors or bus agents for control of the bus are blocked. Software can
specify other occasions when the LOCK semantics are to be followed by prepending the LOCK prefix to an instruc-
tion.
In the case of the Intel386, Intel486, and Pentium processors, explicitly locked instructions will result in the asser-
tion of the LOCK# signal. It is the responsibility of the hardware designer to make the LOCK# signal available in
system hardware to control memory accesses among processors.
For the P6 and more recent processor families, if the memory area being accessed is cached internally in the
processor, the LOCK# signal is generally not asserted; instead, locking is only applied to the processor’s caches
(see Section 9.1.4, “Effects of a LOCK Operation on Internal Processor Caches”). These processors will assert a bus
lock for a locked access in either of the following situations: (1) the access is to multiple cache lines (a split lock);
or (2) the access uses a memory type other than WB (a UC lock)1.
9.1.2.1
Automatic Locking
The operations on which the processor automatically follows the LOCK semantics are as follows:
When executing an XCHG instruction that references memory.
When switching to a task, the processor tests and sets the busy flag in the type field of the TSS descriptor. To
ensure that two processors do not switch to the same task simultaneously, the processor follows the LOCK
semantics while testing and setting this flag.
When loading a segment descriptor, the processor sets the accessed flag in the segment descriptor if the flag is
clear. During this operation, the processor follows the LOCK semantics so that the descriptor will not be
modified by another processor while it is being updated. For this action to be effective, operating-system
procedures that update descriptors should use the following steps:
- Use a locked operation to modify the access-rights byte to indicate that the segment descriptor is not-
present, and specify a value for the type field that indicates that the descriptor is being updated.
- Update the fields of the segment descriptor. (This operation may require several memory accesses;
therefore, locked operations cannot be used.)
- Use a locked operation to modify the access-rights byte to indicate that the segment descriptor is valid and
present.
- The Intel386 processor always updates the accessed flag in the segment descriptor, whether it is clear or
not. The Pentium 4, Intel Xeon, P6 family, Pentium, and Intel486 processors only update this flag if it is not
already set.
The processor uses locked cycles to set the accessed and dirty flag in paging-structure entries.
After an interrupt request, an interrupt controller may use the data bus to send the interrupt’s vector to the
processor. The processor follows the LOCK semantics during this time to ensure that no other data appears on
the data bus while the vector is being transmitted.
1. The term “UC lock” is used because the most common situation regards accesses to UC memory. Despite the name, locked accesses
to WC, WP, and WT memory also cause bus locks.
Vol. 3A
9-3
MULTIPLE-PROCESSOR MANAGEMENT
9.1.2.2
Software Controlled Bus Locking
To explicitly force the LOCK semantics, software can use the LOCK prefix with the following instructions when they
are used to modify a memory location. An invalid-opcode exception (#UD) is generated when the LOCK prefix is
used with any other instruction or when no write operation is made to memory (that is, when the destination
operand is in a register).
The bit test and modify instructions (BTS, BTR, and BTC).
The exchange instructions (XADD, CMPXCHG, CMPXCHG8B, and CMPXCHG16B).
The LOCK prefix is automatically assumed for XCHG instruction.
The following single-operand arithmetic and logical instructions: INC, DEC, NOT, and NEG.
The following two-operand arithmetic and logical instructions: ADD, ADC, SUB, SBB, AND, OR, and XOR.
A locked instruction is guaranteed to lock only the area of memory defined by the destination operand, but may be
interpreted by the system as a lock for a larger memory area.
Software should access semaphores (shared memory used for signalling between multiple processors) using iden-
tical addresses and operand lengths. For example, if one processor accesses a semaphore using a word access,
other processors should not access the semaphore using a byte access.
NOTE
Do not implement semaphores using the WC memory type. Do not perform non-temporal stores to
a cache line containing a location used to implement a semaphore.
The integrity of a bus lock is not affected by the alignment of the memory field. The LOCK semantics are followed
for as many bus cycles as necessary to update the entire operand. However, it is recommend that locked accesses
be aligned on their natural boundaries for better system performance:
Any boundary for an 8-bit access (locked or otherwise).
16-bit boundary for locked word accesses.
32-bit boundary for locked doubleword accesses.
64-bit boundary for locked quadword accesses.
Locked operations are atomic with respect to all other memory operations and all externally visible events. Only
instruction fetch and page table accesses can pass locked instructions. Locked instructions can be used to synchro-
nize data written by one processor and read by another processor.
For the P6 family processors, locked operations serialize all outstanding load and store operations (that is, wait for
them to complete). This rule is also true for the Pentium 4 and Intel Xeon processors, with one exception. Load
operations that reference weakly ordered memory types (such as the WC memory type) may not be serialized.
Locked instructions should not be used to ensure that data written can be fetched as instructions.
NOTE
The locked instructions for the current versions of the Pentium 4, Intel Xeon, P6 family, Pentium,
and Intel486 processors allow data written to be fetched as instructions. However, Intel
recommends that developers who require the use of self-modifying code use a different synchro-
nizing mechanism, described in the following sections.
9.1.2.3
Features to Disable Bus Locks
Because bus locks may adversely affect performance in certain situations, processors may support two features
that system software can use to disable bus locking. These are called UC-lock disable and split-lock disable.
A processor enumerates support for UC-lock disable by setting bit 4 of the IA32_CORE_CAPABILITIES MSR (MSR
index CFH). Support for split-lock disable is enumerated by IA32_CORE_CAPABILITIES[5].
Software enables UC-lock disable by setting bit 28 of the MSR_MEMORY_CTRL MSR (MSR index 33H). When this bit
is set, a locked access using a memory type other than WB causes a general-protection exception (#GP) with a
zero error code. The locked access does not occur.
9-4
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
Software enables split-lock disable by setting MSR_MEMORY_CTRL[29]. When this bit is set, a locked access to
multiple cache lines causes an alignment-check exception (#AC) with a zero error code.1 The locked access does
not occur.
If both features are enabled, a locked access to multiple cache lines causes #AC(0) regardless of the memory
type(s) being accessed.
While MSR_MEMORY_CTRL is not an architectural MSR, the behavior described above is consistent across
processor models that enumerate the support in IA32_CORE_CAPABILITIES.
In addition to these features that disable bus locks, there are features that allow software to detect when a bus lock
has occurred. See Section 18.3.1.6 for information about OS bus-lock detection and Section 26.2 for information
about the VMM bus-lock detection.
9.1.3
Handling Self- and Cross-Modifying Code
The act of a processor writing data into a currently executing code segment with the intent of executing that data
as code is called self-modifying code. IA-32 processors exhibit model-specific behavior when executing self-
modified code, depending upon how far ahead of the current execution pointer the code has been modified.
As processor microarchitectures become more complex and start to speculatively execute code ahead of the retire-
ment point (as in P6 and more recent processor families), the rules regarding which code should execute, pre- or
post-modification, become blurred. To write self-modifying code and ensure that it is compliant with current and
future versions of the IA-32 architectures, use one of the following coding options:
(* OPTION 1 *)
Store modified code (as data) into code segment;
Jump to new code or an intermediate location;
Execute new code;
(* OPTION 2 *)
Store modified code (as data) into code segment;
Execute a serializing instruction; (* For example, CPUID instruction *)
Execute new code;
The use of one of these options is not required for programs intended to run on the Pentium or Intel486 processors,
but are recommended to ensure compatibility with the P6 and more recent processor families.
Self-modifying code will execute at a lower level of performance than non-self-modifying or normal code. The
degree of the performance deterioration will depend upon the frequency of modification and specific characteristics
of the code.
The act of one processor writing data into the currently executing code segment of a second processor with the
intent of having the second processor execute that data as code is called cross-modifying code. As with self-
modifying code, IA-32 processors exhibit model-specific behavior when executing cross-modifying code,
depending upon how far ahead of the executing processors current execution pointer the code has been modified.
To write cross-modifying code and ensure that it is compliant with current and future versions of the IA-32 archi-
tecture, the following processor synchronization algorithm must be implemented:
(* Action of Modifying Processor *)
Memory_Flag := 0; (* Set Memory_Flag to value other than 1 *)
Store modified code (as data) into code segment;
Memory_Flag := 1;
(* Action of Executing Processor *)
WHILE (Memory_Flag ≠ 1)
Wait for code to update;
1. Other alignment-check exceptions occur only if CR0.AM = 1, EFLAGS.AC = 1, and CPL = 3. The alignment-check exceptions resulting
from split-lock disable may occur even if CR0.AM = 0, EFLAGS.AC = 0, or CPL < 3.
Vol. 3A
9-5
MULTIPLE-PROCESSOR MANAGEMENT
ELIHW;
Execute serializing instruction; (* For example, CPUID instruction *)
Begin executing modified code;
(The use of this option is not required for programs intended to run on the Intel486 processor, but is recommended
to ensure compatibility with the Pentium 4, Intel Xeon, P6 family, and Pentium processors.)
Like self-modifying code, cross-modifying code will execute at a lower level of performance than non-cross-modi-
fying (normal) code, depending upon the frequency of modification and specific characteristics of the code.
The restrictions on self-modifying code and cross-modifying code also apply to the Intel 64 architecture.
9.1.4
Effects of a LOCK Operation on Internal Processor Caches
For the Intel486 and Pentium processors, the LOCK# signal is always asserted on the bus during a LOCK operation,
even if the area of memory being locked is cached in the processor.
For the P6 and more recent processor families, if the area of memory being locked during a LOCK operation is
cached in the processor that is performing the LOCK operation as write-back memory and is completely contained
in a cache line, the processor may not assert the LOCK# signal on the bus. Instead, it will modify the memory loca-
tion internally and allow it’s cache coherency mechanism to ensure that the operation is carried out atomically. This
operation is called “cache locking.” The cache coherency mechanism automatically prevents two or more proces-
sors that have cached the same area of memory from simultaneously modifying data in that area.
9.2
MEMORY ORDERING
The term memory ordering refers to the order in which the processor issues reads (loads) and writes (stores)
through the system bus to system memory. The Intel 64 and IA-32 architectures support several memory-ordering
models depending on the implementation of the architecture. For example, the Intel386 processor enforces
program ordering (generally referred to as strong ordering), where reads and writes are issued on the system
bus in the order they occur in the instruction stream under all circumstances.
To allow performance optimization of instruction execution, the IA-32 architecture allows departures from strong-
ordering model called processor ordering in Pentium 4, Intel Xeon, and P6 family processors. These processor-
ordering variations (called here the memory-ordering model) allow performance enhancing operations such as
allowing reads to go ahead of buffered writes. The goal of any of these variations is to increase instruction execu-
tion speeds, while maintaining memory coherency, even in multiple-processor systems.
Section 9.2.1 and Section 9.2.2 describe the memory-ordering implemented by Intel486, Pentium, Intel Core 2
Duo, Intel Atom, Intel Core Duo, Pentium 4, Intel Xeon, and P6 family processors. Section 9.2.3 gives examples
illustrating the behavior of the memory-ordering model on IA-32 and Intel-64 processors. Section 9.2.4 considers
the special treatment of stores for string operations and Section 9.2.5 discusses how memory-ordering behavior
may be modified through the use of specific instructions.
9.2.1
Memory Ordering in the Intel® Pentium® and Intel486™ Processors
The Pentium and Intel486 processors follow the processor-ordered memory model; however, they operate as
strongly-ordered processors under most circumstances. Reads and writes always appear in programmed order at
the system bus-except for the following situation where processor ordering is exhibited. Read misses are
permitted to go ahead of buffered writes on the system bus when all the buffered writes are cache hits and, there-
fore, are not directed to the same address being accessed by the read miss.
In the case of I/O operations, both reads and writes always appear in programmed order.
Software intended to operate correctly in processor-ordered processors (such as the Pentium 4, Intel Xeon, and P6
family processors) should not depend on the relatively strong ordering of the Pentium or Intel486 processors.
Instead, it should ensure that accesses to shared variables that are intended to control concurrent execution
among processors are explicitly required to obey program ordering through the use of appropriate locking or seri-
alizing operations (see Section 9.2.5, “Strengthening or Weakening the Memory-Ordering Model”).
9-6
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
9.2.2
Memory Ordering in P6 and More Recent Processor Families
The Intel Core 2 Duo, Intel Atom, Intel Core Duo, Pentium 4, and P6 family processors also use a processor-
ordered memory-ordering model that can be further defined as “write ordered with store-buffer forwarding.” This
model can be characterized as follows.
In a single-processor system for memory regions defined as write-back cacheable, the memory-ordering model
respects the following principles (Note the memory-ordering principles for single-processor and multiple-
processor systems are written from the perspective of software executing on the processor, where the term
“processor” refers to a logical processor. For example, a physical processor supporting multiple cores and/or Intel
Hyper-Threading Technology is treated as a multi-processor systems.):
Reads are not reordered with other reads.
Writes are not reordered with older reads.
Writes to memory are not reordered with other writes, with the following exceptions:
- streaming stores (writes) executed with the non-temporal move instructions (MOVNTI, MOVNTQ,
MOVNTDQ, MOVNTPS, and MOVNTPD); and
- string operations (see Section 9.2.4.1).
No write to memory may be reordered with an execution of the CLFLUSH instruction; a write may be reordered
with an execution of the CLFLUSHOPT instruction that flushes a cache line other than the one being written.1
Executions of the CLFLUSH instruction are not reordered with each other. Executions of CLFLUSHOPT that
access different cache lines may be reordered with each other. An execution of CLFLUSHOPT may be reordered
with an execution of CLFLUSH that accesses a different cache line.
Reads may be reordered with older writes to different locations but not with older writes to the same location.
Reads or writes cannot be reordered with I/O instructions, locked instructions, or serializing instructions.
Reads cannot pass earlier LFENCE and MFENCE instructions.
Writes and executions of CLFLUSH and CLFLUSHOPT cannot pass earlier LFENCE, SFENCE, and MFENCE
instructions.
LFENCE instructions cannot pass earlier reads.
SFENCE instructions cannot pass earlier writes or executions of CLFLUSH and CLFLUSHOPT.
MFENCE instructions cannot pass earlier reads, writes, or executions of CLFLUSH and CLFLUSHOPT.
In a multiple-processor system, the following ordering principles apply:
Individual processors use the same ordering principles as in a single-processor system.
Writes by a single processor are observed in the same order by all processors.
Writes from an individual processor are NOT ordered with respect to the writes from other processors.
Memory ordering obeys causality (memory ordering respects transitive visibility).
Any two stores are seen in a consistent order by processors other than those performing the stores
Locked instructions have a total order.
See the example in Figure 9-1. Consider three processors in a system and each processor performs three writes,
one to each of three defined locations (A, B, and C). Individually, the processors perform the writes in the same
program order, but because of bus arbitration and other memory access mechanisms, the order that the three
processors write the individual memory locations can differ each time the respective code sequences are executed
on the processors. The final values in location A, B, and C would possibly vary on each execution of the write
sequence.
The processor-ordering model described in this section is virtually identical to that used by the Pentium and
Intel486 processors. The only enhancements in the Pentium 4, Intel Xeon, and P6 family processors are:
Added support for speculative reads, while still adhering to the ordering principles above.
Store-buffer forwarding, when a read passes a write to the same memory location.
1. Earlier versions of this manual specified that writes to memory may be reordered with executions of the CLFLUSH instruction. No
processors implementing the CLFLUSH instruction allow such reordering.
Vol. 3A
9-7
MULTIPLE-PROCESSOR MANAGEMENT
Out of order store from long string store and string move operations (see Section 9.2.4, “Fast-String Operation
and Out-of-Order Stores,” below).
Order of Writes From Individual Processors
Processor #1
Processor #2
Processor #3
Each processor
Write A.1
Write A.2
Write A.3
is guaranteed to
Write B.1
Write B.2
Write B.3
perform writes in
Write C.1
Write C.2
Write C.3
program order.
Example of order of actual writes
from all processors to memory
Writes are in order
Write A.1
with respect to
Write B.1
individual processes.
Write A.2
Writes from all
Write A.3
processors are
Write C.1
not guaranteed
Write B.2
to occur in a
particular order.
Write C.2
Write B.3
Write C.3
Figure 9-1. Example of Write Ordering in Multiple-Processor Systems
NOTE
In P6 processor family, store-buffer forwarding to reads of WC memory from streaming stores to
the same address does not occur due to errata.
9.2.3
Examples Illustrating the Memory-Ordering Principles
This section provides a set of examples that illustrate the behavior of the memory-ordering principles introduced in
Section 9.2.2. They are designed to give software writers an understanding of how memory ordering may affect the
results of different sequences of instructions.
These examples are limited to accesses to memory regions defined as write-back cacheable (WB). (Section 9.2.3.1
describes other limitations on the generality of the examples.) The reader should understand that they describe
only software-visible behavior. A logical processor may reorder two accesses even if one of examples indicates that
they may not be reordered. Such an example states only that software cannot detect that such a reordering
occurred. Similarly, a logical processor may execute a memory access more than once as long as the behavior
visible to software is consistent with a single execution of the memory access.
9.2.3.1
Assumptions, Terminology, and Notation
As noted above, the examples in this section are limited to accesses to memory regions defined as write-back
cacheable (WB). They apply only to ordinary loads stores and to locked read-modify-write instructions. They do not
necessarily apply to any of the following: out-of-order stores for string instructions (see Section 9.2.4); accesses
with a non-temporal hint; reads from memory by the processor as part of address translation (e.g., page walks);
and updates to segmentation and paging structures by the processor (e.g., to update “accessed” bits).
The principles underlying the examples in this section apply to individual memory accesses and to locked read-
modify-write instructions. The Intel-64 memory-ordering model guarantees that, for each of the following
memory-access instructions, the constituent memory operation appears to execute as a single memory access:
Instructions that read or write a single byte.
Instructions that read or write a word (2 bytes) whose address is aligned on a 2 byte boundary.
9-8
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
Instructions that read or write a doubleword (4 bytes) whose address is aligned on a 4 byte boundary.
Instructions that read or write a quadword (8 bytes) whose address is aligned on an 8 byte boundary.
Any locked instruction (either the XCHG instruction or another read-modify-write instruction with a LOCK prefix)
appears to execute as an indivisible and uninterruptible sequence of load(s) followed by store(s) regardless of
alignment.
Other instructions may be implemented with multiple memory accesses. From a memory-ordering point of view,
there are no guarantees regarding the relative order in which the constituent memory accesses are made. There is
also no guarantee that the constituent operations of a store are executed in the same order as the constituent
operations of a load.
Section 9.2.3.2 through Section 9.2.3.7 give examples using the MOV instruction. The principles that underlie
these examples apply to load and store accesses in general and to other instructions that load from or store to
memory. Section 9.2.3.8 and Section 9.2.3.9 give examples using the XCHG instruction. The principles that
underlie these examples apply to other locked read-modify-write instructions.
This section uses the term “processor” is to refer to a logical processor. The examples are written using Intel-64
assembly-language syntax and use the following notational conventions:
Arguments beginning with an “r”, such as r1 or r2 refer to registers (e.g., EAX) visible only to the processor
being considered.
Memory locations are denoted with x, y, z.
Stores are written as mov [ _x], val, which implies that val is being stored into the memory location x.
Loads are written as mov r, [ _x], which implies that the contents of the memory location x are being loaded
into the register r.
As noted earlier, the examples refer only to software visible behavior. When the succeeding sections make state-
ment such as “the two stores are reordered,” the implication is only that “the two stores appear to be reordered
from the point of view of software.”
9.2.3.2
Neither Loads Nor Stores Are Reordered with Like Operations
The Intel-64 memory-ordering model allows neither loads nor stores to be reordered with the same kind of opera-
tion. That is, it ensures that loads are seen in program order and that stores are seen in program order. This is illus-
trated by the following example:
Example 9-1. Stores Are Not Reordered with Other Stores
Processor 0
Processor 1
mov [ _x], 1
mov r1, [ _y]
mov [ _y], 1
mov r2, [ _x]
Initially x = y = 0
r1 = 1 and r2 = 0 is not allowed
The disallowed return values could be exhibited only if processor 0’s two stores are reordered (with the two loads
occurring between them) or if processor 1’s two loads are reordered (with the two stores occurring between them).
If r1 = 1, the store to y occurs before the load from y. Because the Intel-64 memory-ordering model does not allow
stores to be reordered, the earlier store to x occurs before the load from y. Because the Intel-64 memory-ordering
model does not allow loads to be reordered, the store to x also occurs before the later load from x. This r2 = 1.
9.2.3.3
Stores Are Not Reordered With Earlier Loads
The Intel-64 memory-ordering model ensures that a store by a processor may not occur before a previous load by
the same processor. This is illustrated in Example 9-2.
Vol. 3A
9-9
MULTIPLE-PROCESSOR MANAGEMENT
Example 9-2. Stores Are Not Reordered with Older Loads
Processor 0
Processor 1
mov r1, [ _x]
mov r2, [ _y]
mov [ _y], 1
mov [ _x], 1
Initially x = y = 0
r1 = 1 and r2 = 1 is not allowed
Assume r1 = 1.
Because r1 = 1, processor 1’s store to x occurs before processor 0’s load from x.
Because the Intel-64 memory-ordering model prevents each store from being reordered with the earlier load
by the same processor, processor 1’s load from y occurs before its store to x.
Similarly, processor 0’s load from x occurs before its store to y.
Thus, processor 1’s load from y occurs before processor 0’s store to y, implying r2 = 0.
9.2.3.4
Loads May Be Reordered with Earlier Stores to Different Locations
The Intel-64 memory-ordering model allows a load to be reordered with an earlier store to a different location.
However, loads are not reordered with stores to the same location.
The fact that a load may be reordered with an earlier store to a different location is illustrated by the following
example:
Example 9-3. Loads May be Reordered with Older Stores
Processor 0
Processor 1
mov [ _x], 1
mov [ _y], 1
mov r1, [ _y]
mov r2, [ _x]
Initially x = y = 0
r1 = 0 and r2 = 0 is allowed
At each processor, the load and the store are to different locations and hence may be reordered. Any interleaving
of the operations is thus allowed. One such interleaving has the two loads occurring before the two stores. This
would result in each load returning value 0.
The fact that a load may not be reordered with an earlier store to the same location is illustrated by the following
example:
Example 9-4. Loads Are not Reordered with Older Stores to the Same Location
Processor 0
mov [ _x], 1
mov r1, [ _x]
Initially x = 0
r1 = 0 is not allowed
The Intel-64 memory-ordering model does not allow the load to be reordered with the earlier store because the
accesses are to the same location. Therefore, r1 = 1 must hold.
9-10
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
9.2.3.5
Intra-Processor Forwarding Is Allowed
The memory-ordering model allows concurrent stores by two processors to be seen in different orders by those two
processors; specifically, each processor may perceive its own store occurring before that of the other. This is illus-
trated by the following example:
Example 9-5. Intra-Processor Forwarding is Allowed
Processor 0
Processor 1
mov [ _x], 1
mov [ _y], 1
mov r1, [ _x]
mov r3, [ _y]
mov r2, [ _y]
mov r4, [ _x]
Initially x = y = 0
r2 = 0 and r4 = 0 is allowed
The memory-ordering model imposes no constraints on the order in which the two stores appear to execute by the
two processors. This fact allows processor 0 to see its store before seeing processor 1's, while processor 1 sees its
store before seeing processor 0's. (Each processor is self consistent.) This allows r2 = 0 and r4 = 0.
In practice, the reordering in this example can arise as a result of store-buffer forwarding. While a store is tempo-
rarily held in a processor's store buffer, it can satisfy the processor's own loads but is not visible to (and cannot
satisfy) loads by other processors.
9.2.3.6
Stores Are Transitively Visible
The memory-ordering model ensures transitive visibility of stores; stores that are causally related appear to all
processors to occur in an order consistent with the causality relation. This is illustrated by the following example:
Example 9-6. Stores Are Transitively Visible
Processor 0
Processor 1
Processor 2
mov [ _x], 1
mov r1, [ _x]
mov [ _y], 1
mov r2, [ _y]
mov r3, [_x]
Initially x = y = 0
r1 = 1, r2 = 1, r3 = 0 is not allowed
Assume that r1 = 1 and r2 = 1.
Because r1 = 1, processor 0’s store occurs before processor 1’s load.
Because the memory-ordering model prevents a store from being reordered with an earlier load (see Section
9.2.3.3), processor 1’s load occurs before its store. Thus, processor 0’s store causally precedes processor 1’s
store.
Because processor 0’s store causally precedes processor 1’s store, the memory-ordering model ensures that
processor 0’s store appears to occur before processor 1’s store from the point of view of all processors.
Because r2 = 1, processor 1’s store occurs before processor 2’s load.
Because the Intel-64 memory-ordering model prevents loads from being reordered (see Section 9.2.3.2),
processor 2’s load occur in order.
The above items imply that processor 0’s store to x occurs before processor 2’s load from x. This implies that
r3 = 1.
Vol. 3A
9-11
MULTIPLE-PROCESSOR MANAGEMENT
9.2.3.7
Stores Are Seen in a Consistent Order by Other Processors
As noted in Section 9.2.3.5, the memory-ordering model allows stores by two processors to be seen in different
orders by those two processors. However, any two stores must appear to execute in the same order to all proces-
sors other than those performing the stores. This is illustrated by the following example:
Example 9-7. Stores Are Seen in a Consistent Order by Other Processors
Processor 0
Processor 1
Processor 2
Processor 3
mov [ _x], 1
mov [ _y], 1
mov r1, [ _x]
mov r3, [_y]
mov r2, [ _y]
mov r4, [_x]
Initially x = y =0
r1 = 1, r2 = 0, r3 = 1, r4 = 0 is not allowed
By the principles discussed in Section 9.2.3.2:
Processor 2’s first and second load cannot be reordered.
Processor 3’s first and second load cannot be reordered.
If r1 = 1 and r2 = 0, processor 0’s store appears to precede processor 1’s store with respect to processor 2.
Similarly, r3 = 1 and r4 = 0 imply that processor 1’s store appears to precede processor 0’s store with respect
to processor 1.
Because the memory-ordering model ensures that any two stores appear to execute in the same order to all
processors (other than those performing the stores), this set of return values is not allowed.
9.2.3.8
Locked Instructions Have a Total Order
The memory-ordering model ensures that all processors agree on a single execution order of all locked instructions,
including those that are larger than 8 bytes or are not naturally aligned. This is illustrated by the following example:
Example 9-8. Locked Instructions Have a Total Order
Processor 0
Processor 1
Processor 2
Processor 3
xchg [ _x], r1
xchg [ _y], r2
mov r3, [ _x]
mov r5, [_y]
mov r4, [ _y]
mov r6, [_x]
Initially r1 = r2 = 1, x = y = 0
r3 = 1, r4 = 0, r5 = 1, r6 = 0 is not allowed
Processor 2 and processor 3 must agree on the order of the two executions of XCHG. Without loss of generality,
suppose that processor 0’s XCHG occurs first.
If r5 = 1, processor 1’s XCHG into y occurs before processor 3’s load from y.
Because the Intel-64 memory-ordering model prevents loads from being reordered (see Section 9.2.3.2),
processor 3’s loads occur in order and, therefore, processor 1’s XCHG occurs before processor 3’s load from x.
Since processor 0’s XCHG into x occurs before processor 1’s XCHG (by assumption), it occurs before
processor 3’s load from x. Thus, r6 = 1.
A similar argument (referring instead to processor 2’s loads) applies if processor 1’s XCHG occurs before
processor 0’s XCHG.
9.2.3.9
Loads and Stores Are Not Reordered with Locked Instructions
The memory-ordering model prevents loads and stores from being reordered with locked instructions that execute
earlier or later. The examples in this section illustrate only cases in which a locked instruction is executed before a
9-12
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
load or a store. The reader should note that reordering is prevented also if the locked instruction is executed after
a load or a store.
The first example illustrates that loads may not be reordered with earlier locked instructions:
Example 9-9. Loads Are not Reordered with Locks
Processor 0
Processor 1
xchg [ _x], r1
xchg [ _y], r3
mov r2, [ _y]
mov r4, [ _x]
Initially x = y = 0, r1 = r3 = 1
r2 = 0 and r4 = 0 is not allowed
As explained in Section 9.2.3.8, there is a total order of the executions of locked instructions. Without loss of
generality, suppose that processor 0’s XCHG occurs first.
Because the Intel-64 memory-ordering model prevents processor 1’s load from being reordered with its earlier
XCHG, processor 0’s XCHG occurs before processor 1’s load. This implies r4 = 1.
A similar argument (referring instead to processor 2’s accesses) applies if processor 1’s XCHG occurs before
processor 0’s XCHG.
The second example illustrates that a store may not be reordered with an earlier locked instruction:
Example 9-10. Stores Are not Reordered with Locks
Processor 0
Processor 1
xchg [ _x], r1
mov r2, [ _y]
mov [ _y], 1
mov r3, [ _x]
Initially x = y = 0, r1 = 1
r2 = 1 and r3 = 0 is not allowed
Assume r2 = 1.
Because r2 = 1, processor 0’s store to y occurs before processor 1’s load from y.
Because the memory-ordering model prevents a store from being reordered with an earlier locked instruction,
processor 0’s XCHG into x occurs before its store to y. Thus, processor 0’s XCHG into x occurs before
processor 1’s load from y.
Because the memory-ordering model prevents loads from being reordered (see Section 9.2.3.2), processor 1’s
loads occur in order and, therefore, processor 1’s XCHG into x occurs before processor 1’s load from x. Thus,
r3 = 1.
9.2.4
Fast-String Operation and Out-of-Order Stores
Section 7.3.9.3 of Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1, described an optimi-
zation of repeated string operations called fast-string operation.
As explained in that section, the stores produced by fast-string operation may appear to execute out of order. Soft-
ware dependent upon sequential store ordering should not use string operations for the entire data structure to be
stored. Data and semaphores should be separated. Order-dependent code should write to a discrete semaphore
variable after any string operations to allow correctly ordered data to be seen by all processors. Atomicity of load
and store operations is guaranteed only for native data elements of the string with native data size, and only if they
are included in a single cache line.
Section 9.2.4.1 and Section 9.2.4.2 provide further explain and examples.
9.2.4.1
Memory-Ordering Model for String Operations on Write-Back (WB) Memory
This section deals with the memory-ordering model for string operations on write-back (WB) memory for the Intel
64 architecture.
Vol. 3A
9-13
MULTIPLE-PROCESSOR MANAGEMENT
The memory-ordering model respects the follow principles:
1. Stores within a single string operation may be executed out of order.
2. Stores from separate string operations (for example, stores from consecutive string operations) do not execute
out of order. All the stores from an earlier string operation will complete before any store from a later string
operation.
3. String operations are not reordered with other store operations.
Fast string operations (e.g., string operations initiated with the MOVS/STOS instructions and the REP prefix) may
be interrupted by exceptions or interrupts. The interrupts are precise but may be delayed - for example, the inter-
ruptions may be taken at cache line boundaries, after every few iterations of the loop, or after operating on every
few bytes. Different implementations may choose different options, or may even choose not to delay interrupt
handling, so software should not rely on the delay. When the interrupt/trap handler is reached, the source/destina-
tion registers point to the next string element to be operated on, while the EIP stored in the stack points to the
string instruction, and the ECX register has the value it held following the last successful iteration. The return from
that trap/interrupt handler should cause the string instruction to be resumed from the point where it was inter-
rupted.
The string operation memory-ordering principles, (item 2 and 3 above) should be interpreted by taking the incor-
ruptibility of fast string operations into account. For example, if a fast string operation gets interrupted after k iter-
ations, then stores performed by the interrupt handler will become visible after the fast string stores from iteration
0 to k, and before the fast string stores from the (k+1)th iteration onward.
Stores within a single string operation may execute out of order (item 1 above) only if fast string operation is
enabled. Fast string operations are enabled/disabled through the IA32_MISC_ENABLE model specific register.
9.2.4.2
Examples Illustrating Memory-Ordering Principles for String Operations
The following examples uses the same notation and convention as described in Section 9.2.3.1.
In Example 9-11, processor 0 does one round of (128 iterations) doubleword string store operation via rep:stosd,
writing the value 1 (value in EAX) into a block of 512 bytes from location _x (kept in ES:EDI) in ascending order.
Since each operation stores a doubleword (4 bytes), the operation is repeated 128 times (value in ECX). The block
of memory initially contained 0. Processor 1 is reading two memory locations that are part of the memory block
being updated by processor 0, i.e, reading locations in the range _x to (_x+511).
Example 9-11. Stores Within a String Operation May be Reordered
Processor 0
Processor 1
rep:stosd [ _x]
mov r1, [ _z]
mov r2, [ _y]
Initially on processor 0: EAX = 1, ECX=128, ES:EDI =_x
Initially [_x] to 511[_x]= 0, _x <= _y < _z < _x+512
r1 = 1 and r2 = 0 is allowed
It is possible for processor 1 to perceive that the repeated string stores in processor 0 are happening out of order.
Assume that fast string operations are enabled on processor 0.
In Example 9-12, processor 0 does two separate rounds of rep stosd operation of 128 doubleword stores, writing
the value 1 (value in EAX) into the first block of 512 bytes from location _x (kept in ES:EDI) in ascending order. It
then writes 1 into a second block of memory from (_x+512) to (_x+1023). All of the memory locations initially
contain 0. The block of memory initially contained 0. Processor 1 performs two load operations from the two blocks
of memory.
9-14
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
Example 9-12. Stores Across String Operations Are not Reordered
Processor 0
Processor 1
rep:stosd [ _x]
mov r1, [ _z]
mov ecx, $128
mov r2, [ _y]
rep:stosd 512[ _x]
Initially on processor 0: EAX = 1, ECX=128, ES:EDI =_x
Initially [_x] to 1023[_x]= 0, _x <= _y < _x+512 < _z < _x+1024
r1 = 1 and r2 = 0 is not allowed
It is not possible in the above example for processor 1 to perceive any of the stores from the later string operation
(to the second 512 block) in processor 0 before seeing the stores from the earlier string operation to the first 512
block.
The above example assumes that writes to the second block (_x+512 to _x+1023) does not get executed while
processor 0’s string operation to the first block has been interrupted. If the string operation to the first block by
processor 0 is interrupted, and a write to the second memory block is executed by the interrupt handler, then that
change in the second memory block will be visible before the string operation to the first memory block resumes.
In Example 9-13, processor 0 does one round of (128 iterations) doubleword string store operation via rep:stosd,
writing the value 1 (value in EAX) into a block of 512 bytes from location _x (kept in ES:EDI) in ascending order. It
then writes to a second memory location outside the memory block of the previous string operation. Processor 1
performs two read operations, the first read is from an address outside the 512-byte block but to be updated by
processor 0, the second ready is from inside the block of memory of string operation.
Example 9-13. String Operations Are not Reordered with later Stores
Processor 0
Processor 1
rep:stosd [ _x]
mov r1, [ _z]
mov [_z], $1
mov r2, [ _y]
Initially on processor 0: EAX = 1, ECX=128, ES:EDI =_x
Initially [_y] = [_z] = 0, [_x] to 511[_x]= 0, _x <= _y < _x+512, _z is a separate memory location
r1 = 1 and r2 = 0 is not allowed
Processor 1 cannot perceive the later store by processor 0 until it sees all the stores from the string operation.
Example 9-13 assumes that processor 0’s store to [_z] is not executed while the string operation has been inter-
rupted. If the string operation is interrupted and the store to [_z] by processor 0 is executed by the interrupt
handler, then changes to [_z] will become visible before the string operation resumes.
Example 9-14 illustrates the visibility principle when a string operation is interrupted.
Example 9-14. Interrupted String Operation
Processor 0
Processor 1
rep:stosd [ _x] // interrupted before es:edi reach _y
mov r1, [ _z]
mov [_z], $1 // interrupt handler
mov r2, [ _y]
Initially on processor 0: EAX = 1, ECX=128, ES:EDI =_x
Initially [_y] = [_z] = 0, [_x] to 511[_x]= 0, _x <= _y < _x+512, _z is a separate memory location
r1 = 1 and r2 = 0 is allowed
Vol. 3A
9-15
MULTIPLE-PROCESSOR MANAGEMENT
In Example 9-14, processor 0 started a string operation to write to a memory block of 512 bytes starting at address
_x. Processor 0 got interrupted after k iterations of store operations. The address _y has not yet been updated by
processor 0 when processor 0 got interrupted. The interrupt handler that took control on processor 0 writes to the
address _z. Processor 1 may see the store to _z from the interrupt handler, before seeing the remaining stores to
the 512-byte memory block that are executed when the string operation resumes.
Example 9-15 illustrates the ordering of string operations with earlier stores. No store from a string operation can
be visible before all prior stores are visible.
Example 9-15. String Operations Are not Reordered with Earlier Stores
Processor 0
Processor 1
mov [_z], $1
mov r1, [ _y]
rep:stosd [ _x]
mov r2, [ _z]
Initially on processor 0: EAX = 1, ECX=128, ES:EDI =_x
Initially [_y] = [_z] = 0, [_x] to 511[_x]= 0, _x <= _y < _x+512, _z is a separate memory location
r1 = 1 and r2 = 0 is not allowed
9.2.5
Strengthening or Weakening the Memory-Ordering Model
The Intel 64 and IA-32 architectures provide several mechanisms for strengthening or weakening the memory-
ordering model to handle special programming situations. These mechanisms include:
The I/O instructions, locked instructions, the LOCK prefix, and serializing instructions force stronger ordering
on the processor.
The SFENCE instruction (introduced to the IA-32 architecture in the Pentium III processor) and the LFENCE and
MFENCE instructions (introduced in the Pentium 4 processor) provide memory-ordering and serialization
capabilities for specific types of memory operations.
The memory type range registers (MTRRs) can be used to strengthen or weaken memory ordering for specific
area of physical memory (see Section 12.11, “Memory Type Range Registers (MTRRs)”). MTRRs are available
only in the Pentium 4, Intel Xeon, and P6 family processors.
The page attribute table (PAT) can be used to strengthen memory ordering for a specific page or group of pages
(see Section 12.12, “Page Attribute Table (PAT)”). The PAT is available only in the Pentium 4, Intel Xeon, and
Pentium III processors.
These mechanisms can be used as follows:
Memory mapped devices and other I/O devices on the bus are often sensitive to the order of writes to their I/O
buffers. I/O instructions can be used to (the IN and OUT instructions) impose strong write ordering on such
accesses as follows. Prior to executing an I/O instruction, the processor waits for all previous instructions in the
program to complete and for all buffered writes to drain to memory. Only instruction fetch and page tables walks
can pass I/O instructions. Execution of subsequent instructions do not begin until the processor determines that
the I/O instruction has been completed.
Synchronization mechanisms in multiple-processor systems may depend upon a strong memory-ordering model.
Here, a program can use a locked instruction such as the XCHG instruction or the LOCK prefix to ensure that a read-
modify-write operation on memory is carried out atomically. Locked instructions typically operate like I/O instruc-
tions in that they wait for all previous memory accesses to complete and for all buffered writes to drain to memory
(see Section 9.1.2, “Bus Locking”). Unlike I/O operations, locked instructions do not wait for all previous instruc-
tions to complete execution.
Program synchronization can also be carried out with serializing instructions (see Section 9.3). These instructions
are typically used at critical procedure or task boundaries to force completion of all previous instructions before a
jump to a new section of code or a context switch occurs. Like the I/O instructions, the processor waits until all
previous instructions have been completed and all buffered writes have been drained to memory before executing
the serializing instruction.
9-16
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
The SFENCE, LFENCE, and MFENCE instructions provide a performance-efficient way of ensuring load and store
memory ordering between routines that produce weakly-ordered results and routines that consume that data. The
functions of these instructions are as follows:
SFENCE - Serializes all store (write) operations that occurred prior to the SFENCE instruction in the program
instruction stream, but does not affect load operations.
LFENCE - Serializes all load (read) operations that occurred prior to the LFENCE instruction in the program
instruction stream, but does not affect store operations.1
MFENCE - Serializes all store and load operations that occurred prior to the MFENCE instruction in the
program instruction stream.
Note that the SFENCE, LFENCE, and MFENCE instructions provide a more efficient method of controlling memory
ordering than the CPUID instruction.
The MTRRs were introduced in the P6 family processors to define the cache characteristics for specified areas of
physical memory. The following are two examples of how memory types set up with MTRRs can be used strengthen
or weaken memory ordering for the Pentium 4, Intel Xeon, and P6 family processors:
The strong uncached (UC) memory type forces a strong-ordering model on memory accesses. Here, all reads
and writes to the UC memory region appear on the bus and out-of-order or speculative accesses are not
performed. This memory type can be applied to an address range dedicated to memory mapped I/O devices to
force strong memory ordering.
For areas of memory where weak ordering is acceptable, the write back (WB) memory type can be chosen.
Here, reads can be performed speculatively and writes can be buffered and combined. For this type of memory,
cache locking is performed on atomic (locked) operations that do not split across cache lines, which helps to
reduce the performance penalty associated with the use of the typical synchronization instructions, such as
XCHG, that lock the bus during the entire read-modify-write operation. With the WB memory type, the XCHG
instruction locks the cache instead of the bus if the memory access is contained within a cache line.
The PAT was introduced in the Pentium III processor to enhance the caching characteristics that can be assigned to
pages or groups of pages. The PAT mechanism typically used to strengthen caching characteristics at the page level
with respect to the caching characteristics established by the MTRRs. Table 12-7 shows the interaction of the PAT
with the MTRRs.
Intel recommends that software written to run on Intel Core 2 Duo, Intel Atom, Intel Core Duo, Pentium 4, Intel
Xeon, and P6 family processors assume the processor-ordering model or a weaker memory-ordering model. The
Intel Core 2 Duo, Intel Atom, Intel Core Duo, Pentium 4, Intel Xeon, and P6 family processors do not implement a
strong memory-ordering model, except when using the UC memory type. Despite the fact that Pentium 4, Intel
Xeon, and P6 family processors support processor ordering, Intel does not guarantee that future processors will
support this model. To make software portable to future processors, it is recommended that operating systems
provide critical region and resource control constructs and API’s (application program interfaces) based on I/O,
locking, and/or serializing instructions be used to synchronize access to shared areas of memory in multiple-
processor systems. Also, software should not depend on processor ordering in situations where the system hard-
ware does not support this memory-ordering model.
9.3
SERIALIZING INSTRUCTIONS
The Intel 64 and IA-32 architectures define several serializing instructions. These instructions force the
processor to complete all modifications to flags, registers, and memory by previous instructions and to drain all
buffered writes to memory before the next instruction is fetched and executed. For example, when a MOV to
control register instruction is used to load a new value into control register CR0 to enable protected mode, the
processor must perform a serializing operation before it enters protected mode. This serializing operation ensures
1. Specifically, LFENCE does not execute until all prior instructions have completed locally, and no later instruction begins execution
until LFENCE completes. As a result, an instruction that loads from memory and that precedes an LFENCE receives data from mem-
ory prior to completion of the LFENCE. An LFENCE that follows an instruction that stores to memory might complete before the data
being stored have become globally visible. Instructions following an LFENCE may be fetched from memory before the LFENCE, but
they will not execute until the LFENCE completes.
Vol. 3A
9-17
MULTIPLE-PROCESSOR MANAGEMENT
that all operations that were started while the processor was in real-address mode are completed before the switch
to protected mode is made.
The concept of serializing instructions was introduced into the IA-32 architecture with the Pentium processor to
support parallel instruction execution. Serializing instructions have no meaning for the Intel486 and earlier proces-
sors that do not implement parallel instruction execution.
It is important to note that executing of serializing instructions on P6 and more recent processor families constrain
speculative execution because the results of speculatively executed instructions are discarded. The following
instructions are serializing instructions:
Privileged serializing instructions - INVD, INVEPT, INVLPG, INVVPID, LGDT, LIDT, LLDT, LTR, MOV (to
control register, with the exception of MOV CR81), MOV (to debug register), WBINVD, and WRMSR2.
Non-privileged serializing instructions - CPUID, IRET, RSM, and SERIALIZE.
When the processor serializes instruction execution, it ensures that all pending memory transactions are completed
(including writes stored in its store buffer) before it executes the next instruction. Nothing can pass a serializing
instruction and a serializing instruction cannot pass any other instruction (read, write, instruction fetch, or I/O). For
example, CPUID can be executed at any privilege level to serialize instruction execution with no effect on program
flow, except that the EAX, EBX, ECX, and EDX registers are modified.
The following instructions are memory-ordering instructions, not serializing instructions. These drain the data
memory subsystem. They do not serialize the instruction execution stream:3
Non-privileged memory-ordering instructions - SFENCE, LFENCE, and MFENCE.
The SFENCE, LFENCE, and MFENCE instructions provide more granularity in controlling the serialization of memory
loads and stores (see Section 9.2.5, “Strengthening or Weakening the Memory-Ordering Model”).
The following additional information is worth noting regarding serializing instructions:
The processor does not write back the contents of modified data in its data cache to external memory when it
serializes instruction execution. Software can force modified data to be written back by executing the WBINVD
instruction, which is a serializing instruction. The amount of time or cycles for WBINVD to complete will vary
due to the size of different cache hierarchies and other factors. As a consequence, the use of the WBINVD
instruction can have an impact on interrupt/event response time.
When an instruction is executed that enables or disables paging (that is, changes the PG flag in control register
CR0), the instruction should be followed by a jump instruction. The target instruction of the jump instruction is
fetched with the new setting of the PG flag (that is, paging is enabled or disabled), but the jump instruction
itself is fetched with the previous setting. The Pentium 4, Intel Xeon, and P6 family processors do not require
the jump operation following the move to register CR0 (because any use of the MOV instruction in a Pentium 4,
Intel Xeon, or P6 family processor to write to CR0 is completely serializing). However, to maintain backwards
and forward compatibility with code written to run on other IA-32 processors, it is recommended that the jump
operation be performed.
Whenever an instruction is executed to change the contents of CR3 while paging is enabled, the next instruction
is fetched using the translation tables that correspond to the new value of CR3. Therefore the next instruction
and the sequentially following instructions should have a mapping based upon the new value of CR3. (Global
entries in the TLBs are not invalidated, see Section 4.10.4, “Invalidation of TLBs and Paging-Structure
Caches.”)
The Pentium processor and more recent processor families use branch-prediction techniques to improve
performance by prefetching the destination of a branch instruction before the branch instruction is executed.
Consequently, instruction execution is not deterministically serialized when a branch instruction is executed.
1. MOV CR8 is not defined architecturally as a serializing instruction.
2. An execution of WRMSR to any non-serializing MSR is not serializing. Non-serializing MSRs include the following: IA32_SPEC_CTRL
MSR (MSR index 48H), IA32_PRED_CMD MSR (MSR index 49H), IA32_TSX_CTRL MSR (MSR index 122H), IA32_TSC_DEADLINE MSR
(MSR index 6E0H), IA32_PKRS MSR (MSR index 6E1H), IA32_HWP_REQUEST MSR (MSR index 774H), or any of the x2APIC MSRs
(MSR indices 802H to 83FH).
3. LFENCE does provide some guarantees on instruction ordering. It does not execute until all prior instructions have completed locally,
and no later instruction begins execution until LFENCE completes.
9-18
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
9.4
MULTIPLE-PROCESSOR (MP) INITIALIZATION
The IA-32 architecture (beginning with the P6 family processors) defines a multiple-processor (MP) initialization
protocol called the Multiprocessor Specification Version 1.4. This specification defines the boot protocol to be used
by IA-32 processors in multiple-processor systems. (Here, multiple processors is defined as two or more proces-
sors.) The MP initialization protocol has the following important features:
It supports controlled booting of multiple processors without requiring dedicated system hardware.
It allows hardware to initiate the booting of a system without the need for a dedicated signal or a predefined
boot processor.
It allows all IA-32 processors to be booted in the same manner, including those supporting Intel Hyper-
Threading Technology.
The MP initialization protocol also applies to MP systems using Intel 64 processors.
The mechanism for carrying out the MP initialization protocol differs depending on the Intel processor generations.
The following bullets summarizes the evolution of the changes:
For P6 family or older processors supporting MP operations- The selection of the BSP and APs (see
Section 9.4.1, “BSP and AP Processors”) is handled through arbitration on the APIC bus, using BIPI and FIPI
messages. These processor generations have CPUID signatures of (family=06H, extended_model=0,
model<=0DH), or family <06H. See Section 9.11.1, “Overview of the MP Initialization Process for P6 Family
Processors,” for a complete discussion of MP initialization for P6 family processors.
Early generations of IA processors with family 0FH - The selection of the BSP and APs (see Section
9.4.1, “BSP and AP Processors”) is handled through arbitration on the system bus, using BIPI and FIPI
messages (see Section 9.4.3, “MP Initialization Protocol Algorithm for MP Systems”). These processor
generations have CPUID signatures of family=0FH, model=0H, stepping<=09H.
Later generations of IA processors with family 0FH, and IA processors with system bus - The
selection of the BSP and APs is handled through a special system bus cycle, without using BIPI and FIPI
message arbitration (see Section 9.4.3, “MP Initialization Protocol Algorithm for MP Systems”). These
processor generations have CPUID signatures of family=0FH with (model=0H, stepping>=0AH) or (model >0,
all steppings); or family=06H, extended_model=0, model>=0EH.
All other modern IA processor generations supporting MP operations- The selection of the BSP and
APs in the system is handled by platform-specific arrangement of the combination of hardware, BIOS, and/or
configuration input options. The basis of the selection mechanism is similar to those of the Later generations of
family 0FH and other Intel processor using system bus (see Section 9.4.3, “MP Initialization Protocol Algorithm
for MP Systems”). These processor generations have CPUID signatures of family=06H, extended_model>0.
The family, model, and stepping ID for a processor is given in the EAX register when the CPUID instruction is
executed with a value of 1 in the EAX register.
9.4.1
BSP and AP Processors
The MP initialization protocol defines two classes of processors: the bootstrap processor (BSP) and the application
processors (APs). Following a power-up or RESET of an MP system, system hardware dynamically selects one of
the processors on the system bus as the BSP. The remaining processors are designated as APs.
As part of the BSP selection mechanism, the BSP flag is set in the IA32_APIC_BASE MSR (see Figure 11-5) of the
BSP, indicating that it is the BSP. This flag is cleared for all other processors.
The BSP executes the BIOS’s boot-strap code to configure the APIC environment, sets up system-wide data struc-
tures, and starts and initializes the APs. When the BSP and APs are initialized, the BSP then begins executing the
operating-system initialization code.
Following a power-up or reset, the APs complete a minimal self-configuration, then wait for a startup signal (a SIPI
message) from the BSP processor. Upon receiving a SIPI message, an AP executes the BIOS AP configuration code,
which ends with the AP being placed in halt state.
For Intel 64 and IA-32 processors supporting Intel Hyper-Threading Technology, the MP initialization protocol treats
each of the logical processors on the system bus or coherent link domain as a separate processor (with a unique
Vol. 3A
9-19
MULTIPLE-PROCESSOR MANAGEMENT
APIC ID). During boot-up, one of the logical processors is selected as the BSP and the remainder of the logical
processors are designated as APs.
9.4.2
MP Initialization Protocol Requirements and Restrictions
The MP initialization protocol imposes the following requirements and restrictions on the system:
The MP protocol is executed only after a power-up or RESET. If the MP protocol has completed and a BSP is
chosen, subsequent INITs (either to a specific processor or system wide) do not cause the MP protocol to be
repeated. Instead, each logical processor examines its BSP flag (in the IA32_APIC_BASE MSR) to determine
whether it should execute the BIOS boot-strap code (if it is the BSP) or enter a wait-for-SIPI state (if it is an
AP).
All devices in the system that are capable of delivering interrupts to the processors must be inhibited from
doing so for the duration of the MP initialization protocol. The time during which interrupts must be inhibited
includes the window between when the BSP issues an INIT-SIPI-SIPI sequence to an AP and when the AP
responds to the last SIPI in the sequence.
9.4.3
MP Initialization Protocol Algorithm for MP Systems
Following a power-up or RESET of an MP system, the processors in the system execute the MP initialization protocol
algorithm to initialize each of the logical processors on the system bus or coherent link domain. In the course of
executing this algorithm, the following boot-up and initialization operations are carried out:
1.
Each logical processor is assigned a unique APIC ID, based on system topology. The unique ID is a 32-bit value
if the processor supports CPUID leaf 0BH, otherwise the unique ID is an 8-bit value. (see Section 9.4.5, “Identi-
fying Logical Processors in an MP System”).
2.
Each logical processor is assigned a unique arbitration priority based on its APIC ID.
3.
Each logical processor executes its internal BIST simultaneously with the other logical processors in the
system.
4.
Upon completion of the BIST, the logical processors use a hardware-defined selection mechanism to select the
BSP and the APs from the available logical processors on the system bus. The BSP selection mechanism differs
depending on the family, model, and stepping IDs of the processors, as follows:
- Later generations of IA processors within family 0FH (see Section 9.4), IA processors with system bus
(family=06H, extended_model=0, model>=0EH), or all other modern Intel processors (family=06H,
extended_model>0):
The logical processors begin monitoring the BNR# signal, which is toggling. When the BNR# pin stops
toggling, each processor attempts to issue a NOP special cycle on the system bus.
The logical processor with the highest arbitration priority succeeds in issuing a NOP special cycle and is
nominated the BSP. This processor sets the BSP flag in its IA32_APIC_BASE MSR, then fetches and
begins executing BIOS boot-strap code, beginning at the reset vector (physical address FFFF FFF0H).
The remaining logical processors (that failed in issuing a NOP special cycle) are designated as APs. They
leave their BSP flags in the clear state and enter a “wait-for-SIPI state.”
- Early generations of IA processors within family 0FH (family=0FH, model=0H, stepping<=09H), P6 family
or older processors supporting MP operations (family=06H, extended_model=0, model<=0DH; or family
<06H):
Each processor broadcasts a BIPI to “all including self.” The first processor that broadcasts a BIPI (and
thus receives its own BIPI vector), selects itself as the BSP and sets the BSP flag in its IA32_APIC_BASE
MSR. (See Section 9.11.1, “Overview of the MP Initialization Process for P6 Family Processors,” for a
description of the BIPI, FIPI, and SIPI messages.)
The remainder of the processors (which were not selected as the BSP) are designated as APs. They
leave their BSP flags in the clear state and enter a “wait-for-SIPI state.”
The newly established BSP broadcasts an FIPI message to “all including self,” which the BSP and APs
treat as an end of MP initialization signal. Only the processor with its BSP flag set responds to the FIPI
9-20
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
message. It responds by fetching and executing the BIOS boot-strap code, beginning at the reset
vector (physical address FFFF FFF0H).
5. As part of the boot-strap code, the BSP creates an ACPI table and/or an MP table and adds its initial APIC ID to
these tables as appropriate.
6. At the end of the boot-strap procedure, the BSP sets a processor counter to 1, then broadcasts a SIPI message
to all the APs in the system. Here, the SIPI message contains a vector to the BIOS AP initialization code (at
000VV000H, where VV is the vector contained in the SIPI message).
7. The first action of the AP initialization code is to set up a race (among the APs) to a BIOS initialization
semaphore. The first AP to the semaphore begins executing the initialization code. (See Section 9.4.4, “MP
Initialization Example,” for semaphore implementation details.) As part of the AP initialization procedure, the
AP adds its APIC ID number to the ACPI and/or MP tables as appropriate and increments the processor counter
by 1. At the completion of the initialization procedure, the AP executes a CLI instruction and halts itself.
8. When each of the APs has gained access to the semaphore and executed the AP initialization code, the BSP
establishes a count for the number of processors connected to the system bus, completes executing the BIOS
boot-strap code, and then begins executing operating-system boot-strap and start-up code.
9. While the BSP is executing operating-system boot-strap and start-up code, the APs remain in the halted state.
In this state they will respond only to INITs, NMIs, and SMIs. They will also respond to snoops and to assertions
of the STPCLK# pin.
The following section gives an example (with code) of the MP initialization protocol for of multiple processors oper-
ating in an MP configuration.
Chapter 2, “Model-Specific Registers (MSRs)‚” in the Intel® 64 and IA-32 Architectures Software Developer’s
Manual, Volume 4, describes how to program the LINT[0:1] pins of the processor’s local APICs after an MP config-
uration has been completed.
9.4.4
MP Initialization Example
The following example illustrates the use of the MP initialization protocol used to initialize processors in an MP
system after the BSP and APs have been established. The code runs on Intel 64 or IA-32 processors that use a
protocol. This includes P6 Family processors, Pentium 4 processors, Intel Core Duo, Intel Core 2 Duo and Intel Xeon
processors.
The following constants and data definitions are used in the accompanying
code examples. They are based on the addresses of the APIC registers defined in Table 11-1.
ICR_LOW
EQU 0FEE00300H
SVR
EQU 0FEE000F0H
APIC_ID
EQU 0FEE00020H
LVT3
EQU 0FEE00370H
APIC_ENABLED
EQU 0100H
BOOT_ID
DD ?
COUNT
EQU 00H
VACANT
EQU 00H
9.4.4.1
Typical BSP Initialization Sequence
After the BSP and APs have been selected (by means of a hardware protocol, see Section 9.4.3, “MP Initialization
Protocol Algorithm for MP Systems”), the BSP begins executing BIOS boot-strap code (POST) at the normal IA-32
architecture starting address (FFFF FFF0H). The boot-strap code typically performs the following operations:
1. Initializes memory.
2. Loads the microcode update into the processor.
3. Initializes the MTRRs.
4. Enables the caches.
Vol. 3A
9-21
MULTIPLE-PROCESSOR MANAGEMENT
5.
Executes the CPUID instruction with a value of 0H in the EAX register, then reads the EBX, ECX, and EDX
registers to determine if the BSP is “GenuineIntel.”
6.
Executes the CPUID instruction with a value of 1H in the EAX register, then saves the values in the EAX, ECX,
and EDX registers in a system configuration space in RAM for use later.
7.
Loads start-up code for the AP to execute into a 4-KByte page in the lower 1 MByte of memory.
8.
Switches to protected mode and ensures that the APIC address space is mapped to the strong uncacheable
(UC) memory type.
9.
Determine the BSP’s APIC ID from the local APIC ID register (default is 0), the code snippet below is an
example that applies to logical processors in a system whose local APIC units operate in xAPIC mode that APIC
registers are accessed using memory mapped interface:
MOV ESI, APIC_ID; Address of local APIC ID register
MOV EAX, [ESI];
AND EAX, 0FF000000H; Zero out all other bits except APIC ID
MOV BOOT_ID, EAX; Save in memory
Saves the APIC ID in the ACPI and/or MP tables and optionally in the system configuration space in RAM.
10. Converts the base address of the 4-KByte page for the AP’s bootup code into 8-bit vector. The 8-bit vector
defines the address of a 4-KByte page in the real-address mode address space (1-MByte space). For example,
a vector of 0BDH specifies a start-up memory address of 000BD000H.
11. Enables the local APIC by setting bit 8 of the APIC spurious vector register (SVR).
MOV ESI, SVR; Address of SVR
MOV EAX, [ESI];
OR EAX, APIC_ENABLED; Set bit 8 to enable (0 on reset)
MOV [ESI], EAX;
12. Sets up the LVT error handling entry by establishing an 8-bit vector for the APIC error handler.
MOV ESI, LVT3;
MOV EAX, [ESI];
AND EAX, FFFFFF00H; Clear out previous vector.
OR EAX, 000000xxH; xx is the 8-bit vector the APIC error handler.
MOV [ESI], EAX;
13. Initializes the Lock Semaphore variable VACANT to 00H. The APs use this semaphore to determine the order in
which they execute BIOS AP initialization code.
14. Performs the following operation to set up the BSP to detect the presence of APs in the system and the number
of processors (within a finite duration, minimally 100 milliseconds):
- Sets the value of the COUNT variable to 1.
- In the AP BIOS initialization code, the AP will increment the COUNT variable to indicate its presence. The
finite duration while waiting for the COUNT to be updated can be accomplished with a timer. When the timer
expires, the BSP checks the value of the COUNT variable. If the timer expires and the COUNT variable has
not been incremented, no APs are present or some error has occurred.
15. Broadcasts an INIT-SIPI-SIPI IPI sequence to the APs to wake them up and initialize them. Alternatively,
following a power-up or RESET, since all APs are already in the “wait-for-SIPI state,” the BSP can broadcast just
a single SIPI IPI to the APs to wake them up and initialize them. If software knows how many logical processors
it expects to wake up, it may choose to poll the COUNT variable. If the expected processors show up before the
100 millisecond timer expires, the timer can be canceled and skip to step 16.
The left-hand-side of the procedure illustrated in Table 9-1 provides an algorithm when the expected processor
count is unknown. The right-hand-side of Table 9-1 can be used when the expected processor count is known.
9-22
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
Table 9-1. Broadcast INIT-SIPI-SIPI Sequence and Choice of Timeouts
INIT-SIPI-SIPI when the expected processor count is unknown
INIT-SIPI-SIPI when the expected processor count is known
MOV ESI, ICR_LOW; Load address of ICR low dword into ESI.
MOV ESI, ICR_LOW; Load address of ICR low dword into ESI.
MOV EAX, 000C4500H; Load ICR encoding for broadcast INIT IPI
MOV EAX, 000C4500H; Load ICR encoding for broadcast INIT IPI
; to all APs into EAX.
; to all APs into EAX.
MOV [ESI], EAX; Broadcast INIT IPI to all APs
MOV [ESI], EAX; Broadcast INIT IPI to all APs
; 10-millisecond delay loop.
; 10-millisecond delay loop.
MOV EAX, 000C46XXH; Load ICR encoding for broadcast SIPI IP
MOV EAX, 000C46XXH; Load ICR encoding for broadcast SIPI IP
; to all APs into EAX, where xx is the vector computed in step 10.
; to all APs into EAX, where xx is the vector computed in step 10.
MOV [ESI], EAX; Broadcast SIPI IPI to all APs
MOV [ESI], EAX; Broadcast SIPI IPI to all APs
; 200-microsecond delay loop
; 200 microsecond delay loop with check to see if COUNT has
MOV [ESI], EAX; Broadcast second SIPI IPI to all APs
; reached the expected processor count. If COUNT reaches
;Waits for the timer interrupt until the timer expires
; expected processor count, cancel timer and go to step 16.
MOV [ESI], EAX; Broadcast second SIPI IPI to all APs
; Wait for the timer interrupt polling COUNT. If COUNT reaches
; expected processor count, cancel timer and go to step 16.
; If timer expires, go to step 16.
16. Reads and evaluates the COUNT variable and establishes a processor count.
17. If necessary, reconfigures the APIC and continues with the remaining system diagnostics as appropriate.
9.4.4.2
Typical AP Initialization Sequence
When an AP receives the SIPI, it begins executing BIOS AP initialization code at the vector encoded in the SIPI. The
AP initialization code typically performs the following operations:
1. Waits on the BIOS initialization Lock Semaphore. When control of the semaphore is attained, initialization
continues.
2. Loads the microcode update into the processor.
3. Initializes the MTRRs (using the same mapping that was used for the BSP).
4. Enables the cache.
5. Executes the CPUID instruction with a value of 0H in the EAX register, then reads the EBX, ECX, and EDX
registers to determine if the AP is “GenuineIntel.”
6. Executes the CPUID instruction with a value of 1H in the EAX register, then saves the values in the EAX, ECX,
and EDX registers in a system configuration space in RAM for use later.
7. Switches to protected mode and ensures that the APIC address space is mapped to the strong uncacheable
(UC) memory type.
8. Determines the AP’s APIC ID from the local APIC ID register, and adds it to the MP and ACPI tables and
optionally to the system configuration space in RAM.
9. Initializes and configures the local APIC by setting bit 8 in the SVR register and setting up the LVT3 (error LVT)
for error handling (as described in steps 9 and 10 in Section 9.4.4.1, “Typical BSP Initialization Sequence”).
10. Configures the APs SMI execution environment. (Each AP and the BSP must have a different SMBASE address.)
11. Increments the COUNT variable by 1.
12. Releases the semaphore.
13. Executes one of the following:
Vol. 3A
9-23
MULTIPLE-PROCESSOR MANAGEMENT
- the CLI and HLT instructions (if MONITOR/MWAIT is not supported), or
- the CLI, MONITOR, and MWAIT sequence to enter a deep C-state.
14. Waits for an INIT IPI.
9.4.5
Identifying Logical Processors in an MP System
After the BIOS has completed the MP initialization protocol, each logical processor can be uniquely identified by its
local APIC ID. Software can access these APIC IDs in either of the following ways:
Read APIC ID for a local APIC - Code running on a logical processor can read APIC ID in one of two ways
depending on the local APIC unit is operating in x2APIC mode or in xAPIC mode:
- If the local APIC unit supports x2APIC and is operating in x2APIC mode, 32-bit APIC ID can be read by
executing a RDMSR instruction to read the processor’s x2APIC ID register. This method is equivalent to
executing CPUID leaf 0BH described below.
- If the local APIC unit is operating in xAPIC mode, 8-bit APIC ID can be read by executing a MOV instruction
to read the processor’s local APIC ID register (see Section 11.4.6, “Local APIC ID”). This is the ID to use for
directing physical destination mode interrupts to the processor.
Read ACPI or MP table - As part of the MP initialization protocol, the BIOS creates an ACPI table and an MP
table. These tables are defined in the Multiprocessor Specification Version 1.4 and provide software with a list
of the processors in the system and their local APIC IDs. The format of the ACPI table is derived from the ACPI
specification, which is an industry standard power management and platform configuration specification for MP
systems.
Read Initial APIC ID (If the processor does not support CPUID leaf 0BH) - An APIC ID is assigned to a logical
processor during power up. This is the initial APIC ID reported by CPUID.1:EBX[31:24] and may be different
from the current value read from the local APIC. The initial APIC ID can be used to determine the topological
relationship between logical processors for multi-processor systems that do not support CPUID leaf 0BH.
Bits in the 8-bit initial APIC ID can be interpreted using several bit masks. Each bit mask can be used to extract
an identifier to represent a hierarchical domain of the multi-threading resource topology in an MP system (See
Section 9.9.1, “Hierarchical Mapping of Shared Resources”). The initial APIC ID may consist of up to four bit-
fields. In a non-clustered MP system, the field consists of up to three bit fields.
Read 32-bit APIC ID from CPUID leaf 0BH (If the processor supports CPUID leaf 0BH) - A unique APIC ID
is assigned to a logical processor during power up. This APIC ID is reported by CPUID.0BH:EDX[31:0] as a 32-
bit value. Use the 32-bit APIC ID and CPUID leaf 0BH to determine the topological relationship between logical
processors if the processor supports CPUID leaf 0BH.
Bits in the 32-bit x2APIC ID can be extracted into sub-fields using CPUID leaf 0BH parameters. (See Section
9.9.1, “Hierarchical Mapping of Shared Resources”).
Figure 9-2 shows two examples of APIC ID bit fields in earlier single-core processors. In single-core Intel Xeon
processors, the APIC ID assigned to a logical processor during power-up and initialization is 8 bits. Bits 2:1 form a
2-bit physical package identifier (which can also be thought of as a socket identifier). In systems that configure
physical processors in clusters, bits 4:3 form a 2-bit cluster ID. Bit 0 is used in the Intel Xeon processor MP to iden-
tify the two logical processors within the package (see Section 9.9.3, “Hierarchical ID of Logical Processors in an MP
System”). For Intel Xeon processors that do not support Intel Hyper-Threading Technology, bit 0 is always set to 0;
for Intel Xeon processors supporting Intel Hyper-Threading Technology, bit 0 performs the same function as it does
for Intel Xeon processor MP.
For more recent multi-core processors, see Section 9.9.1, “Hierarchical Mapping of Shared Resources,” for a
complete description of the topological relationships between logical processors and bit field locations within an
initial APIC ID across Intel 64 and IA-32 processor families.
Note the number of bit fields and the width of bit-fields are dependent on processor and platform hardware capa-
bilities. Software should determine these at runtime. When initial APIC IDs are assigned to logical processors, the
value of APIC ID assigned to a logical processor will respect the bit-field boundaries corresponding core, physical
package, etc. Additional examples of the bit fields in the initial APIC ID of multi-threading capable systems are
shown in Section 9.9.
9-24
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
APIC ID Format for Intel Xeon Processors that
do not Support Intel Hyper-Threading Technology
7
5
4
3
2
1
0
Reserved
0
Cluster
Processor ID
APIC ID Format for P6 Family Processors
7
4
3
2
1
0
Reserved
Cluster
Processor ID
Figure 9-2. Interpretation of APIC ID in Early MP Systems
For P6 family processors, the APIC ID that is assigned to a processor during power-up and initialization is 4 bits
(see Figure 9-2). Here, bits 0 and 1 form a 2-bit processor (or socket) identifier and bits 2 and 3 form a 2-bit cluster
ID.
9.5
INTEL® HYPER-THREADING TECHNOLOGY AND INTEL® MULTI-CORE
TECHNOLOGY
Intel Hyper-Threading Technology and Intel multi-core technology are extensions to Intel 64 and IA-32 architec-
tures that enable a single physical processor to execute two or more separate code streams (called threads)
concurrently. In Intel Hyper-Threading Technology, a single processor core provides two logical processors that
share execution resources (see Section 9.7, “Intel® Hyper-Threading Technology Architecture”). In Intel multi-
core technology, a physical processor package provides two or more processor cores. Both configurations require
chipsets and a BIOS that support the technologies.
Software should not rely on processor names to determine whether a processor supports Intel Hyper-Threading
Technology or Intel multi-core technology. Use the CPUID instruction to determine processor capability (see
Section 9.6.2, “Initializing Multi-Core Processors”).
9.6
DETECTING HARDWARE MULTI-THREADING SUPPORT AND TOPOLOGY
Use the CPUID instruction to detect the presence of hardware multi-threading support in a physical processor.
Hardware multi-threading can support several varieties of multigrade and/or Intel Hyper-Threading Technology.
CPUID instruction provides several sets of parameter information to aid software enumerating topology informa-
tion. The relevant topology enumeration parameters provided by CPUID include:
Hardware Multi-Threading feature flag (CPUID.1:EDX[28] = 1) - Indicates when set that the physical
package is capable of supporting Intel Hyper-Threading Technology and/or multiple cores.
Processor topology enumeration parameters for 8-bit APIC ID:
- Addressable IDs for Logical processors in the same Package (CPUID.1:EBX[23:16]) - Indicates
the maximum number of addressable ID for logical processors in a physical package. Within a physical
package, there may be addressable IDs that are not occupied by any logical processors. This parameter
does not represents the hardware capability of the physical processor.1
Vol. 3A
9-25
MULTIPLE-PROCESSOR MANAGEMENT
Addressable IDs for processor cores in the same Package1 (CPUID.(EAX=4, ECX=02):EAX[31:26] +
1 = Y) - Indicates the maximum number of addressable IDs attributable to processor cores (Y) in the physical
package.
Extended Processor Topology Enumeration parameters for 32-bit APIC ID: Intel 64 processors
supporting CPUID leaf 0BH will assign unique APIC IDs to each logical processor in the system. CPUID leaf 0BH
reports the 32-bit APIC ID and provide topology enumeration parameters. See CPUID instruction reference
pages in Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 2A.
The CPUID feature flag may indicate support for hardware multi-threading when only one logical processor avail-
able in the package. In this case, the decimal value represented by bits 16 through 23 in the EBX register will have
a value of 1.
Software should note that the number of logical processors enabled by system software may be less than the value
of “Addressable IDs for Logical processors”. Similarly, the number of cores enabled by system software may be less
than the value of “Addressable IDs for processor cores”.
Software can detect the availability of the CPUID extended topology enumeration leaf (0BH) by performing two
steps:
Check maximum input value for basic CPUID information by executing CPUID with EAX= 0. If CPUID.0H:EAX is
greater than or equal or 11 (0BH), then proceed to next step,
Check CPUID.EAX=0BH, ECX=0H:EBX is non-zero.
If both of the above conditions are true, extended topology enumeration leaf is available. Note the presence of
CPUID leaf 0BH in a processor does not guarantee support that the local APIC supports x2APIC. If
CPUID.(EAX=0BH, ECX=0H):EBX returns zero and maximum input value for basic CPUID information is greater
than 0BH, then CPUID.0BH leaf is not supported on that processor.
9.6.1
Initializing Processors Supporting Intel® Hyper-Threading Technology
The initialization process for an MP system that contains processors supporting Intel Hyper-Threading Technology
is the same as for conventional MP systems (see Section 9.4, “Multiple-Processor (MP) Initialization”). One logical
processor in the system is selected as the BSP and other processors (or logical processors) are designated as APs.
The initialization process is identical to that described in Section 9.4.3, “MP Initialization Protocol Algorithm for MP
Systems,” and Section 9.4.4, “MP Initialization Example.”
During initialization, each logical processor is assigned an APIC ID that is stored in the local APIC ID register for
each logical processor. If two or more processors supporting Intel Hyper-Threading Technology are present, each
logical processor on the system bus is assigned a unique ID (see Section 9.9.3, “Hierarchical ID of Logical Proces-
sors in an MP System”). Once logical processors have APIC IDs, software communicates with them by sending APIC
IPI messages.
9.6.2
Initializing Multi-Core Processors
The initialization process for an MP system that contains multi-core Intel 64 or IA-32 processors is the same as for
conventional MP systems (see Section 9.4, “Multiple-Processor (MP) Initialization”). A logical processor in one core
is selected as the BSP; other logical processors are designated as APs.
During initialization, each logical processor is assigned an APIC ID. Once logical processors have APIC IDs, software
may communicate with them by sending APIC IPI messages.
1. Operating system and BIOS may implement features that reduce the number of logical processors available in a platform to applica-
tions at runtime to less than the number of physical packages times the number of hardware-capable logical processors per package.
1. Software must check CPUID for its support of leaf 4 when implementing support for multi-core. If CPUID leaf 4 is not available at run-
time, software should handle the situation as if there is only one core per package.
2. Maximum number of cores in the physical package must be queried by executing CPUID with EAX=4 and a valid ECX input value.
Valid ECX input values start from 0.
9-26
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
9.6.3
Executing Multiple Threads on an Intel® 64 or IA-32 Processor Supporting Hardware
Multi-Threading
Upon completing the operating system boot-up procedure, the bootstrap processor (BSP) executes operating
system code. Other logical processors are placed in the halt state. To execute a code stream (thread) on a halted
logical processor, the operating system issues an interprocessor interrupt (IPI) addressed to the halted logical
processor. In response to the IPI, the processor wakes up and begins executing the code identified by the vector
received as part of the IPI.
To manage execution of multiple threads on logical processors, an operating system can use conventional
symmetric multiprocessing (SMP) techniques. For example, the operating-system can use a time-slice or load
balancing mechanism to periodically interrupt each of the active logical processors. Upon interrupting a logical
processor, the operating system checks its run queue for a thread waiting to be executed and dispatches the thread
to the interrupted logical processor.
9.6.4
Handling Interrupts on an IA-32 Processor Supporting Hardware Multi-Threading
Interrupts are handled on processors supporting Intel Hyper-Threading Technology as they are on conventional MP
systems. External interrupts are received by the I/O APIC, which distributes them as interrupt messages to specific
logical processors (see Figure 9-3).
Logical processors can also send IPIs to other logical processors by writing to the ICR register of its local APIC (see
Section 11.6, “Issuing Interprocessor Interrupts”). This also applies to dual-core processors.
Intel Processor with Intel
Intel Processor with Intel
Hyper-Threading Technology
Hyper-Threading Technology
Logical
Logical
Logical
Logical
Processor 0
Processor 1
Processor 0
Processor 1
Processor Core
Processor Core
Local APIC
Local APIC
Local APIC
Local APIC
Bus Interface
Bus Interface
Interrupt
Interrupt
IPIs
IPIs
Messages
Messages
Interrupt Messages
Bridge
PCI
I/O APIC
External
Interrupts
System Chipset
Figure 9-3. Local APICs and I/O APIC in MP System Supporting Intel HT Technology
9.7
INTEL® HYPER-THREADING TECHNOLOGY ARCHITECTURE
Figure 9-4 shows a generalized view of an Intel processor supporting Intel Hyper-Threading Technology, using the
original Intel Xeon processor MP as an example. This implementation of the Intel Hyper-Threading Technology
Vol. 3A
9-27
MULTIPLE-PROCESSOR MANAGEMENT
consists of two logical processors (each represented by a separate architectural state) which share the processor’s
execution engine and the bus interface. Each logical processor also has its own advanced programmable interrupt
controller (APIC).
Logical
Logical
Processor 0
Processor 1
Architectural
Architectural
State
State
Execution Engine
Local
APIC
Local APIC
Bus Interface
System Bus
Figure 9-4. IA-32 Processor with Two Logical Processors Supporting Intel HT Technology
9.7.1
State of the Logical Processors
The following features are part of the architectural state of logical processors within Intel 64 or IA-32 processors
supporting Intel Hyper-Threading Technology. The features can be subdivided into three groups:
Duplicated for each logical processor
Shared by logical processors in a physical processor
Shared or duplicated, depending on the implementation
The following features are duplicated for each logical processor:
General purpose registers (EAX, EBX, ECX, EDX, ESI, EDI, ESP, and EBP)
Segment registers (CS, DS, SS, ES, FS, and GS)
EFLAGS and EIP registers. Note that the CS and EIP/RIP registers for each logical processor point to the
instruction stream for the thread being executed by the logical processor.
x87 FPU registers (ST0 through ST7, status word, control word, tag word, data operand pointer, and instruction
pointer)
MMX registers (MM0 through MM7)
XMM registers (XMM0 through XMM7) and the MXCSR register
Control registers and system table pointer registers (GDTR, LDTR, IDTR, task register)
Debug registers (DR0, DR1, DR2, DR3, DR6, DR7) and the debug control MSRs
Machine check global status (IA32_MCG_STATUS) and machine check capability (IA32_MCG_CAP) MSRs
Thermal clock modulation and ACPI Power management control MSRs
Time stamp counter MSRs
Most of the other MSR registers, including the page attribute table (PAT). See the exceptions below.
Local APIC registers.
Additional general purpose registers (R8-R15), XMM registers (XMM8-XMM15), control register, IA32_EFER on
Intel 64 processors.
The following features are shared by logical processors:
9-28
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
Memory type range registers (MTRRs)
Whether the following features are shared or duplicated is implementation-specific:
IA32_MISC_ENABLE MSR (MSR address 1A0H)
Machine check architecture (MCA) MSRs (except for the IA32_MCG_STATUS and IA32_MCG_CAP MSRs)
Performance monitoring control and counter MSRs
9.7.2
APIC Functionality
When a processor supporting Intel Hyper-Threading Technology support is initialized, each logical processor is
assigned a local APIC ID (see Table 11-1). The local APIC ID serves as an ID for the logical processor and is stored
in the logical processor’s APIC ID register. If two or more processors supporting Intel Hyper-Threading Technology
are present in a dual processor (DP) or MP system, each logical processor on the system bus is assigned a unique
local APIC ID (see Section 9.9.3, “Hierarchical ID of Logical Processors in an MP System”).
Software communicates with local processors using the APIC’s interprocessor interrupt (IPI) messaging facility.
Setup and programming for APICs is identical in processors that support and do not support Intel Hyper-Threading
Technology. See Chapter 11, “Advanced Programmable Interrupt Controller (APIC),” for a detailed discussion.
9.7.3
Memory Type Range Registers (MTRR)
MTRRs in a processor supporting Intel Hyper-Threading Technology are shared by logical processors. When one
logical processor updates the setting of the MTRRs, settings are automatically shared with the other logical proces-
sors in the same physical package.
The architectures require that all MP systems based on Intel 64 and IA-32 processors (this includes logical proces-
sors) must use an identical MTRR memory map. This gives software a consistent view of memory, independent of
the processor on which it is running. See Section 12.11, “Memory Type Range Registers (MTRRs),” for information
on setting up MTRRs.
9.7.4
Page Attribute Table (PAT)
Each logical processor has its own PAT MSR (IA32_PAT). However, as described in Section 12.12, “Page Attribute
Table (PAT),” the PAT MSR settings must be the same for all processors in a system, including the logical proces-
sors.
9.7.5
Machine Check Architecture
In the Intel HT Technology context as implemented by processors based on Intel NetBurst® microarchitecture, all
of the machine check architecture (MCA) MSRs (except for the IA32_MCG_STATUS and IA32_MCG_CAP MSRs) are
duplicated for each logical processor. This permits logical processors to initialize, configure, query, and handle
machine-check exceptions simultaneously within the same physical processor. The design is compatible with
machine check exception handlers that follow the guidelines given in Chapter 16, “Machine-Check Architecture.”
The IA32_MCG_STATUS MSR is duplicated for each logical processor so that its machine check in progress bit field
(MCIP) can be used to detect recursion on the part of MCA handlers. In addition, the MSR allows each logical
processor to determine that a machine-check exception is in progress independent of the actions of another logical
processor in the same physical package.
Because the logical processors within a physical package are tightly coupled with respect to shared hardware
resources, both logical processors are notified of machine check errors that occur within a given physical processor.
If machine-check exceptions are enabled when a fatal error is reported, all the logical processors within a physical
package are dispatched to the machine-check exception handler. If machine-check exceptions are disabled, the
logical processors enter the shutdown state and assert the IERR# signal.
When enabling machine-check exceptions, the MCE flag in control register CR4 should be set for each logical
processor.
Vol. 3A
9-29
MULTIPLE-PROCESSOR MANAGEMENT
On Intel Atom family processors that support Intel Hyper-Threading Technology, the MCA facilities are shared
between all logical processors on the same processor core.
9.7.6
Debug Registers and Extensions
Each logical processor has its own set of debug registers (DR0, DR1, DR2, DR3, DR6, DR7) and its own debug
control MSR. These can be set to control and record debug information for each logical processor independently.
Each logical processor also has its own last branch records (LBR) stack.
9.7.7
Performance Monitoring Counters
Performance counters and their companion control MSRs are shared between the logical processors within a
processor core for processors based on Intel NetBurst microarchitecture. As a result, software must manage the
use of these resources. The performance counter interrupts, events, and precise event monitoring support can be
set up and allocated on a per thread (per logical processor) basis.
See Section 20.6.4, “Performance Monitoring and Intel® Hyper-Threading Technology in Processors Based on Intel
NetBurst® Microarchitecture,” for a discussion of performance monitoring in the Intel Xeon processor MP.
In Intel Atom processor family that support Intel Hyper-Threading Technology, the performance counters (general-
purpose and fixed-function counters) and their companion control MSRs are duplicated for each logical processor.
9.7.8
IA32_MISC_ENABLE MSR
The IA32_MISC_ENABLE MSR (MSR address 1A0H) is generally shared between the logical processors in a
processor core supporting Intel Hyper-Threading Technology. However, some bit fields within IA32_MISC_ENABLE
MSR may be duplicated per logical processor. The partition of shared or duplicated bit fields within IA32_MISC_EN-
ABLE is implementation dependent. Software should program duplicated fields carefully on all logical processors in
the system to ensure consistent behavior.
9.7.9
Memory Ordering
The logical processors in an Intel 64 or IA-32 processor supporting Intel Hyper-Threading Technology obey the
same rules for memory ordering as Intel 64 or IA-32 processors without Intel HT Technology (see Section 9.2,
“Memory Ordering”). Each logical processor uses a processor-ordered memory model that can be further defined
as “write-ordered with store buffer forwarding.” All mechanisms for strengthening or weakening the memory-
ordering model to handle special programming situations apply to each logical processor.
9.7.10 Serializing Instructions
As a general rule, when a logical processor in a processor supporting Intel Hyper-Threading Technology executes a
serializing instruction, only that logical processor is affected by the operation. An exception to this rule is the execu-
tion of the WBINVD, INVD, and WRMSR instructions; and the MOV CR instruction when the state of the CD flag in
control register CR0 is modified. Here, both logical processors are serialized.
9.7.11 Microcode Update Resources
In an Intel processor supporting Intel Hyper-Threading Technology, the microcode update facilities are shared
between the logical processors; either logical processor can initiate an update. Each logical processor has its own
BIOS signature MSR (IA32_BIOS_SIGN_ID at MSR address 8BH). When a logical processor performs an update for
the physical processor, the IA32_BIOS_SIGN_ID MSRs for resident logical processors are updated with identical
information. If logical processors initiate an update simultaneously, the processor core provides the necessary
synchronization needed to ensure that only one update is performed at a time.
9-30
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
NOTE
Some processors (prior to the introduction of Intel 64 Architecture and based on Intel NetBurst
microarchitecture) do not support simultaneous loading of microcode update to the sibling logical
processors in the same core. All other processors support logical processors initiating an update
simultaneously. Intel recommends a common approach that the microcode loader use the
sequential technique described in Section 10.11.6.3.
9.7.12 Self Modifying Code
Intel processors supporting Intel Hyper-Threading Technology support self-modifying code, where data writes
modify instructions cached or currently in flight. They also support cross-modifying code, where on an MP system
writes generated by one processor modify instructions cached or currently in flight on another. See Section 9.1.3,
“Handling Self- and Cross-Modifying Code,” for a description of the requirements for self- and cross-modifying code
in an IA-32 processor.
9.7.13 Implementation-Specific Intel® HT Technology Facilities
The following non-architectural facilities are implementation-specific in IA-32 processors supporting Intel Hyper-
Threading Technology:
Caches.
Translation lookaside buffers (TLBs).
Thermal monitoring facilities.
The Intel Xeon processor MP implementation is described in the following sections.
9.7.13.1 Processor Caches
For processors supporting Intel Hyper-Threading Technology, the caches are shared. Any cache manipulation
instruction that is executed on one logical processor has a global effect on the cache hierarchy of the physical
processor. Note the following:
WBINVD instruction - The entire cache hierarchy is invalidated after modified data is written back to
memory. All logical processors are stopped from executing until after the write-back and invalidate operation is
completed. A special bus cycle is sent to all caching agents. The amount of time or cycles for WBINVD to
complete will vary due to the size of different cache hierarchies and other factors. As a consequence, the use of
the WBINVD instruction can have an impact on interrupt/event response time.
INVD instruction - The entire cache hierarchy is invalidated without writing back modified data to memory.
All logical processors are stopped from executing until after the invalidate operation is completed. A special bus
cycle is sent to all caching agents.
CLFLUSH and CLFLUSHOPT instructions - The specified cache line is invalidated from the cache hierarchy
after any modified data is written back to memory and a bus cycle is sent to all caching agents, regardless of
which logical processor caused the cache line to be filled.
CD flag in control register CR0 - Each logical processor has its own CR0 control register, and thus its own
CD flag in CR0. The CD flags for the two logical processors are ORed together, such that when any logical
processor sets its CD flag, the entire cache is nominally disabled.
9.7.13.2 Processor Translation Lookaside Buffers (TLBs)
In processors supporting Intel Hyper-Threading Technology, data cache TLBs are shared. The instruction cache TLB
may be duplicated or shared in each logical processor, depending on implementation specifics of different
processor families.
Entries in the TLBs are tagged with an ID that indicates the logical processor that initiated the translation. This tag
applies even for translations that are marked global using the page-global feature for memory paging. See Section
4.10, “Caching Translation Information,” for information about global translations.
Vol. 3A
9-31
MULTIPLE-PROCESSOR MANAGEMENT
When a logical processor performs a TLB invalidation operation, only the TLB entries that are tagged for that logical
processor are guaranteed to be flushed. This protocol applies to all TLB invalidation operations, including writes to
control registers CR3 and CR4 and uses of the INVLPG instruction.
9.7.13.3 Thermal Monitor
In a processor that supports Intel Hyper-Threading Technology, logical processors share the catastrophic shutdown
detector and the automatic thermal monitoring mechanism (see Section 15.8, “Thermal Monitoring and Protec-
tion”). Sharing results in the following behavior:
If the processor’s core temperature rises above the preset catastrophic shutdown temperature, the processor
core halts execution, which causes both logical processors to stop execution.
When the processor’s core temperature rises above the preset automatic thermal monitor trip temperature, the
frequency of the processor core is automatically modulated, which effects the execution speed of both logical
processors.
For software controlled clock modulation, each logical processor has its own IA32_CLOCK_MODULATION MSR,
allowing clock modulation to be enabled or disabled on a logical processor basis. Typically, if software controlled
clock modulation is going to be used, the feature must be enabled for all the logical processors within a physical
processor and the modulation duty cycle must be set to the same value for each logical processor. If the duty cycle
values differ between the logical processors, the processor clock will be modulated at the highest duty cycle
selected.
9.7.13.4 External Signal Compatibility
This section describes the constraints on external signals received through the pins of a processor supporting Intel
Hyper-Threading Technology and how these signals are shared between its logical processors.
STPCLK# - A single STPCLK# pin is provided on the physical package of the Intel Xeon processor MP. External
control logic uses this pin for power management within the system. When the STPCLK# signal is asserted, the
processor core transitions to the stop-grant state, where instruction execution is halted but the processor core
continues to respond to snoop transactions. Regardless of whether the logical processors are active or halted
when the STPCLK# signal is asserted, execution is stopped on both logical processors and neither will respond
to interrupts.
In MP systems, the STPCLK# pins on all physical processors are generally tied together. As a result this signal
affects all the logical processors within the system simultaneously.
LINT0 and LINT1 pins - A processor supporting Intel Hyper-Threading Technology has only one set of LINT0
and LINT1 pins, which are shared between the logical processors. When one of these pins is asserted, both
logical processors respond unless the pin has been masked in the APIC local vector tables for one or both of the
logical processors.
Typically in MP systems, the LINT0 and LINT1 pins are not used to deliver interrupts to the logical processors.
Instead all interrupts are delivered to the local processors through the I/O APIC.
A20M# pin - On an IA-32 processor, the A20M# pin is typically provided for compatibility with the Intel 286
processor. Asserting this pin causes bit 20 of the physical address to be masked (forced to zero) for all external
bus memory accesses. Processors supporting Intel Hyper-Threading Technology provide one A20M# pin, which
affects the operation of both logical processors within the physical processor.
The functionality of A20M# is used primarily by older operating systems and not used by modern operating
systems. On newer Intel 64 processors, A20M# may be absent.
9.8
MULTI-CORE ARCHITECTURE
This section describes the architecture of Intel 64 and IA-32 processors supporting dual-core and quad-core tech-
nology. The discussion is applicable to the Intel Pentium processor Extreme Edition, Pentium D, Intel Core Duo,
Intel Core 2 Duo, Dual-core Intel Xeon processor, Intel Core 2 Quad processors, and quad-core Intel Xeon proces-
sors. Features vary across different microarchitectures and are detectable using CPUID.
9-32
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
In general, each processor core has dedicated microarchitectural resources identical to a single-processor imple-
mentation of the underlying microarchitecture without hardware multi-threading capability. Each logical processor
in a dual-core processor (whether supporting Intel Hyper-Threading Technology or not) has its own APIC function-
ality, PAT, machine check architecture, debug registers and extensions. Each logical processor handles serialization
instructions or self-modifying code on its own. Memory order is handled the same way as in Intel Hyper-Threading
Technology.
The topology of the cache hierarchy (with respect to whether a given cache level is shared by one or more
processor cores or by all logical processors in the physical package) depends on the processor implementation.
Software must use the deterministic cache parameter leaf of CPUID instruction to discover the cache-sharing
topology between the logical processors in a multi-threading environment.
9.8.1
Logical Processor Support
The topological composition of processor cores and logical processors in a multi-core processor can be discovered
using CPUID. Within each processor core, one or more logical processors may be available.
System software must follow the requirement MP initialization sequences (see Section 9.4, “Multiple-Processor
(MP) Initialization”) to recognize and enable logical processors. At runtime, software can enumerate those logical
processors enabled by system software to identify the topological relationships between these logical processors.
(See Section 9.9.5, “Identifying Topological Relationships in an MP System”).
9.8.2
Memory Type Range Registers (MTRR)
MTRR is shared between two logical processors sharing a processor core if the physical processor supports Intel
Hyper-Threading Technology. MTRR is not shared between logical processors located in different cores or different
physical packages.
The Intel 64 and IA-32 architectures require that all logical processors in an MP system use an identical MTRR
memory map. This gives software a consistent view of memory, independent of the processor on which it is
running.
See Section 12.11, “Memory Type Range Registers (MTRRs).”
9.8.3
Performance Monitoring Counters
Performance counters and their companion control MSRs are shared between two logical processors sharing a
processor core if the processor core supports Intel Hyper-Threading Technology and is based on Intel NetBurst
microarchitecture. They are not shared between logical processors in different cores or different physical packages.
As a result, software must manage the use of these resources, based on the topology of performance monitoring
resources. Performance counter interrupts, events, and precise event monitoring support can be set up and allo-
cated on a per thread (per logical processor) basis.
See Section 20.6.4, “Performance Monitoring and Intel® Hyper-Threading Technology in Processors Based on Intel
NetBurst® Microarchitecture.”
9.8.4
IA32_MISC_ENABLE MSR
Some bit fields in IA32_MISC_ENABLE MSR (MSR address 1A0H) may be shared between two logical processors
sharing a processor core, or may be shared between different cores in a physical processor. See Chapter 2, “Model-
Specific Registers (MSRs)‚” in the Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 4.
9.8.5
Microcode Update Resources
Microcode update facilities are shared between two logical processors sharing a processor core if the physical
package supports Intel Hyper-Threading Technology. They are not shared between logical processors in different
Vol. 3A
9-33
MULTIPLE-PROCESSOR MANAGEMENT
cores or different physical packages. Either logical processor that has access to the microcode update facility can
initiate an update.
Each logical processor has its own BIOS signature MSR (IA32_BIOS_SIGN_ID at MSR address 8BH). When a logical
processor performs an update for the physical processor, the IA32_BIOS_SIGN_ID MSRs for resident logical
processors are updated with identical information.
All microcode update steps during processor initialization should use the same update data on all cores in all phys-
ical packages of the same stepping. Any subsequent microcode update must apply consistent update data to all
cores in all physical packages of the same stepping. If the processor detects an attempt to load an older microcode
update when a newer microcode update had previously been loaded, it may reject the older update to stay with the
newer update.
NOTE
Some processors (prior to the introduction of Intel 64 Architecture and based on Intel NetBurst
microarchitecture) do not support simultaneous loading of microcode update to the sibling logical
processors in the same core. All other processors support logical processors initiating an update
simultaneously. Intel recommends a common approach that the microcode loader use the
sequential technique described in Section 10.11.6.3.
9.9
PROGRAMMING CONSIDERATIONS FOR HARDWARE MULTI-THREADING
CAPABLE PROCESSORS
In a multi-threading environment, there may be certain hardware resources that are physically shared at some
level of the hardware topology. In the multi-processor systems, typically bus and memory sub-systems are physi-
cally shared between multiple sockets. Within a hardware multi-threading capable processors, certain resources
are provided for each processor core, while other resources may be provided for each logical processors (see
Section 9.7, “Intel® Hyper-Threading Technology Architecture,” and Section 9.8, “Multi-Core Architecture”).
From a software programming perspective, control transfer of processor operation is managed at the granularity of
logical processor (operating systems dispatch a runnable task by allocating an available logical processor on the
platform). To manage the topology of shared resources in a multi-threading environment, it may be useful for soft-
ware to understand and manage resources that are shared by more than one logical processors.
9.9.1
Hierarchical Mapping of Shared Resources
The APIC_ID value associated with each logical processor in a multi-processor system is unique (see Section 9.6,
“Detecting Hardware Multi-Threading Support and Topology”). This 8-bit or 32-bit value can be decomposed into
sub-fields, where each sub-field corresponds a hierarchical domain of the topological mapping of hardware
resources.
The decomposition of an APIC_ID may consist of several sub fields representing the topology within a physical
processor package, the higher-order bits of an APIC ID may also be used by cluster vendors to represent the
topology of cluster nodes of each coherent multiprocessor systems:
Cluster - Some multi-threading environments consists of multiple clusters of multi-processor systems. The
CLUSTER_ID sub-field is usually supported by vendor firmware to distinguish different clusters. For non-
clustered systems, CLUSTER_ID is usually 0 and system topology is reduced.
Package - A physical processor package mates with a socket. A package may contain one or more software
visible die. The PACKAGE_ID sub-field distinguishes different physical packages within a cluster.
Die - A software-visible chip inside a package. The DIE_ID sub-field distinguishes different die within a
package. If there are no software visible die, the width of this bit field is 0.
DieGrp - A group of die that share certain resources.
Tile - A set of cores that share certain resources. The TILE_ID sub-field distinguishes different tiles. If there
are no software visible tiles, the width of this bit field is 0.
9-34
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
Module - A set of cores that share certain resources. The MODULE_ID sub-field distinguishes different
modules. If there are no software visible modules, the width of this bit field is 0.
Core - Processor cores may be contained within modules, within tiles, on software-visible die, or appear
directly at the package domain. The CORE_ID sub-field distinguishes processor cores. For a single-core
processor, the width of this bit field is 0.
Logical Processor - A processor core provides one or more logical processors sharing execution resources.
The LOGICAL_PROCESSOR_ID sub-field distinguishes logical processors in a core. The width of this bit field is
non-zero if a processor core provides more than one logical processors.
The LOGICAL_PROCESSOR_ID and CORE_ID sub-fields are bit-wise contiguous in the APIC_ID field (see
Figure 9-5).
X
0
Reserved
CLUSTER_ID
PACKAGE_ID
DIE_ID
TILE_ID
MODULE_ID
CORE_ID
LOGICAL_PROCESSOR_ID
X=31 if x2APIC is supported, otherwise X= 7
Figure 9-5. Generalized Seven-Domain Interpretation of the APIC ID
If the processor supports CPUID leaf 0BH and leaf 1FH, the 32-bit APIC ID can represent cluster plus several
domains of topology within the physical processor package. The exact number of hierarchical domains within a
physical processor package must be enumerated through CPUID leaf 0BH and leaf 1FH. Common processor fami-
lies may employ a topology similar to that represented by the 8-bit Initial APIC ID. In general, CPUID leaf 0BH and
leaf 1FH can support a topology enumeration algorithm that decompose a 32-bit APIC ID into more than four sub-
fields (see Figure 9-6).
NOTE
CPUID leaf 0BH and leaf 1FH can have differences in the number of domain types reported (CPUID
leaf 1FH defines additional domain types). If the processor supports CPUID leaf 1FH, usage of this
leaf is preferred over leaf 0BH. CPUID leaf 0BH is available for legacy compatibility going forward.
The width of each sub-field depends on hardware and software configurations. Field widths can be determined at
runtime using the algorithm discussed below (Example 9-16 through Example 9-21).
Figure 7-6 depicts the relationships of three of the hierarchical sub-fields in a hypothetical MP system. The value of
valid APIC_IDs need not be contiguous across package boundary or core boundaries.
Vol. 3A
9-35
MULTIPLE-PROCESSOR MANAGEMENT
PACKAGE
31
0
Q
R
CORE
Reserved
LOGICAL
PROCESSOR
CLUSTER_ID
PACKAGE_ID
Q_ID
R_ID
CORE_ID
Physical Processor Topology
LOGICAL_PROCESSOR_ID
32-bit APIC ID Composition
Figure 9-6. Conceptual Six-Domain Topology and 32-bit APIC ID Composition
9.9.2
Hierarchical Mapping of CPUID Extended Topology Leaf
CPUID leaf 0BH and leaf 1FH provide enumeration parameters for software to identify each hierarchy of the
processor topology in a deterministic manner. Each hierarchical domain of the topology starting from the Logical
Processor domain is represented numerically by a sub-leaf index within the CPUID 0BH leaf and 1FH leaf. Each
domain of the topology is mapped to a sub-field in the APIC ID, following the general relationship depicted in
Figure 9-6. This mechanism allows software to query the exact number of domains within a physical processor
package and the bit-width of each sub-field of x2APIC ID directly. For example,
Starting from sub-leaf index 0 and incrementing ECX until CPUID.(EAX=0BH or 1FH, ECX=N):ECX[15:8]
returns an invalid “domain type” encoding. The number of domains within the physical processor package is “N”
(excluding PACKAGE). Using Figure 9-6 as an example, CPUID.(EAX=0BH or 1FH, ECX=4):ECX[15:8] will
report 00H, indicating sub leaf 04H is invalid. This is also depicted by a pseudo code example:
Example 9-16. Number of Domains Below the Physical Processor Package
Word NumberOfDomainsBelowPackage = 0;
DWord Subleaf = 0;
EAX = 0BH or 1FH; // query each sub leaf of CPUID leaf 0BH or 1FH; CPUID leaf 1FH is preferred over leaf 0BH if available.
ECX = Subleaf;
CPUID;
while(EBX != 0) // Enumerate until EBX reports 0
{
if(EAX[4:0] != 0)
// A Shift Value of 0 indicates this domain does not exist.
// (Such as no SMT_ID, which is required entry at sub-leaf 0.)
{
NumberOfDomainsBelowPackage++;
}
Subleaf++;
EAX = 0BH or 1FH;
ECX = Subleaf;
CPUID;
}
// NumberOfDomainsBelowPackage contains the absolute number of domains that exist below package.
N = Subleaf;
// Sub-leaf supplies the number of entries CPUID will return.
9-36
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
Sub-leaf index 0 (ECX= 0 as input) provides enumeration parameters to extract the LOGICAL_PROCESSOR_ID
sub-field of x2APIC ID. If EAX = 0BH or 1FH, and ECX =0 is specified as input when executing CPUID,
CPUID.(EAX=0BH or 1FH, ECX=0):EAX[4:0] reports a value (a right-shift count) that allow software to extract
part of x2APIC ID to distinguish the next higher topological entities above the LOGICAL_PROCESSOR_ID
domain. This value also corresponds to the bit-width of the sub-field of x2APIC ID corresponding the hierar-
chical domain with sub-leaf index 0.
For each subsequent higher sub-leaf index m, CPUID.(EAX=0BH or 1FH, ECX=m):EAX[4:0] reports the right-
shift count that will allow software to extract part of x2APIC ID to distinguish higher-domain topological
entities. This means the right-shift value at of sub-leaf m, corresponds to the least significant (m+1) sub-fields
of the 32-bit x2APIC ID.
Example 9-17. BitWidth Determination of x2APIC ID Sub-fields
For m = 0, m < N, m ++;
{
cumulative_width[m] = CPUID.(EAX=0BH or 1FH, ECX= m): EAX[4:0]; }
BitWidth[0] = cumulative_width[0];
For m = 1, m < N, m ++;
BitWidth[m] = cumulative_width[m] - cumulative_width[m-1];
NOTE
CPUID leaf 1FH is a preferred superset to leaf 0BH. Leaf 1FH defines additional domain types, and
it must be parsed by an algorithm that can handle the addition of future domain types.
Previously, only the following encoding of hierarchical domain types were defined: 0 (invalid), 1 (logical processor),
and 2 (core). With the additional hierarchical domain types available (see Section 9.9.1, “Hierarchical Mapping of
Shared Resources,” and Figure 9-5, “Generalized Seven-Domain Interpretation of the APIC ID” ) software must not
assume any “domain type” encoding value to be related to any sub-leaf index, except sub-leaf 0.
Example 9-18. Support Routines for Identifying Package, Die, Core, and Logical Processors from 32-bit x2APIC ID
a.
Derive the extraction bitmask for logical processors in a processor core and associated mask offset for different
cores.
//
// This example shows how to enumerate CPU topology domain types (domain types may or may not be known/supported by the
software)
//
// Below is the list of sample domain types used in the example.
// Refer to the CPUID Leaf 1FH definition for the actual domain type numbers: “V2 Extended Topology Enumeration Leaf (Initial EAX
Value = 1FH)” .
//
// LOGICAL PROCESSOR
// CORE
// MODULE
// TILE
// DIE
// PACKAGE
//
// The example shows how to identify and derive the extraction bitmask for the domains with identify type
LOGICAL_PROCESSOR_ID/CORE_ID/DIE_ID/PACKAGE_ID
//
int DeriveLogical_Processor_Mask_Offsets (void)
{
Vol. 3A
9-37
MULTIPLE-PROCESSOR MANAGEMENT
IF (!HWMTSupported()) return -1;
execute cpuid with EAX = 0BH or 1FH, ECX = 0;
IF (returned domain type encoding in EXC[15:8] does not match LOGICAL_PROCESSOR_ID) return -1;
Mask_Logical_Processor_shift = EAX[4:0];
//# bits shift right of APIC ID to distinguish different cores, note this can be a shift
// of zero if there is only one logical processor per core.
Logical Processor Mask =~( (-1) << Mask_Logical_Processor_shift);
//shift left to derive extraction bitmask for
// LOGICAL_PROCESSOR_ID
return 0;
}
b.
Derive the extraction bitmask for processor cores in a physical processor package and associated mask offset for
different packages.
int DeriveCore_Mask_Offsets (void)
{
IF (!HWMTSupported()) return -1;
execute cpuid with EAX = 0BH or 1FH, ECX = 0;
WHILE( ECX[15:8] ) {
//domain type encoding is valid
Mask_last_known_shift = EAX[4:0]
IF (returned domain type encoding in ECX[15:8] matches CORE) {
Mask_Core_shift = EAX[4:0];
}
ELSE IF (returned domain type encoding in ECX[15:8] matches DIE {
Mask_Die_shift = EAX[4:0];
}
//
// Keep enumerating. Check if the next domain is the desired domain and if not, keep enumerating until you reach a known
// domain or the invalid domain (“0” domain type). If there are more domains between DIE and PACKAGE, the unknown
// domains will be ignored and treated as an extension of the last known domain (i.e., DIE in this case).
//
ECX++;
execute cpuid with EAX = 0BH or 1FH;
}
COREPlusLogical_Processor_MASK = ~( (-1) << Mask_Core_shift);
DIEPlusCORE_MASK = ~( (-1) << Mask_Die_shift);
//
// Treat domains between DIE and physical package as an extension of DIE for software choosing not to implement or recognize
// these unknown domains.
//
CORE_MASK = COREPlusLogical_Processor_MASK ^ Logical Processor Mask;
DIE_MASK = DIEPlusCORE_MASK ^ COREPlusLogical_Processor_MASK;
PACKAGE_MASK = (-1) << Mask_last_known_shift;
return -1;
}
9-38
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
9.9.3
Hierarchical ID of Logical Processors in an MP System
For Intel 64 and IA-32 processors, system hardware establishes an 8-bit initial APIC ID (or 32-bit APIC ID if the
processor supports CPUID leaf 0BH) that is unique for each logical processor following power-up or RESET (see
Section 9.6.1). Each logical processor on the system is allocated an initial APIC ID. BIOS may implement features
that tell the OS to support less than the total number of logical processors on the system bus. Those logical proces-
sors that are not available to applications at runtime are halted during the OS boot process. As a result, the number
valid local APIC_IDs that can be queried by affinitizing-current-thread-context (See Example 9-23) is limited to the
number of logical processors enabled at runtime by the OS boot process.
Table 9-2 shows an example of the 8-bit APIC IDs that are initially reported for logical processors in a system with
four Intel Xeon MP processors that support Intel Hyper-Threading Technology (a total of 8 logical processors, each
physical package has two processor cores and supports Intel Hyper-Threading Technology). Of the two logical
processors within a Intel Xeon processor MP, logical processor 0 is designated the primary logical processor and
logical processor 1 as the secondary logical processor.
LOGICAL_PROCESSOR_ID
CORE_ID
T0
T1
T0
T1
T0
T1
T0
T1
PACKAGE_ID
Core 0
Core 1
Core 0
Core 1
Package 0
Package 1
Figure 9-7. Topological Relationships Between Hierarchical IDs in a Hypothetical MP Platform
Table 9-2. Initial APIC IDs for the Logical Processors in a System that has Four Intel Xeon MP Processors Supporting
Intel Hyper-Threading Technology1
Initial APIC ID
PACKAGE_ID
CORE_ID
LOGICAL_PROCESSOR_ID
0H
0H
0H
0H
1H
0H
0H
1H
2H
1H
0H
0H
3H
1H
0H
1H
4H
2H
0H
0H
5H
2H
0H
1H
6H
3H
0H
0H
7H
3H
0H
1H
NOTE:
1. Because information on the number of processor cores in a physical package was not available in early single-core processors sup-
porting Intel Hyper-Threading Technology, the CORE_ID can be treated as 0.
Table 9-3 shows the initial APIC IDs for a hypothetical situation with a dual processor system. Each physical
package providing two processor cores, and each processor core also supporting Intel Hyper-Threading Tech-
nology.
Vol. 3A
9-39
MULTIPLE-PROCESSOR MANAGEMENT
Table 9-3. Initial APIC IDs for the Logical Processors in a System that has Two Physical Processors Supporting Dual-
Core and Intel Hyper-Threading Technology
Initial APIC ID
PACKAGE_ID
CORE_ID
LOGICAL_PROCESSOR_ID
0H
0H
0H
0H
1H
0H
0H
1H
2H
0H
1H
0H
3H
0H
1H
1H
4H
1H
0H
0H
5H
1H
0H
1H
6H
1H
1H
0H
7H
1H
1H
1H
9.9.3.1
Hierarchical ID of Logical Processors with x2APIC ID
Table 9-4 shows an example of possible x2APIC ID assignments for a dual processor system that support x2APIC.
Each physical package providing four processor cores, and each processor core also supporting Intel Hyper-
Threading Technology. Note that the x2APIC ID need not be contiguous in the system.
Table 9-4. Example of Possible x2APIC ID Assignment in a System that has Two Physical Processors Supporting
x2APIC and Intel Hyper-Threading Technology
x2APIC ID
PACKAGE_ID
CORE_ID
LOGICAL_PROCESSOR_ID
0H
0H
0H
0H
1H
0H
0H
1H
2H
0H
1H
0H
3H
0H
1H
1H
4H
0H
2H
0H
5H
0H
2H
1H
6H
0H
3H
0H
7H
0H
3H
1H
10H
1H
0H
0H
11H
1H
0H
1H
12H
1H
1H
0H
13H
1H
1H
1H
14H
1H
2H
0H
15H
1H
2H
1H
16H
1H
3H
0H
17H
1H
3H
1H
9-40
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
9.9.4
Algorithm for Three-Domain Mappings of APIC_ID
Software can gather the initial APIC_IDs for each logical processor supported by the operating system at runtime1
and extract identifiers corresponding to the three domains of sharing topology (package, core, and logical
processor). The three-domain algorithms below focus on a non-clustered MP system for simplicity. They do not
assume APIC IDs are contiguous or that all logical processors on the platform are enabled.
Intel supports multi-threading systems where all physical processors report identical values in CPUID leaf 0BH,
CPUID.1:EBX[23:16]), CPUID.42:EAX[31:26], and CPUID.43:EAX[25:14]. The algorithms below assume the
target system has symmetry across physical package boundaries with respect to the number of logical processors
per package, number of cores per package, and cache topology within a package.
Software can choose to assume three-domain hierarchy if it was developed to understand only three domains.
However, software implementation needs to ensure it does not break if it runs on systems that have more domains
in the hierarchy even if it does not recognize them.
The extraction algorithm (for three-domain mappings from an APIC ID) uses the general procedure depicted in
Example 9-19, and is supplemented by more detailed descriptions on the derivation of topology enumeration
parameters for extraction bit masks:
1.
Detect hardware multi-threading support in the processor.
2.
Derive a set of bit masks that can extract the sub ID of each hierarchical domain of the topology. The algorithm
to derive extraction bit masks for LOGICAL_PROCESSOR_ID/CORE_ID/PACKAGE_ID differs based on APIC ID
is 32-bit (see step 3 below) or 8-bit (see step 4 below).
3.
If the processor supports CPUID leaf 0BH, each APIC ID contains a 32-bit value, the topology enumeration
parameters needed to derive three-domain extraction bit masks are:
a. Query the right-shift value for the LOGICAL_PROCESSOR_ID domain of the topology using CPUID leaf 0BH
with ECX =0H as input. The number of bits to shift-right on x2APIC ID (EAX[4:0]) can distinguish different
higher-domain entities above logical processor in the same physical package. This is also the width of the
bit mask to extract the LOGICAL_PROCESSOR_ID. The shift value may be 0 and enumerate no logical
processor bit mask to create. A platform where cores only have one logical processor are not required to
enumerate a separate bit layout for logical processor, and the lowest bits may only identify the core (where
core and logical processor are then synonymous).
b. Enumerate until the desired domain is found (i.e., processor cores). Determine if the next domain is the
expected domain. If the next domain is not known to the software, keep enumerating until the next known
or the last domain. Software should use the previous domain before this to represent the last previously
known domain (i.e., processor cores). If the software does not recognize or implement certain hierarchical
domains, it should assume these unknown domains as an extension of the last known domain.
c. Query CPUID leaf 0BH for the amount of bit shift to distinguish next higher-domain entities (e.g., physical
processor packages) in the system. This describes an explicit three-domain-topology situation for
commonly available processors. Consult Example 9-17 to adapt to situations beyond a three-domain
topology of a physical processor. The width of the extraction bit mask can be used to derive the cumulative
extraction bitmask to extract the sub IDs of logical processors (including different processor cores) in the
same physical package. The extraction bit mask to distinguish merely different processor cores can be
derived by xor’ing the logical processor extraction bit mask from the cumulative extraction bit mask.
d. Query the 32-bit x2APIC ID for the logical processor where the current thread is executing.
e. Derive the extraction bit masks corresponding to LOGICAL_PROCESSOR_ID, CORE_ID, and PACKAGE_ID,
starting from LOGICAL_PROCESSOR_ID.
f. Apply each extraction bit mask to the 32-bit x2APIC ID to extract sub-field IDs.
1.
As noted in Section 9.6 and Section 9.9.3, the number of logical processors supported by the OS at runtime may be less than the
total number logical processors available in the platform hardware.
2.
Maximum number of addressable ID for processor cores in a physical processor is obtained by executing CPUID with EAX=4 and a
valid ECX index. The ECX index starts at 0.
3.
Maximum number addressable ID for processor cores sharing the target cache level is obtained by executing CPUID with EAX = 4
and the ECX index corresponding to the target cache level.
Vol. 3A
9-41
MULTIPLE-PROCESSOR MANAGEMENT
4. If the processor does not support CPUID leaf 0BH, each initial APIC ID contains an 8-bit value, the topology
enumeration parameters needed to derive extraction bit masks are:
a. Query the size of address space for sub IDs that can accommodate logical processors in a physical
processor package. This size parameters (CPUID.1:EBX[23:16]) can be used to derive the width of an
extraction bitmask to enumerate the sub IDs of different logical processors in the same physical package.
b. Query the size of address space for sub IDs that can accommodate processor cores in a physical processor
package. This size parameters can be used to derive the width of an extraction bitmask to enumerate the
sub IDs of processor cores in the same physical package.
c. Query the 8-bit initial APIC ID for the logical processor where the current thread is executing.
d. Derive the extraction bit masks using respective address sizes corresponding to LOGICAL_PROCESSOR_ID,
CORE_ID, and PACKAGE_ID, starting from LOGICAL_PROCESSOR_ID.
e. Apply each extraction bit mask to the 8-bit initial APIC ID to extract sub-field IDs.
Example 9-19. Support Routines for Detecting Hardware Multi-Threading and Identifying the Relationships Between Package,
Core, and Logical Processors
1.
Detect support for Hardware Multi-Threading Support in a processor.
// Returns a non-zero value if CPUID reports the presence of hardware multi-threading
// support in the physical package where the current logical processor is located.
// This does not guarantee BIOS or OS will enable all logical processors in the physical
// package and make them available to applications.
// Returns zero if hardware multi-threading is not present.
#define HWMT_BIT 10000000H
unsigned int HWMTSupported(void)
{
// ensure cpuid instruction is supported
execute cpuid with eax = 0 to get vendor string
execute cpuid with eax = 1 to get feature flag and signature
// Check to see if this a Genuine Intel Processor
if (vendor string EQ GenuineIntel) {
return (feature_flag_edx & HWMT_BIT); // bit 28
}
return 0;
}
Example 9-20. Support Routines for Identifying Package, Core, and Logical Processors from 32-bit x2APIC ID
a.
Derive the extraction bitmask for logical processors in a processor core and associated mask offset for different
cores.
int DeriveLogical_Processor_Mask_Offsets (void)
{
if (!HWMTSupported()) return -1;
execute cpuid with eax = 11, ECX = 0;
If (returned domain type encoding in ECX[15:8] does not match logical processor) return -1;
Mask_Logical_Processor_shift = EAX[4:0];
// # bits shift right of APIC ID to distinguish different cores, note this can be a shift
// of zero if there is only one logical processor per core.
Logical Processor Mask = ~( (-1) << Mask_Logical_Processor_shift); // shift left to derive extraction bitmask for
// LOGICAL_PROCESSOR_ID
9-42
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
return 0;
}
b.
Derive the extraction bitmask for processor cores in a physical processor package and associated mask offset for
different packages.
int DeriveCore_Mask_Offsets (void)
{
if (!HWMTSupported()) return -1;
execute cpuid with eax = 11, ECX = 0;
while( ECX[15:8] ) {
// domain type encoding is valid
Mask_Core_shift = EAX[4:0];
// needed to distinguish different physical packages
ECX ++;
execute cpuid with eax = 11;
}
COREPlusLogical_Processor_MASK = ~( (-1) << Mask_Core_shift);
// treat domains between core and physical package as a core for software choosing not to implement or recognize
// these unknown domains
CORE_MASK = COREPlusLogical_Processor_MASK ^ Logical Processor Mask;
PACKAGE_MASK = (-1) << Mask_Core_shift;
return -1;
}
c.
Query the x2APIC ID of a logical processor.
APIC_IDs for each logical processor.
unsigned char Getx2APIC_ID (void)
{
unsigned reg_edx = 0;
execute cpuid with eax = 11, ECX = 0
store returned value of edx
return (unsigned) (reg_edx) ;
}
Example 9-21. Support Routines for Identifying Package, Core, and Logical Processors from 8-bit Initial APIC ID
a.
Find the size of address space for logical processors in a physical processor package.
#define NUM_LOGICAL_BITS 00FF0000H
// Use the mask above and CPUID.1.EBX[23:16] to obtain the max number of addressable IDs
// for logical processors in a physical package,
//Returns the size of address space of logical processors in a physical processor package;
// Software should not assume the value to be a power of 2.
unsigned char MaxLPIDsPerPackage(void)
{
if (!HWMTSupported()) return 1;
execute cpuid with eax = 1
store returned value of ebx
return (unsigned char) ((reg_ebx & NUM_LOGICAL_BITS) >> 16);
}
Vol. 3A
9-43
MULTIPLE-PROCESSOR MANAGEMENT
b.
Find the size of address space for processor cores in a physical processor package.
// Returns the max number of addressable IDs for processor cores in a physical processor package;
// Software should not assume cpuid reports this value to be a power of 2.
unsigned MaxCoreIDsPerPackage(void)
{
if (!HWMTSupported()) return (unsigned char) 1;
if cpuid supports leaf number 4
{ // we can retrieve multi-core topology info using leaf 4
execute cpuid with eax = 4, ecx = 0
store returned value of eax
return (unsigned) ((reg_eax >> 26) +1);
}
else // must be a single-core processor
return 1;
}
c.
Query the initial APIC ID of a logical processor.
#define INITIAL_APIC_ID_BITS FF000000H // CPUID.1.EBX[31:24] initial APIC ID
// Returns the 8-bit unique initial APIC ID for the processor running the code.
// Software can use OS services to affinitize the current thread to each logical processor
// available under the OS to gather the initial APIC_IDs for each logical processor.
unsigned GetInitAPIC_ID (void)
{
unsigned int reg_ebx = 0;
execute cpuid with eax = 1
store returned value of ebx
return (unsigned) ((reg_ebx & INITIAL_APIC_ID_BITS) >> 24;
}
d.
Find the width of an extraction bitmask from the maximum count of the bit-field (address size).
// Returns the mask bit width of a bit field from the maximum count that bit field can represent.
// This algorithm does not assume ‘address size’ to have a value equal to power of 2.
// Address size for LOGICAL_PROCESSOR_ID can be calculated from MaxLPIDsPerPackage()/MaxCoreIDsPerPackage()
// Then use the routine below to derive the corresponding width of logical processor extraction bitmask
// Address size for CORE_ID is MaxCoreIDsPerPackage(),
// Derive the bitwidth for CORE extraction mask similarly
unsigned FindMaskWidth(Unsigned Max_Count)
{unsigned int mask_width, cnt = Max_Count;
__asm {
mov eax, cnt
mov ecx, 0
mov mask_width, ecx
dec eax
bsr cx, ax
jz next
inc cx
mov mask_width, ecx
next:
mov eax, mask_width
9-44
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
}
return mask_width;
}
e.
Extract a sub ID from an 8-bit full ID, using address size of the sub ID and shift count.
// The routine below can extract LOGICAL_PROCESSOR_ID, CORE_ID, and PACKAGE_ID respectively from the init APIC_ID
// To extract LOGICAL_PROCESSOR_ID, MaxSubIDvalue is set to the address size of LOGICAL_PROCESSOR_ID, Shift_Count = 0
// To extract CORE_ID, MaxSubIDvalue is the address size of CORE_ID, Shift_Count is width of logical processor extraction bitmask.
// Returns the value of the sub ID, this is not a zero-based value
Unsigned char GetSubID(unsigned char Full_ID, unsigned char MaxSubIDvalue, unsigned char Shift_Count)
{
MaskWidth = FindMaskWidth(MaxSubIDValue);
MaskBits = ((uchar) (FFH << Shift_Count)) ^ ((uchar) (FFH << Shift_Count + MaskWidth)) ;
SubID = Full_ID & MaskBits;
Return SubID;
}
Software must not assume local APIC_ID values in an MP system are consecutive. Non-consecutive local APIC_IDs
may be the result of hardware configurations or debug features implemented in the BIOS or OS.
An identifier for each hierarchical domain can be extracted from an 8-bit APIC_ID using the support routines illus-
trated in Example 9-21. The appropriate bit mask and shift value to construct the appropriate bit mask for each
domain must be determined dynamically at runtime.
9.9.5
Identifying Topological Relationships in an MP System
To detect the number of physical packages, processor cores, or other topological relationships in a MP system, the
following procedures are recommended:
Extract the three-domain identifiers from the APIC ID of each logical processor enabled by system software.
The sequence is as follows (see the pseudo code shown in Example 9-22 and support routines shown in
Example 9-19):
The extraction start from the right-most bit field, corresponding to LOGICAL_PROCESSOR_ID, the
innermost hierarchy in a three-domain topology (See Figure 9-7). For the right-most bit field, the shift
value of the working mask is zero. The width of the bit field is determined dynamically using the
maximum number of logical processor per core, which can be derived from information provided from
CPUID.
To extract the next bit-field, the shift value of the working mask is determined from the width of the bit
mask of the previous step. The width of the bit field is determined dynamically using the maximum
number of cores per package.
To extract the remaining bit-field, the shift value of the working mask is determined from the maximum
number of logical processor per package. So the remaining bits in the APIC ID (excluding those bits
already extracted in the two previous steps) are extracted as the third identifier. This applies to a non-
clustered MP system, or if there is no need to distinguish between PACKAGE_ID and CLUSTER_ID.
If there is need to distinguish between PACKAGE_ID and CLUSTER_ID, PACKAGE_ID can be extracted
using an algorithm similar to the extraction of CORE_ID, assuming the number of physical packages in
each node of a clustered system is symmetric.
Assemble the three-domain identifiers of LOGICAL_PROCESSOR_ID, CORE_ID, PACKAGE_IDs into arrays for
each enabled logical processor. This is shown in Example 9-23a.
To detect the number of physical packages: use PACKAGE_ID to identify those logical processors that reside in
the same physical package. This is shown in Example 9-23b. This example also depicts a technique to construct
a mask to represent the logical processors that reside in the same package.
Vol. 3A
9-45
MULTIPLE-PROCESSOR MANAGEMENT
To detect the number of processor cores: use CORE_ID to identify those logical processors that reside in the
same core. This is shown in Example 9-23. This example also depicts a technique to construct a mask to
represent the logical processors that reside in the same core.
In Example 9-22, the numerical ID value can be obtained from the value extracted with the mask by shifting it right
by shift count. Algorithms below do not shift the value. The assumption is that the SubID values can be compared
for equivalence without the need to shift.
Example 9-22. Pseudo Code Depicting Three-Domain Extraction Algorithm
For Each local_APIC_ID{
// Calculate Logical Processor Mask, the bit mask pattern to extract LOGICAL_PROCESSOR_ID,
// Logical Processor Mask is determined using topology enumertaion parameters
// from CPUID leaf 0BH (Example 9-20);
// otherwise, Logical Processor Mask is determined using CPUID leaf 01H and leaf 04H (Example 9-21).
// This algorithm assumes there is symmetry across core boundary, i.e., each core within a
// package has the same number of logical processors
// LOGICAL_PROCESSOR_ID always starts from bit 0, corresponding to the right-most bit-field
LOGICAL_PROCESSOR_ID = APIC_ID & Logical Processor Mask;
// Extract CORE_ID:
// Core Mask is determined in Example 9-20 or Example 9-21
CORE_ID = (APIC_ID & Core Mask);
// Extract PACKAGE_ID:
// Assume single cluster.
// Shift out the mask width for maximum logical processors per package
// Package Mask is determined in Example 9-20 or Example 9-21
PACKAGE_ID = (APIC_ID & Package Mask) ;
}
Example 9-23. Compute the Number of Packages, Cores, and Processor Relationships in a MP System
a) Assemble lists of PACKAGE_ID, CORE_ID, and LOGICAL_PROCESSOR_ID of each enabled logical processors
// The BIOS and/or OS may limit the number of logical processors available to applications after system boot.
// The below algorithm will compute topology for the processors visible to the thread that is computing it.
// Extract the 3-domains of IDs on every processor.
// SystemAffinity is a bitmask of all the processors started by the OS. Use OS specific APIs to obtain it.
// ThreadAffinityMask is used to affinitize the topology enumeration thread to each processor using OS specific APIs.
// Allocate per processor arrays to store the Package_ID, Core_ID, and LOGICAL_PROCESSOR_ID for every started processor.
ThreadAffinityMask = 1;
ProcessorNum = 0;
while (ThreadAffinityMask 0 && ThreadAffinityMask <= SystemAffinity) {
// Check to make sure we can utilize this processor first.
if (ThreadAffinityMask & SystemAffinity){
Set thread to run on the processor specified in ThreadAffinityMask
Wait if necessary and ensure thread is running on specified processor
APIC_ID = GetAPIC_ID(); // 32 bit ID in Example 9-20 or 8-bit ID in Example 9-21
Extract the Package_ID, Core_ID, and LOGICAL_PROCESSOR_ID as explained in three domain extraction
algorithm of Example 9-22
PackageID[ProcessorNUM] = PACKAGE_ID;
CoreID[ProcessorNum] = CORE_ID;
9-46
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
LOGICAL_PROCESSOR_ID[ProcessorNum] = LOGICAL_PROCESSOR_ID;
ProcessorNum++;
}
ThreadAffinityMask <<= 1;
}
NumStartedLPs = ProcessorNum;
b) Using the list of PACKAGE_ID to count the number of physical packages in a MP system and construct, for each package, a multi-bit
mask corresponding to those logical processors residing in the same package.
// Compute the number of packages by counting the number of processors with unique PACKAGE_IDs in the PackageID array.
// Compute the mask of processors in each package.
// PackageIDBucket is an array of unique PACKAGE_ID values. Allocate an array of NumStartedLPs count of entries in this array.
// PackageProcessorMask is a corresponding array of the bit mask of processors belonging to the same package, these are
// processors with the same PACKAGE_ID.
// The algorithm below assumes there is symmetry across package boundary if more than one socket is populated in an MP
//system.
// Bucket Package IDs and compute processor mask for every package.
PackageNum = 1;
PackageIDBucket[0] = PackageID[0];
ProcessorMask = 1;
PackageProcessorMask[0] = ProcessorMask;
For (ProcessorNum = 1; ProcessorNum < NumStartedLPs; ProcessorNum++) {
ProcessorMask << = 1;
For (i=0; i < PackageNum; i++) {
// we may be comparing bit-fields of logical processors residing in different
// packages, the code below assume package symmetry
If (PackageID[ProcessorNum] = PackageIDBucket[i]) {
PackageProcessorMask[i] |= ProcessorMask;
Break; // found in existing bucket, skip to next iteration
}
}
if (i =PackageNum) {
//PACKAGE_ID did not match any bucket, start new bucket
PackageIDBucket[i] = PackageID[ProcessorNum];
PackageProcessorMask[i] = ProcessorMask;
PackageNum++;
}
}
// PackageNum has the number of Packages started in OS
// PackageProcessorMask[] array has the processor set of each package
c) Using the list of CORE_ID to count the number of cores in a MP system and construct, for each core, a multi-bit mask corresponding
to those logical processors residing in the same core.
Processors in the same core can be determined by bucketing the processors with the same PACKAGE_ID and CORE_ID. Note that code
below can BIT OR the values of PACKGE and CORE ID because they have not been shifted right.
The algorithm below assumes there is symmetry across package boundary if more than one socket is populated in an MP system.
//Bucketing PACKAGE and CORE IDs and computing processor mask for every core
CoreNum = 1;
CoreIDBucket[0] = PackageID[0] | CoreID[0];
ProcessorMask = 1;
Vol. 3A
9-47
MULTIPLE-PROCESSOR MANAGEMENT
CoreProcessorMask[0] = ProcessorMask;
For (ProcessorNum = 1; ProcessorNum < NumStartedLPs; ProcessorNum++) {
ProcessorMask << = 1;
For (i=0; i < CoreNum; i++) {
// we may be comparing bit-fields of logical processors residing in different
// packages, the code below assume package symmetry
If ((PackageID[ProcessorNum] | CoreID[ProcessorNum]) = CoreIDBucket[i]) {
CoreProcessorMask[i] |= ProcessorMask;
Break; // found in existing bucket, skip to next iteration
}
}
if (i = CoreNum) {
//Did not match any bucket, start new bucket
CoreIDBucket[i] = PackageID[ProcessorNum] | CoreID[ProcessorNum];
CoreProcessorMask[i] = ProcessorMask;
CoreNum++;
}
}
// CoreNum has the number of cores started in the OS
// CoreProcessorMask[] array has the processor set of each core
Other processor relationships such as processor mask of sibling cores can be computed from set operations of the
PackageProcessorMask[] and CoreProcessorMask[].
The algorithm shown above can be adapted to work with earlier generations of single-core IA-32 processors that
support Intel Hyper-Threading Technology and in situations that the deterministic cache parameter leaf is not
supported (provided CPUID supports initial APIC ID). A reference code example is available (see Intel® 64 Archi-
tecture Processor Topology Enumeration Technical Paper).
9.10
MANAGEMENT OF IDLE AND BLOCKED CONDITIONS
When a logical processor in an MP system (including multi-core processor or processors supporting Intel Hyper-
Threading Technology) is idle (no work to do) or blocked (on a lock or semaphore), additional management of the
core execution engine resource can be accomplished by using the HLT (halt), PAUSE, or the MONITOR/MWAIT
instructions.
9.10.1 HLT Instruction
The HLT instruction stops the execution of the logical processor on which it is executed and places it in a halted
state until further notice (see the description of the HLT instruction in Chapter 3 of the Intel® 64 and IA-32 Archi-
tectures Software Developer’s Manual, Volume 2A). When a logical processor is halted, active logical processors
continue to have full access to the shared resources within the physical package. Here shared resources that were
being used by the halted logical processor become available to active logical processors, allowing them to execute
at greater efficiency. When the halted logical processor resumes execution, shared resources are again shared
among all active logical processors. (See Section 9.10.6.3, “Halt Idle Logical Processors,” for more information
about using the HLT instruction with processors supporting Intel Hyper-Threading Technology.)
9.10.2 PAUSE Instruction
The PAUSE instruction can improves the performance of processors supporting Intel Hyper-Threading Technology
when executing “spin-wait loops” and other routines where one thread is accessing a shared lock or semaphore in
a tight polling loop. When executing a spin-wait loop, the processor can suffer a severe performance penalty when
exiting the loop because it detects a possible memory order violation and flushes the core processor’s pipeline. The
PAUSE instruction provides a hint to the processor that the code sequence is a spin-wait loop. The processor uses
9-48
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
this hint to avoid the memory order violation and prevent the pipeline flush. In addition, the PAUSE instruction de-
pipelines the spin-wait loop to prevent it from consuming execution resources excessively and consume power
needlessly. (See Section 9.10.6.1, “Use the PAUSE Instruction in Spin-Wait Loops,” for more information about
using the PAUSE instruction with IA-32 processors supporting Intel Hyper-Threading Technology.)
9.10.3 Detecting Support MONITOR/MWAIT Instruction
Streaming SIMD Extensions 3 introduced two instructions (MONITOR and MWAIT) to help multithreaded software
improve thread synchronization. In the initial implementation, MONITOR and MWAIT are available to software at
ring 0. The instructions are conditionally available at levels greater than 0. Use the following steps to detect the
availability of MONITOR and MWAIT:
Use CPUID to query the MONITOR bit (CPUID.1.ECX[3] = 1).
If CPUID indicates support, execute MONITOR inside a TRY/EXCEPT exception handler and trap for an
exception. If an exception occurs, MONITOR and MWAIT are not supported at a privilege level greater than 0.
See Example 9-24.
Example 9-24. Verifying MONITOR/MWAIT Support
boolean MONITOR_MWAIT_works = TRUE;
try {
_asm {
xor ecx, ecx
xor edx, edx
mov eax, MemArea
monitor
}
// Use monitor
} except (UNWIND) {
// if we get here, MONITOR/MWAIT is not supported
MONITOR_MWAIT_works = FALSE;
}
9.10.4 MONITOR/MWAIT Instruction
Operating systems usually implement idle loops to handle thread synchronization. In a typical idle-loop scenario,
there could be several “busy loops” and they would use a set of memory locations. An impacted processor waits in
a loop and poll a memory location to determine if there is available work to execute. The posting of work is typically
a write to memory (the work-queue of the waiting processor). The time for initiating a work request and getting it
scheduled is on the order of a few bus cycles.
From a resource sharing perspective (logical processors sharing execution resources), use of the HLT instruction in
an OS idle loop is desirable but has implications. Executing the HLT instruction on a idle logical processor puts the
targeted processor in a non-execution state. This requires another processor (when posting work for the halted
logical processor) to wake up the halted processor using an inter-processor interrupt. The posting and servicing of
such an interrupt introduces a delay in the servicing of new work requests.
In a shared memory configuration, exits from busy loops usually occur because of a state change applicable to a
specific memory location; such a change tends to be triggered by writes to the memory location by another agent
(typically a processor).
MONITOR/MWAIT complement the use of HLT and PAUSE to allow for efficient partitioning and un-partitioning of
shared resources among logical processors sharing physical resources. MONITOR sets up an effective address
range that is monitored for write-to-memory activities; MWAIT places the processor in an optimized state (this
may vary between different implementations) until a write to the monitored address range occurs.
In the initial implementation of MONITOR and MWAIT, they are available at CPL = 0 only.
Vol. 3A
9-49
MULTIPLE-PROCESSOR MANAGEMENT
Both instructions rely on the state of the processor’s monitor hardware. The monitor hardware can be either armed
(by executing the MONITOR instruction) or triggered (due to a variety of events, including a store to the monitored
memory region). If upon execution of MWAIT, monitor hardware is in a triggered state: MWAIT behaves as a NOP
and execution continues at the next instruction in the execution stream. The state of monitor hardware is not archi-
tecturally visible except through the behavior of MWAIT.
Multiple events other than a write to the triggering address range can cause a processor that executed MWAIT to
wake up. These include events that would lead to voluntary or involuntary context switches, such as:
External interrupts, including NMI, SMI, INIT, BINIT, MCERR, A20M#
Faults, Aborts (including Machine Check)
Architectural TLB invalidations including writes to CR0, CR3, CR4, and certain MSR writes; execution of LMSW
(occurring prior to issuing MWAIT but after setting the monitor)
Voluntary transitions due to fast system call and far calls (occurring prior to issuing MWAIT but after setting the
monitor)
Power management related events (such as Thermal Monitor 2 or chipset driven STPCLK# assertion) will not cause
the monitor event pending flag to be cleared. Faults will not cause the monitor event pending flag to be cleared.
Software should not allow for voluntary context switches in between MONITOR/MWAIT in the instruction flow. Note
that execution of MWAIT does not re-arm the monitor hardware. This means that MONITOR/MWAIT need to be
executed in a loop. Also note that exits from the MWAIT state could be due to a condition other than a write to the
triggering address; software should explicitly check the triggering data location to determine if the write occurred.
Software should also check the value of the triggering address following the execution of the monitor instruction
(and prior to the execution of the MWAIT instruction). This check is to identify any writes to the triggering address
that occurred during the course of MONITOR execution.
The address range provided to the MONITOR instruction must be of write-back caching type. Only write-back
memory type stores to the monitored address range will trigger the monitor hardware. If the address range is not
in memory of write-back type, the address monitor hardware may not be set up properly or the monitor hardware
may not be armed. Software is also responsible for ensuring that
Writes that are not intended to cause the exit of a busy loop do not write to a location within the address region
being monitored by the monitor hardware,
Writes intended to cause the exit of a busy loop are written to locations within the monitored address region.
Not doing so will lead to more false wakeups (an exit from the MWAIT state not due to a write to the intended data
location). These have negative performance implications. It might be necessary for software to use padding to
prevent false wakeups. CPUID provides a mechanism for determining the size data locations for monitoring as well
as a mechanism for determining the size of a the pad.
9.10.5 Monitor/Mwait Address Range Determination
To use the MONITOR/MWAIT instructions, software should know the length of the region monitored by the
MONITOR/MWAIT instructions and the size of the coherence line size for cache-snoop traffic in a multiprocessor
system. This information can be queried using the CPUID monitor leaf function (EAX = 05H). You will need the
smallest and largest monitor line size:
To avoid missed wake-ups: make sure that the data structure used to monitor writes fits within the smallest
monitor line-size. Otherwise, the processor may not wake up after a write intended to trigger an exit from
MWAIT.
To avoid false wake-ups; use the largest monitor line size to pad the data structure used to monitor writes.
Software must make sure that beyond the data structure, no unrelated data variable exists in the triggering
area for MWAIT. A pad may be needed to avoid this situation.
These above two values bear no relationship to cache line size in the system and software should not make any
assumptions to that effect. Within a single-cluster system, the two parameters should default to be the same (the
size of the monitor triggering area is the same as the system coherence line size).
Based on the monitor line sizes returned by the CPUID, the OS should dynamically allocate structures with appro-
priate padding. If static data structures must be used by an OS, attempt to adapt the data structure and use a
9-50
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
dynamically allocated data buffer for thread synchronization. When the latter technique is not possible, consider
not using MONITOR/MWAIT when using static data structures.
To set up the data structure correctly for MONITOR/MWAIT on multi-clustered systems: interaction between
processors, chipsets, and the BIOS is required (system coherence line size may depend on the chipset used in the
system; the size could be different from the processor’s monitor triggering area). The BIOS is responsible to set the
correct value for system coherence line size using the IA32_MONITOR_FILTER_LINE_SIZE MSR. Depending on the
relative magnitude of the size of the monitor triggering area versus the value written into the IA32_MONITOR_FIL-
TER_LINE_SIZE MSR, the smaller of the parameters will be reported as the Smallest Monitor Line Size. The larger
of the parameters will be reported as the Largest Monitor Line Size.
9.10.6 Required Operating System Support
This section describes changes that must be made to an operating system to run on processors supporting Intel
Hyper-Threading Technology. It also describes optimizations that can help an operating system make more effi-
cient use of the logical processors sharing execution resources. The required changes and suggested optimizations
are representative of the types of modifications that appear in Windows* XP and Linux* kernel 2.4.0 operating
systems for Intel processors supporting Intel Hyper-Threading Technology. Additional optimizations for processors
supporting Intel Hyper-Threading Technology are described in the Intel® 64 and IA-32 Architectures Optimization
Reference Manual.
9.10.6.1 Use the PAUSE Instruction in Spin-Wait Loops
Intel recommends that a PAUSE instruction be placed in all spin-wait loops that run on Intel processors supporting
Intel Hyper-Threading Technology and multi-core processors.
Software routines that use spin-wait loops include multiprocessor synchronization primitives (spin-locks, sema-
phores, and mutex variables) and idle loops. Such routines keep the processor core busy executing a load-compare-
branch loop while a thread waits for a resource to become available. Including a PAUSE instruction in such a loop
greatly improves efficiency (see Section 9.10.2, “PAUSE Instruction”). The following routine gives an example of a
spin-wait loop that uses a PAUSE instruction:
Spin_Lock:
CMP lockvar, 0
;Check if lock is free
JE Get_Lock
PAUSE
;Short delay
JMP Spin_Lock
Get_Lock:
MOV EAX, 1
XCHG EAX, lockvar ;Try to get lock
CMP EAX, 0
;Test if successful
JNE Spin_Lock
Critical_Section:
<critical section code>
MOV lockvar, 0
Continue:
The spin-wait loop above uses a “test, test-and-set” technique for determining the availability of the synchroniza-
tion variable. This technique is recommended when writing spin-wait loops.
In IA-32 processor generations earlier than the Pentium 4 processor, the PAUSE instruction is treated as a NOP
instruction.
9.10.6.2 Potential Usage of MONITOR/MWAIT in C0 Idle Loops
An operating system may implement different handlers for different idle states. A typical OS idle loop on an ACPI-
compatible OS is shown in Example 9-25:
Vol. 3A
9-51
MULTIPLE-PROCESSOR MANAGEMENT
Example 9-25. A Typical OS Idle Loop
// WorkQueue is a memory location indicating there is a thread
// ready to run. A non-zero value for WorkQueue is assumed to
// indicate the presence of work to be scheduled on the processor.
// The idle loop is entered with interrupts disabled.
WHILE (1) {
IF (WorkQueue) THEN {
// Schedule work at WorkQueue.
}
ELSE {
// No work to do - wait in appropriate C-state handler depending
// on Idle time accumulated
IF (IdleTime >= IdleTimeThreshhold) THEN {
// Call appropriate C1, C2, C3 state handler, C1 handler
// shown below
}
}
}
// C1 handler uses a Halt instruction
VOID C1Handler()
{
STI
HLT
}
The MONITOR and MWAIT instructions may be considered for use in the C0 idle state loops, if MONITOR and MWAIT are supported.
Example 9-26. An OS Idle Loop with MONITOR/MWAIT in the C0 Idle Loop
// WorkQueue is a memory location indicating there is a thread
// ready to run. A non-zero value for WorkQueue is assumed to
// indicate the presence of work to be scheduled on the processor.
// The following example assumes that the necessary padding has been
// added surrounding WorkQueue to eliminate false wakeups
// The idle loop is entered with interrupts disabled.
WHILE (1) {
IF (WorkQueue) THEN {
// Schedule work at WorkQueue.
}
ELSE {
// No work to do - wait in appropriate C-state handler depending
// on Idle time accumulated.
IF (IdleTime >= IdleTimeThreshhold) THEN {
// Call appropriate C1, C2, C3 state handler, C1
// handler shown below
MONITOR WorkQueue
// Setup of eax with WorkQueue
// LinearAddress,
// ECX, EDX = 0
IF (WorkQueue = 0) THEN {
MWAIT
}
}
}
9-52
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
}
// C1 handler uses a Halt instruction.
VOID C1Handler()
{
STI
HLT
}
9.10.6.3 Halt Idle Logical Processors
If one of two logical processors is idle or in a spin-wait loop of long duration, explicitly halt that processor by means
of a HLT instruction.
In an MP system, operating systems can place idle processors into a loop that continuously checks the run queue
for runnable software tasks. Logical processors that execute idle loops consume a significant amount of core’s
execution resources that might otherwise be used by the other logical processors in the physical package. For this
reason, halting idle logical processors optimizes the performance.1 If all logical processors within a physical
package are halted, the processor will enter a power-saving state.
9.10.6.4 Potential Usage of MONITOR/MWAIT in C1 Idle Loops
An operating system may also consider replacing HLT with MONITOR/MWAIT in its C1 idle loop. An example is
shown in Example 9-27:
Example 9-27. An OS Idle Loop with MONITOR/MWAIT in the C1 Idle Loop
// WorkQueue is a memory location indicating there is a thread
// ready to run. A non-zero value for WorkQueue is assumed to
// indicate the presence of work to be scheduled on the processor.
// The following example assumes that the necessary padding has been
// added surrounding WorkQueue to eliminate false wakeups
// The idle loop is entered with interrupts disabled.
WHILE (1) {
IF (WorkQueue) THEN {
// Schedule work at WorkQueue
}
ELSE {
// No work to do - wait in appropriate C-state handler depending
// on Idle time accumulated
IF (IdleTime >= IdleTimeThreshhold) THEN {
// Call appropriate C1, C2, C3 state handler, C1
// handler shown below
}
}
}
VOID C1Handler()
{
MONITOR WorkQueue
// Setup of eax with WorkQueue LinearAddress,
// ECX, EDX = 0
IF (WorkQueue = 0) THEN {
STI
1. Excessive transitions into and out of the HALT state could also incur performance penalties. Operating systems should evaluate the
performance trade-offs for their operating system.
Vol. 3A
9-53
MULTIPLE-PROCESSOR MANAGEMENT
MWAIT
// EAX, ECX = 0
}
}
9.10.6.5 Guidelines for Scheduling Threads on Logical Processors Sharing Execution Resources
Because the logical processors, the order in which threads are dispatched to logical processors for execution can
affect the overall efficiency of a system. The following guidelines are recommended for scheduling threads for
execution.
Dispatch threads to one logical processor per processor core before dispatching threads to the other logical
processor sharing execution resources in the same processor core.
In an MP system with two or more physical packages, distribute threads out over all the physical processors,
rather than concentrate them in one or two physical processors.
Use processor affinity to assign a thread to a specific processor core or package, depending on the cache-
sharing topology. The practice increases the chance that the processor’s caches will contain some of the
thread’s code and data when it is dispatched for execution after being suspended.
9.10.6.6 Eliminate Execution-Based Timing Loops
Intel discourages the use of timing loops that depend on a processor’s execution speed to measure time. There are
several reasons:
Timing loops cause problems when they are calibrated on a IA-32 processor running at one frequency and then
executed on a processor running at another frequency.
Routines for calibrating execution-based timing loops produce unpredictable results when run on an IA-32
processor supporting Intel Hyper-Threading Technology. This is due to the sharing of execution resources
between the logical processors within a physical package.
To avoid the problems described, timing loop routines must use a timing mechanism for the loop that does not
depend on the execution speed of the logical processors in the system. The following sources are generally avail-
able:
A high resolution system timer (for example, an Intel 8254).
A high resolution timer within the processor (such as, the local APIC timer or the time-stamp counter).
For additional information, see the Intel® 64 and IA-32 Architectures Optimization Reference Manual.
9.10.6.7 Place Locks and Semaphores in Aligned, 128-Byte Blocks of Memory
When software uses locks or semaphores to synchronize processes, threads, or other code sections; Intel recom-
mends that only one lock or semaphore be present within a cache line (or 128 byte sector, if 128-byte sector is
supported). In processors based on Intel NetBurst microarchitecture (which support 128-byte sector consisting of
two cache lines), following this recommendation means that each lock or semaphore should be contained in a 128-
byte block of memory that begins on a 128-byte boundary. The practice minimizes the bus traffic required to
service locks.
9.11
MP INITIALIZATION FOR P6 FAMILY PROCESSORS
This section describes the MP initialization process for systems that use multiple P6 family processors. This process
uses the MP initialization protocol that was introduced with the Pentium Pro processor (see Section 9.4, “Multiple-
Processor (MP) Initialization”). For P6 family processors, this protocol is typically used to boot 2 or 4 processors
that reside on single system bus; however, it can support from 2 to 15 processors in a multi-clustered system when
the APIC buses are tied together. Larger systems are not supported.
9-54
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
9.11.1 Overview of the MP Initialization Process for P6 Family Processors
During the execution of the MP initialization protocol, one processor is selected as the bootstrap processor (BSP)
and the remaining processors are designated as application processors (APs), see Section 9.4.1, “BSP and AP
Processors.” Thereafter, the BSP manages the initialization of itself and the APs. This initialization includes
executing BIOS initialization code and operating-system initialization code.
The MP protocol imposes the following requirements and restrictions on the system:
An APIC clock (APICLK) must be provided.
The MP protocol will be executed only after a power-up or RESET. If the MP protocol has been completed and a
BSP has been chosen, subsequent INITs (either to a specific processor or system wide) do not cause the MP
protocol to be repeated. Instead, each processor examines its BSP flag (in the APIC_BASE MSR) to determine
whether it should execute the BIOS boot-strap code (if it is the BSP) or enter a wait-for-SIPI state (if it is an
AP).
All devices in the system that are capable of delivering interrupts to the processors must be inhibited from
doing so for the duration of the MP initialization protocol. The time during which interrupts must be inhibited
includes the window between when the BSP issues an INIT-SIPI-SIPI sequence to an AP and when the AP
responds to the last SIPI in the sequence.
The following special-purpose interprocessor interrupts (IPIs) are used during the boot phase of the MP initializa-
tion protocol. These IPIs are broadcast on the APIC bus.
Boot IPI (BIPI)-Initiates the arbitration mechanism that selects a BSP from the group of processors on the
system bus and designates the remainder of the processors as APs. Each processor on the system bus
broadcasts a BIPI to all the processors following a power-up or RESET.
Final Boot IPI (FIPI)-Initiates the BIOS initialization procedure for the BSP. This IPI is broadcast to all the
processors on the system bus, but only the BSP responds to it. The BSP responds by beginning execution of the
BIOS initialization code at the reset vector.
Startup IPI (SIPI)-Initiates the initialization procedure for an AP. The SIPI message contains a vector to the AP
initialization code in the BIOS.
Table 9-5 describes the various fields of the boot phase IPIs.
Table 9-5. Boot Phase IPI Message Format
Destination
Destination
Trigger
Destination
Delivery
Vector
Type
Field
Shorthand
Mode
Level
Mode
Mode
(Hex)
BIPI
Not used
All including self
Edge
Deassert
Don’t Care
Fixed
40 to 4E*
(000)
FIPI
Not used
All including self
Edge
Deassert
Don’t Care
Fixed
10
(000)
SIPI
Used
All excluding self
Edge
Assert
Physical
StartUp
00 to FF
(110)
NOTE:
* For all P6 family processors.
For BIPI messages, the lower 4 bits of the vector field contain the APIC ID of the processor issuing the message and
the upper 4 bits contain the “generation ID” of the message. All P6 family processor will have a generation ID of
4H. BIPIs will therefore use vector values ranging from 40H to 4EH (4FH can not be used because FH is not a valid
APIC ID).
9.11.2 MP Initialization Protocol Algorithm
Following a power-up or RESET of a system, the P6 family processors in the system execute the MP initialization
protocol algorithm to initialize each of the processors on the system bus. In the course of executing this algorithm,
the following boot-up and initialization operations are carried out:
Vol. 3A
9-55
MULTIPLE-PROCESSOR MANAGEMENT
1. Each processor on the system bus is assigned a unique APIC ID, based on system topology (see Section 9.4.5,
“Identifying Logical Processors in an MP System”). This ID is written into the local APIC ID register for each
processor.
2. Each processor executes its internal BIST simultaneously with the other processors on the system bus. Upon
completion of the BIST (at T0), each processor broadcasts a BIPI to “all including self” (see Figure 9-8).
3. APIC arbitration hardware causes all the APICs to respond to the BIPIs one at a time (at T1, T2, T3, and T4).
4. When the first BIPI is received (at time T1), each APIC compares the four least significant bits of the BIPI’s
vector field with its APIC ID. If the vector and APIC ID match, the processor selects itself as the BSP by setting
the BSP flag in its IA32_APIC_BASE MSR. If the vector and APIC ID do not match, the processor selects itself
as an AP by entering the “wait for SIPI” state. (Note that in Figure 9-8, the BIPI from processor 1 is the first
BIPI to be handled, so processor 1 becomes the BSP.)
5. The newly established BSP broadcasts an FIPI message to “all including self.” The FIPI is guaranteed to be
handled only after the completion of the BIPIs that were issued by the non-BSP processors.
System (CPU) Bus
Pentium III
Pentium III
Pentium III
Pentium III
Processor 0
Processor 1
Processor 2
Processor 3
APIC Bus
Processor 1
Becomes BSP
T0
T1
T2
T3
T4
T5
BIPI.1
BIPI.0
BIPI.3
BIPI.2
FIPI
Serial Bus Activity
Figure 9-8. MP System With Multiple Pentium III Processors
6. After the BSP has been established, the outstanding BIPIs are received one at a time (at T2, T3, and T4) and
ignored by all processors.
7. When the FIPI is finally received (at T5), only the BSP responds to it. It responds by fetching and executing
BIOS boot-strap code, beginning at the reset vector (physical address FFFF FFF0H).
8. As part of the boot-strap code, the BSP creates an ACPI table and an MP table and adds its initial APIC ID to
these tables as appropriate.
9. At the end of the boot-strap procedure, the BSP broadcasts a SIPI message to all the APs in the system. Here,
the SIPI message contains a vector to the BIOS AP initialization code (at 000V V000H, where VV is the vector
contained in the SIPI message).
10. All APs respond to the SIPI message by racing to a BIOS initialization semaphore. The first one to the
semaphore begins executing the initialization code. (See MP init code for semaphore implementation details.)
As part of the AP initialization procedure, the AP adds its APIC ID number to the ACPI and MP tables as appro-
priate. At the completion of the initialization procedure, the AP executes a CLI instruction (to clear the IF flag in
the EFLAGS register) and halts itself.
11. When each of the APs has gained access to the semaphore and executed the AP initialization code and all
written their APIC IDs into the appropriate places in the ACPI and MP tables, the BSP establishes a count for the
number of processors connected to the system bus, completes executing the BIOS boot-strap code, and then
begins executing operating-system boot-strap and start-up code.
9-56
Vol. 3A
MULTIPLE-PROCESSOR MANAGEMENT
12. While the BSP is executing operating-system boot-strap and start-up code, the APs remain in the halted state.
In this state they will respond only to INITs, NMIs, and SMIs. They will also respond to snoops and to assertions
of the STPCLK# pin.
See Section 9.4.4, “MP Initialization Example,” for an annotated example the use of the MP protocol to boot IA-32
processors in an MP. This code should run on any IA-32 processor that used the MP protocol.
9.11.2.1 Error Detection and Handling During the MP Initialization Protocol
Errors may occur on the APIC bus during the MP initialization phase. These errors may be transient or permanent
and can be caused by a variety of failure mechanisms (for example, broken traces, soft errors during bus usage,
etc.). All serial bus related errors will result in an APIC checksum or acceptance error.
The MP initialization protocol makes the following assumptions regarding errors that occur during initialization:
If errors are detected on the APIC bus during execution of the MP initialization protocol, the processors that
detect the errors are shut down.
The MP initialization protocol will be executed by processors even if they fail their BIST sequences.
Vol. 3A
9-57
MULTIPLE-PROCESSOR MANAGEMENT
9-58
Vol. 3A
11.Updates to Chapter 12, Volume 3A
Change bars and violet text show changes to Chapter 12 of the Intel® 64 and IA-32 Architectures Software
Developer’s Manual, Volume 3A: System Programming Guide, Part 1.
------------------------------------------------------------------------------------------
Changes to this chapter:
• Updates to Section 12.11.8, “MTRR Considerations in MP Systems,” and Section 12.12.4, “Programming the
PAT.”
Intel® 64 and IA-32 Architectures Software Developer’s Manual Documentation Changes
13
CHAPTER 12
MEMORY CACHE CONTROL
This chapter describes the memory cache and cache control mechanisms, the TLBs, and the store buffer in Intel 64
and IA-32 processors. It also describes the memory type range registers (MTRRs) introduced in the P6 family
processors and how they are used to control caching of physical memory locations.
12.1
INTERNAL CACHES, TLBS, AND BUFFERS
The Intel 64 and IA-32 architectures support cache, translation look aside buffers (TLBs), and a store buffer for
temporary on-chip (and external) storage of instructions and data. (Figure 12-1 shows the arrangement of caches,
TLBs, and the store buffer for the Pentium 4 and Intel Xeon processors.) Table 12-1 shows the characteristics of
these caches and buffers for the Pentium 4, Intel Xeon, P6 family, and Pentium processors. The sizes and char-
acteristics of these units are machine specific and may change in future versions of the processor. The
CPUID instruction returns the sizes and characteristics of the caches and buffers for the processor on which the
instruction is executed. See “CPUID-CPU Identification” in Chapter 3, “Instruction Set Reference, A-L,” of the
Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 2A.
Physical
Memory
System Bus
(External)
Data Cache
L2 Cache
L3 Cache
Unit (L1)
Instruction
TLBs
Bus Interface Unit
Data TLBs
Instruction Decoder
Trace Cache
Store Buffer
† Intel Xeon processors only
Figure 12-1. Cache Structure of the Pentium 4 and Intel Xeon Processors
Vol. 3A
12-1
MEMORY CACHE CONTROL
Instruction
Instruction Decoder and front end
ITLB
Cache
Chipset
Out-of-Order Engine
QPI
STLB
IMC
Data TLB
Data Cache
Unit (L1)
L2 Cache
L3 Cache
Figure 12-2. Cache Structure of the Intel Core i7 Processors
Figure 12-2 shows the cache arrangement of Intel Core i7 processor.
Table 12-1. Characteristics of the Caches, TLBs, Store Buffer, and
Write Combining Buffer in Intel 64 and IA-32 Processors
Cache or Buffer
Characteristics
Trace Cache1
• Pentium 4 and Intel Xeon processors (Based on Intel NetBurst® microarchitecture): 12 Kμops, 8-way set
associative.
• Intel Core i7, Intel Core 2 Duo, Intel Atom, Intel Core Duo, Intel Core Solo, Pentium M processor: not
implemented.
• P6 family and Pentium processors: not implemented.
L1 Instruction Cache
• Pentium 4 and Intel Xeon processors (Based on Intel NetBurst microarchitecture): not implemented.
• Intel Core i7 processor: 32-KByte, 4-way set associative.
• Intel Core 2 Duo, Intel Atom, Intel Core Duo, Intel Core Solo, Pentium M processor: 32-KByte, 8-way set
associative.
• P6 family and Pentium processors: 8- or 16-KByte, 4-way set associative, 32-byte cache line size; 2-way set
associative for earlier Pentium processors.
L1 Data Cache
• Pentium 4 and Intel Xeon processors (Based on Intel NetBurst microarchitecture): 8-KByte, 4-way set
associative, 64-byte cache line size.
• Pentium 4 and Intel Xeon processors (Based on Intel NetBurst microarchitecture): 16-KByte, 8-way set
associative, 64-byte cache line size.
• Intel Atom processors: 24-KByte, 6-way set associative, 64-byte cache line size.
• Intel Core i7, Intel Core 2 Duo, Intel Core Duo, Intel Core Solo, Pentium M and Intel Xeon processors: 32-
KByte, 8-way set associative, 64-byte cache line size.
• P6 family processors: 16-KByte, 4-way set associative, 32-byte cache line size; 8-KBytes, 2-way set
associative for earlier P6 family processors.
• Pentium processors: 16-KByte, 4-way set associative, 32-byte cache line size; 8-KByte, 2-way set
associative for earlier Pentium processors.
12-2
Vol. 3A
MEMORY CACHE CONTROL
Table 12-1. Characteristics of the Caches, TLBs, Store Buffer, and
Write Combining Buffer in Intel 64 and IA-32 Processors (Contd.)
Cache or Buffer
Characteristics
L2 Unified Cache
Intel Core 2 Duo and Intel Xeon processors: up to 4-MByte (or 4MBx2 in quadcore processors), 16-way set
associative, 64-byte cache line size.
Intel Core 2 Duo and Intel Xeon processors: up to 6-MByte (or 6MBx2 in quadcore processors), 24-way set
associative, 64-byte cache line size.
Intel Core i7, i5, i3 processors: 256KBbyte, 8-way set associative, 64-byte cache line size.
Intel Atom processors: 512-KByte, 8-way set associative, 64-byte cache line size.
Intel Core Duo, Intel Core Solo processors: 2-MByte, 8-way set associative, 64-byte cache line size
Pentium 4 and Intel Xeon processors: 256, 512, 1024, or 2048-KByte, 8-way set associative, 64-byte cache
line size, 128-byte sector size.
Pentium M processor: 1 or 2-MByte, 8-way set associative, 64-byte cache line size.
P6 family processors: 128-KByte, 256-KByte, 512-KByte, 1-MByte, or 2-MByte, 4-way set associative,
32-byte cache line size.
Pentium processor (external optional): System specific, typically 256- or 512-KByte, 4-way set associative,
32-byte cache line size.
L3 Unified Cache
Intel Xeon processors: 512-KByte, 1-MByte, 2-MByte, or 4-MByte, 8-way set associative, 64-byte cache line
size, 128-byte sector size.
Intel Core i7 processor, Intel Xeon processor 5500: Up to 8MByte, 16-way set associative, 64-byte cache
line size.
Intel Xeon processor 5600: Up to 12MByte, 64-byte cache line size.
Intel Xeon processor 7500: Up to 24MByte, 64-byte cache line size.
Instruction TLB
Pentium 4 and Intel Xeon processors (Based on Intel NetBurst microarchitecture): 128 entries, 4-way set
(4-KByte Pages)
associative.
Intel Atom processors: 32-entries, fully associative.
Intel Core i7, i5, i3 processors: 64-entries per thread (128-entries per core), 4-way set associative.
Intel Core 2 Duo, Intel Core Duo, Intel Core Solo processors, Pentium M processor: 128 entries, 4-way set
associative.
P6 family processors: 32 entries, 4-way set associative.
Pentium processor: 32 entries, 4-way set associative; fully set associative for Pentium processors with MMX
technology.
Data TLB (4-KByte
Intel Core i7, i5, i3 processors, DTLB0: 64-entries, 4-way set associative.
Pages)
Intel Core 2 Duo processors: DTLB0, 16 entries, DTLB1, 256 entries, 4 ways.
Intel Atom processors: 16-entry-per-thread micro-TLB, fully associative; 64-entry DTLB, 4-way set
associative; 16-entry PDE cache, fully associative.
Pentium 4 and Intel Xeon processors (Based on Intel NetBurst microarchitecture): 64 entry, fully set
associative, shared with large page DTLB.
Intel Core Duo, Intel Core Solo processors, Pentium M processor: 128 entries, 4-way set associative.
Pentium and P6 family processors: 64 entries, 4-way set associative; fully set, associative for Pentium
processors with MMX technology.
Instruction TLB
Intel Core i7, i5, i3 processors: 7-entries per thread, fully associative.
(Large Pages)
Intel Core 2 Duo processors: 4 entries, 4 ways.
Pentium 4 and Intel Xeon processors: large pages are fragmented.
Intel Core Duo, Intel Core Solo, Pentium M processor: 2 entries, fully associative.
P6 family processors: 2 entries, fully associative.
Pentium processor: Uses same TLB as used for 4-KByte pages.
Data TLB (Large
Intel Core i7, i5, i3 processors, DTLB0: 32-entries, 4-way set associative.
Pages)
Intel Core 2 Duo processors: DTLB0, 16 entries, DTLB1, 32 entries, 4 ways.
Intel Atom processors: 8 entries, 4-way set associative.
Pentium 4 and Intel Xeon processors: 64 entries, fully set associative; shared with small page data TLBs.
Intel Core Duo, Intel Core Solo, Pentium M processor: 8 entries, fully associative.
P6 family processors: 8 entries, 4-way set associative.
Pentium processor: 8 entries, 4-way set associative; uses same TLB as used for 4-KByte pages in Pentium
processors with MMX technology.
Second-level Unified
Intel Core i7, i5, i3 processor, STLB: 512-entries, 4-way set associative.
TLB (4-KByte
Pages)
Vol. 3A
12-3
MEMORY CACHE CONTROL
Table 12-1. Characteristics of the Caches, TLBs, Store Buffer, and
Write Combining Buffer in Intel 64 and IA-32 Processors (Contd.)
Cache or Buffer
Characteristics
Store Buffer
• Intel Core i7, i5, i3 processors: 32entries.
• Intel Core 2 Duo processors: 20 entries.
• Intel Atom processors: 8 entries, used for both WC and store buffers.
• Pentium 4 and Intel Xeon processors: 24 entries.
• Pentium M processor: 16 entries.
• P6 family processors: 12 entries.
• Pentium processor: 2 buffers, 1 entry each (Pentium processors with MMX technology have 4 buffers for 4
entries).
Write Combining
• Intel Core 2 Duo processors: 8 entries.
(WC) Buffer
• Intel Atom processors: 8 entries, used for both WC and store buffers.
• Pentium 4 and Intel Xeon processors: 6 or 8 entries.
• Intel Core Duo, Intel Core Solo, Pentium M processors: 6 entries.
• P6 family processors: 4 entries.
NOTES:
1 Introduced to the IA-32 architecture in the Pentium 4 and Intel Xeon processors.
Intel 64 and IA-32 processors may implement four types of caches: the trace cache, the level 1 (L1) cache, the
level 2 (L2) cache, and the level 3 (L3) cache. See Figure 12-1. Cache availability is described below:
Intel Core i7, i5, i3 processor family and Intel Xeon processor family based on Nehalem microarchi-
tecture and Westmere microarchitecture - The L1 cache is divided into two sections: one section is
dedicated to caching instructions (pre-decoded instructions) and the other caches data. The L2 cache is a
unified data and instruction cache. Each processor core has its own L1 and L2. The L3 cache is an inclusive,
unified data and instruction cache, shared by all processor cores inside a physical package. No trace cache is
implemented.
Intel® Core™ 2 processor family and Intel® Xeon® processor family based on Intel® Core™ micro-
architecture - The L1 cache is divided into two sections: one section is dedicated to caching instructions (pre-
decoded instructions) and the other caches data. The L2 cache is a unified data and instruction cache located
on the processor chip; it is shared between two processor cores in a dual-core processor implementation.
Quad-core processors have two L2, each shared by two processor cores. No trace cache is implemented.
Intel Atom® processor - The L1 cache is divided into two sections: one section is dedicated to caching
instructions (pre-decoded instructions) and the other caches data. The L2 cache is a unified data and
instruction cache is located on the processor chip. No trace cache is implemented.
Intel® Core™ Solo and Intel® Core™ Duo processors - The L1 cache is divided into two sections: one
section is dedicated to caching instructions (pre-decoded instructions) and the other caches data. The L2 cache
is a unified data and instruction cache located on the processor chip. It is shared between two processor cores
in a dual-core processor implementation. No trace cache is implemented.
Pentium® 4 and Intel® Xeon® processors Based on Intel NetBurst® microarchitecture - The trace
cache caches decoded instructions (μops) from the instruction decoder and the L1 cache contains data. The L2
and L3 caches are unified data and instruction caches located on the processor chip. Dualcore processors have
two L2, one in each processor core. Note that the L3 cache is only implemented on some Intel Xeon processors.
P6 family processors - The L1 cache is divided into two sections: one dedicated to caching instructions (pre-
decoded instructions) and the other to caching data. The L2 cache is a unified data and instruction cache
located on the processor chip. P6 family processors do not implement a trace cache.
Pentium® processors - The L1 cache has the same structure as on P6 family processors. There is no trace
cache. The L2 cache is a unified data and instruction cache external to the processor chip on earlier Pentium
processors and implemented on the processor chip in later Pentium processors. For Pentium processors where
the L2 cache is external to the processor, access to the cache is through the system bus.
For Intel Core i7 processors and processors based on Intel Core, Intel Atom, and Intel NetBurst microarchitectures,
Intel Core Duo, Intel Core Solo and Pentium M processors, the cache lines for the L1 and L2 caches (and L3 caches
if supported) are 64 bytes wide. The processor always reads a cache line from system memory beginning on a 64-
byte boundary. (A 64-byte aligned cache line begins at an address with its 6 least-significant bits clear.) A cache
12-4
Vol. 3A
MEMORY CACHE CONTROL
line can be filled from memory with a 8-transfer burst transaction. The caches do not support partially-filled cache
lines, so caching even a single doubleword requires caching an entire line.
The L1 and L2 cache lines in the P6 family and Pentium processors are 32 bytes wide, with cache line reads from
system memory beginning on a 32-byte boundary (5 least-significant bits of a memory address clear.) A cache line
can be filled from memory with a 4-transfer burst transaction. Partially-filled cache lines are not supported.
The trace cache in processors based on Intel NetBurst microarchitecture is available in all execution modes:
protected mode, system management mode (SMM), and real-address mode. The L1,L2, and L3 caches are also
available in all execution modes; however, use of them must be handled carefully in SMM (see Section 32.4.2,
“SMRAM Caching”).
The TLBs store the most recently used page-directory and page-table entries. They speed up memory accesses
when paging is enabled by reducing the number of memory accesses that are required to read the page tables
stored in system memory. The TLBs are divided into four groups: instruction TLBs for 4-KByte pages, data TLBs for
4-KByte pages; instruction TLBs for large pages (2-MByte, 4-MByte or 1-GByte pages), and data TLBs for large
pages. The TLBs are normally active only in protected mode with paging enabled. When paging is disabled or the
processor is in real-address mode, the TLBs maintain their contents until explicitly or implicitly flushed (see Section
12.9, “Invalidating the Translation Lookaside Buffers (TLBs)”).
Processors based on Intel Core microarchitectures implement one level of instruction TLB and two levels of data
TLB. Intel Core i7 processor provides a second-level unified TLB.
The store buffer is associated with the processors instruction execution units. It allows writes to system memory
and/or the internal caches to be saved and in some cases combined to optimize the processor’s bus accesses. The
store buffer is always enabled in all execution modes.
The processor’s caches are for the most part transparent to software. When enabled, instructions and data flow
through these caches without the need for explicit software control. However, knowledge of the behavior of these
caches may be useful in optimizing software performance. For example, knowledge of cache dimensions and
replacement algorithms gives an indication of how large of a data structure can be operated on at once without
causing cache thrashing.
In multiprocessor systems, maintenance of cache consistency may, in rare circumstances, require intervention by
system software. For these rare cases, the processor provides privileged cache control instructions for use in
flushing caches and forcing memory ordering.
There are several instructions that software can use to improve the performance of the L1, L2, and L3 caches,
including the PREFETCHh, CLFLUSH, and CLFLUSHOPT instructions and the non-temporal move instructions
(MOVNTI, MOVNTQ, MOVNTDQ, MOVNTPS, and MOVNTPD). The use of these instructions are discussed in Section
12.5.5, “Cache Management Instructions.”
12.2
CACHING TERMINOLOGY
IA-32 processors (beginning with the Pentium processor) and Intel 64 processors use the MESI (modified, exclu-
sive, shared, invalid) cache protocol to maintain consistency with internal caches and caches in other processors
(see Section 12.4, “Cache Control Protocol”).
When the processor recognizes that an operand being read from memory is cacheable, the processor reads an
entire cache line into the appropriate cache (L1, L2, L3, or all). This operation is called a cache line fill. If the
memory location containing that operand is still cached the next time the processor attempts to access the
operand, the processor can read the operand from the cache instead of going back to memory. This operation is
called a cache hit.
When the processor attempts to write an operand to a cacheable area of memory, it first checks if a cache line for
that memory location exists in the cache. If a valid cache line does exist, the processor (depending on the write
policy currently in force) can write the operand into the cache instead of writing it out to system memory. This
operation is called a write hit. If a write misses the cache (that is, a valid cache line is not present for area of
memory being written to), the processor performs a cache line fill, write allocation. Then it writes the operand into
the cache line and (depending on the write policy currently in force) can also write it out to memory. If the operand
is to be written out to memory, it is written first into the store buffer, and then written from the store buffer to
memory when the system bus is available. (Note that for the Pentium processor, write misses do not result in a
cache line fill; they always result in a write to memory. For this processor, only read misses result in cache line fills.)
Vol. 3A
12-5
MEMORY CACHE CONTROL
When operating in an MP system, IA-32 processors (beginning with the Intel486 processor) and Intel 64 processors
have the ability to snoop other processor’s accesses to system memory and to their internal caches. They use this
snooping ability to keep their internal caches consistent both with system memory and with the caches in other
processors on the bus. For example, in the Pentium and P6 family processors, if through snooping one processor
detects that another processor intends to write to a memory location that it currently has cached in shared state,
the snooping processor will invalidate its cache line forcing it to perform a cache line fill the next time it accesses
the same memory location.
Beginning with the P6 family processors, if a processor detects (through snooping) that another processor is trying
to access a memory location that it has modified in its cache, but has not yet written back to system memory, the
snooping processor will signal the other processor (by means of the HITM# signal) that the cache line is held in
modified state and will perform an implicit write-back of the modified data. The implicit write-back is transferred
directly to the initial requesting processor and snooped by the memory controller to assure that system memory
has been updated. Here, the processor with the valid data may pass the data to the other processors without actu-
ally writing it to system memory; however, it is the responsibility of the memory controller to snoop this operation
and update memory.
12.3
METHODS OF CACHING AVAILABLE
The processor allows any area of system memory to be cached in the L1, L2, and L3 caches. In individual pages or
regions of system memory, it allows the type of caching (also called memory type) to be specified (see Section
12.5). Memory types currently defined for the Intel 64 and IA-32 architectures are (see Table 12-2):
Strong Uncacheable (UC) -System memory locations are not cached. All reads and writes appear on the
system bus and are executed in program order without reordering. No speculative memory accesses, page-
table walks, or prefetches of speculated branch targets are made. This type of cache-control is useful for
memory-mapped I/O devices. When used with normal RAM, it greatly reduces processor performance.
NOTE
The behavior of x87 and SIMD instructions referencing memory is implementation dependent. In
some implementations, accesses to UC memory may occur more than once. To ensure predictable
behavior, use loads and stores of general purpose registers to access UC memory that may have
read or write side effects.
Table 12-2. Memory Types and Their Properties
Memory Type and
Cacheable
Writeback
Allows
Memory Ordering Model
Mnemonic
Cacheable
Speculative
Reads
Strong Uncacheable
No
No
No
Strong Ordering
(UC)
Uncacheable (UC-)
No
No
No
Strong Ordering. Can only be selected through the PAT. Can be
overridden by WC in MTRRs.
Write Combining (WC)
No
No
Yes
Weak Ordering. Available by programming MTRRs or by selecting it
through the PAT.
Write Through (WT)
Yes
No
Yes
Speculative Processor Ordering.
Write Back (WB)
Yes
Yes
Yes
Speculative Processor Ordering.
Write Protected (WP)
Yes for
No
Yes
Speculative Processor Ordering. Available by programming MTRRs.
reads; no for
writes
Uncacheable (UC-) - Has same characteristics as the strong uncacheable (UC) memory type, except that
this memory type can be overridden by programming the MTRRs for the WC memory type. This memory type
is available in processor families starting from the Pentium III processors and can only be selected through the
PAT.
12-6
Vol. 3A
MEMORY CACHE CONTROL
Write Combining (WC) - System memory locations are not cached (as with uncacheable memory) and
coherency is not enforced by the processor’s bus coherency protocol. Speculative reads are allowed. Writes
may be delayed and combined in the write combining buffer (WC buffer) to reduce memory accesses. If the WC
buffer is partially filled, the writes may be delayed until the next occurrence of a serializing event; such as an
SFENCE or MFENCE instruction, CPUID or other serializing instruction, a read or write to uncached memory, an
interrupt occurrence, or an execution of a LOCK instruction (including one with an XACQUIRE or XRELEASE
prefix). In addition, an execution of the XEND instruction (to end a transactional region) evicts any writes that
were buffered before the corresponding execution of the XBEGIN instruction (to begin the transactional region)
before evicting any writes that were performed inside the transactional region.
This type of cache-control is appropriate for video frame buffers, where the order of writes is unimportant as
long as the writes update memory so they can be seen on the graphics display. See Section 12.3.1, “Buffering
of Write Combining Memory Locations,” for more information about caching the WC memory type. This memory
type is available in the Pentium Pro and Pentium II processors by programming the MTRRs; or in processor
families starting from the Pentium III processors by programming the MTRRs or by selecting it through the PAT.
Write-through (WT) - Writes and reads to and from system memory are cached. Reads come from cache
lines on cache hits; read misses cause cache fills. Speculative reads are allowed. All writes are written to a
cache line (when possible) and through to system memory. When writing through to memory, invalid cache
lines are never filled, and valid cache lines are either filled or invalidated. Write combining is allowed. This type
of cache-control is appropriate for frame buffers or when there are devices on the system bus that access
system memory, but do not perform snooping of memory accesses. It enforces coherency between caches in
the processors and system memory.
Write-back (WB) - Writes and reads to and from system memory are cached. Reads come from cache lines
on cache hits; read misses cause cache fills. Speculative reads are allowed. Write misses cause cache line fills
(in processor families starting with the P6 family processors), and writes are performed entirely in the cache,
when possible. Write combining is allowed. The write-back memory type reduces bus traffic by eliminating
many unnecessary writes to system memory. Writes to a cache line are not immediately forwarded to system
memory; instead, they are accumulated in the cache. The modified cache lines are written to system memory
later, when a write-back operation is performed. Write-back operations are triggered when cache lines need to
be deallocated, such as when new cache lines are being allocated in a cache that is already full. They also are
triggered by the mechanisms used to maintain cache consistency. This type of cache-control provides the best
performance, but it requires that all devices that access system memory on the system bus be able to snoop
memory accesses to ensure system memory and cache coherency.
Write protected (WP) - Reads come from cache lines when possible, and read misses cause cache fills.
Writes are propagated to the system bus and cause corresponding cache lines on all processors on the bus to
be invalidated. Speculative reads are allowed. This memory type is available in processor families starting from
the P6 family processors by programming the MTRRs (see Table 12-6).
Table 12-3 shows which of these caching methods are available in the Pentium, P6 Family, Pentium 4, and Intel
Xeon processors.
Table 12-3. Methods of Caching Available in Intel Core 2 Duo, Intel Atom, Intel Core Duo, Pentium M, Pentium 4,
Intel Xeon, P6 Family, and Pentium Processors
Memory Type
Intel Core 2 Duo, Intel Atom, Intel Core Duo,
P6 Family
Pentium
Pentium M, Pentium 4 and Intel Xeon Processors
Processors
Processor
Strong Uncacheable (UC)
Yes
Yes
Yes
Uncacheable (UC-)
Yes
Yes*
No
Write Combining (WC)
Yes
Yes
No
Write Through (WT)
Yes
Yes
Yes
Write Back (WB)
Yes
Yes
Yes
Write Protected (WP)
Yes
Yes
No
NOTE:
* Introduced in the Pentium III processor; not available in the Pentium Pro or Pentium II processors
Vol. 3A
12-7
MEMORY CACHE CONTROL
12.3.1 Buffering of Write Combining Memory Locations
Writes to the WC memory type are not cached in the typical sense of the word cached. They are retained in an
internal write combining buffer (WC buffer) that is separate from the internal L1, L2, and L3 caches and the store
buffer. The WC buffer is not snooped and thus does not provide data coherency. Buffering of writes to WC memory
is done to allow software a small window of time to supply more modified data to the WC buffer while remaining as
non-intrusive to software as possible. The buffering of writes to WC memory also causes data to be collapsed; that
is, multiple writes to the same memory location will leave the last data written in the location and the other writes
will be lost.
The size and structure of the WC buffer is not architecturally defined. For the Intel Core 2 Duo, Intel Atom, Intel
Core Duo, Pentium M, Pentium 4 and Intel Xeon processors; the WC buffer is made up of several 64-byte WC
buffers. For the P6 family processors, the WC buffer is made up of several 32-byte WC buffers.
When software begins writing to WC memory, the processor begins filling the WC buffers one at a time. When one
or more WC buffers has been filled, the processor has the option of evicting the buffers to system memory. The
protocol for evicting the WC buffers is implementation dependent and should not be relied on by software for
system memory coherency. When using the WC memory type, software must be sensitive to the fact that the
writing of data to system memory is being delayed and must deliberately empty the WC buffers when system
memory coherency is required.
Once the processor has started to evict data from the WC buffer into system memory, it will make a bus-transaction
style decision based on how much of the buffer contains valid data. If the buffer is full (for example, all bytes are
valid), the processor will execute a burst-write transaction on the bus. This results in all 32 bytes (P6 family proces-
sors) or 64 bytes (Pentium 4 and more recent processor) being transmitted on the data bus in a single burst trans-
action. If one or more of the WC buffer’s bytes are invalid (for example, have not been written by software), the
processor will transmit the data to memory using “partial write” transactions (one chunk at a time, where a “chunk”
is 8 bytes).
This will result in a maximum of 4 partial write transactions (for P6 family processors) or 8 partial write transactions
(for the Pentium 4 and more recent processors) for one WC buffer of data sent to memory.
The WC memory type is weakly ordered by definition. Once the eviction of a WC buffer has started, the data is
subject to the weak ordering semantics of its definition. Ordering is not maintained between the successive alloca-
tion/deallocation of WC buffers (for example, writes to WC buffer 1 followed by writes to WC buffer 2 may appear
as buffer 2 followed by buffer 1 on the system bus). When a WC buffer is evicted to memory as partial writes there
is no guaranteed ordering between successive partial writes (for example, a partial write for chunk 2 may appear
on the bus before the partial write for chunk 1 or vice versa).
The only elements of WC propagation to the system bus that are guaranteed are those provided by transaction
atomicity. For example, with a P6 family processor, a completely full WC buffer will always be propagated as a
single 32-bit burst transaction using any chunk order. In a WC buffer eviction where data will be evicted as partials,
all data contained in the same chunk (0 mod 8 aligned) will be propagated simultaneously. Likewise, for more
recent processors starting with those based on Intel NetBurst microarchitectures, a full WC buffer will always be
propagated as a single burst transactions, using any chunk order within a transaction. For partial buffer propaga-
tions, all data contained in the same chunk will be propagated simultaneously.
12.3.2 Choosing a Memory Type
The simplest system memory model does not use memory-mapped I/O with read or write side effects, does not
include a frame buffer, and uses the write-back memory type for all memory. An I/O agent can perform direct
memory access (DMA) to write-back memory and the cache protocol maintains cache coherency.
A system can use strong uncacheable memory for other memory-mapped I/O, and should always use strong unca-
cheable memory for memory-mapped I/O with read side effects.
Dual-ported memory can be considered a write side effect, making relatively prompt writes desirable, because
those writes cannot be observed at the other port until they reach the memory agent. A system can use strong
uncacheable, uncacheable, write-through, or write-combining memory for frame buffers or dual-ported memory
that contains pixel values displayed on a screen. Frame buffer memory is typically large (a few megabytes) and is
usually written more than it is read by the processor. Using strong uncacheable memory for a frame buffer gener-
ates very large amounts of bus traffic, because operations on the entire buffer are implemented using partial writes
rather than line writes. Using write-through memory for a frame buffer can displace almost all other useful cached
12-8
Vol. 3A
MEMORY CACHE CONTROL
lines in the processor's L2 and L3 caches and L1 data cache. Therefore, systems should use write-combining
memory for frame buffers whenever possible.
Software can use page-level cache control, to assign appropriate effective memory types when software will not
access data structures in ways that benefit from write-back caching. For example, software may read a large data
structure once and not access the structure again until the structure is rewritten by another agent. Such a large
data structure should be marked as uncacheable, or reading it will evict cached lines that the processor will be
referencing again.
A similar example would be a write-only data structure that is written to (to export the data to another agent), but
never read by software. Such a structure can be marked as uncacheable, because software never reads the values
that it writes (though as uncacheable memory, it will be written using partial writes, while as write-back memory,
it will be written using line writes, which may not occur until the other agent reads the structure and triggers
implicit write-backs).
On the Pentium III, Pentium 4, and more recent processors, new instructions are provided that give software
greater control over the caching, prefetching, and the write-back characteristics of data. These instructions allow
software to use weakly ordered or processor ordered memory types to improve processor performance, but when
necessary to force strong ordering on memory reads and/or writes. They also allow software greater control over
the caching of data. For a description of these instructions and their intended use, see Section 12.5.5, “Cache
Management Instructions.”
12.3.3 Code Fetches in Uncacheable Memory
Programs may execute code from uncacheable (UC) memory, but the implications are different from accessing
data in UC memory. When doing code fetches, the processor never transitions from cacheable code to UC code
speculatively. It also never speculatively fetches branch targets that result in UC code.
The processor may fetch the same UC cache line multiple times in order to decode an instruction once. It may
decode consecutive UC instructions in a cache line without fetching between each instruction. It may also fetch
additional cachelines from the same or a consecutive 4-KByte page in order to decode one non-speculative UC
instruction (this can be true even when the instruction is contained fully in one line).
Because of the above and because cache line sizes may change in future processors, software should avoid placing
memory-mapped I/O with read side effects in the same page or in a subsequent page used to execute UC code.
12.4
CACHE CONTROL PROTOCOL
The following section describes the cache control protocol currently defined for the Intel 64 and IA-32 architec-
tures.
In the L1 data cache and in the L2/L3 unified caches, the MESI (modified, exclusive, shared, invalid) cache protocol
maintains consistency with caches of other processors. The L1 data cache and the L2/L3 unified caches have two
MESI status flags per cache line. Each line can be marked as being in one of the states defined in Table 12-4. In
general, the operation of the MESI protocol is transparent to programs.
Table 12-4. MESI Cache Line States
Cache Line State
M (Modified)
E (Exclusive)
S (Shared)
I (Invalid)
This cache line is valid?
Yes
Yes
Yes
No
The memory copy is…
Out of date
Valid
Valid
-
Copies exist in caches of other
No
No
Maybe
Maybe
processors?
A write to this line …
Does not go to the
Does not go to the
Causes the processor to
Goes directly to the
system bus.
system bus.
gain exclusive ownership
system bus.
of the line.
Vol. 3A
12-9
MEMORY CACHE CONTROL
The L1 instruction cache in P6 family processors implements only the “SI” part of the MESI protocol, because the
instruction cache is not writable. The instruction cache monitors changes in the data cache to maintain consistency
between the caches when instructions are modified. See Section 12.6, “Self-Modifying Code,” for more information
on the implications of caching instructions.
12.5
CACHE CONTROL
The Intel 64 and IA-32 architectures provide a variety of mechanisms for controlling the caching of data and
instructions and for controlling the ordering of reads and writes between the processor, the caches, and memory.
These mechanisms can be divided into two groups:
Cache control registers and bits - The Intel 64 and IA-32 architectures define several dedicated registers
and various bits within control registers and page- and directory-table entries that control the caching system
memory locations in the L1, L2, and L3 caches. These mechanisms control the caching of virtual memory pages
and of regions of physical memory.
Cache control and memory ordering instructions - The Intel 64 and IA-32 architectures provide several
instructions that control the caching of data, the ordering of memory reads and writes, and the prefetching of
data. These instructions allow software to control the caching of specific data structures, to control memory
coherency for specific locations in memory, and to force strong memory ordering at specific locations in a
program.
The following sections describe these two groups of cache control mechanisms.
12.5.1 Cache Control Registers and Bits
Figure 12-3 depicts cache-control mechanisms in IA-32 processors. Other than for the matter of memory address
space, these work the same in Intel 64 processors.
The Intel 64 and IA-32 architectures provide the following cache-control registers and bits for use in enabling or
restricting caching to various pages or regions in memory:
CD flag, bit 30 of control register CR0 - Controls caching of system memory locations (see Section 2.5,
“Control Registers”). If the CD flag is clear, caching is enabled for the whole of system memory, but may be
restricted for individual pages or regions of memory by other cache-control mechanisms. When the CD flag is
set, caching is restricted in the processor’s caches (cache hierarchy) for the P6 and more recent processor
families and prevented for the Pentium processor (see note below). With the CD flag set, however, the caches
will still respond to snoop traffic. Caches should be explicitly flushed to ensure memory coherency. For highest
processor performance, both the CD and the NW flags in control register CR0 should be cleared. Table 12-5
shows the interaction of the CD and NW flags.
The effect of setting the CD flag is somewhat different for processor families starting with P6 family than the
Pentium processor (see Table 12-5). To ensure memory coherency after the CD flag is set, the caches should
be explicitly flushed (see Section 12.5.3, “Preventing Caching”). Setting the CD flag for the P6 and more
recent processor families modifies cache line fill and update behavior. Also, setting the CD flag on these
processors do not force strict ordering of memory accesses unless the MTRRs are disabled and/or all memory
is referenced as uncached (see Section 9.2.5, “Strengthening or Weakening the Memory-Ordering Model”).
12-10
Vol. 3A
MEMORY CACHE CONTROL
CR4
P
G
E
Enables global pages
CR3
designated with G flag
Physical Memory
FFFFFFFFH2
P
P
C
W
D
T
PAT4
Control caching of
page directory
PAT controls caching
of virtual memory
Page-Directory or
pages
Page-Table Entry
CR0
P
4
P
P
C
N
A
G1
C
W
D
W
T
D
T
CD and NW Flags
PCD and PWT flags
MTRRs3
control overall caching
control page-level
of system memory
caching
MTRRs control caching
G flag controls page-
of selected regions of
level flushing of TLBs
0
physical memory
Store Buffer
TLBs
1. G flag only available in P6 and later processor families
2. The maximum physical address size is reported by CPUID leaf
function 80000008H. The maximum physical address size of
FFFFFFFFFH applies only If 36-bit physical addressing is used.
3. MTRRs available only in P6 and later processor families;
similar control available in Pentium processor with the KEN#
and WB/WT# pins.
4. PAT available only in Pentium III and later processor families.
5. L3 in processors based on Intel NetBurst microarchitecture can
be disabled using IA32_MISC_ENABLE MSR.
Figure 12-3. Cache-Control Registers and Bits Available in Intel 64 and IA-32 Processors
Vol. 3A
12-11
MEMORY CACHE CONTROL
Table 12-5. Cache Operating Modes
CD
NW
Caching and Read/Write Policy
L1
L2/L31
0
0
Normal Cache Mode. Highest performance cache operation.
Yes
Yes
• Read hits access the cache; read misses may cause replacement.
• Write hits update the cache.
Yes
Yes
• Only writes to shared lines and write misses update system memory.
Yes
Yes
• Write misses cause cache line fills.
Yes
Yes
• Write hits can change shared lines to modified under control of the MTRRs and with associated
Yes
read invalidation cycle.
• (Pentium processor only.) Write misses do not cause cache line fills.
Yes
• (Pentium processor only.) Write hits can change shared lines to exclusive under control of WB/WT#.
Yes
• Invalidation is allowed.
• External snoop traffic is supported.
Yes
Yes
Yes
Yes
0
1
Invalid setting.
NA
NA
Generates a general-protection exception (#GP) with an error code of 0.
1
0
No-fill Cache Mode. Memory coherency is maintained.3
Yes
Yes
• (Pentium 4 and later processor families.) State of processor after a power up or reset.
• Read hits access the cache; read misses do not cause replacement (see Pentium 4 and Intel Xeon
processors reference below).
Yes
Yes
• Write hits update the cache.
• Only writes to shared lines and write misses update system memory.
Yes
Yes
Yes
Yes
• Write misses access memory.
Yes
Yes
• Write hits can change shared lines to exclusive under control of the MTRRs and with associated
Yes
Yes
read invalidation cycle.
• (Pentium processor only.) Write hits can change shared lines to exclusive under control of the
Yes
WB/WT#.
• (P6 and later processor families only.) Strict memory ordering is not enforced unless the MTRRs are
Yes
Yes
disabled and/or all memory is referenced as uncached (see Section 7.2.4., “Strengthening or
Weakening the Memory Ordering Model”).
• Invalidation is allowed.
• External snoop traffic is supported.
Yes
Yes
Yes
Yes
1
1
Memory coherency is not maintained.2, 3
Yes
Yes
• (P6 family and Pentium processors.) State of the processor after a power up or reset.
• Read hits access the cache; read misses do not cause replacement.
• Write hits update the cache and change exclusive lines to modified.
Yes
Yes
Yes
Yes
• Shared lines remain shared after write hit.
Yes
Yes
• Write misses access memory.
Yes
Yes
• Invalidation is inhibited when snooping; but is allowed with INVD and WBINVD instructions.
Yes
Yes
• External snoop traffic is supported.
No
Yes
NOTES:
1. The L2/L3 column in this table is definitive for the Pentium 4, Intel Xeon, and P6 family processors. It is intended to represent what
could be implemented in a system based on a Pentium processor with an external, platform specific, write-back L2 cache.
2. The Pentium 4 and more recent processor families do not support this mode; setting the CD and NW bits to 1 selects the no-fill
cache mode.
3. Not supported In Intel Atom processors. If CD = 1 in an Intel Atom processor, caching is disabled.
12-12
Vol. 3A
MEMORY CACHE CONTROL
NW flag, bit 29 of control register CR0 - Controls the write policy for system memory locations (see
Section 2.5, “Control Registers”). If the NW and CD flags are clear, write-back is enabled for the whole of
system memory, but may be restricted for individual pages or regions of memory by other cache-control
mechanisms. Table 12-5 shows how the other combinations of CD and NW flags affects caching.
NOTES
For the Pentium 4 and Intel Xeon processors, the NW flag is a don’t care flag; that is, when the CD
flag is set, the processor uses the no-fill cache mode, regardless of the setting of the NW flag.
For Intel Atom processors, the NW flag is a don’t care flag; that is, when the CD flag is set, the
processor disables caching, regardless of the setting of the NW flag.
For the Pentium processor, when the L1 cache is disabled (the CD and NW flags in control register
CR0 are set), external snoops are accepted in DP (dual-processor) systems and inhibited in unipro-
cessor systems.
When snoops are inhibited, address parity is not checked and APCHK# is not asserted for a corrupt
address; however, when snoops are accepted, address parity is checked and APCHK# is asserted
for corrupt addresses.
PCD and PWT flags in paging-structure entries - Control the memory type used to access paging
structures and pages (see Section 4.9, “Paging and Memory Typing”).
PCD and PWT flags in control register CR3 - Control the memory type used to access the first paging
structure of the current paging-structure hierarchy (see Section 4.9, “Paging and Memory Typing”).
G (global) flag in the page-directory and page-table entries (introduced to the IA-32 architecture in
the P6 family processors) - Controls the flushing of TLB entries for individual pages. See Section 4.10,
“Caching Translation Information,” for more information about this flag.
PGE (page global enable) flag in control register CR4 - Enables the establishment of global pages with
the G flag. See Section 4.10, “Caching Translation Information,” for more information about this flag.
Memory type range registers (MTRRs) (introduced in P6 family processors) - Control the type of
caching used in specific regions of physical memory. Any of the caching types described in Section 12.3,
“Methods of Caching Available,” can be selected. See Section 12.11, “Memory Type Range Registers (MTRRs),”
for a detailed description of the MTRRs.
Page Attribute Table (PAT) MSR (introduced in the Pentium III processor) - Extends the memory
typing capabilities of the processor to permit memory types to be assigned on a page-by-page basis (see
Section 12.12, “Page Attribute Table (PAT)”).
Third-Level Cache Disable flag, bit 6 of the IA32_MISC_ENABLE MSR (Available only in processors
based on Intel NetBurst microarchitecture) - Allows the L3 cache to be disabled and enabled, indepen-
dently of the L1 and L2 caches.
KEN# and WB/WT# pins (Pentium processor) - Allow external hardware to control the caching method
used for specific areas of memory. They perform similar (but not identical) functions to the MTRRs in the P6
family processors.
PCD and PWT pins (Pentium processor) - These pins (which are associated with the PCD and PWT flags in
control register CR3 and in the page-directory and page-table entries) permit caching in an external L2 cache
to be controlled on a page-by-page basis, consistent with the control exercised on the L1 cache of these
processors. The P6 and more recent processor families do not provide these pins because the L2 cache in
internal to the chip package.
12.5.2 Precedence of Cache Controls
The cache control flags and MTRRs operate hierarchically for restricting caching. That is, if the CD flag is set,
caching is prevented globally (see Table 12-5). If the CD flag is clear, the page-level cache control flags and/or the
MTRRs can be used to restrict caching. If there is an overlap of page-level and MTRR caching controls, the mecha-
nism that prevents caching has precedence. For example, if an MTRR makes a region of system memory uncache-
able, a page-level caching control cannot be used to enable caching for a page in that region. The converse is also
Vol. 3A
12-13
MEMORY CACHE CONTROL
true; that is, if a page-level caching control designates a page as uncacheable, an MTRR cannot be used to make
the page cacheable.
In cases where there is a overlap in the assignment of the write-back and write-through caching policies to a page
and a region of memory, the write-through policy takes precedence. The write-combining policy (which can only be
assigned through an MTRR or the PAT) takes precedence over either write-through or write-back.
The selection of memory types at the page level varies depending on whether PAT is being used to select memory
types for pages, as described in the following sections.
On processors based on Intel NetBurst microarchitecture, the third-level cache can be disabled by bit 6 of the
IA32_MISC_ENABLE MSR. Using IA32_MISC_ENABLE[bit 6] takes precedence over the CD flag, MTRRs, and PAT
for the L3 cache in those processors. That is, when the third-level cache disable flag is set (cache disabled), the
other cache controls have no affect on the L3 cache; when the flag is clear (enabled), the cache controls have the
same affect on the L3 cache as they have on the L1 and L2 caches.
IA32_MISC_ENABLE[bit 6] is not supported in Intel Core i7 processors, nor processors based on Intel Core, and
Intel Atom microarchitectures.
12.5.2.1 Selecting Memory Types for Pentium Pro and Pentium II Processors
The Pentium Pro and Pentium II processors do not support the PAT. Here, the effective memory type for a page is
selected with the MTRRs and the PCD and PWT bits in the page-table or page-directory entry for the page. Table
12-6 describes the mapping of MTRR memory types and page-level caching attributes to effective memory types,
when normal caching is in effect (the CD and NW flags in control register CR0 are clear). Combinations that appear
in gray are implementation-defined for the Pentium Pro and Pentium II processors. System designers are encour-
aged to avoid these implementation-defined combinations.
Table 12-6. Effective Page-Level Memory Type for Pentium Pro and Pentium II Processors
MTRR Memory Type1
PCD Value
PWT Value
Effective Memory Type
UC
X
X
UC
WC
0
0
WC
0
1
WC
1
0
WC
1
1
UC
WT
0
X
WT
1
X
UC
WP
0
0
WP
0
1
WP
1
0
WC
1
1
UC
WB
0
0
WB
0
1
WT
1
X
UC
NOTE:
1. These effective memory types also apply to the Pentium 4, Intel Xeon, and Pentium III processors when the PAT bit is not used
(set to 0) in page-table and page-directory entries.
When normal caching is in effect, the effective memory type shown in Table 12-6 is determined using the following
rules:
1. If the PCD and PWT attributes for the page are both 0, then the effective memory type is identical to the
MTRR-defined memory type.
12-14
Vol. 3A
MEMORY CACHE CONTROL
2. If the PCD flag is set, then the effective memory type is UC.
3. If the PCD flag is clear and the PWT flag is set, the effective memory type is WT for the WB memory type and
the MTRR-defined memory type for all other memory types.
4. Setting the PCD and PWT flags to opposite values is considered model-specific for the WP and WC memory
types and architecturally-defined for the WB, WT, and UC memory types.
12.5.2.2 Selecting Memory Types for Pentium III and More Recent Processor Families
The Intel Core 2 Duo, Intel Atom, Intel Core Duo, Intel Core Solo, Pentium M, Pentium 4, Intel Xeon, and Pentium
III processors use the PAT to select effective page-level memory types. Here, a memory type for a page is selected
by the MTRRs and the value in a PAT entry that is selected with the PAT, PCD, and PWT bits in a page-table or page-
directory entry (see Section 12.12.3, “Selecting a Memory Type from the PAT”). Table 12-7 describes the mapping
of MTRR memory types and PAT entry types to effective memory types, when normal caching is in effect (the CD
and NW flags in control register CR0 are clear).
Table 12-7. Effective Page-Level Memory Types for Pentium III and More Recent Processor Families
MTRR Memory Type
PAT Entry Value
Effective Memory Type
UC
UC
UC1
UC-
UC1
WC
WC
WT
UC1
WB
UC1
WP
UC1
WC
UC
UC2
UC-
WC
WC
WC
WT
UC2,3
WB
WC
WP
UC2,3
WT
UC
UC2
UC-
UC2
WC
WC
WT
WT
WB
WT
WP
WP3
WB
UC
UC2
UC-
UC2
WC
WC
WT
WT
WB
WB
WP
WP
Vol. 3A
12-15

 

 

 

 

 

 

 

Content      ..     2      3      4      5     ..