<!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>KVM Lock Overview — 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="KVM VCPU Requests" href="vcpu-requests.html" />
<link rel="prev" title="The LoongArch paravirtual interface" href="loongarch/hypercalls.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 class="current">
<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 current"><a class="reference internal" href="../../subsystem-apis.html">Subsystems</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="../../subsystem-apis.html#core-subsystems">Core subsystems</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../subsystem-apis.html#human-interfaces">Human interfaces</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../subsystem-apis.html#networking-interfaces">Networking interfaces</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../subsystem-apis.html#storage-interfaces">Storage interfaces</a></li>
<li class="toctree-l2 current"><a class="reference internal" href="../../subsystem-apis.html#other-subsystems">Other subsystems</a><ul class="current">
<li class="toctree-l3"><a class="reference internal" href="../../accounting/index.html">Accounting</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../cpu-freq/index.html">CPUFreq - CPU frequency and voltage scaling code in the Linux(TM) kernel</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../edac/index.html">EDAC Subsystem</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../fpga/index.html">FPGA</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../i2c/index.html">I2C/SMBus Subsystem</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../iio/index.html">Industrial I/O</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../pcmcia/index.html">PCMCIA</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../spi/index.html">Serial Peripheral Interface (SPI)</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../w1/index.html">1-Wire Subsystem</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../watchdog/index.html">Watchdog Support</a></li>
<li class="toctree-l3 current"><a class="reference internal" href="../index.html">Virtualization Support</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../hwmon/index.html">Hardware Monitoring</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../accel/index.html">Compute Accelerators</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../security/index.html">Security Documentation</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../crypto/index.html">Crypto API</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../bpf/index.html">BPF Documentation</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../usb/index.html">USB support</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../PCI/index.html">PCI Bus Subsystem</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../misc-devices/index.html">Assorted Miscellaneous Devices Documentation</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../peci/index.html">PECI Subsystem</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../wmi/index.html">WMI Subsystem</a></li>
<li class="toctree-l3"><a class="reference internal" href="../../tee/index.html">TEE Subsystem</a></li>
</ul>
</li>
</ul>
</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>
<li class="toctree-l1"><a class="reference internal" href="../../arch/index.html">CPU architectures</a></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/virt/kvm/locking.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="kvm-lock-overview">
<h1>KVM Lock Overview<a class="headerlink" href="#kvm-lock-overview" title="Link to this heading">¶</a></h1>
<section id="acquisition-orders">
<h2>1. Acquisition Orders<a class="headerlink" href="#acquisition-orders" title="Link to this heading">¶</a></h2>
<p>The acquisition orders for mutexes are as follows:</p>
<ul class="simple">
<li><p><code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">cpus_read_lock()</span></code> is taken outside kvm_lock</p></li>
<li><p>kvm_usage_lock is taken outside <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">cpus_read_lock()</span></code></p></li>
<li><p>kvm->lock is taken outside vcpu->mutex</p></li>
<li><p>kvm->lock is taken outside kvm->slots_lock and kvm->irq_lock</p></li>
<li><p>kvm->slots_lock is taken outside kvm->irq_lock, though acquiring
them together is quite rare.</p></li>
<li><p>kvm->mn_active_invalidate_count ensures that pairs of
<code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">invalidate_range_start()</span></code> and <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">invalidate_range_end()</span></code> callbacks
use the same memslots array. kvm->slots_lock and kvm->slots_arch_lock
are taken on the waiting side when modifying memslots, so MMU notifiers
must not take either kvm->slots_lock or kvm->slots_arch_lock.</p></li>
</ul>
<p><code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">cpus_read_lock()</span></code> vs kvm_lock:</p>
<ul class="simple">
<li><p>Taking <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">cpus_read_lock()</span></code> outside of kvm_lock is problematic, despite that
being the official ordering, as it is quite easy to unknowingly trigger
<code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">cpus_read_lock()</span></code> while holding kvm_lock. Use caution when walking vm_list,
e.g. avoid complex operations when possible.</p></li>
</ul>
<p>For SRCU:</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">synchronize_srcu(&kvm->srcu)</span></code> is called inside critical sections
for kvm->lock, vcpu->mutex and kvm->slots_lock. These locks _cannot_
be taken inside a kvm->srcu read-side critical section; that is, the
following is broken:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>srcu_read_lock(&kvm->srcu);
mutex_lock(&kvm->slots_lock);
</pre></div>
</div>
</li>
<li><p>kvm->slots_arch_lock instead is released before the call to
<code class="docutils literal notranslate"><span class="pre">synchronize_srcu()</span></code>. It _can_ therefore be taken inside a
kvm->srcu read-side critical section, for example while processing
a vmexit.</p></li>
</ul>
<p>On x86:</p>
<ul class="simple">
<li><p>vcpu->mutex is taken outside kvm->arch.hyperv.hv_lock and kvm->arch.xen.xen_lock</p></li>
<li><p>kvm->arch.mmu_lock is an rwlock; critical sections for
kvm->arch.tdp_mmu_pages_lock and kvm->arch.mmu_unsync_pages_lock must
also take kvm->arch.mmu_lock</p></li>
</ul>
<p>Everything else is a leaf: no other lock is taken inside the critical
sections.</p>
</section>
<section id="exception">
<h2>2. Exception<a class="headerlink" href="#exception" title="Link to this heading">¶</a></h2>
<p>Fast page fault:</p>
<p>Fast page fault is the fast path which fixes the guest page fault out of
the mmu-lock on x86. Currently, the page fault can be fast in one of the
following two cases:</p>
<ol class="arabic simple">
<li><p>Access Tracking: The SPTE is not present, but it is marked for access
tracking. That means we need to restore the saved R/X bits. This is
described in more detail later below.</p></li>
<li><p>Write-Protection: The SPTE is present and the fault is caused by
write-protect. That means we just need to change the W bit of the spte.</p></li>
</ol>
<p>What we use to avoid all the races is the Host-writable bit and MMU-writable bit
on the spte:</p>
<ul class="simple">
<li><p>Host-writable means the gfn is writable in the host kernel page tables and in
its KVM memslot.</p></li>
<li><p>MMU-writable means the gfn is writable in the guest’s mmu and it is not
write-protected by shadow page write-protection.</p></li>
</ul>
<p>On fast page fault path, we will use cmpxchg to atomically set the spte W
bit if spte.HOST_WRITEABLE = 1 and spte.WRITE_PROTECT = 1, to restore the saved
R/X bits if for an access-traced spte, or both. This is safe because whenever
changing these bits can be detected by cmpxchg.</p>
<p>But we need carefully check these cases:</p>
<ol class="arabic simple">
<li><p>The mapping from gfn to pfn</p></li>
</ol>
<p>The mapping from gfn to pfn may be changed since we can only ensure the pfn
is not changed during cmpxchg. This is a ABA problem, for example, below case
will happen:</p>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td colspan="2"><p>At the beginning:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>gpte = gfn1
gfn1 is mapped to pfn1 on host
spte is the shadow page table entry corresponding with gpte and
spte = pfn1
</pre></div>
</div>
</td>
</tr>
<tr class="row-even"><td colspan="2"><p>On fast page fault path:</p></td>
</tr>
<tr class="row-odd"><td><p>CPU 0:</p></td>
<td><p>CPU 1:</p></td>
</tr>
<tr class="row-even"><td><div class="highlight-none notranslate"><div class="highlight"><pre><span></span>old_spte = *spte;
</pre></div>
</div>
</td>
<td></td>
</tr>
<tr class="row-odd"><td></td>
<td><p>pfn1 is swapped out:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>spte = 0;
</pre></div>
</div>
<p>pfn1 is re-alloced for gfn2.</p>
<p>gpte is changed to point to
gfn2 by the guest:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>spte = pfn1;
</pre></div>
</div>
</td>
</tr>
<tr class="row-even"><td colspan="2"><div class="highlight-none notranslate"><div class="highlight"><pre><span></span>if (cmpxchg(spte, old_spte, old_spte+W)
mark_page_dirty(vcpu->kvm, gfn1)
OOPS!!!
</pre></div>
</div>
</td>
</tr>
</tbody>
</table>
<p>We dirty-log for gfn1, that means gfn2 is lost in dirty-bitmap.</p>
<p>For direct sp, we can easily avoid it since the spte of direct sp is fixed
to gfn. For indirect sp, we disabled fast page fault for simplicity.</p>
<p>A solution for indirect sp could be to pin the gfn before the cmpxchg. After
the pinning:</p>
<ul class="simple">
<li><p>We have held the refcount of pfn; that means the pfn can not be freed and
be reused for another gfn.</p></li>
<li><p>The pfn is writable and therefore it cannot be shared between different gfns
by KSM.</p></li>
</ul>
<p>Then, we can ensure the dirty bitmaps is correctly set for a gfn.</p>
<ol class="arabic simple" start="2">
<li><p>Dirty bit tracking</p></li>
</ol>
<p>In the original code, the spte can be fast updated (non-atomically) if the
spte is read-only and the Accessed bit has already been set since the
Accessed bit and Dirty bit can not be lost.</p>
<p>But it is not true after fast page fault since the spte can be marked
writable between reading spte and updating spte. Like below case:</p>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td colspan="2"><p>At the beginning:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>spte.W = 0
spte.Accessed = 1
</pre></div>
</div>
</td>
</tr>
<tr class="row-even"><td><p>CPU 0:</p></td>
<td><p>CPU 1:</p></td>
</tr>
<tr class="row-odd"><td><p>In <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">mmu_spte_update()</span></code>:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>old_spte = *spte;
/* 'if' condition is satisfied. */
if (old_spte.Accessed == 1 &&
old_spte.W == 0)
spte = new_spte;
</pre></div>
</div>
</td>
<td></td>
</tr>
<tr class="row-even"><td></td>
<td><p>on fast page fault path:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>spte.W = 1
</pre></div>
</div>
<p>memory write on the spte:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>spte.Dirty = 1
</pre></div>
</div>
</td>
</tr>
<tr class="row-odd"><td><div class="highlight-none notranslate"><div class="highlight"><pre><span></span>else
old_spte = xchg(spte, new_spte);
if (old_spte.Accessed &&
!new_spte.Accessed)
flush = true;
if (old_spte.Dirty &&
!new_spte.Dirty)
flush = true;
OOPS!!!
</pre></div>
</div>
</td>
<td></td>
</tr>
</tbody>
</table>
<p>The Dirty bit is lost in this case.</p>
<p>In order to avoid this kind of issue, we always treat the spte as “volatile”
if it can be updated out of mmu-lock [see <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">spte_needs_atomic_update()</span></code>]; it means
the spte is always atomically updated in this case.</p>
<ol class="arabic simple" start="3">
<li><p>flush tlbs due to spte updated</p></li>
</ol>
<p>If the spte is updated from writable to read-only, we should flush all TLBs,
otherwise rmap_write_protect will find a read-only spte, even though the
writable spte might be cached on a CPU’s TLB.</p>
<p>As mentioned before, the spte can be updated to writable out of mmu-lock on
fast page fault path. In order to easily audit the path, we see if TLBs needing
to be flushed caused this reason in <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">mmu_spte_update()</span></code> since this is a common
function to update spte (present -> present).</p>
<p>Since the spte is “volatile” if it can be updated out of mmu-lock, we always
atomically update the spte and the race caused by fast page fault can be avoided.
See the comments in <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">spte_needs_atomic_update()</span></code> and <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">mmu_spte_update()</span></code>.</p>
<p>Lockless Access Tracking:</p>
<p>This is used for Intel CPUs that are using EPT but do not support the EPT A/D
bits. In this case, PTEs are tagged as A/D disabled (using ignored bits), and
when the KVM MMU notifier is called to track accesses to a page (via
kvm_mmu_notifier_clear_flush_young), it marks the PTE not-present in hardware
by clearing the RWX bits in the PTE and storing the original R & X bits in more
unused/ignored bits. When the VM tries to access the page later on, a fault is
generated and the fast page fault mechanism described above is used to
atomically restore the PTE to a Present state. The W bit is not saved when the
PTE is marked for access tracking and during restoration to the Present state,
the W bit is set depending on whether or not it was a write access. If it
wasn’t, then the W bit will remain clear until a write access happens, at which
time it will be set using the Dirty tracking mechanism described above.</p>
</section>
<section id="reference">
<h2>3. Reference<a class="headerlink" href="#reference" title="Link to this heading">¶</a></h2>
<section id="kvm-lock">
<h3><code class="docutils literal notranslate"><span class="pre">kvm_lock</span></code><a class="headerlink" href="#kvm-lock" title="Link to this heading">¶</a></h3>
<dl class="field-list simple">
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><p>mutex</p>
</dd>
<dt class="field-even">Arch<span class="colon">:</span></dt>
<dd class="field-even"><p>any</p>
</dd>
<dt class="field-odd">Protects<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p>vm_list</p></li>
</ul>
</dd>
</dl>
</section>
<section id="kvm-usage-lock">
<h3><code class="docutils literal notranslate"><span class="pre">kvm_usage_lock</span></code><a class="headerlink" href="#kvm-usage-lock" title="Link to this heading">¶</a></h3>
<dl class="field-list simple">
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><p>mutex</p>
</dd>
<dt class="field-even">Arch<span class="colon">:</span></dt>
<dd class="field-even"><p>any</p>
</dd>
<dt class="field-odd">Protects<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p>kvm_usage_count</p></li>
<li><p>hardware virtualization enable/disable</p></li>
</ul>
</dd>
<dt class="field-even">Comment<span class="colon">:</span></dt>
<dd class="field-even"><p>Exists to allow taking <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">cpus_read_lock()</span></code> while kvm_usage_count is
protected, which simplifies the virtualization enabling logic.</p>
</dd>
</dl>
</section>
<section id="kvm-mn-invalidate-lock">
<h3><code class="docutils literal notranslate"><span class="pre">kvm->mn_invalidate_lock</span></code><a class="headerlink" href="#kvm-mn-invalidate-lock" title="Link to this heading">¶</a></h3>
<dl class="field-list simple">
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><p>spinlock_t</p>
</dd>
<dt class="field-even">Arch<span class="colon">:</span></dt>
<dd class="field-even"><p>any</p>
</dd>
<dt class="field-odd">Protects<span class="colon">:</span></dt>
<dd class="field-odd"><p>mn_active_invalidate_count, mn_memslots_update_rcuwait</p>
</dd>
</dl>
</section>
<section id="kvm-arch-tsc-write-lock">
<h3><code class="docutils literal notranslate"><span class="pre">kvm_arch::tsc_write_lock</span></code><a class="headerlink" href="#kvm-arch-tsc-write-lock" title="Link to this heading">¶</a></h3>
<dl class="field-list simple">
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><p>raw_spinlock_t</p>
</dd>
<dt class="field-even">Arch<span class="colon">:</span></dt>
<dd class="field-even"><p>x86</p>
</dd>
<dt class="field-odd">Protects<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p>kvm_arch::{last_tsc_write,last_tsc_nsec,last_tsc_offset}</p></li>
<li><p>tsc offset in vmcb</p></li>
</ul>
</dd>
<dt class="field-even">Comment<span class="colon">:</span></dt>
<dd class="field-even"><p>‘raw’ because updating the tsc offsets must not be preempted.</p>
</dd>
</dl>
</section>
<section id="kvm-mmu-lock">
<h3><code class="docutils literal notranslate"><span class="pre">kvm->mmu_lock</span></code><a class="headerlink" href="#kvm-mmu-lock" title="Link to this heading">¶</a></h3>
<dl class="field-list simple">
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><p>spinlock_t or rwlock_t</p>
</dd>
<dt class="field-even">Arch<span class="colon">:</span></dt>
<dd class="field-even"><p>any</p>
</dd>
<dt class="field-odd">Protects<span class="colon">:</span></dt>
<dd class="field-odd"><p>-shadow page/shadow tlb entry</p>
</dd>
<dt class="field-even">Comment<span class="colon">:</span></dt>
<dd class="field-even"><p>it is a spinlock since it is used in mmu notifier.</p>
</dd>
</dl>
</section>
<section id="kvm-srcu">
<h3><code class="docutils literal notranslate"><span class="pre">kvm->srcu</span></code><a class="headerlink" href="#kvm-srcu" title="Link to this heading">¶</a></h3>
<dl class="field-list simple">
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><p>srcu lock</p>
</dd>
<dt class="field-even">Arch<span class="colon">:</span></dt>
<dd class="field-even"><p>any</p>
</dd>
<dt class="field-odd">Protects<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p>kvm->memslots</p></li>
<li><p>kvm->buses</p></li>
</ul>
</dd>
<dt class="field-even">Comment<span class="colon">:</span></dt>
<dd class="field-even"><p>The srcu read lock must be held while accessing memslots (e.g.
when using gfn_to_* functions) and while accessing in-kernel
MMIO/PIO address->device structure mapping (kvm->buses).
The srcu index can be stored in kvm_vcpu->srcu_idx per vcpu
if it is needed by multiple functions.</p>
</dd>
</dl>
</section>
<section id="kvm-slots-arch-lock">
<h3><code class="docutils literal notranslate"><span class="pre">kvm->slots_arch_lock</span></code><a class="headerlink" href="#kvm-slots-arch-lock" title="Link to this heading">¶</a></h3>
<dl class="field-list simple">
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><p>mutex</p>
</dd>
<dt class="field-even">Arch<span class="colon">:</span></dt>
<dd class="field-even"><p>any (only needed on x86 though)</p>
</dd>
<dt class="field-odd">Protects<span class="colon">:</span></dt>
<dd class="field-odd"><p>any arch-specific fields of memslots that have to be modified
in a <code class="docutils literal notranslate"><span class="pre">kvm->srcu</span></code> read-side critical section.</p>
</dd>
<dt class="field-even">Comment<span class="colon">:</span></dt>
<dd class="field-even"><p>must be held before reading the pointer to the current memslots,
until after all changes to the memslots are complete</p>
</dd>
</dl>
</section>
<section id="wakeup-vcpus-on-cpu-lock">
<h3><code class="docutils literal notranslate"><span class="pre">wakeup_vcpus_on_cpu_lock</span></code><a class="headerlink" href="#wakeup-vcpus-on-cpu-lock" title="Link to this heading">¶</a></h3>
<dl class="field-list simple">
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><p>spinlock_t</p>
</dd>
<dt class="field-even">Arch<span class="colon">:</span></dt>
<dd class="field-even"><p>x86</p>
</dd>
<dt class="field-odd">Protects<span class="colon">:</span></dt>
<dd class="field-odd"><p>wakeup_vcpus_on_cpu</p>
</dd>
<dt class="field-even">Comment<span class="colon">:</span></dt>
<dd class="field-even"><p>This is a per-CPU lock and it is used for VT-d posted-interrupts.
When VT-d posted-interrupts are supported and the VM has assigned
devices, we put the blocked vCPU on the list blocked_vcpu_on_cpu
protected by blocked_vcpu_on_cpu_lock. When VT-d hardware issues
wakeup notification event since external interrupts from the
assigned devices happens, we will find the vCPU on the list to
wakeup.</p>
</dd>
</dl>
</section>
<section id="vendor-module-lock">
<h3><code class="docutils literal notranslate"><span class="pre">vendor_module_lock</span></code><a class="headerlink" href="#vendor-module-lock" title="Link to this heading">¶</a></h3>
<dl class="field-list simple">
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><p>mutex</p>
</dd>
<dt class="field-even">Arch<span class="colon">:</span></dt>
<dd class="field-even"><p>x86</p>
</dd>
<dt class="field-odd">Protects<span class="colon">:</span></dt>
<dd class="field-odd"><p>loading a vendor module (kvm_amd or kvm_intel)</p>
</dd>
<dt class="field-even">Comment<span class="colon">:</span></dt>
<dd class="field-even"><p>Exists because using kvm_lock leads to deadlock. kvm_lock is taken
in notifiers, e.g. <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">__kvmclock_cpufreq_notifier()</span></code>, that may be invoked while
cpu_hotplug_lock is held, e.g. from <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">cpufreq_boost_trigger_state()</span></code>, and many
operations need to take cpu_hotplug_lock when loading a vendor module, e.g.
updating static calls.</p>
</dd>
</dl>
</section>
</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/virt/kvm/locking.rst.txt"
rel="nofollow">Page source</a>
</div>
</body>
</html>