<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Jason's Website</title><link href="http://www.lowepower.com/jason/" rel="alternate"></link><link href="http://www.lowepower.com/jason/feeds/all.atom.xml" rel="self"></link><id>http://www.lowepower.com/jason/</id><updated>2018-06-01T00:00:00-05:00</updated><entry><title>Visualizing Spectre with gem5</title><link href="http://www.lowepower.com/jason/visualizing-spectre-with-gem5.html" rel="alternate"></link><published>2018-06-01T00:00:00-05:00</published><updated>2018-06-01T00:00:00-05:00</updated><author><name>Jason Lowe-Power</name></author><id>tag:www.lowepower.com,2018-06-01:/jason/visualizing-spectre-with-gem5.html</id><summary type="html">&lt;p&gt;&lt;a class="reference external" href="https://meltdownattack.com/"&gt;Spectre and Meltdown&lt;/a&gt; took much of our
community by surprise. I personally found these attacks fascinating
because they didn't rely on a &lt;em&gt;bug&lt;/em&gt; in any particular hardware
implementation, but leveraged undefined behavior. Specifically, Spectre
and Meltdown can exfiltrate potentially secret memory data by detecting
the effects of speculative instructions &lt;em&gt;that …&lt;/em&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a class="reference external" href="https://meltdownattack.com/"&gt;Spectre and Meltdown&lt;/a&gt; took much of our
community by surprise. I personally found these attacks fascinating
because they didn't rely on a &lt;em&gt;bug&lt;/em&gt; in any particular hardware
implementation, but leveraged undefined behavior. Specifically, Spectre
and Meltdown can exfiltrate potentially secret memory data by detecting
the effects of speculative instructions &lt;em&gt;that are later squashed&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Very cool!&lt;/p&gt;
&lt;p&gt;Out of order processors are very complex. It would make it easier to
understand exactly what causes speculation attacks like Spectre and
Meltdown if we had a way to &lt;em&gt;visualize&lt;/em&gt; the attacks. Luckily, gem5
already has a way to view the details of it's out of order CPU's
pipeline.&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="o3 pipeline view example" src="images/spectre/o3-example.png" style="width: 750px;" /&gt;
&lt;p class="caption"&gt;o3 pipeline view example&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The image above was created using the O3 pipeline viewer that is
included with gem5. In this post, I'll explain how to use the O3
pipeline viewer and how to generate images like the above. There is also
a new project which makes it easier to navigate large pipeline traces
and it quite useful for comparing different pipeline designs:
&lt;a class="reference external" href="https://github.com/shioyadan/Konata"&gt;Konata&lt;/a&gt; created by Ryota
Shioya. Ryota gave a presentation on Konata at a recent &lt;a class="reference external" href="http://learning.gem5.org/tutorial/index.html"&gt;Learning gem5
tutorial&lt;/a&gt;. You can find
the pdf of his presentation
&lt;a class="reference external" href="http://learning.gem5.org/tutorial/presentations/vis-o3-gem5.pdf"&gt;here&lt;/a&gt;.
Konata is a cool tool that's written in javascript and Ryota describes
it as &amp;quot;Google maps for an out of order pipeline&amp;quot;.&lt;/p&gt;
&lt;div class="section" id="running-spectre"&gt;
&lt;h2&gt;Running Spectre&lt;/h2&gt;
&lt;p&gt;The first step to visualizing what is going on in the pipeline during a
Spectre attack is getting proof of concept exploit code. I used the code
that was posted to a github gist by Erik August soon after the attack
was announced. You can get that code here:
&lt;a class="reference external" href="https://gist.github.com/ErikAugust/724d4a969fb2c6ae1bbd7b2a9e3d4bb6"&gt;https://gist.github.com/ErikAugust/724d4a969fb2c6ae1bbd7b2a9e3d4bb6&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First, you need to compile the proof of concept code on your native
machine (note: I'll be using x86 for all of my examples).&lt;/p&gt;
&lt;pre class="code sh literal-block"&gt;
gcc spectre.c -o spectre -static
&lt;/pre&gt;
&lt;p&gt;I used gcc 7.2 (the default on Ubuntu 17.10) for my tests, and you may
want to do the same. &lt;a class="reference external" href="#effects-of-compilers"&gt;Below&lt;/a&gt; I discuss the
effects different compilers have on the Specre attack. For instance, if
you use clang instead you may not be able to reproduce the Spectre
attack in gem5.&lt;/p&gt;
&lt;pre class="code sh literal-block"&gt;
docker run --rm -v &lt;span class="nv"&gt;$PWD&lt;/span&gt;:&lt;span class="nv"&gt;$PWD&lt;/span&gt; -w &lt;span class="nv"&gt;$PWD&lt;/span&gt; powerjg/gem5-build-gcc48 gcc spectre.c -o spectre -static -std&lt;span class="o"&gt;=&lt;/span&gt;c99
&lt;/pre&gt;
&lt;p&gt;My native machine is still vulnerable to Spectre so when I run the
binary generated above, I get the following output.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdd76c8... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffffffffdd76c9... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdd76ca... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdd76cb... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdd76cc... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffffffffdd76cd... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdd76ce... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdd76cf... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdd76d0... Success: 0x63=’c’ score=2
Reading at malicious_x = 0xffffffffffdd76d1... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdd76d2... Success: 0x57=’W’ score=2
Reading at malicious_x = 0xffffffffffdd76d3... Success: 0x6F=’o’ score=2
Reading at malicious_x = 0xffffffffffdd76d4... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdd76d5... Success: 0x64=’d’ score=2
Reading at malicious_x = 0xffffffffffdd76d6... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdd76d7... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdd76d8... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdd76d9... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdd76da... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdd76db... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdd76dc... Success: 0x53=’S’ score=2
Reading at malicious_x = 0xffffffffffdd76dd... Success: 0x71=’q’ score=2
Reading at malicious_x = 0xffffffffffdd76de... Success: 0x75=’u’ score=2
Reading at malicious_x = 0xffffffffffdd76df... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdd76e0... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdd76e1... Success: 0x6D=’m’ score=2
Reading at malicious_x = 0xffffffffffdd76e2... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdd76e3... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdd76e4... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdd76e5... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdd76e6... Success: 0x50=’P’ score=9 (second best: 0x06 score=2)
Reading at malicious_x = 0xffffffffffdd76e7... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdd76e8... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdd76e9... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdd76ea... Success: 0x66=’f’ score=2
Reading at malicious_x = 0xffffffffffdd76eb... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdd76ec... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdd76ed... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdd76ee... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdd76ef... Success: 0x2E=’.’ score=2
&lt;/pre&gt;
&lt;div class="section" id="running-spectre-in-gem5"&gt;
&lt;h3&gt;Running Spectre in gem5&lt;/h3&gt;
&lt;p&gt;To find out if gem5's out of order CPU implementation is vulnerable to
Spectre, we need to run the code in gem5. The simplest and fastest way
to do this is by running in gem5's syscall-emulation (SE) mode. In SE
mode we won't be modeling an OS or any user-mode to kernel-mode
interaction, but this okay for Spectre since this proof of concept code
is all in user-mode. If we were investigating Metldown, we would have to
use full-system (FS) mode since Meltdown specifically allows user-mode
processes to read data that should only be accessible in kernel mode.&lt;/p&gt;
&lt;p&gt;So, when running something in gem5, the first step is to create a Python
runscript since this is &lt;a class="reference external" href="http://learning.gem5.org/book/part1/simple_config.html"&gt;the &amp;quot;interface&amp;quot; to
gem5&lt;/a&gt;. For
this example, what we need is a system with one CPU, an L1 cache, and
memory. For simplicity, I'm going to modify one of the existing script,
specifically the &lt;tt class="docutils literal"&gt;two_level.py&lt;/tt&gt; script from the &lt;a class="reference external" href="http://learning.gem5.org/"&gt;Learning gem5
book&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the file &lt;tt class="docutils literal"&gt;gem5/configs/learning_gem5/part1/two_level.py&lt;/tt&gt;, I simply
changed the CPU from &lt;tt class="docutils literal"&gt;TimingSimpleCPU()&lt;/tt&gt; to
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;DerivO3CPU(branchPred=LTAGE())&lt;/span&gt;&lt;/tt&gt;. I also set the O3CPU to use the
LTAGE branch predictor instead of the default tournament branch
predictor. It's important to use the LTAGE branch predictor as better
branch predictors actually make Spectre easier to exploit as discussed
further &lt;a class="reference external" href="effects-of-branch-predictor"&gt;below&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now, we simply need to build gem5 and run it.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
scons -j8 build/X86/gem5.opt

build/X86/gem5.opt configs/learning_gem5/part1/two_level.py spectre
&lt;/pre&gt;
&lt;p&gt;And, the output that I get is the following, just like above when I ran
the &lt;tt class="docutils literal"&gt;spectre&lt;/tt&gt; natively. Note: If you use GCC 4.8 it executes much
faster than 7.2 (the default on Ubuntu 17.10).&lt;/p&gt;
&lt;pre class="literal-block"&gt;
gem5 Simulator System.  http://gem5.org
gem5 is copyrighted software; use the --copyright option for details.

gem5 compiled May 10 2018 09:40:08
gem5 started May 24 2018 11:21:16
gem5 executing on palisade, pid 27173
command line: build/X86/gem5.opt configs/learning_gem5/part1/two_level.py spectre

Global frequency set at 1000000000000 ticks per second
warn: DRAM device capacity (8192 Mbytes) does not match the address range assigned (512 Mbytes)
0: system.remote_gdb: listening for remote gdb on port 7000
Beginning simulation!
info: Entering event queue &amp;#64; 0.  Starting simulation...
warn: readlink() called on '/proc/self/exe' may yield unexpected results in various settings.
      Returning '/home/jlp/Code/gem5/spectre-vis/spectre'
info: Increasing stack size by one page.
warn: ignoring syscall access(...)
Reading 40 bytes:                 tput cols
Reading at malicious_x = 0xffffffffffdd76c8... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffffffffdd76c9... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdd76ca... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdd76cb... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdd76cc... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffffffffdd76cd... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdd76ce... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdd76cf... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdd76d0... Success: 0x63=’c’ score=2
Reading at malicious_x = 0xffffffffffdd76d1... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdd76d2... Success: 0x57=’W’ score=2
Reading at malicious_x = 0xffffffffffdd76d3... Success: 0x6F=’o’ score=2
Reading at malicious_x = 0xffffffffffdd76d4... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdd76d5... Success: 0x64=’d’ score=2
Reading at malicious_x = 0xffffffffffdd76d6... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdd76d7... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdd76d8... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdd76d9... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdd76da... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdd76db... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdd76dc... Success: 0x53=’S’ score=2
Reading at malicious_x = 0xffffffffffdd76dd... Success: 0x71=’q’ score=2
Reading at malicious_x = 0xffffffffffdd76de... Success: 0x75=’u’ score=2
Reading at malicious_x = 0xffffffffffdd76df... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdd76e0... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdd76e1... Success: 0x6D=’m’ score=2
Reading at malicious_x = 0xffffffffffdd76e2... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdd76e3... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdd76e4... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdd76e5... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdd76e6... Success: 0x4F=’O’ score=2
Reading at malicious_x = 0xffffffffffdd76e7... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdd76e8... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdd76e9... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdd76ea... Success: 0x66=’f’ score=2
Reading at malicious_x = 0xffffffffffdd76eb... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdd76ec... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdd76ed... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdd76ee... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdd76ef... Success: 0x2E=’.’ score=2
Exiting &amp;#64; tick 113568969000 because exiting with last active thread context
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="visualizing-the-out-of-order-pipeline"&gt;
&lt;h2&gt;Visualizing the out of order pipeline&lt;/h2&gt;
&lt;p&gt;To generate pipeline visualizations, we first need to generate a trace
file of all of the instructions executed by the out of order CPU. To
create this trace, we can use the &lt;tt class="docutils literal"&gt;O3PipeView&lt;/tt&gt; debug flag.&lt;/p&gt;
&lt;p&gt;Now, the trace for the O3 CPU can be &lt;em&gt;very&lt;/em&gt; large up to many GBs. When
creating this trace, you need to be careful to create the smallest trace
possible. Also, it's important to dump the trace to a file and not to
&lt;tt class="docutils literal"&gt;stdout&lt;/tt&gt;, which is the default when using debug flags. You can
redirect the trace to a file by using the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--debug-file&lt;/span&gt;&lt;/tt&gt; option to
gem5.&lt;/p&gt;
&lt;p&gt;To create the trace file, I used the following methodology:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Start running spectre in gem5, then hit ctrl-c after the first couple
of letters. At this point, I wrote down the tick which gem5 exited
(13062347000).&lt;/li&gt;
&lt;li&gt;Run gem5 with the debug flag &lt;tt class="docutils literal"&gt;O3PipeView&lt;/tt&gt; enabled.&lt;/li&gt;
&lt;li&gt;Watch the output and kill gem5 with ctrl-c after two more letters
appeared than in step 1.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To generate the trace, I ran the following command. Note: you may have a
different value for when to start the debugging trace. Also note: when
producing the trace gem5 will run &lt;em&gt;much&lt;/em&gt; slower.&lt;/p&gt;
&lt;pre class="code sh literal-block"&gt;
build/X86/gem5.opt --debug-flags&lt;span class="o"&gt;=&lt;/span&gt;O3PipeView --debug-file&lt;span class="o"&gt;=&lt;/span&gt;pipeview.txt --debug-start&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;13062347000&lt;/span&gt; configs/learning_gem5/part1/two_level.py spectre
&lt;/pre&gt;
&lt;p&gt;My tracefile (&lt;tt class="docutils literal"&gt;pipeview.txt&lt;/tt&gt;) was 600 MB for catching just two letters
in the output.&lt;/p&gt;
&lt;p&gt;Now, we can process this file to generate the visualization with a
script: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;util/o3-pipeview.py&lt;/span&gt;&lt;/tt&gt;. This script requires the path to the
file that contains the output generated with the &lt;tt class="docutils literal"&gt;O3PipeView&lt;/tt&gt; debug
flag. Above, we put the output into the file &lt;tt class="docutils literal"&gt;pipeview.txt&lt;/tt&gt;, and this
file was created in the default output directory of gem5 (&lt;tt class="docutils literal"&gt;m5out/&lt;/tt&gt;).&lt;/p&gt;
&lt;pre class="literal-block"&gt;
util/o3-pipeview.py --store_completions m5out/pipeview.txt --color -w 150
&lt;/pre&gt;
&lt;p&gt;In the above command, I wanted to see when the stores completed
(&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--store_completions&lt;/span&gt;&lt;/tt&gt;) and specified to use color (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--color&lt;/span&gt;&lt;/tt&gt;) in
the output and use a width of 150 characters (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-w&lt;/span&gt; 150&lt;/tt&gt;). Processing a
large file like this one of 600 MB may take a few minutes. The output
will be in a file called &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;o3-pipeview.out&lt;/span&gt;&lt;/tt&gt; in the current working
directory.&lt;/p&gt;
&lt;p&gt;You can view this file with &lt;tt class="docutils literal"&gt;less &lt;span class="pre"&gt;-r&lt;/span&gt; &lt;span class="pre"&gt;o3-pipeview.out&lt;/span&gt;&lt;/tt&gt;. You may want to
use the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-S&lt;/span&gt;&lt;/tt&gt; option with less if your terminal is less than 150
characters wide (or whatever width value you used). Below is a
screenshot of the top of my trace.&lt;/p&gt;
&lt;div class="section" id="understanding-the-o3-pipeline-viewer"&gt;
&lt;h3&gt;Understanding the O3 pipeline viewer&lt;/h3&gt;
&lt;div class="figure"&gt;
&lt;img alt="o3 pipeline view example" src="images/spectre/o3-example-annotated.png" style="width: 750px;" /&gt;
&lt;p class="caption"&gt;o3 pipeline view example&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The above image details how to interpret the output from the pipeline
viewer. Each &lt;tt class="docutils literal"&gt;.&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;=&lt;/tt&gt; represents one cycle of time, which moves
from left to right. The &amp;quot;tick&amp;quot; column shows the tick of the leftmost
&lt;tt class="docutils literal"&gt;.&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;=&lt;/tt&gt;. &lt;tt class="docutils literal"&gt;=&lt;/tt&gt; is used to mark the instructions that were later
squashed. The address of the instruction (and the micro-op number) as
well as the disassembly is also shown. The sequence number can be
ignored as it is always monotonically increasing and is the total order
of every dynamic instruction. Finally, each stage of the O3 pipeline is
shown with a different letter and color.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="digging-deeper-into-spectre"&gt;
&lt;h2&gt;Digging deeper into Spectre&lt;/h2&gt;
&lt;p&gt;First, let's examine the actual instructions that are executed during
the Spectre attack. The vulnerability is in the &lt;tt class="docutils literal"&gt;victim_function&lt;/tt&gt; in
&lt;tt class="docutils literal"&gt;spectre.c&lt;/tt&gt;.&lt;/p&gt;
&lt;pre class="code c literal-block"&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;victim_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;array1_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;=&lt;/span&gt; &lt;span class="n"&gt;array2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;array1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;When this is compiled and then dumped with &lt;tt class="docutils literal"&gt;objdump&lt;/tt&gt;, we get the
following instructions that will be executed. Your code my be slightly
different, especially the exact addresses of each instruction, depending
on the version of the compiler and other system-specific configurations.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
# NOTE: the movzbl below is MOVZX_B_R_M in gem5.
# it is implemented with the following microcode.
#    ld t1, seg, sib, disp, dataSize=1
#    zexti reg, t1, 7
#
000000000040105e &amp;lt;victim_function&amp;gt;:
  40105e:   55                      push   %rbp
  40105f:   48 89 e5                mov    %rsp,%rbp
  401062:   48 89 7d f8             mov    %rdi,-0x8(%rbp)
  401066:   8b 05 14 f0 2b 00       mov    0x2bf014(%rip),%eax # 6c0080 &amp;lt;array1_size&amp;gt; load array1_size (first time is always a miss)
  40106c:   89 c0                   mov    %eax,%eax
  40106e:   48 3b 45 f8             cmp    -0x8(%rbp),%rax  # if (x &amp;lt; array1_size) rax is array1_size, -8(%rbp) is x
  401072:   76 2b                   jbe    40109f &amp;lt;victim_function+0x41&amp;gt; # if (x &amp;lt; array1_size)
  401074:   48 8b 45 f8             mov    -0x8(%rbp),%rax # load x from the stack into rax
  401078:   48 05 a0 00 6c 00       add    $0x6c00a0,%rax  # calculate array1 offset (x+array1)
  40107e:   0f b6 00                movzbl (%rax),%eax # load array1[x]
  401081:   0f b6 c0                movzbl %al,%eax    # zero extend to 32 bits
  401084:   c1 e0 09                shl    $0x9,%eax   # multiply by 512
  401087:   48 98                   cltq               # sign-extend eax
  401089:   0f b6 90 80 1d 6c 00    movzbl 0x6c1d80(%rax),%edx  # load array2[array1[x]*512] **** This is the magic!
  401090:   0f b6 05 e9 0c 2e 00    movzbl 0x2e0ce9(%rip),%eax        # 6e1d80 &amp;lt;temp&amp;gt; Load temp.
  401097:   21 d0                   and    %edx,%eax
  401099:   88 05 e1 0c 2e 00       mov    %al,0x2e0ce1(%rip)        # 6e1d80 &amp;lt;temp&amp;gt;
  40109f:   5d                      pop    %rbp
  4010a0:   c3                      retq
&lt;/pre&gt;
&lt;p&gt;Now, we can search for the instruction that we care about in the trace.
In this case, we want to find a time where the &lt;tt class="docutils literal"&gt;movzbl&lt;/tt&gt; at address
&lt;tt class="docutils literal"&gt;0x401089&lt;/tt&gt; is executed speculatively. When searching through the
pipeline viewer (use &lt;tt class="docutils literal"&gt;\&lt;/tt&gt; in less), we're looking for a time where the
load completes for the instruction at &lt;tt class="docutils literal"&gt;0x401089&lt;/tt&gt; and it is later
squashed (surrounded by &lt;tt class="docutils literal"&gt;=&lt;/tt&gt;). An example is shown below.&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="annotated O3 pipeline view of spectre" src="images/spectre/o3-spectre-annotated.png" style="width: 750px;" /&gt;
&lt;p class="caption"&gt;annotated O3 pipeline view of spectre&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The image above is from my presentation at &lt;a class="reference external" href="http://caslab.csl.yale.edu/workshops/hasp2018/"&gt;Hardware and Architectural
Support for Security and Privacy (HASP)
2018&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What we see in this image is that the instruction at &lt;tt class="docutils literal"&gt;0x401066&lt;/tt&gt; causes
a cache miss (there is a long time between when the load is issued and
the data is returned from memory). Since the load of &lt;tt class="docutils literal"&gt;array1_size&lt;/tt&gt; was
a cache miss, the jump at &lt;tt class="docutils literal"&gt;0x401072&lt;/tt&gt; is speculated to be &lt;em&gt;not&lt;/em&gt; taken
(incorrectly). This causes the following instructions to be executed
speculatively, and, eventually, squashed.&lt;/p&gt;
&lt;p&gt;The key thing in this trace that &lt;em&gt;is&lt;/em&gt; the Spectre vulnerability is that
the load for the instruction at &lt;tt class="docutils literal"&gt;0x40107e&lt;/tt&gt;, which loads secret data
happens during the mis-speculated instructions. Then, this data is
loaded into the registers and operated on (instruction &lt;tt class="docutils literal"&gt;0x401084&lt;/tt&gt;).
Finally, the load at address &lt;tt class="docutils literal"&gt;0x401089&lt;/tt&gt; is executed and loads the
value from memory &lt;em&gt;that is dependent on the secret data loaded
previously&lt;/em&gt;. Thus, we can later probe the cache to retrieve the secret
data.&lt;/p&gt;
&lt;div class="section" id="effects-of-compilers"&gt;
&lt;h3&gt;Effects of compilers&lt;/h3&gt;
&lt;p&gt;As previously mentioned, the specific compiler version and compiler
options have a significant effect on the attack. Below are two traces,
one from GCC 7.2 and one from clang 4.0.&lt;/p&gt;
&lt;div class="section" id="gcc-7-2"&gt;
&lt;h4&gt;GCC 7.2&lt;/h4&gt;
&lt;pre class="literal-block"&gt;
void victim_function(size_t x) {
  400b2d:       55                      push   %rbp
  400b2e:       48 89 e5                mov    %rsp,%rbp
  400b31:       48 89 7d f8             mov    %rdi,-0x8(%rbp)
  if (x &amp;lt; array1_size) {
  400b35:       8b 05 c5 c5 2c 00       mov    0x2cc5c5(%rip),%eax        # 6cd100 &amp;lt;array1_size&amp;gt;
  400b3b:       89 c0                   mov    %eax,%eax
  400b3d:       48 39 45 f8             cmp    %rax,-0x8(%rbp)
  400b41:       73 34                   jae    400b77 &amp;lt;victim_function+0x4a&amp;gt;
    temp &amp;amp;= array2[array1[x] * 512];
  400b43:       48 8d 15 d6 c5 2c 00    lea    0x2cc5d6(%rip),%rdx        # 6cd120 &amp;lt;array1&amp;gt;
  400b4a:       48 8b 45 f8             mov    -0x8(%rbp),%rax
  400b4e:       48 01 d0                add    %rdx,%rax
  400b51:       0f b6 00                movzbl (%rax),%eax
  400b54:       0f b6 c0                movzbl %al,%eax
  400b57:       c1 e0 09                shl    $0x9,%eax
  400b5a:       48 63 d0                movslq %eax,%rdx
  400b5d:       48 8d 05 9c f6 2c 00    lea    0x2cf69c(%rip),%rax        # 6d0200 &amp;lt;array2&amp;gt;
  400b64:       0f b6 14 02             movzbl (%rdx,%rax,1),%edx
  400b68:       0f b6 05 91 e1 2c 00    movzbl 0x2ce191(%rip),%eax        # 6ced00 &amp;lt;temp&amp;gt;
  400b6f:       21 d0                   and    %edx,%eax
  400b71:       88 05 89 e1 2c 00       mov    %al,0x2ce189(%rip)        # 6ced00 &amp;lt;temp&amp;gt;
  }
}
  400b77:       90                      nop
  400b78:       5d                      pop    %rbp
  400b79:       c3                      retq
&lt;/pre&gt;
&lt;iframe width="750" height="500" src="images/spectre/gcc72-static-tage.html" frameborder="0"&gt;
&lt;/iframe&gt;&lt;p&gt;However, clang generates the following code.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
void victim_function(size_t x) {
  400ac0:       55                      push   %rbp
  400ac1:       48 89 e5                mov    %rsp,%rbp
  400ac4:       48 89 7d f8             mov    %rdi,-0x8(%rbp)
  if (x &amp;lt; array1_size) {
  400ac8:       48 8b 7d f8             mov    -0x8(%rbp),%rdi
  400acc:       8b 04 25 90 c0 6c 00    mov    0x6cc090,%eax
  400ad3:       89 c1                   mov    %eax,%ecx
  400ad5:       48 39 cf                cmp    %rcx,%rdi
  400ad8:       0f 83 2f 00 00 00       jae    400b0d &amp;lt;victim_function+0x4d&amp;gt;
    temp &amp;amp;= array2[array1[x] * 512];
  400ade:       48 8b 45 f8             mov    -0x8(%rbp),%rax
  400ae2:       0f b6 0c 05 a0 c0 6c    movzbl 0x6cc0a0(,%rax,1),%ecx
  400ae9:       00
  400aea:       c1 e1 09                shl    $0x9,%ecx
  400aed:       48 63 c1                movslq %ecx,%rax
  400af0:       0f b6 0c 05 40 f2 6c    movzbl 0x6cf240(,%rax,1),%ecx
  400af7:       00
  400af8:       0f b6 14 25 50 dc 6c    movzbl 0x6cdc50,%edx
  400aff:       00
  400b00:       21 ca                   and    %ecx,%edx
  400b02:       40 88 d6                mov    %dl,%sil
  400b05:       40 88 34 25 50 dc 6c    mov    %sil,0x6cdc50
  400b0c:       00
  }
}
  400b0d:       5d                      pop    %rbp
  400b0e:       c3                      retq
  400b0f:       90                      nop
&lt;/pre&gt;
&lt;iframe width="750" height="500" src="images/spectre/clang-static-tage.html" frameborder="0"&gt;
&lt;/iframe&gt;&lt;p&gt;Interestingly, the clang-compiled &lt;tt class="docutils literal"&gt;spectre&lt;/tt&gt; binary is not able to read
the secret data! (At least not in gem5. It is able to read the secret
data on my native machine.)&lt;/p&gt;
&lt;p&gt;We can look into the two traces to see the difference between the clang
version and the GCC version.&lt;/p&gt;
&lt;p&gt;The main difference is that in the clang version, the load generated by
the instruction at &lt;tt class="docutils literal"&gt;0x400af0&lt;/tt&gt; never completes (and thus, must not have
been issued to the memory system).&lt;/p&gt;
&lt;p&gt;I'm not sure the exact cause of this difference. It could be that the
instruction uses a different addressing mode
(&lt;tt class="docutils literal"&gt;movzbl &lt;span class="pre"&gt;0x6cf240(,%rax,1),%ecx&lt;/span&gt;&lt;/tt&gt; in clang vs
&lt;tt class="docutils literal"&gt;movzbl &lt;span class="pre"&gt;(%rdx,%rax,1),%edx&lt;/span&gt;&lt;/tt&gt; in GCC). If you have ideas, please leave a
comment!&lt;/p&gt;
&lt;p&gt;Either way, minor differences in the code generated can have large
impacts on the speculative execution!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="effects-of-branch-predictor"&gt;
&lt;h3&gt;Effects of branch predictor&lt;/h3&gt;
&lt;p&gt;When I was first playing around with Spectre and gem5, I ran into a
problem where I could only &lt;em&gt;sometimes&lt;/em&gt; get Spectre to &amp;quot;work&amp;quot; with the
out of order CPU. After significant digging, I found that the branch
predictor chosen makes a big difference to how quickly the vulnerability
happens. The trace below (with the same code as GCC 4.8 above) shows
what happens when using the tournament branch predictor.&lt;/p&gt;
&lt;iframe width="750" height="500" src="images/spectre/gcc-static-tourn.html" frameborder="0"&gt;
&lt;/iframe&gt;&lt;p&gt;Here, we see that the original branch misprediction comes much earlier
than the jump instruction in &lt;tt class="docutils literal"&gt;victim_function&lt;/tt&gt; that is at address
&lt;tt class="docutils literal"&gt;0x401072&lt;/tt&gt;. Thus, by the time the load instructions in
&lt;tt class="docutils literal"&gt;victim_function&lt;/tt&gt; are executed, the ROB and load-store queue resources
have been taken by other instructions and the rogue loads are not issued
to memory. There are still a few times that the two loads are executed
speculatively, but it is much more rare than with the TAGE predictor.
When using the TAGE branch predictor, only the exact branch that the
attacker wants to mispredict is mispredicted.&lt;/p&gt;
&lt;p&gt;This interestingly shows that a &amp;quot;smarter&amp;quot; system is actually &lt;em&gt;more&lt;/em&gt;
vulnerable to speculation-based attacks!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</content></entry><entry><title>Inferring Kaveri's Shared Virtual Memory Implementation</title><link href="http://www.lowepower.com/jason/inferring-kaveris-shared-virtual-memory-implementation.html" rel="alternate"></link><published>2017-07-03T00:00:00-05:00</published><updated>2017-07-03T00:00:00-05:00</updated><author><name>Jason Lowe-Power</name></author><id>tag:www.lowepower.com,2017-07-03:/jason/inferring-kaveris-shared-virtual-memory-implementation.html</id><summary type="html">&lt;p&gt;&lt;em&gt;Note: Most of this work was completed in 2014. These results may not
hold with current drivers and more recent hardware (e.g., Carrizo)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Kaveri is AMD's first APU (accelerated processing unit, e.g. a chip with
both a CPU and GPU on-die) to provide an implementation of heterogeneous
system …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;Note: Most of this work was completed in 2014. These results may not
hold with current drivers and more recent hardware (e.g., Carrizo)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Kaveri is AMD's first APU (accelerated processing unit, e.g. a chip with
both a CPU and GPU on-die) to provide an implementation of heterogeneous
system architecture (HSA). HSA is set of standards from the &lt;a class="reference external" href="http://www.hsafoundation.com/"&gt;HSA
Foundation&lt;/a&gt; which provides transparent
support for multiple compute platforms. The goal is to allow programmers
to use the GPU to accelerate parts of their applications with minimal
overhead, both in terms of performance overhead and programmer effort.&lt;/p&gt;
&lt;p&gt;The key features which differentiate HSA from other similar technologies
are&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;em&gt;Shared virtual memory&lt;/em&gt; which allows the CPU and GPU to access the
same data transparently.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Heterogeneous queuing&lt;/em&gt; which allows the user-mode program to offload
work to the GPU without OS intervention. Also, it allows CPU to
schedule work for the GPU, the GPU to schedule work for the CPU, the
GPU to schedule work for itself, etc.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Architected signals and synchronization&lt;/em&gt; which is mostly used for
implementing the heterogeneous queues, but also allows for complex
asynchronous communication between different compute platforms.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are many questions about how AMD has implemented these features in
their first iteration of HSA hardware. In this post, I am going to focus
on the implementation of shared virtual memory.&lt;/p&gt;
&lt;div class="section" id="shared-virtual-memory"&gt;
&lt;h2&gt;Shared Virtual Memory&lt;/h2&gt;
&lt;p&gt;Shared virtual memory allows the GPU to access data in exactly the same
fashion as the CPU. Another way to put it, which is often used by the
AMD folks, is shared virtual memory allows &amp;quot;pointer-is-a-pointer&amp;quot;
semantics. For the programmer, this means that she can allocate memory
when executing on the CPU (e.g. by using malloc, tmalloc, or a
user-defined allocator) and access that data from the GPU without any
special translations. There is no need to copy the data to the GPU, or
to declare that the data may be accessed by the GPU in the future. To
implement shared virtual memory there are two main hardware
requirements:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;The CPU and GPU caches must be kept coherent. This doesn't have to be
traditional hardware coherence. A valid implementation would be to
flush the CPU/GPU caches whenever a synchronization instruction is
executed.&lt;/li&gt;
&lt;li&gt;The GPU must access the CPU page tables (e.g. x86-64). This means
that GPU needs either a dedicated memory management unit (MMU) or
that its memory accesses must pass through the IOMMU. (Possibly
another post to come on this later.)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Shared virtual memory, as described here, is similar to &amp;quot;universal
virutal addressing&amp;quot; from NVIDIA. The key difference is that with shared
virtual memory, the GPU is accessing the CPU page tables transparently.
There is no need to declare that a pointer will be used by the GPU
before the GPU accesses it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="deducing-cache-parameters"&gt;
&lt;h2&gt;Deducing Cache Parameters&lt;/h2&gt;
&lt;p&gt;There is a great paper from the early 90's which looks at several
machines available at the time and determines their cache parameters.
Apparently, back then, we didn't have resources like &lt;a class="reference external" href="http://ark.intel.com/"&gt;Intel's
architecture pages&lt;/a&gt; which gives us at least
some information on what is in a manufactured chip. The paper by
Saavedra et. al (available
&lt;a class="reference external" href="http://www.cs.usc.edu/assets/004/83251.pdf"&gt;here&lt;/a&gt;) presents a simple
microbenchmark (described below) and formulas which take the runtime of
the benchmark and tell you the cache parameters.&lt;/p&gt;
&lt;p&gt;This table is an overview of my findings. Below, I detail the methods
and data that lead to these results. Information in italics I'm less
sure about than the rest of the data.&lt;/p&gt;
&lt;table border="1" class="docutils"&gt;
&lt;colgroup&gt;
&lt;col width="20%" /&gt;
&lt;col width="50%" /&gt;
&lt;col width="11%" /&gt;
&lt;col width="19%" /&gt;
&lt;/colgroup&gt;
&lt;thead valign="bottom"&gt;
&lt;tr&gt;&lt;th class="head"&gt;&amp;nbsp;&lt;/th&gt;
&lt;th class="head"&gt;Capacity&lt;/th&gt;
&lt;th class="head"&gt;Miss Latency&lt;/th&gt;
&lt;th class="head"&gt;Associativity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td&gt;L1 Cache&lt;/td&gt;
&lt;td&gt;16 KB (Per CU)&lt;/td&gt;
&lt;td&gt;225 ns&lt;/td&gt;
&lt;td&gt;64-way&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;L2 Cache&lt;/td&gt;
&lt;td&gt;256 KB (8 32 KB banks)&lt;/td&gt;
&lt;td&gt;50 ns&lt;/td&gt;
&lt;td&gt;&lt;em&gt;at least 64-way&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;L1 TLB&lt;/td&gt;
&lt;td&gt;&lt;em&gt;64MB-128MB reach&lt;/em&gt; &lt;em&gt;64-128 2MB entries&lt;/em&gt; &lt;em&gt;2046 32 KB or 64 2 MB entries&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;450 ns&lt;/td&gt;
&lt;td&gt;&lt;em&gt;at least 64-way&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;L2 TLB (none if 2MB pages)&lt;/td&gt;
&lt;td&gt;&lt;em&gt;512 MB reach&lt;/em&gt; &lt;em&gt;256 2 MB entries&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;220 ns&lt;/td&gt;
&lt;td&gt;&lt;em&gt;256-way (for 4K pages)&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="section" id="the-microbenchmark"&gt;
&lt;h3&gt;The microbenchmark&lt;/h3&gt;
&lt;p&gt;(note: the code used to generate the data in this notebook and the data
itself can be found on
&lt;a class="reference external" href="https://github.com/powerjg/hsa-micro-benchmarks"&gt;github&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;The microbenchmark that I used is quite simple. It allocates a chunk of
memory, then issues memory requests to that memory. By varying the
amount of memory allocated and the stride between each memory access,
you can control the cache's effect. For instance, if the size of the
allocated memory is less than or equal to the cache size, we would
expect the entire array to fit in the cache and every access to hit in
the cache, experiencing only the cache hit latency. Alternatively, if
the allocated memory was larger than the cache, and we used a stride
equal to the cache line size, we would expect every access to miss in
the cache, experiencing the cache miss latency on every access.&lt;/p&gt;
&lt;p&gt;Although the benchmark is simple, things are complicated by prefetching,
multi-level caches, TLBs, replacement policies, etc. Some of these are
relatively easy to overcome (we can trick the prefetcher by pointer
chasing, for instance). Other things, like replacement policies other
than LRU, cause the data to be more noisy or to not follow the model
laid out by Saavedra et. al exactly.&lt;/p&gt;
&lt;p&gt;In the data below, I've tried to explain as much as I can about why we
see the data, but there are still some holes in my understanding.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="the-data"&gt;
&lt;h2&gt;The data!&lt;/h2&gt;
&lt;p&gt;For each of the graphs below, I've run the microbenchmark with input
arrays from 4 KB up to 4 GB and strides from 4 bytes to the size of the
array.&lt;/p&gt;
&lt;div class="section" id="baseline-data"&gt;
&lt;h3&gt;Baseline data&lt;/h3&gt;
&lt;p&gt;This first set of data uses the GPU to initialize the data (i.e. the
data is touched by the GPU before the test is performed). It also uses
the default Linux allocator, which uses transparent huge pages (THP) in
this case.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urlbase&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s1"&gt;'data-thp-gpu.csv'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;usecols&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;skipinitialspace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;figsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;6.66&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Init on GPU with THP'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'upper right'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;xscale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'log'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;basex&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;which&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'major'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;xlabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'stride'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'time (ns)'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;annotTHP&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;tight_layout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
&lt;img alt="Init on GPU with THP" class="align-center" src="images/output_14_0.png" style="width: 750px;" /&gt;
&lt;p&gt;Starting on the left (and with smaller inputs):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;The first array size which experiences L1 misses (the first teal
line) is &lt;span class="formula"&gt;2&lt;sup&gt;15&lt;/sup&gt;&lt;/span&gt;&lt;ul&gt;
&lt;li&gt;This implies that the L1 cache capacity is &amp;lt; 32 KB, likely 16 KB.&lt;/li&gt;
&lt;li&gt;Since the latency changes from 300ns to 525ns, we can also infer
that the L1 miss latency is 225ns. This may seem like a very high
miss latency; however, it's not out of the realm of possibility
for GPU caches. I've found similar numbers for both NVIDIA and AMD
discrete GPUs.&lt;/li&gt;
&lt;li&gt;Also, the stride at which the latency is a maximum for the
&lt;span class="formula"&gt;2&lt;sup&gt;15&lt;/sup&gt;&lt;/span&gt; line is 64 bytes, which implies a 64 byte line. The
reason we know it's the line size is that until we stride at the
line size or above, the cache misses are partially amortized by
hitting multiple times within the same cache block.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Next, the next array size (&lt;span class="formula"&gt;2&lt;sup&gt;16&lt;/sup&gt;&lt;/span&gt;) seems to have a
significantly different latency for each access.&lt;ul&gt;
&lt;li&gt;I believe this is the L2 miss latency, which is much smaller than
the L1 miss latency at only 50ns. I assume that this L2 miss
latency is actually the DRAM latency. If this is the case, the
50ns is quite reasonable. In discrete GPUs, the DRAM latency is
much higher, but 50ns is reasonable for DDR3.&lt;/li&gt;
&lt;li&gt;However, I do not believe that the L2 cache is only 32 KB. It
wouldn't make much sense to include if it was so small. What I
believe is going on here (and I've yet to develop a test to
confirm this hypothesis) is that the L2 has a 512 byte &amp;quot;line
size&amp;quot;, or as it's likely implemented, 8 banks and the banks are
addressed by simple address slicing. If this is true, then the L2
is actually 256 KB, a much more reasonable size.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Nothing else interesting happens until we get to arrays larger than
&lt;span class="formula"&gt;2&lt;sup&gt;27&lt;/sup&gt;&lt;/span&gt;. At this point, we start missing in another level of
cache. It's likely that this &amp;quot;cache&amp;quot; is actually the TLB.&lt;ul&gt;
&lt;li&gt;Since there is an increase in latency for &lt;span class="formula"&gt;2&lt;sup&gt;27&lt;/sup&gt;&lt;/span&gt; and it
doesn't level off until &lt;span class="formula"&gt;2&lt;sup&gt;28&lt;/sup&gt;&lt;/span&gt;, it is likely the TLB reach
is between these two sizes (64 MB and 128 MB).&lt;/li&gt;
&lt;li&gt;Looking at the &lt;span class="formula"&gt;2&lt;sup&gt;28&lt;/sup&gt;&lt;/span&gt; line, and the ones after it, we see
that latency levels off after a stride of &lt;span class="formula"&gt;2&lt;sup&gt;21&lt;/sup&gt;&lt;/span&gt; or 2 MB.
Interestingly, this is the large page size for x86-64. Thus, it
seems that the GPU is using huge pages... cool!&lt;/li&gt;
&lt;li&gt;If we use this page size of 2 MB, then the 64 MB to 128 MB reach
implies that the TLB has 32 to 64 entries. This is quite
reasonable for a modern TLB. An interesting question is whether
this TLB is local to the compute unit, or if it's shared between
many compute units on the GPU. This could be the local TLB, or it
could be the IOMMU TLB.&lt;/li&gt;
&lt;li&gt;Finally, we can see that the TLB miss latency is quite large,
almost 500ns. Again, this is quite reasonable, especially if we
assume that a TLB miss will take 1-4 memory accesses. (Well, 1-3
in this case since the GPU is using 2 MB pages).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="gpu-data-without-thp"&gt;
&lt;h3&gt;GPU data without THP&lt;/h3&gt;
&lt;p&gt;Next we are going to look at what happens with the same test if we
disable THP. This forces the GPU to use 4 KB pages. Though,
interestingly, looking at the data, the GPU uses 32 KB pages even though
the underlying page size is 4 KB!&lt;/p&gt;
&lt;p&gt;Let's look at the data. It's generated using exactly the same methods as
before.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urlbase&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s1"&gt;'data-nothp-gpu.csv'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;usecols&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;skipinitialspace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;figsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;6.66&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Init on GPU without THP'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'upper right'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;xscale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'log'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;basex&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;which&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'major'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;xlabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'stride'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'time (ns)'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;annotNoTHP&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;tight_layout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
&lt;img alt="Init on GPU without THP" class="align-center" src="images/output_18_0.png" style="width: 750px;" /&gt;
&lt;p&gt;Most of this data is the same as when using THP. The main difference is
that we can see TLB misses with a much small array than in the previous
data and that there are two TLB &amp;quot;line sizes&amp;quot;.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Looking at the first level TLB, we see the line size is 32 KB. This
actually isn't that strange of a &amp;quot;page&amp;quot; size. It's 8 4 KB pages,
which happens to be the number of page translations that can fit in
one 64 byte cache line. My hypothesis is that the GPU is using
something like a sub-blocked TLB.&lt;/li&gt;
&lt;li&gt;Interestingly, this TLB seems huge (2048 32 KB entries), especially
if we compare it to the TLB in the first data. Since it's so big, my
guess is that it's at the IOMMU and shared by the whole GPU, not a
per-CU TLB. Additionally, there may be more sub-blocking going on all
the way up to the 2 MB page size. Sub-blocking up to 2 MB pages lines
up with the previous THP data the best. If the used 2 MB super-blocks
then it would have 64 entries, which lines up with the L1 TLB in the
previous data (which we found to be 64-128 entries).&lt;/li&gt;
&lt;li&gt;Next, we again see the 2 MB page, but this time only for arrays
larger than 512 MB. I find this quite strange that we didn't see this
level of TLB in the previous data that had only 2 MB pages. It seems
that this &amp;quot;L2 TLB&amp;quot;, whatever it is, has an additional miss penalty
not seen in the previous data. Assuming this TLB uses 2 MB pages,
then it would have 256 entries.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I'm honestly not too sure what exactly is going on here. The data is
pretty clear that there's two levels of TLB, but I'm not sure how these
TLB levels relate to the TLB in the first set of data with 2 MB pages.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="cpu-first-touch"&gt;
&lt;h3&gt;CPU first touch&lt;/h3&gt;
&lt;p&gt;Next, we're going to look at what happens when the GPU doesn't touch the
data before the test is performed. For this test, I used the CPU to
initialize the data and then performed the test on the GPU. Below we
have the data both when THP is enabled and disabled. Since there aren't
too many new data points in these two graphs I'll talk about them
together below the graphs.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urlbase&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s1"&gt;'data-thp-cpu.csv'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;usecols&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;skipinitialspace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;figsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;6.66&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Init on CPU with THP'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'upper right'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;xscale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'log'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;basex&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;which&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'major'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;xlabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'stride'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'time (ns)'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;annotTHP&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;tight_layout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
&lt;img alt="Init on CPU with THP" class="align-center" src="images/output_22_0.png" style="width: 750px;" /&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urlbase&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s1"&gt;'data-nothp-cpu.csv'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;usecols&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;skipinitialspace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;figsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;6.66&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Init on CPU without THP'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'upper right'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;xscale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'log'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;basex&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;which&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'major'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;xlabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'stride'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'time (ns)'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;annotNoTHP&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;tight_layout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
&lt;img alt="Init on CPU without THP" class="align-center" src="images/output_23_0.png" style="width: 750px;" /&gt;
&lt;p&gt;The key difference between these two graphs and the first two (where the
data was first initialized on the GPU) is for arrays of sizes 512 MB and
above we see some pretty strange data. The way I interpret this data,
and I may be totally wrong about this, is that the GPU caches are
disabled. I believe this is true because of the latency seen using the
word (4 byte) stride. Even in this case, when you would expect to get
intra-block hits, the latency equal to the cache miss latency.&lt;/p&gt;
&lt;p&gt;Although disabling the GPU caches really hurts performance for this
microbenchmark, it may make sense for real applications. Maybe the
runtime is somehow detecting that the data is written by the CPU and
assumes that if the GPU wants up to date data that the highest
performance option is to disable the caches (rather than rely on cache
coherence).&lt;/p&gt;
&lt;p&gt;I have considered other possibilities, like 1 GB pages, page faults,
etc. But I can't come up with any other reason other than the above for
this data.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusions"&gt;
&lt;h2&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;There are still many unanswered questions about the design of the caches
in Kaveri. This post just scratches the surface. I think the most
interesting things that I learned are some of the details of the GPU MMU
on Kaveri. (This may be most interesting to me since it's in my domain
;)). Also, it seems that accessing large arrays on the GPU that are
first touched by the CPU results in very low performance. Since
initializing data on the CPU and then processing that data on the GPU is
a common idiom today, programmers will have to be careful to not use
large arrays if they want to get high performance with AMD's current
architecture.&lt;/p&gt;
&lt;p&gt;Below I've included all of the other code that's required to get things
to work. Questions and comments can be directed to me (Jason Lowe-Power)
at &lt;a class="reference external" href="mailto:powerjg&amp;#64;cs.wisc.edu"&gt;powerjg&amp;#64;cs.wisc.edu&lt;/a&gt;. I'd like to thank my advisers Mark Hill and
David Wood for helpful discussions about this data.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="code-for-generating-the-above-graphs"&gt;
&lt;h2&gt;Code for generating the above graphs:&lt;/h2&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'size'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'stride'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'overall_kernel_time'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mf"&gt;1e9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'2^&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s1"&gt; bytes'&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;log2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;annotNoTHP&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# L1&lt;/span&gt;
    &lt;span class="n"&gt;hlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;525&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;hlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;vlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;525&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;350&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;L1 miss latency&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;~225 ns&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rotation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;va&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'bottom'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;vlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;525&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;linestyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'--'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Line size: 64 bytes&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;annotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;L1 capacity: 16 KB&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;350&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;xytext&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
             &lt;span class="n"&gt;arrowprops&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arrowstyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="n"&gt;connectionstyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;arc3,rad=.2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# L2&lt;/span&gt;
    &lt;span class="n"&gt;hlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;570&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;hlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;530&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;vlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;530&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;570&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;580&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;L2 miss latency&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;~50 ns&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ha&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'center'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;vlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;570&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;linestyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'--'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;210&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;L2 &lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s2"&gt;Line size&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s2"&gt;: 512 bytes =&amp;gt; 8 banks&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;annotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;L2 capacity: 256 KB&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;(32 KB * 8 banks)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;450&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;xytext&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;650&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
             &lt;span class="n"&gt;arrowprops&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arrowstyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="n"&gt;connectionstyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;arc3,rad=.2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# L1 TLB&lt;/span&gt;
    &lt;span class="n"&gt;hlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;980&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;hlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;570&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;vlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;570&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;980&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;700&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;L1 TLB miss latency&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;~450 ns&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ha&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'center'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;vlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;980&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;linestyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'--'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;L1 TLB page size: 32 KB (8 4KB pages)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;annotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;L1 TLB reach: 64 MB&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;(2048 entries)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;650&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;xytext&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
             &lt;span class="n"&gt;arrowprops&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arrowstyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="n"&gt;connectionstyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;arc3,rad=.2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# L2 TLB&lt;/span&gt;
    &lt;span class="n"&gt;hlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;hlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;980&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;vlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;980&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;L2 TLB miss latency&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;~220 ns&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ha&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'center'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;vlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;linestyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'--'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;210&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;L2 TLB page size: 2 MB&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;annotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;L2 TLB reach: 512 MB&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;(256 entries)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;700&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;xytext&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
             &lt;span class="n"&gt;arrowprops&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arrowstyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="n"&gt;connectionstyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;arc3,rad=.2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;annotTHP&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# L1&lt;/span&gt;
    &lt;span class="n"&gt;hlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;525&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;hlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;vlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;525&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;350&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;L1 miss latency&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;~225 ns&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rotation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;va&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'bottom'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;vlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;525&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;linestyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'--'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Line size: 64 bytes&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;annotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;L1 capacity: 16 KB&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;350&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;xytext&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
             &lt;span class="n"&gt;arrowprops&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arrowstyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="n"&gt;connectionstyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;arc3,rad=.2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# L2&lt;/span&gt;
    &lt;span class="n"&gt;hlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;570&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;hlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;530&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;vlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;530&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;570&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;580&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;L2 miss latency&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;~50 ns&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ha&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'center'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;vlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;570&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;linestyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'--'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;210&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;L2 &lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s2"&gt;Line size&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s2"&gt;: 512 bytes =&amp;gt; 8 banks&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;annotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;L2 capacity: 256 KB&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;(32 KB * 8 banks)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;450&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;xytext&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;650&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
             &lt;span class="n"&gt;arrowprops&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arrowstyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="n"&gt;connectionstyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;arc3,rad=.2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# TLB&lt;/span&gt;
    &lt;span class="n"&gt;hlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;980&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;hlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;570&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;vlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;570&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;980&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;700&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;TLB miss latency&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;~450 ns&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ha&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'center'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;vlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;980&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;linestyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'--'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;TLB page size: 2 MB&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;annotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;TLB reach: 64-128 MB&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;(32-64 entries)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;700&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;xytext&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
             &lt;span class="n"&gt;arrowprops&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arrowstyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="n"&gt;connectionstyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;arc3,rad=.2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;urlbase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;https://raw.githubusercontent.com/powerjg/hsa-micro-benchmarks/master/caches/data/A10-7850K/&amp;quot;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pandas&lt;/span&gt; &lt;span class="kn"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;pd&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
</content></entry><entry><title>Setting up gem5 full system</title><link href="http://www.lowepower.com/jason/setting-up-gem5-full-system.html" rel="alternate"></link><published>2017-01-13T00:00:00-06:00</published><updated>2017-01-13T00:00:00-06:00</updated><author><name>Jason Lowe-Power</name></author><id>tag:www.lowepower.com,2017-01-13:/jason/setting-up-gem5-full-system.html</id><summary type="html">&lt;p&gt;This is partially a followup to &lt;a class="reference external" href="http://www.lowepower.com/jason/creating-disk-images-for-gem5.html"&gt;Creating disk images for gem5&lt;/a&gt; and partially how to setup x86 full system for gem5.
In this post, I'll discuss how to create a disk image from scratch and start using it with gem5.&lt;/p&gt;
&lt;p&gt;It is important for computer architecture research to use the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;This is partially a followup to &lt;a class="reference external" href="http://www.lowepower.com/jason/creating-disk-images-for-gem5.html"&gt;Creating disk images for gem5&lt;/a&gt; and partially how to setup x86 full system for gem5.
In this post, I'll discuss how to create a disk image from scratch and start using it with gem5.&lt;/p&gt;
&lt;p&gt;It is important for computer architecture research to use the most up-to-date software on the systems we are simulating.
Too much computer architecture research reports results using kernels from 5+ years ago or ancient system software
Hopefully, this post will help others be able to keep up with the ever-changing system software.
This way, researchers can use up-to-date versions of Linux and easily update their kernels.&lt;/p&gt;
&lt;p&gt;This post takes a different approach than &lt;a class="reference external" href="http://www.lowepower.com/jason/creating-disk-images-for-gem5.html"&gt;Creating disk images for gem5&lt;/a&gt;.
Instead of using the gem5 tools, this post uses qemu to create, edit, and set up the disk for gem5 usage.&lt;/p&gt;
&lt;p&gt;This post assumes that you have installed qemu on your system.
In Ubuntu, this can be done with&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo apt-get install qemu-kvm libvirt-bin ubuntu-vm-builder bridge-utils
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I also assume you have downloaded and built gem5.
All of the full system examples use the simple full system scripts that are covered in &lt;a class="reference external" href="http://learning.gem5.org/book/part3/index.html"&gt;Learning gem5&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="step-1-create-an-empty-disk"&gt;
&lt;h2&gt;Step 1: Create an empty disk&lt;/h2&gt;
&lt;p&gt;Using the qemu disk tools, create a blank raw disk image.
In this case, I chose to create a disk named &amp;quot;ubuntu-test.img&amp;quot; that is 8GB.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;qemu-img create ubuntu-test.img 8G
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="step-2-install-ubuntu-with-qemu"&gt;
&lt;h2&gt;Step 2: Install ubuntu with qemu&lt;/h2&gt;
&lt;p&gt;Now that we have a blank disk, we are going to use qemu to install Ubuntu on the disk.
I would encourage you to use the server version of Ubuntu since gem5 does not have great support for displays.
Thus, the desktop environment isn't very useful.&lt;/p&gt;
&lt;p&gt;First, you need to download the installation CD image from the &lt;a class="reference external" href="https://www.ubuntu.com/download/server"&gt;Ubuntu website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Next, use qemu to boot off of the CD image, and set the disk in the system to be the blank disk you created above.
Ubuntu needs at least 1GB of memory to install correctly, so be sure to configure qemu to use at least 1GB memory.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;qemu-system-x86_64 -hda ../gem5-fs-testing/ubuntu-test.img -cdrom ubuntu-16.04.1-server-amd64.iso -m &lt;span class="m"&gt;1024&lt;/span&gt; -enable-kvm -boot d
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With this, you can simply follow the on-screen directions to install Ubuntu to the disk image.
The only gotcha in the installation is that gem5's IDE drivers don't seem to play nicely with logical paritions.
Thus, during the Ubuntu install, be sure to manually partition the disk and remove any logical partitions.
You don't need any swap space on the disk anyway, unless you're doing something specifically with swap space.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="step-3-boot-up-and-install-needed-software"&gt;
&lt;h2&gt;Step 3: Boot up and install needed software&lt;/h2&gt;
&lt;p&gt;Once you have installed Ubuntu on the disk, quit qemu and remove the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-boot&lt;/span&gt; d&lt;/tt&gt; option so that you are not booting off of the CD anymore.
Now, you can again boot off of the main disk image you have installed Ubuntu on.&lt;/p&gt;
&lt;p&gt;Since we're using qemu, you should have a network connection (although &lt;a class="reference external" href="http://wiki.qemu.org/Documentation/Networking#User_Networking_.28SLIRP.29"&gt;ping won't work&lt;/a&gt;).
When booting in qemu, you can just use &lt;tt class="docutils literal"&gt;sudo &lt;span class="pre"&gt;apt-get&lt;/span&gt; install&lt;/tt&gt; and install any software you need on your disk.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;qemu-system-x86_64 -hda ../gem5-fs-testing/ubuntu-test.img -cdrom ubuntu-16.04.1-server-amd64.iso -m &lt;span class="m"&gt;1024&lt;/span&gt; -enable-kvm
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="step-4-build-a-kernel"&gt;
&lt;h2&gt;Step 4: Build a kernel&lt;/h2&gt;
&lt;p&gt;Next, you need to build a Linux kernel.
Unfortunately, the out-of-the-box Ubuntu kernel doesn't play well with gem5.
See the &lt;a class="reference internal" href="#error-below"&gt;error below&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First, you need to download latest kernel from &lt;a class="reference external" href="https://www.kernel.org/"&gt;kernel.org&lt;/a&gt;.
Then, to build the kernel, you are going to want to start with a known-good config file.The config file that I'm used for kernel version 4.8.13 can be downloaded &lt;a class="reference external" href="http://www.lowepower.com/jason/files/config"&gt;here&lt;/a&gt;.
Then, you need to move the good config to &lt;tt class="docutils literal"&gt;.config&lt;/tt&gt; and the run &lt;tt class="docutils literal"&gt;make oldconfig&lt;/tt&gt; which starts the kernel configuration process with an existing config file.&lt;/p&gt;
&lt;!-- code-block::sh

mv &lt;good config&gt; .config
make oldconfig --&gt;
&lt;p&gt;At this point you can select any extra drivers you want to build into the kernel.
Note: You cannot use any kernel modules unless you are planning on copying the modules onto the guest disk at the correct location.
All drivers must be built into the kernel binary.&lt;/p&gt;
&lt;p&gt;It may be possible to use modules by compiling the binary on the guest disk via qemu, but I have not tested this.&lt;/p&gt;
&lt;p&gt;Finally, you need to build the kernel.&lt;/p&gt;
&lt;!-- code-block::sh

make -j5 --&gt;
&lt;/div&gt;
&lt;div class="section" id="step-5-update-init-script"&gt;
&lt;h2&gt;Step 5: Update init script&lt;/h2&gt;
&lt;p&gt;By default, gem5 expects a modified init script which loads a script off of the host to execute in the guest.
To use this feature, you need to follow the steps below.&lt;/p&gt;
&lt;p&gt;Alternatively, you can install the precompiled binaries for x86 found on my website:
From qemu, you can run the following, which completes the above steps for you.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;wget http://cs.wisc.edu/~powerjg/files/gem5-guest-tools-x86.tgz
tar xzvf gem5-guest-tools-x86.tgz
&lt;span class="nb"&gt;cd&lt;/span&gt; gem5-guest-tools/
sudo ./install
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, you can use the &lt;tt class="docutils literal"&gt;system.readfile&lt;/tt&gt; parameter in your Python config scripts.
This file will automatically be loaded (by the &lt;tt class="docutils literal"&gt;gem5init&lt;/tt&gt; script) and executed.&lt;/p&gt;
&lt;div class="section" id="manually-installing-the-gem5-init-script"&gt;
&lt;h3&gt;Manually installing the gem5 init script&lt;/h3&gt;
&lt;p&gt;First, build the m5 binary on the host.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; util/m5
make -f Makefile.x86
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then, copy this binary to the guest and put it in &lt;tt class="docutils literal"&gt;/sbin&lt;/tt&gt;.
Also, create a link from &lt;tt class="docutils literal"&gt;/sbin/gem5&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Then, to get the init script to execute when gem5 boots, create file /lib/systemd/system/gem5.service with the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Unit&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gem5 init script
&lt;span class="nv"&gt;Documentation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://gem5.org
&lt;span class="nv"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;getty.target

&lt;span class="o"&gt;[&lt;/span&gt;Service&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;idle
&lt;span class="nv"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/sbin/gem5init
&lt;span class="nv"&gt;StandardOutput&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tty
&lt;span class="nv"&gt;StandardInput&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tty-force
&lt;span class="nv"&gt;StandardError&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tty

&lt;span class="o"&gt;[&lt;/span&gt;Install&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;default.target
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Enable the gem5 service and disable the ttyS0 service.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; gem5.service
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, create the init script that is executed by the service.
In &lt;tt class="docutils literal"&gt;/sbin/gem5init&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#!/bin/bash -&lt;/span&gt;

&lt;span class="nv"&gt;CPU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;cat /proc/cpuinfo &lt;span class="p"&gt;|&lt;/span&gt; grep vendor_id &lt;span class="p"&gt;|&lt;/span&gt; head -n &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; cut -d &lt;span class="s1"&gt;&amp;#39; &amp;#39;&lt;/span&gt; -f2-&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Got CPU type: &lt;/span&gt;&lt;span class="nv"&gt;$CPU&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$CPU&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; !&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;M5 Simulator&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Not in gem5. Not loading script&amp;quot;&lt;/span&gt;
    &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c1"&gt;# Try to read in the script from the host system&lt;/span&gt;
/sbin/m5 readfile &amp;gt; /tmp/script
chmod &lt;span class="m"&gt;755&lt;/span&gt; /tmp/script
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -s /tmp/script &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="c1"&gt;# If there is a script, execute the script and then exit the simulation&lt;/span&gt;
    su root -c &lt;span class="s1"&gt;&amp;#39;/tmp/script&amp;#39;&lt;/span&gt; &lt;span class="c1"&gt;# gives script full privileges as root user in multi-user mode&lt;/span&gt;
    sync
    sleep &lt;span class="m"&gt;10&lt;/span&gt;
    /sbin/m5 &lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;No script found&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="problems-and-some-solutions"&gt;
&lt;h2&gt;Problems and (some) solutions&lt;/h2&gt;
&lt;div class="section" id="failed-to-early-mount-api-filesystems"&gt;
&lt;h3&gt;Failed to early mount API filesystems&lt;/h3&gt;
&lt;pre class="literal-block"&gt;
Write protecting the kernel read-only data: 8192k
Freeing unused kernel memory: 1956K (ffff880001417000 - ffff880001600000)
Freeing unused kernel memory: 456K (ffff88000178e000 - ffff880001800000)
[!!!!!!] Failed to early mount API filesystems, freezing.
&lt;/pre&gt;
&lt;p&gt;Solutions tried:
Enable cgroups in the kernel. I think. Nope!
I think this is the same as the problem below &lt;a class="reference internal" href="#mount-problem"&gt;mount-problem&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="can-t-mount-dev"&gt;
&lt;span id="mount-problem"&gt;&lt;/span&gt;&lt;h3&gt;Can't mount /dev&lt;/h3&gt;
&lt;pre class="literal-block"&gt;
Failed to mount devtmpfs at /dev: No such device
Freezing execution.
&lt;/pre&gt;
&lt;p&gt;Something like the above (this was taken from arch linux boot).
The problem is that that the right devfs is not compiled into the kernel.
You need to make sure that devtmpfs is enabled.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="panic-kvm-unexpected-exit-exit-reason-8"&gt;
&lt;span id="error-below"&gt;&lt;/span&gt;&lt;h3&gt;panic: KVM: Unexpected exit (exit_reason: 8)&lt;/h3&gt;
&lt;p&gt;Exit reason 8 is &amp;quot;shutdown&amp;quot;. See &lt;a class="reference external" href="http://lxr.free-electrons.com/source/include/uapi/linux/kvm.h#L188"&gt;http://lxr.free-electrons.com/source/include/uapi/linux/kvm.h#L188&lt;/a&gt;.
This seems to happen when there is a triple fault: &lt;a class="reference external" href="http://lxr.free-electrons.com/source/arch/x86/kvm/x86.c#L6498"&gt;http://lxr.free-electrons.com/source/arch/x86/kvm/x86.c#L6498&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I get this error every time I try to boot the unmodified Ubuntu kernel.
I don't know how to solve this problem.
Instead of trying to solve the problem, I used a different config file for &amp;quot;oldconfig&amp;quot; when I compiled the kernel from scratch.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="slow-boot"&gt;
&lt;h3&gt;Slow boot&lt;/h3&gt;
&lt;pre class="literal-block"&gt;
[ TIME ] Timed out waiting for device dev-di...\x2da115\x2de3f263d7b53a.device.
[DEPEND] Dependency failed for /dev/disk/by-...382-f41d-4c99-a115-e3f263d7b53a.
[DEPEND] Dependency failed for Swap.
&lt;/pre&gt;
&lt;p&gt;This may happen if you have changed the disk without updating the fstab on the disk.
To fix it, you can boot the disk in qemu and update fstab with the correct UUID.&lt;/p&gt;
&lt;p&gt;I ran into this when I was resizing the disk.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="disk-is-too-small-for-what-you-want-to-do"&gt;
&lt;h3&gt;Disk is too small for what you want to do&lt;/h3&gt;
&lt;p&gt;Resizing an iso is pretty easy.
You can use the same method you would if you wanted to resize a partition on a regular hard drive.&lt;/p&gt;
&lt;p&gt;First, you need to resize the iso with qemu-image:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;qemu-img resize ubuntu-test.img +8G
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, you have a disk that has 8 GB of free space at the end of the disk.
You need to resize the partitions to use this free space.
To do this, I suggest using gparted just like you would for a real hard drive.&lt;/p&gt;
&lt;p&gt;You can download a gparted ISO from &lt;a class="reference external" href="http://gparted.org/livecd.php"&gt;http://gparted.org/livecd.php&lt;/a&gt;.
Once you download the ISO, you can boot it with qemu the same way as we booted the installation CD.
Then, once its booted you can select the disk you want to modify and follow the howto (&lt;a class="reference external" href="http://gparted.org/display-doc.php%3Fname%3Dhelp-manual"&gt;http://gparted.org/display-doc.php%3Fname%3Dhelp-manual&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><category term="Tools"></category></entry><entry><title>When to use 3D die-stacking for bandwidth-constrained big data workloads</title><link href="http://www.lowepower.com/jason/when-to-use-3d-die-stacking-for-bandwidth-constrained-big-data-workloads.html" rel="alternate"></link><published>2016-04-02T00:00:00-05:00</published><updated>2016-04-02T00:00:00-05:00</updated><author><name>Jason Lowe-Power</name></author><id>tag:www.lowepower.com,2016-04-02:/jason/when-to-use-3d-die-stacking-for-bandwidth-constrained-big-data-workloads.html</id><summary type="html">&lt;p&gt;3D die-stacking is an exciting emerging technology.
It promises extremely high bandwidth interconnects for relatively power (at least when compared to current memory technology).
Some of my previous work has looked at how this increased bandwidth can significantly improve performance.
This is especially true for bandwidth-constrained workloads, like database scan …&lt;/p&gt;</summary><content type="html">&lt;p&gt;3D die-stacking is an exciting emerging technology.
It promises extremely high bandwidth interconnects for relatively power (at least when compared to current memory technology).
Some of my previous work has looked at how this increased bandwidth can significantly improve performance.
This is especially true for bandwidth-constrained workloads, like database scan.
However, my previous work has totally ignored the practicality of building these systems.
In this post (and in the paper I am presenting at &lt;cite&gt;BPOE&lt;/cite&gt;), I'd like to dig into whether, and/or when, 3D die-stacking is really appropriate, with a focus on big-data workloads.&lt;/p&gt;
&lt;p&gt;While 3D die-stacking promises higher memory bandwidth, it comes at the cost of tiny capacities.
Today, each stack of DRAM has 2–4 GB of capacity.
Looking forward this should increase to 8–16 GB in the next few years due to increased DRAM densities and more chips per stack.
Compare this to commodity DIMMs for which you can easily buy a single DIMM with 32 GB, and companies have announced DIMMs up to 128 GB.&lt;/p&gt;
&lt;p&gt;One of the first observations I made when I began looking at 3D stacking is that current systems are incredibly unbalanced for high-bandwidth workloads like scan.
There is currently a big push for in-memory databases, OEMs are designing systems for this workload.
For instance, you can buy a system from Dell (the PowerEdge R930) with 3 TB of DRAM!
Granted, it's likely to cost between $50,000 and $100,000, but Dell is happy to sell it to you.
Oracle and IBM are also selling similar systems with even more DRAM per socket.
So, looking at this system I asked, &amp;quot;What's the most complex query I can make if I only have 10ms to complete it?&amp;quot;
I chose 10 ms as a proxy for a very aggressive SLA (service level agreement).
The visualization below will give you an idea of what this looks like for the Dell system described above.&lt;/p&gt;
&lt;div class="figure align-center" style="width: 80%"&gt;
&lt;img alt="Visualization of the traditional system capacity and bandwidth" src="http://www.lowepower.com/jason/images/traditional-boxes.png" style="width: 600px;" /&gt;
&lt;p class="caption"&gt;A visualization of the traditional system capacity and bandwidth.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In this system, you can only access 0.13% of the total data in 10ms!
In fact, it would take over 7 seconds to read all of the data.
(You can take the bandwidth (408 GB/s) and multiply by the time (10 ms) to find how much data you can access in 10 ms (4 GB). Then, compare this to the total memory ( 3 TB) to get 0.13% of memory capacity accessible in 10 ms.)&lt;/p&gt;
&lt;p&gt;Let's compare this to the die-stacked system pictured below.&lt;/p&gt;
&lt;div class="figure align-center" style="width: 80%"&gt;
&lt;img alt="Die-stacked system overview" src="http://www.lowepower.com/jason/images/die-stacked.png" style="width: 300px;" /&gt;
&lt;p class="caption"&gt;A possible design for a single node of a die-stacked system.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="figure align-center" style="width: 80%"&gt;
&lt;img alt="Visualization of the die-stacked system capacity and bandwidth" src="http://www.lowepower.com/jason/images/die-stacked-boxes.png" style="width: 500px;" /&gt;
&lt;p class="caption"&gt;A visualization of the die-stacked system capacity and bandwidth.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;For the die-stacked system, you can access 32% of the data in 10 ms.
This is over 200 times more than in the traditional system.&lt;/p&gt;
&lt;p&gt;So, it seems that the die-stacked system is way better for bandwidth constrained workloads.
And this is the same conclusion I had in previous work.
However, this ignores the fact that the capacity of the die-stacked system is more than an order of magnitude smaller than conventional systems.
Because of this small capacity, you would need many more die-stacked systems to store the same amount of data as a single traditional system.
For instance, if you have a 16 TB workload, you would need only 5–6 of the Dell servers, but you would need over 2000 die-stacked systems.&lt;/p&gt;
&lt;div class="figure align-center" style="width: 80%"&gt;
&lt;img alt="Visualization of the die-stacked cluster vs traditional cluster" src="http://www.lowepower.com/jason/images/cluster-comparison.png" style="width: 500px;" /&gt;
&lt;p class="caption"&gt;The systems required for a 16 TB workload. While you only need 6 traditional systems, you need over 2000 of the die-stacked systems (which don't even fit in the image)!&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Having so many die-stacked systems greatly increases the power required to run the workload.
And this is the fundamental trade off that we investigated in our BPOE paper.
In a sentence, we found that if you require very high performance (like a 10ms SLA), the die-stacked system is the most reasonable system to build.
However, if you have a less strict SLA (100ms or more) or if you have strict power constraints, then the traditional system is the best.&lt;/p&gt;
&lt;p&gt;To reach these conclusions, we developed a simple back-of-the-envelope style analytical model for the power, performance, and capacity of these systems.
If you're interested in more details, you can find the entire model here: &lt;a class="reference external" href="https://research.cs.wisc.edu/multifacet/bpoe16_3d_bandwidth_model/"&gt;3D Bandwidth Model&lt;/a&gt;.
You can download the IPython (Jupyter) Notebook from that page and run the model interactively on your local computer.
Of course, you can also read the paper.
You can download it from here: &lt;a class="reference external" href="http://www.cs.wisc.edu/multifacet/papers/bpoe16_3d_bandwidth_model.pdf"&gt;Paper link&lt;/a&gt;.&lt;/p&gt;
</content><category term="Papers"></category></entry><entry><title>Creating disk images for gem5</title><link href="http://www.lowepower.com/jason/creating-disk-images-for-gem5.html" rel="alternate"></link><published>2015-11-24T00:00:00-06:00</published><updated>2015-11-24T00:00:00-06:00</updated><author><name>Jason Power</name></author><id>tag:www.lowepower.com,2015-11-24:/jason/creating-disk-images-for-gem5.html</id><summary type="html">&lt;p&gt;When using gem5 in full-system mode, you have to have a disk image with the operating system and all of your data on it.
This is just like having a physical disk in a physical machine.
In this post, I'm going to walk through how to create a new disk …&lt;/p&gt;</summary><content type="html">&lt;p&gt;When using gem5 in full-system mode, you have to have a disk image with the operating system and all of your data on it.
This is just like having a physical disk in a physical machine.
In this post, I'm going to walk through how to create a new disk and install a (semi-)current version of Ubuntu on the disk.
By the end of this post, you should be able to create your own disk with whatever extra data and applications you want.&lt;/p&gt;
&lt;p&gt;This post assumes that you have already checked out a version of gem5 and can build and run gem5 in full-system mode.
The &lt;a class="reference external" href="http://www.lowepower.com/jason/learning_gem5/"&gt;Learning gem5&lt;/a&gt; documentation is a good place to start.
This post uses the x86 ISA for gem5, and is mostly applicable to other ISAs.
More details on setting up ARM systems can be found on the gem5 wiki: &lt;a class="reference external" href="http://gem5.org/Ubuntu_Disk_Image_for_ARM_Full_System"&gt;http://gem5.org/Ubuntu_Disk_Image_for_ARM_Full_System&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the future, this post may be folded into &lt;a class="reference external" href="http://www.lowepower.com/jason/learning_gem5/"&gt;Learning gem5&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="creating-a-blank-disk-image"&gt;
&lt;h2&gt;Creating a blank disk image&lt;/h2&gt;
&lt;p&gt;The first step is to create a blank disk image (usually a .img file).
Luckily, the gem5 developers have already made this easy with a tool that is simple to use.
To create a blank disk image, which is formatted with ext2 by default, simply run the following.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&amp;gt; util/gem5img.py init ubuntu-14.04.img &lt;span class="m"&gt;4096&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This command creates a new image, called &amp;quot;ubuntu-14.04.img&amp;quot; that is 4096 MB.
This command may require you to enter the sudo password, if you don't have permission to create loopback devices.
&lt;em&gt;You should never run commands as the root user that you don't understand!
You should look at the file util/gem5img.py and ensure that it isn't going to do anything malicious to your computer!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We will be using util/gem5img.py heavily throughout this post, so you may want to understand it better.
If you just run &lt;tt class="docutils literal"&gt;util/gem5img.py&lt;/tt&gt;, it displays all of the possible commands.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Usage: %s [command] &amp;lt;command arguments&amp;gt;
where [command] is one of
    init: Create an image with an empty file system.
    mount: Mount the first partition in the disk image.
    umount: Unmount the first partition in the disk image.
    new: File creation part of &amp;quot;init&amp;quot;.
    partition: Partition part of &amp;quot;init&amp;quot;.
    format: Formatting part of &amp;quot;init&amp;quot;.
Watch for orphaned loopback devices and delete them with
losetup -d. Mounted images will belong to root, so you may need
to use sudo to modify their contents
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="copying-root-files-to-the-disk"&gt;
&lt;h2&gt;Copying root files to the disk&lt;/h2&gt;
&lt;p&gt;Now that we have created a blank disk, we need to populate it with all of the OS files.
Ubuntu distributes a set of files explicitly for this purpose.
You can find the &lt;a class="reference external" href="https://wiki.ubuntu.com/Core"&gt;Ubuntu core&lt;/a&gt; distribution for 14.04 at
&lt;a class="reference external" href="http://cdimage.ubuntu.com/ubuntu-core/releases/14.04/release/"&gt;http://cdimage.ubuntu.com/ubuntu-core/releases/14.04/release/&lt;/a&gt;
Since I am simulating an x86 machine, I chose the file &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ubuntu-core-14.04-core-amd64.tar.gz&lt;/span&gt;&lt;/tt&gt;.
Download whatever image is appropriate for the system you are simulating.&lt;/p&gt;
&lt;p&gt;Next, we need to mount the blank disk and copy all of the files onto the disk.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;mkdir mnt
../../util/gem5img.py mount ubuntu-14.04.img mnt
wget http://cdimage.ubuntu.com/ubuntu-core/releases/14.04/release/ubuntu-core-14.04-core-amd64.tar.gz
sudo tar xzvf ubuntu-core-14.04-core-amd64.tar.gz -C mnt
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The next step is to copy a few required files from your working system onto the disk so we can chroot into the new disk.
We need to copy &lt;tt class="docutils literal"&gt;/etc/resolv.conf&lt;/tt&gt; onto the new disk.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo cp /etc/resolv.conf mnt/etc/
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="setting-up-gem5-specific-files"&gt;
&lt;h2&gt;Setting up gem5-specific files&lt;/h2&gt;
&lt;div class="section" id="create-a-serial-terminal"&gt;
&lt;h3&gt;Create a serial terminal&lt;/h3&gt;
&lt;p&gt;By default, gem5 uses the serial port to allow communication from the host system to the simulated system.
To use this, we need to create a serial tty.
Since Ubuntu uses upstart to control the init process, we need to add a file to /etc/init which will initialize our terminal.
Also, in this file, we will add some code to detect if there was a script passed to the simulated system.
If there is a script, we will execute the script instead of creating a terminal.&lt;/p&gt;
&lt;p&gt;Put the following code into a file called /etc/init/tty-gem5.conf&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;# ttyS0 - getty
#
# This service maintains a getty on ttyS0 from the point the system is
# started until it is shut down again, unless there is a script passed to gem5.
# If there is a script, the script is executed then simulation is stopped.

start on stopped rc RUNLEVEL=[12345]
stop on runlevel [!12345]

console owner
respawn
script
   # Create the serial tty if it doesn&amp;#39;t already exist
   if [ ! -c /dev/ttyS0 ]
   then
      mknod /dev/ttyS0 -m 660 /dev/ttyS0 c 4 64
   fi

   # Try to read in the script from the host system
   /sbin/m5 readfile &amp;gt; /tmp/script
   chmod 755 /tmp/script
   if [ -s /tmp/script ]
   then
      # If there is a script, execute the script and then exit the simulation
      exec su root -c &amp;#39;/tmp/script&amp;#39; # gives script full privileges as root user in multi-user mode
      /sbin/m5 exit
   else
      # If there is no script, login the root user and drop to a console
      # Use m5term to connect to this console
      exec /sbin/getty --autologin root -8 38400 ttyS0
   fi
end script
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="setup-localhost"&gt;
&lt;h3&gt;Setup localhost&lt;/h3&gt;
&lt;p&gt;We also need to set up the localhost loopback device if we are going to use any applications that use it.
To do this, we need to add the following to the &lt;tt class="docutils literal"&gt;/etc/hosts&lt;/tt&gt; file.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="update-fstab"&gt;
&lt;h3&gt;Update fstab&lt;/h3&gt;
&lt;p&gt;Next, we need to create an entry in &lt;tt class="docutils literal"&gt;/etc/fstab&lt;/tt&gt; for each partition we want to be able to access from the simulated system.
Only one partition is absolutely required (&lt;tt class="docutils literal"&gt;/&lt;/tt&gt;); however, you may want to add additional partitions, like a swap partition.&lt;/p&gt;
&lt;p&gt;The following should appear in the file &lt;tt class="docutils literal"&gt;/etc/fstab&lt;/tt&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;# /etc/fstab: static file system information.
#
# Use &amp;#39;blkid&amp;#39; to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# &amp;lt;file system&amp;gt;    &amp;lt;mount point&amp;gt;   &amp;lt;type&amp;gt;  &amp;lt;options&amp;gt;       &amp;lt;dump&amp;gt;  &amp;lt;pass&amp;gt;
/dev/hda1          /               ext3            noatime         0 1
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="copy-the-m5-binary-to-the-disk"&gt;
&lt;h3&gt;Copy the &lt;tt class="docutils literal"&gt;m5&lt;/tt&gt; binary to the disk&lt;/h3&gt;
&lt;p&gt;gem5 comes with an extra binary application that executes pseudo-instructions to allow the simulated system to interact with the host system.
To build this binary, run &lt;tt class="docutils literal"&gt;make &lt;span class="pre"&gt;-f&lt;/span&gt; &lt;span class="pre"&gt;Makefile.&amp;lt;isa&amp;gt;&lt;/span&gt;&lt;/tt&gt; in the &lt;tt class="docutils literal"&gt;gem5/m5&lt;/tt&gt; directory, where &lt;tt class="docutils literal"&gt;&amp;lt;isa&amp;gt;&lt;/tt&gt; is the ISA that you are simulating (e.g., x86).
After this, you should have an &lt;tt class="docutils literal"&gt;m5&lt;/tt&gt; binary file.
Copy this file to /sbin on your newly created disk.&lt;/p&gt;
&lt;p&gt;After updating the disk with all of the gem5-specific files, unless you are going on to add more applications or copying additional files, unmount the disk image.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&amp;gt; util/gem5img.py umount mnt
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="install-new-applications"&gt;
&lt;h2&gt;Install new applications&lt;/h2&gt;
&lt;p&gt;The easiest way to install new applications on to your disk, is to use &lt;tt class="docutils literal"&gt;chroot&lt;/tt&gt;.
This program logically changes the root directory (&amp;quot;/&amp;quot;) to a different directory, mnt in this case.
Before you can change the root, you first have to set up the special directories in your new root.
To do this, we use &lt;tt class="docutils literal"&gt;mount &lt;span class="pre"&gt;-o&lt;/span&gt; bind&lt;/tt&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&amp;gt; sudo /bin/mount -o &lt;span class="nb"&gt;bind&lt;/span&gt; /sys mnt/sys
&amp;gt; sudo /bin/mount -o &lt;span class="nb"&gt;bind&lt;/span&gt; /dev mnt/dev
&amp;gt; sudo /bin/mount -o &lt;span class="nb"&gt;bind&lt;/span&gt; /proc mnt/proc
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After binding those directories, you can now &lt;tt class="docutils literal"&gt;chroot&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&amp;gt; sudo /usr/sbin/chroot mnt /bin/bash
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At this point you will see a root prompt and you will be in the &lt;tt class="docutils literal"&gt;/&lt;/tt&gt; directory of your new disk.&lt;/p&gt;
&lt;p&gt;You should update your repository information.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&amp;gt; apt-get update
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You may want to add the universe repositories to your list with the following commands.
Note: The first command is require in 14.04.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&amp;gt; apt-get install software-properties-common
&amp;gt; add-apt-repository universe
&amp;gt; apt-get update
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, you are able to install any applications you could install on a native Ubuntu machine via &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;apt-get&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Remember, after you exit you need to unmount all of the directories we used bind on.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&amp;gt; sudo /bin/umount mnt/sys
&amp;gt; sudo /bin/umount mnt/proc
&amp;gt; sudo /bin/umount mnt/dev
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
</content></entry><entry><title>gem5 Horrors and what we can do about it</title><link href="http://www.lowepower.com/jason/gem5-horrors-and-what-we-can-do-about-it.html" rel="alternate"></link><published>2015-06-09T00:00:00-05:00</published><updated>2015-06-09T00:00:00-05:00</updated><author><name>Jason Power</name></author><id>tag:www.lowepower.com,2015-06-09:/jason/gem5-horrors-and-what-we-can-do-about-it.html</id><summary type="html">&lt;img alt="Little Shop of gem5 Horrors" class="align-center" src="images/gem5-horrors.png" style="width: 300px;" /&gt;
&lt;p&gt;This post is a post which mostly follows the talk that I am giving at the &lt;a class="reference external" href="http://gem5.org/User_workshop_2015"&gt;gem5 Users Workshop&lt;/a&gt;.
This post contains some more details on problems that I skipped in my talk and some references that I was not able to include in a presentation.
You can view my …&lt;/p&gt;</summary><content type="html">&lt;img alt="Little Shop of gem5 Horrors" class="align-center" src="images/gem5-horrors.png" style="width: 300px;" /&gt;
&lt;p&gt;This post is a post which mostly follows the talk that I am giving at the &lt;a class="reference external" href="http://gem5.org/User_workshop_2015"&gt;gem5 Users Workshop&lt;/a&gt;.
This post contains some more details on problems that I skipped in my talk and some references that I was not able to include in a presentation.
You can view my presentation on Google Drive &lt;a class="reference external" href="https://docs.google.com/presentation/d/1QGA5UVaVJkkMITF2TXCY_KlwmfWef1KBzfDP6ocbj7I/pub?start=false&amp;amp;loop=false&amp;amp;delayms=3000"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="i-3-gem5"&gt;
&lt;h2&gt;I &amp;lt;3 gem5&lt;/h2&gt;
&lt;p&gt;Before I get into the negative aspects of &lt;a class="reference external" href="http://gem5.org"&gt;gem5&lt;/a&gt;, I first want to point out that it is a great tool.
gem5 is used by a large number of computer architecture researchers, both in industry and in academia.
Here at Wisconsin, and at other universities, gem5 is used in the classroom to teach students about computer architecture and how to do computer architecture research.&lt;/p&gt;
&lt;p&gt;gem5 is, without a doubt, the most full-featured architecture simulator.
It leverages execute-at-execute semantics for high-fidelity cycle-by-cycle simulation.
gem5 can boot a mostly unmodified Linux image.
It has multiple different CPU and memory models.
gem5 has a modular design which makes it simple to embed and extend.
This has allowed gem5 to be used a large number of projects (see &lt;a class="reference external" href="http://gem5.org/Projects"&gt;http://gem5.org/Projects&lt;/a&gt; and &lt;a class="reference external" href="http://gem5.org/Publications"&gt;http://gem5.org/Publications&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;However, as great as gem5 is, its growth has not been without pain.
Now that gem5 is nearing 15 years of development (if you include the original m5 and GEMS project from which gem5 was born), I believe it's time to look at some of its deficiencies and talk about what we can do to mitigate them.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="gem5-horrors"&gt;
&lt;h2&gt;gem5 horrors&lt;/h2&gt;
&lt;p&gt;Below, I discuss a few specific pain points with that I and others have experienced with gem5.
However, before I get to that, I'd like to talk about what I think the root of these issues are.
gem5 has two main problems&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;There is no formal governance model.&lt;/li&gt;
&lt;li&gt;The gem5 developers do not think of the user first.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Later, after I give some examples of specific problems, I will discuss what I think can be done to fix these to issues.&lt;/p&gt;
&lt;p&gt;Next I discuss four specific &amp;quot;gem5 horrors&amp;quot; that either I have personally experienced or I have talked to others who have experienced them.
These issues are deeper that just bugs, even if sometimes they can be solved with simple changes.
After describing each issue, I will also quickly discuss a possible way to mitigate the problem.&lt;/p&gt;
&lt;div class="section" id="horror-1-merges"&gt;
&lt;h3&gt;Horror 1: Merges&lt;/h3&gt;
&lt;p&gt;There are a number of projects that build on top of gem5.
In fact, I would argue that this is the main use case for gem5.
Everyone that I know who uses gem5 for research, takes the mainline gem5 and builds their own changes on top of it.&lt;/p&gt;
&lt;p&gt;The problem with this model, where people build on top of gem5, is that when new features are added or bugs are fixed in the mainline, downstream users have to consume these changes.
If the downstream users do a good job managing their patch queues, this should be a straightforward thing to do.
However, I have found that even when careful development practices are followed, merging gem5 changes is incredibly difficult.&lt;/p&gt;
&lt;p&gt;Below I discuss a few specific problems that I have run into when merging new changes in gem5.
I believe the problems can be summed up with two high-level issued we currently have in gem5.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;There is no well-defined static API. The interface to different modules is constantly in a state of flux.&lt;/li&gt;
&lt;li&gt;The regression suite we have in gem5 has poor coverage. There are many features that users depend on that are not covered by the regression tester.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="section" id="merge-headache-1-pointless-code-changes"&gt;
&lt;h4&gt;Merge headache #1: Pointless code changes&lt;/h4&gt;
&lt;p&gt;Examples from Ruby and Slicc and packet.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="merge-headache-2-features-break-between-versions"&gt;
&lt;h4&gt;Merge headache #2: Features break between versions&lt;/h4&gt;
&lt;p&gt;Ruby backing store, checkpointing&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="merge-headache-3-apis-are-a-moving-target"&gt;
&lt;h4&gt;Merge headache #3: APIs are a moving target&lt;/h4&gt;
&lt;p&gt;Example with the minimal gem5 script.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="how-to-mitigate"&gt;
&lt;h4&gt;How to mitigate&lt;/h4&gt;
&lt;p&gt;I believe that there are two things we can can do as the gem5 development community to make merging upstream changes much easier.
First, we need a stable set of APIs.
Second, we need a robust testing and regression structure.
I discuss some specifics of these two characteristics below.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="stable-apis"&gt;
&lt;h4&gt;Stable APIs&lt;/h4&gt;
&lt;p&gt;Today in gem5, it is just as easy to change widely used interfaces, like the port interface, as it is to change the implementation of a rarely used function.
We need to change this.
I think that we need to choose a set of interfaces and make them stable.
This is similar to how the Linux kernel operates.&lt;/p&gt;
&lt;p&gt;Once we have chosen a set of stable interfaces, I'm not suggesting that they never change, only that it should be more onerous to change stable APIs than other things.
Additionally, this has the added benefit that &amp;quot;gem5-stable&amp;quot; can actually mean something.
We can now have a stable version, which has non-changing APIs, and a dev version that we can't necessarily count on to have constant APIs.&lt;/p&gt;
&lt;p&gt;I personally do not know what the API should be.
I would like to see the community come together and talk about what they see as important interfaces.
Then, once we find these interfaces, we can architect these interfaces and hopefully make gem5 easier to use.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="testing-structure"&gt;
&lt;h4&gt;Testing structure&lt;/h4&gt;
&lt;p&gt;I do not think that this is a very controversial issue, but gem5 needs a better regression structure.
If all of the features that we used in gem5-gpu had been part of the regression suite, then we would have had many less problems.&lt;/p&gt;
&lt;p&gt;Again, I do not know exactly how to make the regression suite better, but I do think a good idea would be to require new features, and bug fixes, to include a unit-test or something like that.
We really need a softeare engineer to sit down and architect a new regression system.
This would be a great project for someone who is new to the gem5 codebase.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="horror-2-configuration-files"&gt;
&lt;h3&gt;Horror 2: Configuration files&lt;/h3&gt;
&lt;p&gt;gem5 has an incredibly flexible configuration system.
But with flexibility often come complexity.
In fact, I ran SLOCcount on the configs directory and found there was more than 4000 lines of Python code.
According to the SLOCcount tool, this means there was 16 person-months and a quarter of a million dollars worth of code here!&lt;/p&gt;
&lt;p&gt;All of this complexity causes a number of issues.
In my talk, I touched on the fact that the defaults are confusing, and in some cases inconsistent.&lt;/p&gt;
&lt;div class="section" id="id2"&gt;
&lt;h4&gt;How to mitigate&lt;/h4&gt;
&lt;p&gt;Since the m5 and GEMS integration, I have noticed a trend that the number of command line parameters has continued to grow significantly.
It seems that every time a new feature has been added, we have added some new command line parameters as well.
I think this is the wrong way to do it.&lt;/p&gt;
&lt;p&gt;There is an amazing C++-Python wrapper in gem5.
We should be taking advantage of the scripting capabilities of Python.&lt;/p&gt;
&lt;p&gt;I have created a simple script that is under 30 lines of Python.
I think we need to encourage our users to script in Python instead of adding more and more command line parameters.
Which, in my experience, really just leads to scripting in bash instead of in Python anyway.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="horror-3-unexpected-results"&gt;
&lt;h3&gt;Horror 3: Unexpected results&lt;/h3&gt;
&lt;p&gt;This was a very surprising error that I ran into while working on creating a homework assignment for a graduate-level computer architecture course.
The point of the homework was to compare the performance of instruction latency versus instruction throughput.
I wanted the students to take a particular instruction and change the number of execution units, the latency, and how much the units were pipelined.
To do this, we looked at the divide instruction, since it is a long latency instruction.
Below is the code that we used:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this code, every divide is totally independent from every other.
Therefore, we would expect that with he out-of-order CPU, that if the divide is pipelined it the code will speedup by how much the divide unit is pipelined.&lt;/p&gt;
&lt;p&gt;To test this, I looked at two different configurations, a 10 cycle latency divide with &lt;em&gt;no&lt;/em&gt; pipelining, and a 10 cycle latency divide that is fully pipelined.
Below is the data I found for ARM and x86.
I only changed the &amp;quot;obvious&amp;quot; options.
Each functional unit has an option for the execution latency and issue latency.
If the issue latency is 1, then the functional unit is fully pipelined. (Now this is a boolean flag.)
All of the data is relative to x86 with no pipelining.&lt;/p&gt;
&lt;table border="1" class="docutils"&gt;
&lt;colgroup&gt;
&lt;col width="23%" /&gt;
&lt;col width="17%" /&gt;
&lt;col width="20%" /&gt;
&lt;col width="18%" /&gt;
&lt;col width="22%" /&gt;
&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td&gt;Configuration&lt;/td&gt;
&lt;td&gt;Latency&lt;/td&gt;
&lt;td&gt;Issue lat.&lt;/td&gt;
&lt;td&gt;x86 Perf&lt;/td&gt;
&lt;td&gt;ARM Perf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;No Pipeline&lt;/td&gt;
&lt;td&gt;10 cycles&lt;/td&gt;
&lt;td&gt;10 cycles&lt;/td&gt;
&lt;td&gt;1.0x&lt;/td&gt;
&lt;td&gt;8.0x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Full Pipeline&lt;/td&gt;
&lt;td&gt;10 cycles&lt;/td&gt;
&lt;td&gt;1 cycle&lt;/td&gt;
&lt;td&gt;1.0x&lt;/td&gt;
&lt;td&gt;9.6x (1.2x)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;There are two very weird results in this data.
First, when we fully pipelined the divide unit, there was no performance change (at all!!) in x86.
Second, when running the exact same cod with ARM, there was a 8x speedup compared to x86!
I find it very hard to believe that the ARM ISA is inherently better at divide than x86.&lt;/p&gt;
&lt;div class="section" id="id3"&gt;
&lt;h4&gt;How to mitigate&lt;/h4&gt;
&lt;p&gt;This is a much harder problem to mitigate than the others on this list.
Nilay Vaish has taken a step in the right directions with these two patches on reviewboard &lt;a class="reference external" href="http://reviews.gem5.org/r/2744/"&gt;http://reviews.gem5.org/r/2744/&lt;/a&gt; and &lt;a class="reference external" href="http://reviews.gem5.org/r/2744/"&gt;http://reviews.gem5.org/r/2744/&lt;/a&gt;, which have been incorporated in gem5.&lt;/p&gt;
&lt;p&gt;The underlying problem is that the implementation for ARM and x86 are totally distinct.
It is not clear to me what the right way to unify the ISA implementation are.
As a stop-gap, developers who are working on implementing x86 features, need to make sure that they perform similarly to ARM features.
Maybe a solution is to have a single set of C programs which exercise all ISAs and compare the performance across ISAs.
There should be some performance differences, but not an order of magnitude.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="horror-4-lack-of-new-user-support"&gt;
&lt;h3&gt;Horror 4: Lack of new-user support&lt;/h3&gt;
&lt;div class="section" id="id4"&gt;
&lt;h4&gt;How to mitigate&lt;/h4&gt;
&lt;p&gt;What I think we need to do is to create a &amp;quot;gem5 for Dummies&amp;quot; book or a &amp;quot;Learning gem5&amp;quot; book.
This book would be similar to &lt;cite&gt;Learning Python&lt;/cite&gt; or &lt;cite&gt;Learning Mercurial&lt;/cite&gt;.
The book would be open source for anyone to contribute to.
In fact, it should be required to update the book if a developer makes an API-breaking change.&lt;/p&gt;
&lt;p&gt;An initial implementation of this book, which currently only includes about a chapter of &amp;quot;getting started&amp;quot; and is in fact already out of date can be found here: &lt;a class="reference external" href="http://pages.cs.wisc.edu/~david/courses/cs752/Spring2015/gem5-tutorial/index.html"&gt;gem5-tutorial&lt;/a&gt;.
I began working on this in conjunction with the graduate computer architecture class at Wisconsin, so it may currently have some Wisconsin-specific text.
I hope to continue working on this in my &lt;em&gt;copious free time&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;There are many other horrors that other people experience as well.
Here I only discussed some of the horrors that I have heard people discussing.
The purpose in presenting these horrors is not to say that gem5 is a bad simulator!
The purpose is to highlight how there are currently issues that need to be addressed by the gem5 development community.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="what-can-we-do-about-it"&gt;
&lt;h2&gt;What can we do about it?&lt;/h2&gt;
&lt;p&gt;A lot of the problems that I have discussed above come down to poor software engineering.
And yes, we are architects, not software engineers, and there are a lot of things we could do better if we just focused on software engineering.
However, I do not think that this is the underlying issue.&lt;/p&gt;
&lt;p&gt;I believe these four horror stem from two systemic problems in the gem5 development community.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;There is no formal governance model.&lt;/li&gt;
&lt;li&gt;The gem5 developers do not think of the user first.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I believe that if we start to solve these high-level issues, gem5 will be a much better tool for everyone.
Next, I discuss one possible way to address these two points.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="gem5-foundation"&gt;
&lt;h2&gt;gem5 Foundation&lt;/h2&gt;
&lt;p&gt;First, I want to say that I do not believe this is the only way, or the right way, to move gem5 forward.
This is one possibility that I believe will make gem5 a better tool.
I hope that this is a place to begin the discussion and I am sure that others in our community can come up with even better suggestions that this!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I think we should create a gem5 Foundation.&lt;/em&gt;
The gem5 Foundation will be the center for the gem5 community.
It will be a formal way for the community to set goals and push gem5 forward.&lt;/p&gt;
&lt;p&gt;There are two main things I think the gem5 Foundation can help us with.
It can set up a formal governance structure and be a place for outside interests to contribute money towards making gem5 better for everyone.&lt;/p&gt;
&lt;div class="section" id="formalizing-a-governance-structure"&gt;
&lt;h3&gt;Formalizing a governance structure&lt;/h3&gt;
&lt;p&gt;First, we need a governance structure.
This is a document which defines how decisions are made in the community, what matters to the community, how to contribute to the community, etc.&lt;/p&gt;
&lt;p&gt;There is a lot of documentation on how to write governance models and what they are.
&lt;a class="reference external" href="http://oss-watch.ac.uk/"&gt;OSS-Watch&lt;/a&gt; is a great source for this.
Here is a link to a definition of a governance model, which does a much better job that I can explaining it.
&lt;a class="reference external" href="http://oss-watch.ac.uk/resources/governancemodels"&gt;http://oss-watch.ac.uk/resources/governancemodels&lt;/a&gt;
Additionally, here is a link to an example governance model from an academic open-source project: &lt;a class="reference external" href="http://www.taverna.org.uk/about/legal-stuff/taverna-governance-model/"&gt;http://www.taverna.org.uk/about/legal-stuff/taverna-governance-model/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="money-money-money"&gt;
&lt;h3&gt;Money, Money, Money&lt;/h3&gt;
&lt;p&gt;What I think the main solution to all of these problems is to pay software developers &lt;em&gt;not computer architects!&lt;/em&gt; to solve some of these problems.
Already, within ARM and AMD there are a number of people who get paid to work on gem5.
However, these companies do not have gem5's best interests as their key focus.
Their focus is what ARM and AMD find interesting.&lt;/p&gt;
&lt;p&gt;So, I think that if we have something like the gem5 Foundation, these companies and academia, can donate money towards coding things that are good for the community as a whole.
The gem5 Foundation can hire software engineers to work on the parts of gem5 that grad students and researchers do not want to do.
If you look at other academic communities, they often hire non researchers to do the &amp;quot;grunt work&amp;quot;.
Overall, I think this is a good idea for computer architects too, and specifically for gem5.&lt;/p&gt;
&lt;p&gt;I recognize that this may be a crazy idea.
I would love to hear what others think.
I am sure we will have some interesting discussion at the gem5 workshop, and hopefully I will write another post with what other people thought!
Feel free to leave comments below.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</content></entry><entry><title>Setting up a gem5 container</title><link href="http://www.lowepower.com/jason/setting-up-a-gem5-container.html" rel="alternate"></link><published>2015-04-22T00:00:00-05:00</published><updated>2015-04-22T00:00:00-05:00</updated><author><name>Jason Power</name></author><id>tag:www.lowepower.com,2015-04-22:/jason/setting-up-a-gem5-container.html</id><summary type="html">&lt;p&gt;&lt;a class="reference external" href="https://linuxcontainers.org/"&gt;Linux containers&lt;/a&gt; (LXC) are a relatively new feature in Linux.
From what I gather, they allow you to create a sandboxed environment to run applications.
Containers are somewhere between processes and a full virtual machine.
They allow you to use and link to any libraries or applications you need, but …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a class="reference external" href="https://linuxcontainers.org/"&gt;Linux containers&lt;/a&gt; (LXC) are a relatively new feature in Linux.
From what I gather, they allow you to create a sandboxed environment to run applications.
Containers are somewhere between processes and a full virtual machine.
They allow you to use and link to any libraries or applications you need, but they don't cost the same high overheads as full virtualization.&lt;/p&gt;
&lt;p&gt;For gem5, I've been told by some people (mostly &lt;a class="reference external" href="http://pages.cs.wisc.edu/~swift/"&gt;Mike Swift&lt;/a&gt;) that I should look at containers and &lt;a class="reference external" href="https://www.docker.com/"&gt;Docker&lt;/a&gt; to see if it would be something useful for the gem5 community.
So, in this post, I walk through what it took to set up a container for gem5.&lt;/p&gt;
&lt;p&gt;&amp;lt;I WANT AN INSET OR SOMETHING&amp;gt;
After I completed the post, I came back to this section to evaluate whether the work I put into creating a gem5 container was worth it.&lt;/p&gt;
&lt;p&gt;In a word: &amp;quot;no&amp;quot;.&lt;/p&gt;
&lt;p&gt;I don't see the use case for the gem5 container that I just created.
Maybe it's that I don't understand what containers are, or how to distribute them.
The way I see it, I have just created a useful tool for myself, but it's not much use to the community as a whole.
Next, I'm going to try to develop a gem5 Docker application.
Maybe that will be more useful.&lt;/p&gt;
&lt;div class="section" id="install-and-configure-lxc-in-ubuntu"&gt;
&lt;h2&gt;Install and configure lxc in Ubuntu&lt;/h2&gt;
&lt;p&gt;The first step is to install lxc, obviously.
For the most part, I followed the documentation from the Linux Containers .&lt;/p&gt;
&lt;p&gt;In Ubuntu it was as simple as:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&amp;gt; sudo apt-get install lxc
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, I needed to set up user-mode unprivileged containers for my primary user (jason).
First, I found my userid from &lt;tt class="docutils literal"&gt;/etc/subuid&lt;/tt&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;jason:100000:65536
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then, I added my username as an allowed user of the virtual ethernet device by adding the following line to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/etc/lxc/lxc-usernet&lt;/span&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;jason veth lxcbr0 10
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then, as specified in the &lt;a class="reference external" href="https://linuxcontainers.org/lxc/getting-started/"&gt;getting started page&lt;/a&gt;, I created the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.config/lxc&lt;/span&gt;&lt;/tt&gt; directory and copied &lt;tt class="docutils literal"&gt;/etc/lxc/default.conf&lt;/tt&gt; to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.config/lxc/default.conf&lt;/span&gt;&lt;/tt&gt;.
Finally, I added the following lines to that file. Note that I copied the nubers from &lt;tt class="docutils literal"&gt;/etc/subuid&lt;/tt&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;lxc.id_map = u 0 100000 65536
lxc.id_map = g 0 100000 65536
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, I needed to add one more line to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.config/lxc/default.conf&lt;/span&gt;&lt;/tt&gt;.
From what I can tell, there is a bug with my version of Ubuntu and AppArmor, though the pages I found describing the issue were not very clear.
I saw the following error when I initially tried to start my container with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;lxc-start&lt;/span&gt; &lt;span class="pre"&gt;-n&lt;/span&gt; &lt;span class="pre"&gt;my-container&lt;/span&gt; &lt;span class="pre"&gt;-F&lt;/span&gt;&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;lxc-start: lsm/apparmor.c: apparmor_process_label_set: 169 If you really want to start this container, set
lxc-start: lsm/apparmor.c: apparmor_process_label_set: 170 lxc.aa_allow_incomplete = 1
lxc-start: lsm/apparmor.c: apparmor_process_label_set: 171 in your container configuration file
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To solve this problem, I added the follwing to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.config/lxc/default.conf&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;lxc.aa_allow_incomplete = 1
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, I was ready to create a new container for gem5.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="creating-a-container"&gt;
&lt;h2&gt;Creating a container&lt;/h2&gt;
&lt;p&gt;You can use the following command to create a container based on the images from linuxcontainers.org:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&amp;gt; lxc-create -t download -n gem5-container
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You will be shown a number of distributions, versions, and architecture options. I chose Ubuntu, trusty, and amd64.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Distribution: ubuntu
Release: trusty
Architecture: amd64
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, you can start and log into the container with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&amp;gt; lxc-start -n gem5-container -d
&amp;gt; lxc-attach -n gem5-container
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="installing-gem5-dependencies"&gt;
&lt;h3&gt;Installing gem5 dependencies&lt;/h3&gt;
&lt;p&gt;The next step is installing of the dependencies for gem5.
The current dependencies can be found on the &lt;a class="reference external" href="http://gem5.org/Dependencies"&gt;gem5 website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can execute the following &lt;cite&gt;apt-get&lt;/cite&gt; command to get all of gem5's dependencies:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&amp;gt; apt-get install build-essential gdb python-dev scons swig zlib1g-dev m4 libprotobuf-dev python-protobuf protobuf-compiler libgoogle-perftools-dev
&amp;gt; apt-get --no-install-recommends install mercurial
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="finishing-up"&gt;
&lt;h3&gt;Finishing up&lt;/h3&gt;
&lt;p&gt;Next, I created a gem5 user, with the username &lt;tt class="docutils literal"&gt;gem5&lt;/tt&gt; and password &lt;tt class="docutils literal"&gt;gem5&lt;/tt&gt;.
This will allow us to keep gem5 relatively sandboxed when building and running.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&amp;gt; useradd gem5
&amp;gt; passwd gem5
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Before downloading gem5, let's checkpoint our current state so we can come back to it in the future for a clean gem5-free system.
First, we have to halt the container by using the &lt;tt class="docutils literal"&gt;halt&lt;/tt&gt; command&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&amp;gt; halt
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After this, we are dumped back out to the host-system's terminal.
Now we can clone the container with the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&amp;gt; lxc-clone gem5-container gem5-depends
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And restart the container:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&amp;gt; lxc-start -n gem5-container -d
&amp;gt; lxc-attach -n gem5-container
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="downloading-and-building-gem5"&gt;
&lt;h2&gt;Downloading and building gem5&lt;/h2&gt;
&lt;p&gt;Now, let's change to the gem5 user and install and build gem5.
We'll put gem5 in &lt;tt class="docutils literal"&gt;/opt/gem5&lt;/tt&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&amp;gt; mkdir /opt/gem5
&amp;gt; chmod a+rw gem5
&amp;gt; su gem5
&amp;gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /opt
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After creating the directory, we can clone gem5!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&amp;gt; hg clone clone http://repo.gem5.org/gem5 gem5
&amp;gt; &lt;span class="nb"&gt;cd&lt;/span&gt; gem5
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When you list the directory you should see the following from the gem5 repository:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;build_opts  configs  COPYING  ext  LICENSE  README  SConstruct        src  system  tests  util
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, we can build gem5.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;scons build/X86/gem5.opt
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You will be asked to install the style hook the first time you build gem5.
Just press enter and the style hook will automatically be added to you &lt;tt class="docutils literal"&gt;.hg/hgrc&lt;/tt&gt; file.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;You&amp;#39;re missing the gem5 style hook, which automatically checks your code
against the gem5 style rules on hg commit and qrefresh commands.  This
script will now install the hook in your .hg/hgrc file.
Press enter to continue, or ctrl-c to abort:
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we have a full, sandboxed, development environment for gem5!
We can use this to build and make changes to gem5 without affecting the system we are running on.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Tools"></category></entry><entry><title>First post!</title><link href="http://www.lowepower.com/jason/first-post.html" rel="alternate"></link><published>2015-04-08T00:00:00-05:00</published><updated>2015-04-08T00:00:00-05:00</updated><author><name>Jason Power</name></author><id>tag:www.lowepower.com,2015-04-08:/jason/first-post.html</id><summary type="html">&lt;div class="section" id="this-is-my-first-post"&gt;
&lt;h2&gt;This is my first post!&lt;/h2&gt;
&lt;p&gt;So, I've decided that I am going to try to keep a blog of sorts.&lt;/p&gt;
&lt;p&gt;In my work in computer architecture, there are a number of things that I've done that don't warrant writing a whole paper on them, but it seems like it may …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="section" id="this-is-my-first-post"&gt;
&lt;h2&gt;This is my first post!&lt;/h2&gt;
&lt;p&gt;So, I've decided that I am going to try to keep a blog of sorts.&lt;/p&gt;
&lt;p&gt;In my work in computer architecture, there are a number of things that I've done that don't warrant writing a whole paper on them, but it seems like it may be useful to other in the community.
I foresee this being the biggest use of this blog.
However, I may get distracted with other things now and then.&lt;/p&gt;
&lt;/div&gt;
</content></entry></feed>