From nobody Sun Feb 8 09:13:05 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (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 E31F521D3F2; Sun, 21 Dec 2025 04:31:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291481; cv=none; b=P8WEvD2mLrvD4uv5EY+c3Tq//aEDhLc/4orsbhsjH4yYO311taVQqLDejveALO9czHoImj2JnOc3l2HFZThQmPXY1+0HLumCDSZ7dLslXpSQFBUuAU3Lh3ppB+pqo8AqoBZGT/Pn0YEDAks31mkiimPcKdJw+yjdrY3vefZuuEE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291481; c=relaxed/simple; bh=qI1pjgInsVR2QMifm/sOkZ+ghcZwWYvzVBIQL/G0WwM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MjLImeZ9pXNDW9zBgPGegy0w6KSlPqxN55k4lZaNquGC0R9ghM4z9TozXriJ2VxxtI9Dim2YujyBwp0y5m0Xqvw+ogGKDa1rdCVOII+M72O13UuoNhDgIkLdo60EVM0wUcD9HAg3cgnzphzrs1yBtDuXPbfFgtGhUEWO1hxrWto= 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=QkrlAa8R; arc=none smtp.client-ip=198.175.65.21 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="QkrlAa8R" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1766291480; x=1797827480; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=qI1pjgInsVR2QMifm/sOkZ+ghcZwWYvzVBIQL/G0WwM=; b=QkrlAa8RBCcKqIjaDNn6ZZ/KjP20aFRH/7gsFMOS8T8dhRDsTs3quijX Vt+qrUD12ftXrxGXOtl3XjaycKC2eqK3/wRB2Rdyxlg0/09bfUjtPz0n+ BmWOQLx0iNAgdoyaDusjBrOif6IwJOPeMQBhzwyKH+pBlPizi5+QV0IfH Dm6jNRfX7lWblI7sGTLv7zv8h7wFVl/sW15WvCIgrno0DqUkxa4Srlzlx VKRIo7MWGRTDlcb+nawMQcTdlf3Xmp/N10jfeWVrQtT1hIdhtfnOUccdR QkG4U/4JP+DJvNBepGXuKljreES871jjTGuVSoO5cshIM3m1sKZLht0Sh A==; X-CSE-ConnectionGUID: s+tp2myiSPKo6FSN6Vvn7Q== X-CSE-MsgGUID: 6+OxzqM+RpSm0UEBDH/CWQ== X-IronPort-AV: E=McAfee;i="6800,10657,11635"; a="68132373" X-IronPort-AV: E=Sophos;i="6.20,256,1758610800"; d="scan'208";a="68132373" Received: from orviesa002.jf.intel.com ([10.64.159.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Dec 2025 20:31:19 -0800 X-CSE-ConnectionGUID: di/OlJ57RgCoIrurN+1JUA== X-CSE-MsgGUID: nC9L4JxCSYqvaZhrSZK77A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,164,1763452800"; d="scan'208";a="229884919" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.172]) by orviesa002.jf.intel.com with ESMTP; 20 Dec 2025 20:31:19 -0800 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH 01/16] KVM: x86: Rename register accessors to be GPR-specific Date: Sun, 21 Dec 2025 04:07:27 +0000 Message-ID: <20251221040742.29749-2-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251221040742.29749-1-chang.seok.bae@intel.com> References: <20251221040742.29749-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" Refactor the VCPU register state accessors to make them explicitly GPR-only. The existing register accessors operate on the cached VCPU register state. That cache holds GPRs and RIP. RIP has its own interface already. This renaming clarifies GPR access only. No functional changes intended. Signed-off-by: Chang S. Bae --- No change since last version --- arch/x86/kvm/svm/svm.c | 8 ++++---- arch/x86/kvm/vmx/nested.c | 20 ++++++++++---------- arch/x86/kvm/vmx/vmx.c | 12 ++++++------ arch/x86/kvm/x86.c | 10 +++++----- arch/x86/kvm/x86.h | 5 ++--- arch/x86/kvm/xen.c | 2 +- 6 files changed, 28 insertions(+), 29 deletions(-) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index f56c2d895011..ca1dc2342134 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -2473,7 +2473,7 @@ static int cr_interception(struct kvm_vcpu *vcpu) err =3D 0; if (cr >=3D 16) { /* mov to cr */ cr -=3D 16; - val =3D kvm_register_read(vcpu, reg); + val =3D kvm_gpr_read(vcpu, reg); trace_kvm_cr_write(cr, val); switch (cr) { case 0: @@ -2519,7 +2519,7 @@ static int cr_interception(struct kvm_vcpu *vcpu) kvm_queue_exception(vcpu, UD_VECTOR); return 1; } - kvm_register_write(vcpu, reg, val); + kvm_gpr_write(vcpu, reg, val); trace_kvm_cr_read(cr, val); } return kvm_complete_insn_gp(vcpu, err); @@ -2591,9 +2591,9 @@ static int dr_interception(struct kvm_vcpu *vcpu) dr =3D svm->vmcb->control.exit_code - SVM_EXIT_READ_DR0; if (dr >=3D 16) { /* mov to DRn */ dr -=3D 16; - err =3D kvm_set_dr(vcpu, dr, kvm_register_read(vcpu, reg)); + err =3D kvm_set_dr(vcpu, dr, kvm_gpr_read(vcpu, reg)); } else { - kvm_register_write(vcpu, reg, kvm_get_dr(vcpu, dr)); + kvm_gpr_write(vcpu, reg, kvm_get_dr(vcpu, dr)); } =20 return kvm_complete_insn_gp(vcpu, err); diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 40777278eabb..84e2a4a613b7 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -5274,9 +5274,9 @@ int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsign= ed long exit_qualification, else if (addr_size =3D=3D 0) off =3D (gva_t)sign_extend64(off, 15); if (base_is_valid) - off +=3D kvm_register_read(vcpu, base_reg); + off +=3D kvm_gpr_read(vcpu, base_reg); if (index_is_valid) - off +=3D kvm_register_read(vcpu, index_reg) << scaling; + off +=3D kvm_gpr_read(vcpu, index_reg) << scaling; vmx_get_segment(vcpu, &s, seg_reg); =20 /* @@ -5668,7 +5668,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_gpr_read(vcpu, (((instr_info) >> 28) & 0xf)); =20 if (!nested_vmx_is_evmptr12_valid(vmx)) { /* @@ -5717,7 +5717,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu) * 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); + kvm_gpr_write(vcpu, (((instr_info) >> 3) & 0xf), value); } else { len =3D is_64_bit_mode(vcpu) ? 8 : 4; if (get_vmx_mem_address(vcpu, exit_qualification, @@ -5791,7 +5791,7 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) return nested_vmx_failInvalid(vcpu); =20 if (instr_info & BIT(10)) - value =3D kvm_register_read(vcpu, (((instr_info) >> 3) & 0xf)); + value =3D kvm_gpr_read(vcpu, (((instr_info) >> 3) & 0xf)); else { len =3D is_64_bit_mode(vcpu) ? 8 : 4; if (get_vmx_mem_address(vcpu, exit_qualification, @@ -5802,7 +5802,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_gpr_read(vcpu, (((instr_info) >> 28) & 0xf)); =20 offset =3D get_vmcs12_field_offset(field); if (offset < 0) @@ -6000,7 +6000,7 @@ static int handle_invept(struct kvm_vcpu *vcpu) =20 vmx_instruction_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); gpr_index =3D vmx_get_instr_info_reg2(vmx_instruction_info); - type =3D kvm_register_read(vcpu, gpr_index); + type =3D kvm_gpr_read(vcpu, gpr_index); =20 types =3D (vmx->nested.msrs.ept_caps >> VMX_EPT_EXTENT_SHIFT) & 6; =20 @@ -6081,7 +6081,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) =20 vmx_instruction_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); gpr_index =3D vmx_get_instr_info_reg2(vmx_instruction_info); - type =3D kvm_register_read(vcpu, gpr_index); + type =3D kvm_gpr_read(vcpu, gpr_index); =20 types =3D (vmx->nested.msrs.vpid_caps & VMX_VPID_EXTENT_SUPPORTED_MASK) >> 8; @@ -6355,7 +6355,7 @@ static bool nested_vmx_exit_handled_cr(struct kvm_vcp= u *vcpu, switch ((exit_qualification >> 4) & 3) { case 0: /* mov to cr */ reg =3D (exit_qualification >> 8) & 15; - val =3D kvm_register_read(vcpu, reg); + val =3D kvm_gpr_read(vcpu, reg); switch (cr) { case 0: if (vmcs12->cr0_guest_host_mask & @@ -6441,7 +6441,7 @@ static bool nested_vmx_exit_handled_vmcs_access(struc= t kvm_vcpu *vcpu, =20 /* Decode instruction info and find the field to access */ vmx_instruction_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); - field =3D kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf)); + field =3D kvm_gpr_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf)); =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 4cbe8c84b636..c944b75c10a7 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -5591,7 +5591,7 @@ static int handle_cr(struct kvm_vcpu *vcpu) reg =3D (exit_qualification >> 8) & 15; switch ((exit_qualification >> 4) & 3) { case 0: /* mov to cr */ - val =3D kvm_register_read(vcpu, reg); + val =3D kvm_gpr_read(vcpu, reg); trace_kvm_cr_write(cr, val); switch (cr) { case 0: @@ -5633,12 +5633,12 @@ static int handle_cr(struct kvm_vcpu *vcpu) WARN_ON_ONCE(enable_unrestricted_guest); =20 val =3D kvm_read_cr3(vcpu); - kvm_register_write(vcpu, reg, val); + kvm_gpr_write(vcpu, reg, val); trace_kvm_cr_read(cr, val); return kvm_skip_emulated_instruction(vcpu); case 8: val =3D kvm_get_cr8(vcpu); - kvm_register_write(vcpu, reg, val); + kvm_gpr_write(vcpu, reg, val); trace_kvm_cr_read(cr, val); return kvm_skip_emulated_instruction(vcpu); } @@ -5708,10 +5708,10 @@ static int handle_dr(struct kvm_vcpu *vcpu) =20 reg =3D DEBUG_REG_ACCESS_REG(exit_qualification); if (exit_qualification & TYPE_MOV_FROM_DR) { - kvm_register_write(vcpu, reg, kvm_get_dr(vcpu, dr)); + kvm_gpr_write(vcpu, reg, kvm_get_dr(vcpu, dr)); err =3D 0; } else { - err =3D kvm_set_dr(vcpu, dr, kvm_register_read(vcpu, reg)); + err =3D kvm_set_dr(vcpu, dr, kvm_gpr_read(vcpu, reg)); } =20 out: @@ -6070,7 +6070,7 @@ static int handle_invpcid(struct kvm_vcpu *vcpu) =20 vmx_instruction_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); gpr_index =3D vmx_get_instr_info_reg2(vmx_instruction_info); - type =3D kvm_register_read(vcpu, gpr_index); + type =3D kvm_gpr_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) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 0c6d899d53dd..23e57170898a 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2080,8 +2080,8 @@ static int complete_fast_rdmsr(struct kvm_vcpu *vcpu) static int complete_fast_rdmsr_imm(struct kvm_vcpu *vcpu) { if (!vcpu->run->msr.error) - kvm_register_write(vcpu, vcpu->arch.cui_rdmsr_imm_reg, - vcpu->run->msr.data); + kvm_gpr_write(vcpu, vcpu->arch.cui_rdmsr_imm_reg, + vcpu->run->msr.data); =20 return complete_fast_msr_access(vcpu); } @@ -2135,7 +2135,7 @@ static int __kvm_emulate_rdmsr(struct kvm_vcpu *vcpu,= u32 msr, int reg, kvm_rax_write(vcpu, data & -1u); kvm_rdx_write(vcpu, (data >> 32) & -1u); } else { - kvm_register_write(vcpu, reg, data); + kvm_gpr_write(vcpu, reg, data); } } else { /* MSR read failed? See if we should ask user space */ @@ -2193,7 +2193,7 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_emulate_wrmsr); =20 int kvm_emulate_wrmsr_imm(struct kvm_vcpu *vcpu, u32 msr, int reg) { - return __kvm_emulate_wrmsr(vcpu, msr, kvm_register_read(vcpu, reg)); + return __kvm_emulate_wrmsr(vcpu, msr, kvm_gpr_read(vcpu, reg)); } EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_emulate_wrmsr_imm); =20 @@ -2297,7 +2297,7 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(handle_fastpath_wrmsr); =20 fastpath_t handle_fastpath_wrmsr_imm(struct kvm_vcpu *vcpu, u32 msr, int r= eg) { - return __handle_fastpath_wrmsr(vcpu, msr, kvm_register_read(vcpu, reg)); + return __handle_fastpath_wrmsr(vcpu, msr, kvm_gpr_read(vcpu, reg)); } EXPORT_SYMBOL_FOR_KVM_INTERNAL(handle_fastpath_wrmsr_imm); =20 diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index fdab0ad49098..7d6c1c31539f 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -400,15 +400,14 @@ static inline bool vcpu_match_mmio_gpa(struct kvm_vcp= u *vcpu, gpa_t gpa) return false; } =20 -static inline unsigned long kvm_register_read(struct kvm_vcpu *vcpu, int r= eg) +static inline unsigned long kvm_gpr_read(struct kvm_vcpu *vcpu, int reg) { unsigned long val =3D kvm_register_read_raw(vcpu, reg); =20 return is_64_bit_mode(vcpu) ? val : (u32)val; } =20 -static inline void kvm_register_write(struct kvm_vcpu *vcpu, - int reg, unsigned long val) +static inline void kvm_gpr_write(struct kvm_vcpu *vcpu, int reg, unsigned = long val) { if (!is_64_bit_mode(vcpu)) val =3D (u32)val; diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c index d6b2a665b499..c9700dc88bb1 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -1679,7 +1679,7 @@ int kvm_xen_hypercall(struct kvm_vcpu *vcpu) bool handled =3D false; u8 cpl; =20 - input =3D (u64)kvm_register_read(vcpu, VCPU_REGS_RAX); + input =3D (u64)kvm_gpr_read(vcpu, VCPU_REGS_RAX); =20 /* Hyper-V hypercalls get bit 31 set in EAX */ if ((input & 0x80000000) && --=20 2.51.0 From nobody Sun Feb 8 09:13:05 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (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 3800221D599; Sun, 21 Dec 2025 04:31:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291488; cv=none; b=FBDmjD8HOORGUy+uTnuhhrb0kGtuJ2NW079JbXvneAjD2P1TkJqu8i1k8udDAkGD636yEsHvGdPr4FThe7GJmxCedfRjK+/B1oCU5KaZGLWpwZdX9w+RehStM5KodgUBTh4/bKtItbT0Zj5odgC3/pbSoOtPfCUamaTWLTx9CKY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291488; c=relaxed/simple; bh=m4PVmqLInaUcMIDkus+7Y3RqDkU0G1ERKYiwTfpGyD4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BRX/otyuHP6z9zpYEHRwbivHosjco27SEM+jkk4iy+hRWWGagzbrEH5Ml6gunNbQxg5pu4kAh/Jf7bH38WfFmVeGUe3PB1dVclVDiLg9UTyfZJEPpZU3l9i2iowv8XkFjpUfTQbobkZi7brl4hahx3SbPKS9gh9t95Ull5yARWE= 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=jAzWuMRd; arc=none smtp.client-ip=198.175.65.21 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="jAzWuMRd" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1766291486; x=1797827486; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=m4PVmqLInaUcMIDkus+7Y3RqDkU0G1ERKYiwTfpGyD4=; b=jAzWuMRdbNv8NcAB4OWZqAtq965ZMNy6rBeZA+cBpLX0oOpAO8/y6vKi T9TsVWbiGX4EYlzVtyPIKPHX8QVt97bKh6TKYYqAarbqFeCmvLlDkCmil ZasCquK6571WHHHXyxc7o2/VS42N4qvWZ+dXhIgwamiAeunV3ihrFt/b9 7siSvXWedAYWpDhkGE8gd5BtmPC1d5O02mUAzhmcfd3MUMtin2LWU/HXz TA2Kc4/HDuuPsiFChrtKnPuvk5S6BZE6UvENyMKWz9MxvSGNbqnRsbWmL 0iPAbqQ+q32FfeoWZzqekOleUqR2+l+Ca1ZH8kAVILNosbCOQltxNDO8N Q==; X-CSE-ConnectionGUID: DKziS7UUQJC1ACOLzw4HsA== X-CSE-MsgGUID: 794Cv4UlQxWFjbAKtsjvTQ== X-IronPort-AV: E=McAfee;i="6800,10657,11635"; a="68132380" X-IronPort-AV: E=Sophos;i="6.20,256,1758610800"; d="scan'208";a="68132380" Received: from orviesa002.jf.intel.com ([10.64.159.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Dec 2025 20:31:26 -0800 X-CSE-ConnectionGUID: jqYtRxEtTtuDw3ixRAKfvA== X-CSE-MsgGUID: m843+mkqTq2jV042+Z9yNg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,164,1763452800"; d="scan'208";a="229884953" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.172]) by orviesa002.jf.intel.com with ESMTP; 20 Dec 2025 20:31:25 -0800 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH 02/16] KVM: x86: Refactor GPR accessors to differentiate register access types Date: Sun, 21 Dec 2025 04:07:28 +0000 Message-ID: <20251221040742.29749-3-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251221040742.29749-1-chang.seok.bae@intel.com> References: <20251221040742.29749-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" Refactor the GPR accessors to introduce internal helpers to distinguish between legacy and extended GPRs. Add CONFIG_KVM_APX to selectively enable EGPR support. EGPRs will initially remain unused in the kernel. Thus, the state will not be saved in KVM register cache on every VM exit. Instead, the guest state remains live in hardware registers or is stored in guest fpstate. For now, the EGPR accessors are placeholders to be implemented later. Link: https://lore.kernel.org/7cff2a78-94f3-4746-9833-c2a1bf51eed6@redhat.c= om Suggested-by: Paolo Bonzini Signed-off-by: Chang S. Bae --- Changes since last version: * Move kvm_gpr_read_raw() / kvm_gpr_write_raw() into x86.c (Paolo: https://lore.kernel.org/33eacd6f-5598-49cb-bb11-ca3a47bfb111@redh= at.com) * Add CONFIG_KVM_APX to compile out R16-R31 handling (Paolo). Massage the changelog to note this. --- arch/x86/include/asm/kvm_host.h | 18 ++++++++++++++++ arch/x86/include/asm/kvm_vcpu_regs.h | 16 ++++++++++++++ arch/x86/kvm/Kconfig | 4 ++++ arch/x86/kvm/fpu.h | 6 ++++++ arch/x86/kvm/x86.c | 32 ++++++++++++++++++++++++++++ arch/x86/kvm/x86.h | 19 +++++++++++++++-- 6 files changed, 93 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index 5a3bfa293e8b..9dedb8d77222 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -212,6 +212,24 @@ enum { VCPU_SREG_GS, VCPU_SREG_TR, VCPU_SREG_LDTR, +#ifdef CONFIG_X86_64 + VCPU_XREG_R16 =3D __VCPU_XREG_R16, + VCPU_XREG_R17 =3D __VCPU_XREG_R17, + VCPU_XREG_R18 =3D __VCPU_XREG_R18, + VCPU_XREG_R19 =3D __VCPU_XREG_R19, + VCPU_XREG_R20 =3D __VCPU_XREG_R20, + VCPU_XREG_R21 =3D __VCPU_XREG_R21, + VCPU_XREG_R22 =3D __VCPU_XREG_R22, + VCPU_XREG_R23 =3D __VCPU_XREG_R23, + VCPU_XREG_R24 =3D __VCPU_XREG_R24, + VCPU_XREG_R25 =3D __VCPU_XREG_R25, + VCPU_XREG_R26 =3D __VCPU_XREG_R26, + VCPU_XREG_R27 =3D __VCPU_XREG_R27, + VCPU_XREG_R28 =3D __VCPU_XREG_R28, + VCPU_XREG_R29 =3D __VCPU_XREG_R29, + VCPU_XREG_R30 =3D __VCPU_XREG_R30, + VCPU_XREG_R31 =3D __VCPU_XREG_R31, +#endif }; =20 enum exit_fastpath_completion { diff --git a/arch/x86/include/asm/kvm_vcpu_regs.h b/arch/x86/include/asm/kv= m_vcpu_regs.h index 1af2cb59233b..dd0cc171f405 100644 --- a/arch/x86/include/asm/kvm_vcpu_regs.h +++ b/arch/x86/include/asm/kvm_vcpu_regs.h @@ -20,6 +20,22 @@ #define __VCPU_REGS_R13 13 #define __VCPU_REGS_R14 14 #define __VCPU_REGS_R15 15 +#define __VCPU_XREG_R16 16 +#define __VCPU_XREG_R17 17 +#define __VCPU_XREG_R18 18 +#define __VCPU_XREG_R19 19 +#define __VCPU_XREG_R20 20 +#define __VCPU_XREG_R21 21 +#define __VCPU_XREG_R22 22 +#define __VCPU_XREG_R23 23 +#define __VCPU_XREG_R24 24 +#define __VCPU_XREG_R25 25 +#define __VCPU_XREG_R26 26 +#define __VCPU_XREG_R27 27 +#define __VCPU_XREG_R28 28 +#define __VCPU_XREG_R29 29 +#define __VCPU_XREG_R30 30 +#define __VCPU_XREG_R31 31 #endif =20 #endif /* _ASM_X86_KVM_VCPU_REGS_H */ diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index 278f08194ec8..2b2995188e97 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). diff --git a/arch/x86/kvm/fpu.h b/arch/x86/kvm/fpu.h index f898781b6a06..f2613924532d 100644 --- a/arch/x86/kvm/fpu.h +++ b/arch/x86/kvm/fpu.h @@ -4,6 +4,7 @@ #define __KVM_FPU_H_ =20 #include +#include =20 typedef u32 __attribute__((vector_size(16))) sse128_t; #define __sse128_u union { sse128_t vec; u64 as_u64[2]; u32 as_u32[4]; } @@ -203,4 +204,9 @@ static inline void kvm_write_mmx_reg(int reg, const u64= *data) kvm_fpu_put(); } =20 +#ifdef CONFIG_X86_64 +static inline unsigned long kvm_read_egpr(int reg) { return 0; } +static inline void kvm_write_egpr(int reg, unsigned long data) { } +#endif + #endif diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 23e57170898a..819986edb79c 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1255,6 +1255,38 @@ static inline u64 kvm_guest_supported_xfd(struct kvm= _vcpu *vcpu) } #endif =20 +#ifdef CONFIG_KVM_APX +unsigned long kvm_gpr_read_raw(struct kvm_vcpu *vcpu, int reg) +{ + switch (reg) { + case VCPU_REGS_RAX ... VCPU_REGS_R15: + return kvm_register_read_raw(vcpu, reg); + case VCPU_XREG_R16 ... VCPU_XREG_R31: + return kvm_read_egpr(reg); + default: + WARN_ON_ONCE(1); + } + + return 0; +} +EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_gpr_read_raw); + +void kvm_gpr_write_raw(struct kvm_vcpu *vcpu, int reg, unsigned long val) +{ + switch (reg) { + case VCPU_REGS_RAX ... VCPU_REGS_R15: + kvm_register_write_raw(vcpu, reg, val); + break; + case VCPU_XREG_R16 ... VCPU_XREG_R31: + kvm_write_egpr(reg, val); + break; + default: + WARN_ON_ONCE(1); + } +} +EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_gpr_write_raw); +#endif + int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr) { u64 xcr0 =3D xcr; diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 7d6c1c31539f..19183aa92855 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -400,9 +400,24 @@ static inline bool vcpu_match_mmio_gpa(struct kvm_vcpu= *vcpu, gpa_t gpa) return false; } =20 +#ifdef CONFIG_KVM_APX +unsigned long kvm_gpr_read_raw(struct kvm_vcpu *vcpu, int reg); +void kvm_gpr_write_raw(struct kvm_vcpu *vcpu, int reg, unsigned long val); +#else +static inline unsigned long kvm_gpr_read_raw(struct kvm_vcpu *vcpu, int re= g) +{ + return kvm_register_read_raw(vcpu, reg); +} + +static inline void kvm_gpr_write_raw(struct kvm_vcpu *vcpu, int reg, unsig= ned long val) +{ + kvm_register_write_raw(vcpu, reg, val); +} +#endif + static inline unsigned long kvm_gpr_read(struct kvm_vcpu *vcpu, int reg) { - unsigned long val =3D kvm_register_read_raw(vcpu, reg); + unsigned long val =3D kvm_gpr_read_raw(vcpu, reg); =20 return is_64_bit_mode(vcpu) ? val : (u32)val; } @@ -411,7 +426,7 @@ static inline void kvm_gpr_write(struct kvm_vcpu *vcpu,= int reg, unsigned long v { if (!is_64_bit_mode(vcpu)) val =3D (u32)val; - return kvm_register_write_raw(vcpu, reg, val); + kvm_gpr_write_raw(vcpu, reg, val); } =20 static inline bool kvm_check_has_quirk(struct kvm *kvm, u64 quirk) --=20 2.51.0 From nobody Sun Feb 8 09:13:05 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (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 20D961DF723; Sun, 21 Dec 2025 04:31:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291490; cv=none; b=H5v5WZFSdhBr+gCjN41NRm4k5U1JO6FCf4bubZy0wH3ko7xBawDG2/TCB+Uibwm1mZkqe1z5CTTqc/XqSxH6s4jletdbW/HEDf+WBDHrg6txK5RseB7gisK0reWV0CBW+WOvolfiy614Gk34pQpNBiW811AfcDvKbCqXHKiP7l8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291490; c=relaxed/simple; bh=8Qad+bux2mre6hURNDQPJKoXDr2wv4wMXXklm9GNArY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ibBwHrgohn3KSaOrhaLU44zAXnuaT7e2H2pfJ07OGcRrJ7hiyM2G0MBrUqF6BfY1HcDKNoFtnzYmAD8RyjZDy7NuSMnta6eSndxaAMC90GKqJlMV6d0YUJuKcYHvj76X9xkRgcGH0OFIWsDVddT6ZbSahh9+6k0B0+CP3+w5cIs= 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=Y00Is0v4; arc=none smtp.client-ip=198.175.65.21 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="Y00Is0v4" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1766291488; x=1797827488; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=8Qad+bux2mre6hURNDQPJKoXDr2wv4wMXXklm9GNArY=; b=Y00Is0v4R78qqaseLrf/zHvxj/BvSbnV7cVn6W3ByoovDPpCdZ/upd1z S3P7KAtTcjCHUqB3qjJKwCdg7varxNPjdKFgrfz4XWRUvM7WeoVnOE9sr gBM0ew7Y8fcef4Y5QjdXJo4hKuF3/8uv4UW2vJQAOlv0q9Kvfw/ylkYij tSKCtgQ75QT0nkVj1JeYCMJAFuuJjAL1JlPNtRlvXpQmta0pHRw7Ek/+f 4/l9q9Kup92yT/sJhOfi66ftfHNJiWHFEqeZ5WA952fOgBzLWmKwt7S6V 8Ml6D4PAE7EiWdX/YQk5O3RKyNG130QDtuazkIjZoeyLAUSMe7D6OStV6 Q==; X-CSE-ConnectionGUID: 0pHVH37PReeBZnMvwBkKqg== X-CSE-MsgGUID: TxtP/8FBRMmB6SzOKhwTvw== X-IronPort-AV: E=McAfee;i="6800,10657,11635"; a="68132383" X-IronPort-AV: E=Sophos;i="6.20,256,1758610800"; d="scan'208";a="68132383" Received: from orviesa002.jf.intel.com ([10.64.159.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Dec 2025 20:31:27 -0800 X-CSE-ConnectionGUID: 7XkRDpg/TX2rkdQrgrm5Sw== X-CSE-MsgGUID: HD/NjcCWRf+l778PbmNG0Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,164,1763452800"; d="scan'208";a="229884959" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.172]) by orviesa002.jf.intel.com with ESMTP; 20 Dec 2025 20:31:27 -0800 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH 03/16] KVM: x86: Implement accessors for extended GPRs Date: Sun, 21 Dec 2025 04:07:29 +0000 Message-ID: <20251221040742.29749-4-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251221040742.29749-1-chang.seok.bae@intel.com> References: <20251221040742.29749-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 Add helpers to directly read and write EGPRs (R16=E2=80=93R31). Unlike legacy GPRs, EGPRs are not cached in vcpu->arch.regs[]. Their contents remain live in hardware. If preempted, the EGPR state is preserved in the guest XSAVE buffer. The Advanced Performance Extensions (APX) feature introduces EGPRs as an XSAVE-managed state component. The new helpers access the registers directly between kvm_fpu_get() and kvm_fpu_put(). Callers should ensure that EGPRs are enabled before using these helpers. Signed-off-by: Chang S. Bae --- No change since last version --- arch/x86/kvm/fpu.h | 80 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/fpu.h b/arch/x86/kvm/fpu.h index f2613924532d..f132cad4b49e 100644 --- a/arch/x86/kvm/fpu.h +++ b/arch/x86/kvm/fpu.h @@ -148,6 +148,61 @@ static inline void _kvm_write_mmx_reg(int reg, const u= 64 *data) } } =20 +#ifdef CONFIG_X86_64 +/* + * Accessors for extended general-purpose registers. binutils >=3D 2.43 can + * recognize those register symbols. + */ + +static inline void _kvm_read_egpr(int reg, unsigned long *data) +{ + /* mov %r16..%r31, %rax */ + switch (reg) { + case __VCPU_XREG_R16: asm(".byte 0xd5, 0x48, 0x89, 0xc0" : "=3Da"(*data))= ; break; + case __VCPU_XREG_R17: asm(".byte 0xd5, 0x48, 0x89, 0xc8" : "=3Da"(*data))= ; break; + case __VCPU_XREG_R18: asm(".byte 0xd5, 0x48, 0x89, 0xd0" : "=3Da"(*data))= ; break; + case __VCPU_XREG_R19: asm(".byte 0xd5, 0x48, 0x89, 0xd8" : "=3Da"(*data))= ; break; + case __VCPU_XREG_R20: asm(".byte 0xd5, 0x48, 0x89, 0xe0" : "=3Da"(*data))= ; break; + case __VCPU_XREG_R21: asm(".byte 0xd5, 0x48, 0x89, 0xe8" : "=3Da"(*data))= ; break; + case __VCPU_XREG_R22: asm(".byte 0xd5, 0x48, 0x89, 0xf0" : "=3Da"(*data))= ; break; + case __VCPU_XREG_R23: asm(".byte 0xd5, 0x48, 0x89, 0xf8" : "=3Da"(*data))= ; break; + case __VCPU_XREG_R24: asm(".byte 0xd5, 0x4c, 0x89, 0xc0" : "=3Da"(*data))= ; break; + case __VCPU_XREG_R25: asm(".byte 0xd5, 0x4c, 0x89, 0xc8" : "=3Da"(*data))= ; break; + case __VCPU_XREG_R26: asm(".byte 0xd5, 0x4c, 0x89, 0xd0" : "=3Da"(*data))= ; break; + case __VCPU_XREG_R27: asm(".byte 0xd5, 0x4c, 0x89, 0xd8" : "=3Da"(*data))= ; break; + case __VCPU_XREG_R28: asm(".byte 0xd5, 0x4c, 0x89, 0xe0" : "=3Da"(*data))= ; break; + case __VCPU_XREG_R29: asm(".byte 0xd5, 0x4c, 0x89, 0xe8" : "=3Da"(*data))= ; break; + case __VCPU_XREG_R30: asm(".byte 0xd5, 0x4c, 0x89, 0xf0" : "=3Da"(*data))= ; break; + case __VCPU_XREG_R31: asm(".byte 0xd5, 0x4c, 0x89, 0xf8" : "=3Da"(*data))= ; break; + default: BUG(); + } +} + +static inline void _kvm_write_egpr(int reg, unsigned long *data) +{ + /* mov %rax, %r16...%r31*/ + switch (reg) { + case __VCPU_XREG_R16: asm(".byte 0xd5, 0x18, 0x89, 0xc0" : : "a"(*data));= break; + case __VCPU_XREG_R17: asm(".byte 0xd5, 0x18, 0x89, 0xc1" : : "a"(*data));= break; + case __VCPU_XREG_R18: asm(".byte 0xd5, 0x18, 0x89, 0xc2" : : "a"(*data));= break; + case __VCPU_XREG_R19: asm(".byte 0xd5, 0x18, 0x89, 0xc3" : : "a"(*data));= break; + case __VCPU_XREG_R20: asm(".byte 0xd5, 0x18, 0x89, 0xc4" : : "a"(*data));= break; + case __VCPU_XREG_R21: asm(".byte 0xd5, 0x18, 0x89, 0xc5" : : "a"(*data));= break; + case __VCPU_XREG_R22: asm(".byte 0xd5, 0x18, 0x89, 0xc6" : : "a"(*data));= break; + case __VCPU_XREG_R23: asm(".byte 0xd5, 0x18, 0x89, 0xc7" : : "a"(*data));= break; + case __VCPU_XREG_R24: asm(".byte 0xd5, 0x19, 0x89, 0xc0" : : "a"(*data));= break; + case __VCPU_XREG_R25: asm(".byte 0xd5, 0x19, 0x89, 0xc1" : : "a"(*data));= break; + case __VCPU_XREG_R26: asm(".byte 0xd5, 0x19, 0x89, 0xc2" : : "a"(*data));= break; + case __VCPU_XREG_R27: asm(".byte 0xd5, 0x19, 0x89, 0xc3" : : "a"(*data));= break; + case __VCPU_XREG_R28: asm(".byte 0xd5, 0x19, 0x89, 0xc4" : : "a"(*data));= break; + case __VCPU_XREG_R29: asm(".byte 0xd5, 0x19, 0x89, 0xc5" : : "a"(*data));= break; + case __VCPU_XREG_R30: asm(".byte 0xd5, 0x19, 0x89, 0xc6" : : "a"(*data));= break; + case __VCPU_XREG_R31: asm(".byte 0xd5, 0x19, 0x89, 0xc7" : : "a"(*data));= break; + default: BUG(); + } +} +#endif + static inline void kvm_fpu_get(void) { fpregs_lock(); @@ -205,8 +260,29 @@ static inline void kvm_write_mmx_reg(int reg, const u6= 4 *data) } =20 #ifdef CONFIG_X86_64 -static inline unsigned long kvm_read_egpr(int reg) { return 0; } -static inline void kvm_write_egpr(int reg, unsigned long data) { } +static inline unsigned long kvm_read_egpr(int reg) +{ + unsigned long data; + + if (WARN_ON_ONCE(!cpu_has_xfeatures(XFEATURE_MASK_APX, NULL))) + return 0; + + kvm_fpu_get(); + _kvm_read_egpr(reg, &data); + kvm_fpu_put(); + + return data; +} + +static inline void kvm_write_egpr(int reg, unsigned long data) +{ + if (WARN_ON_ONCE(!cpu_has_xfeatures(XFEATURE_MASK_APX, NULL))) + return; + + kvm_fpu_get(); + _kvm_write_egpr(reg, &data); + kvm_fpu_put(); +} #endif =20 #endif --=20 2.51.0 From nobody Sun Feb 8 09:13:05 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (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 F01202236F3; Sun, 21 Dec 2025 04:31:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291492; cv=none; b=j6+SijNNsHRbo/nzmfiJREb4xCyVHcOKmHAqU1sCQpHxh23nWRY8qKtaZ+1obOjoCJsYp0U3VigXpND8GFchSr+ufCPYkiF7gfSkoco1ci73dxBQjIyGjRVUjEQ0rM2iGZ/p7EFf4avAXKvoaPw2miUD9+pqPFYDb0qxqQTD64w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291492; c=relaxed/simple; bh=ETFtYkEoPUqCgEgLksII29RG50I/Tk+UrB4MaRbwwWo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uCix+IrY/YAGBA04m7gO914/Vgnfgqq7Cz5nRNOuRXh2N2OS978eoAYvaqSjqfDk1L9Qjs6TGMUZnIkhIuloOjggcDI8LxU8R0aSmlCFFexZcAus9n4hQA9kYYPUeWp/Ut0b8PsR9+kWp10IBZGkSchAo1ByL+CPRXTOmtsJ2so= 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=NBXDSwmS; arc=none smtp.client-ip=198.175.65.21 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="NBXDSwmS" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1766291490; x=1797827490; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ETFtYkEoPUqCgEgLksII29RG50I/Tk+UrB4MaRbwwWo=; b=NBXDSwmSWHIgcBjKr3Rv5qg1+4a8G1NoZP27HyPWrzfkSs3DOW/9+5Q1 Y58wxn+TlnoUm1O1fcharXL8NOBCcracJpYZiQhND9xyuKZpS8xSqohSx O3tMF/CP/zFTXJe7/MR0iy3iM47hi7US+tPw+/OjWVREQwixafdCMm/k3 X5bdv8tNGUAahihgpkMgnkea9bIo12g2NtobaJrnnJaGsP3bM/X+0DdKQ x9LYAS9umO6paOj+u0CSbe+GTrtGbngfmUFrgxnBokB8LMlHdbRTevj4x OLPEOIV+FZF80ti+19e2A7lRRdaCsIHiZdx3luAIwMgZozNd4vGe7EnAT A==; X-CSE-ConnectionGUID: P8w/v7qyRnW6WoAMtbbdOQ== X-CSE-MsgGUID: cV/L13hmRlmymDHvwWcuKg== X-IronPort-AV: E=McAfee;i="6800,10657,11635"; a="68132387" X-IronPort-AV: E=Sophos;i="6.20,256,1758610800"; d="scan'208";a="68132387" Received: from orviesa002.jf.intel.com ([10.64.159.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Dec 2025 20:31:29 -0800 X-CSE-ConnectionGUID: 5Bv0qkJkSP++ZXZbf/Lg7Q== X-CSE-MsgGUID: 71Aew747Sd+c2LyXiliP4Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,164,1763452800"; d="scan'208";a="229884965" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.172]) by orviesa002.jf.intel.com with ESMTP; 20 Dec 2025 20:31:29 -0800 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH 04/16] KVM: VMX: Introduce unified instruction info structure Date: Sun, 21 Dec 2025 04:07:30 +0000 Message-ID: <20251221040742.29749-5-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251221040742.29749-1-chang.seok.bae@intel.com> References: <20251221040742.29749-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 a unified data structure that can represent both the legacy and extended VMX instruction information formats. VMX provides per-instruction metadata for VM exits to help decode the attributes of the instruction that triggered the exit. The legacy format, however, only supports up to 16 GPRs and thus cannot represent EGPRs. To support these new registers, VMX introduces an extended 64-bit layout. Instead of maintaining separate storage for each format, a single union structure makes the overall handling simple. The field names are consistent across both layouts. While the presence of certain fields depends on the instruction type, the offsets remain fixed within each format. Signed-off-by: Chang S. Bae --- No change since last version --- arch/x86/kvm/vmx/vmx.h | 61 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index bc3ed3145d7e..567320115a5a 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -311,6 +311,67 @@ struct kvm_vmx { u64 *pid_table; }; =20 +/* + * 32-bit layout of the legacy instruction information field. This format + * supports the 16 legacy GPRs. + */ +struct base_insn_info { + u32 scale : 2; /* Scaling factor */ + u32 reserved1 : 1; + u32 reg1 : 4; /* First register index */ + u32 asize : 3; /* Address size */ + u32 is_reg : 1; /* 0: memory, 1: register */ + u32 osize : 2; /* Operand size */ + u32 reserved2 : 2; + u32 seg : 3; /* Segment register index */ + u32 index : 4; /* Index register index */ + u32 index_invalid : 1; /* 0: valid, 1: invalid */ + u32 base : 4; /* Base register index */ + u32 base_invalid : 1; /* 0: valid, 1: invalid */ + u32 reg2 : 4; /* Second register index */ +}; + +/* + * 64-bit layout of the extended instruction information field, which + * supports EGPRs. + */ +struct ext_insn_info { + u64 scale : 2; /* Scaling factor */ + u64 asize : 2; /* Address size */ + u64 is_reg : 1; /* 0: memory, 1: register */ + u64 osize : 2; /* Operand size */ + u64 seg : 3; /* Segment register index */ + u64 index_invalid : 1; /* 0: valid, 1: invalid */ + u64 base_invalid : 1; /* 0: valid, 1: invalid */ + u64 reserved1 : 4; + u64 reg1 : 5; /* First register index */ + u64 reserved2 : 3; + u64 index : 5; /* Index register index */ + u64 reserved3 : 3; + u64 base : 5; /* Base register index */ + u64 reserved4 : 3; + u64 reg2 : 5; /* Second register index */ + u64 reserved5 : 19; +}; + +/* Union for accessing either the legacy or extended format. */ +union insn_info { + struct base_insn_info base; + struct ext_insn_info ext; + u32 word; + u64 dword; +}; + +/* + * Wrapper structure combining the instruction info and a flag indicating + * whether the extended layout is in use. + */ +struct vmx_insn_info { + /* true if using the extended layout */ + bool extended; + union insn_info info; +}; + static __always_inline struct vcpu_vt *to_vt(struct kvm_vcpu *vcpu) { return &(container_of(vcpu, struct vcpu_vmx, vcpu)->vt); --=20 2.51.0 From nobody Sun Feb 8 09:13:05 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (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 20CC021CC7B; Sun, 21 Dec 2025 04:31:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291495; cv=none; b=Tlq/GojUJzZIqWC14mL4Gd2lpZf+s4Mp/yQ9vosqgbKajjPX7xqV43H265+3i2vnZdavXeD+7/ztMFnl/yvjYudXze7KYTlYsPKCZC/aRDmLPAcIV+oTdudMSVTUyH8cLff+OdGm8QFuvbMRpV/TIrBwONiZz3EAlEzbRUG4/NU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291495; c=relaxed/simple; bh=Zey7/cPb/bvZvwRADisMH0xtOMrTQ65Vf8gIwMGuSdo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tEG1LUk/uP23+FCWZRD6C/4nOk2bqo7ZYc5uc7ktnMu6IFRZRmbZrafapJuFtMo4Osarv/78G+iLqGAkXp8rPQjhGEIwncp916xSlFyFOjWAzc/1MAe7lii+fTF8unlA4y6IBq24A6RTdsH/XjNsNMxLf5liwQfHJHJJDCXIocI= 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=Naqlg7YE; arc=none smtp.client-ip=198.175.65.21 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="Naqlg7YE" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1766291493; x=1797827493; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Zey7/cPb/bvZvwRADisMH0xtOMrTQ65Vf8gIwMGuSdo=; b=Naqlg7YEN90Y78HatXP7zb6I0wpYG4Hij7siL804hWBTDjY7pBb6qfWN bRp0bAIt+4CPDTGKfnc5vJkG7c3tVwMHMMh0x2ZypIy4nsgzaNeFfMbQT ZNYHYKpP9Hvocd08+h+9JpR37r4okADLrmVIUj2uL7dIxk7IX9nOf+yOU q+cqgIH8ErMFy8bg1TqqAo/QijtDz0Ma7JpZjeKdhPq+4EhuNeBAOM98Q gZKnrcfOcldSLIRdLqOGTfs/HU3DawrY3ATNv8M1zP6MqdW9WtOuLjtbG biru5HRsek+mzzuw3TFFYK2MwOzPM6/u+UjgbMlrlOIau0bciuoBgf/76 g==; X-CSE-ConnectionGUID: z065+HWaRFaLetI+6w2xBg== X-CSE-MsgGUID: YMFiQ63TSNasTGVTYosvdw== X-IronPort-AV: E=McAfee;i="6800,10657,11635"; a="68132393" X-IronPort-AV: E=Sophos;i="6.20,256,1758610800"; d="scan'208";a="68132393" Received: from orviesa002.jf.intel.com ([10.64.159.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Dec 2025 20:31:32 -0800 X-CSE-ConnectionGUID: ly5JB0FtQ1+ezDEb/3sEiw== X-CSE-MsgGUID: +xlGdVw1Q06dDkg+dNOmsg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,164,1763452800"; d="scan'208";a="229884977" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.172]) by orviesa002.jf.intel.com with ESMTP; 20 Dec 2025 20:31:32 -0800 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH 05/16] KVM: VMX: Refactor instruction information retrieval Date: Sun, 21 Dec 2025 04:07:31 +0000 Message-ID: <20251221040742.29749-6-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251221040742.29749-1-chang.seok.bae@intel.com> References: <20251221040742.29749-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 helpers to convert and extract exited instruction attributes, preparing for EGPR support and deprecating some existing helpers. Previously, VMX exit handlers directly decoded the raw VMCS field, resulting in duplicated logic and assumption tied to the legacy layout. With the unified structure, handlers can convert raw data into a structure form and access each instruction attribute by field name. The helper will later determine the format based on the VCPU configuration. For now, there is no functional change since only the legacy layout is used. Signed-off-by: Chang S. Bae --- No change since last version --- arch/x86/kvm/vmx/nested.c | 73 +++++++++++++++++++-------------------- arch/x86/kvm/vmx/nested.h | 2 +- arch/x86/kvm/vmx/vmx.c | 14 ++++---- arch/x86/kvm/vmx/vmx.h | 23 ++++++------ 4 files changed, 57 insertions(+), 55 deletions(-) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 84e2a4a613b7..558f889db621 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -5238,7 +5238,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) + struct vmx_insn_info info, bool wr, int len, gva_t *ret) { gva_t off; bool exn; @@ -5252,14 +5252,14 @@ int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsi= gned long exit_qualification, * 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 insn_attr(info, scale); + int addr_size =3D insn_attr(info, asize); + bool is_reg =3D insn_attr(info, is_reg); + int seg_reg =3D insn_attr(info, seg); + int index_reg =3D insn_attr(info, index); + bool index_is_valid =3D !insn_attr(info, index_invalid); + int base_reg =3D insn_attr(info, base); + bool base_is_valid =3D !insn_attr(info, base_invalid); =20 if (is_reg) { kvm_queue_exception(vcpu, UD_VECTOR); @@ -5370,7 +5370,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_insn_info(vcpu), false, sizeof(*vmpointer), &gva)) { *ret =3D 1; return -EINVAL; @@ -5655,7 +5655,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); + struct vmx_insn_info info =3D vmx_get_insn_info(vcpu); struct vcpu_vmx *vmx =3D to_vmx(vcpu); struct x86_exception e; unsigned long field; @@ -5668,7 +5668,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu) return 1; =20 /* Decode instruction info and find the field to read */ - field =3D kvm_gpr_read(vcpu, (((instr_info) >> 28) & 0xf)); + field =3D kvm_gpr_read(vcpu, insn_attr(info, reg2)); =20 if (!nested_vmx_is_evmptr12_valid(vmx)) { /* @@ -5716,12 +5716,12 @@ 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_gpr_write(vcpu, (((instr_info) >> 3) & 0xf), value); + if (insn_attr(info, is_reg)) { + kvm_gpr_write(vcpu, insn_attr(info, reg1), value); } else { len =3D is_64_bit_mode(vcpu) ? 8 : 4; if (get_vmx_mem_address(vcpu, exit_qualification, - instr_info, true, len, &gva)) + info, true, len, &gva)) return 1; /* _system ok, nested_vmx_check_permission has verified cpl=3D0 */ r =3D kvm_write_guest_virt_system(vcpu, gva, &value, len, &e); @@ -5761,7 +5761,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); + struct vmx_insn_info info =3D vmx_get_insn_info(vcpu); struct vcpu_vmx *vmx =3D to_vmx(vcpu); struct x86_exception e; unsigned long field; @@ -5790,19 +5790,19 @@ 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_gpr_read(vcpu, (((instr_info) >> 3) & 0xf)); + if (insn_attr(info, is_reg)) + value =3D kvm_gpr_read(vcpu, insn_attr(info, reg1)); else { len =3D is_64_bit_mode(vcpu) ? 8 : 4; if (get_vmx_mem_address(vcpu, exit_qualification, - instr_info, false, len, &gva)) + info, false, len, &gva)) return 1; r =3D kvm_read_guest_virt(vcpu, gva, &value, len, &e); if (r !=3D X86EMUL_CONTINUE) return kvm_handle_memory_failure(vcpu, r, &e); } =20 - field =3D kvm_gpr_read(vcpu, (((instr_info) >> 28) & 0xf)); + field =3D kvm_gpr_read(vcpu, insn_attr(info, reg2)); =20 offset =3D get_vmcs12_field_offset(field); if (offset < 0) @@ -5950,7 +5950,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); + struct vmx_insn_info info =3D vmx_get_insn_info(vcpu); gpa_t current_vmptr =3D to_vmx(vcpu)->nested.current_vmptr; struct x86_exception e; gva_t gva; @@ -5962,7 +5962,7 @@ static int handle_vmptrst(struct kvm_vcpu *vcpu) if (unlikely(nested_vmx_is_evmptr12_valid(to_vmx(vcpu)))) return 1; =20 - if (get_vmx_mem_address(vcpu, exit_qual, instr_info, + if (get_vmx_mem_address(vcpu, exit_qual, info, true, sizeof(gpa_t), &gva)) return 1; /* *_system ok, nested_vmx_check_permission has verified cpl=3D0 */ @@ -5978,15 +5978,16 @@ 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; + struct vmx_insn_info info; struct kvm_mmu *mmu; gva_t gva; struct x86_exception e; struct { u64 eptp, gpa; } operand; - int i, r, gpr_index; + u32 types; + int i, r; =20 if (!(vmx->nested.msrs.secondary_ctls_high & SECONDARY_EXEC_ENABLE_EPT) || @@ -5998,9 +5999,8 @@ 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); - gpr_index =3D vmx_get_instr_info_reg2(vmx_instruction_info); - type =3D kvm_gpr_read(vcpu, gpr_index); + info =3D vmx_get_insn_info(vcpu); + type =3D kvm_gpr_read(vcpu, insn_attr(info, reg2)); =20 types =3D (vmx->nested.msrs.ept_caps >> VMX_EPT_EXTENT_SHIFT) & 6; =20 @@ -6011,7 +6011,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)) + info, false, sizeof(operand), &gva)) return 1; r =3D kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e); if (r !=3D X86EMUL_CONTINUE) @@ -6058,7 +6058,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; + struct vmx_insn_info info; unsigned long type, types; gva_t gva; struct x86_exception e; @@ -6067,7 +6067,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) u64 gla; } operand; u16 vpid02; - int r, gpr_index; + int r; =20 if (!(vmx->nested.msrs.secondary_ctls_high & SECONDARY_EXEC_ENABLE_VPID) || @@ -6079,9 +6079,8 @@ 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); - gpr_index =3D vmx_get_instr_info_reg2(vmx_instruction_info); - type =3D kvm_gpr_read(vcpu, gpr_index); + info =3D vmx_get_insn_info(vcpu); + type =3D kvm_gpr_read(vcpu, insn_attr(info, reg2)); =20 types =3D (vmx->nested.msrs.vpid_caps & VMX_VPID_EXTENT_SUPPORTED_MASK) >> 8; @@ -6094,7 +6093,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)) + info, false, sizeof(operand), &gva)) return 1; r =3D kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e); if (r !=3D X86EMUL_CONTINUE) @@ -6432,7 +6431,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; + struct vmx_insn_info info; unsigned long field; u8 b; =20 @@ -6440,8 +6439,8 @@ 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); - field =3D kvm_gpr_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf)); + info =3D vmx_get_insn_info(vcpu); + field =3D kvm_gpr_read(vcpu, insn_attr(info, reg2)); =20 /* Out-of-range fields always cause a VM exit from L2 to L1 */ if (field >> 15) diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h index 983484d42ebf..e54f4e7b3664 100644 --- a/arch/x86/kvm/vmx/nested.h +++ b/arch/x86/kvm/vmx/nested.h @@ -50,7 +50,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); + struct vmx_insn_info info, bool wr, int len, gva_t *ret); void nested_mark_vmcs12_pages_dirty(struct kvm_vcpu *vcpu); bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port, int size); diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index c944b75c10a7..ae28b06b11f5 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -6054,29 +6054,27 @@ static int handle_monitor_trap(struct kvm_vcpu *vcp= u) =20 static int handle_invpcid(struct kvm_vcpu *vcpu) { - u32 vmx_instruction_info; + struct vmx_insn_info info; unsigned long type; gva_t gva; struct { u64 pcid; u64 gla; } operand; - int gpr_index; =20 if (!guest_cpu_cap_has(vcpu, X86_FEATURE_INVPCID)) { kvm_queue_exception(vcpu, UD_VECTOR); return 1; } =20 - vmx_instruction_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); - gpr_index =3D vmx_get_instr_info_reg2(vmx_instruction_info); - type =3D kvm_gpr_read(vcpu, gpr_index); + info =3D vmx_get_insn_info(vcpu); + type =3D kvm_gpr_read(vcpu, insn_attr(info, reg2)); =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, + info, false, sizeof(operand), &gva)) return 1; =20 @@ -6219,7 +6217,9 @@ 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)); + struct vmx_insn_info info =3D vmx_get_insn_info(vcpu); + + return insn_attr(info, reg1); } =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 567320115a5a..ed02a8bcc15e 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -372,6 +372,19 @@ struct vmx_insn_info { union insn_info info; }; =20 +static inline struct vmx_insn_info vmx_get_insn_info(struct kvm_vcpu *vcpu= __maybe_unused) +{ + struct vmx_insn_info insn; + + insn.extended =3D false; + insn.info.word =3D vmcs_read32(VMX_INSTRUCTION_INFO); + + return insn; +} + +#define insn_attr(insn, attr) \ + ((insn).extended ? (insn).info.ext.attr : (insn).info.base.attr) + static __always_inline struct vcpu_vt *to_vt(struct kvm_vcpu *vcpu) { return &(container_of(vcpu, struct vcpu_vmx, vcpu)->vt); @@ -778,16 +791,6 @@ static inline bool vmx_guest_state_valid(struct kvm_vc= pu *vcpu) =20 void dump_vmcs(struct kvm_vcpu *vcpu); =20 -static inline int vmx_get_instr_info_reg(u32 vmx_instr_info) -{ - return (vmx_instr_info >> 3) & 0xf; -} - -static inline int vmx_get_instr_info_reg2(u32 vmx_instr_info) -{ - return (vmx_instr_info >> 28) & 0xf; -} - static inline bool vmx_can_use_ipiv(struct kvm_vcpu *vcpu) { return lapic_in_kernel(vcpu) && enable_ipiv; --=20 2.51.0 From nobody Sun Feb 8 09:13:05 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (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 CEBBD224B14; Sun, 21 Dec 2025 04:31:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291498; cv=none; b=JxRcbDTnNudPf8VrG5vb2y8LerzTFle3LCFvjH/FWdzrL++x0v59Z/G3gG1mw8tm0jhv1O1brP7FDqToJARNxCweWk+igNgExDBcatnimet7hUQM55fUOaEwQFa5LkG5bHBfqSTbJpELC5dfIuDWPogssE92kHedcnn4aaVQ+kI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291498; c=relaxed/simple; bh=li9hVWBHhty+00eqwTRi0vVQ+K6SA6W4G6nVCNUqAKQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hcrYfXypdOKUHT5ifXR5hGlbPyTnf494vek8rF4yVKq37HeiNlzg2ui8gF9vpoYE99noIZlbaavwjXiwJS4gJ/2TtVu3ZGKUGuxQz1zsDQdGVhoN4DWkT0tfNcbs5NQ6CSnBsK8B7HnK5yDnRSNxnx057kzzvOiLo/1XTHaDMCY= 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=VqXOBcu1; arc=none smtp.client-ip=198.175.65.21 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="VqXOBcu1" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1766291495; x=1797827495; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=li9hVWBHhty+00eqwTRi0vVQ+K6SA6W4G6nVCNUqAKQ=; b=VqXOBcu17N977njR2CPaO2fhnj+I7PxtlEQ9TUOdo8eaZSrqHjlUi99v Lm4i41ozOgEK0GFSpsmnuJafjXC4+jy3z3aCsEUkgLpQ6mJsBZfC1bPho 8NE2k3UKZOB02YtzvmvIpuKA6hi70aLrbKWAusOm0DN2AIbQBy5sfQFRM ntnHGQpg0OdKvA2SJfOcdJmk82BhrFStzpYnZF1E7K4K5Wi5ERN9JfbIi s2a3SJJpEsAfg8dBWBnnfMPEusR5OEsD8HHeYxojXlYEh1By6ioe2FIfC pyoPJvrvQg99512/KgREqmMEtMqYh5rNZFG9M0DkwlXsURZ6SHeGCK+Vm g==; X-CSE-ConnectionGUID: KNW5PAMDTkqG0GSP7JYAsQ== X-CSE-MsgGUID: q8LknoBfRyC/LVl4MwyyJw== X-IronPort-AV: E=McAfee;i="6800,10657,11635"; a="68132398" X-IronPort-AV: E=Sophos;i="6.20,256,1758610800"; d="scan'208";a="68132398" Received: from orviesa002.jf.intel.com ([10.64.159.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Dec 2025 20:31:35 -0800 X-CSE-ConnectionGUID: 166MSMKVRqi3t4tYmIqgOg== X-CSE-MsgGUID: UvZ8OuuXSLOAn/pDfgJjaw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,164,1763452800"; d="scan'208";a="229884987" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.172]) by orviesa002.jf.intel.com with ESMTP; 20 Dec 2025 20:31:35 -0800 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH 06/16] KVM: VMX: Refactor GPR index retrieval from exit qualification Date: Sun, 21 Dec 2025 04:07:32 +0000 Message-ID: <20251221040742.29749-7-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251221040742.29749-1-chang.seok.bae@intel.com> References: <20251221040742.29749-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 GPR index from the exit qualification field. VMX exit qualification, in addition to the VMX instruction info field, encodes a GPR index. With the introduction of EGPRs, this field is extended by a previously reserved bit position. This refactoring centralizes the logic so that future updates can handle the extended GPR index without code duplication. Since the VMCS exit qualification is cached in VCPU state, it is safe for the helper to access it directly via the VCPU pointer. This argument will also be used later to determine EGPR availability. No functional change intended. Signed-off-by: Chang S. Bae --- No change since last version --- arch/x86/kvm/vmx/nested.c | 2 +- arch/x86/kvm/vmx/vmx.c | 2 +- arch/x86/kvm/vmx/vmx.h | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 558f889db621..1e35e1923aec 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -6353,7 +6353,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_gpr(vcpu); val =3D kvm_gpr_read(vcpu, reg); switch (cr) { case 0: diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index ae28b06b11f5..d41e710e8807 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -5588,7 +5588,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_gpr(vcpu); switch ((exit_qualification >> 4) & 3) { case 0: /* mov to cr */ val =3D kvm_gpr_read(vcpu, reg); diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index ed02a8bcc15e..f8dbad161717 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -411,6 +411,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_gpr(struct kvm_vcpu *vcpu) +{ + return (vmx_get_exit_qual(vcpu) >> 8) & 0xf; +} + static __always_inline u32 vmx_get_intr_info(struct kvm_vcpu *vcpu) { struct vcpu_vt *vt =3D to_vt(vcpu); --=20 2.51.0 From nobody Sun Feb 8 09:13:05 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (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 9BF44223705; Sun, 21 Dec 2025 04:31:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291500; cv=none; b=Cl9G6RvnbpxNoU2WPjTsAxBrM14GxqiTtT8c2wyJzfmJvVeOTvNTt0hfwIExUu2L8TqC10fpD+Q49pH80ZucrAGZS+XopEVx0LFrLQjIlMtGe3pK3gB24F9Eq/N0PA1s+lcUdRX0HbLvhbMKuMFLqoEDbK214Mv9Re5IujQe1Ok= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291500; c=relaxed/simple; bh=I8VBhy6rygv+7rZ1aV4AF7DUYQgORjwnVyQili26KyE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fZEg7RpfxkPs+Q8QXZKnKVGzsoRTpz03NPHLQ9bCptjRl/+9hnUUPwfccC6HQjiW1f2RxEGlHkPxpv0GkQBMRj+6pA07q98aIckDjOAcUs9QQDbJ9C/xVuxyaHO0Z622EWXc0wObGAU9YZd09HpUYkN43F4e2nq4xXIlGnDH7XY= 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=WWYVIMHY; arc=none smtp.client-ip=198.175.65.21 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="WWYVIMHY" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1766291498; x=1797827498; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=I8VBhy6rygv+7rZ1aV4AF7DUYQgORjwnVyQili26KyE=; b=WWYVIMHYh+oEZRPlWTNOA4+MJZzzy0lS4w5n0r7c75DX/ASaN7//EZ1d kmguWgB3wSf4tZ1u4fQNVioLDiK5OAlvEfXtLSMSo0gr3YcdLFV2xKBBV ReloO/c6OVSmf3YwPMIwon7RT1pBtb5qY6cnKwf4MQ7aeSClZKdh/mKSP XExbqhF2+W8Owr3oSa193/bto3I99ik3XMerRTafkRdzQrD/FROAxeejW 8oQul80vHmGho36t+SSG5e1ducTn4CXXofWiRKDoPvXL+c/yZxXX76P1P ELZDGaItWGJwyo0XlKNuqd3dAgJMNuoulbhUnUiXyR1qTA/O+rxQU0DZ3 Q==; X-CSE-ConnectionGUID: oAQU7mAATGWOiYVfYdS2Zg== X-CSE-MsgGUID: V3zctVNTTJinzzZS7UeuIQ== X-IronPort-AV: E=McAfee;i="6800,10657,11635"; a="68132402" X-IronPort-AV: E=Sophos;i="6.20,256,1758610800"; d="scan'208";a="68132402" Received: from orviesa002.jf.intel.com ([10.64.159.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Dec 2025 20:31:38 -0800 X-CSE-ConnectionGUID: et7ZrMymRoabH+KTKRX0UQ== X-CSE-MsgGUID: IleDPW+sRMG7K17d1c4kew== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,164,1763452800"; d="scan'208";a="229884992" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.172]) by orviesa002.jf.intel.com with ESMTP; 20 Dec 2025 20:31:38 -0800 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH 07/16] KVM: nVMX: Propagate the extended instruction info field Date: Sun, 21 Dec 2025 04:07:33 +0000 Message-ID: <20251221040742.29749-8-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251221040742.29749-1-chang.seok.bae@intel.com> References: <20251221040742.29749-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, propagate the field to nested VMX. When a virtual CPU enumerates the APX capability, nested VMX should expose the extended field to address higher register indices. Link: https://lore.kernel.org/CABgObfa-vqWCenVvvTAoB773AQ+9a1OOT9n5hjqT=3Dz= ZBDQbb+Q@mail.gmail.com Suggested-by: Chao Gao Signed-off-by: Chang S. Bae --- Changes since last version: * Check the availability based on the guest APX capability (Chao) * Massage the changelog to reflect this fact. --- arch/x86/include/asm/vmx.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/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index c85c50019523..ab0684948c56 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -264,6 +264,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/nested.c b/arch/x86/kvm/vmx/nested.c index 1e35e1923aec..ce972eeaa6f7 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -4746,6 +4746,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 4233b5ca9461..ea2b690a419e 100644 --- a/arch/x86/kvm/vmx/vmcs12.c +++ b/arch/x86/kvm/vmx/vmcs12.c @@ -53,6 +53,7 @@ const unsigned short vmcs12_field_offsets[] =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 4ad6b16525b9..2146e45aaade 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.51.0 From nobody Sun Feb 8 09:13:05 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (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 DDEDC2236E0; Sun, 21 Dec 2025 04:31:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291504; cv=none; b=NNUR5VoSZYUO05fpSjl/PKDA1I6Fz7e6XJbLWOu3te3kaX4Y61G+6nP9e9h77pESbNlABom5zfXCsIRj/mM5Rxs0FgHM00La9PMPEdfSUktIIUiJG4O063Z2ciP14N+fBlHzUEpbbebHZMd0VLjv73j2X6rySNquf2hc/bNTHIc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291504; c=relaxed/simple; bh=FJMJLaZeEkRpouMa6Z8DLyquPu+lMP+v7uZ/KQreFsg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZdJWOPGzbm5XbQkwRqKy/Fsh1Y9pV/PhgalP3lRGTCa2F4wo16bmymPLiSxGNQgNPxwAVh4ZNFi0r2rOxzBHZbqbRh9AxR+fmlHaXXq+k0Dfg2bayzzjCpgEy4jQ82M3uKmyVgScTDjxG50Rr20Ty1HVh1c+lHKeh3pj6y3T2T0= 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=JovDy1yA; arc=none smtp.client-ip=198.175.65.21 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="JovDy1yA" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1766291502; x=1797827502; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=FJMJLaZeEkRpouMa6Z8DLyquPu+lMP+v7uZ/KQreFsg=; b=JovDy1yA4WPPZFq8QpaioFsM5T2LsOYnJy9wb4U3q0GETa4GOI5kPhA4 4oAvPylTYCpiKjP3ZeghGD1Q7G7Us3V3Zfh4p7E045cvo/cps3/F6iT6P 9qXwfdkXxYwzHomf0NtBmqUQGAqwcA8dUaHpxr6lqk0BCUPfqtlobak9g XFfEwl/T3/BmjX2Z9NyW5BxeKLISYvlXXh/nAsebwCsjKycKeUhgDft1h m5HggrFrWphxaXoV4n2BvzrhI12J2Xhwr/sBJ3/eH8qkm6rQjE1Bd0Jkc 5Cis7jjYDS30JTepHd3+KYxVTAa2NqQIrxg+cQG9k3jRoEeWkSGHsuAHD g==; X-CSE-ConnectionGUID: ivY8c4yxTeGe+jb/On1N7Q== X-CSE-MsgGUID: 8XrYOUKyQUeOsxfA+8CSJg== X-IronPort-AV: E=McAfee;i="6800,10657,11635"; a="68132407" X-IronPort-AV: E=Sophos;i="6.20,256,1758610800"; d="scan'208";a="68132407" Received: from orviesa002.jf.intel.com ([10.64.159.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Dec 2025 20:31:41 -0800 X-CSE-ConnectionGUID: 3iUQIzwKTGi/vDgxfrEZUg== X-CSE-MsgGUID: cZbfERRlSbujDbm4mUUC4Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,164,1763452800"; d="scan'208";a="229885001" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.172]) by orviesa002.jf.intel.com with ESMTP; 20 Dec 2025 20:31:41 -0800 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH 08/16] KVM: VMX: Support extended register index in exit handling Date: Sun, 21 Dec 2025 04:07:34 +0000 Message-ID: <20251221040742.29749-9-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251221040742.29749-1-chang.seok.bae@intel.com> References: <20251221040742.29749-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" Support 5-bit register indices in VMCS fields when APX feature is enumerated. The presence of the extended instruction information field is indicated by APX enumeration, regardless of the XCR0.APX bit setting. With APX enumerated, the previously reserved bit in the exit qualification can be referenced safely now. However, there is no guarantee that older implementations always zeroed this bit. Link: https://lore.kernel.org/7bb14722-c036-4835-8ed9-046b4e67909e@redhat.c= om Suggested-by: Paolo Bonzini Signed-off-by: Chang S. Bae --- Changes since last version: * Switch the condition for using the extended instruction information from checking XCR0 to relying on APX enumeration (Paolo). * Rewrite the changelog to clarify this behavior. --- arch/x86/kvm/vmx/vmx.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index f8dbad161717..937f862f060d 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -372,12 +372,26 @@ struct vmx_insn_info { union insn_info info; }; =20 -static inline struct vmx_insn_info vmx_get_insn_info(struct kvm_vcpu *vcpu= __maybe_unused) +/* + * 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_insn_info_extended(void) +{ + return static_cpu_has(X86_FEATURE_APX); +} + +static inline struct vmx_insn_info vmx_get_insn_info(struct kvm_vcpu *vcpu) { struct vmx_insn_info insn; =20 - insn.extended =3D false; - insn.info.word =3D vmcs_read32(VMX_INSTRUCTION_INFO); + if (vmx_insn_info_extended()) { + insn.extended =3D true; + insn.info.dword =3D vmcs_read64(EXTENDED_INSTRUCTION_INFO); + } else { + insn.extended =3D false; + insn.info.word =3D vmcs_read32(VMX_INSTRUCTION_INFO); + } =20 return insn; } @@ -413,7 +427,10 @@ static __always_inline unsigned long vmx_get_exit_qual= (struct kvm_vcpu *vcpu) =20 static inline int vmx_get_exit_qual_gpr(struct kvm_vcpu *vcpu) { - return (vmx_get_exit_qual(vcpu) >> 8) & 0xf; + if (vmx_insn_info_extended()) + return (vmx_get_exit_qual(vcpu) >> 8) & 0x1f; + else + return (vmx_get_exit_qual(vcpu) >> 8) & 0xf; } =20 static __always_inline u32 vmx_get_intr_info(struct kvm_vcpu *vcpu) --=20 2.51.0 From nobody Sun Feb 8 09:13:05 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (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 B242B225779; Sun, 21 Dec 2025 04:31:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291505; cv=none; b=d3PIyvk76Z6r1fl8wiA323xIDFgEOCbZ+NAwNUsdSWptxY38z7HlbOFkr3CDhVCmR+bsgATK5piA0mqhcHSpTablur0wOlg4+8ocpKu5+x/nKJzhbUQc4jlfQLrUwix9f/aU73GgBcnXS/dmzM4D0kV8dn6wfaXKheoTKEZ2c4w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291505; c=relaxed/simple; bh=zkoXqskiBbDIfaa1XN7EYMIqCDWEv3YgveEwuaplNM0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gS5bQG2NvWfvx7yjlUAsKxqBGZ0lThyEX26yvHrXX5bJy/WOyxUKjwBhB4q50S8hTHzSdwtf9KjTftHCQmZrFZznsbZS7L1EUQKyptGN9lAMZSxztcCOCBX9AAceXo9ImrhccemP+OABzYqURE/v7wBVWYDUer0G0KSCEUYYLn4= 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=Y9hDCVJh; arc=none smtp.client-ip=198.175.65.21 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="Y9hDCVJh" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1766291503; x=1797827503; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=zkoXqskiBbDIfaa1XN7EYMIqCDWEv3YgveEwuaplNM0=; b=Y9hDCVJhstpzDB9IrN6gq8igq01dIMotPFOhO2YfYzdtaiireigRBzzr Z6c1Ld5EdlNh9caUoiBmrnvgKIUMmB5SL1OyowtBA6nF5SCV4KjGRb01B CEiDuvLzYtddDFbNNMS8CQ6xGsWxe7YrHILaf7b8bo0poDhv2mRu5XF+E f7B36Kg50eBf/lwav/XXf4Y9Osfl/TE0Du/QY0l+BSL2sjzxc4dFI7Bs6 zHGOniO/6w6+uIIJTWRaFwzy7nA2rw6A6vwKkY7wAw+4+8pGGvVUscdE9 Uoh+MNpdCBAKPY0AE8vefKFON7UiyBprBA7Sy89N1l9WZj9hwRH0+lm4B A==; X-CSE-ConnectionGUID: kTJWFfMWRCm9b/xKSasTUA== X-CSE-MsgGUID: 9whfn61wSgCr0n04ACya3g== X-IronPort-AV: E=McAfee;i="6800,10657,11635"; a="68132412" X-IronPort-AV: E=Sophos;i="6.20,256,1758610800"; d="scan'208";a="68132412" Received: from orviesa002.jf.intel.com ([10.64.159.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Dec 2025 20:31:43 -0800 X-CSE-ConnectionGUID: iqL5rOvJSt2wn3gJE5Q5cA== X-CSE-MsgGUID: 2IWu/6pxQWeOYxN1+/XrLw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,164,1763452800"; d="scan'208";a="229885010" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.172]) by orviesa002.jf.intel.com with ESMTP; 20 Dec 2025 20:31:43 -0800 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH 09/16] KVM: emulate: Support EGPR accessing and tracking Date: Sun, 21 Dec 2025 04:07:35 +0000 Message-ID: <20251221040742.29749-10-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251221040742.29749-1-chang.seok.bae@intel.com> References: <20251221040742.29749-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. Now the KVM GPR accessors can handle EGPRs. Then, the emulator can uniformly cache and track all GPRs without requiring separate handling. Signed-off-by: Chang S. Bae --- No change since last version --- arch/x86/kvm/kvm_emulate.h | 10 +++++----- arch/x86/kvm/x86.c | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h index fb3dab4b5a53..16b35a796a7f 100644 --- a/arch/x86/kvm/kvm_emulate.h +++ b/arch/x86/kvm/kvm_emulate.h @@ -105,13 +105,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. @@ -314,7 +314,7 @@ typedef void (*fastop_t)(struct fastop *); * a ModRM or SIB byte. */ #ifdef CONFIG_X86_64 -#define NR_EMULATOR_GPRS 16 +#define NR_EMULATOR_GPRS 32 #else #define NR_EMULATOR_GPRS 8 #endif @@ -373,9 +373,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; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 819986edb79c..abbc9b8736e7 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -8817,12 +8817,12 @@ static bool emulator_guest_cpuid_is_intel_compatibl= e(struct x86_emulate_ctxt *ct =20 static ulong emulator_read_gpr(struct x86_emulate_ctxt *ctxt, unsigned reg) { - return kvm_register_read_raw(emul_to_vcpu(ctxt), reg); + return kvm_gpr_read_raw(emul_to_vcpu(ctxt), reg); } =20 static void emulator_write_gpr(struct x86_emulate_ctxt *ctxt, unsigned reg= , ulong val) { - kvm_register_write_raw(emul_to_vcpu(ctxt), reg, val); + kvm_gpr_write_raw(emul_to_vcpu(ctxt), reg, val); } =20 static void emulator_set_nmi_mask(struct x86_emulate_ctxt *ctxt, bool mask= ed) --=20 2.51.0 From nobody Sun Feb 8 09:13:05 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (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 20FDC22655B; Sun, 21 Dec 2025 04:31:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291508; cv=none; b=kscowoKiEhOwdsk/0jHqopvpYQx7jRIPG0xB5IAr/JFWIQgAkxZZ48vWDJYX/MNYXA/46bl28aLolMaNEWJtnOYm2rbt0qxSQucT2xH2dRiVcw70Pln0YhxplZZG5wvoHnjvbpryc6lxMj+ekHHdoq/3oUFvsEIZHNyzOkhWD8k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291508; c=relaxed/simple; bh=5CVZJSO1vs60pqptnZve9rSGX1Qu+JSFvxM3nsRVdgQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ErhsWFZPh8XDbNLvjDtNgjiM8i8B8p/h1JOxhLpflB/x2ob1kNX1PvL70JWp0kUjFMaFqTX7eKxEqbOjKjDQAUGBYGzPAmi2uX+RmytoHs9cR9CXi2DaH55N+xFHKoy39Ywa7xHJwatdBHFeDRWV3EIEeidlffqOwDmmBkjOphI= 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=dXEgRduh; arc=none smtp.client-ip=198.175.65.21 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="dXEgRduh" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1766291506; x=1797827506; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=5CVZJSO1vs60pqptnZve9rSGX1Qu+JSFvxM3nsRVdgQ=; b=dXEgRduhpp36wo5h/W0qXEWE91Ulclzs9iYEmWR4fBOz8nENhletdrbz H2Ky5dEl/aouK5pPLPYuRvcyIEC0C5MP1g0T+3NAxwmM1tlbmMXmxlxqc Lt/3Bsgvh1qx+InMEngqdisRKh227m4+Out0ErdfXtDxen5cfO2dGpNlK HBZR1BPMVvDR2/YtWP1T4VFdlFqeeOtRo/Yb6cjpa/bmAxiIHLmgmu6Bj nHp3Y575GMwPZGz9JprHVm4qxXYgPRRg/tb6qrgl7Ii9P1kSh9eyjBl9d 3UjnmxPVWgNMD4LWzK+xYLdoikG27sXM0wym/nveLqWGnc6k3aVhd5IK3 A==; X-CSE-ConnectionGUID: aRp6bso6SEi/a9aecfASeQ== X-CSE-MsgGUID: WjJmfvtlQ1O1SseZAGJuJg== X-IronPort-AV: E=McAfee;i="6800,10657,11635"; a="68132419" X-IronPort-AV: E=Sophos;i="6.20,256,1758610800"; d="scan'208";a="68132419" Received: from orviesa002.jf.intel.com ([10.64.159.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Dec 2025 20:31:45 -0800 X-CSE-ConnectionGUID: ZEjWdzS+R/ez02yKsF97Pw== X-CSE-MsgGUID: BAsLqxneQ5mcF4JNB2efKw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,164,1763452800"; d="scan'208";a="229885020" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.172]) by orviesa002.jf.intel.com with ESMTP; 20 Dec 2025 20:31:45 -0800 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH 10/16] KVM: emulate: Handle EGPR index and REX2-incompatible opcodes Date: Sun, 21 Dec 2025 04:07:36 +0000 Message-ID: <20251221040742.29749-11-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251221040742.29749-1-chang.seok.bae@intel.com> References: <20251221040742.29749-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 NoRex opcode flag and supporting extended register indices. Add a helper to factor out common logic for calculating register indices from a given register identifier and REX bits alone. 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. Link: https://lore.kernel.org/1ebf3a23-5671-41c1-8daa-c83f2f105936@redhat.c= om Suggested-by: Paolo Bonzini Signed-off-by: Chang S. Bae --- Changes since last version: * Introduce a dedicated flag to mark REX2-incompatible opcodes (Paolo). With JMPABS dropped, there is no longer a need to separate opcode tables. * Refactor register index extraction into a common helper (Paolo) and adjust its return value to match existing call sites. Have __always_inline to ensure no build issue with BUILD_BUG_ON(!__builtin_constant_p(fld)) * Rewrite and clarify the changelog accordingly. --- 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 c8e292e9a24d..242e043634b9 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 NoRex ((u64)1 << 58) /* Instruction has no use of REX prefi= x */ =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) @@ -1078,6 +1080,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) { @@ -1117,7 +1128,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); } @@ -1136,9 +1147,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; @@ -4245,7 +4256,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 | NoRex, em_inc)), X8(I(DstReg | NoRex, em_dec)), /* 0x50 - 0x57 */ X8(I(SrcReg | Stack, em_push)), /* 0x58 - 0x5F */ @@ -4263,7 +4274,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 | NoRex)), /* 0x80 - 0x87 */ G(ByteOp | DstMem | SrcImm, group1), G(DstMem | SrcImm, group1), @@ -4287,15 +4298,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 | NoRex, em_mov), + I2bv(DstMem | SrcAcc | Mov | MemAbs | PageTable | NoRex, em_mov), + I2bv(SrcSI | DstDI | Mov | String | TwoMemOp | NoRex, em_mov), + I2bv(SrcSI | DstDI | String | NoWrite | TwoMemOp | NoRex, 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 | NoRex, em_test), + I2bv(SrcAcc | DstDI | Mov | String | NoRex, em_mov), + I2bv(SrcSI | DstAcc | Mov | String | NoRex, em_mov), + I2bv(SrcAcc | DstDI | String | NoWrite | NoRex, em_cmp_r), /* 0xB0 - 0xB7 */ X8(I(ByteOp | DstReg | SrcImm | Mov, em_mov)), /* 0xB8 - 0xBF */ @@ -4325,17 +4336,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 | NoRex, em_loop)), + I(SrcImmByte | NearBranch | IsBranch | NoRex, em_jcxz), + I2bvIP(SrcImmUByte | DstAcc | NoRex, em_in, in, check_perm_in), + I2bvIP(SrcAcc | DstImmUByte | NoRex, 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 | NoRex, em_call), + D(SrcImm | ImplicitOps | NearBranch | IsBranch | NoRex), + I(SrcImmFAddr | No64 | IsBranch | NoRex, em_jmp_far), + D(SrcImmByte | ImplicitOps | NearBranch | IsBranch | NoRex), + I2bvIP(SrcDX | DstAcc | NoRex, em_in, in, check_perm_in), + I2bvIP(SrcAcc | DstDX | NoRex, em_out, out, check_perm_out), /* 0xF0 - 0xF7 */ N, DI(ImplicitOps, icebp), N, N, DI(ImplicitOps | Priv, hlt), D(ImplicitOps), @@ -4376,12 +4387,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 | NoRex, em_wrmsr, wrmsr), + IIP(ImplicitOps | NoRex, em_rdtsc, rdtsc, check_rdtsc), + II(ImplicitOps | Priv | NoRex, em_rdmsr, rdmsr), + IIP(ImplicitOps | NoRex, em_rdpmc, rdpmc, check_rdpmc), + I(ImplicitOps | EmulateOnUD | IsBranch | ShadowStack | NoRex, em_sysenter= ), + I(ImplicitOps | Priv | EmulateOnUD | IsBranch | ShadowStack | NoRex, em_s= ysexit), N, N, N, N, N, N, N, N, N, N, /* 0x40 - 0x4F */ @@ -4399,7 +4410,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 | NoRex)), /* 0x90 - 0x9F */ X16(D(ByteOp | DstMem | SrcNone | ModRM| Mov)), /* 0xA0 - 0xA7 */ @@ -4992,6 +5003,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 NoRex ignore a legacy REX prefix, but + * #UD should be raised when prefixed with REX2. + */ + if (ctxt->d & NoRex && 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 16b35a796a7f..dd5d1e489db6 100644 --- a/arch/x86/kvm/kvm_emulate.h +++ b/arch/x86/kvm/kvm_emulate.h @@ -325,6 +325,7 @@ typedef void (*fastop_t)(struct fastop *); enum rex_type { REX_NONE, REX_PREFIX, + REX2_PREFIX, }; =20 struct x86_emulate_ctxt { --=20 2.51.0 From nobody Sun Feb 8 09:13:05 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (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 38C60224B12; Sun, 21 Dec 2025 04:31:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291510; cv=none; b=X8mCLZe5gJGcEREyxFkaAENl0VIK78zuSMsCPKtJvmjUYnlivroN27URy2IEreBA4Ip4ScqlPDeWupLjVTiqNXgDNI/4ZlXU8f0cbkN+xPJHzgozh+kcARMxeaKP3U8kK8KWjI0bdCp0FJNK9WhfzTq/ln1ixHH1Nmx+Bvz0DtA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291510; c=relaxed/simple; bh=Tp2WE60FQZau2ypCW1hE/j91K5p9W1IYSRQjvongfI4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ajfI5qXTpTgKyePRDJGqzA+ksPe4nzZGFxUkpV/Koo9EzGH3UkUXDBTjx5hvYRHvnf//Jz/u+zRV8x3DZ6mUUmJgxBc9IvfTq9bqktr6QO7e58ieYAAfaXCXVCGssRWHlNaAhEro8VyaG8hV+apkGWmHPN4LITj1hFhnVJElGcY= 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=dv3rHMz/; arc=none smtp.client-ip=198.175.65.21 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="dv3rHMz/" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1766291508; x=1797827508; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Tp2WE60FQZau2ypCW1hE/j91K5p9W1IYSRQjvongfI4=; b=dv3rHMz/6mJzVrrmRkjjD1IMuYCRGJ5S4opR0JJNOcmnc4OtbuzJKqae nce5TJ3QQmsZ5prp+N1dU+8N/+P2zIWN31FRGwPcejl7Y9OZQXawpJnMA rGnEVz6fKx9rdQVu6PAyKDKHmvy9LlK2zCe7d3JDwx46DZxje7md6JoIk kjXjqvSkVrN10+9s8OdPZbygiyUIn31Yl4+UBSExbDVoQBNCHaOW/9JvV EeDNw9csYHhkRSKGU1Eh/2o6jhSg8/TKcFeScTtUURHo2SJ89HdSOJLyY dQLCbnA2WgbyhMk2uxyxWpCC5Fr6hxZDp8fxcxCSVN6yXofBlJxiwl4wY w==; X-CSE-ConnectionGUID: vuhkc8ZSS/W82wab5iFgnA== X-CSE-MsgGUID: CpuBo3+lQxSF4JJ1zFBMpA== X-IronPort-AV: E=McAfee;i="6800,10657,11635"; a="68132424" X-IronPort-AV: E=Sophos;i="6.20,256,1758610800"; d="scan'208";a="68132424" Received: from orviesa002.jf.intel.com ([10.64.159.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Dec 2025 20:31:47 -0800 X-CSE-ConnectionGUID: xMDg+UPlTRyfJEeaJ9lUUA== X-CSE-MsgGUID: gYJ4j9ZYR9+3qd6eFbDm+A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,164,1763452800"; d="scan'208";a="229885030" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.172]) by orviesa002.jf.intel.com with ESMTP; 20 Dec 2025 20:31:47 -0800 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH 11/16] KVM: emulate: Support REX2-prefixed opcode decode Date: Sun, 21 Dec 2025 04:07:37 +0000 Message-ID: <20251221040742.29749-12-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251221040742.29749-1-chang.seok.bae@intel.com> References: <20251221040742.29749-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 NoRex alr= eady invalidates REX2 for these opcodes, adding No64 makes opcode attributes explicit and complete. Link: https://lore.kernel.org/CABgObfYYGTvkYpeyqLSr9JgKMDA_STSff2hXBNchLZuK= FU+MMA@mail.gmail.com Suggested-by: Paolo Bonzini Signed-off-by: Chang S. Bae --- Changes since last version: * Simplify REX2 validation logic (Paolo). * Add direct jumps to the relevant decode paths to reduce control flow complexity (Paolo). * Rewrite and clarify the changelog. --- 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 242e043634b9..fc065ef53400 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -4256,7 +4256,7 @@ static const struct opcode opcode_table[256] =3D { /* 0x38 - 0x3F */ I6ALU(NoWrite, em_cmp), N, N, /* 0x40 - 0x4F */ - X8(I(DstReg | NoRex, em_inc)), X8(I(DstReg | NoRex, em_dec)), + X8(I(DstReg | NoRex | No64, em_inc)), X8(I(DstReg | NoRex | No64, em_dec)= ), /* 0x50 - 0x57 */ X8(I(SrcReg | Stack, em_push)), /* 0x58 - 0x5F */ @@ -4850,6 +4850,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; @@ -4903,7 +4914,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 */ @@ -4949,6 +4960,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; @@ -4971,6 +4993,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 */ @@ -4988,17 +5016,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.51.0 From nobody Sun Feb 8 09:13:05 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (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 E870723A9B3; Sun, 21 Dec 2025 04:31:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291511; cv=none; b=uosAr6VZeuRCYcA1b/GEbylSHQ3B5BU1kEXIQjCo+mYGBynKE5gBNR6VnMS/AtcpWvvOkKJCCKfCVVRp8+EHFVHgDkVd6iVVCCH5aFPFb4p4gr51+Tam82Pj5dg/AEU9UZpCMyNTy69d8kB7d4QFRggd+SUwxkGMZwy5U4P6Oeo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291511; c=relaxed/simple; bh=TRr5hcoQqdjYrW9FJSXg+9zaWcUsOZHBSl3b977kPuw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=f94sesB8QWeviIEjmVcJL2k41C830mFDL+QJ8mtq29IDLNrpQi+1PaG/Lk+fuoPBnd4aC3d5j0NlSNQyj5Hkdb9/Ny0EmVcIFSSGXCW/KGLih5vQsCoz9xhx7Ee+gkC0uaHf3dljkr2KJuq5ikDO/5eREu5/djfSPHMqtF5t4sU= 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=jWiFT+ku; arc=none smtp.client-ip=198.175.65.21 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="jWiFT+ku" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1766291510; x=1797827510; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=TRr5hcoQqdjYrW9FJSXg+9zaWcUsOZHBSl3b977kPuw=; b=jWiFT+kuLhiD/GdEzuG1t1/71Tmrdx+Kod6lmzKyOP1TeM4vnYa+57ti baqn2gIOuwi0mo/Apudf16e2oFI9GK4b5pynRegY5iOzRB94xWtFyJN6V FIjxqhvZ95da+0sxMJq+vOrzsB/u8Ry5QNRp6Ev82MjoKnTiB/+fHUSC4 dlIykRWjE8yA8FUuXaYvSNHW5m5uOpYFVtU2oQDnsKtrKZ8ARRPUN/+Pf vZfE6TH67DrZZxWFVCE1a7ZLCDSw4IyK8JYNL39hDsDgxhN40vynsFGxy W/dnZGWrsf/0fl+ivEiYEL/iVZs0UBJq3uv/zOLI/icpYbbzpWnaJBUiH Q==; X-CSE-ConnectionGUID: f6H0yxtrR06UAujypjIPCw== X-CSE-MsgGUID: aQcs3AcbRj2yO6hMQxDXzw== X-IronPort-AV: E=McAfee;i="6800,10657,11635"; a="68132430" X-IronPort-AV: E=Sophos;i="6.20,256,1758610800"; d="scan'208";a="68132430" Received: from orviesa002.jf.intel.com ([10.64.159.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Dec 2025 20:31:49 -0800 X-CSE-ConnectionGUID: z6EMDUA6RTyvjTwRP9myPg== X-CSE-MsgGUID: g3obFIl/TviXJC9sZsH2aw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,164,1763452800"; d="scan'208";a="229885037" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.172]) by orviesa002.jf.intel.com with ESMTP; 20 Dec 2025 20:31:50 -0800 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH 12/16] KVM: emulate: Reject EVEX-prefixed instructions Date: Sun, 21 Dec 2025 04:07:38 +0000 Message-ID: <20251221040742.29749-13-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251221040742.29749-1-chang.seok.bae@intel.com> References: <20251221040742.29749-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 --- Changes since last version: * Rebase onto the recently merged VEX series. Reuse the previously existing VEX-rejection logic and style. --- 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 fc065ef53400..820ae381e601 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -5040,6 +5040,11 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, v= oid *insn, int insn_len, int if (ctxt->d & NoRex && ctxt->rex_prefix =3D=3D REX2_PREFIX) opcode.flags =3D Undefined; =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; + if (opcode.flags & ModRM) ctxt->modrm =3D insn_fetch(u8, ctxt); =20 --=20 2.51.0 From nobody Sun Feb 8 09:13:05 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (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 7C2782222BF; Sun, 21 Dec 2025 04:31:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291514; cv=none; b=FsLYL4gDMB3nl8gvVO9+9L5whDIo8nS38f4oQ1owdbIYd158fdCVTw5Wg6mUMEZjXLRmAwvdk3dhn5KZuZnOx3QrI135J6wkIlT8nh3LyVbY1nkFcj7og3fcPuG+/SQyg77cKXkfJ2ux7LPFiBOAD2HQTRorPEEco9r1/OFWSao= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291514; c=relaxed/simple; bh=weuoqRDDBv7ieJ0T20j9mdN3G7/5KPySgpcXMMnRAEw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ohRUEhNjn2xviTwG2Sp0amswqQskj/Xks/HYiocC8aP/s9eMqvi9iYZE4kEb2Szzo7PrSuZ/M5KbUGk1x3M1DND1edf8CSSGrKhEEj/1nlwRV+egOPrW0Zd6QzKvUa8NLC9Wz3xSDnJgKFBTLQAGlNt/5ikzs2mU3pbwcbERH/w= 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=Z8XqKljB; arc=none smtp.client-ip=198.175.65.21 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="Z8XqKljB" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1766291512; x=1797827512; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=weuoqRDDBv7ieJ0T20j9mdN3G7/5KPySgpcXMMnRAEw=; b=Z8XqKljBu7OjCF+zyIg+duZxbjboKP+Brlhe+cCXYYQxFlsb4Uorozkm WKb338dTJkiOd2VXKEsJyW6htqnVlaRcJLerMExh8OrfOayGj+5R4Ojto YXE3H0edG+QJMAYouziK08XsnnvVV1a1O+iQ+ieLHqd+zXcQiYXyIk5kp dJ/GyE6156X0KX4WI6GjuhB/kzI26sH5jsrRS6CYZBqKEjkuDDnCQEY0W QS4GMy6nKhNuVYoSToFkWZNWr53KDiHA3yx83onVdWqvetjuyP01lpb/h tNmQ8dBt73kGdoBGW2pxHLnRHdHORz9pBeJXKi7J/lesdbs5Kaxb18wuQ g==; X-CSE-ConnectionGUID: iiqYcbiCRXqf3vy4viLxxw== X-CSE-MsgGUID: gvn7kgbgRfysLY8faTEVbg== X-IronPort-AV: E=McAfee;i="6800,10657,11635"; a="68132435" X-IronPort-AV: E=Sophos;i="6.20,256,1758610800"; d="scan'208";a="68132435" Received: from orviesa002.jf.intel.com ([10.64.159.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Dec 2025 20:31:52 -0800 X-CSE-ConnectionGUID: ug/PgDjlQCWO+uaun9BSsg== X-CSE-MsgGUID: 6dbNNaz5TsGV5ET3Qc2WlA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,164,1763452800"; d="scan'208";a="229885048" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.172]) by orviesa002.jf.intel.com with ESMTP; 20 Dec 2025 20:31:52 -0800 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH 13/16] KVM: x86: Guard valid XCR0.APX settings Date: Sun, 21 Dec 2025 04:07:39 +0000 Message-ID: <20251221040742.29749-14-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251221040742.29749-1-chang.seok.bae@intel.com> References: <20251221040742.29749-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. The addition to the supported XCR0 mask should accompany guest CPUID exposure, which will be done separately. Link: https://lore.kernel.org/ab3f4937-38f5-4354-8850-bf773c159bbe@redhat.c= om Suggested-by: Paolo Bonzini Signed-off-by: Chang S. Bae --- Changes since last version: * Reject setting MPX and APX bits together in XCR0 (Paolo) * Remove XCR0 dependency for extended instruction information (Paolo) * Rewrite the changelog accordingly --- 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 ca1dc2342134..85a150e763b2 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -5299,8 +5299,13 @@ static __init int svm_hardware_setup(void) } kvm_enable_efer_bits(EFER_NX); =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 (boot_cpu_has(X86_FEATURE_FXSR_OPT)) kvm_enable_efer_bits(EFER_FFXSR); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index abbc9b8736e7..0c677af83ee4 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1314,6 +1314,10 @@ int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, = u64 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.51.0 From nobody Sun Feb 8 09:13:05 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (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 953AF22259F; Sun, 21 Dec 2025 04:31:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291516; cv=none; b=mFDly0CwXbnXHSLh0BV52aozECLISRDm5MG576RqBRuMnwN6KwNYcZIM7tVuqkRV6UwAbK2KcRW8L92RKBxPr+vVsQTEJhiPz6ltFotCvUDsecu+bdGBfFCrRwo1yRDMcmLF8yl8E+AEeGg0nEAZg1EbzQZJw7if+5vC503w7ww= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291516; c=relaxed/simple; bh=r2W+MiQjMRr3g0JWHIAQin0ANiKKEp73CXKO3uMG2X0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IrsYxEmTN6A4a8/ey7BP3VxnGqH9fB1qxaDeOIuSHOTgwb8rfokQgYCsr4Vv7Upym9w6c1PCDKyoEj8JBl0oJ3okx9nhbYAcSG0p0GjQx80Ljce2B10IyDeJ2udwkOu7FWpc7sAxSQf6s9TP0cxNar53rf+1M68GC6WaSkCb8zQ= 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=heWdaiOm; arc=none smtp.client-ip=198.175.65.21 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="heWdaiOm" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1766291514; x=1797827514; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=r2W+MiQjMRr3g0JWHIAQin0ANiKKEp73CXKO3uMG2X0=; b=heWdaiOm/03/23B2/si571/p9LSXPfWdY4MBujporpxzSr0zVvnJB3ay C5Q/ykVJWjLSXNTkc0AoBM9aWKwCJv/pbhwO7ha7hHJZK8Oc2fYM0zP2S 67rePUTSb9rTPzG9fkIoWP9i7PRghoHOH2Q6EW2zrAcTNSEkZWw+h8NQ5 lshOTIyOIZ9MVO5qwYUmQajDCV6LQbnZjBipfAZ9QLfm6Injec+ArE8nF TZ0whuSsfWl8w2NKEwPG4LDby+vXF6XqT7oKPhCuReAu5Wa8Bnjujq2ps qGLpEsboWkKdVfjLTg5mHo8jETxpV97S1o8MUOI/Or7Bhr3Q6iJaDhvtc g==; X-CSE-ConnectionGUID: yhLHzBrbRnuh+VivYDYYRg== X-CSE-MsgGUID: waJNr1sDT+ehisT+h2sgPQ== X-IronPort-AV: E=McAfee;i="6800,10657,11635"; a="68132439" X-IronPort-AV: E=Sophos;i="6.20,256,1758610800"; d="scan'208";a="68132439" Received: from orviesa002.jf.intel.com ([10.64.159.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Dec 2025 20:31:54 -0800 X-CSE-ConnectionGUID: AY+d8QEfT7i8POzcMjX2jA== X-CSE-MsgGUID: ex1Grc/kTEmwFSoNk5gDeA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,164,1763452800"; d="scan'208";a="229885052" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.172]) by orviesa002.jf.intel.com with ESMTP; 20 Dec 2025 20:31:54 -0800 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com, Peter Fang Subject: [PATCH 14/16] KVM: x86: Expose APX foundational feature bit to guests Date: Sun, 21 Dec 2025 04:07:40 +0000 Message-ID: <20251221040742.29749-15-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251221040742.29749-1-chang.seok.bae@intel.com> References: <20251221040742.29749-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: Peter Fang Add the APX xfeature bit to the list of supported XCR0 components and expose the APX feature to guests. Define the APX CPUID feature bits and update the maximum supported CPUID leaf to 0x29 to include the APX leaf. On SVM systems, ensure that the feature is not advertised as EGPR support is not yet supported. No APX sub-features are enumerated yet. Those will be exposed in a separate patch. Signed-off-by: Peter Fang Signed-off-by: Chang S. Bae --- No change since last version --- arch/x86/kvm/cpuid.c | 8 +++++++- arch/x86/kvm/reverse_cpuid.h | 2 ++ arch/x86/kvm/svm/svm.c | 8 ++++++++ arch/x86/kvm/x86.c | 3 ++- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index d563a948318b..55b32784c392 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -1031,6 +1031,7 @@ void kvm_set_cpu_caps(void) F(AVX_VNNI_INT16), F(PREFETCHITI), F(AVX10), + SCATTERED_F(APX), ); =20 kvm_cpu_cap_init(CPUID_7_2_EDX, @@ -1394,7 +1395,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); @@ -1639,6 +1640,11 @@ static inline int __do_cpuid_func(struct kvm_cpuid_a= rray *array, u32 function) entry->edx =3D 0; break; } + case 0x29: { + /* No APX sub-features are supported yet */ + 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/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h index 81b4a7acf72e..e538b5444919 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) @@ -125,6 +126,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/svm/svm.c b/arch/x86/kvm/svm/svm.c index 85a150e763b2..afc99afa8dea 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -5282,6 +5282,14 @@ 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); + + /* + * If the APX xfeature bit is not supported, meaning that VMCB + * support for EGPRs is unavailable, then the APX feature should + * not be exposed to the guest. + */ + if (!(kvm_caps.supported_xcr0 & XFEATURE_MASK_APX)) + kvm_cpu_cap_clear(X86_FEATURE_APX); } =20 static __init int svm_hardware_setup(void) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 0c677af83ee4..8b8a532c98eb 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -214,7 +214,8 @@ static DEFINE_PER_CPU(struct kvm_user_return_msrs, user= _return_msrs); #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) + | XFEATURE_MASK_PKRU | XFEATURE_MASK_XTILE \ + | XFEATURE_MASK_APX) =20 #define XFEATURE_MASK_CET_ALL (XFEATURE_MASK_CET_USER | XFEATURE_MASK_CET_= KERNEL) /* --=20 2.51.0 From nobody Sun Feb 8 09:13:05 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (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 0AB5E24677A; Sun, 21 Dec 2025 04:31:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291518; cv=none; b=UjFI28OiKB2PpNv+0oR0/t2v+636O0uS1sV9I/LZsKA0FWs8C29/cZVXOuwQGY/l1efyzmVo5cC4RzqrnPMAb8Nh9dzztfO55LQSYVLrBJvBP1jlzvLjYw2l3Dtr/Le4sFzD62LTv1QtfEkE3QKQ6W7jjr23JyaDbaXe+HQT6G0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291518; c=relaxed/simple; bh=C96fso0takpJoB+lZHZrvgABzsP9IPXlheUDjBPjYoI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ngrMJedeSwS6pJcjoet7EuwzHaFavxWkoQvcxLiZzqy+jEx30kzlrNAFPIUSu3PsKaMU1naN8RSls7EdHKBy9Gg1YVS+9w5pJ7CV0MsR7o11mYMduvAT5aoMwl16sBOfPpNs4px/8ARKgt6wu4UFwrvbt5UVvQQ4s/wkmWJW55g= 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=ItCt4Kn1; arc=none smtp.client-ip=198.175.65.21 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="ItCt4Kn1" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1766291517; x=1797827517; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=C96fso0takpJoB+lZHZrvgABzsP9IPXlheUDjBPjYoI=; b=ItCt4Kn1odMaBemkOVKL/pEwNokmRv+89qugo5nmdHhMxpRWuWU83y+J aRgVYTp5KAAzOCpN/Dq9YpaqI3VIraUS5uZFRccBrnCv2+YPzQ9WWRwOZ mu1VrbvVPfGUWwvhqK6t3Y0tU6r/hRqFXndjkjAlcCB3UjLs0oaqAdYak En+8C0FiZivFuGTeA82FRyCsuVRqLtuWQ0WTRlFj4YSZ1HFCZG9Eb1PcR GguJCX4vuul/fgEpv6GEzvJdcBSQeIYAsNrWJegxdKuAEIljjA8JWEZm5 DWZjdanFOwZA6DEjStb58rZxIbQYkZsPrYclOFVuKQ23GSUzIOmTIcDjR A==; X-CSE-ConnectionGUID: TeX24nrqQ4OL2XdtIk2p3g== X-CSE-MsgGUID: tMbm4fo3Q8ecBmFUK3rgGQ== X-IronPort-AV: E=McAfee;i="6800,10657,11635"; a="68132442" X-IronPort-AV: E=Sophos;i="6.20,256,1758610800"; d="scan'208";a="68132442" Received: from orviesa002.jf.intel.com ([10.64.159.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Dec 2025 20:31:56 -0800 X-CSE-ConnectionGUID: zsIMERelQuK2yRGQrPoFYA== X-CSE-MsgGUID: 9jbmbcysTGeucac/yPPtEg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,164,1763452800"; d="scan'208";a="229885072" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.172]) by orviesa002.jf.intel.com with ESMTP; 20 Dec 2025 20:31:56 -0800 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH 15/16] KVM: x86: Expose APX sub-features to guests Date: Sun, 21 Dec 2025 04:07:41 +0000 Message-ID: <20251221040742.29749-16-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251221040742.29749-1-chang.seok.bae@intel.com> References: <20251221040742.29749-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 enumerate APX sub-features to guests. This leaf currently defines the following sub-features: * New Conditional Instructions (NCI) * New Data Destination (NDD) * Flags Suppression (NF) The CPUID leaf is only exposed if the APX feature is enabled. Signed-off-by: Chang S. Bae --- No change since last version --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/cpuid.c | 10 ++++++++-- arch/x86/kvm/reverse_cpuid.h | 4 ++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index 9dedb8d77222..d75a76152340 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -794,6 +794,7 @@ enum kvm_only_cpuid_leafs { CPUID_24_0_EBX, CPUID_8000_0021_ECX, CPUID_7_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 55b32784c392..e9437bedcafe 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -1063,6 +1063,10 @@ void kvm_set_cpu_caps(void) F(AVX10_512), ); =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), @@ -1641,8 +1645,10 @@ static inline int __do_cpuid_func(struct kvm_cpuid_a= rray *array, u32 function) break; } case 0x29: { - /* No APX sub-features are supported yet */ - entry->eax =3D entry->ebx =3D entry->ecx =3D entry->edx =3D 0; + if (!(kvm_caps.supported_xcr0 & XFEATURE_MASK_APX)) { + entry->eax =3D entry->ebx =3D entry->ecx =3D entry->edx =3D 0; + break; + } break; } case KVM_CPUID_SIGNATURE: { diff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h index e538b5444919..f8587586d031 100644 --- a/arch/x86/kvm/reverse_cpuid.h +++ b/arch/x86/kvm/reverse_cpuid.h @@ -50,6 +50,9 @@ #define X86_FEATURE_AVX10_256 KVM_X86_FEATURE(CPUID_24_0_EBX, 17) #define X86_FEATURE_AVX10_512 KVM_X86_FEATURE(CPUID_24_0_EBX, 18) =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 @@ -91,6 +94,7 @@ static const struct cpuid_reg reverse_cpuid[] =3D { [CPUID_24_0_EBX] =3D { 0x24, 0, CPUID_EBX}, [CPUID_8000_0021_ECX] =3D {0x80000021, 0, CPUID_ECX}, [CPUID_7_1_ECX] =3D { 7, 1, CPUID_ECX}, + [CPUID_29_0_EBX] =3D { 0x29, 0, CPUID_EBX}, }; =20 /* --=20 2.51.0 From nobody Sun Feb 8 09:13:05 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (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 E2EF024DCEB; Sun, 21 Dec 2025 04:31:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291520; cv=none; b=IdcTjNoUbj/bc+2c2ZxTeIcPepmXT4MfmK5q6gHusfMYE75mC5ngAyoj9hQeED8ToPtq2IUFoIg/vEq49R8Uyg5Sj8G6BTJk8l9PHGDi4T+TjcfOkO0EXNqtaX5ViJvr9EssMmEkIPsU3s9Nngw4gzaTZwFyyIqeVhfRQPtk10g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766291520; c=relaxed/simple; bh=/uNM4zNMn5icO82QU9552KoFxkN3gz0ZUeyiQnJC7zg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SZIC2Q9j+8aoKifEyzd1Z9Z1nSIWzp85yH+70WMT2rO7nYL2oO3Gr5jzj62oBjA9KouGb2notoLUUPBOL5g/SkicFZSMrzLhXG35n0YjVkx7MH4FeHf0GM0WkrT5ZCMMFSd4CS5LFrVvYsEJOa7IJ6VAn7dS+iSWPQn+2DBS9fQ= 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=YQ03DMPZ; arc=none smtp.client-ip=198.175.65.21 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="YQ03DMPZ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1766291519; x=1797827519; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=/uNM4zNMn5icO82QU9552KoFxkN3gz0ZUeyiQnJC7zg=; b=YQ03DMPZ5eLE70quFVQi0NMGWd2GeaAaU5ovH/OFT/ITknQ+k1z6Lgl6 ehVzhJQ3D/M4t4z2JyR5nufb1Q3CTraWhclpOjbuETeQ2EoyxvaZ94Fg+ jpOI+mJbUKn3NFirEhErIAbxaEuUKv+hAQoJtpou6M2s8aFg91rR+Kw1H CLmZ6FZ73/ztnf5N1+HUBTg8eUpoht8u4ROTkpG5HJAXmgzXiuQtTz2/8 gHAyL/lme40up7Fd03kFMGzBE+YJkTkSVvd3PCSbEZqbQH7N5FOUYnJm2 LH6epzmeJS07IfsxmBi7U1ZOF/KSlTh/BIrB4FChUL6ekc+McXnfRUGsS Q==; X-CSE-ConnectionGUID: 65l9Hj1QSgmBoWq7w2AUTQ== X-CSE-MsgGUID: KiMh0FUvSEi1UNe5aK31+w== X-IronPort-AV: E=McAfee;i="6800,10657,11635"; a="68132448" X-IronPort-AV: E=Sophos;i="6.20,256,1758610800"; d="scan'208";a="68132448" Received: from orviesa002.jf.intel.com ([10.64.159.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Dec 2025 20:31:58 -0800 X-CSE-ConnectionGUID: kF3pwhpzRAGSwyiYFZSw/g== X-CSE-MsgGUID: JSB1ru6tRy+P3+q+o3YQxQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,164,1763452800"; d="scan'208";a="229885093" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.172]) by orviesa002.jf.intel.com with ESMTP; 20 Dec 2025 20:31:58 -0800 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH 16/16] KVM: x86: selftests: Add APX state handling and XCR0 sanity checks Date: Sun, 21 Dec 2025 04:07:42 +0000 Message-ID: <20251221040742.29749-17-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251221040742.29749-1-chang.seok.bae@intel.com> References: <20251221040742.29749-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 on APX-capable systems, extend the 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 states are 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 --- No change since last version --- .../selftests/kvm/include/x86/processor.h | 1 + tools/testing/selftests/kvm/x86/state_test.c | 6 ++++++ .../selftests/kvm/x86/xcr0_cpuid_test.c | 19 +++++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/te= sting/selftests/kvm/include/x86/processor.h index 57d62a425109..6a1da26780ea 100644 --- a/tools/testing/selftests/kvm/include/x86/processor.h +++ b/tools/testing/selftests/kvm/include/x86/processor.h @@ -88,6 +88,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 | \ diff --git a/tools/testing/selftests/kvm/x86/state_test.c b/tools/testing/s= elftests/kvm/x86/state_test.c index f2c7a1c297e3..2b7aa4cca011 100644 --- a/tools/testing/selftests/kvm/x86/state_test.c +++ b/tools/testing/selftests/kvm/x86/state_test.c @@ -167,6 +167,12 @@ static void __attribute__((__flatten__)) guest_code(vo= id *arg) asm volatile ("vmovupd %0, %%zmm16" :: "m" (buffer)); } =20 + if (supported_xcr0 & XFEATURE_MASK_APX) { + /* mov $0xcccccccc, %r16 */ + asm volatile (".byte 0xd5, 0x18, 0xb8, 0xcc, 0xcc," + "0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00"); + } + if (this_cpu_has(X86_FEATURE_MPX)) { uint64_t bounds[2] =3D { 10, 0xffffffffull }; uint64_t 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 d038c1571729..e3d3af5ab6f2 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) { uint64_t 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.51.0