From patchwork Fri Feb 7 10:36:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 11370213 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9F90A1398 for ; Fri, 7 Feb 2020 10:36:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7E0C72082E for ; Fri, 7 Feb 2020 10:36:34 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="HH+16w6b" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727254AbgBGKgd (ORCPT ); Fri, 7 Feb 2020 05:36:33 -0500 Received: from mail-pl1-f202.google.com ([209.85.214.202]:36379 "EHLO mail-pl1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726899AbgBGKgc (ORCPT ); Fri, 7 Feb 2020 05:36:32 -0500 Received: by mail-pl1-f202.google.com with SMTP id bg1so1075310plb.3 for ; Fri, 07 Feb 2020 02:36:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=7R/dzs2gX8j/iAzEk3ko1uOJm0nEa/ipr/WpACBTbQQ=; b=HH+16w6bSh9kJgwLw/eGP3tT64ip677kQ/rI6KBT1ztBNMY2LuPcn2EtSKmypceuLl XHENXp7zLTq1c9REd5bT4rau+b2DJ4Yds7NZUL9N5w4fnzwGEhWweqg8ZPhU+u6/jEXh 0+qlLVbepZGF4vKYOHbjOkVmB/bYMCCTMcPX7pgn9F1OZWeuoqq7KcAVsI6DkZ0fUW78 cIWFlEPvnCilWFzZY/idDIrIm/63njmUVxk563HSJ/1KR6b2DTunGb3XPtQDaSdZPObi 5XWiB5WvTCdP9M0BafRbFWWoDrlYsvvN0/4tiqU76L2mSj//P5tkk5iunbk3glXQnIOA m4WQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=7R/dzs2gX8j/iAzEk3ko1uOJm0nEa/ipr/WpACBTbQQ=; b=KF1k9W/X/JtBB9slzq+rziYgYi+QdAsI4ZT86la8ie0KEJKfFY2nWyZOALEdZZ6wgY dPgKAmkrj5r2TqdImJJ6MQoARlNFrOYI9Qj/plZb3mrqrLpPhJuFtS653PD9RIvB+Lwg oacdFgooJ8ULM8QodEKRkPdrjuU9m7rMchOIKXJ5FCVDnE9YoM1MBbTO36UEsEcOEZPf 7XDNAwpNC/XKiXVWJo0BRyGKU4OQjOs0XM0e6ngmrVSfBxS2UErB6Xrk5H+zdclVbdMu iL/UuvwjfxSDHB6Be2JBGUMQLZ+mfJp0gQpOly9cGq3FGosrU+KKjQoL7JZYGqN4gI/f iqpw== X-Gm-Message-State: APjAAAWZFamgacBGTTr2BGleFO1VlRyGYskfLC4SPD+XaJwGATpiHn9x RG+T5b57/lt1KdvTQLaRZeTKghcyGmrov3KBmH495SWOur6HTKjKmaMfPQkAQiFhV/8Gc8kIcaS 9w1ws3OAE6XA0tSyoSjttHF2F/Cj62X5JiLglF/BDbo4/QDwElI+HRhCdxw== X-Google-Smtp-Source: APXvYqxrN9GobmXw/X8Yt4hU6wKnPvXV97gls1jHqsBkjRGKq2QvqKN6fJ7klMWLTemuQP9hEwwiZNI+oHM= X-Received: by 2002:a63:7454:: with SMTP id e20mr8820602pgn.192.1581071790694; Fri, 07 Feb 2020 02:36:30 -0800 (PST) Date: Fri, 7 Feb 2020 02:36:04 -0800 In-Reply-To: <20200207103608.110305-1-oupton@google.com> Message-Id: <20200207103608.110305-2-oupton@google.com> Mime-Version: 1.0 References: <20200207103608.110305-1-oupton@google.com> X-Mailer: git-send-email 2.25.0.341.g760bfbb309-goog Subject: [PATCH v3 1/5] KVM: x86: Mask off reserved bit from #DB exception payload From: Oliver Upton To: kvm@vger.kernel.org Cc: Paolo Bonzini , Jim Mattson , Peter Shier , Sean Christopherson , Oliver Upton Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org KVM defines the #DB payload as compatible with the 'pending debug exceptions' field under VMX, not DR6. Mask off bit 12 when applying the payload to DR6, as it is reserved on DR6 but not the 'pending debug exceptions' field. Fixes: f10c729ff965 ("kvm: vmx: Defer setting of DR6 until #DB delivery") Signed-off-by: Oliver Upton --- arch/x86/kvm/x86.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index fbabb2f06273..95b753dab207 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -438,6 +438,14 @@ void kvm_deliver_exception_payload(struct kvm_vcpu *vcpu) * for #DB exceptions under VMX. */ vcpu->arch.dr6 ^= payload & DR6_RTM; + + /* + * The #DB payload is defined as compatible with the 'pending + * debug exceptions' field under VMX, not DR6. While bit 12 is + * defined in the 'pending debug exceptions' field (enabled + * breakpoint), it is reserved and must be zero in DR6. + */ + vcpu->arch.dr6 &= ~BIT(12); break; case PF_VECTOR: vcpu->arch.cr2 = payload; From patchwork Fri Feb 7 10:36:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 11370215 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AE20D1398 for ; Fri, 7 Feb 2020 10:36:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8D2D6217BA for ; Fri, 7 Feb 2020 10:36:36 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="o25Kgm1k" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727317AbgBGKgf (ORCPT ); Fri, 7 Feb 2020 05:36:35 -0500 Received: from mail-pj1-f74.google.com ([209.85.216.74]:53333 "EHLO mail-pj1-f74.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727289AbgBGKgf (ORCPT ); Fri, 7 Feb 2020 05:36:35 -0500 Received: by mail-pj1-f74.google.com with SMTP id h6so1052308pju.3 for ; Fri, 07 Feb 2020 02:36:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=k7kvp2Q+X5KKtfSI8p1ZPpCKg5nn6Yhdzbm1PfKGtkY=; b=o25Kgm1kmvf6F3mjEiIhA6Pl4jji6+z1cg7UB4hFy4w8nVJ2tZlS+Pq6zICFwIXm11 TxHs/MWmO+HlU18zXGwMbTzPdBQKoHvBsCyw0lf8J17+n1gQDOCMCDRrvfKldu5Z4q0m uNcyN7jATMxzFMkfNW0KMDup7fB0jAAmxka3pen8ERi1xpBIBoBxApNNRarMCPH2jRxr TNsjIR4yPHEFpzC/S7LTF3+SBAsQln+sZ0mVECY3caf1te3/oHFirT9pGic1/yU4RiXz KqE0TK6EXg+hm6Ky6F1QzPxJKACrZzKCcSXouJ6jwtch7/001jaOEjMVuO2bFnj5KUqo 9iNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=k7kvp2Q+X5KKtfSI8p1ZPpCKg5nn6Yhdzbm1PfKGtkY=; b=N/ZgP+0MkteY9bdN9pln8qf7PtJk/BWXK/1vTZiLJNTUpVChc1z5GnWGNRxri8AgNE zIkH0iqWMUw/LabyMQlodFZn+mjZ8ju45U5YqcmMuGRqPGAGnnCO7bwxHqREkhTgVvf8 qUeREkndlCPb1+CzISKmdVuN3bNk7CfoBWOqhbRkMG2XU2KG5oBGHmfDNyuSOUG7mhtt nrua4tY/WMRTyIZYa8WPccomypsxvWosE29F+um9WJm6iOUWzjnKmYXHXzWny+WHJrl0 AsooeaRBekCjjK+cU/DtZ/bs4kJMEl8TNnhH31CXbWut0U2l4gMAqnk2Ag+VhDRAmlyW DtrA== X-Gm-Message-State: APjAAAUVcEYR3diAzfLgOv3DgPFFFRKoRkqqH1RLYqiaC4QtF27z0RXA t+Memkf9cSBby4Oi2hU41/FtrzHk8WucSHxcIJs5TYrYr0fMcULBm+RkGCMx3tGQeEUl/+6eA4G Aa76i00e2toY+hPAlVxj3NuyeJChunLXUpLXJiF0VL4MQQ5gupXuOACAR1g== X-Google-Smtp-Source: APXvYqwbgewb6DSXLk2Ht/rqknjGlGwBTjE7AjqfGaEEzJcv/T0jPL0snVAg7XB1JDxR6vPX0aegW07hmcg= X-Received: by 2002:a63:7145:: with SMTP id b5mr8577044pgn.409.1581071792911; Fri, 07 Feb 2020 02:36:32 -0800 (PST) Date: Fri, 7 Feb 2020 02:36:05 -0800 In-Reply-To: <20200207103608.110305-1-oupton@google.com> Message-Id: <20200207103608.110305-3-oupton@google.com> Mime-Version: 1.0 References: <20200207103608.110305-1-oupton@google.com> X-Mailer: git-send-email 2.25.0.341.g760bfbb309-goog Subject: [PATCH v3 2/5] KVM: nVMX: Handle pending #DB when injecting INIT VM-exit From: Oliver Upton To: kvm@vger.kernel.org Cc: Paolo Bonzini , Jim Mattson , Peter Shier , Sean Christopherson , Oliver Upton Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org SDM 27.3.4 states that the 'pending debug exceptions' VMCS field will be populated if a VM-exit caused by an INIT signal takes priority over a debug-trap. Emulate this behavior when synthesizing an INIT signal VM-exit into L1. Fixes: 4b9852f4f389 ("KVM: x86: Fix INIT signal handling in various CPU states") Signed-off-by: Oliver Upton --- arch/x86/kvm/vmx/nested.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 657c2eda357c..1586aaae3a6f 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -3575,6 +3575,33 @@ static void nested_vmx_inject_exception_vmexit(struct kvm_vcpu *vcpu, nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI, intr_info, exit_qual); } +/* + * Returns true if a debug trap is pending delivery. + * + * In KVM, debug traps bear an exception payload. As such, the class of a #DB + * exception may be inferred from the presence of an exception payload. + */ +static inline bool vmx_pending_dbg_trap(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.exception.pending && + vcpu->arch.exception.nr == DB_VECTOR && + vcpu->arch.exception.payload; +} + +/* + * Certain VM-exits set the 'pending debug exceptions' field to indicate a + * recognized #DB (data or single-step) that has yet to be delivered. Since KVM + * represents these debug traps with a payload that is said to be compatible + * with the 'pending debug exceptions' field, write the payload to the VMCS + * field if a VM-exit is delivered before the debug trap. + */ +static void nested_vmx_update_pending_dbg(struct kvm_vcpu *vcpu) +{ + if (vmx_pending_dbg_trap(vcpu)) + vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS, + vcpu->arch.exception.payload); +} + static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr) { struct vcpu_vmx *vmx = to_vmx(vcpu); @@ -3587,6 +3614,7 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr) test_bit(KVM_APIC_INIT, &apic->pending_events)) { if (block_nested_events) return -EBUSY; + nested_vmx_update_pending_dbg(vcpu); clear_bit(KVM_APIC_INIT, &apic->pending_events); nested_vmx_vmexit(vcpu, EXIT_REASON_INIT_SIGNAL, 0, 0); return 0; From patchwork Fri Feb 7 10:36:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 11370217 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6071C112B for ; Fri, 7 Feb 2020 10:36:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3FD1321741 for ; Fri, 7 Feb 2020 10:36:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="nOy8wb3S" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727372AbgBGKgg (ORCPT ); Fri, 7 Feb 2020 05:36:36 -0500 Received: from mail-pl1-f201.google.com ([209.85.214.201]:35070 "EHLO mail-pl1-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727309AbgBGKgf (ORCPT ); Fri, 7 Feb 2020 05:36:35 -0500 Received: by mail-pl1-f201.google.com with SMTP id v24so1073556plo.2 for ; Fri, 07 Feb 2020 02:36:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=vh3v3X1DXxF+Ymma2gVlAjTYvpcrxrg4caBobl2XuBU=; b=nOy8wb3STmb9+NTXzXL4gVt1ksnDKObSWEHFb/bMEX1W+7QiX60OGQ3AsLeMAoa23e lBd6Fd4R/YQOjXI0dliYsC5QTCjeX5Vs3UmDunMVKRNQDwaDqhEAPKZFU22CTz/WuLi2 UgSeq8K/EzfoUw3ojoeqKnmy8mP4x6F+R+d6Uw3o9onivthOyHLpBNxTjawELIomy/Qx Zb3kJJF2jyF03zSt0GvvKEAmVQnzJ3HrRhJk8VusvfyicJK//w997M5rkW2vBw8hBFo+ NyL8W8ijts6dUjCoPVldDdryDV9rNVv8vKOyehFK7XuenNK19Ruw2WjQ31A0+NuZbWmM 8xDw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=vh3v3X1DXxF+Ymma2gVlAjTYvpcrxrg4caBobl2XuBU=; b=hUu0LXTcFI8BPlQZkdpn7yKxdNt/rwm4zsfvyISOyTsEIRyk00Tini3ZdbdQ8j+QZ5 sF45u+TnA9jrMlDs4jeidTICiazmiDI3sopWv+UFCNgfwitDpg+z7saOaAdai7jsvxFr fXIUq2SmQ1W1kJ05374ja4S6wxux0KEnp3Q2tFPR6yaJGakTG3onp+AD9vrslST7Af/t WGuxV50kG14pt5LkufrglBekpuTCFMjrFcpYtglWXsiM8SeITj2UCJdQ8vcZGkoPdtaf BtAtd5jTojz55Lf/OjaHW0U4G+3vEdt5hj23o8jH8MrWdMPDaCsJV1sW3HCXiVKSEbkk GfyQ== X-Gm-Message-State: APjAAAWxPNsfvwVqDaq/zUhrxY+SkYszx5pkgHgCrGMvNUy1TmE01cFX E3LSL4oXANFjL48nYIvpEiuc0xxCnHTZ7e6We/YH0E7KS+KcqkxhYnOJYExvVcp89dJqFnfQTes r9f5I2foEaMpvlEVAFuZA9IcoyVMzJar9/4Qhf2Nq0n0IcZn3+MLpz3QB8g== X-Google-Smtp-Source: APXvYqyQmdX0vgN9Hz/XcyhzRAMGVrlh82fZQE0TAvBrq6kmg8w9Rhzss9eF0HTXSownGVtjUeqQUVYqnw0= X-Received: by 2002:a63:7a0f:: with SMTP id v15mr8668920pgc.139.1581071795043; Fri, 07 Feb 2020 02:36:35 -0800 (PST) Date: Fri, 7 Feb 2020 02:36:06 -0800 In-Reply-To: <20200207103608.110305-1-oupton@google.com> Message-Id: <20200207103608.110305-4-oupton@google.com> Mime-Version: 1.0 References: <20200207103608.110305-1-oupton@google.com> X-Mailer: git-send-email 2.25.0.341.g760bfbb309-goog Subject: [PATCH v3 3/5] KVM: x86: Deliver exception payload on KVM_GET_VCPU_EVENTS From: Oliver Upton To: kvm@vger.kernel.org Cc: Paolo Bonzini , Jim Mattson , Peter Shier , Sean Christopherson , Oliver Upton Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org KVM allows the deferral of exception payloads when a vCPU is in guest mode to allow the L1 hypervisor to intercept certain events (#PF, #DB) before register state has been modified. However, this behavior is incompatible with the KVM_{GET,SET}_VCPU_EVENTS ABI, as userspace expects register state to have been immediately modified. Userspace may opt-in for the payload deferral behavior with the KVM_CAP_EXCEPTION_PAYLOAD per-VM capability. As such, kvm_multiple_exception() will immediately manipulate guest registers if the capability hasn't been requested. Since the deferral is only necessary if a userspace ioctl were to be serviced at the same as a payload bearing exception is recognized, this behavior can be relaxed. Instead, opportunistically defer the payload from kvm_multiple_exception() and deliver the payload before completing a KVM_GET_VCPU_EVENTS ioctl. Signed-off-by: Oliver Upton --- arch/x86/kvm/x86.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 95b753dab207..4d3310df1758 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -498,19 +498,7 @@ static void kvm_multiple_exception(struct kvm_vcpu *vcpu, vcpu->arch.exception.error_code = error_code; vcpu->arch.exception.has_payload = has_payload; vcpu->arch.exception.payload = payload; - /* - * In guest mode, payload delivery should be deferred, - * so that the L1 hypervisor can intercept #PF before - * CR2 is modified (or intercept #DB before DR6 is - * modified under nVMX). However, for ABI - * compatibility with KVM_GET_VCPU_EVENTS and - * KVM_SET_VCPU_EVENTS, we can't delay payload - * delivery unless userspace has enabled this - * functionality via the per-VM capability, - * KVM_CAP_EXCEPTION_PAYLOAD. - */ - if (!vcpu->kvm->arch.exception_payload_enabled || - !is_guest_mode(vcpu)) + if (!is_guest_mode(vcpu)) kvm_deliver_exception_payload(vcpu); return; } @@ -3803,6 +3791,21 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu, { process_nmi(vcpu); + /* + * In guest mode, payload delivery should be deferred, + * so that the L1 hypervisor can intercept #PF before + * CR2 is modified (or intercept #DB before DR6 is + * modified under nVMX). Unless the per-VM capability, + * KVM_CAP_EXCEPTION_PAYLOAD, is set, we may not defer the delivery of + * an exception payload and handle after a KVM_GET_VCPU_EVENTS. Since we + * opportunistically defer the exception payload, deliver it if the + * capability hasn't been requested before processing a + * KVM_GET_VCPU_EVENTS. + */ + if (!vcpu->kvm->arch.exception_payload_enabled && + vcpu->arch.exception.pending && vcpu->arch.exception.has_payload) + kvm_deliver_exception_payload(vcpu); + /* * The API doesn't provide the instruction length for software * exceptions, so don't report them. As long as the guest RIP From patchwork Fri Feb 7 10:36:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 11370219 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 727EA1398 for ; Fri, 7 Feb 2020 10:36:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 47EB22082E for ; Fri, 7 Feb 2020 10:36:39 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="t20V/ONZ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727387AbgBGKgi (ORCPT ); Fri, 7 Feb 2020 05:36:38 -0500 Received: from mail-pl1-f201.google.com ([209.85.214.201]:40662 "EHLO mail-pl1-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726899AbgBGKgi (ORCPT ); Fri, 7 Feb 2020 05:36:38 -0500 Received: by mail-pl1-f201.google.com with SMTP id y2so1064425plt.7 for ; Fri, 07 Feb 2020 02:36:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=jDXvVWSrS9mz8kI8Ow4xbDhWn2NTLmsDo4fcKVe11AY=; b=t20V/ONZ3f9oQXpDG9DGKcSm/lcOV108bIStnYgFL10aWxMB6v54O0u18ayvd/dcBr 9GQt0W6WSPv3eSqtlp1dRsQvtng+RdruBHeStyIVMp33ERa0WTO3L7LRYLHjgrZFf05T k62+7E+V0Uby6AuxdGfiBiNwz7AkHqNXiQSkJxDbS81zTG+Kzkjn+qw+vg6D0Qc8ybV/ IpNjSzJVdvuHwBFJOc59g6mv8zwOP3mm8+XYkngyKO4Pz7+Tm0jZUz+clkmJGNV6Nf9a uETbLKJeg3YnffkdWiDTptC9y36eP3b4k+PsM89ZmCrgWKsD+ksJOGv1c9CxEUjju0tN XSvg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=jDXvVWSrS9mz8kI8Ow4xbDhWn2NTLmsDo4fcKVe11AY=; b=uEaqnYLtB9zwtqu8vzF/1JfLkg0jXJQkYgUZaWDHsldCqeiQTbeoYwZJLAb/4hO4P1 XuADsDLLYDKLw7TIMngHWlZbycG9Rdou6GmAFVnVUs9aT3wpV2r6Bvfe9Ry03eGuOccC 4STFUgW7gELo1rlnoM3tFWMRdfPyisTdahTtY12BxxhStJmZOWMChlPJRIRHmqq99Pqi QtOLq35vD//VTR31z2Dd3+5GfAnrKk0PG7amTPBn7NA0rpon6+ZSXsgt1Mn1RHRBDnnx XRgkcgY+8VWIeUWxII1SbBJRrsuXnmvFyymtUpPEUNLzFR9gh87RnQu9lnF1tBK/o2Ln J0FQ== X-Gm-Message-State: APjAAAWed0VnELO/Mhi5YnsxoSGBgTBWFZ6aFBO88uOv4TKGsQP3iyV2 /38ItmMcTuRY1S4R97KrkRlx5hH5OO7+N9bmiwMD9UalJPtbG/9mdvtRYnf1klmO2sTgq5NhRO8 +29uYrIwsYT8jE2ocOwP05j03faOWu27losjTULlxh7uVucy7JQYBMWMFCg== X-Google-Smtp-Source: APXvYqwOGd9sieaZMt7EcgmZY/su4J1HvM5ACsGZZKsVVFcGwcE6iXZsCHedNxnAJ28ijvuqeKV7tXNWSRs= X-Received: by 2002:a63:7d46:: with SMTP id m6mr8448073pgn.38.1581071797057; Fri, 07 Feb 2020 02:36:37 -0800 (PST) Date: Fri, 7 Feb 2020 02:36:07 -0800 In-Reply-To: <20200207103608.110305-1-oupton@google.com> Message-Id: <20200207103608.110305-5-oupton@google.com> Mime-Version: 1.0 References: <20200207103608.110305-1-oupton@google.com> X-Mailer: git-send-email 2.25.0.341.g760bfbb309-goog Subject: [PATCH v3 4/5] KVM: nVMX: Emulate MTF when performing instruction emulation From: Oliver Upton To: kvm@vger.kernel.org Cc: Paolo Bonzini , Jim Mattson , Peter Shier , Sean Christopherson , Oliver Upton Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Since commit 5f3d45e7f282 ("kvm/x86: add support for MONITOR_TRAP_FLAG"), KVM has allowed an L1 guest to use the monitor trap flag processor-based execution control for its L2 guest. KVM simply forwards any MTF VM-exits to the L1 guest, which works for normal instruction execution. However, when KVM needs to emulate an instruction on the behalf of an L2 guest, the monitor trap flag is not emulated. Add the necessary logic to kvm_skip_emulated_instruction() to synthesize an MTF VM-exit to L1 upon instruction emulation for L2. Fixes: 5f3d45e7f282 ("kvm/x86: add support for MONITOR_TRAP_FLAG") Signed-off-by: Oliver Upton --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/include/uapi/asm/kvm.h | 1 + arch/x86/kvm/svm.c | 1 + arch/x86/kvm/vmx/nested.c | 35 ++++++++++++++++++++++++++++++- arch/x86/kvm/vmx/nested.h | 5 +++++ arch/x86/kvm/vmx/vmx.c | 37 ++++++++++++++++++++++++++++++++- arch/x86/kvm/vmx/vmx.h | 3 +++ arch/x86/kvm/x86.c | 2 ++ 8 files changed, 83 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 4dffbc10d3f8..b930c548674c 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1112,6 +1112,7 @@ struct kvm_x86_ops { int (*handle_exit)(struct kvm_vcpu *vcpu, enum exit_fastpath_completion exit_fastpath); int (*skip_emulated_instruction)(struct kvm_vcpu *vcpu); + void (*update_emulated_instruction)(struct kvm_vcpu *vcpu); void (*set_interrupt_shadow)(struct kvm_vcpu *vcpu, int mask); u32 (*get_interrupt_shadow)(struct kvm_vcpu *vcpu); void (*patch_hypercall)(struct kvm_vcpu *vcpu, diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h index 503d3f42da16..3f3f780c8c65 100644 --- a/arch/x86/include/uapi/asm/kvm.h +++ b/arch/x86/include/uapi/asm/kvm.h @@ -390,6 +390,7 @@ struct kvm_sync_regs { #define KVM_STATE_NESTED_GUEST_MODE 0x00000001 #define KVM_STATE_NESTED_RUN_PENDING 0x00000002 #define KVM_STATE_NESTED_EVMCS 0x00000004 +#define KVM_STATE_NESTED_MTF_PENDING 0x00000008 #define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001 #define KVM_STATE_NESTED_SMM_VMXON 0x00000002 diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index a3e32d61d60c..fa923b5f8158 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -7433,6 +7433,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = { .run = svm_vcpu_run, .handle_exit = handle_exit, .skip_emulated_instruction = skip_emulated_instruction, + .update_emulated_instruction = NULL, .set_interrupt_shadow = svm_set_interrupt_shadow, .get_interrupt_shadow = svm_get_interrupt_shadow, .patch_hypercall = svm_patch_hypercall, diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 1586aaae3a6f..93441821b24e 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -3608,8 +3608,15 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr) unsigned long exit_qual; bool block_nested_events = vmx->nested.nested_run_pending || kvm_event_needs_reinjection(vcpu); + bool mtf_pending = vmx->nested.mtf_pending; struct kvm_lapic *apic = vcpu->arch.apic; + /* + * Clear the MTF state. If a higher priority VM-exit is delivered first, + * this state is discarded. + */ + vmx->nested.mtf_pending = false; + if (lapic_in_kernel(vcpu) && test_bit(KVM_APIC_INIT, &apic->pending_events)) { if (block_nested_events) @@ -3620,8 +3627,28 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr) return 0; } + /* + * Process any exceptions that are not debug traps before MTF. + */ + if (vcpu->arch.exception.pending && + !vmx_pending_dbg_trap(vcpu) && + nested_vmx_check_exception(vcpu, &exit_qual)) { + if (block_nested_events) + return -EBUSY; + nested_vmx_inject_exception_vmexit(vcpu, exit_qual); + return 0; + } + + if (mtf_pending) { + if (block_nested_events) + return -EBUSY; + nested_vmx_update_pending_dbg(vcpu); + nested_vmx_vmexit(vcpu, EXIT_REASON_MONITOR_TRAP_FLAG, 0, 0); + return 0; + } + if (vcpu->arch.exception.pending && - nested_vmx_check_exception(vcpu, &exit_qual)) { + nested_vmx_check_exception(vcpu, &exit_qual)) { if (block_nested_events) return -EBUSY; nested_vmx_inject_exception_vmexit(vcpu, exit_qual); @@ -5711,6 +5738,9 @@ static int vmx_get_nested_state(struct kvm_vcpu *vcpu, if (vmx->nested.nested_run_pending) kvm_state.flags |= KVM_STATE_NESTED_RUN_PENDING; + + if (vmx->nested.mtf_pending) + kvm_state.flags |= KVM_STATE_NESTED_MTF_PENDING; } } @@ -5891,6 +5921,9 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu, vmx->nested.nested_run_pending = !!(kvm_state->flags & KVM_STATE_NESTED_RUN_PENDING); + vmx->nested.mtf_pending = + !!(kvm_state->flags & KVM_STATE_NESTED_MTF_PENDING); + ret = -EINVAL; if (nested_cpu_has_shadow_vmcs(vmcs12) && vmcs12->vmcs_link_pointer != -1ull) { diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h index fc874d4ead0f..e12461776151 100644 --- a/arch/x86/kvm/vmx/nested.h +++ b/arch/x86/kvm/vmx/nested.h @@ -175,6 +175,11 @@ static inline bool nested_cpu_has_virtual_nmis(struct vmcs12 *vmcs12) return vmcs12->pin_based_vm_exec_control & PIN_BASED_VIRTUAL_NMIS; } +static inline int nested_cpu_has_mtf(struct vmcs12 *vmcs12) +{ + return nested_cpu_has(vmcs12, CPU_BASED_MONITOR_TRAP_FLAG); +} + static inline int nested_cpu_has_ept(struct vmcs12 *vmcs12) { return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_EPT); diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 9a6664886f2e..90102830eeb3 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -1599,6 +1599,40 @@ static int skip_emulated_instruction(struct kvm_vcpu *vcpu) return 1; } + +/* + * Recognizes a pending MTF VM-exit and records the nested state for later + * delivery. + */ +static void vmx_update_emulated_instruction(struct kvm_vcpu *vcpu) +{ + struct vmcs12 *vmcs12 = get_vmcs12(vcpu); + struct vcpu_vmx *vmx = to_vmx(vcpu); + + if (!is_guest_mode(vcpu)) + return; + + /* + * Per the SDM, MTF takes priority over debug-trap exceptions besides + * T-bit traps. As instruction emulation is completed (i.e. at the + * instruction boundary), any #DB exception pending delivery must be a + * debug-trap. Record the pending MTF state to be delivered in + * vmx_check_nested_events(). + */ + if (nested_cpu_has_mtf(vmcs12) && + (!vcpu->arch.exception.pending || + vcpu->arch.exception.nr == DB_VECTOR)) + vmx->nested.mtf_pending = true; + else + vmx->nested.mtf_pending = false; +} + +static void vmx_skip_emulated_instruction(struct kvm_vcpu *vcpu) +{ + vmx_update_emulated_instruction(vcpu); + return skip_emulated_instruction(vcpu); +} + static void vmx_clear_hlt(struct kvm_vcpu *vcpu) { /* @@ -7783,7 +7817,8 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = { .run = vmx_vcpu_run, .handle_exit = vmx_handle_exit, - .skip_emulated_instruction = skip_emulated_instruction, + .skip_emulated_instruction = vmx_skip_emulated_instruction, + .update_emulated_instruction = vmx_update_emulated_instruction, .set_interrupt_shadow = vmx_set_interrupt_shadow, .get_interrupt_shadow = vmx_get_interrupt_shadow, .patch_hypercall = vmx_patch_hypercall, diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 7f42cf3dcd70..e64da06c7009 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -150,6 +150,9 @@ struct nested_vmx { /* L2 must run next, and mustn't decide to exit to L1. */ bool nested_run_pending; + /* Pending MTF VM-exit into L1. */ + bool mtf_pending; + struct loaded_vmcs vmcs02; /* diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 4d3310df1758..7dbe48072c54 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6891,6 +6891,8 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, kvm_rip_write(vcpu, ctxt->eip); if (r && ctxt->tf) r = kvm_vcpu_do_singlestep(vcpu); + if (kvm_x86_ops->update_emulated_instruction) + kvm_x86_ops->update_emulated_instruction(vcpu); __kvm_set_rflags(vcpu, ctxt->eflags); } From patchwork Fri Feb 7 10:36:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 11370221 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7153E1398 for ; Fri, 7 Feb 2020 10:36:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 45E012082E for ; Fri, 7 Feb 2020 10:36:42 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="oJUCkzVr" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727392AbgBGKgl (ORCPT ); Fri, 7 Feb 2020 05:36:41 -0500 Received: from mail-yw1-f74.google.com ([209.85.161.74]:52021 "EHLO mail-yw1-f74.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726857AbgBGKgk (ORCPT ); Fri, 7 Feb 2020 05:36:40 -0500 Received: by mail-yw1-f74.google.com with SMTP id a16so1414268ywa.18 for ; Fri, 07 Feb 2020 02:36:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=YURPBE5ARW7OYIGG4d7Fs2AlCTzDPiK6ygILDqAYQdw=; b=oJUCkzVrYh5agU12/jqiJNMmT138pcfYkPU8MYgvHshiygCLkpwNwtpxrv0t59fZ8A aIHMLFxDBEUvxsN2IlwKMuF1+2kW4UeXO5LoRnhyeskWPLklrqfAw5CF0KUPAHNUZTuq yZ4g3uCUTrFkqmz3lZW45eQuYDl0ir6m63+tfB2TXXCbhIbUQCQV3mF7EY3YAIIohIo8 pon18QUJe5ltYdhQmc5zyVLjuI80DVJgidZ5aJke83S/k1koPAitk86oTNmNMVXVFBEq Xblibj1F5O20j4CnMbaNN3GFMVYsjOkv9AybXZcpCW4ppBzqkKddv9UrepeYdi67Tqth zLyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=YURPBE5ARW7OYIGG4d7Fs2AlCTzDPiK6ygILDqAYQdw=; b=qw/ThP0zEUlI8BrJtM7+NPU0fCh1ns3ARkds3K5BfE3p3hgf4cBIhCkiePHj4isXPG DlIIQxCGcY/+HVyiptGEtmQukJ+/ZXcl3luMb0+YRm17IdJqRzQY24n6/rdKyZaG3F2O xAp/TAvS55dAkT81rt+EMKSMP31vPA532lH6QDsqziY8s1qkoMzgNtuGq5YSQz3qRuH9 GH48sNz9vrd8nGviUc8+aMlA3CWF3y7Za42Ec3sLTVhYzie6v0/AeEjwvRZLFCAAXdzc iMOFr+GoI0IY9mk/UiqJB4D3PSwVaF73iWMjufrLKmrMexlGbfc1kQkoqh70ytvblbCg d+Ww== X-Gm-Message-State: APjAAAU8arbXN2anc8DUMi5eeOMaQznUoyr6FQsurerVLgvQfQoXCcvd YaZy6YcoW3anaI5DybQ2OfDd+PmJEHxrQhCwwVe6iKsGmF8nglw4Ok20K44L1IkfESW/PJ2eI4Z weg3NhW0vaSoVIVuiT9nSLizxJ0x3dIseE1LwPCAyAh0ONt8+oybulnFnHA== X-Google-Smtp-Source: APXvYqwrX/1vPam1Ayp2q+Zt8rZ0XgQpe4S3qoOZgWTdICWbahUyzPYe4b8CjZAV4d4M4X7k9JPDaf3j8Zc= X-Received: by 2002:a0d:c981:: with SMTP id l123mr6631413ywd.284.1581071799281; Fri, 07 Feb 2020 02:36:39 -0800 (PST) Date: Fri, 7 Feb 2020 02:36:08 -0800 In-Reply-To: <20200207103608.110305-1-oupton@google.com> Message-Id: <20200207103608.110305-6-oupton@google.com> Mime-Version: 1.0 References: <20200207103608.110305-1-oupton@google.com> X-Mailer: git-send-email 2.25.0.341.g760bfbb309-goog Subject: [kvm-unit-tests PATCH v3 5/5] x86: VMX: Add tests for monitor trap flag From: Oliver Upton To: kvm@vger.kernel.org Cc: Paolo Bonzini , Jim Mattson , Peter Shier , Sean Christopherson , Oliver Upton Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Test to verify that MTF VM-exits into host are synthesized when the 'monitor trap flag' processor-based VM-execution control is set under various conditions. Expect an MTF VM-exit if instruction execution produces no events other than MTF. Should instruction execution produce a concurrent debug-trap and MTF event, expect an MTF VM-exit with the 'pending debug exceptions' VMCS field set. Expect an MTF VM-exit to follow event delivery should instruction execution generate a higher-priority event, such as a general-protection fault. Lastly, expect an MTF VM-exit to follow delivery of a debug-trap software exception (INT1/INT3/INTO/INT n). Signed-off-by: Oliver Upton Reviewed-by: Jim Mattson --- x86/vmx.h | 1 + x86/vmx_tests.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 158 insertions(+) diff --git a/x86/vmx.h b/x86/vmx.h index 6214400f2b53..6adf0916564b 100644 --- a/x86/vmx.h +++ b/x86/vmx.h @@ -399,6 +399,7 @@ enum Ctrl0 { CPU_NMI_WINDOW = 1ul << 22, CPU_IO = 1ul << 24, CPU_IO_BITMAP = 1ul << 25, + CPU_MTF = 1ul << 27, CPU_MSR_BITMAP = 1ul << 28, CPU_MONITOR = 1ul << 29, CPU_PAUSE = 1ul << 30, diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index b31c360c5f3c..0e2c2f8a7d34 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -4970,6 +4970,162 @@ static void test_vmx_preemption_timer(void) vmcs_write(EXI_CONTROLS, saved_exit); } +extern unsigned char test_mtf1; +extern unsigned char test_mtf2; +extern unsigned char test_mtf3; + +__attribute__((noclone)) static void test_mtf_guest(void) +{ + asm ("vmcall;\n\t" + "out %al, $0x80;\n\t" + "test_mtf1:\n\t" + "vmcall;\n\t" + "out %al, $0x80;\n\t" + "test_mtf2:\n\t" + /* + * Prepare for the 'MOV CR3' test. Attempt to induce a + * general-protection fault by moving a non-canonical address into + * CR3. The 'MOV CR3' instruction does not take an imm64 operand, + * so we must MOV the desired value into a register first. + * + * MOV RAX is done before the VMCALL such that MTF is only enabled + * for the instruction under test. + */ + "mov $0x8000000000000000, %rax;\n\t" + "vmcall;\n\t" + "mov %rax, %cr3;\n\t" + "test_mtf3:\n\t" + "vmcall;\n\t" + /* + * ICEBP/INT1 instruction. Though the instruction is now + * documented, don't rely on assemblers enumerating the + * instruction. Resort to hand assembly. + */ + ".byte 0xf1;\n\t"); +} + +static void test_mtf_gp_handler(struct ex_regs *regs) +{ + regs->rip = (unsigned long) &test_mtf3; +} + +static void test_mtf_db_handler(struct ex_regs *regs) +{ +} + +static void enable_mtf(void) +{ + u32 ctrl0 = vmcs_read(CPU_EXEC_CTRL0); + + vmcs_write(CPU_EXEC_CTRL0, ctrl0 | CPU_MTF); +} + +static void disable_mtf(void) +{ + u32 ctrl0 = vmcs_read(CPU_EXEC_CTRL0); + + vmcs_write(CPU_EXEC_CTRL0, ctrl0 & ~CPU_MTF); +} + +static void enable_tf(void) +{ + unsigned long rflags = vmcs_read(GUEST_RFLAGS); + + vmcs_write(GUEST_RFLAGS, rflags | X86_EFLAGS_TF); +} + +static void disable_tf(void) +{ + unsigned long rflags = vmcs_read(GUEST_RFLAGS); + + vmcs_write(GUEST_RFLAGS, rflags & ~X86_EFLAGS_TF); +} + +static void report_mtf(const char *insn_name, unsigned long exp_rip) +{ + unsigned long rip = vmcs_read(GUEST_RIP); + + assert_exit_reason(VMX_MTF); + report(rip == exp_rip, "MTF VM-exit after %s instruction. RIP: 0x%lx (expected 0x%lx)", + insn_name, rip, exp_rip); +} + +static void vmx_mtf_test(void) +{ + unsigned long pending_dbg; + handler old_gp, old_db; + + if (!(ctrl_cpu_rev[0].clr & CPU_MTF)) { + printf("CPU does not support the 'monitor trap flag' processor-based VM-execution control.\n"); + return; + } + + test_set_guest(test_mtf_guest); + + /* Expect an MTF VM-exit after OUT instruction */ + enter_guest(); + skip_exit_vmcall(); + + enable_mtf(); + enter_guest(); + report_mtf("OUT", (unsigned long) &test_mtf1); + disable_mtf(); + + /* + * Concurrent #DB trap and MTF on instruction boundary. Expect MTF + * VM-exit with populated 'pending debug exceptions' VMCS field. + */ + enter_guest(); + skip_exit_vmcall(); + + enable_mtf(); + enable_tf(); + + enter_guest(); + report_mtf("OUT", (unsigned long) &test_mtf2); + pending_dbg = vmcs_read(GUEST_PENDING_DEBUG); + report(pending_dbg & DR_STEP, + "'pending debug exceptions' field after MTF VM-exit: 0x%lx (expected 0x%lx)", + pending_dbg, (unsigned long) DR_STEP); + + disable_mtf(); + disable_tf(); + vmcs_write(GUEST_PENDING_DEBUG, 0); + + /* + * #GP exception takes priority over MTF. Expect MTF VM-exit with RIP + * advanced to first instruction of #GP handler. + */ + enter_guest(); + skip_exit_vmcall(); + + old_gp = handle_exception(GP_VECTOR, test_mtf_gp_handler); + + enable_mtf(); + enter_guest(); + report_mtf("MOV CR3", (unsigned long) get_idt_addr(&boot_idt[GP_VECTOR])); + disable_mtf(); + + /* + * Concurrent MTF and privileged software exception (i.e. ICEBP/INT1). + * MTF should follow the delivery of #DB trap, though the SDM doesn't + * provide clear indication of the relative priority. + */ + enter_guest(); + skip_exit_vmcall(); + + handle_exception(GP_VECTOR, old_gp); + old_db = handle_exception(DB_VECTOR, test_mtf_db_handler); + + enable_mtf(); + enter_guest(); + report_mtf("INT1", (unsigned long) get_idt_addr(&boot_idt[DB_VECTOR])); + disable_mtf(); + + enter_guest(); + handle_exception(DB_VECTOR, old_db); +} + /* * Tests for VM-execution control fields */ @@ -9505,5 +9661,6 @@ struct vmx_test vmx_tests[] = { TEST(atomic_switch_max_msrs_test), TEST(atomic_switch_overflow_msrs_test), TEST(rdtsc_vmexit_diff_test), + TEST(vmx_mtf_test), { NULL, NULL, NULL, NULL, NULL, {0} }, };