From nobody Wed May 7 22:59:33 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.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 EFB1A2248A8 for <linux-kernel@vger.kernel.org>; Tue, 1 Apr 2025 16:12:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1743523954; cv=none; b=KAFb0MRXYV6bV2Kh63OPUrwHEbwU3VWpreT8k8jxTV1o4YxuUViEE9i9LL2jB+Tt4h0lVcv4owi550XWBd94uuHTPz616NHcKCEKiqRMYYs/TX3Oy5tAb5bIsWFNsUFx4/SflkdFY0XmBNb6qlTuV3WwVfjUNyt7OrIYXdcQ0wU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1743523954; c=relaxed/simple; bh=qiOLED8BkRze4KF+KMmrHA+MJ7cag8ndXy7QMTI4Sw0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=afEhdOCC2dvo0TCxk5xyc4NVAP0mzw5HhgqprbKPJZCEqqKq2lcZEOW7wzxtt9SzrvWNA7ZiyQ5n76fkMEwGtYv0NTPutUa73zCqx3GVh1lzPMzm2RxpTPVCV3LpwBYym4ydMywrsCGd7Lb3q3DXx2P9mr+NZgvSCcgtutMtamA= 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=e8ltetUC; arc=none smtp.client-ip=170.10.133.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="e8ltetUC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1743523951; 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=tPLDTEU28EVlLVRImtt+kppWrpwzBYCScgMp8fqLlvI=; b=e8ltetUCCmMGBy/1mpEaWFftDwNG9z4/kkdfB+8Cv+M8SLU7KESbJFUHmCS6cfg3P4h94Y In4/2KWLQOOCKu2U/p1HRrJqoudu3nduG/jWcU6WGvZj+XLRqzbk5JBk1f6kD3os456DXM LNosIUg9Lp/u8iP5bBfydTso8VShbS8= Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-668-wT1Mo0l-Nki21hqXOOh8OQ-1; Tue, 01 Apr 2025 12:12:30 -0400 X-MC-Unique: wT1Mo0l-Nki21hqXOOh8OQ-1 X-Mimecast-MFC-AGG-ID: wT1Mo0l-Nki21hqXOOh8OQ_1743523949 Received: by mail-wr1-f69.google.com with SMTP id ffacd0b85a97d-3913aaf1e32so3298653f8f.0 for <linux-kernel@vger.kernel.org>; Tue, 01 Apr 2025 09:12:30 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1743523949; x=1744128749; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tPLDTEU28EVlLVRImtt+kppWrpwzBYCScgMp8fqLlvI=; b=nnc5wqt1s5BMbOHxVkFuky6vO5hIz2KTp8M551rWWbsKPeJ6WI+vmSFy3Gy1dcS6Yy 3LijgFkUld0/g5hqoEytCKJrJneMnqpOMkMw77zqhbMXw2X3j0kM9n40GWwa2bFybwZS cnq08FBPLYXZIQFJU50TeIA75PQG9JyC1J+IuFTjlmZ5ar616/rC6f0FCtVasyiElSij shK7Ba2hxvNpKZravXV/TmgsLUx1IUdUgXpb3vrhfVfW2sYa4gklKIa040DP+JrH/Ypw vFOtAQVXhwWZKDy2O/JXPGPkocBi5Qo5R9q+IrKT0vLmq2qa5kqHiDA7ASzmUSsw85yi 3vRg== X-Gm-Message-State: AOJu0Yzl1ZzwemtH6bBPorHce3gQMvL8UMrzNHkU9/+M0wAFePaHfCm3 s/rWCfVVzWgNhHHmYSmk93VffC1jSWcKOXq18gB1/gSbWhCL33Gch1pTwV9NY5G+4rp44Qdv7op Lcd6JZPNxx2WM5XAsKspm2/YxVDK2nZ9OiW+LdZ5Ch03hjBVJfcW2BaQORyW0VI5++Vo2Gagum9 UNk9Kk1ssvGGkDQGcVquPUaDdUBtBk2dnOJ59J0+myzfV3xA== X-Gm-Gg: ASbGncv8BHzArJsqxDmo++CNWsq7CZYcKevnkbGwFdw+pONmSpfS95Ta5t8BOB/6oyp RScBMrCDrmT0DzXNyJz4raa4H0L6a/dWsePoxbYKDzZIApE5hH6vWF9KYCRFj8kqxUBsq/R1TCm +UHUDeVLwmojphc/sNqEROJrmDdyUsajlhBZVUVhOjdvr2nLOf0qeIFWSjNmFZ10fMpFDqAsFfr hgcKWyb9JIvNE2RtCQU4WtnL8ThFoCwMZ5K6LPuIPEtpjj4IqrL/gZxOORP4uN5It2U4qb+dx9G JlJWNmVTlHXyHgBfrLEYDg== X-Received: by 2002:a05:6000:2913:b0:391:122c:8b2 with SMTP id ffacd0b85a97d-39c120e1566mr11925050f8f.31.1743523948584; Tue, 01 Apr 2025 09:12:28 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEEasAFSdvxOC3yWEZX6iq1LZ/fATrSFrxZYBcxLlTIQzYSIpNJNzx61Lq79fmq0JTbS0oYjw== X-Received: by 2002:a05:6000:2913:b0:391:122c:8b2 with SMTP id ffacd0b85a97d-39c120e1566mr11924994f8f.31.1743523948129; Tue, 01 Apr 2025 09:12:28 -0700 (PDT) Received: from [192.168.10.48] ([176.206.111.201]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43ea8d2bc7fsm13944985e9.0.2025.04.01.09.12.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Apr 2025 09:12:26 -0700 (PDT) From: Paolo Bonzini <pbonzini@redhat.com> To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: roy.hopkins@suse.com, seanjc@google.com, thomas.lendacky@amd.com, ashish.kalra@amd.com, michael.roth@amd.com, jroedel@suse.de, nsaenz@amazon.com, anelkz@amazon.de, James.Bottomley@HansenPartnership.com Subject: [PATCH 29/29] selftests: kvm: add x86-specific plane test Date: Tue, 1 Apr 2025 18:11:06 +0200 Message-ID: <20250401161106.790710-30-pbonzini@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250401161106.790710-1-pbonzini@redhat.com> References: <20250401161106.790710-1-pbonzini@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: <linux-kernel.vger.kernel.org> List-Subscribe: <mailto:linux-kernel+subscribe@vger.kernel.org> List-Unsubscribe: <mailto:linux-kernel+unsubscribe@vger.kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a new test for x86-specific behavior such as vCPU state sharing and interrupts. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- tools/testing/selftests/kvm/Makefile.kvm | 1 + .../selftests/kvm/include/x86/processor.h | 1 + .../testing/selftests/kvm/lib/x86/processor.c | 15 + tools/testing/selftests/kvm/x86/plane_test.c | 270 ++++++++++++++++++ 4 files changed, 287 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/plane_test.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index b1d0b410cc03..9d94db9d750f 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -82,6 +82,7 @@ TEST_GEN_PROGS_x86 +=3D x86/kvm_pv_test TEST_GEN_PROGS_x86 +=3D x86/monitor_mwait_test TEST_GEN_PROGS_x86 +=3D x86/nested_emulation_test TEST_GEN_PROGS_x86 +=3D x86/nested_exceptions_test +TEST_GEN_PROGS_x86 +=3D x86/plane_test TEST_GEN_PROGS_x86 +=3D x86/platform_info_test TEST_GEN_PROGS_x86 +=3D x86/pmu_counters_test TEST_GEN_PROGS_x86 +=3D x86/pmu_event_filter_test diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/te= sting/selftests/kvm/include/x86/processor.h index 32ab6ca7ec32..cf2095f3a7d5 100644 --- a/tools/testing/selftests/kvm/include/x86/processor.h +++ b/tools/testing/selftests/kvm/include/x86/processor.h @@ -1106,6 +1106,7 @@ static inline void vcpu_clear_cpuid_feature(struct kv= m_vcpu *vcpu, =20 uint64_t vcpu_get_msr(struct kvm_vcpu *vcpu, uint64_t msr_index); int _vcpu_set_msr(struct kvm_vcpu *vcpu, uint64_t msr_index, uint64_t msr_= value); +int _plane_vcpu_set_msr(struct kvm_plane_vcpu *plane_vcpu, uint64_t msr_in= dex, uint64_t msr_value); =20 /* * Assert on an MSR access(es) and pretty print the MSR name when possible. diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testin= g/selftests/kvm/lib/x86/processor.c index bd5a802fa7a5..b4431ca7fbca 100644 --- a/tools/testing/selftests/kvm/lib/x86/processor.c +++ b/tools/testing/selftests/kvm/lib/x86/processor.c @@ -917,6 +917,21 @@ uint64_t vcpu_get_msr(struct kvm_vcpu *vcpu, uint64_t = msr_index) return buffer.entry.data; } =20 +int _plane_vcpu_set_msr(struct kvm_plane_vcpu *plane_vcpu, uint64_t msr_in= dex, uint64_t msr_value) +{ + struct { + struct kvm_msrs header; + struct kvm_msr_entry entry; + } buffer =3D {}; + + memset(&buffer, 0, sizeof(buffer)); + buffer.header.nmsrs =3D 1; + buffer.entry.index =3D msr_index; + buffer.entry.data =3D msr_value; + + return __plane_vcpu_ioctl(plane_vcpu, KVM_SET_MSRS, &buffer.header); +} + int _vcpu_set_msr(struct kvm_vcpu *vcpu, uint64_t msr_index, uint64_t msr_= value) { struct { diff --git a/tools/testing/selftests/kvm/x86/plane_test.c b/tools/testing/s= elftests/kvm/x86/plane_test.c new file mode 100644 index 000000000000..0fdd8a066723 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/plane_test.c @@ -0,0 +1,270 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2025 Red Hat, Inc. + * + * Test for x86-specific VM plane functionality + */ +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "test_util.h" + +#include "kvm_util.h" +#include "processor.h" +#include "apic.h" +#include "asm/kvm.h" +#include "linux/kvm.h" + +static void test_plane_regs(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + struct kvm_plane *plane; + struct kvm_plane_vcpu *plane_vcpu; + + struct kvm_regs regs0, regs1; + + vm =3D vm_create_barebones(); + vcpu =3D __vm_vcpu_add(vm, 0); + plane =3D vm_plane_add(vm, 1); + plane_vcpu =3D __vm_plane_vcpu_add(vcpu, plane); + + vcpu_ioctl(vcpu, KVM_GET_REGS, ®s0); + plane_vcpu_ioctl(plane_vcpu, KVM_GET_REGS, ®s1); + regs0.rax =3D 0x12345678; + regs1.rax =3D 0x87654321; + + vcpu_ioctl(vcpu, KVM_SET_REGS, ®s0); + plane_vcpu_ioctl(plane_vcpu, KVM_SET_REGS, ®s1); + + vcpu_ioctl(vcpu, KVM_GET_REGS, ®s0); + plane_vcpu_ioctl(plane_vcpu, KVM_GET_REGS, ®s1); + TEST_ASSERT_EQ(regs0.rax, 0x12345678); + TEST_ASSERT_EQ(regs1.rax, 0x87654321); + + kvm_vm_free(vm); + ksft_test_result_pass("get/set regs for planes\n"); +} + +/* Offset of XMM0 in the legacy XSAVE area. */ +#define XSTATE_BV_OFFSET (0x200/4) +#define XMM_OFFSET (0xa0/4) +#define PKRU_OFFSET (0xa80/4) + +static void test_plane_fpu_nonshared(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + struct kvm_plane *plane; + struct kvm_plane_vcpu *plane_vcpu; + + struct kvm_xsave xsave0, xsave1; + + vm =3D vm_create_barebones(); + TEST_ASSERT_EQ(vm_check_cap(vm, KVM_CAP_PLANES_FPU), false); + + vcpu =3D __vm_vcpu_add(vm, 0); + vcpu_init_cpuid(vcpu, kvm_get_supported_cpuid()); + vcpu_set_cpuid(vcpu); + + plane =3D vm_plane_add(vm, 1); + plane_vcpu =3D __vm_plane_vcpu_add(vcpu, plane); + + vcpu_ioctl(vcpu, KVM_GET_XSAVE, &xsave0); + xsave0.region[XSTATE_BV_OFFSET] |=3D XFEATURE_MASK_FP | XFEATURE_MASK_SSE; + xsave0.region[XMM_OFFSET] =3D 0x12345678; + vcpu_ioctl(vcpu, KVM_SET_XSAVE, &xsave0); + + plane_vcpu_ioctl(plane_vcpu, KVM_GET_XSAVE, &xsave1); + xsave1.region[XSTATE_BV_OFFSET] |=3D XFEATURE_MASK_FP | XFEATURE_MASK_SSE; + xsave1.region[XMM_OFFSET] =3D 0x87654321; + plane_vcpu_ioctl(plane_vcpu, KVM_SET_XSAVE, &xsave1); + + memset(&xsave0, 0, sizeof(xsave0)); + vcpu_ioctl(vcpu, KVM_GET_XSAVE, &xsave0); + TEST_ASSERT_EQ(xsave0.region[XMM_OFFSET], 0x12345678); + + memset(&xsave1, 0, sizeof(xsave0)); + plane_vcpu_ioctl(plane_vcpu, KVM_GET_XSAVE, &xsave1); + TEST_ASSERT_EQ(xsave1.region[XMM_OFFSET], 0x87654321); + + ksft_test_result_pass("get/set FPU not shared across planes\n"); +} + +static void test_plane_fpu_shared(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + struct kvm_plane *plane; + struct kvm_plane_vcpu *plane_vcpu; + + struct kvm_xsave xsave0, xsave1; + + vm =3D vm_create_barebones(); + vm_enable_cap(vm, KVM_CAP_PLANES_FPU, 1ul); + TEST_ASSERT_EQ(vm_check_cap(vm, KVM_CAP_PLANES_FPU), true); + + vcpu =3D __vm_vcpu_add(vm, 0); + vcpu_init_cpuid(vcpu, kvm_get_supported_cpuid()); + vcpu_set_cpuid(vcpu); + + plane =3D vm_plane_add(vm, 1); + plane_vcpu =3D __vm_plane_vcpu_add(vcpu, plane); + + vcpu_ioctl(vcpu, KVM_GET_XSAVE, &xsave0); + + xsave0.region[XSTATE_BV_OFFSET] |=3D XFEATURE_MASK_FP | XFEATURE_MASK_SSE; + xsave0.region[XMM_OFFSET] =3D 0x12345678; + vcpu_ioctl(vcpu, KVM_SET_XSAVE, &xsave0); + plane_vcpu_ioctl(plane_vcpu, KVM_GET_XSAVE, &xsave1); + TEST_ASSERT_EQ(xsave1.region[XMM_OFFSET], 0x12345678); + + xsave1.region[XSTATE_BV_OFFSET] |=3D XFEATURE_MASK_FP | XFEATURE_MASK_SSE; + xsave1.region[XMM_OFFSET] =3D 0x87654321; + plane_vcpu_ioctl(plane_vcpu, KVM_SET_XSAVE, &xsave1); + vcpu_ioctl(vcpu, KVM_GET_XSAVE, &xsave0); + TEST_ASSERT_EQ(xsave0.region[XMM_OFFSET], 0x87654321); + + ksft_test_result_pass("get/set FPU shared across planes\n"); + + if (!this_cpu_has(X86_FEATURE_PKU)) { + ksft_test_result_skip("get/set PKRU with shared FPU\n"); + goto exit; + } + + xsave0.region[XSTATE_BV_OFFSET] =3D XFEATURE_MASK_PKRU; + xsave0.region[PKRU_OFFSET] =3D 0xffffffff; + vcpu_ioctl(vcpu, KVM_SET_XSAVE, &xsave0); + plane_vcpu_ioctl(plane_vcpu, KVM_GET_XSAVE, &xsave0); + + xsave0.region[XSTATE_BV_OFFSET] =3D XFEATURE_MASK_PKRU; + xsave0.region[PKRU_OFFSET] =3D 0xaaaaaaaa; + vcpu_ioctl(vcpu, KVM_SET_XSAVE, &xsave0); + plane_vcpu_ioctl(plane_vcpu, KVM_GET_XSAVE, &xsave1); + assert(xsave1.region[PKRU_OFFSET] =3D=3D 0xffffffff); + + xsave1.region[XSTATE_BV_OFFSET] =3D XFEATURE_MASK_PKRU; + xsave1.region[PKRU_OFFSET] =3D 0x55555555; + plane_vcpu_ioctl(plane_vcpu, KVM_SET_XSAVE, &xsave1); + vcpu_ioctl(vcpu, KVM_GET_XSAVE, &xsave0); + assert(xsave0.region[PKRU_OFFSET] =3D=3D 0xaaaaaaaa); + + ksft_test_result_pass("get/set PKRU with shared FPU\n"); + +exit: + kvm_vm_free(vm); +} + +#define APIC_SPIV 0xF0 +#define APIC_IRR 0x200 + +#define MYVEC 192 + +#define MAKE_MSI(cpu, vector) ((struct kvm_msi){ \ + .address_lo =3D APIC_DEFAULT_GPA + (((cpu) & 0xff) << 8), \ + .address_hi =3D (cpu) & ~0xff, \ + .data =3D (vector), \ +}) + +static bool has_irr(struct kvm_lapic_state *apic, int vector) +{ + int word =3D vector >> 5; + int bit_in_word =3D vector & 31; + int bit =3D (APIC_IRR + word * 16) * CHAR_BIT + (bit_in_word & 31); + + return apic->regs[bit >> 3] & (1 << (bit & 7)); +} + +static void do_enable_lapic(struct kvm_lapic_state *apic) +{ + /* set bit 8 */ + apic->regs[APIC_SPIV + 1] |=3D 1; +} + +static void test_plane_msi(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + struct kvm_plane *plane; + struct kvm_plane_vcpu *plane_vcpu; + int r; + + struct kvm_msi msi =3D MAKE_MSI(0, MYVEC); + struct kvm_lapic_state lapic0, lapic1; + + vm =3D __vm_create(VM_SHAPE_DEFAULT, 1, 0); + + vcpu =3D __vm_vcpu_add(vm, 0); + vcpu_init_cpuid(vcpu, kvm_get_supported_cpuid()); + vcpu_set_cpuid(vcpu); + + plane =3D vm_plane_add(vm, 1); + plane_vcpu =3D __vm_plane_vcpu_add(vcpu, plane); + + vcpu_set_msr(vcpu, MSR_IA32_APICBASE, + APIC_DEFAULT_GPA | MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE); + vcpu_ioctl(vcpu, KVM_GET_LAPIC, &lapic0); + do_enable_lapic(&lapic0); + vcpu_ioctl(vcpu, KVM_SET_LAPIC, &lapic0); + + _plane_vcpu_set_msr(plane_vcpu, MSR_IA32_APICBASE, + APIC_DEFAULT_GPA | MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE); + plane_vcpu_ioctl(plane_vcpu, KVM_GET_LAPIC, &lapic1); + do_enable_lapic(&lapic1); + plane_vcpu_ioctl(plane_vcpu, KVM_SET_LAPIC, &lapic1); + + r =3D __plane_ioctl(plane, KVM_SIGNAL_MSI, &msi); + TEST_ASSERT(r =3D=3D 1, + "Delivering interrupt to plane 1. ret: %d, errno: %d", r, errno); + + vcpu_ioctl(vcpu, KVM_GET_LAPIC, &lapic0); + TEST_ASSERT(!has_irr(&lapic0, MYVEC), "Vector clear in plane 0"); + plane_vcpu_ioctl(plane_vcpu, KVM_GET_LAPIC, &lapic1); + TEST_ASSERT(has_irr(&lapic1, MYVEC), "Vector set in plane 1"); + + /* req_exit_planes always has priority */ + vcpu->run->req_exit_planes =3D (1 << 1); + vcpu_run(vcpu); + TEST_ASSERT_EQ(vcpu->run->exit_reason, KVM_EXIT_PLANE_EVENT); + TEST_ASSERT_EQ(vcpu->run->plane_event.cause, KVM_PLANE_EVENT_INTERRUPT); + TEST_ASSERT_EQ(vcpu->run->plane_event.pending_event_planes, (1 << 1)); + TEST_ASSERT_EQ(vcpu->run->plane_event.target, (1 << 1)); + + r =3D __vm_ioctl(vm, KVM_SIGNAL_MSI, &msi); + TEST_ASSERT(r =3D=3D 1, + "Delivering interrupt to plane 0. ret: %d, errno: %d", r, errno); + vcpu_ioctl(vcpu, KVM_GET_LAPIC, &lapic0); + TEST_ASSERT(has_irr(&lapic0, MYVEC), "Vector set in plane 0"); + + /* req_exit_planes ignores current plane; current plane is cleared */ + vcpu->run->plane =3D 1; + vcpu->run->req_exit_planes =3D (1 << 0) | (1 << 1); + vcpu_run(vcpu); + TEST_ASSERT_EQ(vcpu->run->exit_reason, KVM_EXIT_PLANE_EVENT); + TEST_ASSERT_EQ(vcpu->run->plane_event.cause, KVM_PLANE_EVENT_INTERRUPT); + TEST_ASSERT_EQ(vcpu->run->plane_event.pending_event_planes, (1 << 0)); + TEST_ASSERT_EQ(vcpu->run->plane_event.target, (1 << 0)); + + kvm_vm_free(vm); + ksft_test_result_pass("signal MSI for planes\n"); +} + +int main(int argc, char *argv[]) +{ + int cap_planes =3D kvm_check_cap(KVM_CAP_PLANES); + TEST_REQUIRE(cap_planes && cap_planes > 1); + + ksft_print_header(); + ksft_set_plan(5); + + pr_info("# KVM_CAP_PLANES: %d\n", cap_planes); + + test_plane_regs(); + test_plane_fpu_nonshared(); + test_plane_fpu_shared(); + test_plane_msi(); + + ksft_finished(); +} --=20 2.49.0