<!DOCTYPE html>
<html lang='en'>
<head>
<title>xen/xen - xen</title>
<meta name='generator' content='cgit v1.2.3'/>
<meta name='robots' content='index, nofollow'/>
<link rel='stylesheet' type='text/css' href='/cgit.css'/>
<link rel='shortcut icon' href='/favicon.ico'/>
<link rel='alternate' title='Atom feed' href='http://openwrt.panaceas.org/cgit/xen/xen/atom/xen/arch/x86/hvm/svm/svm.c?h=master' type='application/atom+xml'/>
<link rel='vcs-git' href='git://git.panaceas.org/xen/xen' title='xen/xen Git repository'/>
<link rel='vcs-git' href='ssh://git@git.panaceas.org/git/xen/xen' title='xen/xen Git repository'/>
</head>
<body>
<div id='cgit'><table id='header'>
<tr>
<td class='logo' rowspan='2'><a href='/cgit/'><img src='/cgit.png' alt='cgit logo'/></a></td>
<td class='main'><a href='/cgit/'>index</a> : <a title='xen/xen' href='/cgit/xen/xen/'>xen/xen</a></td><td class='form'><form method='get'>
<input type='hidden' name='id2' value='d11b4a6bd23c951dc6e7e2e9345938c5e6f8538b'/><select name='h' onchange='this.form.submit();'>
<option value='master' selected='selected'>master</option>
<option value='stable-4.0'>stable-4.0</option>
<option value='stable-4.1'>stable-4.1</option>
<option value='stable-4.2'>stable-4.2</option>
<option value='stable-4.3'>stable-4.3</option>
<option value='staging'>staging</option>
<option value='staging-4.0'>staging-4.0</option>
<option value='staging-4.1'>staging-4.1</option>
<option value='staging-4.2'>staging-4.2</option>
<option value='staging-4.3'>staging-4.3</option>
</select> <input type='submit' value='switch'/></form></td></tr>
<tr><td class='sub'>xen</td><td class='sub right'>James</td></tr></table>
<table class='tabs'><tr><td>
<a href='/cgit/xen/xen/about/'>about</a><a href='/cgit/xen/xen/'>summary</a><a href='/cgit/xen/xen/refs/'>refs</a><a href='/cgit/xen/xen/log/xen/arch/x86/hvm/svm/svm.c'>log</a><a href='/cgit/xen/xen/tree/xen/arch/x86/hvm/svm/svm.c'>tree</a><a href='/cgit/xen/xen/commit/xen/arch/x86/hvm/svm/svm.c'>commit</a><a class='active' href='/cgit/xen/xen/diff/xen/arch/x86/hvm/svm/svm.c?id2=d11b4a6bd23c951dc6e7e2e9345938c5e6f8538b'>diff</a><a href='/cgit/xen/xen/stats/xen/arch/x86/hvm/svm/svm.c'>stats</a></td><td class='form'><form class='right' method='get' action='/cgit/xen/xen/log/xen/arch/x86/hvm/svm/svm.c'>
<input type='hidden' name='id2' value='d11b4a6bd23c951dc6e7e2e9345938c5e6f8538b'/><select name='qt'>
<option value='grep'>log msg</option>
<option value='author'>author</option>
<option value='committer'>committer</option>
<option value='range'>range</option>
</select>
<input class='txt' type='search' size='10' name='q' value=''/>
<input type='submit' value='search'/>
</form>
</td></tr></table>
<div class='path'>path: <a href='/cgit/xen/xen/diff/?id2=d11b4a6bd23c951dc6e7e2e9345938c5e6f8538b'>root</a>/<a href='/cgit/xen/xen/diff/xen?id2=d11b4a6bd23c951dc6e7e2e9345938c5e6f8538b'>xen</a>/<a href='/cgit/xen/xen/diff/xen/arch?id2=d11b4a6bd23c951dc6e7e2e9345938c5e6f8538b'>arch</a>/<a href='/cgit/xen/xen/diff/xen/arch/x86?id2=d11b4a6bd23c951dc6e7e2e9345938c5e6f8538b'>x86</a>/<a href='/cgit/xen/xen/diff/xen/arch/x86/hvm?id2=d11b4a6bd23c951dc6e7e2e9345938c5e6f8538b'>hvm</a>/<a href='/cgit/xen/xen/diff/xen/arch/x86/hvm/svm?id2=d11b4a6bd23c951dc6e7e2e9345938c5e6f8538b'>svm</a>/<a href='/cgit/xen/xen/diff/xen/arch/x86/hvm/svm/svm.c?id2=d11b4a6bd23c951dc6e7e2e9345938c5e6f8538b'>svm.c</a></div><div class='content'><div class='cgit-panel'><b>diff options</b><form method='get'><input type='hidden' name='id2' value='d11b4a6bd23c951dc6e7e2e9345938c5e6f8538b'/><table><tr><td colspan='2'/></tr><tr><td class='label'>context:</td><td class='ctrl'><select name='context' onchange='this.form.submit();'><option value='1'>1</option><option value='2'>2</option><option value='3' selected='selected'>3</option><option value='4'>4</option><option value='5'>5</option><option value='6'>6</option><option value='7'>7</option><option value='8'>8</option><option value='9'>9</option><option value='10'>10</option><option value='15'>15</option><option value='20'>20</option><option value='25'>25</option><option value='30'>30</option><option value='35'>35</option><option value='40'>40</option></select></td></tr><tr><td class='label'>space:</td><td class='ctrl'><select name='ignorews' onchange='this.form.submit();'><option value='0' selected='selected'>include</option><option value='1'>ignore</option></select></td></tr><tr><td class='label'>mode:</td><td class='ctrl'><select name='dt' onchange='this.form.submit();'><option value='0' selected='selected'>unified</option><option value='1'>ssdiff</option><option value='2'>stat only</option></select></td></tr><tr><td/><td class='ctrl'><noscript><input type='submit' value='reload'/></noscript></td></tr></table></form></div><div class='diffstat-header'><a href='/cgit/xen/xen/diff/?id2=d11b4a6bd23c951dc6e7e2e9345938c5e6f8538b'>Diffstat</a> (limited to 'xen/arch/x86/hvm/svm/svm.c')</div><table summary='diffstat' class='diffstat'><tr><td class='mode'>-rw-r--r--</td><td class='upd'><a href='/cgit/xen/xen/diff/xen/arch/x86/hvm/svm/svm.c?id2=d11b4a6bd23c951dc6e7e2e9345938c5e6f8538b'>xen/arch/x86/hvm/svm/svm.c</a></td><td class='right'>1558</td><td class='graph'><table summary='file diffstat' width='100%'><tr><td class='add' style='width: 79.7%;'/><td class='rem' style='width: 20.3%;'/><td class='none' style='width: 0.0%;'/></tr></table></td></tr>
</table><div class='diffstat-summary'>1 files changed, 1241 insertions, 317 deletions</div><table summary='diff' class='diff'><tr><td><div class='head'>diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/<style>pre { line-height: 125%; margin: 0; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #ffffff; }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */</style><div class="highlight"><pre><span></span>Because OpenWrt uses its own init script system, all init scripts must be installed
as <span class="k">\texttt</span><span class="nb">{</span>/etc/init.d/<span class="k">\textit</span><span class="nb">{</span>name<span class="nb">}}</span> use <span class="k">\texttt</span><span class="nb">{</span>/etc/rc.common<span class="nb">}</span> as a wrapper.

Example: <span class="k">\texttt</span><span class="nb">{</span>/etc/init.d/httpd<span class="nb">}</span>

<span class="k">\begin</span><span class="nb">{</span>Verbatim<span class="nb">}</span>
#!/bin/sh /etc/rc.common
# Copyright (C) 2006 OpenWrt.org

START=50
start() <span class="nb">{</span>
    [ -d /www ] <span class="nb">&amp;&amp;</span> httpd -p 80 -h /www -r OpenWrt
<span class="nb">}</span>

stop() <span class="nb">{</span>
    killall httpd
<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>Verbatim<span class="nb">}</span>

as you can see, the script does not actually parse the command line arguments itself.
This is done by the wrapper script <span class="k">\texttt</span><span class="nb">{</span>/etc/rc.common<span class="nb">}</span>.

<span class="k">\texttt</span><span class="nb">{</span>start()<span class="nb">}</span> and <span class="k">\texttt</span><span class="nb">{</span>stop()<span class="nb">}</span> are the basic functions, which almost any init
script should provide. <span class="k">\texttt</span><span class="nb">{</span>start()<span class="nb">}</span> is called when the user runs <span class="k">\texttt</span><span class="nb">{</span>/etc/init.d/httpd start<span class="nb">}</span>
or (if the script is enabled and does not override this behavior) at system boot time.

Enabling and disabling init scripts is done by running <span class="k">\texttt</span><span class="nb">{</span>/etc/init.d/<span class="k">\textit</span><span class="nb">{</span>name<span class="nb">}</span> enable<span class="nb">}</span>
or <span class="k">\texttt</span><span class="nb">{</span>/etc/init.d/<span class="k">\textit</span><span class="nb">{</span>name<span class="nb">}</span> disable<span class="nb">}</span>. This creates or removes symbolic links to the
init script in <span class="k">\texttt</span><span class="nb">{</span>/etc/rc.d<span class="nb">}</span>, which is processed by <span class="k">\texttt</span><span class="nb">{</span>/etc/init.d/rcS<span class="nb">}</span> at boot time.

The order in which these scripts are run is defined in the variable <span class="k">\texttt</span><span class="nb">{</span>START<span class="nb">}</span> in the init
script. Changing it requires running <span class="k">\texttt</span><span class="nb">{</span>/etc/init.d/<span class="k">\textit</span><span class="nb">{</span>name<span class="nb">}</span> enable<span class="nb">}</span> again.

You can also override these standard init script functions:
<span class="k">\begin</span><span class="nb">{</span>itemize<span class="nb">}</span>
    <span class="k">\item</span> <span class="k">\texttt</span><span class="nb">{</span>boot()<span class="nb">}</span> <span class="k">\\</span>
        Commands to be run at boot time. Defaults to <span class="k">\texttt</span><span class="nb">{</span>start()<span class="nb">}</span>

    <span class="k">\item</span> <span class="k">\texttt</span><span class="nb">{</span>restart()<span class="nb">}</span> <span class="k">\\</span>
        Restart your service. Defaults to <span class="k">\texttt</span><span class="nb">{</span>stop(); start()<span class="nb">}</span>

    <span class="k">\item</span> <span class="k">\texttt</span><span class="nb">{</span>reload()<span class="nb">}</span> <span class="k">\\</span>
        Reload the configuration files for your service. Defaults to <span class="k">\texttt</span><span class="nb">{</span>restart()<span class="nb">}</span>

<span class="k">\end</span><span class="nb">{</span>itemize<span class="nb">}</span>

You can also add custom commands by creating the appropriate functions and referencing them
in the <span class="k">\texttt</span><span class="nb">{</span>EXTRA<span class="k">\_</span>COMMANDS<span class="nb">}</span> variable. Helptext is added in <span class="k">\texttt</span><span class="nb">{</span>EXTRA<span class="k">\_</span>HELP<span class="nb">}</span>.

Example:

<span class="k">\begin</span><span class="nb">{</span>Verbatim<span class="nb">}</span>
status() <span class="nb">{</span>
    # print the status info
<span class="nb">}</span>

EXTRA<span class="nb">_</span>COMMANDS=&quot;status&quot;
EXTRA<span class="nb">_</span>HELP=&quot;        status  Print the status of the service&quot;
<span class="k">\end</span><span class="nb">{</span>Verbatim<span class="nb">}</span>
</pre></div>
</code></pre></td></tr></table>
</div> <!-- class=content -->
<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.2.3</a> (<a href='https://git-scm.com/'>git 2.25.1</a>) at 2026-02-22 12:16:22 +0000</div>
</div> <!-- id=cgit -->
</body>
</html>
lass='del'>-</div><div class='ctx'>     if ( v-&gt;arch.hvm_vcpu.flag_dr_dirty )</div><div class='ctx'>         return;</div><div class='ctx'> </div><div class='ctx'>     v-&gt;arch.hvm_vcpu.flag_dr_dirty = 1;</div><div class='del'>-    vmcb-&gt;dr_intercepts = 0;</div><div class='del'>-</div><div class='del'>-    write_debugreg(0, v-&gt;arch.guest_context.debugreg[0]);</div><div class='del'>-    write_debugreg(1, v-&gt;arch.guest_context.debugreg[1]);</div><div class='del'>-    write_debugreg(2, v-&gt;arch.guest_context.debugreg[2]);</div><div class='del'>-    write_debugreg(3, v-&gt;arch.guest_context.debugreg[3]);</div><div class='del'>-    vmcb-&gt;dr6 = v-&gt;arch.guest_context.debugreg[6];</div><div class='del'>-    vmcb-&gt;dr7 = v-&gt;arch.guest_context.debugreg[7];</div><div class='add'>+    vmcb_set_dr_intercepts(vmcb, 0);</div><div class='add'>+</div><div class='add'>+    write_debugreg(0, v-&gt;arch.debugreg[0]);</div><div class='add'>+    write_debugreg(1, v-&gt;arch.debugreg[1]);</div><div class='add'>+    write_debugreg(2, v-&gt;arch.debugreg[2]);</div><div class='add'>+    write_debugreg(3, v-&gt;arch.debugreg[3]);</div><div class='add'>+    vmcb_set_dr6(vmcb, v-&gt;arch.debugreg[6]);</div><div class='add'>+    vmcb_set_dr7(vmcb, v-&gt;arch.debugreg[7]);</div><div class='ctx'> }</div><div class='ctx'> </div><div class='ctx'> /*</div><div class='hunk'>@@ -176,8 +199,9 @@ static void __restore_debug_registers(struct vcpu *v)</div><div class='ctx'>  */</div><div class='ctx'> static void svm_restore_dr(struct vcpu *v)</div><div class='ctx'> {</div><div class='del'>-    if ( unlikely(v-&gt;arch.guest_context.debugreg[7] &amp; DR7_ACTIVE_MASK) )</div><div class='del'>-        __restore_debug_registers(v);</div><div class='add'>+    struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='add'>+    if ( unlikely(v-&gt;arch.debugreg[7] &amp; DR7_ACTIVE_MASK) )</div><div class='add'>+        __restore_debug_registers(vmcb, v);</div><div class='ctx'> }</div><div class='ctx'> </div><div class='ctx'> static int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c)</div><div class='hunk'>@@ -208,15 +232,15 @@ static int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c)</div><div class='ctx'> </div><div class='ctx'> static int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c)</div><div class='ctx'> {</div><div class='del'>-    unsigned long mfn = 0;</div><div class='del'>-    p2m_type_t p2mt;</div><div class='add'>+    struct page_info *page = NULL;</div><div class='ctx'>     struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='add'>+    struct p2m_domain *p2m = p2m_get_hostp2m(v-&gt;domain);</div><div class='ctx'> </div><div class='ctx'>     if ( c-&gt;pending_valid &amp;&amp;</div><div class='ctx'>          ((c-&gt;pending_type == 1) || (c-&gt;pending_type &gt; 6) ||</div><div class='ctx'>           (c-&gt;pending_reserved != 0)) )</div><div class='ctx'>     {</div><div class='del'>-        gdprintk(XENLOG_ERR, "Invalid pending event 0x%"PRIx32".\n",</div><div class='add'>+        gdprintk(XENLOG_ERR, "Invalid pending event %#"PRIx32".\n",</div><div class='ctx'>                  c-&gt;pending_event);</div><div class='ctx'>         return -EINVAL;</div><div class='ctx'>     }</div><div class='hunk'>@@ -225,10 +249,11 @@ static int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c)</div><div class='ctx'>     {</div><div class='ctx'>         if ( c-&gt;cr0 &amp; X86_CR0_PG )</div><div class='ctx'>         {</div><div class='del'>-            mfn = mfn_x(gfn_to_mfn(v-&gt;domain, c-&gt;cr3 &gt;&gt; PAGE_SHIFT, &amp;p2mt));</div><div class='del'>-            if ( !p2m_is_ram(p2mt) || !get_page(mfn_to_page(mfn), v-&gt;domain) )</div><div class='add'>+            page = get_page_from_gfn(v-&gt;domain, c-&gt;cr3 &gt;&gt; PAGE_SHIFT,</div><div class='add'>+                                     NULL, P2M_ALLOC);</div><div class='add'>+            if ( !page )</div><div class='ctx'>             {</div><div class='del'>-                gdprintk(XENLOG_ERR, "Invalid CR3 value=0x%"PRIx64"\n",</div><div class='add'>+                gdprintk(XENLOG_ERR, "Invalid CR3 value=%#"PRIx64"\n",</div><div class='ctx'>                          c-&gt;cr3);</div><div class='ctx'>                 return -EINVAL;</div><div class='ctx'>             }</div><div class='hunk'>@@ -237,31 +262,33 @@ static int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c)</div><div class='ctx'>         if ( v-&gt;arch.hvm_vcpu.guest_cr[0] &amp; X86_CR0_PG )</div><div class='ctx'>             put_page(pagetable_get_page(v-&gt;arch.guest_table));</div><div class='ctx'> </div><div class='del'>-        v-&gt;arch.guest_table = pagetable_from_pfn(mfn);</div><div class='add'>+        v-&gt;arch.guest_table =</div><div class='add'>+            page ? pagetable_from_page(page) : pagetable_null();</div><div class='ctx'>     }</div><div class='ctx'> </div><div class='ctx'>     v-&gt;arch.hvm_vcpu.guest_cr[0] = c-&gt;cr0 | X86_CR0_ET;</div><div class='ctx'>     v-&gt;arch.hvm_vcpu.guest_cr[2] = c-&gt;cr2;</div><div class='ctx'>     v-&gt;arch.hvm_vcpu.guest_cr[3] = c-&gt;cr3;</div><div class='ctx'>     v-&gt;arch.hvm_vcpu.guest_cr[4] = c-&gt;cr4;</div><div class='del'>-    hvm_update_guest_cr(v, 0);</div><div class='del'>-    hvm_update_guest_cr(v, 2);</div><div class='del'>-    hvm_update_guest_cr(v, 4);</div><div class='del'>-</div><div class='del'>-    v-&gt;arch.hvm_svm.guest_sysenter_cs = c-&gt;sysenter_cs;</div><div class='del'>-    v-&gt;arch.hvm_svm.guest_sysenter_esp = c-&gt;sysenter_esp;</div><div class='del'>-    v-&gt;arch.hvm_svm.guest_sysenter_eip = c-&gt;sysenter_eip;</div><div class='del'>-</div><div class='add'>+    svm_update_guest_cr(v, 0);</div><div class='add'>+    svm_update_guest_cr(v, 2);</div><div class='add'>+    svm_update_guest_cr(v, 4);</div><div class='add'>+</div><div class='add'>+    /* Load sysenter MSRs into both VMCB save area and VCPU fields. */</div><div class='add'>+    vmcb-&gt;sysenter_cs = v-&gt;arch.hvm_svm.guest_sysenter_cs = c-&gt;sysenter_cs;</div><div class='add'>+    vmcb-&gt;sysenter_esp = v-&gt;arch.hvm_svm.guest_sysenter_esp = c-&gt;sysenter_esp;</div><div class='add'>+    vmcb-&gt;sysenter_eip = v-&gt;arch.hvm_svm.guest_sysenter_eip = c-&gt;sysenter_eip;</div><div class='add'>+    </div><div class='ctx'>     if ( paging_mode_hap(v-&gt;domain) )</div><div class='ctx'>     {</div><div class='del'>-        vmcb-&gt;np_enable = 1;</div><div class='del'>-        vmcb-&gt;g_pat = MSR_IA32_CR_PAT_RESET; /* guest PAT */</div><div class='del'>-        vmcb-&gt;h_cr3 = pagetable_get_paddr(v-&gt;domain-&gt;arch.phys_table);</div><div class='add'>+        vmcb_set_np_enable(vmcb, 1);</div><div class='add'>+        vmcb_set_g_pat(vmcb, MSR_IA32_CR_PAT_RESET /* guest PAT */);</div><div class='add'>+        vmcb_set_h_cr3(vmcb, pagetable_get_paddr(p2m_get_pagetable(p2m)));</div><div class='ctx'>     }</div><div class='ctx'> </div><div class='ctx'>     if ( c-&gt;pending_valid ) </div><div class='ctx'>     {</div><div class='del'>-        gdprintk(XENLOG_INFO, "Re-injecting 0x%"PRIx32", 0x%"PRIx32"\n",</div><div class='add'>+        gdprintk(XENLOG_INFO, "Re-injecting %#"PRIx32", %#"PRIx32"\n",</div><div class='ctx'>                  c-&gt;pending_event, c-&gt;error_code);</div><div class='ctx'> </div><div class='ctx'>         if ( hvm_event_needs_reinjection(c-&gt;pending_type, c-&gt;pending_vector) )</div><div class='hunk'>@@ -271,6 +298,7 @@ static int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c)</div><div class='ctx'>         }</div><div class='ctx'>     }</div><div class='ctx'> </div><div class='add'>+    vmcb-&gt;cleanbits.bytes = 0;</div><div class='ctx'>     paging_update_paging_modes(v);</div><div class='ctx'> </div><div class='ctx'>     return 0;</div><div class='hunk'>@@ -303,7 +331,7 @@ static void svm_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)</div><div class='ctx'>     vmcb-&gt;cstar      = data-&gt;msr_cstar;</div><div class='ctx'>     vmcb-&gt;sfmask     = data-&gt;msr_syscall_mask;</div><div class='ctx'>     v-&gt;arch.hvm_vcpu.guest_efer = data-&gt;msr_efer;</div><div class='del'>-    hvm_update_guest_efer(v);</div><div class='add'>+    svm_update_guest_efer(v);</div><div class='ctx'> </div><div class='ctx'>     hvm_set_guest_tsc(v, data-&gt;tsc);</div><div class='ctx'> }</div><div class='hunk'>@@ -318,7 +346,7 @@ static int svm_load_vmcb_ctxt(struct vcpu *v, struct hvm_hw_cpu *ctxt)</div><div class='ctx'> {</div><div class='ctx'>     svm_load_cpu_state(v, ctxt);</div><div class='ctx'>     if (svm_vmcb_restore(v, ctxt)) {</div><div class='del'>-        printk("svm_vmcb restore failed!\n");</div><div class='add'>+        gdprintk(XENLOG_ERR, "svm_vmcb restore failed!\n");</div><div class='ctx'>         domain_crash(v-&gt;domain);</div><div class='ctx'>         return -EINVAL;</div><div class='ctx'>     }</div><div class='hunk'>@@ -328,15 +356,17 @@ static int svm_load_vmcb_ctxt(struct vcpu *v, struct hvm_hw_cpu *ctxt)</div><div class='ctx'> </div><div class='ctx'> static void svm_fpu_enter(struct vcpu *v)</div><div class='ctx'> {</div><div class='del'>-    struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='add'>+    struct vmcb_struct *n1vmcb = vcpu_nestedhvm(v).nv_n1vmcx;</div><div class='ctx'> </div><div class='del'>-    setup_fpu(v);</div><div class='del'>-    vmcb-&gt;exception_intercepts &amp;= ~(1U &lt;&lt; TRAP_no_device);</div><div class='add'>+    vcpu_restore_fpu_lazy(v);</div><div class='add'>+    vmcb_set_exception_intercepts(</div><div class='add'>+        n1vmcb,</div><div class='add'>+        vmcb_get_exception_intercepts(n1vmcb) &amp; ~(1U &lt;&lt; TRAP_no_device));</div><div class='ctx'> }</div><div class='ctx'> </div><div class='ctx'> static void svm_fpu_leave(struct vcpu *v)</div><div class='ctx'> {</div><div class='del'>-    struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='add'>+    struct vmcb_struct *n1vmcb = vcpu_nestedhvm(v).nv_n1vmcx;</div><div class='ctx'> </div><div class='ctx'>     ASSERT(!v-&gt;fpu_dirtied);</div><div class='ctx'>     ASSERT(read_cr0() &amp; X86_CR0_TS);</div><div class='hunk'>@@ -349,8 +379,10 @@ static void svm_fpu_leave(struct vcpu *v)</div><div class='ctx'>      */</div><div class='ctx'>     if ( !(v-&gt;arch.hvm_vcpu.guest_cr[0] &amp; X86_CR0_TS) )</div><div class='ctx'>     {</div><div class='del'>-        v-&gt;arch.hvm_svm.vmcb-&gt;exception_intercepts |= 1U &lt;&lt; TRAP_no_device;</div><div class='del'>-        vmcb-&gt;cr0 |= X86_CR0_TS;</div><div class='add'>+        vmcb_set_exception_intercepts(</div><div class='add'>+            n1vmcb,</div><div class='add'>+            vmcb_get_exception_intercepts(n1vmcb) | (1U &lt;&lt; TRAP_no_device));</div><div class='add'>+        vmcb_set_cr0(n1vmcb, vmcb_get_cr0(n1vmcb) | X86_CR0_TS);</div><div class='ctx'>     }</div><div class='ctx'> }</div><div class='ctx'> </div><div class='hunk'>@@ -362,7 +394,7 @@ static unsigned int svm_get_interrupt_shadow(struct vcpu *v)</div><div class='ctx'>     if ( vmcb-&gt;interrupt_shadow )</div><div class='ctx'>         intr_shadow |= HVM_INTR_SHADOW_MOV_SS | HVM_INTR_SHADOW_STI;</div><div class='ctx'> </div><div class='del'>-    if ( vmcb-&gt;general1_intercepts &amp; GENERAL1_INTERCEPT_IRET )</div><div class='add'>+    if ( vmcb_get_general1_intercepts(vmcb) &amp; GENERAL1_INTERCEPT_IRET )</div><div class='ctx'>         intr_shadow |= HVM_INTR_SHADOW_NMI;</div><div class='ctx'> </div><div class='ctx'>     return intr_shadow;</div><div class='hunk'>@@ -371,13 +403,15 @@ static unsigned int svm_get_interrupt_shadow(struct vcpu *v)</div><div class='ctx'> static void svm_set_interrupt_shadow(struct vcpu *v, unsigned int intr_shadow)</div><div class='ctx'> {</div><div class='ctx'>     struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='add'>+    u32 general1_intercepts = vmcb_get_general1_intercepts(vmcb);</div><div class='ctx'> </div><div class='ctx'>     vmcb-&gt;interrupt_shadow =</div><div class='ctx'>         !!(intr_shadow &amp; (HVM_INTR_SHADOW_MOV_SS|HVM_INTR_SHADOW_STI));</div><div class='ctx'> </div><div class='del'>-    vmcb-&gt;general1_intercepts &amp;= ~GENERAL1_INTERCEPT_IRET;</div><div class='add'>+    general1_intercepts &amp;= ~GENERAL1_INTERCEPT_IRET;</div><div class='ctx'>     if ( intr_shadow &amp; HVM_INTR_SHADOW_NMI )</div><div class='del'>-        vmcb-&gt;general1_intercepts |= GENERAL1_INTERCEPT_IRET;</div><div class='add'>+        general1_intercepts |= GENERAL1_INTERCEPT_IRET;</div><div class='add'>+    vmcb_set_general1_intercepts(vmcb, general1_intercepts);</div><div class='ctx'> }</div><div class='ctx'> </div><div class='ctx'> static int svm_guest_x86_mode(struct vcpu *v)</div><div class='hunk'>@@ -393,14 +427,10 @@ static int svm_guest_x86_mode(struct vcpu *v)</div><div class='ctx'>     return (likely(vmcb-&gt;cs.attr.fields.db) ? 4 : 2);</div><div class='ctx'> }</div><div class='ctx'> </div><div class='del'>-static void svm_update_host_cr3(struct vcpu *v)</div><div class='del'>-{</div><div class='del'>-    /* SVM doesn't have a HOST_CR3 equivalent to update. */</div><div class='del'>-}</div><div class='del'>-</div><div class='del'>-static void svm_update_guest_cr(struct vcpu *v, unsigned int cr)</div><div class='add'>+void svm_update_guest_cr(struct vcpu *v, unsigned int cr)</div><div class='ctx'> {</div><div class='ctx'>     struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='add'>+    uint64_t value;</div><div class='ctx'> </div><div class='ctx'>     switch ( cr )</div><div class='ctx'>     {</div><div class='hunk'>@@ -411,27 +441,36 @@ static void svm_update_guest_cr(struct vcpu *v, unsigned int cr)</div><div class='ctx'>         {</div><div class='ctx'>             if ( v != current )</div><div class='ctx'>                 hw_cr0_mask |= X86_CR0_TS;</div><div class='del'>-            else if ( vmcb-&gt;cr0 &amp; X86_CR0_TS )</div><div class='add'>+            else if ( vmcb_get_cr0(vmcb) &amp; X86_CR0_TS )</div><div class='ctx'>                 svm_fpu_enter(v);</div><div class='ctx'>         }</div><div class='ctx'> </div><div class='del'>-        vmcb-&gt;cr0 = v-&gt;arch.hvm_vcpu.guest_cr[0] | hw_cr0_mask;</div><div class='add'>+        value = v-&gt;arch.hvm_vcpu.guest_cr[0] | hw_cr0_mask;</div><div class='ctx'>         if ( !paging_mode_hap(v-&gt;domain) )</div><div class='del'>-            vmcb-&gt;cr0 |= X86_CR0_PG | X86_CR0_WP;</div><div class='add'>+            value |= X86_CR0_PG | X86_CR0_WP;</div><div class='add'>+        vmcb_set_cr0(vmcb, value);</div><div class='ctx'>         break;</div><div class='ctx'>     }</div><div class='ctx'>     case 2:</div><div class='del'>-        vmcb-&gt;cr2 = v-&gt;arch.hvm_vcpu.guest_cr[2];</div><div class='add'>+        vmcb_set_cr2(vmcb, v-&gt;arch.hvm_vcpu.guest_cr[2]);</div><div class='ctx'>         break;</div><div class='ctx'>     case 3:</div><div class='del'>-        vmcb-&gt;cr3 = v-&gt;arch.hvm_vcpu.hw_cr[3];</div><div class='del'>-        hvm_asid_flush_vcpu(v);</div><div class='add'>+        vmcb_set_cr3(vmcb, v-&gt;arch.hvm_vcpu.hw_cr[3]);</div><div class='add'>+        if ( !nestedhvm_enabled(v-&gt;domain) )</div><div class='add'>+            hvm_asid_flush_vcpu(v);</div><div class='add'>+        else if ( nestedhvm_vmswitch_in_progress(v) )</div><div class='add'>+            ; /* CR3 switches during VMRUN/VMEXIT do not flush the TLB. */</div><div class='add'>+        else</div><div class='add'>+            hvm_asid_flush_vcpu_asid(</div><div class='add'>+                nestedhvm_vcpu_in_guestmode(v)</div><div class='add'>+                ? &amp;vcpu_nestedhvm(v).nv_n2asid : &amp;v-&gt;arch.hvm_vcpu.n1asid);</div><div class='ctx'>         break;</div><div class='ctx'>     case 4:</div><div class='del'>-        vmcb-&gt;cr4 = HVM_CR4_HOST_MASK;</div><div class='add'>+        value = HVM_CR4_HOST_MASK;</div><div class='ctx'>         if ( paging_mode_hap(v-&gt;domain) )</div><div class='del'>-            vmcb-&gt;cr4 &amp;= ~X86_CR4_PAE;</div><div class='del'>-        vmcb-&gt;cr4 |= v-&gt;arch.hvm_vcpu.guest_cr[4];</div><div class='add'>+            value &amp;= ~X86_CR4_PAE;</div><div class='add'>+        value |= v-&gt;arch.hvm_vcpu.guest_cr[4];</div><div class='add'>+        vmcb_set_cr4(vmcb, value);</div><div class='ctx'>         break;</div><div class='ctx'>     default:</div><div class='ctx'>         BUG();</div><div class='hunk'>@@ -442,18 +481,12 @@ static void svm_update_guest_efer(struct vcpu *v)</div><div class='ctx'> {</div><div class='ctx'>     struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='ctx'>     bool_t lma = !!(v-&gt;arch.hvm_vcpu.guest_efer &amp; EFER_LMA);</div><div class='add'>+    uint64_t new_efer;</div><div class='ctx'> </div><div class='del'>-    vmcb-&gt;efer = (v-&gt;arch.hvm_vcpu.guest_efer | EFER_SVME) &amp; ~EFER_LME;</div><div class='add'>+    new_efer = (v-&gt;arch.hvm_vcpu.guest_efer | EFER_SVME) &amp; ~EFER_LME;</div><div class='ctx'>     if ( lma )</div><div class='del'>-        vmcb-&gt;efer |= EFER_LME;</div><div class='del'>-</div><div class='del'>-    /*</div><div class='del'>-     * In legacy mode (EFER.LMA=0) we natively support SYSENTER/SYSEXIT with</div><div class='del'>-     * no need for MSR intercepts. When EFER.LMA=1 we must trap and emulate.</div><div class='del'>-     */</div><div class='del'>-    svm_intercept_msr(v, MSR_IA32_SYSENTER_CS, lma);</div><div class='del'>-    svm_intercept_msr(v, MSR_IA32_SYSENTER_ESP, lma);</div><div class='del'>-    svm_intercept_msr(v, MSR_IA32_SYSENTER_EIP, lma);</div><div class='add'>+        new_efer |= EFER_LME;</div><div class='add'>+    vmcb_set_efer(vmcb, new_efer);</div><div class='ctx'> }</div><div class='ctx'> </div><div class='ctx'> static void svm_sync_vmcb(struct vcpu *v)</div><div class='hunk'>@@ -505,7 +538,7 @@ static void svm_get_segment_register(struct vcpu *v, enum x86_segment seg,</div><div class='ctx'>         break;</div><div class='ctx'>     case x86_seg_ss:</div><div class='ctx'>         memcpy(reg, &amp;vmcb-&gt;ss, sizeof(*reg));</div><div class='del'>-        reg-&gt;attr.fields.dpl = vmcb-&gt;cpl;</div><div class='add'>+        reg-&gt;attr.fields.dpl = vmcb-&gt;_cpl;</div><div class='ctx'>         if ( reg-&gt;attr.fields.type == 0 )</div><div class='ctx'>             reg-&gt;attr.fields.db = 0;</div><div class='ctx'>         break;</div><div class='hunk'>@@ -539,6 +572,16 @@ static void svm_set_segment_register(struct vcpu *v, enum x86_segment seg,</div><div class='ctx'> </div><div class='ctx'>     switch ( seg )</div><div class='ctx'>     {</div><div class='add'>+    case x86_seg_cs:</div><div class='add'>+    case x86_seg_ds:</div><div class='add'>+    case x86_seg_es:</div><div class='add'>+    case x86_seg_ss: /* cpl */</div><div class='add'>+        vmcb-&gt;cleanbits.fields.seg = 0;</div><div class='add'>+        break;</div><div class='add'>+    case x86_seg_gdtr:</div><div class='add'>+    case x86_seg_idtr:</div><div class='add'>+        vmcb-&gt;cleanbits.fields.dt = 0;</div><div class='add'>+        break;</div><div class='ctx'>     case x86_seg_fs:</div><div class='ctx'>     case x86_seg_gs:</div><div class='ctx'>     case x86_seg_tr:</div><div class='hunk'>@@ -571,7 +614,7 @@ static void svm_set_segment_register(struct vcpu *v, enum x86_segment seg,</div><div class='ctx'>         break;</div><div class='ctx'>     case x86_seg_ss:</div><div class='ctx'>         memcpy(&amp;vmcb-&gt;ss, reg, sizeof(*reg));</div><div class='del'>-        vmcb-&gt;cpl = vmcb-&gt;ss.attr.fields.dpl;</div><div class='add'>+        vmcb-&gt;_cpl = vmcb-&gt;ss.attr.fields.dpl;</div><div class='ctx'>         break;</div><div class='ctx'>     case x86_seg_tr:</div><div class='ctx'>         memcpy(&amp;vmcb-&gt;tr, reg, sizeof(*reg));</div><div class='hunk'>@@ -595,17 +638,118 @@ static void svm_set_segment_register(struct vcpu *v, enum x86_segment seg,</div><div class='ctx'>         svm_vmload(vmcb);</div><div class='ctx'> }</div><div class='ctx'> </div><div class='add'>+static unsigned long svm_get_shadow_gs_base(struct vcpu *v)</div><div class='add'>+{</div><div class='add'>+    return v-&gt;arch.hvm_svm.vmcb-&gt;kerngsbase;</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+static int svm_set_guest_pat(struct vcpu *v, u64 gpat)</div><div class='add'>+{</div><div class='add'>+    struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='add'>+</div><div class='add'>+    if ( !paging_mode_hap(v-&gt;domain) )</div><div class='add'>+        return 0;</div><div class='add'>+</div><div class='add'>+    vmcb_set_g_pat(vmcb, gpat);</div><div class='add'>+    return 1;</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+static int svm_get_guest_pat(struct vcpu *v, u64 *gpat)</div><div class='add'>+{</div><div class='add'>+    struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='add'>+</div><div class='add'>+    if ( !paging_mode_hap(v-&gt;domain) )</div><div class='add'>+        return 0;</div><div class='add'>+</div><div class='add'>+    *gpat = vmcb_get_g_pat(vmcb);</div><div class='add'>+    return 1;</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+static uint64_t svm_get_tsc_offset(uint64_t host_tsc, uint64_t guest_tsc,</div><div class='add'>+    uint64_t ratio)</div><div class='add'>+{</div><div class='add'>+    uint64_t offset;</div><div class='add'>+</div><div class='add'>+    if (ratio == DEFAULT_TSC_RATIO)</div><div class='add'>+        return guest_tsc - host_tsc;</div><div class='add'>+</div><div class='add'>+    /* calculate hi,lo parts in 64bits to prevent overflow */</div><div class='add'>+    offset = (((host_tsc &gt;&gt; 32U) * (ratio &gt;&gt; 32U)) &lt;&lt; 32U) +</div><div class='add'>+          (host_tsc &amp; 0xffffffffULL) * (ratio &amp; 0xffffffffULL);</div><div class='add'>+    return guest_tsc - offset;</div><div class='add'>+}</div><div class='add'>+</div><div class='ctx'> static void svm_set_tsc_offset(struct vcpu *v, u64 offset)</div><div class='ctx'> {</div><div class='del'>-    v-&gt;arch.hvm_svm.vmcb-&gt;tsc_offset = offset;</div><div class='add'>+    struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='add'>+    struct vmcb_struct *n1vmcb, *n2vmcb;</div><div class='add'>+    uint64_t n2_tsc_offset = 0;</div><div class='add'>+    struct domain *d = v-&gt;domain;</div><div class='add'>+    uint64_t host_tsc, guest_tsc;</div><div class='add'>+</div><div class='add'>+    guest_tsc = hvm_get_guest_tsc(v);</div><div class='add'>+</div><div class='add'>+    /* Re-adjust the offset value when TSC_RATIO is available */</div><div class='add'>+    if ( cpu_has_tsc_ratio &amp;&amp; d-&gt;arch.vtsc ) {</div><div class='add'>+        rdtscll(host_tsc);</div><div class='add'>+        offset = svm_get_tsc_offset(host_tsc, guest_tsc, vcpu_tsc_ratio(v));</div><div class='add'>+    }</div><div class='add'>+</div><div class='add'>+    if ( !nestedhvm_enabled(d) ) {</div><div class='add'>+        vmcb_set_tsc_offset(vmcb, offset);</div><div class='add'>+        return;</div><div class='add'>+    }</div><div class='add'>+</div><div class='add'>+    n1vmcb = vcpu_nestedhvm(v).nv_n1vmcx;</div><div class='add'>+    n2vmcb = vcpu_nestedhvm(v).nv_n2vmcx;</div><div class='add'>+</div><div class='add'>+    if ( nestedhvm_vcpu_in_guestmode(v) ) {</div><div class='add'>+        struct nestedsvm *svm = &amp;vcpu_nestedsvm(v);</div><div class='add'>+</div><div class='add'>+        n2_tsc_offset = vmcb_get_tsc_offset(n2vmcb) -</div><div class='add'>+            vmcb_get_tsc_offset(n1vmcb);</div><div class='add'>+        if ( svm-&gt;ns_tscratio != DEFAULT_TSC_RATIO ) {</div><div class='add'>+            n2_tsc_offset = svm_get_tsc_offset(guest_tsc,</div><div class='add'>+                guest_tsc + n2_tsc_offset, svm-&gt;ns_tscratio);</div><div class='add'>+        }</div><div class='add'>+        vmcb_set_tsc_offset(n1vmcb, offset);</div><div class='add'>+    }</div><div class='add'>+</div><div class='add'>+    vmcb_set_tsc_offset(vmcb, offset + n2_tsc_offset);</div><div class='ctx'> }</div><div class='ctx'> </div><div class='ctx'> static void svm_set_rdtsc_exiting(struct vcpu *v, bool_t enable)</div><div class='ctx'> {</div><div class='ctx'>     struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='del'>-    vmcb-&gt;general1_intercepts &amp;= ~GENERAL1_INTERCEPT_RDTSC;</div><div class='del'>-    if ( enable )</div><div class='del'>-        vmcb-&gt;general1_intercepts |= GENERAL1_INTERCEPT_RDTSC;</div><div class='add'>+    u32 general1_intercepts = vmcb_get_general1_intercepts(vmcb);</div><div class='add'>+    u32 general2_intercepts = vmcb_get_general2_intercepts(vmcb);</div><div class='add'>+</div><div class='add'>+    general1_intercepts &amp;= ~GENERAL1_INTERCEPT_RDTSC;</div><div class='add'>+    general2_intercepts &amp;= ~GENERAL2_INTERCEPT_RDTSCP;</div><div class='add'>+</div><div class='add'>+    if ( enable &amp;&amp; !cpu_has_tsc_ratio )</div><div class='add'>+    {</div><div class='add'>+        general1_intercepts |= GENERAL1_INTERCEPT_RDTSC;</div><div class='add'>+        general2_intercepts |= GENERAL2_INTERCEPT_RDTSCP;</div><div class='add'>+    }</div><div class='add'>+</div><div class='add'>+    vmcb_set_general1_intercepts(vmcb, general1_intercepts);</div><div class='add'>+    vmcb_set_general2_intercepts(vmcb, general2_intercepts);</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+static unsigned int svm_get_insn_bytes(struct vcpu *v, uint8_t *buf)</div><div class='add'>+{</div><div class='add'>+    struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='add'>+    unsigned int len = v-&gt;arch.hvm_svm.cached_insn_len;</div><div class='add'>+</div><div class='add'>+    if ( len != 0 )</div><div class='add'>+    {</div><div class='add'>+        /* Latch and clear the cached instruction. */</div><div class='add'>+        memcpy(buf, vmcb-&gt;guest_ins, 15);</div><div class='add'>+        v-&gt;arch.hvm_svm.cached_insn_len = 0;</div><div class='add'>+    }</div><div class='add'>+</div><div class='add'>+    return len;</div><div class='ctx'> }</div><div class='ctx'> </div><div class='ctx'> static void svm_init_hypercall_page(struct domain *d, void *hypercall_page)</div><div class='hunk'>@@ -615,6 +759,9 @@ static void svm_init_hypercall_page(struct domain *d, void *hypercall_page)</div><div class='ctx'> </div><div class='ctx'>     for ( i = 0; i &lt; (PAGE_SIZE / 32); i++ )</div><div class='ctx'>     {</div><div class='add'>+        if ( i == __HYPERVISOR_iret )</div><div class='add'>+            continue;</div><div class='add'>+</div><div class='ctx'>         p = (char *)(hypercall_page + (i * 32));</div><div class='ctx'>         *(u8  *)(p + 0) = 0xb8; /* mov imm32, %eax */</div><div class='ctx'>         *(u32 *)(p + 1) = i;</div><div class='hunk'>@@ -628,6 +775,87 @@ static void svm_init_hypercall_page(struct domain *d, void *hypercall_page)</div><div class='ctx'>     *(u16 *)(hypercall_page + (__HYPERVISOR_iret * 32)) = 0x0b0f; /* ud2 */</div><div class='ctx'> }</div><div class='ctx'> </div><div class='add'>+static void svm_lwp_interrupt(struct cpu_user_regs *regs)</div><div class='add'>+{</div><div class='add'>+    struct vcpu *curr = current;</div><div class='add'>+</div><div class='add'>+    ack_APIC_irq();</div><div class='add'>+    vlapic_set_irq(</div><div class='add'>+        vcpu_vlapic(curr),</div><div class='add'>+        (curr-&gt;arch.hvm_svm.guest_lwp_cfg &gt;&gt; 40) &amp; 0xff,</div><div class='add'>+        0);</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+static inline void svm_lwp_save(struct vcpu *v)</div><div class='add'>+{</div><div class='add'>+    /* Don't mess up with other guests. Disable LWP for next VCPU. */</div><div class='add'>+    if ( v-&gt;arch.hvm_svm.guest_lwp_cfg )</div><div class='add'>+    {</div><div class='add'>+        wrmsrl(MSR_AMD64_LWP_CFG, 0x0);</div><div class='add'>+        wrmsrl(MSR_AMD64_LWP_CBADDR, 0x0);</div><div class='add'>+    }</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+static inline void svm_lwp_load(struct vcpu *v)</div><div class='add'>+{</div><div class='add'>+    /* Only LWP_CFG is reloaded. LWP_CBADDR will be reloaded via xrstor. */</div><div class='add'>+   if ( v-&gt;arch.hvm_svm.guest_lwp_cfg ) </div><div class='add'>+       wrmsrl(MSR_AMD64_LWP_CFG, v-&gt;arch.hvm_svm.cpu_lwp_cfg);</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+/* Update LWP_CFG MSR (0xc0000105). Return -1 if error; otherwise returns 0. */</div><div class='add'>+static int svm_update_lwp_cfg(struct vcpu *v, uint64_t msr_content)</div><div class='add'>+{</div><div class='add'>+    unsigned int edx;</div><div class='add'>+    uint32_t msr_low;</div><div class='add'>+    static uint8_t lwp_intr_vector;</div><div class='add'>+</div><div class='add'>+    if ( xsave_enabled(v) &amp;&amp; cpu_has_lwp )</div><div class='add'>+    {</div><div class='add'>+        hvm_cpuid(0x8000001c, NULL, NULL, NULL, &amp;edx);</div><div class='add'>+        msr_low = (uint32_t)msr_content;</div><div class='add'>+        </div><div class='add'>+        /* generate #GP if guest tries to turn on unsupported features. */</div><div class='add'>+        if ( msr_low &amp; ~edx)</div><div class='add'>+            return -1;</div><div class='add'>+</div><div class='add'>+        v-&gt;arch.hvm_svm.guest_lwp_cfg = msr_content;</div><div class='add'>+</div><div class='add'>+        /* setup interrupt handler if needed */</div><div class='add'>+        if ( (msr_content &amp; 0x80000000) &amp;&amp; ((msr_content &gt;&gt; 40) &amp; 0xff) )</div><div class='add'>+        {</div><div class='add'>+            alloc_direct_apic_vector(&amp;lwp_intr_vector, svm_lwp_interrupt);</div><div class='add'>+            v-&gt;arch.hvm_svm.cpu_lwp_cfg = (msr_content &amp; 0xffff00ffffffffffULL)</div><div class='add'>+                | ((uint64_t)lwp_intr_vector &lt;&lt; 40);</div><div class='add'>+        }</div><div class='add'>+        else</div><div class='add'>+        {</div><div class='add'>+            /* otherwise disable it */</div><div class='add'>+            v-&gt;arch.hvm_svm.cpu_lwp_cfg = msr_content &amp; 0xffff00ff7fffffffULL;</div><div class='add'>+        }</div><div class='add'>+        </div><div class='add'>+        wrmsrl(MSR_AMD64_LWP_CFG, v-&gt;arch.hvm_svm.cpu_lwp_cfg);</div><div class='add'>+</div><div class='add'>+        /* track nonalzy state if LWP_CFG is non-zero. */</div><div class='add'>+        v-&gt;arch.nonlazy_xstate_used = !!(msr_content);</div><div class='add'>+    }</div><div class='add'>+</div><div class='add'>+    return 0;</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+static inline void svm_tsc_ratio_save(struct vcpu *v)</div><div class='add'>+{</div><div class='add'>+    /* Other vcpus might not have vtsc enabled. So disable TSC_RATIO here. */</div><div class='add'>+    if ( cpu_has_tsc_ratio &amp;&amp; v-&gt;domain-&gt;arch.vtsc )</div><div class='add'>+        wrmsrl(MSR_AMD64_TSC_RATIO, DEFAULT_TSC_RATIO);</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+static inline void svm_tsc_ratio_load(struct vcpu *v)</div><div class='add'>+{</div><div class='add'>+    if ( cpu_has_tsc_ratio &amp;&amp; v-&gt;domain-&gt;arch.vtsc ) </div><div class='add'>+        wrmsrl(MSR_AMD64_TSC_RATIO, vcpu_tsc_ratio(v));</div><div class='add'>+}</div><div class='add'>+</div><div class='ctx'> static void svm_ctxt_switch_from(struct vcpu *v)</div><div class='ctx'> {</div><div class='ctx'>     int cpu = smp_processor_id();</div><div class='hunk'>@@ -635,23 +863,23 @@ static void svm_ctxt_switch_from(struct vcpu *v)</div><div class='ctx'>     svm_fpu_leave(v);</div><div class='ctx'> </div><div class='ctx'>     svm_save_dr(v);</div><div class='add'>+    svm_lwp_save(v);</div><div class='add'>+    svm_tsc_ratio_save(v);</div><div class='ctx'> </div><div class='ctx'>     svm_sync_vmcb(v);</div><div class='del'>-    svm_vmload(root_vmcb[cpu]);</div><div class='add'>+    svm_vmload(per_cpu(root_vmcb, cpu));</div><div class='ctx'> </div><div class='del'>-#ifdef __x86_64__</div><div class='ctx'>     /* Resume use of ISTs now that the host TR is reinstated. */</div><div class='del'>-    idt_tables[cpu][TRAP_double_fault].a  |= IST_DF &lt;&lt; 32;</div><div class='del'>-    idt_tables[cpu][TRAP_nmi].a           |= IST_NMI &lt;&lt; 32;</div><div class='del'>-    idt_tables[cpu][TRAP_machine_check].a |= IST_MCE &lt;&lt; 32;</div><div class='del'>-#endif</div><div class='add'>+    set_ist(&amp;idt_tables[cpu][TRAP_double_fault],  IST_DF);</div><div class='add'>+    set_ist(&amp;idt_tables[cpu][TRAP_nmi],           IST_NMI);</div><div class='add'>+    set_ist(&amp;idt_tables[cpu][TRAP_machine_check], IST_MCE);</div><div class='ctx'> }</div><div class='ctx'> </div><div class='ctx'> static void svm_ctxt_switch_to(struct vcpu *v)</div><div class='ctx'> {</div><div class='add'>+    struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='ctx'>     int cpu = smp_processor_id();</div><div class='ctx'> </div><div class='del'>-#ifdef  __x86_64__</div><div class='ctx'>     /* </div><div class='ctx'>      * This is required, because VMRUN does consistency check</div><div class='ctx'>      * and some of the DOM0 selectors are pointing to </div><div class='hunk'>@@ -666,15 +894,17 @@ static void svm_ctxt_switch_to(struct vcpu *v)</div><div class='ctx'>      * Cannot use ISTs for NMI/#MC/#DF while we are running with the guest TR.</div><div class='ctx'>      * But this doesn't matter: the IST is only req'd to handle SYSCALL/SYSRET.</div><div class='ctx'>      */</div><div class='del'>-    idt_tables[cpu][TRAP_double_fault].a  &amp;= ~(7UL &lt;&lt; 32);</div><div class='del'>-    idt_tables[cpu][TRAP_nmi].a           &amp;= ~(7UL &lt;&lt; 32);</div><div class='del'>-    idt_tables[cpu][TRAP_machine_check].a &amp;= ~(7UL &lt;&lt; 32);</div><div class='del'>-#endif</div><div class='add'>+    set_ist(&amp;idt_tables[cpu][TRAP_double_fault],  IST_NONE);</div><div class='add'>+    set_ist(&amp;idt_tables[cpu][TRAP_nmi],           IST_NONE);</div><div class='add'>+    set_ist(&amp;idt_tables[cpu][TRAP_machine_check], IST_NONE);</div><div class='ctx'> </div><div class='ctx'>     svm_restore_dr(v);</div><div class='ctx'> </div><div class='del'>-    svm_vmsave(root_vmcb[cpu]);</div><div class='del'>-    svm_vmload(v-&gt;arch.hvm_svm.vmcb);</div><div class='add'>+    svm_vmsave(per_cpu(root_vmcb, cpu));</div><div class='add'>+    svm_vmload(vmcb);</div><div class='add'>+    vmcb-&gt;cleanbits.bytes = 0;</div><div class='add'>+    svm_lwp_load(v);</div><div class='add'>+    svm_tsc_ratio_load(v);</div><div class='ctx'> </div><div class='ctx'>     if ( cpu_has_rdtscp )</div><div class='ctx'>         wrmsrl(MSR_TSC_AUX, hvm_msr_tsc_aux(v));</div><div class='hunk'>@@ -682,35 +912,111 @@ static void svm_ctxt_switch_to(struct vcpu *v)</div><div class='ctx'> </div><div class='ctx'> static void svm_do_resume(struct vcpu *v) </div><div class='ctx'> {</div><div class='add'>+    struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='ctx'>     bool_t debug_state = v-&gt;domain-&gt;debugger_attached;</div><div class='add'>+    bool_t vcpu_guestmode = 0;</div><div class='add'>+</div><div class='add'>+    if ( nestedhvm_enabled(v-&gt;domain) &amp;&amp; nestedhvm_vcpu_in_guestmode(v) )</div><div class='add'>+        vcpu_guestmode = 1;</div><div class='ctx'> </div><div class='del'>-    if ( unlikely(v-&gt;arch.hvm_vcpu.debug_state_latch != debug_state) )</div><div class='add'>+    if ( !vcpu_guestmode &amp;&amp;</div><div class='add'>+        unlikely(v-&gt;arch.hvm_vcpu.debug_state_latch != debug_state) )</div><div class='ctx'>     {</div><div class='add'>+        uint32_t intercepts = vmcb_get_exception_intercepts(vmcb);</div><div class='ctx'>         uint32_t mask = (1U &lt;&lt; TRAP_debug) | (1U &lt;&lt; TRAP_int3);</div><div class='ctx'>         v-&gt;arch.hvm_vcpu.debug_state_latch = debug_state;</div><div class='del'>-        if ( debug_state )</div><div class='del'>-            v-&gt;arch.hvm_svm.vmcb-&gt;exception_intercepts |= mask;</div><div class='del'>-        else</div><div class='del'>-            v-&gt;arch.hvm_svm.vmcb-&gt;exception_intercepts &amp;= ~mask;</div><div class='add'>+        vmcb_set_exception_intercepts(</div><div class='add'>+            vmcb, debug_state ? (intercepts | mask) : (intercepts &amp; ~mask));</div><div class='ctx'>     }</div><div class='ctx'> </div><div class='ctx'>     if ( v-&gt;arch.hvm_svm.launch_core != smp_processor_id() )</div><div class='ctx'>     {</div><div class='ctx'>         v-&gt;arch.hvm_svm.launch_core = smp_processor_id();</div><div class='ctx'>         hvm_migrate_timers(v);</div><div class='del'>-</div><div class='add'>+        hvm_migrate_pirqs(v);</div><div class='ctx'>         /* Migrating to another ASID domain.  Request a new ASID. */</div><div class='ctx'>         hvm_asid_flush_vcpu(v);</div><div class='ctx'>     }</div><div class='ctx'> </div><div class='del'>-    /* Reflect the vlapic's TPR in the hardware vtpr */</div><div class='del'>-    v-&gt;arch.hvm_svm.vmcb-&gt;vintr.fields.tpr = </div><div class='del'>-        (vlapic_get_reg(vcpu_vlapic(v), APIC_TASKPRI) &amp; 0xFF) &gt;&gt; 4;</div><div class='add'>+    if ( !vcpu_guestmode )</div><div class='add'>+    {</div><div class='add'>+        vintr_t intr;</div><div class='add'>+</div><div class='add'>+        /* Reflect the vlapic's TPR in the hardware vtpr */</div><div class='add'>+        intr = vmcb_get_vintr(vmcb);</div><div class='add'>+        intr.fields.tpr =</div><div class='add'>+            (vlapic_get_reg(vcpu_vlapic(v), APIC_TASKPRI) &amp; 0xFF) &gt;&gt; 4;</div><div class='add'>+        vmcb_set_vintr(vmcb, intr);</div><div class='add'>+    }</div><div class='ctx'> </div><div class='ctx'>     hvm_do_resume(v);</div><div class='add'>+</div><div class='ctx'>     reset_stack_and_jump(svm_asm_do_resume);</div><div class='ctx'> }</div><div class='ctx'> </div><div class='add'>+static void svm_guest_osvw_init(struct vcpu *vcpu)</div><div class='add'>+{</div><div class='add'>+    if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD )</div><div class='add'>+        return;</div><div class='add'>+</div><div class='add'>+    /*</div><div class='add'>+     * Guests should see errata 400 and 415 as fixed (assuming that</div><div class='add'>+     * HLT and IO instructions are intercepted).</div><div class='add'>+     */</div><div class='add'>+    vcpu-&gt;arch.hvm_svm.osvw.length = (osvw_length &gt;= 3) ? osvw_length : 3;</div><div class='add'>+    vcpu-&gt;arch.hvm_svm.osvw.status = osvw_status &amp; ~(6ULL);</div><div class='add'>+</div><div class='add'>+    /*</div><div class='add'>+     * By increasing VCPU's osvw.length to 3 we are telling the guest that</div><div class='add'>+     * all osvw.status bits inside that length, including bit 0 (which is</div><div class='add'>+     * reserved for erratum 298), are valid. However, if host processor's</div><div class='add'>+     * osvw_len is 0 then osvw_status[0] carries no information. We need to</div><div class='add'>+     * be conservative here and therefore we tell the guest that erratum 298</div><div class='add'>+     * is present (because we really don't know).</div><div class='add'>+     */</div><div class='add'>+    if ( osvw_length == 0 &amp;&amp; boot_cpu_data.x86 == 0x10 )</div><div class='add'>+        vcpu-&gt;arch.hvm_svm.osvw.status |= 1;</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+void svm_host_osvw_reset()</div><div class='add'>+{</div><div class='add'>+    spin_lock(&amp;osvw_lock);</div><div class='add'>+</div><div class='add'>+    osvw_length = 64; /* One register (MSRC001_0141) worth of errata */</div><div class='add'>+    osvw_status = 0;</div><div class='add'>+</div><div class='add'>+    spin_unlock(&amp;osvw_lock);</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+void svm_host_osvw_init()</div><div class='add'>+{</div><div class='add'>+    spin_lock(&amp;osvw_lock);</div><div class='add'>+</div><div class='add'>+    /*</div><div class='add'>+     * Get OSVW bits. If bits are not the same on different processors then</div><div class='add'>+     * choose the worst case (i.e. if erratum is present on one processor and</div><div class='add'>+     * not on another assume that the erratum is present everywhere).</div><div class='add'>+     */</div><div class='add'>+    if ( test_bit(X86_FEATURE_OSVW, &amp;boot_cpu_data.x86_capability) )</div><div class='add'>+    {</div><div class='add'>+        uint64_t len, status;</div><div class='add'>+</div><div class='add'>+        if ( rdmsr_safe(MSR_AMD_OSVW_ID_LENGTH, len) ||</div><div class='add'>+             rdmsr_safe(MSR_AMD_OSVW_STATUS, status) )</div><div class='add'>+            len = status = 0;</div><div class='add'>+</div><div class='add'>+        if (len &lt; osvw_length)</div><div class='add'>+            osvw_length = len;</div><div class='add'>+</div><div class='add'>+        osvw_status |= status;</div><div class='add'>+        osvw_status &amp;= (1ULL &lt;&lt; osvw_length) - 1;</div><div class='add'>+    }</div><div class='add'>+    else</div><div class='add'>+        osvw_length = osvw_status = 0;</div><div class='add'>+</div><div class='add'>+    spin_unlock(&amp;osvw_lock);</div><div class='add'>+}</div><div class='add'>+</div><div class='ctx'> static int svm_domain_initialise(struct domain *d)</div><div class='ctx'> {</div><div class='ctx'>     return 0;</div><div class='hunk'>@@ -738,29 +1044,38 @@ static int svm_vcpu_initialise(struct vcpu *v)</div><div class='ctx'>         return rc;</div><div class='ctx'>     }</div><div class='ctx'> </div><div class='add'>+    vpmu_initialise(v);</div><div class='add'>+</div><div class='add'>+    svm_guest_osvw_init(v);</div><div class='add'>+</div><div class='ctx'>     return 0;</div><div class='ctx'> }</div><div class='ctx'> </div><div class='ctx'> static void svm_vcpu_destroy(struct vcpu *v)</div><div class='ctx'> {</div><div class='add'>+    vpmu_destroy(v);</div><div class='ctx'>     svm_destroy_vmcb(v);</div><div class='add'>+    passive_domain_destroy(v);</div><div class='ctx'> }</div><div class='ctx'> </div><div class='del'>-static void svm_inject_exception(</div><div class='del'>-    unsigned int trapnr, int errcode, unsigned long cr2)</div><div class='add'>+static void svm_inject_trap(struct hvm_trap *trap)</div><div class='ctx'> {</div><div class='ctx'>     struct vcpu *curr = current;</div><div class='ctx'>     struct vmcb_struct *vmcb = curr-&gt;arch.hvm_svm.vmcb;</div><div class='ctx'>     eventinj_t event = vmcb-&gt;eventinj;</div><div class='add'>+    struct hvm_trap _trap = *trap;</div><div class='ctx'> </div><div class='del'>-    switch ( trapnr )</div><div class='add'>+    switch ( _trap.vector )</div><div class='ctx'>     {</div><div class='ctx'>     case TRAP_debug:</div><div class='ctx'>         if ( guest_cpu_user_regs()-&gt;eflags &amp; X86_EFLAGS_TF )</div><div class='ctx'>         {</div><div class='del'>-            __restore_debug_registers(curr);</div><div class='del'>-            vmcb-&gt;dr6 |= 0x4000;</div><div class='add'>+            __restore_debug_registers(vmcb, curr);</div><div class='add'>+            vmcb_set_dr6(vmcb, vmcb_get_dr6(vmcb) | 0x4000);</div><div class='ctx'>         }</div><div class='add'>+        if ( cpu_has_monitor_trap_flag )</div><div class='add'>+            break;</div><div class='add'>+        /* fall through */</div><div class='ctx'>     case TRAP_int3:</div><div class='ctx'>         if ( curr-&gt;domain-&gt;debugger_attached )</div><div class='ctx'>         {</div><div class='hunk'>@@ -773,28 +1088,30 @@ static void svm_inject_exception(</div><div class='ctx'>     if ( unlikely(event.fields.v) &amp;&amp;</div><div class='ctx'>          (event.fields.type == X86_EVENTTYPE_HW_EXCEPTION) )</div><div class='ctx'>     {</div><div class='del'>-        trapnr = hvm_combine_hw_exceptions(event.fields.vector, trapnr);</div><div class='del'>-        if ( trapnr == TRAP_double_fault )</div><div class='del'>-            errcode = 0;</div><div class='add'>+        _trap.vector = hvm_combine_hw_exceptions(</div><div class='add'>+            event.fields.vector, _trap.vector);</div><div class='add'>+        if ( _trap.vector == TRAP_double_fault )</div><div class='add'>+            _trap.error_code = 0;</div><div class='ctx'>     }</div><div class='ctx'> </div><div class='ctx'>     event.bytes = 0;</div><div class='ctx'>     event.fields.v = 1;</div><div class='ctx'>     event.fields.type = X86_EVENTTYPE_HW_EXCEPTION;</div><div class='del'>-    event.fields.vector = trapnr;</div><div class='del'>-    event.fields.ev = (errcode != HVM_DELIVER_NO_ERROR_CODE);</div><div class='del'>-    event.fields.errorcode = errcode;</div><div class='add'>+    event.fields.vector = _trap.vector;</div><div class='add'>+    event.fields.ev = (_trap.error_code != HVM_DELIVER_NO_ERROR_CODE);</div><div class='add'>+    event.fields.errorcode = _trap.error_code;</div><div class='ctx'> </div><div class='ctx'>     vmcb-&gt;eventinj = event;</div><div class='ctx'> </div><div class='del'>-    if ( trapnr == TRAP_page_fault )</div><div class='add'>+    if ( _trap.vector == TRAP_page_fault )</div><div class='ctx'>     {</div><div class='del'>-        vmcb-&gt;cr2 = curr-&gt;arch.hvm_vcpu.guest_cr[2] = cr2;</div><div class='del'>-        HVMTRACE_LONG_2D(PF_INJECT, errcode, TRC_PAR_LONG(cr2));</div><div class='add'>+        curr-&gt;arch.hvm_vcpu.guest_cr[2] = _trap.cr2;</div><div class='add'>+        vmcb_set_cr2(vmcb, _trap.cr2);</div><div class='add'>+        HVMTRACE_LONG_2D(PF_INJECT, _trap.error_code, TRC_PAR_LONG(_trap.cr2));</div><div class='ctx'>     }</div><div class='ctx'>     else</div><div class='ctx'>     {</div><div class='del'>-        HVMTRACE_2D(INJ_EXC, trapnr, errcode);</div><div class='add'>+        HVMTRACE_2D(INJ_EXC, _trap.vector, _trap.error_code);</div><div class='ctx'>     }</div><div class='ctx'> }</div><div class='ctx'> </div><div class='hunk'>@@ -804,77 +1121,131 @@ static int svm_event_pending(struct vcpu *v)</div><div class='ctx'>     return vmcb-&gt;eventinj.fields.v;</div><div class='ctx'> }</div><div class='ctx'> </div><div class='del'>-static int svm_do_pmu_interrupt(struct cpu_user_regs *regs)</div><div class='add'>+static void svm_cpu_dead(unsigned int cpu)</div><div class='ctx'> {</div><div class='del'>-    return 0;</div><div class='add'>+    free_xenheap_page(per_cpu(hsa, cpu));</div><div class='add'>+    per_cpu(hsa, cpu) = NULL;</div><div class='add'>+    free_vmcb(per_cpu(root_vmcb, cpu));</div><div class='add'>+    per_cpu(root_vmcb, cpu) = NULL;</div><div class='ctx'> }</div><div class='ctx'> </div><div class='del'>-static int svm_cpu_prepare(unsigned int cpu)</div><div class='add'>+static int svm_cpu_up_prepare(unsigned int cpu)</div><div class='ctx'> {</div><div class='del'>-    if ( ((hsa[cpu] == NULL) &amp;&amp;</div><div class='del'>-          ((hsa[cpu] = alloc_host_save_area()) == NULL)) ||</div><div class='del'>-         ((root_vmcb[cpu] == NULL) &amp;&amp;</div><div class='del'>-          ((root_vmcb[cpu] = alloc_vmcb()) == NULL)) )</div><div class='add'>+    if ( ((per_cpu(hsa, cpu) == NULL) &amp;&amp;</div><div class='add'>+          ((per_cpu(hsa, cpu) = alloc_host_save_area()) == NULL)) ||</div><div class='add'>+         ((per_cpu(root_vmcb, cpu) == NULL) &amp;&amp;</div><div class='add'>+          ((per_cpu(root_vmcb, cpu) = alloc_vmcb()) == NULL)) )</div><div class='add'>+    {</div><div class='add'>+        svm_cpu_dead(cpu);</div><div class='ctx'>         return -ENOMEM;</div><div class='add'>+    }</div><div class='add'>+</div><div class='ctx'>     return 0;</div><div class='ctx'> }</div><div class='ctx'> </div><div class='del'>-static int svm_cpu_up(struct cpuinfo_x86 *c)</div><div class='add'>+static void svm_init_erratum_383(struct cpuinfo_x86 *c)</div><div class='ctx'> {</div><div class='del'>-    u32 eax, edx, phys_hsa_lo, phys_hsa_hi;   </div><div class='del'>-    u64 phys_hsa;</div><div class='del'>-    int cpu = smp_processor_id();</div><div class='add'>+    uint64_t msr_content;</div><div class='add'>+</div><div class='add'>+    /* check whether CPU is affected */</div><div class='add'>+    if ( !cpu_has_amd_erratum(c, AMD_ERRATUM_383) )</div><div class='add'>+        return;</div><div class='add'>+</div><div class='add'>+    /* use safe methods to be compatible with nested virtualization */</div><div class='add'>+    if (rdmsr_safe(MSR_AMD64_DC_CFG, msr_content) == 0 &amp;&amp;</div><div class='add'>+        wrmsr_safe(MSR_AMD64_DC_CFG, msr_content | (1ULL &lt;&lt; 47)) == 0)</div><div class='add'>+    {</div><div class='add'>+        amd_erratum383_found = 1;</div><div class='add'>+    } else {</div><div class='add'>+        printk("Failed to enable erratum 383\n");</div><div class='add'>+    }</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+static int svm_handle_osvw(struct vcpu *v, uint32_t msr, uint64_t *val, bool_t read)</div><div class='add'>+{</div><div class='add'>+    unsigned int ecx;</div><div class='add'>+</div><div class='add'>+    /* Guest OSVW support */</div><div class='add'>+    hvm_cpuid(0x80000001, NULL, NULL, &amp;ecx, NULL);</div><div class='add'>+    if ( !test_bit((X86_FEATURE_OSVW &amp; 31), &amp;ecx) )</div><div class='add'>+        return -1;</div><div class='add'>+</div><div class='add'>+    if ( read )</div><div class='add'>+    {</div><div class='add'>+        if (msr == MSR_AMD_OSVW_ID_LENGTH)</div><div class='add'>+            *val = v-&gt;arch.hvm_svm.osvw.length;</div><div class='add'>+        else</div><div class='add'>+            *val = v-&gt;arch.hvm_svm.osvw.status;</div><div class='add'>+    }</div><div class='add'>+    /* Writes are ignored */</div><div class='add'>+</div><div class='add'>+    return 0;</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+static int svm_cpu_up(void)</div><div class='add'>+{</div><div class='add'>+    uint64_t msr_content;</div><div class='add'>+    int rc, cpu = smp_processor_id();</div><div class='add'>+    struct cpuinfo_x86 *c = &amp;cpu_data[cpu];</div><div class='ctx'>  </div><div class='ctx'>     /* Check whether SVM feature is disabled in BIOS */</div><div class='del'>-    rdmsr(MSR_K8_VM_CR, eax, edx);</div><div class='del'>-    if ( eax &amp; K8_VMCR_SVME_DISABLE )</div><div class='add'>+    rdmsrl(MSR_K8_VM_CR, msr_content);</div><div class='add'>+    if ( msr_content &amp; K8_VMCR_SVME_DISABLE )</div><div class='ctx'>     {</div><div class='ctx'>         printk("CPU%d: AMD SVM Extension is disabled in BIOS.\n", cpu);</div><div class='del'>-        return 0;</div><div class='add'>+        return -EINVAL;</div><div class='ctx'>     }</div><div class='ctx'> </div><div class='del'>-    if ( svm_cpu_prepare(cpu) != 0 )</div><div class='del'>-        return 0;</div><div class='add'>+    if ( (rc = svm_cpu_up_prepare(cpu)) != 0 )</div><div class='add'>+        return rc;</div><div class='ctx'> </div><div class='ctx'>     write_efer(read_efer() | EFER_SVME);</div><div class='ctx'> </div><div class='ctx'>     /* Initialize the HSA for this core. */</div><div class='del'>-    phys_hsa = (u64)virt_to_maddr(hsa[cpu]);</div><div class='del'>-    phys_hsa_lo = (u32)phys_hsa;</div><div class='del'>-    phys_hsa_hi = (u32)(phys_hsa &gt;&gt; 32);    </div><div class='del'>-    wrmsr(MSR_K8_VM_HSAVE_PA, phys_hsa_lo, phys_hsa_hi);</div><div class='add'>+    wrmsrl(MSR_K8_VM_HSAVE_PA, (uint64_t)virt_to_maddr(per_cpu(hsa, cpu)));</div><div class='add'>+</div><div class='add'>+    /* check for erratum 383 */</div><div class='add'>+    svm_init_erratum_383(c);</div><div class='ctx'> </div><div class='ctx'>     /* Initialize core's ASID handling. */</div><div class='ctx'>     svm_asid_init(c);</div><div class='ctx'> </div><div class='del'>-    return 1;</div><div class='del'>-}</div><div class='del'>-</div><div class='del'>-void start_svm(struct cpuinfo_x86 *c)</div><div class='del'>-{</div><div class='del'>-    static bool_t bootstrapped;</div><div class='del'>-</div><div class='del'>-    if ( test_and_set_bool(bootstrapped) )</div><div class='add'>+    /*</div><div class='add'>+     * Check whether EFER.LMSLE can be written.</div><div class='add'>+     * Unfortunately there's no feature bit defined for this.</div><div class='add'>+     */</div><div class='add'>+    msr_content = read_efer();</div><div class='add'>+    if ( wrmsr_safe(MSR_EFER, msr_content | EFER_LMSLE) == 0 )</div><div class='add'>+        rdmsrl(MSR_EFER, msr_content);</div><div class='add'>+    if ( msr_content &amp; EFER_LMSLE )</div><div class='ctx'>     {</div><div class='del'>-        if ( hvm_enabled &amp;&amp; !svm_cpu_up(c) )</div><div class='del'>-        {</div><div class='del'>-            printk("SVM: FATAL: failed to initialise CPU%d!\n",</div><div class='del'>-                   smp_processor_id());</div><div class='del'>-            BUG();</div><div class='del'>-        }</div><div class='del'>-        return;</div><div class='add'>+        if ( c == &amp;boot_cpu_data )</div><div class='add'>+            cpu_has_lmsl = 1;</div><div class='add'>+        wrmsrl(MSR_EFER, msr_content ^ EFER_LMSLE);</div><div class='add'>+    }</div><div class='add'>+    else</div><div class='add'>+    {</div><div class='add'>+        if ( cpu_has_lmsl )</div><div class='add'>+            printk(XENLOG_WARNING "Inconsistent LMSLE support across CPUs!\n");</div><div class='add'>+        cpu_has_lmsl = 0;</div><div class='ctx'>     }</div><div class='ctx'> </div><div class='del'>-    /* Xen does not fill x86_capability words except 0. */</div><div class='del'>-    boot_cpu_data.x86_capability[5] = cpuid_ecx(0x80000001);</div><div class='add'>+    /* Initialize OSVW bits to be used by guests */</div><div class='add'>+    svm_host_osvw_init();</div><div class='ctx'> </div><div class='del'>-    if ( !test_bit(X86_FEATURE_SVME, &amp;boot_cpu_data.x86_capability) )</div><div class='del'>-        return;</div><div class='add'>+    return 0;</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+const struct hvm_function_table * __init start_svm(void)</div><div class='add'>+{</div><div class='add'>+    bool_t printed = 0;</div><div class='add'>+</div><div class='add'>+    svm_host_osvw_reset();</div><div class='ctx'> </div><div class='del'>-    if ( !svm_cpu_up(c) )</div><div class='add'>+    if ( svm_cpu_up() )</div><div class='ctx'>     {</div><div class='ctx'>         printk("SVM: failed to initialise.\n");</div><div class='del'>-        return;</div><div class='add'>+        return NULL;</div><div class='ctx'>     }</div><div class='ctx'> </div><div class='ctx'>     setup_vmcb_dump();</div><div class='hunk'>@@ -882,55 +1253,109 @@ void start_svm(struct cpuinfo_x86 *c)</div><div class='ctx'>     svm_feature_flags = ((cpuid_eax(0x80000000) &gt;= 0x8000000A) ?</div><div class='ctx'>                          cpuid_edx(0x8000000A) : 0);</div><div class='ctx'> </div><div class='add'>+    printk("SVM: Supported advanced features:\n");</div><div class='add'>+</div><div class='add'>+    /* DecodeAssists fast paths assume nextrip is valid for fast rIP update. */</div><div class='add'>+    if ( !cpu_has_svm_nrips )</div><div class='add'>+        clear_bit(SVM_FEATURE_DECODEASSISTS, &amp;svm_feature_flags);</div><div class='add'>+</div><div class='add'>+#define P(p,s) if ( p ) { printk(" - %s\n", s); printed = 1; }</div><div class='add'>+    P(cpu_has_svm_npt, "Nested Page Tables (NPT)");</div><div class='add'>+    P(cpu_has_svm_lbrv, "Last Branch Record (LBR) Virtualisation");</div><div class='add'>+    P(cpu_has_svm_nrips, "Next-RIP Saved on #VMEXIT");</div><div class='add'>+    P(cpu_has_svm_cleanbits, "VMCB Clean Bits");</div><div class='add'>+    P(cpu_has_svm_decode, "DecodeAssists");</div><div class='add'>+    P(cpu_has_pause_filter, "Pause-Intercept Filter");</div><div class='add'>+    P(cpu_has_tsc_ratio, "TSC Rate MSR");</div><div class='add'>+#undef P</div><div class='add'>+</div><div class='add'>+    if ( !printed )</div><div class='add'>+        printk(" - none\n");</div><div class='add'>+</div><div class='ctx'>     svm_function_table.hap_supported = cpu_has_svm_npt;</div><div class='add'>+    svm_function_table.hap_capabilities = HVM_HAP_SUPERPAGE_2MB |</div><div class='add'>+        ((cpuid_edx(0x80000001) &amp; 0x04000000) ? HVM_HAP_SUPERPAGE_1GB : 0);</div><div class='ctx'> </div><div class='del'>-    hvm_enable(&amp;svm_function_table);</div><div class='add'>+    return &amp;svm_function_table;</div><div class='ctx'> }</div><div class='ctx'> </div><div class='del'>-static void svm_do_nested_pgfault(paddr_t gpa)</div><div class='add'>+static void svm_do_nested_pgfault(struct vcpu *v,</div><div class='add'>+    struct cpu_user_regs *regs, uint32_t npfec, paddr_t gpa)</div><div class='ctx'> {</div><div class='add'>+    int ret;</div><div class='ctx'>     unsigned long gfn = gpa &gt;&gt; PAGE_SHIFT;</div><div class='ctx'>     mfn_t mfn;</div><div class='ctx'>     p2m_type_t p2mt;</div><div class='add'>+    p2m_access_t p2ma;</div><div class='add'>+    struct p2m_domain *p2m = NULL;</div><div class='add'>+</div><div class='add'>+    ret = hvm_hap_nested_page_fault(gpa, 0, ~0ul, </div><div class='add'>+                                    1, /* All NPFs count as reads */</div><div class='add'>+                                    npfec &amp; PFEC_write_access, </div><div class='add'>+                                    npfec &amp; PFEC_insn_fetch);</div><div class='ctx'> </div><div class='ctx'>     if ( tb_init_done )</div><div class='ctx'>     {</div><div class='ctx'>         struct {</div><div class='ctx'>             uint64_t gpa;</div><div class='ctx'>             uint64_t mfn;</div><div class='del'>-            u32 qualification;</div><div class='del'>-            u32 p2mt;</div><div class='add'>+            uint32_t qualification;</div><div class='add'>+            uint32_t p2mt;</div><div class='ctx'>         } _d;</div><div class='ctx'> </div><div class='add'>+        p2m = p2m_get_p2m(v);</div><div class='ctx'>         _d.gpa = gpa;</div><div class='ctx'>         _d.qualification = 0;</div><div class='del'>-        _d.mfn = mfn_x(gfn_to_mfn_query(current-&gt;domain, gfn, &amp;_d.p2mt));</div><div class='add'>+        mfn = __get_gfn_type_access(p2m, gfn, &amp;_d.p2mt, &amp;p2ma, 0, NULL, 0);</div><div class='add'>+        _d.mfn = mfn_x(mfn);</div><div class='ctx'>         </div><div class='del'>-        __trace_var(TRC_HVM_NPF, 0, sizeof(_d), (unsigned char *)&amp;_d);</div><div class='add'>+        __trace_var(TRC_HVM_NPF, 0, sizeof(_d), &amp;_d);</div><div class='ctx'>     }</div><div class='ctx'> </div><div class='del'>-    if ( hvm_hap_nested_page_fault(gfn) )</div><div class='add'>+    switch (ret) {</div><div class='add'>+    case 0:</div><div class='add'>+        break;</div><div class='add'>+    case 1:</div><div class='ctx'>         return;</div><div class='add'>+    case -1:</div><div class='add'>+        ASSERT(nestedhvm_enabled(v-&gt;domain) &amp;&amp; nestedhvm_vcpu_in_guestmode(v));</div><div class='add'>+        /* inject #VMEXIT(NPF) into guest. */</div><div class='add'>+        nestedsvm_vmexit_defer(v, VMEXIT_NPF, npfec, gpa);</div><div class='add'>+        return;</div><div class='add'>+    }</div><div class='ctx'> </div><div class='add'>+    if ( p2m == NULL )</div><div class='add'>+        p2m = p2m_get_p2m(v);</div><div class='ctx'>     /* Everything else is an error. */</div><div class='del'>-    mfn = gfn_to_mfn_type_current(gfn, &amp;p2mt, p2m_guest);</div><div class='del'>-    gdprintk(XENLOG_ERR, "SVM violation gpa %#"PRIpaddr", mfn %#lx, type %i\n",</div><div class='del'>-             gpa, mfn_x(mfn), p2mt);</div><div class='del'>-    domain_crash(current-&gt;domain);</div><div class='add'>+    mfn = __get_gfn_type_access(p2m, gfn, &amp;p2mt, &amp;p2ma, 0, NULL, 0);</div><div class='add'>+    gdprintk(XENLOG_ERR,</div><div class='add'>+         "SVM violation gpa %#"PRIpaddr", mfn %#lx, type %i\n",</div><div class='add'>+         gpa, mfn_x(mfn), p2mt);</div><div class='add'>+    domain_crash(v-&gt;domain);</div><div class='ctx'> }</div><div class='ctx'> </div><div class='ctx'> static void svm_fpu_dirty_intercept(void)</div><div class='ctx'> {</div><div class='del'>-    struct vcpu *curr = current;</div><div class='del'>-    struct vmcb_struct *vmcb = curr-&gt;arch.hvm_svm.vmcb;</div><div class='add'>+    struct vcpu *v = current;</div><div class='add'>+    struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='add'>+    struct vmcb_struct *n1vmcb = vcpu_nestedhvm(v).nv_n1vmcx;</div><div class='add'>+</div><div class='add'>+    svm_fpu_enter(v);</div><div class='ctx'> </div><div class='del'>-    svm_fpu_enter(curr);</div><div class='add'>+    if ( vmcb != n1vmcb )</div><div class='add'>+    {</div><div class='add'>+       /* Check if l1 guest must make FPU ready for the l2 guest */</div><div class='add'>+       if ( v-&gt;arch.hvm_vcpu.guest_cr[0] &amp; X86_CR0_TS )</div><div class='add'>+           hvm_inject_hw_exception(TRAP_no_device, HVM_DELIVER_NO_ERROR_CODE);</div><div class='add'>+       else</div><div class='add'>+           vmcb_set_cr0(n1vmcb, vmcb_get_cr0(n1vmcb) &amp; ~X86_CR0_TS);</div><div class='add'>+       return;</div><div class='add'>+    }</div><div class='ctx'> </div><div class='del'>-    if ( !(curr-&gt;arch.hvm_vcpu.guest_cr[0] &amp; X86_CR0_TS) )</div><div class='del'>-        vmcb-&gt;cr0 &amp;= ~X86_CR0_TS;</div><div class='add'>+    if ( !(v-&gt;arch.hvm_vcpu.guest_cr[0] &amp; X86_CR0_TS) )</div><div class='add'>+        vmcb_set_cr0(vmcb, vmcb_get_cr0(vmcb) &amp; ~X86_CR0_TS);</div><div class='ctx'> }</div><div class='ctx'> </div><div class='del'>-#define bitmaskof(idx)  (1U &lt;&lt; ((idx) &amp; 31))</div><div class='ctx'> static void svm_cpuid_intercept(</div><div class='ctx'>     unsigned int *eax, unsigned int *ebx,</div><div class='ctx'>     unsigned int *ecx, unsigned int *edx)</div><div class='hunk'>@@ -940,11 +1365,32 @@ static void svm_cpuid_intercept(</div><div class='ctx'> </div><div class='ctx'>     hvm_cpuid(input, eax, ebx, ecx, edx);</div><div class='ctx'> </div><div class='del'>-    if ( input == 0x80000001 )</div><div class='del'>-    {</div><div class='add'>+    switch (input) {</div><div class='add'>+    case 0x80000001:</div><div class='ctx'>         /* Fix up VLAPIC details. */</div><div class='ctx'>         if ( vlapic_hw_disabled(vcpu_vlapic(v)) )</div><div class='ctx'>             __clear_bit(X86_FEATURE_APIC &amp; 31, edx);</div><div class='add'>+        break;</div><div class='add'>+    case 0x8000001c: </div><div class='add'>+    {</div><div class='add'>+        /* LWP capability CPUID */</div><div class='add'>+        uint64_t lwp_cfg = v-&gt;arch.hvm_svm.guest_lwp_cfg;</div><div class='add'>+</div><div class='add'>+        if ( cpu_has_lwp )</div><div class='add'>+        {</div><div class='add'>+            if ( !(v-&gt;arch.xcr0 &amp; XSTATE_LWP) )</div><div class='add'>+           {</div><div class='add'>+                *eax = 0x0;</div><div class='add'>+                break;</div><div class='add'>+            }</div><div class='add'>+</div><div class='add'>+            /* turn on available bit and other features specified in lwp_cfg */</div><div class='add'>+            *eax = (*edx &amp; lwp_cfg) | 0x00000001;</div><div class='add'>+        }</div><div class='add'>+        break;</div><div class='add'>+    }</div><div class='add'>+    default:</div><div class='add'>+        break;</div><div class='ctx'>     }</div><div class='ctx'> </div><div class='ctx'>     HVMTRACE_5D (CPUID, input, *eax, *ebx, *ecx, *edx);</div><div class='hunk'>@@ -972,42 +1418,55 @@ static void svm_vmexit_do_cpuid(struct cpu_user_regs *regs)</div><div class='ctx'>     __update_guest_eip(regs, inst_len);</div><div class='ctx'> }</div><div class='ctx'> </div><div class='add'>+static void svm_vmexit_do_cr_access(</div><div class='add'>+    struct vmcb_struct *vmcb, struct cpu_user_regs *regs)</div><div class='add'>+{</div><div class='add'>+    int gp, cr, dir, rc;</div><div class='add'>+</div><div class='add'>+    cr = vmcb-&gt;exitcode - VMEXIT_CR0_READ;</div><div class='add'>+    dir = (cr &gt; 15);</div><div class='add'>+    cr &amp;= 0xf;</div><div class='add'>+    gp = vmcb-&gt;exitinfo1 &amp; 0xf;</div><div class='add'>+</div><div class='add'>+    rc = dir ? hvm_mov_to_cr(cr, gp) : hvm_mov_from_cr(cr, gp);</div><div class='add'>+</div><div class='add'>+    if ( rc == X86EMUL_OKAY )</div><div class='add'>+        __update_guest_eip(regs, vmcb-&gt;nextrip - vmcb-&gt;rip);</div><div class='add'>+}</div><div class='add'>+</div><div class='ctx'> static void svm_dr_access(struct vcpu *v, struct cpu_user_regs *regs)</div><div class='ctx'> {</div><div class='add'>+    struct vmcb_struct *vmcb = vcpu_nestedhvm(v).nv_n1vmcx;</div><div class='add'>+</div><div class='ctx'>     HVMTRACE_0D(DR_WRITE);</div><div class='del'>-    __restore_debug_registers(v);</div><div class='add'>+    __restore_debug_registers(vmcb, v);</div><div class='ctx'> }</div><div class='ctx'> </div><div class='del'>-static int svm_msr_read_intercept(struct cpu_user_regs *regs)</div><div class='add'>+static int svm_msr_read_intercept(unsigned int msr, uint64_t *msr_content)</div><div class='ctx'> {</div><div class='del'>-    u64 msr_content = 0;</div><div class='del'>-    u32 ecx = regs-&gt;ecx, eax, edx;</div><div class='add'>+    int ret;</div><div class='ctx'>     struct vcpu *v = current;</div><div class='ctx'>     struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='ctx'> </div><div class='del'>-    switch ( ecx )</div><div class='add'>+    switch ( msr )</div><div class='ctx'>     {</div><div class='del'>-    case MSR_EFER:</div><div class='del'>-        msr_content = v-&gt;arch.hvm_vcpu.guest_efer;</div><div class='del'>-        break;</div><div class='del'>-</div><div class='ctx'>     case MSR_IA32_SYSENTER_CS:</div><div class='del'>-        msr_content = v-&gt;arch.hvm_svm.guest_sysenter_cs;</div><div class='add'>+        *msr_content = v-&gt;arch.hvm_svm.guest_sysenter_cs;</div><div class='ctx'>         break;</div><div class='ctx'>     case MSR_IA32_SYSENTER_ESP:</div><div class='del'>-        msr_content = v-&gt;arch.hvm_svm.guest_sysenter_esp;</div><div class='add'>+        *msr_content = v-&gt;arch.hvm_svm.guest_sysenter_esp;</div><div class='ctx'>         break;</div><div class='ctx'>     case MSR_IA32_SYSENTER_EIP:</div><div class='del'>-        msr_content = v-&gt;arch.hvm_svm.guest_sysenter_eip;</div><div class='add'>+        *msr_content = v-&gt;arch.hvm_svm.guest_sysenter_eip;</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='del'>-    case MSR_IA32_MC4_MISC: /* Threshold register */</div><div class='add'>+    case MSR_IA32_MCx_MISC(4): /* Threshold register */</div><div class='ctx'>     case MSR_F10_MC4_MISC1 ... MSR_F10_MC4_MISC3:</div><div class='ctx'>         /*</div><div class='ctx'>          * MCA/MCE: We report that the threshold register is unavailable</div><div class='ctx'>          * for OS use (locked by the BIOS).</div><div class='ctx'>          */</div><div class='del'>-        msr_content = 1ULL &lt;&lt; 61; /* MC4_MISC.Locked */</div><div class='add'>+        *msr_content = 1ULL &lt;&lt; 61; /* MC4_MISC.Locked */</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='ctx'>     case MSR_IA32_EBC_FREQUENCY_ID:</div><div class='hunk'>@@ -1016,88 +1475,136 @@ static int svm_msr_read_intercept(struct cpu_user_regs *regs)</div><div class='ctx'>          * has been migrated from an Intel host. The value zero is not</div><div class='ctx'>          * particularly meaningful, but at least avoids the guest crashing!</div><div class='ctx'>          */</div><div class='del'>-        msr_content = 0;</div><div class='add'>+        *msr_content = 0;</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='del'>-    case MSR_K8_VM_HSAVE_PA:</div><div class='del'>-        goto gpf;</div><div class='del'>-</div><div class='ctx'>     case MSR_IA32_DEBUGCTLMSR:</div><div class='del'>-        msr_content = vmcb-&gt;debugctlmsr;</div><div class='add'>+        *msr_content = vmcb_get_debugctlmsr(vmcb);</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='ctx'>     case MSR_IA32_LASTBRANCHFROMIP:</div><div class='del'>-        msr_content = vmcb-&gt;lastbranchfromip;</div><div class='add'>+        *msr_content = vmcb_get_lastbranchfromip(vmcb);</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='ctx'>     case MSR_IA32_LASTBRANCHTOIP:</div><div class='del'>-        msr_content = vmcb-&gt;lastbranchtoip;</div><div class='add'>+        *msr_content = vmcb_get_lastbranchtoip(vmcb);</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='ctx'>     case MSR_IA32_LASTINTFROMIP:</div><div class='del'>-        msr_content = vmcb-&gt;lastintfromip;</div><div class='add'>+        *msr_content = vmcb_get_lastintfromip(vmcb);</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='ctx'>     case MSR_IA32_LASTINTTOIP:</div><div class='del'>-        msr_content = vmcb-&gt;lastinttoip;</div><div class='add'>+        *msr_content = vmcb_get_lastinttoip(vmcb);</div><div class='add'>+        break;</div><div class='add'>+</div><div class='add'>+    case MSR_AMD64_LWP_CFG:</div><div class='add'>+        *msr_content = v-&gt;arch.hvm_svm.guest_lwp_cfg;</div><div class='add'>+        break;</div><div class='add'>+</div><div class='add'>+    case MSR_K7_PERFCTR0:</div><div class='add'>+    case MSR_K7_PERFCTR1:</div><div class='add'>+    case MSR_K7_PERFCTR2:</div><div class='add'>+    case MSR_K7_PERFCTR3:</div><div class='add'>+    case MSR_K7_EVNTSEL0:</div><div class='add'>+    case MSR_K7_EVNTSEL1:</div><div class='add'>+    case MSR_K7_EVNTSEL2:</div><div class='add'>+    case MSR_K7_EVNTSEL3:</div><div class='add'>+    case MSR_AMD_FAM15H_PERFCTR0:</div><div class='add'>+    case MSR_AMD_FAM15H_PERFCTR1:</div><div class='add'>+    case MSR_AMD_FAM15H_PERFCTR2:</div><div class='add'>+    case MSR_AMD_FAM15H_PERFCTR3:</div><div class='add'>+    case MSR_AMD_FAM15H_PERFCTR4:</div><div class='add'>+    case MSR_AMD_FAM15H_PERFCTR5:</div><div class='add'>+    case MSR_AMD_FAM15H_EVNTSEL0:</div><div class='add'>+    case MSR_AMD_FAM15H_EVNTSEL1:</div><div class='add'>+    case MSR_AMD_FAM15H_EVNTSEL2:</div><div class='add'>+    case MSR_AMD_FAM15H_EVNTSEL3:</div><div class='add'>+    case MSR_AMD_FAM15H_EVNTSEL4:</div><div class='add'>+    case MSR_AMD_FAM15H_EVNTSEL5:</div><div class='add'>+        vpmu_do_rdmsr(msr, msr_content);</div><div class='add'>+        break;</div><div class='add'>+</div><div class='add'>+    case MSR_AMD_OSVW_ID_LENGTH:</div><div class='add'>+    case MSR_AMD_OSVW_STATUS:</div><div class='add'>+        ret = svm_handle_osvw(v, msr, msr_content, 1);</div><div class='add'>+        if ( ret &lt; 0 )</div><div class='add'>+            goto gpf;</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='ctx'>     default:</div><div class='add'>+        ret = nsvm_rdmsr(v, msr, msr_content);</div><div class='add'>+        if ( ret &lt; 0 )</div><div class='add'>+            goto gpf;</div><div class='add'>+        else if ( ret )</div><div class='add'>+            break;</div><div class='ctx'> </div><div class='del'>-        if ( rdmsr_viridian_regs(ecx, &amp;msr_content) ||</div><div class='del'>-             rdmsr_hypervisor_regs(ecx, &amp;msr_content) )</div><div class='add'>+        if ( rdmsr_viridian_regs(msr, msr_content) ||</div><div class='add'>+             rdmsr_hypervisor_regs(msr, msr_content) )</div><div class='ctx'>             break;</div><div class='ctx'> </div><div class='del'>-        if ( rdmsr_safe(ecx, eax, edx) == 0 )</div><div class='add'>+        if ( rdmsr_safe(msr, *msr_content) == 0 )</div><div class='add'>+            break;</div><div class='add'>+</div><div class='add'>+        if ( boot_cpu_data.x86 == 0xf &amp;&amp; msr == MSR_F10_BU_CFG )</div><div class='ctx'>         {</div><div class='del'>-            msr_content = ((uint64_t)edx &lt;&lt; 32) | eax;</div><div class='add'>+            /* Win2k8 x64 reads this MSR on revF chips, where it</div><div class='add'>+             * wasn't publically available; it uses a magic constant</div><div class='add'>+             * in %rdi as a password, which we don't have in</div><div class='add'>+             * rdmsr_safe().  Since we'll ignore the later writes,</div><div class='add'>+             * just use a plausible value here (the reset value from</div><div class='add'>+             * rev10h chips) if the real CPU didn't provide one. */</div><div class='add'>+            *msr_content = 0x0000000010200020ull;</div><div class='ctx'>             break;</div><div class='ctx'>         }</div><div class='ctx'> </div><div class='ctx'>         goto gpf;</div><div class='ctx'>     }</div><div class='ctx'> </div><div class='del'>-    regs-&gt;eax = (uint32_t)msr_content;</div><div class='del'>-    regs-&gt;edx = (uint32_t)(msr_content &gt;&gt; 32);</div><div class='del'>-</div><div class='del'>-    HVMTRACE_3D (MSR_READ, ecx, regs-&gt;eax, regs-&gt;edx);</div><div class='del'>-    HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%x, eax=%lx, edx=%lx",</div><div class='del'>-                ecx, (unsigned long)regs-&gt;eax, (unsigned long)regs-&gt;edx);</div><div class='add'>+    HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%x, msr_value=%"PRIx64,</div><div class='add'>+                msr, *msr_content);</div><div class='ctx'>     return X86EMUL_OKAY;</div><div class='ctx'> </div><div class='ctx'>  gpf:</div><div class='del'>-    hvm_inject_exception(TRAP_gp_fault, 0, 0);</div><div class='add'>+    hvm_inject_hw_exception(TRAP_gp_fault, 0);</div><div class='ctx'>     return X86EMUL_EXCEPTION;</div><div class='ctx'> }</div><div class='ctx'> </div><div class='del'>-static int svm_msr_write_intercept(struct cpu_user_regs *regs)</div><div class='add'>+static int svm_msr_write_intercept(unsigned int msr, uint64_t msr_content)</div><div class='ctx'> {</div><div class='del'>-    u64 msr_content = 0;</div><div class='del'>-    u32 ecx = regs-&gt;ecx;</div><div class='add'>+    int ret, result = X86EMUL_OKAY;</div><div class='ctx'>     struct vcpu *v = current;</div><div class='ctx'>     struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='add'>+    int sync = 0;</div><div class='ctx'> </div><div class='del'>-    msr_content = (u32)regs-&gt;eax | ((u64)regs-&gt;edx &lt;&lt; 32);</div><div class='add'>+    switch ( msr )</div><div class='add'>+    {</div><div class='add'>+    case MSR_IA32_SYSENTER_CS:</div><div class='add'>+    case MSR_IA32_SYSENTER_ESP:</div><div class='add'>+    case MSR_IA32_SYSENTER_EIP:</div><div class='add'>+        sync = 1;</div><div class='add'>+        break;</div><div class='add'>+    default:</div><div class='add'>+        break;</div><div class='add'>+    }</div><div class='ctx'> </div><div class='del'>-    HVMTRACE_3D (MSR_WRITE, ecx, regs-&gt;eax, regs-&gt;edx);</div><div class='add'>+    if ( sync )</div><div class='add'>+        svm_sync_vmcb(v);    </div><div class='ctx'> </div><div class='del'>-    switch ( ecx )</div><div class='add'>+    switch ( msr )</div><div class='ctx'>     {</div><div class='del'>-    case MSR_K8_VM_HSAVE_PA:</div><div class='del'>-        goto gpf;</div><div class='del'>-</div><div class='ctx'>     case MSR_IA32_SYSENTER_CS:</div><div class='del'>-        v-&gt;arch.hvm_svm.guest_sysenter_cs = msr_content;</div><div class='add'>+        vmcb-&gt;sysenter_cs = v-&gt;arch.hvm_svm.guest_sysenter_cs = msr_content;</div><div class='ctx'>         break;</div><div class='ctx'>     case MSR_IA32_SYSENTER_ESP:</div><div class='del'>-        v-&gt;arch.hvm_svm.guest_sysenter_esp = msr_content;</div><div class='add'>+        vmcb-&gt;sysenter_esp = v-&gt;arch.hvm_svm.guest_sysenter_esp = msr_content;</div><div class='ctx'>         break;</div><div class='ctx'>     case MSR_IA32_SYSENTER_EIP:</div><div class='del'>-        v-&gt;arch.hvm_svm.guest_sysenter_eip = msr_content;</div><div class='add'>+        vmcb-&gt;sysenter_eip = v-&gt;arch.hvm_svm.guest_sysenter_eip = msr_content;</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='ctx'>     case MSR_IA32_DEBUGCTLMSR:</div><div class='del'>-        vmcb-&gt;debugctlmsr = msr_content;</div><div class='add'>+        vmcb_set_debugctlmsr(vmcb, msr_content);</div><div class='ctx'>         if ( !msr_content || !cpu_has_svm_lbrv )</div><div class='ctx'>             break;</div><div class='ctx'>         vmcb-&gt;lbr_control.fields.enable = 1;</div><div class='hunk'>@@ -1109,42 +1616,96 @@ static int svm_msr_write_intercept(struct cpu_user_regs *regs)</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='ctx'>     case MSR_IA32_LASTBRANCHFROMIP:</div><div class='del'>-        vmcb-&gt;lastbranchfromip = msr_content;</div><div class='add'>+        vmcb_set_lastbranchfromip(vmcb, msr_content);</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='ctx'>     case MSR_IA32_LASTBRANCHTOIP:</div><div class='del'>-        vmcb-&gt;lastbranchtoip = msr_content;</div><div class='add'>+        vmcb_set_lastbranchtoip(vmcb, msr_content);</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='ctx'>     case MSR_IA32_LASTINTFROMIP:</div><div class='del'>-        vmcb-&gt;lastintfromip = msr_content;</div><div class='add'>+        vmcb_set_lastintfromip(vmcb, msr_content);</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='ctx'>     case MSR_IA32_LASTINTTOIP:</div><div class='del'>-        vmcb-&gt;lastinttoip = msr_content;</div><div class='add'>+        vmcb_set_lastinttoip(vmcb, msr_content);</div><div class='add'>+        break;</div><div class='add'>+</div><div class='add'>+    case MSR_AMD64_LWP_CFG:</div><div class='add'>+        if ( svm_update_lwp_cfg(v, msr_content) &lt; 0 )</div><div class='add'>+            goto gpf;</div><div class='add'>+        break;</div><div class='add'>+</div><div class='add'>+    case MSR_K7_PERFCTR0:</div><div class='add'>+    case MSR_K7_PERFCTR1:</div><div class='add'>+    case MSR_K7_PERFCTR2:</div><div class='add'>+    case MSR_K7_PERFCTR3:</div><div class='add'>+    case MSR_K7_EVNTSEL0:</div><div class='add'>+    case MSR_K7_EVNTSEL1:</div><div class='add'>+    case MSR_K7_EVNTSEL2:</div><div class='add'>+    case MSR_K7_EVNTSEL3:</div><div class='add'>+    case MSR_AMD_FAM15H_PERFCTR0:</div><div class='add'>+    case MSR_AMD_FAM15H_PERFCTR1:</div><div class='add'>+    case MSR_AMD_FAM15H_PERFCTR2:</div><div class='add'>+    case MSR_AMD_FAM15H_PERFCTR3:</div><div class='add'>+    case MSR_AMD_FAM15H_PERFCTR4:</div><div class='add'>+    case MSR_AMD_FAM15H_PERFCTR5:</div><div class='add'>+    case MSR_AMD_FAM15H_EVNTSEL0:</div><div class='add'>+    case MSR_AMD_FAM15H_EVNTSEL1:</div><div class='add'>+    case MSR_AMD_FAM15H_EVNTSEL2:</div><div class='add'>+    case MSR_AMD_FAM15H_EVNTSEL3:</div><div class='add'>+    case MSR_AMD_FAM15H_EVNTSEL4:</div><div class='add'>+    case MSR_AMD_FAM15H_EVNTSEL5:</div><div class='add'>+        vpmu_do_wrmsr(msr, msr_content);</div><div class='add'>+        break;</div><div class='add'>+</div><div class='add'>+    case MSR_IA32_MCx_MISC(4): /* Threshold register */</div><div class='add'>+    case MSR_F10_MC4_MISC1 ... MSR_F10_MC4_MISC3:</div><div class='add'>+        /*</div><div class='add'>+         * MCA/MCE: Threshold register is reported to be locked, so we ignore</div><div class='add'>+         * all write accesses. This behaviour matches real HW, so guests should</div><div class='add'>+         * have no problem with this.</div><div class='add'>+         */</div><div class='add'>+        break;</div><div class='add'>+</div><div class='add'>+    case MSR_AMD_OSVW_ID_LENGTH:</div><div class='add'>+    case MSR_AMD_OSVW_STATUS:</div><div class='add'>+        ret = svm_handle_osvw(v, msr, &amp;msr_content, 0);</div><div class='add'>+        if ( ret &lt; 0 )</div><div class='add'>+            goto gpf;</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='ctx'>     default:</div><div class='del'>-        if ( wrmsr_viridian_regs(ecx, msr_content) )</div><div class='add'>+        ret = nsvm_wrmsr(v, msr, msr_content);</div><div class='add'>+        if ( ret &lt; 0 )</div><div class='add'>+            goto gpf;</div><div class='add'>+        else if ( ret )</div><div class='add'>+            break;</div><div class='add'>+</div><div class='add'>+        if ( wrmsr_viridian_regs(msr, msr_content) )</div><div class='ctx'>             break;</div><div class='ctx'> </div><div class='del'>-        switch ( long_mode_do_msr_write(regs) )</div><div class='add'>+        switch ( wrmsr_hypervisor_regs(msr, msr_content) )</div><div class='ctx'>         {</div><div class='del'>-        case HNDL_unhandled:</div><div class='del'>-            wrmsr_hypervisor_regs(ecx, msr_content);</div><div class='add'>+        case -EAGAIN:</div><div class='add'>+            result = X86EMUL_RETRY;</div><div class='ctx'>             break;</div><div class='del'>-        case HNDL_exception_raised:</div><div class='del'>-            return X86EMUL_EXCEPTION;</div><div class='del'>-        case HNDL_done:</div><div class='add'>+        case 0:</div><div class='add'>+        case 1:</div><div class='ctx'>             break;</div><div class='add'>+        default:</div><div class='add'>+            goto gpf;</div><div class='ctx'>         }</div><div class='ctx'>         break;</div><div class='ctx'>     }</div><div class='ctx'> </div><div class='del'>-    return X86EMUL_OKAY;</div><div class='add'>+    if ( sync )</div><div class='add'>+        svm_vmload(vmcb);</div><div class='add'>+</div><div class='add'>+    return result;</div><div class='ctx'> </div><div class='ctx'>  gpf:</div><div class='del'>-    hvm_inject_exception(TRAP_gp_fault, 0, 0);</div><div class='add'>+    hvm_inject_hw_exception(TRAP_gp_fault, 0);</div><div class='ctx'>     return X86EMUL_EXCEPTION;</div><div class='ctx'> }</div><div class='ctx'> </div><div class='hunk'>@@ -1153,18 +1714,22 @@ static void svm_do_msr_access(struct cpu_user_regs *regs)</div><div class='ctx'>     int rc, inst_len;</div><div class='ctx'>     struct vcpu *v = current;</div><div class='ctx'>     struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='add'>+    uint64_t msr_content;</div><div class='ctx'> </div><div class='ctx'>     if ( vmcb-&gt;exitinfo1 == 0 )</div><div class='ctx'>     {</div><div class='ctx'>         if ( (inst_len = __get_instruction_length(v, INSTR_RDMSR)) == 0 )</div><div class='ctx'>             return;</div><div class='del'>-        rc = hvm_msr_read_intercept(regs);</div><div class='add'>+        rc = hvm_msr_read_intercept(regs-&gt;ecx, &amp;msr_content);</div><div class='add'>+        regs-&gt;eax = (uint32_t)msr_content;</div><div class='add'>+        regs-&gt;edx = (uint32_t)(msr_content &gt;&gt; 32);</div><div class='ctx'>     }</div><div class='ctx'>     else</div><div class='ctx'>     {</div><div class='ctx'>         if ( (inst_len = __get_instruction_length(v, INSTR_WRMSR)) == 0 )</div><div class='ctx'>             return;</div><div class='del'>-        rc = hvm_msr_write_intercept(regs);</div><div class='add'>+        msr_content = ((uint64_t)regs-&gt;edx &lt;&lt; 32) | (uint32_t)regs-&gt;eax;</div><div class='add'>+        rc = hvm_msr_write_intercept(regs-&gt;ecx, msr_content);</div><div class='ctx'>     }</div><div class='ctx'> </div><div class='ctx'>     if ( rc == X86EMUL_OKAY )</div><div class='hunk'>@@ -1194,6 +1759,150 @@ static void svm_vmexit_do_rdtsc(struct cpu_user_regs *regs)</div><div class='ctx'>     hvm_rdtsc_intercept(regs);</div><div class='ctx'> }</div><div class='ctx'> </div><div class='add'>+static void svm_vmexit_do_pause(struct cpu_user_regs *regs)</div><div class='add'>+{</div><div class='add'>+    unsigned int inst_len;</div><div class='add'>+</div><div class='add'>+    if ( (inst_len = __get_instruction_length(current, INSTR_PAUSE)) == 0 )</div><div class='add'>+        return;</div><div class='add'>+    __update_guest_eip(regs, inst_len);</div><div class='add'>+</div><div class='add'>+    /*</div><div class='add'>+     * The guest is running a contended spinlock and we've detected it.</div><div class='add'>+     * Do something useful, like reschedule the guest</div><div class='add'>+     */</div><div class='add'>+    perfc_incr(pauseloop_exits);</div><div class='add'>+    do_sched_op_compat(SCHEDOP_yield, 0);</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+static void</div><div class='add'>+svm_vmexit_do_vmrun(struct cpu_user_regs *regs,</div><div class='add'>+                    struct vcpu *v, uint64_t vmcbaddr)</div><div class='add'>+{</div><div class='add'>+    if ( !nsvm_efer_svm_enabled(v) )</div><div class='add'>+    {</div><div class='add'>+        gdprintk(XENLOG_ERR, "VMRUN: nestedhvm disabled, injecting #UD\n");</div><div class='add'>+        hvm_inject_hw_exception(TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE);</div><div class='add'>+        return;</div><div class='add'>+    }</div><div class='add'>+</div><div class='add'>+    if ( !nestedsvm_vmcb_map(v, vmcbaddr) )</div><div class='add'>+    {</div><div class='add'>+        gdprintk(XENLOG_ERR, "VMRUN: mapping vmcb failed, injecting #GP\n");</div><div class='add'>+        hvm_inject_hw_exception(TRAP_gp_fault, HVM_DELIVER_NO_ERROR_CODE);</div><div class='add'>+        return;</div><div class='add'>+    }</div><div class='add'>+</div><div class='add'>+    vcpu_nestedhvm(v).nv_vmentry_pending = 1;</div><div class='add'>+    return;</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+static struct page_info *</div><div class='add'>+nsvm_get_nvmcb_page(struct vcpu *v, uint64_t vmcbaddr)</div><div class='add'>+{</div><div class='add'>+    p2m_type_t p2mt;</div><div class='add'>+    struct page_info *page;</div><div class='add'>+    struct nestedvcpu *nv = &amp;vcpu_nestedhvm(v);</div><div class='add'>+</div><div class='add'>+    if ( !nestedsvm_vmcb_map(v, vmcbaddr) )</div><div class='add'>+        return NULL;</div><div class='add'>+</div><div class='add'>+    /* Need to translate L1-GPA to MPA */</div><div class='add'>+    page = get_page_from_gfn(v-&gt;domain, </div><div class='add'>+                            nv-&gt;nv_vvmcxaddr &gt;&gt; PAGE_SHIFT, </div><div class='add'>+                            &amp;p2mt, P2M_ALLOC | P2M_UNSHARE);</div><div class='add'>+    if ( !page )</div><div class='add'>+        return NULL;</div><div class='add'>+</div><div class='add'>+    if ( !p2m_is_ram(p2mt) || p2m_is_readonly(p2mt) )</div><div class='add'>+    {</div><div class='add'>+        put_page(page);</div><div class='add'>+        return NULL; </div><div class='add'>+    }</div><div class='add'>+</div><div class='add'>+    return  page;</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+static void</div><div class='add'>+svm_vmexit_do_vmload(struct vmcb_struct *vmcb,</div><div class='add'>+                     struct cpu_user_regs *regs,</div><div class='add'>+                     struct vcpu *v, uint64_t vmcbaddr)</div><div class='add'>+{</div><div class='add'>+    int ret;</div><div class='add'>+    unsigned int inst_len;</div><div class='add'>+    struct page_info *page;</div><div class='add'>+</div><div class='add'>+    if ( (inst_len = __get_instruction_length(v, INSTR_VMLOAD)) == 0 )</div><div class='add'>+        return;</div><div class='add'>+</div><div class='add'>+    if ( !nsvm_efer_svm_enabled(v) ) </div><div class='add'>+    {</div><div class='add'>+        gdprintk(XENLOG_ERR, "VMLOAD: nestedhvm disabled, injecting #UD\n");</div><div class='add'>+        ret = TRAP_invalid_op;</div><div class='add'>+        goto inject;</div><div class='add'>+    }</div><div class='add'>+</div><div class='add'>+    page = nsvm_get_nvmcb_page(v, vmcbaddr);</div><div class='add'>+    if ( !page )</div><div class='add'>+    {</div><div class='add'>+        gdprintk(XENLOG_ERR,</div><div class='add'>+            "VMLOAD: mapping failed, injecting #GP\n");</div><div class='add'>+        ret = TRAP_gp_fault;</div><div class='add'>+        goto inject;</div><div class='add'>+    }</div><div class='add'>+</div><div class='add'>+    svm_vmload_pa(page_to_maddr(page));</div><div class='add'>+    put_page(page);</div><div class='add'>+</div><div class='add'>+    /* State in L1 VMCB is stale now */</div><div class='add'>+    v-&gt;arch.hvm_svm.vmcb_in_sync = 0;</div><div class='add'>+</div><div class='add'>+    __update_guest_eip(regs, inst_len);</div><div class='add'>+    return;</div><div class='add'>+</div><div class='add'>+ inject:</div><div class='add'>+    hvm_inject_hw_exception(ret, HVM_DELIVER_NO_ERROR_CODE);</div><div class='add'>+    return;</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+static void</div><div class='add'>+svm_vmexit_do_vmsave(struct vmcb_struct *vmcb,</div><div class='add'>+                     struct cpu_user_regs *regs,</div><div class='add'>+                     struct vcpu *v, uint64_t vmcbaddr)</div><div class='add'>+{</div><div class='add'>+    int ret;</div><div class='add'>+    unsigned int inst_len;</div><div class='add'>+    struct page_info *page;</div><div class='add'>+</div><div class='add'>+    if ( (inst_len = __get_instruction_length(v, INSTR_VMSAVE)) == 0 )</div><div class='add'>+        return;</div><div class='add'>+</div><div class='add'>+    if ( !nsvm_efer_svm_enabled(v) ) </div><div class='add'>+    {</div><div class='add'>+        gdprintk(XENLOG_ERR, "VMSAVE: nestedhvm disabled, injecting #UD\n");</div><div class='add'>+        ret = TRAP_invalid_op;</div><div class='add'>+        goto inject;</div><div class='add'>+    }</div><div class='add'>+</div><div class='add'>+    page = nsvm_get_nvmcb_page(v, vmcbaddr);</div><div class='add'>+    if ( !page )</div><div class='add'>+    {</div><div class='add'>+        gdprintk(XENLOG_ERR,</div><div class='add'>+            "VMSAVE: mapping vmcb failed, injecting #GP\n");</div><div class='add'>+        ret = TRAP_gp_fault;</div><div class='add'>+        goto inject;</div><div class='add'>+    }</div><div class='add'>+</div><div class='add'>+    svm_vmsave_pa(page_to_maddr(page));</div><div class='add'>+    put_page(page);</div><div class='add'>+    __update_guest_eip(regs, inst_len);</div><div class='add'>+    return;</div><div class='add'>+</div><div class='add'>+ inject:</div><div class='add'>+    hvm_inject_hw_exception(ret, HVM_DELIVER_NO_ERROR_CODE);</div><div class='add'>+    return;</div><div class='add'>+}</div><div class='add'>+</div><div class='ctx'> static void svm_vmexit_ud_intercept(struct cpu_user_regs *regs)</div><div class='ctx'> {</div><div class='ctx'>     struct hvm_emulate_ctxt ctxt;</div><div class='hunk'>@@ -1206,11 +1915,11 @@ static void svm_vmexit_ud_intercept(struct cpu_user_regs *regs)</div><div class='ctx'>     switch ( rc )</div><div class='ctx'>     {</div><div class='ctx'>     case X86EMUL_UNHANDLEABLE:</div><div class='del'>-        hvm_inject_exception(TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE, 0);</div><div class='add'>+        hvm_inject_hw_exception(TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE);</div><div class='ctx'>         break;</div><div class='ctx'>     case X86EMUL_EXCEPTION:</div><div class='ctx'>         if ( ctxt.exn_pending )</div><div class='del'>-            hvm_inject_exception(ctxt.exn_vector, ctxt.exn_error_code, 0);</div><div class='add'>+            hvm_inject_hw_exception(ctxt.exn_vector, ctxt.exn_error_code);</div><div class='ctx'>         /* fall through */</div><div class='ctx'>     default:</div><div class='ctx'>         hvm_emulate_writeback(&amp;ctxt);</div><div class='hunk'>@@ -1218,6 +1927,45 @@ static void svm_vmexit_ud_intercept(struct cpu_user_regs *regs)</div><div class='ctx'>     }</div><div class='ctx'> }</div><div class='ctx'> </div><div class='add'>+static int svm_is_erratum_383(struct cpu_user_regs *regs)</div><div class='add'>+{</div><div class='add'>+    uint64_t msr_content;</div><div class='add'>+    uint32_t i;</div><div class='add'>+    struct vcpu *v = current;</div><div class='add'>+</div><div class='add'>+    if ( !amd_erratum383_found )</div><div class='add'>+        return 0;</div><div class='add'>+</div><div class='add'>+    rdmsrl(MSR_IA32_MC0_STATUS, msr_content);</div><div class='add'>+    /* Bit 62 may or may not be set for this mce */</div><div class='add'>+    msr_content &amp;= ~(1ULL &lt;&lt; 62);</div><div class='add'>+</div><div class='add'>+    if ( msr_content != 0xb600000000010015ULL )</div><div class='add'>+        return 0;</div><div class='add'>+    </div><div class='add'>+    /* Clear MCi_STATUS registers */</div><div class='add'>+    for (i = 0; i &lt; nr_mce_banks; i++)</div><div class='add'>+        wrmsrl(MSR_IA32_MCx_STATUS(i), 0ULL);</div><div class='add'>+    </div><div class='add'>+    rdmsrl(MSR_IA32_MCG_STATUS, msr_content);</div><div class='add'>+    wrmsrl(MSR_IA32_MCG_STATUS, msr_content &amp; ~(1ULL &lt;&lt; 2));</div><div class='add'>+</div><div class='add'>+    /* flush TLB */</div><div class='add'>+    flush_tlb_mask(v-&gt;domain-&gt;domain_dirty_cpumask);</div><div class='add'>+</div><div class='add'>+    return 1;</div><div class='add'>+}</div><div class='add'>+</div><div class='add'>+static void svm_vmexit_mce_intercept(</div><div class='add'>+    struct vcpu *v, struct cpu_user_regs *regs)</div><div class='add'>+{</div><div class='add'>+    if ( svm_is_erratum_383(regs) )</div><div class='add'>+    {</div><div class='add'>+        gdprintk(XENLOG_ERR, "SVM hits AMD erratum 383\n");</div><div class='add'>+        domain_crash(v-&gt;domain);</div><div class='add'>+    }</div><div class='add'>+}</div><div class='add'>+</div><div class='ctx'> static void wbinvd_ipi(void *info)</div><div class='ctx'> {</div><div class='ctx'>     wbinvd();</div><div class='hunk'>@@ -1231,7 +1979,7 @@ static void svm_wbinvd_intercept(void)</div><div class='ctx'> </div><div class='ctx'> static void svm_vmexit_do_invalidate_cache(struct cpu_user_regs *regs)</div><div class='ctx'> {</div><div class='del'>-    enum instruction_index list[] = { INSTR_INVD, INSTR_WBINVD };</div><div class='add'>+    static const enum instruction_index list[] = { INSTR_INVD, INSTR_WBINVD };</div><div class='ctx'>     int inst_len;</div><div class='ctx'> </div><div class='ctx'>     inst_len = __get_instruction_length_from_list(</div><div class='hunk'>@@ -1244,6 +1992,15 @@ static void svm_vmexit_do_invalidate_cache(struct cpu_user_regs *regs)</div><div class='ctx'>     __update_guest_eip(regs, inst_len);</div><div class='ctx'> }</div><div class='ctx'> </div><div class='add'>+static void svm_invlpga_intercept(</div><div class='add'>+    struct vcpu *v, unsigned long vaddr, uint32_t asid)</div><div class='add'>+{</div><div class='add'>+    svm_invlpga(vaddr,</div><div class='add'>+                (asid == 0)</div><div class='add'>+                ? v-&gt;arch.hvm_vcpu.n1asid.asid</div><div class='add'>+                : vcpu_nestedhvm(v).nv_n2asid.asid);</div><div class='add'>+}</div><div class='add'>+</div><div class='ctx'> static void svm_invlpg_intercept(unsigned long vaddr)</div><div class='ctx'> {</div><div class='ctx'>     struct vcpu *curr = current;</div><div class='hunk'>@@ -1252,9 +2009,11 @@ static void svm_invlpg_intercept(unsigned long vaddr)</div><div class='ctx'>     svm_asid_g_invlpg(curr, vaddr);</div><div class='ctx'> }</div><div class='ctx'> </div><div class='del'>-static struct hvm_function_table __read_mostly svm_function_table = {</div><div class='add'>+static struct hvm_function_table __initdata svm_function_table = {</div><div class='ctx'>     .name                 = "SVM",</div><div class='del'>-    .cpu_prepare          = svm_cpu_prepare,</div><div class='add'>+    .cpu_up_prepare       = svm_cpu_up_prepare,</div><div class='add'>+    .cpu_dead             = svm_cpu_dead,</div><div class='add'>+    .cpu_up               = svm_cpu_up,</div><div class='ctx'>     .cpu_down             = svm_cpu_down,</div><div class='ctx'>     .domain_initialise    = svm_domain_initialise,</div><div class='ctx'>     .domain_destroy       = svm_domain_destroy,</div><div class='hunk'>@@ -1267,33 +2026,57 @@ static struct hvm_function_table __read_mostly svm_function_table = {</div><div class='ctx'>     .guest_x86_mode       = svm_guest_x86_mode,</div><div class='ctx'>     .get_segment_register = svm_get_segment_register,</div><div class='ctx'>     .set_segment_register = svm_set_segment_register,</div><div class='del'>-    .update_host_cr3      = svm_update_host_cr3,</div><div class='add'>+    .get_shadow_gs_base   = svm_get_shadow_gs_base,</div><div class='ctx'>     .update_guest_cr      = svm_update_guest_cr,</div><div class='ctx'>     .update_guest_efer    = svm_update_guest_efer,</div><div class='add'>+    .set_guest_pat        = svm_set_guest_pat,</div><div class='add'>+    .get_guest_pat        = svm_get_guest_pat,</div><div class='ctx'>     .set_tsc_offset       = svm_set_tsc_offset,</div><div class='del'>-    .inject_exception     = svm_inject_exception,</div><div class='add'>+    .inject_trap          = svm_inject_trap,</div><div class='ctx'>     .init_hypercall_page  = svm_init_hypercall_page,</div><div class='ctx'>     .event_pending        = svm_event_pending,</div><div class='del'>-    .do_pmu_interrupt     = svm_do_pmu_interrupt,</div><div class='ctx'>     .cpuid_intercept      = svm_cpuid_intercept,</div><div class='ctx'>     .wbinvd_intercept     = svm_wbinvd_intercept,</div><div class='ctx'>     .fpu_dirty_intercept  = svm_fpu_dirty_intercept,</div><div class='ctx'>     .msr_read_intercept   = svm_msr_read_intercept,</div><div class='ctx'>     .msr_write_intercept  = svm_msr_write_intercept,</div><div class='ctx'>     .invlpg_intercept     = svm_invlpg_intercept,</div><div class='del'>-    .set_rdtsc_exiting    = svm_set_rdtsc_exiting</div><div class='add'>+    .set_rdtsc_exiting    = svm_set_rdtsc_exiting,</div><div class='add'>+    .get_insn_bytes       = svm_get_insn_bytes,</div><div class='add'>+</div><div class='add'>+    .nhvm_vcpu_initialise = nsvm_vcpu_initialise,</div><div class='add'>+    .nhvm_vcpu_destroy = nsvm_vcpu_destroy,</div><div class='add'>+    .nhvm_vcpu_reset = nsvm_vcpu_reset,</div><div class='add'>+    .nhvm_vcpu_hostrestore = nsvm_vcpu_hostrestore,</div><div class='add'>+    .nhvm_vcpu_vmexit = nsvm_vcpu_vmexit_inject,</div><div class='add'>+    .nhvm_vcpu_vmexit_trap = nsvm_vcpu_vmexit_trap,</div><div class='add'>+    .nhvm_vcpu_guestcr3 = nsvm_vcpu_guestcr3,</div><div class='add'>+    .nhvm_vcpu_p2m_base = nsvm_vcpu_hostcr3,</div><div class='add'>+    .nhvm_vcpu_asid = nsvm_vcpu_asid,</div><div class='add'>+    .nhvm_vmcx_guest_intercepts_trap = nsvm_vmcb_guest_intercepts_trap,</div><div class='add'>+    .nhvm_vmcx_hap_enabled = nsvm_vmcb_hap_enabled,</div><div class='add'>+    .nhvm_intr_blocked = nsvm_intr_blocked,</div><div class='add'>+    .nhvm_hap_walk_L1_p2m = nsvm_hap_walk_L1_p2m,</div><div class='ctx'> };</div><div class='ctx'> </div><div class='del'>-asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)</div><div class='add'>+void svm_vmexit_handler(struct cpu_user_regs *regs)</div><div class='ctx'> {</div><div class='del'>-    unsigned int exit_reason;</div><div class='add'>+    uint64_t exit_reason;</div><div class='ctx'>     struct vcpu *v = current;</div><div class='ctx'>     struct vmcb_struct *vmcb = v-&gt;arch.hvm_svm.vmcb;</div><div class='ctx'>     eventinj_t eventinj;</div><div class='ctx'>     int inst_len, rc;</div><div class='add'>+    vintr_t intr;</div><div class='add'>+    bool_t vcpu_guestmode = 0;</div><div class='add'>+</div><div class='add'>+    hvm_invalidate_regs_fields(regs);</div><div class='ctx'> </div><div class='ctx'>     if ( paging_mode_hap(v-&gt;domain) )</div><div class='del'>-        v-&gt;arch.hvm_vcpu.guest_cr[3] = v-&gt;arch.hvm_vcpu.hw_cr[3] = vmcb-&gt;cr3;</div><div class='add'>+        v-&gt;arch.hvm_vcpu.guest_cr[3] = v-&gt;arch.hvm_vcpu.hw_cr[3] =</div><div class='add'>+            vmcb_get_cr3(vmcb);</div><div class='add'>+</div><div class='add'>+    if ( nestedhvm_enabled(v-&gt;domain) &amp;&amp; nestedhvm_vcpu_in_guestmode(v) )</div><div class='add'>+        vcpu_guestmode = 1;</div><div class='ctx'> </div><div class='ctx'>     /*</div><div class='ctx'>      * Before doing anything else, we need to sync up the VLAPIC's TPR with</div><div class='hunk'>@@ -1302,24 +2085,89 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)</div><div class='ctx'>      * NB. We need to preserve the low bits of the TPR to make checked builds</div><div class='ctx'>      * of Windows work, even though they don't actually do anything.</div><div class='ctx'>      */</div><div class='del'>-    vlapic_set_reg(vcpu_vlapic(v), APIC_TASKPRI,</div><div class='del'>-                   ((vmcb-&gt;vintr.fields.tpr &amp; 0x0F) &lt;&lt; 4) |</div><div class='add'>+    if ( !vcpu_guestmode ) {</div><div class='add'>+        intr = vmcb_get_vintr(vmcb);</div><div class='add'>+        vlapic_set_reg(vcpu_vlapic(v), APIC_TASKPRI,</div><div class='add'>+                   ((intr.fields.tpr &amp; 0x0F) &lt;&lt; 4) |</div><div class='ctx'>                    (vlapic_get_reg(vcpu_vlapic(v), APIC_TASKPRI) &amp; 0x0F));</div><div class='add'>+    }</div><div class='ctx'> </div><div class='ctx'>     exit_reason = vmcb-&gt;exitcode;</div><div class='ctx'> </div><div class='ctx'>     if ( hvm_long_mode_enabled(v) )</div><div class='del'>-        HVMTRACE_ND(VMEXIT64, 1/*cycles*/, 3, exit_reason,</div><div class='add'>+        HVMTRACE_ND(VMEXIT64, vcpu_guestmode ? TRC_HVM_NESTEDFLAG : 0,</div><div class='add'>+                    1/*cycles*/, 3, exit_reason,</div><div class='ctx'>                     (uint32_t)regs-&gt;eip, (uint32_t)((uint64_t)regs-&gt;eip &gt;&gt; 32),</div><div class='ctx'>                     0, 0, 0);</div><div class='ctx'>     else</div><div class='del'>-        HVMTRACE_ND(VMEXIT, 1/*cycles*/, 2, exit_reason,</div><div class='del'>-                    (uint32_t)regs-&gt;eip, </div><div class='add'>+        HVMTRACE_ND(VMEXIT, vcpu_guestmode ? TRC_HVM_NESTEDFLAG : 0,</div><div class='add'>+                    1/*cycles*/, 2, exit_reason,</div><div class='add'>+                    (uint32_t)regs-&gt;eip,</div><div class='ctx'>                     0, 0, 0, 0);</div><div class='ctx'> </div><div class='add'>+    if ( vcpu_guestmode ) {</div><div class='add'>+        enum nestedhvm_vmexits nsret;</div><div class='add'>+        struct nestedvcpu *nv = &amp;vcpu_nestedhvm(v);</div><div class='add'>+        struct vmcb_struct *ns_vmcb = nv-&gt;nv_vvmcx;</div><div class='add'>+        uint64_t exitinfo1, exitinfo2;</div><div class='add'>+</div><div class='add'>+        paging_update_nestedmode(v);</div><div class='add'>+</div><div class='add'>+        /* Write real exitinfo1 back into virtual vmcb.</div><div class='add'>+         * nestedsvm_check_intercepts() expects to have the correct</div><div class='add'>+         * exitinfo1 value there.</div><div class='add'>+         */</div><div class='add'>+        exitinfo1 = ns_vmcb-&gt;exitinfo1;</div><div class='add'>+        ns_vmcb-&gt;exitinfo1 = vmcb-&gt;exitinfo1;</div><div class='add'>+        nsret = nestedsvm_check_intercepts(v, regs, exit_reason);</div><div class='add'>+        switch (nsret) {</div><div class='add'>+        case NESTEDHVM_VMEXIT_CONTINUE:</div><div class='add'>+            BUG();</div><div class='add'>+            break;</div><div class='add'>+        case NESTEDHVM_VMEXIT_HOST:</div><div class='add'>+            break;</div><div class='add'>+        case NESTEDHVM_VMEXIT_INJECT:</div><div class='add'>+            /* Switch vcpu from l2 to l1 guest. We must perform</div><div class='add'>+             * the switch here to have svm_do_resume() working</div><div class='add'>+             * as intended.</div><div class='add'>+             */</div><div class='add'>+            exitinfo1 = vmcb-&gt;exitinfo1;</div><div class='add'>+            exitinfo2 = vmcb-&gt;exitinfo2;</div><div class='add'>+            nv-&gt;nv_vmswitch_in_progress = 1;</div><div class='add'>+            nsret = nestedsvm_vmexit_n2n1(v, regs);</div><div class='add'>+            nv-&gt;nv_vmswitch_in_progress = 0;</div><div class='add'>+            switch (nsret) {</div><div class='add'>+            case NESTEDHVM_VMEXIT_DONE:</div><div class='add'>+                /* defer VMEXIT injection */</div><div class='add'>+                nestedsvm_vmexit_defer(v, exit_reason, exitinfo1, exitinfo2);</div><div class='add'>+                goto out;</div><div class='add'>+            case NESTEDHVM_VMEXIT_FATALERROR:</div><div class='add'>+                gdprintk(XENLOG_ERR, "unexpected nestedsvm_vmexit() error\n");</div><div class='add'>+                goto exit_and_crash;</div><div class='add'>+</div><div class='add'>+            default:</div><div class='add'>+                BUG();</div><div class='add'>+            case NESTEDHVM_VMEXIT_ERROR:</div><div class='add'>+                break;</div><div class='add'>+            }</div><div class='add'>+        case NESTEDHVM_VMEXIT_ERROR:</div><div class='add'>+            gdprintk(XENLOG_ERR,</div><div class='add'>+                "nestedsvm_check_intercepts() returned NESTEDHVM_VMEXIT_ERROR\n");</div><div class='add'>+            goto out;</div><div class='add'>+        case NESTEDHVM_VMEXIT_FATALERROR:</div><div class='add'>+            gdprintk(XENLOG_ERR,</div><div class='add'>+                "unexpected nestedsvm_check_intercepts() error\n");</div><div class='add'>+            goto exit_and_crash;</div><div class='add'>+        default:</div><div class='add'>+            gdprintk(XENLOG_INFO, "nestedsvm_check_intercepts() returned %i\n",</div><div class='add'>+                nsret);</div><div class='add'>+            goto exit_and_crash;</div><div class='add'>+        }</div><div class='add'>+    }</div><div class='add'>+</div><div class='ctx'>     if ( unlikely(exit_reason == VMEXIT_INVALID) )</div><div class='ctx'>     {</div><div class='del'>-        svm_dump_vmcb(__func__, vmcb);</div><div class='add'>+        svm_vmcb_dump(__func__, vmcb);</div><div class='ctx'>         goto exit_and_crash;</div><div class='ctx'>     }</div><div class='ctx'> </div><div class='hunk'>@@ -1327,6 +2175,8 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)</div><div class='ctx'> </div><div class='ctx'>     hvm_maybe_deassert_evtchn_irq();</div><div class='ctx'> </div><div class='add'>+    vmcb-&gt;cleanbits.bytes = cpu_has_svm_cleanbits ? ~0u : 0u;</div><div class='add'>+</div><div class='ctx'>     /* Event delivery caused this intercept? Queue for redelivery. */</div><div class='ctx'>     eventinj = vmcb-&gt;exitintinfo;</div><div class='ctx'>     if ( unlikely(eventinj.fields.v) &amp;&amp;</div><div class='hunk'>@@ -1364,9 +2214,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)</div><div class='ctx'>         if ( (inst_len = __get_instruction_length(v, INSTR_INT3)) == 0 )</div><div class='ctx'>             break;</div><div class='ctx'>         __update_guest_eip(regs, inst_len);</div><div class='del'>-#ifdef XEN_GDBSX_CONFIG</div><div class='ctx'>         current-&gt;arch.gdbsx_vcpu_event = TRAP_int3;</div><div class='del'>-#endif</div><div class='ctx'>         domain_pause_for_debugger();</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='hunk'>@@ -1384,7 +2232,12 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)</div><div class='ctx'>                     (unsigned long)regs-&gt;ecx, (unsigned long)regs-&gt;edx,</div><div class='ctx'>                     (unsigned long)regs-&gt;esi, (unsigned long)regs-&gt;edi);</div><div class='ctx'> </div><div class='del'>-        if ( paging_fault(va, regs) )</div><div class='add'>+        if ( cpu_has_svm_decode )</div><div class='add'>+            v-&gt;arch.hvm_svm.cached_insn_len = vmcb-&gt;guest_ins_len &amp; 0xf;</div><div class='add'>+        rc = paging_fault(va, regs);</div><div class='add'>+        v-&gt;arch.hvm_svm.cached_insn_len = 0;</div><div class='add'>+</div><div class='add'>+        if ( rc )</div><div class='ctx'>         {</div><div class='ctx'>             if ( trace_will_trace_event(TRC_SHADOW) )</div><div class='ctx'>                 break;</div><div class='hunk'>@@ -1395,7 +2248,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)</div><div class='ctx'>             break;</div><div class='ctx'>         }</div><div class='ctx'> </div><div class='del'>-        hvm_inject_exception(TRAP_page_fault, regs-&gt;error_code, va);</div><div class='add'>+        hvm_inject_page_fault(regs-&gt;error_code, va);</div><div class='ctx'>         break;</div><div class='ctx'>     }</div><div class='ctx'> </div><div class='hunk'>@@ -1406,12 +2259,20 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)</div><div class='ctx'>     /* Asynchronous event, handled when we STGI'd after the VMEXIT. */</div><div class='ctx'>     case VMEXIT_EXCEPTION_MC:</div><div class='ctx'>         HVMTRACE_0D(MCE);</div><div class='add'>+        svm_vmexit_mce_intercept(v, regs);</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='del'>-    case VMEXIT_VINTR:</div><div class='del'>-        vmcb-&gt;vintr.fields.irq = 0;</div><div class='del'>-        vmcb-&gt;general1_intercepts &amp;= ~GENERAL1_INTERCEPT_VINTR;</div><div class='add'>+    case VMEXIT_VINTR: {</div><div class='add'>+        u32 general1_intercepts = vmcb_get_general1_intercepts(vmcb);</div><div class='add'>+        intr = vmcb_get_vintr(vmcb);</div><div class='add'>+</div><div class='add'>+        intr.fields.irq = 0;</div><div class='add'>+        general1_intercepts &amp;= ~GENERAL1_INTERCEPT_VINTR;</div><div class='add'>+</div><div class='add'>+        vmcb_set_vintr(vmcb, intr);</div><div class='add'>+        vmcb_set_general1_intercepts(vmcb, general1_intercepts);</div><div class='ctx'>         break;</div><div class='add'>+    }</div><div class='ctx'> </div><div class='ctx'>     case VMEXIT_INVD:</div><div class='ctx'>     case VMEXIT_WBINVD:</div><div class='hunk'>@@ -1450,18 +2311,48 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)</div><div class='ctx'>         svm_vmexit_do_hlt(vmcb, regs);</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='add'>+    case VMEXIT_IOIO:</div><div class='add'>+        if ( (vmcb-&gt;exitinfo1 &amp; (1u&lt;&lt;2)) == 0 )</div><div class='add'>+        {</div><div class='add'>+            uint16_t port = (vmcb-&gt;exitinfo1 &gt;&gt; 16) &amp; 0xFFFF;</div><div class='add'>+            int bytes = ((vmcb-&gt;exitinfo1 &gt;&gt; 4) &amp; 0x07);</div><div class='add'>+            int dir = (vmcb-&gt;exitinfo1 &amp; 1) ? IOREQ_READ : IOREQ_WRITE;</div><div class='add'>+            if ( handle_pio(port, bytes, dir) )</div><div class='add'>+                __update_guest_eip(regs, vmcb-&gt;exitinfo2 - vmcb-&gt;rip);</div><div class='add'>+        }</div><div class='add'>+        else if ( !handle_mmio() )</div><div class='add'>+            hvm_inject_hw_exception(TRAP_gp_fault, 0);</div><div class='add'>+        break;</div><div class='add'>+</div><div class='ctx'>     case VMEXIT_CR0_READ ... VMEXIT_CR15_READ:</div><div class='ctx'>     case VMEXIT_CR0_WRITE ... VMEXIT_CR15_WRITE:</div><div class='add'>+        if ( cpu_has_svm_decode &amp;&amp; (vmcb-&gt;exitinfo1 &amp; (1ULL &lt;&lt; 63)) )</div><div class='add'>+            svm_vmexit_do_cr_access(vmcb, regs);</div><div class='add'>+        else if ( !handle_mmio() ) </div><div class='add'>+            hvm_inject_hw_exception(TRAP_gp_fault, 0);</div><div class='add'>+        break;</div><div class='add'>+</div><div class='ctx'>     case VMEXIT_INVLPG:</div><div class='add'>+        if ( cpu_has_svm_decode )</div><div class='add'>+        {</div><div class='add'>+            svm_invlpg_intercept(vmcb-&gt;exitinfo1);</div><div class='add'>+            __update_guest_eip(regs, vmcb-&gt;nextrip - vmcb-&gt;rip);</div><div class='add'>+        }</div><div class='add'>+        else if ( !handle_mmio() )</div><div class='add'>+            hvm_inject_hw_exception(TRAP_gp_fault, 0);</div><div class='add'>+        break;</div><div class='add'>+</div><div class='ctx'>     case VMEXIT_INVLPGA:</div><div class='del'>-    case VMEXIT_IOIO:</div><div class='del'>-        if ( !handle_mmio() )</div><div class='del'>-            hvm_inject_exception(TRAP_gp_fault, 0, 0);</div><div class='add'>+        if ( (inst_len = __get_instruction_length(v, INSTR_INVLPGA)) == 0 )</div><div class='add'>+            break;</div><div class='add'>+        svm_invlpga_intercept(v, regs-&gt;eax, regs-&gt;ecx);</div><div class='add'>+        __update_guest_eip(regs, inst_len);</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='ctx'>     case VMEXIT_VMMCALL:</div><div class='ctx'>         if ( (inst_len = __get_instruction_length(v, INSTR_VMCALL)) == 0 )</div><div class='ctx'>             break;</div><div class='add'>+        BUG_ON(vcpu_guestmode);</div><div class='ctx'>         HVMTRACE_1D(VMMCALL, regs-&gt;eax);</div><div class='ctx'>         rc = hvm_do_hypercall(regs);</div><div class='ctx'>         if ( rc != HVM_HCALL_preempted )</div><div class='hunk'>@@ -1494,22 +2385,47 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)</div><div class='ctx'> </div><div class='ctx'>     case VMEXIT_MONITOR:</div><div class='ctx'>     case VMEXIT_MWAIT:</div><div class='add'>+        hvm_inject_hw_exception(TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE);</div><div class='add'>+        break;</div><div class='add'>+</div><div class='ctx'>     case VMEXIT_VMRUN:</div><div class='add'>+        svm_vmexit_do_vmrun(regs, v, regs-&gt;eax);</div><div class='add'>+        break;</div><div class='ctx'>     case VMEXIT_VMLOAD:</div><div class='add'>+        svm_vmexit_do_vmload(vmcb, regs, v, regs-&gt;eax);</div><div class='add'>+        break;</div><div class='ctx'>     case VMEXIT_VMSAVE:</div><div class='add'>+        svm_vmexit_do_vmsave(vmcb, regs, v, regs-&gt;eax);</div><div class='add'>+        break;</div><div class='ctx'>     case VMEXIT_STGI:</div><div class='add'>+        svm_vmexit_do_stgi(regs, v);</div><div class='add'>+        break;</div><div class='ctx'>     case VMEXIT_CLGI:</div><div class='add'>+        svm_vmexit_do_clgi(regs, v);</div><div class='add'>+        break;</div><div class='ctx'>     case VMEXIT_SKINIT:</div><div class='del'>-        hvm_inject_exception(TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE, 0);</div><div class='add'>+        hvm_inject_hw_exception(TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE);</div><div class='add'>+        break;</div><div class='add'>+</div><div class='add'>+    case VMEXIT_XSETBV:</div><div class='add'>+        if ( (inst_len = __get_instruction_length(current, INSTR_XSETBV))==0 )</div><div class='add'>+            break;</div><div class='add'>+        if ( hvm_handle_xsetbv(regs-&gt;ecx,</div><div class='add'>+                               (regs-&gt;rdx &lt;&lt; 32) | regs-&gt;_eax) == 0 )</div><div class='add'>+            __update_guest_eip(regs, inst_len);</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='ctx'>     case VMEXIT_NPF:</div><div class='ctx'>         perfc_incra(svmexits, VMEXIT_NPF_PERFC);</div><div class='del'>-        regs-&gt;error_code = vmcb-&gt;exitinfo1;</div><div class='del'>-        svm_do_nested_pgfault(vmcb-&gt;exitinfo2);</div><div class='add'>+        if ( cpu_has_svm_decode )</div><div class='add'>+            v-&gt;arch.hvm_svm.cached_insn_len = vmcb-&gt;guest_ins_len &amp; 0xf;</div><div class='add'>+        svm_do_nested_pgfault(v, regs, vmcb-&gt;exitinfo1, vmcb-&gt;exitinfo2);</div><div class='add'>+        v-&gt;arch.hvm_svm.cached_insn_len = 0;</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='del'>-    case VMEXIT_IRET:</div><div class='add'>+    case VMEXIT_IRET: {</div><div class='add'>+        u32 general1_intercepts = vmcb_get_general1_intercepts(vmcb);</div><div class='add'>+</div><div class='ctx'>         /*</div><div class='ctx'>          * IRET clears the NMI mask. However because we clear the mask</div><div class='ctx'>          * /before/ executing IRET, we set the interrupt shadow to prevent</div><div class='hunk'>@@ -1518,43 +2434,51 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)</div><div class='ctx'>          * may inject an NMI before the NMI handler's IRET instruction is</div><div class='ctx'>          * retired.</div><div class='ctx'>          */</div><div class='del'>-        vmcb-&gt;general1_intercepts &amp;= ~GENERAL1_INTERCEPT_IRET;</div><div class='add'>+        general1_intercepts &amp;= ~GENERAL1_INTERCEPT_IRET;</div><div class='ctx'>         vmcb-&gt;interrupt_shadow = 1;</div><div class='add'>+</div><div class='add'>+        vmcb_set_general1_intercepts(vmcb, general1_intercepts);</div><div class='ctx'>         break;</div><div class='add'>+    }</div><div class='ctx'> </div><div class='ctx'>     case VMEXIT_PAUSE:</div><div class='del'>-        /*</div><div class='del'>-         * The guest is running a contended spinlock and we've detected it.</div><div class='del'>-         * Do something useful, like reschedule the guest</div><div class='del'>-         */</div><div class='del'>-        perfc_incr(pauseloop_exits);</div><div class='del'>-        do_sched_op_compat(SCHEDOP_yield, 0);</div><div class='add'>+        svm_vmexit_do_pause(regs);</div><div class='ctx'>         break;</div><div class='ctx'> </div><div class='ctx'>     default:</div><div class='ctx'>     exit_and_crash:</div><div class='del'>-        gdprintk(XENLOG_ERR, "unexpected VMEXIT: exit reason = 0x%x, "</div><div class='del'>-                 "exitinfo1 = %"PRIx64", exitinfo2 = %"PRIx64"\n",</div><div class='add'>+        gdprintk(XENLOG_ERR, "unexpected VMEXIT: exit reason = %#"PRIx64", "</div><div class='add'>+                 "exitinfo1 = %#"PRIx64", exitinfo2 = %#"PRIx64"\n",</div><div class='ctx'>                  exit_reason, </div><div class='ctx'>                  (u64)vmcb-&gt;exitinfo1, (u64)vmcb-&gt;exitinfo2);</div><div class='ctx'>         domain_crash(v-&gt;domain);</div><div class='ctx'>         break;</div><div class='ctx'>     }</div><div class='ctx'> </div><div class='add'>+  out:</div><div class='add'>+    if ( vcpu_guestmode )</div><div class='add'>+        /* Don't clobber TPR of the nested guest. */</div><div class='add'>+        return;</div><div class='add'>+</div><div class='ctx'>     /* The exit may have updated the TPR: reflect this in the hardware vtpr */</div><div class='del'>-    vmcb-&gt;vintr.fields.tpr = </div><div class='add'>+    intr = vmcb_get_vintr(vmcb);</div><div class='add'>+    intr.fields.tpr =</div><div class='ctx'>         (vlapic_get_reg(vcpu_vlapic(v), APIC_TASKPRI) &amp; 0xFF) &gt;&gt; 4;</div><div class='add'>+    vmcb_set_vintr(vmcb, intr);</div><div class='ctx'> }</div><div class='ctx'> </div><div class='del'>-asmlinkage void svm_trace_vmentry(void)</div><div class='add'>+void svm_trace_vmentry(void)</div><div class='ctx'> {</div><div class='del'>-    HVMTRACE_ND (VMENTRY, 1/*cycles*/, 0, 0, 0, 0, 0, 0, 0);</div><div class='add'>+    struct vcpu *curr = current;</div><div class='add'>+    HVMTRACE_ND(VMENTRY,</div><div class='add'>+                nestedhvm_vcpu_in_guestmode(curr) ? TRC_HVM_NESTEDFLAG : 0,</div><div class='add'>+                1/*cycles*/, 0, 0, 0, 0, 0, 0, 0);</div><div class='ctx'> }</div><div class='ctx'>   </div><div class='ctx'> /*</div><div class='ctx'>  * Local variables:</div><div class='ctx'>  * mode: C</div><div class='del'>- * c-set-style: "BSD"</div><div class='add'>+ * c-file-style: "BSD"</div><div class='ctx'>  * c-basic-offset: 4</div><div class='ctx'>  * tab-width: 4</div><div class='ctx'>  * indent-tabs-mode: nil</div></td></tr></table></div> <!-- class=content -->
<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.2.3</a> (<a href='https://git-scm.com/'>git 2.25.1</a>) at 2026-02-22 12:16:21 +0000</div>
</div> <!-- id=cgit -->
</body>
</html>
