diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kvm/svm.c | 56 |
1 files changed, 40 insertions, 16 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 5abaa5b2f624..d84f6a7c2bc5 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -2745,6 +2745,30 @@ static int cr0_write_interception(struct vcpu_svm *svm) | |||
2745 | return r; | 2745 | return r; |
2746 | } | 2746 | } |
2747 | 2747 | ||
2748 | static int dr_interception(struct vcpu_svm *svm) | ||
2749 | { | ||
2750 | int reg, dr; | ||
2751 | unsigned long val; | ||
2752 | int err; | ||
2753 | |||
2754 | if (!boot_cpu_has(X86_FEATURE_DECODEASSISTS)) | ||
2755 | return emulate_on_interception(svm); | ||
2756 | |||
2757 | reg = svm->vmcb->control.exit_info_1 & SVM_EXITINFO_REG_MASK; | ||
2758 | dr = svm->vmcb->control.exit_code - SVM_EXIT_READ_DR0; | ||
2759 | |||
2760 | if (dr >= 16) { /* mov to DRn */ | ||
2761 | val = kvm_register_read(&svm->vcpu, reg); | ||
2762 | kvm_set_dr(&svm->vcpu, dr - 16, val); | ||
2763 | } else { | ||
2764 | err = kvm_get_dr(&svm->vcpu, dr, &val); | ||
2765 | if (!err) | ||
2766 | kvm_register_write(&svm->vcpu, reg, val); | ||
2767 | } | ||
2768 | |||
2769 | return 1; | ||
2770 | } | ||
2771 | |||
2748 | static int cr8_write_interception(struct vcpu_svm *svm) | 2772 | static int cr8_write_interception(struct vcpu_svm *svm) |
2749 | { | 2773 | { |
2750 | struct kvm_run *kvm_run = svm->vcpu.run; | 2774 | struct kvm_run *kvm_run = svm->vcpu.run; |
@@ -3010,22 +3034,22 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm) = { | |||
3010 | [SVM_EXIT_WRITE_CR3] = cr_interception, | 3034 | [SVM_EXIT_WRITE_CR3] = cr_interception, |
3011 | [SVM_EXIT_WRITE_CR4] = cr_interception, | 3035 | [SVM_EXIT_WRITE_CR4] = cr_interception, |
3012 | [SVM_EXIT_WRITE_CR8] = cr8_write_interception, | 3036 | [SVM_EXIT_WRITE_CR8] = cr8_write_interception, |
3013 | [SVM_EXIT_READ_DR0] = emulate_on_interception, | 3037 | [SVM_EXIT_READ_DR0] = dr_interception, |
3014 | [SVM_EXIT_READ_DR1] = emulate_on_interception, | 3038 | [SVM_EXIT_READ_DR1] = dr_interception, |
3015 | [SVM_EXIT_READ_DR2] = emulate_on_interception, | 3039 | [SVM_EXIT_READ_DR2] = dr_interception, |
3016 | [SVM_EXIT_READ_DR3] = emulate_on_interception, | 3040 | [SVM_EXIT_READ_DR3] = dr_interception, |
3017 | [SVM_EXIT_READ_DR4] = emulate_on_interception, | 3041 | [SVM_EXIT_READ_DR4] = dr_interception, |
3018 | [SVM_EXIT_READ_DR5] = emulate_on_interception, | 3042 | [SVM_EXIT_READ_DR5] = dr_interception, |
3019 | [SVM_EXIT_READ_DR6] = emulate_on_interception, | 3043 | [SVM_EXIT_READ_DR6] = dr_interception, |
3020 | [SVM_EXIT_READ_DR7] = emulate_on_interception, | 3044 | [SVM_EXIT_READ_DR7] = dr_interception, |
3021 | [SVM_EXIT_WRITE_DR0] = emulate_on_interception, | 3045 | [SVM_EXIT_WRITE_DR0] = dr_interception, |
3022 | [SVM_EXIT_WRITE_DR1] = emulate_on_interception, | 3046 | [SVM_EXIT_WRITE_DR1] = dr_interception, |
3023 | [SVM_EXIT_WRITE_DR2] = emulate_on_interception, | 3047 | [SVM_EXIT_WRITE_DR2] = dr_interception, |
3024 | [SVM_EXIT_WRITE_DR3] = emulate_on_interception, | 3048 | [SVM_EXIT_WRITE_DR3] = dr_interception, |
3025 | [SVM_EXIT_WRITE_DR4] = emulate_on_interception, | 3049 | [SVM_EXIT_WRITE_DR4] = dr_interception, |
3026 | [SVM_EXIT_WRITE_DR5] = emulate_on_interception, | 3050 | [SVM_EXIT_WRITE_DR5] = dr_interception, |
3027 | [SVM_EXIT_WRITE_DR6] = emulate_on_interception, | 3051 | [SVM_EXIT_WRITE_DR6] = dr_interception, |
3028 | [SVM_EXIT_WRITE_DR7] = emulate_on_interception, | 3052 | [SVM_EXIT_WRITE_DR7] = dr_interception, |
3029 | [SVM_EXIT_EXCP_BASE + DB_VECTOR] = db_interception, | 3053 | [SVM_EXIT_EXCP_BASE + DB_VECTOR] = db_interception, |
3030 | [SVM_EXIT_EXCP_BASE + BP_VECTOR] = bp_interception, | 3054 | [SVM_EXIT_EXCP_BASE + BP_VECTOR] = bp_interception, |
3031 | [SVM_EXIT_EXCP_BASE + UD_VECTOR] = ud_interception, | 3055 | [SVM_EXIT_EXCP_BASE + UD_VECTOR] = ud_interception, |