From patchwork Sat Apr 2 01:08:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 12798889 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2063DC433F5 for ; Sat, 2 Apr 2022 01:09:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353584AbiDBBLB (ORCPT ); Fri, 1 Apr 2022 21:11:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42992 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234864AbiDBBK7 (ORCPT ); Fri, 1 Apr 2022 21:10:59 -0400 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DBD848A30A for ; Fri, 1 Apr 2022 18:09:07 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id mw8-20020a17090b4d0800b001c717bb058eso4962207pjb.0 for ; Fri, 01 Apr 2022 18:09:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=reply-to:date:in-reply-to:message-id:mime-version:references :subject:from:to:cc; bh=QQuySiCRGCJ6RvPIQ/BSFIhGVMRh766oWZ6w5lwsmv4=; b=HBsk46CaOocW/1oIhQTdaU2YWrEICiKdWGKu4ZKgs7qvpVBmvildZd/bEgCiEKbqiO RPYXO+Ret09cI0WIspij5+anNJWHBVMruj+veU56AX1l7pHRbJl1bt6hq3X3C0yk8ema pZAj0YysYkR4F/fSdoGF1rC94qijWnVQ1PiDiZWrmBZXbPY3EBGGf7NW1p2KdGsDZ/ez uyRWg0eY1nOvK7E2k2YRd5M8lCQUg8gzdcwrjmlJ4snsL21qUAOrq63TrmrrOyo0uc/2 uKIur0FCevxRs4x5oT4sgQLPIxFvx9EdHiA93RdQY1sdz7SWnnl66RBxDPWlvVGVPNbq aZUg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:reply-to:date:in-reply-to:message-id :mime-version:references:subject:from:to:cc; bh=QQuySiCRGCJ6RvPIQ/BSFIhGVMRh766oWZ6w5lwsmv4=; b=Jjq+6/Z7JTOjk19cMGEdAjLRmLDDHs6FxEwro3IfqDap1C/7/0dgHdh6yF+VlS62lr yWintbgsZpQfF7ezHQ135bNz61O9I3CGWcwMqyrmvUWgCx1DrO/KWtnmB6FL0Q02u40Y 3CigYK6/kqqrZLfdoR+UEUBKpAY3T3p+PsF5F9JB6LopPrEqq2fr5f8DMYaZdO8Knf7i 6aCaHIUg5DU/V96mXg0DpjfyBrjpJKOQjpqnsAOQoMXzBi1su393I/qgYy3RrEN717bi 3DdKryM7tKHKZYdxKkNARYpbeHTtPaedDtWrkE8gUj8prkrtAF1YJpl/OXBcn6QrpIiv woig== X-Gm-Message-State: AOAM530RfuFhDfpuP2oN5YEOjijssMuxdubn9b+8OrJ2mGQvyqm7eyqk RuXrBNUkLivAONNnTsLW37PYUE+uYEQ= X-Google-Smtp-Source: ABdhPJxcxwbjgBmS5S7Od5qo4C/vjgUz/Mr0NzGn5XnSKA7RaYrosjsr0mT7mv79D4saIgkrMnnPAakU9Zc= X-Received: from seanjc.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3e5]) (user=seanjc job=sendgmr) by 2002:a05:6a00:24c6:b0:4fd:9038:74f0 with SMTP id d6-20020a056a0024c600b004fd903874f0mr13594229pfv.63.1648861747326; Fri, 01 Apr 2022 18:09:07 -0700 (PDT) Reply-To: Sean Christopherson Date: Sat, 2 Apr 2022 01:08:56 +0000 In-Reply-To: <20220402010903.727604-1-seanjc@google.com> Message-Id: <20220402010903.727604-2-seanjc@google.com> Mime-Version: 1.0 References: <20220402010903.727604-1-seanjc@google.com> X-Mailer: git-send-email 2.35.1.1094.g7c7d902a7c-goog Subject: [PATCH 1/8] KVM: nSVM: Sync next_rip field from vmcb12 to vmcb02 From: Sean Christopherson To: Paolo Bonzini Cc: Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, "Maciej S . Szmigiero" Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Maciej S. Szmigiero The next_rip field of a VMCB is *not* an output-only field for a VMRUN. This field value (instead of the saved guest RIP) in used by the CPU for the return address pushed on stack when injecting a software interrupt or INT3 or INTO exception. Make sure this field gets synced from vmcb12 to vmcb02 when entering L2 or loading a nested state and NRIPS is exposed to L1. If NRIPS is supported in hardware but not exposed to L1 (nrips=0 or hidden by userspace), stuff vmcb02's next_rip from the new L2 RIP to emulate a !NRIPS CPU (which saves RIP on the stack as-is). Signed-off-by: Maciej S. Szmigiero Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Reviewed-by: Maxim Levitsky --- arch/x86/kvm/svm/nested.c | 22 +++++++++++++++++++--- arch/x86/kvm/svm/svm.h | 1 + 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 73b545278f5f..9a6dc2b38fcf 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -369,6 +369,7 @@ void __nested_copy_vmcb_control_to_cache(struct kvm_vcpu *vcpu, to->nested_ctl = from->nested_ctl; to->event_inj = from->event_inj; to->event_inj_err = from->event_inj_err; + to->next_rip = from->next_rip; to->nested_cr3 = from->nested_cr3; to->virt_ext = from->virt_ext; to->pause_filter_count = from->pause_filter_count; @@ -606,7 +607,8 @@ static void nested_vmcb02_prepare_save(struct vcpu_svm *svm, struct vmcb *vmcb12 } } -static void nested_vmcb02_prepare_control(struct vcpu_svm *svm) +static void nested_vmcb02_prepare_control(struct vcpu_svm *svm, + unsigned long vmcb12_rip) { u32 int_ctl_vmcb01_bits = V_INTR_MASKING_MASK; u32 int_ctl_vmcb12_bits = V_TPR_MASK | V_IRQ_INJECTION_BITS_MASK; @@ -660,6 +662,19 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm) vmcb02->control.event_inj = svm->nested.ctl.event_inj; vmcb02->control.event_inj_err = svm->nested.ctl.event_inj_err; + /* + * next_rip is consumed on VMRUN as the return address pushed on the + * stack for injected soft exceptions/interrupts. If nrips is exposed + * to L1, take it verbatim from vmcb12. If nrips is supported in + * hardware but not exposed to L1, stuff the actual L2 RIP to emulate + * what a nrips=0 CPU would do (L1 is responsible for advancing RIP + * prior to injecting the event). + */ + if (svm->nrips_enabled) + vmcb02->control.next_rip = svm->nested.ctl.next_rip; + else if (boot_cpu_has(X86_FEATURE_NRIPS)) + vmcb02->control.next_rip = vmcb12_rip; + vmcb02->control.virt_ext = vmcb01->control.virt_ext & LBR_CTL_ENABLE_MASK; if (svm->lbrv_enabled) @@ -743,7 +758,7 @@ int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vmcb12_gpa, nested_svm_copy_common_state(svm->vmcb01.ptr, svm->nested.vmcb02.ptr); svm_switch_vmcb(svm, &svm->nested.vmcb02); - nested_vmcb02_prepare_control(svm); + nested_vmcb02_prepare_control(svm, vmcb12->save.rip); nested_vmcb02_prepare_save(svm, vmcb12); ret = nested_svm_load_cr3(&svm->vcpu, svm->nested.save.cr3, @@ -1422,6 +1437,7 @@ static void nested_copy_vmcb_cache_to_control(struct vmcb_control_area *dst, dst->nested_ctl = from->nested_ctl; dst->event_inj = from->event_inj; dst->event_inj_err = from->event_inj_err; + dst->next_rip = from->next_rip; dst->nested_cr3 = from->nested_cr3; dst->virt_ext = from->virt_ext; dst->pause_filter_count = from->pause_filter_count; @@ -1606,7 +1622,7 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu, nested_copy_vmcb_control_to_cache(svm, ctl); svm_switch_vmcb(svm, &svm->nested.vmcb02); - nested_vmcb02_prepare_control(svm); + nested_vmcb02_prepare_control(svm, save->rip); /* * While the nested guest CR3 is already checked and set by diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index e246793cbeae..47e7427d0395 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -139,6 +139,7 @@ struct vmcb_ctrl_area_cached { u64 nested_ctl; u32 event_inj; u32 event_inj_err; + u64 next_rip; u64 nested_cr3; u64 virt_ext; u32 clean; From patchwork Sat Apr 2 01:08:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 12798890 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7B75CC4332F for ; Sat, 2 Apr 2022 01:09:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353590AbiDBBLD (ORCPT ); Fri, 1 Apr 2022 21:11:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43152 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352893AbiDBBLA (ORCPT ); Fri, 1 Apr 2022 21:11:00 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 837CC8CD96 for ; Fri, 1 Apr 2022 18:09:09 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id l6-20020a17090a150600b001c95a6ab60cso4927718pja.5 for ; Fri, 01 Apr 2022 18:09:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=reply-to:date:in-reply-to:message-id:mime-version:references :subject:from:to:cc; bh=8RHA9aUNJxFpM8yTJhP4ef1t/aKUFmzX6SMgtUXeSlU=; b=mu6m/a5O3VjsafgbIgGavNyaMXeK5i+9etdubuU+TMNUVKvHADJfk8RbYW9jX8JI6L fGcg3as7WwEUTD6BKHO8x+X8rl/KoQ0vXmuQKH+tbFQNlDrVvXZfTE7zAoIuYPNuYoyG 4rF6f4FEvRvKghKoT+T7LWlsqJkTfx+WAiA7dIFsjZBYLQK5i2aQ5Q3aDkknDP5IkLuK 8PZqwQKJXWZbP5fXXW8tZzVRpDTNYrHK2DY3GJtJN+1PdWtwqmiueLkl/nNduvbKONov n1k+OwCK0aN+DiRconoQP9ZKaQXkMGXCPrWjncL4jUH0SPVC14/yi5H2rq2jZXbaJ8IA nYUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:reply-to:date:in-reply-to:message-id :mime-version:references:subject:from:to:cc; bh=8RHA9aUNJxFpM8yTJhP4ef1t/aKUFmzX6SMgtUXeSlU=; b=VdG8OqTM8z1LbGpsxTXJ70ruzd4qsb64U5/O/1NNtQb+Zmuf1+HwUSDrSuhvVvouuh jta4xYeqt2CNmONyTXFO6ahEliBaPbt2Y5VmQ6k5JWou/jozjtdqNgiJEbZPSaseuAB0 3PO+/ssd+D7w1QSpF5PyC0ers/qhdjhpz/zIzGOOZWrZVN0mUgl/ZgJm/eOQSzNBNeSs 6vo1kyTJfyPw6c+yoVMK1MhAzvB/W0ty9hRu3FZ5QF8qYolcQH/Jb7mYX8WDFANoPyKS sly8CMXzQpAjmEofFnlTHGIiFIQ2UvwxOpdAugfPIW/Rw5csowwBYEQb3TD6RrLWg4u8 pcoA== X-Gm-Message-State: AOAM533Y1ghYp2O4qsCLiVSwNmMrvtaBWv2QFocvbtDWmzoJz3j6HtrM VdpBP6K71NHJQKeCYExU8r01p1olfEg= X-Google-Smtp-Source: ABdhPJz6eEt/o/RMT6jRF4o5mIUgYCP3Lxw3z5+HYs6xIhuayeX7wPusWKnd7JasHteXF2zCH0UcWHuQWv8= X-Received: from seanjc.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3e5]) (user=seanjc job=sendgmr) by 2002:a05:6a00:114e:b0:4c8:55f7:faad with SMTP id b14-20020a056a00114e00b004c855f7faadmr13709370pfm.86.1648861749019; Fri, 01 Apr 2022 18:09:09 -0700 (PDT) Reply-To: Sean Christopherson Date: Sat, 2 Apr 2022 01:08:57 +0000 In-Reply-To: <20220402010903.727604-1-seanjc@google.com> Message-Id: <20220402010903.727604-3-seanjc@google.com> Mime-Version: 1.0 References: <20220402010903.727604-1-seanjc@google.com> X-Mailer: git-send-email 2.35.1.1094.g7c7d902a7c-goog Subject: [PATCH 2/8] KVM: SVM: Downgrade BUG_ON() to WARN_ON() in svm_inject_irq() From: Sean Christopherson To: Paolo Bonzini Cc: Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, "Maciej S . Szmigiero" Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Maciej S. Szmigiero There is no need to bring down the whole host just because there might be some issue with respect to guest GIF handling in KVM. Signed-off-by: Maciej S. Szmigiero Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/svm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 95b26dbfd561..2c86bd9176c6 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -3383,7 +3383,7 @@ static void svm_inject_irq(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); - BUG_ON(!(gif_set(svm))); + WARN_ON(!gif_set(svm)); trace_kvm_inj_virq(vcpu->arch.interrupt.nr); ++vcpu->stat.irq_injections; From patchwork Sat Apr 2 01:08:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 12798891 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 06601C433EF for ; Sat, 2 Apr 2022 01:09:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353618AbiDBBLF (ORCPT ); Fri, 1 Apr 2022 21:11:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43256 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353423AbiDBBLB (ORCPT ); Fri, 1 Apr 2022 21:11:01 -0400 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 21AE98FE73 for ; Fri, 1 Apr 2022 18:09:11 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id bv2-20020a17090af18200b001c63c69a774so1908460pjb.0 for ; Fri, 01 Apr 2022 18:09:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=reply-to:date:in-reply-to:message-id:mime-version:references :subject:from:to:cc; bh=Czzn9i/2i6B1OBdabyWFgGFqRWslyQJuAsyXE6/7mj0=; b=I/sR5Eyp0KnE20qAVSatSC9Qd8LA6B9L+YQcL1RO6LZoG+nQbxj7gR8VC+pSt159MB naW8IqzSxUtZ1tkcXuzCgT7fC4s7FNy2JBiqGuFCUJMOnwXaad4wfxO+RSJlGt2nKvta x8Lqh+z04e0vhr5s2mHUvv8LFCb7ORgxG0nTuZlyOWuMpkrGsYZOh+d9zG7eljfwEmpg lois9n6XSdpXL+FfqvQIWupDiB7tQCpF6alcGuoKdBg/DJVmUNxbOxLfSqj8ntciaMlV 8uVjEXlWKdmoAfv9fKjNkGOjM2f5M55lgONHC2aG3W0wwH5Z8xplGambc5G8kWZWdUA3 GhGg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:reply-to:date:in-reply-to:message-id :mime-version:references:subject:from:to:cc; bh=Czzn9i/2i6B1OBdabyWFgGFqRWslyQJuAsyXE6/7mj0=; b=uV0vbowtFwf78mIq2SiwrfON997rjaKyjiQ+hnGvjXGt3xqXi0DMwVtDuiytFn/b6r lBTMuXgtC4nkb+DTw1mtypSozn6GcIH1YvxNplaisSyg5Xb8coZXKGvl+ks/qMV9JWIN EQCJJe8ccqiof8O3eCe28QM3a3a64JBK5Mmt/cr0Iba7B2JPzalXcepkUFCjeGiuKT3p 7TSvy2l7SGXXAPXxUYGJ/0PAoQvcBBX6IRZBeGkedUfp+9RPng8uCW25YxX2RpanFn6C 8fLoVHdo4AE33/jFsC5KGFCT38gdY17ZTR0Of6vWfC/40yiXNHUtzIHk0TZM0i6ooBwz mHyQ== X-Gm-Message-State: AOAM531kgzht1Zv+sJtNfz/UHOeiLe1yVeTfc5CuMXsGkCz0Z1Tox8Ch kzlhQ1KzaPbtuU63i+Uc6tvb+/fmxRQ= X-Google-Smtp-Source: ABdhPJxUeBeLfnRYVU4NNoaIAkOp173uUFizIUjEgmhgVSqVzzTW/5EspfQz0Niq83TzQz2SLpLto22aL1Q= X-Received: from seanjc.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3e5]) (user=seanjc job=sendgmr) by 2002:a17:902:8c81:b0:156:7fee:643b with SMTP id t1-20020a1709028c8100b001567fee643bmr203850plo.59.1648861750610; Fri, 01 Apr 2022 18:09:10 -0700 (PDT) Reply-To: Sean Christopherson Date: Sat, 2 Apr 2022 01:08:58 +0000 In-Reply-To: <20220402010903.727604-1-seanjc@google.com> Message-Id: <20220402010903.727604-4-seanjc@google.com> Mime-Version: 1.0 References: <20220402010903.727604-1-seanjc@google.com> X-Mailer: git-send-email 2.35.1.1094.g7c7d902a7c-goog Subject: [PATCH 3/8] KVM: SVM: Unwind "speculative" RIP advancement if INTn injection "fails" From: Sean Christopherson To: Paolo Bonzini Cc: Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, "Maciej S . Szmigiero" Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Unwind the RIP advancement done by svm_queue_exception() when injecting an INT3 ultimately "fails" due to the CPU encountering a VM-Exit while vectoring the injected event, even if the exception reported by the CPU isn't the same event that was injected. If vectoring INT3 encounters an exception, e.g. #NP, and vectoring the #NP encounters an intercepted exception, e.g. #PF when KVM is using shadow paging, then the #NP will be reported as the event that was in-progress. Note, this is still imperfect, as it will get a false positive if the INT3 is cleanly injected, no VM-Exit occurs before the IRET from the INT3 handler in the guest, the instruction following the INT3 generates an exception (directly or indirectly), _and_ vectoring that exception encounters an exception that is intercepted by KVM. The false positives could theoretically be solved by further analyzing the vectoring event, e.g. by comparing the error code against the expected error code were an exception to occur when vectoring the original injected exception, but SVM without NRIPS is a complete disaster, trying to make it 100% correct is a waste of time. Fixes: 66b7138f9136 ("KVM: SVM: Emulate nRIP feature when reinjecting INT3") Signed-off-by: Sean Christopherson Reviewed-by: Maxim Levitsky --- arch/x86/kvm/svm/svm.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 2c86bd9176c6..30cef3b10838 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -3699,6 +3699,18 @@ static void svm_complete_interrupts(struct kvm_vcpu *vcpu) vector = exitintinfo & SVM_EXITINTINFO_VEC_MASK; type = exitintinfo & SVM_EXITINTINFO_TYPE_MASK; + /* + * If NextRIP isn't enabled, KVM must manually advance RIP prior to + * injecting the soft exception/interrupt. That advancement needs to + * be unwound if vectoring didn't complete. Note, the _new_ event may + * not be the injected event, e.g. if KVM injected an INTn, the INTn + * hit a #NP in the guest, and the #NP encountered a #PF, the #NP will + * be the reported vectored event, but RIP still needs to be unwound. + */ + if (int3_injected && type == SVM_EXITINTINFO_TYPE_EXEPT && + kvm_is_linear_rip(vcpu, svm->int3_rip)) + kvm_rip_write(vcpu, kvm_rip_read(vcpu) - int3_injected); + switch (type) { case SVM_EXITINTINFO_TYPE_NMI: vcpu->arch.nmi_injected = true; @@ -3715,13 +3727,9 @@ static void svm_complete_interrupts(struct kvm_vcpu *vcpu) * but re-execute the instruction instead. Rewind RIP first * if we emulated INT3 before. */ - if (kvm_exception_is_soft(vector)) { - if (vector == BP_VECTOR && int3_injected && - kvm_is_linear_rip(vcpu, svm->int3_rip)) - kvm_rip_write(vcpu, - kvm_rip_read(vcpu) - int3_injected); + if (kvm_exception_is_soft(vector)) break; - } + if (exitintinfo & SVM_EXITINTINFO_VALID_ERR) { u32 err = svm->vmcb->control.exit_int_info_err; kvm_requeue_exception_e(vcpu, vector, err); From patchwork Sat Apr 2 01:08:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 12798892 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 50615C4332F for ; Sat, 2 Apr 2022 01:09:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353600AbiDBBLG (ORCPT ); Fri, 1 Apr 2022 21:11:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43410 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353598AbiDBBLD (ORCPT ); Fri, 1 Apr 2022 21:11:03 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8A9348FE73 for ; Fri, 1 Apr 2022 18:09:12 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id l2-20020a17090ad10200b001ca56de815aso135865pju.0 for ; Fri, 01 Apr 2022 18:09:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=reply-to:date:in-reply-to:message-id:mime-version:references :subject:from:to:cc; bh=7avyx91O5ONbDknYrTN91hag2V92Uiaf3yyc7ikJ6Oo=; b=lgN0JGg0wAU/S9xkkCMagwMhbjg+igv1CYSqU9NWY3LszidXgY9Q8mwSKtd0cN+kfP bbwg4h40YSIeXaYQyKZlaaD3Y1gdb9B4VINZmKU3T6ZvbTxe2t7Y8gDAD3ZnBDEZjCgj qG5lPOTOTYQ1rudMZVmQSZvIaffENRyCo7qIPIpLuPnyBlyk90j809EPFrK71YU/BFOk ALHT+cBCZJ5n9EQbfIka2+Pbe7xzXWWI3IycDUwkPM7/55Nw/Si1q3/WuWRZc1ERadnY 33HJeNGUtuLj+u2b9Ia8DrX1kuO/igrZ3L9FgTg8YxiQpeuN2rWqhtMvGg2tcENOx7F4 bVlA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:reply-to:date:in-reply-to:message-id :mime-version:references:subject:from:to:cc; bh=7avyx91O5ONbDknYrTN91hag2V92Uiaf3yyc7ikJ6Oo=; b=ZEACem/wlEoRNYx4npNrnAWxy9AJ+gb0vyxA+q8t+4w/TYHK+osY8eQWdQ0w6hGlDM NJXIH1klvHDAJDTTkvGj/+mkOyDIPi3hhXxUG59PD5lwvUIH4MIdWMeI8/s6d3SCADvL tjUBWc2ZfedhxNVGdoK6LPFPq10gix60+miMrozrJnh/AtAn+Y574wGm0erbFaCzYKYN wdGpFESCe8yv/Rdy5WEu0lMaXqNaWlFjk36LaDcXsXq/HQQJ5AwJ0aPylGsefCvGwBP2 7stzoWp5WPEk2odHd1qGgYGoe/bNTEZyQZe1u8pJASqYey8cmxsbkt/ILEc20OQaQYoj LhlA== X-Gm-Message-State: AOAM53230Tqq2lIzuthGBbqYVkfS6wUfIZyD9gaSt6a4WthixWgGXkJo CYQccC/6lqClhG8qdyMMyg6PYyaXbgY= X-Google-Smtp-Source: ABdhPJzvMNImKhhmy2dldTQRHr/5DfEDlkVSAfluMJDr/3Vdc7HuHvWtI4mJ23ei5/ubz4qjXLU7GsXO62Q= X-Received: from seanjc.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3e5]) (user=seanjc job=sendgmr) by 2002:aa7:8256:0:b0:4e0:78ad:eb81 with SMTP id e22-20020aa78256000000b004e078adeb81mr13590929pfn.30.1648861752031; Fri, 01 Apr 2022 18:09:12 -0700 (PDT) Reply-To: Sean Christopherson Date: Sat, 2 Apr 2022 01:08:59 +0000 In-Reply-To: <20220402010903.727604-1-seanjc@google.com> Message-Id: <20220402010903.727604-5-seanjc@google.com> Mime-Version: 1.0 References: <20220402010903.727604-1-seanjc@google.com> X-Mailer: git-send-email 2.35.1.1094.g7c7d902a7c-goog Subject: [PATCH 4/8] KVM: SVM: Stuff next_rip on emualted INT3 injection if NRIPS is supported From: Sean Christopherson To: Paolo Bonzini Cc: Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, "Maciej S . Szmigiero" Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org If NRIPS is supported in hardware but disabled in KVM, set next_rip to the next RIP when advancing RIP as part of emulating INT3 injection. There is no flag to tell the CPU that KVM isn't using next_rip, and so leaving next_rip is left as is will result in the CPU pushing garbage onto the stack when vectoring the injected event. Fixes: 66b7138f9136 ("KVM: SVM: Emulate nRIP feature when reinjecting INT3") Signed-off-by: Sean Christopherson Reviewed-by: Maxim Levitsky --- arch/x86/kvm/svm/svm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 30cef3b10838..6ea8f16e39ac 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -391,6 +391,10 @@ static void svm_queue_exception(struct kvm_vcpu *vcpu) */ (void)svm_skip_emulated_instruction(vcpu); rip = kvm_rip_read(vcpu); + + if (boot_cpu_has(X86_FEATURE_NRIPS)) + svm->vmcb->control.next_rip = rip; + svm->int3_rip = rip + svm->vmcb->save.cs.base; svm->int3_injected = rip - old_rip; } From patchwork Sat Apr 2 01:09:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 12798893 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7EAC6C433EF for ; Sat, 2 Apr 2022 01:09:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353633AbiDBBLL (ORCPT ); Fri, 1 Apr 2022 21:11:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43594 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353616AbiDBBLF (ORCPT ); Fri, 1 Apr 2022 21:11:05 -0400 Received: from mail-pf1-x44a.google.com (mail-pf1-x44a.google.com [IPv6:2607:f8b0:4864:20::44a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 36EE38FE73 for ; Fri, 1 Apr 2022 18:09:14 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id j17-20020a62b611000000b004fa6338bd77so2432946pff.10 for ; Fri, 01 Apr 2022 18:09:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=reply-to:date:in-reply-to:message-id:mime-version:references :subject:from:to:cc; bh=Ol8exfApW6qp8ksY+lqUpF5z/oy5z9y8ZI2QOtFIzaY=; b=Mg+HcPSPAzhKgemV6VtSyQw1b+lZxkXiayU8hXXSVt6JO3BCHvxXvdSbAbQOTL7+Yp sxvAAyE2cJZIMrQwjYrdwNgEdaYb8oq0BOIfdnWcJ2r0R0lUZCQ0h1egoCn5Lqp8UHLj LdBk8g+GujiQY7A4CyhaTKH5gfXr2rXfIVZOpvRuooZYAX/tYWTMesQNuu4QIQIpakaj J77gqdAv3XNBVxnt9fwS8wkpo9hVd/eBSeaQmaNCzEHbMKC1zvGEKLyQOBbIJHOCyTvx Hs5SIDIKRbhwak/of+DWADUUjZTyKVz+w/bWKJN6FuLavdX//9ckRo5XlZoT8H/HEFKm 9z3g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:reply-to:date:in-reply-to:message-id :mime-version:references:subject:from:to:cc; bh=Ol8exfApW6qp8ksY+lqUpF5z/oy5z9y8ZI2QOtFIzaY=; b=ZVH3gm/ylfxmk0SrlGURGtyKD6DXkAc1msSC0GsLPlkQ48/KrnxtLD63aHrPAIOKEC oe8N9KW6AOvLvpJ/oNrJpNHdwMVc6SUBHZrP0flsreGa0E1HAPHnUilj++lBAPMmjy9C IbzXsk7X2heb4/ujE8BX/AIUSjw0NLE6wq9nsO6sHKxKKe8wP7A26UcPUw7JEMFJSmN8 Eazx6d7buXU9u2mwuuD1THYyJofSHO09PyjAIr4MqF+KKj9w58Zf6SIdf83o+2Uz7CBD 0uDENhiECPpLa2z6a6DhIdijm1b4owbxHjk7KAXt2KsvSoqq8cB0th3rxNOAdfC0dWwb lVEw== X-Gm-Message-State: AOAM531awHHkR0JFZSwdU49IKzMXctEaLYBt5ACxvfIrMYhkPmJC+ENc cLE4KGZaM4nhfhcdgWywPDkLkilWm5g= X-Google-Smtp-Source: ABdhPJwh/+tkHKjROpI8f4YVjL3HYSEb25RxtMSK2Di63Mhnl5I5MjZhGP/4LburLgNSPXEAy1Gz5q6Y8DM= X-Received: from seanjc.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3e5]) (user=seanjc job=sendgmr) by 2002:a17:90b:2246:b0:1c6:5781:7193 with SMTP id hk6-20020a17090b224600b001c657817193mr14995812pjb.48.1648861753762; Fri, 01 Apr 2022 18:09:13 -0700 (PDT) Reply-To: Sean Christopherson Date: Sat, 2 Apr 2022 01:09:00 +0000 In-Reply-To: <20220402010903.727604-1-seanjc@google.com> Message-Id: <20220402010903.727604-6-seanjc@google.com> Mime-Version: 1.0 References: <20220402010903.727604-1-seanjc@google.com> X-Mailer: git-send-email 2.35.1.1094.g7c7d902a7c-goog Subject: [PATCH 5/8] KVM: SVM: Re-inject INT3/INTO instead of retrying the instruction From: Sean Christopherson To: Paolo Bonzini Cc: Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, "Maciej S . Szmigiero" Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Re-inject INT3/INTO instead of retrying the instruction if the CPU encountered an intercepted exception while vectoring the software exception, e.g. if vectoring INT3 encounters a #PF and KVM is using shadow paging. Retrying the instruction is architecturally wrong, e.g. will result in a spurious #DB if there's a code breakpoint on the INT3/O, and lack of re-injection also breaks nested virtualization, e.g. if L1 injects a software exception and vectoring the injected exception encounters an exception that is intercepted by L0 but not L1. Due to, ahem, deficiencies in the SVM architecture, acquiring the next RIP may require flowing through the emulator even if NRIPS is supported, as the CPU clears next_rip if the VM-Exit is due to an exception other than "exceptions caused by the INT3, INTO, and BOUND instructions". To deal with this, "skip" the instruction to calculate next_ript, and then unwind the RIP write and any side effects (RFLAGS updates). Reported-by: Maciej S. Szmigiero Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/svm.c | 111 ++++++++++++++++++++++++++++------------- arch/x86/kvm/svm/svm.h | 4 +- 2 files changed, 79 insertions(+), 36 deletions(-) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 6ea8f16e39ac..ecc828d6921e 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -341,9 +341,11 @@ static void svm_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask) } -static int svm_skip_emulated_instruction(struct kvm_vcpu *vcpu) +static int __svm_skip_emulated_instruction(struct kvm_vcpu *vcpu, + bool commit_side_effects) { struct vcpu_svm *svm = to_svm(vcpu); + unsigned long old_rflags; /* * SEV-ES does not expose the next RIP. The RIP update is controlled by @@ -358,18 +360,71 @@ static int svm_skip_emulated_instruction(struct kvm_vcpu *vcpu) } if (!svm->next_rip) { + if (unlikely(!commit_side_effects)) + old_rflags = svm->vmcb->save.rflags; + if (!kvm_emulate_instruction(vcpu, EMULTYPE_SKIP)) return 0; + + if (unlikely(!commit_side_effects)) + svm->vmcb->save.rflags = old_rflags; } else { kvm_rip_write(vcpu, svm->next_rip); } done: - svm_set_interrupt_shadow(vcpu, 0); + if (likely(commit_side_effects)) + svm_set_interrupt_shadow(vcpu, 0); return 1; } +static int svm_skip_emulated_instruction(struct kvm_vcpu *vcpu) +{ + return __svm_skip_emulated_instruction(vcpu, true); +} + +static int svm_update_soft_interrupt_rip(struct kvm_vcpu *vcpu) +{ + unsigned long rip, old_rip = kvm_rip_read(vcpu); + struct vcpu_svm *svm = to_svm(vcpu); + + /* + * Due to architectural shortcomings, the CPU doesn't always provide + * NextRIP, e.g. if KVM intercepted an exception that occurred while + * the CPU was vectoring an INTO/INT3 in the guest. Temporarily skip + * the instruction even if NextRIP is supported to acquire the next + * RIP so that it can be shoved into the NextRIP field, otherwise + * hardware will fail to advance guest RIP during event injection. + * Drop the exception/interrupt if emulation fails and effectively + * retry the instruction, it's the least awful option. If NRIPS is + * in use, the skip must not commit any side effects such as clearing + * the interrupt shadow or RFLAGS.RF. + */ + if (!__svm_skip_emulated_instruction(vcpu, !nrips)) + return -EIO; + + rip = kvm_rip_read(vcpu); + + /* + * If NextRIP is supported, rewind RIP and update NextRip. If NextRip + * isn't supported, keep the result of the skip as the CPU obviously + * won't advance RIP, but stash away the injection information so that + * RIP can be unwound if injection fails. + */ + if (nrips) { + kvm_rip_write(vcpu, old_rip); + svm->vmcb->control.next_rip = rip; + } else { + if (boot_cpu_has(X86_FEATURE_NRIPS)) + svm->vmcb->control.next_rip = rip; + + svm->soft_int_linear_rip = rip + svm->vmcb->save.cs.base; + svm->soft_int_injected = rip - old_rip; + } + return 0; +} + static void svm_queue_exception(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); @@ -379,25 +434,9 @@ static void svm_queue_exception(struct kvm_vcpu *vcpu) kvm_deliver_exception_payload(vcpu); - if (nr == BP_VECTOR && !nrips) { - unsigned long rip, old_rip = kvm_rip_read(vcpu); - - /* - * For guest debugging where we have to reinject #BP if some - * INT3 is guest-owned: - * Emulate nRIP by moving RIP forward. Will fail if injection - * raises a fault that is not intercepted. Still better than - * failing in all cases. - */ - (void)svm_skip_emulated_instruction(vcpu); - rip = kvm_rip_read(vcpu); - - if (boot_cpu_has(X86_FEATURE_NRIPS)) - svm->vmcb->control.next_rip = rip; - - svm->int3_rip = rip + svm->vmcb->save.cs.base; - svm->int3_injected = rip - old_rip; - } + if (kvm_exception_is_soft(nr) && + svm_update_soft_interrupt_rip(vcpu)) + return; svm->vmcb->control.event_inj = nr | SVM_EVTINJ_VALID @@ -3676,9 +3715,9 @@ static void svm_complete_interrupts(struct kvm_vcpu *vcpu) u8 vector; int type; u32 exitintinfo = svm->vmcb->control.exit_int_info; - unsigned int3_injected = svm->int3_injected; + unsigned soft_int_injected = svm->soft_int_injected; - svm->int3_injected = 0; + svm->soft_int_injected = 0; /* * If we've made progress since setting HF_IRET_MASK, we've @@ -3698,6 +3737,18 @@ static void svm_complete_interrupts(struct kvm_vcpu *vcpu) if (!(exitintinfo & SVM_EXITINTINFO_VALID)) return; + /* + * If NextRIP isn't enabled, KVM must manually advance RIP prior to + * injecting the soft exception/interrupt. That advancement needs to + * be unwound if vectoring didn't complete. Note, the _new_ event may + * not be the injected event, e.g. if KVM injected an INTn, the INTn + * hit a #NP in the guest, and the #NP encountered a #PF, the #NP will + * be the reported vectored event, but RIP still needs to be unwound. + */ + if (soft_int_injected && + kvm_is_linear_rip(vcpu, to_svm(vcpu)->soft_int_linear_rip)) + kvm_rip_write(vcpu, kvm_rip_read(vcpu) - soft_int_injected); + kvm_make_request(KVM_REQ_EVENT, vcpu); vector = exitintinfo & SVM_EXITINTINFO_VEC_MASK; @@ -3711,9 +3762,9 @@ static void svm_complete_interrupts(struct kvm_vcpu *vcpu) * hit a #NP in the guest, and the #NP encountered a #PF, the #NP will * be the reported vectored event, but RIP still needs to be unwound. */ - if (int3_injected && type == SVM_EXITINTINFO_TYPE_EXEPT && - kvm_is_linear_rip(vcpu, svm->int3_rip)) - kvm_rip_write(vcpu, kvm_rip_read(vcpu) - int3_injected); + if (soft_int_injected && type == SVM_EXITINTINFO_TYPE_EXEPT && + kvm_is_linear_rip(vcpu, svm->soft_int_linear_rip)) + kvm_rip_write(vcpu, kvm_rip_read(vcpu) - soft_int_injected); switch (type) { case SVM_EXITINTINFO_TYPE_NMI: @@ -3726,14 +3777,6 @@ static void svm_complete_interrupts(struct kvm_vcpu *vcpu) if (vector == X86_TRAP_VC) break; - /* - * In case of software exceptions, do not reinject the vector, - * but re-execute the instruction instead. Rewind RIP first - * if we emulated INT3 before. - */ - if (kvm_exception_is_soft(vector)) - break; - if (exitintinfo & SVM_EXITINTINFO_VALID_ERR) { u32 err = svm->vmcb->control.exit_int_info_err; kvm_requeue_exception_e(vcpu, vector, err); diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 47e7427d0395..a770a1c7ddd2 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -230,8 +230,8 @@ struct vcpu_svm { bool nmi_singlestep; u64 nmi_singlestep_guest_rflags; - unsigned int3_injected; - unsigned long int3_rip; + unsigned soft_int_injected; + unsigned long soft_int_linear_rip; /* optional nested SVM features that are enabled for this guest */ bool nrips_enabled : 1; From patchwork Sat Apr 2 01:09:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 12798894 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 77B0BC433F5 for ; Sat, 2 Apr 2022 01:09:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353631AbiDBBLO (ORCPT ); Fri, 1 Apr 2022 21:11:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43780 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353634AbiDBBLH (ORCPT ); Fri, 1 Apr 2022 21:11:07 -0400 Received: from mail-pl1-x64a.google.com (mail-pl1-x64a.google.com [IPv6:2607:f8b0:4864:20::64a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0ADDE92D33 for ; Fri, 1 Apr 2022 18:09:15 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id i16-20020a170902cf1000b001540b6a09e3so2277667plg.0 for ; Fri, 01 Apr 2022 18:09:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=reply-to:date:in-reply-to:message-id:mime-version:references :subject:from:to:cc; bh=i0u4JArrhDsLDMn+I/rLz2mNP22Vvf7YGTWgik9+mpU=; b=qVDGL0IdD2Tdx7CvPjoGFys1TnI3wEvpBvsUv8P9V8q3FTljNfYJ2DPnWLfm/35OzJ PbT6IaDPucWH4KICB7hzdigaoj7xvylWvGxJeXIi+P9ovIJ148bq9LI//YlDaqEzycU2 H/Pec4/sMRC9KWL7rORgGHEqFqi2d2F97le923SgGv2YQbfootQxz9AvlO1zdiO1VdEF 3mWwX4hpVHo+UInfjOKAbUMF9PORaispXqGHyqdBTBY7jvasQQJ116Ey0kXxNHfncbBx UBr1yRcFTaFzGw3N7BwncRChA6aQNMe5g41GnN18St3Rs3Jk1uO1hEPfkW5BKVbj6Z8p cNCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:reply-to:date:in-reply-to:message-id :mime-version:references:subject:from:to:cc; bh=i0u4JArrhDsLDMn+I/rLz2mNP22Vvf7YGTWgik9+mpU=; b=JT4Kk2zcvzF9fDIN6LGZmJnfKLtoYKvJjA+UE5qnMx1DXDidjnT0seV8q3SBlwaWUR 74Rq9/H9pTrLsa8fpWyJ6Oy2a94mV9Vmmh7r7osmxD0zhaAxwpDHW0A0zaAzDvrmz8Rh oFTXgcgjRL4MKdjiffUgoIAVNcCsbHrWhNBaZ7TC2UgnmdYmM95uMUoBgrjDtLp374e+ +54z1bjs1TGYNJmWuqddNjA/fvOyYM/FDOBVxn7tJMTB7kFRkz+FSVge6hY6xZPQaRnu pcrjRiJRApyXQ3duyCT++5KBzkaI61o0EL25+udnKOEkr+CTdIiJC8vCSDsijxoVfMyi Dk+Q== X-Gm-Message-State: AOAM531JJrB5mInAL5BThVvIpt3wF3Ou78AFQgbMNYBcpQAV1MzU4Ows Jpm5YozfPFdxZc7HoPQKJunJj8b5IBs= X-Google-Smtp-Source: ABdhPJw+XcYjlX+TSsfNHGCX0p23GeF8EZ6cBnRjeUKPNISQbQvhYa3RrRsEt0XFpT2wLgjalMQPqT+9e+Y= X-Received: from seanjc.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3e5]) (user=seanjc job=sendgmr) by 2002:a05:6a00:10c2:b0:4fd:a140:d5a9 with SMTP id d2-20020a056a0010c200b004fda140d5a9mr13602205pfu.77.1648861755423; Fri, 01 Apr 2022 18:09:15 -0700 (PDT) Reply-To: Sean Christopherson Date: Sat, 2 Apr 2022 01:09:01 +0000 In-Reply-To: <20220402010903.727604-1-seanjc@google.com> Message-Id: <20220402010903.727604-7-seanjc@google.com> Mime-Version: 1.0 References: <20220402010903.727604-1-seanjc@google.com> X-Mailer: git-send-email 2.35.1.1094.g7c7d902a7c-goog Subject: [PATCH 6/8] KVM: SVM: Re-inject INTn instead of retrying the insn on "failure" From: Sean Christopherson To: Paolo Bonzini Cc: Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, "Maciej S . Szmigiero" Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Re-inject INTn software interrupts instead of retrying the instruction if the CPU encountered an intercepted exception while vectoring the INTn, e.g. if KVM intercepted a #PF when utilizing shadow paging. Retrying the instruction is architecturally wrong e.g. will result in a spurious #DB if there's a code breakpoint on the INT3/O, and lack of re-injection also breaks nested virtualization, e.g. if L1 injects a software interrupt and vectoring the injected interrupt encounters an exception that is intercepted by L0 but not L1. Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/svm.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index ecc828d6921e..00b1399681d1 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -3425,14 +3425,24 @@ static void svm_inject_nmi(struct kvm_vcpu *vcpu) static void svm_inject_irq(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); + u32 type; WARN_ON(!gif_set(svm)); + if (vcpu->arch.interrupt.soft) { + if (svm_update_soft_interrupt_rip(vcpu)) + return; + + type = SVM_EVTINJ_TYPE_SOFT; + } else { + type = SVM_EVTINJ_TYPE_INTR; + } + trace_kvm_inj_virq(vcpu->arch.interrupt.nr); ++vcpu->stat.irq_injections; svm->vmcb->control.event_inj = vcpu->arch.interrupt.nr | - SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR; + SVM_EVTINJ_VALID | type; } void svm_complete_interrupt_delivery(struct kvm_vcpu *vcpu, int delivery_mode, @@ -3787,9 +3797,13 @@ static void svm_complete_interrupts(struct kvm_vcpu *vcpu) case SVM_EXITINTINFO_TYPE_INTR: kvm_queue_interrupt(vcpu, vector, false); break; + case SVM_EXITINTINFO_TYPE_SOFT: + kvm_queue_interrupt(vcpu, vector, true); + break; default: break; } + } static void svm_cancel_injection(struct kvm_vcpu *vcpu) From patchwork Sat Apr 2 01:09:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 12798896 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DEAE7C433EF for ; Sat, 2 Apr 2022 01:09:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353664AbiDBBLT (ORCPT ); Fri, 1 Apr 2022 21:11:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43878 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353646AbiDBBLI (ORCPT ); Fri, 1 Apr 2022 21:11:08 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A1A7D99EEE for ; Fri, 1 Apr 2022 18:09:17 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id i5-20020a639d05000000b003822fae3e50so2359573pgd.8 for ; Fri, 01 Apr 2022 18:09:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=reply-to:date:in-reply-to:message-id:mime-version:references :subject:from:to:cc; bh=ypH5s9Nl45kyR4SuhKSlPLb77qSDCCBtuo3KelNxUkU=; b=BXvV6YKppMwrneibybdzCprZebgaEvZuaku3g2RP08ReeutXggwQUvUEMu2PdJkNW/ A0OeCGqKs5NsravDHk7WH5WR0/9K3xTlj8jSH5jMz19zxO6c5vICa+jOJdm5PfsonavW GzlcTn15RsgJexM1+R6HT8bULRuo8uhHwG/io90+NPf/VUA7DQY/rjEYkotOnuiffcK2 2mFahGJuY3hMiBB5eajBIsKa9CNmYVcV2NmeyNJkeCK4SyDKmR9+hi58C4dcY/ftu9Oz KYZ1yWUU+lOeGCrRX8XJdUgsmNpaGFeCwI1uNGOM1KALML8V9ri800OZVVfpYSo6aR9t X4gg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:reply-to:date:in-reply-to:message-id :mime-version:references:subject:from:to:cc; bh=ypH5s9Nl45kyR4SuhKSlPLb77qSDCCBtuo3KelNxUkU=; b=jyESdGb556kpHwviM2p5FVnKXT+pYhJ/z8CvybayR8VFRUxjrT19HiHXfKfNL0fi1x uZAGvP9nZK2lvetEgCLmllsrDVOqrooYOAY18Oh8Bqr6tBeP/Kv/WjFYJkjoHNewokFt 1p8JZEcRaMC+4jp6pZSrlnKL4IGsBAajD+uPnI9v6PVudKpN6BIEX2GMj2ZyapGCi+L0 Wt3a7OyFWo+VA//8cgCwbLO2VDlLYrUL872wQvbTPdNNbBSVgUIYxbyj8n0w/0WdxRHZ 3pSRhv4SEKE/Bcgc2C7fBU8fm7W5O/lxdv3WmpgbWyhKmAPXbKPjnAFCAr3Fkit4VX/o W+BA== X-Gm-Message-State: AOAM533s/UEgFnxReLBuhcoB2dPPiiUy4EcEXH12mov/YPQJ6YefT8zp U9/juqRjSsrY9ZtlE/mGMZse2jqJQPs= X-Google-Smtp-Source: ABdhPJwVqOaLLTOsAFXe7H2DrUpM4AjNGa3ENYnyWHTSNot0jahAIZOQE0GVR+TBjQ6kE1cm0gpXEbB0OFA= X-Received: from seanjc.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3e5]) (user=seanjc job=sendgmr) by 2002:a17:902:bf06:b0:14d:8c72:96c6 with SMTP id bi6-20020a170902bf0600b0014d8c7296c6mr13129728plb.156.1648861757108; Fri, 01 Apr 2022 18:09:17 -0700 (PDT) Reply-To: Sean Christopherson Date: Sat, 2 Apr 2022 01:09:02 +0000 In-Reply-To: <20220402010903.727604-1-seanjc@google.com> Message-Id: <20220402010903.727604-8-seanjc@google.com> Mime-Version: 1.0 References: <20220402010903.727604-1-seanjc@google.com> X-Mailer: git-send-email 2.35.1.1094.g7c7d902a7c-goog Subject: [PATCH 7/8] KVM: x86: Trace re-injected exceptions From: Sean Christopherson To: Paolo Bonzini Cc: Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, "Maciej S . Szmigiero" Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Trace exceptions that are re-injected, not just those that KVM is injecting for the first time. Debugging re-injection bugs is painful enough as is, not having visibility into what KVM is doing only makes things worse. Signed-off-by: Sean Christopherson --- arch/x86/kvm/x86.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 7a066cf92692..384091600bc2 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -9382,6 +9382,10 @@ int kvm_check_nested_events(struct kvm_vcpu *vcpu) static void kvm_inject_exception(struct kvm_vcpu *vcpu) { + trace_kvm_inj_exception(vcpu->arch.exception.nr, + vcpu->arch.exception.has_error_code, + vcpu->arch.exception.error_code); + if (vcpu->arch.exception.error_code && !is_protmode(vcpu)) vcpu->arch.exception.error_code = false; static_call(kvm_x86_queue_exception)(vcpu); @@ -9439,10 +9443,6 @@ static int inject_pending_event(struct kvm_vcpu *vcpu, bool *req_immediate_exit) /* try to inject new event if pending */ if (vcpu->arch.exception.pending) { - trace_kvm_inj_exception(vcpu->arch.exception.nr, - vcpu->arch.exception.has_error_code, - vcpu->arch.exception.error_code); - vcpu->arch.exception.pending = false; vcpu->arch.exception.injected = true; From patchwork Sat Apr 2 01:09:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 12798895 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E4EFCC433FE for ; Sat, 2 Apr 2022 01:09:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353654AbiDBBLQ (ORCPT ); Fri, 1 Apr 2022 21:11:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44324 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353623AbiDBBLN (ORCPT ); Fri, 1 Apr 2022 21:11:13 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5F1C5A0BF0 for ; Fri, 1 Apr 2022 18:09:19 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id z132-20020a63338a000000b003844e317066so2342537pgz.19 for ; Fri, 01 Apr 2022 18:09:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=reply-to:date:in-reply-to:message-id:mime-version:references :subject:from:to:cc; bh=OExX1Igb+SEI7PdUVeKXKi/G1aHbfTSQe6uvI8ZE66s=; b=QoWYxsIze+C3Ee47cmi+k5goTPGx2Io4H2IyLGbi5BL+YuSOtk8JZB9VbBiKfn+5KE tyrkF6Zyy4naj8XbTkWvhkg/sFU+thgF+DR7zGxHaU0Zufu1ol74uxq4AXOtb0GAHX2+ RCwbWhRxvZMYnWlv5Pel0agogKAldZa+yRq1pBY6qslSIaYI1EsqNARyskD1VinUqj37 0o4B7ukkXknlytvlvFrKfIN3Log0v9sa7s+sDwVihw3X5My32CK4QQgkdwX9QMxI0OCg rolELI0I7ldjj+6WJTt4XTF7oYy1R+nt/GzVXksOb23zb7L7SLrRPoB+qBeferqjl3zT i/Qg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:reply-to:date:in-reply-to:message-id :mime-version:references:subject:from:to:cc; bh=OExX1Igb+SEI7PdUVeKXKi/G1aHbfTSQe6uvI8ZE66s=; b=HnZcxJDQbufhMX5sc07BrIeRVoNc2vWa5AKhXUWjb90m0odlGXAcXdWRdeYsVrqJRA ejou8ulPgE4adZmakpRo4icmV4KboPhVZg0EbO19mOyNbkHkhdWkHqfXdjDnpeFmmFSb 4sjfcqp9553Uw4VrXtbdWxPzT0ADQpT96Yuc51OPQnFyW/aAPtjCSZlEF0NAiFN8qWZT VYxak3AVDk+VEN9O8EWHTLCHjN2hs/ueVy0rS6BxDEFsUn94FquIySvZgbpqW09zFRjW k2jhwNiu3tCSxdXhAf8kwq7ZEJK4J6pX5xg1MjeWgtZdKsAkRL8vxBNjsjpnlg1lL1cW e0Mg== X-Gm-Message-State: AOAM531iT5fUatJSiaSbhgioGT4wPYpZM4epNL9VE8hwSEsIMnrf3XYx OG0fZEq0Y4nGL563aWEOUsxuB6akubY= X-Google-Smtp-Source: ABdhPJySbHKlONilMxgSTz0tRz1iIrI+IQGst6MP1o+Dhm9cpdIUyvg75yFzuaUSapncQePMHGO9Y0zty3A= X-Received: from seanjc.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3e5]) (user=seanjc job=sendgmr) by 2002:a63:6d4c:0:b0:398:7c40:c160 with SMTP id i73-20020a636d4c000000b003987c40c160mr17309928pgc.109.1648861758524; Fri, 01 Apr 2022 18:09:18 -0700 (PDT) Reply-To: Sean Christopherson Date: Sat, 2 Apr 2022 01:09:03 +0000 In-Reply-To: <20220402010903.727604-1-seanjc@google.com> Message-Id: <20220402010903.727604-9-seanjc@google.com> Mime-Version: 1.0 References: <20220402010903.727604-1-seanjc@google.com> X-Mailer: git-send-email 2.35.1.1094.g7c7d902a7c-goog Subject: [PATCH 8/8] KVM: selftests: nSVM: Add svm_nested_soft_inject_test From: Sean Christopherson To: Paolo Bonzini Cc: Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, "Maciej S . Szmigiero" Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Maciej S. Szmigiero Add a KVM self-test that checks whether a nSVM L1 is able to successfully inject a software interrupt and a soft exception into its L2 guest. In practice, this tests both the next_rip field consistency and L1-injected event with intervening L0 VMEXIT during its delivery: the first nested VMRUN (that's also trying to inject a software interrupt) will immediately trigger a L0 NPF. This L0 NPF will have zero in its CPU-returned next_rip field, which if incorrectly reused by KVM will trigger a #PF when trying to return to such address 0 from the interrupt handler. Signed-off-by: Maciej S. Szmigiero Signed-off-by: Sean Christopherson Reviewed-by: Maxim levitsky --- tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/include/x86_64/svm_util.h | 2 + .../kvm/x86_64/svm_nested_soft_inject_test.c | 147 ++++++++++++++++++ 4 files changed, 151 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86_64/svm_nested_soft_inject_test.c diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore index 1f1b6c978bf7..1354d3f4a362 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -33,6 +33,7 @@ /x86_64/state_test /x86_64/svm_vmcall_test /x86_64/svm_int_ctl_test +/x86_64/svm_nested_soft_inject_test /x86_64/sync_regs_test /x86_64/tsc_msrs_test /x86_64/userspace_io_test diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index c9cdbd248727..cef6d583044b 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -66,6 +66,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/state_test TEST_GEN_PROGS_x86_64 += x86_64/vmx_preemption_timer_test TEST_GEN_PROGS_x86_64 += x86_64/svm_vmcall_test TEST_GEN_PROGS_x86_64 += x86_64/svm_int_ctl_test +TEST_GEN_PROGS_x86_64 += x86_64/svm_nested_soft_inject_test TEST_GEN_PROGS_x86_64 += x86_64/tsc_scaling_sync TEST_GEN_PROGS_x86_64 += x86_64/sync_regs_test TEST_GEN_PROGS_x86_64 += x86_64/userspace_io_test diff --git a/tools/testing/selftests/kvm/include/x86_64/svm_util.h b/tools/testing/selftests/kvm/include/x86_64/svm_util.h index a25aabd8f5e7..d49f7c9b4564 100644 --- a/tools/testing/selftests/kvm/include/x86_64/svm_util.h +++ b/tools/testing/selftests/kvm/include/x86_64/svm_util.h @@ -16,6 +16,8 @@ #define CPUID_SVM_BIT 2 #define CPUID_SVM BIT_ULL(CPUID_SVM_BIT) +#define SVM_EXIT_EXCP_BASE 0x040 +#define SVM_EXIT_HLT 0x078 #define SVM_EXIT_MSR 0x07c #define SVM_EXIT_VMMCALL 0x081 diff --git a/tools/testing/selftests/kvm/x86_64/svm_nested_soft_inject_test.c b/tools/testing/selftests/kvm/x86_64/svm_nested_soft_inject_test.c new file mode 100644 index 000000000000..d39be5d885c1 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/svm_nested_soft_inject_test.c @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022 Oracle and/or its affiliates. + * + * Based on: + * svm_int_ctl_test + * + * Copyright (C) 2021, Red Hat, Inc. + * + */ + +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" +#include "svm_util.h" + +#define VCPU_ID 0 +#define INT_NR 0x20 +#define X86_FEATURE_NRIPS BIT(3) + +#define vmcall() \ + __asm__ __volatile__( \ + "vmmcall\n" \ + ) + +#define ud2() \ + __asm__ __volatile__( \ + "ud2\n" \ + ) + +#define hlt() \ + __asm__ __volatile__( \ + "hlt\n" \ + ) + +static unsigned int bp_fired; +static void guest_bp_handler(struct ex_regs *regs) +{ + bp_fired++; +} + +static unsigned int int_fired; +static void guest_int_handler(struct ex_regs *regs) +{ + int_fired++; +} + +static void l2_guest_code(void) +{ + GUEST_ASSERT(int_fired == 1); + vmcall(); + ud2(); + + GUEST_ASSERT(bp_fired == 1); + hlt(); +} + +static void l1_guest_code(struct svm_test_data *svm) +{ + #define L2_GUEST_STACK_SIZE 64 + unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; + struct vmcb *vmcb = svm->vmcb; + + /* Prepare for L2 execution. */ + generic_svm_setup(svm, l2_guest_code, + &l2_guest_stack[L2_GUEST_STACK_SIZE]); + + vmcb->control.intercept_exceptions |= BIT(PF_VECTOR) | BIT(UD_VECTOR); + vmcb->control.intercept |= BIT(INTERCEPT_HLT); + + vmcb->control.event_inj = INT_NR | SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_SOFT; + /* The return address pushed on stack */ + vmcb->control.next_rip = vmcb->save.rip; + + run_guest(vmcb, svm->vmcb_gpa); + GUEST_ASSERT_3(vmcb->control.exit_code == SVM_EXIT_VMMCALL, + vmcb->control.exit_code, + vmcb->control.exit_info_1, vmcb->control.exit_info_2); + + /* Skip over VMCALL */ + vmcb->save.rip += 3; + + vmcb->control.event_inj = BP_VECTOR | SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_EXEPT; + /* The return address pushed on stack, skip over UD2 */ + vmcb->control.next_rip = vmcb->save.rip + 2; + + run_guest(vmcb, svm->vmcb_gpa); + GUEST_ASSERT_3(vmcb->control.exit_code == SVM_EXIT_HLT, + vmcb->control.exit_code, + vmcb->control.exit_info_1, vmcb->control.exit_info_2); + + GUEST_DONE(); +} + +int main(int argc, char *argv[]) +{ + struct kvm_cpuid_entry2 *cpuid; + struct kvm_vm *vm; + vm_vaddr_t svm_gva; + struct kvm_guest_debug debug; + + nested_svm_check_supported(); + + cpuid = kvm_get_supported_cpuid_entry(0x8000000a); + if (!(cpuid->edx & X86_FEATURE_NRIPS)) { + print_skip("nRIP Save unavailable"); + exit(KSFT_SKIP); + } + + vm = vm_create_default(VCPU_ID, 0, (void *) l1_guest_code); + + vm_init_descriptor_tables(vm); + vcpu_init_descriptor_tables(vm, VCPU_ID); + + vm_install_exception_handler(vm, BP_VECTOR, guest_bp_handler); + vm_install_exception_handler(vm, INT_NR, guest_int_handler); + + vcpu_alloc_svm(vm, &svm_gva); + vcpu_args_set(vm, VCPU_ID, 1, svm_gva); + + memset(&debug, 0, sizeof(debug)); + vcpu_set_guest_debug(vm, VCPU_ID, &debug); + + struct kvm_run *run = vcpu_state(vm, VCPU_ID); + struct ucall uc; + + vcpu_run(vm, VCPU_ID); + TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, + "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n", + run->exit_reason, + exit_reason_str(run->exit_reason)); + + switch (get_ucall(vm, VCPU_ID, &uc)) { + case UCALL_ABORT: + TEST_FAIL("%s at %s:%ld, vals = 0x%lx 0x%lx 0x%lx", (const char *)uc.args[0], + __FILE__, uc.args[1], uc.args[2], uc.args[3], uc.args[4]); + break; + /* NOT REACHED */ + case UCALL_DONE: + goto done; + default: + TEST_FAIL("Unknown ucall 0x%lx.", uc.cmd); + } +done: + kvm_vm_free(vm); + return 0; +}