<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://daynix.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://daynix.github.io/" rel="alternate" type="text/html" /><updated>2025-05-07T08:21:55+00:00</updated><id>https://daynix.github.io/feed.xml</id><title type="html">daynix.github.io</title><subtitle>GitHub Pages of Daynix Computing Ltd.</subtitle><entry><title type="html">Git Basics</title><link href="https://daynix.github.io/2024/03/26/git-basics.html" rel="alternate" type="text/html" title="Git Basics" /><published>2024-03-26T11:22:39+00:00</published><updated>2024-03-26T11:22:39+00:00</updated><id>https://daynix.github.io/2024/03/26/git-basics</id><content type="html" xml:base="https://daynix.github.io/2024/03/26/git-basics.html"><![CDATA[<h1 id="git-basics">Git Basics</h1>

<h2 id="introduction">Introduction</h2>

<p>Git is a distributed version control system that helps track changes in source code during software development. This article will cover the fundamental concepts and commands that every developer should know.</p>

<h2 id="basic-concepts">Basic Concepts</h2>

<h3 id="repository">Repository</h3>
<p>A Git repository is a storage location where your project files and their complete history are stored.</p>

<h3 id="commit">Commit</h3>
<p>A commit is a snapshot of your project at a specific point in time. Each commit has a unique identifier (hash) and contains information about what changed.</p>

<h3 id="branch">Branch</h3>
<p>A branch is a separate line of development. The default branch is usually called <code class="language-plaintext highlighter-rouge">main</code> or <code class="language-plaintext highlighter-rouge">master</code>.</p>

<h1 id="basic-git-usage">Basic Git usage</h1>

<h3 id="initial-configuration">Initial Configuration</h3>

<p>If this is the first time you are using Git as a specific user, you should configure it with your details first.</p>

<ul>
  <li>
    <p>Set user credentials:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git config --global user.name "Your name"
git config --global user.email your_name@yourdomain.com
</code></pre></div>    </div>

    <ul>
      <li>The global user credentials are saved in the <code class="language-plaintext highlighter-rouge">~/.gitconfig</code> file. You can open it and see the current status of configuration.</li>
    </ul>
  </li>
  <li>
    <p>You can also configure credentials per repository, by using:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git config user.name "Your name"
git config user.email your_name@yourdomain.com
</code></pre></div>    </div>

    <ul>
      <li>These local settings are saved in the <code class="language-plaintext highlighter-rouge">.git/config</code> file, in the local directory.</li>
    </ul>
  </li>
  <li>
    <p>To use the &#8220;<code class="language-plaintext highlighter-rouge">git send-email</code>&#8221; command (which allows sending patches to a mailing list for review) your email server and account details will need to be configured in the <code class="language-plaintext highlighter-rouge">~/.gitconfig</code> file as well. Use these settings for the Daynix mail server (Obviously, replace the &#8220;<code class="language-plaintext highlighter-rouge">from</code>&#8221; and &#8220;<code class="language-plaintext highlighter-rouge">smtpuser</code>&#8221; fields with your own data):</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[sendemail]
        from = Your Name &lt;your_name@yourdomain.com&gt;
        smtpserver = smtp.gmail.com
        smtpuser = your_name@yourdomain.com
        smtpencryption = tls
        chainreplyto = false
        smtpserverport = 587
</code></pre></div>    </div>
  </li>
</ul>

<h3 id="getting-remote-repositories-and-creating-new-ones">Getting remote repositories, and creating new ones</h3>

<h4 id="clone-repository-get-it-locally">Clone repository (get it locally)</h4>

<p>To clone a repository into a local directory do:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone &lt;repo URL&gt; [optional local directory]
</code></pre></div></div>

<p>This operation sometimes called &#8220;checkout&#8221; in other source control systems.</p>

<h4 id="create-repository">Create repository</h4>

<p>In the required directory do:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git init
</code></pre></div></div>

<p>The above command will create a new empty repository. You can also use &#8220;&#8211;bare&#8221; option to create repository without a file tree (can be useful if this is a central repository that no one is actively working on but only pushes to and pulling from).</p>

<p>Next, <strong>assuming that we are working with GitHub</strong> the stages are:</p>

<ul>
  <li>
    <p>Create the remote repository on GitHub:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl -u '&lt;USER&gt;' https://api.github.com/user/repos -d '{"name":"&lt;REPOSITORY&gt;"}'
</code></pre></div>    </div>

    <ul>
      <li>In the above command, <strong>ONLY</strong> <code class="language-plaintext highlighter-rouge">&lt;USER&gt;</code> and <code class="language-plaintext highlighter-rouge">&lt;REPOSITORY&gt;</code> should be changed to the appropriate values (your username on GitHub and the desired name for the new repository). The &#8220;<code class="language-plaintext highlighter-rouge">user/repos</code>&#8221; part should be kept as-is, and used literally.</li>
      <li>The output of this command will print a lot of useful information on the newly created repository. It may be useful to keep.</li>
    </ul>
  </li>
  <li>
    <p>Next, define the remote &#8220;origin&#8221; for the new local repository, in the newly created one on GitHub:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git remote add origin https://github.com/&lt;USER&gt;/&lt;REPOSITORY&gt;.git
</code></pre></div>    </div>

    <ul>
      <li>Again, <code class="language-plaintext highlighter-rouge">&lt;USER&gt;</code> and <code class="language-plaintext highlighter-rouge">&lt;REPOSITORY&gt;</code> should be changed here to the same values that were used above.</li>
      <li>
        <p>If you had a typo above, or just want to use a different remote origin, use the command below to remove the origin and start over:</p>

        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git remote rm origin
</code></pre></div>        </div>
      </li>
    </ul>
  </li>
</ul>

<h3 id="important-commands-to-see-the-current-status">Important commands to see the current status</h3>

<ul>
  <li><code class="language-plaintext highlighter-rouge">git status</code> : Shows the files that were modified since the last commit, and the files that are currently untracked by Git. Very useful to get the current status of things</li>
  <li><code class="language-plaintext highlighter-rouge">git log</code> : Shows the history of the commits, their hash numbers <strong>(very useful)</strong>, and their commit messages.</li>
</ul>

<h3 id="committing">Committing</h3>

<ol>
  <li>
    <p>Before beginning to work on a specific issue, create a branch for it, and switch to it. These two actions can be achieved using a single command:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git checkout -b newFeature
</code></pre></div>    </div>

    <p>&#8230;Where <code class="language-plaintext highlighter-rouge">newFeature</code> is the name of the new branch you&#8217;re creating. If you forgot to perform this before making your changes, you can do this later. But, it will be best to create the new branch before any changes are made.</p>
  </li>
  <li>Edit the files and make the desired changes to the code.</li>
  <li>Perform &#8220;<code class="language-plaintext highlighter-rouge">git status</code>&#8221;, &#8220;<code class="language-plaintext highlighter-rouge">git diff</code>&#8221; or &#8220;<code class="language-plaintext highlighter-rouge">git diff &lt;file&gt;</code>&#8221;, in order to see the changes from the master branch (in all files or in a specific one).</li>
  <li>To stage the desired changes to a commit, use:
    <ol>
      <li>&#8220;<code class="language-plaintext highlighter-rouge">git add -i</code>&#8221; or &#8220;<code class="language-plaintext highlighter-rouge">git add -i &lt;file&gt;</code>&#8221;. This will let you interactively select the wanted changes for committing.
        <ol>
          <li>Press &#8220;<code class="language-plaintext highlighter-rouge">5</code>&#8221; (patch) then the number of file to look at (if there are several) and then press Enter.</li>
          <li>Blocks of changed code will be presented to you. To include the whole block press &#8220;<code class="language-plaintext highlighter-rouge">y</code>&#8221;, to skip the whole block press &#8220;<code class="language-plaintext highlighter-rouge">n</code>&#8221;, to split it into smaller blocks (if, <em>e.g.</em>, it is not continuous, and only one part is required) press &#8220;<code class="language-plaintext highlighter-rouge">s</code>&#8221;, or, to manually edit the changes, press &#8220;<code class="language-plaintext highlighter-rouge">e</code>&#8221;.</li>
          <li>After finishing going over a file, select the next file to look at, or quit (&#8220;<code class="language-plaintext highlighter-rouge">7</code>&#8221;).</li>
          <li>If you would like to include a previously untraccked file, just type &#8220;<code class="language-plaintext highlighter-rouge">a</code>&#8221; in the prompt, and choose the number of the file.</li>
        </ol>
      </li>
      <li>Or &#8220;<code class="language-plaintext highlighter-rouge">git add -u</code>&#8221; to add all changes in tracked files (be careful - new files will not be added!).</li>
      <li>Or &#8220;<code class="language-plaintext highlighter-rouge">git add .</code>&#8221; to add all changes and untracked files in local directory (be very careful, as this can add intermediate files. Should be used for initial commits).</li>
    </ol>
  </li>
  <li>Run &#8220;<code class="language-plaintext highlighter-rouge">git diff --cached</code>&#8221; to see only the changes that will be included in the next commit.
    <ul>
      <li>
        <p>In case there were mistakes in staging (running &#8220;add&#8221;) you can always fix it by:</p>

        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git reset &lt;file&gt;
</code></pre></div>        </div>

        <p>This will unstage the file, and you will need to add it (or parts of it) again. You can also run this command without &#8220;<code class="language-plaintext highlighter-rouge">&lt;file&gt;</code>&#8221;, to unstage all changes.</p>
      </li>
    </ul>
  </li>
  <li>
    <p>Perform the commit:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git commit -s
</code></pre></div>    </div>

    <p>In the editor that will appear, write the commit title (starting with &#8220;<code class="language-plaintext highlighter-rouge">PROJECT NAME:</code>&#8221;) then, <strong>if</strong> the title is not informative enough, make a one-line space and underneath it write a more detailed description. Save and quit.</p>
  </li>
  <li>Repeat steps 4&#8211;6 as many times as necessary, to create commits for all the introduced changes. It is a good practice to make the commits as small and specific as possible.</li>
</ol>

<h3 id="formatting-patches-and-sending-them-for-review">Formatting patches and sending them for review</h3>

<p><strong>How to determine the subject prefix of a patch:</strong>
The subject prefix of a patch is determined by the mailing list the patch will be sent to, for example:</p>

<ul>
  <li>
    <p>When a patch is send to a mailing list related to one repository only (like qemu-devel) subject should be prefixed with [PATCH]</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git config format.subjectprefix "PATCH"
</code></pre></div>    </div>
  </li>
</ul>

<!-- end list -->

<ol>
  <li>
    <p>To format the patches use the command:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git format-patch master -n -o &lt;desired output directory&gt;
</code></pre></div>    </div>

    <p>(If this is the second (or any other number) iteration of patches after review use):</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git format-patch master -n -o &lt;desired output directory&gt; -v&lt;iteration number&gt;
</code></pre></div>    </div>

    <p>This command will format the patches (as differences from the &#8220;master&#8221; branch), and output them as &#8220;.patch&#8221; files into the specified output directory.</p>
    <ul>
      <li>Other useful options for this command include:
        <ul>
          <li>&#8221;<code class="language-plaintext highlighter-rouge">--cover-letter</code>&#8221;, which will enable you to write a cover letter explaining the patches.</li>
          <li>&#8221;<code class="language-plaintext highlighter-rouge">--subject-prefix=&lt;Desired-Subject-Prefix&gt;</code>&#8221;, which will replace the standard subject prefix from the default, which is &#8220;<code class="language-plaintext highlighter-rouge">[PATCH]</code>&#8221;.</li>
          <li>It is also possible to replace subject prefix for all patches generated from a specific working copy by running <code class="language-plaintext highlighter-rouge">"git config format.subjectprefix &lt;Desired-Subject-Prefix&gt;"</code></li>
          <li>When renaming files use &#8211;minimal or -M in order to make patch size minimal and readable.</li>
          <li>Use -v option to append version number to [PATCH] prefix. Example -v 2 will create &#8220;[PATCH v2]&#8221; prefix.</li>
        </ul>
      </li>
    </ul>
  </li>
</ol>

<h4 id="important-note-for-gmail-usage">Important note for GMail usage</h4>

<p>https://support.google.com/accounts/answer/6010255 - users should allow the usage of &#8220;less secure apps&#8221; in order to be able to send emails with send-patch</p>

<h3 id="editing-commits">Editing commits</h3>

<p>After peer review, or if you just found an error in a commit, editing the commits may be needed.
TBD</p>

<h4 id="resolving-merge-conflict-while-rebasing"><a href="http://tedfelix.com/software/git-conflict-resolution.html#git-rebase">Resolving merge conflict while rebasing</a></h4>

<h3 id="pull-requests">Pull Requests</h3>

<p>TBD</p>

<h3 id="force-push-a-pull-request">Force push a Pull Request</h3>

<p>TBD</p>

<h3 id="pushing-changes-to-master">Pushing changes to Master</h3>

<p>After your patches were peer-reviewed and approved, and no changes are needed to be performed on the commits, you can push them to the production branch (Master) on the remote server.</p>

<p><strong>[PLEASE VERIFY AGAIN THAT ALL THE COMMITS ARE CORRECT AND FINAL!!!]</strong></p>

<p><strong>There are several ways to push changes:</strong></p>

<p>The simplest one assumes that no one was changing the remote repository while you were working on your feature, and you did not modify your local &#8220;master&#8221; branch while working on the branch dedicated to your new feature. Basically, it means that you are the only one working on the project, and you make one change at a time:</p>

<h4 id="you-are-the-only-one-working-on-the-remote-repository-and-you-know-it-did-not-change-while-you-were-working-on-your-feature">[[You are the only one working on the remote repository, and you KNOW it did not change while you were working on your feature]]</h4>

<p>TBD</p>

<p>If other people may have changed the remote repository, but you did not change the local &#8220;master&#8221; branch since starting to work on your separate branch, use the following method:</p>

<h4 id="your-local-master-branch-didnt-change-since-you-started-to-work-on-your-feature">[[Your LOCAL &#8220;master&#8221; branch didn&#8217;t change since you started to work on your feature]]</h4>

<p>TBD</p>

<p>The longest method does not assume anything. <strong>IF IN ANY DOUBT, USE ONLY THE FOLLOWING METHOD:</strong></p>

<h4 id="you-are-not-sure-of-anything---the-longest-but-the-most-reliable-way">[[You are not sure of anything - the longest, but the most reliable way]]</h4>
<p>TBD</p>

<h2 id="advanced-how-tos">Advanced How-To&#8217;s</h2>

<h3 id="how-to-revert-commits-in-git">How to revert commit(s) in GIT</h3>

<p>Let&#8217;s say you have the branch history like:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>HashA -&gt; HashB -&gt; HashC ... -&gt; HashPreLast -&gt; HashLast
</code></pre></div></div>

<p>Then you can use:</p>

<ul>
  <li>to revert <code class="language-plaintext highlighter-rouge">HashLast</code> commit either:
    <ul>
      <li><code class="language-plaintext highlighter-rouge">git revert HEAD</code></li>
      <li><code class="language-plaintext highlighter-rouge">git revert HashPreLast..HEAD</code></li>
    </ul>
  </li>
  <li>to revert <code class="language-plaintext highlighter-rouge">HashPreLast</code> commit:
    <ul>
      <li><code class="language-plaintext highlighter-rouge">git revert ^HEAD</code></li>
    </ul>
  </li>
  <li>to revert <code class="language-plaintext highlighter-rouge">HashB</code> commit:
    <ul>
      <li><code class="language-plaintext highlighter-rouge">git revert HashA..HashB</code></li>
    </ul>
  </li>
  <li>to revert <code class="language-plaintext highlighter-rouge">HashB</code> to <code class="language-plaintext highlighter-rouge">HashLast</code> commits:
    <ul>
      <li><code class="language-plaintext highlighter-rouge">git revert HashA..HEAD</code></li>
    </ul>
  </li>
</ul>

<p>More information can be found <a href="http://book.git-scm.com/4_undoing_in_git\_-\_reset,\_checkout_and_revert.html">here</a></p>

<h3 id="checking-out-pull-request-from-github">Checking out pull request from GitHub</h3>

<p>Sometimes you would like to checkout pull request from Github to do additional tests.
In order to do it follow: https://help.github.com/articles/checking-out-pull-requests-locally/</p>

<p>Fetch pull request by ID and add new branch name:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git fetch origin pull/ID/head:BRANCHNAME
</code></pre></div></div>

<p>Check out the branch:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> git checkout BRANCHNAME
</code></pre></div></div>

<h3 id="bisection-with-git-git-bisect">Bisection with GIT (<strong>git bisect</strong>)</h3>

<p>Let&#8217;s say you have a branch history with regression, you know commit that worked and commit that doesn&#8217;t work, but there are commits between those and you do not know which one introduced a problem. For cases like that GIT provides the bisect mode (<strong>git bisect</strong>) that allows to find a change that introduced a bug by binary search.</p>

<p><strong>git bisect</strong> command is described in great details at http://git-scm.com/docs/git-bisect</p>

<p>It worth noting that GIT bisect mode may be used for finding both regressions, i.e. commits that broke something (in a natural way) and commits that fixed something. In the latter case <strong>good</strong> and <strong>bad</strong> commits concepts have exactly opposite meaning, i.e. <strong>good</strong> - commit that doesn&#8217;t work, <strong>bad</strong> - commit that works.</p>]]></content><author><name>Yan Vugenfirer</name></author><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Resource Management in Ruby - AutoHCK Case Study</title><link href="https://daynix.github.io/2023/08/11/resource-management-in-ruby-autohck-case-study.html" rel="alternate" type="text/html" title="Resource Management in Ruby - AutoHCK Case Study" /><published>2023-08-11T11:00:00+00:00</published><updated>2023-08-11T11:00:00+00:00</updated><id>https://daynix.github.io/2023/08/11/resource-management-in-ruby-autohck-case-study</id><content type="html" xml:base="https://daynix.github.io/2023/08/11/resource-management-in-ruby-autohck-case-study.html"><![CDATA[<svg style="width: 100%" width="69.896mm" height="69.702mm" version="1.1" viewBox="0 0 69.896 69.702"><title>Ruby logo</title><defs><linearGradient id="linearGradient6" x2="1" gradientTransform="matrix(-41.8 -73.8 73.8 -41.8 381.75 -279.75)" gradientUnits="userSpaceOnUse"><stop stop-color="#fb7655" offset="0" /><stop stop-color="#e42b1e" offset=".41" /><stop stop-color="#900" offset=".99001" /><stop stop-color="#900" offset="1" /></linearGradient><linearGradient id="linearGradient10" x2="1" gradientTransform="matrix(-53.869 -36.149 36.149 -53.869 402.57 -341.73)" gradientUnits="userSpaceOnUse"><stop stop-color="#871101" offset="0" /><stop stop-color="#911209" offset=".99001" /><stop stop-color="#911209" offset="1" /></linearGradient><linearGradient id="linearGradient14" x2="1" gradientTransform="matrix(-53.869 -36.149 36.149 -53.869 359.47 -277.51)" gradientUnits="userSpaceOnUse"><stop stop-color="#871101" offset="0" /><stop stop-color="#911209" offset=".99001" /><stop stop-color="#911209" offset="1" /></linearGradient><linearGradient id="linearGradient20" x2="1" gradientTransform="matrix(8.351 54.273 -54.273 8.351 246.38 -367.9)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0" /><stop stop-color="#e57252" offset=".23" /><stop stop-color="#de3b20" offset=".46001" /><stop stop-color="#a60003" offset=".99001" /><stop stop-color="#a60003" offset="1" /></linearGradient><linearGradient id="linearGradient26" x2="1" gradientTransform="matrix(3.077 55.39 -55.39 3.077 303.81 -418.58)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0" /><stop stop-color="#e4714e" offset=".23" /><stop stop-color="#be1a0d" offset=".56" /><stop stop-color="#a80d00" offset=".99001" /><stop stop-color="#a80d00" offset="1" /></linearGradient><linearGradient id="linearGradient32" x2="1" gradientTransform="matrix(9.211 39.695 -39.695 9.211 354.78 -469.77)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0" /><stop stop-color="#e46342" offset=".17999" /><stop stop-color="#c82410" offset=".39999" /><stop stop-color="#a80d00" offset=".99001" /><stop stop-color="#a80d00" offset="1" /></linearGradient><linearGradient id="linearGradient37" x2="1" gradientTransform="matrix(39.694 -19.847 19.847 39.694 326.66 -483.75)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0" /><stop stop-color="#c81f11" offset=".53999" /><stop stop-color="#bf0905" offset=".99001" /><stop stop-color="#bf0905" offset="1" /></linearGradient><linearGradient id="linearGradient42" x2="1" gradientTransform="matrix(3.267 32.71 -32.71 3.267 211.58 -381.73)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0" /><stop stop-color="#de4024" offset=".31" /><stop stop-color="#bf190b" offset=".99001" /><stop stop-color="#bf190b" offset="1" /></linearGradient><linearGradient id="linearGradient52" x2="1" gradientTransform="matrix(153.57 -157.92 157.92 153.57 189.12 -340.18)" gradientUnits="userSpaceOnUse"><stop stop-color="#bd0012" offset="0" /><stop stop-color="#fff" offset=".07001" /><stop stop-color="#fff" offset=".17" /><stop stop-color="#c82f1c" offset=".27" /><stop stop-color="#820c01" offset=".33" /><stop stop-color="#a31601" offset=".46001" /><stop stop-color="#b31301" offset=".72" /><stop stop-color="#e82609" offset=".99001" /><stop stop-color="#e82609" offset="1" /></linearGradient><linearGradient id="linearGradient57" x2="1" gradientTransform="matrix(-46.254 -11.416 11.416 -46.254 306.76 -324.26)" gradientUnits="userSpaceOnUse"><stop stop-color="#8c0c01" offset="0" /><stop stop-color="#990c00" offset=".53999" /><stop stop-color="#a80d0e" offset=".99001" /><stop stop-color="#a80d0e" offset="1" /></linearGradient><linearGradient id="linearGradient61" x2="1" gradientTransform="matrix(-41.094 -36.831 36.831 -41.094 386.21 -379.78)" gradientUnits="userSpaceOnUse"><stop stop-color="#7e110b" offset="0" /><stop stop-color="#9e0c00" offset=".99001" /><stop stop-color="#9e0c00" offset="1" /></linearGradient><linearGradient id="linearGradient65" x2="1" gradientTransform="matrix(-20.47 -21.884 21.884 -20.47 401.3 -447.35)" gradientUnits="userSpaceOnUse"><stop stop-color="#79130d" offset="0" /><stop stop-color="#9e120b" offset=".99001" /><stop stop-color="#9e120b" offset="1" /></linearGradient><radialGradient id="radialGradient69" cx="0" cy="0" r="1" gradientTransform="matrix(50.36 0 0 50.36 351.51 -415.9)" gradientUnits="userSpaceOnUse"><stop stop-color="#a80d00" offset="0" /><stop stop-color="#7e0e08" offset=".99001" /><stop stop-color="#7e0e08" offset="1" /></radialGradient><radialGradient id="radialGradient73" cx="0" cy="0" r="1" gradientTransform="matrix(66.947 0 0 66.947 281.77 -349.54)" gradientUnits="userSpaceOnUse"><stop stop-color="#a30c00" offset="0" /><stop stop-color="#800e08" offset=".99001" /><stop stop-color="#800e08" offset="1" /></radialGradient><linearGradient id="linearGradient78" x2="1" gradientTransform="matrix(-16.682 -56.597 56.597 -16.682 234.35 -297.95)" gradientUnits="userSpaceOnUse"><stop stop-color="#8b2114" offset="0" /><stop stop-color="#9e100a" offset=".42999" /><stop stop-color="#b3100c" offset=".99001" /><stop stop-color="#b3100c" offset="1" /></linearGradient><linearGradient id="linearGradient83" x2="1" gradientTransform="matrix(37.4 16.509 -16.509 37.4 362.32 -485.49)" gradientUnits="userSpaceOnUse"><stop stop-color="#b31000" offset="0" /><stop stop-color="#910f08" offset=".44" /><stop stop-color="#791c12" offset=".99001" /><stop stop-color="#791c12" offset="1" /></linearGradient></defs><g transform="translate(-78.052 -23.812)"><g transform="matrix(.26458 0 0 .26458 4.7871 -80.86)" fill-rule="evenodd"><path transform="matrix(1.3333 0 0 1.3333 0 1056)" d="m248.06-297.71 146.47-9.9399 11.28-147.69s-44.63 90.46-44.63 90.46l-113.12 67.17z" fill="url(#linearGradient6)" /><path transform="matrix(1.3333 0 0 1.3333 0 1056)" d="m347.89-349.36 46.88 41.61-12.59-86.89s-34.29 45.28-34.29 45.28z" fill="url(#linearGradient10)" /><path transform="matrix(1.3333 0 0 1.3333 0 1056)" d="m248.55-297.9 146.39-9.8501-92.23-7.2402-54.16 17.09z" fill="url(#linearGradient14)" /><path transform="matrix(1.3333 0 0 1.3333 0 1056)" d="m221.02-362.52s27.66 64.64 27.66 64.64 23.04-75.48 23.04-75.48l-50.7 10.84z" fill="url(#linearGradient20)" /><path transform="matrix(1.3333 0 0 1.3333 0 1056)" d="m266.01-375.28 81.87 26.17s-21.2-83.04-21.2-83.04z" fill="url(#linearGradient26)" /><path transform="matrix(1.3333 0 0 1.3333 0 1056)" d="m327.68-426.19 73.32-4.79-57.35-46.84s-15.97 51.63-15.97 51.63z" fill="url(#linearGradient32)" /><path transform="matrix(1.3333 0 0 1.3333 0 1056)" d="m319.17-494.77 55.01 0.25-33.73 18.64z" fill="url(#linearGradient37)" /><path transform="matrix(1.3333 0 0 1.3333 0 1056)" d="m210.38-393.67-2.6997 56.47 14.13-25.77z" fill="url(#linearGradient42)" /><path transform="matrix(1.3333 0 0 1.3333 0 1056)" d="m209.62-394.64 11.5 32.62 49.97-11.21 57.05-53.02s16.1-51.14 16.1-51.14l-25.35-17.9-43.1 16.13c-13.58 12.63-39.93 37.62-40.88 38.09-0.93995 0.47998-17.4 31.59-25.29 46.43z" fill="#fff" /><path transform="matrix(1.3333 0 0 1.3333 0 1056)" d="m250-453.24c29.43-29.18 67.37-46.42 81.93-31.73 14.55 14.69-0.88038 50.39-30.31 79.56-29.43 29.17-66.9 47.36-81.45 32.67-14.56-14.68 0.3999-51.33 29.83-80.5z" fill="url(#linearGradient52)" /><path transform="matrix(1.3333 0 0 1.3333 0 1056)" d="m248.68-297.91s22.86-75.72 22.86-75.72l75.92 24.39c-27.45 25.74-57.98 47.5-98.78 51.33z" fill="url(#linearGradient57)" /><path transform="matrix(1.3333 0 0 1.3333 0 1056)" d="m328.24-426.4 19.49 77.2c22.93-24.11 43.51-50.03 53.59-82.09z" fill="url(#linearGradient61)" /><path transform="matrix(1.3333 0 0 1.3333 0 1056)" d="m401.12-430.9c7.7998-23.54 9.5996-57.31-27.18-63.58l-30.18 16.67z" fill="url(#linearGradient65)" /><path transform="matrix(1.3333 0 0 1.3333 0 1056)" d="m207.68-337.54c1.0796 38.85 29.11 39.43 41.05 39.77l-27.58-64.41-13.47 24.64z" fill="#9e1209" /><path transform="matrix(1.3333 0 0 1.3333 0 1056)" d="m328.35-426.28c17.62 10.83 53.13 32.58 53.85 32.98 1.1196 0.62988 15.31-23.93 18.53-37.81l-72.38 4.8301z" fill="url(#radialGradient69)" /><path transform="matrix(1.3333 0 0 1.3333 0 1056)" d="m271.51-373.63 30.56 58.96c18.07-9.8003 32.22-21.74 45.18-34.53z" fill="url(#radialGradient73)" /><path transform="matrix(1.3333 0 0 1.3333 0 1056)" d="m221.03-362.1s-4.3296 51.56-4.3296 51.56c8.1699 11.16 19.41 12.13 31.2 11.26-8.5298-21.23-25.57-63.68-26.87-62.82z" fill="url(#linearGradient78)" /><path transform="matrix(1.3333 0 0 1.3333 0 1056)" d="m343.58-477.68s60.71 8.52 60.71 8.52c-3.2402-13.73-13.19-22.59-30.15-25.36l-30.56 16.84z" fill="url(#linearGradient83)" /></g></g></svg>

<h2 id="resource-management-is-a-solved-problem-in-ruby-or-is-it">Resource management is a solved problem in Ruby… or is it?</h2>

<p>In C language, you need to call <code class="language-plaintext highlighter-rouge">free()</code> whenever an allocated memory is no
longer used. If you fail to call <code class="language-plaintext highlighter-rouge">free()</code>, you will get out of memory. If you
try to use memory already freed, it results in a hard-to-debug bug and security
vulnerabilities. And the code gets cluttered with so frequent <code class="language-plaintext highlighter-rouge">free()</code> calls.</p>

<p>But such <code class="language-plaintext highlighter-rouge">free()</code> calls are unnecessary on Ruby. Ruby has a garbage collector so
the memory associated with an object that is no longer referenced by anybody
will be freed automatically. Resource management is a solved problem in Ruby…
or is it?</p>

<p>Unfortunately, the garbage collector only works with resources managed by Ruby.
A notable example of resources <em>not</em> managed by Ruby is an external process
created with <code class="language-plaintext highlighter-rouge">spawn</code>. In this post, we discuss why the garbage collector is
<em>not</em> a one-size-fits-for-all approach, and how to <em>safely</em> manage resources
without the garbage collector by illustrating
<a href="https://github.com/HCK-CI/AutoHCK/pull/227">a new resource management mechanism I’m proposing for our Ruby product, AutoHCK</a>.</p>

<h2 id="what-is-autohck">What is AutoHCK?</h2>

<p><a href="https://github.com/HCK-CI/AutoHCK">AutoHCK</a> is a tool to automate Windows driver
testing. AutoHCK runs
<a href="https://learn.microsoft.com/en-us/windows-hardware/test/hlk/">the Windows Hardware Lab Kit (Windows HLK)</a>,
a testing framework for Windows drivers, on QEMU virtual machines. It is
particularly useful when you want to test with para-virtualized devices
implemented in QEMU or when you want to run Windows HLK on a Linux host.</p>

<p>AutoHCK is responsible to prepare files required by test runs, to manage virtual
machines, and to collect test results. These features are implemented in Ruby.</p>

<h2 id="problem-with-garbage-collector">Problem with garbage collector</h2>

<p>As described earlier, resource management is not a solved problem even for Ruby,
which comes with a garbage collector.</p>

<p>The problem with a garbage collector is that it is highly <em>asynchronous</em>. Its
asynchronous nature benefits when managing pure-Ruby objects. For example,
consider of freeing a long linked list of Ruby objects:</p>

<pre><code class="language-Ruby">S = Struct.new(:next)
l = 10000000.times.reduce(S.new) { |sum| S.new(sum) }
</code></pre>

<p>If you naively try to free something like <code class="language-plaintext highlighter-rouge">l</code> on a platform that lacks garbage
collector (e.g. C++ and Rust), it will freeze the process for a while as it will
need 10 million objects at once, but Ruby can do that when it is idle and avoid
freezing.</p>

<fig style="text-align: center">

<svg aria-roledescription="sequence" role="graphics-document document" viewBox="-68 -10 286 465" style="max-width: 100%; padding: 0 25%; box-sizing: border-box" width="100%" id="synchronous" height="100%"><style>@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css");'</style><g><rect class="actor" ry="3" rx="3" height="65" width="150" stroke="#666" fill="#eaeaea" y="379" x="0"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="411.5" x="75"><tspan dy="0" x="75">Application</tspan></text></g><g><line stroke="#999" stroke-width="0.5px" class="200" y2="379" x2="75" y1="5" x1="75" id="actor548"></line><g id="root-548"><rect class="actor" ry="3" rx="3" height="65" width="150" stroke="#666" fill="#eaeaea" y="0" x="0"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="32.5" x="75"><tspan dy="0" x="75">Application</tspan></text></g></g><style>#synchronous{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#synchronous .error-icon{fill:#552222;}#synchronous .error-text{fill:#552222;stroke:#552222;}#synchronous .edge-thickness-normal{stroke-width:2px;}#synchronous .edge-thickness-thick{stroke-width:3.5px;}#synchronous .edge-pattern-solid{stroke-dasharray:0;}#synchronous .edge-pattern-dashed{stroke-dasharray:3;}#synchronous .edge-pattern-dotted{stroke-dasharray:2;}#synchronous .marker{fill:#333333;stroke:#333333;}#synchronous .marker.cross{stroke:#333333;}#synchronous svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#synchronous .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#synchronous text.actor&gt;tspan{fill:black;stroke:none;}#synchronous .actor-line{stroke:grey;}#synchronous .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#synchronous .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#synchronous #arrowhead path{fill:#333;stroke:#333;}#synchronous .sequenceNumber{fill:white;}#synchronous #sequencenumber{fill:#333;}#synchronous #crosshead path{fill:#333;stroke:#333;}#synchronous .messageText{fill:#333;stroke:none;}#synchronous .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#synchronous .labelText,#synchronous .labelText&gt;tspan{fill:black;stroke:none;}#synchronous .loopText,#synchronous .loopText&gt;tspan{fill:black;stroke:none;}#synchronous .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#synchronous .note{stroke:#aaaa33;fill:#fff5ad;}#synchronous .noteText,#synchronous .noteText&gt;tspan{fill:black;stroke:none;}#synchronous .activation0{fill:#f4f4f4;stroke:#666;}#synchronous .activation1{fill:#f4f4f4;stroke:#666;}#synchronous .activation2{fill:#f4f4f4;stroke:#666;}#synchronous .actorPopupMenu{position:absolute;}#synchronous .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#synchronous .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#synchronous .actor-man circle,#synchronous line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#synchronous :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g></g><defs><symbol height="24" width="24" id="computer"><path d="M2 2v13h20v-13h-20zm18 11h-16v-9h16v9zm-10.228 6l.466-1h3.524l.467 1h-4.457zm14.228 3h-24l2-6h2.104l-1.33 4h18.45l-1.297-4h2.073l2 6zm-5-10h-14v-7h14v7z" transform="scale(.5)"></path></symbol></defs><defs><symbol clip-rule="evenodd" fill-rule="evenodd" id="database"><path d="M12.258.001l.256.004.255.005.253.008.251.01.249.012.247.015.246.016.242.019.241.02.239.023.236.024.233.027.231.028.229.031.225.032.223.034.22.036.217.038.214.04.211.041.208.043.205.045.201.046.198.048.194.05.191.051.187.053.183.054.18.056.175.057.172.059.168.06.163.061.16.063.155.064.15.066.074.033.073.033.071.034.07.034.069.035.068.035.067.035.066.035.064.036.064.036.062.036.06.036.06.037.058.037.058.037.055.038.055.038.053.038.052.038.051.039.05.039.048.039.047.039.045.04.044.04.043.04.041.04.04.041.039.041.037.041.036.041.034.041.033.042.032.042.03.042.029.042.027.042.026.043.024.043.023.043.021.043.02.043.018.044.017.043.015.044.013.044.012.044.011.045.009.044.007.045.006.045.004.045.002.045.001.045v17l-.001.045-.002.045-.004.045-.006.045-.007.045-.009.044-.011.045-.012.044-.013.044-.015.044-.017.043-.018.044-.02.043-.021.043-.023.043-.024.043-.026.043-.027.042-.029.042-.03.042-.032.042-.033.042-.034.041-.036.041-.037.041-.039.041-.04.041-.041.04-.043.04-.044.04-.045.04-.047.039-.048.039-.05.039-.051.039-.052.038-.053.038-.055.038-.055.038-.058.037-.058.037-.06.037-.06.036-.062.036-.064.036-.064.036-.066.035-.067.035-.068.035-.069.035-.07.034-.071.034-.073.033-.074.033-.15.066-.155.064-.16.063-.163.061-.168.06-.172.059-.175.057-.18.056-.183.054-.187.053-.191.051-.194.05-.198.048-.201.046-.205.045-.208.043-.211.041-.214.04-.217.038-.22.036-.223.034-.225.032-.229.031-.231.028-.233.027-.236.024-.239.023-.241.02-.242.019-.246.016-.247.015-.249.012-.251.01-.253.008-.255.005-.256.004-.258.001-.258-.001-.256-.004-.255-.005-.253-.008-.251-.01-.249-.012-.247-.015-.245-.016-.243-.019-.241-.02-.238-.023-.236-.024-.234-.027-.231-.028-.228-.031-.226-.032-.223-.034-.22-.036-.217-.038-.214-.04-.211-.041-.208-.043-.204-.045-.201-.046-.198-.048-.195-.05-.19-.051-.187-.053-.184-.054-.179-.056-.176-.057-.172-.059-.167-.06-.164-.061-.159-.063-.155-.064-.151-.066-.074-.033-.072-.033-.072-.034-.07-.034-.069-.035-.068-.035-.067-.035-.066-.035-.064-.036-.063-.036-.062-.036-.061-.036-.06-.037-.058-.037-.057-.037-.056-.038-.055-.038-.053-.038-.052-.038-.051-.039-.049-.039-.049-.039-.046-.039-.046-.04-.044-.04-.043-.04-.041-.04-.04-.041-.039-.041-.037-.041-.036-.041-.034-.041-.033-.042-.032-.042-.03-.042-.029-.042-.027-.042-.026-.043-.024-.043-.023-.043-.021-.043-.02-.043-.018-.044-.017-.043-.015-.044-.013-.044-.012-.044-.011-.045-.009-.044-.007-.045-.006-.045-.004-.045-.002-.045-.001-.045v-17l.001-.045.002-.045.004-.045.006-.045.007-.045.009-.044.011-.045.012-.044.013-.044.015-.044.017-.043.018-.044.02-.043.021-.043.023-.043.024-.043.026-.043.027-.042.029-.042.03-.042.032-.042.033-.042.034-.041.036-.041.037-.041.039-.041.04-.041.041-.04.043-.04.044-.04.046-.04.046-.039.049-.039.049-.039.051-.039.052-.038.053-.038.055-.038.056-.038.057-.037.058-.037.06-.037.061-.036.062-.036.063-.036.064-.036.066-.035.067-.035.068-.035.069-.035.07-.034.072-.034.072-.033.074-.033.151-.066.155-.064.159-.063.164-.061.167-.06.172-.059.176-.057.179-.056.184-.054.187-.053.19-.051.195-.05.198-.048.201-.046.204-.045.208-.043.211-.041.214-.04.217-.038.22-.036.223-.034.226-.032.228-.031.231-.028.234-.027.236-.024.238-.023.241-.02.243-.019.245-.016.247-.015.249-.012.251-.01.253-.008.255-.005.256-.004.258-.001.258.001zm-9.258 20.499v.01l.001.021.003.021.004.022.005.021.006.022.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.023.018.024.019.024.021.024.022.025.023.024.024.025.052.049.056.05.061.051.066.051.07.051.075.051.079.052.084.052.088.052.092.052.097.052.102.051.105.052.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.048.144.049.147.047.152.047.155.047.16.045.163.045.167.043.171.043.176.041.178.041.183.039.187.039.19.037.194.035.197.035.202.033.204.031.209.03.212.029.216.027.219.025.222.024.226.021.23.02.233.018.236.016.24.015.243.012.246.01.249.008.253.005.256.004.259.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.021.224-.024.22-.026.216-.027.212-.028.21-.031.205-.031.202-.034.198-.034.194-.036.191-.037.187-.039.183-.04.179-.04.175-.042.172-.043.168-.044.163-.045.16-.046.155-.046.152-.047.148-.048.143-.049.139-.049.136-.05.131-.05.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.053.083-.051.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.05.023-.024.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.023.01-.022.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.127l-.077.055-.08.053-.083.054-.085.053-.087.052-.09.052-.093.051-.095.05-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.045-.118.044-.12.043-.122.042-.124.042-.126.041-.128.04-.13.04-.132.038-.134.038-.135.037-.138.037-.139.035-.142.035-.143.034-.144.033-.147.032-.148.031-.15.03-.151.03-.153.029-.154.027-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.01-.179.008-.179.008-.181.006-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.006-.179-.008-.179-.008-.178-.01-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.027-.153-.029-.151-.03-.15-.03-.148-.031-.146-.032-.145-.033-.143-.034-.141-.035-.14-.035-.137-.037-.136-.037-.134-.038-.132-.038-.13-.04-.128-.04-.126-.041-.124-.042-.122-.042-.12-.044-.117-.043-.116-.045-.113-.045-.112-.046-.109-.047-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.05-.093-.052-.09-.051-.087-.052-.085-.053-.083-.054-.08-.054-.077-.054v4.127zm0-5.654v.011l.001.021.003.021.004.021.005.022.006.022.007.022.009.022.01.022.011.023.012.023.013.023.015.024.016.023.017.024.018.024.019.024.021.024.022.024.023.025.024.024.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.052.11.051.114.051.119.052.123.05.127.051.131.05.135.049.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.044.171.042.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.022.23.02.233.018.236.016.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.012.241-.015.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.048.139-.05.136-.049.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.051.051-.049.023-.025.023-.024.021-.025.02-.024.019-.024.018-.024.017-.024.015-.023.014-.023.013-.024.012-.022.01-.023.01-.023.008-.022.006-.022.006-.022.004-.021.004-.022.001-.021.001-.021v-4.139l-.077.054-.08.054-.083.054-.085.052-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.044-.118.044-.12.044-.122.042-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.035-.143.033-.144.033-.147.033-.148.031-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.009-.179.009-.179.007-.181.007-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.007-.179-.007-.179-.009-.178-.009-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.031-.146-.033-.145-.033-.143-.033-.141-.035-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.04-.126-.041-.124-.042-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.051-.093-.051-.09-.051-.087-.053-.085-.052-.083-.054-.08-.054-.077-.054v4.139zm0-5.666v.011l.001.02.003.022.004.021.005.022.006.021.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.024.018.023.019.024.021.025.022.024.023.024.024.025.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.051.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.043.171.043.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.021.23.02.233.018.236.017.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.013.241-.014.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.049.139-.049.136-.049.131-.051.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.049.023-.025.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.022.01-.023.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.153l-.077.054-.08.054-.083.053-.085.053-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.048-.105.048-.106.048-.109.046-.111.046-.114.046-.115.044-.118.044-.12.043-.122.043-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.034-.143.034-.144.033-.147.032-.148.032-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.024-.161.024-.162.023-.163.023-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.01-.178.01-.179.009-.179.007-.181.006-.182.006-.182.004-.184.003-.184.001-.185.001-.185-.001-.184-.001-.184-.003-.182-.004-.182-.006-.181-.006-.179-.007-.179-.009-.178-.01-.176-.01-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.023-.162-.023-.161-.024-.159-.024-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.032-.146-.032-.145-.033-.143-.034-.141-.034-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.041-.126-.041-.124-.041-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.048-.105-.048-.102-.048-.1-.05-.097-.049-.095-.051-.093-.051-.09-.052-.087-.052-.085-.053-.083-.053-.08-.054-.077-.054v4.153zm8.74-8.179l-.257.004-.254.005-.25.008-.247.011-.244.012-.241.014-.237.016-.233.018-.231.021-.226.022-.224.023-.22.026-.216.027-.212.028-.21.031-.205.032-.202.033-.198.034-.194.036-.191.038-.187.038-.183.04-.179.041-.175.042-.172.043-.168.043-.163.045-.16.046-.155.046-.152.048-.148.048-.143.048-.139.049-.136.05-.131.05-.126.051-.123.051-.118.051-.114.052-.11.052-.106.052-.101.052-.096.052-.092.052-.088.052-.083.052-.079.052-.074.051-.07.052-.065.051-.06.05-.056.05-.051.05-.023.025-.023.024-.021.024-.02.025-.019.024-.018.024-.017.023-.015.024-.014.023-.013.023-.012.023-.01.023-.01.022-.008.022-.006.023-.006.021-.004.022-.004.021-.001.021-.001.021.001.021.001.021.004.021.004.022.006.021.006.023.008.022.01.022.01.023.012.023.013.023.014.023.015.024.017.023.018.024.019.024.02.025.021.024.023.024.023.025.051.05.056.05.06.05.065.051.07.052.074.051.079.052.083.052.088.052.092.052.096.052.101.052.106.052.11.052.114.052.118.051.123.051.126.051.131.05.136.05.139.049.143.048.148.048.152.048.155.046.16.046.163.045.168.043.172.043.175.042.179.041.183.04.187.038.191.038.194.036.198.034.202.033.205.032.21.031.212.028.216.027.22.026.224.023.226.022.231.021.233.018.237.016.241.014.244.012.247.011.25.008.254.005.257.004.26.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.022.224-.023.22-.026.216-.027.212-.028.21-.031.205-.032.202-.033.198-.034.194-.036.191-.038.187-.038.183-.04.179-.041.175-.042.172-.043.168-.043.163-.045.16-.046.155-.046.152-.048.148-.048.143-.048.139-.049.136-.05.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.05.051-.05.023-.025.023-.024.021-.024.02-.025.019-.024.018-.024.017-.023.015-.024.014-.023.013-.023.012-.023.01-.023.01-.022.008-.022.006-.023.006-.021.004-.022.004-.021.001-.021.001-.021-.001-.021-.001-.021-.004-.021-.004-.022-.006-.021-.006-.023-.008-.022-.01-.022-.01-.023-.012-.023-.013-.023-.014-.023-.015-.024-.017-.023-.018-.024-.019-.024-.02-.025-.021-.024-.023-.024-.023-.025-.051-.05-.056-.05-.06-.05-.065-.051-.07-.052-.074-.051-.079-.052-.083-.052-.088-.052-.092-.052-.096-.052-.101-.052-.106-.052-.11-.052-.114-.052-.118-.051-.123-.051-.126-.051-.131-.05-.136-.05-.139-.049-.143-.048-.148-.048-.152-.048-.155-.046-.16-.046-.163-.045-.168-.043-.172-.043-.175-.042-.179-.041-.183-.04-.187-.038-.191-.038-.194-.036-.198-.034-.202-.033-.205-.032-.21-.031-.212-.028-.216-.027-.22-.026-.224-.023-.226-.022-.231-.021-.233-.018-.237-.016-.241-.014-.244-.012-.247-.011-.25-.008-.254-.005-.257-.004-.26-.001-.26.001z" transform="scale(.5)"></path></symbol></defs><defs><symbol height="24" width="24" id="clock"><path d="M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.848 12.459c.202.038.202.333.001.372-1.907.361-6.045 1.111-6.547 1.111-.719 0-1.301-.582-1.301-1.301 0-.512.77-5.447 1.125-7.445.034-.192.312-.181.343.014l.985 6.238 5.394 1.011z" transform="scale(.5)"></path></symbol></defs><defs><marker orient="auto" markerHeight="12" markerWidth="12" markerUnits="userSpaceOnUse" refY="5" refX="9" id="arrowhead"><path d="M 0 0 L 10 5 L 0 10 z"></path></marker></defs><defs><marker refY="5" refX="4" orient="auto" markerHeight="8" markerWidth="15" id="crosshead"><path d="M 1,2 L 6,7 M 6,2 L 1,7" stroke-width="1pt" style="stroke-dasharray: 0px, 0px;" stroke="#000000" fill="none"></path></marker></defs><defs><marker orient="auto" markerHeight="28" markerWidth="20" refY="7" refX="18" id="filled-head"><path d="M 18,7 L9,13 L14,7 L9,1 Z"></path></marker></defs><defs><marker orient="auto" markerHeight="40" markerWidth="60" refY="15" refX="15" id="sequencenumber"><circle r="6" cy="15" cx="15"></circle></marker></defs><g><rect class="note" ry="0" rx="0" height="39" width="186" stroke="#666" fill="#EDF2AE" y="75" x="-18"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="80" x="75"><tspan x="75">Delete reference to "l"</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="150" stroke="#666" fill="#EDF2AE" y="124" x="0"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="129" x="75"><tspan x="75">Free an object</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="150" stroke="#666" fill="#EDF2AE" y="173" x="0"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="178" x="75"><tspan x="75">Free an object</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="150" stroke="#666" fill="#EDF2AE" y="222" x="0"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="227" x="75"><tspan x="75">Free an object</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="150" stroke="#666" fill="#EDF2AE" y="271" x="0"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="276" x="75"><tspan x="75">Free an object</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="150" stroke="#666" fill="#EDF2AE" y="320" x="0"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="325" x="75"><tspan x="75">...</tspan></text></g></svg>
<figcaption>Synchronous resource deallocation (naive C++/Rust)</figcaption>
</fig>

<fig style="text-align: center">

<svg aria-roledescription="sequence" role="graphics-document document" viewBox="-87.5 -10 493.5 622" style="max-width: 100%;" width="100%" id="asynchronous" height="100%"><title>Asynchronous resource deallocation by Ruby garbage collector</title><style>@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css");'</style><g><rect class="actor" ry="3" rx="3" height="65" width="156" stroke="#666" fill="#eaeaea" y="536" x="200"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="568.5" x="278"><tspan dy="0" x="278">Garbage Collector</tspan></text></g><g><rect class="actor" ry="3" rx="3" height="65" width="150" stroke="#666" fill="#eaeaea" y="536" x="0"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="568.5" x="75"><tspan dy="0" x="75">Application</tspan></text></g><g><line stroke="#999" stroke-width="0.5px" class="200" y2="536" x2="278" y1="5" x1="278" id="actor554"></line><g id="root-554"><rect class="actor" ry="3" rx="3" height="65" width="156" stroke="#666" fill="#eaeaea" y="0" x="200"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="32.5" x="278"><tspan dy="0" x="278">Garbage Collector</tspan></text></g></g><g><line stroke="#999" stroke-width="0.5px" class="200" y2="536" x2="75" y1="5" x1="75" id="actor553"></line><g id="root-553"><rect class="actor" ry="3" rx="3" height="65" width="150" stroke="#666" fill="#eaeaea" y="0" x="0"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="32.5" x="75"><tspan dy="0" x="75">Application</tspan></text></g></g><style>#asynchronous{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#asynchronous .error-icon{fill:#552222;}#asynchronous .error-text{fill:#552222;stroke:#552222;}#asynchronous .edge-thickness-normal{stroke-width:2px;}#asynchronous .edge-thickness-thick{stroke-width:3.5px;}#asynchronous .edge-pattern-solid{stroke-dasharray:0;}#asynchronous .edge-pattern-dashed{stroke-dasharray:3;}#asynchronous .edge-pattern-dotted{stroke-dasharray:2;}#asynchronous .marker{fill:#333333;stroke:#333333;}#asynchronous .marker.cross{stroke:#333333;}#asynchronous svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#asynchronous .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#asynchronous text.actor&gt;tspan{fill:black;stroke:none;}#asynchronous .actor-line{stroke:grey;}#asynchronous .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#asynchronous .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#asynchronous #arrowhead path{fill:#333;stroke:#333;}#asynchronous .sequenceNumber{fill:white;}#asynchronous #sequencenumber{fill:#333;}#asynchronous #crosshead path{fill:#333;stroke:#333;}#asynchronous .messageText{fill:#333;stroke:none;}#asynchronous .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#asynchronous .labelText,#asynchronous .labelText&gt;tspan{fill:black;stroke:none;}#asynchronous .loopText,#asynchronous .loopText&gt;tspan{fill:black;stroke:none;}#asynchronous .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#asynchronous .note{stroke:#aaaa33;fill:#fff5ad;}#asynchronous .noteText,#asynchronous .noteText&gt;tspan{fill:black;stroke:none;}#asynchronous .activation0{fill:#f4f4f4;stroke:#666;}#asynchronous .activation1{fill:#f4f4f4;stroke:#666;}#asynchronous .activation2{fill:#f4f4f4;stroke:#666;}#asynchronous .actorPopupMenu{position:absolute;}#asynchronous .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#asynchronous .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#asynchronous .actor-man circle,#asynchronous line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#asynchronous :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g></g><defs><symbol height="24" width="24" id="computer"><path d="M2 2v13h20v-13h-20zm18 11h-16v-9h16v9zm-10.228 6l.466-1h3.524l.467 1h-4.457zm14.228 3h-24l2-6h2.104l-1.33 4h18.45l-1.297-4h2.073l2 6zm-5-10h-14v-7h14v7z" transform="scale(.5)"></path></symbol></defs><defs><symbol clip-rule="evenodd" fill-rule="evenodd" id="database"><path d="M12.258.001l.256.004.255.005.253.008.251.01.249.012.247.015.246.016.242.019.241.02.239.023.236.024.233.027.231.028.229.031.225.032.223.034.22.036.217.038.214.04.211.041.208.043.205.045.201.046.198.048.194.05.191.051.187.053.183.054.18.056.175.057.172.059.168.06.163.061.16.063.155.064.15.066.074.033.073.033.071.034.07.034.069.035.068.035.067.035.066.035.064.036.064.036.062.036.06.036.06.037.058.037.058.037.055.038.055.038.053.038.052.038.051.039.05.039.048.039.047.039.045.04.044.04.043.04.041.04.04.041.039.041.037.041.036.041.034.041.033.042.032.042.03.042.029.042.027.042.026.043.024.043.023.043.021.043.02.043.018.044.017.043.015.044.013.044.012.044.011.045.009.044.007.045.006.045.004.045.002.045.001.045v17l-.001.045-.002.045-.004.045-.006.045-.007.045-.009.044-.011.045-.012.044-.013.044-.015.044-.017.043-.018.044-.02.043-.021.043-.023.043-.024.043-.026.043-.027.042-.029.042-.03.042-.032.042-.033.042-.034.041-.036.041-.037.041-.039.041-.04.041-.041.04-.043.04-.044.04-.045.04-.047.039-.048.039-.05.039-.051.039-.052.038-.053.038-.055.038-.055.038-.058.037-.058.037-.06.037-.06.036-.062.036-.064.036-.064.036-.066.035-.067.035-.068.035-.069.035-.07.034-.071.034-.073.033-.074.033-.15.066-.155.064-.16.063-.163.061-.168.06-.172.059-.175.057-.18.056-.183.054-.187.053-.191.051-.194.05-.198.048-.201.046-.205.045-.208.043-.211.041-.214.04-.217.038-.22.036-.223.034-.225.032-.229.031-.231.028-.233.027-.236.024-.239.023-.241.02-.242.019-.246.016-.247.015-.249.012-.251.01-.253.008-.255.005-.256.004-.258.001-.258-.001-.256-.004-.255-.005-.253-.008-.251-.01-.249-.012-.247-.015-.245-.016-.243-.019-.241-.02-.238-.023-.236-.024-.234-.027-.231-.028-.228-.031-.226-.032-.223-.034-.22-.036-.217-.038-.214-.04-.211-.041-.208-.043-.204-.045-.201-.046-.198-.048-.195-.05-.19-.051-.187-.053-.184-.054-.179-.056-.176-.057-.172-.059-.167-.06-.164-.061-.159-.063-.155-.064-.151-.066-.074-.033-.072-.033-.072-.034-.07-.034-.069-.035-.068-.035-.067-.035-.066-.035-.064-.036-.063-.036-.062-.036-.061-.036-.06-.037-.058-.037-.057-.037-.056-.038-.055-.038-.053-.038-.052-.038-.051-.039-.049-.039-.049-.039-.046-.039-.046-.04-.044-.04-.043-.04-.041-.04-.04-.041-.039-.041-.037-.041-.036-.041-.034-.041-.033-.042-.032-.042-.03-.042-.029-.042-.027-.042-.026-.043-.024-.043-.023-.043-.021-.043-.02-.043-.018-.044-.017-.043-.015-.044-.013-.044-.012-.044-.011-.045-.009-.044-.007-.045-.006-.045-.004-.045-.002-.045-.001-.045v-17l.001-.045.002-.045.004-.045.006-.045.007-.045.009-.044.011-.045.012-.044.013-.044.015-.044.017-.043.018-.044.02-.043.021-.043.023-.043.024-.043.026-.043.027-.042.029-.042.03-.042.032-.042.033-.042.034-.041.036-.041.037-.041.039-.041.04-.041.041-.04.043-.04.044-.04.046-.04.046-.039.049-.039.049-.039.051-.039.052-.038.053-.038.055-.038.056-.038.057-.037.058-.037.06-.037.061-.036.062-.036.063-.036.064-.036.066-.035.067-.035.068-.035.069-.035.07-.034.072-.034.072-.033.074-.033.151-.066.155-.064.159-.063.164-.061.167-.06.172-.059.176-.057.179-.056.184-.054.187-.053.19-.051.195-.05.198-.048.201-.046.204-.045.208-.043.211-.041.214-.04.217-.038.22-.036.223-.034.226-.032.228-.031.231-.028.234-.027.236-.024.238-.023.241-.02.243-.019.245-.016.247-.015.249-.012.251-.01.253-.008.255-.005.256-.004.258-.001.258.001zm-9.258 20.499v.01l.001.021.003.021.004.022.005.021.006.022.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.023.018.024.019.024.021.024.022.025.023.024.024.025.052.049.056.05.061.051.066.051.07.051.075.051.079.052.084.052.088.052.092.052.097.052.102.051.105.052.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.048.144.049.147.047.152.047.155.047.16.045.163.045.167.043.171.043.176.041.178.041.183.039.187.039.19.037.194.035.197.035.202.033.204.031.209.03.212.029.216.027.219.025.222.024.226.021.23.02.233.018.236.016.24.015.243.012.246.01.249.008.253.005.256.004.259.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.021.224-.024.22-.026.216-.027.212-.028.21-.031.205-.031.202-.034.198-.034.194-.036.191-.037.187-.039.183-.04.179-.04.175-.042.172-.043.168-.044.163-.045.16-.046.155-.046.152-.047.148-.048.143-.049.139-.049.136-.05.131-.05.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.053.083-.051.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.05.023-.024.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.023.01-.022.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.127l-.077.055-.08.053-.083.054-.085.053-.087.052-.09.052-.093.051-.095.05-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.045-.118.044-.12.043-.122.042-.124.042-.126.041-.128.04-.13.04-.132.038-.134.038-.135.037-.138.037-.139.035-.142.035-.143.034-.144.033-.147.032-.148.031-.15.03-.151.03-.153.029-.154.027-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.01-.179.008-.179.008-.181.006-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.006-.179-.008-.179-.008-.178-.01-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.027-.153-.029-.151-.03-.15-.03-.148-.031-.146-.032-.145-.033-.143-.034-.141-.035-.14-.035-.137-.037-.136-.037-.134-.038-.132-.038-.13-.04-.128-.04-.126-.041-.124-.042-.122-.042-.12-.044-.117-.043-.116-.045-.113-.045-.112-.046-.109-.047-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.05-.093-.052-.09-.051-.087-.052-.085-.053-.083-.054-.08-.054-.077-.054v4.127zm0-5.654v.011l.001.021.003.021.004.021.005.022.006.022.007.022.009.022.01.022.011.023.012.023.013.023.015.024.016.023.017.024.018.024.019.024.021.024.022.024.023.025.024.024.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.052.11.051.114.051.119.052.123.05.127.051.131.05.135.049.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.044.171.042.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.022.23.02.233.018.236.016.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.012.241-.015.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.048.139-.05.136-.049.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.051.051-.049.023-.025.023-.024.021-.025.02-.024.019-.024.018-.024.017-.024.015-.023.014-.023.013-.024.012-.022.01-.023.01-.023.008-.022.006-.022.006-.022.004-.021.004-.022.001-.021.001-.021v-4.139l-.077.054-.08.054-.083.054-.085.052-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.044-.118.044-.12.044-.122.042-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.035-.143.033-.144.033-.147.033-.148.031-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.009-.179.009-.179.007-.181.007-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.007-.179-.007-.179-.009-.178-.009-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.031-.146-.033-.145-.033-.143-.033-.141-.035-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.04-.126-.041-.124-.042-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.051-.093-.051-.09-.051-.087-.053-.085-.052-.083-.054-.08-.054-.077-.054v4.139zm0-5.666v.011l.001.02.003.022.004.021.005.022.006.021.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.024.018.023.019.024.021.025.022.024.023.024.024.025.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.051.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.043.171.043.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.021.23.02.233.018.236.017.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.013.241-.014.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.049.139-.049.136-.049.131-.051.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.049.023-.025.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.022.01-.023.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.153l-.077.054-.08.054-.083.053-.085.053-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.048-.105.048-.106.048-.109.046-.111.046-.114.046-.115.044-.118.044-.12.043-.122.043-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.034-.143.034-.144.033-.147.032-.148.032-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.024-.161.024-.162.023-.163.023-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.01-.178.01-.179.009-.179.007-.181.006-.182.006-.182.004-.184.003-.184.001-.185.001-.185-.001-.184-.001-.184-.003-.182-.004-.182-.006-.181-.006-.179-.007-.179-.009-.178-.01-.176-.01-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.023-.162-.023-.161-.024-.159-.024-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.032-.146-.032-.145-.033-.143-.034-.141-.034-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.041-.126-.041-.124-.041-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.048-.105-.048-.102-.048-.1-.05-.097-.049-.095-.051-.093-.051-.09-.052-.087-.052-.085-.053-.083-.053-.08-.054-.077-.054v4.153zm8.74-8.179l-.257.004-.254.005-.25.008-.247.011-.244.012-.241.014-.237.016-.233.018-.231.021-.226.022-.224.023-.22.026-.216.027-.212.028-.21.031-.205.032-.202.033-.198.034-.194.036-.191.038-.187.038-.183.04-.179.041-.175.042-.172.043-.168.043-.163.045-.16.046-.155.046-.152.048-.148.048-.143.048-.139.049-.136.05-.131.05-.126.051-.123.051-.118.051-.114.052-.11.052-.106.052-.101.052-.096.052-.092.052-.088.052-.083.052-.079.052-.074.051-.07.052-.065.051-.06.05-.056.05-.051.05-.023.025-.023.024-.021.024-.02.025-.019.024-.018.024-.017.023-.015.024-.014.023-.013.023-.012.023-.01.023-.01.022-.008.022-.006.023-.006.021-.004.022-.004.021-.001.021-.001.021.001.021.001.021.004.021.004.022.006.021.006.023.008.022.01.022.01.023.012.023.013.023.014.023.015.024.017.023.018.024.019.024.02.025.021.024.023.024.023.025.051.05.056.05.06.05.065.051.07.052.074.051.079.052.083.052.088.052.092.052.096.052.101.052.106.052.11.052.114.052.118.051.123.051.126.051.131.05.136.05.139.049.143.048.148.048.152.048.155.046.16.046.163.045.168.043.172.043.175.042.179.041.183.04.187.038.191.038.194.036.198.034.202.033.205.032.21.031.212.028.216.027.22.026.224.023.226.022.231.021.233.018.237.016.241.014.244.012.247.011.25.008.254.005.257.004.26.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.022.224-.023.22-.026.216-.027.212-.028.21-.031.205-.032.202-.033.198-.034.194-.036.191-.038.187-.038.183-.04.179-.041.175-.042.172-.043.168-.043.163-.045.16-.046.155-.046.152-.048.148-.048.143-.048.139-.049.136-.05.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.05.051-.05.023-.025.023-.024.021-.024.02-.025.019-.024.018-.024.017-.023.015-.024.014-.023.013-.023.012-.023.01-.023.01-.022.008-.022.006-.023.006-.021.004-.022.004-.021.001-.021.001-.021-.001-.021-.001-.021-.004-.021-.004-.022-.006-.021-.006-.023-.008-.022-.01-.022-.01-.023-.012-.023-.013-.023-.014-.023-.015-.024-.017-.023-.018-.024-.019-.024-.02-.025-.021-.024-.023-.024-.023-.025-.051-.05-.056-.05-.06-.05-.065-.051-.07-.052-.074-.051-.079-.052-.083-.052-.088-.052-.092-.052-.096-.052-.101-.052-.106-.052-.11-.052-.114-.052-.118-.051-.123-.051-.126-.051-.131-.05-.136-.05-.139-.049-.143-.048-.148-.048-.152-.048-.155-.046-.16-.046-.163-.045-.168-.043-.172-.043-.175-.042-.179-.041-.183-.04-.187-.038-.191-.038-.194-.036-.198-.034-.202-.033-.205-.032-.21-.031-.212-.028-.216-.027-.22-.026-.224-.023-.226-.022-.231-.021-.233-.018-.237-.016-.241-.014-.244-.012-.247-.011-.25-.008-.254-.005-.257-.004-.26-.001-.26.001z" transform="scale(.5)"></path></symbol></defs><defs><symbol height="24" width="24" id="clock"><path d="M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.848 12.459c.202.038.202.333.001.372-1.907.361-6.045 1.111-6.547 1.111-.719 0-1.301-.582-1.301-1.301 0-.512.77-5.447 1.125-7.445.034-.192.312-.181.343.014l.985 6.238 5.394 1.011z" transform="scale(.5)"></path></symbol></defs><defs><marker orient="auto" markerHeight="12" markerWidth="12" markerUnits="userSpaceOnUse" refY="5" refX="9" id="arrowhead"><path d="M 0 0 L 10 5 L 0 10 z"></path></marker></defs><defs><marker refY="5" refX="4" orient="auto" markerHeight="8" markerWidth="15" id="crosshead"><path d="M 1,2 L 6,7 M 6,2 L 1,7" stroke-width="1pt" style="stroke-dasharray: 0px, 0px;" stroke="#000000" fill="none"></path></marker></defs><defs><marker orient="auto" markerHeight="28" markerWidth="20" refY="7" refX="18" id="filled-head"><path d="M 18,7 L9,13 L14,7 L9,1 Z"></path></marker></defs><defs><marker orient="auto" markerHeight="40" markerWidth="60" refY="15" refX="15" id="sequencenumber"><circle r="6" cy="15" cx="15"></circle></marker></defs><g><rect class="note" ry="0" rx="0" height="39" width="186" stroke="#666" fill="#EDF2AE" y="75" x="-18"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="80" x="75"><tspan x="75">Delete reference to "l"</tspan></text></g><g><rect class="activation0" ry="0" rx="0" height="400" width="10" stroke="#666" fill="#EDF2AE" y="116" x="70"></rect></g><g><rect class="note" ry="0" rx="0" height="39" width="225" stroke="#666" fill="#EDF2AE" y="124" x="-37.5"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="129" x="75"><tspan x="75">Start another useful work...</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="156" stroke="#666" fill="#EDF2AE" y="281" x="200"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="286" x="278"><tspan x="278">Free an object</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="156" stroke="#666" fill="#EDF2AE" y="330" x="200"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="335" x="278"><tspan x="278">Free an object</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="156" stroke="#666" fill="#EDF2AE" y="379" x="200"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="384" x="278"><tspan x="278">Free an object</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="156" stroke="#666" fill="#EDF2AE" y="428" x="200"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="433" x="278"><tspan x="278">Free an object</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="156" stroke="#666" fill="#EDF2AE" y="477" x="200"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="482" x="278"><tspan x="278">...</tspan></text></g><text dy="1em" class="messageText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="178" x="179">Inspect memory</text><line marker-end="url(#arrowhead)" style="fill: none;" stroke="none" stroke-width="2" class="messageLine0" y2="217" x2="80" y1="217" x1="278"></line><text dy="1em" class="messageText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="232" x="179">Retrieve stale "l"</text><line marker-end="url(#arrowhead)" style="fill: none;" stroke="none" stroke-width="2" class="messageLine0" y2="271" x2="278" y1="271" x1="80"></line></svg>
<figcaption>
Asynchronous resource deallocation by Ruby garbage collector
</figcaption>
</fig>

<p>However, it relies on the fact that there is plenty of resources available;
nobody cares even if the garbage collector increases the memory usage by a few
megabytes. It is untrue for scarce resources. Such an example in AutoHCK is
access to a disk image. AutoHCK sometimes performs a sequential run of two QEMU
processes using a disk image; the earlier one sets up a virtual machine and the
later one does the actual work. It will corrupt the disk image if the later
reads it while the earlier is still writing. This means only one virtual machine
can use a disk image at a time so access to the image is very scarce. In such a
case, <em>synchronous</em> resource management is mandatory, and a garbage collector is
a poor option for that.</p>

<fig style="text-align: center">

<svg aria-roledescription="sequence" role="graphics-document document" viewBox="-161 -10 724.5 505" style="max-width: 100%;" width="100%" id="hazard" height="100%"><title>Asynchronous resource deallocation with mutually exclusive access hazard (red)</title><style>@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css");'</style><rect class="rect" height="275" width="544.5" fill="rgb(249, 117, 131)" y="124" x="-31"></rect><g><rect class="actor" ry="3" rx="3" height="65" width="156" stroke="#666" fill="#eaeaea" y="419" x="330"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="451.5" x="408"><tspan dy="0" x="408">Garbage Collector</tspan></text></g><g><rect class="actor" ry="3" rx="3" height="65" width="150" stroke="#666" fill="#eaeaea" y="419" x="0"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="451.5" x="75"><tspan dy="0" x="75">Application</tspan></text></g><g><line stroke="#999" stroke-width="0.5px" class="200" y2="419" x2="408" y1="5" x1="408" id="actor581"></line><g id="root-581"><rect class="actor" ry="3" rx="3" height="65" width="156" stroke="#666" fill="#eaeaea" y="0" x="330"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="32.5" x="408"><tspan dy="0" x="408">Garbage Collector</tspan></text></g></g><g><line stroke="#999" stroke-width="0.5px" class="200" y2="419" x2="75" y1="5" x1="75" id="actor580"></line><g id="root-580"><rect class="actor" ry="3" rx="3" height="65" width="150" stroke="#666" fill="#eaeaea" y="0" x="0"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="32.5" x="75"><tspan dy="0" x="75">Application</tspan></text></g></g><style>#hazard{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#hazard .error-icon{fill:#552222;}#hazard .error-text{fill:#552222;stroke:#552222;}#hazard .edge-thickness-normal{stroke-width:2px;}#hazard .edge-thickness-thick{stroke-width:3.5px;}#hazard .edge-pattern-solid{stroke-dasharray:0;}#hazard .edge-pattern-dashed{stroke-dasharray:3;}#hazard .edge-pattern-dotted{stroke-dasharray:2;}#hazard .marker{fill:#333333;stroke:#333333;}#hazard .marker.cross{stroke:#333333;}#hazard svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#hazard .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#hazard text.actor&gt;tspan{fill:black;stroke:none;}#hazard .actor-line{stroke:grey;}#hazard .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#hazard .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#hazard #arrowhead path{fill:#333;stroke:#333;}#hazard .sequenceNumber{fill:white;}#hazard #sequencenumber{fill:#333;}#hazard #crosshead path{fill:#333;stroke:#333;}#hazard .messageText{fill:#333;stroke:none;}#hazard .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#hazard .labelText,#hazard .labelText&gt;tspan{fill:black;stroke:none;}#hazard .loopText,#hazard .loopText&gt;tspan{fill:black;stroke:none;}#hazard .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#hazard .note{stroke:#aaaa33;fill:#fff5ad;}#hazard .noteText,#hazard .noteText&gt;tspan{fill:black;stroke:none;}#hazard .activation0{fill:#f4f4f4;stroke:#666;}#hazard .activation1{fill:#f4f4f4;stroke:#666;}#hazard .activation2{fill:#f4f4f4;stroke:#666;}#hazard .actorPopupMenu{position:absolute;}#hazard .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#hazard .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#hazard .actor-man circle,#hazard line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#hazard :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g></g><defs><symbol height="24" width="24" id="computer"><path d="M2 2v13h20v-13h-20zm18 11h-16v-9h16v9zm-10.228 6l.466-1h3.524l.467 1h-4.457zm14.228 3h-24l2-6h2.104l-1.33 4h18.45l-1.297-4h2.073l2 6zm-5-10h-14v-7h14v7z" transform="scale(.5)"></path></symbol></defs><defs><symbol clip-rule="evenodd" fill-rule="evenodd" id="database"><path d="M12.258.001l.256.004.255.005.253.008.251.01.249.012.247.015.246.016.242.019.241.02.239.023.236.024.233.027.231.028.229.031.225.032.223.034.22.036.217.038.214.04.211.041.208.043.205.045.201.046.198.048.194.05.191.051.187.053.183.054.18.056.175.057.172.059.168.06.163.061.16.063.155.064.15.066.074.033.073.033.071.034.07.034.069.035.068.035.067.035.066.035.064.036.064.036.062.036.06.036.06.037.058.037.058.037.055.038.055.038.053.038.052.038.051.039.05.039.048.039.047.039.045.04.044.04.043.04.041.04.04.041.039.041.037.041.036.041.034.041.033.042.032.042.03.042.029.042.027.042.026.043.024.043.023.043.021.043.02.043.018.044.017.043.015.044.013.044.012.044.011.045.009.044.007.045.006.045.004.045.002.045.001.045v17l-.001.045-.002.045-.004.045-.006.045-.007.045-.009.044-.011.045-.012.044-.013.044-.015.044-.017.043-.018.044-.02.043-.021.043-.023.043-.024.043-.026.043-.027.042-.029.042-.03.042-.032.042-.033.042-.034.041-.036.041-.037.041-.039.041-.04.041-.041.04-.043.04-.044.04-.045.04-.047.039-.048.039-.05.039-.051.039-.052.038-.053.038-.055.038-.055.038-.058.037-.058.037-.06.037-.06.036-.062.036-.064.036-.064.036-.066.035-.067.035-.068.035-.069.035-.07.034-.071.034-.073.033-.074.033-.15.066-.155.064-.16.063-.163.061-.168.06-.172.059-.175.057-.18.056-.183.054-.187.053-.191.051-.194.05-.198.048-.201.046-.205.045-.208.043-.211.041-.214.04-.217.038-.22.036-.223.034-.225.032-.229.031-.231.028-.233.027-.236.024-.239.023-.241.02-.242.019-.246.016-.247.015-.249.012-.251.01-.253.008-.255.005-.256.004-.258.001-.258-.001-.256-.004-.255-.005-.253-.008-.251-.01-.249-.012-.247-.015-.245-.016-.243-.019-.241-.02-.238-.023-.236-.024-.234-.027-.231-.028-.228-.031-.226-.032-.223-.034-.22-.036-.217-.038-.214-.04-.211-.041-.208-.043-.204-.045-.201-.046-.198-.048-.195-.05-.19-.051-.187-.053-.184-.054-.179-.056-.176-.057-.172-.059-.167-.06-.164-.061-.159-.063-.155-.064-.151-.066-.074-.033-.072-.033-.072-.034-.07-.034-.069-.035-.068-.035-.067-.035-.066-.035-.064-.036-.063-.036-.062-.036-.061-.036-.06-.037-.058-.037-.057-.037-.056-.038-.055-.038-.053-.038-.052-.038-.051-.039-.049-.039-.049-.039-.046-.039-.046-.04-.044-.04-.043-.04-.041-.04-.04-.041-.039-.041-.037-.041-.036-.041-.034-.041-.033-.042-.032-.042-.03-.042-.029-.042-.027-.042-.026-.043-.024-.043-.023-.043-.021-.043-.02-.043-.018-.044-.017-.043-.015-.044-.013-.044-.012-.044-.011-.045-.009-.044-.007-.045-.006-.045-.004-.045-.002-.045-.001-.045v-17l.001-.045.002-.045.004-.045.006-.045.007-.045.009-.044.011-.045.012-.044.013-.044.015-.044.017-.043.018-.044.02-.043.021-.043.023-.043.024-.043.026-.043.027-.042.029-.042.03-.042.032-.042.033-.042.034-.041.036-.041.037-.041.039-.041.04-.041.041-.04.043-.04.044-.04.046-.04.046-.039.049-.039.049-.039.051-.039.052-.038.053-.038.055-.038.056-.038.057-.037.058-.037.06-.037.061-.036.062-.036.063-.036.064-.036.066-.035.067-.035.068-.035.069-.035.07-.034.072-.034.072-.033.074-.033.151-.066.155-.064.159-.063.164-.061.167-.06.172-.059.176-.057.179-.056.184-.054.187-.053.19-.051.195-.05.198-.048.201-.046.204-.045.208-.043.211-.041.214-.04.217-.038.22-.036.223-.034.226-.032.228-.031.231-.028.234-.027.236-.024.238-.023.241-.02.243-.019.245-.016.247-.015.249-.012.251-.01.253-.008.255-.005.256-.004.258-.001.258.001zm-9.258 20.499v.01l.001.021.003.021.004.022.005.021.006.022.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.023.018.024.019.024.021.024.022.025.023.024.024.025.052.049.056.05.061.051.066.051.07.051.075.051.079.052.084.052.088.052.092.052.097.052.102.051.105.052.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.048.144.049.147.047.152.047.155.047.16.045.163.045.167.043.171.043.176.041.178.041.183.039.187.039.19.037.194.035.197.035.202.033.204.031.209.03.212.029.216.027.219.025.222.024.226.021.23.02.233.018.236.016.24.015.243.012.246.01.249.008.253.005.256.004.259.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.021.224-.024.22-.026.216-.027.212-.028.21-.031.205-.031.202-.034.198-.034.194-.036.191-.037.187-.039.183-.04.179-.04.175-.042.172-.043.168-.044.163-.045.16-.046.155-.046.152-.047.148-.048.143-.049.139-.049.136-.05.131-.05.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.053.083-.051.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.05.023-.024.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.023.01-.022.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.127l-.077.055-.08.053-.083.054-.085.053-.087.052-.09.052-.093.051-.095.05-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.045-.118.044-.12.043-.122.042-.124.042-.126.041-.128.04-.13.04-.132.038-.134.038-.135.037-.138.037-.139.035-.142.035-.143.034-.144.033-.147.032-.148.031-.15.03-.151.03-.153.029-.154.027-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.01-.179.008-.179.008-.181.006-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.006-.179-.008-.179-.008-.178-.01-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.027-.153-.029-.151-.03-.15-.03-.148-.031-.146-.032-.145-.033-.143-.034-.141-.035-.14-.035-.137-.037-.136-.037-.134-.038-.132-.038-.13-.04-.128-.04-.126-.041-.124-.042-.122-.042-.12-.044-.117-.043-.116-.045-.113-.045-.112-.046-.109-.047-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.05-.093-.052-.09-.051-.087-.052-.085-.053-.083-.054-.08-.054-.077-.054v4.127zm0-5.654v.011l.001.021.003.021.004.021.005.022.006.022.007.022.009.022.01.022.011.023.012.023.013.023.015.024.016.023.017.024.018.024.019.024.021.024.022.024.023.025.024.024.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.052.11.051.114.051.119.052.123.05.127.051.131.05.135.049.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.044.171.042.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.022.23.02.233.018.236.016.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.012.241-.015.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.048.139-.05.136-.049.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.051.051-.049.023-.025.023-.024.021-.025.02-.024.019-.024.018-.024.017-.024.015-.023.014-.023.013-.024.012-.022.01-.023.01-.023.008-.022.006-.022.006-.022.004-.021.004-.022.001-.021.001-.021v-4.139l-.077.054-.08.054-.083.054-.085.052-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.044-.118.044-.12.044-.122.042-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.035-.143.033-.144.033-.147.033-.148.031-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.009-.179.009-.179.007-.181.007-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.007-.179-.007-.179-.009-.178-.009-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.031-.146-.033-.145-.033-.143-.033-.141-.035-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.04-.126-.041-.124-.042-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.051-.093-.051-.09-.051-.087-.053-.085-.052-.083-.054-.08-.054-.077-.054v4.139zm0-5.666v.011l.001.02.003.022.004.021.005.022.006.021.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.024.018.023.019.024.021.025.022.024.023.024.024.025.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.051.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.043.171.043.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.021.23.02.233.018.236.017.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.013.241-.014.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.049.139-.049.136-.049.131-.051.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.049.023-.025.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.022.01-.023.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.153l-.077.054-.08.054-.083.053-.085.053-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.048-.105.048-.106.048-.109.046-.111.046-.114.046-.115.044-.118.044-.12.043-.122.043-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.034-.143.034-.144.033-.147.032-.148.032-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.024-.161.024-.162.023-.163.023-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.01-.178.01-.179.009-.179.007-.181.006-.182.006-.182.004-.184.003-.184.001-.185.001-.185-.001-.184-.001-.184-.003-.182-.004-.182-.006-.181-.006-.179-.007-.179-.009-.178-.01-.176-.01-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.023-.162-.023-.161-.024-.159-.024-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.032-.146-.032-.145-.033-.143-.034-.141-.034-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.041-.126-.041-.124-.041-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.048-.105-.048-.102-.048-.1-.05-.097-.049-.095-.051-.093-.051-.09-.052-.087-.052-.085-.053-.083-.053-.08-.054-.077-.054v4.153zm8.74-8.179l-.257.004-.254.005-.25.008-.247.011-.244.012-.241.014-.237.016-.233.018-.231.021-.226.022-.224.023-.22.026-.216.027-.212.028-.21.031-.205.032-.202.033-.198.034-.194.036-.191.038-.187.038-.183.04-.179.041-.175.042-.172.043-.168.043-.163.045-.16.046-.155.046-.152.048-.148.048-.143.048-.139.049-.136.05-.131.05-.126.051-.123.051-.118.051-.114.052-.11.052-.106.052-.101.052-.096.052-.092.052-.088.052-.083.052-.079.052-.074.051-.07.052-.065.051-.06.05-.056.05-.051.05-.023.025-.023.024-.021.024-.02.025-.019.024-.018.024-.017.023-.015.024-.014.023-.013.023-.012.023-.01.023-.01.022-.008.022-.006.023-.006.021-.004.022-.004.021-.001.021-.001.021.001.021.001.021.004.021.004.022.006.021.006.023.008.022.01.022.01.023.012.023.013.023.014.023.015.024.017.023.018.024.019.024.02.025.021.024.023.024.023.025.051.05.056.05.06.05.065.051.07.052.074.051.079.052.083.052.088.052.092.052.096.052.101.052.106.052.11.052.114.052.118.051.123.051.126.051.131.05.136.05.139.049.143.048.148.048.152.048.155.046.16.046.163.045.168.043.172.043.175.042.179.041.183.04.187.038.191.038.194.036.198.034.202.033.205.032.21.031.212.028.216.027.22.026.224.023.226.022.231.021.233.018.237.016.241.014.244.012.247.011.25.008.254.005.257.004.26.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.022.224-.023.22-.026.216-.027.212-.028.21-.031.205-.032.202-.033.198-.034.194-.036.191-.038.187-.038.183-.04.179-.041.175-.042.172-.043.168-.043.163-.045.16-.046.155-.046.152-.048.148-.048.143-.048.139-.049.136-.05.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.05.051-.05.023-.025.023-.024.021-.024.02-.025.019-.024.018-.024.017-.023.015-.024.014-.023.013-.023.012-.023.01-.023.01-.022.008-.022.006-.023.006-.021.004-.022.004-.021.001-.021.001-.021-.001-.021-.001-.021-.004-.021-.004-.022-.006-.021-.006-.023-.008-.022-.01-.022-.01-.023-.012-.023-.013-.023-.014-.023-.015-.024-.017-.023-.018-.024-.019-.024-.02-.025-.021-.024-.023-.024-.023-.025-.051-.05-.056-.05-.06-.05-.065-.051-.07-.052-.074-.051-.079-.052-.083-.052-.088-.052-.092-.052-.096-.052-.101-.052-.106-.052-.11-.052-.114-.052-.118-.051-.123-.051-.126-.051-.131-.05-.136-.05-.139-.049-.143-.048-.148-.048-.152-.048-.155-.046-.16-.046-.163-.045-.168-.043-.172-.043-.175-.042-.179-.041-.183-.04-.187-.038-.191-.038-.194-.036-.198-.034-.202-.033-.205-.032-.21-.031-.212-.028-.216-.027-.22-.026-.224-.023-.226-.022-.231-.021-.233-.018-.237-.016-.241-.014-.244-.012-.247-.011-.25-.008-.254-.005-.257-.004-.26-.001-.26.001z" transform="scale(.5)"></path></symbol></defs><defs><symbol height="24" width="24" id="clock"><path d="M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.848 12.459c.202.038.202.333.001.372-1.907.361-6.045 1.111-6.547 1.111-.719 0-1.301-.582-1.301-1.301 0-.512.77-5.447 1.125-7.445.034-.192.312-.181.343.014l.985 6.238 5.394 1.011z" transform="scale(.5)"></path></symbol></defs><defs><marker orient="auto" markerHeight="12" markerWidth="12" markerUnits="userSpaceOnUse" refY="5" refX="9" id="arrowhead"><path d="M 0 0 L 10 5 L 0 10 z"></path></marker></defs><defs><marker refY="5" refX="4" orient="auto" markerHeight="8" markerWidth="15" id="crosshead"><path d="M 1,2 L 6,7 M 6,2 L 1,7" stroke-width="1pt" style="stroke-dasharray: 0px, 0px;" stroke="#000000" fill="none"></path></marker></defs><defs><marker orient="auto" markerHeight="28" markerWidth="20" refY="7" refX="18" id="filled-head"><path d="M 18,7 L9,13 L14,7 L9,1 Z"></path></marker></defs><defs><marker orient="auto" markerHeight="40" markerWidth="60" refY="15" refX="15" id="sequencenumber"><circle r="6" cy="15" cx="15"></circle></marker></defs><g><rect class="note" ry="0" rx="0" height="39" width="372" stroke="#666" fill="#EDF2AE" y="75" x="-111"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="80" x="75"><tspan x="75">Finishes the setup process (but doesn't stop it!)</tspan></text></g><g><rect class="activation0" ry="0" rx="0" height="253" width="10" stroke="#666" fill="#EDF2AE" y="136" x="70"></rect></g><g><rect class="note" ry="0" rx="0" height="39" width="192" stroke="#666" fill="#EDF2AE" y="144" x="-21"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="149" x="75"><tspan x="75">Start the test process...</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="383" stroke="#666" fill="#EDF2AE" y="247" x="50"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="252" x="242"><tspan x="242">Concurrent disk image accesses!</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="191" stroke="#666" fill="#EDF2AE" y="350" x="312.5"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="355" x="408"><tspan x="408">Stop the setup process</tspan></text></g><text dy="1em" class="messageText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="198" x="244">Inspect memory</text><line marker-end="url(#arrowhead)" style="fill: none;" stroke="none" stroke-width="2" class="messageLine0" y2="237" x2="80" y1="237" x1="408"></line><text dy="1em" class="messageText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="301" x="244">Retrieve finished the setup process</text><line marker-end="url(#arrowhead)" style="fill: none;" stroke="none" stroke-width="2" class="messageLine0" y2="340" x2="408" y1="340" x1="80"></line></svg>
<figcaption>
Asynchronous resource deallocation with mutually exclusive access hazard (red)
</figcaption>
</fig>

<h2 id="alternatives">Alternatives</h2>

<p>As shown above, the garbage collector is not a silver bullet. This section
presents alternative options for resource management.</p>

<h3 id="reference-counting">Reference counting</h3>

<p>The idea behind reference counting is simple; remember how many references are
out there and release the resource when the count reaches zero. The resource
deallocation timing in a reference counting system is more predictable than in
the garbage collector as the deallocation happens exactly when the references
are deleted.</p>

<p>The obvious downside is that a stale reference may keep a resource occupied. In
the earlier example of a sequential run of two QEMU processes, if the earlier
process keeps the stale reference to the disk image, the later process will
never have access to the image, which makes AutoHCK hang. In such a case, you
will want to mark the stale reference invalid instead of waiting forever till it
disappears.</p>

<h3 id="resource-scope">Resource scope</h3>

<p>The resource scope is an inherent concept in many programming languages. In such
languages, a variable becomes available when the execution enters a <em>scope</em>, and
it will be released when the execution leaves the scope.</p>

<p>The resource scope mechanism works neatly when the execution does not involve
persistent states. For example, if a system works like a mathematical function
that simply computes the output from the input, obviously intermediate values
computed in the system can be released after the execution.</p>

<p>The mechanism will not work well for applications like daemon. For example,
consider a key-value storage that accepts <em>set</em> and <em>get</em> operations. A pair of
a key and a value needs to persist after exiting the scope of the <em>set</em>
operation. In other words, the pair of a key and a value needs to <em>escape</em> the
scope.</p>

<h2 id="introducing-autohckresourcescope">Introducing AutoHCK::ResourceScope</h2>

<p>So how can we complement the garbage collector for resource management in
AutoHCK? Determining the best method for resource management requires an
understanding of the workload. In the case of AutoHCK, there are two important
facts:</p>

<ul>
  <li>
    <p>AutoHCK is not a daemon but more function-like. It consumes a Windows image
and test configurations, outputs the test results, and terminates.</p>
  </li>
  <li>
    <p>AutoHCK has essential resources that require mutually-exclusive access:
disk images. Disk images are needed for virtual machines and virtual machines
are needed for… literally everything AutoHCK does.</p>
  </li>
</ul>

<p>They make a clear case for introducing a resource management mechanism using
scope.</p>

<h3 id="the-interface">The interface</h3>

<p>Below is an example usage of <code class="language-plaintext highlighter-rouge">AutoHCK::ResourceScope</code>:</p>

<pre><code class="language-Ruby">ResourceScope.open do |scope|
  a = File.new('a.txt')
  scope &lt;&lt; a
  a.read
end
</code></pre>

<p>This code opens a file, reads it, and closes it. <code class="language-plaintext highlighter-rouge">ResourceScope</code> can be applied
to any resources that can be freed by calling its <code class="language-plaintext highlighter-rouge">close</code> method.</p>

<p>For this simple example,
<a href="https://docs.ruby-lang.org/en/3.2/File.html#method-c-open">you may just give a block to <code class="language-plaintext highlighter-rouge">File.open</code></a>
to get the identical result, but the strength of <code class="language-plaintext highlighter-rouge">AutoHCK::ResourceScope</code> is
that it is <em>composable</em>.</p>

<p>The composability relies on the fact that it can be nested.</p>

<pre><code class="language-Ruby">ResourceScope.open do |a|
  file = ResourceScope.open do |b|
    path_file = File.new('path.txt')
    b &lt;&lt; path_file
    File.new(path_file.read)
  end

  a &lt;&lt; file
  file.read
end
</code></pre>

<p>This way, you can have function-like structures nested. Moreover,
<code class="language-plaintext highlighter-rouge">ResourceScope</code> has a special method named <code class="language-plaintext highlighter-rouge">transaction</code>:</p>

<pre><code class="language-Ruby">ResourceScope.open do |a|
  do_something_with a.transaction do |b|
    file = File.new('a.txt')
    b &lt;&lt; file
    raise 'unexpected header' if file.readline != 'magic'
    file.rewind
    file
  end
end
</code></pre>

<p>Resources attached to a transaction scope will be freed if an exception occurs.
Otherwise, they will escape from the transaction scope to the original scope.
It is known as <em>move</em> semantics in C++ and Rust. This makes sure resources will
not leak due to exceptions during resource allocation.</p>

<p>Finally, a scope object can be passed to methods.</p>

<pre><code class="language-Ruby">class C
  def new(scope)
    @file = File.new('a.txt')
    scope &lt;&lt; @file
  end

  def read
    @file.read
  end
end

ResourceScope.open do |scope|
  c = C.new(scope)
  c.read
end
</code></pre>

<p>A scope parameter of a method forces the programmer to consider what scope is
appropriate to manage the allocated resource.</p>

<p>Nested scopes, transactions, and scope parameters make it possible to compose
a complex procedure from simple ones involving resource allocation and usage.</p>

<h3 id="interrupts">Interrupts</h3>

<p>A major pitfall when managing resources without the garbage collector in Ruby is
interrupt handling. In Ruby, an interrupt can happen anywhere in the code so a
resource will leak if an interrupt happens after it is allocated and before it
is freed.</p>

<svg aria-roledescription="sequence" role="graphics-document document" viewBox="-86 -10 504.5 470" style="max-width: 100%;" width="100%" id="unmasked" height="100%"><title>Resource cleanup and unmasked interrupt</title><style>@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css");'</style><g><rect class="actor" ry="3" rx="3" height="65" width="153" stroke="#666" fill="#eaeaea" y="384" x="215.5"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="416.5" x="292"><tspan dy="0" x="292">Interrupt Handler</tspan></text></g><g><rect class="actor" ry="3" rx="3" height="65" width="150" stroke="#666" fill="#eaeaea" y="384" x="0"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="416.5" x="75"><tspan dy="0" x="75">Application</tspan></text></g><g><line stroke="#999" stroke-width="0.5px" class="200" y2="384" x2="292" y1="5" x1="292" id="actor556"></line><g id="root-556"><rect class="actor" ry="3" rx="3" height="65" width="153" stroke="#666" fill="#eaeaea" y="0" x="215.5"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="32.5" x="292"><tspan dy="0" x="292">Interrupt Handler</tspan></text></g></g><g><line stroke="#999" stroke-width="0.5px" class="200" y2="384" x2="75" y1="5" x1="75" id="actor555"></line><g id="root-555"><rect class="actor" ry="3" rx="3" height="65" width="150" stroke="#666" fill="#eaeaea" y="0" x="0"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="32.5" x="75"><tspan dy="0" x="75">Application</tspan></text></g></g><style>#unmasked{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#unmasked .error-icon{fill:#552222;}#unmasked .error-text{fill:#552222;stroke:#552222;}#unmasked .edge-thickness-normal{stroke-width:2px;}#unmasked .edge-thickness-thick{stroke-width:3.5px;}#unmasked .edge-pattern-solid{stroke-dasharray:0;}#unmasked .edge-pattern-dashed{stroke-dasharray:3;}#unmasked .edge-pattern-dotted{stroke-dasharray:2;}#unmasked .marker{fill:#333333;stroke:#333333;}#unmasked .marker.cross{stroke:#333333;}#unmasked svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#unmasked .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#unmasked text.actor&gt;tspan{fill:black;stroke:none;}#unmasked .actor-line{stroke:grey;}#unmasked .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#unmasked .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#unmasked #arrowhead path{fill:#333;stroke:#333;}#unmasked .sequenceNumber{fill:white;}#unmasked #sequencenumber{fill:#333;}#unmasked #crosshead path{fill:#333;stroke:#333;}#unmasked .messageText{fill:#333;stroke:none;}#unmasked .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#unmasked .labelText,#unmasked .labelText&gt;tspan{fill:black;stroke:none;}#unmasked .loopText,#unmasked .loopText&gt;tspan{fill:black;stroke:none;}#unmasked .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#unmasked .note{stroke:#aaaa33;fill:#fff5ad;}#unmasked .noteText,#unmasked .noteText&gt;tspan{fill:black;stroke:none;}#unmasked .activation0{fill:#f4f4f4;stroke:#666;}#unmasked .activation1{fill:#f4f4f4;stroke:#666;}#unmasked .activation2{fill:#f4f4f4;stroke:#666;}#unmasked .actorPopupMenu{position:absolute;}#unmasked .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#unmasked .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#unmasked .actor-man circle,#unmasked line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#unmasked :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g></g><defs><symbol height="24" width="24" id="computer"><path d="M2 2v13h20v-13h-20zm18 11h-16v-9h16v9zm-10.228 6l.466-1h3.524l.467 1h-4.457zm14.228 3h-24l2-6h2.104l-1.33 4h18.45l-1.297-4h2.073l2 6zm-5-10h-14v-7h14v7z" transform="scale(.5)"></path></symbol></defs><defs><symbol clip-rule="evenodd" fill-rule="evenodd" id="database"><path d="M12.258.001l.256.004.255.005.253.008.251.01.249.012.247.015.246.016.242.019.241.02.239.023.236.024.233.027.231.028.229.031.225.032.223.034.22.036.217.038.214.04.211.041.208.043.205.045.201.046.198.048.194.05.191.051.187.053.183.054.18.056.175.057.172.059.168.06.163.061.16.063.155.064.15.066.074.033.073.033.071.034.07.034.069.035.068.035.067.035.066.035.064.036.064.036.062.036.06.036.06.037.058.037.058.037.055.038.055.038.053.038.052.038.051.039.05.039.048.039.047.039.045.04.044.04.043.04.041.04.04.041.039.041.037.041.036.041.034.041.033.042.032.042.03.042.029.042.027.042.026.043.024.043.023.043.021.043.02.043.018.044.017.043.015.044.013.044.012.044.011.045.009.044.007.045.006.045.004.045.002.045.001.045v17l-.001.045-.002.045-.004.045-.006.045-.007.045-.009.044-.011.045-.012.044-.013.044-.015.044-.017.043-.018.044-.02.043-.021.043-.023.043-.024.043-.026.043-.027.042-.029.042-.03.042-.032.042-.033.042-.034.041-.036.041-.037.041-.039.041-.04.041-.041.04-.043.04-.044.04-.045.04-.047.039-.048.039-.05.039-.051.039-.052.038-.053.038-.055.038-.055.038-.058.037-.058.037-.06.037-.06.036-.062.036-.064.036-.064.036-.066.035-.067.035-.068.035-.069.035-.07.034-.071.034-.073.033-.074.033-.15.066-.155.064-.16.063-.163.061-.168.06-.172.059-.175.057-.18.056-.183.054-.187.053-.191.051-.194.05-.198.048-.201.046-.205.045-.208.043-.211.041-.214.04-.217.038-.22.036-.223.034-.225.032-.229.031-.231.028-.233.027-.236.024-.239.023-.241.02-.242.019-.246.016-.247.015-.249.012-.251.01-.253.008-.255.005-.256.004-.258.001-.258-.001-.256-.004-.255-.005-.253-.008-.251-.01-.249-.012-.247-.015-.245-.016-.243-.019-.241-.02-.238-.023-.236-.024-.234-.027-.231-.028-.228-.031-.226-.032-.223-.034-.22-.036-.217-.038-.214-.04-.211-.041-.208-.043-.204-.045-.201-.046-.198-.048-.195-.05-.19-.051-.187-.053-.184-.054-.179-.056-.176-.057-.172-.059-.167-.06-.164-.061-.159-.063-.155-.064-.151-.066-.074-.033-.072-.033-.072-.034-.07-.034-.069-.035-.068-.035-.067-.035-.066-.035-.064-.036-.063-.036-.062-.036-.061-.036-.06-.037-.058-.037-.057-.037-.056-.038-.055-.038-.053-.038-.052-.038-.051-.039-.049-.039-.049-.039-.046-.039-.046-.04-.044-.04-.043-.04-.041-.04-.04-.041-.039-.041-.037-.041-.036-.041-.034-.041-.033-.042-.032-.042-.03-.042-.029-.042-.027-.042-.026-.043-.024-.043-.023-.043-.021-.043-.02-.043-.018-.044-.017-.043-.015-.044-.013-.044-.012-.044-.011-.045-.009-.044-.007-.045-.006-.045-.004-.045-.002-.045-.001-.045v-17l.001-.045.002-.045.004-.045.006-.045.007-.045.009-.044.011-.045.012-.044.013-.044.015-.044.017-.043.018-.044.02-.043.021-.043.023-.043.024-.043.026-.043.027-.042.029-.042.03-.042.032-.042.033-.042.034-.041.036-.041.037-.041.039-.041.04-.041.041-.04.043-.04.044-.04.046-.04.046-.039.049-.039.049-.039.051-.039.052-.038.053-.038.055-.038.056-.038.057-.037.058-.037.06-.037.061-.036.062-.036.063-.036.064-.036.066-.035.067-.035.068-.035.069-.035.07-.034.072-.034.072-.033.074-.033.151-.066.155-.064.159-.063.164-.061.167-.06.172-.059.176-.057.179-.056.184-.054.187-.053.19-.051.195-.05.198-.048.201-.046.204-.045.208-.043.211-.041.214-.04.217-.038.22-.036.223-.034.226-.032.228-.031.231-.028.234-.027.236-.024.238-.023.241-.02.243-.019.245-.016.247-.015.249-.012.251-.01.253-.008.255-.005.256-.004.258-.001.258.001zm-9.258 20.499v.01l.001.021.003.021.004.022.005.021.006.022.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.023.018.024.019.024.021.024.022.025.023.024.024.025.052.049.056.05.061.051.066.051.07.051.075.051.079.052.084.052.088.052.092.052.097.052.102.051.105.052.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.048.144.049.147.047.152.047.155.047.16.045.163.045.167.043.171.043.176.041.178.041.183.039.187.039.19.037.194.035.197.035.202.033.204.031.209.03.212.029.216.027.219.025.222.024.226.021.23.02.233.018.236.016.24.015.243.012.246.01.249.008.253.005.256.004.259.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.021.224-.024.22-.026.216-.027.212-.028.21-.031.205-.031.202-.034.198-.034.194-.036.191-.037.187-.039.183-.04.179-.04.175-.042.172-.043.168-.044.163-.045.16-.046.155-.046.152-.047.148-.048.143-.049.139-.049.136-.05.131-.05.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.053.083-.051.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.05.023-.024.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.023.01-.022.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.127l-.077.055-.08.053-.083.054-.085.053-.087.052-.09.052-.093.051-.095.05-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.045-.118.044-.12.043-.122.042-.124.042-.126.041-.128.04-.13.04-.132.038-.134.038-.135.037-.138.037-.139.035-.142.035-.143.034-.144.033-.147.032-.148.031-.15.03-.151.03-.153.029-.154.027-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.01-.179.008-.179.008-.181.006-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.006-.179-.008-.179-.008-.178-.01-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.027-.153-.029-.151-.03-.15-.03-.148-.031-.146-.032-.145-.033-.143-.034-.141-.035-.14-.035-.137-.037-.136-.037-.134-.038-.132-.038-.13-.04-.128-.04-.126-.041-.124-.042-.122-.042-.12-.044-.117-.043-.116-.045-.113-.045-.112-.046-.109-.047-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.05-.093-.052-.09-.051-.087-.052-.085-.053-.083-.054-.08-.054-.077-.054v4.127zm0-5.654v.011l.001.021.003.021.004.021.005.022.006.022.007.022.009.022.01.022.011.023.012.023.013.023.015.024.016.023.017.024.018.024.019.024.021.024.022.024.023.025.024.024.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.052.11.051.114.051.119.052.123.05.127.051.131.05.135.049.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.044.171.042.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.022.23.02.233.018.236.016.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.012.241-.015.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.048.139-.05.136-.049.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.051.051-.049.023-.025.023-.024.021-.025.02-.024.019-.024.018-.024.017-.024.015-.023.014-.023.013-.024.012-.022.01-.023.01-.023.008-.022.006-.022.006-.022.004-.021.004-.022.001-.021.001-.021v-4.139l-.077.054-.08.054-.083.054-.085.052-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.044-.118.044-.12.044-.122.042-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.035-.143.033-.144.033-.147.033-.148.031-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.009-.179.009-.179.007-.181.007-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.007-.179-.007-.179-.009-.178-.009-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.031-.146-.033-.145-.033-.143-.033-.141-.035-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.04-.126-.041-.124-.042-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.051-.093-.051-.09-.051-.087-.053-.085-.052-.083-.054-.08-.054-.077-.054v4.139zm0-5.666v.011l.001.02.003.022.004.021.005.022.006.021.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.024.018.023.019.024.021.025.022.024.023.024.024.025.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.051.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.043.171.043.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.021.23.02.233.018.236.017.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.013.241-.014.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.049.139-.049.136-.049.131-.051.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.049.023-.025.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.022.01-.023.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.153l-.077.054-.08.054-.083.053-.085.053-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.048-.105.048-.106.048-.109.046-.111.046-.114.046-.115.044-.118.044-.12.043-.122.043-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.034-.143.034-.144.033-.147.032-.148.032-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.024-.161.024-.162.023-.163.023-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.01-.178.01-.179.009-.179.007-.181.006-.182.006-.182.004-.184.003-.184.001-.185.001-.185-.001-.184-.001-.184-.003-.182-.004-.182-.006-.181-.006-.179-.007-.179-.009-.178-.01-.176-.01-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.023-.162-.023-.161-.024-.159-.024-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.032-.146-.032-.145-.033-.143-.034-.141-.034-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.041-.126-.041-.124-.041-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.048-.105-.048-.102-.048-.1-.05-.097-.049-.095-.051-.093-.051-.09-.052-.087-.052-.085-.053-.083-.053-.08-.054-.077-.054v4.153zm8.74-8.179l-.257.004-.254.005-.25.008-.247.011-.244.012-.241.014-.237.016-.233.018-.231.021-.226.022-.224.023-.22.026-.216.027-.212.028-.21.031-.205.032-.202.033-.198.034-.194.036-.191.038-.187.038-.183.04-.179.041-.175.042-.172.043-.168.043-.163.045-.16.046-.155.046-.152.048-.148.048-.143.048-.139.049-.136.05-.131.05-.126.051-.123.051-.118.051-.114.052-.11.052-.106.052-.101.052-.096.052-.092.052-.088.052-.083.052-.079.052-.074.051-.07.052-.065.051-.06.05-.056.05-.051.05-.023.025-.023.024-.021.024-.02.025-.019.024-.018.024-.017.023-.015.024-.014.023-.013.023-.012.023-.01.023-.01.022-.008.022-.006.023-.006.021-.004.022-.004.021-.001.021-.001.021.001.021.001.021.004.021.004.022.006.021.006.023.008.022.01.022.01.023.012.023.013.023.014.023.015.024.017.023.018.024.019.024.02.025.021.024.023.024.023.025.051.05.056.05.06.05.065.051.07.052.074.051.079.052.083.052.088.052.092.052.096.052.101.052.106.052.11.052.114.052.118.051.123.051.126.051.131.05.136.05.139.049.143.048.148.048.152.048.155.046.16.046.163.045.168.043.172.043.175.042.179.041.183.04.187.038.191.038.194.036.198.034.202.033.205.032.21.031.212.028.216.027.22.026.224.023.226.022.231.021.233.018.237.016.241.014.244.012.247.011.25.008.254.005.257.004.26.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.022.224-.023.22-.026.216-.027.212-.028.21-.031.205-.032.202-.033.198-.034.194-.036.191-.038.187-.038.183-.04.179-.041.175-.042.172-.043.168-.043.163-.045.16-.046.155-.046.152-.048.148-.048.143-.048.139-.049.136-.05.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.05.051-.05.023-.025.023-.024.021-.024.02-.025.019-.024.018-.024.017-.023.015-.024.014-.023.013-.023.012-.023.01-.023.01-.022.008-.022.006-.023.006-.021.004-.022.004-.021.001-.021.001-.021-.001-.021-.001-.021-.004-.021-.004-.022-.006-.021-.006-.023-.008-.022-.01-.022-.01-.023-.012-.023-.013-.023-.014-.023-.015-.024-.017-.023-.018-.024-.019-.024-.02-.025-.021-.024-.023-.024-.023-.025-.051-.05-.056-.05-.06-.05-.065-.051-.07-.052-.074-.051-.079-.052-.083-.052-.088-.052-.092-.052-.096-.052-.101-.052-.106-.052-.11-.052-.114-.052-.118-.051-.123-.051-.126-.051-.131-.05-.136-.05-.139-.049-.143-.048-.148-.048-.152-.048-.155-.046-.16-.046-.163-.045-.168-.043-.172-.043-.175-.042-.179-.041-.183-.04-.187-.038-.191-.038-.194-.036-.198-.034-.202-.033-.205-.032-.21-.031-.212-.028-.216-.027-.22-.026-.224-.023-.226-.022-.231-.021-.233-.018-.237-.016-.241-.014-.244-.012-.247-.011-.25-.008-.254-.005-.257-.004-.26-.001-.26.001z" transform="scale(.5)"></path></symbol></defs><defs><symbol height="24" width="24" id="clock"><path d="M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.848 12.459c.202.038.202.333.001.372-1.907.361-6.045 1.111-6.547 1.111-.719 0-1.301-.582-1.301-1.301 0-.512.77-5.447 1.125-7.445.034-.192.312-.181.343.014l.985 6.238 5.394 1.011z" transform="scale(.5)"></path></symbol></defs><defs><marker orient="auto" markerHeight="12" markerWidth="12" markerUnits="userSpaceOnUse" refY="5" refX="9" id="arrowhead"><path d="M 0 0 L 10 5 L 0 10 z"></path></marker></defs><defs><marker refY="5" refX="4" orient="auto" markerHeight="8" markerWidth="15" id="crosshead"><path d="M 1,2 L 6,7 M 6,2 L 1,7" stroke-width="1pt" style="stroke-dasharray: 0px, 0px;" stroke="#000000" fill="none"></path></marker></defs><defs><marker orient="auto" markerHeight="28" markerWidth="20" refY="7" refX="18" id="filled-head"><path d="M 18,7 L9,13 L14,7 L9,1 Z"></path></marker></defs><defs><marker orient="auto" markerHeight="40" markerWidth="60" refY="15" refX="15" id="sequencenumber"><circle r="6" cy="15" cx="15"></circle></marker></defs><g><rect class="note" ry="0" rx="0" height="39" width="200" stroke="#666" fill="#EDF2AE" y="75" x="-25"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="80" x="75"><tspan x="75">Mask AutoHCKInterrupt</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="202" stroke="#666" fill="#EDF2AE" y="124" x="-26"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="129" x="75"><tspan x="75">Start resource cleanup...</tspan></text></g><g><rect class="activation0" ry="0" rx="0" height="103" width="10" stroke="#666" fill="#EDF2AE" y="163" x="70"></rect></g><g><rect class="note" ry="0" rx="0" height="39" width="197" stroke="#666" fill="#EDF2AE" y="227" x="-23.5"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="232" x="75"><tspan x="75">Finish resource cleanup</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="222" stroke="#666" fill="#EDF2AE" y="276" x="-36"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="281" x="75"><tspan x="75">Unmask AutoHCKInterrupt</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="200" stroke="#666" fill="#EDF2AE" y="325" x="-25"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="330" x="75"><tspan x="75">Raise AutoHCKInterrupt</tspan></text></g><text dy="1em" class="messageText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="178" x="186">Deliver an interrupt</text><line marker-end="url(#arrowhead)" style="fill: none;" stroke="none" stroke-width="2" class="messageLine0" y2="217" x2="80" y1="217" x1="292"></line></svg>

<p><code class="language-plaintext highlighter-rouge">Thread.handle_interrupt</code> allows to mask interrupts but its use is tedious.
<code class="language-plaintext highlighter-rouge">AutoHCK::ResourceScope.open</code> automatically use the method and make it simple.</p>

<svg aria-roledescription="sequence" role="graphics-document document" viewBox="-86 -10 504.5 470" style="max-width: 100%;" width="100%" id="masked" height="100%"><title>Resource cleanup and masked interrupt</title><style>@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css");'</style><g><rect class="actor" ry="3" rx="3" height="65" width="153" stroke="#666" fill="#eaeaea" y="384" x="215.5"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="416.5" x="292"><tspan dy="0" x="292">Interrupt Handler</tspan></text></g><g><rect class="actor" ry="3" rx="3" height="65" width="150" stroke="#666" fill="#eaeaea" y="384" x="0"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="416.5" x="75"><tspan dy="0" x="75">Application</tspan></text></g><g><line stroke="#999" stroke-width="0.5px" class="200" y2="384" x2="292" y1="5" x1="292" id="actor576"></line><g id="root-576"><rect class="actor" ry="3" rx="3" height="65" width="153" stroke="#666" fill="#eaeaea" y="0" x="215.5"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="32.5" x="292"><tspan dy="0" x="292">Interrupt Handler</tspan></text></g></g><g><line stroke="#999" stroke-width="0.5px" class="200" y2="384" x2="75" y1="5" x1="75" id="actor575"></line><g id="root-575"><rect class="actor" ry="3" rx="3" height="65" width="150" stroke="#666" fill="#eaeaea" y="0" x="0"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="32.5" x="75"><tspan dy="0" x="75">Application</tspan></text></g></g><style>#masked{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#masked .error-icon{fill:#552222;}#masked .error-text{fill:#552222;stroke:#552222;}#masked .edge-thickness-normal{stroke-width:2px;}#masked .edge-thickness-thick{stroke-width:3.5px;}#masked .edge-pattern-solid{stroke-dasharray:0;}#masked .edge-pattern-dashed{stroke-dasharray:3;}#masked .edge-pattern-dotted{stroke-dasharray:2;}#masked .marker{fill:#333333;stroke:#333333;}#masked .marker.cross{stroke:#333333;}#masked svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#masked .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#masked text.actor&gt;tspan{fill:black;stroke:none;}#masked .actor-line{stroke:grey;}#masked .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#masked .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#masked #arrowhead path{fill:#333;stroke:#333;}#masked .sequenceNumber{fill:white;}#masked #sequencenumber{fill:#333;}#masked #crosshead path{fill:#333;stroke:#333;}#masked .messageText{fill:#333;stroke:none;}#masked .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#masked .labelText,#masked .labelText&gt;tspan{fill:black;stroke:none;}#masked .loopText,#masked .loopText&gt;tspan{fill:black;stroke:none;}#masked .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#masked .note{stroke:#aaaa33;fill:#fff5ad;}#masked .noteText,#masked .noteText&gt;tspan{fill:black;stroke:none;}#masked .activation0{fill:#f4f4f4;stroke:#666;}#masked .activation1{fill:#f4f4f4;stroke:#666;}#masked .activation2{fill:#f4f4f4;stroke:#666;}#masked .actorPopupMenu{position:absolute;}#masked .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#masked .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#masked .actor-man circle,#masked line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#masked :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g></g><defs><symbol height="24" width="24" id="computer"><path d="M2 2v13h20v-13h-20zm18 11h-16v-9h16v9zm-10.228 6l.466-1h3.524l.467 1h-4.457zm14.228 3h-24l2-6h2.104l-1.33 4h18.45l-1.297-4h2.073l2 6zm-5-10h-14v-7h14v7z" transform="scale(.5)"></path></symbol></defs><defs><symbol clip-rule="evenodd" fill-rule="evenodd" id="database"><path d="M12.258.001l.256.004.255.005.253.008.251.01.249.012.247.015.246.016.242.019.241.02.239.023.236.024.233.027.231.028.229.031.225.032.223.034.22.036.217.038.214.04.211.041.208.043.205.045.201.046.198.048.194.05.191.051.187.053.183.054.18.056.175.057.172.059.168.06.163.061.16.063.155.064.15.066.074.033.073.033.071.034.07.034.069.035.068.035.067.035.066.035.064.036.064.036.062.036.06.036.06.037.058.037.058.037.055.038.055.038.053.038.052.038.051.039.05.039.048.039.047.039.045.04.044.04.043.04.041.04.04.041.039.041.037.041.036.041.034.041.033.042.032.042.03.042.029.042.027.042.026.043.024.043.023.043.021.043.02.043.018.044.017.043.015.044.013.044.012.044.011.045.009.044.007.045.006.045.004.045.002.045.001.045v17l-.001.045-.002.045-.004.045-.006.045-.007.045-.009.044-.011.045-.012.044-.013.044-.015.044-.017.043-.018.044-.02.043-.021.043-.023.043-.024.043-.026.043-.027.042-.029.042-.03.042-.032.042-.033.042-.034.041-.036.041-.037.041-.039.041-.04.041-.041.04-.043.04-.044.04-.045.04-.047.039-.048.039-.05.039-.051.039-.052.038-.053.038-.055.038-.055.038-.058.037-.058.037-.06.037-.06.036-.062.036-.064.036-.064.036-.066.035-.067.035-.068.035-.069.035-.07.034-.071.034-.073.033-.074.033-.15.066-.155.064-.16.063-.163.061-.168.06-.172.059-.175.057-.18.056-.183.054-.187.053-.191.051-.194.05-.198.048-.201.046-.205.045-.208.043-.211.041-.214.04-.217.038-.22.036-.223.034-.225.032-.229.031-.231.028-.233.027-.236.024-.239.023-.241.02-.242.019-.246.016-.247.015-.249.012-.251.01-.253.008-.255.005-.256.004-.258.001-.258-.001-.256-.004-.255-.005-.253-.008-.251-.01-.249-.012-.247-.015-.245-.016-.243-.019-.241-.02-.238-.023-.236-.024-.234-.027-.231-.028-.228-.031-.226-.032-.223-.034-.22-.036-.217-.038-.214-.04-.211-.041-.208-.043-.204-.045-.201-.046-.198-.048-.195-.05-.19-.051-.187-.053-.184-.054-.179-.056-.176-.057-.172-.059-.167-.06-.164-.061-.159-.063-.155-.064-.151-.066-.074-.033-.072-.033-.072-.034-.07-.034-.069-.035-.068-.035-.067-.035-.066-.035-.064-.036-.063-.036-.062-.036-.061-.036-.06-.037-.058-.037-.057-.037-.056-.038-.055-.038-.053-.038-.052-.038-.051-.039-.049-.039-.049-.039-.046-.039-.046-.04-.044-.04-.043-.04-.041-.04-.04-.041-.039-.041-.037-.041-.036-.041-.034-.041-.033-.042-.032-.042-.03-.042-.029-.042-.027-.042-.026-.043-.024-.043-.023-.043-.021-.043-.02-.043-.018-.044-.017-.043-.015-.044-.013-.044-.012-.044-.011-.045-.009-.044-.007-.045-.006-.045-.004-.045-.002-.045-.001-.045v-17l.001-.045.002-.045.004-.045.006-.045.007-.045.009-.044.011-.045.012-.044.013-.044.015-.044.017-.043.018-.044.02-.043.021-.043.023-.043.024-.043.026-.043.027-.042.029-.042.03-.042.032-.042.033-.042.034-.041.036-.041.037-.041.039-.041.04-.041.041-.04.043-.04.044-.04.046-.04.046-.039.049-.039.049-.039.051-.039.052-.038.053-.038.055-.038.056-.038.057-.037.058-.037.06-.037.061-.036.062-.036.063-.036.064-.036.066-.035.067-.035.068-.035.069-.035.07-.034.072-.034.072-.033.074-.033.151-.066.155-.064.159-.063.164-.061.167-.06.172-.059.176-.057.179-.056.184-.054.187-.053.19-.051.195-.05.198-.048.201-.046.204-.045.208-.043.211-.041.214-.04.217-.038.22-.036.223-.034.226-.032.228-.031.231-.028.234-.027.236-.024.238-.023.241-.02.243-.019.245-.016.247-.015.249-.012.251-.01.253-.008.255-.005.256-.004.258-.001.258.001zm-9.258 20.499v.01l.001.021.003.021.004.022.005.021.006.022.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.023.018.024.019.024.021.024.022.025.023.024.024.025.052.049.056.05.061.051.066.051.07.051.075.051.079.052.084.052.088.052.092.052.097.052.102.051.105.052.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.048.144.049.147.047.152.047.155.047.16.045.163.045.167.043.171.043.176.041.178.041.183.039.187.039.19.037.194.035.197.035.202.033.204.031.209.03.212.029.216.027.219.025.222.024.226.021.23.02.233.018.236.016.24.015.243.012.246.01.249.008.253.005.256.004.259.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.021.224-.024.22-.026.216-.027.212-.028.21-.031.205-.031.202-.034.198-.034.194-.036.191-.037.187-.039.183-.04.179-.04.175-.042.172-.043.168-.044.163-.045.16-.046.155-.046.152-.047.148-.048.143-.049.139-.049.136-.05.131-.05.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.053.083-.051.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.05.023-.024.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.023.01-.022.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.127l-.077.055-.08.053-.083.054-.085.053-.087.052-.09.052-.093.051-.095.05-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.045-.118.044-.12.043-.122.042-.124.042-.126.041-.128.04-.13.04-.132.038-.134.038-.135.037-.138.037-.139.035-.142.035-.143.034-.144.033-.147.032-.148.031-.15.03-.151.03-.153.029-.154.027-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.01-.179.008-.179.008-.181.006-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.006-.179-.008-.179-.008-.178-.01-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.027-.153-.029-.151-.03-.15-.03-.148-.031-.146-.032-.145-.033-.143-.034-.141-.035-.14-.035-.137-.037-.136-.037-.134-.038-.132-.038-.13-.04-.128-.04-.126-.041-.124-.042-.122-.042-.12-.044-.117-.043-.116-.045-.113-.045-.112-.046-.109-.047-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.05-.093-.052-.09-.051-.087-.052-.085-.053-.083-.054-.08-.054-.077-.054v4.127zm0-5.654v.011l.001.021.003.021.004.021.005.022.006.022.007.022.009.022.01.022.011.023.012.023.013.023.015.024.016.023.017.024.018.024.019.024.021.024.022.024.023.025.024.024.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.052.11.051.114.051.119.052.123.05.127.051.131.05.135.049.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.044.171.042.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.022.23.02.233.018.236.016.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.012.241-.015.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.048.139-.05.136-.049.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.051.051-.049.023-.025.023-.024.021-.025.02-.024.019-.024.018-.024.017-.024.015-.023.014-.023.013-.024.012-.022.01-.023.01-.023.008-.022.006-.022.006-.022.004-.021.004-.022.001-.021.001-.021v-4.139l-.077.054-.08.054-.083.054-.085.052-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.044-.118.044-.12.044-.122.042-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.035-.143.033-.144.033-.147.033-.148.031-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.009-.179.009-.179.007-.181.007-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.007-.179-.007-.179-.009-.178-.009-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.031-.146-.033-.145-.033-.143-.033-.141-.035-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.04-.126-.041-.124-.042-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.051-.093-.051-.09-.051-.087-.053-.085-.052-.083-.054-.08-.054-.077-.054v4.139zm0-5.666v.011l.001.02.003.022.004.021.005.022.006.021.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.024.018.023.019.024.021.025.022.024.023.024.024.025.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.051.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.043.171.043.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.021.23.02.233.018.236.017.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.013.241-.014.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.049.139-.049.136-.049.131-.051.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.049.023-.025.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.022.01-.023.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.153l-.077.054-.08.054-.083.053-.085.053-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.048-.105.048-.106.048-.109.046-.111.046-.114.046-.115.044-.118.044-.12.043-.122.043-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.034-.143.034-.144.033-.147.032-.148.032-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.024-.161.024-.162.023-.163.023-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.01-.178.01-.179.009-.179.007-.181.006-.182.006-.182.004-.184.003-.184.001-.185.001-.185-.001-.184-.001-.184-.003-.182-.004-.182-.006-.181-.006-.179-.007-.179-.009-.178-.01-.176-.01-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.023-.162-.023-.161-.024-.159-.024-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.032-.146-.032-.145-.033-.143-.034-.141-.034-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.041-.126-.041-.124-.041-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.048-.105-.048-.102-.048-.1-.05-.097-.049-.095-.051-.093-.051-.09-.052-.087-.052-.085-.053-.083-.053-.08-.054-.077-.054v4.153zm8.74-8.179l-.257.004-.254.005-.25.008-.247.011-.244.012-.241.014-.237.016-.233.018-.231.021-.226.022-.224.023-.22.026-.216.027-.212.028-.21.031-.205.032-.202.033-.198.034-.194.036-.191.038-.187.038-.183.04-.179.041-.175.042-.172.043-.168.043-.163.045-.16.046-.155.046-.152.048-.148.048-.143.048-.139.049-.136.05-.131.05-.126.051-.123.051-.118.051-.114.052-.11.052-.106.052-.101.052-.096.052-.092.052-.088.052-.083.052-.079.052-.074.051-.07.052-.065.051-.06.05-.056.05-.051.05-.023.025-.023.024-.021.024-.02.025-.019.024-.018.024-.017.023-.015.024-.014.023-.013.023-.012.023-.01.023-.01.022-.008.022-.006.023-.006.021-.004.022-.004.021-.001.021-.001.021.001.021.001.021.004.021.004.022.006.021.006.023.008.022.01.022.01.023.012.023.013.023.014.023.015.024.017.023.018.024.019.024.02.025.021.024.023.024.023.025.051.05.056.05.06.05.065.051.07.052.074.051.079.052.083.052.088.052.092.052.096.052.101.052.106.052.11.052.114.052.118.051.123.051.126.051.131.05.136.05.139.049.143.048.148.048.152.048.155.046.16.046.163.045.168.043.172.043.175.042.179.041.183.04.187.038.191.038.194.036.198.034.202.033.205.032.21.031.212.028.216.027.22.026.224.023.226.022.231.021.233.018.237.016.241.014.244.012.247.011.25.008.254.005.257.004.26.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.022.224-.023.22-.026.216-.027.212-.028.21-.031.205-.032.202-.033.198-.034.194-.036.191-.038.187-.038.183-.04.179-.041.175-.042.172-.043.168-.043.163-.045.16-.046.155-.046.152-.048.148-.048.143-.048.139-.049.136-.05.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.05.051-.05.023-.025.023-.024.021-.024.02-.025.019-.024.018-.024.017-.023.015-.024.014-.023.013-.023.012-.023.01-.023.01-.022.008-.022.006-.023.006-.021.004-.022.004-.021.001-.021.001-.021-.001-.021-.001-.021-.004-.021-.004-.022-.006-.021-.006-.023-.008-.022-.01-.022-.01-.023-.012-.023-.013-.023-.014-.023-.015-.024-.017-.023-.018-.024-.019-.024-.02-.025-.021-.024-.023-.024-.023-.025-.051-.05-.056-.05-.06-.05-.065-.051-.07-.052-.074-.051-.079-.052-.083-.052-.088-.052-.092-.052-.096-.052-.101-.052-.106-.052-.11-.052-.114-.052-.118-.051-.123-.051-.126-.051-.131-.05-.136-.05-.139-.049-.143-.048-.148-.048-.152-.048-.155-.046-.16-.046-.163-.045-.168-.043-.172-.043-.175-.042-.179-.041-.183-.04-.187-.038-.191-.038-.194-.036-.198-.034-.202-.033-.205-.032-.21-.031-.212-.028-.216-.027-.22-.026-.224-.023-.226-.022-.231-.021-.233-.018-.237-.016-.241-.014-.244-.012-.247-.011-.25-.008-.254-.005-.257-.004-.26-.001-.26.001z" transform="scale(.5)"></path></symbol></defs><defs><symbol height="24" width="24" id="clock"><path d="M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.848 12.459c.202.038.202.333.001.372-1.907.361-6.045 1.111-6.547 1.111-.719 0-1.301-.582-1.301-1.301 0-.512.77-5.447 1.125-7.445.034-.192.312-.181.343.014l.985 6.238 5.394 1.011z" transform="scale(.5)"></path></symbol></defs><defs><marker orient="auto" markerHeight="12" markerWidth="12" markerUnits="userSpaceOnUse" refY="5" refX="9" id="arrowhead"><path d="M 0 0 L 10 5 L 0 10 z"></path></marker></defs><defs><marker refY="5" refX="4" orient="auto" markerHeight="8" markerWidth="15" id="crosshead"><path d="M 1,2 L 6,7 M 6,2 L 1,7" stroke-width="1pt" style="stroke-dasharray: 0px, 0px;" stroke="#000000" fill="none"></path></marker></defs><defs><marker orient="auto" markerHeight="28" markerWidth="20" refY="7" refX="18" id="filled-head"><path d="M 18,7 L9,13 L14,7 L9,1 Z"></path></marker></defs><defs><marker orient="auto" markerHeight="40" markerWidth="60" refY="15" refX="15" id="sequencenumber"><circle r="6" cy="15" cx="15"></circle></marker></defs><g><rect class="note" ry="0" rx="0" height="39" width="200" stroke="#666" fill="#EDF2AE" y="75" x="-25"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="80" x="75"><tspan x="75">Mask AutoHCKInterrupt</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="202" stroke="#666" fill="#EDF2AE" y="124" x="-26"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="129" x="75"><tspan x="75">Start resource cleanup...</tspan></text></g><g><rect class="activation0" ry="0" rx="0" height="103" width="10" stroke="#666" fill="#EDF2AE" y="163" x="70"></rect></g><g><rect class="note" ry="0" rx="0" height="39" width="197" stroke="#666" fill="#EDF2AE" y="227" x="-23.5"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="232" x="75"><tspan x="75">Finish resource cleanup</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="222" stroke="#666" fill="#EDF2AE" y="276" x="-36"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="281" x="75"><tspan x="75">Unmask AutoHCKInterrupt</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="200" stroke="#666" fill="#EDF2AE" y="325" x="-25"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="330" x="75"><tspan x="75">Raise AutoHCKInterrupt</tspan></text></g><text dy="1em" class="messageText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="178" x="186">Deliver an interrupt</text><line marker-end="url(#arrowhead)" style="fill: none;" stroke="none" stroke-width="2" class="messageLine0" y2="217" x2="80" y1="217" x1="292"></line></svg>

<p>Below is the actual implementation of <code class="language-plaintext highlighter-rouge">AutoHCK::ResourceScope.open</code>:</p>

<pre><code class="language-Ruby">def self.open(resources = [])
  scope = new(resources)
  Thread.handle_interrupt(AutoHCKInterrupt =&gt; :never) do
    Thread.handle_interrupt(AutoHCKInterrupt =&gt; :on_blocking) do
      yield scope
    end
  ensure
    resources.reverse_each(&amp;:close)
  end
end
</code></pre>

<p><code class="language-plaintext highlighter-rouge">Thread.handle_interrupt(AutoHCKInterrupt =&gt; :never)</code> ensures an interrupt will
not occur when freeing resources.</p>

<p><code class="language-plaintext highlighter-rouge">Thread.handle_interrupt(AutoHCKInterrupt =&gt; :on_blocking)</code> ensures an interrupt
will not occur after a resource is allocated and before it is assigned to the
scope.</p>

<p><code class="language-plaintext highlighter-rouge">AutoHCK::ResourceScope.open</code> use a specialized exception class
(<code class="language-plaintext highlighter-rouge">AutoHCKInterrupt</code>) so that third-party code that creates a child thread and
interrupt it works. A typical example is
<a href="https://github.com/ruby/timeout">timeout</a>. As timeout works by creating a
thread and interrupting it after a specified period, masking generic interrupts
prevents it from functioning.</p>

<svg aria-roledescription="sequence" role="graphics-document document" viewBox="-76 -10 693 681" style="max-width: 100%;" width="100%" id="timeout" height="100%"><title>Timeout and incorrect interrupt mask</title><style>@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css");'</style><g><rect class="actor" ry="3" rx="3" height="65" width="150" stroke="#666" fill="#eaeaea" y="595" x="417"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="627.5" x="492"><tspan dy="0" x="492">Timer</tspan></text></g><g><rect class="actor" ry="3" rx="3" height="65" width="150" stroke="#666" fill="#eaeaea" y="595" x="217"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="627.5" x="292"><tspan dy="0" x="292">Timeout Thread</tspan></text></g><g><rect class="actor" ry="3" rx="3" height="65" width="150" stroke="#666" fill="#eaeaea" y="595" x="0"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="627.5" x="75"><tspan dy="0" x="75">Application</tspan></text></g><g><line stroke="#999" stroke-width="0.5px" class="200" y2="595" x2="492" y1="5" x1="492" id="actor579"></line><g id="root-579"><rect class="actor" ry="3" rx="3" height="65" width="150" stroke="#666" fill="#eaeaea" y="0" x="417"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="32.5" x="492"><tspan dy="0" x="492">Timer</tspan></text></g></g><g><line stroke="#999" stroke-width="0.5px" class="200" y2="595" x2="292" y1="5" x1="292" id="actor578"></line><g id="root-578"><rect class="actor" ry="3" rx="3" height="65" width="150" stroke="#666" fill="#eaeaea" y="0" x="217"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="32.5" x="292"><tspan dy="0" x="292">Timeout Thread</tspan></text></g></g><g><line stroke="#999" stroke-width="0.5px" class="200" y2="595" x2="75" y1="5" x1="75" id="actor577"></line><g id="root-577"><rect class="actor" ry="3" rx="3" height="65" width="150" stroke="#666" fill="#eaeaea" y="0" x="0"></rect><text class="actor" alignment-baseline="central" dominant-baseline="central" style="text-anchor: middle; font-size: 16px; font-weight: 400;" y="32.5" x="75"><tspan dy="0" x="75">Application</tspan></text></g></g><style>#timeout{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#timeout .error-icon{fill:#552222;}#timeout .error-text{fill:#552222;stroke:#552222;}#timeout .edge-thickness-normal{stroke-width:2px;}#timeout .edge-thickness-thick{stroke-width:3.5px;}#timeout .edge-pattern-solid{stroke-dasharray:0;}#timeout .edge-pattern-dashed{stroke-dasharray:3;}#timeout .edge-pattern-dotted{stroke-dasharray:2;}#timeout .marker{fill:#333333;stroke:#333333;}#timeout .marker.cross{stroke:#333333;}#timeout svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#timeout .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#timeout text.actor&gt;tspan{fill:black;stroke:none;}#timeout .actor-line{stroke:grey;}#timeout .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#timeout .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#timeout #arrowhead path{fill:#333;stroke:#333;}#timeout .sequenceNumber{fill:white;}#timeout #sequencenumber{fill:#333;}#timeout #crosshead path{fill:#333;stroke:#333;}#timeout .messageText{fill:#333;stroke:none;}#timeout .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#timeout .labelText,#timeout .labelText&gt;tspan{fill:black;stroke:none;}#timeout .loopText,#timeout .loopText&gt;tspan{fill:black;stroke:none;}#timeout .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#timeout .note{stroke:#aaaa33;fill:#fff5ad;}#timeout .noteText,#timeout .noteText&gt;tspan{fill:black;stroke:none;}#timeout .activation0{fill:#f4f4f4;stroke:#666;}#timeout .activation1{fill:#f4f4f4;stroke:#666;}#timeout .activation2{fill:#f4f4f4;stroke:#666;}#timeout .actorPopupMenu{position:absolute;}#timeout .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#timeout .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#timeout .actor-man circle,#timeout line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#timeout :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g></g><defs><symbol height="24" width="24" id="computer"><path d="M2 2v13h20v-13h-20zm18 11h-16v-9h16v9zm-10.228 6l.466-1h3.524l.467 1h-4.457zm14.228 3h-24l2-6h2.104l-1.33 4h18.45l-1.297-4h2.073l2 6zm-5-10h-14v-7h14v7z" transform="scale(.5)"></path></symbol></defs><defs><symbol clip-rule="evenodd" fill-rule="evenodd" id="database"><path d="M12.258.001l.256.004.255.005.253.008.251.01.249.012.247.015.246.016.242.019.241.02.239.023.236.024.233.027.231.028.229.031.225.032.223.034.22.036.217.038.214.04.211.041.208.043.205.045.201.046.198.048.194.05.191.051.187.053.183.054.18.056.175.057.172.059.168.06.163.061.16.063.155.064.15.066.074.033.073.033.071.034.07.034.069.035.068.035.067.035.066.035.064.036.064.036.062.036.06.036.06.037.058.037.058.037.055.038.055.038.053.038.052.038.051.039.05.039.048.039.047.039.045.04.044.04.043.04.041.04.04.041.039.041.037.041.036.041.034.041.033.042.032.042.03.042.029.042.027.042.026.043.024.043.023.043.021.043.02.043.018.044.017.043.015.044.013.044.012.044.011.045.009.044.007.045.006.045.004.045.002.045.001.045v17l-.001.045-.002.045-.004.045-.006.045-.007.045-.009.044-.011.045-.012.044-.013.044-.015.044-.017.043-.018.044-.02.043-.021.043-.023.043-.024.043-.026.043-.027.042-.029.042-.03.042-.032.042-.033.042-.034.041-.036.041-.037.041-.039.041-.04.041-.041.04-.043.04-.044.04-.045.04-.047.039-.048.039-.05.039-.051.039-.052.038-.053.038-.055.038-.055.038-.058.037-.058.037-.06.037-.06.036-.062.036-.064.036-.064.036-.066.035-.067.035-.068.035-.069.035-.07.034-.071.034-.073.033-.074.033-.15.066-.155.064-.16.063-.163.061-.168.06-.172.059-.175.057-.18.056-.183.054-.187.053-.191.051-.194.05-.198.048-.201.046-.205.045-.208.043-.211.041-.214.04-.217.038-.22.036-.223.034-.225.032-.229.031-.231.028-.233.027-.236.024-.239.023-.241.02-.242.019-.246.016-.247.015-.249.012-.251.01-.253.008-.255.005-.256.004-.258.001-.258-.001-.256-.004-.255-.005-.253-.008-.251-.01-.249-.012-.247-.015-.245-.016-.243-.019-.241-.02-.238-.023-.236-.024-.234-.027-.231-.028-.228-.031-.226-.032-.223-.034-.22-.036-.217-.038-.214-.04-.211-.041-.208-.043-.204-.045-.201-.046-.198-.048-.195-.05-.19-.051-.187-.053-.184-.054-.179-.056-.176-.057-.172-.059-.167-.06-.164-.061-.159-.063-.155-.064-.151-.066-.074-.033-.072-.033-.072-.034-.07-.034-.069-.035-.068-.035-.067-.035-.066-.035-.064-.036-.063-.036-.062-.036-.061-.036-.06-.037-.058-.037-.057-.037-.056-.038-.055-.038-.053-.038-.052-.038-.051-.039-.049-.039-.049-.039-.046-.039-.046-.04-.044-.04-.043-.04-.041-.04-.04-.041-.039-.041-.037-.041-.036-.041-.034-.041-.033-.042-.032-.042-.03-.042-.029-.042-.027-.042-.026-.043-.024-.043-.023-.043-.021-.043-.02-.043-.018-.044-.017-.043-.015-.044-.013-.044-.012-.044-.011-.045-.009-.044-.007-.045-.006-.045-.004-.045-.002-.045-.001-.045v-17l.001-.045.002-.045.004-.045.006-.045.007-.045.009-.044.011-.045.012-.044.013-.044.015-.044.017-.043.018-.044.02-.043.021-.043.023-.043.024-.043.026-.043.027-.042.029-.042.03-.042.032-.042.033-.042.034-.041.036-.041.037-.041.039-.041.04-.041.041-.04.043-.04.044-.04.046-.04.046-.039.049-.039.049-.039.051-.039.052-.038.053-.038.055-.038.056-.038.057-.037.058-.037.06-.037.061-.036.062-.036.063-.036.064-.036.066-.035.067-.035.068-.035.069-.035.07-.034.072-.034.072-.033.074-.033.151-.066.155-.064.159-.063.164-.061.167-.06.172-.059.176-.057.179-.056.184-.054.187-.053.19-.051.195-.05.198-.048.201-.046.204-.045.208-.043.211-.041.214-.04.217-.038.22-.036.223-.034.226-.032.228-.031.231-.028.234-.027.236-.024.238-.023.241-.02.243-.019.245-.016.247-.015.249-.012.251-.01.253-.008.255-.005.256-.004.258-.001.258.001zm-9.258 20.499v.01l.001.021.003.021.004.022.005.021.006.022.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.023.018.024.019.024.021.024.022.025.023.024.024.025.052.049.056.05.061.051.066.051.07.051.075.051.079.052.084.052.088.052.092.052.097.052.102.051.105.052.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.048.144.049.147.047.152.047.155.047.16.045.163.045.167.043.171.043.176.041.178.041.183.039.187.039.19.037.194.035.197.035.202.033.204.031.209.03.212.029.216.027.219.025.222.024.226.021.23.02.233.018.236.016.24.015.243.012.246.01.249.008.253.005.256.004.259.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.021.224-.024.22-.026.216-.027.212-.028.21-.031.205-.031.202-.034.198-.034.194-.036.191-.037.187-.039.183-.04.179-.04.175-.042.172-.043.168-.044.163-.045.16-.046.155-.046.152-.047.148-.048.143-.049.139-.049.136-.05.131-.05.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.053.083-.051.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.05.023-.024.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.023.01-.022.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.127l-.077.055-.08.053-.083.054-.085.053-.087.052-.09.052-.093.051-.095.05-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.045-.118.044-.12.043-.122.042-.124.042-.126.041-.128.04-.13.04-.132.038-.134.038-.135.037-.138.037-.139.035-.142.035-.143.034-.144.033-.147.032-.148.031-.15.03-.151.03-.153.029-.154.027-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.01-.179.008-.179.008-.181.006-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.006-.179-.008-.179-.008-.178-.01-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.027-.153-.029-.151-.03-.15-.03-.148-.031-.146-.032-.145-.033-.143-.034-.141-.035-.14-.035-.137-.037-.136-.037-.134-.038-.132-.038-.13-.04-.128-.04-.126-.041-.124-.042-.122-.042-.12-.044-.117-.043-.116-.045-.113-.045-.112-.046-.109-.047-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.05-.093-.052-.09-.051-.087-.052-.085-.053-.083-.054-.08-.054-.077-.054v4.127zm0-5.654v.011l.001.021.003.021.004.021.005.022.006.022.007.022.009.022.01.022.011.023.012.023.013.023.015.024.016.023.017.024.018.024.019.024.021.024.022.024.023.025.024.024.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.052.11.051.114.051.119.052.123.05.127.051.131.05.135.049.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.044.171.042.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.022.23.02.233.018.236.016.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.012.241-.015.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.048.139-.05.136-.049.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.051.051-.049.023-.025.023-.024.021-.025.02-.024.019-.024.018-.024.017-.024.015-.023.014-.023.013-.024.012-.022.01-.023.01-.023.008-.022.006-.022.006-.022.004-.021.004-.022.001-.021.001-.021v-4.139l-.077.054-.08.054-.083.054-.085.052-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.044-.118.044-.12.044-.122.042-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.035-.143.033-.144.033-.147.033-.148.031-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.009-.179.009-.179.007-.181.007-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.007-.179-.007-.179-.009-.178-.009-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.031-.146-.033-.145-.033-.143-.033-.141-.035-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.04-.126-.041-.124-.042-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.051-.093-.051-.09-.051-.087-.053-.085-.052-.083-.054-.08-.054-.077-.054v4.139zm0-5.666v.011l.001.02.003.022.004.021.005.022.006.021.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.024.018.023.019.024.021.025.022.024.023.024.024.025.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.051.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.043.171.043.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.021.23.02.233.018.236.017.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.013.241-.014.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.049.139-.049.136-.049.131-.051.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.049.023-.025.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.022.01-.023.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.153l-.077.054-.08.054-.083.053-.085.053-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.048-.105.048-.106.048-.109.046-.111.046-.114.046-.115.044-.118.044-.12.043-.122.043-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.034-.143.034-.144.033-.147.032-.148.032-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.024-.161.024-.162.023-.163.023-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.01-.178.01-.179.009-.179.007-.181.006-.182.006-.182.004-.184.003-.184.001-.185.001-.185-.001-.184-.001-.184-.003-.182-.004-.182-.006-.181-.006-.179-.007-.179-.009-.178-.01-.176-.01-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.023-.162-.023-.161-.024-.159-.024-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.032-.146-.032-.145-.033-.143-.034-.141-.034-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.041-.126-.041-.124-.041-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.048-.105-.048-.102-.048-.1-.05-.097-.049-.095-.051-.093-.051-.09-.052-.087-.052-.085-.053-.083-.053-.08-.054-.077-.054v4.153zm8.74-8.179l-.257.004-.254.005-.25.008-.247.011-.244.012-.241.014-.237.016-.233.018-.231.021-.226.022-.224.023-.22.026-.216.027-.212.028-.21.031-.205.032-.202.033-.198.034-.194.036-.191.038-.187.038-.183.04-.179.041-.175.042-.172.043-.168.043-.163.045-.16.046-.155.046-.152.048-.148.048-.143.048-.139.049-.136.05-.131.05-.126.051-.123.051-.118.051-.114.052-.11.052-.106.052-.101.052-.096.052-.092.052-.088.052-.083.052-.079.052-.074.051-.07.052-.065.051-.06.05-.056.05-.051.05-.023.025-.023.024-.021.024-.02.025-.019.024-.018.024-.017.023-.015.024-.014.023-.013.023-.012.023-.01.023-.01.022-.008.022-.006.023-.006.021-.004.022-.004.021-.001.021-.001.021.001.021.001.021.004.021.004.022.006.021.006.023.008.022.01.022.01.023.012.023.013.023.014.023.015.024.017.023.018.024.019.024.02.025.021.024.023.024.023.025.051.05.056.05.06.05.065.051.07.052.074.051.079.052.083.052.088.052.092.052.096.052.101.052.106.052.11.052.114.052.118.051.123.051.126.051.131.05.136.05.139.049.143.048.148.048.152.048.155.046.16.046.163.045.168.043.172.043.175.042.179.041.183.04.187.038.191.038.194.036.198.034.202.033.205.032.21.031.212.028.216.027.22.026.224.023.226.022.231.021.233.018.237.016.241.014.244.012.247.011.25.008.254.005.257.004.26.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.022.224-.023.22-.026.216-.027.212-.028.21-.031.205-.032.202-.033.198-.034.194-.036.191-.038.187-.038.183-.04.179-.041.175-.042.172-.043.168-.043.163-.045.16-.046.155-.046.152-.048.148-.048.143-.048.139-.049.136-.05.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.05.051-.05.023-.025.023-.024.021-.024.02-.025.019-.024.018-.024.017-.023.015-.024.014-.023.013-.023.012-.023.01-.023.01-.022.008-.022.006-.023.006-.021.004-.022.004-.021.001-.021.001-.021-.001-.021-.001-.021-.004-.021-.004-.022-.006-.021-.006-.023-.008-.022-.01-.022-.01-.023-.012-.023-.013-.023-.014-.023-.015-.024-.017-.023-.018-.024-.019-.024-.02-.025-.021-.024-.023-.024-.023-.025-.051-.05-.056-.05-.06-.05-.065-.051-.07-.052-.074-.051-.079-.052-.083-.052-.088-.052-.092-.052-.096-.052-.101-.052-.106-.052-.11-.052-.114-.052-.118-.051-.123-.051-.126-.051-.131-.05-.136-.05-.139-.049-.143-.048-.148-.048-.152-.048-.155-.046-.16-.046-.163-.045-.168-.043-.172-.043-.175-.042-.179-.041-.183-.04-.187-.038-.191-.038-.194-.036-.198-.034-.202-.033-.205-.032-.21-.031-.212-.028-.216-.027-.22-.026-.224-.023-.226-.022-.231-.021-.233-.018-.237-.016-.241-.014-.244-.012-.247-.011-.25-.008-.254-.005-.257-.004-.26-.001-.26.001z" transform="scale(.5)"></path></symbol></defs><defs><symbol height="24" width="24" id="clock"><path d="M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.848 12.459c.202.038.202.333.001.372-1.907.361-6.045 1.111-6.547 1.111-.719 0-1.301-.582-1.301-1.301 0-.512.77-5.447 1.125-7.445.034-.192.312-.181.343.014l.985 6.238 5.394 1.011z" transform="scale(.5)"></path></symbol></defs><defs><marker orient="auto" markerHeight="12" markerWidth="12" markerUnits="userSpaceOnUse" refY="5" refX="9" id="arrowhead"><path d="M 0 0 L 10 5 L 0 10 z"></path></marker></defs><defs><marker refY="5" refX="4" orient="auto" markerHeight="8" markerWidth="15" id="crosshead"><path d="M 1,2 L 6,7 M 6,2 L 1,7" stroke-width="1pt" style="stroke-dasharray: 0px, 0px;" stroke="#000000" fill="none"></path></marker></defs><defs><marker orient="auto" markerHeight="28" markerWidth="20" refY="7" refX="18" id="filled-head"><path d="M 18,7 L9,13 L14,7 L9,1 Z"></path></marker></defs><defs><marker orient="auto" markerHeight="40" markerWidth="60" refY="15" refX="15" id="sequencenumber"><circle r="6" cy="15" cx="15"></circle></marker></defs><g><rect class="note" ry="0" rx="0" height="39" width="160" stroke="#666" fill="#EDF2AE" y="75" x="-5"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="80" x="75"><tspan x="75">Mask all interrupts</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="202" stroke="#666" fill="#EDF2AE" y="124" x="-26"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="129" x="75"><tspan x="75">Start resource cleanup...</tspan></text></g><g></g><g><rect class="note" ry="0" rx="0" height="39" width="150" stroke="#666" fill="#EDF2AE" y="281" x="217"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="286" x="292"><tspan x="292">Start a task</tspan></text></g><g><rect class="activation0" ry="0" rx="0" height="253" width="10" stroke="#666" fill="#EDF2AE" y="322" x="287"></rect></g><g><rect class="note" ry="0" rx="0" height="39" width="150" stroke="#666" fill="#EDF2AE" y="330" x="217"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="335" x="292"><tspan x="292">Hang!</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="150" stroke="#666" fill="#EDF2AE" y="487" x="217"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="492" x="292"><tspan x="292">...</tspan></text></g><g><rect class="note" ry="0" rx="0" height="39" width="467" stroke="#666" fill="#EDF2AE" y="536" x="50"></rect><text dy="1em" class="noteText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="541" x="284"><tspan x="284">System hangs!</tspan></text></g><text dy="1em" class="messageText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="178" x="186">Create a thread</text><line marker-end="url(#arrowhead)" style="fill: none;" stroke="none" stroke-width="2" class="messageLine0" y2="217" x2="292" y1="217" x1="80"></line><text dy="1em" class="messageText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="232" x="286">Arm</text><line marker-end="url(#arrowhead)" style="fill: none;" stroke="none" stroke-width="2" class="messageLine0" y2="271" x2="492" y1="271" x1="80"></line><text dy="1em" class="messageText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="384" x="286">Fire</text><line marker-end="url(#arrowhead)" style="fill: none;" stroke="none" stroke-width="2" class="messageLine0" y2="423" x2="80" y1="423" x1="492"></line><text dy="1em" class="messageText" style="font-size: 16px; font-weight: 400;" alignment-baseline="middle" dominant-baseline="middle" text-anchor="middle" y="438" x="184">Deliver an interrupt</text><line marker-end="url(#arrowhead)" style="fill: none;" stroke="none" stroke-width="2" class="messageLine0" y2="477" x2="287" y1="477" x1="80"></line></svg>

<p>This also means <code class="language-plaintext highlighter-rouge">AutoHCK::ResourceScope</code> cannot be modified in a thread that can
have an interrupt other than <code class="language-plaintext highlighter-rouge">AutoHCKInterrupt</code>.</p>

<h2 id="conclusion">Conclusion</h2>

<p>We discussed the resource scope as an alternative to the garbage collector, and
how to implement it in Ruby. There is no single universal way to manage
resources. For example, Chromium, a large program written in C++, uses all
of <a href="https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md">a garbage collector</a>,
<a href="https://chromium.googlesource.com/chromium/src/+/master/base/memory/">reference counting and resource scope</a>.
Sometimes you may find something missing in the programming platform and you may
need to implement it by yourself. In such a case, carefully design your own
solution and also watch out for platform-specific pitfalls.</p>]]></content><author><name>Akihiko Odaki</name></author><summary type="html"><![CDATA[Ruby logo]]></summary></entry><entry><title type="html">Developing QEMU on Asahi Linux (or Arm in general)</title><link href="https://daynix.github.io/2023/06/03/developing-qemu-on-asahi-linux-linux-port-for-apple-silicon.html" rel="alternate" type="text/html" title="Developing QEMU on Asahi Linux (or Arm in general)" /><published>2023-06-03T06:00:00+00:00</published><updated>2023-06-03T06:00:00+00:00</updated><id>https://daynix.github.io/2023/06/03/developing-qemu-on-asahi-linux-linux-port-for-apple-silicon</id><content type="html" xml:base="https://daynix.github.io/2023/06/03/developing-qemu-on-asahi-linux-linux-port-for-apple-silicon.html"><![CDATA[<svg viewBox="0 0 2500 700" version="1.1" xml:space="preserve" style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2" id="svg92" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"><title id="title880">Asahi Linux logo</title><metadata id="metadata98"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title>Asahi Linux logo</dc:title><cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" /><dc:date>2021-01-03</dc:date><dc:creator><cc:Agent><dc:title>soundflora* / marcan</dc:title></cc:Agent></dc:creator><dc:contributor><cc:Agent><dc:title>Font: Bangla MN (c) 2009 Muthu Nedumaran
Used with permission</dc:title></cc:Agent></dc:contributor><dc:rights><cc:Agent><dc:title>CC BY-SA 4.0 / (c) 2021 soundflora*</dc:title></cc:Agent></dc:rights></cc:Work><cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/"><cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction" /><cc:permits rdf:resource="http://creativecommons.org/ns#Distribution" /><cc:requires rdf:resource="http://creativecommons.org/ns#Notice" /><cc:requires rdf:resource="http://creativecommons.org/ns#Attribution" /><cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /><cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike" /></cc:License></rdf:RDF></metadata><defs id="defs96" />
    
<g id="layer8" style="display:inline" transform="matrix(2.9388721,0,0,2.9388721,1515.3356,107.104)"><g id="g2019" transform="matrix(1.0740314,0,0,1.0740314,0.02039,20.77591)" style="clip-rule:evenodd;display:inline;fill-rule:evenodd;stroke-width:0.931068;stroke-linejoin:round;stroke-miterlimit:2"><g transform="matrix(6.8429911,0,0,6.8429911,-781.84064,-1365.7951)" id="g1731-0" style="clip-rule:evenodd;display:inline;opacity:1;fill-rule:evenodd;stroke-width:0.931068;stroke-linejoin:round;stroke-miterlimit:2"><g transform="matrix(12,0,0,12,78.5809,213.091)" id="g1693-7" style="stroke-width:0.931068"><path d="M 0.388,-0.753 0.735,0 H 0.609 L 0.497,-0.246 H 0.181 L 0.064,0 H 0.002 l 0.355,-0.753 z m -0.186,0.46 H 0.474 L 0.34,-0.585 Z" style="fill:#2c2c2c;fill-rule:nonzero;stroke-width:0.931068" id="path1691-8" /></g><g transform="matrix(12,0,0,12,87.4276,213.091)" id="g1697-6" style="stroke-width:0.931068"><path d="m 0.272,-0.027 c 0.015,0 0.029,-0.003 0.042,-0.007 C 0.327,-0.039 0.338,-0.045 0.347,-0.053 0.357,-0.061 0.364,-0.07 0.369,-0.08 0.375,-0.09 0.377,-0.1 0.377,-0.111 0.377,-0.129 0.373,-0.144 0.364,-0.157 0.355,-0.17 0.344,-0.181 0.33,-0.191 0.315,-0.202 0.299,-0.211 0.281,-0.219 0.263,-0.228 0.244,-0.237 0.226,-0.246 0.207,-0.255 0.188,-0.265 0.17,-0.275 0.152,-0.285 0.136,-0.297 0.121,-0.311 0.107,-0.324 0.096,-0.34 0.087,-0.358 0.078,-0.376 0.074,-0.397 0.074,-0.421 c 0,-0.023 0.005,-0.044 0.014,-0.063 0.01,-0.02 0.023,-0.036 0.041,-0.05 0.017,-0.015 0.037,-0.026 0.061,-0.034 0.024,-0.007 0.05,-0.011 0.078,-0.011 0.019,0 0.036,0.001 0.053,0.003 0.016,0.003 0.032,0.008 0.048,0.015 0.015,0.008 0.031,0.018 0.047,0.032 0.015,0.014 0.032,0.032 0.049,0.055 L 0.423,-0.437 C 0.402,-0.472 0.378,-0.499 0.351,-0.516 0.325,-0.533 0.297,-0.542 0.267,-0.542 c -0.017,0 -0.031,0.002 -0.045,0.006 -0.013,0.004 -0.024,0.009 -0.034,0.016 -0.009,0.007 -0.017,0.015 -0.022,0.024 -0.006,0.01 -0.008,0.02 -0.008,0.03 0,0.017 0.005,0.032 0.014,0.044 0.009,0.013 0.022,0.024 0.037,0.034 0.016,0.011 0.034,0.02 0.054,0.029 0.019,0.008 0.04,0.017 0.06,0.026 0.021,0.009 0.041,0.018 0.061,0.029 0.019,0.01 0.037,0.022 0.053,0.035 0.015,0.014 0.028,0.03 0.037,0.047 0.01,0.018 0.014,0.039 0.014,0.063 0,0.024 -0.004,0.046 -0.013,0.067 -0.009,0.021 -0.022,0.039 -0.04,0.054 C 0.417,-0.022 0.394,-0.01 0.367,-0.001 0.34,0.008 0.308,0.012 0.272,0.012 0.255,0.012 0.238,0.011 0.22,0.008 0.203,0.006 0.185,0.001 0.167,-0.007 0.149,-0.015 0.132,-0.025 0.114,-0.039 0.096,-0.053 0.079,-0.071 0.062,-0.093 l 0.046,-0.041 c 0.013,0.019 0.027,0.035 0.039,0.049 0.013,0.013 0.026,0.024 0.039,0.033 0.013,0.009 0.027,0.015 0.04,0.019 0.014,0.004 0.029,0.006 0.046,0.006 z" style="fill:#2c2c2c;fill-rule:nonzero;stroke-width:0.931068" id="path1695-8" /></g><g transform="matrix(12,0,0,12,94.0076,213.091)" id="g1701-8" style="stroke-width:0.931068"><path d="M 0.454,0 C 0.439,-0.007 0.427,-0.018 0.416,-0.031 0.406,-0.045 0.401,-0.06 0.401,-0.078 0.388,-0.068 0.375,-0.057 0.362,-0.047 0.349,-0.036 0.335,-0.026 0.32,-0.018 0.305,-0.009 0.289,-0.002 0.27,0.004 0.252,0.009 0.231,0.012 0.207,0.012 0.184,0.012 0.164,0.009 0.146,0.001 0.128,-0.006 0.113,-0.016 0.101,-0.028 0.088,-0.041 0.079,-0.056 0.072,-0.073 0.065,-0.091 0.062,-0.109 0.062,-0.129 c 0,-0.025 0.004,-0.047 0.014,-0.067 0.01,-0.019 0.023,-0.037 0.04,-0.052 0.017,-0.015 0.036,-0.029 0.058,-0.041 0.023,-0.012 0.046,-0.023 0.072,-0.032 0.025,-0.01 0.051,-0.018 0.077,-0.026 0.027,-0.007 0.053,-0.014 0.078,-0.02 V -0.403 C 0.401,-0.429 0.399,-0.451 0.396,-0.468 0.392,-0.486 0.386,-0.5 0.378,-0.511 0.371,-0.522 0.361,-0.53 0.349,-0.535 0.337,-0.539 0.322,-0.542 0.306,-0.542 c -0.016,0 -0.031,0.003 -0.044,0.01 -0.014,0.006 -0.025,0.014 -0.036,0.025 -0.01,0.011 -0.018,0.023 -0.025,0.037 -0.006,0.015 -0.01,0.03 -0.013,0.046 H 0.085 c 0.003,-0.025 0.011,-0.047 0.025,-0.066 0.014,-0.019 0.032,-0.035 0.053,-0.049 0.021,-0.013 0.045,-0.023 0.072,-0.03 0.027,-0.007 0.054,-0.01 0.083,-0.01 0.037,0 0.068,0.003 0.094,0.01 0.025,0.008 0.045,0.018 0.06,0.031 0.015,0.013 0.026,0.028 0.033,0.047 0.006,0.019 0.009,0.04 0.009,0.062 v 0.351 c 0,0.018 0.006,0.033 0.016,0.047 C 0.54,-0.018 0.552,-0.007 0.567,0 Z M 0.401,-0.331 c -0.016,0.005 -0.033,0.011 -0.05,0.018 -0.018,0.006 -0.035,0.014 -0.052,0.022 -0.016,0.009 -0.032,0.017 -0.047,0.027 -0.016,0.01 -0.029,0.02 -0.04,0.031 -0.012,0.011 -0.021,0.023 -0.028,0.035 -0.006,0.012 -0.01,0.025 -0.01,0.039 0,0.014 0.003,0.027 0.008,0.039 0.005,0.013 0.012,0.024 0.021,0.033 0.008,0.009 0.018,0.017 0.029,0.022 0.011,0.006 0.023,0.008 0.035,0.008 0.012,0 0.024,-0.001 0.036,-0.005 0.011,-0.003 0.022,-0.008 0.033,-0.013 0.011,-0.006 0.022,-0.013 0.032,-0.02 0.011,-0.007 0.022,-0.015 0.033,-0.024 z" style="fill:#2c2c2c;fill-rule:nonzero;stroke-width:0.931068" id="path1699-4" /></g><g transform="matrix(12,0,0,12,101.174,213.091)" id="g1705-3" style="stroke-width:0.931068"><path d="m 0.213,-0.464 c 0.034,-0.039 0.07,-0.068 0.107,-0.087 0.037,-0.019 0.075,-0.028 0.113,-0.028 0.02,0 0.039,0.004 0.056,0.013 0.017,0.009 0.032,0.021 0.045,0.037 0.013,0.015 0.024,0.033 0.031,0.054 0.007,0.021 0.011,0.044 0.011,0.067 V 0 H 0.463 v -0.388 c 0,-0.038 -0.008,-0.067 -0.025,-0.086 -0.017,-0.02 -0.039,-0.029 -0.066,-0.029 -0.012,0 -0.024,0.002 -0.038,0.006 -0.013,0.004 -0.026,0.009 -0.04,0.017 -0.014,0.007 -0.028,0.016 -0.041,0.026 -0.014,0.01 -0.027,0.021 -0.04,0.033 V 0 H 0.1 v -0.827 l 0.081,-0.032 h 0.032 z" style="fill:#2c2c2c;fill-rule:nonzero;stroke-width:0.931068" id="path1703-1" /></g><g transform="matrix(12,0,0,12,109.288,213.091)" id="g1709-4" style="stroke-width:0.931068"><path d="M 0.109,-0.547 0.188,-0.579 H 0.221 V 0 H 0.109 Z M 0.1,-0.787 c 0,-0.009 0.002,-0.017 0.005,-0.025 0.003,-0.007 0.008,-0.014 0.014,-0.02 0.006,-0.006 0.013,-0.011 0.02,-0.014 0.008,-0.003 0.017,-0.005 0.025,-0.005 0.009,0 0.018,0.002 0.025,0.005 0.008,0.003 0.015,0.008 0.021,0.014 0.006,0.006 0.011,0.013 0.014,0.02 0.003,0.008 0.005,0.016 0.005,0.025 0,0.009 -0.002,0.018 -0.005,0.025 -0.003,0.008 -0.008,0.015 -0.014,0.021 -0.006,0.006 -0.013,0.01 -0.021,0.014 -0.007,0.003 -0.016,0.005 -0.025,0.005 -0.008,0 -0.017,-0.002 -0.025,-0.005 C 0.132,-0.731 0.125,-0.735 0.119,-0.741 0.113,-0.747 0.108,-0.754 0.105,-0.762 0.102,-0.769 0.1,-0.778 0.1,-0.787 Z" style="fill:#2c2c2c;fill-rule:nonzero;stroke-width:0.931068" id="path1707-9" /></g><g transform="matrix(12,0,0,12,116.034,213.091)" id="g1713-2" style="stroke-width:0.931068"><path d="m 0.1,-0.737 h 0.124 v 0.689 H 0.595 V 0 H 0.1 Z" style="fill:#2c2c2c;fill-rule:nonzero;stroke-width:0.931068" id="path1711-0" /></g><g transform="matrix(12,0,0,12,123.301,213.091)" id="g1717-6" style="stroke-width:0.931068"><path d="M 0.109,-0.547 0.188,-0.579 H 0.221 V 0 H 0.109 Z M 0.1,-0.787 c 0,-0.009 0.002,-0.017 0.005,-0.025 0.003,-0.007 0.008,-0.014 0.014,-0.02 0.006,-0.006 0.013,-0.011 0.02,-0.014 0.008,-0.003 0.017,-0.005 0.025,-0.005 0.009,0 0.018,0.002 0.025,0.005 0.008,0.003 0.015,0.008 0.021,0.014 0.006,0.006 0.011,0.013 0.014,0.02 0.003,0.008 0.005,0.016 0.005,0.025 0,0.009 -0.002,0.018 -0.005,0.025 -0.003,0.008 -0.008,0.015 -0.014,0.021 -0.006,0.006 -0.013,0.01 -0.021,0.014 -0.007,0.003 -0.016,0.005 -0.025,0.005 -0.008,0 -0.017,-0.002 -0.025,-0.005 C 0.132,-0.731 0.125,-0.735 0.119,-0.741 0.113,-0.747 0.108,-0.754 0.105,-0.762 0.102,-0.769 0.1,-0.778 0.1,-0.787 Z" style="fill:#2c2c2c;fill-rule:nonzero;stroke-width:0.931068" id="path1715-8" /></g><g transform="matrix(12,0,0,12,127.248,213.091)" id="g1721-9" style="stroke-width:0.931068"><path d="m 0.181,-0.579 h 0.032 v 0.115 c 0.035,-0.039 0.071,-0.068 0.108,-0.087 0.037,-0.019 0.074,-0.028 0.112,-0.028 0.02,0 0.039,0.004 0.056,0.013 0.017,0.009 0.032,0.021 0.045,0.037 0.013,0.015 0.024,0.033 0.031,0.054 0.007,0.021 0.011,0.044 0.011,0.067 V 0 H 0.463 v -0.388 c 0,-0.019 -0.002,-0.036 -0.006,-0.05 C 0.452,-0.452 0.446,-0.464 0.438,-0.474 0.43,-0.484 0.42,-0.491 0.409,-0.496 0.398,-0.501 0.386,-0.503 0.373,-0.503 c -0.012,0 -0.025,0.002 -0.038,0.006 -0.013,0.004 -0.027,0.009 -0.041,0.017 -0.014,0.007 -0.028,0.016 -0.041,0.026 -0.014,0.01 -0.027,0.021 -0.04,0.033 V 0 H 0.1 v -0.548 z" style="fill:#2c2c2c;fill-rule:nonzero;stroke-width:0.931068" id="path1719-2" /></g><g transform="matrix(12,0,0,12,135.294,213.091)" id="g1725-6" style="stroke-width:0.931068"><path d="m 0.213,-0.569 v 0.405 c 0,0.014 0.004,0.028 0.01,0.04 0.007,0.013 0.016,0.024 0.027,0.033 0.011,0.009 0.025,0.016 0.04,0.022 0.015,0.005 0.031,0.008 0.048,0.008 0.011,0 0.023,-0.003 0.036,-0.007 0.013,-0.005 0.025,-0.012 0.038,-0.02 0.012,-0.008 0.023,-0.018 0.034,-0.029 0.01,-0.012 0.019,-0.024 0.027,-0.036 V -0.569 H 0.585 V 0 H 0.473 V -0.107 C 0.463,-0.09 0.45,-0.075 0.435,-0.061 0.42,-0.046 0.404,-0.034 0.387,-0.023 0.369,-0.012 0.351,-0.004 0.333,0.003 0.314,0.009 0.297,0.012 0.28,0.012 0.255,0.012 0.232,0.008 0.21,-0.002 0.188,-0.011 0.169,-0.024 0.153,-0.039 0.136,-0.055 0.124,-0.074 0.114,-0.096 0.105,-0.117 0.1,-0.14 0.1,-0.164 v -0.405 z" style="fill:#2c2c2c;fill-rule:nonzero;stroke-width:0.931068" id="path1723-6" /></g><g transform="matrix(12,0,0,12,143.514,213.091)" id="g1729-4" style="stroke-width:0.931068"><path d="M 0.006,-0.569 H 0.139 L 0.532,0 H 0.399 Z M 0.067,0 H 0.006 L 0.47,-0.569 h 0.062 z" style="fill:#2c2c2c;fill-rule:nonzero;stroke-width:0.931068" id="path1727-9" /></g></g></g></g><g id="layer7" style="display:inline" transform="translate(350,612.5)"><path id="path1639" style="color:#000000;overflow:visible;fill:#2c2c2c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:0.5;paint-order:stroke markers fill" d="M 475,150 H 350 L 349.998,550 483.73242,455.27344 460,390 515.63477,432.67383 600,372.91602 Z" transform="translate(-350,-550)" /><path style="color:#000000;overflow:visible;fill:#d3506f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:0.5;paint-order:stroke markers fill" d="M -250,-177.08333 0,0 15,-45 21.340931,-300 0,-347.67442 5e-5,-360 -100,-400 h -25 z" id="path1627" /><path style="color:#000000;overflow:visible;fill:#a61200;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:0.5;paint-order:stroke markers fill" d="M -125,-400 0,-442.45283 59.405965,-422.27722 40,-405 l 85,5 -125,52.32558" id="path1629" /><path style="color:#000000;overflow:visible;fill:#00a67c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:0.5;paint-order:stroke markers fill" d="M -24.999998,-475 H 50 l -10,-50 z" id="path1631" /><path style="color:#000000;overflow:visible;fill:#edbb60;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:0.5;paint-order:stroke markers fill" d="M 4.9025e-5,-400 5e-5,-525 l -50.000053,25 z" id="path1633" /><path style="color:#000000;overflow:visible;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:0.5;paint-order:stroke markers fill" d="M 133.73205,-94.726837 100.91329,-140.33988 -0.00182072,0 0,-347.67442 165.63569,-117.32525 Z" id="path1641" /><path style="color:#000000;overflow:visible;fill:#96caf3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:0.5;paint-order:stroke markers fill" d="M 40,-106.7907 V -225 l 42.566303,59.10669 z" id="path1643" /><path style="color:#000000;overflow:visible;opacity:1;fill:#530900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.803;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:0.5;paint-order:stroke markers fill" d="M 4.9025e-5,-400 H 125 l -65.594035,-22.27722" id="path1955" /></g></svg>

<p>Recently I described
<a href="https://daynix.github.io/2023/05/06/igb-developing-a-new-device-for-qemu-part-1-introduction.html">how igb, a new Intel NIC support for QEMU, was added</a>
here. The development was done on an x86 machine until I buy a M2 Macbook Air,
which carries Arm-based Apple Silicon. This computer is way faster than the x86
machine so I decided to use <a href="https://asahilinux.org/">Asahi Linux</a>, a community
port of Linux for Apple Silicon and to move the development to this new machine.</p>

<p>You can find details like currently supported features on
<a href="https://github.com/AsahiLinux/docs/wiki">its wiki</a> and fantastic write-ups
about the development on <a href="https://asahilinux.org/blog/">its blog</a>. Here, I
describe what worked well during my QEMU development on the platform, or what
didn’t (and how I fixed them).</p>

<h2 id="asahi-linux-usually-works-well">Asahi Linux (usually) works well</h2>

<p>Asahi Linux works so well, which may be surprising if you don’t closely follow
the development, finding skilled and motivated developers and tooling like
<a href="https://github.com/AsahiLinux/m1n1">m1n1 hypervisor</a>.</p>

<p><a href="https://asahilinux.org/2022/12/gpu-drivers-now-in-asahi-linux/">The introduction of GPU driver</a>
made it truly pleasant to work with. The GPU driver is one of the challenging
features and while it still lacks functionalities of modern OpenGL versions like
4.0+, it implements everything that is needed to provide a decent desktop
experience. Things I regularly use like GNOME, Firefox, Thunderbird, and
Visual Studio Code all work just fine<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>.</p>

<p>And the GPU driver was <em>the last missing piece</em> for the simple workload. There
are many things not implemented like speakers, cameras, and external display
support. However, Asahi Linux is perfect if you just need the keyboard, touchpad
(with multi-finger detection), display, audio jack, (minimal) power management,
and USB. It’s perfect for QEMU development.</p>

<h2 id="when-asahi-linux-does-not-work-well">When Asahi Linux does not work well</h2>

<h3 id="legacy-programs">Legacy programs</h3>

<p>If your desktop environment on Asahi Linux does not work well, it’s probably
because your configuration includes legacy components, notably Pulse Audio and
X.</p>

<p>Well, Pulse Audio is not <em>that</em> old compared to X, but
<a href="https://asahilinux.org/2022/11/november-2022-report/#audio-advances-track--1">it’s known to be faulty on Asahi Linux</a>
so it’s better to use PipeWire.</p>

<p>X is known for various protocol limitations that are nearly impossible to fix.
Fortunately, Wayland compositors that substitute X are so mature today that you
find fewer quirks on Wayland compositors than X. I see nothing quirky with
GNOME’s Wayland implementation these days.</p>

<h3 id="superficial-lack-of-arm-support">(Superficial) lack of Arm support</h3>

<p>The more serious problem in practice is (superficial) lack of Arm support on
Linux system. Arm is supported well by Linux kernel and userspace when compared
with other non-x86 architectures like RISC-V, but you likely find something
missing.</p>

<p>The reason I call it <em>superficial</em> is that in many cases things do not work just
because Arm is not listed in the list of supported architectures. For example,
many packages on Flathub are not available on Arm just because they are marked
only for x86_64. Such things just work fine by adding Arm as a supported
architecture.</p>

<p>Some programs actually lack Arm support. Adding Arm support is usually not hard
in such a case either as <em>the hard part</em> like porting runtimes with JIT
compilers is already done for Arm.</p>

<p>An emulator like <a href="https://fex-emu.com/">FEX</a> help in unfortunate cases of binary
distribution.</p>

<h3 id="lack-of-biglittle-support">Lack of big.LITTLE support</h3>

<p>It seems big.LITTLE confuses some programs that assume only one processor type
is supported and they need to be handled separately.</p>

<h2 id="what-did-not-work-for-me-on-asahi-linux-and-how-i-fixed-them">What did not work for me on Asahi Linux and how I fixed them</h2>

<p>As I described earlier, usually Asahi Linux just works. If something does not
work, well, it’s a chance for an open-source contribution. This section
describes what didn’t work and how I fixed them. The fixes are all applicable
for any Arm or big.LITTLE systems, meaning fixes for Asahi Linux actually
benefits the entire Arm community.</p>

<h3 id="kvm-and-biglittle">KVM and big.LITTLE</h3>

<p>KVM works fine if you pin the vCPU threads only to big or LITTLE cores; it
magically fails if you don’t. Unfortunately, QEMU does not support pinning vCPU
threads to distinct cores<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup> so you can’t use both big and LITTLE cores on a
VM at the same time.</p>

<p>It is somewhat unsafe to allow a vCPU thread to migrate between big and LITTLE
cores. An operating system often carries workarounds for cores and can be
confused by such migration. To limit the confusion, the register that identifies
the processor must be overridden. This requires extra caution and
<a href="https://qemu.readthedocs.io/en/v8.0.0/system/qemu-cpu-models.html">QEMU has lengthy documentation to describe safe configurations for x86</a>.
KVM on Arm64 does not support overriding the register, <code class="language-plaintext highlighter-rouge">MIDR</code> anyway<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup>.
Nevertheless, I decided to use this <em>unsafe</em> configuration because it should
work for me™.</p>

<p>When QEMU fails with big.LITTLE, the serial console outputs the following before
it shows GRUB menu:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Synchronous Exception at 0xXXXXXXXXXXXXXXXX
</code></pre></div></div>

<p>This corresponds to a line in
<a href="https://github.com/tianocore/edk2/blob/edk2-stable202305/ArmPkg/Library/DefaultExceptionHandlerLib/AArch64/DefaultExceptionHandler.c#L208">EDK2</a>
so something in EDK2 should have gone wrong. To investigate further, I built
EDK2 with debug information and ran it to find that it results in an assertion
failure in
<a href="https://github.com/tianocore/edk2/blob/edk2-stable202305/ArmPlatformPkg/PrePi/MainUniCore.c">the following function of <code class="language-plaintext highlighter-rouge">ArmPlatformPkg/PrePi/MainUniCore.c</code></a>:</p>
<pre><code class="language-C">VOID
EFIAPI
SecondaryMain (
  IN UINTN  MpId
  )
{
  ASSERT (FALSE);
}
</code></pre>

<p>This implies the following possibilities:</p>
<ol>
  <li>EDK2 wrongly used <code class="language-plaintext highlighter-rouge">MainUniCore.c</code> for QEMU.</li>
  <li>QEMU wrongly started secondary processors.</li>
</ol>

<p>I decided to investigate possibility 2. KVM should have some interface to start
or not to start vCPU so I looked at
<a href="https://www.kernel.org/doc/html/v6.3/virt/kvm/api.html#kvm-arm-vcpu-init">the kernel documentation</a>
and found <code class="language-plaintext highlighter-rouge">KVM_ARM_VCPU_POWER_OFF</code> is passed to <code class="language-plaintext highlighter-rouge">KVM_ARM_VCPU_INIT</code> ioctl to
start vCPU is started powered off, and <code class="language-plaintext highlighter-rouge">KVM_SET_MP_STATE</code> ioctl is used to start
or stop vCPU during execution. I instrumented both ioctl calls and pinned QEMU
to big cores to see how they should work in an ideal state.</p>

<p>Surprisingly, QEMU didn’t start secondary processors but used <code class="language-plaintext highlighter-rouge">KVM_SET_MP_STATE</code>
ioctl to make vCPU stopped instead of passing the <code class="language-plaintext highlighter-rouge">KVM_ARM_VCPU_POWER_OFF</code> flag
to <code class="language-plaintext highlighter-rouge">KVM_ARM_VCPU_INIT</code>. Anyway, I looked at the QEMU code to find what caused
the <code class="language-plaintext highlighter-rouge">KVM_SET_MP_STATE</code> ioctl, which led to the following lines:</p>

<pre><code class="language-C">for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
    Object *cpuobj = OBJECT(cs);

    object_property_set_int(cpuobj, "psci-conduit", info-&gt;psci_conduit,
                            &amp;error_abort);
    /*
     * Secondary CPUs start in PSCI powered-down state. Like the
     * code in do_cpu_reset(), we assume first_cpu is the primary
     * CPU.
     */
    if (cs != first_cpu) {
        object_property_set_bool(cpuobj, "start-powered-off", true,
                                 &amp;error_abort);
    }
}
</code></pre>

<p>This proved possibility 2 is true. I then added <code class="language-plaintext highlighter-rouge">printf</code> before
<code class="language-plaintext highlighter-rouge">KVM_SET_MP_STATE</code> ioctl and ran QEMU without pinning vCPUs. Surprisingly the
ioctl was not called in this scenario.</p>

<p>Looking back at the execution path before QEMU reaches <code class="language-plaintext highlighter-rouge">KVM_SET_MP_STATE</code> ioctl,
I found the following lines at the end of the <code class="language-plaintext highlighter-rouge">kvm_arch_put_registers</code> function:</p>

<pre><code class="language-C">    if (!write_list_to_kvmstate(cpu, level)) {
        return -EINVAL;
    }

   /*
    * Setting VCPU events should be triggered after syncing the registers
    * to avoid overwriting potential changes made by KVM upon calling
    * KVM_SET_VCPU_EVENTS ioctl
    */
    ret = kvm_put_vcpu_events(cpu);
    if (ret) {
        return ret;
    }

    kvm_arm_sync_mpstate_to_kvm(cpu);

    return ret;
</code></pre>

<p>In a big.LITTLE environment, the <code class="language-plaintext highlighter-rouge">write_list_to_kvmstate</code> function fails when
writing <code class="language-plaintext highlighter-rouge">CCSIDR_EL1</code> register. This failure didn’t result in a user-friendly
message because the value <code class="language-plaintext highlighter-rouge">kvm_arch_put_registers</code> was never checked.
<a href="https://patchew.org/QEMU/20221201102728.69751-1-akihiko.odaki@daynix.com/">I submitted a fix to add error checks</a>,
but this of course doesn’t make it compatible with big.LITTLE.</p>

<p><code class="language-plaintext highlighter-rouge">CCSIDR_EL1</code> is not a register, but is an array of registers whose element is
selected with the <code class="language-plaintext highlighter-rouge">CSSELR_EL1</code> register. Each element describes a level of
cache. It looks a bit awkward in KVM; KVM calls such a register as a demux
register and exposes each element as a separate register. KVM usually does not
list read-only registers with <code class="language-plaintext highlighter-rouge">KVM_GET_REG_LIST</code> ioctl, but somehow it lists
demux registers even though they are read-only and writing different values
fails. This makes QEMU try to restore the <code class="language-plaintext highlighter-rouge">CCSIDR_EL1</code> values as VM states.</p>

<p>As big and LITTLE cores have different cache configurations, they have different
<code class="language-plaintext highlighter-rouge">CCSIDR_EL1</code> values, and migrating a vCPU thread between big and LITTLE cores
make the values change. If QEMU tries to restore <code class="language-plaintext highlighter-rouge">CCSIDR_EL1</code> values before
migration, it conflicts with the current values of <code class="language-plaintext highlighter-rouge">CCSIDR_EL1</code> and results in
an error.</p>

<p>After discussing with upstream maintainers, I decided to write patches to
generate a common cache configuration that looks valid for any physical CPU.
<a href="https://patchwork.kernel.org/project/linux-arm-kernel/list/?series=711156&amp;state=%2A&amp;archive=both">This patch is now merged and included since 6.3</a>.
Now you can run guests on QEMU/KVM without pinning to big or LITTLE cores.</p>

<p>Note that this configuration is strictly not safe as described above. There are
room for improvement in both KVM and QEMU when it comes to big.LITTLE-like
configuration.
<a href="https://gitlab.com/qemu-project/qemu/-/issues/777">Even Alder Lake, Intel’s own big.LITTLE design is not supported well on QEMU/KVM</a>.</p>

<h3 id="kvm-and-watchpoint">KVM and watchpoint</h3>

<p>Now QEMU/KVM works without doing anything special on Apple Silicon. However,
when debugging igb I realized the watchpoint exception passes through the host
and reaches the guest when I put watchpoint. QEMU receives the notification of
the watchpoint hit, but the notification shows some random address as the cause
of the watchpoint exception. This prevents QEMU from looking up the watchpoint
and makes it think the exception is not from the watchpoint QEMU set and passes
it to the guest.</p>

<p>It turned out that KVM just forgot to retrieve the address triggering the
watchpoint. This bug was present for a year and 8 months; you cannot expect such
a bug will be found soon like x86 bugs. It is still always possible to fix a bug
by yourself.</p>

<p><a href="https://patchwork.kernel.org/project/linux-arm-kernel/patch/20230530024651.10014-1-akihiko.odaki@daynix.com/">The fix is submitted to the upstream</a>
and will be backported to stable kernels soon.</p>

<h3 id="libvirt">libvirt</h3>

<p>The next thing I tried after QEMU is libvirt. Anything specific to architecture
should be handled by QEMU so I didn’t expect it to fail, but it did fail. It
executes QEMU to probe its features, but this probing QEMU process failed to
start.</p>

<p>It was easy to debug as QEMU showed a nice error message this time. It said
<code class="language-plaintext highlighter-rouge">KVM_CREATE_VM</code> ioctl fails with <code class="language-plaintext highlighter-rouge">EINVAL</code>. This ioctl has a <code class="language-plaintext highlighter-rouge">type</code> parameter
that defines the configuration of the VM. When the <code class="language-plaintext highlighter-rouge">none</code> machine type, which is
a machine that <em>does nothing</em>, is used for feature probing, QEMU passes <code class="language-plaintext highlighter-rouge">0</code> for
the parameter, meaning the VM should be created with the default configuration.</p>

<p>The default configuration should work for anyone, but Apple Silicon was an
exception. The <code class="language-plaintext highlighter-rouge">type</code> parameter in KVM/arm64 has a field called <code class="language-plaintext highlighter-rouge">IPA_Bits</code>,
which denotes the physical address size of the guest.
<a href="https://www.kernel.org/doc/html/v6.3/virt/kvm/api.html#kvm-create-vm">The kernel documentation describes it as follows:</a></p>

<blockquote>
  <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>The requested size (IPA_Bits) must be:

 ==   =========================================================
  0   Implies default size, 40bits (for backward compatibility)
  N   Implies N bits, where N is a positive integer such that,
      32 &lt;= N &lt;= Host_IPA_Limit
 ==   =========================================================

Host_IPA_Limit is the maximum possible value for IPA_Bits on the host and is
dependent on the CPU capability and the kernel configuration. The limit can be
retrieved using KVM_CAP_ARM_VM_IPA_SIZE of the KVM_CHECK_EXTENSION ioctl() at
run-time.
</code></pre></div>  </div>
</blockquote>

<p><code class="language-plaintext highlighter-rouge">Host_IPA_Limit</code> is 36 bits on Apple Silicon, meaning the default size, 40 bits,
is not valid for the system. 32 bits should work for anyone so
<a href="https://patchew.org/QEMU/20230109062259.79074-1-akihiko.odaki@daynix.com/">I submitted a patch to always specify 32 bits as <code class="language-plaintext highlighter-rouge">IPA_Bits</code> on Arm64</a>.</p>

<p>The kernel should hide most details of the underlying architecture, and even
leaked details should be covered by QEMU, but sometimes there are still leaked
details and a hardware-independent component like libvirt can fail due to that.</p>

<h3 id="qemu-memory-leak">QEMU memory leak</h3>

<p>Another bug I caught when using QEMU/KVM is a simple memory leak that always
happens in SMP configuration. It seemed nobody has tried LeakSanitizer on Arm64.
This was an easy one, and
<a href="https://gitlab.com/qemu-project/qemu/-/commit/ad5c6ddea327758daa9f0e6edd916be39dce7dca">the fix is already upstream</a>.</p>

<h3 id="lscpu">lscpu</h3>

<p>DPDK Test Suite uses lscpu to enumerate all cores and to identify them, but it
was not working properly on big.LITTLE system. lscpu shows something like the
following on big.LITTLE system:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Architecture:           aarch64
  CPU op-mode(s):       64-bit
  Byte Order:           Little Endian
CPU(s):                 8
  On-line CPU(s) list:  0-7
Vendor ID:              Apple
  Model name:           -
    Model:              0
    Thread(s) per core: 1
    Core(s) per socket: 4
    Socket(s):          1
    Stepping:           0x1
    CPU(s) scaling MHz: 25%
    CPU max MHz:        2424.0000
    CPU min MHz:        600.0000
    BogoMIPS:           48.00
    Flags:              fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 asimddp sha512 asimdfhm dit uscat ilrcpc flagm ssbs sb paca pacg dcpodp flagm2 frint i8mm bf16 bti ecv
  Model name:           -
    Model:              0
    Thread(s) per core: 1
    Core(s) per socket: 4
    Socket(s):          1
    Stepping:           0x1
    CPU(s) scaling MHz: 21%
    CPU max MHz:        3204.0000
    CPU min MHz:        660.0000
    BogoMIPS:           48.00
    Flags:              fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 asimddp sha512 asimdfhm dit uscat ilrcpc flagm ssbs sb paca pacg dcpodp flagm2 frint i8mm bf16 bti ecv
Caches (sum of all):    
  L1d:                  768 KiB (8 instances)
  L1i:                  1.3 MiB (8 instances)
  L2:                   20 MiB (2 instances)
Vulnerabilities:        
  Itlb multihit:        Not affected
  L1tf:                 Not affected
  Mds:                  Not affected
  Meltdown:             Not affected
  Mmio stale data:      Not affected
  Retbleed:             Not affected
  Spec store bypass:    Mitigation; Speculative Store Bypass disabled via prctl
  Spectre v1:           Mitigation; __user pointer sanitization
  Spectre v2:           Not affected
  Srbds:                Not affected
  Tsx async abort:      Not affected
</code></pre></div></div>

<p>Note that each CPU “model” has a field named “Socket(s)” and
“Core(s) per socket”. lscpu assumes different CPU models are installed into
different sockets (or another larger unit if present) and tells how many sockets
each model occupies, but in reality, they are on the same socket, and the CPU
package on the socket has 8 cores in total.</p>

<p>What is more awkward is the output of <code class="language-plaintext highlighter-rouge">lscpu -p=CPU,Core,Socket</code>. This command
is expected to give unique identifiers for CPUs (threads), cores, and sockets.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># The following is the parsable format, which can be fed to other
# programs. Each different item in every column has an unique ID
# starting usually from zero.
# CPU,Core,Socket
0,0,0
1,1,0
2,2,0
3,3,0
4,0,0
5,1,0
6,2,0
7,3,0
</code></pre></div></div>

<p>Note that the same core number appears twice. It looks like this processor
implements SMT and a core has two threads, but in reality, the two threads are
in distinct cores. It is because the Core ID is assigned independently in each
CPU model type.
<a href="https://lore.kernel.org/util-linux/5092a67c-0b86-134a-df77-433a6db10900@daynix.com/T/">I proposed a patch to decouple the topology information from CPU model type</a>.</p>

<h3 id="pixman-on-arch-linux-arm">Pixman on Arch Linux ARM</h3>

<p><a href="https://lore.kernel.org/qemu-devel/483662d9-2565-db44-0e19-fb9128f28bde@eik.bme.hu/">I received a report that QEMU does not display correctly when emulating MorphOS on macOS on Apple Silicon</a>.
I tried the emulation on Asahi Linux and its display output also had glitches so
I assumed it should be a bug common for Arm or Apple Silicon. Eventually, I
realized Pixman library is not working so I built it myself to find it
surprisingly works.</p>

<p>The fact is that Arch Linux ARM copied the script to build Pixman for x86 to
reuse it for Arm, and it was forgot to enable Arm-specific code. It didn’t work
on macOS because
<a href="https://gitlab.freedesktop.org/pixman/pixman/-/issues/46">the Arm-specific code was disabled due to incompatibility with the LLVM assembler</a>.</p>

<p>I submitted a change to enable
<a href="https://github.com/archlinuxarm/PKGBUILDs/pull/1985">Arm-specific code for Arch Linux ARM</a>.
There is also
<a href="https://gitlab.freedesktop.org/pixman/pixman/-/merge_requests/71">a change proposed to make it compatible with LLVM assembler</a>.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Asahi Linux works very well. Sometimes it doesn’t when doing something
somewhat peculiar like using KVM, but it is often trivial to fix things even in
such a case. Perhaps it may not be recommended for everyone, but it’s a nice
platform for a software developer.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>Except for various WebGL pages, which may require functionalities not
  implemented yet. Providing environment variable <code class="language-plaintext highlighter-rouge">LIBGL_ALWAYS_SOFTWARE=1</code>
  only for such applications will solve the problem while not damaging the
  performance of the entire system. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>And I don’t know its performance implication. Please tell me if you know
  Linux scheduler internals and the answer. I know
  <a href="https://chromium.googlesource.com/chromiumos/platform/crosvm/">crosvm</a>
  has an option for this. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>Hypervisor.framework on macOS does support this. In general,
  Hypervisor.framework just exposes everything to the VMM and the kernel
  behaves like a shim. This gives greater control to VMM but also hurts the
  performance so this architecture is not suited for systems like servers
  that KVM targets. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Akihiko Odaki</name></author><summary type="html"><![CDATA[Asahi Linux logoimage/svg+xmlAsahi Linux logo2021-01-03soundflora* / marcanFont: Bangla MN (c) 2009 Muthu Nedumaran Used with permissionCC BY-SA 4.0 / (c) 2021 soundflora*]]></summary></entry><entry><title type="html">igb: Developing a new device for QEMU (part 4: Debugging and submitting patches)</title><link href="https://daynix.github.io/2023/06/01/igb-developing-a-new-device-for-qemu-part-4-debugging-and-submitting-patches.html" rel="alternate" type="text/html" title="igb: Developing a new device for QEMU (part 4: Debugging and submitting patches)" /><published>2023-06-01T08:00:00+00:00</published><updated>2023-06-01T08:00:00+00:00</updated><id>https://daynix.github.io/2023/06/01/igb-developing-a-new-device-for-qemu-part-4-debugging-and-submitting-patches</id><content type="html" xml:base="https://daynix.github.io/2023/06/01/igb-developing-a-new-device-for-qemu-part-4-debugging-and-submitting-patches.html"><![CDATA[<p>This is the last post of a walkthrough of new device emulator development for
QEMU which uses
<a href="https://qemu.readthedocs.io/en/v8.0.0/system/devices/igb.html">igb</a>,
a recently introduced Intel NIC emulation as an example.</p>

<p><a href="/2023/05/06/igb-developing-a-new-device-for-qemu-part-1-introduction.html">The first post</a>
roughly described there are several development steps:</p>

<ol>
  <li>Writing a boilerplate and adding basic features</li>
  <li>Adding QTest</li>
  <li>Adding advanced features and libvirt support</li>
  <li>Running more tests and increasing feature coverage</li>
  <li>Debugging</li>
  <li>Contributing to the upstream</li>
</ol>

<p>This post discusses 5 and 6. Though this post is written with new device
emulator development in mind, the debugging techniques shown here apply to other
kinds of QEMU development as well.</p>

<h2 id="debugging">Debugging</h2>

<p>Debugging is the most interesting (and tiresome) part of the device emulator
development.</p>

<p>The first step of debugging is to make a bug reproduction case. Usually, you will
start debugging by creating a minimal reproduction case, but it is often
impractical for low-level software like QEMU as the higher-level software
is just too big; you cannot trim Linux down. The higher-level software may even
lack source code (c.f., Windows). In such a situation, you can’t do anything but
use the real workload as a reproduction case. That also means
<em>there can be bugs anywhere</em>: guest user-space program, guest kernel,
QEMU, or even compiler.</p>

<p><a href="https://makeameme.org/meme/bugs-bugs-everywhere-4o3kqj"><img src="/bugs-bugs-everywhere.jpg" alt="BUGS - BUGS EVERYWHERE" /></a></p>

<p>But don’t worry. It is always possible to figure out a bug no matter how the
reproduction case is complex. You just need right tools, knowledge,
methodology, and patience.</p>

<h3 id="tools">Tools</h3>

<p>First, let me introduce useful tools. You can’t (or don’t want to) debug
everything just with <code class="language-plaintext highlighter-rouge">printf()</code>, but you don’t need dozens of tools either. The
most important thing is to choose tools according to the situation.</p>

<h4 id="hand-written-scripts">Hand-written scripts</h4>

<p>The first thing to do, even before you try to figure out the bug, is to make
the iterations fast. Write some scripts to automate repetitive tasks, especially
the program launch. Scripts I used during development are available at:
<a href="https://github.com/akihikodaki/q">https://github.com/akihikodaki/q</a></p>

<p>You can choose whatever script language. Below is possible options:</p>

<h5 id="shell-script">Shell script</h5>

<p>Shell is available everywhere so it may be handy. Unfortunately, it has various
quirks and compatibility issues.</p>

<h5 id="c">C</h5>

<p>C is actually not that bad. Basically, you just need to call <code class="language-plaintext highlighter-rouge">system()</code>
everywhere and omit error handling to write it “script-like”.</p>

<p>The downside is that it requires compiling and is bad at error handling.</p>

<h5 id="ruby">Ruby</h5>

<p>An interesting characteristic of Ruby is that it exposes various Unix functions.
<a href="https://ruby-doc.org/3.2.2/exts/fiddle/Fiddle.html">It can also call C functions without any external library</a>
so you can have unlimited access to the underlying system.</p>

<p>While Ruby is a good option for <em>system</em> scripting as described above, it is not
as popular as Python or JavaScript. For example, Visual Studio Code comes with
mature support for Python and JavaScript, but Microsoft does not directly
provide support for Ruby.</p>

<h5 id="nodejs">Node.js</h5>

<p>Node.js employs JavaScript language. Modern JavaScript is comfortable to write,
and its rich documentation on <a href="https://developer.mozilla.org/">MDN</a> and
<a href="https://www.ecma-international.org/publications-and-standards/standards/ecma-262/">formal specification</a>
are helpful if you are not familiar with the language.</p>

<p>Node.js’ asynchronous nature is also attractive for scripting. For example,
if you need to <code class="language-plaintext highlighter-rouge">buildProject()</code> and <code class="language-plaintext highlighter-rouge">copyFiles()</code> (assuming both of them return
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises">Promise</a>)
in parallel, you can just write as follows:</p>

<pre><code class="language-JavaScript">await Promise.all([buildProject(), copyFiles()])
</code></pre>

<p><a href="https://github.com/google/zx">Google’s zx</a> makes it even easier to write
scripts.</p>

<p>However, Node.js is somewhat more restrictive than Ruby so you cannot easily
interact with file descriptors, for example.</p>

<h4 id="git-bisect">git-bisect</h4>

<p><a href="https://git-scm.com/docs/git-bisect">The man page</a> says:</p>
<blockquote>
  <p>git-bisect - Use binary search to find the commit that introduced a bug</p>
</blockquote>

<p>In principle, it’s so simple and very effective to debug regressions, but
sometimes the bug you are debugging may involve several regressions introduced
in different commits. Naively performing binary search may not be sufficient in
such a case so you need to keep considering what is happening during git-bisect.</p>

<h4 id="sanitizers">Sanitizers</h4>

<p><a href="https://github.com/google/sanitizers">Sanitizers</a> detect common bugs in C code
at runtime. AddressSanitizer and UndefinedBehaviorSanitizer can be enabled by
passing the <code class="language-plaintext highlighter-rouge">--enable-sanitizers</code> flag to the <code class="language-plaintext highlighter-rouge">configure</code> script. I recommend
keeping them enabled.</p>

<p>Note that the entire QEMU code base is not free of addressability issues and
undefined behaviors. It’s better to keep your workload minimal to avoid noise
from existing issues. There were several noisy bugs affecting my minimal
workload so I fixed them to keep the console clean<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup><sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup><sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup><sup id="fnref:4" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">4</a></sup>.</p>

<h4 id="printf">printf()</h4>

<p>It may sound stupid but, in fact, <em><code class="language-plaintext highlighter-rouge">printf()</code> is a great tool for debugging</em>. It
works everywhere, and it has all of the expressiveness of the programming
language. Want the state of the program when the loop count is 42? Just write
<code class="language-plaintext highlighter-rouge">if (i == 42)</code>. Need to parse the bytes in an array? Write a parsing function
and call it. It’s so simple and effective.</p>

<p>A downside is that such code can be often left after debugging. You may annotate
the logging code with a debug flag to pollute the console, which <em>mitigates</em> the
problem but does not <em>solve</em> it; it’ll still end up with a lot of logs you
cannot really digest when the debug flag is set.</p>

<p>The rule of thumb for <code class="language-plaintext highlighter-rouge">printf()</code> debugging is to check in the code beforehand.
You can then just <code class="language-plaintext highlighter-rouge">git checkout .</code> (or safer: <code class="language-plaintext highlighter-rouge">git stash</code>) to discard all of
debug code at once. Another useful trick is to add your name to debug logs. A
person’s name is often very distinguishable from the other code; you can easily
find it with <code class="language-plaintext highlighter-rouge">grep</code>. And if you forgot to delete it, others will ask you: “Hey,
there is your name in the code, did you forget to remove it?”</p>

<p>Another problem with <code class="language-plaintext highlighter-rouge">printf()</code> debugging is that it needs recompilation. There
may be tools for live patching, but live patching has inherently confusing as
the state of the old code persists. Don’t stick to <code class="language-plaintext highlighter-rouge">printf()</code>, and switch to
debugging using GDB/LLDB when appropriate.</p>

<h4 id="tracepoints">tracepoints</h4>

<p>QEMU has
<a href="https://qemu.readthedocs.io/en/v8.0.0/devel/tracing.html">tracing infrastructure</a>.
It is basically <code class="language-plaintext highlighter-rouge">printf()</code> with external tooling support, but it is still useful
even if you just use the default “log” trace backend, which outputs traces to
standard error as it allows filtering traces.</p>

<p>For example, you can get all
traces from igb (except e1000x-common code) by adding the following to the
command line:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">-trace</span> <span class="s1">'igb_*'</span>
</code></pre></div></div>

<p>The name of tracepoints for igb is listed in <code class="language-plaintext highlighter-rouge">hw/net/trace-events</code>. Tracepoints
for other devices are listed in corresponding <code class="language-plaintext highlighter-rouge">trace-events</code> files.</p>

<p>The output of this pattern will be huge as it enables <em>all</em> tracepoints igb has
so you can first skim it and narrow down the code. If you find something related
to IRQ suspicious, you can write:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">-trace</span> <span class="s1">'igb_irq_*'</span>
</code></pre></div></div>

<p>…and keep narrowing it down. It is also possible to enable/disable tracepoints
at runtime using the QEMU monitor, which will be described later.</p>

<p>To add a new trace point, you can add a new line to the <code class="language-plaintext highlighter-rouge">trace-events</code> file and
call the corresponding trace function. For example,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>igb_set_vfmailbox(uint32_t vf_num, uint32_t val) "VFMailbox[%d]: 0x%x"
</code></pre></div></div>

<p>It is easy to filter tracepoints, but it is still important not to add too many
tracepoints. The documentation gives
<a href="https://qemu.readthedocs.io/en/v8.0.0/devel/tracing.html#hints-for-adding-new-trace-events">some hints for adding new trace events</a>:</p>

<blockquote>
  <ol>
    <li>Trace state changes in the code. Interesting points in the code usually
involve a state change like starting, stopping, allocating, freeing. State
changes are good trace events because they can be used to understand the
execution of the system.</li>
    <li>Trace guest operations. Guest I/O accesses like reading device registers
are good trace events because they can be used to understand guest
interactions.</li>
    <li>Use correlator fields so the context of an individual line of trace output
can be understood. For example, trace the pointer returned by malloc and
used as an argument to free. This way mallocs and frees can be matched up.
Trace events with no context are not very useful.</li>
    <li>Name trace events after their function. If there are multiple trace events
in one function, append a unique distinguisher at the end of the name.</li>
  </ol>
</blockquote>

<p>In other words, you should think carefully if you add a trace event that does
not fit well with this description. For example, it usually does not make sense
to add tracepoints for individual <code class="language-plaintext highlighter-rouge">if</code> statements or functions. If there are
well-designed trace events to trace state changes and guest operations with
meaningful correlator fields, you should be able to infer which <code class="language-plaintext highlighter-rouge">if</code> statements
or functions will be evaluated.</p>

<h4 id="gdb-and-lldb">GDB and LLDB</h4>

<p>GDB and LLDB are debuggers for C programs. They both provide features you will
expect; it allows you to pause the execution at some point of code (breakpoint)
or to pause the execution when it accesses some region of memory (watchpoint)
without recompilation. GDB is widely used so you can expect good support from
debugged programs. LLDB is a more modern alternative and (in my experience) has
superior reliability. You can pick either of them or use both of them, depending
on the situation.</p>

<p>As QEMU debugging involves software at various levels, you need to attach GDB to
some or even all of them, depending on the nature of the bug. In particular,
there are three levels you may be interested in:</p>

<ul>
  <li>QEMU</li>
  <li>Guest kernel</li>
  <li>Guest userspace</li>
</ul>

<h5 id="qemu">QEMU</h5>

<p>Attaching GDB or LLDB to QEMU is no different from attaching it to other
userspace programs; simply put, you just type:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gdb build/qemu-system-aarch64
</code></pre></div></div>

<p>QEMU also has some GDB scripts that tweak it for debugging QEMU so it’s better
to use them. To use them, load the <code class="language-plaintext highlighter-rouge">.gdbinit</code> file in the QEMU source tree. GDB
has a feature to load <code class="language-plaintext highlighter-rouge">.gdbinit</code> automatically, but usually, it’s disabled for
the security reason so type the following to load it manually:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>source .gdbinit
</code></pre></div></div>

<h5 id="guest-kernel">Guest kernel</h5>

<p>Kernels often implement remote debugging protocols;
<a href="/2023/01/20/Guest-Windows-debugging-and-crashdumping-under-QEMU-KVM-Introduction.html">one of our blog posts covers such a protocol of Windows</a>.
Linux also comes with
<a href="https://www.kernel.org/doc/html/v6.3/dev-tools/kgdb.html">a similar feature called kgdb</a>.
However, they are sometimes unreliable when e.g., interrupts happen.</p>

<p>The remote debugging feature of QEMU is more reliable as it operates in a more
lower-level.
<a href="https://qemu.readthedocs.io/en/v8.0.0/system/gdb.html">This feature is documented well</a>,
but, in short, start QEMU with option <code class="language-plaintext highlighter-rouge">-s</code> added to the QEMU command line, start
gdb (with no argument), and type:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>target remote :1234
</code></pre></div></div>

<p>Now GDB is attached to the guest and you can freely place breakpoints and
watchpoints.</p>

<p>However, this comes with no debug information so it’s not practically usable in
this state. To use debug information from a guest kernel, you need to take some
procedure specific to it. Linux comes with
<a href="https://www.kernel.org/doc/html/v6.3/dev-tools/gdb-kernel-debugging.html">a good documentation describing the procedure to debug it with QEMU</a>
so I recommend reading it. A common pitfall is that KASLR confuses the
symbolizer, which is described in the documentation. I also had to disable
in-kernel pointer authentication (<code class="language-plaintext highlighter-rouge">CONFIG_ARM64_PTR_AUTH_KERNEL</code>) for my Arm64
environment.</p>

<p>It may be still necessary to interrupt the guest execution without knowing the
address to place a breakpoint. For example,
<a href="https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/setting-up-qemu-kernel-mode-debugging-using-exdi">Windows does support debugging the kernel with QEMU</a>,
but it requires another Windows machine and so troublesome to set up. It doesn’t
come with source code so you cannot know the exact address to place a breakpoint
anyway. A useful technique in such a case is to pause the execution from the
QEMU device code.</p>

<p>First, add the following includes to the head of the source file:</p>

<pre><code class="language-C">#include "exec/gdbstub.h"
#include "hw/core/cpu.h"
#include "sysemu/runstate.h"
</code></pre>

<p>Now you can add the following to the point where you want to pause the guest:</p>

<pre><code class="language-C">gdb_set_stop_cpu(current_cpu);
vm_stop(RUN_STATE_PAUSED);
</code></pre>

<p>The first line switches the CPU GDB interacts with. The second line actually
stops the VM. You can add conditions with <code class="language-plaintext highlighter-rouge">if</code> or do whatever since it’s C.</p>

<h4 id="filter-dump">filter-dump</h4>

<p>Sometimes there may be debug tools specialized for a particular feature.
filter-dump is such a tool included in QEMU for networking and allows to dump
network traffic in QEMU. It’s usually superior to <code class="language-plaintext highlighter-rouge">dumpcap</code> running on a tap
device attached to QEMU <code class="language-plaintext highlighter-rouge">netdev</code> as it runs at the very end of QEMU; it can see
corrupted packets sent from QEMU that will be filtered out by the tap device,
for example.</p>

<p>This tool was not working with packets with virtio-net headers attached so I
wrote
<a href="https://gitlab.com/qemu-project/qemu/-/commit/481c52320a26e2e3a3c8a1cdac3d1460b9b15d13">a fix</a>.
Such investment for a specialized tool is not essential but pays off well.</p>

<h4 id="qemu-monitor">QEMU monitor</h4>

<p><a href="https://www.qemu.org/docs/master/system/monitor.html">QEMU monitor</a> allows you
to interact with a live QEMU session. You can change the configuration of QEMU
by changing the command line, but it requires frequent restart so it’s
recommended to learn how to change the configuration at runtime with the QEMU
monitor. Sometimes live configuration change is inevitable; you may need to add
and remove filter-dump to capture only a particular part of network traffic, for
example.</p>

<p>Snapshotting and hotplugging are only available with interactive access with
QEMU. You should occasionally test them as they are error-prone features.</p>

<h3 id="case-study">Case study</h3>

<p>This section describes actual bug hunting during the igb development. The cause
of the bugs are not limited to QEMU, but include guest kernel and compiler.</p>

<h4 id="dma-reentry-bug">DMA reentry bug</h4>

<p>After sending igb patches to the upstream, several crash reports generated with
fuzzer came up:</p>

<p><a href="https://gitlab.com/qemu-project/qemu/-/issues/1543">Heap-use-after-free in e1000e_receive_internal (#1543) · Issues · QEMU / QEMU · GitLab</a></p>

<p>This crash happened with e1000e, but I still got the report as I did lots of
cleanup before copying the e1000e code for igb. It is also likely that a bug
affecting e1000e affects igb as well.</p>

<p>Locally reproducing the crash resulted in the following logs:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>==17147==ERROR: AddressSanitizer: heap-use-after-free on address 0xfffec4259798 at pc 0xaaabab108f88 bp 0xffffe3a4a780 sp 0xffffe3a4a790
READ of size 8 at 0xfffec4259798 thread T0
    #0 0xaaabab108f84 in e1000e_write_packet_to_guest ../hw/net/e1000e_core.c:1651
    #1 0xaaabab108f84 in e1000e_receive_internal ../hw/net/e1000e_core.c:1776
    #2 0xaaabab0cb978 in net_tx_pkt_send_custom ../hw/net/net_tx_pkt.c:823
    #3 0xaaabab0fe608 in e1000e_tx_pkt_send ../hw/net/e1000e_core.c:682
    #4 0xaaabab0fe608 in e1000e_process_tx_desc ../hw/net/e1000e_core.c:762
    #5 0xaaabab0fe608 in e1000e_start_xmit ../hw/net/e1000e_core.c:953
    #6 0xaaabab102694 in e1000e_set_tctl ../hw/net/e1000e_core.c:2496
    #7 0xaaabab10f918 in e1000e_core_write ../hw/net/e1000e_core.c:3349
    #8 0xaaababc913bc in memory_region_write_accessor ../softmmu/memory.c:493
(snip)

0xfffec4259798 is located 24 bytes inside of 208-byte region [0xfffec4259780,0xfffec4259850)
freed by thread T0 here:
    #0 0xfffecfc9d7cc in __interceptor_free /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:52
    #1 0xaaabab0cc3d0 in net_rx_pkt_iovec_realloc ../hw/net/net_rx_pkt.c:76
    #2 0xaaabab0cc3d0 in net_rx_pkt_pull_data ../hw/net/net_rx_pkt.c:99
    #3 0xaaabab0cf33c in net_rx_pkt_attach_iovec_ex ../hw/net/net_rx_pkt.c:153
    #4 0xaaabab102e70 in e1000e_receive_internal ../hw/net/e1000e_core.c:1764
    #5 0xaaabab0cb978 in net_tx_pkt_send_custom ../hw/net/net_tx_pkt.c:823
    #6 0xaaabab0fe608 in e1000e_tx_pkt_send ../hw/net/e1000e_core.c:682
    #7 0xaaabab0fe608 in e1000e_process_tx_desc ../hw/net/e1000e_core.c:762
    #8 0xaaabab0fe608 in e1000e_start_xmit ../hw/net/e1000e_core.c:953
    #9 0xaaabab102694 in e1000e_set_tctl ../hw/net/e1000e_core.c:2496
    #10 0xaaabab10f918 in e1000e_core_write ../hw/net/e1000e_core.c:3349
    #11 0xaaababc913bc in memory_region_write_accessor ../softmmu/memory.c:493
(snip)
    #21 0xaaabab0e5e5c in pci_dma_write /home/alarm/q/var/qemu/include/hw/pci/pci_device.h:271
    #22 0xaaabab0e5e5c in e1000e_write_to_rx_buffers ../hw/net/e1000e_core.c:1474
    #23 0xaaabab105218 in e1000e_write_packet_to_guest ../hw/net/e1000e_core.c:1646
    #24 0xaaabab105218 in e1000e_receive_internal ../hw/net/e1000e_core.c:1776
    #25 0xaaabab0cb978 in net_tx_pkt_send_custom ../hw/net/net_tx_pkt.c:823
    #26 0xaaabab0fe608 in e1000e_tx_pkt_send ../hw/net/e1000e_core.c:682
    #27 0xaaabab0fe608 in e1000e_process_tx_desc ../hw/net/e1000e_core.c:762
    #28 0xaaabab0fe608 in e1000e_start_xmit ../hw/net/e1000e_core.c:953
    #29 0xaaabab102694 in e1000e_set_tctl ../hw/net/e1000e_core.c:2496
    #30 0xaaabab10f918 in e1000e_core_write ../hw/net/e1000e_core.c:3349
    #31 0xaaababc913bc in memory_region_write_accessor ../softmmu/memory.c:493
(snip)

previously allocated by thread T0 here:
    #0 0xfffecfc9ed24 in __interceptor_malloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:69
    #1 0xfffece700ea4 in g_malloc (/usr/lib/libglib-2.0.so.0+0x70ea4)
    #2 0xaaabab0cc3d8 in net_rx_pkt_iovec_realloc ../hw/net/net_rx_pkt.c:77
    #3 0xaaabab0cc3d8 in net_rx_pkt_pull_data ../hw/net/net_rx_pkt.c:99
    #4 0xaaabab0cf33c in net_rx_pkt_attach_iovec_ex ../hw/net/net_rx_pkt.c:153
    #5 0xaaabab102e70 in e1000e_receive_internal ../hw/net/e1000e_core.c:1764
    #6 0xaaabab0cb978 in net_tx_pkt_send_custom ../hw/net/net_tx_pkt.c:823
    #7 0xaaabab0fe608 in e1000e_tx_pkt_send ../hw/net/e1000e_core.c:682
    #8 0xaaabab0fe608 in e1000e_process_tx_desc ../hw/net/e1000e_core.c:762
    #9 0xaaabab0fe608 in e1000e_start_xmit ../hw/net/e1000e_core.c:953
    #10 0xaaabab102694 in e1000e_set_tctl ../hw/net/e1000e_core.c:2496
    #11 0xaaabab10f918 in e1000e_core_write ../hw/net/e1000e_core.c:3349
    #12 0xaaababc913bc in memory_region_write_accessor ../softmmu/memory.c:493
(snip)
</code></pre></div></div>

<p>I omitted most stack trace entries of common QEMU code for brevity.</p>

<p>Looking at the logs, it seems use-after-free happened at line 1651 of
<code class="language-plaintext highlighter-rouge">hw/net/e1000e_core.c</code>. The content of the line is:</p>

<pre><code class="language-C">if (iov_ofs == iov-&gt;iov_len) {
</code></pre>

<p>This means <code class="language-plaintext highlighter-rouge">iov</code> was a dangling pointer when AddressSanitizer got triggered.
<code class="language-plaintext highlighter-rouge">iov</code> is assigned very early in the <code class="language-plaintext highlighter-rouge">e1000e_write_packet_to_guest</code> function and
the function appears in the stack trace of <em>free</em> so it’s likely that the <code class="language-plaintext highlighter-rouge">iov</code>
was valid at the beginning of the function but it got corrupted while the
function progresses. This leads to two possible explanations for the bug:</p>
<ol>
  <li>It was a mistake to retrieve <code class="language-plaintext highlighter-rouge">iov</code> early and to keep it in the function.</li>
  <li>It was a mistake to free <code class="language-plaintext highlighter-rouge">iov</code> in the function.</li>
</ol>

<p>To prove explanation 2, I looked at the stack trace of <em>free</em>. The stack trace
shows it tried to write the packet with DMA. In common sense, such DMA should
write RAM, but the stack trace says it triggered <em>another packet transmission</em>.
This sounds very wrong. In a nutshell, the following is what happened here:</p>

<ol>
  <li>The address of the MMIO register to trigger transmission was specified as the
address of the received packet buffer.</li>
  <li>Packet transmission was triggered.</li>
  <li>The packet was looped back, and written to the address of the received packet
buffer, which in reality points to the MMIO register specified in 1.</li>
  <li>Another packet transmission and loopback happened, corrupting the first
loopback.</li>
  <li>The second loopback finishes, and the first loopback resumes.</li>
  <li>The first loopback sees the corrupted state and AddressSanitizer triggers.</li>
</ol>

<p>The first condition is very unlikely to happen in the real world, but a fuzzer
and malicious actors it tries to mimic can create such an abnormal situation.</p>

<p>I could devise a fix with this explanation; such a fix should add a flag which
indicates an MMIO access already happened and reject another MMIO access if the
flag is set. The easiest way is to add such a flag to e1000e, but considering
the entire QEMU program, it is likely that other devices need the same flag so
I decided to add it to the common memory subsystem.</p>

<p>Eventually, <a href="https://patchew.org/QEMU/20230316162044.31607-1-akihiko.odaki@daynix.com/">I finished my fix and sent the upstream</a>
to find out
<a href="https://patchew.org/QEMU/20230427211013.2994127-1-alxndr@bu.edu/">there is already a fix for this kind of situation</a>.</p>

<h5 id="lessons-learned">Lessons learned</h5>

<ul>
  <li>Sanitizers and fuzzers do help.</li>
  <li>It is sometimes better to fix the common code instead of fixing the
device-specific code.</li>
  <li>Don’t forget to look for patches and issue reports for a common code bug ;)</li>
</ul>

<h4 id="linux-bug">Linux bug</h4>

<p>I first tried Linux Test Project with e1000e instead of igb. That led to a
kernel warning and device reset:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[  194.808645] NETDEV WATCHDOG: enp0s4 (e1000e): transmit queue 0 timed out
[  194.809321] WARNING: CPU: 3 PID: 0 at net/sched/sch_generic.c:525 dev_watchdog+0x6f4/0x7f0
[  194.810092] Modules linked in:
[  194.810388] CPU: 3 PID: 0 Comm: swapper/3 Not tainted 6.3.0-rc6+ #24
[  194.810987] Hardware name: QEMU KVM Virtual Machine, BIOS edk2-stable202302-for-qemu 03/01/2023
[  194.811805] pstate: 61400005 (nZCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
[  194.812461] pc : dev_watchdog+0x6f4/0x7f0
[  194.812845] lr : dev_watchdog+0x6f4/0x7f0
[  194.813233] sp : ffff800013227ad0
[  194.813552] x29: ffff800013227ad0 x28: ffff0000ef528510 x27: ffff80000e7cc000
[  194.814237] x26: 0000000000000003 x25: 0000000000000000 x24: 0000000000000000
[  194.814916] x23: ffff80000e7cc520 x22: ffff80000e7afac0 x21: ffff0000ef528420
[  194.815602] x20: ffff0000ef528000 x19: 1ffff00002644f6a x18: 0000000000000000
[  194.816284] x17: 1ffff00001f49ab0 x16: 0000000000000000 x15: 00000000a0f72ce0
[  194.818185] x14: 0000000000000000 x13: 0000000000000001 x12: ffff700002644ef3
[  194.820795] x11: 1ffff00002644ef2 x10: ffff700002644ef2 x9 : ffff80000831e908
[  194.823443] x8 : ffff800013227797 x7 : 00008ffffd9bb10e x6 : 0000000000000001
[  194.826174] x5 : ffff800013227790 x4 : 1fffe000184e560a x3 : dfff800000000000
[  194.828648] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff0000c272b040
[  194.831117] Call trace:
[  194.831960]  dev_watchdog+0x6f4/0x7f0
[  194.833231]  call_timer_fn+0x1f4/0x860
[  194.834378]  __run_timers+0x73c/0xa50
[  194.835201]  run_timer_softirq+0x54/0xb8
[  194.836098]  __do_softirq+0x304/0xe4c
[  194.836986]  ____do_softirq+0x14/0x28
[  194.837879]  call_on_irq_stack+0x24/0x30
[  194.838782]  do_softirq_own_stack+0x20/0x30
[  194.839736]  __irq_exit_rcu+0x23c/0x5e8
[  194.840615]  irq_exit_rcu+0x18/0x88
[  194.841421]  el1_interrupt+0x34/0x50
[  194.842314]  el1h_64_irq_handler+0x14/0x20
[  194.843321]  el1h_64_irq+0x68/0x70
[  194.844117]  cpuidle_idle_call+0x254/0x358
[  194.844856]  do_idle+0x124/0x1e0
[  194.845460]  cpu_startup_entry+0x2c/0x38
[  194.846174]  secondary_start_kernel+0x12c/0x168
[  194.846976]  __secondary_switched+0xa4/0xa8
[  194.847741] irq event stamp: 447143
[  194.848385] hardirqs last  enabled at (447142): [&lt;ffff80000b28db18&gt;] el1_interrupt+0x40/0x50
[  194.849731] hardirqs last disabled at (447143): [&lt;ffff80000b28d4e0&gt;] el1_dbg+0x20/0x90
[  194.850987] softirqs last  enabled at (446880): [&lt;ffff800008011128&gt;] __do_softirq+0x8f0/0xe4c
[  194.852350] softirqs last disabled at (447119): [&lt;ffff80000801b184&gt;] ____do_softirq+0x14/0x28
</code></pre></div></div>

<p>The call trace originates from a watchdog timer and does not tell much. The
error message implies something with the transmission is wrong, but it is not
enough to identify the bug.</p>

<p>I first minimized the reproduction case because repetitively running LTP takes
too long. The test that triggered the warning was a test to make parallel HTTP
requests. In the end, I figured out that this bug can be reproduced by running
Apache on e1000e and requesting a 2-GiB file twice in parallel.</p>

<p>As I wrote earlier, it originates from a watchdog timer, which triggers a bit
after a problematic behavior occurs. This means it is unlikely that you can
understand the issue by looking at the last few QEMU traces.</p>

<p>It is necessary to inspect the kernel to identify the true origin of the
warning. I attached GDB to the guest and put the breakpoint at the line that
emits the warning. Below is the snippet from the kernel:</p>

<pre><code class="language-C">for (i = 0; i &lt; dev-&gt;num_tx_queues; i++) {
	struct netdev_queue *txq;

	txq = netdev_get_tx_queue(dev, i);
	trans_start = READ_ONCE(txq-&gt;trans_start);
	if (netif_xmit_stopped(txq) &amp;&amp;
	    time_after(jiffies, (trans_start +
				 dev-&gt;watchdog_timeo))) {
		some_queue_timedout = 1;
		atomic_long_inc(&amp;txq-&gt;trans_timeout);
		break;
	}
}

if (unlikely(some_queue_timedout)) {
	trace_net_dev_xmit_timeout(dev, i);
	WARN_ONCE(1, KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit queue %u timed out\n",
	       dev-&gt;name, netdev_drivername(dev), i);
	netif_freeze_queues(dev);
	dev-&gt;netdev_ops-&gt;ndo_tx_timeout(dev, i);
	netif_unfreeze_queues(dev);
}
</code></pre>

<p>When the breakpoint hit, I typed: <code class="language-plaintext highlighter-rouge">p *dev</code>. This spams the console with all of
the information related to the network device. Skimming the output, I found the
value of the <code class="language-plaintext highlighter-rouge">name</code> member is <code class="language-plaintext highlighter-rouge">enp0s4</code>, which is the name of the e1000e device
and confirms it is a problem with e1000e.</p>

<p>Investigating further requires a more educated methodology than just skimming
<code class="language-plaintext highlighter-rouge">p *dev</code>. Below is the definition of <code class="language-plaintext highlighter-rouge">netdev_get_tx_queue</code>.</p>

<pre><code class="language-C">static inline
struct netdev_queue *netdev_get_tx_queue(const struct net_device *dev,
					 unsigned int index)
{
	return &amp;dev-&gt;_tx[index];
}
</code></pre>

<p><code class="language-plaintext highlighter-rouge">p dev-&gt;num_tx_queues</code> tells it’s 1, so <code class="language-plaintext highlighter-rouge">dev-&gt;_tx[0]</code> should be the queue that
timed out. Then I looked at <code class="language-plaintext highlighter-rouge">netif_xmit_stopped</code>:</p>

<pre><code class="language-C">static inline bool netif_xmit_stopped(const struct netdev_queue *dev_queue)
{
	return dev_queue-&gt;state &amp; QUEUE_STATE_ANY_XOFF;
}
</code></pre>

<p>where <code class="language-plaintext highlighter-rouge">QUEUE_STATE_ANY_XOFF</code> is defined as
<code class="language-plaintext highlighter-rouge">QUEUE_STATE_DRV_XOFF | QUEUE_STATE_STACK_XOFF</code>. <code class="language-plaintext highlighter-rouge">p dev-&gt;_tx[0].state</code> showed
<code class="language-plaintext highlighter-rouge">QUEUE_STATE_DRV_XOFF</code> was set so certainly this transmit queue is stopped.</p>

<p>Searching the kernel code base for <code class="language-plaintext highlighter-rouge">QUEUE_STATE_DRV_XOFF</code>, it seemed that the
bit is cleared with <code class="language-plaintext highlighter-rouge">netif_tx_wake_queue</code> and <code class="language-plaintext highlighter-rouge">netif_tx_start_queue</code>. Looking
for these symbols in <code class="language-plaintext highlighter-rouge">drivers/net/ethernet/intel/e1000e</code> led to the
<code class="language-plaintext highlighter-rouge">e1000_clean_tx_irq</code> function, which means the guest is not receiving tx IRQ
after the queue is stopped. I looked for kernel code that requests transmission
since tx IRQ will be generated only after that, finding such code in the
<code class="language-plaintext highlighter-rouge">e1000_xmit_frame</code> function.</p>

<pre><code class="language-C">netdev_sent_queue(netdev, skb-&gt;len);
e1000_tx_queue(tx_ring, tx_flags, count);
/* Make sure there is space in the ring for the next send. */
e1000_maybe_stop_tx(tx_ring,
		    (MAX_SKB_FRAGS *
		     DIV_ROUND_UP(PAGE_SIZE,
				  adapter-&gt;tx_fifo_limit) + 2));

if (!netdev_xmit_more() ||
    netif_xmit_stopped(netdev_get_tx_queue(netdev, 0))) {
	if (adapter-&gt;flags2 &amp; FLAG2_PCIM2PCI_ARBITER_WA)
		e1000e_update_tdt_wa(tx_ring,
				     tx_ring-&gt;next_to_use);
	else
		writel(tx_ring-&gt;next_to_use, tx_ring-&gt;tail);
}
</code></pre>

<p>It seemed the kernel requests transmission by writing the first TDT register,
which is pointed to by <code class="language-plaintext highlighter-rouge">tx_ring-&gt;tail</code>. If QEMU works properly, the last call
for the <code class="language-plaintext highlighter-rouge">e1000e_set_tdt</code> function in the device emulation code before the reset
happens should be matched with a call for the <code class="language-plaintext highlighter-rouge">e1000e_set_interrupt_cause</code>
function with <code class="language-plaintext highlighter-rouge">E1000_ICR_TXQ0</code> as its argument. To confirm this, I added
<code class="language-plaintext highlighter-rouge">printf</code> calls to print when <code class="language-plaintext highlighter-rouge">e1000e_set_tdt</code> is called or
<code class="language-plaintext highlighter-rouge">e1000e_set_interrupt_cause</code> is called with <code class="language-plaintext highlighter-rouge">E1000_ICR_TXQ0</code>, and enabled
<code class="language-plaintext highlighter-rouge">e1000e_core_ctrl_sw_reset</code> trace.</p>

<p>Surprisingly, <code class="language-plaintext highlighter-rouge">e1000e_set_interrupt_cause</code> was always happening after the last
<code class="language-plaintext highlighter-rouge">e1000e_set_tdt</code> call, meaning QEMU emulates the device properly. This made me
question the kernel driver implementation. There was an earlier call of the
<code class="language-plaintext highlighter-rouge">e1000_maybe_stop_tx</code> kernel function, which stops the Tx queue, in
<code class="language-plaintext highlighter-rouge">e1000_xmit_frame</code>, but it was not followed with TDT register write:</p>

<pre><code class="language-C">int count = 0;

/* snip */

/* reserve a descriptor for the offload context */
if ((mss) || (skb-&gt;ip_summed == CHECKSUM_PARTIAL))
	count++;
count++;

count += DIV_ROUND_UP(len, adapter-&gt;tx_fifo_limit);

nr_frags = skb_shinfo(skb)-&gt;nr_frags;
for (f = 0; f &lt; nr_frags; f++)
	count += DIV_ROUND_UP(skb_frag_size(&amp;skb_shinfo(skb)-&gt;frags[f]),
			      adapter-&gt;tx_fifo_limit);

if (adapter-&gt;hw.mac.tx_pkt_filtering)
	e1000_transfer_dhcp_info(adapter, skb);

/* need: count + 2 desc gap to keep tail from touching
 * head, otherwise try next time
 */
if (e1000_maybe_stop_tx(tx_ring, count + 2))
	return NETDEV_TX_BUSY;
</code></pre>

<p>I added <code class="language-plaintext highlighter-rouge">writel(tx_ring-&gt;next_to_use, tx_ring-&gt;tail);</code> before the <code class="language-plaintext highlighter-rouge">return</code>
statement and it worked.</p>

<p>So this was a kernel bug. Before submitting it as a fix, I tried to understand
the intention of <code class="language-plaintext highlighter-rouge">e1000_xmit_frame</code>. Below is the summary of this function:</p>

<ol>
  <li>Check if there is sufficient space to put the current packet in the tx ring.
Otherwise, return <code class="language-plaintext highlighter-rouge">NETDEV_TX_BUSY</code>.</li>
  <li>Queue the current packet to the tx ring.</li>
  <li>Stop the tx queue if there is no sufficient space for the next packet in
tx ring.</li>
  <li>Trigger transmission if there are no more packets or the tx is stopped.</li>
</ol>

<p>And what I observed is that the check in step 1 was failing. In such a case,
the previous <code class="language-plaintext highlighter-rouge">e1000_xmit_frame</code> should have stopped the tx queue in step 3
triggered transmission in step 4. In fact,
<code class="language-plaintext highlighter-rouge">Documentation/networking/netdevices.rst</code> states the check in step 1 should
never fail:</p>

<blockquote>
  <ul>
    <li>NETDEV_TX_BUSY Cannot transmit packet, try later
Usually a bug, means queue start/stop flow control is broken in
the driver. Note: the driver must NOT put the skb in its DMA ring.</li>
  </ul>
</blockquote>

<p>This implies it is a bug that the tx queue was not stopped in step 3 so I
inspected the condition to stop the tx queue in step 3.
<code class="language-plaintext highlighter-rouge">e1000_maybe_stop_tx</code> stops the queue if the tx queue has space specified with
the <code class="language-plaintext highlighter-rouge">size</code> argument. In this case, the value is:
<code class="language-plaintext highlighter-rouge">(MAX_SKB_FRAGS * DIV_ROUND_UP(PAGE_SIZE, adapter-&gt;tx_fifo_limit) + 2)</code></p>

<p>This looks so complex and suspicious. I followed the computation of the <code class="language-plaintext highlighter-rouge">size</code>
argument of the earlier <code class="language-plaintext highlighter-rouge">e1000_maybe_stop_tx</code> call triggering <code class="language-plaintext highlighter-rouge">NETDEV_TX_BUSY</code>
in step 1 to find its maximum value. There are two increments of <code class="language-plaintext highlighter-rouge">count</code> at the
beginning so that counts two. <code class="language-plaintext highlighter-rouge">DIV_ROUND_UP(len, adapter-&gt;tx_fifo_limit)</code> will
be <code class="language-plaintext highlighter-rouge">MAX_SKB_FRAGS</code> at maximum. The later iterations on fragments will be
summed into <code class="language-plaintext highlighter-rouge">MAX_SKB_FRAGS * DIV_ROUND_UP(PAGE_SIZE, adapter-&gt;tx_fifo_limit)</code>
at maximum. In the end, <code class="language-plaintext highlighter-rouge">2</code> is added to <code class="language-plaintext highlighter-rouge">count</code>. Summarizing this, the maximum
value will be:</p>

<pre><code class="language-C">2 + MAX_SKB_FRAGS + MAX_SKB_FRAGS * DIV_ROUND_UP(PAGE_SIZE, adapter-&gt;tx_fifo_limit) + 2
= (MAX_SKB_FRAGS + 1) * DIV_ROUND_UP(PAGE_SIZE, adapter-&gt;tx_fifo_limit) + 4
</code></pre>

<p>This is greater than the value used in step 4. A patch to update the value fixed
the problem so I submitted the upstream and it’s now merged<sup id="fnref:5" role="doc-noteref"><a href="#fn:5" class="footnote" rel="footnote">5</a></sup>. This bug was
present since the introduction of the e1000e driver in 2007 and 15-year-old when
it was fixed. It is surprising considering the affected workload is a plain
common HTTP server.</p>

<h5 id="lessons-learned-1">Lessons learned</h5>

<ul>
  <li>Don’t naively trust the kernel even if the code is mature.
(I also hit several other kernel bugs<sup id="fnref:6" role="doc-noteref"><a href="#fn:6" class="footnote" rel="footnote">6</a></sup><sup id="fnref:7" role="doc-noteref"><a href="#fn:7" class="footnote" rel="footnote">7</a></sup><sup id="fnref:8" role="doc-noteref"><a href="#fn:8" class="footnote" rel="footnote">8</a></sup><sup id="fnref:9" role="doc-noteref"><a href="#fn:9" class="footnote" rel="footnote">9</a></sup>.)</li>
  <li>The kernel source visibility matters.</li>
  <li>Sometimes it’s necessary to track the bug both from the host and guest side.</li>
</ul>

<h4 id="gcc-bug">GCC bug</h4>

<p>We covered a kernel bug so the next thing to cover is obviously (?) a compiler
bug. This compiler bug was found when running
<a href="https://doc.dpdk.org/guides/sample_app_ug/ip_pipeline.html">the Internet Protocol (IP) Pipeline application of DPDK</a>
under DPDK Test Suite. A DPDK program has a somewhat unconventional architecture
that <em>polls the hardware with an infinite loop</em>, which confused GCC.</p>

<p>It was quite easy to locate the bug except it was something that
<em>looked impossible</em>. It was clear that the DPDK application hung since the QEMU
trace and the output of the application stopped. That usually implies QEMU did
something wrong and the application got confused by that and froze. However,
I could not find any bug looking at the source code of the application or adding
lots of <code class="language-plaintext highlighter-rouge">printf()</code> and attaching GDB. It seemed the request for the worker
thread is silently ignored so I looked at the implementation of the request
queue to find no bug.</p>

<p>After observing this impossible behavior for an hour, eventually, I decided to
trim down the infinite loop of the worker thread. There were several conditions
to process requests and function calls so I removed each of them and replaced
the request processing function with simple <code class="language-plaintext highlighter-rouge">puts()</code>. Below is what I got in the
end:</p>

<pre><code class="language-C">#include &lt;stdio.h&gt;

int g;
int h;

int main(void)
{
	for (int i = 0; ; i++) {
		for (int j = 0; j &lt; g; j++);

		if (i &amp; 1) {
			if (h)
				continue;

			if (g)
				puts("a");

			g = 1;
		}
	}
}
</code></pre>

<p>This code should indefinitely emit <code class="language-plaintext highlighter-rouge">a</code>, but it did nothing. It was indeed a
compiler bug.</p>

<p>To identify the buggy optimization pass I replaced the <code class="language-plaintext highlighter-rouge">-O3</code> compiler flag with
<a href="https://gcc.gnu.org/onlinedocs/gcc-13.1.0/gcc/Optimize-Options.html">individual optimization flags listed in the documentation</a>
and performed binary search and derived the minimal reproducing combination of
flags: <code class="language-plaintext highlighter-rouge">-O1 -ftree-pre -ftree-partial-pre</code></p>

<p>The bug was reported to the upstream and promptly fixed<sup id="fnref:10" role="doc-noteref"><a href="#fn:10" class="footnote" rel="footnote">10</a></sup>. Meanwhile, as it
takes a long for a fix to be available on a distribution, I added
<code class="language-plaintext highlighter-rouge">-fno-tree-partial-pre</code> to the compiler flag to disable the faulty optimization.</p>

<h5 id="lessons-learned-2">Lessons learned</h5>

<ul>
  <li>Something that looks impossible happens sometimes.
(I hit yet another seemingly-impossible bug during igb development<sup id="fnref:11" role="doc-noteref"><a href="#fn:11" class="footnote" rel="footnote">11</a></sup>.
 Although it was not the fault of the compiler, it also teaches the same
 lesson.)</li>
  <li>The usual methodologies like minimizing the reproduction case or binary search
do apply to unusual cases.</li>
</ul>

<h2 id="contributing-to-the-upstream">Contributing to the upstream</h2>

<p>With all known bugs fixed, it’s time to submit the changes to the upstream.
<a href="https://qemu.readthedocs.io/en/v8.0.0/devel/submitting-a-patch.html">QEMU has extensive documentation for patch submission</a>.</p>

<p>This process is a repetition of getting reviews and submitting a new version.
New device emulation code is often large as in the case of igb, and such code
takes many rounds of reviews; it took 9 versions before igb gets merged<sup id="fnref:12" role="doc-noteref"><a href="#fn:12" class="footnote" rel="footnote">12</a></sup>. As
igb and e1000e have
<a href="https://qemu.readthedocs.io/en/v8.0.0/devel/fuzzing.html#the-generic-fuzzer">generic virtual-device fuzzing</a>
enabled, I also received reports of bugs found with the fuzzer and had to fix
each of them.</p>

<blockquote>
  <p>Patience you must have, my young Padawan. - Master Yoda</p>
</blockquote>

<p>The merge of the new device code marks the end of the initial development, but
it is not the end of the entire development process. Introducing a new device
makes you its maintainer so you will get patches and bug reports for it.
Community involvement keeps the code being improved.</p>

<h2 id="conclusion">Conclusion</h2>

<p>This series covered what new device emulation code for QEMU looks like by
depicting the introduction of igb, which was a 6-month journey<sup id="fnref:13" role="doc-noteref"><a href="#fn:13" class="footnote" rel="footnote">13</a></sup>. It is
complex and time-consuming, but tractable if you break it down into several
steps and divide-and-conquer. The new device code will benefit the entire QEMU
community and downstream once you finish the process and get it merged.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p><a href="https://gitlab.com/qemu-project/qemu/-/commit/ad5c6ddea327758daa9f0e6edd916be39dce7dca">target/arm: Initialize debug capabilities only once (ad5c6dde) · Commits · QEMU / QEMU · GitLab</a> <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p><a href="https://gitlab.com/qemu-project/qemu/-/commit/daae36c13abc73cf1055abc2d33cb71cc5d34310">vhost-user-gpio: Configure vhost_dev when connecting (daae36c1) · Commits · QEMU / QEMU · GitLab</a> <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p><a href="https://gitlab.com/qemu-project/qemu/-/commit/331acddc87b739c64b936ba4e58518f8491f1c6b">vhost-user-fs: Back up vqs before cleaning up vhost_dev (331acddc) · Commits · QEMU / QEMU · GitLab</a> <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:4" role="doc-endnote">
      <p><a href="https://gitlab.com/qemu-project/qemu/-/commit/0126793bee853e7c134627f51d2de5428a612e99">vhost-user-i2c: Back up vqs before cleaning up vhost_dev (0126793b) · Commits · QEMU / QEMU · GitLab</a> <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:5" role="doc-endnote">
      <p><a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=eed913f6919e253f35d454b2f115f2a4db2b741a">e1000e: Fix TX dispatch condition</a> <a href="#fnref:5" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:6" role="doc-endnote">
      <p><a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=28e96556baca7056d11d9fb3cdd0aba4483e00d8">igb: Allocate MSI-X vector when testing</a> <a href="#fnref:6" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:7" role="doc-endnote">
      <p><a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=50f303496d92e25b79bdfb73e3707ad0684ad67f">igb: Enable SR-IOV after reinit</a> <a href="#fnref:7" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:8" role="doc-endnote">
      <p><a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=02c83791ef969c6a8a150b4927193d0d0e50fb23">igbvf: Regard vf reset nack as success</a> <a href="#fnref:8" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:9" role="doc-endnote">
      <p><a href="https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git/commit/?h=virtio&amp;id=809d0810e3520da669d231303608cdf5fe5c1a70">iommu/virtio: Detach domain on endpoint release</a> <a href="#fnref:9" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:10" role="doc-endnote">
      <p><a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109002">109002 – [13 Regression] -O1 -ftree-pre -ftree-partial-pre results in stall value</a> <a href="#fnref:10" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:11" role="doc-endnote">
      <p><a href="https://gitlab.freedesktop.org/slirp/libslirp/-/merge_requests/131">ip: Enforce strict aliasing (!131) · Merge requests · slirp / libslirp · GitLab</a> <a href="#fnref:11" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:12" role="doc-endnote">
      <p><a href="https://patchew.org/QEMU/20230223105057.144309-1-akihiko.odaki@daynix.com/">[v9] Introduce igb | Patchew</a> <a href="#fnref:12" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:13" role="doc-endnote">
      <p>This does not include the time spent on the initial bring-up that was
    already done when I started working on igb. I also didn’t spend
    full-time for igb development. <a href="#fnref:13" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Akihiko Odaki</name></author><summary type="html"><![CDATA[This is the last post of a walkthrough of new device emulator development for QEMU which uses igb, a recently introduced Intel NIC emulation as an example.]]></summary></entry><entry><title type="html">Guest Windows debugging and crashdumping under QEMU/KVM: elf2dmp</title><link href="https://daynix.github.io/2023/05/23/Guest-Windows-debugging-and-crashdumping-under-QEMU-KVM-elf2dmp.html" rel="alternate" type="text/html" title="Guest Windows debugging and crashdumping under QEMU/KVM: elf2dmp" /><published>2023-05-23T08:30:00+00:00</published><updated>2023-05-23T08:30:00+00:00</updated><id>https://daynix.github.io/2023/05/23/Guest-Windows-debugging-and-crashdumping-under-QEMU-KVM-elf2dmp</id><content type="html" xml:base="https://daynix.github.io/2023/05/23/Guest-Windows-debugging-and-crashdumping-under-QEMU-KVM-elf2dmp.html"><![CDATA[<p><img src="https://github.com/virtio-win/kvm-guest-drivers-windows/assets/8286747/67410fd0-71ec-44e4-85a6-1a58c9ca571d" alt="image" /></p>

<p>In the <a href="/2023/02/19/Guest-Windows-debugging-and-crashdumping-under-QEMU-KVM-dump-guest-memory-vmcoreinfo-and-virtio-win.html">previous post</a> we discussed capturing a guest Windows crash dump using the vmcoreinfo device, the virtio-win driver called FwCfg, and the QEMU command called <code class="language-plaintext highlighter-rouge">dump-guest-memory -w</code>. In contrast to that method, this post considers a method to create a Complete Memory Dump of the 64-bit Windows guest, running inside a QEMU/KVM virtual machine, which doesn’t require any actions inside the guest. We will discuss the <code class="language-plaintext highlighter-rouge">elf2dmp</code> tool which can convert QEMU ELF dump obtained with <code class="language-plaintext highlighter-rouge">dump-guest-memory</code> to WinDbg-readable DMP format.</p>

<h2 id="preparation">Preparation</h2>

<h3 id="obtaining-elf2dmp">Obtaining elf2dmp</h3>

<p>The <code class="language-plaintext highlighter-rouge">elf2dmp</code> tool is a standalone executable, but its source code is <a href="https://gitlab.com/qemu-project/qemu/-/tree/master/contrib/elf2dmp">a part of the QEMU project</a> and resides in <code class="language-plaintext highlighter-rouge">contrib/elf2dmp</code>. For building along with QEMU, elf2dmp requires <code class="language-plaintext highlighter-rouge">tools</code> to be enabled in <code class="language-plaintext highlighter-rouge">configure</code> and depends on <code class="language-plaintext highlighter-rouge">libcurl</code>.</p>

<p>Also, <code class="language-plaintext highlighter-rouge">elf2dmp</code> can be obtained through package manager. For example, <code class="language-plaintext highlighter-rouge">qemu-tools</code> package contains <code class="language-plaintext highlighter-rouge">elf2dmp</code> on Fedora.</p>

<h3 id="capturing-elf-dump">Capturing ELF dump</h3>

<p>QEMU has a <code class="language-plaintext highlighter-rouge">dump-guest-memory</code> command to dump guest memory into an ELF file. In contrast to <code class="language-plaintext highlighter-rouge">dump-guest-memory -w</code>, no complex work will be done other than writing a snapshot of physical memory and register contexts to the ELF file.</p>

<h2 id="converting-elf-to-dmp">Converting ELF to DMP</h2>

<p>Run the following command to convert ELF dump file to DMP dump file:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>elf2dmp memory.elf memory.dmp
</code></pre></div></div>

<p>The example output for VM with Windows Server 2022 and 4 CPUs:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>4 CPU states has been found
CPU #0 CR3 is 0x000000012b109002
CPU #0 IDT is at 0xfffff8007d545000
CPU #0 IDT[0] -&gt; 0xfffff80081e88100
Searching kernel downwards from 0xfffff80081e88000...
Data directory entry #0: RVA = 0x0000c000
Data directory entry #0: RVA = 0x00008000
Data directory entry #0: RVA = 0x00108000
Data directory entry #0: RVA = 0x00024000
Data directory entry #0: RVA = 0x0005b000
Data directory entry #0: RVA = 0x00065000
Data directory entry #0: RVA = 0x00007000
Data directory entry #0: RVA = 0x000190b0
Data directory entry #0: RVA = 0x0000e000
Data directory entry #0: RVA = 0x00022000
Data directory entry #0: RVA = 0x00063000
Data directory entry #0: RVA = 0x00012000
Data directory entry #0: RVA = 0x000356e0
Data directory entry #0: RVA = 0x0013a000
KernBase = 0xfffff80081400000, signature is 'MZ'
Data directory entry #6: RVA = 0x000154b8
CodeView signature is 'RSDS'
PDB name is 'ntkrnlmp.pdb', 'ntkrnlmp.pdb' expected
PDB URL is https://msdl.microsoft.com/download/symbols/ntkrnlmp.pdb/adc00fa5fc34456ba16e2687457240991/ntkrnlmp.pdb
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100 11.5M  100 11.5M    0     0  1046k      0  0:00:11  0:00:11 --:--:-- 1674k
KdDebuggerDataBlock: 0x0000000000c00000(24:'.data') + 0x00000a30 = 0x000c00a30
KdDebuggerDataBlock = 0xfffff80082000a30
KdVersionBlock: 0x0000000000c00000(24:'.data') + 0x00015508 = 0x000c15508
KdVersionBlock = 0xfffff80082015508
KiWaitNever: 0x0000000000d0f000(25:'ALMOSTRO') + 0x00001bd0 = 0x000d10bd0
KiWaitNever = 0xfffff80082110bd0
KiWaitAlways: 0x0000000000d0f000(25:'ALMOSTRO') + 0x00001e38 = 0x000d10e38
KiWaitAlways = 0xfffff80082110e38
KdpDataBlockEncoded: 0x0000000000c00000(24:'.data') + 0x0010b148 = 0x000d0b148
KdpDataBlockEncoded = 0xfffff8008210b148
[KiWaitNever] = 0x1a5b030053af49fd
[KiWaitAlways] = 0x0029d7b15ae2d898
Decoding KDBG header...
Owner tag is 'KDBG'
Decoding KdDebuggerDataBlock...
Filling context for CPU #0...
Filling context for CPU #1...
Filling context for CPU #2...
Filling context for CPU #3...
Writing header to file...
Writing block #0/13 to file...
Writing block #1/13 to file...
Writing block #2/13 to file...
Writing block #3/13 to file...
Writing block #4/13 to file...
Writing block #5/13 to file...
Writing block #6/13 to file...
Writing block #7/13 to file...
Writing block #8/13 to file...
Writing block #9/13 to file...
Writing block #10/13 to file...
Writing block #11/13 to file...
Writing block #12/13 to file...
</code></pre></div></div>

<p>Since <code class="language-plaintext highlighter-rouge">elf2dmp</code> downloads the PDB file from Microsoft public symbol server, <strong>the network access is required</strong>. Also, both read and write accesses to the ELF dump file is required, although <strong>the ELF file is guaranteed to remain unchanged</strong>.</p>

<p>After the conversion, the DMP file can be opened in WinDbg.</p>

<h2 id="typical-issues">Typical issues</h2>

<p>QEMU generates ELF dump with <code class="language-plaintext highlighter-rouge">0400</code> rights, but <code class="language-plaintext highlighter-rouge">elf2dmp</code> requires read and write accesses, so the file rights should be modified to give these permissions to the user. Otherwise <code class="language-plaintext highlighter-rouge">elf2dmp</code> will say something like that:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Failed to map ELF dump file 'memory.elf'
Failed to initialize QEMU ELF dump
</code></pre></div></div>

<h2 id="internals">Internals</h2>

<p>As described in the previous posts in this series, Complete Memory Dump consists of a header and a snapshot of the physical memory of the system (which contains, among other things, the register contexts for all CPUs). The physical memory and register contexts are taken from the ELF dump file and saved to the DMP file, just like <code class="language-plaintext highlighter-rouge">dump-guest-memory -w</code> does, so the main challenge for elf2dmp is to fill the dump header correctly and decrypt the <code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock</code> structure.</p>

<h3 id="elf">ELF</h3>

<p>ELF dump file produced by QEMU with <code class="language-plaintext highlighter-rouge">dump-guest-memory</code> consists of a <code class="language-plaintext highlighter-rouge">PT_NOTE</code> with registers for each virtual CPU and several <code class="language-plaintext highlighter-rouge">PT_LOAD</code> with physical memory snapshots:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              CORE (Core file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         14
  Size of section headers:           0 (bytes)
  Number of section headers:         0
  Section header string table index: 0

There are no sections in this file.

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  NOTE           0x0000000000000350 0x0000000000000000 0x0000000000000000
                 0x0000000000000cc0 0x0000000000000cc0         0x0
  LOAD           0x0000000000001010 0x0000000000000000 0x0000000000000000
                 0x0000000000018000 0x0000000000018000         0x0
  LOAD           0x0000000000019010 0x0000000000018000 0x0000000000018000
                 0x0000000000001000 0x0000000000001000         0x0
  LOAD           0x000000000001a010 0x0000000000019000 0x0000000000019000
                 0x0000000000001000 0x0000000000001000         0x0
  LOAD           0x000000000001b010 0x000000000001a000 0x000000000001a000
                 0x0000000000001000 0x0000000000001000         0x0
  LOAD           0x000000000001c010 0x000000000001b000 0x000000000001b000
                 0x0000000000001000 0x0000000000001000         0x0
  LOAD           0x000000000001d010 0x000000000001c000 0x000000000001c000
                 0x0000000000084000 0x0000000000084000         0x0
  LOAD           0x00000000000a1010 0x00000000000a0000 0x00000000000a0000
                 0x0000000000010000 0x0000000000010000         0x0
  LOAD           0x00000000000b1010 0x00000000000c0000 0x00000000000c0000
                 0x0000000000004000 0x0000000000004000         0x0
  LOAD           0x00000000000b5010 0x00000000000c4000 0x00000000000c4000
                 0x000000000001c000 0x000000000001c000         0x0
  LOAD           0x00000000000d1010 0x00000000000e0000 0x00000000000e0000
                 0x0000000000020000 0x0000000000020000         0x0
  LOAD           0x00000000000f1010 0x0000000000100000 0x0000000000100000
                 0x000000007ff00000 0x000000007ff00000         0x0
  LOAD           0x000000007fff1010 0x00000000c0000000 0x00000000c0000000
                 0x0000000001000000 0x0000000001000000         0x0
  LOAD           0x0000000080ff1010 0x0000000100000000 0x0000000100000000
                 0x0000000080000000 0x0000000080000000         0x0
</code></pre></div></div>

<p>The following <code class="language-plaintext highlighter-rouge">QEMUCPUState</code> structure is available for each virtual x86 CPU:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typedef</span> <span class="k">struct</span> <span class="n">QEMUCPUSegment</span> <span class="p">{</span>
    <span class="kt">uint32_t</span> <span class="n">selector</span><span class="p">;</span>
    <span class="kt">uint32_t</span> <span class="n">limit</span><span class="p">;</span>
    <span class="kt">uint32_t</span> <span class="n">flags</span><span class="p">;</span>
    <span class="kt">uint32_t</span> <span class="n">pad</span><span class="p">;</span>
    <span class="kt">uint64_t</span> <span class="n">base</span><span class="p">;</span>
<span class="p">}</span> <span class="n">QEMUCPUSegment</span><span class="p">;</span>
        
<span class="k">typedef</span> <span class="k">struct</span> <span class="n">QEMUCPUState</span> <span class="p">{</span>
    <span class="kt">uint32_t</span> <span class="n">version</span><span class="p">;</span>
    <span class="kt">uint32_t</span> <span class="n">size</span><span class="p">;</span>
    <span class="kt">uint64_t</span> <span class="n">rax</span><span class="p">,</span> <span class="n">rbx</span><span class="p">,</span> <span class="n">rcx</span><span class="p">,</span> <span class="n">rdx</span><span class="p">,</span> <span class="n">rsi</span><span class="p">,</span> <span class="n">rdi</span><span class="p">,</span> <span class="n">rsp</span><span class="p">,</span> <span class="n">rbp</span><span class="p">;</span>
    <span class="kt">uint64_t</span> <span class="n">r8</span><span class="p">,</span> <span class="n">r9</span><span class="p">,</span> <span class="n">r10</span><span class="p">,</span> <span class="n">r11</span><span class="p">,</span> <span class="n">r12</span><span class="p">,</span> <span class="n">r13</span><span class="p">,</span> <span class="n">r14</span><span class="p">,</span> <span class="n">r15</span><span class="p">;</span>
    <span class="kt">uint64_t</span> <span class="n">rip</span><span class="p">,</span> <span class="n">rflags</span><span class="p">;</span>
    <span class="n">QEMUCPUSegment</span> <span class="n">cs</span><span class="p">,</span> <span class="n">ds</span><span class="p">,</span> <span class="n">es</span><span class="p">,</span> <span class="n">fs</span><span class="p">,</span> <span class="n">gs</span><span class="p">,</span> <span class="n">ss</span><span class="p">;</span>
    <span class="n">QEMUCPUSegment</span> <span class="n">ldt</span><span class="p">,</span> <span class="n">tr</span><span class="p">,</span> <span class="n">gdt</span><span class="p">,</span> <span class="n">idt</span><span class="p">;</span>
    <span class="kt">uint64_t</span> <span class="n">cr</span><span class="p">[</span><span class="mi">5</span><span class="p">];</span>
    <span class="kt">uint64_t</span> <span class="n">kernel_gs_base</span><span class="p">;</span>
<span class="p">}</span> <span class="n">QEMUCPUState</span><span class="p">;</span>
</code></pre></div></div>

<p>Processing of QEMU ELF dump file is implemented in <a href="https://gitlab.com/qemu-project/qemu/-/blob/master/contrib/elf2dmp/qemu_elf.c">qemu_elf.c</a>.</p>

<h3 id="directorytablebase">DirectoryTableBase</h3>

<p>One of the header fields is <code class="language-plaintext highlighter-rouge">DirectoryTableBase</code> (DTB). DTB contains the physical address of the root of the virtual-to-physical page address translation. In the method based on vmcoreinfo device and guest driver the field was filled by the guest OS, but elf2dmp had to calculate this value based on data from the ELF file. DTB is also required to access guest kernel virtual memory when searching for <code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock</code> and other header fields. In elf2dmp <a href="https://gitlab.com/qemu-project/qemu/-/blob/master/contrib/elf2dmp/addrspace.c">addrspace.c</a> is responsible for handling the physical and virtual address spaces.</p>

<p>The elf2dmp finds DTB value for several tries. The correctness of the value is checked by accessing <code class="language-plaintext highlighter-rouge">0xfffff78000000000</code> in kernel virtual address space. This address belongs to <a href="https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi_x/kuser_shared_data/index.htm"><code class="language-plaintext highlighter-rouge">SharedUserData</code></a>. There are 3 attempts in total:</p>
<ol>
  <li>Set DTB to CPU#0 CR3 taken from ELF.</li>
  <li>Set DTB to CR3 for each CPU context from ELF with a negative GS base. Negative GS base means the CPU is in Windows kernel context.</li>
  <li>Set temporary DTB to CPU#0 CR3 from ELF. Set DTB to a value from <code class="language-plaintext highlighter-rouge">[IA32_KERNEL_GS_BASE+0x7000]</code> by using temporary DTB to access virtual memory, where <a href="https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/ntos/amd64_x/kpcr.htm"><code class="language-plaintext highlighter-rouge">IA32_KERNEL_GS_BASE</code></a> is an MSR value from ELF.</li>
</ol>

<p>After finding the DTB, elf2dmp can access both the user and kernel virtual address space. Now elf2dmp needs to find where in virtual memory the Windows kernel PE image is located.</p>

<h3 id="kernel-base">Kernel base</h3>

<p>Windows kernel image is represented by <code class="language-plaintext highlighter-rouge">ntoskrnl.exe</code>. This PE image exports all the debugging symbols required by elf2dmp, such as <code class="language-plaintext highlighter-rouge">nt!KdDebuggerDataBlock</code> and <code class="language-plaintext highlighter-rouge">nt!KdVersionBlock</code>. To be able to resolve the debug symbols, elf2dmp needs to find the address where the kernel image is loaded.</p>

<p>To find the kernel base address, elf2dmp relies on the fact that there are interrupt handlers somewhere inside the Windows kernel image. Because the IDT base register value is stored in the ELF dump, elf2dmp takes the first address from the interrupt descriptor table. Now elf2dmp can scan the virtual memory downwards starting at that address using the following kernel image properties:</p>
<ul>
  <li>Any PE image starts with the signature <code class="language-plaintext highlighter-rouge">MZ</code>.</li>
  <li>The kernel image is aligned to the page boundary</li>
  <li>The kernel export table lists the image name as <code class="language-plaintext highlighter-rouge">ntoskrnl.exe</code></li>
</ul>

<p>Once elf2dmp has access to the loaded kernel image, it needs to find debugging symbols for it.</p>

<h3 id="ntkrnlmppdb">ntkrnlmp.pdb</h3>

<p>Debugging symbols are stored in PDB format. The PDB file for the Windows kernel (<code class="language-plaintext highlighter-rouge">ntkrnlmp.pdb</code>) and some other system modules can be downloaded from Microsoft public symbol store. WinDbg also downloads PDBs from this location. To do this, elf2dmp must form a download UR which looks like <code class="language-plaintext highlighter-rouge">https://msdl.microsoft.com/download/symbols/ntkrnlmp.pdb/adc00fa5fc34456ba16e2687457240991/ntkrnlmp.pdb</code>. The link contains a PDB name and a PDB hash. The PDB hash is calculated from a GUID from the debug directory of the kernel PE image. A routine named <a href="https://gitlab.com/qemu-project/qemu/-/blob/master/contrib/elf2dmp/main.c#L428"><code class="language-plaintext highlighter-rouge">pe_get_pdb_symstore_hash</code></a> does this in elf2dmp.</p>

<p>When the URL is generated, elf2dmp downloads the PDB file. This is described in <a href="https://gitlab.com/qemu-project/qemu/-/blob/master/contrib/elf2dmp/download.c">download.c</a>.</p>

<p>Now elf2dmp can parse the PDB file and resolve the required debugging symbols with the <code class="language-plaintext highlighter-rouge">pdb_find_public_v3_symbol</code> function from <a href="https://gitlab.com/qemu-project/qemu/-/blob/master/contrib/elf2dmp/pdb.c">pdb.c</a>.</p>

<h3 id="kddebuggerdatablock">KdDebuggerDataBlock</h3>

<p>The importance of the KdDebuggerData block structure was described in the previous post of the series. To find this structure in the virual address space, elf2dmp resolves the symbol <code class="language-plaintext highlighter-rouge">nt!KdDebuggerDataBlock</code>. Recall that when Debug Mode is disabled, this structure is encrypted. The encryption function is parameterized by the symbols <code class="language-plaintext highlighter-rouge">nt!KdpDataBlockEncoded</code>, <code class="language-plaintext highlighter-rouge">nt!KiWaitAlways</code> and <code class="language-plaintext highlighter-rouge">nt!KiWaitNever</code> and looks like this
<img src="https://github.com/virtio-win/kvm-guest-drivers-windows/assets/8286747/cca132e5-68ae-4401-82c8-70ce824365d2" alt="image" />
Here <code class="language-plaintext highlighter-rouge">ror</code> is right circular bit shift and <code class="language-plaintext highlighter-rouge">bswap</code> is 64-bit byte swap. Obviously, the function is easily reversible. Since elf2dmp now has access to all the debug symbols, knowing these parameters it can decrypt the structure.</p>

<h3 id="kdversionblock">KdVersionBlock</h3>

<p>The dump contains fields such as <code class="language-plaintext highlighter-rouge">MinorVersion</code>, <code class="language-plaintext highlighter-rouge">MajorVersion</code>, <code class="language-plaintext highlighter-rouge">MachineType</code> and <code class="language-plaintext highlighter-rouge">SecondaryDataState</code>. Their copies are available in a structure called <code class="language-plaintext highlighter-rouge">KdVersionBlock</code>, the address of which can also be resolved.</p>

<h3 id="dump-file-writing">Dump file writing</h3>

<p>When <code class="language-plaintext highlighter-rouge">DirectoryTableBase</code>, <code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock</code> and <code class="language-plaintext highlighter-rouge">KdVersionBlock</code> are available, elf2dmp can completely fill the dump header. The tool always sets the <code class="language-plaintext highlighter-rouge">BugcheckCode</code> to <code class="language-plaintext highlighter-rouge">0x161</code> (<code class="language-plaintext highlighter-rouge">LIVE_SYSTEM_DUMP</code>). After the physical memory blocks are copied from the ELF file to the DMP file, the Complete Memory Dump is ready.</p>

<h2 id="conclusion">Conclusion</h2>

<p>We have discussed the usage and internals of <code class="language-plaintext highlighter-rouge">elf2dmp</code> tool which can help to capture the Complete Memory Dump of the 64-bit Windows guest running under QEMU, without any actions inside the guest. This is a useful tool when the debug dump is needed, but the vmcoreinfo device is not connected or virtio-win drivers are not installed in the guest.</p>]]></content><author><name>Viktor Prutyanov</name></author><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Automate SSH access to Microsoft Validation OS</title><link href="https://daynix.github.io/2023/05/22/Automate-SSH-access-to-Microsoft-Validation-OS.html" rel="alternate" type="text/html" title="Automate SSH access to Microsoft Validation OS" /><published>2023-05-22T08:48:00+00:00</published><updated>2023-05-22T08:48:00+00:00</updated><id>https://daynix.github.io/2023/05/22/Automate-SSH-access-to-Microsoft-Validation-OS</id><content type="html" xml:base="https://daynix.github.io/2023/05/22/Automate-SSH-access-to-Microsoft-Validation-OS.html"><![CDATA[<p>Microsoft Validation OS, built on the foundation of Windows 11, offers a controlled
environment for software testing and validation, ensuring compatibility and reliability.
Microsoft Validation OS includes various core features and come with installed but not
configured OpenSSH server. However, by following a series of straightforward steps,
system administrators and developers can configure the OpenSSH server, enabling secure
remote access to Microsoft Validation OS. This article will provide a comprehensive guide,
outlining the necessary configuration steps and best practices to successfully set up
the OpenSSH server on Microsoft Validation OS, empowering users with secure remote
administration capabilities and streamlined file transfer functionalities.</p>

<p>Microsoft Validation OS is a lightweight, fast, and customizable Windows 11-based
operating system that you can use on the factory floor to diagnose, mitigate and
repair hardware defects during Windows device manufacturing. Validation OS boots
into a Command Line environment to increase reliability on the factory floor and
supports running Win32 apps, smoothing the transition from early hardware bring-up
to retail OS and apps development.</p>

<h2 id="image-customization-in-general">Image customization in general</h2>

<p>Microsoft provides enough documentation to customize image and add necessary software:</p>
<ul>
  <li><a href="https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/validation-os-mount-and-customize?view=windows-11">Mount and customize a Validation OS image</a></li>
  <li><a href="https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/validation-os-run-an-app-on-boot?view=windows-11">Launching an app or command when Validation OS starts</a></li>
</ul>

<p>The important point for all steps is select proper WIM image. From Microsoft note:</p>
<ul>
  <li>Use index:1 if you’ll be applying your image to a device’s hard drive.</li>
  <li>Use index:2 if you’ll be using the image to boot from a USB drive.</li>
</ul>

<p>In case when we prepare image for VM boot from ISO we should use <code class="language-plaintext highlighter-rouge">/index:2</code> in the DISM command.</p>

<p>What should be done for SSH access:</p>

<ol>
  <li>Generate SSH key pair</li>
  <li>Copy SSH public key into Validation OS as a authorized key</li>
  <li>Add OpenSSH server to autostart</li>
  <li>Export new image</li>
</ol>

<h2 id="image-preparation">Image preparation</h2>

<p>Microsoft provide non-bootable <a href="https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/validation-os-overview?view=windows-11">Validation OS ISO</a>. This image should be used only as a base.</p>

<ol>
  <li>Download Validation OS from the link above and extract is to some folder (C:\validation_os)</li>
  <li>Start the Deployment and Imaging Tools Environment as an administrator.</li>
  <li>Run <code class="language-plaintext highlighter-rouge">copype</code> to create a working copy of the Windows PE files.
    <div class="language-batch highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">copype</span> <span class="kd">amd64</span> <span class="kd">C</span>:\WinPE_amd64
</code></pre></div>    </div>
  </li>
  <li>Copy Validation OS wim and replace the WinPE boot.wim
    <div class="language-batch highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">xcopy</span> <span class="kd">C</span>:\validation_os\ValidationOS.wim <span class="kd">C</span>:\WinPE_amd64\media\sources\boot.wim
</code></pre></div>    </div>
  </li>
  <li>Create a folder where you’ll mount your image
    <div class="language-batch highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">md</span> <span class="kd">c</span>:\mount
</code></pre></div>    </div>
  </li>
  <li>Use DISM to mount the image
    <div class="language-batch highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">DISM</span> <span class="na">/Mount-Image /imagefile</span>:<span class="s2">"C:\WinPE_amd64\media\sources\boot.wim"</span> <span class="na">/index</span>:2 <span class="na">/MountDir</span>:<span class="s2">"C:\mount"</span>
</code></pre></div>    </div>
  </li>
  <li>Generate SSH key pair
    <div class="language-batch highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">md</span> <span class="kd">c</span>:\validation_ssh
<span class="kd">ssh</span><span class="na">-keygen -t </span><span class="kd">ed25519</span> <span class="na">-C </span><span class="s2">"your_email@example.com"</span> <span class="na">-f </span><span class="kd">c</span>:\validation_ssh\id_ed25519
</code></pre></div>    </div>
  </li>
  <li>Configure SSH server and add SSH public key as a authorized key
    <div class="language-batch highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">copy</span> <span class="kd">C</span>:\mount\Windows\System32\OpenSSH\sshd_config_default <span class="kd">C</span>:\mount\ProgramData\ssh\sshd_config
<span class="nb">type</span> <span class="kd">c</span>:\validation_ssh\id_ed25519.pub <span class="o">&gt;</span> <span class="kd">C</span>:\mount\ProgramData\ssh\administrators_authorized_keys
</code></pre></div>    </div>
  </li>
  <li>Create and configure the SSH startup script <code class="language-plaintext highlighter-rouge">C:\mount\sshd.bat</code> with the following content
    <div class="language-batch highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">rem "Generate SSH host keys"</span>
<span class="nb">cmd</span> <span class="na">/c </span><span class="s2">"ssh-keygen -A"</span>
<span class="c">rem "Start SSH server"</span>
<span class="nb">cmd</span> <span class="na">/k </span><span class="s2">"c:\Windows\System32\OpenSSH\sshd.exe"</span>
</code></pre></div>    </div>
  </li>
  <li>Add script to startup via registry
    <div class="language-batch highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">reg</span> <span class="kd">load</span> <span class="kd">HKLM</span>\Image_SOFTWARE <span class="kd">C</span>:\mount\windows\system32\config\software
<span class="nb">reg</span> <span class="kd">add</span> <span class="s2">"HKLM\Image_SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"</span> <span class="na">/v </span><span class="kd">Shell</span> <span class="na">/t </span><span class="kd">REG_SZ</span> <span class="na">/F /D </span><span class="s2">"cmd /k c:\sshd.bat"</span>
<span class="nb">reg</span> <span class="kd">unload</span> <span class="kd">HKLM</span>\Image_SOFTWARE
</code></pre></div>    </div>
  </li>
  <li>Unmount image and apply changes
    <div class="language-batch highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">DISM</span> <span class="na">/Unmount-Image /MountDir</span>:<span class="s2">"C:\mount"</span> <span class="na">/Commit
</span></code></pre></div>    </div>
  </li>
  <li>Generate bootable iso
    <div class="language-batch highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">MakeWinPEMedia</span> <span class="na">/ISO </span><span class="kd">C</span>:\WinPE_amd64 <span class="kd">C</span>:\ValidationOS_SSH.iso
</code></pre></div>    </div>
  </li>
</ol>

<h2 id="usage-of-created-iso">Usage of created ISO</h2>

<ol>
  <li>Boot any VM with ethernet adapter from <code class="language-plaintext highlighter-rouge">ValidationOS_SSH.iso</code></li>
  <li>Use the following SSH command to connect
    <div class="language-batch highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">ssh</span> <span class="na">-i </span><span class="kd">c</span>:\validation_ssh\id_ed25519 <span class="na">-o </span><span class="kd">IdentitiesOnly</span><span class="o">=</span><span class="kd">yes</span> <span class="kd">Administrator</span>@&lt;VM_IP&gt;
</code></pre></div>    </div>
  </li>
</ol>

<h2 id="conclusion">Conclusion</h2>

<p>In conclusion, configuring the OpenSSH server on Microsoft Validation OS opens
up a world of possibilities for secure remote access within this specialized
testing and validation environment. By following the steps outlined in this
article, you can establish a robust infrastructure that ensures the confidentiality,
integrity, and authenticity of your remote connections. With the OpenSSH server in
place, you can confidently administer and manage Microsoft Validation OS, transfer
files securely, and streamline your workflows. Embracing the power of OpenSSH
within the Microsoft Validation OS environment not only enhances your productivity
but also reinforces your commitment to maintaining a strong security posture.</p>]]></content><author><name>Konstantin Kostiuk</name></author><summary type="html"><![CDATA[Microsoft Validation OS, built on the foundation of Windows 11, offers a controlled environment for software testing and validation, ensuring compatibility and reliability. Microsoft Validation OS includes various core features and come with installed but not configured OpenSSH server. However, by following a series of straightforward steps, system administrators and developers can configure the OpenSSH server, enabling secure remote access to Microsoft Validation OS. This article will provide a comprehensive guide, outlining the necessary configuration steps and best practices to successfully set up the OpenSSH server on Microsoft Validation OS, empowering users with secure remote administration capabilities and streamlined file transfer functionalities.]]></summary></entry><entry><title type="html">igb: Developing a new device for QEMU (part 3: Implementing advanced features)</title><link href="https://daynix.github.io/2023/05/21/igb-developing-a-new-device-for-qemu-part-3-implementing-basic-features.html" rel="alternate" type="text/html" title="igb: Developing a new device for QEMU (part 3: Implementing advanced features)" /><published>2023-05-21T09:00:00+00:00</published><updated>2023-05-21T09:00:00+00:00</updated><id>https://daynix.github.io/2023/05/21/igb-developing-a-new-device-for-qemu-part-3-implementing-basic-features</id><content type="html" xml:base="https://daynix.github.io/2023/05/21/igb-developing-a-new-device-for-qemu-part-3-implementing-basic-features.html"><![CDATA[<p>This is the third post of a walkthrough of new device emulator development for
QEMU which uses <a href="https://qemu.readthedocs.io/en/v8.0.0/system/devices/igb.html">igb</a>,
a recently introduced Intel NIC emulation as an example.
<a href="/2023/05/06/igb-developing-a-new-device-for-qemu-part-1-introduction.html">The first post</a>
roughly described there are several development steps:</p>

<ol>
  <li>Writing a boilerplate and adding basic features</li>
  <li>Adding QTest</li>
  <li>Adding advanced features and libvirt support</li>
  <li>Running more tests and increasing feature coverage</li>
  <li>Debugging</li>
  <li>Contributing to the upstream</li>
</ol>

<p>This post discusses 3 and 4. The goal is to make the device implementation,
which was introduced in
<a href="/2023/05/12/igb-developing-a-new-device-for-qemu-part-2-implementing-basic-features.html">the previous post</a>,
<em>usable</em> for practical purposes.</p>

<h2 id="adding-advanced-features-and-libvirt-support">Adding advanced features and libvirt support</h2>

<h3 id="determining-test-workloads">Determining test workloads</h3>

<p>The previous post discussed bringing up the first device implementation and
letting the guest initialize the device. In the case of igb, it is not very
difficult to bring features implemented for e1000e, the predecessor in Intel’s
NIC product line, to igb as these devices are very similar, and igb development
started by forking e1000e’s code. However, this initial state of the device
emulation is not really usable; you would expect the new device will bring
features not present in the existing devices.</p>

<p>Therefore, the next step of the device development will be to implement such
advanced features. As described in the first post, the most notable features of
igb are VMDq and SR-IOV. VMDq implements L2 switching among (nested) VMs, and
SR-IOV allows to attach some tx/rx queues as a <em>virtual function</em> to a VM.
The first thing to do when implementing a new feature is to fabricate a workload
that will exercise it. To exercise VMDq and SR-IOV features, we have to perform
the following operations on a Linux guest:</p>
<ul>
  <li>Enabling SR-IOV virtual functions</li>
  <li>Sending and receiving packets with different combinations of peers:
    <ul>
      <li>The physical function and an external host</li>
      <li>The physical function and a virtual function</li>
      <li>A virtual function and an external host</li>
      <li>A virtual function and the physical function</li>
      <li>A virtual function and another virtual function</li>
    </ul>
  </li>
</ul>

<p>The physical function is the PCI function always available. Testing the
various combinations of peers is important to ensure the L2 switching capability
VMDq provides correctly functions.</p>

<p>Once the workloads were determined, you can test it and implement missing
features and fix bugs for them, just like the basic features are tested and
fixed. This process is <em>incremental</em> so it is important to prevent regressions
and to ensure forward progress. It is better to continuously run qtest and
simple workloads like ping and curl. Commit changes to Git frequently so that
you can isolate regressions by e.g., running
<a href="https://git-scm.com/docs/git-bisect">git bisect</a>.</p>

<p>Note that
<strong>it is <em>not</em> necessary to complete this step before sending the new device implementation to the upstream</strong>.
It is actually often <em>better</em> to send the patches upstream as soon as you get
confidence in the implementation of the basic functionalities. A small patch
that implements the basics is easier to review than a long patch that includes
many advanced features. The upstream reviewers can also discuss the design of
the implementation early and you can correct it before writing more changes if
you send patches early. It is even possible to send patches before you
thoroughly test them as
<a href="https://qemu.readthedocs.io/en/v8.0.0/devel/submitting-a-patch.html#use-the-rfc-tag-if-needed">RFC</a>.</p>

<p>For igb, I sent the first version of patches when VMDq and SR-IOV features
become usable on Linux. The other target platforms, Windows and DPDK followed
later.</p>

<h3 id="libvirt-support">libvirt support</h3>

<p>libvirt is a very popular frontend for QEMU so we need it to have the support
for the new device to some extent at least. The details of the code change
vary by the type of the device, but the principle same with QEMU applies:
find a similar device, copy the code for it, and extend it if necessary.</p>

<p>libvirt often requires few changes for a new device. The libvirt change for igb
is just a copy of e1000e support, and you can see it at:
<a href="https://gitlab.com/akihiko.odaki/libvirt/-/commit/f0e85eed7398c35b77a775d8178edc23b757ae6d">https://gitlab.com/akihiko.odaki/libvirt/-/commit/f0e85eed7398c35b77a775d8178edc23b757ae6d</a></p>

<h2 id="running-more-tests-and-increasing-feature-coverage">Running more tests and increasing feature coverage</h2>

<p>As you add more and more features, it gets harder to continuously test all of
the implemented features. Automated testing is essential to keep various
features working.</p>

<p>It is not common that there are tests for the emulated device as hardware
vendors do not release tests they presumably created during the hardware
development. It is theoretically possible to develop a complete unit testing
suite that covers all the features, but in practice, it consumes too much time.</p>

<p>A more practical way to introduce automated testing is to borrow existing test
suites for drivers and platforms. As they target more high-level constructs,
sometimes they do not suit well for device testing. For example, such a test
suite may include tests for a pure software construct, which costs time and
contributes nothing to device development. Such a test suite neither tests the
device functionalities the platform does not use. Nevertheless, high-level tests
are pragmatically very useful as they can ensure the success of the ultimate
objective: to get the device to work for the target platform.</p>

<p>Usually, there are test suites specialized for a device type and an operating
system so you have to choose appropriate ones. Such test suites for NICs and
popular platforms will be presented below:</p>

<h3 id="ethtool">ethtool</h3>

<p><a href="https://mirrors.edge.kernel.org/pub/software/network/ethtool/">ethtool</a> is a
Linux utility for controlling network devices. The kernel exposes an ioctl
that triggers device tests when requested by ethtool. The coverage of the
tests is fairly limited but it is so easy to use that it is automated for igb
using Avocado testing framework. The automating script is available at:
<a href="https://gitlab.com/qemu-project/qemu/-/blob/v8.0.0/tests/avocado/netdev-ethtool.py">https://gitlab.com/qemu-project/qemu/-/blob/v8.0.0/tests/avocado/netdev-ethtool.py</a></p>

<h3 id="linux-test-project-ltp">Linux Test Project (LTP)</h3>

<p><a href="https://github.com/linux-test-project/ltp/blob/20230516/README.md">Its README</a>
describes itself as follows:</p>
<blockquote>
  <p>The LTP testsuite contains a collection of tools for testing the Linux kernel
and related features.</p>
</blockquote>

<p>As the README states, LTP is not specific to networking and contains various
tests for Linux.
<a href="https://github.com/linux-test-project/ltp/blob/20230516/testcases/network/README.md">The network tests have their own README</a>.</p>

<p>The main advantage of LTP is that it contains various kinds of tests from ping
to applications like HTTP, FTP, telnet, etc. The downside is that its network
tests are somewhat unmaintained, and require manual setup of network
applications.</p>

<p>I have sent patches to
<a href="https://github.com/linux-test-project/ltp/commits?author=akihikodaki">fix the tests for a modern system</a>,
and wrote <a href="https://github.com/akihikodaki/q">some scripts to manage VMs</a>. These
scripts are particularly helpful as they allow us to easily reproduce the model
system for manual testing/debugging and to automatically run the LTP. The
automated scripts test all of the combinations of peers described above.</p>

<p>As Linux was the first target platform, the LTP was the first test suite igb
passes. However, later changes for the other platforms sometimes regressed the
Linux support and automated LTP runs greatly helped to spot such regressions.</p>

<h3 id="windows-hardware-lab-kit-hlk">Windows Hardware Lab Kit (HLK)</h3>

<blockquote>
  <p>The Windows Hardware Lab Kit (Windows HLK) is a test framework used to test
hardware devices and drivers for Windows 11, Windows 10 and all versions of
Windows Server starting with Windows Server 2016.</p>
</blockquote>

<p><a href="https://learn.microsoft.com/en-us/windows-hardware/test/hlk/">Windows Hardware Lab Kit | Microsoft Learn</a></p>

<p>Windows HLK includes comprehensive tests for network devices and exercises more
advanced features like VMDq and SR-IOV. We maintain
<a href="https://github.com/HCK-CI/AutoHCK">AutoHCK</a>, a tool for automating HLK runs
on QEMU so it is quite easy to set up VMs using it. Windows HLK spotted several
bugs which were missed by the LTP in the case of igb.</p>

<p>The downside of Windows HLK, or rather Windows platform is that it is
closed-source. When I first tried igb with Windows, its driver just hung and
repeated resets without any helpful information. You can only see traces from
QEMU and the disassembly of the driver. The next post will discuss debugging
with this closed-source platform, but you will want to get the device to work
with an open-source platform before testing with Windows.</p>

<h3 id="dpdk-test-suite-dts">DPDK Test Suite (DTS)</h3>

<p>DPDK is not an operating system like Linux and Windows, but an application
framework for low-level packet processing. DPDK implements its own driver to
implement the interaction with the hardware in the userspace and to eliminate
context switches with the kernel. The DPDK driver needs to be tested as it
employs low-level hardware access as operating system drivers do.</p>

<p>The nice thing with DPDK is that
<em>it can be debugged as a normal user-space application</em>. It can also use more
minor device features, and DPDK Test Suite covers details of such features.
However, DPDK is not for a user-facing application like curl so DTS cannot
ensure the usability of the device emulation in common situations.</p>

<h2 id="conclusion">Conclusion</h2>

<p>This post discussed how to add advanced features and libvirt support, and to
test them. This part of device development takes a significantly long time so
you need some strategy. You have to choose features and tests appropriate for
the current development stage and sometimes send (RFC) patches to get design
reviews.</p>

<p>The development process is not always smooth, and you may have difficulty
getting a new feature to function, or the device implementation may suffer from
regressions. Therefore
<a href="/2023/06/01/igb-developing-a-new-device-for-qemu-part-4-debugging-and-submitting-patches.html">the next post</a>
will mostly be spent on one thing: <strong>debugging</strong>.</p>]]></content><author><name>Akihiko Odaki</name></author><summary type="html"><![CDATA[This is the third post of a walkthrough of new device emulator development for QEMU which uses igb, a recently introduced Intel NIC emulation as an example. The first post roughly described there are several development steps:]]></summary></entry><entry><title type="html">igb: Developing a new device for QEMU (part 2: Implementing basic features)</title><link href="https://daynix.github.io/2023/05/12/igb-developing-a-new-device-for-qemu-part-2-implementing-basic-features.html" rel="alternate" type="text/html" title="igb: Developing a new device for QEMU (part 2: Implementing basic features)" /><published>2023-05-12T12:00:00+00:00</published><updated>2023-05-12T12:00:00+00:00</updated><id>https://daynix.github.io/2023/05/12/igb-developing-a-new-device-for-qemu-part-2-implementing-basic-features</id><content type="html" xml:base="https://daynix.github.io/2023/05/12/igb-developing-a-new-device-for-qemu-part-2-implementing-basic-features.html"><![CDATA[<p>This is the second post of a walkthrough of new device emulator development for
QEMU.
<a href="/2023/05/06/igb-developing-a-new-device-for-qemu-part-1-introduction.html">The first post</a>
briefly described the development process and device which we will discuss, igb,
an Intel NIC. This post details the first steps of the development: filling a
boilerplate and adding basic features necessary to get the device <em>work</em> and to
establish the foundation of further development.</p>

<h2 id="writing-a-boilerplate-and-adding-basic-features">Writing a boilerplate and adding basic features</h2>

<p>QEMU provides infrastructure common for different devices. The first step of 
device emulator development is to write a boilerplate to utilize it. Then, you
can implement some basic features like MMIO register accesses.</p>

<p>There are three possible options when implementing a new device.</p>
<ol>
  <li>Extending the existing code for a similar device.</li>
  <li>Copying and rewriting the existing code for a similar device.</li>
  <li>Writing from scratch.</li>
</ol>

<p>The first option is the easiest if the new device has small differences from an
existing device or it is a strict superset of one, but in the case of igb, there
are so many differences from the predecessor, e1000e, that we had to choose
option 2.</p>

<p>Even if there is no device that is particularly similar to the device you are
going to implement and you are going with option 3, it is still a good idea to
look for a device recently added that uses the same type of bus (e.g., PCIe) or
implements the same category of feature (e.g., NIC). This ensures that the new
device implementation follows the convention already established in the QEMU
code base.</p>

<p>The initial goal of the development is to get the device to <em>work</em>. Concretely,
this implies:</p>
<ul>
  <li>The code can be built.</li>
  <li>The operating system can see and initialize the device.</li>
</ul>

<p>If you choose option 2, the first thing to do after copying the code is to
rename C identifiers to make the copied code buildable. Once renaming the
identifiers is done, rename the device type name.</p>

<p>In the copied code, the type name is defined with the following line:</p>

<pre><code class="language-C">#define TYPE_IGB "e1000e"
</code></pre>

<p>We can simply replace it with <code class="language-plaintext highlighter-rouge">igb</code>.</p>

<pre><code class="language-C">#define TYPE_IGB "igb"
</code></pre>

<p>Before doing any more changes, we ensure that we can build the code and it
functions as a drop-in replacement for e1000e. First, write a simple command
line to run QEMU with e1000e.</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>build/qemu-system-aarch64 <span class="nt">-M</span> virt <span class="nt">-device</span> e1000e,netdev<span class="o">=</span>netdev <span class="nt">-netdev</span> user,id<span class="o">=</span>netdev...
</code></pre></div></div>

<p>Make sure this command line works, and then replace <code class="language-plaintext highlighter-rouge">e1000e</code> with <code class="language-plaintext highlighter-rouge">igb</code>.</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>build/qemu-system-aarch64 <span class="nt">-M</span> virt <span class="nt">-device</span> igb,netdev<span class="o">=</span>netdev <span class="nt">-netdev</span> user,id<span class="o">=</span>netdev...
</code></pre></div></div>

<p>Now the new device should be working 🎉</p>

<p>…but the operating system sees e1000e instead of igb because the actual code
is just simply copied from e1000e. Before making it function as igb, let’s
check in this first version of the new device into Git so that you can always go
back to the buildable state. Implementing a device is complicated and it is
likely to have regressions during development; frequently committing to Git may
save hours in such a situation.</p>

<p>We can then change the identifiers exposed to the guest to make it function as
a new device. We have the following lines in the class initialization function
of the copied code.</p>

<pre><code class="language-C">    c-&gt;realize = igb_pci_realize;
    c-&gt;exit = igb_pci_uninit;
    c-&gt;vendor_id = PCI_VENDOR_ID_INTEL;
    c-&gt;device_id = E1000_DEV_ID_82574L;
    c-&gt;revision = 0;
    c-&gt;romfile = "efi-e1000e.rom";
    c-&gt;class_id = PCI_CLASS_NETWORK_ETHERNET;

    rc-&gt;phases.hold = igb_qdev_reset_hold;

    dc-&gt;desc = "Intel 82574L GbE Controller";
    dc-&gt;vmsd = &amp;igb_vmstate;
</code></pre>

<p>Replace the PCI identifiers and other fields.</p>

<pre><code class="language-C">    c-&gt;realize = igb_pci_realize;
    c-&gt;exit = igb_pci_uninit;
    c-&gt;vendor_id = PCI_VENDOR_ID_INTEL;
    c-&gt;device_id = E1000_DEV_ID_82576;
    c-&gt;revision = 1;
    c-&gt;class_id = PCI_CLASS_NETWORK_ETHERNET;

    rc-&gt;phases.hold = igb_qdev_reset_hold;

    dc-&gt;desc = "Intel 82576 Gigabit Ethernet Controller";
    dc-&gt;vmsd = &amp;igb_vmstate;
</code></pre>

<p>Now the guest thinks the device is igb, but the actual implementation is e1000e
so the guest cannot properly initialize it. In theory, you can implement all
features igb has according to
<a href="https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/82576eg-gbe-datasheet.pdf">the datasheet</a>
and get the working code, but it’s unrealistic considering that the datasheet
has even <em>960 pages</em>. A practical approach is to read the device driver code and
implement features accessed during the initialization.</p>

<figure style="text-align: center">
<svg viewBox="0 0 612 792" style="height: 30rem">
 <desc>The cover of the datasheet</desc>
 <defs>
  <symbol id="glyph0-1" overflow="visible"></symbol>
  <symbol id="glyph1-1" overflow="visible">
   <path d="m12.594 0h-2.2656l-4.375-5.2031h-2.4531v5.2031h-1.7344v-13.094h3.6562c0.78906 0 1.4453 0.054688 1.9688 0.15625 0.53125 0.10547 1.0078 0.28906 1.4375 0.54688 0.46875 0.30469 0.83594 0.68359 1.1094 1.1406 0.26953 0.44922 0.40625 1.0234 0.40625 1.7188 0 0.94922-0.24219 1.7422-0.71875 2.375-0.48047 0.63672-1.1328 1.1172-1.9531 1.4375zm-4.0781-9.4062c0-0.375-0.070313-0.70703-0.20312-1-0.125-0.28906-0.33984-0.53516-0.64062-0.73438-0.26172-0.16406-0.5625-0.28125-0.90625-0.34375-0.34375-0.070313-0.75-0.10938-1.2188-0.10938h-2.0469v4.9375h1.75c0.55078 0 1.0312-0.046875 1.4375-0.14062 0.41406-0.09375 0.76953-0.27344 1.0625-0.54688 0.25781-0.23828 0.45312-0.51953 0.57812-0.84375 0.125-0.32031 0.1875-0.72656 0.1875-1.2188z" />
  </symbol>
  <symbol id="glyph1-2" overflow="visible">
   <path d="m9.8438-4.7344h-7.2344c0 0.60547 0.085937 1.1328 0.26562 1.5781 0.1875 0.44922 0.4375 0.8125 0.75 1.0938s0.67578 0.49609 1.0938 0.64062c0.41406 0.13672 0.875 0.20312 1.375 0.20312 0.67578 0 1.3477-0.12891 2.0156-0.39062 0.67578-0.26953 1.1602-0.53516 1.4531-0.79688h0.09375v1.8125c-0.5625 0.23047-1.1367 0.42969-1.7188 0.59375-0.57422 0.15625-1.1797 0.23438-1.8125 0.23438-1.6367 0-2.9141-0.44141-3.8281-1.3281-0.90625-0.88281-1.3594-2.1406-1.3594-3.7656 0-1.6016 0.4375-2.875 1.3125-3.8125 0.875-0.94531 2.0234-1.4219 3.4531-1.4219 1.3203 0 2.3438 0.39062 3.0625 1.1719 0.71875 0.77344 1.0781 1.8672 1.0781 3.2812zm-1.6094-1.2656c0-0.86328-0.21875-1.5352-0.65625-2.0156-0.42969-0.47656-1.0859-0.71875-1.9688-0.71875-0.875 0-1.5781 0.26562-2.1094 0.79688-0.52344 0.52344-0.82031 1.168-0.89062 1.9375z" />
  </symbol>
  <symbol id="glyph1-3" overflow="visible">
   <path d="m10.109-9.8125-3.9688 9.8125h-1.6562l-3.9531-9.8125h1.7969l3.0469 7.8125 3.0156-7.8125z" />
  </symbol>
  <symbol id="glyph1-4" overflow="visible">
   <path d="m3.4062-11.469h-1.875v-1.7031h1.875zm-0.10938 11.469h-1.6562v-9.8125h1.6562z" />
  </symbol>
  <symbol id="glyph1-5" overflow="visible">
   <path d="m8.6406-2.8281c0 0.89844-0.37109 1.6328-1.1094 2.2031-0.74219 0.57422-1.7578 0.85938-3.0469 0.85938-0.71875 0-1.3867-0.085937-2-0.25-0.60547-0.17578-1.1094-0.36719-1.5156-0.57812v-1.8438h0.09375c0.51953 0.38672 1.0977 0.69922 1.7344 0.9375 0.63281 0.23047 1.2422 0.34375 1.8281 0.34375 0.72656 0 1.2969-0.11328 1.7031-0.34375 0.41406-0.23828 0.625-0.61328 0.625-1.125 0-0.38281-0.10938-0.67578-0.32812-0.875-0.23047-0.19531-0.66406-0.36719-1.2969-0.51562-0.23047-0.050781-0.53906-0.10938-0.92188-0.17188-0.375-0.070312-0.71484-0.14844-1.0156-0.23438-0.86719-0.22656-1.4805-0.5625-1.8438-1-0.35547-0.44531-0.53125-0.99219-0.53125-1.6406 0-0.40625 0.082031-0.78516 0.25-1.1406 0.16406-0.35156 0.41406-0.67188 0.75-0.95312 0.33203-0.28125 0.75-0.5 1.25-0.65625 0.50781-0.16406 1.0781-0.25 1.7031-0.25 0.59375 0 1.1875 0.074219 1.7812 0.21875 0.60156 0.14844 1.1016 0.32422 1.5 0.53125v1.7656h-0.078125c-0.42969-0.3125-0.94531-0.57031-1.5469-0.78125-0.60547-0.21875-1.1953-0.32812-1.7656-0.32812-0.60547 0-1.1172 0.11719-1.5312 0.34375-0.41797 0.23047-0.625 0.57422-0.625 1.0312 0 0.40625 0.125 0.71484 0.375 0.92188 0.25 0.19922 0.64453 0.36719 1.1875 0.5 0.3125 0.074219 0.65625 0.14844 1.0312 0.21875 0.375 0.0625 0.6875 0.125 0.9375 0.1875 0.76953 0.17969 1.3633 0.48047 1.7812 0.90625 0.41406 0.42969 0.625 1 0.625 1.7188z" />
  </symbol>
  <symbol id="glyph1-6" overflow="visible">
   <path d="m10-4.9062c0 1.6055-0.41406 2.8711-1.2344 3.7969-0.82422 0.91797-1.9219 1.375-3.2969 1.375-1.3867 0-2.4922-0.45703-3.3125-1.375-0.8125-0.92578-1.2188-2.1914-1.2188-3.7969 0-1.5938 0.40625-2.8516 1.2188-3.7812 0.82031-0.9375 1.9258-1.4062 3.3125-1.4062 1.375 0 2.4727 0.46875 3.2969 1.4062 0.82031 0.92969 1.2344 2.1875 1.2344 3.7812zm-1.7188 0c0-1.2695-0.25-2.2109-0.75-2.8281-0.49219-0.625-1.1797-0.9375-2.0625-0.9375-0.89844 0-1.5938 0.3125-2.0938 0.9375-0.49219 0.61719-0.73438 1.5586-0.73438 2.8281 0 1.2305 0.24219 2.1641 0.73438 2.7969 0.5 0.63672 1.1953 0.95312 2.0938 0.95312 0.875 0 1.5625-0.3125 2.0625-0.9375 0.5-0.63281 0.75-1.5703 0.75-2.8125z" />
  </symbol>
  <symbol id="glyph1-7" overflow="visible">
   <path d="m9.8281 0h-1.6406v-5.5938c0-0.44531-0.027344-0.86719-0.078125-1.2656-0.054687-0.39453-0.15234-0.70312-0.29688-0.92188-0.14844-0.25-0.35938-0.42969-0.64062-0.54688-0.27344-0.125-0.625-0.1875-1.0625-0.1875-0.44922 0-0.92188 0.11719-1.4219 0.34375-0.49219 0.21875-0.96094 0.5-1.4062 0.84375v7.3281h-1.6562v-9.8125h1.6562v1.0781c0.50781-0.42578 1.0391-0.75781 1.5938-1 0.55078-0.23828 1.1172-0.35938 1.7031-0.35938 1.0625 0 1.8672 0.32422 2.4219 0.96875 0.55078 0.63672 0.82812 1.5547 0.82812 2.75z" />
  </symbol>
  <symbol id="glyph1-8" overflow="visible">
   <path d="m5.1406-7.3125h-2.0938v-2.5h2.0938zm0 7.3125h-2.0938v-2.5h2.0938z" />
  </symbol>
  <symbol id="glyph1-9" overflow="visible"></symbol>
  <symbol id="glyph1-10" overflow="visible">
   <path d="m10.281 0h-8.8594v-1.8438c0.61328-0.51953 1.2266-1.0391 1.8438-1.5625 0.61328-0.53125 1.1914-1.0625 1.7344-1.5938 1.125-1.082 1.8906-1.9414 2.2969-2.5781 0.41406-0.64453 0.625-1.3438 0.625-2.0938 0-0.67578-0.22656-1.207-0.67188-1.5938-0.44922-0.38281-1.0742-0.57812-1.875-0.57812-0.53125 0-1.1094 0.09375-1.7344 0.28125-0.61719 0.1875-1.2188 0.47656-1.8125 0.85938h-0.09375v-1.8438c0.41406-0.19531 0.97266-0.37891 1.6719-0.54688 0.69531-0.17578 1.3672-0.26562 2.0156-0.26562 1.3438 0 2.3945 0.32422 3.1562 0.96875 0.75781 0.64844 1.1406 1.5273 1.1406 2.6406 0 0.49219-0.0625 0.95312-0.1875 1.3906-0.125 0.42969-0.3125 0.83594-0.5625 1.2188-0.23047 0.36719-0.5 0.72656-0.8125 1.0781-0.30469 0.35547-0.67188 0.74609-1.1094 1.1719-0.625 0.61719-1.2734 1.2148-1.9375 1.7969-0.66797 0.57422-1.293 1.1055-1.875 1.5938h7.0469z" />
  </symbol>
  <symbol id="glyph1-11" overflow="visible">
   <path d="m4.3281 0h-2.1094v-2.5h2.1094z" />
  </symbol>
  <symbol id="glyph1-12" overflow="visible">
   <path d="m10.312-11.125-5.9219 11.125h-1.8906l6.3125-11.547h-7.4531v-1.5469h8.9531z" />
  </symbol>
  <symbol id="glyph1-13" overflow="visible">
   <path d="m6.5625-3.4062c0 1.1562-0.35547 2.0469-1.0625 2.6719-0.69922 0.61719-1.6367 0.92188-2.8125 0.92188-0.28125 0-0.65625-0.027344-1.125-0.078125-0.46875-0.054688-0.85938-0.11328-1.1719-0.1875v-1.625h0.09375c0.23828 0.085937 0.53516 0.17188 0.89062 0.26562 0.35156 0.085938 0.71094 0.125 1.0781 0.125 0.53906 0 0.96875-0.054688 1.2812-0.17188 0.32031-0.125 0.5625-0.30078 0.71875-0.53125 0.15625-0.23828 0.25391-0.52344 0.29688-0.85938 0.039062-0.34375 0.0625-0.73828 0.0625-1.1875v-7.6406h-2.7656v-1.3906h4.5156z" />
  </symbol>
  <symbol id="glyph1-14" overflow="visible">
   <path d="m9.7656 0h-1.6562v-1.0938c-0.55469 0.4375-1.0859 0.77734-1.5938 1.0156-0.51172 0.22656-1.0742 0.34375-1.6875 0.34375-1.0312 0-1.8359-0.3125-2.4062-0.9375-0.57422-0.63281-0.85938-1.5625-0.85938-2.7812v-6.3594h1.6406v5.5781c0 0.5 0.019531 0.92969 0.0625 1.2812 0.050781 0.35547 0.15625 0.65625 0.3125 0.90625 0.15625 0.26172 0.35938 0.45312 0.60938 0.57812 0.25781 0.11719 0.62891 0.17188 1.1094 0.17188 0.42578 0 0.89062-0.10938 1.3906-0.32812 0.50781-0.22656 0.98438-0.51562 1.4219-0.85938v-7.3281h1.6562z" />
  </symbol>
  <symbol id="glyph1-15" overflow="visible">
   <path d="m10.25-6.5469c0 2.3438-0.37109 4.0703-1.1094 5.1719-0.73047 1.0938-1.8672 1.6406-3.4062 1.6406-1.5742 0-2.7266-0.55078-3.4531-1.6562-0.71875-1.1133-1.0781-2.8281-1.0781-5.1406 0-2.3203 0.36328-4.0352 1.0938-5.1406 0.73828-1.1133 1.8828-1.6719 3.4375-1.6719 1.5703 0 2.7188 0.5625 3.4375 1.6875s1.0781 2.8281 1.0781 5.1094zm-2.2969 3.9844c0.19531-0.46875 0.33203-1.0195 0.40625-1.6562 0.070313-0.64453 0.10938-1.4219 0.10938-2.3281 0-0.89453-0.039062-1.6719-0.10938-2.3281-0.074219-0.65625-0.21484-1.207-0.42188-1.6562-0.21094-0.45703-0.49219-0.80078-0.84375-1.0312-0.35547-0.22656-0.80859-0.34375-1.3594-0.34375-0.55469 0-1.0117 0.11719-1.375 0.34375-0.35547 0.23047-0.64062 0.57812-0.85938 1.0469-0.19922 0.42969-0.33594 0.99219-0.40625 1.6875-0.074219 0.69922-0.10938 1.4648-0.10938 2.2969 0 0.91797 0.03125 1.6836 0.09375 2.2969 0.070313 0.61719 0.21094 1.168 0.42188 1.6562 0.1875 0.44922 0.45703 0.79688 0.8125 1.0469 0.36328 0.24219 0.83594 0.35938 1.4219 0.35938 0.55078 0 1.0039-0.11328 1.3594-0.34375 0.36328-0.22656 0.64844-0.57812 0.85938-1.0469z" />
  </symbol>
  <symbol id="glyph1-16" overflow="visible">
   <path d="m9.5312 0h-7.0938v-1.3438h2.7344v-8.7656h-2.7344v-1.1875c0.375 0 0.76953-0.03125 1.1875-0.09375 0.42578-0.0625 0.75-0.14844 0.96875-0.26562 0.26953-0.15625 0.47656-0.34375 0.625-0.5625 0.15625-0.22656 0.25-0.53125 0.28125-0.90625h1.3594v11.781h2.6719z" />
  </symbol>
  <symbol id="glyph1-17" overflow="visible">
   <path d="m10.578-3.6875h-1.9531v3.6875h-1.6875v-3.6875h-6.2656v-2.0156l6.3438-7.3906h1.6094v8h1.9531zm-3.6406-1.4062v-5.9062l-5.0625 5.9062z" />
  </symbol>
  <symbol id="glyph2-1" overflow="visible">
   <path d="m10.672 0h-9.3594v-2.8281h2.625v-10.297h-2.625v-2.8438h9.3594v2.8438h-2.625v10.297h2.625z" />
  </symbol>
  <symbol id="glyph2-2" overflow="visible">
   <path d="m13.906 0h-3.875v-5.9688c0-0.48828-0.027344-0.97266-0.078125-1.4531-0.042969-0.47656-0.125-0.83203-0.25-1.0625-0.14844-0.26953-0.35938-0.46094-0.64062-0.57812-0.27344-0.125-0.65234-0.1875-1.1406-0.1875-0.35547 0-0.71484 0.058594-1.0781 0.17188-0.35547 0.11719-0.74219 0.29688-1.1562 0.54688v8.5312h-3.8594v-12.031h3.8594v1.3281c0.67578-0.53906 1.332-0.95312 1.9688-1.2344 0.63281-0.28906 1.3359-0.4375 2.1094-0.4375 1.3008 0 2.3164 0.38281 3.0469 1.1406 0.72656 0.76172 1.0938 1.8984 1.0938 3.4062z" />
  </symbol>
  <symbol id="glyph2-3" overflow="visible">
   <path d="m9.5156-0.10938c-0.41797 0.10547-0.85938 0.1875-1.3281 0.25-0.46094 0.0625-1.0234 0.09375-1.6875 0.09375-1.5 0-2.6211-0.30078-3.3594-0.90625-0.73047-0.61328-1.0938-1.6562-1.0938-3.125v-5.625h-1.5938v-2.6094h1.5938v-3.4531h3.8594v3.4531h3.6094v2.6094h-3.6094v4.2656 1.1094c0.007812 0.3125 0.070312 0.59375 0.1875 0.84375 0.09375 0.25 0.26562 0.44922 0.51562 0.59375 0.25781 0.14844 0.63281 0.21875 1.125 0.21875 0.19531 0 0.45703-0.039063 0.78125-0.125 0.32031-0.082031 0.55078-0.16016 0.6875-0.23438h0.3125z" />
  </symbol>
  <symbol id="glyph2-4" overflow="visible">
   <path d="m13.672-5.3125h-8.8281c0.0625 0.94922 0.42188 1.6719 1.0781 2.1719s1.6289 0.75 2.9219 0.75c0.8125 0 1.5977-0.14453 2.3594-0.4375 0.76953-0.28906 1.3789-0.60156 1.8281-0.9375h0.42188v3.0938c-0.875 0.34375-1.6992 0.59766-2.4688 0.75-0.77344 0.16406-1.625 0.25-2.5625 0.25-2.418 0-4.2734-0.53906-5.5625-1.625-1.2812-1.0938-1.9219-2.6445-1.9219-4.6562 0-1.9766 0.60938-3.5469 1.8281-4.7031 1.2188-1.1641 2.8906-1.75 5.0156-1.75 1.957 0 3.4258 0.49609 4.4062 1.4844 0.98828 0.99219 1.4844 2.4141 1.4844 4.2656zm-3.8281-2.25c-0.023438-0.8125-0.22656-1.4219-0.60938-1.8281-0.375-0.40625-0.96484-0.60938-1.7656-0.60938-0.74219 0-1.3516 0.19531-1.8281 0.57812-0.48047 0.38672-0.75 1.0078-0.8125 1.8594z" />
  </symbol>
  <symbol id="glyph2-5" overflow="visible">
   <path d="m5.6875 0h-3.8594v-16.672h3.8594z" />
  </symbol>
  <symbol id="glyph2-6" overflow="visible"></symbol>
  <symbol id="glyph2-7" overflow="visible">
   <path d="m14.547-4.4531c0 1.4062-0.60547 2.5625-1.8125 3.4688-1.1992 0.89844-2.8516 1.3438-4.9531 1.3438-1.1797 0-2.1875-0.12109-3.0312-0.35938s-1.543-0.57031-2.0938-1c-0.54297-0.42578-0.94531-0.92188-1.2031-1.4844-0.26172-0.5625-0.39062-1.1719-0.39062-1.8281 0-0.80078 0.23438-1.5078 0.70312-2.125 0.46875-0.61328 1.2734-1.1562 2.4219-1.625v-0.0625c-0.92969-0.42578-1.6094-0.96094-2.0469-1.6094-0.4375-0.65625-0.65625-1.4102-0.65625-2.2656 0-1.2695 0.58203-2.3047 1.75-3.1094 1.1758-0.8125 2.707-1.2188 4.5938-1.2188 1.9688 0 3.5078 0.37109 4.625 1.1094 1.125 0.73047 1.6875 1.7031 1.6875 2.9219 0 0.76172-0.24219 1.4375-0.71875 2.0312-0.46875 0.59375-1.1875 1.1016-2.1562 1.5156v0.0625c1.1133 0.41797 1.9375 0.98438 2.4688 1.7031 0.53906 0.71094 0.8125 1.5547 0.8125 2.5312zm-4.4219-7.375c0-0.55078-0.21484-0.98438-0.64062-1.2969-0.41797-0.32031-0.96875-0.48438-1.6562-0.48438-0.26172 0-0.52734 0.03125-0.79688 0.09375-0.26172 0.0625-0.50781 0.15625-0.73438 0.28125-0.21094 0.11719-0.38281 0.27344-0.51562 0.46875-0.13672 0.19922-0.20312 0.42188-0.20312 0.67188 0 0.42969 0.11719 0.76172 0.35938 1 0.23828 0.23047 0.63281 0.46484 1.1875 0.70312 0.19531 0.085937 0.46875 0.1875 0.8125 0.3125s0.76562 0.26562 1.2656 0.42188c0.32031-0.38281 0.55469-0.72656 0.70312-1.0312 0.14453-0.3125 0.21875-0.69141 0.21875-1.1406zm0.32812 7.5469c0-0.50781-0.13281-0.89453-0.39062-1.1562-0.26172-0.26953-0.78906-0.57812-1.5781-0.92188-0.24219-0.10156-0.58594-0.23438-1.0312-0.39062-0.44922-0.15625-0.82812-0.28906-1.1406-0.40625-0.30469 0.27344-0.57812 0.60938-0.82812 1.0156-0.25 0.39844-0.375 0.83984-0.375 1.3281 0 0.74219 0.26562 1.3359 0.79688 1.7812 0.53125 0.4375 1.2266 0.65625 2.0938 0.65625 0.22656 0 0.49219-0.03125 0.79688-0.09375 0.3125-0.070312 0.57812-0.17969 0.79688-0.32812 0.25781-0.16406 0.46875-0.35938 0.625-0.57812s0.23438-0.51953 0.23438-0.90625z" />
  </symbol>
  <symbol id="glyph2-8" overflow="visible">
   <path d="m14.516 0h-12.531v-2.6406c0.95703-0.6875 1.9141-1.4219 2.875-2.2031 0.95703-0.78125 1.7266-1.4531 2.3125-2.0156 0.86328-0.83203 1.4766-1.5625 1.8438-2.1875 0.36328-0.625 0.54688-1.2383 0.54688-1.8438 0-0.72656-0.23438-1.2891-0.70312-1.6875-0.46875-0.39453-1.1406-0.59375-2.0156-0.59375-0.65625 0-1.3516 0.13672-2.0781 0.40625-0.73047 0.27344-1.4023 0.61719-2.0156 1.0312h-0.34375v-3.5469c0.5-0.21875 1.2422-0.4375 2.2344-0.65625 0.98828-0.21875 1.9844-0.32812 2.9844-0.32812 2 0 3.5234 0.42188 4.5781 1.2656 1.0508 0.83594 1.5781 2.0156 1.5781 3.5469 0 1.0117-0.25781 1.9688-0.76562 2.875-0.5 0.90625-1.2734 1.8438-2.3125 2.8125-0.64844 0.60547-1.2969 1.1562-1.9531 1.6562s-1.125 0.85156-1.4062 1.0469h7.1719z" />
  </symbol>
  <symbol id="glyph2-9" overflow="visible">
   <path d="m14.172-5.4062c0 0.83594-0.15625 1.6055-0.46875 2.3125-0.3125 0.71094-0.76562 1.3203-1.3594 1.8281-0.65625 0.54297-1.4141 0.94531-2.2656 1.2031-0.85547 0.25781-1.8281 0.39062-2.9219 0.39062-1.2812 0-2.3672-0.10156-3.25-0.29688-0.875-0.19531-1.5898-0.41406-2.1406-0.65625v-3.5312h0.4375c0.65625 0.38672 1.3594 0.71094 2.1094 0.96875 0.75 0.25 1.4922 0.375 2.2344 0.375 0.44531 0 0.92969-0.050781 1.4531-0.15625 0.53125-0.10156 0.95312-0.28906 1.2656-0.5625 0.23828-0.21875 0.42188-0.44141 0.54688-0.67188 0.125-0.22656 0.1875-0.58203 0.1875-1.0625 0-0.375-0.085938-0.69141-0.25-0.95312-0.16797-0.26953-0.38672-0.48828-0.65625-0.65625-0.38672-0.22656-0.85156-0.37891-1.3906-0.45312-0.54297-0.082031-1.0312-0.125-1.4688-0.125-0.64844 0-1.2656 0.058594-1.8594 0.17188-0.58594 0.10547-1.1016 0.21484-1.5469 0.32812h-0.46875v-9.0156h11.344v3.0625h-7.4688v2.6094c0.21875-0.019531 0.49219-0.035156 0.82812-0.046875 0.34375-0.007812 0.64453-0.015625 0.90625-0.015625 0.875 0 1.6562 0.089844 2.3438 0.26562 0.69531 0.16797 1.2969 0.39844 1.7969 0.6875 0.64453 0.39844 1.1484 0.91797 1.5156 1.5625 0.36328 0.64844 0.54688 1.4609 0.54688 2.4375z" />
  </symbol>
  <symbol id="glyph2-10" overflow="visible">
   <path d="m14.188-12.781-7.2344 12.781h-4.5781l7.5-12.906h-8.2031v-3.0625h12.516z" />
  </symbol>
  <symbol id="glyph2-11" overflow="visible">
   <path d="m14.5-5.4375c0 0.82422-0.15234 1.6016-0.45312 2.3281-0.30469 0.71875-0.72656 1.3242-1.2656 1.8125-0.58594 0.53125-1.2578 0.9375-2.0156 1.2188-0.76172 0.26953-1.6523 0.40625-2.6719 0.40625-0.96094 0-1.8359-0.13281-2.625-0.39062-0.79297-0.25781-1.4688-0.65625-2.0312-1.1875-0.64844-0.61328-1.1406-1.4062-1.4844-2.375-0.34375-0.97656-0.51562-2.1445-0.51562-3.5 0-1.3945 0.16016-2.6328 0.48438-3.7188 0.32031-1.0938 0.84766-2.0547 1.5781-2.8906 0.69531-0.80078 1.6016-1.4219 2.7188-1.8594 1.125-0.44531 2.457-0.67188 4-0.67188 0.51953 0 1.0859 0.039063 1.7031 0.10938 0.625 0.074219 1.0312 0.125 1.2188 0.15625v3.1406h-0.40625c-0.19922-0.082031-0.52734-0.17969-0.98438-0.29688-0.46094-0.125-0.98047-0.1875-1.5625-0.1875-1.375 0-2.4492 0.33984-3.2188 1.0156-0.76172 0.66797-1.2188 1.6016-1.375 2.7969 0.55078-0.32031 1.1289-0.58594 1.7344-0.79688 0.61328-0.20703 1.2734-0.3125 1.9844-0.3125 0.625 0 1.2031 0.074219 1.7344 0.21875 0.53125 0.14844 1.0234 0.375 1.4844 0.6875 0.59375 0.41797 1.0664 0.97656 1.4219 1.6719 0.36328 0.69922 0.54688 1.5742 0.54688 2.625zm-4.8906 2.4219c0.22656-0.25 0.40625-0.53906 0.53125-0.875 0.13281-0.33203 0.20312-0.78125 0.20312-1.3438 0-0.53125-0.078125-0.95703-0.23438-1.2812-0.14844-0.33203-0.35156-0.60156-0.60938-0.8125-0.26172-0.19531-0.57031-0.33203-0.92188-0.40625-0.34375-0.070313-0.70312-0.10938-1.0781-0.10938-0.3125 0-0.64062 0.039062-0.98438 0.10938-0.34375 0.074219-0.65625 0.16406-0.9375 0.26562 0 0.074219-0.007813 0.19531-0.015625 0.35938-0.011719 0.15625-0.015625 0.35938-0.015625 0.60938 0 0.88672 0.085937 1.6172 0.26562 2.1875 0.17578 0.5625 0.41016 0.99609 0.70312 1.2969 0.19531 0.21875 0.42969 0.38281 0.70312 0.48438 0.26953 0.10547 0.56641 0.15625 0.89062 0.15625 0.22656 0 0.48438-0.050781 0.76562-0.15625 0.28906-0.11328 0.53516-0.27344 0.73438-0.48438z" />
  </symbol>
  <symbol id="glyph2-12" overflow="visible">
   <path d="m13.578 0h-11.547v-15.969h11.547v3.0938h-7.4531v2.75h6.9219v3.0938h-6.9219v3.9375h7.4531z" />
  </symbol>
  <symbol id="glyph2-13" overflow="visible">
   <path d="m15.688-4.8906c0 0.77344-0.15625 1.4648-0.46875 2.0781-0.30469 0.60547-0.72656 1.1055-1.2656 1.5-0.63672 0.48047-1.3359 0.82031-2.0938 1.0156-0.75 0.19922-1.7031 0.29688-2.8594 0.29688h-6.9688v-15.969h6.2031c1.2812 0 2.2188 0.046875 2.8125 0.14062 0.60156 0.085937 1.1953 0.27344 1.7812 0.5625 0.60156 0.3125 1.0508 0.73047 1.3438 1.25 0.30078 0.51172 0.45312 1.1016 0.45312 1.7656 0 0.77344-0.20312 1.4531-0.60938 2.0469-0.40625 0.58594-0.98047 1.043-1.7188 1.375v0.078125c1.0391 0.21094 1.8633 0.64062 2.4688 1.2969 0.61328 0.64844 0.92188 1.5 0.92188 2.5625zm-5.2656-6.5625c0-0.25781-0.070313-0.51953-0.20312-0.78125-0.13672-0.26953-0.37109-0.46875-0.70312-0.59375-0.30469-0.11328-0.67969-0.17578-1.125-0.1875-0.4375-0.007813-1.0625-0.015625-1.875-0.015625h-0.39062v3.375h0.65625c0.64453 0 1.1953-0.007812 1.6562-0.03125 0.45703-0.019531 0.81641-0.09375 1.0781-0.21875 0.375-0.16406 0.61719-0.37891 0.73438-0.64062 0.11328-0.25781 0.17188-0.5625 0.17188-0.90625zm1 6.5c0-0.50781-0.10156-0.89844-0.29688-1.1719-0.1875-0.26953-0.52344-0.47656-1-0.625-0.32422-0.082031-0.76562-0.12891-1.3281-0.14062-0.5625-0.007813-1.1523-0.015625-1.7656-0.015625h-0.90625v3.9844h0.3125c1.1562 0 1.9844-0.003906 2.4844-0.015625 0.5-0.007812 0.95703-0.10156 1.375-0.28125 0.42578-0.17578 0.71875-0.41016 0.875-0.70312 0.16406-0.30078 0.25-0.64453 0.25-1.0312z" />
  </symbol>
  <symbol id="glyph2-14" overflow="visible">
   <path d="m16.156-0.90625c-0.71875 0.27344-1.668 0.54688-2.8438 0.82812-1.1797 0.26953-2.3555 0.40625-3.5312 0.40625-2.7109 0-4.8359-0.73438-6.375-2.2031-1.5312-1.4766-2.2969-3.5195-2.2969-6.125 0-2.4766 0.76953-4.4727 2.3125-5.9844 1.5508-1.5195 3.7188-2.2812 6.5-2.2812 1.0391 0 2.0352 0.09375 2.9844 0.28125 0.95703 0.1875 2.0195 0.5625 3.1875 1.125v3.75h-0.46875c-0.19922-0.15625-0.49219-0.36719-0.875-0.64062-0.38672-0.28125-0.75781-0.51562-1.1094-0.70312-0.41797-0.22656-0.90234-0.42578-1.4531-0.59375-0.55469-0.16406-1.1406-0.25-1.7656-0.25-0.73047 0-1.3906 0.10938-1.9844 0.32812-0.59375 0.21094-1.125 0.53906-1.5938 0.98438-0.46094 0.42969-0.82031 0.97656-1.0781 1.6406-0.26172 0.65625-0.39062 1.418-0.39062 2.2812 0 1.7734 0.46875 3.125 1.4062 4.0625 0.9375 0.92969 2.3203 1.3906 4.1562 1.3906h0.51562c0.1875-0.007813 0.35938-0.019531 0.51562-0.03125v-3.1406h-3.1719v-3.0156h7.3594z" />
  </symbol>
  <symbol id="glyph2-15" overflow="visible">
   <path d="m5.6875 0h-3.8594v-12.031h3.8594zm0.09375-13.75h-4.0625v-2.9219h4.0625z" />
  </symbol>
  <symbol id="glyph2-16" overflow="visible">
   <path d="m13.531-1.375c0 1.125-0.16406 2.0703-0.48438 2.8438-0.32422 0.76953-0.77734 1.375-1.3594 1.8125-0.57422 0.4375-1.2734 0.75391-2.0938 0.95312-0.8125 0.19531-1.7344 0.29688-2.7656 0.29688-0.83594 0-1.6562-0.054688-2.4688-0.15625-0.8125-0.09375-1.5156-0.21484-2.1094-0.35938v-3.0156h0.46875c0.47656 0.1875 1.0547 0.35938 1.7344 0.51562 0.67578 0.15625 1.2812 0.23438 1.8125 0.23438 0.71875 0 1.3008-0.070312 1.75-0.20312 0.44531-0.13672 0.78516-0.32422 1.0156-0.5625 0.22656-0.23047 0.39062-0.52344 0.48438-0.875 0.10156-0.35156 0.15625-0.78125 0.15625-1.2812v-0.23438c-0.46875 0.375-0.98438 0.67969-1.5469 0.90625-0.5625 0.21875-1.1953 0.32812-1.8906 0.32812-1.6875 0-2.9922-0.50391-3.9062-1.5156-0.90625-1.0195-1.3594-2.5664-1.3594-4.6406 0-0.98828 0.13281-1.8438 0.40625-2.5625 0.28125-0.72656 0.67578-1.3594 1.1875-1.8906 0.46875-0.5 1.0469-0.89062 1.7344-1.1719 0.69531-0.28125 1.4062-0.42188 2.125-0.42188 0.64453 0 1.2344 0.078125 1.7656 0.23438 0.53906 0.15625 1.0234 0.37109 1.4531 0.64062l0.14062-0.53125h3.75zm-3.8594-2.4219v-5.4531c-0.21875-0.09375-0.49219-0.16406-0.8125-0.21875-0.32422-0.050781-0.61719-0.078125-0.875-0.078125-1.0117 0-1.7734 0.29297-2.2812 0.875-0.51172 0.58594-0.76562 1.3984-0.76562 2.4375 0 1.1562 0.21094 1.9648 0.64062 2.4219 0.4375 0.46094 1.082 0.6875 1.9375 0.6875 0.38281 0 0.75781-0.0625 1.125-0.1875 0.375-0.125 0.71875-0.28516 1.0312-0.48438z" />
  </symbol>
  <symbol id="glyph2-17" overflow="visible">
   <path d="m9.1094-3.1406v-2.5156c-0.52344 0.054688-1.0898 0.11719-1.7031 0.1875-0.60547 0.074219-1.0625 0.16406-1.375 0.26562-0.38672 0.11719-0.68359 0.29297-0.89062 0.53125-0.19922 0.23047-0.29688 0.53125-0.29688 0.90625 0 0.25 0.019531 0.45312 0.0625 0.60938 0.039062 0.15625 0.14844 0.30859 0.32812 0.45312 0.16406 0.14844 0.35938 0.25781 0.57812 0.32812 0.22656 0.0625 0.58594 0.09375 1.0781 0.09375 0.38281 0 0.77344-0.078125 1.1719-0.23438 0.39453-0.15625 0.74219-0.36328 1.0469-0.625zm0 1.8594c-0.21094 0.15625-0.46875 0.35156-0.78125 0.57812-0.30469 0.21875-0.58984 0.39062-0.85938 0.51562-0.375 0.17969-0.76562 0.30469-1.1719 0.39062-0.40625 0.082031-0.85547 0.125-1.3438 0.125-1.1484 0-2.1055-0.35156-2.875-1.0625-0.77344-0.70703-1.1562-1.6133-1.1562-2.7188 0-0.875 0.19141-1.5859 0.57812-2.1406 0.39453-0.5625 0.95703-1.0039 1.6875-1.3281 0.70703-0.32031 1.5859-0.55078 2.6406-0.6875 1.0625-0.13281 2.1641-0.23438 3.3125-0.29688v-0.0625c0-0.66406-0.27734-1.125-0.82812-1.375-0.54297-0.25781-1.3398-0.39062-2.3906-0.39062-0.63672 0-1.3203 0.11719-2.0469 0.34375-0.71875 0.21875-1.2344 0.39062-1.5469 0.51562h-0.35938v-2.9062c0.40625-0.10156 1.0664-0.22656 1.9844-0.375 0.92578-0.14453 1.8477-0.21875 2.7656-0.21875 2.1953 0 3.7812 0.33984 4.75 1.0156 0.97656 0.66797 1.4688 1.7266 1.4688 3.1719v8.1875h-3.8281z" />
  </symbol>
  <symbol id="glyph2-18" overflow="visible">
   <path d="m14.391-6.1875c0 1.8984-0.52734 3.4453-1.5781 4.6406-1.043 1.1875-2.3516 1.7812-3.9219 1.7812-0.66797 0-1.2578-0.074219-1.7656-0.21875-0.5-0.13281-0.98047-0.33594-1.4375-0.60938l-0.17188 0.59375h-3.6875v-16.672h3.8594v5.8906c0.59375-0.46875 1.1953-0.84766 1.8125-1.1406 0.61328-0.30078 1.3281-0.45312 2.1406-0.45312 1.5195 0 2.6914 0.55469 3.5156 1.6562 0.82031 1.0938 1.2344 2.6055 1.2344 4.5312zm-3.9844 0.078125c0-1.0703-0.18359-1.8945-0.54688-2.4688-0.36719-0.58203-1.0156-0.875-1.9531-0.875-0.36719 0-0.74219 0.058594-1.125 0.17188-0.38672 0.10547-0.75 0.26172-1.0938 0.46875v6.0469c0.26953 0.10547 0.53125 0.17188 0.78125 0.20312s0.55078 0.046875 0.90625 0.046875c1.0195 0 1.7812-0.29688 2.2812-0.89062 0.5-0.60156 0.75-1.5039 0.75-2.7031z" />
  </symbol>
  <symbol id="glyph2-19" overflow="visible">
   <path d="m13.906 0h-3.875v-5.9688c0-0.48828-0.027344-0.97266-0.078125-1.4531-0.042969-0.47656-0.125-0.83203-0.25-1.0625-0.14844-0.26953-0.35938-0.46094-0.64062-0.57812-0.27344-0.125-0.65234-0.1875-1.1406-0.1875-0.35547 0-0.71484 0.058594-1.0781 0.17188-0.35547 0.11719-0.74219 0.29688-1.1562 0.54688v8.5312h-3.8594v-16.672h3.8594v5.9688c0.67578-0.53906 1.332-0.95312 1.9688-1.2344 0.63281-0.28906 1.3359-0.4375 2.1094-0.4375 1.3008 0 2.3164 0.38281 3.0469 1.1406 0.72656 0.76172 1.0938 1.8984 1.0938 3.4062z" />
  </symbol>
  <symbol id="glyph2-20" overflow="visible">
   <path d="m10.547-8.3594h-0.34375c-0.16797-0.0625-0.43359-0.10156-0.79688-0.125-0.36719-0.03125-0.66797-0.046875-0.90625-0.046875-0.55469 0-1.043 0.039062-1.4688 0.10938-0.41797 0.074219-0.86719 0.19531-1.3438 0.35938v8.0625h-3.8594v-12.031h3.8594v1.7656c0.84375-0.72656 1.5781-1.2109 2.2031-1.4531 0.63281-0.23828 1.2188-0.35938 1.75-0.35938 0.13281 0 0.28516 0.007813 0.45312 0.015625 0.17578 0 0.32812 0.011719 0.45312 0.03125z" />
  </symbol>
  <symbol id="glyph2-21" overflow="visible">
   <path d="m9.25 0.3125c-1.1875 0-2.2891-0.17578-3.2969-0.51562-1-0.35156-1.8594-0.87891-2.5781-1.5781-0.71875-0.6875-1.2773-1.5469-1.6719-2.5781-0.39844-1.0391-0.59375-2.2422-0.59375-3.6094 0-1.2578 0.1875-2.4062 0.5625-3.4375s0.92578-1.9102 1.6562-2.6406c0.6875-0.70703 1.5391-1.2539 2.5625-1.6406 1.0312-0.38281 2.1562-0.57812 3.375-0.57812 0.66406 0 1.2695 0.039063 1.8125 0.10938 0.53906 0.074219 1.0391 0.17188 1.5 0.29688 0.47656 0.13672 0.91016 0.28906 1.2969 0.45312 0.38281 0.16797 0.72656 0.32422 1.0312 0.46875v3.8594h-0.48438c-0.19922-0.16406-0.44922-0.36328-0.75-0.59375-0.30469-0.23828-0.64844-0.47266-1.0312-0.70312-0.39844-0.22656-0.82422-0.42188-1.2812-0.57812-0.46094-0.16406-0.94922-0.25-1.4688-0.25-0.57422 0-1.125 0.09375-1.6562 0.28125-0.52344 0.17969-1 0.48047-1.4375 0.90625-0.42969 0.40625-0.77344 0.94922-1.0312 1.625-0.26172 0.66797-0.39062 1.4805-0.39062 2.4375 0 1 0.14062 1.8398 0.42188 2.5156 0.28906 0.66797 0.64844 1.1953 1.0781 1.5781 0.4375 0.39844 0.92188 0.67969 1.4531 0.84375 0.53906 0.16797 1.0703 0.25 1.5938 0.25 0.5 0 0.99219-0.070313 1.4844-0.21875 0.48828-0.15625 0.9375-0.36328 1.3438-0.625 0.35156-0.19531 0.67969-0.41406 0.98438-0.65625 0.30078-0.23828 0.54688-0.44141 0.73438-0.60938h0.4375v3.8125c-0.40625 0.17969-0.79297 0.34375-1.1562 0.5-0.36719 0.15625-0.74609 0.29297-1.1406 0.40625-0.52344 0.15625-1.0117 0.26953-1.4688 0.34375-0.46094 0.082031-1.0898 0.125-1.8906 0.125z" />
  </symbol>
  <symbol id="glyph2-22" overflow="visible">
   <path d="m14.125-6.0156c0 1.9805-0.57812 3.543-1.7344 4.6875-1.1484 1.1367-2.7656 1.7031-4.8594 1.7031-2.0859 0-3.7031-0.56641-4.8594-1.7031-1.1562-1.1445-1.7344-2.707-1.7344-4.6875 0-1.9883 0.57812-3.5508 1.7344-4.6875 1.1641-1.1328 2.7852-1.7031 4.8594-1.7031 2.1016 0 3.7266 0.57422 4.875 1.7188 1.1445 1.1367 1.7188 2.6953 1.7188 4.6719zm-4.75 2.9219c0.25-0.30078 0.4375-0.66406 0.5625-1.0938 0.125-0.4375 0.1875-1.0352 0.1875-1.7969 0-0.70703-0.0625-1.3008-0.1875-1.7812-0.125-0.47656-0.30469-0.86328-0.53125-1.1562-0.23047-0.28906-0.50781-0.49219-0.82812-0.60938-0.32422-0.125-0.67188-0.1875-1.0469-0.1875-0.36719 0-0.69531 0.054688-0.98438 0.15625-0.29297 0.09375-0.57031 0.29297-0.82812 0.59375-0.24219 0.28125-0.43359 0.66797-0.57812 1.1562-0.13672 0.48047-0.20312 1.0898-0.20312 1.8281 0 0.65625 0.0625 1.2266 0.1875 1.7031 0.125 0.48047 0.30078 0.86719 0.53125 1.1562 0.22656 0.28125 0.5 0.49219 0.8125 0.625 0.32031 0.125 0.6875 0.1875 1.0938 0.1875 0.35156 0 0.6875-0.054688 1-0.17188 0.32031-0.125 0.59375-0.32812 0.8125-0.60938z" />
  </symbol>
  <symbol id="glyph2-23" overflow="visible">
   <path d="m17.125-7.9688c0 1.4922-0.34375 2.8242-1.0312 4-0.67969 1.1797-1.5312 2.0781-2.5625 2.7031-0.78125 0.46875-1.6367 0.79688-2.5625 0.98438-0.92969 0.1875-2.0273 0.28125-3.2969 0.28125h-5.6406v-15.969h5.7969c1.3008 0 2.4219 0.10938 3.3594 0.32812 0.94531 0.21875 1.7422 0.53125 2.3906 0.9375 1.0938 0.66797 1.957 1.5742 2.5938 2.7188 0.63281 1.1367 0.95312 2.4766 0.95312 4.0156zm-4.2656-0.03125c0-1.0508-0.19531-1.9453-0.57812-2.6875-0.375-0.75-0.98047-1.332-1.8125-1.75-0.41797-0.20703-0.85156-0.34766-1.2969-0.42188-0.4375-0.082031-1.1016-0.125-1.9844-0.125h-1.0312v10h1.0312c0.97656 0 1.6953-0.046875 2.1562-0.14062 0.45703-0.09375 0.90625-0.25391 1.3438-0.48438 0.75-0.42578 1.2969-1 1.6406-1.7188 0.35156-0.71875 0.53125-1.6094 0.53125-2.6719z" />
  </symbol>
  <symbol id="glyph2-24" overflow="visible">
   <path d="m12.281-3.8125c0 1.2422-0.55859 2.2422-1.6719 3-1.1172 0.76172-2.6406 1.1406-4.5781 1.1406-1.0742 0-2.0469-0.10156-2.9219-0.29688-0.86719-0.19531-1.5625-0.41406-2.0938-0.65625v-3.1875h0.35938c0.1875 0.13672 0.40625 0.28906 0.65625 0.45312 0.25781 0.15625 0.625 0.32812 1.0938 0.51562 0.39453 0.16797 0.84375 0.3125 1.3438 0.4375 0.50781 0.11719 1.0547 0.17188 1.6406 0.17188 0.75781 0 1.3203-0.082031 1.6875-0.25 0.36328-0.17578 0.54688-0.42578 0.54688-0.75 0-0.28906-0.10938-0.50391-0.32812-0.64062-0.21094-0.13281-0.61719-0.25781-1.2188-0.375-0.28125-0.070312-0.66797-0.14453-1.1562-0.21875-0.49219-0.070312-0.9375-0.16016-1.3438-0.26562-1.0938-0.28906-1.9062-0.73828-2.4375-1.3438-0.52344-0.60156-0.78125-1.3516-0.78125-2.25 0-1.1562 0.54688-2.1172 1.6406-2.8906 1.0938-0.76953 2.5938-1.1562 4.5-1.1562 0.89453 0 1.7539 0.09375 2.5781 0.28125 0.83203 0.17969 1.4766 0.37109 1.9375 0.57812v3.0469h-0.32812c-0.57422-0.39453-1.2305-0.71094-1.9688-0.95312-0.73047-0.25-1.4688-0.375-2.2188-0.375-0.61719 0-1.1367 0.089844-1.5625 0.26562-0.42969 0.16797-0.64062 0.40625-0.64062 0.71875 0 0.29297 0.09375 0.51172 0.28125 0.65625 0.19531 0.14844 0.65625 0.29688 1.375 0.45312 0.38281 0.074219 0.80469 0.15234 1.2656 0.23438 0.45703 0.074219 0.91016 0.16797 1.3594 0.28125 1.0195 0.26172 1.7695 0.67969 2.25 1.25 0.48828 0.5625 0.73438 1.2734 0.73438 2.125z" />
  </symbol>
  <symbol id="glyph3-1" overflow="visible">
   <path d="m15.891-5.625c0 2.0547-0.72656 3.8047-2.1719 5.25-1.4492 1.4453-3.1992 2.1719-5.25 2.1719-2.043 0-3.793-0.72656-5.25-2.1719-1.4492-1.4453-2.1719-3.1953-2.1719-5.25 0-2.0391 0.72266-3.7852 2.1719-5.2344 1.457-1.457 3.207-2.1875 5.25-2.1875 2.0508 0 3.8008 0.73047 5.25 2.1875 1.4453 1.4492 2.1719 3.1953 2.1719 5.2344zm-1.625 0c0-1.5938-0.57031-2.9609-1.7031-4.1094-1.125-1.1445-2.4844-1.7188-4.0781-1.7188-1.6055 0-2.9766 0.57422-4.1094 1.7188-1.125 1.1484-1.6875 2.5156-1.6875 4.1094s0.5625 2.9688 1.6875 4.125c1.1328 1.1484 2.5039 1.7188 4.1094 1.7188 1.5938 0 2.9531-0.57031 4.0781-1.7188 1.1328-1.1562 1.7031-2.5312 1.7031-4.125zm-1.625 3.5156h-2.3281l-2.2344-2.7031h-0.73438v2.7031h-1.8281v-7.3906h2.8125c0.51953 0 0.9375 0.023438 1.25 0.0625 0.3125 0.042969 0.625 0.14844 0.9375 0.3125 0.33203 0.1875 0.57812 0.41797 0.73438 0.6875 0.16406 0.27344 0.25 0.60547 0.25 1 0 0.54297-0.15625 0.99219-0.46875 1.3438-0.30469 0.34375-0.69531 0.61719-1.1719 0.8125zm-3.1719-5.1875c0-0.15625-0.039062-0.29688-0.10938-0.42188-0.0625-0.125-0.17188-0.22656-0.32812-0.3125-0.13672-0.082031-0.29688-0.13281-0.48438-0.15625-0.1875-0.019531-0.40234-0.03125-0.64062-0.03125h-0.5625v2.0938h0.4375c0.30078 0 0.5625-0.019531 0.78125-0.0625 0.21875-0.039062 0.39062-0.11328 0.51562-0.21875 0.13281-0.10156 0.23438-0.22266 0.29688-0.35938 0.0625-0.14453 0.09375-0.32031 0.09375-0.53125z" />
  </symbol>
  <symbol id="glyph4-1" overflow="visible">
   <path d="m9.0469 0h-2.1719l-3.7031-5.9844v5.9844h-2.0625v-8.7188h2.6875l3.1875 4.9844v-4.9844h2.0625z" />
  </symbol>
  <symbol id="glyph4-2" overflow="visible">
   <path d="m7.4844-2.9062h-4.8281c0.03125 0.52344 0.22266 0.91797 0.57812 1.1875 0.36328 0.27344 0.89453 0.40625 1.5938 0.40625 0.44531 0 0.87891-0.078125 1.2969-0.23438 0.41406-0.15625 0.75-0.32812 1-0.51562h0.23438v1.6875c-0.48047 0.19922-0.93359 0.33984-1.3594 0.42188-0.41797 0.082031-0.88281 0.125-1.3906 0.125-1.3242 0-2.3398-0.29688-3.0469-0.89062-0.69922-0.59375-1.0469-1.4375-1.0469-2.5312 0-1.082 0.33203-1.9414 1-2.5781 0.66406-0.63281 1.5781-0.95312 2.7344-0.95312 1.0703 0 1.8789 0.27344 2.4219 0.8125 0.53906 0.54297 0.8125 1.3203 0.8125 2.3281zm-2.1094-1.2344c-0.011719-0.4375-0.12109-0.76562-0.32812-0.98438-0.21094-0.22656-0.53125-0.34375-0.96875-0.34375-0.40625 0-0.74219 0.10938-1 0.32812-0.26172 0.21094-0.40625 0.54297-0.4375 1z" />
  </symbol>
  <symbol id="glyph4-3" overflow="visible">
   <path d="m5.2031-0.0625c-0.23047 0.0625-0.46875 0.10938-0.71875 0.14062s-0.5625 0.046875-0.9375 0.046875c-0.8125 0-1.4219-0.16406-1.8281-0.5-0.39844-0.33203-0.59375-0.89844-0.59375-1.7031v-3.0781h-0.875v-1.4219h0.875v-1.8906h2.1094v1.8906h1.9688v1.4219h-1.9688v2.3438 0.60938c0 0.16797 0.03125 0.32031 0.09375 0.45312 0.050781 0.13672 0.14453 0.24609 0.28125 0.32812 0.14453 0.074219 0.34766 0.10938 0.60938 0.10938 0.11328 0 0.25781-0.019531 0.4375-0.0625 0.17578-0.050781 0.30078-0.09375 0.375-0.125h0.17188z" />
  </symbol>
  <symbol id="glyph4-4" overflow="visible">
   <path d="m11.484-6.5781-2.0312 6.5781h-2.2344l-1.3438-4.4375-1.3281 4.4375h-2.2656l-2.0156-6.5781h2.2188l1.125 4.5312 1.4062-4.5312h1.8594l1.3438 4.5312 1.1094-4.5312z" />
  </symbol>
  <symbol id="glyph4-5" overflow="visible">
   <path d="m7.7188-3.2812c0 1.0742-0.32031 1.9219-0.95312 2.5469-0.625 0.625-1.5078 0.9375-2.6406 0.9375-1.1484 0-2.0391-0.3125-2.6719-0.9375-0.625-0.625-0.9375-1.4727-0.9375-2.5469 0-1.0938 0.31641-1.9453 0.95312-2.5625 0.63281-0.625 1.5195-0.9375 2.6562-0.9375 1.1445 0 2.0312 0.3125 2.6562 0.9375s0.9375 1.4805 0.9375 2.5625zm-2.5938 1.5938c0.13281-0.16406 0.23438-0.36719 0.29688-0.60938 0.070313-0.23828 0.10938-0.56641 0.10938-0.98438 0-0.38281-0.039062-0.70703-0.10938-0.96875-0.0625-0.25781-0.15625-0.46875-0.28125-0.625s-0.27734-0.26562-0.45312-0.32812c-0.17969-0.070313-0.36719-0.10938-0.5625-0.10938-0.21094 0-0.39062 0.027344-0.54688 0.078125-0.15625 0.054687-0.30859 0.16406-0.45312 0.32812-0.125 0.15625-0.23047 0.37109-0.3125 0.64062-0.074219 0.26172-0.10938 0.58984-0.10938 0.98438 0 0.36719 0.03125 0.67969 0.09375 0.9375 0.070313 0.26172 0.17188 0.47656 0.29688 0.64062 0.125 0.14844 0.26953 0.25781 0.4375 0.32812 0.17578 0.074219 0.37891 0.10938 0.60938 0.10938 0.1875 0 0.36719-0.03125 0.54688-0.09375 0.17578-0.0625 0.32031-0.17188 0.4375-0.32812z" />
  </symbol>
  <symbol id="glyph4-6" overflow="visible">
   <path d="m5.7656-4.5781h-0.1875c-0.09375-0.03125-0.24219-0.050781-0.4375-0.0625-0.19922-0.019531-0.36719-0.03125-0.5-0.03125-0.29297 0-0.55859 0.023437-0.79688 0.0625-0.23047 0.042969-0.47656 0.10938-0.73438 0.20312v4.4062h-2.1094v-6.5781h2.1094v0.96875c0.45703-0.40625 0.85938-0.67188 1.2031-0.79688 0.34375-0.13281 0.66016-0.20312 0.95312-0.20312 0.070313 0 0.15625 0.007813 0.25 0.015625 0.09375 0 0.17578 0.007812 0.25 0.015625z" />
  </symbol>
  <symbol id="glyph4-7" overflow="visible">
   <path d="m7.9844 0h-2.4531l-1.8438-2.8594-0.57812 0.6875v2.1719h-2.1094v-9.125h2.1094v5.4531l2.2656-2.9062h2.4375l-2.375 2.8281z" />
  </symbol>
  <symbol id="glyph4-8" overflow="visible">
   <path d="m3.1094 0h-2.1094v-6.5781h2.1094zm0.0625-7.5156h-2.2344v-1.6094h2.2344z" />
  </symbol>
  <symbol id="glyph4-9" overflow="visible">
   <path d="m7.6094 0h-2.125v-3.2656c0-0.25781-0.015625-0.51953-0.046875-0.78125-0.023438-0.26953-0.070312-0.46875-0.14062-0.59375-0.074219-0.14453-0.1875-0.25-0.34375-0.3125-0.14844-0.070313-0.35547-0.10938-0.625-0.10938-0.1875 0-0.38281 0.03125-0.57812 0.09375-0.19922 0.0625-0.41406 0.16406-0.64062 0.29688v4.6719h-2.1094v-6.5781h2.1094v0.71875c0.375-0.28906 0.73438-0.51562 1.0781-0.67188s0.72656-0.23438 1.1562-0.23438c0.70703 0 1.2578 0.21094 1.6562 0.625 0.40625 0.41797 0.60938 1.0391 0.60938 1.8594z" />
  </symbol>
  <symbol id="glyph4-10" overflow="visible">
   <path d="m7.3906-0.75c0 0.61719-0.089844 1.1289-0.26562 1.5469-0.16797 0.42578-0.41406 0.75781-0.73438 1-0.3125 0.23828-0.69531 0.41016-1.1406 0.51562-0.44922 0.11328-0.95312 0.17188-1.5156 0.17188-0.46094 0-0.91406-0.03125-1.3594-0.09375-0.4375-0.054687-0.82031-0.11719-1.1406-0.1875v-1.6562h0.25c0.25781 0.10156 0.57031 0.19531 0.9375 0.28125 0.375 0.082031 0.70703 0.125 1 0.125 0.39453 0 0.71094-0.039063 0.95312-0.10938 0.25-0.074219 0.4375-0.17188 0.5625-0.29688s0.21094-0.28906 0.26562-0.48438c0.050781-0.19531 0.078125-0.42969 0.078125-0.70312v-0.125c-0.25 0.21094-0.53125 0.375-0.84375 0.5-0.30469 0.11719-0.64844 0.17188-1.0312 0.17188-0.91797 0-1.625-0.27344-2.125-0.82812-0.5-0.5625-0.75-1.4062-0.75-2.5312 0-0.53906 0.070312-1.0078 0.21875-1.4062 0.15625-0.39453 0.375-0.73828 0.65625-1.0312 0.25-0.28125 0.5625-0.49219 0.9375-0.64062 0.38281-0.15625 0.77344-0.23438 1.1719-0.23438 0.35156 0 0.67578 0.042969 0.96875 0.125 0.28906 0.085937 0.55469 0.20312 0.79688 0.35938l0.0625-0.29688h2.0469zm-2.1094-1.3281v-2.9844c-0.11719-0.050781-0.26172-0.085938-0.4375-0.10938-0.17969-0.03125-0.33984-0.046875-0.48438-0.046875-0.55469 0-0.96875 0.16406-1.25 0.48438-0.27344 0.3125-0.40625 0.75781-0.40625 1.3281 0 0.625 0.11328 1.0625 0.34375 1.3125 0.23828 0.25 0.59375 0.375 1.0625 0.375 0.20703 0 0.41016-0.03125 0.60938-0.09375 0.20703-0.0625 0.39453-0.14844 0.5625-0.26562z" />
  </symbol>
  <symbol id="glyph4-11" overflow="visible"></symbol>
  <symbol id="glyph4-12" overflow="visible">
   <path d="m9.3594-4.3594c0 0.8125-0.1875 1.543-0.5625 2.1875-0.36719 0.64844-0.83594 1.1406-1.4062 1.4844-0.42969 0.25-0.89844 0.42969-1.4062 0.53125-0.5 0.10547-1.1016 0.15625-1.7969 0.15625h-3.0781v-8.7188h3.1719c0.70703 0 1.3164 0.058594 1.8281 0.17188 0.51953 0.11719 0.95703 0.28125 1.3125 0.5 0.60156 0.375 1.0781 0.875 1.4219 1.5 0.34375 0.61719 0.51562 1.3438 0.51562 2.1875zm-2.3281-0.015625c0-0.57031-0.10547-1.0625-0.3125-1.4688-0.21094-0.40625-0.54297-0.72266-1-0.95312-0.23047-0.11328-0.46484-0.19141-0.70312-0.23438-0.24219-0.039062-0.60156-0.0625-1.0781-0.0625h-0.57812v5.4531h0.57812c0.53125 0 0.92188-0.019531 1.1719-0.0625 0.25-0.050781 0.49219-0.14062 0.73438-0.26562 0.40625-0.23828 0.70312-0.55078 0.89062-0.9375 0.19531-0.39453 0.29688-0.88281 0.29688-1.4688z" />
  </symbol>
  <symbol id="glyph4-13" overflow="visible">
   <path d="m7.625-6.5781-2.5312 6.5781h-2.3906l-2.5312-6.5781h2.2344l1.5312 4.5156 1.5-4.5156z" />
  </symbol>
  <symbol id="glyph4-14" overflow="visible">
   <path d="m6.7188-2.0938c0 0.6875-0.30859 1.2422-0.92188 1.6562-0.60547 0.41797-1.4375 0.625-2.5 0.625-0.58594 0-1.1172-0.058594-1.5938-0.17188-0.48047-0.10156-0.85938-0.22266-1.1406-0.35938v-1.7344h0.1875c0.10156 0.074219 0.22266 0.15625 0.35938 0.25 0.14453 0.085937 0.34375 0.17969 0.59375 0.28125 0.21875 0.085937 0.46094 0.16406 0.73438 0.23438 0.28125 0.0625 0.58203 0.09375 0.90625 0.09375 0.41406 0 0.72266-0.046875 0.92188-0.14062 0.19531-0.09375 0.29688-0.22656 0.29688-0.40625 0-0.16406-0.0625-0.28516-0.1875-0.35938-0.11719-0.070312-0.33594-0.14062-0.65625-0.20312-0.15625-0.03125-0.37109-0.066406-0.64062-0.10938-0.27344-0.039062-0.51562-0.09375-0.73438-0.15625-0.59375-0.15625-1.0391-0.39453-1.3281-0.71875-0.28125-0.33203-0.42188-0.74219-0.42188-1.2344 0-0.63281 0.29688-1.1602 0.89062-1.5781 0.60156-0.42578 1.4219-0.64062 2.4531-0.64062 0.5 0 0.97266 0.054687 1.4219 0.15625 0.44531 0.09375 0.80078 0.19922 1.0625 0.3125v1.6719h-0.1875c-0.3125-0.21875-0.67188-0.39453-1.0781-0.53125-0.39844-0.13281-0.79688-0.20312-1.2031-0.20312-0.34375 0-0.63281 0.046875-0.85938 0.14062-0.23047 0.09375-0.34375 0.23047-0.34375 0.40625 0 0.15625 0.050781 0.27734 0.15625 0.35938 0.10156 0.074219 0.34766 0.15234 0.73438 0.23438 0.21875 0.042969 0.45312 0.085938 0.70312 0.125 0.25 0.042969 0.5 0.09375 0.75 0.15625 0.55078 0.14844 0.95703 0.375 1.2188 0.6875 0.26953 0.3125 0.40625 0.69922 0.40625 1.1562z" />
  </symbol>
  <symbol id="glyph4-15" overflow="visible">
   <path d="m5.5469 2.4219h-2.2031c-0.75-0.88672-1.3086-1.793-1.6719-2.7188-0.36719-0.92578-0.54688-1.9453-0.54688-3.0625 0-1.1016 0.17969-2.1172 0.54688-3.0469 0.36328-0.92578 0.92188-1.832 1.6719-2.7188h2.2031v0.17188c-0.3125 0.29297-0.61719 0.62109-0.90625 0.98438-0.28125 0.35547-0.54688 0.77734-0.79688 1.2656-0.23047 0.46094-0.42188 0.97656-0.57812 1.5469-0.14844 0.5625-0.21875 1.1641-0.21875 1.7969 0 0.67969 0.070313 1.2891 0.21875 1.8281 0.14453 0.54297 0.33594 1.0547 0.57812 1.5312 0.23828 0.46875 0.50391 0.89062 0.79688 1.2656 0.28906 0.375 0.59375 0.70312 0.90625 0.98438z" />
  </symbol>
  <symbol id="glyph4-16" overflow="visible">
   <path d="m5.3906-3.3594c0 1.1172-0.18359 2.1367-0.54688 3.0625-0.35547 0.92578-0.90625 1.832-1.6562 2.7188h-2.2188v-0.17188c0.3125-0.28125 0.61328-0.60938 0.90625-0.98438 0.30078-0.375 0.56641-0.79688 0.79688-1.2656 0.25-0.47656 0.44141-0.98828 0.57812-1.5312 0.14453-0.53906 0.21875-1.1484 0.21875-1.8281 0-0.63281-0.074219-1.2344-0.21875-1.7969-0.14844-0.57031-0.33984-1.0859-0.57812-1.5469-0.24219-0.48828-0.50781-0.91016-0.79688-1.2656-0.28125-0.36328-0.58594-0.69141-0.90625-0.98438v-0.17188h2.2188c0.75 0.88672 1.3008 1.793 1.6562 2.7188 0.36328 0.92969 0.54688 1.9453 0.54688 3.0469z" />
  </symbol>
  <symbol id="glyph5-1" overflow="visible">
   <path d="m6.8906-4.9531c0 0.32422-0.058594 0.64062-0.17188 0.95312-0.10547 0.3125-0.26562 0.57422-0.48438 0.78125-0.28125 0.28125-0.60156 0.49609-0.95312 0.64062-0.35547 0.14844-0.79688 0.21875-1.3281 0.21875h-1.1562v2.3594h-1.875v-7.2344h3.0781c0.45703 0 0.84375 0.042969 1.1562 0.125 0.3125 0.074219 0.59375 0.1875 0.84375 0.34375 0.28906 0.19922 0.50781 0.44922 0.65625 0.75 0.15625 0.29297 0.23438 0.64844 0.23438 1.0625zm-1.9219 0.046875c0-0.20703-0.058594-0.38281-0.17188-0.53125-0.10547-0.14453-0.23047-0.25-0.375-0.3125-0.19922-0.070312-0.39062-0.11328-0.57812-0.125-0.17969-0.007812-0.42188-0.015625-0.73438-0.015625h-0.3125v2.1719h0.53125c0.3125 0 0.57031-0.015625 0.78125-0.046875 0.20703-0.039063 0.37891-0.125 0.51562-0.25 0.125-0.10156 0.21094-0.22266 0.26562-0.35938 0.050781-0.14453 0.078125-0.32031 0.078125-0.53125z" />
  </symbol>
  <symbol id="glyph5-2" overflow="visible">
   <path d="m4.9844-5.0156c0-0.1875-0.039063-0.34375-0.10938-0.46875-0.074219-0.13281-0.20312-0.23828-0.39062-0.3125-0.125-0.050781-0.27344-0.082031-0.4375-0.09375-0.16797-0.007813-0.36719-0.015625-0.59375-0.015625h-0.67188v1.9531h0.57812c0.28906 0 0.53516-0.015625 0.73438-0.046875 0.20703-0.03125 0.37891-0.097656 0.51562-0.20312 0.125-0.09375 0.21875-0.20312 0.28125-0.32812s0.09375-0.28516 0.09375-0.48438zm2.9062 5.0156h-2.2812l-1.9688-2.6562h-0.85938v2.6562h-1.8594v-7.2344h3.125c0.42578 0 0.79688 0.027344 1.1094 0.078125 0.3125 0.042969 0.59766 0.14844 0.85938 0.3125 0.26953 0.15625 0.48438 0.36719 0.64062 0.625 0.16406 0.26172 0.25 0.58594 0.25 0.96875 0 0.53125-0.125 0.96875-0.375 1.3125-0.24219 0.33594-0.58984 0.61719-1.0469 0.84375z" />
  </symbol>
  <symbol id="glyph5-3" overflow="visible">
   <path d="m7.9531-3.6094c0 1.1484-0.32812 2.0625-0.98438 2.75-0.65625 0.67969-1.5703 1.0156-2.7344 1.0156-1.168 0-2.0859-0.33594-2.75-1.0156-0.65625-0.6875-0.98438-1.6016-0.98438-2.75 0-1.1641 0.32812-2.0859 0.98438-2.7656 0.66406-0.67578 1.582-1.0156 2.75-1.0156 1.1562 0 2.0625 0.33984 2.7188 1.0156 0.66406 0.67969 1 1.6016 1 2.7656zm-2.4688 1.8281c0.1875-0.21875 0.32031-0.47656 0.40625-0.78125 0.082031-0.30078 0.125-0.65625 0.125-1.0625 0-0.42578-0.054687-0.78906-0.15625-1.0938-0.09375-0.3125-0.21875-0.5625-0.375-0.75-0.16797-0.19531-0.35938-0.33594-0.57812-0.42188-0.21875-0.082031-0.44531-0.125-0.67188-0.125-0.24219 0-0.46484 0.042969-0.67188 0.125-0.21094 0.085937-0.40234 0.21875-0.57812 0.40625-0.15625 0.1875-0.28906 0.44531-0.39062 0.76562-0.10547 0.3125-0.15625 0.68359-0.15625 1.1094 0 0.42969 0.046875 0.79297 0.14062 1.0938 0.10156 0.30469 0.23828 0.54688 0.40625 0.73438 0.15625 0.19922 0.34375 0.34375 0.5625 0.4375 0.21875 0.085938 0.44531 0.125 0.6875 0.125 0.23828 0 0.46875-0.039062 0.6875-0.125 0.21875-0.09375 0.40625-0.23828 0.5625-0.4375z" />
  </symbol>
  <symbol id="glyph5-4" overflow="visible">
   <path d="m7.7656-3.6094c0 0.67969-0.15625 1.2812-0.46875 1.8125-0.30469 0.53125-0.6875 0.9375-1.1562 1.2188-0.35547 0.21875-0.74609 0.37109-1.1719 0.45312-0.41797 0.085938-0.91797 0.125-1.5 0.125h-2.5469v-7.2344h2.625c0.59375 0 1.1016 0.054687 1.5312 0.15625 0.42578 0.09375 0.78516 0.23047 1.0781 0.40625 0.5 0.30469 0.89062 0.71484 1.1719 1.2344 0.28906 0.52344 0.4375 1.1328 0.4375 1.8281zm-1.9375-0.015625c0-0.47656-0.089844-0.88281-0.26562-1.2188-0.16797-0.34375-0.4375-0.60938-0.8125-0.79688-0.1875-0.09375-0.38672-0.15625-0.59375-0.1875-0.19922-0.039063-0.49609-0.0625-0.89062-0.0625h-0.46875v4.5312h0.46875c0.4375 0 0.75781-0.019531 0.96875-0.0625 0.20703-0.039063 0.41016-0.11328 0.60938-0.21875 0.34375-0.1875 0.59375-0.44141 0.75-0.76562 0.15625-0.33203 0.23438-0.73828 0.23438-1.2188z" />
  </symbol>
  <symbol id="glyph5-5" overflow="visible">
   <path d="m7.2656-2.625c0 0.89844-0.27734 1.5859-0.82812 2.0625-0.54297 0.48047-1.3438 0.71875-2.4062 0.71875-1.0547 0-1.8516-0.23828-2.3906-0.71875-0.54297-0.47656-0.8125-1.1602-0.8125-2.0469v-4.625h1.875v4.5156c0 0.5 0.10156 0.875 0.3125 1.125 0.20703 0.24219 0.54688 0.35938 1.0156 0.35938s0.8125-0.11328 1.0312-0.34375c0.21875-0.23828 0.32812-0.61719 0.32812-1.1406v-4.5156h1.875z" />
  </symbol>
  <symbol id="glyph5-6" overflow="visible">
   <path d="m4.1875 0.14062c-0.53125 0-1.0273-0.082031-1.4844-0.23438-0.46094-0.15625-0.85156-0.39453-1.1719-0.71875-0.32422-0.3125-0.57812-0.70312-0.76562-1.1719-0.17969-0.46875-0.26562-1.0078-0.26562-1.625 0-0.57031 0.082031-1.0938 0.25-1.5625 0.17578-0.46875 0.42578-0.86719 0.75-1.2031 0.32031-0.32031 0.71094-0.56641 1.1719-0.73438 0.46875-0.17578 0.97656-0.26562 1.5312-0.26562 0.30078 0 0.57031 0.015625 0.8125 0.046875 0.25 0.03125 0.47656 0.078125 0.6875 0.14062 0.21875 0.0625 0.41406 0.13281 0.59375 0.20312 0.17578 0.074219 0.32812 0.14062 0.45312 0.20312v1.7656h-0.20312c-0.09375-0.082031-0.21094-0.17578-0.34375-0.28125-0.13672-0.10156-0.29297-0.20703-0.46875-0.3125-0.17969-0.10156-0.37109-0.19141-0.57812-0.26562-0.21094-0.070312-0.43359-0.10938-0.67188-0.10938-0.26172 0-0.51172 0.042969-0.75 0.125-0.24219 0.085937-0.46094 0.21875-0.65625 0.40625-0.1875 0.1875-0.34375 0.4375-0.46875 0.75-0.11719 0.30469-0.17188 0.66797-0.17188 1.0938 0 0.46094 0.0625 0.83984 0.1875 1.1406 0.13281 0.30469 0.29688 0.54297 0.48438 0.71875 0.19531 0.17969 0.41406 0.30859 0.65625 0.39062 0.25 0.074219 0.49219 0.10938 0.73438 0.10938 0.21875 0 0.4375-0.03125 0.65625-0.09375 0.22656-0.070312 0.4375-0.17188 0.625-0.29688 0.15625-0.09375 0.30078-0.19141 0.4375-0.29688 0.13281-0.10156 0.25-0.19531 0.34375-0.28125h0.1875v1.7344c-0.17969 0.085937-0.35156 0.16406-0.51562 0.23438-0.16797 0.074219-0.33984 0.13672-0.51562 0.1875-0.24219 0.0625-0.46484 0.10938-0.67188 0.14062-0.21094 0.039063-0.49609 0.0625-0.85938 0.0625z" />
  </symbol>
  <symbol id="glyph5-7" overflow="visible">
   <path d="m6.5781-5.8438h-2.25v5.8438h-1.875v-5.8438h-2.25v-1.3906h6.375z" />
  </symbol>
  <symbol id="glyph5-8" overflow="visible"></symbol>
  <symbol id="glyph5-9" overflow="visible">
   <path d="m6.1094-5.8438h-3.3281v1.3594h3.0781v1.3906h-3.0781v3.0938h-1.8594v-7.2344h5.1875z" />
  </symbol>
  <symbol id="glyph5-10" overflow="visible">
   <path d="m6.1562 0h-5.2344v-7.2344h5.2344v1.3906h-3.375v1.25h3.1406v1.4062h-3.1406v1.7812h3.375z" />
  </symbol>
  <symbol id="glyph5-11" overflow="visible">
   <path d="m7.6094 0h-1.9219l-0.5-1.4688h-2.6875l-0.5 1.4688h-1.8906l2.6875-7.2344h2.1406zm-2.875-2.7969-0.89062-2.5938-0.89062 2.5938z" />
  </symbol>
  <symbol id="glyph5-12" overflow="visible">
   <path d="m6.7188-2.2812c0 0.71875-0.30469 1.3047-0.90625 1.75-0.60547 0.4375-1.4297 0.65625-2.4688 0.65625-0.59375 0-1.1172-0.054688-1.5625-0.15625-0.44922-0.10156-0.86719-0.23438-1.25-0.39062v-1.7344h0.20312c0.38281 0.30469 0.81641 0.53906 1.2969 0.70312 0.47656 0.16797 0.9375 0.25 1.375 0.25 0.11328 0 0.25781-0.007813 0.4375-0.03125 0.1875-0.019531 0.34375-0.050781 0.46875-0.09375 0.13281-0.0625 0.25-0.13281 0.34375-0.21875 0.09375-0.09375 0.14062-0.22266 0.14062-0.39062 0-0.15625-0.070313-0.28906-0.20312-0.40625-0.13672-0.11328-0.33594-0.20312-0.59375-0.26562-0.27344-0.070313-0.55859-0.13281-0.85938-0.1875-0.30469-0.050781-0.58984-0.125-0.85938-0.21875-0.60547-0.19531-1.043-0.46094-1.3125-0.79688-0.26172-0.34375-0.39062-0.76562-0.39062-1.2656 0-0.67578 0.30078-1.2266 0.90625-1.6562 0.60156-0.42578 1.3789-0.64062 2.3281-0.64062 0.47656 0 0.94531 0.046875 1.4062 0.14062 0.46875 0.09375 0.86719 0.21484 1.2031 0.35938v1.6562h-0.1875c-0.29297-0.22656-0.65234-0.42188-1.0781-0.57812-0.41797-0.15625-0.85156-0.23438-1.2969-0.23438-0.15625 0-0.3125 0.011719-0.46875 0.03125-0.14844 0.023438-0.29297 0.058594-0.4375 0.10938-0.125 0.054687-0.23438 0.13281-0.32812 0.23438-0.085938 0.09375-0.125 0.20312-0.125 0.32812 0 0.1875 0.070312 0.33594 0.21875 0.4375 0.14453 0.10547 0.41406 0.19922 0.8125 0.28125 0.26953 0.054687 0.52344 0.10547 0.76562 0.15625 0.25 0.054687 0.51562 0.125 0.79688 0.21875 0.55078 0.1875 0.95703 0.4375 1.2188 0.75 0.26953 0.3125 0.40625 0.71484 0.40625 1.2031z" />
  </symbol>
  <symbol id="glyph6-1" overflow="visible">
   <path d="m4.9375 0h-4.2031v-5.8125h4.2031v1.125h-2.7031v1h2.5156v1.125h-2.5156v1.4375h2.7031z" />
  </symbol>
  <symbol id="glyph6-2" overflow="visible">
   <path d="m5.2344 0h-1.625l-0.9375-1.3125-0.96875 1.3125h-1.6094l1.7344-2.1875-1.7031-2.1875h1.6406l0.92188 1.2812 0.92188-1.2812h1.6094l-1.7031 2.1562z" />
  </symbol>
  <symbol id="glyph6-3" overflow="visible">
   <path d="m3.4688-0.03125c-0.15625 0.03125-0.32031 0.054688-0.48438 0.078125-0.16797 0.019531-0.375 0.03125-0.625 0.03125-0.54297 0-0.94922-0.10938-1.2188-0.32812-0.26172-0.21875-0.39062-0.59375-0.39062-1.125v-2.0469h-0.57812v-0.95312h0.57812v-1.25h1.3906v1.25h1.3281v0.95312h-1.3281v1.5469 0.40625c0.007813 0.11719 0.035156 0.21484 0.078125 0.29688 0.03125 0.09375 0.09375 0.16797 0.1875 0.21875 0.09375 0.054687 0.22656 0.078125 0.40625 0.078125 0.070312 0 0.16406-0.015625 0.28125-0.046875 0.125-0.03125 0.20703-0.054687 0.25-0.078125h0.125z" />
  </symbol>
  <symbol id="glyph6-4" overflow="visible">
   <path d="m4.9688-1.9375h-3.2031c0.019531 0.34375 0.14844 0.60938 0.39062 0.79688 0.23828 0.17969 0.59375 0.26562 1.0625 0.26562 0.28906 0 0.57812-0.050781 0.85938-0.15625 0.28125-0.10156 0.5-0.21875 0.65625-0.34375h0.15625v1.125c-0.3125 0.13672-0.60938 0.23047-0.89062 0.28125s-0.59375 0.078125-0.9375 0.078125c-0.875 0-1.5469-0.19141-2.0156-0.57812-0.46875-0.39453-0.70312-0.95703-0.70312-1.6875 0-0.72656 0.21875-1.3008 0.65625-1.7188 0.44531-0.42578 1.0547-0.64062 1.8281-0.64062 0.71875 0 1.2539 0.18359 1.6094 0.54688 0.35156 0.35547 0.53125 0.87109 0.53125 1.5469zm-1.3906-0.8125c-0.011719-0.28906-0.085937-0.50781-0.21875-0.65625-0.13672-0.15625-0.35156-0.23438-0.64062-0.23438-0.27344 0-0.49609 0.074219-0.67188 0.21875-0.16797 0.13672-0.26172 0.35938-0.28125 0.67188z" />
  </symbol>
  <symbol id="glyph6-5" overflow="visible">
   <path d="m3.8438-3.0469h-0.125c-0.0625-0.019531-0.16406-0.035156-0.29688-0.046875-0.13672-0.007812-0.24609-0.015625-0.32812-0.015625-0.19922 0-0.375 0.015625-0.53125 0.046875-0.15625 0.023438-0.32422 0.0625-0.5 0.125v2.9375h-1.4062v-4.375h1.4062v0.64062c0.3125-0.25781 0.58203-0.42969 0.8125-0.51562 0.22656-0.09375 0.4375-0.14062 0.625-0.14062h0.17188c0.0625 0 0.11719 0.007813 0.17188 0.015625z" />
  </symbol>
  <symbol id="glyph6-6" overflow="visible">
   <path d="m5.0625 0h-1.4062v-2.1719c0-0.17578-0.011719-0.35156-0.03125-0.53125-0.023438-0.17578-0.054688-0.30469-0.09375-0.39062-0.054688-0.09375-0.13281-0.16016-0.23438-0.20312-0.09375-0.039063-0.23438-0.0625-0.42188-0.0625-0.125 0-0.25781 0.023437-0.39062 0.0625-0.125 0.042969-0.26562 0.10547-0.42188 0.1875v3.1094h-1.4062v-4.375h1.4062v0.48438c0.25-0.19531 0.48828-0.34766 0.71875-0.45312 0.22656-0.10156 0.48438-0.15625 0.76562-0.15625 0.47656 0 0.84766 0.14062 1.1094 0.42188 0.26953 0.27344 0.40625 0.68359 0.40625 1.2344z" />
  </symbol>
  <symbol id="glyph6-7" overflow="visible">
   <path d="m3.3125-1.1406v-0.90625c-0.1875 0.011719-0.39844 0.03125-0.625 0.0625-0.21875 0.023437-0.38672 0.054687-0.5 0.09375-0.13672 0.042969-0.24219 0.10547-0.3125 0.1875-0.074219 0.085937-0.10938 0.19531-0.10938 0.32812 0 0.09375 0.003906 0.17188 0.015625 0.23438 0.019531 0.054687 0.0625 0.10547 0.125 0.15625 0.0625 0.054687 0.12891 0.09375 0.20312 0.125 0.082031 0.023437 0.21094 0.03125 0.39062 0.03125 0.14453 0 0.28906-0.023437 0.4375-0.078125 0.14453-0.0625 0.26953-0.14062 0.375-0.23438zm0 0.67188c-0.074219 0.0625-0.16797 0.13672-0.28125 0.21875-0.11719 0.074219-0.21875 0.13672-0.3125 0.1875-0.13672 0.0625-0.28125 0.10156-0.4375 0.125-0.14844 0.03125-0.30859 0.046875-0.48438 0.046875-0.41797 0-0.76562-0.125-1.0469-0.375-0.28125-0.25781-0.42188-0.58594-0.42188-0.98438 0-0.32031 0.070313-0.58203 0.21875-0.78125 0.14453-0.20703 0.34766-0.36719 0.60938-0.48438 0.25781-0.11328 0.58203-0.19531 0.96875-0.25 0.38281-0.050781 0.78516-0.085937 1.2031-0.10938v-0.03125c0-0.23828-0.10156-0.40625-0.29688-0.5-0.19922-0.09375-0.49219-0.14062-0.875-0.14062-0.23047 0-0.48047 0.042969-0.75 0.125-0.26172 0.085937-0.44922 0.14844-0.5625 0.1875h-0.125v-1.0469c0.14453-0.039062 0.38281-0.085938 0.71875-0.14062 0.33203-0.050781 0.66406-0.078125 1-0.078125 0.80078 0 1.3789 0.125 1.7344 0.375 0.35156 0.24219 0.53125 0.62109 0.53125 1.1406v2.9844h-1.3906z" />
  </symbol>
  <symbol id="glyph6-8" overflow="visible">
   <path d="m2.0625 0h-1.4062v-6.0625h1.4062z" />
  </symbol>
  <symbol id="glyph6-9" overflow="visible"></symbol>
  <symbol id="glyph6-10" overflow="visible">
   <path d="m3.875 0h-3.3906v-1.0312h0.95312v-3.75h-0.95312v-1.0312h3.3906v1.0312h-0.95312v3.75h0.95312z" />
  </symbol>
  <symbol id="glyph6-11" overflow="visible">
   <path d="m3.5-5.0312h-0.10938c-0.0625-0.019531-0.14844-0.039062-0.25-0.0625-0.09375-0.03125-0.19922-0.046875-0.3125-0.046875-0.27344 0-0.46094 0.054687-0.5625 0.15625-0.09375 0.09375-0.14062 0.28906-0.14062 0.57812v0.03125h1.0781v0.95312h-1.0312v3.4219h-1.4062v-3.4219h-0.59375v-0.95312h0.59375v-0.125c0-0.53125 0.14062-0.92969 0.42188-1.2031 0.28906-0.26953 0.72266-0.40625 1.2969-0.40625 0.20703 0 0.39453 0.011719 0.5625 0.03125 0.17578 0.011719 0.32812 0.027344 0.45312 0.046875z" />
  </symbol>
  <symbol id="glyph6-12" overflow="visible">
   <path d="m2.9375 0.10938c-0.375 0-0.72656-0.042969-1.0469-0.125-0.3125-0.09375-0.58594-0.23438-0.8125-0.42188-0.24219-0.1875-0.42188-0.42578-0.54688-0.71875-0.125-0.28906-0.1875-0.62891-0.1875-1.0156 0-0.40625 0.066406-0.75391 0.20312-1.0469 0.13281-0.30078 0.32812-0.55078 0.57812-0.75 0.22656-0.17578 0.5-0.30469 0.8125-0.39062 0.3125-0.09375 0.63281-0.14062 0.96875-0.14062 0.28906 0 0.5625 0.039062 0.8125 0.10938 0.25781 0.0625 0.5 0.14844 0.71875 0.25v1.1875h-0.20312c-0.054687-0.039063-0.12109-0.09375-0.20312-0.15625-0.074219-0.0625-0.16797-0.125-0.28125-0.1875-0.10547-0.0625-0.21875-0.10938-0.34375-0.14062-0.125-0.039062-0.27734-0.0625-0.45312-0.0625-0.375 0-0.66406 0.12109-0.85938 0.35938-0.19922 0.24219-0.29688 0.5625-0.29688 0.96875 0 0.41797 0.097656 0.73438 0.29688 0.95312 0.20703 0.21875 0.50391 0.32812 0.89062 0.32812 0.17578 0 0.33203-0.015625 0.46875-0.046875 0.14453-0.039062 0.26562-0.09375 0.35938-0.15625 0.09375-0.050781 0.17188-0.10156 0.23438-0.15625 0.0625-0.0625 0.125-0.11719 0.1875-0.17188h0.20312v1.2031c-0.23047 0.10547-0.46484 0.18359-0.70312 0.23438-0.24219 0.0625-0.50781 0.09375-0.79688 0.09375z" />
  </symbol>
  <symbol id="glyph6-13" overflow="visible">
   <path d="m4.4688-1.3906c0 0.46094-0.20312 0.82812-0.60938 1.1094-0.40625 0.27344-0.96484 0.40625-1.6719 0.40625-0.38672 0-0.74219-0.039062-1.0625-0.10938-0.3125-0.070312-0.5625-0.15625-0.75-0.25v-1.1562h0.125c0.070312 0.054687 0.14844 0.10938 0.23438 0.17188 0.09375 0.054688 0.22656 0.11719 0.40625 0.1875 0.14453 0.0625 0.30469 0.11719 0.48438 0.15625 0.1875 0.042969 0.38281 0.0625 0.59375 0.0625 0.28125 0 0.48438-0.03125 0.60938-0.09375 0.13281-0.0625 0.20312-0.14844 0.20312-0.26562 0-0.11328-0.042969-0.19141-0.125-0.23438-0.074219-0.050781-0.21875-0.097656-0.4375-0.14062-0.10547-0.019531-0.24609-0.046875-0.42188-0.078125-0.17969-0.03125-0.33984-0.0625-0.48438-0.09375-0.39844-0.10156-0.69531-0.26562-0.89062-0.48438-0.1875-0.21875-0.28125-0.49219-0.28125-0.82812 0-0.41406 0.19531-0.76562 0.59375-1.0469 0.40625-0.28125 0.95312-0.42188 1.6406-0.42188 0.32031 0 0.63281 0.039062 0.9375 0.10938 0.30078 0.0625 0.53516 0.13281 0.70312 0.20312v1.1094h-0.125c-0.19922-0.14453-0.43359-0.25781-0.70312-0.34375-0.27344-0.09375-0.54297-0.14062-0.8125-0.14062-0.23047 0-0.42188 0.03125-0.57812 0.09375-0.14844 0.0625-0.21875 0.15234-0.21875 0.26562 0 0.10547 0.03125 0.18359 0.09375 0.23438 0.070313 0.054688 0.23828 0.10938 0.5 0.17188 0.14453 0.023437 0.30078 0.046875 0.46875 0.078125 0.16406 0.03125 0.33203 0.070312 0.5 0.10938 0.36328 0.09375 0.63281 0.24609 0.8125 0.45312 0.17578 0.19922 0.26562 0.45312 0.26562 0.76562z" />
  </symbol>
  <symbol id="glyph6-14" overflow="visible">
   <path d="m7.2188-2.5469c0 0.92969-0.32812 1.7188-0.98438 2.375-0.65625 0.65234-1.4531 0.98438-2.3906 0.98438-0.92969 0-1.7266-0.33203-2.3906-0.98438-0.65625-0.65625-0.98438-1.4453-0.98438-2.375 0-0.9375 0.32812-1.7344 0.98438-2.3906 0.66406-0.65625 1.4609-0.98438 2.3906-0.98438 0.9375 0 1.7344 0.32812 2.3906 0.98438s0.98438 1.4531 0.98438 2.3906zm-0.73438 0c0-0.72656-0.26172-1.3516-0.78125-1.875-0.51172-0.51953-1.125-0.78125-1.8438-0.78125-0.73047 0-1.3555 0.26172-1.875 0.78125-0.51172 0.52344-0.76562 1.1484-0.76562 1.875 0 0.71875 0.25391 1.3398 0.76562 1.8594 0.51953 0.52344 1.1445 0.78125 1.875 0.78125 0.71875 0 1.332-0.25781 1.8438-0.78125 0.51953-0.51953 0.78125-1.1406 0.78125-1.8594zm-0.73438 1.5938h-1.0625l-1.0156-1.2344h-0.34375v1.2344h-0.82812v-3.3594h1.2812c0.23828 0 0.42578 0.011719 0.5625 0.03125 0.14453 0.023438 0.28906 0.070312 0.4375 0.14062 0.14453 0.085937 0.25391 0.1875 0.32812 0.3125 0.070313 0.11719 0.10938 0.26562 0.10938 0.45312 0 0.24219-0.070312 0.44531-0.20312 0.60938-0.13672 0.15625-0.32031 0.27734-0.54688 0.35938zm-1.4531-2.3594c0-0.070312-0.015625-0.13281-0.046875-0.1875-0.03125-0.0625-0.078125-0.11328-0.14062-0.15625-0.074219-0.03125-0.15234-0.050781-0.23438-0.0625-0.085938-0.007812-0.17969-0.015625-0.28125-0.015625h-0.26562v0.95312h0.20312c0.13281 0 0.25-0.007812 0.34375-0.03125 0.10156-0.019531 0.1875-0.050781 0.25-0.09375 0.0625-0.050781 0.10156-0.10938 0.125-0.17188 0.03125-0.0625 0.046875-0.14062 0.046875-0.23438z" />
  </symbol>
  <symbol id="glyph6-15" overflow="visible">
   <path d="m4.7656-6.0625-3.0938 7.3281h-1.1875l3.0781-7.3281z" />
  </symbol>
  <symbol id="glyph6-16" overflow="visible">
   <path d="m6.3906-2.9062c0 0.92969-0.26562 1.668-0.79688 2.2188-0.53125 0.54297-1.2656 0.8125-2.2031 0.8125-0.92969 0-1.6562-0.26953-2.1875-0.8125-0.53125-0.55078-0.79688-1.2891-0.79688-2.2188 0-0.92578 0.26562-1.6602 0.79688-2.2031 0.53125-0.53906 1.2578-0.8125 2.1875-0.8125 0.92578 0 1.6562 0.27344 2.1875 0.8125 0.53906 0.54297 0.8125 1.2773 0.8125 2.2031zm-1.9844 1.4688c0.14453-0.17578 0.25-0.38281 0.3125-0.625 0.070312-0.23828 0.10938-0.51953 0.10938-0.84375 0-0.34375-0.042969-0.63281-0.125-0.875-0.074219-0.25-0.17969-0.45312-0.3125-0.60938-0.13672-0.15625-0.29297-0.26562-0.46875-0.32812-0.16797-0.070312-0.34375-0.10938-0.53125-0.10938s-0.36719 0.039063-0.53125 0.10938c-0.16797 0.0625-0.32422 0.17188-0.46875 0.32812-0.125 0.14844-0.23047 0.35156-0.3125 0.60938-0.085937 0.25-0.125 0.54297-0.125 0.875 0 0.35547 0.035156 0.65234 0.10938 0.89062 0.082031 0.24219 0.19141 0.4375 0.32812 0.59375 0.125 0.15625 0.27344 0.27344 0.45312 0.34375 0.17578 0.074219 0.35938 0.10938 0.54688 0.10938 0.19531 0 0.37891-0.035156 0.54688-0.10938 0.17578-0.082031 0.33203-0.20312 0.46875-0.35938z" />
  </symbol>
  <symbol id="glyph6-17" overflow="visible">
   <path d="m6.1094 0h-1.5469l-0.40625-1.1719h-2.1562l-0.39062 1.1719h-1.5156l2.1406-5.8125h1.7344zm-2.3125-2.2344-0.71875-2.0781-0.71875 2.0781z" />
  </symbol>
  <symbol id="glyph6-18" overflow="visible">
   <path d="m2.0625 0h-1.4062v-4.375h1.4062zm0.046875-5h-1.4844v-1.0625h1.4844z" />
  </symbol>
  <symbol id="glyph6-19" overflow="visible">
   <path d="m5.1406-2.1875c0 0.71875-0.21484 1.2891-0.64062 1.7031-0.41797 0.41797-1.0078 0.625-1.7656 0.625-0.75 0-1.3398-0.20703-1.7656-0.625-0.41797-0.41406-0.625-0.98438-0.625-1.7031 0-0.72656 0.20703-1.2969 0.625-1.7031 0.42578-0.41406 1.0156-0.625 1.7656-0.625 0.76953 0 1.3633 0.21094 1.7812 0.625 0.41406 0.41797 0.625 0.98438 0.625 1.7031zm-1.7344 1.0625c0.09375-0.11328 0.16016-0.25 0.20312-0.40625 0.050781-0.15625 0.078125-0.36719 0.078125-0.64062 0-0.25781-0.027344-0.47656-0.078125-0.65625-0.042969-0.17578-0.10547-0.31641-0.1875-0.42188-0.085937-0.10156-0.1875-0.17578-0.3125-0.21875-0.11719-0.039062-0.24219-0.0625-0.375-0.0625-0.13672 0-0.25781 0.023438-0.35938 0.0625-0.10547 0.03125-0.20312 0.10156-0.29688 0.20312-0.085937 0.10547-0.15234 0.24609-0.20312 0.42188-0.054688 0.17969-0.078125 0.40234-0.078125 0.67188 0 0.23047 0.019531 0.43359 0.0625 0.60938 0.050781 0.17969 0.11719 0.32031 0.20312 0.42188 0.082031 0.10547 0.17969 0.18359 0.29688 0.23438 0.11328 0.042969 0.24219 0.0625 0.39062 0.0625 0.125 0 0.24219-0.019531 0.35938-0.0625 0.125-0.039062 0.22266-0.11328 0.29688-0.21875z" />
  </symbol>
  <symbol id="glyph6-20" overflow="visible">
   <path d="m5.2812-4.6875h-1.8125v4.6875h-1.5v-4.6875h-1.8125v-1.125h5.125z" />
  </symbol>
  <symbol id="glyph6-21" overflow="visible">
   <path d="m5.0625 0h-1.4062v-2.1719c0-0.17578-0.011719-0.35156-0.03125-0.53125-0.023438-0.17578-0.054688-0.30469-0.09375-0.39062-0.054688-0.09375-0.13281-0.16016-0.23438-0.20312-0.09375-0.039063-0.23438-0.0625-0.42188-0.0625-0.125 0-0.25781 0.023437-0.39062 0.0625-0.125 0.042969-0.26562 0.10547-0.42188 0.1875v3.1094h-1.4062v-6.0625h1.4062v2.1719c0.25-0.19531 0.48828-0.34766 0.71875-0.45312 0.22656-0.10156 0.48438-0.15625 0.76562-0.15625 0.47656 0 0.84766 0.14062 1.1094 0.42188 0.26953 0.27344 0.40625 0.68359 0.40625 1.2344z" />
  </symbol>
  <symbol id="glyph6-22" overflow="visible">
   <path d="m4.9219-0.5c0 0.40625-0.0625 0.75-0.1875 1.0312-0.11719 0.28125-0.27734 0.5-0.48438 0.65625-0.21094 0.16406-0.46484 0.28516-0.76562 0.35938-0.29297 0.070313-0.625 0.10938-1 0.10938-0.30469 0-0.60547-0.023438-0.90625-0.0625-0.29297-0.03125-0.54688-0.074219-0.76562-0.125v-1.1094h0.17188c0.17578 0.070313 0.38281 0.13281 0.625 0.1875 0.25 0.0625 0.47266 0.09375 0.67188 0.09375 0.25781 0 0.46875-0.027344 0.625-0.078125 0.16406-0.054688 0.28906-0.12109 0.375-0.20312 0.082031-0.085937 0.14062-0.19531 0.17188-0.32812 0.039063-0.125 0.0625-0.27344 0.0625-0.45312v-0.09375c-0.16797 0.14844-0.35547 0.26172-0.5625 0.34375-0.21094 0.074219-0.4375 0.10938-0.6875 0.10938-0.61719 0-1.0898-0.17969-1.4219-0.54688-0.33594-0.375-0.5-0.9375-0.5-1.6875 0-0.36328 0.050781-0.67578 0.15625-0.9375 0.10156-0.25781 0.25-0.48828 0.4375-0.6875 0.16406-0.17578 0.375-0.31641 0.625-0.42188 0.25-0.10156 0.50391-0.15625 0.76562-0.15625 0.23828 0 0.45312 0.03125 0.64062 0.09375 0.19531 0.054688 0.37891 0.125 0.54688 0.21875l0.046875-0.1875h1.3594zm-1.4062-0.875v-1.9844c-0.085937-0.039063-0.18359-0.066406-0.29688-0.078125-0.11719-0.019531-0.21875-0.03125-0.3125-0.03125-0.375 0-0.65625 0.10547-0.84375 0.3125-0.17969 0.21094-0.26562 0.50781-0.26562 0.89062 0 0.41797 0.078125 0.71094 0.23438 0.875 0.15625 0.16797 0.39062 0.25 0.70312 0.25 0.13281 0 0.26953-0.019531 0.40625-0.0625 0.13281-0.039063 0.25781-0.097656 0.375-0.17188z" />
  </symbol>
  <symbol id="glyph6-23" overflow="visible">
   <path d="m2.6406-1.5469 1-2.8281h1.4375l-2.4375 5.9844h-1.5156l0.70312-1.6406-1.7188-4.3438h1.4844z" />
  </symbol>
  <symbol id="glyph6-24" overflow="visible">
   <path d="m6-5.8125-2.1094 5.8125h-1.6875l-2.1094-5.8125h1.5781l1.3906 4.0781 1.4062-4.0781z" />
  </symbol>
  <symbol id="glyph6-25" overflow="visible">
   <path d="m5.0312 0h-1.4062v-0.48438c-0.26172 0.19922-0.5 0.35156-0.71875 0.45312-0.21875 0.10156-0.47656 0.15625-0.76562 0.15625-0.49219 0-0.86719-0.14062-1.125-0.42188-0.26172-0.28125-0.39062-0.69141-0.39062-1.2344v-2.8438h1.4062v2.1719c0 0.21875 0.003906 0.40234 0.015625 0.54688 0.019531 0.14844 0.054687 0.26562 0.10938 0.35938 0.050781 0.10547 0.125 0.17969 0.21875 0.21875 0.10156 0.042969 0.24219 0.0625 0.42188 0.0625 0.125 0 0.25781-0.019531 0.40625-0.0625 0.14453-0.039063 0.28516-0.10938 0.42188-0.20312v-3.0938h1.4062z" />
  </symbol>
  <symbol id="glyph6-26" overflow="visible">
   <path d="m4.4375 0h-4.1094v-0.90625l2.3125-2.4531h-2.2188v-1.0156h3.9688v0.875l-2.2656 2.4531h2.3125z" />
  </symbol>
  <symbol id="glyph6-27" overflow="visible">
   <path d="m4-4.0312c0-0.14453-0.03125-0.26953-0.09375-0.375-0.0625-0.10156-0.16797-0.17969-0.3125-0.23438-0.09375-0.039063-0.21094-0.066406-0.34375-0.078125-0.13672-0.007812-0.29688-0.015625-0.48438-0.015625h-0.53125v1.5625h0.45312c0.23828 0 0.4375-0.007813 0.59375-0.03125 0.16406-0.03125 0.30469-0.085937 0.42188-0.17188 0.10156-0.070312 0.17578-0.15625 0.21875-0.25 0.050781-0.10156 0.078125-0.23828 0.078125-0.40625zm2.3281 4.0312h-1.8281l-1.5781-2.125h-0.6875v2.125h-1.5v-5.8125h2.5156c0.34375 0 0.63281 0.023438 0.875 0.0625 0.25 0.042969 0.48438 0.125 0.70312 0.25 0.21875 0.13672 0.39062 0.30859 0.51562 0.51562 0.13281 0.21094 0.20312 0.46875 0.20312 0.78125 0 0.42969-0.10156 0.77734-0.29688 1.0469-0.19922 0.27344-0.48438 0.49609-0.85938 0.67188z" />
  </symbol>
  <symbol id="glyph6-28" overflow="visible">
   <path d="m4.9219 0h-1.4062v-0.45312c-0.24219 0.19922-0.46875 0.34375-0.6875 0.4375-0.21094 0.09375-0.44922 0.14062-0.71875 0.14062-0.53125 0-0.96094-0.20312-1.2812-0.60938-0.32422-0.41406-0.48438-0.97266-0.48438-1.6719 0-0.375 0.050781-0.70312 0.15625-0.98438 0.11328-0.28906 0.26562-0.53906 0.45312-0.75 0.17578-0.1875 0.39062-0.33203 0.64062-0.4375 0.25781-0.11328 0.51562-0.17188 0.76562-0.17188 0.25781 0 0.47266 0.03125 0.64062 0.09375 0.16406 0.054688 0.33594 0.12109 0.51562 0.20312v-1.8594h1.4062zm-1.4062-1.2031v-2.1562c-0.09375-0.039063-0.19922-0.066406-0.3125-0.078125-0.10547-0.019531-0.20312-0.03125-0.29688-0.03125-0.375 0-0.65625 0.11719-0.84375 0.34375-0.17969 0.23047-0.26562 0.54688-0.26562 0.95312 0 0.42969 0.070313 0.74219 0.21875 0.9375 0.14453 0.1875 0.38281 0.28125 0.71875 0.28125 0.125 0 0.25781-0.019531 0.40625-0.0625 0.14453-0.050781 0.26953-0.11328 0.375-0.1875z" />
  </symbol>
  <symbol id="glyph6-29" overflow="visible">
   <path d="m4.9062-4.6875h-2.6719v1.0781h2.4688v1.125h-2.4688v2.4844h-1.5v-5.8125h4.1719z" />
  </symbol>
  <symbol id="glyph6-30" overflow="visible">
   <path d="m3.4062-2.0156h-2.9844v-1.125h2.9844z" />
  </symbol>
  <symbol id="glyph6-31" overflow="visible">
   <path d="m5.3906-1.8281c0 0.57422-0.24609 1.043-0.73438 1.4062-0.48047 0.35547-1.1367 0.53125-1.9688 0.53125-0.48047 0-0.90234-0.042969-1.2656-0.125-0.35547-0.082031-0.6875-0.19141-1-0.32812v-1.3906h0.17188c0.30078 0.25 0.64453 0.44531 1.0312 0.57812 0.38281 0.125 0.75391 0.1875 1.1094 0.1875 0.09375 0 0.21094-0.003906 0.35938-0.015625 0.14453-0.019531 0.26562-0.046875 0.35938-0.078125 0.11328-0.050781 0.20703-0.10938 0.28125-0.17188 0.070313-0.070313 0.10938-0.17969 0.10938-0.32812 0-0.125-0.054688-0.22656-0.15625-0.3125-0.10547-0.09375-0.26172-0.16406-0.46875-0.21875-0.21875-0.050781-0.45312-0.097656-0.70312-0.14062-0.24219-0.050781-0.46484-0.11328-0.67188-0.1875-0.49219-0.15625-0.84375-0.36719-1.0625-0.64062-0.21875-0.26953-0.32812-0.60938-0.32812-1.0156 0-0.53906 0.24219-0.97656 0.73438-1.3125 0.48828-0.34375 1.1133-0.51562 1.875-0.51562 0.375 0 0.75 0.039062 1.125 0.10938 0.375 0.074219 0.69531 0.16797 0.96875 0.28125v1.3281h-0.15625c-0.24219-0.1875-0.53125-0.34375-0.875-0.46875-0.33594-0.125-0.67969-0.1875-1.0312-0.1875-0.125 0-0.25 0.011719-0.375 0.03125-0.11719 0.011719-0.23047 0.042969-0.34375 0.09375-0.10547 0.042969-0.19531 0.10547-0.26562 0.1875-0.074219 0.074219-0.10938 0.16406-0.10938 0.26562 0 0.14844 0.054688 0.26172 0.17188 0.34375 0.11328 0.085937 0.33594 0.15625 0.67188 0.21875 0.20703 0.054687 0.41016 0.10156 0.60938 0.14062 0.19531 0.042969 0.40625 0.10156 0.625 0.17188 0.44531 0.14844 0.77344 0.34375 0.98438 0.59375 0.21875 0.25 0.32812 0.57422 0.32812 0.96875z" />
  </symbol>
  <symbol id="glyph6-32" overflow="visible">
   <path d="m5.2344-2.25c0 0.36719-0.058594 0.69922-0.17188 1-0.10547 0.29297-0.25 0.53125-0.4375 0.71875-0.1875 0.21094-0.40234 0.36719-0.64062 0.46875-0.23047 0.089844-0.48047 0.14062-0.75 0.14062-0.25 0-0.46484-0.027344-0.64062-0.078125-0.16797-0.050781-0.34375-0.125-0.53125-0.21875v1.8281h-1.4062v-5.9844h1.4062v0.45312c0.21875-0.16406 0.4375-0.30078 0.65625-0.40625 0.22656-0.11328 0.48828-0.17188 0.78125-0.17188 0.55078 0 0.97656 0.20312 1.2812 0.60938 0.30078 0.39844 0.45312 0.94531 0.45312 1.6406zm-1.4531 0.03125c0-0.42578-0.074219-0.73438-0.21875-0.92188-0.14844-0.19531-0.375-0.29688-0.6875-0.29688-0.13672 0-0.27734 0.023438-0.42188 0.0625-0.13672 0.042969-0.26562 0.10156-0.39062 0.17188v2.2031c0.09375 0.03125 0.19141 0.054688 0.29688 0.0625 0.11328 0.011719 0.22266 0.015625 0.32812 0.015625 0.36328 0 0.63281-0.10156 0.8125-0.3125 0.1875-0.21875 0.28125-0.54688 0.28125-0.98438z" />
  </symbol>
  <symbol id="glyph6-33" overflow="visible">
   <path d="m4.9375-3.1094v3.1094h-1.4062v-2.1875c0-0.20703-0.007812-0.38281-0.015625-0.53125-0.011719-0.15625-0.039063-0.28125-0.078125-0.375-0.054688-0.09375-0.125-0.16016-0.21875-0.20312-0.09375-0.039063-0.23047-0.0625-0.40625-0.0625-0.13672 0-0.27344 0.027344-0.40625 0.078125-0.125 0.054688-0.24219 0.10938-0.34375 0.17188v3.1094h-1.4062v-4.375h1.4062v0.48438c0.23828-0.1875 0.46875-0.33203 0.6875-0.4375 0.22656-0.11328 0.47656-0.17188 0.75-0.17188 0.28125 0 0.53125 0.070312 0.75 0.20312 0.22656 0.125 0.40625 0.3125 0.53125 0.5625 0.28125-0.23828 0.55078-0.42578 0.8125-0.5625 0.25781-0.13281 0.51953-0.20312 0.78125-0.20312 0.46875 0 0.82812 0.14062 1.0781 0.42188s0.375 0.69531 0.375 1.2344v2.8438h-1.4219v-2.1875c0-0.21875-0.007812-0.39844-0.015625-0.54688-0.011719-0.14453-0.039063-0.26562-0.078125-0.35938-0.042969-0.09375-0.11719-0.16016-0.21875-0.20312-0.09375-0.039063-0.22656-0.0625-0.39062-0.0625-0.125 0-0.24609 0.023437-0.35938 0.0625-0.10547 0.03125-0.24219 0.09375-0.40625 0.1875z" />
  </symbol>
  <symbol id="glyph6-34" overflow="visible">
   <path d="m5.5312-3.9688c0 0.26172-0.046875 0.51562-0.14062 0.76562-0.085937 0.24219-0.21484 0.44922-0.39062 0.625-0.23047 0.23047-0.48438 0.40234-0.76562 0.51562-0.28125 0.11719-0.63672 0.17188-1.0625 0.17188h-0.9375v1.8906h-1.5v-5.8125h2.4688c0.375 0 0.6875 0.039062 0.9375 0.10938 0.25 0.0625 0.47266 0.15625 0.67188 0.28125 0.22656 0.15625 0.40625 0.35547 0.53125 0.59375 0.125 0.24219 0.1875 0.52734 0.1875 0.85938zm-1.5469 0.03125c0-0.16406-0.046875-0.30469-0.14062-0.42188-0.085938-0.11328-0.18359-0.19531-0.29688-0.25-0.15625-0.0625-0.3125-0.09375-0.46875-0.09375-0.14844-0.007813-0.33984-0.015625-0.57812-0.015625h-0.26562v1.7344h0.4375c0.25 0 0.45703-0.015625 0.625-0.046875 0.16406-0.03125 0.30469-0.09375 0.42188-0.1875 0.09375-0.082031 0.16016-0.17969 0.20312-0.29688 0.039063-0.11328 0.0625-0.25391 0.0625-0.42188z" />
  </symbol>
  <symbol id="glyph6-35" overflow="visible">
   <path d="m6.2188-2.8906c0 0.54297-0.125 1.0273-0.375 1.4531-0.24219 0.42969-0.54688 0.75781-0.92188 0.98438-0.28125 0.16797-0.59375 0.28906-0.9375 0.35938-0.33594 0.0625-0.73438 0.09375-1.2031 0.09375h-2.0469v-5.8125h2.1094c0.47656 0 0.88281 0.042969 1.2188 0.125 0.34375 0.085938 0.63281 0.19922 0.875 0.34375 0.39453 0.24219 0.70703 0.57031 0.9375 0.98438 0.22656 0.41797 0.34375 0.90625 0.34375 1.4688zm-1.5469-0.015625c0-0.38281-0.070313-0.71094-0.20312-0.98438-0.13672-0.26953-0.35547-0.48438-0.65625-0.64062-0.15625-0.070312-0.32031-0.11719-0.48438-0.14062-0.15625-0.03125-0.39844-0.046875-0.71875-0.046875h-0.375v3.625h0.375c0.36328 0 0.62891-0.015625 0.79688-0.046875 0.16406-0.03125 0.32812-0.085937 0.48438-0.17188 0.26953-0.15625 0.46875-0.36328 0.59375-0.625 0.125-0.25781 0.1875-0.58203 0.1875-0.96875z" />
  </symbol>
  <symbol id="glyph7-1" overflow="visible">
   <path d="m0.59375-0.5v-4.0156h4.0156v4.0156z" />
  </symbol>
  <symbol id="glyph8-1" overflow="visible">
   <path d="m4.5781-4.0469c0 0.25-0.046875 0.49219-0.14062 0.71875-0.085938 0.21875-0.21094 0.40625-0.375 0.5625-0.19922 0.19922-0.43359 0.35156-0.70312 0.45312-0.27344 0.10547-0.61719 0.15625-1.0312 0.15625h-0.78125v2.1562h-0.76562v-5.8125h1.5781c0.34375 0 0.63281 0.03125 0.875 0.09375 0.25 0.0625 0.46875 0.15625 0.65625 0.28125 0.21875 0.14844 0.38281 0.32812 0.5 0.54688 0.125 0.21875 0.1875 0.5 0.1875 0.84375zm-0.79688 0.015625c0-0.19531-0.039062-0.36719-0.10938-0.51562-0.074219-0.15625-0.18359-0.28125-0.32812-0.375-0.125-0.070313-0.26562-0.125-0.42188-0.15625-0.15625-0.039063-0.35938-0.0625-0.60938-0.0625h-0.76562v2.3125h0.65625c0.3125 0 0.5625-0.023437 0.75-0.078125 0.19531-0.050781 0.35938-0.14062 0.48438-0.26562s0.21094-0.25391 0.26562-0.39062c0.050781-0.14453 0.078125-0.30078 0.078125-0.46875z" />
  </symbol>
  <symbol id="glyph8-2" overflow="visible">
   <path d="m5.2656-0.42188c-0.14844 0.0625-0.27734 0.125-0.39062 0.1875-0.11719 0.054687-0.26562 0.10547-0.45312 0.15625-0.15625 0.054688-0.32812 0.09375-0.51562 0.125-0.1875 0.039062-0.39062 0.0625-0.60938 0.0625-0.42969 0-0.8125-0.058594-1.1562-0.17188-0.34375-0.125-0.64062-0.3125-0.89062-0.5625s-0.44922-0.5625-0.59375-0.9375c-0.13672-0.38281-0.20312-0.82812-0.20312-1.3281 0-0.47656 0.066406-0.90625 0.20312-1.2812 0.13281-0.38281 0.32812-0.70703 0.57812-0.96875 0.25-0.25 0.54688-0.4375 0.89062-0.5625 0.35156-0.13281 0.74219-0.20312 1.1719-0.20312 0.3125 0 0.61719 0.039062 0.92188 0.10938 0.3125 0.074219 0.66016 0.20312 1.0469 0.39062v0.92188h-0.0625c-0.32422-0.26953-0.64062-0.46094-0.95312-0.57812-0.3125-0.125-0.64844-0.1875-1-0.1875-0.30469 0-0.57422 0.046875-0.8125 0.14062-0.23047 0.09375-0.43359 0.24219-0.60938 0.4375-0.1875 0.19922-0.33594 0.44922-0.4375 0.75-0.09375 0.29297-0.14062 0.63672-0.14062 1.0312 0 0.40625 0.050781 0.75781 0.15625 1.0469 0.11328 0.29297 0.25781 0.53125 0.4375 0.71875 0.17578 0.1875 0.38281 0.32812 0.625 0.42188 0.25 0.09375 0.50781 0.14062 0.78125 0.14062 0.375 0 0.72266-0.0625 1.0469-0.1875 0.32031-0.125 0.625-0.31641 0.90625-0.57812h0.0625z" />
  </symbol>
  <symbol id="glyph8-3" overflow="visible">
   <path d="m2.8281 0h-2.2969v-0.59375h0.76562v-4.625h-0.76562v-0.59375h2.2969v0.59375h-0.76562v4.625h0.76562z" />
  </symbol>
  <symbol id="glyph8-4" overflow="visible">
   <path d="m4.3594-2.0938h-3.2031c0 0.26172 0.039062 0.49219 0.125 0.6875 0.082031 0.19922 0.19141 0.36719 0.32812 0.5 0.13281 0.125 0.29688 0.21875 0.48438 0.28125s0.39062 0.09375 0.60938 0.09375c0.30078 0 0.59766-0.054688 0.89062-0.17188 0.30078-0.125 0.51562-0.24219 0.64062-0.35938h0.046875v0.79688c-0.25 0.10547-0.50781 0.19531-0.76562 0.26562-0.25 0.0625-0.51562 0.09375-0.79688 0.09375-0.73047 0-1.2969-0.19141-1.7031-0.57812-0.40625-0.39453-0.60938-0.95312-0.60938-1.6719 0-0.70703 0.19141-1.2695 0.57812-1.6875 0.39453-0.41406 0.91016-0.625 1.5469-0.625 0.58203 0 1.0312 0.17188 1.3438 0.51562 0.32031 0.33594 0.48438 0.82031 0.48438 1.4531zm-0.70312-0.5625c0-0.38281-0.10156-0.67969-0.29688-0.89062-0.1875-0.21875-0.48047-0.32812-0.875-0.32812-0.38672 0-0.69922 0.12109-0.9375 0.35938-0.23047 0.23047-0.35938 0.51562-0.39062 0.85938z" />
  </symbol>
  <symbol id="glyph8-5" overflow="visible">
   <path d="m4.4375-3.4531-0.25 0.42188-1.4219-0.82812 0.03125 1.4062h-0.5l0.015625-1.4062-1.4062 0.82812-0.25-0.42188 1.4844-0.8125-1.4844-0.79688 0.25-0.4375 1.4062 0.82812-0.015625-1.3906h0.5l-0.03125 1.3906 1.4219-0.82812 0.25 0.4375-1.4844 0.79688z" />
  </symbol>
  <symbol id="glyph8-6" overflow="visible"></symbol>
  <symbol id="glyph8-7" overflow="visible">
   <path d="m4.4844-4.3594-1.7656 4.3594h-0.73438l-1.75-4.3594h0.79688l1.3438 3.4688 1.3438-3.4688z" />
  </symbol>
  <symbol id="glyph8-8" overflow="visible">
   <path d="m4.5625 0h-3.9375v-0.8125c0.26953-0.23828 0.53906-0.47266 0.8125-0.70312 0.28125-0.23828 0.53906-0.47266 0.78125-0.70312 0.5-0.47656 0.83594-0.85938 1.0156-1.1406 0.1875-0.28906 0.28125-0.59766 0.28125-0.92188 0-0.30078-0.10156-0.53516-0.29688-0.70312-0.19922-0.17578-0.47656-0.26562-0.82812-0.26562-0.24219 0-0.5 0.042969-0.78125 0.125-0.27344 0.085938-0.53906 0.21094-0.79688 0.375h-0.046875v-0.8125c0.1875-0.09375 0.42969-0.17578 0.73438-0.25 0.3125-0.070312 0.61328-0.10938 0.90625-0.10938 0.59375 0 1.0547 0.14844 1.3906 0.4375 0.34375 0.28125 0.51562 0.66797 0.51562 1.1562 0 0.21875-0.03125 0.42969-0.09375 0.625-0.054688 0.1875-0.13281 0.36719-0.23438 0.53125-0.10547 0.16797-0.22656 0.32812-0.35938 0.48438-0.13672 0.15625-0.30469 0.32812-0.5 0.51562-0.28125 0.27344-0.57031 0.53906-0.85938 0.79688-0.29297 0.25-0.57031 0.48438-0.82812 0.70312h3.125z" />
  </symbol>
  <symbol id="glyph8-9" overflow="visible">
   <path d="m1.9219 0h-0.9375v-1.1094h0.9375z" />
  </symbol>
  <symbol id="glyph8-10" overflow="visible">
   <path d="m4.5469-2.9062c0 1.043-0.16406 1.8086-0.48438 2.2969-0.32422 0.49219-0.82812 0.73438-1.5156 0.73438-0.69922 0-1.2109-0.24219-1.5312-0.73438-0.32422-0.5-0.48438-1.2578-0.48438-2.2812 0-1.0312 0.16016-1.7891 0.48438-2.2812 0.33203-0.5 0.84375-0.75 1.5312-0.75 0.69531 0 1.2031 0.25 1.5156 0.75 0.32031 0.5 0.48438 1.2578 0.48438 2.2656zm-1.0156 1.7656c0.082031-0.20703 0.14062-0.45312 0.17188-0.73438 0.039063-0.28125 0.0625-0.625 0.0625-1.0312 0-0.39453-0.023437-0.73828-0.0625-1.0312-0.03125-0.28906-0.09375-0.53516-0.1875-0.73438-0.085937-0.19531-0.21094-0.34766-0.375-0.45312-0.15625-0.10156-0.35547-0.15625-0.59375-0.15625-0.25 0-0.45312 0.054688-0.60938 0.15625-0.15625 0.10547-0.28125 0.25781-0.375 0.45312-0.09375 0.19922-0.15625 0.45312-0.1875 0.76562-0.03125 0.30469-0.046875 0.64062-0.046875 1.0156 0 0.40625 0.007813 0.74609 0.03125 1.0156 0.03125 0.27344 0.09375 0.51562 0.1875 0.73438 0.09375 0.19922 0.21875 0.35547 0.375 0.46875 0.15625 0.10547 0.36328 0.15625 0.625 0.15625 0.23828 0 0.4375-0.050781 0.59375-0.15625 0.16406-0.10156 0.29688-0.25781 0.39062-0.46875z" />
  </symbol>
  <symbol id="glyph8-11" overflow="visible">
   <path d="m3.0469 1.6094h-0.89062c-0.46094-0.53125-0.82031-1.1133-1.0781-1.7344-0.25-0.625-0.375-1.3281-0.375-2.1094s0.125-1.4844 0.375-2.1094c0.25781-0.625 0.61719-1.1953 1.0781-1.7188h0.89062v0.03125c-0.21094 0.1875-0.41406 0.40625-0.60938 0.65625-0.1875 0.25-0.35938 0.54297-0.51562 0.875-0.15625 0.32422-0.28906 0.67969-0.39062 1.0625-0.09375 0.375-0.14062 0.77734-0.14062 1.2031 0 0.44922 0.046875 0.85938 0.14062 1.2344 0.09375 0.36719 0.22266 0.71484 0.39062 1.0469 0.15625 0.3125 0.33203 0.59766 0.53125 0.85938 0.19531 0.25781 0.39453 0.47656 0.59375 0.65625z" />
  </symbol>
  <symbol id="glyph8-12" overflow="visible">
   <path d="m4.5156-1.8438c0 0.27344-0.054687 0.53125-0.15625 0.78125-0.09375 0.24219-0.23047 0.44922-0.40625 0.625-0.1875 0.17969-0.41406 0.32031-0.67188 0.42188-0.25 0.09375-0.54688 0.14062-0.89062 0.14062-0.3125 0-0.62109-0.039062-0.92188-0.10938-0.29297-0.0625-0.53906-0.14062-0.73438-0.23438v-0.82812h0.046875c0.21875 0.13672 0.46875 0.25781 0.75 0.35938 0.28906 0.09375 0.57031 0.14062 0.84375 0.14062 0.1875 0 0.36328-0.023437 0.53125-0.078125 0.17578-0.050781 0.33203-0.14453 0.46875-0.28125 0.11328-0.11328 0.19531-0.25 0.25-0.40625 0.0625-0.15625 0.09375-0.33203 0.09375-0.53125 0-0.19531-0.039062-0.36328-0.10938-0.5-0.0625-0.14453-0.15625-0.25781-0.28125-0.34375-0.13672-0.09375-0.30469-0.16016-0.5-0.20312-0.1875-0.039063-0.40234-0.0625-0.64062-0.0625-0.23047 0-0.45312 0.015625-0.67188 0.046875-0.21094 0.03125-0.38672 0.0625-0.53125 0.09375v-3h3.4844v0.6875h-2.7344v1.5469c0.11328-0.007813 0.22656-0.015625 0.34375-0.015625 0.11328-0.007812 0.21094-0.015625 0.29688-0.015625 0.3125 0 0.58594 0.027344 0.82812 0.078125 0.23828 0.054688 0.45703 0.14844 0.65625 0.28125 0.20703 0.14844 0.36719 0.33594 0.48438 0.5625 0.11328 0.21875 0.17188 0.5 0.17188 0.84375z" />
  </symbol>
  <symbol id="glyph8-13" overflow="visible">
   <path d="m5.625-0.42188c-0.32422 0.14844-0.67188 0.27344-1.0469 0.375-0.375 0.10156-0.73438 0.15625-1.0781 0.15625-0.46094 0-0.875-0.066406-1.25-0.1875-0.375-0.125-0.69922-0.3125-0.96875-0.5625-0.26172-0.25-0.46484-0.5625-0.60938-0.9375-0.14844-0.375-0.21875-0.81641-0.21875-1.3281 0-0.92578 0.26953-1.6562 0.8125-2.1875 0.53906-0.53906 1.2852-0.8125 2.2344-0.8125 0.32031 0 0.65625 0.042969 1 0.125 0.34375 0.074219 0.71875 0.20312 1.125 0.39062v0.92188h-0.078125c-0.085937-0.0625-0.20312-0.14453-0.35938-0.25-0.14844-0.10156-0.29297-0.1875-0.4375-0.25-0.1875-0.082031-0.39844-0.14844-0.625-0.20312-0.21875-0.050781-0.47656-0.078125-0.76562-0.078125-0.64844 0-1.1641 0.21094-1.5469 0.625-0.375 0.41797-0.5625 0.98047-0.5625 1.6875 0 0.75 0.19531 1.3398 0.59375 1.7656 0.39453 0.41797 0.92969 0.625 1.6094 0.625 0.25 0 0.5-0.023437 0.75-0.078125 0.25-0.050781 0.46875-0.11328 0.65625-0.1875v-1.4219h-1.5625v-0.6875h2.3281z" />
  </symbol>
  <symbol id="glyph8-14" overflow="visible">
   <path d="m4.9219-5.125h-2.0781v5.125h-0.76562v-5.125h-2.0781v-0.6875h4.9219z" />
  </symbol>
  <symbol id="glyph8-15" overflow="visible">
   <path d="m3.3594-6.0625-2.7969 7.25h-0.67188l2.7812-7.25z" />
  </symbol>
  <symbol id="glyph8-16" overflow="visible">
   <path d="m3.8281-1.25c0 0.39844-0.16797 0.72656-0.5 0.98438-0.32422 0.25-0.76562 0.375-1.3281 0.375-0.32422 0-0.62109-0.039062-0.89062-0.10938-0.27344-0.082031-0.5-0.17188-0.6875-0.26562v-0.8125h0.046875c0.22656 0.16797 0.48438 0.30469 0.76562 0.40625 0.28906 0.10547 0.5625 0.15625 0.8125 0.15625 0.32031 0 0.57031-0.050781 0.75-0.15625 0.1875-0.10156 0.28125-0.26562 0.28125-0.48438 0-0.17578-0.046875-0.30469-0.14062-0.39062-0.10547-0.09375-0.29688-0.17188-0.57812-0.23438-0.10547-0.019531-0.24219-0.046875-0.40625-0.078125-0.16797-0.03125-0.32031-0.066406-0.45312-0.10938-0.38672-0.09375-0.65625-0.23828-0.8125-0.4375-0.15625-0.19531-0.23438-0.4375-0.23438-0.71875 0-0.1875 0.035156-0.35938 0.10938-0.51562 0.070312-0.15625 0.17969-0.29688 0.32812-0.42188 0.14453-0.125 0.33203-0.21875 0.5625-0.28125 0.22656-0.070312 0.47656-0.10938 0.75-0.10938 0.25781 0 0.51953 0.03125 0.78125 0.09375 0.26953 0.0625 0.49219 0.14062 0.67188 0.23438v0.78125h-0.03125c-0.1875-0.14453-0.41797-0.26562-0.6875-0.35938-0.27344-0.09375-0.53125-0.14062-0.78125-0.14062-0.27344 0-0.5 0.054688-0.6875 0.15625-0.17969 0.10547-0.26562 0.25781-0.26562 0.45312 0 0.1875 0.050781 0.32422 0.15625 0.40625 0.11328 0.09375 0.28906 0.17188 0.53125 0.23438 0.13281 0.03125 0.28516 0.0625 0.45312 0.09375 0.16406 0.03125 0.30469 0.058594 0.42188 0.078125 0.34375 0.085937 0.60938 0.21875 0.79688 0.40625 0.17578 0.1875 0.26562 0.44531 0.26562 0.76562z" />
  </symbol>
  <symbol id="glyph8-17" overflow="visible">
   <path d="m2.9219-2.2344c0 0.78125-0.13281 1.4844-0.39062 2.1094-0.25 0.62109-0.60547 1.2031-1.0625 1.7344h-0.89062v-0.046875c0.19531-0.17969 0.39453-0.39844 0.59375-0.65625 0.20703-0.26172 0.38281-0.54688 0.53125-0.85938 0.16406-0.33203 0.29688-0.67969 0.39062-1.0469 0.09375-0.375 0.14062-0.78516 0.14062-1.2344 0-0.42578-0.046875-0.82812-0.14062-1.2031-0.09375-0.38281-0.22656-0.73828-0.39062-1.0625-0.15625-0.33203-0.33594-0.625-0.53125-0.875-0.1875-0.25-0.38672-0.46875-0.59375-0.65625v-0.03125h0.89062c0.45703 0.52344 0.8125 1.0938 1.0625 1.7188 0.25781 0.625 0.39062 1.3281 0.39062 2.1094z" />
  </symbol>
  <symbol id="glyph8-18" overflow="visible">
   <path d="m4.4844 0h-0.92188l-1.2344-1.6719-1.2344 1.6719h-0.85938l1.7031-2.1719-1.6875-2.1875h0.92188l1.2344 1.6562 1.2344-1.6562h0.84375l-1.7031 2.1562z" />
  </symbol>
  <symbol id="glyph8-19" overflow="visible">
   <path d="m4.6875-1.6406h-0.85938v1.6406h-0.75v-1.6406h-2.7812v-0.89062l2.8125-3.2812h0.71875v3.5625h0.85938zm-1.6094-0.60938v-2.625l-2.25 2.625z" />
  </symbol>
  <symbol id="glyph8-20" overflow="visible">
   <path d="m4.2188 0h-3.1406v-0.59375h1.2188v-3.8906h-1.2188v-0.53125c0.16406 0 0.34375-0.007813 0.53125-0.03125 0.1875-0.03125 0.32812-0.070313 0.42188-0.125 0.125-0.0625 0.21875-0.14453 0.28125-0.25 0.070312-0.10156 0.11328-0.23828 0.125-0.40625h0.60938v5.2344h1.1719z" />
  </symbol>
  <symbol id="glyph8-21" overflow="visible">
   <path d="m2.2812-3.25h-0.9375v-1.1094h0.9375zm0.28125 2.1406-1.0938 2.5469h-0.57812l0.6875-2.5469z" />
  </symbol>
  <symbol id="glyph8-22" overflow="visible">
   <path d="m3.9375-0.26562c-0.24219 0.11719-0.46875 0.20312-0.6875 0.26562s-0.45312 0.09375-0.70312 0.09375c-0.3125 0-0.60547-0.042969-0.875-0.125-0.26172-0.09375-0.48438-0.23438-0.67188-0.42188s-0.33594-0.42188-0.4375-0.70312c-0.10547-0.28906-0.15625-0.62891-0.15625-1.0156 0-0.70703 0.19141-1.2656 0.57812-1.6719 0.39453-0.40625 0.91406-0.60938 1.5625-0.60938 0.25 0 0.49219 0.039063 0.73438 0.10938 0.23828 0.0625 0.45703 0.14844 0.65625 0.25v0.8125h-0.03125c-0.23047-0.17578-0.46484-0.3125-0.70312-0.40625-0.23047-0.09375-0.46094-0.14062-0.6875-0.14062-0.41797 0-0.74609 0.14062-0.98438 0.42188-0.24219 0.28125-0.35938 0.69531-0.35938 1.2344 0 0.52344 0.11328 0.92969 0.34375 1.2188 0.23828 0.28125 0.57031 0.42188 1 0.42188 0.14453 0 0.29688-0.019531 0.45312-0.0625 0.15625-0.039062 0.28906-0.09375 0.40625-0.15625 0.11328-0.050781 0.21875-0.10938 0.3125-0.17188s0.16406-0.11328 0.21875-0.15625h0.03125z" />
  </symbol>
  <symbol id="glyph8-23" overflow="visible">
   <path d="m4.1094 0h-0.73438v-0.46875c-0.0625 0.054688-0.15234 0.12109-0.26562 0.20312-0.10547 0.074219-0.21094 0.13281-0.3125 0.17188-0.125 0.0625-0.27344 0.11328-0.4375 0.15625-0.15625 0.039062-0.33984 0.0625-0.54688 0.0625-0.39844 0-0.73047-0.12891-1-0.39062-0.27344-0.25781-0.40625-0.59375-0.40625-1 0-0.33203 0.066406-0.59766 0.20312-0.79688 0.14453-0.20703 0.34766-0.36719 0.60938-0.48438 0.26953-0.11328 0.58594-0.19141 0.95312-0.23438 0.375-0.039062 0.77344-0.070312 1.2031-0.09375v-0.10938c0-0.16406-0.03125-0.30078-0.09375-0.40625-0.054688-0.11328-0.13672-0.20312-0.25-0.26562-0.10547-0.0625-0.23047-0.10156-0.375-0.125-0.14844-0.019531-0.29688-0.03125-0.45312-0.03125-0.1875 0-0.40234 0.027344-0.64062 0.078125-0.24219 0.054687-0.48438 0.125-0.73438 0.21875h-0.03125v-0.75c0.13281-0.03125 0.33594-0.066406 0.60938-0.10938 0.26953-0.050781 0.53516-0.078125 0.79688-0.078125 0.3125 0 0.58203 0.027344 0.8125 0.078125 0.22656 0.042969 0.42578 0.125 0.59375 0.25 0.15625 0.11719 0.27344 0.27344 0.35938 0.46875 0.09375 0.1875 0.14062 0.42188 0.14062 0.70312zm-0.73438-1.0781v-1.2031c-0.21875 0.011719-0.48438 0.03125-0.79688 0.0625-0.30469 0.023438-0.53906 0.058594-0.70312 0.10938-0.21875 0.0625-0.39844 0.15625-0.53125 0.28125-0.125 0.125-0.1875 0.29688-0.1875 0.51562 0 0.25 0.070312 0.4375 0.21875 0.5625 0.15625 0.125 0.39062 0.1875 0.70312 0.1875 0.25781 0 0.49219-0.046875 0.70312-0.14062 0.21875-0.10156 0.41406-0.22656 0.59375-0.375z" />
  </symbol>
  <symbol id="glyph8-24" overflow="visible">
   <path d="m1.4688 0h-0.73438v-6.0625h0.73438z" />
  </symbol>
  <symbol id="glyph8-25" overflow="visible">
   <path d="m4.25 0h-0.73438v-0.45312c-0.21094 0.17969-0.42969 0.32031-0.65625 0.42188-0.23047 0.10156-0.48047 0.15625-0.75 0.15625-0.51172 0-0.92188-0.19531-1.2344-0.59375-0.30469-0.40625-0.45312-0.96094-0.45312-1.6719 0-0.375 0.050781-0.70312 0.15625-0.98438 0.10156-0.28906 0.24219-0.53906 0.42188-0.75 0.17578-0.1875 0.38281-0.33203 0.625-0.4375 0.23828-0.10156 0.48438-0.15625 0.73438-0.15625 0.22656 0 0.42969 0.027344 0.60938 0.078125 0.17578 0.042969 0.35938 0.11719 0.54688 0.21875v-1.8906h0.73438zm-0.73438-1.0781v-2.5c-0.19922-0.082031-0.375-0.14062-0.53125-0.17188-0.15625-0.039062-0.32422-0.0625-0.5-0.0625-0.41797 0-0.74219 0.14844-0.96875 0.4375-0.23047 0.28125-0.34375 0.6875-0.34375 1.2188 0 0.51172 0.085937 0.90234 0.26562 1.1719 0.17578 0.27344 0.46094 0.40625 0.85938 0.40625 0.20703 0 0.41406-0.046875 0.625-0.14062 0.21875-0.09375 0.41406-0.21094 0.59375-0.35938z" />
  </symbol>
  <symbol id="glyph8-26" overflow="visible">
   <path d="m1.5156-5.0781h-0.82812v-0.76562h0.82812zm-0.046875 5.0781h-0.73438v-4.3594h0.73438z" />
  </symbol>
  <symbol id="glyph8-27" overflow="visible">
   <path d="m4.3594 0h-0.73438v-2.4844c0-0.19531-0.011719-0.38281-0.03125-0.5625-0.023438-0.17578-0.0625-0.3125-0.125-0.40625-0.0625-0.11328-0.15625-0.19531-0.28125-0.25-0.125-0.050781-0.28906-0.078125-0.48438-0.078125-0.19922 0-0.40625 0.054688-0.625 0.15625-0.21875 0.09375-0.42969 0.21875-0.625 0.375v3.25h-0.73438v-4.3594h0.73438v0.48438c0.22656-0.1875 0.46094-0.33203 0.70312-0.4375 0.25-0.10156 0.50391-0.15625 0.76562-0.15625 0.46875 0 0.82031 0.14062 1.0625 0.42188 0.25 0.28125 0.375 0.6875 0.375 1.2188z" />
  </symbol>
  <symbol id="glyph8-28" overflow="visible">
   <path d="m2.9844-0.03125c-0.13672 0.03125-0.28906 0.054688-0.45312 0.078125-0.16797 0.019531-0.3125 0.03125-0.4375 0.03125-0.4375 0-0.77734-0.11328-1.0156-0.34375-0.23047-0.23828-0.34375-0.625-0.34375-1.1562v-2.3125h-0.5v-0.625h0.5v-1.25h0.73438v1.25h1.5156v0.625h-1.5156v1.9844c0 0.23047 0.003906 0.40625 0.015625 0.53125 0.007813 0.125 0.046875 0.24609 0.10938 0.35938 0.0625 0.10547 0.14062 0.18359 0.23438 0.23438 0.10156 0.042969 0.25391 0.0625 0.45312 0.0625 0.125 0 0.25-0.015625 0.375-0.046875 0.13281-0.03125 0.22656-0.0625 0.28125-0.09375h0.046875z" />
  </symbol>
  <symbol id="glyph8-29" overflow="visible">
   <path d="m4.3594 0h-0.73438v-2.4844c0-0.19531-0.011719-0.38281-0.03125-0.5625-0.023438-0.17578-0.0625-0.3125-0.125-0.40625-0.0625-0.11328-0.15625-0.19531-0.28125-0.25-0.125-0.050781-0.28906-0.078125-0.48438-0.078125-0.19922 0-0.40625 0.054688-0.625 0.15625-0.21875 0.09375-0.42969 0.21875-0.625 0.375v3.25h-0.73438v-6.0625h0.73438v2.1875c0.22656-0.1875 0.46094-0.33203 0.70312-0.4375 0.25-0.10156 0.50391-0.15625 0.76562-0.15625 0.46875 0 0.82031 0.14062 1.0625 0.42188 0.25 0.28125 0.375 0.6875 0.375 1.2188z" />
  </symbol>
  <symbol id="glyph8-30" overflow="visible">
   <path d="m4.4375-2.1719c0 0.71094-0.18359 1.2734-0.54688 1.6875-0.36719 0.40625-0.85547 0.60938-1.4688 0.60938-0.61719 0-1.1055-0.20312-1.4688-0.60938-0.36719-0.41406-0.54688-0.97656-0.54688-1.6875 0-0.70703 0.17969-1.2656 0.54688-1.6719 0.36328-0.41406 0.85156-0.625 1.4688-0.625 0.61328 0 1.1016 0.21094 1.4688 0.625 0.36328 0.40625 0.54688 0.96484 0.54688 1.6719zm-0.76562 0c0-0.5625-0.10938-0.97656-0.32812-1.25-0.21875-0.28125-0.52734-0.42188-0.92188-0.42188-0.39844 0-0.70312 0.14062-0.92188 0.42188-0.21875 0.27344-0.32812 0.6875-0.32812 1.25 0 0.54297 0.10938 0.95312 0.32812 1.2344s0.52344 0.42188 0.92188 0.42188c0.39453 0 0.70312-0.13281 0.92188-0.40625 0.21875-0.28125 0.32812-0.69531 0.32812-1.25z" />
  </symbol>
  <symbol id="glyph8-31" overflow="visible">
   <path d="m4.3281 0h-0.73438v-0.48438c-0.24219 0.19922-0.47656 0.35156-0.70312 0.45312-0.23047 0.10156-0.48047 0.15625-0.75 0.15625-0.46094 0-0.82031-0.14062-1.0781-0.42188-0.25-0.28125-0.375-0.69141-0.375-1.2344v-2.8281h0.73438v2.4844c0 0.21875 0.007813 0.40625 0.03125 0.5625 0.019531 0.15625 0.066406 0.29297 0.14062 0.40625 0.0625 0.11719 0.14844 0.19922 0.26562 0.25 0.11328 0.054688 0.27344 0.078125 0.48438 0.078125 0.1875 0 0.39453-0.046875 0.625-0.14062 0.22656-0.10156 0.4375-0.23438 0.625-0.39062v-3.25h0.73438z" />
  </symbol>
  <symbol id="glyph8-32" overflow="visible">
   <path d="m7.0781 0h-0.73438v-2.4844c0-0.1875-0.011719-0.36328-0.03125-0.53125-0.011719-0.17578-0.046875-0.31641-0.10938-0.42188-0.054687-0.11328-0.13672-0.19531-0.25-0.25-0.11719-0.0625-0.27734-0.09375-0.48438-0.09375-0.21094 0-0.41797 0.054688-0.625 0.15625-0.19922 0.10547-0.40234 0.23438-0.60938 0.39062 0.007813 0.0625 0.015625 0.13672 0.015625 0.21875 0.007812 0.074219 0.015625 0.15234 0.015625 0.23438v2.7812h-0.73438v-2.4844c0-0.1875-0.011719-0.36328-0.03125-0.53125-0.011719-0.17578-0.042969-0.31641-0.09375-0.42188-0.0625-0.11328-0.15234-0.19531-0.26562-0.25-0.11719-0.0625-0.27734-0.09375-0.48438-0.09375-0.19922 0-0.40234 0.054688-0.60938 0.15625-0.19922 0.09375-0.39844 0.21875-0.59375 0.375v3.25h-0.73438v-4.3594h0.73438v0.48438c0.22656-0.1875 0.45703-0.33203 0.6875-0.4375 0.22656-0.10156 0.46875-0.15625 0.71875-0.15625 0.30078 0 0.55469 0.0625 0.76562 0.1875 0.20703 0.125 0.35938 0.29688 0.45312 0.51562 0.30078-0.25 0.57031-0.42578 0.8125-0.53125 0.25-0.11328 0.50781-0.17188 0.78125-0.17188 0.47656 0 0.83203 0.14844 1.0625 0.4375 0.22656 0.28125 0.34375 0.68359 0.34375 1.2031z" />
  </symbol>
  <symbol id="glyph8-33" overflow="visible">
   <path d="m5.9531 0h-0.78125v-5l-1.6094 3.4062h-0.45312l-1.6094-3.4062v5h-0.71875v-5.8125h1.0469l1.5469 3.2344 1.5-3.2344h1.0781z" />
  </symbol>
  <symbol id="glyph8-34" overflow="visible">
   <path d="m5.6875-2.8906c0 0.52344-0.11719 1-0.34375 1.4375-0.23047 0.42969-0.53906 0.75781-0.92188 0.98438-0.27344 0.16797-0.57031 0.28906-0.89062 0.35938-0.32422 0.074219-0.75 0.10938-1.2812 0.10938h-1.4688v-5.8125h1.4531c0.5625 0 1.0078 0.042969 1.3438 0.125 0.33203 0.085938 0.61328 0.19922 0.84375 0.34375 0.39453 0.25 0.70312 0.57812 0.92188 0.98438 0.22656 0.40625 0.34375 0.89844 0.34375 1.4688zm-0.8125-0.015625c0-0.45703-0.078125-0.84375-0.23438-1.1562s-0.39062-0.55469-0.70312-0.73438c-0.23047-0.125-0.47656-0.21094-0.73438-0.26562-0.26172-0.050781-0.57031-0.078125-0.92188-0.078125h-0.73438v4.4844h0.73438c0.36328 0 0.6875-0.023438 0.96875-0.078125 0.28125-0.0625 0.53516-0.16406 0.76562-0.3125 0.28125-0.1875 0.49219-0.42969 0.64062-0.73438 0.14453-0.30078 0.21875-0.67578 0.21875-1.125z" />
  </symbol>
  <symbol id="glyph8-35" overflow="visible">
   <path d="m4.5469-2.2344c0 0.35547-0.054687 0.67969-0.15625 0.96875-0.09375 0.29297-0.23438 0.54297-0.42188 0.75-0.16797 0.1875-0.37109 0.33594-0.60938 0.4375-0.23047 0.10156-0.47656 0.15625-0.73438 0.15625-0.23047 0-0.4375-0.027344-0.625-0.078125-0.17969-0.039062-0.35938-0.11328-0.54688-0.21875v1.8281h-0.73438v-5.9688h0.73438v0.45312c0.19531-0.15625 0.41406-0.28516 0.65625-0.39062 0.23828-0.11328 0.5-0.17188 0.78125-0.17188 0.51953 0 0.92578 0.19922 1.2188 0.59375 0.28906 0.39844 0.4375 0.94531 0.4375 1.6406zm-0.75 0.03125c0-0.53125-0.089844-0.92578-0.26562-1.1875-0.17969-0.25781-0.45312-0.39062-0.82812-0.39062-0.21094 0-0.42188 0.046875-0.64062 0.14062-0.21094 0.09375-0.41406 0.21484-0.60938 0.35938v2.4688c0.20703 0.09375 0.38281 0.15625 0.53125 0.1875 0.15625 0.03125 0.32812 0.046875 0.51562 0.046875 0.40625 0 0.72266-0.13281 0.95312-0.40625 0.22656-0.28125 0.34375-0.6875 0.34375-1.2188z" />
  </symbol>
  <symbol id="glyph8-36" overflow="visible">
   <path d="m3.4375-3.5625h-0.03125c-0.11719-0.019531-0.22656-0.035156-0.32812-0.046875-0.10547-0.007813-0.22656-0.015625-0.35938-0.015625-0.23047 0-0.44922 0.054688-0.65625 0.15625-0.21094 0.09375-0.41406 0.21875-0.60938 0.375v3.0938h-0.73438v-4.3594h0.73438v0.64062c0.28906-0.22656 0.54688-0.39062 0.76562-0.48438 0.22656-0.10156 0.45703-0.15625 0.6875-0.15625 0.125 0 0.21094 0.007813 0.26562 0.015625 0.0625 0.011719 0.14844 0.023438 0.26562 0.03125z" />
  </symbol>
  <symbol id="glyph8-37" overflow="visible">
   <path d="m4.6094 0h-3.8281v-5.8125h3.8281v0.6875h-3.0625v1.5938h3.0625v0.6875h-3.0625v2.1562h3.0625z" />
  </symbol>
  <symbol id="glyph8-38" overflow="visible">
   <path d="m4.5938-1.625c0 0.51172-0.19922 0.93359-0.59375 1.2656-0.38672 0.32422-0.875 0.48438-1.4688 0.48438-0.625 0-1.125-0.16016-1.5-0.48438-0.375-0.32031-0.5625-0.73828-0.5625-1.25 0-0.3125 0.09375-0.59766 0.28125-0.85938 0.1875-0.26953 0.45312-0.47656 0.79688-0.625v-0.03125c-0.3125-0.16406-0.54688-0.34766-0.70312-0.54688-0.14844-0.19531-0.21875-0.44141-0.21875-0.73438 0-0.4375 0.17578-0.80078 0.53125-1.0938 0.36328-0.28906 0.82031-0.4375 1.375-0.4375 0.58203 0 1.0469 0.14062 1.3906 0.42188 0.34375 0.27344 0.51562 0.625 0.51562 1.0625 0 0.26172-0.085938 0.51562-0.25 0.76562-0.15625 0.25-0.39062 0.44922-0.70312 0.59375v0.03125c0.35156 0.15625 0.625 0.35156 0.8125 0.57812 0.19531 0.23047 0.29688 0.51562 0.29688 0.85938zm-0.92188-2.8281c0-0.28125-0.10938-0.5-0.32812-0.65625-0.21094-0.16406-0.48047-0.25-0.8125-0.25-0.32422 0-0.58984 0.078125-0.79688 0.23438-0.21094 0.15625-0.3125 0.36719-0.3125 0.625 0 0.1875 0.050781 0.35156 0.15625 0.48438 0.10156 0.13672 0.25781 0.25781 0.46875 0.35938 0.09375 0.054688 0.22656 0.11719 0.40625 0.1875 0.1875 0.074219 0.36719 0.13672 0.54688 0.1875 0.25-0.16406 0.42188-0.34375 0.51562-0.53125 0.10156-0.1875 0.15625-0.39844 0.15625-0.64062zm0.125 2.9062c0-0.23828-0.054687-0.42578-0.15625-0.5625-0.10547-0.14453-0.3125-0.28906-0.625-0.4375-0.11719-0.0625-0.24609-0.11328-0.39062-0.15625-0.14844-0.050781-0.34375-0.125-0.59375-0.21875-0.23047 0.125-0.41797 0.29688-0.5625 0.51562-0.13672 0.21875-0.20312 0.46875-0.20312 0.75 0 0.34375 0.11719 0.63281 0.35938 0.85938 0.23828 0.23047 0.54688 0.34375 0.92188 0.34375s0.67578-0.09375 0.90625-0.28125c0.22656-0.19531 0.34375-0.46875 0.34375-0.8125z" />
  </symbol>
  <symbol id="glyph8-39" overflow="visible">
   <path d="m4.0469-2.7969c0.125 0.11719 0.22266 0.25781 0.29688 0.42188 0.082031 0.16797 0.125 0.38672 0.125 0.65625 0 0.26172-0.046875 0.50781-0.14062 0.73438-0.09375 0.21875-0.23047 0.41406-0.40625 0.57812-0.1875 0.17969-0.41797 0.3125-0.6875 0.40625-0.26172 0.082031-0.54688 0.125-0.85938 0.125-0.32422 0-0.64062-0.042969-0.95312-0.125-0.3125-0.070312-0.57031-0.15625-0.76562-0.25v-0.8125h0.046875c0.22656 0.14844 0.48828 0.27344 0.78125 0.375 0.30078 0.09375 0.59375 0.14062 0.875 0.14062 0.15625 0 0.32812-0.023437 0.51562-0.078125 0.1875-0.0625 0.33594-0.14453 0.45312-0.25 0.11328-0.11328 0.20312-0.23828 0.26562-0.375 0.0625-0.14453 0.09375-0.32031 0.09375-0.53125 0-0.20703-0.039062-0.37891-0.10938-0.51562-0.0625-0.13281-0.15234-0.23828-0.26562-0.3125-0.125-0.082031-0.27344-0.14062-0.4375-0.17188-0.16797-0.03125-0.34375-0.046875-0.53125-0.046875h-0.34375v-0.64062h0.26562c0.39453 0 0.70703-0.082031 0.9375-0.25 0.23828-0.16406 0.35938-0.40625 0.35938-0.71875 0-0.14453-0.03125-0.26953-0.09375-0.375-0.054688-0.10156-0.13672-0.19141-0.25-0.26562-0.10547-0.0625-0.22656-0.10156-0.35938-0.125-0.125-0.03125-0.26562-0.046875-0.42188-0.046875-0.25 0-0.51562 0.046875-0.79688 0.14062-0.27344 0.085937-0.53125 0.20312-0.78125 0.35938h-0.046875v-0.8125c0.1875-0.09375 0.42969-0.17578 0.73438-0.25 0.3125-0.070312 0.61328-0.10938 0.90625-0.10938 0.28125 0 0.53125 0.027344 0.75 0.078125 0.21875 0.054688 0.41016 0.13672 0.57812 0.25 0.1875 0.125 0.32812 0.27734 0.42188 0.45312 0.10156 0.17969 0.15625 0.38281 0.15625 0.60938 0 0.32422-0.11719 0.60547-0.34375 0.84375-0.23047 0.24219-0.5 0.39062-0.8125 0.45312v0.0625c0.125 0.023437 0.26562 0.070313 0.42188 0.14062 0.16406 0.0625 0.30469 0.14062 0.42188 0.23438z" />
  </symbol>
  <symbol id="glyph8-40" overflow="visible">
   <path d="m3.0625-5.3594h-0.03125c-0.085938-0.019531-0.19531-0.039063-0.32812-0.0625-0.125-0.03125-0.24219-0.046875-0.34375-0.046875-0.3125 0-0.54297 0.074219-0.6875 0.21875-0.13672 0.13672-0.20312 0.38672-0.20312 0.75v0.14062h1.3281v0.625h-1.2969v3.7344h-0.73438v-3.7344h-0.5v-0.625h0.5v-0.14062c0-0.51953 0.125-0.91406 0.375-1.1875 0.25781-0.28125 0.63281-0.42188 1.125-0.42188 0.15625 0 0.30078 0.011719 0.4375 0.03125 0.13281 0.011719 0.25391 0.027344 0.35938 0.046875z" />
  </symbol>
  <symbol id="glyph8-41" overflow="visible">
   <path d="m5.1562-1.7812c0 0.28125-0.058594 0.53906-0.17188 0.76562-0.10547 0.21875-0.25 0.40234-0.4375 0.54688-0.21875 0.16797-0.46094 0.28906-0.71875 0.35938-0.26172 0.074219-0.58984 0.10938-0.98438 0.10938h-2.0625v-5.8125h1.7188c0.42578 0 0.74219 0.015625 0.95312 0.046875 0.20703 0.03125 0.40625 0.10156 0.59375 0.20312 0.21875 0.11719 0.375 0.26172 0.46875 0.4375 0.09375 0.16797 0.14062 0.375 0.14062 0.625 0 0.27344-0.074219 0.50781-0.21875 0.70312-0.13672 0.1875-0.32031 0.34375-0.54688 0.46875v0.03125c0.39453 0.074219 0.70312 0.24609 0.92188 0.51562 0.22656 0.26172 0.34375 0.59375 0.34375 1zm-1.2969-2.625c0-0.13281-0.027344-0.25-0.078125-0.34375-0.042969-0.10156-0.11719-0.17969-0.21875-0.23438-0.125-0.070313-0.27734-0.11328-0.45312-0.125-0.16797-0.019531-0.38281-0.03125-0.64062-0.03125h-0.92188v1.6719h1c0.23828 0 0.42969-0.007812 0.57812-0.03125 0.14453-0.03125 0.28125-0.082031 0.40625-0.15625 0.11328-0.082031 0.19531-0.17969 0.25-0.29688 0.050781-0.125 0.078125-0.27344 0.078125-0.45312zm0.5 2.6562c0-0.23828-0.039063-0.42578-0.10938-0.5625-0.074219-0.13281-0.19922-0.25-0.375-0.34375-0.125-0.070312-0.28125-0.11328-0.46875-0.125-0.17969-0.019531-0.39062-0.03125-0.64062-0.03125h-1.2188v2.1562h1.0312c0.33203 0 0.60938-0.015625 0.82812-0.046875 0.21875-0.039063 0.39453-0.10938 0.53125-0.20312 0.14453-0.10156 0.25-0.21875 0.3125-0.34375 0.070312-0.13281 0.10938-0.30078 0.10938-0.5z" />
  </symbol>
  <symbol id="glyph8-42" overflow="visible">
   <path d="m5.3594 0h-0.82812l-0.5625-1.625h-2.5156l-0.5625 1.625h-0.79688l2.125-5.8125h1.0312zm-1.625-2.2812-1.0312-2.8438-1.0156 2.8438z" />
  </symbol>
  <symbol id="glyph8-43" overflow="visible">
   <path d="m5-1.6562c0 0.23047-0.054688 0.45312-0.15625 0.67188-0.10547 0.21875-0.25781 0.40625-0.45312 0.5625-0.21094 0.16797-0.45312 0.29688-0.73438 0.39062-0.27344 0.089844-0.60156 0.14062-0.98438 0.14062-0.41797 0-0.79297-0.039062-1.125-0.10938-0.33594-0.082031-0.67969-0.20312-1.0312-0.35938v-0.96875h0.0625c0.28906 0.25 0.62891 0.44531 1.0156 0.57812 0.38281 0.125 0.74219 0.1875 1.0781 0.1875 0.47656 0 0.84766-0.085938 1.1094-0.26562 0.26953-0.17578 0.40625-0.41406 0.40625-0.71875 0-0.25781-0.0625-0.44531-0.1875-0.5625-0.125-0.125-0.3125-0.22266-0.5625-0.29688-0.19922-0.050781-0.41406-0.09375-0.64062-0.125-0.23047-0.03125-0.46875-0.070312-0.71875-0.125-0.52344-0.11328-0.90625-0.30078-1.1562-0.5625-0.24219-0.25781-0.35938-0.60156-0.35938-1.0312 0-0.48828 0.20312-0.88281 0.60938-1.1875 0.41406-0.3125 0.9375-0.46875 1.5625-0.46875 0.40625 0 0.78125 0.042969 1.125 0.125 0.34375 0.074219 0.64453 0.16797 0.90625 0.28125v0.90625h-0.0625c-0.21875-0.1875-0.51172-0.34375-0.875-0.46875-0.35547-0.125-0.71875-0.1875-1.0938-0.1875-0.41797 0-0.75 0.089844-1 0.26562-0.25 0.16797-0.375 0.38672-0.375 0.65625 0 0.24219 0.0625 0.43359 0.1875 0.57812 0.125 0.13672 0.34375 0.24219 0.65625 0.3125 0.16406 0.03125 0.39844 0.074219 0.70312 0.125 0.3125 0.054688 0.57812 0.10938 0.79688 0.17188 0.42578 0.11719 0.75 0.28906 0.96875 0.51562 0.21875 0.23047 0.32812 0.55469 0.32812 0.96875z" />
  </symbol>
  <symbol id="glyph8-44" overflow="visible">
   <path d="m3.0312-2.1875h-2.4375v-0.70312h2.4375z" />
  </symbol>
  <symbol id="glyph8-45" overflow="visible">
   <path d="m2.2344-1.1094-1.0938 2.5469h-0.5625l0.67188-2.5469z" />
  </symbol>
  <symbol id="glyph8-46" overflow="visible">
   <path d="m5.2031-5.8125-2 2.875 2 2.9375h-0.89062l-1.5781-2.3906-1.625 2.3906h-0.84375l2.0156-2.9062-1.9688-2.9062h0.89062l1.5625 2.3594 1.5938-2.3594z" />
  </symbol>
  <symbol id="glyph8-47" overflow="visible">
   <path d="m4.5469-2.2031c0 0.35547-0.054687 0.67969-0.15625 0.96875-0.09375 0.29297-0.23047 0.53906-0.40625 0.73438-0.1875 0.21094-0.39062 0.36719-0.60938 0.46875-0.21875 0.10156-0.46484 0.15625-0.73438 0.15625-0.24219 0-0.45312-0.03125-0.64062-0.09375-0.1875-0.050781-0.37109-0.12891-0.54688-0.23438l-0.046875 0.20312h-0.6875v-6.0625h0.73438v2.1562c0.20703-0.16406 0.42578-0.30078 0.65625-0.40625 0.22656-0.10156 0.48828-0.15625 0.78125-0.15625 0.50781 0 0.91016 0.19922 1.2031 0.59375 0.30078 0.38672 0.45312 0.94531 0.45312 1.6719zm-0.75 0.015625c0-0.51953-0.089844-0.91406-0.26562-1.1875-0.16797-0.26953-0.44531-0.40625-0.82812-0.40625-0.21094 0-0.42188 0.046875-0.64062 0.14062s-0.42188 0.21484-0.60938 0.35938v2.5c0.20703 0.09375 0.38281 0.16406 0.53125 0.20312 0.15625 0.03125 0.32812 0.046875 0.51562 0.046875 0.40625 0 0.72266-0.13281 0.95312-0.40625 0.22656-0.26953 0.34375-0.6875 0.34375-1.25z" />
  </symbol>
  <symbol id="glyph8-48" overflow="visible">
   <path d="m3.875 0h-3.5156v-0.54688l2.5469-3.2031h-2.4844v-0.60938h3.3906v0.53125l-2.5469 3.2031h2.6094z" />
  </symbol>
  <symbol id="glyph8-49" overflow="visible">
   <path d="m5.5781 0h-1l-1.9375-2.3125h-1.0938v2.3125h-0.76562v-5.8125h1.625c0.35156 0 0.64453 0.027344 0.875 0.078125 0.23828 0.042969 0.45312 0.12109 0.64062 0.23438 0.20703 0.13672 0.36719 0.30859 0.48438 0.51562 0.11328 0.19922 0.17188 0.45312 0.17188 0.76562 0 0.41797-0.10547 0.76562-0.3125 1.0469-0.21094 0.28125-0.49609 0.49609-0.85938 0.64062zm-1.7969-4.1719c0-0.16406-0.03125-0.3125-0.09375-0.4375-0.054688-0.13281-0.14844-0.24219-0.28125-0.32812-0.11719-0.070312-0.25-0.125-0.40625-0.15625s-0.33984-0.046875-0.54688-0.046875h-0.90625v2.1875h0.78125c0.25 0 0.46094-0.019531 0.64062-0.0625 0.1875-0.039063 0.34375-0.11719 0.46875-0.23438 0.11328-0.11328 0.19531-0.23828 0.25-0.375 0.0625-0.14453 0.09375-0.32812 0.09375-0.54688z" />
  </symbol>
  <symbol id="glyph8-50" overflow="visible">
   <path d="m4.4531 0h-3.6719v-5.8125h0.76562v5.125h2.9062z" />
  </symbol>
  <symbol id="glyph8-51" overflow="visible">
   <path d="m4.25-0.5c0 0.73828-0.16797 1.2812-0.5 1.625-0.33594 0.35156-0.85156 0.53125-1.5469 0.53125-0.23047 0-0.45312-0.023438-0.67188-0.0625-0.21875-0.03125-0.4375-0.074219-0.65625-0.125v-0.75h0.046875c0.11328 0.039062 0.30078 0.09375 0.5625 0.15625 0.25781 0.070312 0.51953 0.10938 0.78125 0.10938 0.25 0 0.45312-0.03125 0.60938-0.09375 0.16406-0.054687 0.29688-0.13281 0.39062-0.23438 0.09375-0.10547 0.15625-0.23047 0.1875-0.375 0.039063-0.14844 0.0625-0.30078 0.0625-0.46875v-0.40625c-0.21875 0.17969-0.43359 0.3125-0.64062 0.40625-0.19922 0.085938-0.45312 0.125-0.76562 0.125-0.51172 0-0.92188-0.1875-1.2344-0.5625-0.30469-0.375-0.45312-0.90625-0.45312-1.5938 0-0.375 0.050781-0.69531 0.15625-0.96875 0.10156-0.26953 0.25-0.50391 0.4375-0.70312 0.16406-0.1875 0.36719-0.32812 0.60938-0.42188 0.23828-0.10156 0.47656-0.15625 0.71875-0.15625 0.25 0 0.45703 0.027344 0.625 0.078125 0.17578 0.042969 0.35938 0.11719 0.54688 0.21875l0.046875-0.1875h0.6875zm-0.73438-0.70312v-2.375c-0.1875-0.082031-0.37109-0.14062-0.54688-0.17188-0.16797-0.039062-0.33594-0.0625-0.5-0.0625-0.39844 0-0.71484 0.13672-0.95312 0.40625-0.23047 0.27344-0.34375 0.66406-0.34375 1.1719 0 0.49219 0.082031 0.85938 0.25 1.1094 0.17578 0.25 0.46094 0.375 0.85938 0.375 0.21875 0 0.42969-0.035156 0.64062-0.10938 0.21875-0.082031 0.41406-0.19531 0.59375-0.34375z" />
  </symbol>
  <symbol id="glyph8-52" overflow="visible">
   <path d="m4.6719 0h-0.96875l-1.7344-1.9062-0.48438 0.45312v1.4531h-0.73438v-6.0625h0.73438v3.8906l2.125-2.1875h0.92188l-2.0312 2.0156z" />
  </symbol>
  <symbol id="glyph8-53" overflow="visible">
   <path d="m4.4844-5.125h-2.9375v1.6406h2.5312v0.6875h-2.5312v2.7969h-0.76562v-5.8125h3.7031z" />
  </symbol>
  <symbol id="glyph8-54" overflow="visible">
   <path d="m5.2188 0h-0.76562v-2.8438h-2.9062v2.8438h-0.76562v-5.8125h0.76562v2.2812h2.9062v-2.2812h0.76562z" />
  </symbol>
  <symbol id="glyph8-55" overflow="visible">
   <path d="m4.8906-5.8125-2.0469 3.2656v2.5469h-0.76562v-2.4688l-2.0625-3.3438h0.85938l1.5938 2.6094 1.5938-2.6094z" />
  </symbol>
  <symbol id="glyph8-56" overflow="visible">
   <path d="m5.2031 0h-0.95312l-2.75-5.1875v5.1875h-0.71875v-5.8125h1.2031l2.5 4.75v-4.75h0.71875z" />
  </symbol>
  <symbol id="glyph8-57" overflow="visible">
   <path d="m4.4844-4.3594-2.5312 5.9688h-0.79688l0.8125-1.8125-1.7344-4.1562h0.79688l1.3438 3.2344 1.3438-3.2344z" />
  </symbol>
  <symbol id="glyph8-58" overflow="visible">
   <path d="m4.5469-3.25c0 0.51172-0.058594 0.97656-0.17188 1.3906-0.11719 0.40625-0.28906 0.75781-0.51562 1.0469-0.24219 0.29297-0.54297 0.52344-0.90625 0.6875-0.35547 0.15234-0.77344 0.23438-1.25 0.23438-0.13672 0-0.26562-0.011719-0.39062-0.03125-0.11719-0.011719-0.21875-0.03125-0.3125-0.0625v-0.73438h0.046875c0.070313 0.042969 0.17578 0.078125 0.3125 0.10938 0.14453 0.03125 0.30078 0.046875 0.46875 0.046875 0.57031 0 1.0195-0.17188 1.3438-0.51562 0.33203-0.34375 0.52344-0.81641 0.57812-1.4219-0.25 0.14844-0.48438 0.25-0.70312 0.3125-0.21094 0.0625-0.4375 0.09375-0.6875 0.09375-0.24219 0-0.46094-0.019531-0.65625-0.0625-0.1875-0.050781-0.38281-0.14453-0.57812-0.28125-0.23047-0.15625-0.40234-0.35156-0.51562-0.59375-0.11719-0.25-0.17188-0.54688-0.17188-0.89062 0-0.59375 0.19141-1.0703 0.57812-1.4375 0.39453-0.375 0.875-0.5625 1.4375-0.5625 0.28125 0 0.53906 0.046875 0.78125 0.14062 0.23828 0.085938 0.44531 0.21094 0.625 0.375 0.21875 0.21875 0.38281 0.5 0.5 0.84375 0.125 0.33594 0.1875 0.77344 0.1875 1.3125zm-0.78125-0.17188c0-0.39453-0.042969-0.71094-0.125-0.95312-0.085937-0.25-0.19922-0.44141-0.34375-0.57812-0.125-0.125-0.26172-0.20703-0.40625-0.25-0.13672-0.050781-0.28906-0.078125-0.45312-0.078125-0.36719 0-0.65625 0.12109-0.875 0.35938-0.21875 0.23047-0.32812 0.55469-0.32812 0.96875 0 0.25 0.03125 0.45312 0.09375 0.60938 0.070313 0.15625 0.19141 0.29297 0.35938 0.40625 0.125 0.085938 0.25391 0.14062 0.39062 0.17188 0.13281 0.023437 0.28906 0.03125 0.46875 0.03125 0.19531 0 0.39844-0.023437 0.60938-0.078125 0.20703-0.050781 0.40625-0.12891 0.59375-0.23438v-0.17188c0.007812-0.050781 0.015625-0.11719 0.015625-0.20312z" />
  </symbol>
  <symbol id="glyph8-59" overflow="visible">
   <path d="m2.9062-1.5156c0 0.51172-0.15625 0.90625-0.46875 1.1875-0.30469 0.27344-0.71875 0.40625-1.25 0.40625-0.125 0-0.29297-0.011719-0.5-0.03125-0.21094-0.023438-0.38281-0.046875-0.51562-0.078125v-0.71875h0.046875c0.10156 0.03125 0.23438 0.070312 0.39062 0.10938 0.15625 0.042969 0.31641 0.0625 0.48438 0.0625 0.23828 0 0.42578-0.023437 0.5625-0.078125 0.14453-0.0625 0.25-0.14062 0.3125-0.23438 0.070312-0.10156 0.11719-0.22656 0.14062-0.375 0.019531-0.15625 0.03125-0.33203 0.03125-0.53125v-3.3906h-1.2344v-0.625h2z" />
  </symbol>
  <symbol id="glyph8-60" overflow="visible">
   <path d="m7.3594-2.5469c0 0.92969-0.32812 1.7188-0.98438 2.375-0.65625 0.65234-1.4492 0.98438-2.375 0.98438-0.9375 0-1.7344-0.33203-2.3906-0.98438-0.65625-0.65625-0.98438-1.4453-0.98438-2.375 0-0.9375 0.32812-1.7344 0.98438-2.3906s1.4531-0.98438 2.3906-0.98438c0.92578 0 1.7188 0.32812 2.375 0.98438s0.98438 1.4531 0.98438 2.3906zm-0.45312 0c0-0.8125-0.28906-1.5039-0.85938-2.0781-0.5625-0.58203-1.2461-0.875-2.0469-0.875-0.8125 0-1.5078 0.29297-2.0781 0.875-0.5625 0.57422-0.84375 1.2656-0.84375 2.0781 0 0.80469 0.28125 1.4961 0.84375 2.0781 0.57031 0.57031 1.2656 0.85938 2.0781 0.85938 0.80078 0 1.4844-0.28906 2.0469-0.85938 0.57031-0.58203 0.85938-1.2734 0.85938-2.0781zm-0.75 1.7031h-0.85938l-1.2969-1.375h-0.625v1.375h-0.64062v-3.5625h1.2188c0.23828 0 0.4375 0.011719 0.59375 0.03125 0.15625 0.023438 0.3125 0.074219 0.46875 0.15625 0.16406 0.085938 0.28516 0.1875 0.35938 0.3125 0.082031 0.125 0.125 0.28906 0.125 0.48438 0 0.25-0.078125 0.46094-0.23438 0.625-0.14844 0.16797-0.34375 0.30469-0.59375 0.40625zm-1.3594-2.5469c0-0.09375-0.023437-0.17578-0.0625-0.25-0.03125-0.070313-0.09375-0.12891-0.1875-0.17188-0.074219-0.039062-0.15625-0.066406-0.25-0.078125-0.09375-0.019531-0.21094-0.03125-0.34375-0.03125h-0.57812v1.2031h0.5c0.15625 0 0.28906-0.007812 0.40625-0.03125 0.11328-0.019531 0.21094-0.0625 0.29688-0.125 0.070313-0.0625 0.125-0.12891 0.15625-0.20312 0.039063-0.082031 0.0625-0.1875 0.0625-0.3125z" />
  </symbol>
  <symbol id="glyph8-61" overflow="visible">
   <path d="m5.9531 1.4219c-0.15625 0.039063-0.3125 0.066406-0.46875 0.078125-0.14844 0.019531-0.29688 0.03125-0.45312 0.03125-0.46094 0-0.82422-0.125-1.0938-0.375-0.27344-0.25-0.41797-0.60547-0.4375-1.0625-0.0625 0.007812-0.125 0.015625-0.1875 0.015625-0.0625 0.007813-0.12109 0.015625-0.17188 0.015625-0.40625 0-0.77734-0.070312-1.1094-0.20312-0.33594-0.13281-0.62109-0.33203-0.85938-0.59375-0.23047-0.25781-0.40625-0.57031-0.53125-0.9375-0.125-0.375-0.1875-0.80469-0.1875-1.2969 0-0.46875 0.0625-0.89062 0.1875-1.2656s0.30469-0.69531 0.54688-0.96875c0.22656-0.25 0.50781-0.44141 0.84375-0.57812 0.34375-0.13281 0.71094-0.20312 1.1094-0.20312 0.41406 0 0.78906 0.070313 1.125 0.20312 0.33203 0.13672 0.61328 0.32812 0.84375 0.57812 0.23828 0.26172 0.42188 0.57812 0.54688 0.95312s0.1875 0.80469 0.1875 1.2812c0 0.71094-0.14844 1.3086-0.4375 1.7969-0.29297 0.49219-0.68359 0.83594-1.1719 1.0312 0.007813 0.28906 0.078125 0.51562 0.20312 0.67188 0.13281 0.16406 0.375 0.25 0.71875 0.25 0.10156 0 0.22656-0.015625 0.375-0.046875 0.15625-0.03125 0.26562-0.058594 0.32812-0.078125h0.09375zm-0.92188-4.3281c0-0.75-0.17188-1.3281-0.51562-1.7344-0.33594-0.41406-0.79297-0.625-1.375-0.625-0.58594 0-1.0469 0.21094-1.3906 0.625-0.33594 0.40625-0.5 0.98438-0.5 1.7344 0 0.76172 0.17188 1.3438 0.51562 1.75s0.80078 0.60938 1.375 0.60938c0.58203 0 1.0391-0.20312 1.375-0.60938 0.34375-0.40625 0.51562-0.98828 0.51562-1.75z" />
  </symbol>
  <symbol id="glyph8-62" overflow="visible">
   <path d="m5.3594-5.8125-2.1094 5.8125h-1.0312l-2.125-5.8125h0.82812l1.8281 5.1094 1.8125-5.1094z" />
  </symbol>
  <symbol id="glyph8-63" overflow="visible">
   <path d="m4.25 1.6094h-0.73438v-2.0938c-0.21875 0.1875-0.44531 0.32812-0.67188 0.42188-0.21875 0.089844-0.46094 0.14062-0.71875 0.14062-0.52344 0-0.9375-0.19531-1.25-0.59375-0.30469-0.39453-0.45312-0.94141-0.45312-1.6406 0-0.375 0.050781-0.70703 0.15625-1 0.11328-0.28906 0.25781-0.53125 0.4375-0.71875 0.16406-0.1875 0.36328-0.33203 0.59375-0.4375 0.23828-0.10156 0.48438-0.15625 0.73438-0.15625 0.23828 0 0.44531 0.027344 0.625 0.078125 0.17578 0.054687 0.35938 0.125 0.54688 0.21875l0.046875-0.1875h0.6875zm-0.73438-2.7188v-2.4688c-0.19922-0.082031-0.375-0.14062-0.53125-0.17188-0.15625-0.039062-0.32812-0.0625-0.51562-0.0625-0.41797 0-0.74219 0.14844-0.96875 0.4375-0.21875 0.28125-0.32812 0.67188-0.32812 1.1719 0 0.51172 0.085937 0.90625 0.26562 1.1875 0.1875 0.27344 0.46875 0.40625 0.84375 0.40625 0.21875 0 0.42969-0.046875 0.64062-0.14062 0.21875-0.09375 0.41406-0.21094 0.59375-0.35938z" />
  </symbol>
  <symbol id="glyph8-64" overflow="visible">
   <path d="m5.1094-5.1406c0.23828 0.26172 0.42188 0.57812 0.54688 0.95312s0.1875 0.80469 0.1875 1.2812c0 0.48047-0.070312 0.91406-0.20312 1.2969-0.125 0.375-0.30469 0.6875-0.53125 0.9375-0.24219 0.26172-0.52734 0.46094-0.85938 0.59375-0.32422 0.13281-0.69531 0.20312-1.1094 0.20312-0.40625 0-0.77734-0.070312-1.1094-0.20312-0.33594-0.13281-0.62109-0.33203-0.85938-0.59375-0.23047-0.25781-0.40625-0.57031-0.53125-0.9375-0.125-0.375-0.1875-0.80469-0.1875-1.2969 0-0.46875 0.0625-0.89062 0.1875-1.2656s0.30469-0.69531 0.54688-0.96875c0.22656-0.25 0.50781-0.44141 0.84375-0.57812 0.34375-0.13281 0.71094-0.20312 1.1094-0.20312 0.41406 0 0.78906 0.070313 1.125 0.20312 0.33203 0.13672 0.61328 0.32812 0.84375 0.57812zm-0.078125 2.2344c0-0.75-0.17188-1.3281-0.51562-1.7344-0.33594-0.41406-0.79297-0.625-1.375-0.625-0.58594 0-1.0469 0.21094-1.3906 0.625-0.33594 0.40625-0.5 0.98438-0.5 1.7344 0 0.76172 0.17188 1.3438 0.51562 1.75s0.80078 0.60938 1.375 0.60938c0.58203 0 1.0391-0.20312 1.375-0.60938 0.34375-0.40625 0.51562-0.98828 0.51562-1.75z" />
  </symbol>
  <symbol id="glyph8-65" overflow="visible">
   <path d="m2.2812-3.25h-0.9375v-1.1094h0.9375zm0 3.25h-0.9375v-1.1094h0.9375z" />
  </symbol>
  <symbol id="glyph8-66" overflow="visible">
   <path d="m4.6406-1.8906c0 0.59375-0.19531 1.0781-0.57812 1.4531-0.38672 0.375-0.86719 0.5625-1.4375 0.5625-0.28125 0-0.54297-0.042969-0.78125-0.125-0.23047-0.09375-0.43359-0.22656-0.60938-0.40625-0.23047-0.21875-0.40625-0.50391-0.53125-0.85938-0.11719-0.35156-0.17188-0.78125-0.17188-1.2812 0-0.51953 0.050781-0.97656 0.15625-1.375 0.11328-0.39453 0.29688-0.75 0.54688-1.0625 0.22656-0.28906 0.51953-0.51953 0.875-0.6875 0.36328-0.16406 0.78516-0.25 1.2656-0.25 0.15625 0 0.28516 0.011719 0.39062 0.03125 0.10156 0.011719 0.20703 0.03125 0.3125 0.0625v0.75h-0.046875c-0.0625-0.039063-0.17188-0.078125-0.32812-0.10938-0.14844-0.039062-0.29297-0.0625-0.4375-0.0625-0.5625 0-1.0117 0.17969-1.3438 0.53125-0.33594 0.35547-0.52734 0.82812-0.57812 1.4219 0.21875-0.13281 0.42969-0.23438 0.64062-0.29688 0.20703-0.070312 0.45312-0.10938 0.73438-0.10938 0.25 0 0.46875 0.023437 0.65625 0.0625 0.1875 0.042969 0.37891 0.13672 0.57812 0.28125 0.22656 0.15625 0.39844 0.35547 0.51562 0.59375 0.11328 0.24219 0.17188 0.53125 0.17188 0.875zm-0.78125 0.03125c0-0.23828-0.039063-0.4375-0.10938-0.59375-0.074219-0.15625-0.19531-0.28906-0.35938-0.40625-0.11719-0.082031-0.24609-0.13281-0.39062-0.15625-0.14844-0.03125-0.30469-0.046875-0.46875-0.046875-0.21875 0-0.42188 0.027344-0.60938 0.078125-0.1875 0.054687-0.38281 0.13281-0.57812 0.23438-0.011719 0.0625-0.015625 0.12109-0.015625 0.17188v0.20312c0 0.40625 0.039063 0.73047 0.125 0.96875 0.082031 0.24219 0.19531 0.42969 0.34375 0.5625 0.125 0.11719 0.25391 0.19922 0.39062 0.25 0.13281 0.054688 0.28516 0.078125 0.45312 0.078125 0.375 0 0.67188-0.11328 0.89062-0.34375 0.21875-0.22656 0.32812-0.5625 0.32812-1z" />
  </symbol>
  <symbol id="glyph8-67" overflow="visible">
   <path d="m2.2188-6.0625-1.0625 2.1719h-0.53125l0.64062-2.1719z" />
  </symbol>
  <symbol id="glyph8-68" overflow="visible">
   <path d="m4.5781-4.9375-2.625 4.9375h-0.84375l2.7969-5.125h-3.3125v-0.6875h3.9844z" />
  </symbol>
  <symbol id="glyph8-69" overflow="visible">
   <path d="m2.9531 1.5312h-2.0156v-7.5938h2.0156v0.54688h-1.3438v6.4844h1.3438z" />
  </symbol>
  <symbol id="glyph8-70" overflow="visible">
   <path d="m2.6875 1.5312h-2.0156v-0.5625h1.3438v-6.4844h-1.3438v-0.54688h2.0156z" />
  </symbol>
  <symbol id="glyph8-71" overflow="visible">
   <path d="m6.2031-4.3594-1.1406 4.3594h-0.67188l-1.125-3.3594-1.1094 3.3594h-0.67188l-1.1562-4.3594h0.76562l0.8125 3.375 1.0781-3.375h0.60938l1.1094 3.375 0.76562-3.375z" />
  </symbol>
  <symbol id="glyph8-72" overflow="visible">
   <path d="m7.5312-5.8125-1.5 5.8125h-0.875l-1.2188-4.8125-1.1875 4.8125h-0.85938l-1.5312-5.8125h0.79688l1.2188 4.8281 1.2031-4.8281h0.78125l1.2031 4.875 1.2188-4.875z" />
  </symbol>
  <clipPath id="clip1">
   <path d="m389.28 45.059h149.72v98.883h-149.72z" />
  </clipPath>
  <image id="image7390" width="625" height="413" xlink:href="data:image/jpeg;base64,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" />
  <clipPath id="clip2">
   <path d="m72.781 222h461.22v2h-461.22z" />
  </clipPath>
 </defs>
 <g>
  <g fill="#f00">
   <use x="515.4" y="664.74" xlink:href="#glyph0-1" />
   <use x="523.596" y="664.74" xlink:href="#glyph0-1" />
   <use x="531.792" y="664.74" xlink:href="#glyph0-1" />
  </g>
  <g fill="#0071c5">
   <use x="421.14" y="711.78" xlink:href="#glyph1-1" />
   <use x="433.254" y="711.78" xlink:href="#glyph1-2" />
   <use x="443.9388" y="711.78" xlink:href="#glyph1-3" />
   <use x="454.6218" y="711.78" xlink:href="#glyph1-4" />
   <use x="459.4746" y="711.78" xlink:href="#glyph1-5" />
   <use x="468.894" y="711.78" xlink:href="#glyph1-4" />
   <use x="473.7468" y="711.78" xlink:href="#glyph1-6" />
   <use x="484.6674" y="711.78" xlink:href="#glyph1-7" />
   <use x="496.0704" y="711.78" xlink:href="#glyph1-8" />
   <use x="504.228" y="711.78" xlink:href="#glyph1-9" />
   <use x="510.5964" y="711.78" xlink:href="#glyph1-10" />
   <use x="522.0012" y="711.78" xlink:href="#glyph1-11" />
   <use x="528.546" y="711.78" xlink:href="#glyph1-12" />
   <use x="446.2194" y="733.74" xlink:href="#glyph1-13" />
   <use x="454.4058" y="733.74" xlink:href="#glyph1-14" />
   <use x="465.7962" y="733.74" xlink:href="#glyph1-7" />
   <use x="477.1866" y="733.74" xlink:href="#glyph1-2" />
   <use x="487.911" y="733.74" xlink:href="#glyph1-9" />
   <use x="494.2182" y="733.74" xlink:href="#glyph1-10" />
   <use x="505.6626" y="733.74" xlink:href="#glyph1-15" />
   <use x="517.107" y="733.74" xlink:href="#glyph1-16" />
   <use x="528.5514" y="733.74" xlink:href="#glyph1-17" />
  </g>
  <path d="m389.28 143.94h149.94v-98.883h-149.94z" fill="#fff" />
 </g>
 <g clip-path="url(#clip1)">
  <use transform="matrix(.24007 0 0 .23942 389.28 45.06)" xlink:href="#image7390" />
 </g>
 <g fill="#0071c5">
  <use x="72.78" y="177.84" xlink:href="#glyph2-1" />
  <use x="84.796512" y="177.84" xlink:href="#glyph2-2" />
  <use x="100.458384" y="177.84" xlink:href="#glyph2-3" />
  <use x="110.498496" y="177.84" xlink:href="#glyph2-4" />
  <use x="125.106288" y="177.84" xlink:href="#glyph2-5" />
  <use x="132.6" y="169.08" xlink:href="#glyph3-1" />
  <use x="149.58" y="177.84" xlink:href="#glyph2-6" />
  <use x="157.103496" y="177.84" xlink:href="#glyph2-7" />
  <use x="172.732428" y="177.84" xlink:href="#glyph2-8" />
  <use x="188.36136" y="177.84" xlink:href="#glyph2-9" />
  <use x="203.990292" y="177.84" xlink:href="#glyph2-10" />
  <use x="219.619224" y="177.84" xlink:href="#glyph2-11" />
  <use x="235.248156" y="177.84" xlink:href="#glyph2-12" />
  <use x="250.262208" y="177.84" xlink:href="#glyph2-13" />
  <use x="267.0111" y="177.84" xlink:href="#glyph2-6" />
  <use x="274.534596" y="177.84" xlink:href="#glyph2-14" />
  <use x="292.359528" y="177.84" xlink:href="#glyph2-15" />
  <use x="299.88522" y="177.84" xlink:href="#glyph2-16" />
  <use x="315.250632" y="177.84" xlink:href="#glyph2-17" />
  <use x="329.935284" y="177.84" xlink:href="#glyph2-18" />
  <use x="345.300696" y="177.84" xlink:href="#glyph2-15" />
  <use x="352.826388" y="177.84" xlink:href="#glyph2-3" />
  <use x="362.85552" y="177.84" xlink:href="#glyph2-6" />
  <use x="370.379016" y="177.84" xlink:href="#glyph2-12" />
  <use x="385.393068" y="177.84" xlink:href="#glyph2-3" />
  <use x="395.4222" y="177.84" xlink:href="#glyph2-19" />
  <use x="411.073092" y="177.84" xlink:href="#glyph2-4" />
  <use x="425.669904" y="177.84" xlink:href="#glyph2-20" />
  <use x="436.599396" y="177.84" xlink:href="#glyph2-2" />
  <use x="452.250288" y="177.84" xlink:href="#glyph2-4" />
  <use x="466.8471" y="177.84" xlink:href="#glyph2-3" />
  <use x="476.876232" y="177.84" xlink:href="#glyph2-6" />
  <use x="72.779292" y="201.840084" xlink:href="#glyph2-21" />
  <use x="88.6959" y="201.840084" xlink:href="#glyph2-22" />
  <use x="103.799988" y="201.840084" xlink:href="#glyph2-2" />
  <use x="119.453076" y="201.840084" xlink:href="#glyph2-3" />
  <use x="129.484404" y="201.840084" xlink:href="#glyph2-20" />
  <use x="140.416092" y="201.840084" xlink:href="#glyph2-22" />
  <use x="155.52018" y="201.840084" xlink:href="#glyph2-5" />
  <use x="163.048068" y="201.840084" xlink:href="#glyph2-5" />
  <use x="170.575956" y="201.840084" xlink:href="#glyph2-4" />
  <use x="185.174964" y="201.840084" xlink:href="#glyph2-20" />
  <use x="196.106652" y="201.840084" xlink:href="#glyph2-6" />
  <use x="203.671872" y="201.840084" xlink:href="#glyph2-23" />
  <use x="221.91624" y="201.840084" xlink:href="#glyph2-17" />
  <use x="236.603088" y="201.840084" xlink:href="#glyph2-3" />
  <use x="246.634416" y="201.840084" xlink:href="#glyph2-17" />
  <use x="261.321264" y="201.840084" xlink:href="#glyph2-24" />
  <use x="274.361112" y="201.840084" xlink:href="#glyph2-19" />
  <use x="290.0142" y="201.840084" xlink:href="#glyph2-4" />
  <use x="304.613208" y="201.840084" xlink:href="#glyph2-4" />
  <use x="319.212216" y="201.840084" xlink:href="#glyph2-3" />
 </g>
 <g clip-path="url(#clip2)">
  <path d="m72.781 223.74h460.5v-1.0195h-460.5z" />
 </g>
 <g>
  <g fill="#0071c5">
   <use x="72.78" y="237.18" xlink:href="#glyph4-1" />
   <use x="82.9236" y="237.18" xlink:href="#glyph4-2" />
   <use x="90.9024" y="237.18" xlink:href="#glyph4-3" />
   <use x="96.39" y="237.18" xlink:href="#glyph4-4" />
   <use x="108.1536" y="237.18" xlink:href="#glyph4-5" />
   <use x="116.4132" y="237.18" xlink:href="#glyph4-6" />
   <use x="122.352" y="237.18" xlink:href="#glyph4-7" />
   <use x="130.4196" y="237.18" xlink:href="#glyph4-8" />
   <use x="134.502" y="237.18" xlink:href="#glyph4-9" />
   <use x="143.0616" y="237.18" xlink:href="#glyph4-10" />
   <use x="151.3992" y="237.18" xlink:href="#glyph4-11" />
   <use x="155.5116" y="237.18" xlink:href="#glyph4-12" />
   <use x="165.4872" y="237.18" xlink:href="#glyph4-8" />
   <use x="169.5696" y="237.18" xlink:href="#glyph4-13" />
   <use x="177.3852" y="237.18" xlink:href="#glyph4-8" />
   <use x="181.4676" y="237.18" xlink:href="#glyph4-14" />
   <use x="188.5992" y="237.18" xlink:href="#glyph4-8" />
   <use x="192.6816" y="237.18" xlink:href="#glyph4-5" />
   <use x="200.9412" y="237.18" xlink:href="#glyph4-9" />
   <use x="209.4564" y="237.18" xlink:href="#glyph4-11" />
   <use x="213.5688" y="237.18" xlink:href="#glyph4-15" />
   <use x="220.1004" y="237.18" xlink:href="#glyph4-1" />
   <use x="230.244" y="237.18" xlink:href="#glyph4-12" />
   <use x="240.2196" y="237.18" xlink:href="#glyph4-16" />
   <use x="76.26" y="267.84" xlink:href="#glyph5-1" />
   <use x="83.581596" y="267.84" xlink:href="#glyph5-2" />
   <use x="91.391232" y="267.84" xlink:href="#glyph5-3" />
   <use x="99.878148" y="267.84" xlink:href="#glyph5-4" />
   <use x="108.165864" y="267.84" xlink:href="#glyph5-5" />
   <use x="116.2743" y="267.84" xlink:href="#glyph5-6" />
   <use x="123.506256" y="267.84" xlink:href="#glyph5-7" />
   <use x="130.319892" y="267.84" xlink:href="#glyph5-8" />
   <use x="133.742148" y="267.84" xlink:href="#glyph5-9" />
   <use x="140.237064" y="267.84" xlink:href="#glyph5-10" />
   <use x="147.06066" y="267.84" xlink:href="#glyph5-11" />
   <use x="154.857348" y="267.84" xlink:href="#glyph5-7" />
   <use x="161.641104" y="267.84" xlink:href="#glyph5-5" />
   <use x="169.801332" y="267.84" xlink:href="#glyph5-2" />
   <use x="177.599016" y="267.84" xlink:href="#glyph5-10" />
   <use x="184.422612" y="267.84" xlink:href="#glyph5-12" />
   <use x="76.26" y="297.54" xlink:href="#glyph6-1" />
   <use x="81.727896" y="297.54" xlink:href="#glyph6-2" />
   <use x="87.084072" y="297.54" xlink:href="#glyph6-3" />
   <use x="90.740508" y="297.54" xlink:href="#glyph6-4" />
   <use x="96.020076" y="297.54" xlink:href="#glyph6-5" />
   <use x="100.003692" y="297.54" xlink:href="#glyph6-6" />
   <use x="105.703008" y="297.54" xlink:href="#glyph6-7" />
   <use x="111.051204" y="297.54" xlink:href="#glyph6-8" />
   <use x="113.79792" y="297.54" xlink:href="#glyph6-9" />
   <use x="116.49915" y="297.54" xlink:href="#glyph6-10" />
   <use x="120.873786" y="297.54" xlink:href="#glyph6-6" />
   <use x="126.573102" y="297.54" xlink:href="#glyph6-3" />
   <use x="130.229538" y="297.54" xlink:href="#glyph6-4" />
   <use x="135.509106" y="297.54" xlink:href="#glyph6-5" />
   <use x="139.492722" y="297.54" xlink:href="#glyph6-11" />
   <use x="142.877838" y="297.54" xlink:href="#glyph6-7" />
   <use x="148.226034" y="297.54" xlink:href="#glyph6-12" />
   <use x="152.93583" y="297.54" xlink:href="#glyph6-4" />
   <use x="158.252106" y="297.54" xlink:href="#glyph6-13" />
   <use x="76.26" y="307.56" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="88.26" y="307.56" xlink:href="#glyph8-1" />
   <use x="93.059172" y="307.56" xlink:href="#glyph8-2" />
   <use x="98.616444" y="307.56" xlink:href="#glyph8-3" />
   <use x="101.963256" y="307.56" xlink:href="#glyph8-4" />
   <use x="106.76562" y="307.56" xlink:href="#glyph8-5" />
   <use x="111.828132" y="307.56" xlink:href="#glyph8-6" />
   <use x="114.651456" y="307.56" xlink:href="#glyph8-7" />
   <use x="119.393172" y="307.56" xlink:href="#glyph8-8" />
   <use x="124.495584" y="307.56" xlink:href="#glyph8-9" />
   <use x="127.387536" y="307.56" xlink:href="#glyph8-10" />
   <use x="132.489948" y="307.56" xlink:href="#glyph8-6" />
   <use x="135.313272" y="307.56" xlink:href="#glyph8-11" />
   <use x="138.972102" y="307.56" xlink:href="#glyph8-8" />
   <use x="144.013866" y="307.56" xlink:href="#glyph8-9" />
   <use x="146.956092" y="307.56" xlink:href="#glyph8-12" />
   <use x="152.058504" y="307.56" xlink:href="#glyph8-6" />
   <use x="154.821978" y="307.56" xlink:href="#glyph8-13" />
   <use x="161.059146" y="307.56" xlink:href="#glyph8-14" />
   <use x="165.97722" y="307.56" xlink:href="#glyph8-15" />
   <use x="169.587372" y="307.56" xlink:href="#glyph8-16" />
   <use x="173.787246" y="307.56" xlink:href="#glyph8-17" />
   <use x="177.397398" y="307.56" xlink:href="#glyph8-6" />
   <use x="180.220722" y="307.56" xlink:href="#glyph8-18" />
   <use x="184.962438" y="307.56" xlink:href="#glyph8-19" />
   <use x="190.06485" y="307.56" xlink:href="#glyph8-15" />
   <use x="193.675002" y="307.56" xlink:href="#glyph8-18" />
   <use x="198.416718" y="307.56" xlink:href="#glyph8-8" />
   <use x="203.51913" y="307.56" xlink:href="#glyph8-15" />
   <use x="207.11811" y="307.56" xlink:href="#glyph8-18" />
   <use x="211.859826" y="307.56" xlink:href="#glyph8-20" />
   <use x="216.962238" y="307.56" xlink:href="#glyph8-21" />
   <use x="220.621068" y="307.56" xlink:href="#glyph8-6" />
   <use x="223.444392" y="307.56" xlink:href="#glyph8-22" />
   <use x="227.589204" y="307.56" xlink:href="#glyph8-23" />
   <use x="232.372416" y="307.56" xlink:href="#glyph8-24" />
   <use x="234.546168" y="307.56" xlink:href="#glyph8-24" />
   <use x="236.763012" y="307.56" xlink:href="#glyph8-4" />
   <use x="241.506324" y="307.56" xlink:href="#glyph8-25" />
   <use x="246.465096" y="307.56" xlink:href="#glyph8-6" />
   <use x="249.28842" y="307.56" xlink:href="#glyph8-1" />
   <use x="254.087592" y="307.56" xlink:href="#glyph8-2" />
   <use x="259.644864" y="307.56" xlink:href="#glyph8-3" />
   <use x="262.991676" y="307.56" xlink:href="#glyph8-4" />
   <use x="267.79404" y="307.56" xlink:href="#glyph8-6" />
   <use x="270.617364" y="307.56" xlink:href="#glyph8-26" />
   <use x="272.791116" y="307.56" xlink:href="#glyph8-27" />
   <use x="277.829688" y="307.56" xlink:href="#glyph8-6" />
   <use x="280.653012" y="307.56" xlink:href="#glyph8-28" />
   <use x="283.833042" y="307.56" xlink:href="#glyph8-29" />
   <use x="288.874806" y="307.56" xlink:href="#glyph8-26" />
   <use x="291.048558" y="307.56" xlink:href="#glyph8-16" />
   <use x="295.248432" y="307.56" xlink:href="#glyph8-6" />
   <use x="88.26" y="315.54" xlink:href="#glyph8-25" />
   <use x="93.23553" y="315.54" xlink:href="#glyph8-30" />
   <use x="98.08338" y="315.54" xlink:href="#glyph8-22" />
   <use x="102.24495" y="315.54" xlink:href="#glyph8-31" />
   <use x="107.30028" y="315.54" xlink:href="#glyph8-32" />
   <use x="115.06881" y="315.54" xlink:href="#glyph8-4" />
   <use x="119.82888" y="315.54" xlink:href="#glyph8-27" />
   <use x="124.930494" y="315.54" xlink:href="#glyph8-28" />
  </g>
  <g fill="#0071c5">
   <use x="76.26" y="323.52" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="88.26" y="323.52" xlink:href="#glyph8-33" />
   <use x="94.994322" y="323.52" xlink:href="#glyph8-34" />
   <use x="101.154084" y="323.52" xlink:href="#glyph8-3" />
   <use x="104.520846" y="323.52" xlink:href="#glyph8-6" />
   <use x="107.34417" y="323.52" xlink:href="#glyph8-11" />
   <use x="110.974272" y="323.52" xlink:href="#glyph8-2" />
   <use x="116.551494" y="323.52" xlink:href="#glyph8-30" />
   <use x="121.402536" y="323.52" xlink:href="#glyph8-35" />
   <use x="126.381258" y="323.52" xlink:href="#glyph8-35" />
   <use x="131.35998" y="323.52" xlink:href="#glyph8-4" />
   <use x="136.123242" y="323.52" xlink:href="#glyph8-36" />
   <use x="139.537884" y="323.52" xlink:href="#glyph8-17" />
   <use x="143.167986" y="323.52" xlink:href="#glyph8-6" />
   <use x="145.99131" y="323.52" xlink:href="#glyph8-16" />
   <use x="150.156072" y="323.52" xlink:href="#glyph8-28" />
   <use x="153.307374" y="323.52" xlink:href="#glyph8-23" />
   <use x="158.110536" y="323.52" xlink:href="#glyph8-27" />
   <use x="163.169058" y="323.52" xlink:href="#glyph8-25" />
   <use x="168.14778" y="323.52" xlink:href="#glyph8-23" />
   <use x="172.950942" y="323.52" xlink:href="#glyph8-36" />
   <use x="176.365584" y="323.52" xlink:href="#glyph8-25" />
   <use x="181.344306" y="323.52" xlink:href="#glyph8-6" />
   <use x="184.16763" y="323.52" xlink:href="#glyph8-3" />
   <use x="187.534392" y="323.52" xlink:href="#glyph8-37" />
   <use x="192.584934" y="323.52" xlink:href="#glyph8-37" />
   <use x="197.635476" y="323.52" xlink:href="#glyph8-37" />
   <use x="202.686018" y="323.52" xlink:href="#glyph8-6" />
   <use x="205.499766" y="323.52" xlink:href="#glyph8-38" />
   <use x="210.606966" y="323.52" xlink:href="#glyph8-10" />
   <use x="215.64873" y="323.52" xlink:href="#glyph8-8" />
   <use x="220.75593" y="323.52" xlink:href="#glyph8-9" />
   <use x="223.69257" y="323.52" xlink:href="#glyph8-39" />
   <use x="228.79977" y="323.52" xlink:href="#glyph8-6" />
   <use x="231.563244" y="323.52" xlink:href="#glyph8-37" />
   <use x="236.638524" y="323.52" xlink:href="#glyph8-28" />
   <use x="239.757906" y="323.52" xlink:href="#glyph8-29" />
   <use x="244.841166" y="323.52" xlink:href="#glyph8-4" />
   <use x="249.58368" y="323.52" xlink:href="#glyph8-36" />
   <use x="253.02306" y="323.52" xlink:href="#glyph8-27" />
   <use x="258.10632" y="323.52" xlink:href="#glyph8-4" />
   <use x="262.89432" y="323.52" xlink:href="#glyph8-28" />
   <use x="266.013702" y="323.52" xlink:href="#glyph8-6" />
   <use x="268.837026" y="323.52" xlink:href="#glyph8-26" />
   <use x="270.99402" y="323.52" xlink:href="#glyph8-27" />
   <use x="276.095634" y="323.52" xlink:href="#glyph8-28" />
   <use x="279.215016" y="323.52" xlink:href="#glyph8-4" />
   <use x="284.01738" y="323.52" xlink:href="#glyph8-36" />
   <use x="287.379354" y="323.52" xlink:href="#glyph8-40" />
   <use x="290.202678" y="323.52" xlink:href="#glyph8-23" />
   <use x="295.030578" y="323.52" xlink:href="#glyph8-22" />
   <use x="299.220078" y="323.52" xlink:href="#glyph8-4" />
   <use x="303.962592" y="323.52" xlink:href="#glyph8-6" />
   <use x="88.26" y="331.55985" xlink:href="#glyph8-40" />
   <use x="91.089708" y="331.55985" xlink:href="#glyph8-30" />
   <use x="95.890476" y="331.55985" xlink:href="#glyph8-36" />
   <use x="99.318684" y="331.55985" xlink:href="#glyph8-6" />
   <use x="102.142008" y="331.55985" xlink:href="#glyph8-20" />
   <use x="107.238036" y="331.55985" xlink:href="#glyph8-10" />
   <use x="112.334064" y="331.55985" xlink:href="#glyph8-10" />
   <use x="117.430092" y="331.55985" xlink:href="#glyph8-10" />
   <use x="122.471856" y="331.55985" xlink:href="#glyph8-41" />
   <use x="127.966884" y="331.55985" xlink:href="#glyph8-42" />
   <use x="133.370142" y="331.55985" xlink:href="#glyph8-43" />
   <use x="138.84921" y="331.55985" xlink:href="#glyph8-37" />
   <use x="143.913318" y="331.55985" xlink:href="#glyph8-44" />
   <use x="146.912202" y="331.55985" xlink:href="#glyph8-14" />
   <use x="150.750582" y="331.55985" xlink:href="#glyph8-45" />
   <use x="153.63216" y="331.55985" xlink:href="#glyph8-6" />
   <use x="156.455484" y="331.55985" xlink:href="#glyph8-20" />
   <use x="161.551512" y="331.55985" xlink:href="#glyph8-10" />
   <use x="166.593276" y="331.55985" xlink:href="#glyph8-10" />
   <use x="171.689304" y="331.55985" xlink:href="#glyph8-41" />
   <use x="177.184332" y="331.55985" xlink:href="#glyph8-42" />
   <use x="182.58759" y="331.55985" xlink:href="#glyph8-43" />
   <use x="188.050698" y="331.55985" xlink:href="#glyph8-37" />
   <use x="193.114806" y="331.55985" xlink:href="#glyph8-44" />
   <use x="196.174338" y="331.55985" xlink:href="#glyph8-14" />
   <use x="201.110766" y="331.55985" xlink:href="#glyph8-46" />
   <use x="206.597814" y="331.55985" xlink:href="#glyph8-45" />
   <use x="209.479392" y="331.55985" xlink:href="#glyph8-6" />
   <use x="212.302716" y="331.55985" xlink:href="#glyph8-23" />
   <use x="217.119444" y="331.55985" xlink:href="#glyph8-27" />
   <use x="222.191532" y="331.55985" xlink:href="#glyph8-25" />
   <use x="227.18382" y="331.55985" xlink:href="#glyph8-6" />
   <use x="229.947294" y="331.55985" xlink:href="#glyph8-20" />
   <use x="235.043322" y="331.55985" xlink:href="#glyph8-10" />
   <use x="240.13935" y="331.55985" xlink:href="#glyph8-41" />
   <use x="245.634378" y="331.55985" xlink:href="#glyph8-42" />
   <use x="251.113446" y="331.55985" xlink:href="#glyph8-43" />
   <use x="256.592514" y="331.55985" xlink:href="#glyph8-37" />
   <use x="261.656622" y="331.55985" xlink:href="#glyph8-44" />
   <use x="264.716154" y="331.55985" xlink:href="#glyph8-14" />
   <use x="269.634228" y="331.55985" xlink:href="#glyph8-6" />
   <use x="88.26" y="339.53985" xlink:href="#glyph8-23" />
   <use x="93.077526" y="339.53985" xlink:href="#glyph8-35" />
   <use x="98.070612" y="339.53985" xlink:href="#glyph8-35" />
   <use x="103.063698" y="339.53985" xlink:href="#glyph8-24" />
   <use x="105.220692" y="339.53985" xlink:href="#glyph8-26" />
   <use x="107.377686" y="339.53985" xlink:href="#glyph8-22" />
   <use x="111.57756" y="339.53985" xlink:href="#glyph8-23" />
   <use x="116.395086" y="339.53985" xlink:href="#glyph8-28" />
   <use x="119.514468" y="339.53985" xlink:href="#glyph8-26" />
   <use x="121.722534" y="339.53985" xlink:href="#glyph8-30" />
   <use x="126.523302" y="339.53985" xlink:href="#glyph8-27" />
   <use x="131.596188" y="339.53985" xlink:href="#glyph8-16" />
   <use x="135.736212" y="339.53985" xlink:href="#glyph8-6" />
   <use x="138.559536" y="339.53985" xlink:href="#glyph8-11" />
   <use x="142.204002" y="339.53985" xlink:href="#glyph8-38" />
   <use x="147.245766" y="339.53985" xlink:href="#glyph8-10" />
   <use x="152.342592" y="339.53985" xlink:href="#glyph8-8" />
   <use x="157.439418" y="339.53985" xlink:href="#glyph8-9" />
   <use x="160.320996" y="339.53985" xlink:href="#glyph8-39" />
   <use x="165.417822" y="339.53985" xlink:href="#glyph8-45" />
   <use x="168.344088" y="339.53985" xlink:href="#glyph8-6" />
   <use x="171.167412" y="339.53985" xlink:href="#glyph8-38" />
   <use x="176.209176" y="339.53985" xlink:href="#glyph8-10" />
   <use x="181.306002" y="339.53985" xlink:href="#glyph8-8" />
   <use x="186.402828" y="339.53985" xlink:href="#glyph8-9" />
   <use x="189.284406" y="339.53985" xlink:href="#glyph8-39" />
   <use x="194.381232" y="339.53985" xlink:href="#glyph8-31" />
   <use x="199.454118" y="339.53985" xlink:href="#glyph8-45" />
   <use x="202.380384" y="339.53985" xlink:href="#glyph8-6" />
   <use x="205.203708" y="339.53985" xlink:href="#glyph8-23" />
   <use x="210.021234" y="339.53985" xlink:href="#glyph8-27" />
   <use x="215.09412" y="339.53985" xlink:href="#glyph8-25" />
   <use x="220.087206" y="339.53985" xlink:href="#glyph8-6" />
   <use x="222.91053" y="339.53985" xlink:href="#glyph8-38" />
   <use x="228.007356" y="339.53985" xlink:href="#glyph8-10" />
   <use x="233.104182" y="339.53985" xlink:href="#glyph8-8" />
   <use x="238.201008" y="339.53985" xlink:href="#glyph8-9" />
   <use x="241.082586" y="339.53985" xlink:href="#glyph8-39" />
   <use x="246.179412" y="339.53985" xlink:href="#glyph8-23" />
   <use x="250.996938" y="339.53985" xlink:href="#glyph8-47" />
   <use x="255.990024" y="339.53985" xlink:href="#glyph8-17" />
  </g>
  <g fill="#0071c5">
   <use x="76.26" y="347.52" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="88.26" y="347.52" xlink:href="#glyph8-43" />
   <use x="93.705552" y="347.52" xlink:href="#glyph8-4" />
   <use x="98.448864" y="347.52" xlink:href="#glyph8-36" />
   <use x="101.870688" y="347.52" xlink:href="#glyph8-26" />
   <use x="104.027682" y="347.52" xlink:href="#glyph8-23" />
   <use x="108.810894" y="347.52" xlink:href="#glyph8-24" />
   <use x="111.027738" y="347.52" xlink:href="#glyph8-26" />
   <use x="113.20149" y="347.52" xlink:href="#glyph8-48" />
   <use x="117.378222" y="347.52" xlink:href="#glyph8-4" />
   <use x="122.180586" y="347.52" xlink:href="#glyph8-36" />
   <use x="125.48271" y="347.52" xlink:href="#glyph8-44" />
   <use x="129.14154" y="347.52" xlink:href="#glyph8-34" />
   <use x="135.265392" y="347.52" xlink:href="#glyph8-4" />
   <use x="140.067756" y="347.52" xlink:href="#glyph8-16" />
   <use x="144.20778" y="347.52" xlink:href="#glyph8-4" />
   <use x="149.010144" y="347.52" xlink:href="#glyph8-36" />
   <use x="152.431968" y="347.52" xlink:href="#glyph8-26" />
   <use x="154.60572" y="347.52" xlink:href="#glyph8-23" />
   <use x="159.388932" y="347.52" xlink:href="#glyph8-24" />
   <use x="161.562684" y="347.52" xlink:href="#glyph8-26" />
   <use x="163.736436" y="347.52" xlink:href="#glyph8-48" />
   <use x="167.913168" y="347.52" xlink:href="#glyph8-4" />
   <use x="172.65648" y="347.52" xlink:href="#glyph8-36" />
   <use x="176.078304" y="347.52" xlink:href="#glyph8-6" />
   <use x="178.901628" y="347.52" xlink:href="#glyph8-11" />
   <use x="182.51178" y="347.52" xlink:href="#glyph8-43" />
   <use x="187.957332" y="347.52" xlink:href="#glyph8-37" />
   <use x="193.054956" y="347.52" xlink:href="#glyph8-49" />
   <use x="198.540408" y="347.52" xlink:href="#glyph8-34" />
   <use x="204.708948" y="347.52" xlink:href="#glyph8-37" />
   <use x="209.768268" y="347.52" xlink:href="#glyph8-43" />
   <use x="215.242548" y="347.52" xlink:href="#glyph8-17" />
   <use x="218.881428" y="347.52" xlink:href="#glyph8-6" />
   <use x="221.704752" y="347.52" xlink:href="#glyph8-28" />
   <use x="224.864832" y="347.52" xlink:href="#glyph8-30" />
   <use x="229.724652" y="347.52" xlink:href="#glyph8-6" />
   <use x="232.547976" y="347.52" xlink:href="#glyph8-16" />
   <use x="236.721516" y="347.52" xlink:href="#glyph8-31" />
   <use x="241.788816" y="347.52" xlink:href="#glyph8-35" />
   <use x="246.776316" y="347.52" xlink:href="#glyph8-35" />
   <use x="251.763816" y="347.52" xlink:href="#glyph8-30" />
   <use x="256.623636" y="347.52" xlink:href="#glyph8-36" />
   <use x="260.047056" y="347.52" xlink:href="#glyph8-28" />
   <use x="263.207136" y="347.52" xlink:href="#glyph8-6" />
   <use x="266.03046" y="347.52" xlink:href="#glyph8-20" />
   <use x="271.1217" y="347.52" xlink:href="#glyph8-10" />
   <use x="276.21294" y="347.52" xlink:href="#glyph8-10" />
   <use x="281.254704" y="347.52" xlink:href="#glyph8-10" />
   <use x="286.345944" y="347.52" xlink:href="#glyph8-41" />
   <use x="291.836184" y="347.52" xlink:href="#glyph8-23" />
   <use x="296.648124" y="347.52" xlink:href="#glyph8-16" />
   <use x="300.821664" y="347.52" xlink:href="#glyph8-4" />
   <use x="305.593704" y="347.52" xlink:href="#glyph8-44" />
   <use x="88.26" y="355.55985" xlink:href="#glyph8-43" />
   <use x="93.721512" y="355.55985" xlink:href="#glyph8-46" />
   <use x="99.191004" y="355.55985" xlink:href="#glyph8-15" />
   <use x="102.817116" y="355.55985" xlink:href="#glyph8-46" />
   <use x="108.286608" y="355.55985" xlink:href="#glyph8-15" />
   <use x="111.91272" y="355.55985" xlink:href="#glyph8-50" />
   <use x="116.415834" y="355.55985" xlink:href="#glyph8-46" />
   <use x="121.885326" y="355.55985" xlink:href="#glyph8-6" />
   <use x="124.70865" y="355.55985" xlink:href="#glyph8-11" />
   <use x="128.334762" y="355.55985" xlink:href="#glyph8-30" />
   <use x="133.181814" y="355.55985" xlink:href="#glyph8-35" />
   <use x="138.156546" y="355.55985" xlink:href="#glyph8-28" />
   <use x="141.303858" y="355.55985" xlink:href="#glyph8-26" />
   <use x="143.49357" y="355.55985" xlink:href="#glyph8-22" />
   <use x="147.654342" y="355.55985" xlink:href="#glyph8-23" />
   <use x="152.453514" y="355.55985" xlink:href="#glyph8-24" />
   <use x="154.643226" y="355.55985" xlink:href="#glyph8-6" />
   <use x="157.46655" y="355.55985" xlink:href="#glyph8-40" />
   <use x="160.278702" y="355.55985" xlink:href="#glyph8-26" />
   <use x="162.468414" y="355.55985" xlink:href="#glyph8-47" />
   <use x="167.443146" y="355.55985" xlink:href="#glyph8-4" />
   <use x="172.202418" y="355.55985" xlink:href="#glyph8-36" />
   <use x="175.61307" y="355.55985" xlink:href="#glyph8-17" />
   <use x="179.239182" y="355.55985" xlink:href="#glyph8-6" />
   <use x="182.062506" y="355.55985" xlink:href="#glyph8-40" />
   <use x="184.82598" y="355.55985" xlink:href="#glyph8-30" />
   <use x="189.686598" y="355.55985" xlink:href="#glyph8-36" />
   <use x="193.09725" y="355.55985" xlink:href="#glyph8-6" />
   <use x="195.920574" y="355.55985" xlink:href="#glyph8-13" />
   <use x="202.108266" y="355.55985" xlink:href="#glyph8-26" />
   <use x="204.297978" y="355.55985" xlink:href="#glyph8-51" />
   <use x="209.27271" y="355.55985" xlink:href="#glyph8-23" />
   <use x="214.071882" y="355.55985" xlink:href="#glyph8-47" />
   <use x="219.046614" y="355.55985" xlink:href="#glyph8-26" />
   <use x="221.236326" y="355.55985" xlink:href="#glyph8-28" />
   <use x="224.383638" y="355.55985" xlink:href="#glyph8-6" />
   <use x="227.206962" y="355.55985" xlink:href="#glyph8-47" />
   <use x="232.181694" y="355.55985" xlink:href="#glyph8-23" />
   <use x="236.980866" y="355.55985" xlink:href="#glyph8-22" />
   <use x="241.141638" y="355.55985" xlink:href="#glyph8-52" />
   <use x="245.86899" y="355.55985" xlink:href="#glyph8-35" />
   <use x="250.843722" y="355.55985" xlink:href="#glyph8-24" />
   <use x="253.033434" y="355.55985" xlink:href="#glyph8-23" />
   <use x="257.832606" y="355.55985" xlink:href="#glyph8-27" />
   <use x="262.93422" y="355.55985" xlink:href="#glyph8-4" />
   <use x="267.693492" y="355.55985" xlink:href="#glyph8-6" />
   <use x="88.26" y="363.53985" xlink:href="#glyph8-23" />
   <use x="93.045606" y="363.53985" xlink:href="#glyph8-35" />
   <use x="98.006772" y="363.53985" xlink:href="#glyph8-35" />
   <use x="102.967938" y="363.53985" xlink:href="#glyph8-24" />
   <use x="105.144084" y="363.53985" xlink:href="#glyph8-26" />
   <use x="107.32023" y="363.53985" xlink:href="#glyph8-22" />
   <use x="111.520104" y="363.53985" xlink:href="#glyph8-23" />
   <use x="116.30571" y="363.53985" xlink:href="#glyph8-28" />
   <use x="119.439456" y="363.53985" xlink:href="#glyph8-26" />
   <use x="121.6563" y="363.53985" xlink:href="#glyph8-30" />
   <use x="126.457068" y="363.53985" xlink:href="#glyph8-27" />
   <use x="131.558682" y="363.53985" xlink:href="#glyph8-16" />
   <use x="135.698706" y="363.53985" xlink:href="#glyph8-9" />
  </g>
  <g fill="#0071c5">
   <use x="76.26" y="371.52" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="88.26" y="371.52" xlink:href="#glyph8-43" />
   <use x="93.725502" y="371.52" xlink:href="#glyph8-13" />
   <use x="99.917184" y="371.52" xlink:href="#glyph8-33" />
   <use x="106.651506" y="371.52" xlink:href="#glyph8-3" />
   <use x="110.072532" y="371.52" xlink:href="#glyph8-3" />
   <use x="113.439294" y="371.52" xlink:href="#glyph8-6" />
   <use x="116.262618" y="371.52" xlink:href="#glyph8-40" />
   <use x="119.026092" y="371.52" xlink:href="#glyph8-30" />
   <use x="123.88671" y="371.52" xlink:href="#glyph8-36" />
   <use x="127.301352" y="371.52" xlink:href="#glyph8-6" />
   <use x="130.124676" y="371.52" xlink:href="#glyph8-43" />
   <use x="135.590178" y="371.52" xlink:href="#glyph8-53" />
   <use x="140.18586" y="371.52" xlink:href="#glyph8-1" />
   <use x="145.004982" y="371.52" xlink:href="#glyph8-15" />
   <use x="148.635084" y="371.52" xlink:href="#glyph8-4" />
   <use x="153.398346" y="371.52" xlink:href="#glyph8-18" />
   <use x="158.129688" y="371.52" xlink:href="#glyph8-28" />
   <use x="161.28099" y="371.52" xlink:href="#glyph8-4" />
   <use x="166.044252" y="371.52" xlink:href="#glyph8-36" />
   <use x="169.458894" y="371.52" xlink:href="#glyph8-27" />
   <use x="174.517416" y="371.52" xlink:href="#glyph8-23" />
   <use x="179.320578" y="371.52" xlink:href="#glyph8-24" />
   <use x="181.51428" y="371.52" xlink:href="#glyph8-6" />
   <use x="184.337604" y="371.52" xlink:href="#glyph8-1" />
   <use x="189.156726" y="371.52" xlink:href="#glyph8-54" />
   <use x="195.156888" y="371.52" xlink:href="#glyph8-55" />
   <use x="200.07177" y="371.52" xlink:href="#glyph8-6" />
   <use x="202.895094" y="371.52" xlink:href="#glyph8-22" />
   <use x="207.059856" y="371.52" xlink:href="#glyph8-30" />
   <use x="211.910898" y="371.52" xlink:href="#glyph8-27" />
   <use x="216.96942" y="371.52" xlink:href="#glyph8-27" />
   <use x="222.027942" y="371.52" xlink:href="#glyph8-4" />
   <use x="226.791204" y="371.52" xlink:href="#glyph8-22" />
   <use x="230.955966" y="371.52" xlink:href="#glyph8-28" />
   <use x="234.107268" y="371.52" xlink:href="#glyph8-26" />
   <use x="236.30097" y="371.52" xlink:href="#glyph8-30" />
   <use x="241.101738" y="371.52" xlink:href="#glyph8-27" />
   <use x="246.203352" y="371.52" xlink:href="#glyph8-16" />
  </g>
  <g fill="#0071c5">
   <use x="76.26" y="379.56" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="88.26" y="379.56" xlink:href="#glyph8-56" />
   <use x="94.211484" y="379.56" xlink:href="#glyph8-2" />
   <use x="99.609156" y="379.56" xlink:href="#glyph8-44" />
   <use x="103.148286" y="379.56" xlink:href="#glyph8-43" />
   <use x="108.611394" y="379.56" xlink:href="#glyph8-3" />
   <use x="112.03242" y="379.56" xlink:href="#glyph8-6" />
   <use x="114.795894" y="379.56" xlink:href="#glyph8-11" />
   <use x="118.401258" y="379.56" xlink:href="#glyph8-14" />
   <use x="122.539686" y="379.56" xlink:href="#glyph8-57" />
   <use x="127.281402" y="379.56" xlink:href="#glyph8-35" />
   <use x="132.260922" y="379.56" xlink:href="#glyph8-4" />
   <use x="137.063286" y="379.56" xlink:href="#glyph8-6" />
   <use x="139.82676" y="379.56" xlink:href="#glyph8-2" />
   <use x="145.379244" y="379.56" xlink:href="#glyph8-17" />
   <use x="148.984608" y="379.56" xlink:href="#glyph8-6" />
   <use x="151.748082" y="379.56" xlink:href="#glyph8-30" />
   <use x="156.6087" y="379.56" xlink:href="#glyph8-36" />
   <use x="160.030524" y="379.56" xlink:href="#glyph8-6" />
   <use x="162.793998" y="379.56" xlink:href="#glyph8-43" />
   <use x="168.234762" y="379.56" xlink:href="#glyph8-33" />
   <use x="174.944346" y="379.56" xlink:href="#glyph8-41" />
   <use x="180.468102" y="379.56" xlink:href="#glyph8-31" />
   <use x="185.509866" y="379.56" xlink:href="#glyph8-16" />
   <use x="189.70974" y="379.56" xlink:href="#glyph8-6" />
   <use x="192.473214" y="379.56" xlink:href="#glyph8-40" />
   <use x="195.296538" y="379.56" xlink:href="#glyph8-30" />
   <use x="200.157156" y="379.56" xlink:href="#glyph8-36" />
   <use x="203.54706" y="379.56" xlink:href="#glyph8-6" />
   <use x="206.370384" y="379.56" xlink:href="#glyph8-33" />
   <use x="213.079968" y="379.56" xlink:href="#glyph8-23" />
   <use x="217.858392" y="379.56" xlink:href="#glyph8-27" />
   <use x="222.892176" y="379.56" xlink:href="#glyph8-23" />
   <use x="227.6706" y="379.56" xlink:href="#glyph8-51" />
   <use x="232.624584" y="379.56" xlink:href="#glyph8-4" />
   <use x="237.426948" y="379.56" xlink:href="#glyph8-23" />
   <use x="242.205372" y="379.56" xlink:href="#glyph8-47" />
   <use x="247.159356" y="379.56" xlink:href="#glyph8-26" />
   <use x="249.32832" y="379.56" xlink:href="#glyph8-24" />
   <use x="251.497284" y="379.56" xlink:href="#glyph8-26" />
   <use x="253.714128" y="379.56" xlink:href="#glyph8-28" />
   <use x="256.840692" y="379.56" xlink:href="#glyph8-57" />
   <use x="261.547296" y="379.56" xlink:href="#glyph8-6" />
   <use x="264.31077" y="379.56" xlink:href="#glyph8-22" />
   <use x="268.510644" y="379.56" xlink:href="#glyph8-30" />
   <use x="273.371262" y="379.56" xlink:href="#glyph8-27" />
   <use x="278.405046" y="379.56" xlink:href="#glyph8-27" />
   <use x="283.50666" y="379.56" xlink:href="#glyph8-4" />
   <use x="288.245184" y="379.56" xlink:href="#glyph8-22" />
   <use x="292.385208" y="379.56" xlink:href="#glyph8-28" />
   <use x="295.565238" y="379.56" xlink:href="#glyph8-26" />
   <use x="297.722232" y="379.56" xlink:href="#glyph8-30" />
   <use x="302.58285" y="379.56" xlink:href="#glyph8-27" />
   <use x="307.624614" y="379.56" xlink:href="#glyph8-6" />
   <use x="88.26" y="387.54" xlink:href="#glyph8-28" />
   <use x="91.398534" y="387.54" xlink:href="#glyph8-30" />
   <use x="96.259152" y="387.54" xlink:href="#glyph8-6" />
   <use x="99.082476" y="387.54" xlink:href="#glyph8-41" />
   <use x="104.55117" y="387.54" xlink:href="#glyph8-33" />
   <use x="111.333372" y="387.54" xlink:href="#glyph8-2" />
   <use x="116.897826" y="387.54" xlink:href="#glyph8-9" />
  </g>
  <g fill="#0071c5">
   <use x="76.26" y="395.52" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="88.26" y="395.52" xlink:href="#glyph8-3" />
   <use x="91.628358" y="395.52" xlink:href="#glyph8-37" />
   <use x="96.680496" y="395.52" xlink:href="#glyph8-37" />
   <use x="101.732634" y="395.52" xlink:href="#glyph8-37" />
   <use x="106.784772" y="395.52" xlink:href="#glyph8-6" />
   <use x="109.608096" y="395.52" xlink:href="#glyph8-20" />
   <use x="114.692154" y="395.52" xlink:href="#glyph8-20" />
   <use x="119.776212" y="395.52" xlink:href="#glyph8-19" />
   <use x="124.86027" y="395.52" xlink:href="#glyph8-58" />
   <use x="129.902034" y="395.52" xlink:href="#glyph8-9" />
   <use x="132.815532" y="395.52" xlink:href="#glyph8-20" />
   <use x="137.89959" y="395.52" xlink:href="#glyph8-6" />
   <use x="140.722914" y="395.52" xlink:href="#glyph8-59" />
   <use x="144.362592" y="395.52" xlink:href="#glyph8-14" />
   <use x="148.801068" y="395.52" xlink:href="#glyph8-42" />
   <use x="154.324026" y="395.52" xlink:href="#glyph8-13" />
   <use x="160.500546" y="395.52" xlink:href="#glyph8-6" />
   <use x="163.32387" y="395.52" xlink:href="#glyph8-6" />
   <use x="166.147194" y="395.52" xlink:href="#glyph8-6" />
  </g>
  <g fill="#0071c5">
   <use x="76.259676" y="413.519688" xlink:href="#glyph6-10" />
   <use x="80.60319" y="413.519688" xlink:href="#glyph6-6" />
   <use x="86.271384" y="413.519688" xlink:href="#glyph6-3" />
   <use x="89.935002" y="413.519688" xlink:href="#glyph6-4" />
   <use x="95.27442" y="413.519688" xlink:href="#glyph6-8" />
   <use x="97.990014" y="413.519688" xlink:href="#glyph6-14" />
   <use x="105.731412" y="413.519688" xlink:href="#glyph6-9" />
   <use x="108.43344" y="413.519688" xlink:href="#glyph6-10" />
   <use x="112.81446" y="413.519688" xlink:href="#glyph6-15" />
   <use x="118.331034" y="413.519688" xlink:href="#glyph6-16" />
   <use x="125.100468" y="413.519688" xlink:href="#glyph6-9" />
   <use x="127.862346" y="413.519688" xlink:href="#glyph6-17" />
   <use x="134.04126" y="413.519688" xlink:href="#glyph6-12" />
   <use x="138.719934" y="413.519688" xlink:href="#glyph6-12" />
   <use x="143.456862" y="413.519688" xlink:href="#glyph6-4" />
   <use x="148.742016" y="413.519688" xlink:href="#glyph6-8" />
   <use x="151.503894" y="413.519688" xlink:href="#glyph6-4" />
   <use x="156.789048" y="413.519688" xlink:href="#glyph6-5" />
   <use x="160.808574" y="413.519688" xlink:href="#glyph6-7" />
   <use x="166.125648" y="413.519688" xlink:href="#glyph6-3" />
   <use x="169.750962" y="413.519688" xlink:href="#glyph6-18" />
   <use x="172.51284" y="413.519688" xlink:href="#glyph6-19" />
   <use x="177.976746" y="413.519688" xlink:href="#glyph6-6" />
   <use x="183.64494" y="413.519688" xlink:href="#glyph6-9" />
   <use x="186.406818" y="413.519688" xlink:href="#glyph6-20" />
   <use x="191.835612" y="413.519688" xlink:href="#glyph6-4" />
   <use x="197.120766" y="413.519688" xlink:href="#glyph6-12" />
   <use x="201.857694" y="413.519688" xlink:href="#glyph6-21" />
   <use x="207.554616" y="413.519688" xlink:href="#glyph6-6" />
   <use x="213.22281" y="413.519688" xlink:href="#glyph6-19" />
   <use x="218.746566" y="413.519688" xlink:href="#glyph6-8" />
   <use x="221.508444" y="413.519688" xlink:href="#glyph6-19" />
   <use x="226.97235" y="413.519688" xlink:href="#glyph6-22" />
   <use x="232.536804" y="413.519688" xlink:href="#glyph6-23" />
   <use x="76.26" y="423.54" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="88.26" y="423.54" xlink:href="#glyph8-43" />
   <use x="93.711936" y="423.54" xlink:href="#glyph8-28" />
   <use x="96.849672" y="423.54" xlink:href="#glyph8-23" />
   <use x="101.639268" y="423.54" xlink:href="#glyph8-28" />
   <use x="104.819298" y="423.54" xlink:href="#glyph8-4" />
   <use x="109.568994" y="423.54" xlink:href="#glyph8-24" />
   <use x="111.785838" y="423.54" xlink:href="#glyph8-4" />
   <use x="116.535534" y="423.54" xlink:href="#glyph8-16" />
   <use x="120.68673" y="423.54" xlink:href="#glyph8-16" />
   <use x="124.886604" y="423.54" xlink:href="#glyph8-6" />
   <use x="127.709928" y="423.54" xlink:href="#glyph8-30" />
   <use x="132.547404" y="423.54" xlink:href="#glyph8-40" />
   <use x="135.34998" y="423.54" xlink:href="#glyph8-40" />
   <use x="138.152556" y="423.54" xlink:href="#glyph8-24" />
   <use x="140.3694" y="423.54" xlink:href="#glyph8-30" />
   <use x="145.206876" y="423.54" xlink:href="#glyph8-23" />
   <use x="149.996472" y="423.54" xlink:href="#glyph8-25" />
   <use x="154.961628" y="423.54" xlink:href="#glyph8-16" />
   <use x="159.112824" y="423.54" xlink:href="#glyph8-6" />
   <use x="161.936148" y="423.54" xlink:href="#glyph8-11" />
   <use x="165.594978" y="423.54" xlink:href="#glyph8-54" />
   <use x="171.59115" y="423.54" xlink:href="#glyph8-4" />
   <use x="176.340846" y="423.54" xlink:href="#glyph8-23" />
   <use x="181.130442" y="423.54" xlink:href="#glyph8-25" />
   <use x="186.095598" y="423.54" xlink:href="#glyph8-4" />
   <use x="190.897962" y="423.54" xlink:href="#glyph8-36" />
   <use x="194.299038" y="423.54" xlink:href="#glyph8-6" />
   <use x="197.062512" y="423.54" xlink:href="#glyph8-16" />
   <use x="201.262386" y="423.54" xlink:href="#glyph8-35" />
   <use x="206.241906" y="423.54" xlink:href="#glyph8-24" />
   <use x="208.422042" y="423.54" xlink:href="#glyph8-26" />
   <use x="210.602178" y="423.54" xlink:href="#glyph8-28" />
   <use x="213.782208" y="423.54" xlink:href="#glyph8-45" />
   <use x="216.680544" y="423.54" xlink:href="#glyph8-6" />
   <use x="219.503868" y="423.54" xlink:href="#glyph8-49" />
   <use x="225.08109" y="423.54" xlink:href="#glyph8-43" />
   <use x="230.484348" y="423.54" xlink:href="#glyph8-43" />
   <use x="235.936284" y="423.54" xlink:href="#glyph8-17" />
  </g>
  <g fill="#0071c5">
   <use x="76.26" y="431.52" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="88.26" y="431.52" xlink:href="#glyph8-3" />
   <use x="91.608408" y="431.52" xlink:href="#glyph8-27" />
   <use x="96.648576" y="431.52" xlink:href="#glyph8-28" />
   <use x="99.828606" y="431.52" xlink:href="#glyph8-4" />
   <use x="104.57112" y="431.52" xlink:href="#glyph8-24" />
   <use x="106.746468" y="431.52" xlink:href="#glyph8-60" />
   <use x="114.786318" y="431.52" xlink:href="#glyph8-6" />
   <use x="117.549792" y="431.52" xlink:href="#glyph8-61" />
   <use x="123.849204" y="431.52" xlink:href="#glyph8-31" />
   <use x="128.950818" y="431.52" xlink:href="#glyph8-26" />
   <use x="131.126166" y="431.52" xlink:href="#glyph8-22" />
   <use x="135.272574" y="431.52" xlink:href="#glyph8-52" />
   <use x="140.01429" y="431.52" xlink:href="#glyph8-34" />
   <use x="146.197992" y="431.52" xlink:href="#glyph8-23" />
   <use x="150.9828" y="431.52" xlink:href="#glyph8-28" />
   <use x="154.16283" y="431.52" xlink:href="#glyph8-23" />
   <use x="158.947638" y="431.52" xlink:href="#glyph8-6" />
   <use x="161.770962" y="431.52" xlink:href="#glyph8-11" />
   <use x="165.38271" y="431.52" xlink:href="#glyph8-34" />
   <use x="171.566412" y="431.52" xlink:href="#glyph8-2" />
   <use x="177.12528" y="431.52" xlink:href="#glyph8-42" />
   <use x="182.572428" y="431.52" xlink:href="#glyph8-6" />
   <use x="185.395752" y="431.52" xlink:href="#glyph8-44" />
   <use x="189.0075" y="431.52" xlink:href="#glyph8-6" />
   <use x="191.830824" y="431.52" xlink:href="#glyph8-34" />
   <use x="198.014526" y="431.52" xlink:href="#glyph8-26" />
   <use x="200.17152" y="431.52" xlink:href="#glyph8-36" />
   <use x="203.593344" y="431.52" xlink:href="#glyph8-4" />
   <use x="208.395708" y="431.52" xlink:href="#glyph8-22" />
   <use x="212.542116" y="431.52" xlink:href="#glyph8-28" />
   <use x="215.722146" y="431.52" xlink:href="#glyph8-6" />
   <use x="218.54547" y="431.52" xlink:href="#glyph8-2" />
   <use x="224.104338" y="431.52" xlink:href="#glyph8-23" />
   <use x="228.889146" y="431.52" xlink:href="#glyph8-22" />
   <use x="233.035554" y="431.52" xlink:href="#glyph8-29" />
   <use x="238.075722" y="431.52" xlink:href="#glyph8-4" />
   <use x="242.878086" y="431.52" xlink:href="#glyph8-6" />
   <use x="245.70141" y="431.52" xlink:href="#glyph8-42" />
   <use x="251.148558" y="431.52" xlink:href="#glyph8-22" />
   <use x="255.294966" y="431.52" xlink:href="#glyph8-22" />
   <use x="259.49484" y="431.52" xlink:href="#glyph8-4" />
   <use x="264.237354" y="431.52" xlink:href="#glyph8-16" />
   <use x="268.437228" y="431.52" xlink:href="#glyph8-16" />
   <use x="272.577252" y="431.52" xlink:href="#glyph8-17" />
  </g>
  <g fill="#0071c5">
   <use x="318.479808" y="287.520102" xlink:href="#glyph6-24" />
   <use x="324.596478" y="287.520102" xlink:href="#glyph6-18" />
   <use x="327.297708" y="287.520102" xlink:href="#glyph6-5" />
   <use x="331.283718" y="287.520102" xlink:href="#glyph6-3" />
   <use x="334.942548" y="287.520102" xlink:href="#glyph6-25" />
   <use x="340.644258" y="287.520102" xlink:href="#glyph6-7" />
   <use x="345.994848" y="287.520102" xlink:href="#glyph6-8" />
   <use x="348.743958" y="287.520102" xlink:href="#glyph6-18" />
   <use x="351.445986" y="287.520102" xlink:href="#glyph6-26" />
   <use x="356.229996" y="287.520102" xlink:href="#glyph6-7" />
   <use x="361.580586" y="287.520102" xlink:href="#glyph6-3" />
   <use x="365.239416" y="287.520102" xlink:href="#glyph6-18" />
   <use x="367.941444" y="287.520102" xlink:href="#glyph6-19" />
   <use x="373.443654" y="287.520102" xlink:href="#glyph6-6" />
   <use x="379.145364" y="287.520102" xlink:href="#glyph6-9" />
   <use x="381.846594" y="287.520102" xlink:href="#glyph6-27" />
   <use x="388.106904" y="287.520102" xlink:href="#glyph6-4" />
   <use x="393.425574" y="287.520102" xlink:href="#glyph6-7" />
   <use x="398.776164" y="287.520102" xlink:href="#glyph6-28" />
   <use x="404.374134" y="287.520102" xlink:href="#glyph6-23" />
   <use x="318.48" y="297.54" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="330.48" y="297.54" xlink:href="#glyph8-56" />
   <use x="336.419514" y="297.54" xlink:href="#glyph8-4" />
   <use x="341.221878" y="297.54" xlink:href="#glyph8-18" />
   <use x="345.962796" y="297.54" xlink:href="#glyph8-28" />
   <use x="349.123674" y="297.54" xlink:href="#glyph8-6" />
   <use x="351.946998" y="297.54" xlink:href="#glyph8-13" />
   <use x="358.148256" y="297.54" xlink:href="#glyph8-4" />
   <use x="362.921094" y="297.54" xlink:href="#glyph8-27" />
   <use x="367.989192" y="297.54" xlink:href="#glyph8-4" />
   <use x="372.76203" y="297.54" xlink:href="#glyph8-36" />
   <use x="376.004304" y="297.54" xlink:href="#glyph8-23" />
   <use x="380.807466" y="297.54" xlink:href="#glyph8-28" />
   <use x="383.968344" y="297.54" xlink:href="#glyph8-26" />
   <use x="386.125338" y="297.54" xlink:href="#glyph8-30" />
   <use x="390.985956" y="297.54" xlink:href="#glyph8-27" />
   <use x="396.054054" y="297.54" xlink:href="#glyph8-6" />
   <use x="398.877378" y="297.54" xlink:href="#glyph8-62" />
   <use x="404.352456" y="297.54" xlink:href="#glyph8-33" />
   <use x="411.134658" y="297.54" xlink:href="#glyph8-34" />
   <use x="417.25851" y="297.54" xlink:href="#glyph8-63" />
   <use x="422.29788" y="297.54" xlink:href="#glyph8-6" />
   <use x="425.121204" y="297.54" xlink:href="#glyph8-16" />
   <use x="429.295542" y="297.54" xlink:href="#glyph8-31" />
   <use x="434.36364" y="297.54" xlink:href="#glyph8-35" />
   <use x="439.351938" y="297.54" xlink:href="#glyph8-35" />
   <use x="444.340236" y="297.54" xlink:href="#glyph8-30" />
   <use x="449.200854" y="297.54" xlink:href="#glyph8-36" />
   <use x="452.625072" y="297.54" xlink:href="#glyph8-28" />
   <use x="455.78595" y="297.54" xlink:href="#glyph8-6" />
   <use x="458.549424" y="297.54" xlink:href="#glyph8-11" />
   <use x="462.189102" y="297.54" xlink:href="#glyph8-38" />
   <use x="467.28114" y="297.54" xlink:href="#glyph8-6" />
   <use x="470.104464" y="297.54" xlink:href="#glyph8-62" />
   <use x="475.579542" y="297.54" xlink:href="#glyph8-33" />
   <use x="482.32344" y="297.54" xlink:href="#glyph8-16" />
   <use x="486.497778" y="297.54" xlink:href="#glyph8-17" />
  </g>
  <g fill="#0071c5">
   <use x="318.48" y="305.52" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="330.48" y="305.52" xlink:href="#glyph8-1" />
   <use x="335.279172" y="305.52" xlink:href="#glyph8-2" />
   <use x="340.836444" y="305.52" xlink:href="#glyph8-3" />
   <use x="344.077122" y="305.52" xlink:href="#glyph8-44" />
   <use x="347.616252" y="305.52" xlink:href="#glyph8-43" />
   <use x="353.13921" y="305.52" xlink:href="#glyph8-3" />
   <use x="356.500386" y="305.52" xlink:href="#glyph8-13" />
   <use x="362.672118" y="305.52" xlink:href="#glyph8-6" />
   <use x="365.495442" y="305.52" xlink:href="#glyph8-43" />
   <use x="370.940994" y="305.52" xlink:href="#glyph8-26" />
   <use x="373.114746" y="305.52" xlink:href="#glyph8-27" />
   <use x="378.21636" y="305.52" xlink:href="#glyph8-51" />
   <use x="383.19588" y="305.52" xlink:href="#glyph8-24" />
   <use x="385.369632" y="305.52" xlink:href="#glyph8-4" />
   <use x="390.112944" y="305.52" xlink:href="#glyph8-6" />
   <use x="392.936268" y="305.52" xlink:href="#glyph8-49" />
   <use x="398.33394" y="305.52" xlink:href="#glyph8-30" />
   <use x="403.194558" y="305.52" xlink:href="#glyph8-30" />
   <use x="408.02565" y="305.52" xlink:href="#glyph8-28" />
   <use x="411.20568" y="305.52" xlink:href="#glyph8-6" />
   <use x="414.029004" y="305.52" xlink:href="#glyph8-3" />
   <use x="417.375816" y="305.52" xlink:href="#glyph8-15" />
   <use x="420.985968" y="305.52" xlink:href="#glyph8-64" />
   <use x="427.28538" y="305.52" xlink:href="#glyph8-6" />
   <use x="430.108704" y="305.52" xlink:href="#glyph8-62" />
   <use x="435.554256" y="305.52" xlink:href="#glyph8-26" />
   <use x="437.7711" y="305.52" xlink:href="#glyph8-36" />
   <use x="441.192924" y="305.52" xlink:href="#glyph8-28" />
   <use x="444.312306" y="305.52" xlink:href="#glyph8-31" />
   <use x="449.350878" y="305.52" xlink:href="#glyph8-23" />
   <use x="454.21389" y="305.52" xlink:href="#glyph8-24" />
   <use x="456.387642" y="305.52" xlink:href="#glyph8-26" />
   <use x="458.561394" y="305.52" xlink:href="#glyph8-48" />
   <use x="462.738126" y="305.52" xlink:href="#glyph8-23" />
   <use x="467.521338" y="305.52" xlink:href="#glyph8-28" />
   <use x="470.701368" y="305.52" xlink:href="#glyph8-26" />
   <use x="472.87512" y="305.52" xlink:href="#glyph8-30" />
   <use x="477.735738" y="305.52" xlink:href="#glyph8-27" />
   <use x="482.77431" y="305.52" xlink:href="#glyph8-6" />
   <use x="485.597634" y="305.52" xlink:href="#glyph8-11" />
   <use x="489.257262" y="305.52" xlink:href="#glyph8-34" />
   <use x="495.381114" y="305.52" xlink:href="#glyph8-26" />
   <use x="497.597958" y="305.52" xlink:href="#glyph8-36" />
   <use x="500.959932" y="305.52" xlink:href="#glyph8-4" />
   <use x="505.762296" y="305.52" xlink:href="#glyph8-22" />
   <use x="509.90232" y="305.52" xlink:href="#glyph8-28" />
   <use x="513.08235" y="305.52" xlink:href="#glyph8-6" />
   <use x="330.48" y="313.55985" xlink:href="#glyph8-23" />
   <use x="335.279172" y="313.55985" xlink:href="#glyph8-16" />
   <use x="339.439944" y="313.55985" xlink:href="#glyph8-16" />
   <use x="343.600716" y="313.55985" xlink:href="#glyph8-26" />
   <use x="345.790428" y="313.55985" xlink:href="#glyph8-51" />
   <use x="350.76516" y="313.55985" xlink:href="#glyph8-27" />
   <use x="355.819692" y="313.55985" xlink:href="#glyph8-32" />
   <use x="363.587424" y="313.55985" xlink:href="#glyph8-4" />
   <use x="368.346696" y="313.55985" xlink:href="#glyph8-27" />
   <use x="373.44831" y="313.55985" xlink:href="#glyph8-28" />
   <use x="376.567692" y="313.55985" xlink:href="#glyph8-17" />
  </g>
  <g fill="#0071c5">
   <use x="318.48" y="321.54" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="330.48" y="321.54" xlink:href="#glyph8-61" />
   <use x="336.770634" y="321.54" xlink:href="#glyph8-31" />
   <use x="341.832348" y="321.54" xlink:href="#glyph8-4" />
   <use x="346.598802" y="321.54" xlink:href="#glyph8-31" />
   <use x="351.660516" y="321.54" xlink:href="#glyph8-4" />
   <use x="356.42697" y="321.54" xlink:href="#glyph8-16" />
   <use x="360.594924" y="321.54" xlink:href="#glyph8-6" />
   <use x="363.418248" y="321.54" xlink:href="#glyph8-35" />
   <use x="368.400162" y="321.54" xlink:href="#glyph8-4" />
   <use x="373.166616" y="321.54" xlink:href="#glyph8-36" />
   <use x="376.58445" y="321.54" xlink:href="#glyph8-6" />
   <use x="379.407774" y="321.54" xlink:href="#glyph8-35" />
   <use x="384.389688" y="321.54" xlink:href="#glyph8-30" />
   <use x="389.243922" y="321.54" xlink:href="#glyph8-36" />
   <use x="392.661756" y="321.54" xlink:href="#glyph8-28" />
   <use x="395.81625" y="321.54" xlink:href="#glyph8-65" />
   <use x="399.449544" y="321.54" xlink:href="#glyph8-6" />
   <use x="402.272868" y="321.54" xlink:href="#glyph8-20" />
   <use x="407.314632" y="321.54" xlink:href="#glyph8-66" />
   <use x="412.417044" y="321.54" xlink:href="#glyph8-6" />
   <use x="415.240368" y="321.54" xlink:href="#glyph8-14" />
   <use x="420.166422" y="321.54" xlink:href="#glyph8-46" />
   <use x="425.643096" y="321.54" xlink:href="#glyph8-6" />
   <use x="428.400186" y="321.54" xlink:href="#glyph8-63" />
   <use x="433.37811" y="321.54" xlink:href="#glyph8-31" />
   <use x="438.479724" y="321.54" xlink:href="#glyph8-4" />
   <use x="443.242188" y="321.54" xlink:href="#glyph8-31" />
   <use x="448.299912" y="321.54" xlink:href="#glyph8-4" />
   <use x="453.062376" y="321.54" xlink:href="#glyph8-16" />
   <use x="457.22634" y="321.54" xlink:href="#glyph8-6" />
   <use x="460.049664" y="321.54" xlink:href="#glyph8-23" />
   <use x="464.852028" y="321.54" xlink:href="#glyph8-27" />
   <use x="469.953642" y="321.54" xlink:href="#glyph8-25" />
   <use x="474.931566" y="321.54" xlink:href="#glyph8-6" />
   <use x="477.75489" y="321.54" xlink:href="#glyph8-20" />
   <use x="482.796654" y="321.54" xlink:href="#glyph8-66" />
   <use x="487.899066" y="321.54" xlink:href="#glyph8-6" />
   <use x="490.72239" y="321.54" xlink:href="#glyph8-49" />
   <use x="496.274874" y="321.54" xlink:href="#glyph8-46" />
   <use x="501.747558" y="321.54" xlink:href="#glyph8-6" />
   <use x="504.570882" y="321.54" xlink:href="#glyph8-63" />
   <use x="509.548806" y="321.54" xlink:href="#glyph8-31" />
   <use x="514.60653" y="321.54" xlink:href="#glyph8-4" />
   <use x="519.368994" y="321.54" xlink:href="#glyph8-31" />
   <use x="524.426718" y="321.54" xlink:href="#glyph8-4" />
   <use x="529.189182" y="321.54" xlink:href="#glyph8-16" />
  </g>
  <g fill="#0071c5">
   <use x="318.480474" y="339.539688" xlink:href="#glyph6-29" />
   <use x="323.665878" y="339.539688" xlink:href="#glyph6-25" />
   <use x="329.346042" y="339.539688" xlink:href="#glyph6-8" />
   <use x="332.10792" y="339.539688" xlink:href="#glyph6-8" />
   <use x="334.809948" y="339.539688" xlink:href="#glyph6-30" />
   <use x="338.638752" y="339.539688" xlink:href="#glyph6-31" />
   <use x="344.334876" y="339.539688" xlink:href="#glyph6-32" />
   <use x="349.9113" y="339.539688" xlink:href="#glyph6-4" />
   <use x="355.250718" y="339.539688" xlink:href="#glyph6-12" />
   <use x="359.941362" y="339.539688" xlink:href="#glyph6-3" />
   <use x="363.578646" y="339.539688" xlink:href="#glyph6-5" />
   <use x="367.54311" y="339.539688" xlink:href="#glyph6-25" />
   <use x="373.223274" y="339.539688" xlink:href="#glyph6-33" />
   <use x="381.664518" y="339.539688" xlink:href="#glyph6-9" />
   <use x="384.366546" y="339.539688" xlink:href="#glyph6-31" />
   <use x="390.06267" y="339.539688" xlink:href="#glyph6-4" />
   <use x="395.402088" y="339.539688" xlink:href="#glyph6-12" />
   <use x="400.092732" y="339.539688" xlink:href="#glyph6-25" />
   <use x="405.772896" y="339.539688" xlink:href="#glyph6-5" />
   <use x="409.73736" y="339.539688" xlink:href="#glyph6-18" />
   <use x="412.499238" y="339.539688" xlink:href="#glyph6-3" />
   <use x="416.136522" y="339.539688" xlink:href="#glyph6-23" />
   <use x="318.48" y="349.56" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="330.48" y="349.56" xlink:href="#glyph8-3" />
   <use x="333.862722" y="349.56" xlink:href="#glyph8-1" />
   <use x="338.697804" y="349.56" xlink:href="#glyph8-16" />
   <use x="342.878526" y="349.56" xlink:href="#glyph8-4" />
   <use x="347.62104" y="349.56" xlink:href="#glyph8-22" />
   <use x="351.801762" y="349.56" xlink:href="#glyph8-6" />
   <use x="354.565236" y="349.56" xlink:href="#glyph8-11" />
   <use x="358.211298" y="349.56" xlink:href="#glyph8-8" />
   <use x="363.30972" y="349.56" xlink:href="#glyph8-12" />
   <use x="368.351484" y="349.56" xlink:href="#glyph8-66" />
   <use x="373.453896" y="349.56" xlink:href="#glyph8-6" />
   <use x="376.27722" y="349.56" xlink:href="#glyph8-43" />
   <use x="381.680478" y="349.56" xlink:href="#glyph8-42" />
   <use x="386.663988" y="349.56" xlink:href="#glyph8-67" />
   <use x="388.587168" y="349.56" xlink:href="#glyph8-16" />
   <use x="392.727192" y="349.56" xlink:href="#glyph8-17" />
   <use x="396.373254" y="349.56" xlink:href="#glyph8-6" />
   <use x="399.136728" y="349.56" xlink:href="#glyph8-26" />
   <use x="401.34639" y="349.56" xlink:href="#glyph8-27" />
   <use x="406.420872" y="349.56" xlink:href="#glyph8-6" />
   <use x="409.244196" y="349.56" xlink:href="#glyph8-38" />
   <use x="414.342618" y="349.56" xlink:href="#glyph8-8" />
   <use x="419.384382" y="349.56" xlink:href="#glyph8-12" />
   <use x="424.482804" y="349.56" xlink:href="#glyph8-68" />
   <use x="429.581226" y="349.56" xlink:href="#glyph8-66" />
   <use x="434.679648" y="349.56" xlink:href="#glyph8-37" />
   <use x="439.74615" y="349.56" xlink:href="#glyph8-41" />
   <use x="445.243572" y="349.56" xlink:href="#glyph8-21" />
   <use x="448.889634" y="349.56" xlink:href="#glyph8-6" />
   <use x="451.712958" y="349.56" xlink:href="#glyph8-3" />
   <use x="455.09568" y="349.56" xlink:href="#glyph8-1" />
   <use x="459.930762" y="349.56" xlink:href="#glyph8-16" />
   <use x="464.111484" y="349.56" xlink:href="#glyph8-4" />
   <use x="468.853998" y="349.56" xlink:href="#glyph8-22" />
   <use x="473.03472" y="349.56" xlink:href="#glyph8-6" />
   <use x="475.798194" y="349.56" xlink:href="#glyph8-27" />
   <use x="480.872676" y="349.56" xlink:href="#glyph8-30" />
   <use x="485.739678" y="349.56" xlink:href="#glyph8-28" />
   <use x="488.85906" y="349.56" xlink:href="#glyph8-6" />
   <use x="491.682384" y="349.56" xlink:href="#glyph8-35" />
   <use x="496.677066" y="349.56" xlink:href="#glyph8-36" />
   <use x="500.107668" y="349.56" xlink:href="#glyph8-4" />
   <use x="504.850182" y="349.56" xlink:href="#glyph8-16" />
   <use x="509.050056" y="349.56" xlink:href="#glyph8-4" />
   <use x="513.79257" y="349.56" xlink:href="#glyph8-27" />
   <use x="518.894184" y="349.56" xlink:href="#glyph8-28" />
   <use x="522.013566" y="349.56" xlink:href="#glyph8-6" />
   <use x="524.83689" y="349.56" xlink:href="#glyph8-26" />
   <use x="526.993884" y="349.56" xlink:href="#glyph8-27" />
   <use x="532.095498" y="349.56" xlink:href="#glyph8-6" />
   <use x="330.48" y="357.54" xlink:href="#glyph8-38" />
   <use x="335.578422" y="357.54" xlink:href="#glyph8-8" />
   <use x="340.620186" y="357.54" xlink:href="#glyph8-12" />
   <use x="345.718608" y="357.54" xlink:href="#glyph8-68" />
   <use x="350.81703" y="357.54" xlink:href="#glyph8-66" />
   <use x="355.915452" y="357.54" xlink:href="#glyph8-56" />
   <use x="361.854966" y="357.54" xlink:href="#glyph8-43" />
   <use x="367.336428" y="357.54" xlink:href="#glyph8-6" />
   <use x="370.159752" y="357.54" xlink:href="#glyph8-69" />
   <use x="373.805814" y="357.54" xlink:href="#glyph8-56" />
   <use x="379.797996" y="357.54" xlink:href="#glyph8-30" />
   <use x="384.598764" y="357.54" xlink:href="#glyph8-27" />
   <use x="389.700378" y="357.54" xlink:href="#glyph8-44" />
   <use x="393.239508" y="357.54" xlink:href="#glyph8-43" />
   <use x="398.702616" y="357.54" xlink:href="#glyph8-4" />
   <use x="403.481838" y="357.54" xlink:href="#glyph8-22" />
   <use x="407.621862" y="357.54" xlink:href="#glyph8-31" />
   <use x="412.696344" y="357.54" xlink:href="#glyph8-36" />
   <use x="416.126946" y="357.54" xlink:href="#glyph8-26" />
   <use x="418.28394" y="357.54" xlink:href="#glyph8-28" />
   <use x="421.403322" y="357.54" xlink:href="#glyph8-57" />
   <use x="426.150624" y="357.54" xlink:href="#glyph8-70" />
  </g>
  <g fill="#0071c5">
   <use x="318.48" y="365.52" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="330.48" y="365.52" xlink:href="#glyph8-33" />
   <use x="337.210332" y="365.52" xlink:href="#glyph8-42" />
   <use x="342.671844" y="365.52" xlink:href="#glyph8-2" />
   <use x="348.245076" y="365.52" xlink:href="#glyph8-43" />
   <use x="353.706588" y="365.52" xlink:href="#glyph8-4" />
   <use x="358.508952" y="365.52" xlink:href="#glyph8-22" />
  </g>
  <g fill="#0071c5">
   <use x="318.479676" y="383.519688" xlink:href="#glyph6-17" />
   <use x="324.6945" y="383.519688" xlink:href="#glyph6-28" />
   <use x="330.294864" y="383.519688" xlink:href="#glyph6-28" />
   <use x="335.895228" y="383.519688" xlink:href="#glyph6-18" />
   <use x="338.596458" y="383.519688" xlink:href="#glyph6-3" />
   <use x="342.257682" y="383.519688" xlink:href="#glyph6-18" />
   <use x="344.95971" y="383.519688" xlink:href="#glyph6-19" />
   <use x="350.464314" y="383.519688" xlink:href="#glyph6-6" />
   <use x="356.168418" y="383.519688" xlink:href="#glyph6-7" />
   <use x="361.521402" y="383.519688" xlink:href="#glyph6-8" />
   <use x="364.222632" y="383.519688" xlink:href="#glyph6-9" />
   <use x="366.98451" y="383.519688" xlink:href="#glyph6-34" />
   <use x="372.856194" y="383.519688" xlink:href="#glyph6-5" />
   <use x="376.844598" y="383.519688" xlink:href="#glyph6-19" />
   <use x="382.349202" y="383.519688" xlink:href="#glyph6-28" />
   <use x="387.949566" y="383.519688" xlink:href="#glyph6-25" />
   <use x="393.65367" y="383.519688" xlink:href="#glyph6-12" />
   <use x="398.368254" y="383.519688" xlink:href="#glyph6-3" />
   <use x="402.029478" y="383.519688" xlink:href="#glyph6-9" />
   <use x="404.731506" y="383.519688" xlink:href="#glyph6-35" />
   <use x="411.37725" y="383.519688" xlink:href="#glyph6-4" />
   <use x="416.656818" y="383.519688" xlink:href="#glyph6-3" />
   <use x="420.318042" y="383.519688" xlink:href="#glyph6-7" />
   <use x="425.671026" y="383.519688" xlink:href="#glyph6-18" />
   <use x="428.42253" y="383.519688" xlink:href="#glyph6-8" />
   <use x="431.124558" y="383.519688" xlink:href="#glyph6-13" />
   <use x="318.48" y="393.54" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="330.48" y="393.54" xlink:href="#glyph8-8" />
   <use x="335.58321" y="393.54" xlink:href="#glyph8-12" />
   <use x="340.624974" y="393.54" xlink:href="#glyph8-32" />
   <use x="348.417444" y="393.54" xlink:href="#glyph8-32" />
   <use x="356.209914" y="393.54" xlink:href="#glyph8-6" />
   <use x="359.033238" y="393.54" xlink:href="#glyph8-18" />
   <use x="363.715104" y="393.54" xlink:href="#glyph8-6" />
   <use x="366.538428" y="393.54" xlink:href="#glyph8-8" />
   <use x="371.641638" y="393.54" xlink:href="#glyph8-12" />
   <use x="376.744848" y="393.54" xlink:href="#glyph8-32" />
   <use x="384.537318" y="393.54" xlink:href="#glyph8-32" />
   <use x="392.280312" y="393.54" xlink:href="#glyph8-6" />
   <use x="395.103636" y="393.54" xlink:href="#glyph8-1" />
   <use x="399.723258" y="393.54" xlink:href="#glyph8-23" />
   <use x="404.52642" y="393.54" xlink:href="#glyph8-22" />
   <use x="408.71193" y="393.54" xlink:href="#glyph8-52" />
   <use x="413.46402" y="393.54" xlink:href="#glyph8-23" />
   <use x="418.28793" y="393.54" xlink:href="#glyph8-51" />
   <use x="423.2874" y="393.54" xlink:href="#glyph8-4" />
  </g>
  <g fill="#0071c5">
   <use x="318.48" y="401.52" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="330.48" y="401.52" xlink:href="#glyph8-1" />
   <use x="335.099622" y="401.52" xlink:href="#glyph8-30" />
   <use x="339.96024" y="401.52" xlink:href="#glyph8-71" />
   <use x="346.506234" y="401.52" xlink:href="#glyph8-4" />
   <use x="351.248748" y="401.52" xlink:href="#glyph8-36" />
   <use x="354.674562" y="401.52" xlink:href="#glyph8-6" />
   <use x="357.497886" y="401.52" xlink:href="#glyph8-8" />
   <use x="362.59152" y="401.52" xlink:href="#glyph8-9" />
   <use x="365.473098" y="401.52" xlink:href="#glyph8-38" />
   <use x="370.566732" y="401.52" xlink:href="#glyph8-72" />
   <use x="378.477306" y="401.52" xlink:href="#glyph8-6" />
   <use x="381.30063" y="401.52" xlink:href="#glyph8-11" />
   <use x="384.89961" y="401.52" xlink:href="#glyph8-32" />
   <use x="392.702454" y="401.52" xlink:href="#glyph8-23" />
   <use x="397.516788" y="401.52" xlink:href="#glyph8-18" />
   <use x="402.259302" y="401.52" xlink:href="#glyph8-17" />
  </g>
  <g fill="#0071c5">
   <use x="318.48" y="409.56" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="330.48" y="409.56" xlink:href="#glyph8-43" />
   <use x="335.928744" y="409.56" xlink:href="#glyph8-31" />
   <use x="340.970508" y="409.56" xlink:href="#glyph8-35" />
   <use x="345.932472" y="409.56" xlink:href="#glyph8-35" />
   <use x="350.894436" y="409.56" xlink:href="#glyph8-30" />
   <use x="355.755054" y="409.56" xlink:href="#glyph8-36" />
   <use x="359.152938" y="409.56" xlink:href="#glyph8-28" />
   <use x="362.332968" y="409.56" xlink:href="#glyph8-6" />
   <use x="365.156292" y="409.56" xlink:href="#glyph8-40" />
   <use x="367.955676" y="409.56" xlink:href="#glyph8-30" />
   <use x="372.816294" y="409.56" xlink:href="#glyph8-36" />
   <use x="376.214178" y="409.56" xlink:href="#glyph8-6" />
   <use x="379.037502" y="409.56" xlink:href="#glyph8-1" />
   <use x="383.897322" y="409.56" xlink:href="#glyph8-2" />
   <use x="389.475342" y="409.56" xlink:href="#glyph8-3" />
   <use x="392.825346" y="409.56" xlink:href="#glyph8-6" />
   <use x="395.64867" y="409.56" xlink:href="#glyph8-39" />
   <use x="400.714374" y="409.56" xlink:href="#glyph8-9" />
   <use x="403.6566" y="409.56" xlink:href="#glyph8-10" />
   <use x="408.759012" y="409.56" xlink:href="#glyph8-6" />
   <use x="411.582336" y="409.56" xlink:href="#glyph8-62" />
   <use x="417.03108" y="409.56" xlink:href="#glyph8-26" />
   <use x="419.208024" y="409.56" xlink:href="#glyph8-28" />
   <use x="422.342568" y="409.56" xlink:href="#glyph8-23" />
   <use x="427.20558" y="409.56" xlink:href="#glyph8-24" />
   <use x="429.382524" y="409.56" xlink:href="#glyph8-6" />
   <use x="432.205848" y="409.56" xlink:href="#glyph8-1" />
   <use x="437.008212" y="409.56" xlink:href="#glyph8-36" />
   <use x="440.406096" y="409.56" xlink:href="#glyph8-30" />
   <use x="445.266714" y="409.56" xlink:href="#glyph8-25" />
   <use x="450.246234" y="409.56" xlink:href="#glyph8-31" />
   <use x="455.287998" y="409.56" xlink:href="#glyph8-22" />
   <use x="459.487872" y="409.56" xlink:href="#glyph8-28" />
   <use x="462.622416" y="409.56" xlink:href="#glyph8-6" />
   <use x="465.44574" y="409.56" xlink:href="#glyph8-34" />
   <use x="471.629442" y="409.56" xlink:href="#glyph8-23" />
   <use x="476.432604" y="409.56" xlink:href="#glyph8-28" />
   <use x="479.567148" y="409.56" xlink:href="#glyph8-23" />
   <use x="484.353552" y="409.56" xlink:href="#glyph8-6" />
  </g>
  <g fill="#0071c5">
   <use x="318.48" y="417.54" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="330.48" y="417.54" xlink:href="#glyph8-33" />
   <use x="337.218312" y="417.54" xlink:href="#glyph8-4" />
   <use x="341.985564" y="417.54" xlink:href="#glyph8-32" />
   <use x="349.761276" y="417.54" xlink:href="#glyph8-30" />
   <use x="354.616308" y="417.54" xlink:href="#glyph8-36" />
   <use x="358.03494" y="417.54" xlink:href="#glyph8-26" />
   <use x="360.191934" y="417.54" xlink:href="#glyph8-4" />
   <use x="364.959186" y="417.54" xlink:href="#glyph8-16" />
   <use x="369.127938" y="417.54" xlink:href="#glyph8-6" />
   <use x="371.951262" y="417.54" xlink:href="#glyph8-1" />
   <use x="376.570884" y="417.54" xlink:href="#glyph8-23" />
   <use x="381.374046" y="417.54" xlink:href="#glyph8-36" />
   <use x="384.792678" y="417.54" xlink:href="#glyph8-26" />
   <use x="386.949672" y="417.54" xlink:href="#glyph8-28" />
   <use x="390.104964" y="417.54" xlink:href="#glyph8-57" />
   <use x="394.840296" y="417.54" xlink:href="#glyph8-6" />
   <use x="397.66362" y="417.54" xlink:href="#glyph8-30" />
   <use x="402.518652" y="417.54" xlink:href="#glyph8-36" />
   <use x="405.937284" y="417.54" xlink:href="#glyph8-6" />
   <use x="408.760608" y="417.54" xlink:href="#glyph8-37" />
   <use x="413.81514" y="417.54" xlink:href="#glyph8-2" />
   <use x="419.396352" y="417.54" xlink:href="#glyph8-2" />
   <use x="424.977564" y="417.54" xlink:href="#glyph8-6" />
   <use x="427.800888" y="417.54" xlink:href="#glyph8-1" />
   <use x="432.624" y="417.54" xlink:href="#glyph8-36" />
   <use x="436.042632" y="417.54" xlink:href="#glyph8-30" />
   <use x="440.897664" y="417.54" xlink:href="#glyph8-28" />
   <use x="444.052956" y="417.54" xlink:href="#glyph8-4" />
   <use x="448.820208" y="417.54" xlink:href="#glyph8-22" />
   <use x="452.98896" y="417.54" xlink:href="#glyph8-28" />
   <use x="456.144252" y="417.54" xlink:href="#glyph8-26" />
   <use x="458.301246" y="417.54" xlink:href="#glyph8-30" />
   <use x="463.156278" y="417.54" xlink:href="#glyph8-27" />
  </g>
  <g fill="#0071c5">
   <use x="318.48" y="425.52" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="330.48" y="425.52" xlink:href="#glyph8-3" />
   <use x="333.844368" y="425.52" xlink:href="#glyph8-1" />
   <use x="338.661096" y="425.52" xlink:href="#glyph8-33" />
   <use x="345.443298" y="425.52" xlink:href="#glyph8-3" />
   <use x="348.804474" y="425.52" xlink:href="#glyph8-6" />
   <use x="351.627798" y="425.52" xlink:href="#glyph8-33" />
   <use x="358.359726" y="425.52" xlink:href="#glyph8-2" />
   <use x="363.934554" y="425.52" xlink:href="#glyph8-6" />
   <use x="366.757878" y="425.52" xlink:href="#glyph8-1" />
   <use x="371.3775" y="425.52" xlink:href="#glyph8-23" />
   <use x="376.180662" y="425.52" xlink:href="#glyph8-16" />
   <use x="380.380536" y="425.52" xlink:href="#glyph8-16" />
   <use x="384.52056" y="425.52" xlink:href="#glyph8-44" />
   <use x="388.17939" y="425.52" xlink:href="#glyph8-28" />
   <use x="391.298772" y="425.52" xlink:href="#glyph8-29" />
   <use x="396.3549" y="425.52" xlink:href="#glyph8-36" />
   <use x="399.767148" y="425.52" xlink:href="#glyph8-31" />
   <use x="404.868762" y="425.52" xlink:href="#glyph8-21" />
   <use x="408.467742" y="425.52" xlink:href="#glyph8-6" />
   <use x="411.291066" y="425.52" xlink:href="#glyph8-33" />
   <use x="418.022994" y="425.52" xlink:href="#glyph8-31" />
   <use x="423.124608" y="425.52" xlink:href="#glyph8-24" />
   <use x="425.315916" y="425.52" xlink:href="#glyph8-28" />
   <use x="428.464824" y="425.52" xlink:href="#glyph8-26" />
   <use x="430.656132" y="425.52" xlink:href="#glyph8-44" />
   <use x="434.28384" y="425.52" xlink:href="#glyph8-25" />
   <use x="439.260168" y="425.52" xlink:href="#glyph8-36" />
   <use x="442.672416" y="425.52" xlink:href="#glyph8-30" />
   <use x="447.521064" y="425.52" xlink:href="#glyph8-35" />
   <use x="452.497392" y="425.52" xlink:href="#glyph8-6" />
   <use x="455.320716" y="425.52" xlink:href="#glyph8-56" />
   <use x="461.294544" y="425.52" xlink:href="#glyph8-2" />
   <use x="466.693014" y="425.52" xlink:href="#glyph8-44" />
   <use x="470.232144" y="425.52" xlink:href="#glyph8-43" />
   <use x="475.695252" y="425.52" xlink:href="#glyph8-3" />
  </g>
  <g fill="#0071c5">
   <use x="318.48" y="433.56" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="330.48" y="433.56" xlink:href="#glyph8-38" />
   <use x="335.56725" y="433.56" xlink:href="#glyph8-10" />
   <use x="340.609014" y="433.56" xlink:href="#glyph8-8" />
   <use x="345.696264" y="433.56" xlink:href="#glyph8-9" />
   <use x="348.612954" y="433.56" xlink:href="#glyph8-20" />
   <use x="353.654718" y="433.56" xlink:href="#glyph8-42" />
   <use x="359.125008" y="433.56" xlink:href="#glyph8-43" />
   <use x="364.595298" y="433.56" xlink:href="#glyph8-6" />
   <use x="367.418622" y="433.56" xlink:href="#glyph8-25" />
   <use x="372.402132" y="433.56" xlink:href="#glyph8-36" />
   <use x="375.644406" y="433.56" xlink:href="#glyph8-23" />
   <use x="380.507418" y="433.56" xlink:href="#glyph8-40" />
   <use x="383.270892" y="433.56" xlink:href="#glyph8-28" />
   <use x="386.426982" y="433.56" xlink:href="#glyph8-6" />
   <use x="389.250306" y="433.56" xlink:href="#glyph8-16" />
   <use x="393.419856" y="433.56" xlink:href="#glyph8-28" />
   <use x="396.575946" y="433.56" xlink:href="#glyph8-23" />
   <use x="401.383896" y="433.56" xlink:href="#glyph8-27" />
   <use x="406.447206" y="433.56" xlink:href="#glyph8-25" />
   <use x="411.430716" y="433.56" xlink:href="#glyph8-23" />
   <use x="416.238666" y="433.56" xlink:href="#glyph8-36" />
   <use x="419.658096" y="433.56" xlink:href="#glyph8-25" />
   <use x="424.641606" y="433.56" xlink:href="#glyph8-6" />
   <use x="427.46493" y="433.56" xlink:href="#glyph8-26" />
   <use x="429.66342" y="433.56" xlink:href="#glyph8-32" />
   <use x="437.43993" y="433.56" xlink:href="#glyph8-35" />
   <use x="442.42344" y="433.56" xlink:href="#glyph8-24" />
   <use x="444.62193" y="433.56" xlink:href="#glyph8-4" />
   <use x="449.38998" y="433.56" xlink:href="#glyph8-32" />
   <use x="457.16649" y="433.56" xlink:href="#glyph8-4" />
   <use x="461.93454" y="433.56" xlink:href="#glyph8-27" />
   <use x="466.99785" y="433.56" xlink:href="#glyph8-28" />
   <use x="470.15394" y="433.56" xlink:href="#glyph8-23" />
   <use x="474.96189" y="433.56" xlink:href="#glyph8-28" />
   <use x="478.11798" y="433.56" xlink:href="#glyph8-26" />
   <use x="480.31647" y="433.56" xlink:href="#glyph8-30" />
   <use x="485.117238" y="433.56" xlink:href="#glyph8-27" />
  </g>
  <g fill="#0071c5">
   <use x="318.48" y="441.54" xlink:href="#glyph7-1" />
  </g>
  <g>
   <use x="330.48" y="441.54" xlink:href="#glyph8-50" />
   <use x="334.940022" y="441.54" xlink:href="#glyph8-23" />
   <use x="339.683334" y="441.54" xlink:href="#glyph8-57" />
   <use x="344.3652" y="441.54" xlink:href="#glyph8-30" />
   <use x="349.225818" y="441.54" xlink:href="#glyph8-31" />
   <use x="354.29232" y="441.54" xlink:href="#glyph8-28" />
   <use x="357.411702" y="441.54" xlink:href="#glyph8-6" />
   <use x="360.235026" y="441.54" xlink:href="#glyph8-2" />
   <use x="365.820228" y="441.54" xlink:href="#glyph8-30" />
   <use x="370.67925" y="441.54" xlink:href="#glyph8-32" />
   <use x="378.458952" y="441.54" xlink:href="#glyph8-35" />
   <use x="383.445654" y="441.54" xlink:href="#glyph8-23" />
   <use x="388.256796" y="441.54" xlink:href="#glyph8-28" />
   <use x="391.416078" y="441.54" xlink:href="#glyph8-26" />
   <use x="393.573072" y="441.54" xlink:href="#glyph8-47" />
   <use x="398.552592" y="441.54" xlink:href="#glyph8-24" />
   <use x="400.709586" y="441.54" xlink:href="#glyph8-4" />
   <use x="405.51195" y="441.54" xlink:href="#glyph8-6" />
   <use x="408.275424" y="441.54" xlink:href="#glyph8-71" />
   <use x="414.818226" y="441.54" xlink:href="#glyph8-26" />
   <use x="417.019908" y="441.54" xlink:href="#glyph8-28" />
   <use x="420.13929" y="441.54" xlink:href="#glyph8-29" />
   <use x="425.240904" y="441.54" xlink:href="#glyph8-6" />
   <use x="428.064228" y="441.54" xlink:href="#glyph8-38" />
   <use x="433.105992" y="441.54" xlink:href="#glyph8-8" />
   <use x="438.196434" y="441.54" xlink:href="#glyph8-12" />
   <use x="443.286876" y="441.54" xlink:href="#glyph8-68" />
   <use x="448.377318" y="441.54" xlink:href="#glyph8-12" />
  </g>
 </g>
</svg>

<figcaption>Yes, this innocent-looking datasheet has 960 pages.</figcaption>
</figure>

<p>Linux is a good target for the initial bring-up. Its drivers are open-source,
and, combined with QEMU, it can provide
<a href="https://www.kernel.org/doc/html/v6.3/dev-tools/gdb-kernel-debugging.html">interactive debugging experience with gdb</a>
which is comparable with usual user-space development.</p>

<p>Once you get confidence that you implemented everything necessary for the
initialization, run the guest and debug it until it works. We’ll cover the
details of debugging technique in a future post, but basically, normal
debugging tools like GDB work well with QEMU. QEMU also has
<a href="https://www.qemu.org/docs/master/devel/tracing.html">a tracing feature</a> which
greatly helps debugging.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-trace e1000* -trace e1000e* -trace igb*
</code></pre></div></div>

<p>Once it works, check in the code again.</p>

<p>Fortunately, this step was already done by Gal Hammer and Marcel Apfelbaum so I
had working code when I started working on igb. Nevertheless, I performed this
step by myself again to understand the difference between igb and e1000e, and
to backport the recent changes made for e1000e to igb, which was already
diverged from e1000e.</p>

<h2 id="adding-qtest">Adding QTest</h2>

<p><a href="https://www.qemu.org/docs/master/devel/qtest.html">QTest</a> is a device emulation
testing framework and provides low-level access to the emulated device such as
MMIO access. While QTest does not run a real guest and is not suitable for
integration testing, it can cheaply test specific aspects of the device.</p>

<p>A recommended usage of QTest is to write tests for the basic features. As QTest
is ran by <a href="https://www.qemu.org/docs/master/devel/ci.html">the CI</a>, it can
effectively prevent fatal regressions after the code is merged into the
upstream. Of course, you can run it during development too: QTest is so fast
that you can run the test cases for a device always after compiling.</p>

<p>It is also possible to use the framework in a manner more like unit testing and
write tests for most behaviors. Some argue that low-level software components
are not suited for unit testing and while I believe otherwise, it is also true
that unit testing incurs significant cost. For igb, I deemed the gain from the
unit testing to be limited compared to the cost.</p>

<p>The process of writing QTest is not so different from writing the device
emulation itself: copy the existing code, rename identifiers, and tweak it for
the new device.</p>

<h2 id="conclusion">Conclusion</h2>

<p>With these steps finished, now we have:</p>
<ul>
  <li>Buildable code</li>
  <li>Running Linux guest</li>
  <li>Basic QTest</li>
</ul>

<p>These are the foundations of the further development. New features will be added
and more testing will be done in the future, but that cannot be done without
these essential components.</p>

<p><a href="/2023/05/21/igb-developing-a-new-device-for-qemu-part-3-implementing-basic-features.html">The next post</a>
will discuss implementing advanced features and libvirt support to make the
device practically <em>usable</em>.</p>]]></content><author><name>Akihiko Odaki</name></author><summary type="html"><![CDATA[This is the second post of a walkthrough of new device emulator development for QEMU. The first post briefly described the development process and device which we will discuss, igb, an Intel NIC. This post details the first steps of the development: filling a boilerplate and adding basic features necessary to get the device work and to establish the foundation of further development.]]></summary></entry><entry><title type="html">igb: Developing a new device for QEMU (part 1: Introduction)</title><link href="https://daynix.github.io/2023/05/06/igb-developing-a-new-device-for-qemu-part-1-introduction.html" rel="alternate" type="text/html" title="igb: Developing a new device for QEMU (part 1: Introduction)" /><published>2023-05-06T09:00:00+00:00</published><updated>2023-05-06T09:00:00+00:00</updated><id>https://daynix.github.io/2023/05/06/igb-developing-a-new-device-for-qemu-part-1-introduction</id><content type="html" xml:base="https://daynix.github.io/2023/05/06/igb-developing-a-new-device-for-qemu-part-1-introduction.html"><![CDATA[<p><em><a href="https://www.qemu.org/">QEMU</a></em> is a machine emulator and virtualizer; it
emulates or virtualizes various devices which consist in a machine. Such
emulated/virtualized devices include but are not limited to CPU, memory,
storage, bus, serial console, and network interface. QEMU is under active
development, and there is always demand for new device implementations. However,
the journey of new device implementation is complex and not always smooth.</p>

<p>This is a series of four posts and presents challenges and their resolutions
by describing the process of the development of <em>igb</em>, a device implementation
we recently contributed to the project. While igb emulates a
<em>PCI Express (PCIe)</em> network interface card (NIC) and this series will
illustrate some aspects of PCIe and NIC, many parts of it should be generally
applicable for new device emulator development.</p>

<p>* By the way, for igb development, I used a
<em><a href="https://www.apple.com/macbook-air-m2/">M2 MacBook Air</a></em>, which contains
<em>Apple Silicon</em> and runs <em><a href="https://asahilinux.org/">Asahi Linux</a></em>, a community
port of Linux for this system. While there are some pitfalls, it has decent KVM
support and provides a nice environment for QEMU development.</p>

<h2 id="qemu-device-emulator-development-in-a-nutshell">QEMU device emulator development in a nutshell</h2>

<p>Briefly speaking, developing a new QEMU device emulator involves the following
steps:</p>

<ol>
  <li>Writing a boilerplate and adding basic features</li>
  <li>Adding QTest</li>
  <li>Adding advanced features and libvirt support</li>
  <li>Running more tests and increasing feature coverage</li>
  <li>Debugging</li>
  <li>Contributing to the upstream</li>
</ol>

<p>Writing a boilerplate is necessary to integrate the new device into QEMU. After
completing the boilerplate, basic features need to be added so that the guest
can access more advanced features.</p>

<p><em><a href="https://qemu.readthedocs.io/en/v7.2.0/devel/qtest.html">qtest</a></em> is QEMU’s
testing framework and useful to ensure there is no regression in essential
features.</p>

<p>With basic features covered, more advanced but non-essential features can be
added. <em><a href="https://libvirt.org/">libvirt</a></em> is a popular frontend of QEMU, and it
is important for usability to make the device and its features accessible from
libvirt.</p>

<p>During the development, tests will reveal regressions or features which are
missing but necessary for a workload. It is often unclear what is making tests
fail and a significant debugging effort will be required.</p>

<p>Finally, the code will be sent upstream. By upstreaming, you can ensure that the
code will be updated as the other parts of the code base change, and others can
appreciate the contributed code.</p>

<p>This series details each step and provides insight into how a device emulator
can be developed.</p>

<p><a href="/2023/05/12/igb-developing-a-new-device-for-qemu-part-2-implementing-basic-features.html">The next post</a>
will describe steps 1 and 2.
<a href="/2023/05/21/igb-developing-a-new-device-for-qemu-part-3-implementing-basic-features.html">The third post</a>
will describe steps 3 and 4.
<a href="/2023/06/01/igb-developing-a-new-device-for-qemu-part-4-debugging-and-submitting-patches.html">The last post</a>
will be about steps 5 and 6.</p>

<h2 id="what-is-igb">What is igb?</h2>

<p>Before describing the device development process in depth, first, let me
introduce the hardware which will be emulated by igb.</p>

<p>igb is actually the name of a family of Intel’s NIC. In particular, QEMU’s igb
implementation emulates
<a href="https://ark.intel.com/content/www/us/en/ark/products/37166/intel-82576eb-gigabit-ethernet-controller.html">82576</a>,
launched in 2008.</p>

<p>QEMU already has emulation code for several Intel NICs. The following device
implementations are present in the current QEMU (from oldest hardware to newest one):</p>
<ul>
  <li>i82596</li>
  <li>eepro100 for 8255x</li>
  <li>e1000 for 8254x</li>
  <li>e1000e for 82574L</li>
</ul>

<p>igb succeeds <em>e1000e</em> in Intel’s product line. As the name suggests, e1000 and
newer devices have gigabit bandwidth.</p>

<p>While paravirtualization is common these days, igb emulates actual hardware.
In most cases, a para-virtualized device is superior to emulated hardware, but
there are a few advantages emulated hardware has:</p>
<ul>
  <li>Widely available driver. In particular, Windows bundles the driver for igb and
works with it out-of-box.</li>
  <li>Feature-richness. Particularly features which make little sense for software
implementation may be absent in a para-virtualized device, but having such
features emulated may be required for testing purposes.</li>
</ul>

<p>The latter is the major motivation for introducing igb. igb has so many features
added since e1000e so the later part of this section lists particularly notable
features of igb.</p>

<h3 id="vmdq">VMDq</h3>

<p><em><a href="https://www.intel.com/content/www/us/en/products/docs/network-io/ethernet/network-adapters/io-acceleration-technology-vmdq.html">VMDq</a></em>
is a feature to assign <em>queues</em> to different virtual machines. (<em>nested</em> virtual
machine in this case as the underlying system with igb is emulated/virtualized).
A network interface typically has a “queue” for each of tx and rx, and the
software puts a packet to transmit to the Tx queue and retrieves the received
packet from the rx queue.</p>

<p>e1000e has two queues for each of tx and rx to avoid contention of queues on a
multi-processor system. For tx, two processors can submit packets to transmit
at the same time by using different queues. For rx, e1000e can assign packets
from different peers to different queues; this feature is called RSS (receive
side scaling). Each queue can be processed in parallel by two
processors, improving the throughput.</p>

<p>igb has 16 queues for each of tx and rx. These queues can be used for effective
use of multiple processors as in e1000e, but igb also allows to use the queues
for efficient isolation of virtual machines. This isolation is achieved by
hardware-level L2 switching.</p>

<p>In a conventional system, the hypervisor emulates a NIC for each VMs and
performs L2 switching at the software level to route packets to the appropriate
VM. For example, the diagram below illustrates the case when VMs are receiving
packets from an external host:</p>

<svg aria-roledescription="flowchart-v2" role="graphics-document document" viewBox="-8 -8 546.8416748046875 647.88330078125" style="max-width: 100%;" xmlns="http://www.w3.org/2000/svg" width="100%" id="graph-div" height="100%" xmlns:xlink="http://www.w3.org/1999/xlink"><style>@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css");'</style><style>#graph-div{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#graph-div .error-icon{fill:#552222;}#graph-div .error-text{fill:#552222;stroke:#552222;}#graph-div .edge-thickness-normal{stroke-width:2px;}#graph-div .edge-thickness-thick{stroke-width:3.5px;}#graph-div .edge-pattern-solid{stroke-dasharray:0;}#graph-div .edge-pattern-dashed{stroke-dasharray:3;}#graph-div .edge-pattern-dotted{stroke-dasharray:2;}#graph-div .marker{fill:#333333;stroke:#333333;}#graph-div .marker.cross{stroke:#333333;}#graph-div svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#graph-div .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#graph-div .cluster-label text{fill:#333;}#graph-div .cluster-label span,#graph-div p{color:#333;}#graph-div .label text,#graph-div span,#graph-div p{fill:#333;color:#333;}#graph-div .node rect,#graph-div .node circle,#graph-div .node ellipse,#graph-div .node polygon,#graph-div .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#graph-div .flowchart-label text{text-anchor:middle;}#graph-div .node .label{text-align:center;}#graph-div .node.clickable{cursor:pointer;}#graph-div .arrowheadPath{fill:#333333;}#graph-div .edgePath .path{stroke:#333333;stroke-width:2.0px;}#graph-div .flowchart-link{stroke:#333333;fill:none;}#graph-div .edgeLabel{background-color:#e8e8e8;text-align:center;}#graph-div .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#graph-div .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#graph-div .cluster text{fill:#333;}#graph-div .cluster span,#graph-div p{color:#333;}#graph-div div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#graph-div .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#graph-div :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker orient="auto" markerHeight="12" markerWidth="12" markerUnits="userSpaceOnUse" refY="5" refX="10" viewBox="0 0 12 20" class="marker flowchart" id="flowchart-pointEnd"><path style="stroke-width: 1px; stroke-dasharray: 1px, 0px;" class="arrowMarkerPath" d="M 0 0 L 10 5 L 0 10 z"></path></marker><marker orient="auto" markerHeight="12" markerWidth="12" markerUnits="userSpaceOnUse" refY="5" refX="0" viewBox="0 0 10 10" class="marker flowchart" id="flowchart-pointStart"><path style="stroke-width: 1px; stroke-dasharray: 1px, 0px;" class="arrowMarkerPath" d="M 0 5 L 10 10 L 10 0 z"></path></marker><marker orient="auto" markerHeight="11" markerWidth="11" markerUnits="userSpaceOnUse" refY="5" refX="11" viewBox="0 0 10 10" class="marker flowchart" id="flowchart-circleEnd"><circle style="stroke-width: 1px; stroke-dasharray: 1px, 0px;" class="arrowMarkerPath" r="5" cy="5" cx="5"></circle></marker><marker orient="auto" markerHeight="11" markerWidth="11" markerUnits="userSpaceOnUse" refY="5" refX="-1" viewBox="0 0 10 10" class="marker flowchart" id="flowchart-circleStart"><circle style="stroke-width: 1px; stroke-dasharray: 1px, 0px;" class="arrowMarkerPath" r="5" cy="5" cx="5"></circle></marker><marker orient="auto" markerHeight="11" markerWidth="11" markerUnits="userSpaceOnUse" refY="5.2" refX="12" viewBox="0 0 11 11" class="marker cross flowchart" id="flowchart-crossEnd"><path style="stroke-width: 2px; stroke-dasharray: 1px, 0px;" class="arrowMarkerPath" d="M 1,1 l 9,9 M 10,1 l -9,9"></path></marker><marker orient="auto" markerHeight="11" markerWidth="11" markerUnits="userSpaceOnUse" refY="5.2" refX="-1" viewBox="0 0 11 11" class="marker cross flowchart" id="flowchart-crossStart"><path style="stroke-width: 2px; stroke-dasharray: 1px, 0px;" class="arrowMarkerPath" d="M 1,1 l 9,9 M 10,1 l -9,9"></path></marker><g class="root"><g class="clusters"><g id="igb" class="cluster default flowchart-label"><rect height="225.88333129882812" width="530.8416442871094" y="317" x="0" ry="0" rx="0" style=""></rect><g transform="translate(254.74581909179688, 317)" class="cluster-label"><foreignObject height="24" width="21.350006103515625"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">igb</span></div></foreignObject></g></g><g id="Hypervisor" class="cluster default flowchart-label"><rect height="178" width="475.9291572570801" y="89" x="18.48749542236328" ry="0" rx="0" style=""></rect><g transform="translate(218.2187442779541, 89)" class="cluster-label"><foreignObject height="24" width="76.46665954589844"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">Hypervisor</span></div></foreignObject></g></g></g><g class="edgePaths"><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-EmulatedNIC0 LE-VM0" id="L-EmulatedNIC0-VM0-0" d="M120.02083206176758,114L120.02083206176758,109.83333333333333C120.02083206176758,105.66666666666667,120.02083206176758,97.33333333333333,120.02083206176758,89C120.02083206176758,80.66666666666667,120.02083206176758,72.33333333333333,120.02083206176758,64C120.02083206176758,55.666666666666664,120.02083206176758,47.333333333333336,120.02083206176758,43.166666666666664L120.02083206176758,39"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-EmulatedNIC1 LE-VM1" id="L-EmulatedNIC1-VM1-0" d="M395.44165420532227,114L395.44165420532227,109.83333333333333C395.44165420532227,105.66666666666667,395.44165420532227,97.33333333333333,395.44165420532227,89C395.44165420532227,80.66666666666667,395.44165420532227,72.33333333333333,395.44165420532227,64C395.44165420532227,55.666666666666664,395.44165420532227,47.333333333333336,395.44165420532227,43.166666666666664L395.44165420532227,39"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Bridge LE-EmulatedNIC0" id="L-Bridge-EmulatedNIC0-0" d="M201.70621974816484,203L188.09198846709864,198.83333333333334C174.4777571860324,194.66666666666666,147.2492946239,186.33333333333334,133.63506334283377,178C120.02083206176758,169.66666666666666,120.02083206176758,161.33333333333334,120.02083206176758,157.16666666666666L120.02083206176758,153"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Bridge LE-EmulatedNIC1" id="L-Bridge-EmulatedNIC1-0" d="M322.3962429346663,203L334.5704781464423,198.83333333333334C346.74471335821835,194.66666666666666,371.0931837817703,186.33333333333334,383.2674189935463,178C395.44165420532227,169.66666666666666,395.44165420532227,161.33333333333334,395.44165420532227,157.16666666666666L395.44165420532227,153"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Queue0 LE-Bridge" id="L-Queue0-Bridge-0" d="M75.82083129882812,342L75.82083129882812,337.8333333333333C75.82083129882812,333.6666666666667,75.82083129882812,325.3333333333333,75.82083129882812,317C75.82083129882812,308.6666666666667,75.82083129882812,300.3333333333333,75.82083129882812,292C75.82083129882812,283.6666666666667,75.82083129882812,275.3333333333333,95.27638498942058,266.60035769495164C114.73193868001302,257.86738205656997,153.6430460611979,248.73476411313985,173.09859975179037,244.16845514142483L192.5541534423828,239.60214616970978"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Queue1 LE-Bridge" id="L-Queue1-Bridge-0" d="M202.2208251953125,342L202.2208251953125,337.8333333333333C202.2208251953125,333.6666666666667,202.2208251953125,325.3333333333333,202.2208251953125,317C202.2208251953125,308.6666666666667,202.2208251953125,300.3333333333333,202.2208251953125,292C202.2208251953125,283.6666666666667,202.2208251953125,275.3333333333333,208.13842790582206,267C214.05603061633164,258.6666666666667,225.89123603735075,250.33333333333334,231.80883874786034,246.16666666666666L237.72644145836992,242"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Queue2 LE-Bridge" id="L-Queue2-Bridge-0" d="M328.6208190917969,342L328.6208190917969,337.8333333333333C328.6208190917969,333.6666666666667,328.6208190917969,325.3333333333333,328.6208190917969,317C328.6208190917969,308.6666666666667,328.6208190917969,300.3333333333333,328.6208190917969,292C328.6208190917969,283.6666666666667,328.6208190917969,275.3333333333333,322.7032163812873,267C316.78561367077776,258.6666666666667,304.9504082497586,250.33333333333334,299.03280553924907,246.16666666666666L293.1152028287395,242"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Queue3 LE-Bridge" id="L-Queue3-Bridge-0" d="M455.02081298828125,342L455.02081298828125,337.8333333333333C455.02081298828125,333.6666666666667,455.02081298828125,325.3333333333333,455.02081298828125,317C455.02081298828125,308.6666666666667,455.02081298828125,300.3333333333333,455.02081298828125,292C455.02081298828125,283.6666666666667,455.02081298828125,275.3333333333333,435.5652592976888,266.60035769495164C416.1097056070964,257.86738205656997,377.19859822591144,248.73476411313985,357.74304453531903,244.16845514142483L338.28749084472656,239.60214616970978"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-RSS LE-Queue0" id="L-RSS-Queue0-0" d="M234.00140447544024,463.41941766811436L207.63797561267154,453.8495147234286C181.2745467499029,444.27961177874295,128.5476890243655,425.1398058893715,102.18426016159681,411.40323627801905C75.82083129882812,397.6666666666667,75.82083129882812,389.3333333333333,75.82083129882812,385.1666666666667L75.82083129882812,381"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-RSS LE-Queue1" id="L-RSS-Queue1-0" d="M245.06486300195078,452.3559591416039L237.92419003417774,444.62996595133654C230.7835170664047,436.90397276106927,216.5021711308586,421.4519863805346,209.36149816308554,409.55932652360065C202.2208251953125,397.6666666666667,202.2208251953125,389.3333333333333,202.2208251953125,385.1666666666667L202.2208251953125,381"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-RSS LE-Queue2" id="L-RSS-Queue2-0" d="M286.77678128515856,452.3559591416039L293.75078758626495,444.62996595133654C300.72479388737133,436.90397276106927,314.6728064895841,421.4519863805346,321.6468127906905,409.55932652360065C328.6208190917969,397.6666666666667,328.6208190917969,389.3333333333333,328.6208190917969,385.1666666666667L328.6208190917969,381"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-RSS LE-Queue3" id="L-RSS-Queue3-0" d="M297.84023981166905,463.41941766811436L324.0370020077711,453.8495147234286C350.23376420387314,444.27961177874295,402.6272885960772,425.1398058893715,428.8240507921792,411.40323627801905C455.02081298828125,397.6666666666667,455.02081298828125,389.3333333333333,455.02081298828125,385.1666666666667L455.02081298828125,381"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-ExternalHost LE-RSS" id="L-ExternalHost-RSS-0" d="M265.4208221435547,592.8833312988281L265.4208221435547,588.7166646321615C265.4208221435547,584.5499979654948,265.4208221435547,576.2166646321615,265.4208221435547,567.8833312988281C265.4208221435547,559.5499979654948,265.4208221435547,551.2166646321615,265.504155476888,542.9666646321615C265.5874888102214,534.7166646321615,265.754155476888,526.5499979654949,265.8374888102214,522.4666646321615L265.9208221435547,518.3833312988282"></path></g><g class="edgeLabels"><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g transform="translate(75.82083129882812, 361.5)" id="flowchart-Queue0-366" class="node default default flowchart-label"><rect height="39" width="76.39999389648438" y="-19.5" x="-38.19999694824219" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-30.699996948242188, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="61.399993896484375"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">Queue 0</span></div></foreignObject></g></g><g transform="translate(202.2208251953125, 361.5)" id="flowchart-Queue1-368" class="node default default flowchart-label"><rect height="39" width="76.39999389648438" y="-19.5" x="-38.19999694824219" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-30.699996948242188, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="61.399993896484375"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">Queue 1</span></div></foreignObject></g></g><g transform="translate(328.6208190917969, 361.5)" id="flowchart-Queue2-370" class="node default default flowchart-label"><rect height="39" width="76.39999389648438" y="-19.5" x="-38.19999694824219" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-30.699996948242188, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="61.399993896484375"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">Queue 2</span></div></foreignObject></g></g><g transform="translate(455.02081298828125, 361.5)" id="flowchart-Queue3-372" class="node default default flowchart-label"><rect height="39" width="76.39999389648438" y="-19.5" x="-38.19999694824219" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-30.699996948242188, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="61.399993896484375"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">Queue 3</span></div></foreignObject></g></g><g transform="translate(265.4208221435547, 474.44166564941406)" id="flowchart-RSS-374" class="node default default flowchart-label"><polygon style="" transform="translate(-43.44166564941406,43.44166564941406)" class="label-container" points="43.44166564941406,0 86.88333129882812,-43.44166564941406 43.44166564941406,-86.88333129882812 0,-43.44166564941406"></polygon><g transform="translate(-16.441665649414062, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="32.883331298828125"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">RSS</span></div></foreignObject></g></g><g transform="translate(120.02083206176758, 133.5)" id="flowchart-EmulatedNIC0-358" class="node default default flowchart-label"><rect height="39" width="127.94999694824219" y="-19.5" x="-63.974998474121094" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-56.474998474121094, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="112.94999694824219"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">Emulated NIC 0</span></div></foreignObject></g></g><g transform="translate(265.4208221435547, 222.5)" id="flowchart-Bridge-362" class="node default default flowchart-label"><rect height="39" width="145.73333740234375" y="-19.5" x="-72.86666870117188" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-65.36666870117188, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="130.73333740234375"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">L2 Switch (Bridge)</span></div></foreignObject></g></g><g transform="translate(395.44165420532227, 133.5)" id="flowchart-EmulatedNIC1-360" class="node default default flowchart-label"><rect height="39" width="127.94999694824219" y="-19.5" x="-63.974998474121094" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-56.474998474121094, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="112.94999694824219"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">Emulated NIC 1</span></div></foreignObject></g></g><g transform="translate(120.02083206176758, 19.5)" id="flowchart-VM0-359" class="node default default flowchart-label"><rect height="39" width="52.350006103515625" y="-19.5" x="-26.175003051757812" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-18.675003051757812, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="37.350006103515625"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">VM 0</span></div></foreignObject></g></g><g transform="translate(395.44165420532227, 19.5)" id="flowchart-VM1-361" class="node default default flowchart-label"><rect height="39" width="52.350006103515625" y="-19.5" x="-26.175003051757812" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-18.675003051757812, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="37.350006103515625"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">VM 1</span></div></foreignObject></g></g><g transform="translate(265.4208221435547, 612.3833312988281)" id="flowchart-ExternalHost-382" class="node default default flowchart-label"><rect height="39" width="111.05000305175781" y="-19.5" x="-55.525001525878906" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-48.025001525878906, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="96.05000305175781"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">External Host</span></div></foreignObject></g></g></g></g></g></svg>

<p>In this diagram, packets are first stored in queues determined with RSS. The
hypervisor acquires these stored packets and performs L2 switching to route them
to appropriate VMs. This switching imposes a substantial load on the host.</p>

<p>With VMDq enabled, igb automatically performs this switching and assigns packets
to different queues accordingly, reducing the load of the host:</p>

<svg aria-roledescription="flowchart-v2" role="graphics-document document" viewBox="-8 -8 565.0833129882812 732.25" style="max-width: 100%;" xmlns="http://www.w3.org/2000/svg" width="100%" id="graph-div" height="100%" xmlns:xlink="http://www.w3.org/1999/xlink"><style>@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css");'</style><style>#graph-div{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#graph-div .error-icon{fill:#552222;}#graph-div .error-text{fill:#552222;stroke:#552222;}#graph-div .edge-thickness-normal{stroke-width:2px;}#graph-div .edge-thickness-thick{stroke-width:3.5px;}#graph-div .edge-pattern-solid{stroke-dasharray:0;}#graph-div .edge-pattern-dashed{stroke-dasharray:3;}#graph-div .edge-pattern-dotted{stroke-dasharray:2;}#graph-div .marker{fill:#333333;stroke:#333333;}#graph-div .marker.cross{stroke:#333333;}#graph-div svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#graph-div .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#graph-div .cluster-label text{fill:#333;}#graph-div .cluster-label span,#graph-div p{color:#333;}#graph-div .label text,#graph-div span,#graph-div p{fill:#333;color:#333;}#graph-div .node rect,#graph-div .node circle,#graph-div .node ellipse,#graph-div .node polygon,#graph-div .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#graph-div .flowchart-label text{text-anchor:middle;}#graph-div .node .label{text-align:center;}#graph-div .node.clickable{cursor:pointer;}#graph-div .arrowheadPath{fill:#333333;}#graph-div .edgePath .path{stroke:#333333;stroke-width:2.0px;}#graph-div .flowchart-link{stroke:#333333;fill:none;}#graph-div .edgeLabel{background-color:#e8e8e8;text-align:center;}#graph-div .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#graph-div .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#graph-div .cluster text{fill:#333;}#graph-div .cluster span,#graph-div p{color:#333;}#graph-div div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#graph-div .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#graph-div :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker orient="auto" markerHeight="12" markerWidth="12" markerUnits="userSpaceOnUse" refY="5" refX="10" viewBox="0 0 12 20" class="marker flowchart" id="flowchart-pointEnd"><path style="stroke-width: 1px; stroke-dasharray: 1px, 0px;" class="arrowMarkerPath" d="M 0 0 L 10 5 L 0 10 z"></path></marker><marker orient="auto" markerHeight="12" markerWidth="12" markerUnits="userSpaceOnUse" refY="5" refX="0" viewBox="0 0 10 10" class="marker flowchart" id="flowchart-pointStart"><path style="stroke-width: 1px; stroke-dasharray: 1px, 0px;" class="arrowMarkerPath" d="M 0 5 L 10 10 L 10 0 z"></path></marker><marker orient="auto" markerHeight="11" markerWidth="11" markerUnits="userSpaceOnUse" refY="5" refX="11" viewBox="0 0 10 10" class="marker flowchart" id="flowchart-circleEnd"><circle style="stroke-width: 1px; stroke-dasharray: 1px, 0px;" class="arrowMarkerPath" r="5" cy="5" cx="5"></circle></marker><marker orient="auto" markerHeight="11" markerWidth="11" markerUnits="userSpaceOnUse" refY="5" refX="-1" viewBox="0 0 10 10" class="marker flowchart" id="flowchart-circleStart"><circle style="stroke-width: 1px; stroke-dasharray: 1px, 0px;" class="arrowMarkerPath" r="5" cy="5" cx="5"></circle></marker><marker orient="auto" markerHeight="11" markerWidth="11" markerUnits="userSpaceOnUse" refY="5.2" refX="12" viewBox="0 0 11 11" class="marker cross flowchart" id="flowchart-crossEnd"><path style="stroke-width: 2px; stroke-dasharray: 1px, 0px;" class="arrowMarkerPath" d="M 1,1 l 9,9 M 10,1 l -9,9"></path></marker><marker orient="auto" markerHeight="11" markerWidth="11" markerUnits="userSpaceOnUse" refY="5.2" refX="-1" viewBox="0 0 11 11" class="marker cross flowchart" id="flowchart-crossStart"><path style="stroke-width: 2px; stroke-dasharray: 1px, 0px;" class="arrowMarkerPath" d="M 1,1 l 9,9 M 10,1 l -9,9"></path></marker><g class="root"><g class="clusters"><g id="igb" class="cluster default flowchart-label"><rect height="399.25" width="549.0833129882812" y="228" x="0" ry="0" rx="0" style=""></rect><g transform="translate(263.8666534423828, 228)" class="cluster-label"><foreignObject height="24" width="21.350006103515625"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">igb</span></div></foreignObject></g></g><g id="Hypervisor" class="cluster default flowchart-label"><rect height="89" width="508.1749801635742" y="89" x="15.454166412353516" ry="0" rx="0" style=""></rect><g transform="translate(231.3083267211914, 89)" class="cluster-label"><foreignObject height="24" width="76.46665954589844"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">Hypervisor</span></div></foreignObject></g></g></g><g class="edgePaths"><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-EmulatedNIC0 LE-VM0" id="L-EmulatedNIC0-VM0-0" d="M148.14166259765625,114L148.14166259765625,109.83333333333333C148.14166259765625,105.66666666666667,148.14166259765625,97.33333333333333,148.14166259765625,89C148.14166259765625,80.66666666666667,148.14166259765625,72.33333333333333,148.14166259765625,64C148.14166259765625,55.666666666666664,148.14166259765625,47.333333333333336,148.14166259765625,43.166666666666664L148.14166259765625,39"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-EmulatedNIC1 LE-VM1" id="L-EmulatedNIC1-VM1-0" d="M400.941650390625,114L400.941650390625,109.83333333333333C400.941650390625,105.66666666666667,400.941650390625,97.33333333333333,400.941650390625,89C400.941650390625,80.66666666666667,400.941650390625,72.33333333333333,400.941650390625,64C400.941650390625,55.666666666666664,400.941650390625,47.333333333333336,400.941650390625,43.166666666666664L400.941650390625,39"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Queue0 LE-EmulatedNIC0" id="L-Queue0-EmulatedNIC0-0" d="M84.94166564941406,253L84.94166564941406,248.83333333333334C84.94166564941406,244.66666666666666,84.94166564941406,236.33333333333334,84.94166564941406,228C84.94166564941406,219.66666666666666,84.94166564941406,211.33333333333334,84.94166564941406,203C84.94166564941406,194.66666666666666,84.94166564941406,186.33333333333334,90.85926835992363,178C96.77687107043319,169.66666666666666,108.61207649145233,161.33333333333334,114.52967920196188,157.16666666666666L120.44728191247147,153"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Queue1 LE-EmulatedNIC0" id="L-Queue1-EmulatedNIC0-0" d="M211.34165954589844,253L211.34165954589844,248.83333333333334C211.34165954589844,244.66666666666666,211.34165954589844,236.33333333333334,211.34165954589844,228C211.34165954589844,219.66666666666666,211.34165954589844,211.33333333333334,211.34165954589844,203C211.34165954589844,194.66666666666666,211.34165954589844,186.33333333333334,205.42405683538888,178C199.5064541248793,169.66666666666666,187.6712487038602,161.33333333333334,181.75364599335057,157.16666666666666L175.83604328284102,153"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Queue2 LE-EmulatedNIC1" id="L-Queue2-EmulatedNIC1-0" d="M337.7416534423828,253L337.7416534423828,248.83333333333334C337.7416534423828,244.66666666666666,337.7416534423828,236.33333333333334,337.7416534423828,228C337.7416534423828,219.66666666666666,337.7416534423828,211.33333333333334,337.7416534423828,203C337.7416534423828,194.66666666666666,337.7416534423828,186.33333333333334,343.65925615289234,178C349.5768588634019,169.66666666666666,361.4120642844211,161.33333333333334,367.3296669949306,157.16666666666666L373.2472697054402,153"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Queue3 LE-EmulatedNIC1" id="L-Queue3-EmulatedNIC1-0" d="M464.1416473388672,253L464.1416473388672,248.83333333333334C464.1416473388672,244.66666666666666,464.1416473388672,236.33333333333334,464.1416473388672,228C464.1416473388672,219.66666666666666,464.1416473388672,211.33333333333334,464.1416473388672,203C464.1416473388672,194.66666666666666,464.1416473388672,186.33333333333334,458.22404462835766,178C452.3064419178481,169.66666666666666,440.4712364968289,161.33333333333334,434.5536337863194,157.16666666666666L428.6360310758098,153"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-RSS0 LE-Queue0" id="L-RSS0-Queue0-0" d="M127.78570345605236,363.3559591416039L120.6450304882793,355.62996595133654C113.50435752050628,347.90397276106927,99.22301158496016,332.4519863805346,92.08233861718712,320.55932652360065C84.94166564941406,308.6666666666667,84.94166564941406,300.3333333333333,84.94166564941406,296.1666666666667L84.94166564941406,292"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-RSS0 LE-Queue1" id="L-RSS0-Queue1-0" d="M169.49762173926018,363.35595914160393L176.47162804036657,355.6299659513366C183.44563434147292,347.9039727610693,197.3936469436857,332.45198638053466,204.36765324479208,320.55932652360065C211.34165954589844,308.6666666666667,211.34165954589844,300.3333333333333,211.34165954589844,296.1666666666667L211.34165954589844,292"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-RSS1 LE-Queue2" id="L-RSS1-Queue2-0" d="M380.5856912490211,363.3559591416039L373.4450182812481,355.62996595133654C366.30434531347504,347.90397276106927,352.02299937792895,332.4519863805346,344.8823264101559,320.55932652360065C337.7416534423828,308.6666666666667,337.7416534423828,300.3333333333333,337.7416534423828,296.1666666666667L337.7416534423828,292"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-RSS1 LE-Queue3" id="L-RSS1-Queue3-0" d="M422.2976095322289,363.35595914160393L429.27161583333526,355.6299659513366C436.24562213444165,347.9039727610693,450.19363473665436,332.45198638053466,457.1676410377608,320.55932652360065C464.1416473388672,308.6666666666667,464.1416473388672,300.3333333333333,464.1416473388672,296.1666666666667L464.1416473388672,292"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-L2Switch LE-RSS0" id="L-L2Switch-RSS0-0" d="M238.45140258000757,515.9735852129612L223.39977924961568,505.6252095606057C208.34815591922379,495.2768339082502,178.24490925844,474.5800826035391,163.27661926138146,460.14837361785027C148.3083292643229,445.71666463216144,148.4749959309896,437.5499979654948,148.5583292643229,433.46666463216144L148.64166259765625,429.3833312988281"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-L2Switch LE-RSS1" id="L-L2Switch-RSS1-0" d="M311.6319104082737,515.9735852129612L326.5168670719989,505.6252095606057C341.4018237357241,495.2768339082502,371.17173706317453,474.5800826035391,386.1400270602331,460.14837361785027C401.1083170572917,445.71666463216144,401.2749837239583,437.5499979654948,401.3583170572916,433.46666463216144L401.44165039062494,429.3833312988281"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-ExternalHost LE-L2Switch" id="L-ExternalHost-L2Switch-0" d="M274.5416564941406,677.25L274.5416564941406,673.0833333333334C274.5416564941406,668.9166666666666,274.5416564941406,660.5833333333334,274.5416564941406,652.25C274.5416564941406,643.9166666666666,274.5416564941406,635.5833333333334,274.62498982747394,627.3333333333334C274.7083231608073,619.0833333333334,274.87498982747394,610.9166666666666,274.9583231608073,606.8333333333334L275.0416564941406,602.75"></path></g><g class="edgeLabels"><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g transform="translate(84.94166564941406, 272.5)" id="flowchart-Queue0-504" class="node default default flowchart-label"><rect height="39" width="76.39999389648438" y="-19.5" x="-38.19999694824219" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-30.699996948242188, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="61.399993896484375"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">Queue 0</span></div></foreignObject></g></g><g transform="translate(211.34165954589844, 272.5)" id="flowchart-Queue1-506" class="node default default flowchart-label"><rect height="39" width="76.39999389648438" y="-19.5" x="-38.19999694824219" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-30.699996948242188, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="61.399993896484375"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">Queue 1</span></div></foreignObject></g></g><g transform="translate(337.7416534423828, 272.5)" id="flowchart-Queue2-508" class="node default default flowchart-label"><rect height="39" width="76.39999389648438" y="-19.5" x="-38.19999694824219" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-30.699996948242188, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="61.399993896484375"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">Queue 2</span></div></foreignObject></g></g><g transform="translate(464.1416473388672, 272.5)" id="flowchart-Queue3-510" class="node default default flowchart-label"><rect height="39" width="76.39999389648438" y="-19.5" x="-38.19999694824219" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-30.699996948242188, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="61.399993896484375"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">Queue 3</span></div></foreignObject></g></g><g transform="translate(148.14166259765625, 385.44166564941406)" id="flowchart-RSS0-512" class="node default default flowchart-label"><polygon style="" transform="translate(-43.44166564941406,43.44166564941406)" class="label-container" points="43.44166564941406,0 86.88333129882812,-43.44166564941406 43.44166564941406,-86.88333129882812 0,-43.44166564941406"></polygon><g transform="translate(-16.441665649414062, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="32.883331298828125"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">RSS</span></div></foreignObject></g></g><g transform="translate(400.941650390625, 385.44166564941406)" id="flowchart-RSS1-516" class="node default default flowchart-label"><polygon style="" transform="translate(-43.44166564941406,43.44166564941406)" class="label-container" points="43.44166564941406,0 86.88333129882812,-43.44166564941406 43.44166564941406,-86.88333129882812 0,-43.44166564941406"></polygon><g transform="translate(-16.441665649414062, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="32.883331298828125"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">RSS</span></div></foreignObject></g></g><g transform="translate(274.5416564941406, 540.5666656494141)" id="flowchart-L2Switch-520" class="node default default flowchart-label"><polygon style="" transform="translate(-61.68333435058594,61.68333435058594)" class="label-container" points="61.68333435058594,0 123.36666870117188,-61.68333435058594 61.68333435058594,-123.36666870117188 0,-61.68333435058594"></polygon><g transform="translate(-34.68333435058594, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="69.36666870117188"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">L2 Switch</span></div></foreignObject></g></g><g transform="translate(148.14166259765625, 133.5)" id="flowchart-EmulatedNIC0-498" class="node default default flowchart-label"><rect height="39" width="127.94999694824219" y="-19.5" x="-63.974998474121094" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-56.474998474121094, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="112.94999694824219"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">Emulated NIC 0</span></div></foreignObject></g></g><g transform="translate(400.941650390625, 133.5)" id="flowchart-EmulatedNIC1-500" class="node default default flowchart-label"><rect height="39" width="127.94999694824219" y="-19.5" x="-63.974998474121094" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-56.474998474121094, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="112.94999694824219"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">Emulated NIC 1</span></div></foreignObject></g></g><g transform="translate(148.14166259765625, 19.5)" id="flowchart-VM0-499" class="node default default flowchart-label"><rect height="39" width="52.350006103515625" y="-19.5" x="-26.175003051757812" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-18.675003051757812, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="37.350006103515625"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">VM 0</span></div></foreignObject></g></g><g transform="translate(400.941650390625, 19.5)" id="flowchart-VM1-501" class="node default default flowchart-label"><rect height="39" width="52.350006103515625" y="-19.5" x="-26.175003051757812" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-18.675003051757812, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="37.350006103515625"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">VM 1</span></div></foreignObject></g></g><g transform="translate(274.5416564941406, 696.75)" id="flowchart-ExternalHost-524" class="node default default flowchart-label"><rect height="39" width="111.05000305175781" y="-19.5" x="-55.525001525878906" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-48.025001525878906, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="96.05000305175781"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">External Host</span></div></foreignObject></g></g></g></g></g></svg>

<p>This L2 switching is achieved with the packet filtering capability igb has.
e1000e can filter packets by the destination MAC address, and igb extends this
feature further by allowing the driver to configure different filters for
queues.</p>

<h3 id="sr-iov">SR-IOV</h3>

<p>VMDq is more effective when combined with igb’s <em>SR-IOV</em> feature. SR-IOV is
an extension of PCIe to allow a device to export several <em>virtual functions</em>
which looks like different devices for the operating system. Virtual functions
can be directly assigned to VMs (by using
<a href="https://docs.kernel.org/driver-api/vfio.html">VFIO</a> in the case of Linux),
which removes the hypervisor from the traffic path between the VM and hardware:</p>

<svg aria-roledescription="flowchart-v2" role="graphics-document document" viewBox="-8 -8 565.0833129882812 682.25" style="max-width: 100%;" xmlns="http://www.w3.org/2000/svg" width="100%" id="graph-div" height="100%" xmlns:xlink="http://www.w3.org/1999/xlink"><style>@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css");'</style><style>#graph-div{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#graph-div .error-icon{fill:#552222;}#graph-div .error-text{fill:#552222;stroke:#552222;}#graph-div .edge-thickness-normal{stroke-width:2px;}#graph-div .edge-thickness-thick{stroke-width:3.5px;}#graph-div .edge-pattern-solid{stroke-dasharray:0;}#graph-div .edge-pattern-dashed{stroke-dasharray:3;}#graph-div .edge-pattern-dotted{stroke-dasharray:2;}#graph-div .marker{fill:#333333;stroke:#333333;}#graph-div .marker.cross{stroke:#333333;}#graph-div svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#graph-div .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#graph-div .cluster-label text{fill:#333;}#graph-div .cluster-label span,#graph-div p{color:#333;}#graph-div .label text,#graph-div span,#graph-div p{fill:#333;color:#333;}#graph-div .node rect,#graph-div .node circle,#graph-div .node ellipse,#graph-div .node polygon,#graph-div .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#graph-div .flowchart-label text{text-anchor:middle;}#graph-div .node .label{text-align:center;}#graph-div .node.clickable{cursor:pointer;}#graph-div .arrowheadPath{fill:#333333;}#graph-div .edgePath .path{stroke:#333333;stroke-width:2.0px;}#graph-div .flowchart-link{stroke:#333333;fill:none;}#graph-div .edgeLabel{background-color:#e8e8e8;text-align:center;}#graph-div .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#graph-div .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#graph-div .cluster text{fill:#333;}#graph-div .cluster span,#graph-div p{color:#333;}#graph-div div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#graph-div .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#graph-div :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker orient="auto" markerHeight="12" markerWidth="12" markerUnits="userSpaceOnUse" refY="5" refX="10" viewBox="0 0 12 20" class="marker flowchart" id="flowchart-pointEnd"><path style="stroke-width: 1px; stroke-dasharray: 1px, 0px;" class="arrowMarkerPath" d="M 0 0 L 10 5 L 0 10 z"></path></marker><marker orient="auto" markerHeight="12" markerWidth="12" markerUnits="userSpaceOnUse" refY="5" refX="0" viewBox="0 0 10 10" class="marker flowchart" id="flowchart-pointStart"><path style="stroke-width: 1px; stroke-dasharray: 1px, 0px;" class="arrowMarkerPath" d="M 0 5 L 10 10 L 10 0 z"></path></marker><marker orient="auto" markerHeight="11" markerWidth="11" markerUnits="userSpaceOnUse" refY="5" refX="11" viewBox="0 0 10 10" class="marker flowchart" id="flowchart-circleEnd"><circle style="stroke-width: 1px; stroke-dasharray: 1px, 0px;" class="arrowMarkerPath" r="5" cy="5" cx="5"></circle></marker><marker orient="auto" markerHeight="11" markerWidth="11" markerUnits="userSpaceOnUse" refY="5" refX="-1" viewBox="0 0 10 10" class="marker flowchart" id="flowchart-circleStart"><circle style="stroke-width: 1px; stroke-dasharray: 1px, 0px;" class="arrowMarkerPath" r="5" cy="5" cx="5"></circle></marker><marker orient="auto" markerHeight="11" markerWidth="11" markerUnits="userSpaceOnUse" refY="5.2" refX="12" viewBox="0 0 11 11" class="marker cross flowchart" id="flowchart-crossEnd"><path style="stroke-width: 2px; stroke-dasharray: 1px, 0px;" class="arrowMarkerPath" d="M 1,1 l 9,9 M 10,1 l -9,9"></path></marker><marker orient="auto" markerHeight="11" markerWidth="11" markerUnits="userSpaceOnUse" refY="5.2" refX="-1" viewBox="0 0 11 11" class="marker cross flowchart" id="flowchart-crossStart"><path style="stroke-width: 2px; stroke-dasharray: 1px, 0px;" class="arrowMarkerPath" d="M 1,1 l 9,9 M 10,1 l -9,9"></path></marker><g class="root"><g class="clusters"><g id="igb" class="cluster default flowchart-label"><rect height="488.25" width="549.0833129882812" y="89" x="0" ry="0" rx="0" style=""></rect><g transform="translate(263.8666534423828, 89)" class="cluster-label"><foreignObject height="24" width="21.350006103515625"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">igb</span></div></foreignObject></g></g></g><g class="edgePaths"><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-VF0 LE-VM0" id="L-VF0-VM0-0" d="M148.14166259765625,114L148.14166259765625,109.83333333333333C148.14166259765625,105.66666666666667,148.14166259765625,97.33333333333333,148.14166259765625,89C148.14166259765625,80.66666666666667,148.14166259765625,72.33333333333333,148.14166259765625,64C148.14166259765625,55.666666666666664,148.14166259765625,47.333333333333336,148.14166259765625,43.166666666666664L148.14166259765625,39"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-VF1 LE-VM1" id="L-VF1-VM1-0" d="M400.941650390625,114L400.941650390625,109.83333333333333C400.941650390625,105.66666666666667,400.941650390625,97.33333333333333,400.941650390625,89C400.941650390625,80.66666666666667,400.941650390625,72.33333333333333,400.941650390625,64C400.941650390625,55.666666666666664,400.941650390625,47.333333333333336,400.941650390625,43.166666666666664L400.941650390625,39"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Queue0 LE-VF0" id="L-Queue0-VF0-0" d="M84.94166564941406,203L84.94166564941406,198.83333333333334C84.94166564941406,194.66666666666666,84.94166564941406,186.33333333333334,91.40972010294597,177.61241924450482C97.87777455647786,168.89150515567627,110.81388346354167,159.78301031135254,117.28193791707356,155.22876288919068L123.74999237060547,150.6745154670288"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Queue1 LE-VF0" id="L-Queue1-VF0-0" d="M211.34165954589844,203L211.34165954589844,198.83333333333334C211.34165954589844,194.66666666666666,211.34165954589844,186.33333333333334,204.87360509236655,177.61241924450482C198.40555063883463,168.89150515567627,185.46944173177084,159.78301031135254,179.00138727823892,155.22876288919068L172.53333282470703,150.6745154670288"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Queue2 LE-VF1" id="L-Queue2-VF1-0" d="M337.7416534423828,203L337.7416534423828,198.83333333333334C337.7416534423828,194.66666666666666,337.7416534423828,186.33333333333334,344.20970789591473,177.61241924450482C350.6777623494466,168.89150515567627,363.61387125651044,159.78301031135254,370.0819257100423,155.22876288919068L376.5499801635742,150.6745154670288"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Queue3 LE-VF1" id="L-Queue3-VF1-0" d="M464.1416473388672,203L464.1416473388672,198.83333333333334C464.1416473388672,194.66666666666666,464.1416473388672,186.33333333333334,457.67359288533527,177.61241924450482C451.2055384318034,168.89150515567627,438.26942952473956,159.78301031135254,431.8013750712077,155.22876288919068L425.3333206176758,150.6745154670288"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-RSS0 LE-Queue0" id="L-RSS0-Queue0-0" d="M127.78570345605233,313.3559591416039L120.64503048827929,305.62996595133654C113.50435752050623,297.90397276106927,99.22301158496015,282.4519863805346,92.08233861718709,270.55932652360065C84.94166564941406,258.6666666666667,84.94166564941406,250.33333333333334,84.94166564941406,246.16666666666666L84.94166564941406,242"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-RSS0 LE-Queue1" id="L-RSS0-Queue1-0" d="M169.49762173926018,313.35595914160393L176.47162804036657,305.6299659513366C183.44563434147292,297.90397276106927,197.3936469436857,282.45198638053466,204.36765324479208,270.55932652360065C211.34165954589844,258.6666666666667,211.34165954589844,250.33333333333334,211.34165954589844,246.16666666666666L211.34165954589844,242"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-RSS1 LE-Queue2" id="L-RSS1-Queue2-0" d="M380.5856912490211,313.3559591416039L373.4450182812481,305.62996595133654C366.30434531347504,297.90397276106927,352.02299937792895,282.4519863805346,344.8823264101559,270.55932652360065C337.7416534423828,258.6666666666667,337.7416534423828,250.33333333333334,337.7416534423828,246.16666666666666L337.7416534423828,242"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-RSS1 LE-Queue3" id="L-RSS1-Queue3-0" d="M422.2976095322289,313.35595914160393L429.27161583333526,305.6299659513366C436.24562213444165,297.90397276106927,450.19363473665436,282.45198638053466,457.1676410377608,270.55932652360065C464.1416473388672,258.6666666666667,464.1416473388672,250.33333333333334,464.1416473388672,246.16666666666666L464.1416473388672,242"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-L2Switch LE-RSS0" id="L-L2Switch-RSS0-0" d="M238.45140258000757,465.9735852129612L223.39977924961568,455.6252095606057C208.34815591922379,445.2768339082502,178.24490925844,424.5800826035391,163.27661926138146,410.14837361785027C148.3083292643229,395.71666463216144,148.4749959309896,387.5499979654948,148.5583292643229,383.46666463216144L148.64166259765625,379.3833312988281"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-L2Switch LE-RSS1" id="L-L2Switch-RSS1-0" d="M311.6319104082737,465.97358521296115L326.5168670719989,455.6252095606057C341.4018237357241,445.2768339082501,371.17173706317453,424.5800826035391,386.1400270602331,410.14837361785027C401.1083170572917,395.71666463216144,401.2749837239583,387.5499979654948,401.3583170572916,383.46666463216144L401.44165039062494,379.3833312988281"></path><path marker-end="url(#flowchart-pointEnd)" style="fill:none;" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-ExternalHost LE-L2Switch" id="L-ExternalHost-L2Switch-0" d="M274.5416564941406,627.25L274.5416564941406,623.0833333333334C274.5416564941406,618.9166666666666,274.5416564941406,610.5833333333334,274.5416564941406,602.25C274.5416564941406,593.9166666666666,274.5416564941406,585.5833333333334,274.62498982747394,577.3333333333334C274.7083231608073,569.0833333333334,274.87498982747394,560.9166666666666,274.9583231608073,556.8333333333334L275.0416564941406,552.75"></path></g><g class="edgeLabels"><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g transform="translate(0, 0)" class="label"><foreignObject height="0" width="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g transform="translate(148.14166259765625, 133.5)" id="flowchart-VF0-632" class="node default default flowchart-label"><rect height="39" width="48.78334045410156" y="-19.5" x="-24.39167022705078" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-16.89167022705078, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="33.78334045410156"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">VF 0</span></div></foreignObject></g></g><g transform="translate(84.94166564941406, 222.5)" id="flowchart-Queue0-636" class="node default default flowchart-label"><rect height="39" width="76.39999389648438" y="-19.5" x="-38.19999694824219" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-30.699996948242188, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="61.399993896484375"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">Queue 0</span></div></foreignObject></g></g><g transform="translate(211.34165954589844, 222.5)" id="flowchart-Queue1-638" class="node default default flowchart-label"><rect height="39" width="76.39999389648438" y="-19.5" x="-38.19999694824219" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-30.699996948242188, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="61.399993896484375"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">Queue 1</span></div></foreignObject></g></g><g transform="translate(400.941650390625, 133.5)" id="flowchart-VF1-634" class="node default default flowchart-label"><rect height="39" width="48.78334045410156" y="-19.5" x="-24.39167022705078" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-16.89167022705078, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="33.78334045410156"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">VF 1</span></div></foreignObject></g></g><g transform="translate(337.7416534423828, 222.5)" id="flowchart-Queue2-640" class="node default default flowchart-label"><rect height="39" width="76.39999389648438" y="-19.5" x="-38.19999694824219" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-30.699996948242188, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="61.399993896484375"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">Queue 2</span></div></foreignObject></g></g><g transform="translate(464.1416473388672, 222.5)" id="flowchart-Queue3-642" class="node default default flowchart-label"><rect height="39" width="76.39999389648438" y="-19.5" x="-38.19999694824219" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-30.699996948242188, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="61.399993896484375"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">Queue 3</span></div></foreignObject></g></g><g transform="translate(148.14166259765625, 335.44166564941406)" id="flowchart-RSS0-644" class="node default default flowchart-label"><polygon style="" transform="translate(-43.44166564941406,43.44166564941406)" class="label-container" points="43.44166564941406,0 86.88333129882812,-43.44166564941406 43.44166564941406,-86.88333129882812 0,-43.44166564941406"></polygon><g transform="translate(-16.441665649414062, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="32.883331298828125"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">RSS</span></div></foreignObject></g></g><g transform="translate(400.941650390625, 335.44166564941406)" id="flowchart-RSS1-648" class="node default default flowchart-label"><polygon style="" transform="translate(-43.44166564941406,43.44166564941406)" class="label-container" points="43.44166564941406,0 86.88333129882812,-43.44166564941406 43.44166564941406,-86.88333129882812 0,-43.44166564941406"></polygon><g transform="translate(-16.441665649414062, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="32.883331298828125"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">RSS</span></div></foreignObject></g></g><g transform="translate(274.5416564941406, 490.56666564941406)" id="flowchart-L2Switch-652" class="node default default flowchart-label"><polygon style="" transform="translate(-61.68333435058594,61.68333435058594)" class="label-container" points="61.68333435058594,0 123.36666870117188,-61.68333435058594 61.68333435058594,-123.36666870117188 0,-61.68333435058594"></polygon><g transform="translate(-34.68333435058594, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="69.36666870117188"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">L2 Switch</span></div></foreignObject></g></g><g transform="translate(148.14166259765625, 19.5)" id="flowchart-VM0-633" class="node default default flowchart-label"><rect height="39" width="52.350006103515625" y="-19.5" x="-26.175003051757812" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-18.675003051757812, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="37.350006103515625"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">VM 0</span></div></foreignObject></g></g><g transform="translate(400.941650390625, 19.5)" id="flowchart-VM1-635" class="node default default flowchart-label"><rect height="39" width="52.350006103515625" y="-19.5" x="-26.175003051757812" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-18.675003051757812, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="37.350006103515625"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">VM 1</span></div></foreignObject></g></g><g transform="translate(274.5416564941406, 646.75)" id="flowchart-ExternalHost-656" class="node default default flowchart-label"><rect height="39" width="111.05000305175781" y="-19.5" x="-55.525001525878906" ry="0" rx="0" style="" class="basic label-container"></rect><g transform="translate(-48.025001525878906, -12)" style="" class="label"><rect></rect><foreignObject height="24" width="96.05000305175781"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">External Host</span></div></foreignObject></g></g></g></g></g></svg>

<p>The context switch between the hypervisor and VM incurs significant overhead so
bypassing the hypervisor can result in a great performance gain.</p>

<h2 id="summary">Summary</h2>

<p>This article introduced QEMU device emulator development in general and igb,
QEMU’s new NIC emulation.
<a href="/2023/05/12/igb-developing-a-new-device-for-qemu-part-2-implementing-basic-features.html">The next post</a>
will discuss the first step of a new device emulator development: writing a
boilerplate and adding basic features. The goal of this step is to get the
emulated device to work (even though the functionality may be limited) and to
create the foundation for further development.</p>]]></content><author><name>Akihiko Odaki</name></author><summary type="html"><![CDATA[QEMU is a machine emulator and virtualizer; it emulates or virtualizes various devices which consist in a machine. Such emulated/virtualized devices include but are not limited to CPU, memory, storage, bus, serial console, and network interface. QEMU is under active development, and there is always demand for new device implementations. However, the journey of new device implementation is complex and not always smooth.]]></summary></entry><entry><title type="html">Guest Windows debugging and crashdumping under QEMU/KVM: dump-guest-memory, vmcoreinfo and virtio-win</title><link href="https://daynix.github.io/2023/02/19/Guest-Windows-debugging-and-crashdumping-under-QEMU-KVM-dump-guest-memory-vmcoreinfo-and-virtio-win.html" rel="alternate" type="text/html" title="Guest Windows debugging and crashdumping under QEMU/KVM: dump-guest-memory, vmcoreinfo and virtio-win" /><published>2023-02-19T20:15:00+00:00</published><updated>2023-02-19T20:15:00+00:00</updated><id>https://daynix.github.io/2023/02/19/Guest-Windows-debugging-and-crashdumping-under-QEMU-KVM-dump-guest-memory-vmcoreinfo-and-virtio-win</id><content type="html" xml:base="https://daynix.github.io/2023/02/19/Guest-Windows-debugging-and-crashdumping-under-QEMU-KVM-dump-guest-memory-vmcoreinfo-and-virtio-win.html"><![CDATA[<p>In the previous <a href="/2023/01/20/Guest-Windows-debugging-and-crashdumping-under-QEMU-KVM-Introduction.html">introductory article</a> we’ve discussed crash dump capturing and debugging of guest Windows with built-in tools. This post address a case when Windows can’t produce the Complete Memory Dump during BSoD by itself or a live dump is needed. We will discuss QEMU’s command <code class="language-plaintext highlighter-rouge">dump-guest-memory -w</code> which captures guest Windows dump in WinDbg-readable DMP format and saves it on the host side.</p>

<h2 id="preparation">Preparation</h2>

<p>This method is applicable for all Windows versions from Windows Server 2012 to, at least, Windows Server 2022 (in other words, any of the versions supported by Microsoft as of 2023) for both 32-bit and 64-bit platforms. It requires two things:</p>
<ul>
  <li>vmcoreinfo device on the QEMU side</li>
  <li>FwCfg driver on the guest side</li>
</ul>

<h3 id="vmcoreinfo">vmcoreinfo</h3>

<p>If QEMU is run from the command line, add <code class="language-plaintext highlighter-rouge">-device vmcoreinfo</code> to argument list. In case of <a href="https://libvirt.org/formatdomain.html">libvirt</a>, add <code class="language-plaintext highlighter-rouge">&lt;vmcoreinfo state='on'/&gt;</code> to the XML config under <code class="language-plaintext highlighter-rouge">&lt;features&gt;&lt;/features&gt;</code>.</p>

<h3 id="virtio-win">virtio-win</h3>

<p>Install FwCfg driver from <a href="https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/latest-virtio/">virtio-win</a> to the guest Windows. <strong>Note:</strong> There is also <a href="https://github.com/virtio-win/kvm-guest-drivers-windows/tree/02.12.2021-last-buildable-point-Win7/fwcfg64">an old driver</a> which doesn’t support 32-bit platform, but supports deprecated Windows kernel versions starting from 6.1 (Windows 7 and Windows Server 2008 R2).</p>

<h2 id="capturing-crash-or-live-dump">Capturing crash or live dump</h2>

<p>When either the system is still alive, or a BSoD occurs and the system does not reboot (this can be achieved using PVPanic device or unchecking “Automatically restart” option), the following command can be executed in QEMU monitor:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dump-guest-memory -w memory.dmp
</code></pre></div></div>
<p>The Complete Memory Dump will be written to <code class="language-plaintext highlighter-rouge">memory.dmp</code> file. Then it can be opened in WinDbg like any other dump.</p>

<h2 id="typical-issues">Typical issues</h2>

<p>These are messages typically reported by <code class="language-plaintext highlighter-rouge">dump-guest-memory -w</code>:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">win-dump: invalid vmcoreinfo note size</code>: most likely, guest driver is not running yet (too early stage of Windows kernel initiatization) or not present at all, so the dump can’t be captured</li>
  <li><code class="language-plaintext highlighter-rouge">win-dump: number of QEMU CPUs is bigger than NumberProcessors (%u) in guest Windows</code>: mostly likely, a desktop version of Windows is running and limits number of CPUs, but the dump can still be captured</li>
</ul>

<h2 id="internals">Internals</h2>

<p>This section is dedicated to internals of the method discussed above.</p>

<h3 id="anatomy-of-the-complete-memory-dump">Anatomy of the Complete Memory Dump</h3>

<p>The structure of the Complete Memory Dump consists of several large parts:</p>

<ul>
  <li>A one-page (4 KiB) header on a 32-bit system and 2 pages (8 KiB) on a 64-bit system.</li>
  <li>Snapshots (so-called “runs”) of contiguous regions of physical memory (Run #0 - Run #N).</li>
</ul>

<p><img src="https://user-images.githubusercontent.com/8286747/218570184-a37f8799-1feb-4e95-9266-932ffb81c519.png" alt="image" /></p>
<p align="center">Simplified scheme of the Complete Memory Dump</p>

<p>The number of runs, start addresses, and lengths are stored in the header. The <code class="language-plaintext highlighter-rouge">dumpchk.exe</code> utility, which comes with the WinDbg debugger, is able to show information about the physical memory stored in the dump file. Usually there is more than one region due to PCI holes, because some of the physical address space is used for communication with peripherals and is not suitable for data storage. Therefore, not all of the physical address space is stored in the dump file. On 64-bit platform, each physical memory region is described in the dump header with the <code class="language-plaintext highlighter-rouge">_PHYSICAL_MEMORY_RUN64</code> structure, which stores the start and the length of the region:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="n">_PHYSICAL_MEMORY_RUN64</span> <span class="p">{</span>
    <span class="n">ULONG64</span> <span class="n">BasePage</span><span class="p">;</span>
    <span class="n">ULONG64</span> <span class="n">PageCount</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p><img src="https://user-images.githubusercontent.com/8286747/218570814-18b739fb-0875-4061-a758-c5a591107edf.png" alt="image" /></p>
<p align="center">The list of physical memory regions is displayed by the <code>dumpchk.exe</code></p>

<p>In addition to information about physical memory regions, the dump header contains other fields required for debugger operation, including:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">BugcheckData</code> - error code and 4 parameters that describe the reason of the crash</li>
  <li><code class="language-plaintext highlighter-rouge">RequiredDumpSpace</code> - total dump size in bytes</li>
  <li><code class="language-plaintext highlighter-rouge">DirectoryTableBase</code> - the physical address of the root of the virtual-to-physical address translation for the debugger</li>
  <li><code class="language-plaintext highlighter-rouge">PsLoadedModuleList</code> - the virtual address of the list of loaded executable modules</li>
  <li><code class="language-plaintext highlighter-rouge">PfnDatabase</code> - virtual address of page frame number database</li>
  <li><code class="language-plaintext highlighter-rouge">MinorVersion, MajorVersion</code> - two fields that together determine the version of Windows kernel</li>
  <li><code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock</code> - virtual address of Windows kernel structure, which stores information required for debugger (see below)</li>
</ul>

<h3 id="kddebuggerdatablock">KdDebuggerDataBlock</h3>

<p>KdDebuggerDataBlock contains the addresses of another important kernel data structures and offsets within them, for example:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">KernBase</code> - virtual address of the Windows kernel image loaded into memory (ntoskrnl.exe) which is required for WinDbg to download PDB symbols</li>
  <li><code class="language-plaintext highlighter-rouge">KiProcessorBlock</code> is a pointer to an array of pointers to PRCBs (processor control block) where Windows stores the data on each processor in use
processor used</li>
  <li><code class="language-plaintext highlighter-rouge">OffsetPrcbContext</code> - the offset of the structure inside PRCB, where Windows saves register context on crash</li>
  <li><code class="language-plaintext highlighter-rouge">OwnerTag</code> - KdDebuggerDataBlock signature - ASCII characters <code class="language-plaintext highlighter-rouge">"KDBG"</code>.</li>
</ul>

<p>The following fields contained in KdDebuggerDataBlock have their analogs in the dump header:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">KiBugcheckData</code></li>
  <li><code class="language-plaintext highlighter-rouge">MmPfnDatabase</code></li>
  <li><code class="language-plaintext highlighter-rouge">PsLoadedModuleList</code></li>
</ul>

<p>The structure of the KdDDebuggerDataBlock contents is described in <code class="language-plaintext highlighter-rouge">_KDDEBUGGER_DATA64</code> structure in <code class="language-plaintext highlighter-rouge">wdbgexts.h</code>, which comes with WinDbg. With a new version of Windows, new fields are only added to end of this structure, and already existing fields remain at the same offsets, this can be relied on regardless of the version of Windows.</p>

<p>It is easy to see that header fields such as <code class="language-plaintext highlighter-rouge">RequiredDumpSpace</code> can be calculated and filled based on data from QEMU, but fields like <code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock</code> and <code class="language-plaintext highlighter-rouge">PsLoadedModuleList</code> are known only to the guest kernel.</p>

<p>Unfortunately, practice shows that <code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock</code> in modern versions of Windows may be encrypted by the system at boot time and be inaccessible during operation, and decrypted only during a crash. So we need a way to decrypt it, but let’s come back to this problem a bit later.</p>

<h3 id="keinitializecrashdumpheader">KeInitializeCrashDumpHeader</h3>

<p><code class="language-plaintext highlighter-rouge">KeInitializeCrashDumpHeader</code> is a <a href="https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-keinitializecrashdumphead">partially documented function</a> that driver calls to get the dump header. According to the documentation, the function returns a header that will be correct for the lifetime of the system, although it has the following limitations:</p>
<ul>
  <li>If the amount of physical memory is changed, the header has to be retrieved again.</li>
  <li>The header received in this way does not contain data about the occurred exception (<code class="language-plaintext highlighter-rouge">BugcheckData</code>).</li>
</ul>

<p>Also, according to the documentation, starting with Windows 8 the <code class="language-plaintext highlighter-rouge">DirectoryTableBase</code> address in the resulting header always corresponds to the system context, but for earlier versions the context will be the same as the context of the current process. It can also be user context, which may then prevent the debugger from accessing the system structures using the virtual addresses.</p>

<p>Furthermore, after analyzing of some number of such dumps, some more inconsistencies were found:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">RequiredDumpSpace</code> is not filled</li>
  <li><code class="language-plaintext highlighter-rouge">Context</code> structure is empty</li>
  <li><code class="language-plaintext highlighter-rouge">PfnDatabase</code> field has wrong value</li>
</ul>

<p>The <code class="language-plaintext highlighter-rouge">RequiredDumpSpace</code> value must be filled properly othewise WinDbg will not work properly. The filling of the <code class="language-plaintext highlighter-rouge">Context</code> structure does not affect the result, but the similar structures in the memory do. They are required by WinDbg to display register and call stack values. Some header values are duplicated in <code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock</code>, so it can be used to restore them. The ways of restoring the header fields are gathered in the corresponding table:</p>

<table>
  <thead>
    <tr>
      <th>Header field</th>
      <th>How to fix</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">BugcheckData</code></td>
      <td>Take structure pointed to by <code class="language-plaintext highlighter-rouge">KiBugcheckData</code> from <code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock</code> in case of BSoD or set <code class="language-plaintext highlighter-rouge">BugcheckCode</code> to <code class="language-plaintext highlighter-rouge">0x161</code> in case of live dump</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">PfnDatabase</code></td>
      <td>Take <code class="language-plaintext highlighter-rouge">MmPfnDatabase</code> from <code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">RequiredDumpSpace</code></td>
      <td>Calculate from physical memory info</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">Context</code></td>
      <td>No fix needed</td>
    </tr>
  </tbody>
</table>

<h3 id="fw_cfg-and-vmcoreinfo">fw_cfg and vmcoreinfo</h3>

<p>After the header is received, it must be passed to the host. The <code class="language-plaintext highlighter-rouge">vmcoreinfo</code> device is used to do this. The <code class="language-plaintext highlighter-rouge">vmcoreinfo</code> device is an add-on to the <code class="language-plaintext highlighter-rouge">fw_cfg</code> device.</p>

<p><code class="language-plaintext highlighter-rouge">fw_cfg</code> is a virtual device <a href="https://github.com/qemu/qemu/blob/master/docs/specs/fw_cfg.rst">provided by QEMU</a> that helps guest software to communicate with the host. From the guest point of view, it is a device with I/O ports <code class="language-plaintext highlighter-rouge">0x510-0x51B</code>. It provides access to an array of entries, which are simply blocks of arbitrary data and a string key associated with them.</p>

<p><code class="language-plaintext highlighter-rouge">vmcoreinfo</code> is a virtual device <a href="">from QEMU</a> accessed via a <code class="language-plaintext highlighter-rouge">fw_cfg</code> entry named <code class="language-plaintext highlighter-rouge">"etc/vmcoreinfo"</code>. The device was originally designed to <a href="https://docs.kernel.org/admin-guide/kdump/vmcoreinfo.html">transfer some Linux kernel data</a> when creating guest Linux dumps.</p>

<p>To read from any <code class="language-plaintext highlighter-rouge">fw_cfg</code> entry, the driver does the following:</p>
<ol>
  <li>Sends the number of the desired entry to port <code class="language-plaintext highlighter-rouge">0x510</code></li>
  <li>Reads the data from port <code class="language-plaintext highlighter-rouge">0x511</code> byte-by-byte</li>
</ol>

<p>To write data to <code class="language-plaintext highlighter-rouge">vmcoreinfo</code>, we first need to find the entry by its name (<code class="language-plaintext highlighter-rouge">"etc/vmcoreinfo"</code>) and check that data transfer from the guest to the host is possible:</p>
<ol>
  <li>Read 4-byte entry with number <code class="language-plaintext highlighter-rouge">0x19</code> to get total number of entries</li>
  <li>Read entries until the desired name is found</li>
  <li>Read 8 bytes from <code class="language-plaintext highlighter-rouge">0x514-0x51B</code> and check against <code class="language-plaintext highlighter-rouge">"QEMU CFG"</code> - this means that <code class="language-plaintext highlighter-rouge">fw_cfg</code> supports DMA-like writing interface</li>
</ol>

<p>In case of VMCoreInfo a packed structure of the following type is passed:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="k">struct</span> <span class="n">FWCfgVMCoreInfo</span> <span class="p">{</span>
      <span class="kt">uint16_t</span> <span class="n">host_format</span><span class="p">;</span>  <span class="cm">/* formats host supports */</span>
      <span class="kt">uint16_t</span> <span class="n">guest_format</span><span class="p">;</span> <span class="cm">/* format guest supplies */</span>
      <span class="kt">uint32_t</span> <span class="n">size</span><span class="p">;</span>         <span class="cm">/* size of vmcoreinfo region */</span>
      <span class="kt">uint64_t</span> <span class="n">paddr</span><span class="p">;</span>        <span class="cm">/* physical address of vmcoreinfo region */</span>
  <span class="p">}</span> <span class="n">QEMU_PACKED</span><span class="p">;</span>
</code></pre></div></div>
<p>Data transfer to host is done through a DMA-like interface:</p>
<ol>
  <li>Write physical address of <code class="language-plaintext highlighter-rouge">FWCfgDmaAccess</code> structure containing the physical address of the data to be written, size, entry number and control bits to <code class="language-plaintext highlighter-rouge">0x514-0x51B</code></li>
  <li>Check control bits, if they are all equal to 0, then the data
has been successfully transferred</li>
</ol>

<p><img src="https://user-images.githubusercontent.com/8286747/218884764-710e70b2-e79d-4d38-b72b-e2238b89e5e2.png" alt="image" /></p>

<p>After this, QEMU will have access to the data at <code class="language-plaintext highlighter-rouge">paddr</code> address. QEMU interprets them as an ELF Note section, which consists of a name (in this case <code class="language-plaintext highlighter-rouge">"VMCOREINFO"</code>) and content - the dump header. If the structure of the section is correct, it becomes available to the <a href="https://github.com/qemu/qemu/blob/master/dump/dump.c">QEMU dumping subsystem</a>.</p>

<p>All the driver logic described above is implemented <a href="https://github.com/virtio-win/kvm-guest-drivers-windows/blob/master/fwcfg64/fwcfg.c">here</a>.</p>

<h3 id="register-context">Register context</h3>

<p>In the debug dump analysis process, the register values are important in and of themselves, moreover, their values are necessary for the correct reconstruction of the call stack.</p>

<p>In the <code class="language-plaintext highlighter-rouge">wdm.h</code> header file, which is delivered as part of the WDK, there is a definition of a structure called <code class="language-plaintext highlighter-rouge">CONTEXT</code>. After comparing this definition, the register values from QEMU and <code class="language-plaintext highlighter-rouge">Context</code> field from the saved Windows dump, it is clear that <code class="language-plaintext highlighter-rouge">Context</code> field contains an implementation of this structure. But as on modern systems there is more than one processor, register contexts of all processors can’t fit into dump header (there is only space for one <code class="language-plaintext highlighter-rouge">CONTEXT</code> instance).</p>

<p>An address space of Windows kernel contains per-CPU <code class="language-plaintext highlighter-rouge">PRCB</code> structures with <code class="language-plaintext highlighter-rouge">ContextFrame</code> fields. Each of these fields stores an address of a context frame from a corresponding CPU. If these structures are filled with zeroes, WinDbg cannot recover the context. In addition, the context structure contains a field of flags, one of which indicates that the context is 64-bit, so when the structure is zeroed, the debugger displays a message that only the 32-bit context is available. Once the context structures are filled in, these messages do not occur. So WinDbg definetely takes the contents of registers from these structures.</p>

<p>Thus, in order for WinDbg to retrieve the actual register values, they must be stored in the corresponding structures inside the memory dump. This procedure is implemeted in <code class="language-plaintext highlighter-rouge">patch_and_save_context</code> function from <a href="https://github.com/qemu/qemu/blob/master/dump/win_dump.c"><code class="language-plaintext highlighter-rouge">dump/win_dump.c</code></a>.</p>

<h3 id="kibugcheckdata">KiBugcheckData</h3>

<p><code class="language-plaintext highlighter-rouge">BugcheckData</code> is automatically saved at BSoD and this data can be simply copied to the header. But it turns out that when creating a live system dump, it is not enough to write BugcheckData to the header. In order for the debugger to use this data, it must also be saved in <code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock-&gt;KiBugcheckData</code>. This logic is implemented in <code class="language-plaintext highlighter-rouge">patch_bugcheck_data</code> routine from <a href="https://github.com/qemu/qemu/blob/master/dump/win_dump.c"><code class="language-plaintext highlighter-rouge">dump/win_dump.c</code></a>.</p>

<h3 id="small-memory-dump">Small Memory Dump</h3>

<p>Along with a full memory dump, there is a Small Memory Dump. For example, Windows creates a dump in this format after a BSoD at default settings. Such dump contains the following data:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">BugcheckData</code> structure</li>
  <li><code class="language-plaintext highlighter-rouge">EPROCESS</code> structure with an information about the faulty process</li>
  <li><code class="language-plaintext highlighter-rouge">ETHREAD</code> structure with an information about the faulty thread</li>
  <li><code class="language-plaintext highlighter-rouge">PRCB</code> structure for the CPU on which the error occured</li>
  <li>List of loaded modules</li>
  <li><code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock</code> structure</li>
</ul>

<p>Unlike the Complete Memory Dump, <code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock</code> is stored in the Small Memory Dump at the offset written in its header, so the address translation is not required. Thus, if we have a small dump, we can use it to create a full memory dump.</p>

<h3 id="kecapturepersistentthreadstate">KeCapturePersistentThreadState</h3>

<p><code class="language-plaintext highlighter-rouge">KeCapturePersistentThreadState</code> is an undocumented Windows kernel function. The driver can use it to retrieve a Small Memory Dump.
<code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock</code> inside such dump will be decrypted. The guest driver can pass to the hypervisor not only the address of the original <code class="language-plaintext highlighter-rouge">KdDDebuggerDataBlock</code> (which can be encrypted), obtained with <code class="language-plaintext highlighter-rouge">KeCapturePersistentThreadState</code>, but also the address of its decrypted version, which will be stored in the driver’s memory.</p>

<p>In order for the hypervisor to take advantage of this feature, it must check the signature of the <code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock</code> whose address lies in its usual place in the header and, if the signature does not match, use the <code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock</code> whose address is passed by the driver through one of the unused header fields, such as <code class="language-plaintext highlighter-rouge">BugcheckParameter1</code>, since this field has a null value anyway and must be filled in by the hypervisor. This is what QEMU does in <code class="language-plaintext highlighter-rouge">check_kdbg</code> from <a href="https://github.com/qemu/qemu/blob/master/dump/win_dump.c"><code class="language-plaintext highlighter-rouge">dump/win_dump.c</code></a>.</p>

<p><img src="https://user-images.githubusercontent.com/8286747/219972209-dceb26e6-914f-4db2-be60-cc7e0d2e7e8a.png" alt="image" /></p>
<p align="center">Connection between dump elements at the stage of their loading from the guest memory</p>

<h3 id="overall-host-side-algorithm">Overall host-side algorithm</h3>

<ol>
  <li>Pause the VM</li>
  <li>Synchronize state with KVM</li>
  <li>Take the header from the <code class="language-plaintext highlighter-rouge">vmcoreinfo</code> device</li>
  <li>Calculate <code class="language-plaintext highlighter-rouge">RequiredDumpSpace</code> field value as the sum of the sizes of continuous physical memory regions described in the header</li>
  <li>Use <code class="language-plaintext highlighter-rouge">DirectoryTableBase</code> field value from the header as <code class="language-plaintext highlighter-rouge">CR3</code> register value when further accessing the guest OS virtual address space from QEMU</li>
  <li>Take <code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock</code> structure address from the header</li>
  <li>Substitute <code class="language-plaintext highlighter-rouge">PfnDatabase</code> field value with the <code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock-&gt;MmPfnDatabase</code> value</li>
  <li>Fill <code class="language-plaintext highlighter-rouge">BugcheckData</code> structure (error code and parameters)
    <ul>
      <li>In the case of the BSoD, take the content from <code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock-&gt;KiBugcheckData</code></li>
      <li>In the case of the live system dump, write <code class="language-plaintext highlighter-rouge">0x161</code> (<code class="language-plaintext highlighter-rouge">LIVE_SYSTEM_DUMP</code>) code and zero error parameters to <code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock-&gt;KiBugcheckData</code></li>
    </ul>
  </li>
  <li>Write the register context to <code class="language-plaintext highlighter-rouge">KdDebuggerDataBlock-&gt;KiProcessorBlock[i]-&gt;ContextFrame</code> for each <code class="language-plaintext highlighter-rouge">i</code> in a range of CPU numbers, based on the registers from QEMU</li>
  <li>Write header to the file</li>
  <li>Write regions of the guest physical memory to the file</li>
  <li>Unpause the VM</li>
</ol>

<h2 id="conclusion">Conclusion</h2>

<p>We have discussed the usage and internals of <code class="language-plaintext highlighter-rouge">dump-guest-memory -w</code> command which is a useful tool for anyone looking to debug their Windows guests in the QEMU/KVM environment. The next post will be devoted to creating a dump with literally no action on the guest side.</p>]]></content><author><name>Viktor Prutyanov</name></author><summary type="html"><![CDATA[In the previous introductory article we’ve discussed crash dump capturing and debugging of guest Windows with built-in tools. This post address a case when Windows can’t produce the Complete Memory Dump during BSoD by itself or a live dump is needed. We will discuss QEMU’s command dump-guest-memory -w which captures guest Windows dump in WinDbg-readable DMP format and saves it on the host side.]]></summary></entry></feed>