Introduction
These sets protect code and data, each against a different threat:
- CET (Control-flow Enforcement Technology) stops attacks that
redirect returns and indirect jumps. A shadow stack keeps a second copy of
each return address, in pages that ordinary stores cannot write, and a return
faults (#CP) when the two differ. Indirect branch tracking makes every
indirect
callandjmpland on anendbr. Intel’s Tiger Lake brought both in 2020; AMD’s Zen 3 the same year brought shadow stacks only. CPUID leaf 7: ECX bit 7 for shadow stacks, EDX bit 20 for indirect branch tracking. - SGX (Software Guard Extensions), from Intel’s Skylake in 2015, runs part of a program in an enclave, memory that is encrypted and that not even the operating system can read. Intel has since dropped it from its desktop and laptop processors, from the 11th-generation Core on, and kept it on Xeon. CPUID leaf 7: EBX bit 2.
- TDX (Trust Domain Extensions, Intel) and SEV-SNP (Secure Encrypted Virtualization with Secure Nested Paging, AMD) run whole virtual machines whose memory the hypervisor can neither read nor remap. TDX came with the 4th- and 5th-generation Xeon processors in 2023; SEV-SNP with the EPYC 7003 (Milan) in 2021, CPUID leaf 8000_001Fh: EAX bit 4.
- SMX (Safer Mode Extensions), Intel’s Trusted Execution Technology, starts a measured, trusted environment from a known state. CPUID leaf 1: ECX bit 6.
- PCONFIG and PBNDKB program the keys of Intel’s memory and storage encryption engines.
- MPX (Memory Protection Extensions), from Skylake in 2015, checked pointers against bounds in four new registers, bnd0 to bnd3. It was little used, and Intel has withdrawn it: its newer processors lack it, and GCC and Linux have dropped support. It is still in Intel’s manual, and the disassembler decodes it. CPUID leaf 7: EBX bit 14.
Most of these instructions run only at privilege level 0, or only inside an enclave or a guest. SGX, SMX, TDX and SEV pick a function with a leaf number in EAX or RAX, as CPUID does: one opcode covers many operations.
The instructions
In the forms, r32 and r64 are general registers,
bnd a bound register in ModRM.reg, and m a memory operand.
NP means that no 66, F2 or F3 prefix may be present.
CET: shadow stack
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
rdsspd | r32 | F3 0F 1E /1 (ModRM.mod 11) | Reads the low 32 bits of the shadow-stack pointer (SSP). With shadow stacks off it is a no-operation and the register is unchanged, so code can test for them. | CET (Intel Tiger Lake, 2020; AMD Zen 3, 2020) |
rdsspq | r64 | F3 REX.W 0F 1E /1 (ModRM.mod 11) | Reads the 64-bit SSP. 64-bit mode only. | CET (Intel Tiger Lake, 2020; AMD Zen 3, 2020) |
incsspd | r32 | F3 0F AE /5 (ModRM.mod 11) | Pops shadow-stack entries: adds 4 times the low 8 bits of the register to SSP. Used to unwind, as for longjmp. | CET (Intel Tiger Lake, 2020; AMD Zen 3, 2020) |
incsspq | r64 | F3 REX.W 0F AE /5 (ModRM.mod 11) | The same in 8-byte entries. 64-bit mode only. | CET (Intel Tiger Lake, 2020; AMD Zen 3, 2020) |
saveprevssp | – | F3 0F 01 EA | After a switch of shadow stacks with rstorssp, writes a restore token for the previous shadow stack onto it, so that it can be switched back to. | CET (Intel Tiger Lake, 2020; AMD Zen 3, 2020) |
rstorssp | m64 | F3 0F 01 /5 (memory) | Switches to another shadow stack: checks the restore token at the address, and makes SSP point to it. | CET (Intel Tiger Lake, 2020; AMD Zen 3, 2020) |
wrssd | m32, r32 | NP 0F 38 F6 /rAPX: EVEX map 4, NP 66 /r | Writes a doubleword to shadow-stack memory, where the operating system has allowed it for that privilege level. | CET (Intel Tiger Lake, 2020; AMD Zen 3, 2020) |
wrssq | m64, r64 | NP REX.W 0F 38 F6 /rAPX: EVEX map 4, NP 66 /r, W = 1 | The same for a quadword. 64-bit mode only. | CET (Intel Tiger Lake, 2020; AMD Zen 3, 2020) |
wrussd | m32, r32 | 66 0F 38 F5 /rAPX: EVEX map 4, 66 65 /r | Writes a doubleword to a user-mode shadow stack, from privilege level 0. | CET (Intel Tiger Lake, 2020; AMD Zen 3, 2020) |
wrussq | m64, r64 | 66 REX.W 0F 38 F5 /rAPX: EVEX map 4, 66 65 /r, W = 1 | The same for a quadword. 64-bit mode only. | CET (Intel Tiger Lake, 2020; AMD Zen 3, 2020) |
setssbsy | – | F3 0F 01 E8 | Marks the supervisor shadow stack named by IA32_PL0_SSP busy, checking its token, and loads SSP from it. Privilege level 0 only. | CET (Intel Tiger Lake, 2020; AMD Zen 3, 2020) |
clrssbsy | m64 | F3 0F AE /6 (memory) | Clears the busy flag in the supervisor shadow-stack token at the address, and sets SSP to 0. Privilege level 0 only. | CET (Intel Tiger Lake, 2020; AMD Zen 3, 2020) |
CET: indirect branch tracking
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
endbr64 | – | F3 0F 1E FA | Marks a place that an indirect call or jmp may reach, in 64-bit code. Without indirect branch tracking it is a no-operation, so compilers put it at the start of functions on every processor. | CET (Intel Tiger Lake, 2020) |
endbr32 | – | F3 0F 1E FB | The same in 32-bit and 16-bit code. | CET (Intel Tiger Lake, 2020) |
SGX: enclaves
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
encls | EAX = leaf (implicit) | NP 0F 01 CF | The supervisor functions: the operating system builds, measures and pages enclaves (ECREATE, EADD, EEXTEND, EINIT, EWB and the rest). Privilege level 0 only. | SGX (Intel Skylake, 2015) |
enclu | EAX = leaf (implicit) | NP 0F 01 D7 | The user functions: a program enters and leaves an enclave (EENTER, EEXIT, ERESUME), and the enclave seals data and makes reports (EGETKEY, EREPORT). Privilege level 3 only. | SGX (Intel Skylake, 2015) |
enclv | EAX = leaf (implicit) | NP 0F 01 C0 | The functions for a hypervisor that lets guests share enclave memory (oversubscription). Privilege level 0 only. | SGX (Intel, with the oversubscription extensions) |
TDX: trust domains
A trust domain is a virtual machine protected by the TDX module, Intel-signed code that runs in a new processor mode, SEAM, between the hypervisor and the guest.
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
tdcall | RAX = leaf (implicit) | 66 0F 01 CC | Called in a trust domain, calls the TDX module, for example to ask the hypervisor for a service or to accept a page. | TDX (Intel 4th-generation Xeon, 2023) |
seamcall | RAX = leaf (implicit) | 66 0F 01 CF | Called by the hypervisor, enters SEAM mode to call the TDX module, to create and run trust domains. Privilege level 0, 64-bit mode only. | TDX (Intel 4th-generation Xeon, 2023) |
seamret | – | 66 0F 01 CD | Returns from the TDX module to the hypervisor that called it. SEAM mode only. | TDX (Intel 4th-generation Xeon, 2023) |
seamops | RAX = leaf (implicit) | 66 0F 01 CE | Operations that only the TDX module may use, such as reading its capabilities and producing attestation reports. SEAM mode only. | TDX (Intel 4th-generation Xeon, 2023) |
SEV-SNP: the reverse map table
SEV-SNP records the owner of every page of memory in a reverse map table (RMP), which the processor checks on each access.
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
pvalidate | rAX, ECX, EDX (implicit) | F2 0F 01 FF | Called in a guest, marks the page at the address in rAX valid or not (EDX), with the page size in ECX. A guest accepts only pages it has validated. | SEV-SNP (AMD EPYC 7003 (Milan), 2021) |
rmpadjust | RAX, RCX, RDX (implicit) | F3 0F 01 FE | Called in a guest, sets the permissions of one of its pages for a less privileged level of the same guest (VMPL). 64-bit mode only. | SEV-SNP (AMD EPYC 7003 (Milan), 2021) |
rmpupdate | RAX, RCX (implicit) | F2 0F 01 FE | Called by the hypervisor, writes the RMP entry of the page at the system physical address in RAX, from the 16 bytes at RCX. 64-bit mode only. | SEV-SNP (AMD EPYC 7003 (Milan), 2021) |
psmash | RAX (implicit) | F3 0F 01 FF | Called by the hypervisor, splits the RMP entry of a 2 MB page into 512 entries for 4 KB pages. 64-bit mode only. | SEV-SNP (AMD EPYC 7003 (Milan), 2021) |
rmpquery | implicit registers | F3 0F 01 FD | Reads the permissions that an RMP entry gives a page. A later addition to SEV-SNP. 64-bit mode only. | SEV-SNP (AMD, later than Milan) |
SMX, PCONFIG and PBNDKB
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
getsec | EAX = leaf (implicit) | NP 0F 37 | The SMX functions: reports the capabilities (leaf 0), loads and runs an Intel-signed authenticated code module (ENTERACCS), and starts and ends a measured launch (SENTER, SEXIT). CR4.SMXE (bit 14) must be set. | SMX (Intel Core 2, 2007) |
pconfig | EAX = leaf (implicit) | NP 0F 01 C5 | Configures a platform feature. Leaf 0 programs a key for multi-key total memory encryption (TME-MK), which encrypts each guest’s memory with its own key. Privilege level 0 only. CPUID leaf 7: EDX bit 18. | PCONFIG (Intel Ice Lake-SP, 2021) |
pbndkb | implicit registers | NP 0F 01 C7 | Binds data to this platform: encrypts it with a key that never leaves the processor, so that pconfig can later program it into the Total Storage Encryption engine. Privilege level 0, 64-bit mode only. CPUID leaf 7, sub-leaf 1: EBX bit 1. | PBNDKB (Intel, for Total Storage Encryption; first listed for Lunar Lake, 2024) |
MPX: bounds checking (withdrawn)
Each bound register holds a lower bound and an upper bound (the upper one stored inverted). The MPX instructions sit in the hint no-operation space (0F 1A and 0F 1B), so code built with them still runs, unchecked, on processors without MPX.
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
bndmk | bnd, m32bnd, m64 | F3 0F 1B /r (memory) | Makes bounds from an address computation: the lower bound is the base register, the upper bound the whole effective address. No memory is read. | MPX (Intel Skylake, 2015) |
bndcl | bnd, r/m32bnd, r/m64 | F3 0F 1A /r | Raises #BR if the address (a register, or the effective address) is below the lower bound. | MPX (Intel Skylake, 2015) |
bndcu | as bndcl | F2 0F 1A /r | Raises #BR if the address is above the upper bound, taking the stored upper bound as inverted. | MPX (Intel Skylake, 2015) |
bndcn | as bndcl | F2 0F 1B /r | The same, taking the upper bound as stored, not inverted. | MPX (Intel Skylake, 2015) |
bndmov | bnd1, bnd2/m64bnd1, bnd2/m128bnd2/m64, bnd1bnd2/m128, bnd1 | 66 0F 1A /r66 0F 1A /r (64-bit mode)66 0F 1B /r66 0F 1B /r (64-bit mode) | Copies bounds between bound registers, or to and from memory: two 32-bit bounds outside 64-bit mode, two 64-bit bounds in it. | MPX (Intel Skylake, 2015) |
bndldx | bnd, mib | NP 0F 1A /r (memory) | Loads bounds from the bound tables, a two-level table in memory found from the pointer’s address (the base) and checked against the pointer’s value (the index register). | MPX (Intel Skylake, 2015) |
bndstx | mib, bnd | NP 0F 1B /r (memory) | Stores bounds, with the pointer’s value, into the bound tables. | MPX (Intel Skylake, 2015) |
MPX also gave F2 a meaning on branches, the bnd prefix: a
call, ret or jmp with it keeps the bound
registers, where one without it may reset them. The disassembler shows F2 on
branches as bnd.
Notes
- Prefixes pick the instruction. 0F 01 CC to CF, FD to FF and E8
to EA each hold several of these instructions, told apart by the 66, F2 or F3
prefix, and some only in 64-bit mode. Outside 64-bit mode the disassembler, as
LLVM does, leaves the 64-bit-only ones out and shows the plain form, such as
rdprufor F3 0F 01 FD. - Shadow-stack faults. A mismatched return, a bad token or a
missing
endbrraises #CP (control protection, vector 21). - ENDBR on other processors. 0F 1E lies in the hint
no-operation space, so processors without CET run
endbr32andendbr64as no-operations, which is why compilers can emit them everywhere.
Links
Reference
- Intel 64 and IA-32 Architectures Software Developer’s Manuals – Intel’s manuals; volume 2 describes each instruction, volume 1 CET and MPX, volume 3 SGX and SMX
- Intel Architecture Instruction Set Extensions Programming Reference – Intel’s description of instructions not yet in the main manual, with PBNDKB and Total Storage Encryption
- AMD64 Architecture Programmer’s Manual, Volume 2 – AMD’s system programming manual, with SEV-SNP and shadow stacks
- AMD64 Architecture Programmer’s Manual, Volume 3 – AMD’s reference to the general-purpose and system instructions
- x86 and amd64 instruction reference – Félix Cloutier’s web copy of the instruction pages of Intel’s manual