From nobody Wed Apr 8 04:46:08 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 43B123EBF1C for ; Tue, 10 Mar 2026 20:24:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773174272; cv=none; b=e3Ubdhysn85e1cXfp4WFAdNyXh79SXWLv404baIqBoA2Vw9L6PIeVJhhGVHH/TV/lScvFFaplEbK71xHosHgqeYdXNhUypjFMt+GRsMvgoUOvAMKiUwNjQaT+3ZhFAQKyvK4dNXXutgAZaX3Rr1/IYacEzyj+pyqnuxkAVDq/Vo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773174272; c=relaxed/simple; bh=6rB+UB1kEMw6k+b86L/qIAQ+B3zVuFeQgsyZVjk7hWQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tZsIYcVRg6hk36SoW4tbTAvQW4kyvHoQ292CfoaZOvkbFdfW15C3/Ees0+sJDDZ/6Rr9mkGtr09nziGPZ30VzPD8BIzGljBRZXhX6yHYH1OfkSuGOiFdEP6NYV7Y7Gg3DY/kSEbOk2ozFq7tJ57gGykcydNV+Tg15odWphkl28I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=GRnmBCBW; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b=sj0pN6aW; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="GRnmBCBW"; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b="sj0pN6aW" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1773174270; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=LhOFlLPWZiB7d69MOKPXsBv2+W178XJ/rSiUNGxujFE=; b=GRnmBCBWVgX/ICtNtfCELovM0I7rVsgAsDDEtXrfIM33m+S/z15209NkHTUQ8lt9/OYC/R KakuVfpAVUM+dLTit1qh3qYESqlG2kVYf8kBGPXY2cJWILLc/Z5LtGGNpq0Vo+Q3ozCNsQ 9O6fYjYd5CGtKezjtzdMKYLr5vsJzfg= Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-551-am6PLJVUP_WqAF2ywXvtgw-1; Tue, 10 Mar 2026 16:24:29 -0400 X-MC-Unique: am6PLJVUP_WqAF2ywXvtgw-1 X-Mimecast-MFC-AGG-ID: am6PLJVUP_WqAF2ywXvtgw_1773174268 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-485335f4466so26899205e9.0 for ; Tue, 10 Mar 2026 13:24:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1773174267; x=1773779067; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=LhOFlLPWZiB7d69MOKPXsBv2+W178XJ/rSiUNGxujFE=; b=sj0pN6aWy7LJUle2fB1hMlJCxRMLDCO4I9jD/Bm6f4n+Uiq5er5AsPY5cvdmrKUOgi jiwcQqwuF356KdHXBFptjDxeriBZ/eEYauIuG7Dxw/ZI6gstZQ5YgP1vjBGapSgYn38B 5hn4gD9M8VDqFjgXfQk2Rr1nOeZPOJl9fxWAKdKQ7KqrtPRPMWdvKFhIvPQnGbyEVaCD a5YyiakLduzGrFyAmRboGpm/imrzuEKRICX/FP0Gmhhv5Uxwa9+uMCGZoDq1Xvbv7kg8 FWjEryjEeB6C/7qYcQNHeMb01hoPXgcVTZ5TbKWt9MyU2eDsJdL+rTo8FchxKirMipt2 aVdw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773174267; x=1773779067; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=LhOFlLPWZiB7d69MOKPXsBv2+W178XJ/rSiUNGxujFE=; b=CnAuKQSEpH2vNGgvPsi1yFw7uRyonSPrUPKex2bbAxsZSXGYctdirV8SEzG4A9vfWE E7R04WBgn2o2HfzJTQKlKkiQ6zHHKJm0rGb6iwZy5SlEcF/6If7HwFaL8ELd0wlzjGwG Z3HbxY7Mya6MwZnnmxsjlpbc53dvInv7f+tWo/THyCouO6c5+JAwNaWlrHdk7SwwRBhO XwqOPz7N4AHG/TPlSs9f7fKaqmWnK4VM4POFx64jIBHDAnmhCC58mpdIs0IIrq2hZ1eI gCQJaz9gq+I5cBXXS3L94SwpcchcrmM+MibLP55F5EG+e9IYF/0RVewsCK83Ggt1DjCB +2IA== X-Gm-Message-State: AOJu0Yzs88HXY05UEVpDa1UeMQRte8ztZvWDDOaTGvPgdI9tTV2Rhn97 BN7CBCGOK7GxJaflUNJO6xVyXXNyzxng0NVoAbECqpltkbDD0BRY4XKCIKd8EsBJq1BjuuFRetE zS7nau2LGfegq9AaM+JHTkNqIDRLM6AIYpnqjIU0cEG9sesBS94yXFzgymYkM4g9tVwNLOKCFJc MCK/fioRuTqS/5YZor9iMp81WXsBwvlfWBtTSPzh7kz37kIzMoFA== X-Gm-Gg: ATEYQzxal8Ut9x0AKO8UGlga9ivtMOscxtp5ji99J4b5keOqvVvV/60WQrglzfBRdxL Cv+Tw7hvpfse73cyvjsQ9S6c4z92f75tmqtUlCThXipupEmrlHIsi64z/kh348UTAehHhZBnZ8h 1yGOzorB5nd7iTmgSgM3DCZqNSrOkT12HHitSkyq7F6/hlMBHptfp9Zp22HqheNVeffJ3L8q8+M adixuVrFmEcKmtZbbSi2fg97gnTevLswIUHX/Z787QqepvykZBgOB4BGL9r3gtDe3NSgS1MEWp5 vRYXEfqDV2dSgTBkSfP3lYzOou3yE7/lLs6PRXSppDeIRGNTBwnlNbFRrhHxOHavdylVBBZmlJz 3TPoj00eM2RDk/Nn48guXyyI+lebqFCrAyHMvOZG1noCxu2Y0UqnufH4eVLo7jj/6OWK8MlL5aq /cNmK/NTdsk5r7KSGzuZl6KSpZNo0= X-Received: by 2002:a05:600c:4f95:b0:483:3380:ca11 with SMTP id 5b1f17b1804b1-4854b13e0f6mr1539545e9.33.1773174266638; Tue, 10 Mar 2026 13:24:26 -0700 (PDT) X-Received: by 2002:a05:600c:4f95:b0:483:3380:ca11 with SMTP id 5b1f17b1804b1-4854b13e0f6mr1538915e9.33.1773174265985; Tue, 10 Mar 2026 13:24:25 -0700 (PDT) Received: from [192.168.10.48] ([151.95.144.138]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4854a307bc4sm4723665e9.3.2026.03.10.13.24.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 10 Mar 2026 13:24:24 -0700 (PDT) From: Paolo Bonzini To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: seanjc@google.com, xinyang@anthropic.com, stable@vger.kernel.org Subject: [PATCH 4/5] selftests: kvm: add a test that VMX validates controls on RSM Date: Tue, 10 Mar 2026 21:24:13 +0100 Message-ID: <20260310202414.406078-5-pbonzini@redhat.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260310202414.406078-1-pbonzini@redhat.com> References: <20260310202414.406078-1-pbonzini@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a test checking that invalid eVMCS contents are validated after an RSM instruction is emulated. The failure mode is simply that the RSM succeeds, because KVM virtualizes NMIs anyway while running L2; the two pin-based execution controls used by the test are entirely handled by KVM and not by the processor. Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini --- tools/testing/selftests/kvm/Makefile.kvm | 1 + .../kvm/x86/evmcs_smm_controls_test.c | 150 ++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/evmcs_smm_controls_test= .c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index fdec90e85467..dc68371f76a3 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -71,6 +71,7 @@ TEST_GEN_PROGS_x86 +=3D x86/cpuid_test TEST_GEN_PROGS_x86 +=3D x86/cr4_cpuid_sync_test TEST_GEN_PROGS_x86 +=3D x86/dirty_log_page_splitting_test TEST_GEN_PROGS_x86 +=3D x86/feature_msrs_test +TEST_GEN_PROGS_x86 +=3D x86/evmcs_smm_controls_test TEST_GEN_PROGS_x86 +=3D x86/exit_on_emulation_failure_test TEST_GEN_PROGS_x86 +=3D x86/fastops_test TEST_GEN_PROGS_x86 +=3D x86/fix_hypercall_test diff --git a/tools/testing/selftests/kvm/x86/evmcs_smm_controls_test.c b/to= ols/testing/selftests/kvm/x86/evmcs_smm_controls_test.c new file mode 100644 index 000000000000..af7c90103396 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/evmcs_smm_controls_test.c @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2026, Red Hat, Inc. + * + * Test that vmx_leave_smm() validates vmcs12 controls before re-entering + * nested guest mode on RSM. + */ +#include +#include +#include +#include +#include + +#include "test_util.h" +#include "kvm_util.h" +#include "smm.h" +#include "hyperv.h" +#include "vmx.h" + +#define SMRAM_GPA 0x1000000 +#define SMRAM_STAGE 0xfe + +#define SYNC_PORT 0xe + +#define STR(x) #x +#define XSTR(s) STR(s) + +/* + * SMI handler: runs in real-address mode. + * Reports SMRAM_STAGE via port IO, then does RSM. + */ +static uint8_t smi_handler[] =3D { + 0xb0, SMRAM_STAGE, /* mov $SMRAM_STAGE, %al */ + 0xe4, SYNC_PORT, /* in $SYNC_PORT, %al */ + 0x0f, 0xaa, /* rsm */ +}; + +static inline void sync_with_host(uint64_t phase) +{ + asm volatile("in $" XSTR(SYNC_PORT) ", %%al \n" + : "+a" (phase)); +} + +static void l2_guest_code(void) +{ + sync_with_host(1); + + /* After SMI+RSM with invalid controls, we should not reach here. */ + vmcall(); +} + +static void guest_code(struct vmx_pages *vmx_pages, + struct hyperv_test_pages *hv_pages) +{ +#define L2_GUEST_STACK_SIZE 64 + unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; + + /* Set up Hyper-V enlightenments and eVMCS */ + wrmsr(HV_X64_MSR_GUEST_OS_ID, HYPERV_LINUX_OS_ID); + enable_vp_assist(hv_pages->vp_assist_gpa, hv_pages->vp_assist); + evmcs_enable(); + + GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); + GUEST_ASSERT(load_evmcs(hv_pages)); + prepare_vmcs(vmx_pages, l2_guest_code, + &l2_guest_stack[L2_GUEST_STACK_SIZE]); + + GUEST_ASSERT(!vmlaunch()); + + /* L2 exits via vmcall if test fails */ + sync_with_host(2); +} + +int main(int argc, char *argv[]) +{ + vm_vaddr_t vmx_pages_gva =3D 0, hv_pages_gva =3D 0; + struct hyperv_test_pages *hv; + struct hv_enlightened_vmcs *evmcs; + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + struct kvm_regs regs; + int stage_reported; + + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX)); + TEST_REQUIRE(kvm_has_cap(KVM_CAP_NESTED_STATE)); + TEST_REQUIRE(kvm_has_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS)); + TEST_REQUIRE(kvm_has_cap(KVM_CAP_X86_SMM)); + + vm =3D vm_create_with_one_vcpu(&vcpu, guest_code); + + setup_smram(vm, vcpu, SMRAM_GPA, smi_handler, sizeof(smi_handler)); + + vcpu_set_hv_cpuid(vcpu); + vcpu_enable_evmcs(vcpu); + vcpu_alloc_vmx(vm, &vmx_pages_gva); + hv =3D vcpu_alloc_hyperv_test_pages(vm, &hv_pages_gva); + vcpu_args_set(vcpu, 2, vmx_pages_gva, hv_pages_gva); + + vcpu_run(vcpu); + + /* L2 is running and syncs with host. */ + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + vcpu_regs_get(vcpu, ®s); + stage_reported =3D regs.rax & 0xff; + TEST_ASSERT(stage_reported =3D=3D 1, + "Expected stage 1, got %d", stage_reported); + + /* Inject SMI while L2 is running. */ + inject_smi(vcpu); + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + vcpu_regs_get(vcpu, ®s); + stage_reported =3D regs.rax & 0xff; + TEST_ASSERT(stage_reported =3D=3D SMRAM_STAGE, + "Expected SMM handler stage %#x, got %#x", + SMRAM_STAGE, stage_reported); + + /* + * Guest is now paused in the SMI handler, about to execute RSM. + * Hack the eVMCS page to set-up invalid pin-based execution + * control (PIN_BASED_VIRTUAL_NMIS without PIN_BASED_NMI_EXITING). + */ + evmcs =3D hv->enlightened_vmcs_hva; + evmcs->pin_based_vm_exec_control |=3D PIN_BASED_VIRTUAL_NMIS; + evmcs->hv_clean_fields =3D 0; + + /* + * Trigger copy_enlightened_to_vmcs12() via KVM_GET_NESTED_STATE, + * copying the invalid pin_based_vm_exec_control into cached_vmcs12. + */ + union { + struct kvm_nested_state state; + char state_[16384]; + } nested_state_buf; + + memset(&nested_state_buf, 0, sizeof(nested_state_buf)); + nested_state_buf.state.size =3D sizeof(nested_state_buf); + vcpu_nested_state_get(vcpu, &nested_state_buf.state); + + /* + * Resume the guest. The SMI handler executes RSM, which calls + * vmx_leave_smm(). nested_vmx_check_controls() should detect + * VIRTUAL_NMIS without NMI_EXITING and cause a triple fault. + */ + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_SHUTDOWN); + + kvm_vm_free(vm); + return 0; +} --=20 2.53.0