ia32-64/x86/saveprevssp.html
2025-07-08 02:23:29 -03:00

152 lines
5.7 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg" xmlns:x86="http://www.felixcloutier.com/x86"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="style.css"></link><title>SAVEPREVSSP
— Save Previous Shadow Stack Pointer</title></head><body><header><nav><ul><li><a href='index.html'>Index</a></li><li>December 2023</li></ul></nav></header><h1>SAVEPREVSSP
— Save Previous Shadow Stack Pointer</h1>
<table>
<tr>
<th>Opcode/Instruction</th>
<th>Op/En</th>
<th>64/32 bit Mode Support</th>
<th>CPUID Feature Flag</th>
<th>Description</th></tr>
<tr>
<td>F3 0F 01 EA (mod!=11, /5, RM=010) SAVEPREVSSP</td>
<td>ZO</td>
<td>V/V</td>
<td>CET_SS</td>
<td>Save a restore-shadow-stack token on previous shadow stack.</td></tr></table>
<h2 id="instruction-operand-encoding">Instruction Operand Encoding<a class="anchor" href="#instruction-operand-encoding">
</a></h2>
<table>
<tr>
<th>Op/En</th>
<th>Operand 1</th>
<th>Operand 2</th>
<th>Operand 3</th>
<th>Operand 4</th></tr>
<tr>
<td>ZO</td>
<td>N/A</td>
<td>N/A</td>
<td>N/A</td>
<td>N/A</td></tr></table>
<h2 id="description">Description<a class="anchor" href="#description">
</a></h2>
<p>Push a restore-shadow-stack token on the previous shadow stack at the next 8 byte aligned boundary. The previous SSP is obtained from the previous-ssp token at the top of the current shadow stack.</p>
<h2 id="operation">Operation<a class="anchor" href="#operation">
</a></h2>
<pre>IF CPL = 3
IF (CR4.CET &amp; IA32_U_CET.SH_STK_EN) = 0
THEN #UD; FI;
ELSE
IF (CR4.CET &amp; IA32_S_CET.SH_STK_EN) = 0
THEN #UD; FI;
FI;
IF SSP not aligned to 8 bytes
THEN #GP(0); FI;
(* Pop the “previous-ssp” token from current shadow stack *)
previous_ssp_token = ShadowStackPop8B(SSP)
(* If the CF flag indicates there was a alignment hole on current shadow stack then pop that alignment hole *)
(* Note that the alignment hole must be zero and can be present only when in legacy/compatibility mode *)
IF RFLAGS.CF == 1 AND (IA32_EFER.LMA AND CS.L)
#GP(0)
FI;
IF RFLAGS.CF == 1
must_be_zero = ShadowStackPop4B(SSP)
IF must_be_zero != 0 THEN #GP(0)
FI;
(* Previous SSP token must have the bit 1 set *)
IF ((previous_ssp_token &amp; 0x02) == 0)
THEN #GP(0); (* bit 1 was 0 *)
IF ((IA32_EFER.LMA AND CS.L) = 0 AND previous_ssp_token [63:32] != 0)
THEN #GP(0); FI; (* If compatibility/legacy mode and SSP not in 4G *)
(* Save Prev SSP from previous_ssp_token to the old shadow stack at next 8 byte aligned address *)
old_SSP = previous_ssp_token &amp; ~0x03
temp := (old_SSP | (IA32_EFER.LMA &amp; CS.L));
Shadow_stack_store 4 bytes of 0 to (old_SSP - 4)
old_SSP := old_SSP &amp; ~0x07;
Shadow_stack_store 8 bytes of temp to (old_SSP - 8)
</pre>
<h2 id="flags-affected">Flags Affected<a class="anchor" href="#flags-affected">
</a></h2>
<p>None.</p>
<h2 id="c-c++-compiler-intrinsic-equivalent">C/C++ Compiler Intrinsic Equivalent<a class="anchor" href="#c-c++-compiler-intrinsic-equivalent">
</a></h2>
<pre>SAVEPREVSSP void _saveprevssp(void);
</pre>
<h2 class="exceptions" id="protected-mode-exceptions">Protected Mode Exceptions<a class="anchor" href="#protected-mode-exceptions">
</a></h2>
<table>
<tr>
<td rowspan="4">#UD</td>
<td>If the LOCK prefix is used.</td></tr>
<tr>
<td>If CR4.CET = 0.</td></tr>
<tr>
<td>IF CPL = 3 and IA32_U_CET.SH_STK_EN = 0.</td></tr>
<tr>
<td>IF CPL &lt; 3 and IA32_S_CET.SH_STK_EN = 0.</td></tr>
<tr>
<td rowspan="4">#GP(0)</td>
<td>If SSP not 8 byte aligned.</td></tr>
<tr>
<td>If alignment hole on shadow stack is not 0.</td></tr>
<tr>
<td>If bit 1 of the previous-ssp token is not set to 1.</td></tr>
<tr>
<td>If in 32-bit/compatibility mode and SSP recorded in previous-ssp token is beyond 4G.</td></tr>
<tr>
<td>#PF(fault-code)</td>
<td>If a page fault occurs.</td></tr></table>
<h2 class="exceptions" id="real-address-mode-exceptions">Real-Address Mode Exceptions<a class="anchor" href="#real-address-mode-exceptions">
</a></h2>
<table>
<tr>
<td>#UD</td>
<td>The SAVEPREVSSP instruction is not recognized in real-address mode.</td></tr></table>
<h2 class="exceptions" id="virtual-8086-mode-exceptions">Virtual-8086 Mode Exceptions<a class="anchor" href="#virtual-8086-mode-exceptions">
</a></h2>
<table>
<tr>
<td>#UD</td>
<td>The SAVEPREVSSP instruction is not recognized in virtual-8086 mode.</td></tr></table>
<h2 class="exceptions" id="compatibility-mode-exceptions">Compatibility Mode Exceptions<a class="anchor" href="#compatibility-mode-exceptions">
</a></h2>
<p>Same as protected mode exceptions.</p>
<h2 class="exceptions" id="64-bit-mode-exceptions">64-Bit Mode Exceptions<a class="anchor" href="#64-bit-mode-exceptions">
</a></h2>
<table>
<tr>
<td rowspan="4">#UD</td>
<td>If the LOCK prefix is used.</td></tr>
<tr>
<td>If CR4.CET = 0.</td></tr>
<tr>
<td>If CPL = 3 and IA32_U_CET.SH_STK_EN = 0.</td></tr>
<tr>
<td>If CPL &lt; 3 and IA32_S_CET.SH_STK_EN = 0.</td></tr>
<tr>
<td rowspan="3">#GP(0)</td>
<td>If SSP not 8 byte aligned.</td></tr>
<tr>
<td>If carry flag is set.</td></tr>
<tr>
<td>If bit 1 of the previous-ssp token is not set to 1.</td></tr>
<tr>
<td>#PF(fault-code)</td>
<td>If a page fault occurs.</td></tr></table><footer><p>
This UNOFFICIAL, mechanically-separated, non-verified reference is provided for convenience, but it may be
inc<span style="opacity: 0.2">omp</span>lete or b<sub>r</sub>oke<sub>n</sub> in various obvious or non-obvious
ways. Refer to <a href="https://software.intel.com/en-us/download/intel-64-and-ia-32-architectures-sdm-combined-volumes-1-2a-2b-2c-2d-3a-3b-3c-3d-and-4">Intel® 64 and IA-32 Architectures Software Developers Manual</a> for anything serious.
</p></footer></body></html>