aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kvm/svm.c132
1 files changed, 69 insertions, 63 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index e3c61a32249d..6edefabd5a82 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2924,70 +2924,9 @@ static bool nested_vmcb_checks(struct vmcb *vmcb)
2924 return true; 2924 return true;
2925} 2925}
2926 2926
2927static bool nested_svm_vmrun(struct vcpu_svm *svm) 2927static void enter_svm_guest_mode(struct vcpu_svm *svm, u64 vmcb_gpa,
2928 struct vmcb *nested_vmcb, struct page *page)
2928{ 2929{
2929 struct vmcb *nested_vmcb;
2930 struct vmcb *hsave = svm->nested.hsave;
2931 struct vmcb *vmcb = svm->vmcb;
2932 struct page *page;
2933 u64 vmcb_gpa;
2934
2935 vmcb_gpa = svm->vmcb->save.rax;
2936
2937 nested_vmcb = nested_svm_map(svm, svm->vmcb->save.rax, &page);
2938 if (!nested_vmcb)
2939 return false;
2940
2941 if (!nested_vmcb_checks(nested_vmcb)) {
2942 nested_vmcb->control.exit_code = SVM_EXIT_ERR;
2943 nested_vmcb->control.exit_code_hi = 0;
2944 nested_vmcb->control.exit_info_1 = 0;
2945 nested_vmcb->control.exit_info_2 = 0;
2946
2947 nested_svm_unmap(page);
2948
2949 return false;
2950 }
2951
2952 trace_kvm_nested_vmrun(svm->vmcb->save.rip, vmcb_gpa,
2953 nested_vmcb->save.rip,
2954 nested_vmcb->control.int_ctl,
2955 nested_vmcb->control.event_inj,
2956 nested_vmcb->control.nested_ctl);
2957
2958 trace_kvm_nested_intercepts(nested_vmcb->control.intercept_cr & 0xffff,
2959 nested_vmcb->control.intercept_cr >> 16,
2960 nested_vmcb->control.intercept_exceptions,
2961 nested_vmcb->control.intercept);
2962
2963 /* Clear internal status */
2964 kvm_clear_exception_queue(&svm->vcpu);
2965 kvm_clear_interrupt_queue(&svm->vcpu);
2966
2967 /*
2968 * Save the old vmcb, so we don't need to pick what we save, but can
2969 * restore everything when a VMEXIT occurs
2970 */
2971 hsave->save.es = vmcb->save.es;
2972 hsave->save.cs = vmcb->save.cs;
2973 hsave->save.ss = vmcb->save.ss;
2974 hsave->save.ds = vmcb->save.ds;
2975 hsave->save.gdtr = vmcb->save.gdtr;
2976 hsave->save.idtr = vmcb->save.idtr;
2977 hsave->save.efer = svm->vcpu.arch.efer;
2978 hsave->save.cr0 = kvm_read_cr0(&svm->vcpu);
2979 hsave->save.cr4 = svm->vcpu.arch.cr4;
2980 hsave->save.rflags = kvm_get_rflags(&svm->vcpu);
2981 hsave->save.rip = kvm_rip_read(&svm->vcpu);
2982 hsave->save.rsp = vmcb->save.rsp;
2983 hsave->save.rax = vmcb->save.rax;
2984 if (npt_enabled)
2985 hsave->save.cr3 = vmcb->save.cr3;
2986 else
2987 hsave->save.cr3 = kvm_read_cr3(&svm->vcpu);
2988
2989 copy_vmcb_control_area(hsave, vmcb);
2990
2991 if (kvm_get_rflags(&svm->vcpu) & X86_EFLAGS_IF) 2930 if (kvm_get_rflags(&svm->vcpu) & X86_EFLAGS_IF)
2992 svm->vcpu.arch.hflags |= HF_HIF_MASK; 2931 svm->vcpu.arch.hflags |= HF_HIF_MASK;
2993 else 2932 else
@@ -3080,6 +3019,73 @@ static bool nested_svm_vmrun(struct vcpu_svm *svm)
3080 enable_gif(svm); 3019 enable_gif(svm);
3081 3020
3082 mark_all_dirty(svm->vmcb); 3021 mark_all_dirty(svm->vmcb);
3022}
3023
3024static bool nested_svm_vmrun(struct vcpu_svm *svm)
3025{
3026 struct vmcb *nested_vmcb;
3027 struct vmcb *hsave = svm->nested.hsave;
3028 struct vmcb *vmcb = svm->vmcb;
3029 struct page *page;
3030 u64 vmcb_gpa;
3031
3032 vmcb_gpa = svm->vmcb->save.rax;
3033
3034 nested_vmcb = nested_svm_map(svm, svm->vmcb->save.rax, &page);
3035 if (!nested_vmcb)
3036 return false;
3037
3038 if (!nested_vmcb_checks(nested_vmcb)) {
3039 nested_vmcb->control.exit_code = SVM_EXIT_ERR;
3040 nested_vmcb->control.exit_code_hi = 0;
3041 nested_vmcb->control.exit_info_1 = 0;
3042 nested_vmcb->control.exit_info_2 = 0;
3043
3044 nested_svm_unmap(page);
3045
3046 return false;
3047 }
3048
3049 trace_kvm_nested_vmrun(svm->vmcb->save.rip, vmcb_gpa,
3050 nested_vmcb->save.rip,
3051 nested_vmcb->control.int_ctl,
3052 nested_vmcb->control.event_inj,
3053 nested_vmcb->control.nested_ctl);
3054
3055 trace_kvm_nested_intercepts(nested_vmcb->control.intercept_cr & 0xffff,
3056 nested_vmcb->control.intercept_cr >> 16,
3057 nested_vmcb->control.intercept_exceptions,
3058 nested_vmcb->control.intercept);
3059
3060 /* Clear internal status */
3061 kvm_clear_exception_queue(&svm->vcpu);
3062 kvm_clear_interrupt_queue(&svm->vcpu);
3063
3064 /*
3065 * Save the old vmcb, so we don't need to pick what we save, but can
3066 * restore everything when a VMEXIT occurs
3067 */
3068 hsave->save.es = vmcb->save.es;
3069 hsave->save.cs = vmcb->save.cs;
3070 hsave->save.ss = vmcb->save.ss;
3071 hsave->save.ds = vmcb->save.ds;
3072 hsave->save.gdtr = vmcb->save.gdtr;
3073 hsave->save.idtr = vmcb->save.idtr;
3074 hsave->save.efer = svm->vcpu.arch.efer;
3075 hsave->save.cr0 = kvm_read_cr0(&svm->vcpu);
3076 hsave->save.cr4 = svm->vcpu.arch.cr4;
3077 hsave->save.rflags = kvm_get_rflags(&svm->vcpu);
3078 hsave->save.rip = kvm_rip_read(&svm->vcpu);
3079 hsave->save.rsp = vmcb->save.rsp;
3080 hsave->save.rax = vmcb->save.rax;
3081 if (npt_enabled)
3082 hsave->save.cr3 = vmcb->save.cr3;
3083 else
3084 hsave->save.cr3 = kvm_read_cr3(&svm->vcpu);
3085
3086 copy_vmcb_control_area(hsave, vmcb);
3087
3088 enter_svm_guest_mode(svm, vmcb_gpa, nested_vmcb, page);
3083 3089
3084 return true; 3090 return true;
3085} 3091}