aboutsummaryrefslogtreecommitdiff
path: root/target/i386/svm_helper.c
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@siemens.com>2018-06-30 08:08:23 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2018-07-02 15:41:18 +0200
commitfe441054bb3f0c75ff23335790342c0408e11c3a (patch)
tree4c33bcd58c69d2a1dc66ba3f10d98e3108976195 /target/i386/svm_helper.c
parent76b004d10da09bb77a4343edf7b98b2d662fb4f2 (diff)
target-i386: Add NPT support
This implements NPT suport for SVM by hooking into x86_cpu_handle_mmu_fault where it reads the stage-1 page table. Whether we need to perform this 2nd stage translation, and how, is decided during vmrun and stored in hflags2, along with nested_cr3 and nested_pg_mode. As get_hphys performs a direct cpu_vmexit in case of NPT faults, we need retaddr in that function. To avoid changing the signature of cpu_handle_mmu_fault, this passes the value from tlb_fill to get_hphys via the CPU state. This was tested successfully via the Jailhouse hypervisor. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Message-Id: <567473a0-6005-5843-4c73-951f476085ca@web.de> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'target/i386/svm_helper.c')
-rw-r--r--target/i386/svm_helper.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/target/i386/svm_helper.c b/target/i386/svm_helper.c
index f245aec310..342ece082f 100644
--- a/target/i386/svm_helper.c
+++ b/target/i386/svm_helper.c
@@ -124,6 +124,7 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
{
CPUState *cs = CPU(x86_env_get_cpu(env));
target_ulong addr;
+ uint64_t nested_ctl;
uint32_t event_inj;
uint32_t int_ctl;
@@ -206,6 +207,26 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
control.intercept_exceptions
));
+ nested_ctl = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
+ control.nested_ctl));
+ if (nested_ctl & SVM_NPT_ENABLED) {
+ env->nested_cr3 = x86_ldq_phys(cs,
+ env->vm_vmcb + offsetof(struct vmcb,
+ control.nested_cr3));
+ env->hflags2 |= HF2_NPT_MASK;
+
+ env->nested_pg_mode = 0;
+ if (env->cr[4] & CR4_PAE_MASK) {
+ env->nested_pg_mode |= SVM_NPT_PAE;
+ }
+ if (env->hflags & HF_LMA_MASK) {
+ env->nested_pg_mode |= SVM_NPT_LMA;
+ }
+ if (env->efer & MSR_EFER_NXE) {
+ env->nested_pg_mode |= SVM_NPT_NXE;
+ }
+ }
+
/* enable intercepts */
env->hflags |= HF_SVMI_MASK;
@@ -616,6 +637,7 @@ void do_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
x86_stl_phys(cs,
env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0);
}
+ env->hflags2 &= ~HF2_NPT_MASK;
/* Save the VM state in the vmcb */
svm_save_seg(env, env->vm_vmcb + offsetof(struct vmcb, save.es),