diff options
| -rw-r--r-- | arch/x86/kvm/svm.c | 132 |
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 | ||
| 2927 | static bool nested_svm_vmrun(struct vcpu_svm *svm) | 2927 | static 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 | |||
| 3024 | static 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 | } |
