From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 3CCFA44A710; Mon, 20 Jul 2026 17:46:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569567; cv=none; b=gAhBnoK94ySTffrA6zFUcGhNURAWXCGGLVVn62UiajMW/yfHAaYvDCDj2A0EGs8iW0HcwF/fG1FtZrOf8w1MN+FVSdZqEAX0wRbmJre9umA6HBada6hAeIpblgogKi6wTXadWHCApX5zzpCSTJCRiDnBAs9xU3V4chESepsoN5E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569567; c=relaxed/simple; bh=cPmzi01/ZLhdABcjMjlUHBte7VRdK4w1HW4jeNZEJ0A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nYyNvtPxgBDyemM5d12DlbXU4Y0M9aC6+jT0ADIOMYL+qZ72Nnf65WoKj2QwwWQY1G5Bv832037Ssf02Ov1SiAscTMEA8v85dF3svVntZ/Kpa3fBp9p/ssMM27NmOUhlzcrrnFW9cbqjq1OWgtkjYey4UOn+NSiJIn0fg4uDRBY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=aYxY5THg; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="aYxY5THg" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569564; x=1816105564; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=cPmzi01/ZLhdABcjMjlUHBte7VRdK4w1HW4jeNZEJ0A=; b=aYxY5THgMPu9JXpw0v6KhfClHmmESb+ZOd3j0ClrRyZgG0P+YCh4oDDe G8MIB7r9ftjckyLKcjkAB/Gf3sXQzvqkMP3wG0TNfvAcvYwhV9wUisLtl +DpyC2LnBRbWffP5I+NOU8gMCAW19t1a6NeLLhPsZzeBldtou6TV+KcCL YMZtO1pT61OEd+mPiUtV1BoCZwACofPA6yt8N085gjlcT+C7n7FhGXXJM MlyKm3vTCaIdt4C5L5R6jweFJRFnvLmSolA3qV1FwHtsdmOhFOqJUuBpA l9nJ4Vftr5v4su1MgEGkX11yEfjGutSjYFgAA21koq6G5AJ7DWsh4VQ1O A==; X-CSE-ConnectionGUID: oOOxwsw/SK+tNFGhpnQ2ZA== X-CSE-MsgGUID: NszpEmbHTP6YnlYNZH9lUg== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691623" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691623" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:45:56 -0700 X-CSE-ConnectionGUID: twIrDAYiSiKMuHZUZhsbGw== X-CSE-MsgGUID: mQhICc5yRGy/yEJAh1OBLw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575333" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:45:56 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com Subject: [PATCH v5 01/20] KVM: x86: Extend VCPU registers for EGPRs Date: Mon, 20 Jul 2026 17:19:30 +0000 Message-ID: <20260720171949.498680-2-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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" Extend the storage to include extended general-purpose registers (EGPRs: R16-R31) when CONFIG_KVM_APX=3Dy. This option is for VMX only. Although EGPR state is XSAVE-managed, and thus could be stored in the guest fpstate, VCPU storage provides a more convenient and efficient access path for KVM. Suggested-by: Sean Christopherson Signed-off-by: Chang S. Bae Link: https://lore.kernel.org/abL8SW5JS1aV5goa@google.com --- arch/x86/include/asm/kvm_host.h | 18 ++++++++++++++++++ arch/x86/kvm/Kconfig | 4 ++++ 2 files changed, 22 insertions(+) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index b517257a6315..48547842d9fa 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -178,6 +178,24 @@ enum kvm_reg { VCPU_REGS_R13, VCPU_REGS_R14, VCPU_REGS_R15, +#endif +#ifdef CONFIG_KVM_APX + VCPU_REGS_R16, + VCPU_REGS_R17, + VCPU_REGS_R18, + VCPU_REGS_R19, + VCPU_REGS_R20, + VCPU_REGS_R21, + VCPU_REGS_R22, + VCPU_REGS_R23, + VCPU_REGS_R24, + VCPU_REGS_R25, + VCPU_REGS_R26, + VCPU_REGS_R27, + VCPU_REGS_R28, + VCPU_REGS_R29, + VCPU_REGS_R30, + VCPU_REGS_R31, #endif NR_VCPU_GENERAL_PURPOSE_REGS, =20 diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index 801bf9e520db..f27e3f2937f0 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig @@ -93,10 +93,14 @@ config KVM_SW_PROTECTED_VM =20 If unsure, say "N". =20 +config KVM_APX + bool + config KVM_INTEL tristate "KVM for Intel (and compatible) processors support" depends on KVM && IA32_FEAT_CTL select X86_FRED if X86_64 + select KVM_APX if X86_64 help Provides support for KVM on processors equipped with Intel's VT extensions, a.k.a. Virtual Machine Extensions (VMX). --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 3CE6B44B662; Mon, 20 Jul 2026 17:46:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569569; cv=none; b=PC3Qa+lQeljmnFjhZxsJldtDbYqIZrSwg9m6z58TYDTR00u/GDmPBSigGRwKZUoNQwSIthZZFsKtQBYyguiCrqOhQVYWdhi14lUbvoVjRz3fN4keoPZwYODySJbfxnjkV0T80VJzo3SUTkF5h3MmS9FuAoQquusuZwdf+YLz34c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569569; c=relaxed/simple; bh=NikDnVUX6VQnNXngTYOh4WTBmA9RIh6iowgiytdOB9g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QdcEz6NFPbEsd8ZGKfZnE/1kzz27dMHpkRZpyUsneNNTEce9SxHEPDq1Hgg0FypZwC/kVEf6DeddofXicinpsBavPsalh1pvszThHSprwxabzktTcyAgEZATUrgFXyEomLgPnz945t9Tk1vqgPMwzCJVh+gqbWk+H2lVsMf9xuU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=ZUNFe1NH; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="ZUNFe1NH" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569563; x=1816105563; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=NikDnVUX6VQnNXngTYOh4WTBmA9RIh6iowgiytdOB9g=; b=ZUNFe1NHwJWTj+FvzmUHadBT6Y0biBowaFBfzNOBnPalIhT8/Zu7atm5 TT7fp0Pwa/zZ45Uplsn4RH2IA27YDs6/LXg/DSi73nSf11U+a6/ErKBq9 hgl2Uw8q8OaG6uB9W3yfZALT26QZJu+AyXBczEdB3iB1IrRAtXakLzb7v oMfcEEyOw26Meu8ferXglBVqDokFxLOitNcKk4PiP+oC1BQg6CNN9uBim HRqdN+dEeT5enjbCxbB2X2L7puZrwXCHH/wSylnxXyi0HPnKkZPrqGC7x JVTimfe96hmpQXYw8p5MU+WIFKSrFz9ZzCkt1Mh5dmqq7T9EoM+SyvO9d Q==; X-CSE-ConnectionGUID: 8BF0b9ACRseYR0TvMvAhDw== X-CSE-MsgGUID: Fq2H0G4ZTSiMOEARCKp7Kg== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691630" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691630" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:45:58 -0700 X-CSE-ConnectionGUID: RSO9VCAJRJWLNnC3EwmXOg== X-CSE-MsgGUID: LwChBOkvRcy+HpMA0FvxWA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575338" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:45:57 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com Subject: [PATCH v5 02/20] KVM: VMX: Save guest EGPRs in VCPU cache Date: Mon, 20 Jul 2026 17:19:31 +0000 Message-ID: <20260720171949.498680-3-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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" Save and restore the guest EGPRs on VM exit/entry if the system supports Advanced Performance Extensions (APX). There are two possible ways of handling EGPR accesses: reading them from the processor lazily, or switching them in the vmentry/vmexit path and accessing them via vcpu->arch.regs. Prepare for the latter; it does not pollute kvm_reg_read/write() with conditionals to treat GPRs vs. EGPRs differently, and it allows for future usage of APX registers in the kernel. KVM intercepts all XCR0 writes, therefore XCR0 cannot change during the execution of VMLAUNCH/VMRESUME. Thus, for a guest that does not set XCR0[APX], the EGPR state does not have to be loaded/saved. The register restore path is placed after SPEC_CTRL is restored, so as to avoid any mis-speculation into EGPR accesses when APX is disabled. While saving may be skipped on VM-Fail, it is not worth the added complication for a slow path. Suggested-by: Sean Christopherson Signed-off-by: Chang S. Bae Link: https://lore.kernel.org/adPRA4ZhnvbaXSn0@google.com --- V4 -> V5: * Massage the chagnelog (Paolo [*]) * Fix typo; use KVM_ENTER_EGPR_SWITCH consistently [*]: Paolo's rewording appeared when it was once picked into his queue bran= ch --- arch/x86/Kconfig.assembler | 5 +++ arch/x86/include/asm/kvm_vcpu_regs.h | 50 ++++++++++++++++++++++++++++ arch/x86/kvm/Kconfig | 2 +- arch/x86/kvm/vmenter.h | 1 + arch/x86/kvm/vmx/vmenter.S | 31 +++++++++++++++-- arch/x86/kvm/vmx/vmx.c | 13 ++++++++ 6 files changed, 99 insertions(+), 3 deletions(-) diff --git a/arch/x86/Kconfig.assembler b/arch/x86/Kconfig.assembler index b1c59fb0a4c9..3b41ec89468d 100644 --- a/arch/x86/Kconfig.assembler +++ b/arch/x86/Kconfig.assembler @@ -1,6 +1,11 @@ # SPDX-License-Identifier: GPL-2.0 # Copyright (C) 2020 Jason A. Donenfeld . All Rights Rese= rved. =20 +config AS_APX + def_bool $(as-instr64,xor %r16$(comma)%r16) + help + Supported by binutils >=3D 2.42 and LLVM integrated assembler >=3D V18 + config AS_WRUSS def_bool $(as-instr64,wrussq %rax$(comma)(%rbx)) help diff --git a/arch/x86/include/asm/kvm_vcpu_regs.h b/arch/x86/include/asm/kv= m_vcpu_regs.h index d9f1528fab2b..d6658c9909aa 100644 --- a/arch/x86/include/asm/kvm_vcpu_regs.h +++ b/arch/x86/include/asm/kvm_vcpu_regs.h @@ -99,6 +99,56 @@ .ifc \r64,%r15 \opd =3D 15 .endif +#endif +#ifdef CONFIG_KVM_APX + .ifc \r64,%r16 + \opd =3D 16 + .endif + .ifc \r64,%r17 + \opd =3D 17 + .endif + .ifc \r64,%r18 + \opd =3D 18 + .endif + .ifc \r64,%r19 + \opd =3D 19 + .endif + .ifc \r64,%r20 + \opd =3D 20 + .endif + .ifc \r64,%r21 + \opd =3D 21 + .endif + .ifc \r64,%r22 + \opd =3D 22 + .endif + .ifc \r64,%r23 + \opd =3D 23 + .endif + .ifc \r64,%r24 + \opd =3D 24 + .endif + .ifc \r64,%r25 + \opd =3D 25 + .endif + .ifc \r64,%r26 + \opd =3D 26 + .endif + .ifc \r64,%r27 + \opd =3D 27 + .endif + .ifc \r64,%r28 + \opd =3D 28 + .endif + .ifc \r64,%r29 + \opd =3D 29 + .endif + .ifc \r64,%r30 + \opd =3D 30 + .endif + .ifc \r64,%r31 + \opd =3D 31 + .endif #endif .endm =20 diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index f27e3f2937f0..eb71cd7e5b37 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig @@ -100,7 +100,7 @@ config KVM_INTEL tristate "KVM for Intel (and compatible) processors support" depends on KVM && IA32_FEAT_CTL select X86_FRED if X86_64 - select KVM_APX if X86_64 + select KVM_APX if X86_64 && AS_APX help Provides support for KVM on processors equipped with Intel's VT extensions, a.k.a. Virtual Machine Extensions (VMX). diff --git a/arch/x86/kvm/vmenter.h b/arch/x86/kvm/vmenter.h index 77376812c81b..690c05696824 100644 --- a/arch/x86/kvm/vmenter.h +++ b/arch/x86/kvm/vmenter.h @@ -7,6 +7,7 @@ #define KVM_ENTER_VMRESUME BIT(0) #define KVM_ENTER_SAVE_SPEC_CTRL BIT(1) #define KVM_ENTER_CLEAR_CPU_BUFFERS_FOR_MMIO BIT(2) +#define KVM_ENTER_EGPR_SWITCH BIT(3) =20 #ifdef __ASSEMBLER__ .macro RESTORE_GUEST_SPEC_CTRL_BODY guest_spec_ctrl:req, label:req diff --git a/arch/x86/kvm/vmx/vmenter.S b/arch/x86/kvm/vmx/vmenter.S index 00d807505fc8..702d86ade6b1 100644 --- a/arch/x86/kvm/vmx/vmenter.S +++ b/arch/x86/kvm/vmx/vmenter.S @@ -16,6 +16,7 @@ * @flags: KVM_ENTER_VMRESUME: use VMRESUME instead of VMLAUNCH * KVM_ENTER_SAVE_SPEC_CTRL: save guest SPEC_CTRL into vmx->spec_ctrl * KVM_ENTER_CLEAR_CPU_BUFFERS_FOR_MMIO: vCPU can access host MMIO + * KVM_ENTER_EGPR_SWITCH: load/store guest EGPRs * * Returns: * 0 on VM-Exit, 1 on VM-Fail @@ -46,6 +47,16 @@ SYM_FUNC_START(__vmx_vcpu_run) /* Reload @vmx, _ASM_ARG1 may be modified by vmx_update_host_rsp(). */ mov WORD_SIZE(%_ASM_SP), %_ASM_DI =20 +#ifdef CONFIG_KVM_APX + ALTERNATIVE "jmp .Lload_egprs_done", "", X86_FEATURE_APX + testl $KVM_ENTER_EGPR_SWITCH, (%_ASM_SP) + jz .Lload_egprs_done + LOAD_REGS %_ASM_DI, VMX_vcpu_arch_regs, \ + %r16, %r17, %r18, %r19, %r20, %r21, %r22, %r23, \ + %r24, %r25, %r26, %r27, %r28, %r29, %r30, %r31 +.Lload_egprs_done: +#endif + /* * Unlike AMD there's no V_SPEC_CTRL here, so do not leave the body * out of line. Clobbers RAX, RCX, RDX, RSI. @@ -193,8 +204,24 @@ SYM_INNER_LABEL_ALIGN(vmx_vmexit, SYM_L_GLOBAL) mov %_ASM_BX, %_ASM_AX =20 /* Pop our saved arguments from the stack */ - pop %_ASM_BX - pop %_ASM_BX + pop %_ASM_BX /* @flags */ + pop %_ASM_DI /* @vmx */ + +#ifdef CONFIG_KVM_APX + ALTERNATIVE "jmp .Lclear_egprs_done", "", X86_FEATURE_APX + test $KVM_ENTER_EGPR_SWITCH, %_ASM_BX + jz .Lclear_egprs_done + /* + * Unlike legacy GPRs, saving could be conditional here on VM-Fail, + * which however isn't in fastpath. Instead, simply saving EGPRs always. + */ + STORE_REGS %_ASM_DI, VMX_vcpu_arch_regs, \ + %r16, %r17, %r18, %r19, %r20, %r21, %r22, %r23, \ + %r24, %r25, %r26, %r27, %r28, %r29, %r30, %r31 + CLEAR_REGS %r16d, %r17d, %r18d, %r19d, %r20d, %r21d, %r22d, %r23d, \ + %r24d, %r25d, %r26d, %r27d, %r28d, %r29d, %r30d, %r31d +.Lclear_egprs_done: +#endif =20 /* ... and then the callee-save registers */ pop %_ASM_BX diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 3681d565f177..1c86919d14d4 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -991,6 +991,19 @@ unsigned int __vmx_vcpu_enter_flags(struct vcpu_vmx *v= mx) kvm_vcpu_can_access_host_mmio(&vmx->vcpu)) flags |=3D KVM_ENTER_CLEAR_CPU_BUFFERS_FOR_MMIO; =20 + /* + * KVM intercepts XSETBV and thus always tracks the guest XCR0. EGPR + * save/restore is gated by this flag. The resulting behavior is: + * + * - When the guest enables APX, KVM restores EGPRs (initially zeroed). + * - When the guest disables APX, EGPRs are preserved in the VCPU cache. + * - When APX is re-enabled, the saved state is restored, which matches + * architectural expectations. + */ + if (IS_ENABLED(CONFIG_KVM_APX) && cpu_feature_enabled(X86_FEATURE_APX) && + vmx->vcpu.arch.xcr0 & XFEATURE_MASK_APX) + flags |=3D KVM_ENTER_EGPR_SWITCH; + return flags; } =20 --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 C0E2444CAEA; Mon, 20 Jul 2026 17:46:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569571; cv=none; b=RdGozQ7UvvcjLBhWr0me/d5fu5TNJeXAdfswwlbZQPEyeH6fI0gf43TJH3LBBoUMX3R2S+ccPpmCGjuxy4gawEVrEfIkBM5T8NDKMkgRZWSrAVQHdApNpdC1KWEe5z+YCkehX0/aKeonHz0F5hWIQJtGB42MB2Ya7hSb/7Fz/eY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569571; c=relaxed/simple; bh=kG+Cg7KjUxJiD/cDFeug4X+aUCKAq0WWuRVOa/dS818=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mUa+CewePsUUT2NFeWdnzeOaarJV/THCDoHBce4f/bKrdE6IYg9jLgrF39qrNGyI8EJ5Y2w5D6QGHV4EG9wFbMNwPQj9BTT9a1yxFVeVsskzibYSfW9JuhObBUoFEh4jbeFGaSO5kSi7C+kJV/NfiFHaRdbJsqukFAc1y0vW710= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=jR4n2er9; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="jR4n2er9" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569568; x=1816105568; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=kG+Cg7KjUxJiD/cDFeug4X+aUCKAq0WWuRVOa/dS818=; b=jR4n2er9xm7xFucTQRvHdisJpgOWH8v8YKY2aBjUAHff4k0DrtxT5bEY nwhIEtjsLGaLnrkO6zqC4/FAv1MY5JVeSOXtUIxwGQgGyOg3Lq+id7LBP 184Mmzovc+5rJjAvWEJsMkEnwBJrqVA2/P0KCz7+s1G2ufsO37CmPK5BQ Hw8fRNupuW24rghc96vyu78ryjl9TghYKDAxNYRLwsmgud1NmuN0nK1PL sz4XqCCnBK9fSWKtgo25vA4d/uWWoqCVckisEmrY6VVE4Et6SD/KBX+dB ncoT0jpopfMGPKNYx5cKM96jrlCEHSrduFT5eu5DGvbw7qBWD6D8Y+cOO w==; X-CSE-ConnectionGUID: zt0UgwZVRrGb+gNBc1zCnQ== X-CSE-MsgGUID: LDaixkPNQSmGErzMQBX9Xw== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691638" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691638" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:45:59 -0700 X-CSE-ConnectionGUID: bkW6Ut0QRtafXVsA3jSzKQ== X-CSE-MsgGUID: dLF3RPmTTYin4zppmGpgTw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575342" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:45:59 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com Subject: [PATCH v5 03/20] KVM: x86: Support APX state for XSAVE ABI Date: Mon, 20 Jul 2026 17:19:32 +0000 Message-ID: <20260720171949.498680-4-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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" Introduce a facility to copy APX state between the VCPU cache and the userspace buffer as VCPU cache is the single source of truth. The existing fpstate copy functions historically sync all XSTATEs in between userspace and kernel buffers [1]. In this regard, any additional state handling logic should be consistent with them -- i.e. validation of XSTATE_BV against the supported XCR0 mask. Now with the two copy paths, their invocations require to take care of these facts: * When exporting to userspace, the fpstate function should run first since it zeros out the area of components either not present or inactive. Then the VCPU cache function ensures copying APX state. * On the opposite way, both will copy the state to both storages. This duplication is avoidable by tweaking either the generic function or XSTATE_BV/XCR0. But the optimization while at a slow path looks to rather add complication. So keep it simple although sub-optimal. [1] Except for PKRU state, as stored in struct thread_struct. Signed-off-by: Chang S. Bae --- V4 -> V5: Copy to both storages The optimization bit had been reconsidered a little. V4 was attempting to introduce the one-off exception into the generic copy function. Before that, V3 had the tweak at the KVM site under the APX copy function. But unless either approach could reach some agreeable shape, the tweak appears to remain mere optimization. Here the third option would be simply absorbing the duplication, which isn't significant in this slow path in practice. Making simple looks to be a overall win, otherwise. --- arch/x86/kvm/cpuid.c | 10 ++++++++ arch/x86/kvm/cpuid.h | 2 ++ arch/x86/kvm/x86.c | 61 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 2698fa42cd97..122e46db9a15 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -60,6 +60,16 @@ void __init kvm_init_xstate_sizes(void) } } =20 +u32 xstate_size(unsigned int xfeature) +{ + return xstate_sizes[xfeature].eax; +} + +u32 xstate_offset(unsigned int xfeature) +{ + return xstate_sizes[xfeature].ebx; +} + u32 xstate_required_size(u64 xstate_bv, bool compacted) { u32 ret =3D XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET; diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index 8d863f45585d..1716f3b6b885 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -66,6 +66,8 @@ bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, =20 void __init kvm_init_xstate_sizes(void); u32 xstate_required_size(u64 xstate_bv, bool compacted); +u32 xstate_size(unsigned int xfeature); +u32 xstate_offset(unsigned int xfeature); =20 int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu); int cpuid_query_maxguestphyaddr(struct kvm_vcpu *vcpu); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 0626e835e9eb..5578df10179a 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3124,6 +3124,49 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct= kvm_vcpu *vcpu, return 0; } =20 +#ifdef CONFIG_KVM_APX +static void kvm_copy_vcpu_regs_to_uabi(struct kvm_vcpu *vcpu, void *buf, u= 64 supported_xcr0) +{ + union fpregs_state *xstate =3D (union fpregs_state *)buf; + + BUILD_BUG_ON(NR_VCPU_GENERAL_PURPOSE_REGS <=3D VCPU_REGS_R31); + + if (!(supported_xcr0 & XFEATURE_MASK_APX)) + return; + + memcpy(buf + xstate_offset(XFEATURE_APX), + &vcpu->arch.regs[VCPU_REGS_R16], + xstate_size(XFEATURE_APX)); + + xstate->xsave.header.xfeatures |=3D XFEATURE_MASK_APX; +} + +static int kvm_copy_uabi_to_vcpu_regs(struct kvm_vcpu *vcpu, void *buf, u6= 4 supported_xcr0) +{ + union fpregs_state *xstate =3D (union fpregs_state *)buf; + + if (!(xstate->xsave.header.xfeatures & XFEATURE_MASK_APX)) + return 0; + + if (!(supported_xcr0 & XFEATURE_MASK_APX)) + return -EINVAL; + + BUILD_BUG_ON(NR_VCPU_GENERAL_PURPOSE_REGS <=3D VCPU_REGS_R31); + + memcpy(&vcpu->arch.regs[VCPU_REGS_R16], + buf + xstate_offset(XFEATURE_APX), + xstate_size(XFEATURE_APX)); + + return 0; +} +#else +static void kvm_copy_vcpu_regs_to_uabi(struct kvm_vcpu *vcpu, void *buf, u= 64 supported_xcr0) { } +static int kvm_copy_uabi_to_vcpu_regs(struct kvm_vcpu *vcpu, void *buf, u6= 4 supported_xcr0) +{ + return 0; +} +#endif + static int kvm_vcpu_ioctl_x86_get_xsave2(struct kvm_vcpu *vcpu, u8 *state, unsigned int size) { @@ -3145,8 +3188,15 @@ static int kvm_vcpu_ioctl_x86_get_xsave2(struct kvm_= vcpu *vcpu, if (fpstate_is_confidential(&vcpu->arch.guest_fpu)) return vcpu->kvm->arch.has_protected_state ? -EINVAL : 0; =20 + /* + * This copy function zeros out userspace memory for any gap from the + * guest fpstate. So invoke before copying any other state, i.e. APX, + * that is not saved in fpstate. + */ fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu, state, size, supported_xcr0, vcpu->arch.pkru); + kvm_copy_vcpu_regs_to_uabi(vcpu, state, supported_xcr0); + return 0; } =20 @@ -3161,6 +3211,7 @@ static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vc= pu *vcpu, struct kvm_xsave *guest_xsave) { union fpregs_state *xstate =3D (union fpregs_state *)guest_xsave->region; + int err; =20 if (fpstate_is_confidential(&vcpu->arch.guest_fpu)) return vcpu->kvm->arch.has_protected_state ? -EINVAL : 0; @@ -3172,6 +3223,16 @@ static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_v= cpu *vcpu, */ xstate->xsave.header.xfeatures &=3D ~vcpu->arch.guest_fpu.fpstate->xfd; =20 + /* + * This and the following copy functions copy APX state into each + * storage. The VCPU cache is the single source of truth but avoiding + * this redundant copy tends to introduce special-case handling. Since + * this lies in a slow path, keep the implementation simple. + */ + err =3D kvm_copy_uabi_to_vcpu_regs(vcpu, guest_xsave->region, kvm_caps.su= pported_xcr0); + if (err) + return err; + return fpu_copy_uabi_to_guest_fpstate(&vcpu->arch.guest_fpu, guest_xsave->region, kvm_caps.supported_xcr0, --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 20D594508F8; Mon, 20 Jul 2026 17:46:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569577; cv=none; b=RarfwL5H+bM78vCWIBNOlsZg2C9s5uynG/1KB44OUVOhx/rVZ5uesMVwXOZ270+Cq2Iyba9fupj8S1/9PDiyTUqll1+112wPW+ajNhtgcW0LDenNV8FaJl//j6epWS/bozaiS1E1ZlrTVUT6XYfPgh/sYqFJ+Z9gTSWf4x5O+rI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569577; c=relaxed/simple; bh=tio3cp9B5/Kj79xKjqBojFllG1Xx1jqzA924PcO48Ic=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rbpajoPp4XdOdSjK8ntNU0iAHpntmBe2QPVuzxa4jfQ1kazhxvF+EoLO+crj4ehEo8MF1Z8tPkOjb8z6sjV/wGpn2PGZlZnX76Bxo8TO+4zNukk4eUo8waBPcukvyUuDm8vd2HSt4EyukIPQiaNoyI/mnJmuapk63MT2zLyauuY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=RAqSvTp+; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="RAqSvTp+" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569571; x=1816105571; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=tio3cp9B5/Kj79xKjqBojFllG1Xx1jqzA924PcO48Ic=; b=RAqSvTp+dQDXc6jz270WCwHBAlyCtnsBCXI/CPviqmtBLOvJwhOAqbxv 1OZEzKGp8iL4ljgr/mkHCFqKUCqpovD4e4JOMO88cfNJOcNn0Fb2pi6vP bU6vNmEG8Ufzou1lz87KN1RpSbPJApSHyEjLwsRrB3agn5cwW2c/NbwVw xar844oOwnEvbETCp76xZOSYEmwdPmT7BNB32yqhB5R+WyEayTQxpOfbm i0iyc0z0yehVCBsL8TluzTPQUBteplI0Onf0CX16ksTaqqoWkyfr9A9zX gNVCf3NaVBvqkSJemoplBTZCB3gBdWIm/lMsubMyEwfJh5GK1HVnYTNLv w==; X-CSE-ConnectionGUID: G+8Jk2X0RkStf0QoyL6c7g== X-CSE-MsgGUID: z2d/qWFcTc6MOcC8irft9A== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691646" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691646" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:46:00 -0700 X-CSE-ConnectionGUID: 7oN8tR5gRzakOi/Tql/RGg== X-CSE-MsgGUID: tph4NU2QTo2UdtCi25V0uA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575347" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:46:00 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com Subject: [PATCH v5 04/20] KVM: VMX: Refactor VMX instruction information access Date: Mon, 20 Jul 2026 17:19:33 +0000 Message-ID: <20260720171949.498680-5-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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" Introduce a helper that returns the instruction information as a 64-bit value and adjust existing sites to prepare for a wider field. The VMX instruction information field is currently 32 bits. Future extensions may expand this field to support extended register IDs, requiring a wider width. The change provides a single access point for the transition. No functional change intended. Signed-off-by: Chang S. Bae --- V4 -> V5: Convert vmx_get_msr_imm_reg() and keep `u32 type` in handle_invep= t() --- arch/x86/kvm/vmx/nested.c | 23 ++++++++++++----------- arch/x86/kvm/vmx/nested.h | 2 +- arch/x86/kvm/vmx/vmx.c | 6 +++--- arch/x86/kvm/vmx/vmx.h | 10 ++++++++-- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 0635e92471c8..92b530baa0ee 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -5234,7 +5234,7 @@ static void nested_vmx_triple_fault(struct kvm_vcpu *= vcpu) * #UD, #GP, or #SS. */ int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualific= ation, - u32 vmx_instruction_info, bool wr, int len, gva_t *ret) + u64 vmx_instruction_info, bool wr, int len, gva_t *ret) { gva_t off; bool exn; @@ -5366,7 +5366,7 @@ static int nested_vmx_get_vmptr(struct kvm_vcpu *vcpu= , gpa_t *vmpointer, int r; =20 if (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu), - vmcs_read32(VMX_INSTRUCTION_INFO), false, + vmx_get_instr_info(), false, sizeof(*vmpointer), &gva)) { *ret =3D 1; return -EINVAL; @@ -5651,7 +5651,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu) struct vmcs12 *vmcs12 =3D is_guest_mode(vcpu) ? get_shadow_vmcs12(vcpu) : get_vmcs12(vcpu); unsigned long exit_qualification =3D vmx_get_exit_qual(vcpu); - u32 instr_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); + u64 instr_info =3D vmx_get_instr_info(); struct vcpu_vmx *vmx =3D to_vmx(vcpu); struct x86_exception e; unsigned long field; @@ -5757,7 +5757,7 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) struct vmcs12 *vmcs12 =3D is_guest_mode(vcpu) ? get_shadow_vmcs12(vcpu) : get_vmcs12(vcpu); unsigned long exit_qualification =3D vmx_get_exit_qual(vcpu); - u32 instr_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); + u64 instr_info =3D vmx_get_instr_info(); struct vcpu_vmx *vmx =3D to_vmx(vcpu); struct x86_exception e; unsigned long field; @@ -5946,7 +5946,7 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu) static int handle_vmptrst(struct kvm_vcpu *vcpu) { unsigned long exit_qual =3D vmx_get_exit_qual(vcpu); - u32 instr_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); + u64 instr_info =3D vmx_get_instr_info(); gpa_t current_vmptr =3D to_vmx(vcpu)->nested.current_vmptr; struct x86_exception e; gva_t gva; @@ -5974,8 +5974,8 @@ static int handle_vmptrst(struct kvm_vcpu *vcpu) static int handle_invept(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx =3D to_vmx(vcpu); - u32 vmx_instruction_info, types; unsigned long type, roots_to_free; + u64 vmx_instruction_info; struct kvm_mmu *mmu; gva_t gva; struct x86_exception e; @@ -5983,6 +5983,7 @@ static int handle_invept(struct kvm_vcpu *vcpu) u64 eptp, gpa; } operand; int i, r, gpr_index; + u32 types; =20 if (!(vmx->nested.msrs.secondary_ctls_high & SECONDARY_EXEC_ENABLE_EPT) || @@ -5994,7 +5995,7 @@ static int handle_invept(struct kvm_vcpu *vcpu) if (!nested_vmx_check_permission(vcpu)) return 1; =20 - vmx_instruction_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); + vmx_instruction_info =3D vmx_get_instr_info(); gpr_index =3D vmx_get_instr_info_reg2(vmx_instruction_info); type =3D kvm_register_read(vcpu, gpr_index); =20 @@ -6054,7 +6055,7 @@ static int handle_invept(struct kvm_vcpu *vcpu) static int handle_invvpid(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx =3D to_vmx(vcpu); - u32 vmx_instruction_info; + u64 vmx_instruction_info; unsigned long type, types; gva_t gva; struct x86_exception e; @@ -6075,7 +6076,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) if (!nested_vmx_check_permission(vcpu)) return 1; =20 - vmx_instruction_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); + vmx_instruction_info =3D vmx_get_instr_info(); gpr_index =3D vmx_get_instr_info_reg2(vmx_instruction_info); type =3D kvm_register_read(vcpu, gpr_index); =20 @@ -6428,7 +6429,7 @@ static bool nested_vmx_exit_handled_encls(struct kvm_= vcpu *vcpu, static bool nested_vmx_exit_handled_vmcs_access(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, gpa_t bitmap) { - u32 vmx_instruction_info; + u64 vmx_instruction_info; unsigned long field; u8 b; =20 @@ -6436,7 +6437,7 @@ static bool nested_vmx_exit_handled_vmcs_access(struc= t kvm_vcpu *vcpu, return true; =20 /* Decode instruction info and find the field to access */ - vmx_instruction_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); + vmx_instruction_info =3D vmx_get_instr_info(); field =3D kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf)); =20 /* Out-of-range fields always cause a VM exit from L2 to L1 */ diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h index 6d6cd5904ddf..fb4f1757cb40 100644 --- a/arch/x86/kvm/vmx/nested.h +++ b/arch/x86/kvm/vmx/nested.h @@ -51,7 +51,7 @@ void nested_sync_vmcs12_to_shadow(struct kvm_vcpu *vcpu); int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data); int vmx_get_vmx_msr(struct nested_vmx_msrs *msrs, u32 msr_index, u64 *pdat= a); int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualific= ation, - u32 vmx_instruction_info, bool wr, int len, gva_t *ret); + u64 vmx_instruction_info, bool wr, int len, gva_t *ret); bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port, int size); =20 diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 1c86919d14d4..8a4b578252c2 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -6158,7 +6158,7 @@ static int handle_monitor_trap(struct kvm_vcpu *vcpu) =20 static int handle_invpcid(struct kvm_vcpu *vcpu) { - u32 vmx_instruction_info; + u64 vmx_instruction_info; unsigned long type; gva_t gva; struct { @@ -6172,7 +6172,7 @@ static int handle_invpcid(struct kvm_vcpu *vcpu) return 1; } =20 - vmx_instruction_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); + vmx_instruction_info =3D vmx_get_instr_info(); gpr_index =3D vmx_get_instr_info_reg2(vmx_instruction_info); type =3D kvm_register_read(vcpu, gpr_index); =20 @@ -6323,7 +6323,7 @@ static int handle_notify(struct kvm_vcpu *vcpu) =20 static int vmx_get_msr_imm_reg(struct kvm_vcpu *vcpu) { - return vmx_get_instr_info_reg(vmcs_read32(VMX_INSTRUCTION_INFO)); + return vmx_get_instr_info_reg(vmx_get_instr_info()); } =20 static int handle_rdmsr_imm(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index de9de0d2016c..a3f58a3d90e5 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -702,12 +702,18 @@ static inline bool vmx_guest_state_valid(struct kvm_v= cpu *vcpu) =20 void dump_vmcs(struct kvm_vcpu *vcpu); =20 -static inline int vmx_get_instr_info_reg(u32 vmx_instr_info) +/* A placeholder to smoothen 64-bit extension */ +static inline u64 vmx_get_instr_info(void) +{ + return vmcs_read32(VMX_INSTRUCTION_INFO); +} + +static inline int vmx_get_instr_info_reg(u64 vmx_instr_info) { return (vmx_instr_info >> 3) & 0xf; } =20 -static inline int vmx_get_instr_info_reg2(u32 vmx_instr_info) +static inline int vmx_get_instr_info_reg2(u64 vmx_instr_info) { return (vmx_instr_info >> 28) & 0xf; } --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 20E804508FD; Mon, 20 Jul 2026 17:46:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569577; cv=none; b=n7Yz7g2oeBKRTeGVYJ6pYXQaceTmEzl3mSmRIe83KuKsQm7QOHXFgb21tuxH2veO/Lev3lNswmfK81dgURkx3PNWB86Uu3iHPvJC611/bPuK4ObdQ3d8/R0tz6MFKZlcj6XesHZjzZ8SKeQUwydhIMYa9o/YGAikGtJ8pcnvBc0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569577; c=relaxed/simple; bh=O1xhkzOGXusgvLfmxyYRVYWISC6vKWJTATx1ya9pGsc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TdcIlsedbMe0JwlteT14aOB4/P56Lt5HIsuLjs1qh7G+MYAXAvGsaNpYt7xvxmCHmGIdVHebxPh0Jsnq5eDT77+bAy9WfAu3ZH0gMRhHovqZ7IInwFw+i7ezjd8wLMMlRbsiOUdZY6o7BB8gEBbfLcpJ+VMQ8oEjgx4xTuCKiUk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=jY9BOceB; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="jY9BOceB" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569572; x=1816105572; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=O1xhkzOGXusgvLfmxyYRVYWISC6vKWJTATx1ya9pGsc=; b=jY9BOceBBd2R23vzLJXxBDjGd5KgO4zj7fHSCqzJNUfdNkafzV7HjpAf uHIaGUGdNRQWDoM85oDHe5gpN+5k6PJrC8oika6Ron3oET/yGjc42I7Bm Ng11TTN1jJQFa09VtJxPTdYZfRce23EBRZhebmFV+gad1VjhyAVBsR3AS YNLfuH7jTdzPWxymASsmzPI0IPfgqsZh7uLrKduBlCEV6U8ywxJY9RtLC x3kA8htbVJeychDBRRxpm9FMNF/rkx7hK0LuwAPJKVbd2rjgmf3A2Fo+I 7TeCb8fJAYrMY99S8vDeSXoci+8pdgUpqIiC0qI3rbsrl6adonVmV6l4i g==; X-CSE-ConnectionGUID: as/gxfXXT6eu+ZHOw9j5YQ== X-CSE-MsgGUID: 8UDAcVLsRhmEUEcD1vSdWA== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691651" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691651" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:46:01 -0700 X-CSE-ConnectionGUID: Nd7VzCToSKO4kaiRA8GJhA== X-CSE-MsgGUID: ciVyY+S3TW2gkPtU3RfFDA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575350" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:46:01 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com Subject: [PATCH v5 05/20] KVM: VMX: Refactor instruction information decoding Date: Mon, 20 Jul 2026 17:19:34 +0000 Message-ID: <20260720171949.498680-6-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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" KVM currently decodes the VMX instruction information field using a mix of open-coded bit manipulations and ad hoc helpers. Convert all decoding to use helpers to centralize the decoding logic for the transition to a wider instruction information. No functional change intended. Signed-off-by: Chang S. Bae --- V4 -> V5: Fix handle_vmread() first accesses reg2 (0-day). --- arch/x86/kvm/vmx/nested.c | 58 +++++++++++++++++++-------------------- arch/x86/kvm/vmx/vmx.c | 9 +++--- arch/x86/kvm/vmx/vmx.h | 48 +++++++++++++++++++++++++++++--- 3 files changed, 77 insertions(+), 38 deletions(-) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 92b530baa0ee..fdec041e95c7 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -5234,7 +5234,7 @@ static void nested_vmx_triple_fault(struct kvm_vcpu *= vcpu) * #UD, #GP, or #SS. */ int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualific= ation, - u64 vmx_instruction_info, bool wr, int len, gva_t *ret) + u64 instr_info, bool wr, int len, gva_t *ret) { gva_t off; bool exn; @@ -5242,20 +5242,20 @@ int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsi= gned long exit_qualification, =20 /* * According to Vol. 3B, "Information for VM Exits Due to Instruction - * Execution", on an exit, vmx_instruction_info holds most of the - * addressing components of the operand. Only the displacement part - * is put in exit_qualification (see 3B, "Basic VM-Exit Information"). + * Execution", on an exit, instr_info holds most of the addressing + * components of the operand. Only the displacement part is put in + * exit_qualification (see 3B, "Basic VM-Exit Information"). * For how an actual address is calculated from all these components, * refer to Vol. 1, "Operand Addressing". */ - int scaling =3D vmx_instruction_info & 3; - int addr_size =3D (vmx_instruction_info >> 7) & 7; - bool is_reg =3D vmx_instruction_info & (1u << 10); - int seg_reg =3D (vmx_instruction_info >> 15) & 7; - int index_reg =3D (vmx_instruction_info >> 18) & 0xf; - bool index_is_valid =3D !(vmx_instruction_info & (1u << 22)); - int base_reg =3D (vmx_instruction_info >> 23) & 0xf; - bool base_is_valid =3D !(vmx_instruction_info & (1u << 27)); + int scaling =3D vmx_get_instr_info_scaling(instr_info); + int addr_size =3D vmx_get_instr_info_addr_size(instr_info); + bool is_reg =3D vmx_get_instr_info_is_reg(instr_info); + int seg_reg =3D vmx_get_instr_info_seg_reg(instr_info); + int index_reg =3D vmx_get_instr_info_index_reg(instr_info); + bool index_is_valid =3D vmx_get_instr_info_index_is_valid(instr_info); + int base_reg =3D vmx_get_instr_info_base_reg(instr_info); + bool base_is_valid =3D vmx_get_instr_info_base_is_valid(instr_info); =20 if (is_reg) { kvm_queue_exception(vcpu, UD_VECTOR); @@ -5664,7 +5664,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu) return 1; =20 /* Decode instruction info and find the field to read */ - field =3D kvm_register_read(vcpu, (((instr_info) >> 28) & 0xf)); + field =3D kvm_register_read(vcpu, vmx_get_instr_info_reg2(instr_info)); =20 if (!nested_vmx_is_evmptr12_valid(vmx)) { /* @@ -5712,8 +5712,8 @@ static int handle_vmread(struct kvm_vcpu *vcpu) * Note that the number of bits actually copied is 32 or 64 depending * on the guest's mode (32 or 64 bit), not on the given field's length. */ - if (instr_info & BIT(10)) { - kvm_register_write(vcpu, (((instr_info) >> 3) & 0xf), value); + if (vmx_get_instr_info_is_reg(instr_info)) { + kvm_register_write(vcpu, vmx_get_instr_info_reg(instr_info), value); } else { len =3D is_64_bit_mode(vcpu) ? 8 : 4; if (get_vmx_mem_address(vcpu, exit_qualification, @@ -5786,8 +5786,8 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) get_vmcs12(vcpu)->vmcs_link_pointer =3D=3D INVALID_GPA)) return nested_vmx_failInvalid(vcpu); =20 - if (instr_info & BIT(10)) - value =3D kvm_register_read(vcpu, (((instr_info) >> 3) & 0xf)); + if (vmx_get_instr_info_is_reg(instr_info)) + value =3D kvm_register_read(vcpu, vmx_get_instr_info_reg(instr_info)); else { len =3D is_64_bit_mode(vcpu) ? 8 : 4; if (get_vmx_mem_address(vcpu, exit_qualification, @@ -5798,7 +5798,7 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) return kvm_handle_memory_failure(vcpu, r, &e); } =20 - field =3D kvm_register_read(vcpu, (((instr_info) >> 28) & 0xf)); + field =3D kvm_register_read(vcpu, vmx_get_instr_info_reg2(instr_info)); =20 offset =3D get_vmcs12_field_offset(field); if (offset < 0) @@ -5975,7 +5975,7 @@ static int handle_invept(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx =3D to_vmx(vcpu); unsigned long type, roots_to_free; - u64 vmx_instruction_info; + u64 instr_info; struct kvm_mmu *mmu; gva_t gva; struct x86_exception e; @@ -5995,8 +5995,8 @@ static int handle_invept(struct kvm_vcpu *vcpu) if (!nested_vmx_check_permission(vcpu)) return 1; =20 - vmx_instruction_info =3D vmx_get_instr_info(); - gpr_index =3D vmx_get_instr_info_reg2(vmx_instruction_info); + instr_info =3D vmx_get_instr_info(); + gpr_index =3D vmx_get_instr_info_reg2(instr_info); type =3D kvm_register_read(vcpu, gpr_index); =20 types =3D (vmx->nested.msrs.ept_caps >> VMX_EPT_EXTENT_SHIFT) & 6; @@ -6008,7 +6008,7 @@ static int handle_invept(struct kvm_vcpu *vcpu) * operand is read even if it isn't needed (e.g., for type=3D=3Dglobal) */ if (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu), - vmx_instruction_info, false, sizeof(operand), &gva)) + instr_info, false, sizeof(operand), &gva)) return 1; r =3D kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e); if (r !=3D X86EMUL_CONTINUE) @@ -6055,8 +6055,8 @@ static int handle_invept(struct kvm_vcpu *vcpu) static int handle_invvpid(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx =3D to_vmx(vcpu); - u64 vmx_instruction_info; unsigned long type, types; + u64 instr_info; gva_t gva; struct x86_exception e; struct { @@ -6076,8 +6076,8 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) if (!nested_vmx_check_permission(vcpu)) return 1; =20 - vmx_instruction_info =3D vmx_get_instr_info(); - gpr_index =3D vmx_get_instr_info_reg2(vmx_instruction_info); + instr_info =3D vmx_get_instr_info(); + gpr_index =3D vmx_get_instr_info_reg2(instr_info); type =3D kvm_register_read(vcpu, gpr_index); =20 types =3D (vmx->nested.msrs.vpid_caps & @@ -6091,7 +6091,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) * operand is read even if it isn't needed (e.g., for type=3D=3Dglobal) */ if (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu), - vmx_instruction_info, false, sizeof(operand), &gva)) + instr_info, false, sizeof(operand), &gva)) return 1; r =3D kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e); if (r !=3D X86EMUL_CONTINUE) @@ -6429,16 +6429,16 @@ static bool nested_vmx_exit_handled_encls(struct kv= m_vcpu *vcpu, static bool nested_vmx_exit_handled_vmcs_access(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, gpa_t bitmap) { - u64 vmx_instruction_info; unsigned long field; + u64 instr_info; u8 b; =20 if (!nested_cpu_has_shadow_vmcs(vmcs12)) return true; =20 /* Decode instruction info and find the field to access */ - vmx_instruction_info =3D vmx_get_instr_info(); - field =3D kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf)); + instr_info =3D vmx_get_instr_info(); + field =3D kvm_register_read(vcpu, vmx_get_instr_info_reg2(instr_info)); =20 /* Out-of-range fields always cause a VM exit from L2 to L1 */ if (field >> 15) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 8a4b578252c2..c49bc6fabae3 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -6158,8 +6158,8 @@ static int handle_monitor_trap(struct kvm_vcpu *vcpu) =20 static int handle_invpcid(struct kvm_vcpu *vcpu) { - u64 vmx_instruction_info; unsigned long type; + u64 instr_info; gva_t gva; struct { u64 pcid; @@ -6172,16 +6172,15 @@ static int handle_invpcid(struct kvm_vcpu *vcpu) return 1; } =20 - vmx_instruction_info =3D vmx_get_instr_info(); - gpr_index =3D vmx_get_instr_info_reg2(vmx_instruction_info); + instr_info =3D vmx_get_instr_info(); + gpr_index =3D vmx_get_instr_info_reg2(instr_info); type =3D kvm_register_read(vcpu, gpr_index); =20 /* According to the Intel instruction reference, the memory operand * is read even if it isn't needed (e.g., for type=3D=3Dall) */ if (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu), - vmx_instruction_info, false, - sizeof(operand), &gva)) + instr_info, false, sizeof(operand), &gva)) return 1; =20 return kvm_handle_invpcid(vcpu, type, gva); diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index a3f58a3d90e5..acb4d7ac8b0a 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -708,14 +708,54 @@ static inline u64 vmx_get_instr_info(void) return vmcs_read32(VMX_INSTRUCTION_INFO); } =20 -static inline int vmx_get_instr_info_reg(u64 vmx_instr_info) +static inline int vmx_get_instr_info_reg(u64 instr_info) { - return (vmx_instr_info >> 3) & 0xf; + return (instr_info >> 3) & 0xf; } =20 -static inline int vmx_get_instr_info_reg2(u64 vmx_instr_info) +static inline int vmx_get_instr_info_reg2(u64 instr_info) { - return (vmx_instr_info >> 28) & 0xf; + return (instr_info >> 28) & 0xf; +} + +static inline int vmx_get_instr_info_scaling(u64 instr_info) +{ + return instr_info & 3; +} + +static inline int vmx_get_instr_info_addr_size(u64 instr_info) +{ + return (instr_info >> 7) & 7; +} + +static inline bool vmx_get_instr_info_is_reg(u64 instr_info) +{ + return !!(instr_info & BIT(10)); +} + +static inline int vmx_get_instr_info_seg_reg(u64 instr_info) +{ + return (instr_info >> 15) & 7; +} + +static inline int vmx_get_instr_info_index_reg(u64 instr_info) +{ + return (instr_info >> 18) & 0xf; +} + +static inline bool vmx_get_instr_info_index_is_valid(u64 instr_info) +{ + return !(instr_info & BIT(22)); +} + +static inline int vmx_get_instr_info_base_reg(u64 instr_info) +{ + return (instr_info >> 23) & 0xf; +} + +static inline bool vmx_get_instr_info_base_is_valid(u64 instr_info) +{ + return !(instr_info & BIT(27)); } =20 static inline bool vmx_can_use_ipiv(struct kvm_vcpu *vcpu) --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 0EAF74499A6; Mon, 20 Jul 2026 17:46:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569579; cv=none; b=MKfORQ6/mzcoXt+VSRW6GUQMPVBvBUWwYg1Y+eY12D19G4inU+C5eIXIhIAZH8yFoP+2XtWA40aJulDtRSpnKpfjxhLxh09H+Nqsu+W72ur8lil6Oi/tVU8h0+W+PNb4TqO1OArRo24+dq9S6MpQtYd5EO/B8c0ArTTW05miVv0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569579; c=relaxed/simple; bh=RccZqAU7DsjT2BnjXuB9JQRn+cgJksFm9RQr9cHY5do=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mmDAIvYckpYWR7GQpNkYVVfOpdY41Xnyd7F2DZPulGsRwfI4MQpWvixmphqDVkl1yl7qOhSdkNLSlj84jlkkShs07WhmmCtXfzYyYWv3IY7kEllPNvHw3/pGcx7JC7b4QEgUzqSmvKidJdtUDG08wRPzTidbnU/ymPAKJwsHGPc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=BniZSHTD; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="BniZSHTD" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569574; x=1816105574; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=RccZqAU7DsjT2BnjXuB9JQRn+cgJksFm9RQr9cHY5do=; b=BniZSHTDy5Hjg+Wjj6nfXRNTmABzwMyFIgsAUcE5Kgtzl8pZ4o715tuI J6pmO/L+68N247VSs48rR+F2KYrOGZt0MVyXOnj5C2dU82MjrrBxIJSvn m/iwGtj90moEgpSQEbf/bz+Eg6Ho8JdICfV6QamdPYI3obeWbAzuGmHsb k8LBDaLCiAoCIqC3qTLD+zDYxhURQdDt9ptDPEZHPYBqxoCLm7NnGtKZd Je3s5zvCaBzP4VR88sllViaIY1wKx/A4x6NYtRo2AJOpG7qdu8cn3MwTJ Ft7a459KbU36/wI798ULm4ZPTr+DfdYGkSQQ/EnVnQcBhz0j+p5MQxvLs Q==; X-CSE-ConnectionGUID: eXhQxQvPSB+LtJ9x7S4cRA== X-CSE-MsgGUID: a9t1/KL9R0GiAQ3d7k1D6w== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691656" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691656" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:46:02 -0700 X-CSE-ConnectionGUID: xriCJnXXQ6u0+hY+2tPoBw== X-CSE-MsgGUID: 9JwKUzuxQ5STwsGHhQe78g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575353" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:46:01 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com Subject: [PATCH v5 06/20] KVM: VMX: Remove unused control-register access defines Date: Mon, 20 Jul 2026 17:19:35 +0000 Message-ID: <20260720171949.498680-7-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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" CONTROL_REG_ACCESS_REG becomes misleading with EGPRs. Rather than leave stale, unused definitions behind, remove them all. Signed-off-by: Chang S. Bae --- V4 -> V5: New patch When looking around DEBUG_REG_ACCESS_REG() for the next patch, this dead code was discovered. --- arch/x86/include/asm/vmx.h | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index ed2ded531e55..30cf48e1c390 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -444,27 +444,8 @@ enum vmcs_field { /* * Exit Qualifications for MOV for Control Register Access */ -#define CONTROL_REG_ACCESS_NUM 0x7 /* 2:0, number of control = reg.*/ -#define CONTROL_REG_ACCESS_TYPE 0x30 /* 5:4, access type */ -#define CONTROL_REG_ACCESS_REG 0xf00 /* 10:8, general purpose r= eg. */ #define LMSW_SOURCE_DATA_SHIFT 16 #define LMSW_SOURCE_DATA (0xFFFF << LMSW_SOURCE_DATA_SHIFT) /* 16:31 lmsw= source */ -#define REG_EAX (0 << 8) -#define REG_ECX (1 << 8) -#define REG_EDX (2 << 8) -#define REG_EBX (3 << 8) -#define REG_ESP (4 << 8) -#define REG_EBP (5 << 8) -#define REG_ESI (6 << 8) -#define REG_EDI (7 << 8) -#define REG_R8 (8 << 8) -#define REG_R9 (9 << 8) -#define REG_R10 (10 << 8) -#define REG_R11 (11 << 8) -#define REG_R12 (12 << 8) -#define REG_R13 (13 << 8) -#define REG_R14 (14 << 8) -#define REG_R15 (15 << 8) =20 /* * Exit Qualifications for MOV for Debug Register Access --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 0D5BC44CF39; Mon, 20 Jul 2026 17:46:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569583; cv=none; b=nsWmhVsUhaKxot8D1oHlOixAvwH0mC+PRu8Ry1NE2gZJNsborbqLpIcBffcHbszOknKT2uySaWdSXjurEbiOP7mfzU36/mewd69vBnrbGi2+EnpRhvtP76YcwPJ1Doe2NXBQ43eEiTDneAIxvRFqvk8YtUWu+PmgMol46kyf4M4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569583; c=relaxed/simple; bh=PJ85R0g/sdegGOHOO6FWQPR+l4Q3s6OMsmAFNqmBfTA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SpKgYHE1M81LsTZaX4FK/aROCTLvEtHEz3FI5GsugXX1WA/2BtioblMXCnSinOIe1kRFSdScDePMKy/tjIx6W1YyZJhJ3uJkDzl6Fi3VjPUpf60rCdkp05Em6ANyUQA2MdRGxMyZ2cyLFVYJHJDU8P/Z7qNlWOxBxVyARLac1SA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=e6AYzKzB; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="e6AYzKzB" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569580; x=1816105580; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=PJ85R0g/sdegGOHOO6FWQPR+l4Q3s6OMsmAFNqmBfTA=; b=e6AYzKzBY0el80G4eSov5Wrnmb04RQguIwPARqFLiaYHJYnzBmlnroG2 rVqvG6W6IxFrmjd/q1oEs5vH0GEvDanWc0eBQoZq7tiB7SlZ1w9LxtaZY pCQyjABwIK8owfFIMbQ/rvOAMG6gV6oEY6nkGjfu6/DqoTH3qEwMjDXGa FpKYjU3nF2m++eUefgZuteV8Yd2GoSEBmP3dLyLBhMpxt9oKuSqgtAblz tsYIEToP6F3OqmzXvLQhasKooBtVTtelJVCBIQ7CmwQ80MyzXwsqOHbKJ xDxMMw8DLjfiWawRuexN0yq1lP1wSCepBJigC+VK+xLNGYYZ7Ix5V6hQI A==; X-CSE-ConnectionGUID: IzNlSV2zTOyFkzTYeAGoQQ== X-CSE-MsgGUID: DXWPoYsbSry9y2EKW+IrAQ== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691661" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691661" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:46:03 -0700 X-CSE-ConnectionGUID: OdvC4JmQT46PjYmO68BW8Q== X-CSE-MsgGUID: L9QO2YeARdqhRX2lnjCf7A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575357" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:46:02 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com Subject: [PATCH v5 07/20] KVM: VMX: Refactor register index retrieval from exit qualification Date: Mon, 20 Jul 2026 17:19:36 +0000 Message-ID: <20260720171949.498680-8-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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" Introduce a helper to extract the register index from the VMX exit qualification field. In addition to the VMX instruction information field, exit qualification also encodes a register index. This field will expand into the previously reserved bit for extended register IDs. This refactoring will simplify the extended register handling without code duplication. No functional change intended. Signed-off-by: Chang S. Bae --- V4 -> V5: Switch the argument and convert DEBUG_REG_ACCESS_REG() (review bo= t [*]) [*]: locally running Sashiko with gemini-3.1-pro-preview --- arch/x86/include/asm/vmx.h | 1 - arch/x86/kvm/vmx/nested.c | 2 +- arch/x86/kvm/vmx/vmx.c | 4 ++-- arch/x86/kvm/vmx/vmx.h | 5 +++++ 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 30cf48e1c390..5645a84f4fbc 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -454,7 +454,6 @@ enum vmcs_field { #define DEBUG_REG_ACCESS_TYPE 0x10 /* 4, direction of access = */ #define TYPE_MOV_TO_DR (0 << 4) #define TYPE_MOV_FROM_DR (1 << 4) -#define DEBUG_REG_ACCESS_REG(eq) (((eq) >> 8) & 0xf) /* 11:8, gener= al purpose reg. */ =20 =20 /* diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index fdec041e95c7..8e0523e40477 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -6351,7 +6351,7 @@ static bool nested_vmx_exit_handled_cr(struct kvm_vcp= u *vcpu, =20 switch ((exit_qualification >> 4) & 3) { case 0: /* mov to cr */ - reg =3D (exit_qualification >> 8) & 15; + reg =3D vmx_get_exit_qual_reg(exit_qualification); val =3D kvm_register_read(vcpu, reg); switch (cr) { case 0: diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index c49bc6fabae3..e7f968e66bfd 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -5692,7 +5692,7 @@ static int handle_cr(struct kvm_vcpu *vcpu) =20 exit_qualification =3D vmx_get_exit_qual(vcpu); cr =3D exit_qualification & 15; - reg =3D (exit_qualification >> 8) & 15; + reg =3D vmx_get_exit_qual_reg(exit_qualification); switch ((exit_qualification >> 4) & 3) { case 0: /* mov to cr */ val =3D kvm_register_read(vcpu, reg); @@ -5810,7 +5810,7 @@ static int handle_dr(struct kvm_vcpu *vcpu) return 1; } =20 - reg =3D DEBUG_REG_ACCESS_REG(exit_qualification); + reg =3D vmx_get_exit_qual_reg(exit_qualification); if (exit_qualification & TYPE_MOV_FROM_DR) { kvm_register_write(vcpu, reg, kvm_get_dr(vcpu, dr)); err =3D 0; diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index acb4d7ac8b0a..f3b0ec7ccb03 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -323,6 +323,11 @@ static __always_inline unsigned long vmx_get_exit_qual= (struct kvm_vcpu *vcpu) return vt->exit_qualification; } =20 +static inline int vmx_get_exit_qual_reg(unsigned long exit_qualification) +{ + return (exit_qualification >> 8) & 0xf; +} + static __always_inline u32 vmx_get_intr_info(struct kvm_vcpu *vcpu) { struct vcpu_vt *vt =3D to_vt(vcpu); --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 96DF544D020; Mon, 20 Jul 2026 17:46:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569587; cv=none; b=jJrPP5Kf+Rbg/6fyGU7bsTOPvobnPYn6he9Z57po+uKeJbHJP4E/LtiluarMBcCBjUkYOuHkelmj/bZ3m5EMOnmzIA8tAoRBIgxuPeaOhSazEfeaCCLtSIWOxLfSMoLVW6d7aM0ZJFHl6mOPqb0XVHmUzYvOGlcgmi85t1CcNx4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569587; c=relaxed/simple; bh=ngASC3yIZlP9NAPrPDwQbSk5sSArSJVG0BhmmCPskzo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KKURcPAgVP/zTio3MHx9HHe7FgknF4UYnp5/w9pu6txWpfOp+RLcwglejEktCcCnF5VT8zgGrgfYQ7ye9aAieRaKSx0O/tywZf3SDqBj2DF57oJ55+vrIkqRiitl8QfMk/gXTeQGgcdfYHrU5txjmNN42P+haPcrdmt+OO2rWUQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=do29aq3h; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="do29aq3h" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569581; x=1816105581; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ngASC3yIZlP9NAPrPDwQbSk5sSArSJVG0BhmmCPskzo=; b=do29aq3hMljttXyoQJ33FPKrBw47Kj6+bT7thDrZbJMinYqxbxzP1mkm ghjVugNejOoWMBSaMnbvJzG1bezo+lLj4tdLdSJ1WqdGZBXNFovARSYKh jAyDAqqTlJFEDJyQ+Gg6zWnZo0DdWDzgxZItlsXdw52cCKqStn6y1aAHu T3w23MyTTjhV+MFQpw2WpBSHqdFNl9k6UUOR8O/ea2CW0AIb7/y02Wn1s HasRIGfHW//a+0TkXj7VSE3vMqKA1aSp4PqhJ2hae97eIGmCI50Zxp1Tv 2zgnMLGxgN3nlTHgKoYnCnBQymhP0YyrXXKZQhOdP4WLLlNO5EdOZ7U2c g==; X-CSE-ConnectionGUID: kTN+3ABWQlu398y3CGiFgA== X-CSE-MsgGUID: 1KMC6gPrTFGj1FNVflhdRg== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691666" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691666" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:46:04 -0700 X-CSE-ConnectionGUID: lCKTapOBQ5+ztGcND2scTw== X-CSE-MsgGUID: 604wR9mYQSiWA6jO3d+rQg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575360" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:46:03 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com Subject: [PATCH v5 08/20] KVM: VMX: Support instruction information extension Date: Mon, 20 Jul 2026 17:19:37 +0000 Message-ID: <20260720171949.498680-9-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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" Define the VMCS field offset for the extended instruction information. Then, support 5-bit register indices retrieval from VMCS fields. Note the APX enumeration alone indicates the extension is available. For safety, do not assume that previously reserved bits were zero on older implementations. Suggested-by: Paolo Bonzini Suggested-by: Sean Christopherson Signed-off-by: Chang S. Bae Link: https://lore.kernel.org/aakEsXJgO-3m2xca@google.com --- Note for the review of extensions in following functions: +-------+------------------+------------------------------------+ | Bits | Field Name | Related KVM Functions | +=3D=3D=3D=3D=3D=3D=3D+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D+ | 3:2 | ASIZE | vmx_get_instr_info_addr_size() | +-------+------------------+------------------------------------+ | 4 | Mem/Reg (1=3D>reg) | vmx_get_instr_info_is_reg() | +-------+------------------+------------------------------------+ | 9:7 | Segment | vmx_get_instr_info_seg_reg() | +-------+------------------+------------------------------------+ | 10 | IndexInvalid | vmx_get_instr_info_base_reg() | +-------+------------------+------------------------------------+ | 11 | BaseInvalid | vmx_get_instr_info_base_is_valid() | +-------+------------------+------------------------------------+ | 20:16 | Reg1 | vmx_get_instr_info_reg() | +-------+------------------+------------------------------------+ | 28:24 | Index | vmx_get_instr_info_index_reg() | +-------+------------------+------------------------------------+ | 36:32 | Base | vmx_get_instr_info_base_reg() | +-------+------------------+------------------------------------+ | 44:40 | Reg2 | vmx_get_instr_info_reg2() | +-------+------------------+------------------------------------+ Reference: APX Specification, Table 3.11 Extended Instruction-Information (EII) VMCS Field --- arch/x86/include/asm/vmx.h | 2 ++ arch/x86/kvm/vmx/vmx.h | 42 +++++++++++++++++++++++++++----------- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 5645a84f4fbc..2334f52071f9 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -276,6 +276,8 @@ enum vmcs_field { PID_POINTER_TABLE_HIGH =3D 0x00002043, GUEST_PHYSICAL_ADDRESS =3D 0x00002400, GUEST_PHYSICAL_ADDRESS_HIGH =3D 0x00002401, + EXTENDED_INSTRUCTION_INFO =3D 0x00002406, + EXTENDED_INSTRUCTION_INFO_HIGH =3D 0x00002407, VMCS_LINK_POINTER =3D 0x00002800, VMCS_LINK_POINTER_HIGH =3D 0x00002801, GUEST_IA32_DEBUGCTL =3D 0x00002802, diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index f3b0ec7ccb03..2f53338f84f0 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -323,9 +323,18 @@ static __always_inline unsigned long vmx_get_exit_qual= (struct kvm_vcpu *vcpu) return vt->exit_qualification; } =20 +/* + * The APX enumeration guarantees the presence of the extended fields. + * The host CPUID bit alone is sufficient to rely on it. + */ +static inline bool vmx_instr_info_extended(void) +{ + return static_cpu_has(X86_FEATURE_APX); +} + static inline int vmx_get_exit_qual_reg(unsigned long exit_qualification) { - return (exit_qualification >> 8) & 0xf; + return (exit_qualification >> 8) & (vmx_instr_info_extended() ? 0x1f : 0x= f); } =20 static __always_inline u32 vmx_get_intr_info(struct kvm_vcpu *vcpu) @@ -707,20 +716,22 @@ static inline bool vmx_guest_state_valid(struct kvm_v= cpu *vcpu) =20 void dump_vmcs(struct kvm_vcpu *vcpu); =20 -/* A placeholder to smoothen 64-bit extension */ static inline u64 vmx_get_instr_info(void) { - return vmcs_read32(VMX_INSTRUCTION_INFO); + return vmx_instr_info_extended() ? vmcs_read64(EXTENDED_INSTRUCTION_INFO)= : + vmcs_read32(VMX_INSTRUCTION_INFO); } =20 static inline int vmx_get_instr_info_reg(u64 instr_info) { - return (instr_info >> 3) & 0xf; + return vmx_instr_info_extended() ? (instr_info >> 16) & 0x1f : + (instr_info >> 3) & 0xf; } =20 static inline int vmx_get_instr_info_reg2(u64 instr_info) { - return (instr_info >> 28) & 0xf; + return vmx_instr_info_extended() ? (instr_info >> 40) & 0x1f : + (instr_info >> 28) & 0xf; } =20 static inline int vmx_get_instr_info_scaling(u64 instr_info) @@ -730,37 +741,44 @@ static inline int vmx_get_instr_info_scaling(u64 inst= r_info) =20 static inline int vmx_get_instr_info_addr_size(u64 instr_info) { - return (instr_info >> 7) & 7; + return vmx_instr_info_extended() ? (instr_info >> 2) & 3 : + (instr_info >> 7) & 7; } =20 static inline bool vmx_get_instr_info_is_reg(u64 instr_info) { - return !!(instr_info & BIT(10)); + return vmx_instr_info_extended() ? !!(instr_info & BIT(4)) : + !!(instr_info & BIT(10)); } =20 static inline int vmx_get_instr_info_seg_reg(u64 instr_info) { - return (instr_info >> 15) & 7; + return vmx_instr_info_extended() ? (instr_info >> 7) & 7 : + (instr_info >> 15) & 7; } =20 static inline int vmx_get_instr_info_index_reg(u64 instr_info) { - return (instr_info >> 18) & 0xf; + return vmx_instr_info_extended() ? (instr_info >> 24) & 0x1f : + (instr_info >> 18) & 0xf; } =20 static inline bool vmx_get_instr_info_index_is_valid(u64 instr_info) { - return !(instr_info & BIT(22)); + return vmx_instr_info_extended() ? !(instr_info & BIT(10)) : + !(instr_info & BIT(22)); } =20 static inline int vmx_get_instr_info_base_reg(u64 instr_info) { - return (instr_info >> 23) & 0xf; + return vmx_instr_info_extended() ? (instr_info >> 32) & 0x1f : + (instr_info >> 23) & 0xf; } =20 static inline bool vmx_get_instr_info_base_is_valid(u64 instr_info) { - return !(instr_info & BIT(27)); + return vmx_instr_info_extended() ? !(instr_info & BIT(11)) : + !(instr_info & BIT(27)); } =20 static inline bool vmx_can_use_ipiv(struct kvm_vcpu *vcpu) --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 220A04611C2; Mon, 20 Jul 2026 17:46:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569586; cv=none; b=kqrfG7uKka9U75jZ/7/ZP/pvqVKaW6daCWV92YKS2KCRpmCcSLSve7cc/5fUyMoL5+TEMJxsk97AxuLWGf6TAkuZUSM/PpUHrYQdajWmbRsJ+oZYOLanHBYE8D5Pu/VzI7ROX6hGTBRYCQveHDPlJQnwX1bp86gGUXiOj/n7vUg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569586; c=relaxed/simple; bh=j2KuJ+FnCMF5fGTyEVeJK/Qa4zDs6L2/RfMWpLjdBLU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qVisiEoBhjLbJiPclAbE0x0ERZ0qXWWLbbpjwmiTJi05XWmOEAMIJXPwa2pwrjpTPzlPEsCSejZf4G1BOd/EJX7gbpPv3+9au0GqE6G65e+QjM788osolMMdEpkMDd9k4N7mTlt9NGMepbNtJl1j/QDWTwMPFHIn1AZLTJ32Jvw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Goa94W2E; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Goa94W2E" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569582; x=1816105582; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=j2KuJ+FnCMF5fGTyEVeJK/Qa4zDs6L2/RfMWpLjdBLU=; b=Goa94W2Ep9xxz+v/EvA4Lwl4JZNrnJq1dzewupP4lgOEvNY8azCQ6crp LIUXc5u2mw7mlS3mB8HYHw78C/iAWNN7pzdHo4aiOMihF9/vR8tFE4XyE wRWsZYSMTGyrUVyQQh+/l8QKGZorc/LI/TzkWWX1ZGCj8lyWLp9LDd+EP +fAsMyghgXE7/67Gb15d3WgOLWSblpMrnR5ReBG8a1P8yJFswF2Xs1ToY 7bTOrDYCjR9O/IV40Az8z0u3lwk4NBkhrswrqhxTXgkEafK/XmPhzLmMG jNIRNYLGi/zR7PgsqQ+wGlSVP5pYxwstwG5kcZVwfUW3JJ63UCn/E0N8J A==; X-CSE-ConnectionGUID: oIbdi54JQz6F9cNeyw6VCw== X-CSE-MsgGUID: eUlm77R1SlmxN6UZvLAzEg== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691671" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691671" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:46:05 -0700 X-CSE-ConnectionGUID: B2XjDyXrSHiuorMgGFgY0w== X-CSE-MsgGUID: 0Qi4KyWYSbSjFMcS0KOwKA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575366" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:46:04 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com, Chao Gao Subject: [PATCH v5 09/20] KVM: nVMX: Propagate extended instruction information Date: Mon, 20 Jul 2026 17:19:38 +0000 Message-ID: <20260720171949.498680-10-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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" Define the new extended_instruction_info field in struct vmcs12 and propagate it to nested VMX. Gate the propagation on the guest APX enumeration, which aligns with bare metal behavior. Thus, define the CPUID bit here too. Suggested-by: Chao Gao Signed-off-by: Chang S. Bae Link: https://lore.kernel.org/aRvOSnaUt1E+%2FpkC@intel.com --- arch/x86/kvm/reverse_cpuid.h | 2 ++ arch/x86/kvm/vmx/nested.c | 6 ++++++ arch/x86/kvm/vmx/vmcs12.c | 1 + arch/x86/kvm/vmx/vmcs12.h | 3 ++- 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h index 657f5f743ed9..de90697c4e5a 100644 --- a/arch/x86/kvm/reverse_cpuid.h +++ b/arch/x86/kvm/reverse_cpuid.h @@ -35,6 +35,7 @@ #define X86_FEATURE_AVX_VNNI_INT16 KVM_X86_FEATURE(CPUID_7_1_EDX, 10) #define X86_FEATURE_PREFETCHITI KVM_X86_FEATURE(CPUID_7_1_EDX, 14) #define X86_FEATURE_AVX10 KVM_X86_FEATURE(CPUID_7_1_EDX, 19) +#define KVM_X86_FEATURE_APX KVM_X86_FEATURE(CPUID_7_1_EDX, 21) =20 /* Intel-defined sub-features, CPUID level 0x00000007:2 (EDX) */ #define X86_FEATURE_INTEL_PSFD KVM_X86_FEATURE(CPUID_7_2_EDX, 0) @@ -144,6 +145,7 @@ static __always_inline u32 __feature_translate(int x86_= feature) KVM_X86_TRANSLATE_FEATURE(SGX1); KVM_X86_TRANSLATE_FEATURE(SGX2); KVM_X86_TRANSLATE_FEATURE(SGX_EDECCSSA); + KVM_X86_TRANSLATE_FEATURE(APX); KVM_X86_TRANSLATE_FEATURE(CONSTANT_TSC); KVM_X86_TRANSLATE_FEATURE(PERFMON_V2); KVM_X86_TRANSLATE_FEATURE(RRSBA_CTRL); diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 8e0523e40477..1684f5d1dbf4 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -4766,6 +4766,12 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, st= ruct vmcs12 *vmcs12, vmcs12->vm_exit_intr_info =3D exit_intr_info; vmcs12->vm_exit_instruction_len =3D exit_insn_len; vmcs12->vmx_instruction_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); + /* + * The APX enumeration guarantees the presence of the extended + * fields. This CPUID bit alone is sufficient to rely on it. + */ + if (guest_cpu_cap_has(vcpu, X86_FEATURE_APX)) + vmcs12->extended_instruction_info =3D vmcs_read64(EXTENDED_INSTRUCTION_= INFO); =20 /* * According to spec, there's no need to store the guest's diff --git a/arch/x86/kvm/vmx/vmcs12.c b/arch/x86/kvm/vmx/vmcs12.c index 1ebe67c384ad..267aa64f005e 100644 --- a/arch/x86/kvm/vmx/vmcs12.c +++ b/arch/x86/kvm/vmx/vmcs12.c @@ -53,6 +53,7 @@ static const u16 kvm_supported_vmcs12_field_offsets[] __i= nitconst =3D { FIELD64(XSS_EXIT_BITMAP, xss_exit_bitmap), FIELD64(ENCLS_EXITING_BITMAP, encls_exiting_bitmap), FIELD64(GUEST_PHYSICAL_ADDRESS, guest_physical_address), + FIELD64(EXTENDED_INSTRUCTION_INFO, extended_instruction_info), FIELD64(VMCS_LINK_POINTER, vmcs_link_pointer), FIELD64(GUEST_IA32_DEBUGCTL, guest_ia32_debugctl), FIELD64(GUEST_IA32_PAT, guest_ia32_pat), diff --git a/arch/x86/kvm/vmx/vmcs12.h b/arch/x86/kvm/vmx/vmcs12.h index 21cd1b75e4fd..25e9a41c248f 100644 --- a/arch/x86/kvm/vmx/vmcs12.h +++ b/arch/x86/kvm/vmx/vmcs12.h @@ -71,7 +71,7 @@ struct __packed vmcs12 { u64 pml_address; u64 encls_exiting_bitmap; u64 tsc_multiplier; - u64 padding64[1]; /* room for future expansion */ + u64 extended_instruction_info; /* * To allow migration of L1 (complete with its L2 guests) between * machines of different natural widths (32 or 64 bit), we cannot have @@ -261,6 +261,7 @@ static inline void vmx_check_vmcs12_offsets(void) CHECK_OFFSET(pml_address, 312); CHECK_OFFSET(encls_exiting_bitmap, 320); CHECK_OFFSET(tsc_multiplier, 328); + CHECK_OFFSET(extended_instruction_info, 336); CHECK_OFFSET(cr0_guest_host_mask, 344); CHECK_OFFSET(cr4_guest_host_mask, 352); CHECK_OFFSET(cr0_read_shadow, 360); --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 AFAE8446BF1; Mon, 20 Jul 2026 17:46:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569591; cv=none; b=cG8DT+bJTg/fHFaY39Vp0Hf45Bs5Yd8eU9hAVelNmxqPcanoviTeqJhHXbMvdGP1k+NXgTbH7UoYAQ2hiWD6YN6hOtj3XMa0i5+7lNc4dlWKix04LhCXkKWz1nvxbyUYC6WNCq336ugD1gVshjPlOdjZ7t0oFuCnVrySyI4plpk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569591; c=relaxed/simple; bh=0GUmgwR1+KzxXTJz6iffTPJCSR7dd2qwxnZp+au4HrE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Hfj0XS2LWsqh8vXyOiVt5zCOOjlREU+3oI+gfhx80OGfEKoSH0UWWRv4ImuFeCtdyD8n3Jd67Ic4VkHpuZrHDCzQFp3BJcwoD0BQvf3t3lVfLgPU9vP/IDh9gxOSD2oo+fQXfqfvuXR3HSZOVAMHy+z9Oz/+WmP5+frdyPRQHYM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Nt85NjwY; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Nt85NjwY" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569585; x=1816105585; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=0GUmgwR1+KzxXTJz6iffTPJCSR7dd2qwxnZp+au4HrE=; b=Nt85NjwYju6dIMwNOyEVtACU31Ptaa2Ot4mZ2CgRykiXHwI5xfo0w022 5TM1B5lsmiEm5EhyPlQSf+rlicA04tMYZG9tgbxFma717LrnfLhxPUplj jLQjDFwjrMDlpDMTML9fiYZl76QOlVsBaeRW8NyhbFY8DsrqqYYz9tYjG Flvyc9MvIkHSAF0sYHYD7j+eNc3L7/JCPpCUOh8CX36JhwqxciQHuMTEA MXVddvVFqY0kNGhmjzI397ATOc4J2Qshuv6RlGxEQScGtuaroZNLqvjlF fzXp5FjzMa3Q1DU/rqOxDtICfFtAM7wpr6ThedHrymj6Nq17LK7nI2ZHM w==; X-CSE-ConnectionGUID: yv3AXKCWSpeJLprxK2ugWQ== X-CSE-MsgGUID: iGjfPrYtTdGUSaKqYWahHQ== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691676" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691676" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:46:06 -0700 X-CSE-ConnectionGUID: UGXY7/G+Q+a3KLdgPBPEPA== X-CSE-MsgGUID: +UmXK2smRq2JSc9TggSYwg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575373" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:46:05 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com Subject: [PATCH v5 10/20] KVM: x86: Support EGPR accessing and tracking for emulator Date: Mon, 20 Jul 2026 17:19:39 +0000 Message-ID: <20260720171949.498680-11-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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" Extend the emulator context and GPR accessors to handle EGPRs before adding support for REX2-prefixed instructions. Like VCPU cache, the emulator can uniformly cache and track all GPRs. Also replace `1 << reg` with `BIT(reg)` in reg_read()/reg_write(). The former performs a signed 32-bit shift, which becomes undefined for R31. BIT() instead shifts an unsigned value that is suitable for all indices. Signed-off-by: Chang S. Bae --- V4 -> V5: Fix possible shift-out-of-bounds (review bot [*]) [*]: locally running Sashiko with gemini-3.1-pro-preview --- arch/x86/kvm/kvm_emulate.h | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h index 3e375af15c03..b1498f618c81 100644 --- a/arch/x86/kvm/kvm_emulate.h +++ b/arch/x86/kvm/kvm_emulate.h @@ -109,13 +109,13 @@ struct x86_instruction_info { struct x86_emulate_ops { void (*vm_bugged)(struct x86_emulate_ctxt *ctxt); /* - * read_gpr: read a general purpose register (rax - r15) + * read_gpr: read a general purpose register (rax - r31) * * @reg: gpr number. */ ulong (*read_gpr)(struct x86_emulate_ctxt *ctxt, unsigned reg); /* - * write_gpr: write a general purpose register (rax - r15) + * write_gpr: write a general purpose register (rax - r31) * * @reg: gpr number. * @val: value to write. @@ -321,7 +321,9 @@ typedef void (*fastop_t)(struct fastop *); * also uses _eip, RIP cannot be a register operand nor can it be an opera= nd in * a ModRM or SIB byte. */ -#ifdef CONFIG_X86_64 +#if defined(CONFIG_KVM_APX) +#define NR_EMULATOR_GPRS 32 +#elif defined(CONFIG_X86_64) #define NR_EMULATOR_GPRS 16 #else #define NR_EMULATOR_GPRS 8 @@ -381,9 +383,9 @@ struct x86_emulate_ctxt { u8 lock_prefix; u8 rep_prefix; /* bitmaps of registers in _regs[] that can be read */ - u16 regs_valid; + u32 regs_valid; /* bitmaps of registers in _regs[] that have been written */ - u16 regs_dirty; + u32 regs_dirty; /* modrm */ u8 modrm; u8 modrm_mod; @@ -547,8 +549,8 @@ static inline ulong reg_read(struct x86_emulate_ctxt *c= txt, unsigned nr) if (KVM_EMULATOR_BUG_ON(nr >=3D NR_EMULATOR_GPRS, ctxt)) nr &=3D NR_EMULATOR_GPRS - 1; =20 - if (!(ctxt->regs_valid & (1 << nr))) { - ctxt->regs_valid |=3D 1 << nr; + if (!(ctxt->regs_valid & BIT(nr))) { + ctxt->regs_valid |=3D BIT(nr); ctxt->_regs[nr] =3D ctxt->ops->read_gpr(ctxt, nr); } return ctxt->_regs[nr]; @@ -562,8 +564,8 @@ static inline ulong *reg_write(struct x86_emulate_ctxt = *ctxt, unsigned nr) BUILD_BUG_ON(sizeof(ctxt->regs_dirty) * BITS_PER_BYTE < NR_EMULATOR_GPRS); BUILD_BUG_ON(sizeof(ctxt->regs_valid) * BITS_PER_BYTE < NR_EMULATOR_GPRS); =20 - ctxt->regs_valid |=3D 1 << nr; - ctxt->regs_dirty |=3D 1 << nr; + ctxt->regs_valid |=3D BIT(nr); + ctxt->regs_dirty |=3D BIT(nr); return &ctxt->_regs[nr]; } =20 --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 DC02C453486; Mon, 20 Jul 2026 17:46:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569594; cv=none; b=RRZkdki50Q/B0onUGPOKLf3SoumcyGP6Hbmbn6kh5uWusMhmNjz4oDg5IlfpzwBq0IvuQ3X5k7AnNtJ6n66Kr5F6V+Imkx2BRCUMzg+FpKybRziHmwoe8B6S3x0lkg/4Slmi9Aan2EphFzT8miKoYEAEBqlJCTHjbvWcBQLeMOo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569594; c=relaxed/simple; bh=hJrxV2vh1Ac+o1soV5h5EKzDyGNXsx1NRnZwGnyHvMs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hM5AmAHl0acAjYHWA5ZIPIX2dAiOfBziFCtMR+HwBodF5hbYmTpUuTZUqah9JlMLzZSV+szKorzyr/RCpyglYJGh0pAnNOUoewnmy5gcuMWCSNXjNP1awc1DKziwg5cCKQnEMk4jUoUUQBdoZJAPyxfdn5mxe7W1FdFhA8EWaWs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=LQIZnqqb; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="LQIZnqqb" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569590; x=1816105590; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=hJrxV2vh1Ac+o1soV5h5EKzDyGNXsx1NRnZwGnyHvMs=; b=LQIZnqqby0AtueIqiQcH3C5+qhBDgWq0/KRza4sywxaJ60kdVHkCcfck rtKdSzMU+LAIE6munoha6vmECV+lAfxhwM2uYd50UDB3BsADlWcl6eWOs +lEXbWJYVcPtyyf6yIpqdiOcJZetzZ1oJc7eaTwVETKc+ki5iiAKAgGMt 7WWLtjBrSyr8FePpOE+2zUaupWCDZ4F5rAyCI7qWGPt39PEqSLkAc6nBb 7xrN1eoUCUCqe1jNOV6SseaIfgmWAsQYssBKBCKjsaYcEgrfdalDaReQu PcAuyAo18P9IC8cfSFC5ZZmrzW/cRWqB0oJYCdf8HGS308huMKJmOBvYT A==; X-CSE-ConnectionGUID: 8MU5eR7BQUGZfHlcQYtpIQ== X-CSE-MsgGUID: tsC83hbpTzSgCUwlDhAylg== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691682" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691682" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:46:07 -0700 X-CSE-ConnectionGUID: evOMLHL9Rb+OKDdlM0TwiQ== X-CSE-MsgGUID: rjT9kpG8S+G8QPk0JIv6XA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575377" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:46:06 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com Subject: [PATCH v5 11/20] KVM: x86: Handle EGPR index and REX2-incompatible opcodes Date: Mon, 20 Jul 2026 17:19:40 +0000 Message-ID: <20260720171949.498680-12-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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" Prepare the emulator for REX2 handling by introducing the NoRex2 opcode flag and supporting extended register indices. For the latter, factor out common logic for calculating register IDs. REX2 does not support three-byte opcodes. Instead, the REX2.M bit selects between one- and two-byte opcode tables, which were previously distinguished by the 0x0F escape byte. Some legacy instructions in those tables never reference extended registers. When prefixed with REX, such instructions are treated as if the prefix were absent. In contrast, a REX2 prefix causes a #UD, which should be handled explicitly. Suggested-by: Paolo Bonzini Signed-off-by: Chang S. Bae Link: https://lore.kernel.org/1ebf3a23-5671-41c1-8daa-c83f2f105936@redhat.c= om --- arch/x86/kvm/emulate.c | 80 +++++++++++++++++++++++--------------- arch/x86/kvm/kvm_emulate.h | 1 + 2 files changed, 50 insertions(+), 31 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index b566ab5c7515..12a822870d08 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -175,6 +175,7 @@ #define TwoMemOp ((u64)1 << 55) /* Instruction has two memory operand = */ #define IsBranch ((u64)1 << 56) /* Instruction is considered a branch.= */ #define ShadowStack ((u64)1 << 57) /* Instruction affects Shadow Stacks. = */ +#define NoRex2 ((u64)1 << 58) /* Instruction not present in REX2 map= s */ =20 #define DstXacc (DstAccLo | SrcAccHi | SrcWrite) =20 @@ -244,6 +245,7 @@ enum rex_bits { REX_X =3D 2, REX_R =3D 4, REX_W =3D 8, + REX_M =3D 0x80, }; =20 static void writeback_registers(struct x86_emulate_ctxt *ctxt) @@ -1079,6 +1081,15 @@ static int em_fnstsw(struct x86_emulate_ctxt *ctxt) return X86EMUL_CONTINUE; } =20 +static __always_inline int rex_get_rxb(u8 rex, u8 fld) +{ + BUILD_BUG_ON(!__builtin_constant_p(fld)); + BUILD_BUG_ON(fld !=3D REX_B && fld !=3D REX_X && fld !=3D REX_R); + + rex >>=3D ffs(fld) - 1; + return (rex & 1 ? 8 : 0) + (rex & 0x10 ? 16 : 0); +} + static void __decode_register_operand(struct x86_emulate_ctxt *ctxt, struct operand *op, int reg) { @@ -1118,7 +1129,7 @@ static void decode_register_operand(struct x86_emulat= e_ctxt *ctxt, if (ctxt->d & ModRM) reg =3D ctxt->modrm_reg; else - reg =3D (ctxt->b & 7) | (ctxt->rex_bits & REX_B ? 8 : 0); + reg =3D (ctxt->b & 7) | rex_get_rxb(ctxt->rex_bits, REX_B); =20 __decode_register_operand(ctxt, op, reg); } @@ -1137,9 +1148,9 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt, int rc =3D X86EMUL_CONTINUE; ulong modrm_ea =3D 0; =20 - ctxt->modrm_reg =3D (ctxt->rex_bits & REX_R ? 8 : 0); - index_reg =3D (ctxt->rex_bits & REX_X ? 8 : 0); - base_reg =3D (ctxt->rex_bits & REX_B ? 8 : 0); + ctxt->modrm_reg =3D rex_get_rxb(ctxt->rex_bits, REX_R); + index_reg =3D rex_get_rxb(ctxt->rex_bits, REX_X); + base_reg =3D rex_get_rxb(ctxt->rex_bits, REX_B); =20 ctxt->modrm_mod =3D (ctxt->modrm & 0xc0) >> 6; ctxt->modrm_reg |=3D (ctxt->modrm & 0x38) >> 3; @@ -4247,7 +4258,7 @@ static const struct opcode opcode_table[256] =3D { /* 0x38 - 0x3F */ I6ALU(NoWrite, em_cmp), N, N, /* 0x40 - 0x4F */ - X8(I(DstReg, em_inc)), X8(I(DstReg, em_dec)), + X8(I(DstReg | NoRex2, em_inc)), X8(I(DstReg | NoRex2, em_dec)), /* 0x50 - 0x57 */ X8(I(SrcReg | Stack, em_push)), /* 0x58 - 0x5F */ @@ -4265,7 +4276,7 @@ static const struct opcode opcode_table[256] =3D { I2bvIP(DstDI | SrcDX | Mov | String | Unaligned, em_in, ins, check_perm_i= n), /* insb, insw/insd */ I2bvIP(SrcSI | DstDX | String, em_out, outs, check_perm_out), /* outsb, o= utsw/outsd */ /* 0x70 - 0x7F */ - X16(D(SrcImmByte | NearBranch | IsBranch)), + X16(D(SrcImmByte | NearBranch | IsBranch | NoRex2)), /* 0x80 - 0x87 */ G(ByteOp | DstMem | SrcImm, group1), G(DstMem | SrcImm, group1), @@ -4289,15 +4300,15 @@ static const struct opcode opcode_table[256] =3D { II(ImplicitOps | Stack, em_popf, popf), I(ImplicitOps, em_sahf), I(ImplicitOps, em_lahf), /* 0xA0 - 0xA7 */ - I2bv(DstAcc | SrcMem | Mov | MemAbs, em_mov), - I2bv(DstMem | SrcAcc | Mov | MemAbs | PageTable, em_mov), - I2bv(SrcSI | DstDI | Mov | String | TwoMemOp, em_mov), - I2bv(SrcSI | DstDI | String | NoWrite | TwoMemOp, em_cmp_r), + I2bv(DstAcc | SrcMem | Mov | MemAbs | NoRex2, em_mov), + I2bv(DstMem | SrcAcc | Mov | MemAbs | PageTable | NoRex2, em_mov), + I2bv(SrcSI | DstDI | Mov | String | TwoMemOp | NoRex2, em_mov), + I2bv(SrcSI | DstDI | String | NoWrite | TwoMemOp | NoRex2, em_cmp_r), /* 0xA8 - 0xAF */ - I2bv(DstAcc | SrcImm | NoWrite, em_test), - I2bv(SrcAcc | DstDI | Mov | String, em_mov), - I2bv(SrcSI | DstAcc | Mov | String, em_mov), - I2bv(SrcAcc | DstDI | String | NoWrite, em_cmp_r), + I2bv(DstAcc | SrcImm | NoWrite | NoRex2, em_test), + I2bv(SrcAcc | DstDI | Mov | String | NoRex2, em_mov), + I2bv(SrcSI | DstAcc | Mov | String | NoRex2, em_mov), + I2bv(SrcAcc | DstDI | String | NoWrite | NoRex2, em_cmp_r), /* 0xB0 - 0xB7 */ X8(I(ByteOp | DstReg | SrcImm | Mov, em_mov)), /* 0xB8 - 0xBF */ @@ -4327,17 +4338,17 @@ static const struct opcode opcode_table[256] =3D { /* 0xD8 - 0xDF */ N, E(0, &escape_d9), N, E(0, &escape_db), N, E(0, &escape_dd), N, N, /* 0xE0 - 0xE7 */ - X3(I(SrcImmByte | NearBranch | IsBranch, em_loop)), - I(SrcImmByte | NearBranch | IsBranch, em_jcxz), - I2bvIP(SrcImmUByte | DstAcc, em_in, in, check_perm_in), - I2bvIP(SrcAcc | DstImmUByte, em_out, out, check_perm_out), + X3(I(SrcImmByte | NearBranch | IsBranch | NoRex2, em_loop)), + I(SrcImmByte | NearBranch | IsBranch | NoRex2, em_jcxz), + I2bvIP(SrcImmUByte | DstAcc | NoRex2, em_in, in, check_perm_in), + I2bvIP(SrcAcc | DstImmUByte | NoRex2, em_out, out, check_perm_out), /* 0xE8 - 0xEF */ - I(SrcImm | NearBranch | IsBranch | ShadowStack, em_call), - D(SrcImm | ImplicitOps | NearBranch | IsBranch), - I(SrcImmFAddr | No64 | IsBranch, em_jmp_far), - D(SrcImmByte | ImplicitOps | NearBranch | IsBranch), - I2bvIP(SrcDX | DstAcc, em_in, in, check_perm_in), - I2bvIP(SrcAcc | DstDX, em_out, out, check_perm_out), + I(SrcImm | NearBranch | IsBranch | ShadowStack | NoRex2, em_call), + D(SrcImm | ImplicitOps | NearBranch | IsBranch | NoRex2), + I(SrcImmFAddr | No64 | IsBranch | NoRex2, em_jmp_far), + D(SrcImmByte | ImplicitOps | NearBranch | IsBranch | NoRex2), + I2bvIP(SrcDX | DstAcc | NoRex2, em_in, in, check_perm_in), + I2bvIP(SrcAcc | DstDX | NoRex2, em_out, out, check_perm_out), /* 0xF0 - 0xF7 */ N, DI(ImplicitOps, icebp), N, N, DI(ImplicitOps | Priv, hlt), D(ImplicitOps), @@ -4378,12 +4389,12 @@ static const struct opcode twobyte_table[256] =3D { N, GP(ModRM | DstMem | SrcReg | Mov | Sse | Avx, &pfx_0f_2b), N, N, N, N, /* 0x30 - 0x3F */ - II(ImplicitOps | Priv, em_wrmsr, wrmsr), - IIP(ImplicitOps, em_rdtsc, rdtsc, check_rdtsc), - II(ImplicitOps | Priv, em_rdmsr, rdmsr), - IIP(ImplicitOps, em_rdpmc, rdpmc, check_rdpmc), - I(ImplicitOps | EmulateOnUD | IsBranch | ShadowStack, em_sysenter), - I(ImplicitOps | Priv | EmulateOnUD | IsBranch | ShadowStack, em_sysexit), + II(ImplicitOps | Priv | NoRex2, em_wrmsr, wrmsr), + IIP(ImplicitOps | NoRex2, em_rdtsc, rdtsc, check_rdtsc), + II(ImplicitOps | Priv | NoRex2, em_rdmsr, rdmsr), + IIP(ImplicitOps | NoRex2, em_rdpmc, rdpmc, check_rdpmc), + I(ImplicitOps | EmulateOnUD | IsBranch | ShadowStack | NoRex2, em_sysente= r), + I(ImplicitOps | Priv | EmulateOnUD | IsBranch | ShadowStack | NoRex2, em_= sysexit), N, N, N, N, N, N, N, N, N, N, /* 0x40 - 0x4F */ @@ -4401,7 +4412,7 @@ static const struct opcode twobyte_table[256] =3D { N, N, N, N, N, N, N, GP(SrcReg | DstMem | ModRM | Mov, &pfx_0f_6f_0f_7f), /* 0x80 - 0x8F */ - X16(D(SrcImm | NearBranch | IsBranch)), + X16(D(SrcImm | NearBranch | IsBranch | NoRex2)), /* 0x90 - 0x9F */ X16(D(ByteOp | DstMem | SrcNone | ModRM| Mov)), /* 0xA0 - 0xA7 */ @@ -4994,6 +5005,13 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, v= oid *insn, int insn_len, int opcode =3D opcode_table[ctxt->b]; } =20 + /* + * Instructions marked with NoRex2 ignore a legacy REX prefix, but #UD + * should be raised when prefixed with REX2. + */ + if (opcode.flags & NoRex2 && ctxt->rex_prefix =3D=3D REX2_PREFIX) + opcode.flags =3D Undefined; + if (opcode.flags & ModRM) ctxt->modrm =3D insn_fetch(u8, ctxt); =20 diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h index b1498f618c81..f1ca1938af71 100644 --- a/arch/x86/kvm/kvm_emulate.h +++ b/arch/x86/kvm/kvm_emulate.h @@ -335,6 +335,7 @@ typedef void (*fastop_t)(struct fastop *); enum rex_type { REX_NONE, REX_PREFIX, + REX2_PREFIX, }; =20 struct x86_emulate_ctxt { --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 DAF48451076; Mon, 20 Jul 2026 17:46:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569593; cv=none; b=nsvSUVpp3JCEr0laW5WMDvcy9o93+368uoDnbcQw/od2IYCRVkcji0swVsOVqT8Aw6bZyz8ea+Dn9/3oGk+tdKbAS3V1Fezq/o8irp4qI8neP5RxuDBtaMVGcML6fQcApAU0lQVhiGarUHp6k+aYZYAL1kMNr3Kej9pBZfFa+pA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569593; c=relaxed/simple; bh=mf7PIUkmhPMkGVj3mk9Bxldu32ClxvFg/P+gC1ir4ZQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=UkOKOGXuczbUl6OcjlZueQexkoL8xDJZB0Bp7KKFgY8VbmEs7WFzUs42VeiPOAFcb/4JQLKG/QkuCwjqsMgelLCwGvxYAROnuPJ1675Ekqwcubq4W6iyL702J/nQX3ApgpmQLadVDrTcUX5FxsaEdxIO2up++Q3XvMG39PjfaS8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=c1iGrdte; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="c1iGrdte" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569589; x=1816105589; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=mf7PIUkmhPMkGVj3mk9Bxldu32ClxvFg/P+gC1ir4ZQ=; b=c1iGrdteZbrPQyo1jIOh8joVeksSkkwjf6c726KFD7GDctX4PIxztJry ZRnE2sGP3wULe2QmfVFaJ8yILdHtwFrj71foTt7ZC6ooY04fx7KLSauQf OrBUtvmgnyHvgGRIs3f0ScH5XDWEHW9MXmD4XYOSceyxhtZgmra4mawHD KIuzeiWfPosfTw7gzy9BMUZwdE+qOe6yl6mYm6yWf/KsqNONwK6IYZ6NQ o8rYNkknuR+NmxNT526LX8kJqoOnrknW2DcaT3i/E+5QDOxkDFjb7gq+9 JDR4yX3CNIpNWwhb7gRhQp69adVDRbIOLGmVBXqkGXNfw/wBpEXTj5+aS w==; X-CSE-ConnectionGUID: B4oUilUFQ92LqeSbhxmL9g== X-CSE-MsgGUID: DzF0rXPeTo6O1nP9H7nknw== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691687" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691687" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:46:07 -0700 X-CSE-ConnectionGUID: vLvn24NgSM2Fs9HiJ68piA== X-CSE-MsgGUID: j+xUcyjkQoG/Mqexn2jeLQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575380" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:46:07 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com Subject: [PATCH v5 12/20] KVM: x86: Support REX2-prefixed opcode decode Date: Mon, 20 Jul 2026 17:19:41 +0000 Message-ID: <20260720171949.498680-13-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Extend the instruction decoder to recognize and handle the REX2 prefix, including validation of prefix sequences and correct opcode table selection. REX2 is a terminal prefix: once 0xD5 is encountered, the following byte is the opcode. When REX.M=3D0, most prefix bytes are invalid after REX2, including REX, VEX, EVEX, and another REX2. Also, REX2-prefixed instructions are only valid in 64-bit mode. All of the invalid prefix combinations after REX2 coincide with opcodes that are architecturally invalid in 64-bit mode. Thus, marking such opcodes with No64 in opcode_table[] naturally disallows those illegal prefix sequences. The 0x40=E2=80=930x4F opcode row was missing the No64 flag. While NoRex2 al= ready invalidates REX2 for these opcodes, adding No64 makes opcode attributes explicit and complete. Suggested-by: Paolo Bonzini Signed-off-by: Chang S. Bae Link: https://lore.kernel.org/CABgObfYYGTvkYpeyqLSr9JgKMDA_STSff2hXBNchLZuK= FU+MMA@mail.gmail.com --- arch/x86/kvm/emulate.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 12a822870d08..cb075bd74f76 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -4258,7 +4258,7 @@ static const struct opcode opcode_table[256] =3D { /* 0x38 - 0x3F */ I6ALU(NoWrite, em_cmp), N, N, /* 0x40 - 0x4F */ - X8(I(DstReg | NoRex2, em_inc)), X8(I(DstReg | NoRex2, em_dec)), + X8(I(DstReg | NoRex2 | No64, em_inc)), X8(I(DstReg | NoRex2 | No64, em_de= c)), /* 0x50 - 0x57 */ X8(I(SrcReg | Stack, em_push)), /* 0x58 - 0x5F */ @@ -4852,6 +4852,17 @@ static int x86_decode_avx(struct x86_emulate_ctxt *c= txt, return rc; } =20 +static inline bool rex2_invalid(struct x86_emulate_ctxt *ctxt) +{ + const struct x86_emulate_ops *ops =3D ctxt->ops; + u64 xcr =3D 0; + + return ctxt->rex_prefix =3D=3D REX_PREFIX || + !(ops->get_cr(ctxt, 4) & X86_CR4_OSXSAVE) || + ops->get_xcr(ctxt, 0, &xcr) || + !(xcr & XFEATURE_MASK_APX); +} + int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_le= n, int emulation_type) { int rc =3D X86EMUL_CONTINUE; @@ -4905,7 +4916,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, vo= id *insn, int insn_len, int ctxt->op_bytes =3D def_op_bytes; ctxt->ad_bytes =3D def_ad_bytes; =20 - /* Legacy prefixes. */ + /* Legacy and REX/REX2 prefixes. */ for (;;) { switch (ctxt->b =3D insn_fetch(u8, ctxt)) { case 0x66: /* operand-size override */ @@ -4951,6 +4962,17 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, v= oid *insn, int insn_len, int ctxt->rex_prefix =3D REX_PREFIX; ctxt->rex_bits =3D ctxt->b & 0xf; continue; + case 0xd5: /* REX2 */ + if (mode !=3D X86EMUL_MODE_PROT64) + goto done_prefixes; + if (rex2_invalid(ctxt)) { + opcode =3D ud; + goto done_modrm; + } + ctxt->rex_prefix =3D REX2_PREFIX; + ctxt->rex_bits =3D insn_fetch(u8, ctxt); + ctxt->b =3D insn_fetch(u8, ctxt); + goto done_prefixes; case 0xf0: /* LOCK */ ctxt->lock_prefix =3D 1; break; @@ -4973,6 +4995,12 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, v= oid *insn, int insn_len, int if (ctxt->rex_bits & REX_W) ctxt->op_bytes =3D 8; =20 + /* REX2 opcode is one byte unless M-bit selects the two-byte map */ + if (ctxt->rex_bits & REX_M) + goto decode_twobytes; + else if (ctxt->rex_prefix =3D=3D REX2_PREFIX) + goto decode_onebyte; + /* Opcode byte(s). */ if (ctxt->b =3D=3D 0xc4 || ctxt->b =3D=3D 0xc5) { /* VEX or LDS/LES */ @@ -4990,17 +5018,19 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, = void *insn, int insn_len, int goto done; } else if (ctxt->b =3D=3D 0x0f) { /* Two- or three-byte opcode */ - ctxt->opcode_len =3D 2; ctxt->b =3D insn_fetch(u8, ctxt); +decode_twobytes: + ctxt->opcode_len =3D 2; opcode =3D twobyte_table[ctxt->b]; =20 /* 0F_38 opcode map */ - if (ctxt->b =3D=3D 0x38) { + if (ctxt->b =3D=3D 0x38 && ctxt->rex_prefix !=3D REX2_PREFIX) { ctxt->opcode_len =3D 3; ctxt->b =3D insn_fetch(u8, ctxt); opcode =3D opcode_map_0f_38[ctxt->b]; } } else { +decode_onebyte: /* Opcode byte(s). */ opcode =3D opcode_table[ctxt->b]; } --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 A6DC64779A7; Mon, 20 Jul 2026 17:46:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569604; cv=none; b=AWziX5jUt/QP8bj5NHag8ysljeRMHxojGuuzyYERNrJmY5NmPW8+nvkuePdC5yeCW6rEPvXNWFbDQi0EY7dQbmSbGTUkiq3fjo6++qliEz1qFuRHwUGCzw4x4guMAwb16tE0V5ZuhiZJiN/ExmHX7Wok34+1O+qfbGeMUfmlZs8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569604; c=relaxed/simple; bh=K0a43zC/CH1JRV9XZ9iaXKo0MS6XUMZZHsZPAiQ70Pc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OQafnn/o+AVGLn3NugWzzEHzCaQeac8H4hwOFV9CtUb8Y4sqXiV3VTW2T9F/TuXv5CjxgyKNlLD+AmtlHg9tQRM7PpJ9frA9FwNzoHfm0gSqKwn+Ybs2PeZUuwjLnY4kasKupB6uPOfnYf03dim5aWP1uaLOY1VODkzafV3S7t8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=QxFMMS92; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="QxFMMS92" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569593; x=1816105593; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=K0a43zC/CH1JRV9XZ9iaXKo0MS6XUMZZHsZPAiQ70Pc=; b=QxFMMS92OzfaTeesmu4TgAVNeBmGgJXf5AHr3HZ1j8gxosg2oEJlG9Mu F7wOqRIHxdKCXrVybiJjEJv5DAksjS3VU9ZzMaQeY//5wpcPUT3l89ZOT 41QpdSX6Sxu8hcnOpAFphePmvn9zzS8QNZDE8I4R9vJgWdANaV83s/Z1A bRqlJ7wEJZrx+bGF6gMC7T4ZVeLNjVJjiZuAfoAtR4tVMY1Yr0ivLlzY0 gQIbZhO+Q8cOjkUpRkUTh9emrJLdIaBQhdZAQBLUbq4X8CDkuUwgXZLD2 GFotP260sBMNRBNc3Sl5JGIEslSCll0Pukapjpk6IonoPqDOWh3A1XhAB A==; X-CSE-ConnectionGUID: 2lEmtkh3TM2u1hqDKGDK2Q== X-CSE-MsgGUID: nT7e92vbQ+iEASTJ+hODmA== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691692" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691692" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:46:08 -0700 X-CSE-ConnectionGUID: ma1vnY4ZTpOHzj8lxS7X4A== X-CSE-MsgGUID: BHpi7cttTm+BMXpM8movJA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575383" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:46:08 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com Subject: [PATCH v5 13/20] KVM: x86: Reject EVEX-prefixed instructions Date: Mon, 20 Jul 2026 17:19:42 +0000 Message-ID: <20260720171949.498680-14-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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" Explicitly mark EVEX-prefixed opcodes (0x62) as unsupported. Signed-off-by: Chang S. Bae --- arch/x86/kvm/emulate.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index cb075bd74f76..fc7f9f17c1da 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -5045,6 +5045,11 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, v= oid *insn, int insn_len, int if (opcode.flags & ModRM) ctxt->modrm =3D insn_fetch(u8, ctxt); =20 + /* EVEX-prefixed instructions are not implemented */ + if (ctxt->opcode_len =3D=3D 1 && ctxt->b =3D=3D 0x62 && + (mode =3D=3D X86EMUL_MODE_PROT64 || (ctxt->modrm & 0xc0) =3D=3D 0xc0)) + opcode.flags =3D NotImpl; + done_modrm: ctxt->d =3D opcode.flags; while (ctxt->d & GroupMask) { --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 282D64534B7; Mon, 20 Jul 2026 17:46:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569603; cv=none; b=d9orDXYsFFtO+So1S0tdh3paS+ACy+M94yxvIauoRWq/DTP5VyLh1ygEIRmbBVory3KWSQ5JX7AAMJFJUG1+DjF9HDX7PsnfN0G4OTNuTjWD2/MR697/NJiRJ15dWrG3Tl8y4C+9acuyIKGiQKOmmCk9fZ5EpN/kteGZkFT1t8E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569603; c=relaxed/simple; bh=RwLBDBbobIqfFHCU7EokVXN2+HJdk9ueCTsifluUNac=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Cn2bPAxUMWjJehmU6lF5icw6M+k3/Ffu96rvcjEYu1nNl70WqgiboEeT3uUPeZ7arPsn+rrCNrC28zuc9IGN5FG5tEpqyKGOiIC/lvmOSr2rQQadbaK9AbiDT4gAz5N32BMnvTuqlhggUkDCQ5HGOVk5zHtBCeYzmE+1QPfxtoM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Cd7xNlEO; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Cd7xNlEO" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569594; x=1816105594; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=RwLBDBbobIqfFHCU7EokVXN2+HJdk9ueCTsifluUNac=; b=Cd7xNlEOT+H0i7rAuLChW7SM5Xj5VYzc+brgcroxaqE/Drz95L2zBmZY jnQZRjnA1+Z4AGjutKqVsYTYAtfRESwt7Ohigv14XndU0uV61ZBh1ow6E OsOmNCJuHULnAUjk2HcPqFNtAwPZg8Qek3+5LfQEDvI44tCDyB9KFRIfk JEY5KLiIvPVsV9kGaLb/V7cxEGXxfXcC3aOyZ8CnxdpihR1UyPpfAMmxD N4afICt0fk4o8SqIJJHsQaN77pz27MuuuSIUcUFdZK8XKDxh13KhftUPx cd+vMSdrAF0CVikTClKruTG16vAvMdnaZFey7sZ86e7fWLcin+5XJOicF Q==; X-CSE-ConnectionGUID: qpaYB8PjRqKZhoukezlvwQ== X-CSE-MsgGUID: 3Vn5VnhxTReX7ffz2Sqp0w== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691696" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691696" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:46:09 -0700 X-CSE-ConnectionGUID: yB5LLLWIQUaP379BC6MjxQ== X-CSE-MsgGUID: kH02+0qMTw6MutGN1mT91w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575386" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:46:09 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com Subject: [PATCH v5 14/20] KVM: x86: Move KVM_SUPPORTED_{XCR0,XSS} into kvm_x86_vendor_init() Date: Mon, 20 Jul 2026 17:19:43 +0000 Message-ID: <20260720171949.498680-15-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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" From: Sean Christopherson Move KVM_SUPPORTED_{XCR0,XSS} into kvm_x86_vendor_init() as "const u64" values so that KVM's initialization code can further manipulate the set of supported XCR0/XSS features without ugly #ifdeffery and without risking other code treating KVM_SUPPORTED_{XCR0,XSS} as 100% authoritative. No functional change intended. Signed-off-by: Sean Christopherson Signed-off-by: Chang S. Bae Link: https://lore.kernel.org/ahmtyMNsj2BCoEEo@google.com --- V4 -> V5: New patch (Sean) --- arch/x86/kvm/cpuid.c | 2 +- arch/x86/kvm/x86.c | 25 +++++++++++++------------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 122e46db9a15..1fc7a0f9a13a 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -264,7 +264,7 @@ static u32 kvm_apply_cpuid_pv_features_quirk(struct kvm= _vcpu *vcpu) =20 /* * Calculate guest's supported XCR0 taking into account guest CPUID data a= nd - * KVM's supported XCR0 (comprised of host's XCR0 and KVM_SUPPORTED_XCR0). + * KVM's supported XCR0 (the host's actual XCR0 masked by what KVM support= s). */ static u64 cpuid_get_supported_xcr0(struct kvm_vcpu *vcpu) { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 5578df10179a..84b2dcfcb007 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -191,19 +191,7 @@ module_param(pi_inject_timer, bint, 0644); static bool __read_mostly mitigate_smt_rsb; module_param(mitigate_smt_rsb, bool, 0444); =20 -#define KVM_SUPPORTED_XCR0 (XFEATURE_MASK_FP | XFEATURE_MASK_SSE \ - | XFEATURE_MASK_YMM | XFEATURE_MASK_BNDREGS \ - | XFEATURE_MASK_BNDCSR | XFEATURE_MASK_AVX512 \ - | XFEATURE_MASK_PKRU | XFEATURE_MASK_XTILE) - #define XFEATURE_MASK_CET_ALL (XFEATURE_MASK_CET_USER | XFEATURE_MASK_CET_= KERNEL) -/* - * Note, KVM supports exposing PT to the guest, but does not support conte= xt - * switching PT via XSTATE (KVM's PT virtualization relies on perf; swappi= ng - * PT via guest XSTATE would clobber perf state), i.e. KVM doesn't support - * IA32_XSS[bit 8] (guests can/must use RDMSR/WRMSR to save/restore PT MSR= s). - */ -#define KVM_SUPPORTED_XSS (XFEATURE_MASK_CET_ALL) =20 bool __read_mostly allow_smaller_maxphyaddr =3D 0; EXPORT_SYMBOL_FOR_KVM_INTERNAL(allow_smaller_maxphyaddr); @@ -7009,6 +6997,19 @@ static void kvm_x86_check_cpu_compat(void *ret) =20 int kvm_x86_vendor_init(struct kvm_x86_init_ops *ops) { + const u64 KVM_SUPPORTED_XCR0 =3D XFEATURE_MASK_FP | XFEATURE_MASK_SSE | + XFEATURE_MASK_YMM | XFEATURE_MASK_BNDREGS | + XFEATURE_MASK_BNDCSR | XFEATURE_MASK_AVX512 | + XFEATURE_MASK_PKRU | XFEATURE_MASK_XTILE; + /* + * Note, KVM supports exposing PT to the guest, but does not support + * context switching PT via XSTATE (KVM's PT virtualization relies on + * perf; swapping PT via guest XSTATE would clobber perf state), i.e. + * KVM doesn't support IA32_XSS[bit 8] (guests can/must use RDMSR/WRMSR + * to save/restore PT MSRs). + */ + const u64 KVM_SUPPORTED_XSS =3D XFEATURE_MASK_CET_ALL; + u64 host_pat; int r, cpu; =20 --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 96FF0478859; Mon, 20 Jul 2026 17:46:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569603; cv=none; b=TsOhtasPLr1NggmatI20icK4kL2tldG48ZL3Lg+5Ed9ncuIb7L0WUqRNPhBsyha9hjCOAhrt8bLzjNUqhPMUSy46uQ8/dzIUC+z5wGOLAFiVWM7NWnU7mRECiE/YwV8S7DxmChTlvIbYG63jSLySdvp5BPGrib7xlStTINjh5WU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569603; c=relaxed/simple; bh=6uCcnulSABEeTlE4lQI/MpQP8kkqc07y5hMWHwPijIQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mbOlZ6ITPwzHPQ0hreuIeaHR6jESu/bRU4bqQqlzMATdP/ioP5MZtIfJemq7fVmrnPJQWIxIa7HQggBK5X3kY3mBdOCpu6c5Ek43mL7awRdJmb6oBSNvTptKMW6cL0nsv5ly4cwzXpNyv6+R7F2z7we+RjlHr3tmM+XjyhLvroI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=kK0Ug1n2; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="kK0Ug1n2" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569597; x=1816105597; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=6uCcnulSABEeTlE4lQI/MpQP8kkqc07y5hMWHwPijIQ=; b=kK0Ug1n2Ul21Lj97rHr8LpJDvUBJyMljckeJN94Wl91Fmlw2KPuS1okh gOrmyKmQ7xkrb49AVNEW/WQ+JkjTQkaS7WS6duKOC7rCb4vxBi1oe92gM ofFNGxqrn4rE4mPHuZTzHVLw4hHgo97zOH2FkkpvKhTa6NrKdlAIOgYml FgJgbWMGpAfCRT2CihTVlO1yQ3ES2LE4Qf2z3gnjcIzqDFyXygUQpNpK5 3XzwUOoHJbfjp+V3oBqkMSyWFeRdLAe+sglRHEUwps2LNGQOkumRGQDHX 0C64Xh2Eo9V6O2I1xTJZeu6CFf+mwhkOUVUCTP+rQ0Ca/SSdpm8mDPDd0 A==; X-CSE-ConnectionGUID: TqCMJLVISoSYXKHMujzk1A== X-CSE-MsgGUID: UqOFqop7QM+7jphUWEWlLw== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691700" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691700" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:46:10 -0700 X-CSE-ConnectionGUID: B/ws+TGVT26LGmaBarRWEA== X-CSE-MsgGUID: hK7yXLCmReSbD8L3AgyZMQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575389" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:46:10 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com Subject: [PATCH v5 15/20] KVM: x86: Guard valid XCR0.APX settings Date: Mon, 20 Jul 2026 17:19:44 +0000 Message-ID: <20260720171949.498680-16-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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" Prevent invalid XCR0.APX configurations in two cases: conflict with MPX and lack of SVM support. In the non-compacted XSAVE format, APX and MPX conflict on the same offset. Although MPX is being deprecated in practice, KVM should explicitly reject such configurations that set both bits. At this point, only VMX supports EGPRs. SVM will require corresponding extensions to handle EGPR indices. Updating the supported XCR0 mask will be done separately. Suggested-by: Paolo Bonzini Signed-off-by: Chang S. Bae Link: https://lore.kernel.org/ab3f4937-38f5-4354-8850-bf773c159bbe@redhat.c= om --- arch/x86/kvm/svm/svm.c | 7 ++++++- arch/x86/kvm/x86.c | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index ef69a51ab27f..eb1b2ba1261d 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -5612,8 +5612,13 @@ static __init int svm_hardware_setup(void) return -EOPNOTSUPP; } =20 + /* + * APX introduces EGPRs, which require additional VMCB support. + * Disable APX until the necessary extensions are handled. + */ kvm_caps.supported_xcr0 &=3D ~(XFEATURE_MASK_BNDREGS | - XFEATURE_MASK_BNDCSR); + XFEATURE_MASK_BNDCSR | + XFEATURE_MASK_APX); =20 if (tsc_scaling) { if (!boot_cpu_has(X86_FEATURE_TSCRATEMSR)) { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 84b2dcfcb007..266d7a02855b 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -682,6 +682,10 @@ int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u6= 4 xcr) (!(xcr0 & XFEATURE_MASK_BNDCSR))) return 1; =20 + /* MPX and APX conflict in the non-compacted XSAVE format */ + if (xcr0 & XFEATURE_MASK_BNDREGS && xcr0 & XFEATURE_MASK_APX) + return 1; + if (xcr0 & XFEATURE_MASK_AVX512) { if (!(xcr0 & XFEATURE_MASK_YMM)) return 1; --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 59F9A47DFBD; Mon, 20 Jul 2026 17:46:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569613; cv=none; b=O7SKhzyBJxqVlCiGx2TpsPfzYkI6fbOTG8/nDUT0Svshj+14MKHzdlV8ceSF1P89R92EBvUPKH7p66DpzTbK2JSFb7phFJV+UDt/az1ov+wG6baaNFCTdtNfSomVUTVy5a2uvlTGN0UBd28vQIue4akUzNEMcGn5QXtTE0hig3I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569613; c=relaxed/simple; bh=dWEdx2vtF+kR8c3/Y7QXeQKcBYYo4wB2YJK9sr/AYLs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VuoTkxxiFcDtF5PaN5MA+y/CBgWSI9oKSYXequ8Cl/+luyU11Ikn98rMat022arvMdDPi8Tn7pzifVlzeIPdLA3zuojOAO6gzHjBakIiJygofTn3aZaafFTXNm8JscVrTCjWQrUQKtPjZUBQ5aS4lYyxjCDDZYcSQjtyfoUixMw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=RVJgOPHf; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="RVJgOPHf" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569605; x=1816105605; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=dWEdx2vtF+kR8c3/Y7QXeQKcBYYo4wB2YJK9sr/AYLs=; b=RVJgOPHfoGjQwF5CT8zOvLkDjbjgSKMTUIn1ZHF7DR8BdustucjiDuc4 liTFFQzap5g43pZiuATliV2IdMXBCwCCo1d5It4iEtVGRgPps16kT+eX1 Snjt71H17axJxP+nv0FJ4ZWfCx9kyCwdkw+Cw9bNJbh/aLzIlRvk1IVIC 02idxI1Faec+XmRBXBMSoEB929/yN9qmj7dLmV8CUi9+uAEBH0fqKK6l0 hxp3s3x9Xk+74Dv9dEMw14Ff35y2ro1NEimbrQoJFzejLbodn7IGsBkZn oiBMNzOnB+aGK/S9DYTdmwgZVDQ8/T2XQ2Kkkz/8YY7B/qhcSunRdOPcv w==; X-CSE-ConnectionGUID: +9O7mBf4TCCD1DWSimtXoQ== X-CSE-MsgGUID: 3TQakZBHRMiFeShzLvWp6Q== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691705" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691705" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:46:11 -0700 X-CSE-ConnectionGUID: Cavo8xnxTAaJ+xjply297A== X-CSE-MsgGUID: nBNctmIjQbywpxgjJRvHRg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575393" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:46:11 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com Subject: [PATCH v5 16/20] KVM: x86: Add APX in supported XCR0 Date: Mon, 20 Jul 2026 17:19:45 +0000 Message-ID: <20260720171949.498680-17-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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" Set kvm_caps.supported_xcr0[APX] when the host has enabled the APX state along with CONFIG_KVM_APX=3Dy. Signed-off-by: Chang S. Bae --- V4 -> V5: Separate out from userspace exposure (Sean) --- arch/x86/kvm/x86.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 266d7a02855b..48f8a2d69987 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -7082,6 +7082,8 @@ int kvm_x86_vendor_init(struct kvm_x86_init_ops *ops) if (boot_cpu_has(X86_FEATURE_XSAVE)) { kvm_host.xcr0 =3D xgetbv(XCR_XFEATURE_ENABLED_MASK); kvm_caps.supported_xcr0 =3D kvm_host.xcr0 & KVM_SUPPORTED_XCR0; + if (IS_ENABLED(CONFIG_KVM_APX)) + kvm_caps.supported_xcr0 |=3D kvm_host.xcr0 & XFEATURE_MASK_APX; } =20 if (boot_cpu_has(X86_FEATURE_XSAVES)) { --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 46CFF47DF93; Mon, 20 Jul 2026 17:46:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569612; cv=none; b=Ok5Xw751ij+G0W1iGdvGKfvYfdmY9fU7s18tBkxaUGrb05CHzNn6L5gQNQTAulGS29afWU8Td+fDhHvtNjbuTnzB2RKNbtk+EYKl/HwDkKT7ruWH2f4Y+fhlTxM8lTaGsAHUIzs6zH45cZRAxMxU3bJX5R7Pr0IEuETIoQvbRZw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569612; c=relaxed/simple; bh=IhZeM7zxjWaSgsnlxClxC83wEUNt59WiQ2MHUpItWFc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=U3y2QOulw+YXQJR7JiJOOjpL3oGSR/+4i01m/XQSc7dM+8jI/x2rC6BS3v2C/BsqchXeDoUOWIEF2PygEW0aWGQBw3nf1yeHmjDy+rbwJc8XAN1NFX0NtU6pRw23HEjfJzR0Q+Fc+Phi9q0qvyVbTQf+1cJsTtuAczIDnRhcsSo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=UuFIubv3; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="UuFIubv3" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569605; x=1816105605; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=IhZeM7zxjWaSgsnlxClxC83wEUNt59WiQ2MHUpItWFc=; b=UuFIubv3LE3XRap7+olFIEOGoW2h01smLzHJ/B9NjijdfnfiYP8AI9ju Wq52QRM+WAY9mTjZCXQ8tepBc4VVUf1/asUdbBu1RucuGycAV4T0lVHYm pqILuGQ+yX83vUS5iGlRXebXc1U4OYYwl5zv927klG/fFE0hdVpEKekMQ nfQidQ8eq8wR2kUEmau/Sb4JZwg4FWxMO/uucL+C3nMp7VQZOrN7iaHMF ZbNVJniZtGL6RxdXB5pyBEssshV8WZH6HHTlKPGtDBg5eyR3Zj54PCLjg hHJIxxzYn+WzrnEgHSIWDuC+BRMXOe5mOQcpp31HyNNMuRO50kl4XJx/o A==; X-CSE-ConnectionGUID: z6aZTtPMRrW0Cu92UqflPA== X-CSE-MsgGUID: a0JO+rsNT5+dSlpbmis9VQ== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691710" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691710" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:46:12 -0700 X-CSE-ConnectionGUID: /cH0cVd7QUOHk5mYhG2HhA== X-CSE-MsgGUID: aVfnZWW5TMOJZHqvXtnwFg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575396" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:46:12 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com, Peter Fang Subject: [PATCH v5 17/20] KVM: x86: Expose APX foundation feature to userspace Date: Mon, 20 Jul 2026 17:19:46 +0000 Message-ID: <20260720171949.498680-18-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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" Expose the APX feature to userspace component. Update the maximum supported CPUID leaf to 0x29 to include the APX leaf. On SVM, do not advertise APX, as EGPR support is not yet implemented. No APX sub-features are enumerated yet. Those will be exposed in a separate patch. Originally-by: Peter Fang Signed-off-by: Chang S. Bae --- arch/x86/kvm/cpuid.c | 10 +++++++++- arch/x86/kvm/svm/svm.c | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 1fc7a0f9a13a..db95f6b578d0 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -1062,8 +1062,12 @@ void kvm_initialize_cpu_caps(void) F(AVX_VNNI_INT16), F(PREFETCHITI), F(AVX10), + SCATTERED_F(APX), ); =20 + if (!IS_ENABLED(CONFIG_KVM_APX)) + kvm_cpu_cap_clear(X86_FEATURE_APX); + kvm_cpu_cap_init(CPUID_7_2_EDX, F(INTEL_PSFD), F(IPRED_CTRL), @@ -1442,7 +1446,7 @@ static inline int __do_cpuid_func(struct kvm_cpuid_ar= ray *array, u32 function) switch (function) { case 0: /* Limited to the highest leaf implemented in KVM. */ - entry->eax =3D min(entry->eax, 0x24U); + entry->eax =3D min(entry->eax, 0x29U); break; case 1: cpuid_entry_override(entry, CPUID_1_EDX); @@ -1713,6 +1717,10 @@ static inline int __do_cpuid_func(struct kvm_cpuid_a= rray *array, u32 function) } break; } + /* APX sub-features */ + case 0x29: + entry->eax =3D entry->ebx =3D entry->ecx =3D entry->edx =3D 0; + break; case KVM_CPUID_SIGNATURE: { const u32 *sigptr =3D (const u32 *)KVM_SIGNATURE; entry->eax =3D KVM_CPUID_FEATURES; diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index eb1b2ba1261d..573411777662 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -5593,6 +5593,7 @@ static __init void svm_set_cpu_caps(void) */ kvm_cpu_cap_clear(X86_FEATURE_BUS_LOCK_DETECT); kvm_cpu_cap_clear(X86_FEATURE_MSR_IMM); + kvm_cpu_cap_clear(X86_FEATURE_APX); =20 kvm_setup_xss_caps(); kvm_finalize_cpu_caps(); --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 9DA8044D01F; Mon, 20 Jul 2026 17:46:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569608; cv=none; b=X/ZXNB34zmJGLGps4CU8eOoNeMdQCNsaJ1RXY6Y3yuG9H1ov+0D1CaRaE4tuGDrQGGFM7sY0vusNWyhyprQ4kwG3Eyksvt7rFxAj3fGRJB5BU9+JzrRC/IhIC3a6Bl9TujkhR5FJ8/D9Pnxms2vqQjh2AeXcqOtYWNSUqYmsxHA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569608; c=relaxed/simple; bh=bqZmDjqMzToiwaBoty66E+PLAi3LUEdaxonitqJz6L0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BDARohwyF2JWY+1H5oUD8ZtwSTh8+cdP0GzMaXuDBcInZlhGkmoeG15UpNpRum+eJ71zodCJguuW8SqfgESey9RWOuYZqca9SvOKEcWZGTOEAwUx0w9tL1EqWLxwNLsgpnBjUj2GLSrskEude3lWAp6kx1NpSI1TUClIm4coCFk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=T8uhSxve; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="T8uhSxve" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569606; x=1816105606; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=bqZmDjqMzToiwaBoty66E+PLAi3LUEdaxonitqJz6L0=; b=T8uhSxveX1nUugxj8HdcoVCBxgVoL6l8nwTmFaQLgr5VcPSDifRYPA8g z7g5+ZjQBwi8pbxBC5fNhitYz4oxOkYKANlCil9yrTf7M66La1x+cCUAQ bKDX4gqtp0QAIKqp6LiBD0YVZF9J+yD7NXYD4qV/xy+G1p+Aj5Uu8fwDa QrPcb++7q4a6JFKly+6B45tz4UlcT4QYswJbzehfu6+sl0HHoP770mQB0 Yt4yCwJkXA0wQp82f2Of7GBlcUaUGCQNB1KuaK+Oe0WUPn0Dha3AaAUKk M2OBCKnRnzmuh0uJmr5SbXFBrpZ8LleIu3/W+qMlpw5trvDdQXEIIEyJ4 w==; X-CSE-ConnectionGUID: TMNxXey0RGa+lz1hlhEtzg== X-CSE-MsgGUID: UJZ29HHmRImCqzKcU4qFdw== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691716" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691716" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:46:13 -0700 X-CSE-ConnectionGUID: SNT/Mzj7QVKL0sGwAdLiSg== X-CSE-MsgGUID: qktTMKeHTNembi/YB89CKQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575399" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:46:12 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com Subject: [PATCH v5 18/20] KVM: x86: Expose APX sub-features to userspace Date: Mon, 20 Jul 2026 17:19:47 +0000 Message-ID: <20260720171949.498680-19-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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 CPUID leaf 0x29 sub-leaf 0 to expose these APX sub-features, if the APX foundation is available: * New Conditional Instructions (NCI) * New Data Destination (NDD) * Flags Suppression (NF) Signed-off-by: Chang S. Bae --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/cpuid.c | 7 ++++++- arch/x86/kvm/reverse_cpuid.h | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index 48547842d9fa..7df964f32ba0 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -868,6 +868,7 @@ enum kvm_only_cpuid_leafs { CPUID_7_1_ECX, CPUID_1E_1_EAX, CPUID_24_1_ECX, + CPUID_29_0_EBX, NR_KVM_CPU_CAPS, =20 NKVMCAPINTS =3D NR_KVM_CPU_CAPS - NCAPINTS, diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index db95f6b578d0..0339700e885d 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -1112,6 +1112,10 @@ void kvm_initialize_cpu_caps(void) F(AVX10_VNNI_INT), ); =20 + kvm_cpu_cap_init(CPUID_29_0_EBX, + F(APX_NCI_NDD_NF), + ); + kvm_cpu_cap_init(CPUID_8000_0001_ECX, F(LAHF_LM), F(CMP_LEGACY), @@ -1719,7 +1723,8 @@ static inline int __do_cpuid_func(struct kvm_cpuid_ar= ray *array, u32 function) } /* APX sub-features */ case 0x29: - entry->eax =3D entry->ebx =3D entry->ecx =3D entry->edx =3D 0; + if (!kvm_cpu_cap_has(X86_FEATURE_APX)) + entry->eax =3D entry->ebx =3D entry->ecx =3D entry->edx =3D 0; break; case KVM_CPUID_SIGNATURE: { const u32 *sigptr =3D (const u32 *)KVM_SIGNATURE; diff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h index de90697c4e5a..cff071ccf926 100644 --- a/arch/x86/kvm/reverse_cpuid.h +++ b/arch/x86/kvm/reverse_cpuid.h @@ -67,6 +67,9 @@ /* Intel-defined sub-features, CPUID level 0x00000024:1 (ECX) */ #define X86_FEATURE_AVX10_VNNI_INT KVM_X86_FEATURE(CPUID_24_1_ECX, 2) =20 +/* Intel-defined sub-features, CPUID level 0x00000029:0 (EBX) */ +#define X86_FEATURE_APX_NCI_NDD_NF KVM_X86_FEATURE(CPUID_29_0_EBX, 0) + /* CPUID level 0x80000007 (EDX). */ #define KVM_X86_FEATURE_CONSTANT_TSC KVM_X86_FEATURE(CPUID_8000_0007_EDX, = 8) =20 @@ -110,6 +113,7 @@ static const struct cpuid_reg reverse_cpuid[] =3D { [CPUID_7_1_ECX] =3D { 7, 1, CPUID_ECX}, [CPUID_1E_1_EAX] =3D { 0x1e, 1, CPUID_EAX}, [CPUID_24_1_ECX] =3D { 0x24, 1, CPUID_ECX}, + [CPUID_29_0_EBX] =3D { 0x29, 0, CPUID_EBX}, }; =20 /* --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 8CC714499B8; Mon, 20 Jul 2026 17:46:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569621; cv=none; b=dzBPDO9HU6tV4agLMI0zFKSMcZyWTfPScEFkaSHcewf2WTaiBUVDI9Ry/7IEbpV1Lbh7tqSMjIRmHCBwrVZkpr6BwnV0DPBDcJVAz6eW/lFI5N8/6U8r2PdRaz8tvT9CUlsv28zht5fxIN37pwghuVPTBmM3fmAXzyr5V3dRqj8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569621; c=relaxed/simple; bh=MBpESReHfnPAxHPFbT1e55nwk9KD92PIzLuNlBSxn3k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=G0zCDAL1JBkZdlKxvmN/kXC/Y78mZIXgXOkkSsCjrP00MoXLJe9CKcITqcMii+N4qJArnftdCAgVs4cOGQCr2fNhcV5aRUTkUrgQffr4XfuCD4tAdDFC1pHrPrBa8WIkn/B9GMQLAELrSYck0guN5rCD0C1GMCqtbycdBwwPxqU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=jZnFZlpz; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="jZnFZlpz" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569611; x=1816105611; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=MBpESReHfnPAxHPFbT1e55nwk9KD92PIzLuNlBSxn3k=; b=jZnFZlpzmD4gSlTpwPvxXNOrFIp3tm0JAt3mVD78Buj9F0SjEGxqqYl6 YiKuWbrWGCudYwzwGTxvBsty2BxQ2LfRh0BNzXnZr1v9s7vdhWBw/MXyl oGAMN1lJU1FU/tTJvtIJGSCuZCveIPx6DA6ZVbMR1uysNtyNtctH1HEj3 rJ4le6EggM5Gbtnh0GldZ/cEuyvJMktsT8i32rhNWa+OnJZ701J/t/oKg vCdSExaDnv3LQks59U6aw2gscgS8ukMQdG5fiRajRQ5sq/2oFXvvYv2xx 7JtcQObdwFFndKHJn/JNenJnQ0lgRSSFsC2duvozRhWJwgAYcdRgCf3TW w==; X-CSE-ConnectionGUID: CLVEx/qyT1uPTiNJqDD2Dw== X-CSE-MsgGUID: 2i56Way+RcaomYVXpKvTBg== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691720" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691720" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:46:14 -0700 X-CSE-ConnectionGUID: RP29JR3aQ1mSEjbePjC8Pw== X-CSE-MsgGUID: ABTfwLXtSumgxMO2qaa9Ow== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575402" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:46:13 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com Subject: [PATCH v5 19/20] KVM: x86: selftests: Add APX state and ABI test Date: Mon, 20 Jul 2026 17:19:48 +0000 Message-ID: <20260720171949.498680-20-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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" Test APX-specific behavior and ABI interactions as these are unique comparing to other state components: * EGPR state is saved on VM entry assembly (unlike other components). * The saved state is retained even if the guest disables APX. * EGPR state is exposed via the XSAVE ABI while not stored in the kernel XSAVE buffer. Signed-off-by: Chang S. Bae --- V4 -> V5: Use vcpu_xsave2_get() instead of vcpu_xsave_get() (review bot [*]) [*]: locally running Sashiko with gemini-3.1-pro-preview --- tools/testing/selftests/kvm/Makefile.kvm | 1 + .../selftests/kvm/include/x86/processor.h | 120 +++++++++++ tools/testing/selftests/kvm/x86/apx_test.c | 191 ++++++++++++++++++ 3 files changed, 312 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/apx_test.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index 4ace12606e93..373d685caae2 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -162,6 +162,7 @@ TEST_GEN_PROGS_x86 +=3D rseq_test TEST_GEN_PROGS_x86 +=3D steal_time TEST_GEN_PROGS_x86 +=3D system_counter_offset_test TEST_GEN_PROGS_x86 +=3D pre_fault_memory_test +TEST_GEN_PROGS_x86 +=3D x86/apx_test =20 # Compiled outputs used by test targets TEST_GEN_PROGS_EXTENDED_x86 +=3D x86/nx_huge_pages_test diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/te= sting/selftests/kvm/include/x86/processor.h index 7d3a27bc0d84..5f5acc33486a 100644 --- a/tools/testing/selftests/kvm/include/x86/processor.h +++ b/tools/testing/selftests/kvm/include/x86/processor.h @@ -107,6 +107,7 @@ struct xstate { #define XFEATURE_MASK_LBR BIT_ULL(15) #define XFEATURE_MASK_XTILE_CFG BIT_ULL(17) #define XFEATURE_MASK_XTILE_DATA BIT_ULL(18) +#define XFEATURE_MASK_APX BIT_ULL(19) =20 #define XFEATURE_MASK_AVX512 (XFEATURE_MASK_OPMASK | \ XFEATURE_MASK_ZMM_Hi256 | \ @@ -194,6 +195,7 @@ struct kvm_x86_cpu_feature { #define X86_FEATURE_SPEC_CTRL KVM_X86_CPU_FEATURE(0x7, 0, EDX, 26) #define X86_FEATURE_ARCH_CAPABILITIES KVM_X86_CPU_FEATURE(0x7, 0, EDX, 29) #define X86_FEATURE_PKS KVM_X86_CPU_FEATURE(0x7, 0, ECX, 31) +#define X86_FEATURE_APX KVM_X86_CPU_FEATURE(0x7, 1, EDX, 21) #define X86_FEATURE_XTILECFG KVM_X86_CPU_FEATURE(0xD, 0, EAX, 17) #define X86_FEATURE_XTILEDATA KVM_X86_CPU_FEATURE(0xD, 0, EAX, 18) #define X86_FEATURE_XSAVES KVM_X86_CPU_FEATURE(0xD, 1, EAX, 3) @@ -877,6 +879,124 @@ static inline void write_sse_reg(int reg, const sse12= 8_t *data) } } =20 +static inline unsigned long read_egpr(int reg) +{ + unsigned long data =3D 0; + + /* mov %r16..%r31, %rax */ + switch (reg) { + case 16: + asm(".byte 0xd5, 0x48, 0x89, 0xc0" : "=3Da"(data)); + break; + case 17: + asm(".byte 0xd5, 0x48, 0x89, 0xc8" : "=3Da"(data)); + break; + case 18: + asm(".byte 0xd5, 0x48, 0x89, 0xd0" : "=3Da"(data)); + break; + case 19: + asm(".byte 0xd5, 0x48, 0x89, 0xd8" : "=3Da"(data)); + break; + case 20: + asm(".byte 0xd5, 0x48, 0x89, 0xe0" : "=3Da"(data)); + break; + case 21: + asm(".byte 0xd5, 0x48, 0x89, 0xe8" : "=3Da"(data)); + break; + case 22: + asm(".byte 0xd5, 0x48, 0x89, 0xf0" : "=3Da"(data)); + break; + case 23: + asm(".byte 0xd5, 0x48, 0x89, 0xf8" : "=3Da"(data)); + break; + case 24: + asm(".byte 0xd5, 0x4c, 0x89, 0xc0" : "=3Da"(data)); + break; + case 25: + asm(".byte 0xd5, 0x4c, 0x89, 0xc8" : "=3Da"(data)); + break; + case 26: + asm(".byte 0xd5, 0x4c, 0x89, 0xd0" : "=3Da"(data)); + break; + case 27: + asm(".byte 0xd5, 0x4c, 0x89, 0xd8" : "=3Da"(data)); + break; + case 28: + asm(".byte 0xd5, 0x4c, 0x89, 0xe0" : "=3Da"(data)); + break; + case 29: + asm(".byte 0xd5, 0x4c, 0x89, 0xe8" : "=3Da"(data)); + break; + case 30: + asm(".byte 0xd5, 0x4c, 0x89, 0xf0" : "=3Da"(data)); + break; + case 31: + asm(".byte 0xd5, 0x4c, 0x89, 0xf8" : "=3Da"(data)); + break; + default: + BUG(); + } + + return data; +} + +static inline void write_egpr(int reg, unsigned long data) +{ + /* mov %%rax, %r16...%r31*/ + switch (reg) { + case 16: + asm(".byte 0xd5, 0x18, 0x89, 0xc0" : : "a"(data)); + break; + case 17: + asm(".byte 0xd5, 0x18, 0x89, 0xc1" : : "a"(data)); + break; + case 18: + asm(".byte 0xd5, 0x18, 0x89, 0xc2" : : "a"(data)); + break; + case 19: + asm(".byte 0xd5, 0x18, 0x89, 0xc3" : : "a"(data)); + break; + case 20: + asm(".byte 0xd5, 0x18, 0x89, 0xc4" : : "a"(data)); + break; + case 21: + asm(".byte 0xd5, 0x18, 0x89, 0xc5" : : "a"(data)); + break; + case 22: + asm(".byte 0xd5, 0x18, 0x89, 0xc6" : : "a"(data)); + break; + case 23: + asm(".byte 0xd5, 0x18, 0x89, 0xc7" : : "a"(data)); + break; + case 24: + asm(".byte 0xd5, 0x19, 0x89, 0xc0" : : "a"(data)); + break; + case 25: + asm(".byte 0xd5, 0x19, 0x89, 0xc1" : : "a"(data)); + break; + case 26: + asm(".byte 0xd5, 0x19, 0x89, 0xc2" : : "a"(data)); + break; + case 27: + asm(".byte 0xd5, 0x19, 0x89, 0xc3" : : "a"(data)); + break; + case 28: + asm(".byte 0xd5, 0x19, 0x89, 0xc4" : : "a"(data)); + break; + case 29: + asm(".byte 0xd5, 0x19, 0x89, 0xc5" : : "a"(data)); + break; + case 30: + asm(".byte 0xd5, 0x19, 0x89, 0xc6" : : "a"(data)); + break; + case 31: + asm(".byte 0xd5, 0x19, 0x89, 0xc7" : : "a"(data)); + break; + default: + BUG(); + } +} + static inline void cpu_relax(void) { asm volatile("rep; nop" ::: "memory"); diff --git a/tools/testing/selftests/kvm/x86/apx_test.c b/tools/testing/sel= ftests/kvm/x86/apx_test.c new file mode 100644 index 000000000000..4825003d0616 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/apx_test.c @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "processor.h" + +enum stages { + GUEST_UPDATE, + USERSPACE_UPDATE, + GUEST_APXOFF, +}; + +enum egpr_ops { + EGPRS_WRITE, + EGPRS_CHECK, +}; + +#define for_each_egpr(reg) for (reg =3D 16; reg <=3D 31; reg++) + +/* + * Deterministic per-stage test values for EGPRs so that guest and + * userspace can validate state transitions. + */ +static inline unsigned long egpr_data(enum stages stage, int reg) +{ + switch (stage) { + case GUEST_UPDATE: + return 0xabcd + reg; + case USERSPACE_UPDATE: + return 0xbcde + reg; + case GUEST_APXOFF: + return 0xcdef + reg; + default: + return 0; + } +} + +/* + * Read/write or validate EGPR values either directly via registers + * (guest context) or via a provided buffer (userspace XSAVE). + */ +static bool handle_egprs(enum egpr_ops ops, unsigned long *egprs, enum sta= ges stage) +{ + unsigned long data; + int reg; + + for_each_egpr(reg) { + data =3D egpr_data(stage, reg); + + if (ops =3D=3D EGPRS_WRITE) { + if (egprs) + egprs[reg - 16] =3D data; + else + write_egpr(reg, data); + continue; + } + + if (ops !=3D EGPRS_CHECK) + return false; + + if (egprs) { + if (egprs[reg - 16] !=3D data) + return false; + continue; + } + + if (read_egpr(reg) !=3D data) + return false; + } + + return true; +} + +static void write_egprs(enum stages stage) +{ + handle_egprs(EGPRS_WRITE, NULL, stage); +} + +static bool validate_egprs(enum stages stage) +{ + return handle_egprs(EGPRS_CHECK, NULL, stage); +} + +static void test_guest_update(void) +{ + write_egprs(GUEST_UPDATE); + GUEST_SYNC(GUEST_UPDATE); + GUEST_ASSERT(validate_egprs(GUEST_UPDATE)); +} + +static void test_userspace_update(void) +{ + /* Userspace updates EGPR state via the KVM XSAVE ABI */ + GUEST_SYNC(USERSPACE_UPDATE); + GUEST_ASSERT(validate_egprs(USERSPACE_UPDATE)); +} + +static void test_guest_apxoff(void) +{ + write_egprs(GUEST_APXOFF); + /* Disable APX to verify state is preserved */ + GUEST_ASSERT(!xsetbv_safe(0, this_cpu_supported_xcr0() & ~XFEATURE_MASK_A= PX)); + GUEST_SYNC(GUEST_APXOFF); + GUEST_ASSERT(!xsetbv_safe(0, this_cpu_supported_xcr0())); + GUEST_ASSERT(validate_egprs(GUEST_APXOFF)); +} + +static void guest_code(void) +{ + set_cr4(get_cr4() | X86_CR4_OSXSAVE); + GUEST_ASSERT(!xsetbv_safe(0, this_cpu_supported_xcr0())); + + test_guest_update(); + test_userspace_update(); + test_guest_apxoff(); + + GUEST_DONE(); +} + +#define X86_PROPERTY_XSTATE_APX_OFFSET KVM_X86_CPU_PROPERTY(0xd, 19, EBX, = 0, 31) +#define XSAVE_HDR_OFFSET 512 + +static inline unsigned long *xsave_egprs(void *xsave) +{ + return xsave + kvm_cpu_property(X86_PROPERTY_XSTATE_APX_OFFSET); +} + +static inline void xstatebv_set(void *xsave, uint64_t mask) +{ + *(uint64_t *)(xsave + XSAVE_HDR_OFFSET) |=3D mask; +} + +static void write_xsave_egprs(void *xsave, enum stages stage) +{ + handle_egprs(EGPRS_WRITE, xsave_egprs(xsave), stage); + xstatebv_set(xsave, XFEATURE_MASK_APX); +} + +static bool validate_xsave_egprs(void *xsave, enum stages stage) +{ + return handle_egprs(EGPRS_CHECK, xsave_egprs(xsave), stage); +} + +int main(int argc, char *argv[]) +{ + struct kvm_xsave *xsave; + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + enum stages stage; + struct ucall uc; + int xsave_size; + + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_XSAVE)); + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_APX)); + + vm =3D vm_create_with_one_vcpu(&vcpu, guest_code); + xsave_size =3D vm_check_cap(vcpu->vm, KVM_CAP_XSAVE2); + TEST_ASSERT(xsave_size, "KVM_CAP_XSAVE2 not supported"); + xsave =3D malloc(xsave_size); + TEST_ASSERT(xsave, "Failed to allocate XSAVE buffer"); + + while (1) { + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + + switch (get_ucall(vcpu, &uc)) { + case UCALL_ABORT: + REPORT_GUEST_ASSERT(uc); + break; + case UCALL_SYNC: { + stage =3D uc.args[1]; + vcpu_xsave2_get(vcpu, xsave); + if (stage =3D=3D USERSPACE_UPDATE) { + write_xsave_egprs(xsave, stage); + } else { + TEST_ASSERT(validate_xsave_egprs(xsave, stage), + "EGPR state mismatch in userspace XSAVE buffer"); + } + vcpu_xsave_set(vcpu, xsave); + break; + } + case UCALL_DONE: + goto done; + default: + TEST_FAIL("Unknown ucall %lu", uc.cmd); + } + } + +done: + free(xsave); + kvm_vm_free(vm); + return 0; +} --=20 2.53.0 From nobody Sat Jul 25 02:11:03 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (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 718DF47DD76; Mon, 20 Jul 2026 17:46:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569623; cv=none; b=jw/PDHIuSbcJkpIOTJqYXEPb1Az9wGIfbyNhHU3JG2TV8Ppl4BCBUKXN1wtMPpHlWaY1HdxTQZDuhXeDGPtcEtOxxylxTmw0XtTEGw1EJF4HxQ24s8FYNyUl4byJfBW3ZB4IOgT9jghjYVlJapIcSVMWXjTbcs7uu8fVaK7sRBM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784569623; c=relaxed/simple; bh=anr9jp6F95ZMl5OuNXc1gxmHfRhIi2vcRZyTglo+qmk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pBGIx130ygp+oRHScEOy9gHfD1O6XqXYLhENt1dSQQKjK63PbAIrbWDyQjoaP23IUdmdEGaULKu8fd3dybrqCshWp429fnsQRH2/MNsdn4DNjNKnr5lNsi2aw7DBGdVoQhNlSsFk9iKvppoC29/o1bZQFS3RrCJC1bhkadSmBCY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=BrC49w6o; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="BrC49w6o" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784569616; x=1816105616; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=anr9jp6F95ZMl5OuNXc1gxmHfRhIi2vcRZyTglo+qmk=; b=BrC49w6oK4QA4AubRl0y+VDb7R4Z1SxZTEdFCwASdpBCs8R1KDH00nAv SzZrGZgvkfKrRsch7FqlbXSec88S+wpWN29CYwT6Ko5w0hm5ZcfCh37ED +rV3KeuIfc40PIzeMBdlRn2YzBiDxcfh//RcNemAlqHj5z9enQ1OML+ii 7xvv21CsKHdCLEx7Ke94aWY7jQSlR06YrozT73h9SAF/Ohdnyvq34LwbZ ieK1w+FhCxov0a5okx+JcreC672DuEpofP/w5ow95BymSQB3OQCoWzNe5 lrhafkmxyxx6Q8gzQcz0+rRDo2NSKNARZ+G8qKN8CuBhgVTJDXfZwtAft A==; X-CSE-ConnectionGUID: 2LBe41T3Q/mwCO5c2vcv4Q== X-CSE-MsgGUID: hbS6JkvHSRmp1DPOjVZqRg== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72691724" X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="72691724" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 10:46:15 -0700 X-CSE-ConnectionGUID: 5FzX9gdrQT6oA5eJ6aFeZQ== X-CSE-MsgGUID: 22/wnI0iQyWo0bB70nGtKQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,175,1779174000"; d="scan'208";a="257575407" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa007.jf.intel.com with ESMTP; 20 Jul 2026 10:46:14 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com Subject: [PATCH v5 20/20] KVM: x86: selftests: Add APX state handling and XCR0 sanity checks Date: Mon, 20 Jul 2026 17:19:49 +0000 Message-ID: <20260720171949.498680-21-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260720171949.498680-1-chang.seok.bae@intel.com> References: <20260720171949.498680-1-chang.seok.bae@intel.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" Now that KVM exposes the APX feature to guests, extend some existing selftests to validate XCR0 configuration and state management. Since APX repurposes the XSAVE area previously used by MPX in the non-compacted format, add a check to ensure that MPX state is not set when APX is enabled. Also, load non-init APX state data in the guest so that XSTATE_BV[APX] is set, allowing validation of APX state testing. Signed-off-by: Chang S. Bae --- tools/testing/selftests/kvm/x86/state_test.c | 3 +++ .../selftests/kvm/x86/xcr0_cpuid_test.c | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/tools/testing/selftests/kvm/x86/state_test.c b/tools/testing/s= elftests/kvm/x86/state_test.c index 4a1056a6cb8d..9727dbb2b981 100644 --- a/tools/testing/selftests/kvm/x86/state_test.c +++ b/tools/testing/selftests/kvm/x86/state_test.c @@ -164,6 +164,9 @@ static void __attribute__((__flatten__)) guest_code(voi= d *arg) asm volatile ("vmovupd %0, %%zmm16" :: "m" (buffer)); } =20 + if (supported_xcr0 & XFEATURE_MASK_APX) + write_egpr(16, 0xcccccccc); + if (this_cpu_has(X86_FEATURE_MPX)) { u64 bounds[2] =3D { 10, 0xffffffffull }; u64 output[2] =3D { }; diff --git a/tools/testing/selftests/kvm/x86/xcr0_cpuid_test.c b/tools/test= ing/selftests/kvm/x86/xcr0_cpuid_test.c index 40dc9e6b3fad..f74978ef5951 100644 --- a/tools/testing/selftests/kvm/x86/xcr0_cpuid_test.c +++ b/tools/testing/selftests/kvm/x86/xcr0_cpuid_test.c @@ -46,6 +46,20 @@ do { \ __supported, (xfeatures)); \ } while (0) =20 +/* + * Verify that mutually exclusive architectural features do not overlap. + * For example, APX and MPX must never be reported as supported together. + */ +#define ASSERT_XFEATURE_CONFLICT(supported_xcr0, xfeatures, conflicts) \ +do { \ + uint64_t __supported =3D (supported_xcr0) & ((xfeatures) | (conflicts)); = \ + \ + __GUEST_ASSERT((__supported & (xfeatures)) !=3D (xfeatures) || \ + !(__supported & (conflicts)), \ + "supported =3D 0x%lx, xfeatures =3D 0x%llx, conflicts =3D 0x%llx"= , \ + __supported, (xfeatures), (conflicts)); \ +} while (0) + static void guest_code(void) { u64 initial_xcr0; @@ -79,6 +93,11 @@ static void guest_code(void) ASSERT_ALL_OR_NONE_XFEATURE(supported_xcr0, XFEATURE_MASK_XTILE); =20 + /* Check APX by ensuring MPX is not exposed concurrently */ + ASSERT_XFEATURE_CONFLICT(supported_xcr0, + XFEATURE_MASK_APX, + XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR); + vector =3D xsetbv_safe(0, XFEATURE_MASK_FP); __GUEST_ASSERT(!vector, "Expected success on XSETBV(FP), got %s", --=20 2.53.0