<!DOCTYPE html>
<html lang="en" data-content_root="../../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>33. Software Guard eXtensions (SGX) — The Linux Kernel documentation</title>
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css?v=fa44fd50" />
<link rel="stylesheet" type="text/css" href="../../_static/alabaster.css?v=3918102e" />
<script src="../../_static/documentation_options.js?v=5929fcd5"></script>
<script src="../../_static/doctools.js?v=9bcbadda"></script>
<script src="../../_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="index" title="Index" href="../../genindex.html" />
<link rel="search" title="Search" href="../../search.html" />
<link rel="next" title="34. Feature status on x86 architecture" href="features.html" />
<link rel="prev" title="32. Shared Virtual Addressing (SVA) with ENQCMD" href="sva.html" />
<link rel="stylesheet" href="../../_static/custom.css" type="text/css" />
</head><body>
<div class="document">
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../../index.html">
<img class="logo" src="../../_static/logo.svg" alt="Logo of The Linux Kernel"/>
</a></p>
<h1 class="logo"><a href="../../index.html">The Linux Kernel</a></h1>
<p class="blurb">6.18.50</p>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script>
<p>
<h3 class="kernel-toc-contents">Contents</h3>
<input type="checkbox" class="kernel-toc-toggle" id = "kernel-toc-toggle" checked>
<label class="kernel-toc-title" for="kernel-toc-toggle"></label>
<div class="kerneltoc" id="kerneltoc">
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../process/development-process.html">Development process</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../process/submitting-patches.html">Submitting patches</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../process/code-of-conduct.html">Code of conduct</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../maintainer/index.html">Maintainer handbook</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../process/index.html">All development-process docs</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../core-api/index.html">Core API</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../driver-api/index.html">Driver APIs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../subsystem-apis.html">Subsystems</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../locking/index.html">Locking</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../process/license-rules.html">Licensing rules</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../doc-guide/index.html">Writing documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../dev-tools/index.html">Development tools</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../dev-tools/testing-overview.html">Testing guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../kernel-hacking/index.html">Hacking guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../trace/index.html">Tracing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../fault-injection/index.html">Fault injection</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../livepatch/index.html">Livepatching</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../rust/index.html">Rust</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../admin-guide/index.html">Administration</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../kbuild/index.html">Build system</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../admin-guide/reporting-issues.html">Reporting issues</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../tools/index.html">Userspace tools</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../userspace-api/index.html">Userspace API</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../firmware-guide/index.html">Firmware</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../devicetree/index.html">Firmware and Devicetree</a></li>
</ul>
<ul class="current">
<li class="toctree-l1 current"><a class="reference internal" href="../index.html">CPU architectures</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="../arc/index.html">ARC architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../arm/index.html">ARM Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../arm64/index.html">ARM64 Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../loongarch/index.html">LoongArch Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../m68k/index.html">m68k Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../mips/index.html">MIPS-specific Documentation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../nios2/index.html">Nios II Specific Documentation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../openrisc/index.html">OpenRISC Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../parisc/index.html">PA-RISC Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../powerpc/index.html">powerpc</a></li>
<li class="toctree-l2"><a class="reference internal" href="../riscv/index.html">RISC-V architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../s390/index.html">s390 Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../sh/index.html">SuperH Interfaces Guide</a></li>
<li class="toctree-l2"><a class="reference internal" href="../sparc/index.html">Sparc Architecture</a></li>
<li class="toctree-l2 current"><a class="reference internal" href="index.html">x86-specific Documentation</a><ul class="current">
<li class="toctree-l3"><a class="reference internal" href="boot.html">1. The Linux/x86 Boot Protocol</a></li>
<li class="toctree-l3"><a class="reference internal" href="booting-dt.html">2. DeviceTree Booting</a></li>
<li class="toctree-l3"><a class="reference internal" href="cpuinfo.html">3. x86 Feature Flags</a></li>
<li class="toctree-l3"><a class="reference internal" href="topology.html">4. x86 Topology</a></li>
<li class="toctree-l3"><a class="reference internal" href="exception-tables.html">5. Kernel level exception handling</a></li>
<li class="toctree-l3"><a class="reference internal" href="kernel-stacks.html">6. Kernel Stacks</a></li>
<li class="toctree-l3"><a class="reference internal" href="entry_64.html">7. Kernel Entries</a></li>
<li class="toctree-l3"><a class="reference internal" href="earlyprintk.html">8. Early Printk</a></li>
<li class="toctree-l3"><a class="reference internal" href="orc-unwinder.html">9. ORC unwinder</a></li>
<li class="toctree-l3"><a class="reference internal" href="zero-page.html">10. Zero Page</a></li>
<li class="toctree-l3"><a class="reference internal" href="tlb.html">11. The TLB</a></li>
<li class="toctree-l3"><a class="reference internal" href="mtrr.html">12. MTRR (Memory Type Range Register) control</a></li>
<li class="toctree-l3"><a class="reference internal" href="pat.html">13. PAT (Page Attribute Table)</a></li>
<li class="toctree-l3"><a class="reference internal" href="intel-hfi.html">14. Hardware-Feedback Interface for scheduling on Intel Hardware</a></li>
<li class="toctree-l3"><a class="reference internal" href="shstk.html">15. Control-flow Enforcement Technology (CET) Shadow Stack</a></li>
<li class="toctree-l3"><a class="reference internal" href="iommu.html">16. x86 IOMMU Support</a></li>
<li class="toctree-l3"><a class="reference internal" href="intel_txt.html">17. Intel(R) TXT Overview</a></li>
<li class="toctree-l3"><a class="reference internal" href="amd-debugging.html">18. Debugging AMD Zen systems</a></li>
<li class="toctree-l3"><a class="reference internal" href="amd-memory-encryption.html">19. AMD Memory Encryption</a></li>
<li class="toctree-l3"><a class="reference internal" href="amd_hsmp.html">20. AMD HSMP interface</a></li>
<li class="toctree-l3"><a class="reference internal" href="amd-hfi.html">21. Hardware Feedback Interface For Hetero Core Scheduling On AMD Platform</a></li>
<li class="toctree-l3"><a class="reference internal" href="tdx.html">22. Intel Trust Domain Extensions (TDX)</a></li>
<li class="toctree-l3"><a class="reference internal" href="pti.html">23. Page Table Isolation (PTI)</a></li>
<li class="toctree-l3"><a class="reference internal" href="mds.html">24. Microarchitectural Data Sampling (MDS) mitigation</a></li>
<li class="toctree-l3"><a class="reference internal" href="microcode.html">25. The Linux Microcode Loader</a></li>
<li class="toctree-l3"><a class="reference internal" href="tsx_async_abort.html">26. TSX Async Abort (TAA) mitigation</a></li>
<li class="toctree-l3"><a class="reference internal" href="buslock.html">27. Bus lock detection and handling</a></li>
<li class="toctree-l3"><a class="reference internal" href="usb-legacy-support.html">28. USB Legacy support</a></li>
<li class="toctree-l3"><a class="reference internal" href="i386/index.html">29. i386 Support</a></li>
<li class="toctree-l3"><a class="reference internal" href="x86_64/index.html">30. x86_64 Support</a></li>
<li class="toctree-l3"><a class="reference internal" href="ifs.html">31. In-Field Scan</a></li>
<li class="toctree-l3"><a class="reference internal" href="sva.html">32. Shared Virtual Addressing (SVA) with ENQCMD</a></li>
<li class="toctree-l3 current"><a class="current reference internal" href="#">33. Software Guard eXtensions (SGX)</a></li>
<li class="toctree-l3"><a class="reference internal" href="features.html">34. Feature status on x86 architecture</a></li>
<li class="toctree-l3"><a class="reference internal" href="elf_auxvec.html">35. x86-specific ELF Auxiliary Vectors</a></li>
<li class="toctree-l3"><a class="reference internal" href="xstate.html">36. Using XSTATE features in user space applications</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../xtensa/index.html">Xtensa Architecture</a></li>
</ul>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../staging/index.html">Unsorted documentation</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../translations/index.html">Translations</a></li>
</ul>
</div>
<script type="text/javascript"> <!--
var sbar = document.getElementsByClassName("sphinxsidebar")[0];
let currents = document.getElementsByClassName("current")
if (currents.length) {
sbar.scrollTop = currents[currents.length - 1].offsetTop;
}
--> </script>
<div role="note" aria-label="source link">
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../../_sources/arch/x86/sgx.rst.txt"
rel="nofollow">Show Source</a></li>
</ul>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="software-guard-extensions-sgx">
<h1><span class="section-number">33. </span>Software Guard eXtensions (SGX)<a class="headerlink" href="#software-guard-extensions-sgx" title="Link to this heading">¶</a></h1>
<section id="overview">
<h2><span class="section-number">33.1. </span>Overview<a class="headerlink" href="#overview" title="Link to this heading">¶</a></h2>
<p>Software Guard eXtensions (SGX) hardware enables for user space applications
to set aside private memory regions of code and data:</p>
<ul class="simple">
<li><p>Privileged (ring-0) ENCLS functions orchestrate the construction of the
regions.</p></li>
<li><p>Unprivileged (ring-3) ENCLU functions allow an application to enter and
execute inside the regions.</p></li>
</ul>
<p>These memory regions are called enclaves. An enclave can be only entered at a
fixed set of entry points. Each entry point can hold a single hardware thread
at a time. While the enclave is loaded from a regular binary file by using
ENCLS functions, only the threads inside the enclave can access its memory. The
region is denied from outside access by the CPU, and encrypted before it leaves
from LLC.</p>
<p>The support can be determined by</p>
<blockquote>
<div><p><code class="docutils literal notranslate"><span class="pre">grep</span> <span class="pre">sgx</span> <span class="pre">/proc/cpuinfo</span></code></p>
</div></blockquote>
<p>SGX must both be supported in the processor and enabled by the BIOS. If SGX
appears to be unsupported on a system which has hardware support, ensure
support is enabled in the BIOS. If a BIOS presents a choice between “Enabled”
and “Software Enabled” modes for SGX, choose “Enabled”.</p>
</section>
<section id="enclave-page-cache">
<h2><span class="section-number">33.2. </span>Enclave Page Cache<a class="headerlink" href="#enclave-page-cache" title="Link to this heading">¶</a></h2>
<p>SGX utilizes an <em>Enclave Page Cache (EPC)</em> to store pages that are associated
with an enclave. It is contained in a BIOS-reserved region of physical memory.
Unlike pages used for regular memory, pages can only be accessed from outside of
the enclave during enclave construction with special, limited SGX instructions.</p>
<p>Only a CPU executing inside an enclave can directly access enclave memory.
However, a CPU executing inside an enclave may access normal memory outside the
enclave.</p>
<p>The kernel manages enclave memory similar to how it treats device memory.</p>
<section id="enclave-page-types">
<h3><span class="section-number">33.2.1. </span>Enclave Page Types<a class="headerlink" href="#enclave-page-types" title="Link to this heading">¶</a></h3>
<dl class="simple">
<dt><strong>SGX Enclave Control Structure (SECS)</strong></dt><dd><p>Enclave’s address range, attributes and other global data are defined
by this structure.</p>
</dd>
<dt><strong>Regular (REG)</strong></dt><dd><p>Regular EPC pages contain the code and data of an enclave.</p>
</dd>
<dt><strong>Thread Control Structure (TCS)</strong></dt><dd><p>Thread Control Structure pages define the entry points to an enclave and
track the execution state of an enclave thread.</p>
</dd>
<dt><strong>Version Array (VA)</strong></dt><dd><p>Version Array pages contain 512 slots, each of which can contain a version
number for a page evicted from the EPC.</p>
</dd>
</dl>
</section>
<section id="enclave-page-cache-map">
<h3><span class="section-number">33.2.2. </span>Enclave Page Cache Map<a class="headerlink" href="#enclave-page-cache-map" title="Link to this heading">¶</a></h3>
<p>The processor tracks EPC pages in a hardware metadata structure called the
<em>Enclave Page Cache Map (EPCM)</em>. The EPCM contains an entry for each EPC page
which describes the owning enclave, access rights and page type among the other
things.</p>
<p>EPCM permissions are separate from the normal page tables. This prevents the
kernel from, for instance, allowing writes to data which an enclave wishes to
remain read-only. EPCM permissions may only impose additional restrictions on
top of normal x86 page permissions.</p>
<p>For all intents and purposes, the SGX architecture allows the processor to
invalidate all EPCM entries at will. This requires that software be prepared to
handle an EPCM fault at any time. In practice, this can happen on events like
power transitions when the ephemeral key that encrypts enclave memory is lost.</p>
</section>
</section>
<section id="application-interface">
<h2><span class="section-number">33.3. </span>Application interface<a class="headerlink" href="#application-interface" title="Link to this heading">¶</a></h2>
<section id="enclave-build-functions">
<h3><span class="section-number">33.3.1. </span>Enclave build functions<a class="headerlink" href="#enclave-build-functions" title="Link to this heading">¶</a></h3>
<p>In addition to the traditional compiler and linker build process, SGX has a
separate enclave “build” process. Enclaves must be built before they can be
executed (entered). The first step in building an enclave is opening the
<strong>/dev/sgx_enclave</strong> device. Since enclave memory is protected from direct
access, special privileged instructions are then used to copy data into enclave
pages and establish enclave page permissions.</p>
<dl class="c function">
<dt class="sig sig-object c" id="c.sgx_ioc_enclave_create">
<span class="kt"><span class="pre">long</span></span><span class="w"> </span><span class="sig-name descname"><span class="n"><span class="pre">sgx_ioc_enclave_create</span></span></span><span class="sig-paren">(</span><span class="k"><span class="pre">struct</span></span><span class="w"> </span><span class="n"><span class="pre">sgx_encl</span></span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="n"><span class="pre">encl</span></span>, <span class="kt"><span class="pre">void</span></span><span class="w"> </span><span class="pre">__user</span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="n"><span class="pre">arg</span></span><span class="sig-paren">)</span><a class="headerlink" href="#c.sgx_ioc_enclave_create" title="Link to this definition">¶</a><br /></dt>
<dd><p>handler for <code class="docutils literal notranslate"><span class="pre">SGX_IOC_ENCLAVE_CREATE</span></code></p>
</dd></dl>
<div class="kernelindent docutils container">
<p><strong>Parameters</strong></p>
<dl class="simple">
<dt><code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">sgx_encl</span> <span class="pre">*encl</span></code></dt><dd><p>An enclave pointer.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">__user</span> <span class="pre">*arg</span></code></dt><dd><p>The ioctl argument.</p>
</dd>
</dl>
<p><strong>Description</strong></p>
<p>Allocate kernel data structures for the enclave and invoke ECREATE.</p>
<p><strong>Return</strong></p>
<ul class="simple">
<li><p>0: Success.</p></li>
<li><p>-EIO: ECREATE failed.</p></li>
<li><p>-errno: POSIX error.</p></li>
</ul>
</div>
<dl class="c function">
<dt class="sig sig-object c" id="c.sgx_ioc_enclave_add_pages">
<span class="kt"><span class="pre">long</span></span><span class="w"> </span><span class="sig-name descname"><span class="n"><span class="pre">sgx_ioc_enclave_add_pages</span></span></span><span class="sig-paren">(</span><span class="k"><span class="pre">struct</span></span><span class="w"> </span><span class="n"><span class="pre">sgx_encl</span></span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="n"><span class="pre">encl</span></span>, <span class="kt"><span class="pre">void</span></span><span class="w"> </span><span class="pre">__user</span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="n"><span class="pre">arg</span></span><span class="sig-paren">)</span><a class="headerlink" href="#c.sgx_ioc_enclave_add_pages" title="Link to this definition">¶</a><br /></dt>
<dd><p>The handler for <code class="docutils literal notranslate"><span class="pre">SGX_IOC_ENCLAVE_ADD_PAGES</span></code></p>
</dd></dl>
<div class="kernelindent docutils container">
<p><strong>Parameters</strong></p>
<dl class="simple">
<dt><code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">sgx_encl</span> <span class="pre">*encl</span></code></dt><dd><p>an enclave pointer</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">__user</span> <span class="pre">*arg</span></code></dt><dd><p>a user pointer to a <code class="xref c c-struct broken_xref docutils literal notranslate"><span class="pre">struct</span> <span class="pre">sgx_enclave_add_pages</span></code> instance</p>
</dd>
</dl>
<p><strong>Description</strong></p>
<p>Add one or more pages to an uninitialized enclave, and optionally extend the
measurement with the contents of the page. The SECINFO and measurement mask
are applied to all pages.</p>
<p>A SECINFO for a TCS is required to always contain zero permissions because
CPU silently zeros them. Allowing anything else would cause a mismatch in
the measurement.</p>
<p>mmap()’s protection bits are capped by the page permissions. For each page
address, the maximum protection bits are computed with the following
heuristics:</p>
<ol class="arabic simple">
<li><p>A regular page: PROT_R, PROT_W and PROT_X match the SECINFO permissions.</p></li>
<li><p>A TCS page: PROT_R | PROT_W.</p></li>
</ol>
<p>mmap() is not allowed to surpass the minimum of the maximum protection bits
within the given address range.</p>
<p>The function deinitializes kernel data structures for enclave and returns
-EIO in any of the following conditions:</p>
<ul class="simple">
<li><p>Enclave Page Cache (EPC), the physical memory holding enclaves, has
been invalidated. This will cause EADD and EEXTEND to fail.</p></li>
<li><p>If the source address is corrupted somehow when executing EADD.</p></li>
</ul>
<p><strong>Return</strong></p>
<ul class="simple">
<li><p>0: Success.</p></li>
<li><p>-EACCES: The source page is located in a noexec partition.</p></li>
<li><p>-ENOMEM: Out of EPC pages.</p></li>
<li><p>-EINTR: The call was interrupted before data was processed.</p></li>
<li><dl class="simple">
<dt>-EIO: Either EADD or EEXTEND failed because invalid source address</dt><dd><p>or power cycle.</p>
</dd>
</dl>
</li>
<li><p>-errno: POSIX error.</p></li>
</ul>
</div>
<dl class="c function">
<dt class="sig sig-object c" id="c.sgx_ioc_enclave_init">
<span class="kt"><span class="pre">long</span></span><span class="w"> </span><span class="sig-name descname"><span class="n"><span class="pre">sgx_ioc_enclave_init</span></span></span><span class="sig-paren">(</span><span class="k"><span class="pre">struct</span></span><span class="w"> </span><span class="n"><span class="pre">sgx_encl</span></span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="n"><span class="pre">encl</span></span>, <span class="kt"><span class="pre">void</span></span><span class="w"> </span><span class="pre">__user</span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="n"><span class="pre">arg</span></span><span class="sig-paren">)</span><a class="headerlink" href="#c.sgx_ioc_enclave_init" title="Link to this definition">¶</a><br /></dt>
<dd><p>handler for <code class="docutils literal notranslate"><span class="pre">SGX_IOC_ENCLAVE_INIT</span></code></p>
</dd></dl>
<div class="kernelindent docutils container">
<p><strong>Parameters</strong></p>
<dl class="simple">
<dt><code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">sgx_encl</span> <span class="pre">*encl</span></code></dt><dd><p>an enclave pointer</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">__user</span> <span class="pre">*arg</span></code></dt><dd><p>userspace pointer to a <code class="xref c c-struct broken_xref docutils literal notranslate"><span class="pre">struct</span> <span class="pre">sgx_enclave_init</span></code> instance</p>
</dd>
</dl>
<p><strong>Description</strong></p>
<p>Flush any outstanding enqueued EADD operations and perform EINIT. The
Launch Enclave Public Key Hash MSRs are rewritten as necessary to match
the enclave’s MRSIGNER, which is calculated from the provided sigstruct.</p>
<p><strong>Return</strong></p>
<ul class="simple">
<li><p>0: Success.</p></li>
<li><p>-EPERM: Invalid SIGSTRUCT.</p></li>
<li><p>-EIO: EINIT failed because of a power cycle.</p></li>
<li><p>-errno: POSIX error.</p></li>
</ul>
</div>
<dl class="c function">
<dt class="sig sig-object c" id="c.sgx_ioc_enclave_provision">
<span class="kt"><span class="pre">long</span></span><span class="w"> </span><span class="sig-name descname"><span class="n"><span class="pre">sgx_ioc_enclave_provision</span></span></span><span class="sig-paren">(</span><span class="k"><span class="pre">struct</span></span><span class="w"> </span><span class="n"><span class="pre">sgx_encl</span></span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="n"><span class="pre">encl</span></span>, <span class="kt"><span class="pre">void</span></span><span class="w"> </span><span class="pre">__user</span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="n"><span class="pre">arg</span></span><span class="sig-paren">)</span><a class="headerlink" href="#c.sgx_ioc_enclave_provision" title="Link to this definition">¶</a><br /></dt>
<dd><p>handler for <code class="docutils literal notranslate"><span class="pre">SGX_IOC_ENCLAVE_PROVISION</span></code></p>
</dd></dl>
<div class="kernelindent docutils container">
<p><strong>Parameters</strong></p>
<dl class="simple">
<dt><code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">sgx_encl</span> <span class="pre">*encl</span></code></dt><dd><p>an enclave pointer</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">__user</span> <span class="pre">*arg</span></code></dt><dd><p>userspace pointer to a <code class="xref c c-struct broken_xref docutils literal notranslate"><span class="pre">struct</span> <span class="pre">sgx_enclave_provision</span></code> instance</p>
</dd>
</dl>
<p><strong>Description</strong></p>
<p>Allow ATTRIBUTE.PROVISION_KEY for an enclave by providing a file handle to
/dev/sgx_provision.</p>
<p><strong>Return</strong></p>
<ul class="simple">
<li><p>0: Success.</p></li>
<li><p>-errno: Otherwise.</p></li>
</ul>
</div>
</section>
<section id="enclave-runtime-management">
<h3><span class="section-number">33.3.2. </span>Enclave runtime management<a class="headerlink" href="#enclave-runtime-management" title="Link to this heading">¶</a></h3>
<p>Systems supporting SGX2 additionally support changes to initialized
enclaves: modifying enclave page permissions and type, and dynamically
adding and removing of enclave pages. When an enclave accesses an address
within its address range that does not have a backing page then a new
regular page will be dynamically added to the enclave. The enclave is
still required to run EACCEPT on the new page before it can be used.</p>
<dl class="c function">
<dt class="sig sig-object c" id="c.sgx_ioc_enclave_restrict_permissions">
<span class="kt"><span class="pre">long</span></span><span class="w"> </span><span class="sig-name descname"><span class="n"><span class="pre">sgx_ioc_enclave_restrict_permissions</span></span></span><span class="sig-paren">(</span><span class="k"><span class="pre">struct</span></span><span class="w"> </span><span class="n"><span class="pre">sgx_encl</span></span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="n"><span class="pre">encl</span></span>, <span class="kt"><span class="pre">void</span></span><span class="w"> </span><span class="pre">__user</span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="n"><span class="pre">arg</span></span><span class="sig-paren">)</span><a class="headerlink" href="#c.sgx_ioc_enclave_restrict_permissions" title="Link to this definition">¶</a><br /></dt>
<dd><p>handler for <code class="docutils literal notranslate"><span class="pre">SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS</span></code></p>
</dd></dl>
<div class="kernelindent docutils container">
<p><strong>Parameters</strong></p>
<dl class="simple">
<dt><code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">sgx_encl</span> <span class="pre">*encl</span></code></dt><dd><p>an enclave pointer</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">__user</span> <span class="pre">*arg</span></code></dt><dd><p>userspace pointer to a <code class="xref c c-type docutils literal notranslate"><span class="pre">struct</span> <span class="pre">sgx_enclave_restrict_permissions</span></code>
instance</p>
</dd>
</dl>
<p><strong>Description</strong></p>
<p>SGX2 distinguishes between relaxing and restricting the enclave page
permissions maintained by the hardware (EPCM permissions) of pages
belonging to an initialized enclave (after SGX_IOC_ENCLAVE_INIT).</p>
<p>EPCM permissions cannot be restricted from within the enclave, the enclave
requires the kernel to run the privileged level 0 instructions ENCLS[EMODPR]
and ENCLS[ETRACK]. An attempt to relax EPCM permissions with this call
will be ignored by the hardware.</p>
<p><strong>Return</strong></p>
<ul class="simple">
<li><p>0: Success</p></li>
<li><p>-errno: Otherwise</p></li>
</ul>
</div>
<dl class="c function">
<dt class="sig sig-object c" id="c.sgx_ioc_enclave_modify_types">
<span class="kt"><span class="pre">long</span></span><span class="w"> </span><span class="sig-name descname"><span class="n"><span class="pre">sgx_ioc_enclave_modify_types</span></span></span><span class="sig-paren">(</span><span class="k"><span class="pre">struct</span></span><span class="w"> </span><span class="n"><span class="pre">sgx_encl</span></span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="n"><span class="pre">encl</span></span>, <span class="kt"><span class="pre">void</span></span><span class="w"> </span><span class="pre">__user</span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="n"><span class="pre">arg</span></span><span class="sig-paren">)</span><a class="headerlink" href="#c.sgx_ioc_enclave_modify_types" title="Link to this definition">¶</a><br /></dt>
<dd><p>handler for <code class="docutils literal notranslate"><span class="pre">SGX_IOC_ENCLAVE_MODIFY_TYPES</span></code></p>
</dd></dl>
<div class="kernelindent docutils container">
<p><strong>Parameters</strong></p>
<dl class="simple">
<dt><code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">sgx_encl</span> <span class="pre">*encl</span></code></dt><dd><p>an enclave pointer</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">__user</span> <span class="pre">*arg</span></code></dt><dd><p>userspace pointer to a <code class="xref c c-type docutils literal notranslate"><span class="pre">struct</span> <span class="pre">sgx_enclave_modify_types</span></code> instance</p>
</dd>
</dl>
<p><strong>Description</strong></p>
<p>Ability to change the enclave page type supports the following use cases:</p>
<ul class="simple">
<li><p>It is possible to add TCS pages to an enclave by changing the type of
regular pages (<code class="docutils literal notranslate"><span class="pre">SGX_PAGE_TYPE_REG</span></code>) to TCS (<code class="docutils literal notranslate"><span class="pre">SGX_PAGE_TYPE_TCS</span></code>) pages.
With this support the number of threads supported by an initialized
enclave can be increased dynamically.</p></li>
<li><p>Regular or TCS pages can dynamically be removed from an initialized
enclave by changing the page type to <code class="docutils literal notranslate"><span class="pre">SGX_PAGE_TYPE_TRIM</span></code>. Changing the
page type to <code class="docutils literal notranslate"><span class="pre">SGX_PAGE_TYPE_TRIM</span></code> marks the page for removal with actual
removal done by handler of <code class="docutils literal notranslate"><span class="pre">SGX_IOC_ENCLAVE_REMOVE_PAGES</span></code> ioctl() called
after ENCLU[EACCEPT] is run on <code class="docutils literal notranslate"><span class="pre">SGX_PAGE_TYPE_TRIM</span></code> page from within the
enclave.</p></li>
</ul>
<p><strong>Return</strong></p>
<ul class="simple">
<li><p>0: Success</p></li>
<li><p>-errno: Otherwise</p></li>
</ul>
</div>
<dl class="c function">
<dt class="sig sig-object c" id="c.sgx_ioc_enclave_remove_pages">
<span class="kt"><span class="pre">long</span></span><span class="w"> </span><span class="sig-name descname"><span class="n"><span class="pre">sgx_ioc_enclave_remove_pages</span></span></span><span class="sig-paren">(</span><span class="k"><span class="pre">struct</span></span><span class="w"> </span><span class="n"><span class="pre">sgx_encl</span></span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="n"><span class="pre">encl</span></span>, <span class="kt"><span class="pre">void</span></span><span class="w"> </span><span class="pre">__user</span><span class="w"> </span><span class="p"><span class="pre">*</span></span><span class="n"><span class="pre">arg</span></span><span class="sig-paren">)</span><a class="headerlink" href="#c.sgx_ioc_enclave_remove_pages" title="Link to this definition">¶</a><br /></dt>
<dd><p>handler for <code class="docutils literal notranslate"><span class="pre">SGX_IOC_ENCLAVE_REMOVE_PAGES</span></code></p>
</dd></dl>
<div class="kernelindent docutils container">
<p><strong>Parameters</strong></p>
<dl class="simple">
<dt><code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">sgx_encl</span> <span class="pre">*encl</span></code></dt><dd><p>an enclave pointer</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">__user</span> <span class="pre">*arg</span></code></dt><dd><p>userspace pointer to <code class="xref c c-type docutils literal notranslate"><span class="pre">struct</span> <span class="pre">sgx_enclave_remove_pages</span></code> instance</p>
</dd>
</dl>
<p><strong>Description</strong></p>
<p>Final step of the flow removing pages from an initialized enclave. The
complete flow is:</p>
<ol class="arabic simple">
<li><p>User changes the type of the pages to be removed to <code class="docutils literal notranslate"><span class="pre">SGX_PAGE_TYPE_TRIM</span></code>
using the <code class="docutils literal notranslate"><span class="pre">SGX_IOC_ENCLAVE_MODIFY_TYPES</span></code> ioctl().</p></li>
<li><p>User approves the page removal by running ENCLU[EACCEPT] from within
the enclave.</p></li>
<li><p>User initiates actual page removal using the
<code class="docutils literal notranslate"><span class="pre">SGX_IOC_ENCLAVE_REMOVE_PAGES</span></code> ioctl() that is handled here.</p></li>
</ol>
<p>First remove any page table entries pointing to the page and then proceed
with the actual removal of the enclave page and data in support of it.</p>
<p>VA pages are not affected by this removal. It is thus possible that the
enclave may end up with more VA pages than needed to support all its
pages.</p>
<p><strong>Return</strong></p>
<ul class="simple">
<li><p>0: Success</p></li>
<li><p>-errno: Otherwise</p></li>
</ul>
</div>
</section>
<section id="enclave-vdso">
<h3><span class="section-number">33.3.3. </span>Enclave vDSO<a class="headerlink" href="#enclave-vdso" title="Link to this heading">¶</a></h3>
<p>Entering an enclave can only be done through SGX-specific EENTER and ERESUME
functions, and is a non-trivial process. Because of the complexity of
transitioning to and from an enclave, enclaves typically utilize a library to
handle the actual transitions. This is roughly analogous to how glibc
implementations are used by most applications to wrap system calls.</p>
<p>Another crucial characteristic of enclaves is that they can generate exceptions
as part of their normal operation that need to be handled in the enclave or are
unique to SGX.</p>
<p>Instead of the traditional signal mechanism to handle these exceptions, SGX
can leverage special exception fixup provided by the vDSO. The kernel-provided
vDSO function wraps low-level transitions to/from the enclave like EENTER and
ERESUME. The vDSO function intercepts exceptions that would otherwise generate
a signal and return the fault information directly to its caller. This avoids
the need to juggle signal handlers.</p>
<dl class="c macro">
<dt class="sig sig-object c" id="c.vdso_sgx_enter_enclave_t">
<span class="sig-name descname"><span class="n"><span class="pre">vdso_sgx_enter_enclave_t</span></span></span><a class="headerlink" href="#c.vdso_sgx_enter_enclave_t" title="Link to this definition">¶</a><br /></dt>
<dd><p><strong>Typedef</strong>: Prototype for <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">__vdso_sgx_enter_enclave()</span></code>, a vDSO function to enter an SGX enclave.</p>
</dd></dl>
<p><strong>Syntax</strong></p>
<blockquote>
<div><p><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">vdso_sgx_enter_enclave_t</span> <span class="pre">(unsigned</span> <span class="pre">long</span> <span class="pre">rdi,</span> <span class="pre">unsigned</span> <span class="pre">long</span> <span class="pre">rsi,</span> <span class="pre">unsigned</span> <span class="pre">long</span> <span class="pre">rdx,</span> <span class="pre">unsigned</span> <span class="pre">int</span> <span class="pre">function,</span> <span class="pre">unsigned</span> <span class="pre">long</span> <span class="pre">r8,</span> <span class="pre">unsigned</span> <span class="pre">long</span> <span class="pre">r9,</span> <span class="pre">struct</span> <span class="pre">sgx_enclave_run</span> <span class="pre">*run)</span></code></p>
</div></blockquote>
<div class="kernelindent docutils container">
<p><strong>Parameters</strong></p>
<dl class="simple">
<dt><code class="docutils literal notranslate"><span class="pre">unsigned</span> <span class="pre">long</span> <span class="pre">rdi</span></code></dt><dd><p>Pass-through value for RDI</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">unsigned</span> <span class="pre">long</span> <span class="pre">rsi</span></code></dt><dd><p>Pass-through value for RSI</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">unsigned</span> <span class="pre">long</span> <span class="pre">rdx</span></code></dt><dd><p>Pass-through value for RDX</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">unsigned</span> <span class="pre">int</span> <span class="pre">function</span></code></dt><dd><p>ENCLU function, must be EENTER or ERESUME</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">unsigned</span> <span class="pre">long</span> <span class="pre">r8</span></code></dt><dd><p>Pass-through value for R8</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">unsigned</span> <span class="pre">long</span> <span class="pre">r9</span></code></dt><dd><p>Pass-through value for R9</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">sgx_enclave_run</span> <span class="pre">*run</span></code></dt><dd><p><code class="xref c c-struct broken_xref docutils literal notranslate"><span class="pre">struct</span> <span class="pre">sgx_enclave_run</span></code>, must be non-NULL</p>
</dd>
</dl>
<p><strong>NOTE</strong></p>
<p><code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">__vdso_sgx_enter_enclave()</span></code> does not ensure full compliance with the
x86-64 ABI, e.g. doesn’t handle XSAVE state. Except for non-volatile
general purpose registers, EFLAGS.DF, and RSP alignment, preserving/setting
state in accordance with the x86-64 ABI is the responsibility of the enclave
and its runtime, i.e. <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">__vdso_sgx_enter_enclave()</span></code> cannot be called from C
code without careful consideration by both the enclave and its runtime.</p>
<p>All general purpose registers except RAX, RBX and RCX are passed as-is to the
enclave. RAX, RBX and RCX are consumed by EENTER and ERESUME and are loaded
with <strong>function</strong>, asynchronous exit pointer, and <strong>run.tcs</strong> respectively.</p>
<p>RBP and the stack are used to anchor <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">__vdso_sgx_enter_enclave()</span></code> to the
pre-enclave state, e.g. to retrieve <strong>run.exception</strong> and <strong>run.user_handler</strong>
after an enclave exit. All other registers are available for use by the
enclave and its runtime, e.g. an enclave can push additional data onto the
stack (and modify RSP) to pass information to the optional user handler (see
below).</p>
<p>Most exceptions reported on ENCLU, including those that occur within the
enclave, are fixed up and reported synchronously instead of being delivered
via a standard signal. Debug Exceptions (#DB) and Breakpoints (#BP) are
never fixed up and are always delivered via standard signals. On synchronously
reported exceptions, -EFAULT is returned and details about the exception are
recorded in <strong>run.exception</strong>, the optional sgx_enclave_exception struct.</p>
<p><strong>Return</strong></p>
<ul class="simple">
<li><p>0: ENCLU function was successfully executed.</p></li>
<li><p>-EINVAL: Invalid ENCL number (neither EENTER nor ERESUME).</p></li>
</ul>
</div>
</section>
</section>
<section id="ksgxd">
<h2><span class="section-number">33.4. </span>ksgxd<a class="headerlink" href="#ksgxd" title="Link to this heading">¶</a></h2>
<p>SGX support includes a kernel thread called <em>ksgxd</em>.</p>
<section id="epc-sanitization">
<h3><span class="section-number">33.4.1. </span>EPC sanitization<a class="headerlink" href="#epc-sanitization" title="Link to this heading">¶</a></h3>
<p>ksgxd is started when SGX initializes. Enclave memory is typically ready
for use when the processor powers on or resets. However, if SGX has been in
use since the reset, enclave pages may be in an inconsistent state. This might
occur after a crash and <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">kexec()</span></code> cycle, for instance. At boot, ksgxd
reinitializes all enclave pages so that they can be allocated and re-used.</p>
<p>The sanitization is done by going through EPC address space and applying the
EREMOVE function to each physical page. Some enclave pages like SECS pages have
hardware dependencies on other pages which prevents EREMOVE from functioning.
Executing two EREMOVE passes removes the dependencies.</p>
</section>
<section id="page-reclaimer">
<h3><span class="section-number">33.4.2. </span>Page reclaimer<a class="headerlink" href="#page-reclaimer" title="Link to this heading">¶</a></h3>
<p>Similar to the core kswapd, ksgxd, is responsible for managing the
overcommitment of enclave memory. If the system runs out of enclave memory,
<em>ksgxd</em> “swaps” enclave memory to normal memory.</p>
</section>
</section>
<section id="launch-control">
<h2><span class="section-number">33.5. </span>Launch Control<a class="headerlink" href="#launch-control" title="Link to this heading">¶</a></h2>
<p>SGX provides a launch control mechanism. After all enclave pages have been
copied, kernel executes EINIT function, which initializes the enclave. Only after
this the CPU can execute inside the enclave.</p>
<p>EINIT function takes an RSA-3072 signature of the enclave measurement. The function
checks that the measurement is correct and signature is signed with the key
hashed to the four <strong>IA32_SGXLEPUBKEYHASH{0, 1, 2, 3}</strong> MSRs representing the
SHA256 of a public key.</p>
<p>Those MSRs can be configured by the BIOS to be either readable or writable.
Linux supports only writable configuration in order to give full control to the
kernel on launch control policy. Before calling EINIT function, the driver sets
the MSRs to match the enclave’s signing key.</p>
</section>
<section id="encryption-engines">
<h2><span class="section-number">33.6. </span>Encryption engines<a class="headerlink" href="#encryption-engines" title="Link to this heading">¶</a></h2>
<p>In order to conceal the enclave data while it is out of the CPU package, the
memory controller has an encryption engine to transparently encrypt and decrypt
enclave memory.</p>
<p>In CPUs prior to Ice Lake, the Memory Encryption Engine (MEE) is used to
encrypt pages leaving the CPU caches. MEE uses a n-ary Merkle tree with root in
SRAM to maintain integrity of the encrypted data. This provides integrity and
anti-replay protection but does not scale to large memory sizes because the time
required to update the Merkle tree grows logarithmically in relation to the
memory size.</p>
<p>CPUs starting from Icelake use Total Memory Encryption (TME) in the place of
MEE. TME-based SGX implementations do not have an integrity Merkle tree, which
means integrity and replay-attacks are not mitigated. B, it includes
additional changes to prevent cipher text from being returned and SW memory
aliases from being created.</p>
<p>DMA to enclave memory is blocked by range registers on both MEE and TME systems
(SDM section 41.10).</p>
</section>
<section id="usage-models">
<h2><span class="section-number">33.7. </span>Usage Models<a class="headerlink" href="#usage-models" title="Link to this heading">¶</a></h2>
<section id="shared-library">
<h3><span class="section-number">33.7.1. </span>Shared Library<a class="headerlink" href="#shared-library" title="Link to this heading">¶</a></h3>
<p>Sensitive data and the code that acts on it is partitioned from the application
into a separate library. The library is then linked as a DSO which can be loaded
into an enclave. The application can then make individual function calls into
the enclave through special SGX instructions. A run-time within the enclave is
configured to marshal function parameters into and out of the enclave and to
call the correct library function.</p>
</section>
<section id="application-container">
<h3><span class="section-number">33.7.2. </span>Application Container<a class="headerlink" href="#application-container" title="Link to this heading">¶</a></h3>
<p>An application may be loaded into a container enclave which is specially
configured with a library OS and run-time which permits the application to run.
The enclave run-time and library OS work together to execute the application
when a thread enters the enclave.</p>
</section>
</section>
<section id="impact-of-potential-kernel-sgx-bugs">
<h2><span class="section-number">33.8. </span>Impact of Potential Kernel SGX Bugs<a class="headerlink" href="#impact-of-potential-kernel-sgx-bugs" title="Link to this heading">¶</a></h2>
<section id="epc-leaks">
<h3><span class="section-number">33.8.1. </span>EPC leaks<a class="headerlink" href="#epc-leaks" title="Link to this heading">¶</a></h3>
<p>When EPC page leaks happen, a WARNING like this is shown in dmesg:</p>
<p>“EREMOVE returned ... and an EPC page was leaked. SGX may become unusable...”</p>
<p>This is effectively a kernel use-after-free of an EPC page, and due
to the way SGX works, the bug is detected at freeing. Rather than
adding the page back to the pool of available EPC pages, the kernel
intentionally leaks the page to avoid additional errors in the future.</p>
<p>When this happens, the kernel will likely soon leak more EPC pages, and
SGX will likely become unusable because the memory available to SGX is
limited. However, while this may be fatal to SGX, the rest of the kernel
is unlikely to be impacted and should continue to work.</p>
<p>As a result, when this happens, user should stop running any new
SGX workloads, (or just any new workloads), and migrate all valuable
workloads. Although a machine reboot can recover all EPC memory, the bug
should be reported to Linux developers.</p>
</section>
</section>
<section id="virtual-epc">
<h2><span class="section-number">33.9. </span>Virtual EPC<a class="headerlink" href="#virtual-epc" title="Link to this heading">¶</a></h2>
<p>The implementation has also a virtual EPC driver to support SGX enclaves
in guests. Unlike the SGX driver, an EPC page allocated by the virtual
EPC driver doesn’t have a specific enclave associated with it. This is
because KVM doesn’t track how a guest uses EPC pages.</p>
<p>As a result, the SGX core page reclaimer doesn’t support reclaiming EPC
pages allocated to KVM guests through the virtual EPC driver. If the
user wants to deploy SGX applications both on the host and in guests
on the same machine, the user should reserve enough EPC (by taking out
total virtual EPC size of all SGX VMs from the physical EPC size) for
host SGX applications so they can run with acceptable performance.</p>
<p>Architectural behavior is to restore all EPC pages to an uninitialized
state also after a guest reboot. Because this state can be reached only
through the privileged <code class="docutils literal notranslate"><span class="pre">ENCLS[EREMOVE]</span></code> instruction, <code class="docutils literal notranslate"><span class="pre">/dev/sgx_vepc</span></code>
provides the <code class="docutils literal notranslate"><span class="pre">SGX_IOC_VEPC_REMOVE_ALL</span></code> ioctl to execute the instruction
on all pages in the virtual EPC.</p>
<p><code class="docutils literal notranslate"><span class="pre">EREMOVE</span></code> can fail for three reasons. Userspace must pay attention
to expected failures and handle them as follows:</p>
<ol class="arabic simple">
<li><p>Page removal will always fail when any thread is running in the
enclave to which the page belongs. In this case the ioctl will
return <code class="docutils literal notranslate"><span class="pre">EBUSY</span></code> independent of whether it has successfully removed
some pages; userspace can avoid these failures by preventing execution
of any vcpu which maps the virtual EPC.</p></li>
<li><p>Page removal will cause a general protection fault if two calls to
<code class="docutils literal notranslate"><span class="pre">EREMOVE</span></code> happen concurrently for pages that refer to the same
“SECS” metadata pages. This can happen if there are concurrent
invocations to <code class="docutils literal notranslate"><span class="pre">SGX_IOC_VEPC_REMOVE_ALL</span></code>, or if a <code class="docutils literal notranslate"><span class="pre">/dev/sgx_vepc</span></code>
file descriptor in the guest is closed at the same time as
<code class="docutils literal notranslate"><span class="pre">SGX_IOC_VEPC_REMOVE_ALL</span></code>; it will also be reported as <code class="docutils literal notranslate"><span class="pre">EBUSY</span></code>.
This can be avoided in userspace by serializing calls to the ioctl()
and to close(), but in general it should not be a problem.</p></li>
<li><p>Finally, page removal will fail for SECS metadata pages which still
have child pages. Child pages can be removed by executing
<code class="docutils literal notranslate"><span class="pre">SGX_IOC_VEPC_REMOVE_ALL</span></code> on all <code class="docutils literal notranslate"><span class="pre">/dev/sgx_vepc</span></code> file descriptors
mapped into the guest. This means that the ioctl() must be called
twice: an initial set of calls to remove child pages and a subsequent
set of calls to remove SECS pages. The second set of calls is only
required for those mappings that returned a nonzero value from the
first call. It indicates a bug in the kernel or the userspace client
if any of the second round of <code class="docutils literal notranslate"><span class="pre">SGX_IOC_VEPC_REMOVE_ALL</span></code> calls has
a return code other than 0.</p></li>
</ol>
</section>
</section>
</div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer">
©The kernel development community.
|
Powered by <a href="https://www.sphinx-doc.org/">Sphinx 8.1.3</a>
& <a href="https://alabaster.readthedocs.io">Alabaster 0.7.16</a>
|
<a href="../../_sources/arch/x86/sgx.rst.txt"
rel="nofollow">Page source</a>
</div>
</body>
</html>