diff options
author | Avi Kivity <avi@redhat.com> | 2011-11-10 07:57:24 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-12-27 04:24:37 -0500 |
commit | 332b56e4841ef62db4dbf1b4b92195575e1c7338 (patch) | |
tree | 11240229fa71468e7b8d2e3d617c3c45468f0a98 /arch/x86/kvm | |
parent | 022cd0e84020eec8b589bc119699c935c7b29584 (diff) |
KVM: SVM: Intercept RDPMC
Intercept RDPMC and forward it to the PMU emulation code.
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r-- | arch/x86/kvm/svm.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index e32243eac2f4..5fa553babe56 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -1014,6 +1014,7 @@ static void init_vmcb(struct vcpu_svm *svm) | |||
1014 | set_intercept(svm, INTERCEPT_NMI); | 1014 | set_intercept(svm, INTERCEPT_NMI); |
1015 | set_intercept(svm, INTERCEPT_SMI); | 1015 | set_intercept(svm, INTERCEPT_SMI); |
1016 | set_intercept(svm, INTERCEPT_SELECTIVE_CR0); | 1016 | set_intercept(svm, INTERCEPT_SELECTIVE_CR0); |
1017 | set_intercept(svm, INTERCEPT_RDPMC); | ||
1017 | set_intercept(svm, INTERCEPT_CPUID); | 1018 | set_intercept(svm, INTERCEPT_CPUID); |
1018 | set_intercept(svm, INTERCEPT_INVD); | 1019 | set_intercept(svm, INTERCEPT_INVD); |
1019 | set_intercept(svm, INTERCEPT_HLT); | 1020 | set_intercept(svm, INTERCEPT_HLT); |
@@ -2770,6 +2771,19 @@ static int emulate_on_interception(struct vcpu_svm *svm) | |||
2770 | return emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE; | 2771 | return emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE; |
2771 | } | 2772 | } |
2772 | 2773 | ||
2774 | static int rdpmc_interception(struct vcpu_svm *svm) | ||
2775 | { | ||
2776 | int err; | ||
2777 | |||
2778 | if (!static_cpu_has(X86_FEATURE_NRIPS)) | ||
2779 | return emulate_on_interception(svm); | ||
2780 | |||
2781 | err = kvm_rdpmc(&svm->vcpu); | ||
2782 | kvm_complete_insn_gp(&svm->vcpu, err); | ||
2783 | |||
2784 | return 1; | ||
2785 | } | ||
2786 | |||
2773 | bool check_selective_cr0_intercepted(struct vcpu_svm *svm, unsigned long val) | 2787 | bool check_selective_cr0_intercepted(struct vcpu_svm *svm, unsigned long val) |
2774 | { | 2788 | { |
2775 | unsigned long cr0 = svm->vcpu.arch.cr0; | 2789 | unsigned long cr0 = svm->vcpu.arch.cr0; |
@@ -3190,6 +3204,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm) = { | |||
3190 | [SVM_EXIT_SMI] = nop_on_interception, | 3204 | [SVM_EXIT_SMI] = nop_on_interception, |
3191 | [SVM_EXIT_INIT] = nop_on_interception, | 3205 | [SVM_EXIT_INIT] = nop_on_interception, |
3192 | [SVM_EXIT_VINTR] = interrupt_window_interception, | 3206 | [SVM_EXIT_VINTR] = interrupt_window_interception, |
3207 | [SVM_EXIT_RDPMC] = rdpmc_interception, | ||
3193 | [SVM_EXIT_CPUID] = cpuid_interception, | 3208 | [SVM_EXIT_CPUID] = cpuid_interception, |
3194 | [SVM_EXIT_IRET] = iret_interception, | 3209 | [SVM_EXIT_IRET] = iret_interception, |
3195 | [SVM_EXIT_INVD] = emulate_on_interception, | 3210 | [SVM_EXIT_INVD] = emulate_on_interception, |