From patchwork Mon Feb 15 18:17:17 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 79447 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o1FIHlNt015055 for ; Mon, 15 Feb 2010 18:17:48 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755873Ab0BOSRh (ORCPT ); Mon, 15 Feb 2010 13:17:37 -0500 Received: from david.siemens.de ([192.35.17.14]:24974 "EHLO david.siemens.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755787Ab0BOSRh (ORCPT ); Mon, 15 Feb 2010 13:17:37 -0500 Received: from mail2.siemens.de (localhost [127.0.0.1]) by david.siemens.de (8.12.11.20060308/8.12.11) with ESMTP id o1FIHJPk020940; Mon, 15 Feb 2010 19:17:19 +0100 Received: from localhost.localdomain (mchn012c.mchp.siemens.de [139.25.109.167] (may be forged)) by mail2.siemens.de (8.12.11.20060308/8.12.11) with ESMTP id o1FIHIqZ013529; Mon, 15 Feb 2010 19:17:19 +0100 From: Jan Kiszka To: Avi Kivity , Marcelo Tosatti Cc: kvm , Gleb Natapov Subject: [PATCH 1/2] KVM: SVM: Emulate nRIP feature when reinjecting INT3 Date: Mon, 15 Feb 2010 19:17:17 +0100 Message-Id: <79170b70424440dfbede5b6eac85f734aa8785e8.1266257833.git.jan.kiszka@siemens.com> X-Mailer: git-send-email 1.6.0.2 In-Reply-To: References: In-Reply-To: References: Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Mon, 15 Feb 2010 18:17:48 +0000 (UTC) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 52f78dd..f63f1db 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -46,6 +46,7 @@ MODULE_LICENSE("GPL"); #define SVM_FEATURE_NPT (1 << 0) #define SVM_FEATURE_LBRV (1 << 1) #define SVM_FEATURE_SVML (1 << 2) +#define SVM_FEATURE_NRIP (1 << 3) #define SVM_FEATURE_PAUSE_FILTER (1 << 10) #define NESTED_EXIT_HOST 0 /* Exit handled on host level */ @@ -109,6 +110,8 @@ struct vcpu_svm { struct nested_state nested; bool nmi_singlestep; + + bool int3_injected; }; /* enable NPT for AMD64 and X86 with PAE */ @@ -234,23 +237,6 @@ static void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) vcpu->arch.efer = efer; } -static void svm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr, - bool has_error_code, u32 error_code) -{ - struct vcpu_svm *svm = to_svm(vcpu); - - /* If we are within a nested VM we'd better #VMEXIT and let the - guest handle the exception */ - if (nested_svm_check_exception(svm, nr, has_error_code, error_code)) - return; - - svm->vmcb->control.event_inj = nr - | SVM_EVTINJ_VALID - | (has_error_code ? SVM_EVTINJ_VALID_ERR : 0) - | SVM_EVTINJ_TYPE_EXEPT; - svm->vmcb->control.event_inj_err = error_code; -} - static int is_external_interrupt(u32 info) { info &= SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID; @@ -296,6 +282,36 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu) svm_set_interrupt_shadow(vcpu, 0); } +static void svm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr, + bool has_error_code, u32 error_code) +{ + struct vcpu_svm *svm = to_svm(vcpu); + + /* If we are within a nested VM we'd better #VMEXIT and let the + guest handle the exception */ + if (nested_svm_check_exception(svm, nr, has_error_code, error_code)) + return; + + if (nr == BP_VECTOR && !svm_has(SVM_FEATURE_NRIP)) { + /* + * For guest debugging where we have to reinject #BP if some + * INT3 is guest-owned: + * Emulate nRIP by moving RIP one forward. Will fail if + * injection raises a fault that is not intercepted. Still + * better than failing in all cases. + */ + svm->next_rip = kvm_rip_read(&svm->vcpu) + 1; + skip_emulated_instruction(&svm->vcpu); + svm->int3_injected = true; + } + + svm->vmcb->control.event_inj = nr + | SVM_EVTINJ_VALID + | (has_error_code ? SVM_EVTINJ_VALID_ERR : 0) + | SVM_EVTINJ_TYPE_EXEPT; + svm->vmcb->control.event_inj_err = error_code; +} + static int has_svm(void) { const char *msg; @@ -2653,6 +2669,9 @@ static void svm_complete_interrupts(struct vcpu_svm *svm) if (is_nested(svm)) break; if (kvm_exception_is_soft(vector)) + if (vector == BP_VECTOR && svm->int3_injected) + kvm_rip_write(&svm->vcpu, + kvm_rip_read(&svm->vcpu) - 1); break; if (exitintinfo & SVM_EXITINTINFO_VALID_ERR) { u32 err = svm->vmcb->control.exit_int_info_err; @@ -2667,6 +2686,7 @@ static void svm_complete_interrupts(struct vcpu_svm *svm) default: break; } + svm->int3_injected =false; } #ifdef CONFIG_X86_64