From nobody Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 6895A25524C; Tue, 12 May 2026 01:40:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550023; cv=none; b=qG9N0uPFNIXIyGj8bvrl4+HA+1PFo8nrLW549UuHhY+6vilNO0gA1AexOggBinuJYmVQlw7LtTyYgM8fWo4pwmf4Xn851KXhXxD4h33n/TKbGZB6/CLf1ZUeZ8vgVcOsKfCNRJNBRzr8XFnPEtLGhMvAg8ZKKBDifa9GQLj3Ysg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550023; c=relaxed/simple; bh=pABCKqelu9t82yLPP2W9f2r6BBfN6Gi3ZEUXzDSPH/A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ox1X7m5t49gKsHFfIAvALFLg9rvFZRQGTS0mQhnXXCbTXekImw55OnCrDv9l4C+T2QRapsaLh/D+NaISjjQSe/7p4jdKaAhgAf1X8b6vzROvTxmF3ciL3qG58/7zeMLhenCMLWaxFCGyqDR+fDkxrSRt7EWKjxeRlANZH9F0eZs= 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=YT6VcpoH; arc=none smtp.client-ip=198.175.65.14 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="YT6VcpoH" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550022; x=1810086022; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=pABCKqelu9t82yLPP2W9f2r6BBfN6Gi3ZEUXzDSPH/A=; b=YT6VcpoHTYsYUb+1Ncu+G3HpvorLOZwzJC4TpwjG+N2sppTZVnrw7ePQ EErpXhuICpagQnkuRC+g/zEtsx/mfRn5AU2pQCuft4wJNrCpa0YFInn5H /BE8OMJyFNDfUjLgFQFkA67L857ALAL0I/nd8tmgO0uNe1VP6YykLlYl3 TOZCOYwJ8JYONDHeKtrFIh/biIatIT+vWbaKIyVwryrGYvRWiVOZ9qE1N zUOzekxS15OMVvIR6N6cg4f3ibRy1h5GPnmo07acb4cK5SfWKS9oelOwM zPJbk84PAChdS8aY309R3zqEWZ675N5SKRWOCrPbT+PW8WyKospuvtio1 Q==; X-CSE-ConnectionGUID: eWG8qhdVTTm6lUTENfD6XA== X-CSE-MsgGUID: inRCNv7CSFG37R2rKItACA== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322100" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322100" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:19 -0700 X-CSE-ConnectionGUID: c3VkMGh3QBWka8MSP0CU0w== X-CSE-MsgGUID: zDDU+9PjSH2BMRnQlhd+ow== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572740" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:16 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 01/21] KVM: VMX: Macrofy GPR swapping in __vmx_vcpu_run() Date: Tue, 12 May 2026 01:14:42 +0000 Message-ID: <20260512011502.53072-2-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-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" Convert the repeated register save/restore sequences into macros to simplify the VM entry code. This can also make it easier to extend for additional registers. Reuse the previously deprecated macros in inst.h by moving them into KVM, and remove unused ones there. No functional change intended. Suggested-by: Paolo Bonzini Cc: x86@kernel.org Signed-off-by: Chang S. Bae Link: https://lore.kernel.org/6e67df0e-e5f0-43f5-aa86-22e8b01b75d2@redhat.c= om --- V3 -> V4: * Move inst.h into KVM (Paolo) * Generalize macros to cover all GPRs (Paolo) Dependency: Based on Paolo's SPEC_CTRL rework, currently at https://git.kernel.org/pub/scm/virt/kvm/kvm.git/log/?h=3Dqueue --- arch/x86/{include/asm =3D> kvm}/inst.h | 38 ++++-------- arch/x86/kvm/svm/vmenter.S | 2 - arch/x86/kvm/vmenter.h | 43 ++++++++++++++ arch/x86/kvm/vmx/vmenter.S | 89 +++++++--------------------- 4 files changed, 74 insertions(+), 98 deletions(-) rename arch/x86/{include/asm =3D> kvm}/inst.h (67%) diff --git a/arch/x86/include/asm/inst.h b/arch/x86/kvm/inst.h similarity index 67% rename from arch/x86/include/asm/inst.h rename to arch/x86/kvm/inst.h index e48a00b3311d..3a878850ea20 100644 --- a/arch/x86/include/asm/inst.h +++ b/arch/x86/kvm/inst.h @@ -1,19 +1,15 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Generate .byte code for some instructions not supported by old - * binutils. + * Convert register names to their sizes and the indices used when + * encoding instructions. */ -#ifndef X86_ASM_INST_H -#define X86_ASM_INST_H +#ifndef X86_KVM_INST_H +#define X86_KVM_INST_H =20 #ifdef __ASSEMBLER__ =20 #define REG_NUM_INVALID 100 =20 -#define REG_TYPE_R32 0 -#define REG_TYPE_R64 1 -#define REG_TYPE_INVALID 100 - .macro R32_NUM opd r32 \opd =3D REG_NUM_INVALID .ifc \r32,%eax @@ -122,27 +118,15 @@ #endif .endm =20 - .macro REG_TYPE type reg - R32_NUM reg_type_r32 \reg - R64_NUM reg_type_r64 \reg - .if reg_type_r64 <> REG_NUM_INVALID - \type =3D REG_TYPE_R64 - .elseif reg_type_r32 <> REG_NUM_INVALID - \type =3D REG_TYPE_R32 - .else - \type =3D REG_TYPE_INVALID - .endif - .endm +.macro REG_NUM reg_num reg +#ifdef CONFIG_X86_64 + R64_NUM \reg_num \reg +#else + R32_NUM \reg_num \reg +#endif +.endm =20 - .macro PFX_REX opd1 opd2 W=3D0 - .if ((\opd1 | \opd2) & 8) || \W - .byte 0x40 | ((\opd1 & 8) >> 3) | ((\opd2 & 8) >> 1) | (\W << 3) - .endif - .endm =20 - .macro MODRM mod opd1 opd2 - .byte \mod | (\opd1 & 7) | ((\opd2 & 7) << 3) - .endm #endif =20 #endif diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S index f523d9e49839..0bad9707d219 100644 --- a/arch/x86/kvm/svm/vmenter.S +++ b/arch/x86/kvm/svm/vmenter.S @@ -9,8 +9,6 @@ #include "kvm-asm-offsets.h" #include "vmenter.h" =20 -#define WORD_SIZE (BITS_PER_LONG / 8) - /* Intentionally omit RAX as it's context switched by hardware */ #define VCPU_RCX (SVM_vcpu_arch_regs + __VCPU_REGS_RCX * WORD_SIZE) #define VCPU_RDX (SVM_vcpu_arch_regs + __VCPU_REGS_RDX * WORD_SIZE) diff --git a/arch/x86/kvm/vmenter.h b/arch/x86/kvm/vmenter.h index ba3f71449c62..a68020254a8d 100644 --- a/arch/x86/kvm/vmenter.h +++ b/arch/x86/kvm/vmenter.h @@ -2,6 +2,8 @@ #ifndef __KVM_X86_VMENTER_H #define __KVM_X86_VMENTER_H =20 +#include "inst.h" + #define KVM_ENTER_VMRESUME BIT(0) #define KVM_ENTER_SAVE_SPEC_CTRL BIT(1) #define KVM_ENTER_CLEAR_CPU_BUFFERS_FOR_MMIO BIT(2) @@ -76,5 +78,46 @@ wrmsr .endm =20 +#define WORD_SIZE (BITS_PER_LONG / 8) + +.macro LOAD_REGS src:req, regs_ofs:req, regs:vararg +.irp reg, \regs + REG_NUM reg_num \reg + .if reg_num <> REG_NUM_INVALID + mov (\regs_ofs + reg_num * WORD_SIZE)(\src), \reg + .else + .err invalid register \reg + .endif +.endr +.endm + +.macro STORE_REGS dst:req, regs_ofs:req, regs:vararg +.irp reg, \regs + REG_NUM reg_num \reg + .if reg_num <> REG_NUM_INVALID + mov \reg, (\regs_ofs + reg_num * WORD_SIZE)(\dst) + .else + .err invalid register \reg + .endif +.endr +.endm + +.macro POP_REGS dst:req, regs_ofs:req, regs:vararg +.irp reg, \regs + REG_NUM reg_num \reg + .if reg_num <> REG_NUM_INVALID + pop (\regs_ofs + reg_num * WORD_SIZE)(\dst) + .else + .err invalid register \reg + .endif +.endr +.endm + +.macro CLEAR_REGS regs:vararg +.irp reg, \regs + xorl \reg, \reg +.endr +.endm + #endif /* __ASSEMBLER__ */ #endif /* __KVM_X86_VMENTER_H */ diff --git a/arch/x86/kvm/vmx/vmenter.S b/arch/x86/kvm/vmx/vmenter.S index 7e4dc17fc0b8..4b7aaa7430fb 100644 --- a/arch/x86/kvm/vmx/vmenter.S +++ b/arch/x86/kvm/vmx/vmenter.S @@ -2,35 +2,12 @@ #include #include #include -#include #include #include #include #include "kvm-asm-offsets.h" #include "vmenter.h" =20 -#define WORD_SIZE (BITS_PER_LONG / 8) - -#define VCPU_RAX (VMX_vcpu_arch_regs + __VCPU_REGS_RAX * WORD_SIZE) -#define VCPU_RCX (VMX_vcpu_arch_regs + __VCPU_REGS_RCX * WORD_SIZE) -#define VCPU_RDX (VMX_vcpu_arch_regs + __VCPU_REGS_RDX * WORD_SIZE) -#define VCPU_RBX (VMX_vcpu_arch_regs + __VCPU_REGS_RBX * WORD_SIZE) -/* Intentionally omit RSP as it's context switched by hardware */ -#define VCPU_RBP (VMX_vcpu_arch_regs + __VCPU_REGS_RBP * WORD_SIZE) -#define VCPU_RSI (VMX_vcpu_arch_regs + __VCPU_REGS_RSI * WORD_SIZE) -#define VCPU_RDI (VMX_vcpu_arch_regs + __VCPU_REGS_RDI * WORD_SIZE) - -#ifdef CONFIG_X86_64 -#define VCPU_R8 (VMX_vcpu_arch_regs + __VCPU_REGS_R8 * WORD_SIZE) -#define VCPU_R9 (VMX_vcpu_arch_regs + __VCPU_REGS_R9 * WORD_SIZE) -#define VCPU_R10 (VMX_vcpu_arch_regs + __VCPU_REGS_R10 * WORD_SIZE) -#define VCPU_R11 (VMX_vcpu_arch_regs + __VCPU_REGS_R11 * WORD_SIZE) -#define VCPU_R12 (VMX_vcpu_arch_regs + __VCPU_REGS_R12 * WORD_SIZE) -#define VCPU_R13 (VMX_vcpu_arch_regs + __VCPU_REGS_R13 * WORD_SIZE) -#define VCPU_R14 (VMX_vcpu_arch_regs + __VCPU_REGS_R14 * WORD_SIZE) -#define VCPU_R15 (VMX_vcpu_arch_regs + __VCPU_REGS_R15 * WORD_SIZE) -#endif - .macro VMX_DO_EVENT_IRQOFF call_insn call_target /* * Unconditionally create a stack frame, getting the correct RSP on the @@ -114,25 +91,18 @@ SYM_FUNC_START(__vmx_vcpu_run) * an LFENCE to stop speculation from skipping the wrmsr. */ =20 - /* Load guest registers. Don't clobber flags. */ - mov VCPU_RAX(%_ASM_DI), %_ASM_AX - mov VCPU_RCX(%_ASM_DI), %_ASM_CX - mov VCPU_RDX(%_ASM_DI), %_ASM_DX - mov VCPU_RBX(%_ASM_DI), %_ASM_BX - mov VCPU_RBP(%_ASM_DI), %_ASM_BP - mov VCPU_RSI(%_ASM_DI), %_ASM_SI + /* + * Load guest registers. Don't clobber flags. Intentionally omit + * %_ASM_SP as it's context switched by hardware + */ + LOAD_REGS %_ASM_DI, VMX_vcpu_arch_regs, \ + %_ASM_AX, %_ASM_CX, %_ASM_DX, %_ASM_BX, %_ASM_BP, %_ASM_SI #ifdef CONFIG_X86_64 - mov VCPU_R8 (%_ASM_DI), %r8 - mov VCPU_R9 (%_ASM_DI), %r9 - mov VCPU_R10(%_ASM_DI), %r10 - mov VCPU_R11(%_ASM_DI), %r11 - mov VCPU_R12(%_ASM_DI), %r12 - mov VCPU_R13(%_ASM_DI), %r13 - mov VCPU_R14(%_ASM_DI), %r14 - mov VCPU_R15(%_ASM_DI), %r15 + LOAD_REGS %_ASM_DI, VMX_vcpu_arch_regs, \ + %r8, %r9, %r10, %r11, %r12, %r13, %r14, %r15 #endif /* Load guest RDI. This kills the @vmx pointer! */ - mov VCPU_RDI(%_ASM_DI), %_ASM_DI + LOAD_REGS %_ASM_DI, VMX_vcpu_arch_regs, %_ASM_DI =20 /* * Note, ALTERNATIVE_2 works in reverse order. If CLEAR_CPU_BUF_VM is @@ -187,23 +157,16 @@ SYM_INNER_LABEL_ALIGN(vmx_vmexit, SYM_L_GLOBAL) /* Reload @vmx to RDI. */ mov 2*WORD_SIZE(%_ASM_SP), %_ASM_DI =20 - /* Save all guest registers, including RDI from the stack */ - mov %_ASM_AX, VCPU_RAX(%_ASM_DI) - mov %_ASM_CX, VCPU_RCX(%_ASM_DI) - mov %_ASM_DX, VCPU_RDX(%_ASM_DI) - mov %_ASM_BX, VCPU_RBX(%_ASM_DI) - mov %_ASM_BP, VCPU_RBP(%_ASM_DI) - mov %_ASM_SI, VCPU_RSI(%_ASM_DI) - pop VCPU_RDI(%_ASM_DI) + /* + * Save all guest registers, including RDI from the stack. Intentionally + * omit %_ASM_SP as it's context switched by hardware + */ + STORE_REGS %_ASM_DI, VMX_vcpu_arch_regs, \ + %_ASM_AX, %_ASM_CX, %_ASM_DX, %_ASM_BX, %_ASM_BP, %_ASM_SI + POP_REGS %_ASM_DI, VMX_vcpu_arch_regs, %_ASM_DI #ifdef CONFIG_X86_64 - mov %r8, VCPU_R8 (%_ASM_DI) - mov %r9, VCPU_R9 (%_ASM_DI) - mov %r10, VCPU_R10(%_ASM_DI) - mov %r11, VCPU_R11(%_ASM_DI) - mov %r12, VCPU_R12(%_ASM_DI) - mov %r13, VCPU_R13(%_ASM_DI) - mov %r14, VCPU_R14(%_ASM_DI) - mov %r15, VCPU_R15(%_ASM_DI) + STORE_REGS %_ASM_DI, VMX_vcpu_arch_regs, \ + %r8, %r9, %r10, %r11, %r12, %r13, %r14, %r15 #endif =20 /* Clear return value to indicate VM-Exit (as opposed to VM-Fail). */ @@ -220,21 +183,9 @@ SYM_INNER_LABEL_ALIGN(vmx_vmexit, SYM_L_GLOBAL) * VM-Exit and RBX is explicitly loaded with 0 or 1 to hold the return * value. */ - xor %eax, %eax - xor %ecx, %ecx - xor %edx, %edx - xor %ebp, %ebp - xor %esi, %esi - xor %edi, %edi + CLEAR_REGS %eax, %ecx, %edx, %ebp, %esi, %edi #ifdef CONFIG_X86_64 - xor %r8d, %r8d - xor %r9d, %r9d - xor %r10d, %r10d - xor %r11d, %r11d - xor %r12d, %r12d - xor %r13d, %r13d - xor %r14d, %r14d - xor %r15d, %r15d + CLEAR_REGS %r8d, %r9d, %r10d, %r11d, %r12d, %r13d, %r14d, %r15d #endif =20 /* --=20 2.51.0 From nobody Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 9D052282F0B; Tue, 12 May 2026 01:40:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550024; cv=none; b=PR7lsl6lU3163jlDOUCgimCIDi49iWXOIXO5GujM6BgK5y/tWszq6CmcJdi7sQrH1CmVo7G3/j9bx3uGV73zPGva1jT/g+2n82AACavauN3wNFGlrjtg9T0DVDMUwGgh2aYoLRpv/PLUxyCGkfonuW2nrEmjJ0lIg5JDtO4d8vE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550024; c=relaxed/simple; bh=CuNhR80TgKSoL7gKCP7RKKN445VjKhu1x3xRLOfFPeQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nRZ/iUUSVfXmASmvyNor927ECepqvDIATUm//7/QTRLIRz0Vxa74eTQftHeOqPBmC/dplDje0lTCRop9n7pwKR9HBKgOQ6U4eHQDBFjCuakfp9mL/4vWEOoqVQRVALzh1P+iSxDnaU8pLWSZIFSlYYOL+XRXbVIgb89z2W1cGE4= 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=jzxDXXgn; arc=none smtp.client-ip=198.175.65.14 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="jzxDXXgn" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550023; x=1810086023; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=CuNhR80TgKSoL7gKCP7RKKN445VjKhu1x3xRLOfFPeQ=; b=jzxDXXgn1LpLKlZk/w3w68ksUTOsenp/zFShNHBGMd7lt7zXAalPeA6E jOrkS65hWtIxeqQQCuhBkz8fgrtP/sL+ABhXgNWsa/Yz2ahHr5tnfibsB ILD4JpdaA8qN910nMJTNE3qlD2+BkiWLA8vT1Zapt1jyEZ6yAPnyL0U1M iQft56XMjvTmuUrFKB3np3/MOQITD0tcy0Bgr6+JhJnU0dbMB+qeh2Tab ImC5/osELjWRhBFFo10JFAtAXcAbtAouefDftcrNxchJY6ybXrIik1uEt HvTi3vMHBdE+MR2w+nss869HmyQ+a0yPMmWjIgVDyTZ/E8d/IOSfypzYO g==; X-CSE-ConnectionGUID: aezIfkKVRPSeKLPYRmlLfQ== X-CSE-MsgGUID: OsUEa2SCQGyi/4/a8FmoGw== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322104" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322104" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:19 -0700 X-CSE-ConnectionGUID: TVw0kgP4Rqqmyq0nODkF9w== X-CSE-MsgGUID: ekAK8volRIyBbrf83s4Xiw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572742" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:18 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 02/21] KVM: SVM: Macrofy GPR swapping in __svm_vcpu_run() Date: Tue, 12 May 2026 01:14:43 +0000 Message-ID: <20260512011502.53072-3-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-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" Convert the register save/restore sequences in the SVM entry into macros, following the VMX code. Drop the now-redundant register offset defines. No functional change intended. Signed-off-by: Chang S. Bae --- V3 -> V4: Cover all GPRs (Paolo) --- arch/x86/kvm/svm/vmenter.S | 83 +++++++++----------------------------- 1 file changed, 19 insertions(+), 64 deletions(-) diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S index 0bad9707d219..4b20aadbb741 100644 --- a/arch/x86/kvm/svm/vmenter.S +++ b/arch/x86/kvm/svm/vmenter.S @@ -9,26 +9,6 @@ #include "kvm-asm-offsets.h" #include "vmenter.h" =20 -/* Intentionally omit RAX as it's context switched by hardware */ -#define VCPU_RCX (SVM_vcpu_arch_regs + __VCPU_REGS_RCX * WORD_SIZE) -#define VCPU_RDX (SVM_vcpu_arch_regs + __VCPU_REGS_RDX * WORD_SIZE) -#define VCPU_RBX (SVM_vcpu_arch_regs + __VCPU_REGS_RBX * WORD_SIZE) -/* Intentionally omit RSP as it's context switched by hardware */ -#define VCPU_RBP (SVM_vcpu_arch_regs + __VCPU_REGS_RBP * WORD_SIZE) -#define VCPU_RSI (SVM_vcpu_arch_regs + __VCPU_REGS_RSI * WORD_SIZE) -#define VCPU_RDI (SVM_vcpu_arch_regs + __VCPU_REGS_RDI * WORD_SIZE) - -#ifdef CONFIG_X86_64 -#define VCPU_R8 (SVM_vcpu_arch_regs + __VCPU_REGS_R8 * WORD_SIZE) -#define VCPU_R9 (SVM_vcpu_arch_regs + __VCPU_REGS_R9 * WORD_SIZE) -#define VCPU_R10 (SVM_vcpu_arch_regs + __VCPU_REGS_R10 * WORD_SIZE) -#define VCPU_R11 (SVM_vcpu_arch_regs + __VCPU_REGS_R11 * WORD_SIZE) -#define VCPU_R12 (SVM_vcpu_arch_regs + __VCPU_REGS_R12 * WORD_SIZE) -#define VCPU_R13 (SVM_vcpu_arch_regs + __VCPU_REGS_R13 * WORD_SIZE) -#define VCPU_R14 (SVM_vcpu_arch_regs + __VCPU_REGS_R14 * WORD_SIZE) -#define VCPU_R15 (SVM_vcpu_arch_regs + __VCPU_REGS_R15 * WORD_SIZE) -#endif - #define SVM_vmcb01_pa (SVM_vmcb01 + KVM_VMCB_pa) =20 .section .noinstr.text, "ax" @@ -109,23 +89,17 @@ SYM_FUNC_START(__svm_vcpu_run) mov SVM_current_vmcb(%_ASM_DI), %_ASM_AX mov KVM_VMCB_pa(%_ASM_AX), %_ASM_AX =20 - /* Load guest registers. */ - mov VCPU_RCX(%_ASM_DI), %_ASM_CX - mov VCPU_RDX(%_ASM_DI), %_ASM_DX - mov VCPU_RBX(%_ASM_DI), %_ASM_BX - mov VCPU_RBP(%_ASM_DI), %_ASM_BP - mov VCPU_RSI(%_ASM_DI), %_ASM_SI + /* + * Load guest registers. Intentionally omit %_ASM_AX and %_ASM_SP as + * context switched by hardware + */ + LOAD_REGS %_ASM_DI, SVM_vcpu_arch_regs, \ + %_ASM_CX, %_ASM_DX, %_ASM_BX, %_ASM_BP, %_ASM_SI #ifdef CONFIG_X86_64 - mov VCPU_R8 (%_ASM_DI), %r8 - mov VCPU_R9 (%_ASM_DI), %r9 - mov VCPU_R10(%_ASM_DI), %r10 - mov VCPU_R11(%_ASM_DI), %r11 - mov VCPU_R12(%_ASM_DI), %r12 - mov VCPU_R13(%_ASM_DI), %r13 - mov VCPU_R14(%_ASM_DI), %r14 - mov VCPU_R15(%_ASM_DI), %r15 + LOAD_REGS %_ASM_DI, SVM_vcpu_arch_regs, \ + %r8, %r9, %r10, %r11, %r12, %r13, %r14, %r15 #endif - mov VCPU_RDI(%_ASM_DI), %_ASM_DI + LOAD_REGS %_ASM_DI, SVM_vcpu_arch_regs, %_ASM_DI =20 /* Clobbers EFLAGS.ZF */ SVM_CLEAR_CPU_BUFFERS @@ -136,22 +110,15 @@ SYM_FUNC_START(__svm_vcpu_run) /* Pop @svm to RAX while it's the only available register. */ pop %_ASM_AX =20 - /* Save all guest registers. */ - mov %_ASM_CX, VCPU_RCX(%_ASM_AX) - mov %_ASM_DX, VCPU_RDX(%_ASM_AX) - mov %_ASM_BX, VCPU_RBX(%_ASM_AX) - mov %_ASM_BP, VCPU_RBP(%_ASM_AX) - mov %_ASM_SI, VCPU_RSI(%_ASM_AX) - mov %_ASM_DI, VCPU_RDI(%_ASM_AX) + /* + * Save all guest registers. Intentionally omit %_ASM_AX and %_ASM_SP as + * context switched by hardware + */ + STORE_REGS %_ASM_AX, SVM_vcpu_arch_regs, \ + %_ASM_CX, %_ASM_DX, %_ASM_BX, %_ASM_BP, %_ASM_SI, %_ASM_DI #ifdef CONFIG_X86_64 - mov %r8, VCPU_R8 (%_ASM_AX) - mov %r9, VCPU_R9 (%_ASM_AX) - mov %r10, VCPU_R10(%_ASM_AX) - mov %r11, VCPU_R11(%_ASM_AX) - mov %r12, VCPU_R12(%_ASM_AX) - mov %r13, VCPU_R13(%_ASM_AX) - mov %r14, VCPU_R14(%_ASM_AX) - mov %r15, VCPU_R15(%_ASM_AX) + STORE_REGS %_ASM_AX, SVM_vcpu_arch_regs, \ + %r8, %r9, %r10, %r11, %r12, %r13, %r14, %r15 #endif =20 /* @svm can stay in RDI from now on. */ @@ -194,21 +161,9 @@ SYM_FUNC_START(__svm_vcpu_run) * free. RSP and RAX are exempt as they are restored by hardware * during VM-Exit. */ - xor %ecx, %ecx - xor %edx, %edx - xor %ebx, %ebx - xor %ebp, %ebp - xor %esi, %esi - xor %edi, %edi + CLEAR_REGS %ecx, %edx, %ebx, %ebp, %esi, %edi #ifdef CONFIG_X86_64 - xor %r8d, %r8d - xor %r9d, %r9d - xor %r10d, %r10d - xor %r11d, %r11d - xor %r12d, %r12d - xor %r13d, %r13d - xor %r14d, %r14d - xor %r15d, %r15d + CLEAR_REGS %r8d, %r9d, %r10d, %r11d, %r12d, %r13d, %r14d, %r15d #endif =20 /* "Pop" @enter_flags. */ --=20 2.51.0 From nobody Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 E571228F948; Tue, 12 May 2026 01:40:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550024; cv=none; b=OsT88oQZ8TRPdz6+s7G/gKM//M6sBfGq8x2j3IeKs5QyufK6wx9GHHI+ucRVqNGiCnNhHLwgJmbvgH8QbbjqF+oECK8oB/CsojWwnQuLuZdY8+iv263RuGAq4YlJDw8YcPbmIWz/qr5/Q4DlVafwWyvJisQcOF9i5PPOV26DuQI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550024; c=relaxed/simple; bh=kAu4T49LD7VwdBtT0T7G0uDEz/d6M3rIZ/6tJcIopWM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XFJ+uCCu6rrD5SvmSmPRae9K2gexBevxlIBSizRU1OL0fkRzCSfeAy4S/kb3bJX9m+7lcx0iUGACVK8vIFDMmdkP6DIUtq1uwStayaogGE6WXo2J3S3TUedyjAZTxLAo7G8GKkSXxCroBYgb8Fws1sd1TyrXDHfI8BS6a84yQUI= 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=hm6XamUQ; arc=none smtp.client-ip=198.175.65.14 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="hm6XamUQ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550023; x=1810086023; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=kAu4T49LD7VwdBtT0T7G0uDEz/d6M3rIZ/6tJcIopWM=; b=hm6XamUQvS08Hm4qs3NgYpzNfqZ+pkwMuAizUNuBglcj5TVmdw8QzePo Ao37FPJh3cTKqSYGQDGxrb+NKOQGaeJoE/PFJJvAHC5k0S0oNy7yR+kcp JTycT8cq/CxX8JHbthDVNMMZO1aLDnXHf+X1nSVF51Ez2FyHY8+ZEIWZu xzU5iTosMAxjyTxxCsA58fpvRrwttt9UPVPw6TvlQ0nelY8cxkvmVWSMl UfziR1gfA4Pw8lzUkb/hbwLsTtufFYUu5NzUH1yuBjplxVEz7P4ZcU11e b85Q62W8KSuT0vSWwLxWMUFXtoI13kvs3JhrT+VtsPWIK/j/WUm09XceF Q==; X-CSE-ConnectionGUID: BcqAJDDHRUa4KEaAxFDzWg== X-CSE-MsgGUID: RrkjCMb7SXqw/NETJs2xWQ== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322107" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322107" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:20 -0700 X-CSE-ConnectionGUID: k5sdgBHBRmaZ3J4X8bvmIg== X-CSE-MsgGUID: gG6WdW6lRYCSssfZnxtFYg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572748" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:19 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 03/21] KVM: SEV: Macrofy GPR swapping in __svm_sev_es_vcpu_run() Date: Tue, 12 May 2026 01:14:44 +0000 Message-ID: <20260512011502.53072-4-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-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" Convert the SEV-ES entry code to use macros for saving guest GPRs, following VMX/SVM paths. Drop now-unused register offsets and __VCPU_REGS_* defines. No functional change intended. Signed-off-by: Chang S. Bae --- V3 -> V4: Cover all GPRs (Paolo) --- arch/x86/include/asm/kvm_host.h | 33 ++++++++++++++-------------- arch/x86/include/asm/kvm_vcpu_regs.h | 25 --------------------- arch/x86/kvm/svm/vmenter.S | 22 ++----------------- 3 files changed, 18 insertions(+), 62 deletions(-) delete mode 100644 arch/x86/include/asm/kvm_vcpu_regs.h diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index 8a53ca619570..a70ed9a6a4fa 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -39,7 +39,6 @@ #include #include #include -#include #include =20 #include @@ -173,23 +172,23 @@ #define ASYNC_PF_PER_VCPU 64 =20 enum kvm_reg { - VCPU_REGS_RAX =3D __VCPU_REGS_RAX, - VCPU_REGS_RCX =3D __VCPU_REGS_RCX, - VCPU_REGS_RDX =3D __VCPU_REGS_RDX, - VCPU_REGS_RBX =3D __VCPU_REGS_RBX, - VCPU_REGS_RSP =3D __VCPU_REGS_RSP, - VCPU_REGS_RBP =3D __VCPU_REGS_RBP, - VCPU_REGS_RSI =3D __VCPU_REGS_RSI, - VCPU_REGS_RDI =3D __VCPU_REGS_RDI, + VCPU_REGS_RAX, + VCPU_REGS_RCX, + VCPU_REGS_RDX, + VCPU_REGS_RBX, + VCPU_REGS_RSP, + VCPU_REGS_RBP, + VCPU_REGS_RSI, + VCPU_REGS_RDI, #ifdef CONFIG_X86_64 - VCPU_REGS_R8 =3D __VCPU_REGS_R8, - VCPU_REGS_R9 =3D __VCPU_REGS_R9, - VCPU_REGS_R10 =3D __VCPU_REGS_R10, - VCPU_REGS_R11 =3D __VCPU_REGS_R11, - VCPU_REGS_R12 =3D __VCPU_REGS_R12, - VCPU_REGS_R13 =3D __VCPU_REGS_R13, - VCPU_REGS_R14 =3D __VCPU_REGS_R14, - VCPU_REGS_R15 =3D __VCPU_REGS_R15, + VCPU_REGS_R8, + VCPU_REGS_R9, + VCPU_REGS_R10, + VCPU_REGS_R11, + VCPU_REGS_R12, + VCPU_REGS_R13, + VCPU_REGS_R14, + VCPU_REGS_R15, #endif NR_VCPU_GENERAL_PURPOSE_REGS, =20 diff --git a/arch/x86/include/asm/kvm_vcpu_regs.h b/arch/x86/include/asm/kv= m_vcpu_regs.h deleted file mode 100644 index 1af2cb59233b..000000000000 --- a/arch/x86/include/asm/kvm_vcpu_regs.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_X86_KVM_VCPU_REGS_H -#define _ASM_X86_KVM_VCPU_REGS_H - -#define __VCPU_REGS_RAX 0 -#define __VCPU_REGS_RCX 1 -#define __VCPU_REGS_RDX 2 -#define __VCPU_REGS_RBX 3 -#define __VCPU_REGS_RSP 4 -#define __VCPU_REGS_RBP 5 -#define __VCPU_REGS_RSI 6 -#define __VCPU_REGS_RDI 7 - -#ifdef CONFIG_X86_64 -#define __VCPU_REGS_R8 8 -#define __VCPU_REGS_R9 9 -#define __VCPU_REGS_R10 10 -#define __VCPU_REGS_R11 11 -#define __VCPU_REGS_R12 12 -#define __VCPU_REGS_R13 13 -#define __VCPU_REGS_R14 14 -#define __VCPU_REGS_R15 15 -#endif - -#endif /* _ASM_X86_KVM_VCPU_REGS_H */ diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S index 4b20aadbb741..99701892f8ec 100644 --- a/arch/x86/kvm/svm/vmenter.S +++ b/arch/x86/kvm/svm/vmenter.S @@ -4,7 +4,6 @@ #include #include #include -#include #include #include "kvm-asm-offsets.h" #include "vmenter.h" @@ -212,18 +211,7 @@ SYM_FUNC_END(__svm_vcpu_run) =20 #ifdef CONFIG_KVM_AMD_SEV =20 - -#ifdef CONFIG_X86_64 #define SEV_ES_GPRS_BASE 0x300 -#define SEV_ES_RBX (SEV_ES_GPRS_BASE + __VCPU_REGS_RBX * WORD_SIZE) -#define SEV_ES_RBP (SEV_ES_GPRS_BASE + __VCPU_REGS_RBP * WORD_SIZE) -#define SEV_ES_RSI (SEV_ES_GPRS_BASE + __VCPU_REGS_RSI * WORD_SIZE) -#define SEV_ES_RDI (SEV_ES_GPRS_BASE + __VCPU_REGS_RDI * WORD_SIZE) -#define SEV_ES_R12 (SEV_ES_GPRS_BASE + __VCPU_REGS_R12 * WORD_SIZE) -#define SEV_ES_R13 (SEV_ES_GPRS_BASE + __VCPU_REGS_R13 * WORD_SIZE) -#define SEV_ES_R14 (SEV_ES_GPRS_BASE + __VCPU_REGS_R14 * WORD_SIZE) -#define SEV_ES_R15 (SEV_ES_GPRS_BASE + __VCPU_REGS_R15 * WORD_SIZE) -#endif =20 /** * __svm_sev_es_vcpu_run - Run a SEV-ES vCPU via a transition to SVM guest= mode @@ -238,19 +226,13 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run) * Except for RAX and RSP, all GPRs are restored on #VMEXIT, but not * saved on VMRUN. */ - mov %rbp, SEV_ES_RBP (%rdx) - mov %r15, SEV_ES_R15 (%rdx) - mov %r14, SEV_ES_R14 (%rdx) - mov %r13, SEV_ES_R13 (%rdx) - mov %r12, SEV_ES_R12 (%rdx) - mov %rbx, SEV_ES_RBX (%rdx) + STORE_REGS %rdx, SEV_ES_GPRS_BASE, %rbp, %r15, %r14, %r13, %r12, %rbx =20 /* * Save volatile registers that hold arguments that are needed after * #VMEXIT (RDI=3D@svm and RSI=3D@enter_flags). */ - mov %rdi, SEV_ES_RDI (%rdx) - mov %rsi, SEV_ES_RSI (%rdx) + STORE_REGS %rdx, SEV_ES_GPRS_BASE, %rdi, %rsi =20 /* Clobbers RAX, RCX, and RDX (@hostsa), consumes RDI (@svm). */ RESTORE_GUEST_SPEC_CTRL --=20 2.51.0 From nobody Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 133B82989B0; Tue, 12 May 2026 01:40:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550025; cv=none; b=uCDHpjbNx/WPWUAglSksnKgGx5xRBEOcl5qVUZ1GyqRDkP2dStq9s1tgzyu18hUZ/XS6YdvDUZpOOpASpuEOfvQPWV8GQgoVMOkOvftgHT/trJkb0RlYTJKs623a1gOclEePyovHyY9VXHzMV4C1TT6n7XkKxd/jq22pSw8tTcY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550025; c=relaxed/simple; bh=2TGAuMuXZXBMg+CMihQ+9JLMd8mCwZ+D0TVpxQ1UN/8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eY8ZNXg1nm+uvLPjiItDBqJkU3BMmJLxm3REkMz5rAlm30Z8gdKypRc6OtUH/mPBWG1HmzHFlj1o47s1B/wsXyYdjyPOW5NIF49QMM/wDyr6X4u3Tq7bv2FKMURyx5vOKI3Q1n1pJiZlKNX+30zOhy/vMwnnk/OxOwlJUVwzWII= 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=l22rjVLA; arc=none smtp.client-ip=198.175.65.14 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="l22rjVLA" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550023; x=1810086023; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=2TGAuMuXZXBMg+CMihQ+9JLMd8mCwZ+D0TVpxQ1UN/8=; b=l22rjVLAt8Nw5yjZA1f5Ke2S4EoEvpao0GJ5MvfaQ0qrlwLERzFqva37 d0m2xi1iyGhxEVxtjykyeU7FM5iNiH34wMQWi+tLcMchvI4iqM7ZuzimB 7fAe82EAUSz15sZTMQKAwsbFhkPHZOqzoEBOLxXu40GsCdz6FqT8VLmDG TiuCrNJBI3K0qczAj4vfBS3+y4En/AHEpaWyK7S1LiiONaDzZh0S3xloj zH0MshQjwPgsC5kHi91c5N3YmDpVvqZ7fmLgLWo4NSJKsUX0HqnsKc4wa erNU0zrUzp4xPFgrjCh4Gfjv1ilWDtiuO2qQg44damQVA+jZt7JVCFnOF w==; X-CSE-ConnectionGUID: +zreieEQQ2i/2v8P36KnOA== X-CSE-MsgGUID: zvp3YzQQTJKjwJRQI9MfhQ== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322113" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322113" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:21 -0700 X-CSE-ConnectionGUID: qpRTF3u4QhmarKQOQX2gSg== X-CSE-MsgGUID: ofe+mE1bSmS8qmk5LpCQ2A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572752" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:20 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 04/21] KVM: x86: Extend VCPU registers for EGPRs Date: Tue, 12 May 2026 01:14:45 +0000 Message-ID: <20260512011502.53072-5-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend the storage to include extended general-purpose registers (EGPRs: R16-R31) when CONFIG_KVM_APX=3Dy. This option is for VMX only. Although EGPR state is XSAVE-managed, and thus could be stored in the guest fpstate, VCPU storage provides a more convenient and efficient access path for KVM. Suggested-by: Sean Christopherson Signed-off-by: Chang S. Bae Link: https://lore.kernel.org/abL8SW5JS1aV5goa@google.com --- Dependency: Based on Sean's APX preparatory series https://lore.kernel.org/20260409224236.2021562-1-seanjc@google.= com/ --- arch/x86/include/asm/kvm_host.h | 18 ++++++++++++++++++ arch/x86/kvm/Kconfig | 4 ++++ 2 files changed, 22 insertions(+) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index a70ed9a6a4fa..76c91efca722 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -189,6 +189,24 @@ enum kvm_reg { VCPU_REGS_R13, VCPU_REGS_R14, VCPU_REGS_R15, +#endif +#ifdef CONFIG_KVM_APX + VCPU_REGS_R16, + VCPU_REGS_R17, + VCPU_REGS_R18, + VCPU_REGS_R19, + VCPU_REGS_R20, + VCPU_REGS_R21, + VCPU_REGS_R22, + VCPU_REGS_R23, + VCPU_REGS_R24, + VCPU_REGS_R25, + VCPU_REGS_R26, + VCPU_REGS_R27, + VCPU_REGS_R28, + VCPU_REGS_R29, + VCPU_REGS_R30, + VCPU_REGS_R31, #endif NR_VCPU_GENERAL_PURPOSE_REGS, =20 diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index 801bf9e520db..f27e3f2937f0 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig @@ -93,10 +93,14 @@ config KVM_SW_PROTECTED_VM =20 If unsure, say "N". =20 +config KVM_APX + bool + config KVM_INTEL tristate "KVM for Intel (and compatible) processors support" depends on KVM && IA32_FEAT_CTL select X86_FRED if X86_64 + select KVM_APX if X86_64 help Provides support for KVM on processors equipped with Intel's VT extensions, a.k.a. Virtual Machine Extensions (VMX). --=20 2.51.0 From nobody Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 5B4242C21FD; Tue, 12 May 2026 01:40:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550026; cv=none; b=hRKkp90/Rolxej9MehcG+t6jFOIB2B8S3TDeIA9/fWF2lyNhSNhMTgKmv8XYJaDwpLH1gFzbFqBW+RTYWmXoTQhFodkY+LK62GWnvK+kzy8p4HWW7flaxB1svLFP5EIuzuHUx6puNss5LIbu17L+9R8ozowETb94ZhkX00kTPRA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550026; c=relaxed/simple; bh=tqLOlyU40BGh2J/817UFTtIxy7VEtWO968Fjv47Vt3k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cy/24dadcuAPtXFINj5YscpSl+SRIVj5BXi1MLGN3jARjm375kV0uWcXbEz1l48gco6YFdYeYxio3tVHZ+KIC8wbjhjhnx8kx/UWypIXjNpcLH7Dhlpx/HUGZuKZor31k7RZyDfiC/WVaxzDWTFDFEJpQuffjKVC6lGqcXQEBWw= 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=OqR6Jwcf; arc=none smtp.client-ip=198.175.65.14 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="OqR6Jwcf" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550025; x=1810086025; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=tqLOlyU40BGh2J/817UFTtIxy7VEtWO968Fjv47Vt3k=; b=OqR6Jwcf645EiICo7Y69DD+NoV1guqSYHombiIDKoqSexEkG7PrXG4At enygfMPJoptl6iIqrT0BM9qYQTidUzZngpn3FA/DWoen2tzTGC1wUdsZ/ 4zat5wmrhjKXT+gitMAdz2eQh24jJaXTEfjw5m+tj2NgxcyOmbJLxC/Li u1biXOVknmUIFSeykN9tdUW0i68VNu+BQPALj86XFo6XLDDt09BLjc0vG 9pWOh96FpYwQu+o1KCb0Nydct9IMD+r51E/IxuM7cHR34pHgoHd8NcT64 9Jj0Ps8MpCXPRRW09LtREnrIJfm7SlZOU9eC4pHXxX8EPkH375rWax92z Q==; X-CSE-ConnectionGUID: kvQgJ2QvSWihjSoboBLbKw== X-CSE-MsgGUID: Ttv0/wHBS6yL42pKEZ/4bA== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322118" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322118" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:22 -0700 X-CSE-ConnectionGUID: aKnjo0YOQ5mskkEURvDrKA== X-CSE-MsgGUID: 00fqAblhQlORCSQYcOdYtQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572759" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:21 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 05/21] KVM: VMX: Save guest EGPRs in VCPU cache Date: Tue, 12 May 2026 01:14:46 +0000 Message-ID: <20260512011502.53072-6-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Save and restore the guest EGPRs on VM exit/entry if the system supports Advanced Performance Extensions (APX). KVM switches XCR0 outside of the fastpath loop. As a result, there is a window of still running with guest XCR0 where any EGPR access would induce #UD. But fastpath handlers may access guest EGPRs, i.e. for exits from an immediate form of WRMSR. So it is safe to handle them in __vmx_vcpu_run(). KVM intercepts all XCR0 writes, allowing itself to track the guest XCR0 state. Pivot XCR0[APX] to conditionally handle them. This in turn makes the VM behaves architecturally aligned. If XCR0[APX] is cleared, for example, the EGPR state is preserved and will be restored when APX is re-enabled. Guard the switching path with speculation-safe control as well to avoid any mis-speculation into EGPR accesses when APX is disabled. Saving may be skipped on VM-Fail but leave it unconditional simply because that's only for the slow path. Suggested-by: Sean Christopherson Signed-off-by: Chang S. Bae Link: https://lore.kernel.org/adPRA4ZhnvbaXSn0@google.com --- V3 -> V4: Rebase on macro updates (PATCH1) with adding EGPRs to R64_NUM in = inst.h Dependency: Based on Paolo's SPEC_CTRL rework, currently at https://git.kernel.org/pub/scm/virt/kvm/kvm.git/log/?h=3Dqueue --- arch/x86/Kconfig.assembler | 5 ++++ arch/x86/kvm/Kconfig | 2 +- arch/x86/kvm/inst.h | 50 ++++++++++++++++++++++++++++++++++++++ arch/x86/kvm/vmenter.h | 1 + arch/x86/kvm/vmx/vmenter.S | 31 +++++++++++++++++++++-- arch/x86/kvm/vmx/vmx.c | 13 ++++++++++ 6 files changed, 99 insertions(+), 3 deletions(-) diff --git a/arch/x86/Kconfig.assembler b/arch/x86/Kconfig.assembler index b1c59fb0a4c9..3b41ec89468d 100644 --- a/arch/x86/Kconfig.assembler +++ b/arch/x86/Kconfig.assembler @@ -1,6 +1,11 @@ # SPDX-License-Identifier: GPL-2.0 # Copyright (C) 2020 Jason A. Donenfeld . All Rights Rese= rved. =20 +config AS_APX + def_bool $(as-instr64,xor %r16$(comma)%r16) + help + Supported by binutils >=3D 2.42 and LLVM integrated assembler >=3D V18 + config AS_WRUSS def_bool $(as-instr64,wrussq %rax$(comma)(%rbx)) help diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index f27e3f2937f0..eb71cd7e5b37 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig @@ -100,7 +100,7 @@ config KVM_INTEL tristate "KVM for Intel (and compatible) processors support" depends on KVM && IA32_FEAT_CTL select X86_FRED if X86_64 - select KVM_APX if X86_64 + select KVM_APX if X86_64 && AS_APX help Provides support for KVM on processors equipped with Intel's VT extensions, a.k.a. Virtual Machine Extensions (VMX). diff --git a/arch/x86/kvm/inst.h b/arch/x86/kvm/inst.h index 3a878850ea20..059ea4ea56f3 100644 --- a/arch/x86/kvm/inst.h +++ b/arch/x86/kvm/inst.h @@ -115,6 +115,56 @@ .ifc \r64,%r15 \opd =3D 15 .endif +#endif +#ifdef CONFIG_KVM_APX + .ifc \r64,%r16 + \opd =3D 16 + .endif + .ifc \r64,%r17 + \opd =3D 17 + .endif + .ifc \r64,%r18 + \opd =3D 18 + .endif + .ifc \r64,%r19 + \opd =3D 19 + .endif + .ifc \r64,%r20 + \opd =3D 20 + .endif + .ifc \r64,%r21 + \opd =3D 21 + .endif + .ifc \r64,%r22 + \opd =3D 22 + .endif + .ifc \r64,%r23 + \opd =3D 23 + .endif + .ifc \r64,%r24 + \opd =3D 24 + .endif + .ifc \r64,%r25 + \opd =3D 25 + .endif + .ifc \r64,%r26 + \opd =3D 26 + .endif + .ifc \r64,%r27 + \opd =3D 27 + .endif + .ifc \r64,%r28 + \opd =3D 28 + .endif + .ifc \r64,%r29 + \opd =3D 29 + .endif + .ifc \r64,%r30 + \opd =3D 30 + .endif + .ifc \r64,%r31 + \opd =3D 31 + .endif #endif .endm =20 diff --git a/arch/x86/kvm/vmenter.h b/arch/x86/kvm/vmenter.h index a68020254a8d..81bf3ccf4da5 100644 --- a/arch/x86/kvm/vmenter.h +++ b/arch/x86/kvm/vmenter.h @@ -7,6 +7,7 @@ #define KVM_ENTER_VMRESUME BIT(0) #define KVM_ENTER_SAVE_SPEC_CTRL BIT(1) #define KVM_ENTER_CLEAR_CPU_BUFFERS_FOR_MMIO BIT(2) +#define KVM_ENTER_EGPR_SWITCH BIT(3) =20 #ifdef __ASSEMBLER__ .macro RESTORE_GUEST_SPEC_CTRL_BODY guest_spec_ctrl:req, label:req diff --git a/arch/x86/kvm/vmx/vmenter.S b/arch/x86/kvm/vmx/vmenter.S index 4b7aaa7430fb..60e5669bdbab 100644 --- a/arch/x86/kvm/vmx/vmenter.S +++ b/arch/x86/kvm/vmx/vmenter.S @@ -48,6 +48,7 @@ * @flags: KVM_ENTER_VMRESUME: use VMRESUME instead of VMLAUNCH * KVM_ENTER_SAVE_SPEC_CTRL: save guest SPEC_CTRL into vmx->spec_ctrl * KVM_ENTER_CLEAR_CPU_BUFFERS_FOR_MMIO: vCPU can access host MMIO + * KVM_ENTER_EGPRS_SWITCH: load/store guest EGPRs * * Returns: * 0 on VM-Exit, 1 on VM-Fail @@ -78,6 +79,16 @@ SYM_FUNC_START(__vmx_vcpu_run) /* Reload @vmx, _ASM_ARG1 may be modified by vmx_update_host_rsp(). */ mov WORD_SIZE(%_ASM_SP), %_ASM_DI =20 +#ifdef CONFIG_KVM_APX + ALTERNATIVE "jmp .Lload_egprs_done", "", X86_FEATURE_APX + testl $KVM_ENTER_EGPR_SWITCH, (%_ASM_SP) + jz .Lload_egprs_done + LOAD_REGS %_ASM_DI, VMX_vcpu_arch_regs, \ + %r16, %r17, %r18, %r19, %r20, %r21, %r22, %r23, \ + %r24, %r25, %r26, %r27, %r28, %r29, %r30, %r31 +.Lload_egprs_done: +#endif + /* * Unlike AMD there's no V_SPEC_CTRL here, so do not leave the body * out of line. Clobbers RAX, RCX, RDX, RSI. @@ -225,8 +236,24 @@ SYM_INNER_LABEL_ALIGN(vmx_vmexit, SYM_L_GLOBAL) mov %_ASM_BX, %_ASM_AX =20 /* Pop our saved arguments from the stack */ - pop %_ASM_BX - pop %_ASM_BX + pop %_ASM_BX /* @flags */ + pop %_ASM_DI /* @vmx */ + +#ifdef CONFIG_KVM_APX + ALTERNATIVE "jmp .Lclear_egprs_done", "", X86_FEATURE_APX + test $KVM_ENTER_EGPR_SWITCH, %_ASM_BX + jz .Lclear_egprs_done + /* + * Unlike legacy GPRs, saving could be conditional here on VM-Fail, + * which however isn't in fastpath. Instead, simply saving EGPRs always. + */ + STORE_REGS %_ASM_DI, VMX_vcpu_arch_regs, \ + %r16, %r17, %r18, %r19, %r20, %r21, %r22, %r23, \ + %r24, %r25, %r26, %r27, %r28, %r29, %r30, %r31 + CLEAR_REGS %r16d, %r17d, %r18d, %r19d, %r20d, %r21d, %r22d, %r23d, \ + %r24d, %r25d, %r26d, %r27d, %r28d, %r29d, %r30d, %r31d +.Lclear_egprs_done: +#endif =20 /* ... and then the callee-save registers */ pop %_ASM_BX diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 1701db1b2e18..e8dd5d5b33ad 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -987,6 +987,19 @@ unsigned int __vmx_vcpu_enter_flags(struct vcpu_vmx *v= mx) kvm_vcpu_can_access_host_mmio(&vmx->vcpu)) flags |=3D KVM_ENTER_CLEAR_CPU_BUFFERS_FOR_MMIO; =20 + /* + * KVM intercepts XSETBV and thus always tracks the guest XCR0. EGPR + * save/restore is gated by this flag. The resulting behavior is: + * + * - When the guest enables APX, KVM restores EGPRs (initially zeroed). + * - When the guest disables APX, EGPRs are preserved in the VCPU cache + * - When APX is re-enabled, the saved state is restored, which matches + * with architectural expectations. + */ + if (IS_ENABLED(CONFIG_KVM_APX) && cpu_feature_enabled(X86_FEATURE_APX) && + vmx->vcpu.arch.xcr0 & XFEATURE_MASK_APX) + flags |=3D KVM_ENTER_EGPR_SWITCH; + return flags; } =20 --=20 2.51.0 From nobody Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 01601299AAB; Tue, 12 May 2026 01:40:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550026; cv=none; b=LiA+yt9kRDX1cSScSnvNE4qvSrcLNhnPfa6oQtE1wJVbh6JbyDGgL9DZYk+2lywDt+zZvEAIYpnlyZV8gBNmfirX+BysRuYJsuvJiBHRZVURXyU/l8/ZEc3xCILamSRwcHNjEbmqz2wAWcXoDm1mepCoTznYPPViFR5VPLSilko= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550026; c=relaxed/simple; bh=rRYx/DqFwQylNMC80SODlgxoMESxSmqvmCvmeT0talw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cuGOIQt1Mx0KtXPtExXjLINNdu3WRggxvscmbfWPoHFcyXIhvNcxjuCVFF3WEsF69vMptF5fFk/2KPnLnnSlLqZoY1PK7HDgL8QIOxoQdqxcS1t0fviGqIo5MIWW6j2delw8X/d9l+EYF35QjZEcrD0ODbTzuZk+9NXeEGwVR/E= 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=n8Ch19fr; arc=none smtp.client-ip=198.175.65.14 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="n8Ch19fr" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550025; x=1810086025; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=rRYx/DqFwQylNMC80SODlgxoMESxSmqvmCvmeT0talw=; b=n8Ch19frv5crJ3TQDPa2d35B+XA3Cf9MsyhCR4WP5uQKGUeVclanTE6x eUyZoglIzRo+0lFIw+MBZKGKZYy3rDncL/taWpX+0ZuXZmWQuq0RqcKcn 8WIFVYtHvJAE2CCnnKzH6y0u/wFOyjCyUxsG42tr/jFNgPKBaLe0oXEhq HwuzjqqTOyAVZn+f/cmpOu8BWpVMK/1LI6SiwBQQ3byirHJROCDkaY5Py McsnSxFVg64oaKgH4ZX5gKIST3nqyb8EHBnAE21daGL5o8koDE/ybztTX wSEzLbaLZuQiukHI1VbWkowPNlvqrw0qJ2ONEZUfU60qcwJrN+wprCIHS w==; X-CSE-ConnectionGUID: LASADdcBTZSwE4Njs06yRg== X-CSE-MsgGUID: 11+N/KX6SCSCDPkWz3TZ7w== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322124" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322124" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:23 -0700 X-CSE-ConnectionGUID: aNQ1fHAOSNWhnxT7a1Y8kA== X-CSE-MsgGUID: 0Mu/YesDRlO9oNzbUS9DTg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572763" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:22 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 06/21] x86/fpu: Ignore APX when copying from/to guest FPU Date: Tue, 12 May 2026 01:14:47 +0000 Message-ID: <20260512011502.53072-7-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-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: Paolo Bonzini KVM will store APX extended GPRs directly in the regs[] field of struct kvm_vcpu. This is done to make accessors more uniform between GPRs and EGPRs, and partly because x86 maintainers expressed the desire to compile Linux with APX enabled sooner or later; accessing guest EGPRs from KVM's C code would get in the way. Therefore, let KVM handle the APX feature on its own when executing ioctls to get and set the virtual machine's XSAVE state. Cc: x86@kernel.org Signed-off-by: Paolo Bonzini [ chang: adjust function prototype ] Signed-off-by: Chang S. Bae --- V3 -> V4: New patch --- arch/x86/include/asm/fpu/api.h | 2 +- arch/x86/kernel/fpu/core.c | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/fpu/api.h b/arch/x86/include/asm/fpu/api.h index cd6f194a912b..0b218f5eaafd 100644 --- a/arch/x86/include/asm/fpu/api.h +++ b/arch/x86/include/asm/fpu/api.h @@ -160,7 +160,7 @@ static inline void fpu_sync_guest_vmexit_xfd_state(void= ) { } =20 extern void fpu_copy_guest_fpstate_to_uabi(struct fpu_guest *gfpu, void *b= uf, unsigned int size, u64 xfeatures, u32 pkru); -extern int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, const vo= id *buf, u64 xcr0, u32 *vpkru); +extern int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, void *bu= f, u64 xcr0, u32 *vpkru); =20 static inline void fpstate_set_confidential(struct fpu_guest *gfpu) { diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c index 608983806fd7..ae5c73faed69 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c @@ -420,6 +420,8 @@ void fpu_copy_guest_fpstate_to_uabi(struct fpu_guest *g= fpu, void *buf, struct membuf mb =3D { .p =3D buf, .left =3D size }; =20 if (cpu_feature_enabled(X86_FEATURE_XSAVE)) { + /* Up to date APX registers are in struct kvm_vcpu anyway. */ + xfeatures &=3D ~XFEATURE_MASK_APX; __copy_xstate_to_uabi_buf(mb, kstate, xfeatures, pkru, XSTATE_COPY_XSAVE); } else { @@ -431,11 +433,11 @@ void fpu_copy_guest_fpstate_to_uabi(struct fpu_guest = *gfpu, void *buf, } EXPORT_SYMBOL_FOR_KVM(fpu_copy_guest_fpstate_to_uabi); =20 -int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, const void *buf, +int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, void *buf, u64 xcr0, u32 *vpkru) { struct fpstate *kstate =3D gfpu->fpstate; - const union fpregs_state *ustate =3D buf; + union fpregs_state *ustate =3D buf; =20 if (!cpu_feature_enabled(X86_FEATURE_XSAVE)) { if (ustate->xsave.header.xfeatures & ~XFEATURE_MASK_FPSSE) @@ -464,6 +466,9 @@ int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gf= pu, const void *buf, if (!(ustate->xsave.header.xfeatures & XFEATURE_MASK_PKRU)) vpkru =3D NULL; =20 + /* APX registers are copied to and from struct kvm_vcpu, not the FPU. */ + ustate->xsave.header.xfeatures &=3D ~XFEATURE_MASK_APX; + return copy_uabi_from_kernel_to_xstate(kstate, ustate, vpkru); } EXPORT_SYMBOL_FOR_KVM(fpu_copy_uabi_to_guest_fpstate); --=20 2.51.0 From nobody Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 5F24B2DA76F; Tue, 12 May 2026 01:40:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550027; cv=none; b=oG95rg0BLgZvZpXbggST7YMvuSr14I5wpunEuZP/ZbHos7LrdtpXw1qjaXYC7owYmKn59fRbicPwNe65QNYSZrPfQYqL5nIvfMnY36WKdzk5ZF14UJ0qMcAGVcbiyvZ6j9z2mx2mVCjAq496tC0eGsH07Ah0eybG3fKI3Kf8+zI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550027; c=relaxed/simple; bh=Kkh2WSjqSDJKNMeGmSp6Tqv/mRakjmsf5Igfh4Fczgg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uJJx7CO+JwUg+4Kmh8ATHtIxoOY9GR8cfZv1YWYq/B/z/tZIIELJYwk42cyVyyOALzWWwI+TJAxOOTBV9tYZ52ZXkH6jjipcCDuPGhij9ZLmVDbOHhOokueJcOXIXIMuudqm6pwUwh4SQfadBvVp2l85q8I8+pgRy3PaYz7nu6k= 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=TePPQAPA; arc=none smtp.client-ip=198.175.65.14 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="TePPQAPA" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550026; x=1810086026; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Kkh2WSjqSDJKNMeGmSp6Tqv/mRakjmsf5Igfh4Fczgg=; b=TePPQAPAQ+V3KvpnWZ5seDhbeAREFvJlttL6X1IoiVNdB335LBMu9uQ5 J19uHfh4IQdyx5nnrTA9u8uhuQirzPXfig9+MZn/sC0ZtUTr8SjxZWdZS SaCKU6+43hA56V95+pcEl5AHYZjUMPpyIJ3TT7pkenrVHO0bmhUd1n8kO GXET0/g+aRV54E9OKl1v+TXVQgkN7hNvBxI/vDBEGKHCB/Zm2SRIXIE97 c72Rm0xDxfWBYHcTg5HeRIETGHoXKZhX7sT51ZofqRpPGwPlXx/YK2+8W q3Z06QoOAtPEtkVQUTA4PgxGgW5jZO7THgh8NgcitcGViyehwqP92zSNn Q==; X-CSE-ConnectionGUID: wYfZK+t2Sged1erRgGO+NA== X-CSE-MsgGUID: NW4cgd6JQwWfq974DCqzFg== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322129" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322129" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:23 -0700 X-CSE-ConnectionGUID: fHIrze4NTU6fQfguInKCNA== X-CSE-MsgGUID: upaeYl8fRL+tzv8hYg9e5g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572773" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:23 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 07/21] KVM: x86: Support APX state for XSAVE ABI Date: Tue, 12 May 2026 01:14:48 +0000 Message-ID: <20260512011502.53072-8-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce a facility to copy APX state between the VCPU cache and the userspace buffer since APX state is stored there. The existing fpstate copy functions historically sync all XSTATEs in between userspace and kernel buffers [1]. In this regard, any additional state handling logic should be consistent with them -- i.e. validation of XSTATE_BV against the supported XCR0 mask. Now with the two copy paths, their invocations require to take care of orderings: * When exporting to userspace, the fpstate function should runs first since it zeros out the area of components either not present or inactive. Then the VCPU cache function ensures its state copy. * When importing from userspace, the VCPU cache function should run first as the fpstate function always clears XSTATE_BV[APX] for not saving in the storage. [1] Except for PKRU state, as stored in struct thread_struct. Signed-off-by: Chang S. Bae --- V3 -> V4: Do not reset XSTATE_BV[APX], now with PATCH6 (Paolo) --- arch/x86/kvm/cpuid.c | 10 ++++++++ arch/x86/kvm/cpuid.h | 2 ++ arch/x86/kvm/x86.c | 58 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index e69156b54cff..82cb7c8fbc07 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -59,6 +59,16 @@ void __init kvm_init_xstate_sizes(void) } } =20 +u32 xstate_size(unsigned int xfeature) +{ + return xstate_sizes[xfeature].eax; +} + +u32 xstate_offset(unsigned int xfeature) +{ + return xstate_sizes[xfeature].ebx; +} + u32 xstate_required_size(u64 xstate_bv, bool compacted) { u32 ret =3D XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET; diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index 039b8e6f40ba..5ace99dd152b 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -64,6 +64,8 @@ bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, =20 void __init kvm_init_xstate_sizes(void); u32 xstate_required_size(u64 xstate_bv, bool compacted); +u32 xstate_size(unsigned int xfeature); +u32 xstate_offset(unsigned int xfeature); =20 int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu); int cpuid_query_maxguestphyaddr(struct kvm_vcpu *vcpu); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 48f259015ce4..3f029f9272a2 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5805,6 +5805,48 @@ static int kvm_vcpu_ioctl_x86_set_debugregs(struct k= vm_vcpu *vcpu, return 0; } =20 +#ifdef CONFIG_KVM_APX +static void kvm_copy_vcpu_regs_to_uabi(struct kvm_vcpu *vcpu, void *buf, u= 64 supported_xcr0) +{ + union fpregs_state *xstate =3D (union fpregs_state *)buf; + + BUILD_BUG_ON(NR_VCPU_GENERAL_PURPOSE_REGS <=3D VCPU_REGS_R31); + + if (!(supported_xcr0 & XFEATURE_MASK_APX)) + return; + + memcpy(buf + xstate_offset(XFEATURE_APX), + &vcpu->arch.regs[VCPU_REGS_R16], + xstate_size(XFEATURE_APX)); + + xstate->xsave.header.xfeatures |=3D XFEATURE_MASK_APX; +} + +static int kvm_copy_uabi_to_vcpu_regs(struct kvm_vcpu *vcpu, void *buf, u6= 4 supported_xcr0) +{ + union fpregs_state *xstate =3D (union fpregs_state *)buf; + + if (!(xstate->xsave.header.xfeatures & XFEATURE_MASK_APX)) + return 0; + + if (!(supported_xcr0 & XFEATURE_MASK_APX)) + return -EINVAL; + + BUILD_BUG_ON(NR_VCPU_GENERAL_PURPOSE_REGS <=3D VCPU_REGS_R31); + + memcpy(&vcpu->arch.regs[VCPU_REGS_R16], + buf + xstate_offset(XFEATURE_APX), + xstate_size(XFEATURE_APX)); + + return 0; +} +#else +static void kvm_copy_vcpu_regs_to_uabi(struct kvm_vcpu *vcpu, void *buf, u= 64 supported_xcr0) { }; +static int kvm_copy_uabi_to_vcpu_regs(struct kvm_vcpu *vcpu, void *buf, u6= 4 supported_xcr0) +{ + return 0; +} +#endif =20 static int kvm_vcpu_ioctl_x86_get_xsave2(struct kvm_vcpu *vcpu, u8 *state, unsigned int size) @@ -5827,8 +5869,15 @@ static int kvm_vcpu_ioctl_x86_get_xsave2(struct kvm_= vcpu *vcpu, if (fpstate_is_confidential(&vcpu->arch.guest_fpu)) return vcpu->kvm->arch.has_protected_state ? -EINVAL : 0; =20 + /* + * This copy function zeros out userspace memory for any gap from the + * guest fpstate. So invoke before copying any other state, i.e. APX, + * that is not saved in fpstate. + */ fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu, state, size, supported_xcr0, vcpu->arch.pkru); + kvm_copy_vcpu_regs_to_uabi(vcpu, state, supported_xcr0); + return 0; } =20 @@ -5843,6 +5892,7 @@ static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vc= pu *vcpu, struct kvm_xsave *guest_xsave) { union fpregs_state *xstate =3D (union fpregs_state *)guest_xsave->region; + int err; =20 if (fpstate_is_confidential(&vcpu->arch.guest_fpu)) return vcpu->kvm->arch.has_protected_state ? -EINVAL : 0; @@ -5854,6 +5904,14 @@ static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_v= cpu *vcpu, */ xstate->xsave.header.xfeatures &=3D ~vcpu->arch.guest_fpu.fpstate->xfd; =20 + /* + * Copy APX state to VCPU cache before the following copy function + * which always unsets XSTATE_BV[APX] to avoid savings in its storage. + */ + err =3D kvm_copy_uabi_to_vcpu_regs(vcpu, guest_xsave->region, kvm_caps.su= pported_xcr0); + if (err) + return err; + return fpu_copy_uabi_to_guest_fpstate(&vcpu->arch.guest_fpu, guest_xsave->region, kvm_caps.supported_xcr0, --=20 2.51.0 From nobody Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 4A0A52FE591; Tue, 12 May 2026 01:40:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550028; cv=none; b=VtySSrFWGG6GrHjyPh1/SxbVPPlRA44oqmQV+9gvDh/X7s9Bn49Jyk3F7xiSIbaYcOJgueMSCiP617o8us4ftn0ygUMgCk20Ys/bcEY3cv5fLc4Qwa3Kalvd0nrDm1tOatrPDecJkXfisvqny3rK2zpDbt20i5VqCLsSVHTvNE0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550028; c=relaxed/simple; bh=HvCf23gmSkOy76CGM56OWXbHaZO+hiu5SjYZeun++OM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=S/IV6Tu5pk2GWHHJGMzPPijyolBWfbpaGmDIJPoFbvp90x5LO0EyM9Uf6dpHR2wUsnZVCvTVOXzRNx0In6lSSnhLESPWgK+NHjDni6ilh3hNmLMkOqUa2y+4tnYWs7CsLIyZ/euyXF1BS6YrbPqw5DDqUVVzguOFm4UjKQ4W2Qs= 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=ERx6lFOt; arc=none smtp.client-ip=198.175.65.14 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="ERx6lFOt" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550026; x=1810086026; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=HvCf23gmSkOy76CGM56OWXbHaZO+hiu5SjYZeun++OM=; b=ERx6lFOtahIWgzGvaLYVU+ZBaoosm9h8PLz9V/6W5lhKbFmDzL+D+Y3s zo6vezG0sclfc3bj/V6t5i4sYSTFDfFJHuYmBn5YOR9ctTunEm05uMvdH MqwgpS3T2YveTgu8SiOmePoBwlrYTqNkEcnG+RBC1VyKHG/Tq/6zP3TI1 ouHGMxrko/hAUz/iVQ4Oqsh+j4tjbhbvWjXyDgFrpsYBac3hUdodFQHVp Yl9UWVURv8U0CIYKvzl0HlDoamY1KSsBSkYJtQ82t+vVBkBgP6P2jU2Or iWMF+N4w2Pm7lvBbwF4DUaZn5SobPA+Ocs0ktqlaC4GKGjeX6L1X/bU+f Q==; X-CSE-ConnectionGUID: hkdPiV1KRKSbC2BvRjDFjQ== X-CSE-MsgGUID: ayv+n+g6RXm/qXVarFiuiw== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322138" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322138" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:24 -0700 X-CSE-ConnectionGUID: X4lGJMCMTbKuuhe6HbV0vQ== X-CSE-MsgGUID: n0ZCvJ1NRau1327bzUyP0A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572779" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:24 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 08/21] KVM: VMX: Refactor VMX instruction information access Date: Tue, 12 May 2026 01:14:49 +0000 Message-ID: <20260512011502.53072-9-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce a helper that returns the instruction information as 64-bit value and adjust existing sites to prepare for a wider field. The VMX instruction information field is currently 32 bits. Future extensions may expand this field to support extended register IDs, requiring a wider width. The change provides a single access point for the transition. No functional change intended. Signed-off-by: Chang S. Bae --- arch/x86/kvm/vmx/nested.c | 22 +++++++++++----------- arch/x86/kvm/vmx/nested.h | 2 +- arch/x86/kvm/vmx/vmx.c | 4 ++-- arch/x86/kvm/vmx/vmx.h | 10 ++++++++-- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 4690a4d23709..06c1d83a8082 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -5229,7 +5229,7 @@ static void nested_vmx_triple_fault(struct kvm_vcpu *= vcpu) * #UD, #GP, or #SS. */ int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualific= ation, - u32 vmx_instruction_info, bool wr, int len, gva_t *ret) + u64 vmx_instruction_info, bool wr, int len, gva_t *ret) { gva_t off; bool exn; @@ -5361,7 +5361,7 @@ static int nested_vmx_get_vmptr(struct kvm_vcpu *vcpu= , gpa_t *vmpointer, int r; =20 if (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu), - vmcs_read32(VMX_INSTRUCTION_INFO), false, + vmx_get_instr_info(), false, sizeof(*vmpointer), &gva)) { *ret =3D 1; return -EINVAL; @@ -5646,7 +5646,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu) struct vmcs12 *vmcs12 =3D is_guest_mode(vcpu) ? get_shadow_vmcs12(vcpu) : get_vmcs12(vcpu); unsigned long exit_qualification =3D vmx_get_exit_qual(vcpu); - u32 instr_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); + u64 instr_info =3D vmx_get_instr_info(); struct vcpu_vmx *vmx =3D to_vmx(vcpu); struct x86_exception e; unsigned long field; @@ -5752,7 +5752,7 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) struct vmcs12 *vmcs12 =3D is_guest_mode(vcpu) ? get_shadow_vmcs12(vcpu) : get_vmcs12(vcpu); unsigned long exit_qualification =3D vmx_get_exit_qual(vcpu); - u32 instr_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); + u64 instr_info =3D vmx_get_instr_info(); struct vcpu_vmx *vmx =3D to_vmx(vcpu); struct x86_exception e; unsigned long field; @@ -5941,7 +5941,7 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu) static int handle_vmptrst(struct kvm_vcpu *vcpu) { unsigned long exit_qual =3D vmx_get_exit_qual(vcpu); - u32 instr_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); + u64 instr_info =3D vmx_get_instr_info(); gpa_t current_vmptr =3D to_vmx(vcpu)->nested.current_vmptr; struct x86_exception e; gva_t gva; @@ -5969,7 +5969,7 @@ 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; + u64 vmx_instruction_info, types; unsigned long type, roots_to_free; struct kvm_mmu *mmu; gva_t gva; @@ -5989,7 +5989,7 @@ static int handle_invept(struct kvm_vcpu *vcpu) if (!nested_vmx_check_permission(vcpu)) return 1; =20 - vmx_instruction_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); + vmx_instruction_info =3D vmx_get_instr_info(); gpr_index =3D vmx_get_instr_info_reg2(vmx_instruction_info); type =3D kvm_register_read(vcpu, gpr_index); =20 @@ -6049,7 +6049,7 @@ static int handle_invept(struct kvm_vcpu *vcpu) static int handle_invvpid(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx =3D to_vmx(vcpu); - u32 vmx_instruction_info; + u64 vmx_instruction_info; unsigned long type, types; gva_t gva; struct x86_exception e; @@ -6070,7 +6070,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) if (!nested_vmx_check_permission(vcpu)) return 1; =20 - vmx_instruction_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); + vmx_instruction_info =3D vmx_get_instr_info(); gpr_index =3D vmx_get_instr_info_reg2(vmx_instruction_info); type =3D kvm_register_read(vcpu, gpr_index); =20 @@ -6423,7 +6423,7 @@ static bool nested_vmx_exit_handled_encls(struct kvm_= vcpu *vcpu, static bool nested_vmx_exit_handled_vmcs_access(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, gpa_t bitmap) { - u32 vmx_instruction_info; + u64 vmx_instruction_info; unsigned long field; u8 b; =20 @@ -6431,7 +6431,7 @@ static bool nested_vmx_exit_handled_vmcs_access(struc= t kvm_vcpu *vcpu, return true; =20 /* Decode instruction info and find the field to access */ - vmx_instruction_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); + vmx_instruction_info =3D vmx_get_instr_info(); field =3D kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf)); =20 /* Out-of-range fields always cause a VM exit from L2 to L1 */ diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h index 213a448104af..ff1ea771d1fb 100644 --- a/arch/x86/kvm/vmx/nested.h +++ b/arch/x86/kvm/vmx/nested.h @@ -51,7 +51,7 @@ void nested_sync_vmcs12_to_shadow(struct kvm_vcpu *vcpu); int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data); int vmx_get_vmx_msr(struct nested_vmx_msrs *msrs, u32 msr_index, u64 *pdat= a); int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualific= ation, - u32 vmx_instruction_info, bool wr, int len, gva_t *ret); + u64 vmx_instruction_info, bool wr, int len, gva_t *ret); bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port, int size); =20 diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index e8dd5d5b33ad..6bf3b79c69f3 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -6136,7 +6136,7 @@ static int handle_monitor_trap(struct kvm_vcpu *vcpu) =20 static int handle_invpcid(struct kvm_vcpu *vcpu) { - u32 vmx_instruction_info; + u64 vmx_instruction_info; unsigned long type; gva_t gva; struct { @@ -6150,7 +6150,7 @@ static int handle_invpcid(struct kvm_vcpu *vcpu) return 1; } =20 - vmx_instruction_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); + vmx_instruction_info =3D vmx_get_instr_info(); gpr_index =3D vmx_get_instr_info_reg2(vmx_instruction_info); type =3D kvm_register_read(vcpu, gpr_index); =20 diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index daedf663c0a9..aa4190620e82 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -702,12 +702,18 @@ static inline bool vmx_guest_state_valid(struct kvm_v= cpu *vcpu) =20 void dump_vmcs(struct kvm_vcpu *vcpu); =20 -static inline int vmx_get_instr_info_reg(u32 vmx_instr_info) +/* A placeholder to smoothen 64-bit extension */ +static inline u64 vmx_get_instr_info(void) +{ + return vmcs_read32(VMX_INSTRUCTION_INFO); +} + +static inline int vmx_get_instr_info_reg(u64 vmx_instr_info) { return (vmx_instr_info >> 3) & 0xf; } =20 -static inline int vmx_get_instr_info_reg2(u32 vmx_instr_info) +static inline int vmx_get_instr_info_reg2(u64 vmx_instr_info) { return (vmx_instr_info >> 28) & 0xf; } --=20 2.51.0 From nobody Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 06A3C30E83A; Tue, 12 May 2026 01:40:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550028; cv=none; b=Va5ZfFlXwxQpYTsBPgLff4VRhDymujvHT8NC/wzuUUSmnVusMXR26b/4MvmWQ0fHtjrdc4IiZZ1ReEVUsVsOYSNCMaXNWIfpMzfPIszgEEluIdMgHuCNNtE5so4Wwqi4PKPbX8cwXYYRnxUs+LVWNV/3n9yFj6xUSJGLbEKawLY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550028; c=relaxed/simple; bh=17SJZN9erCEFmYGU07Hu1UJh0ymOBvqaeUSqVQ3irE4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Z5fStcok4V4sRyTDQqYo9JaNIpDRzYqdDBZJf8a+LMPoevSYDDqmxBYmZlNdxKAO0X2zlGlhVj1wXMd4JqlH4d9GhAJIU2N5J0yd1kMUbV++bQyh56jn5HuAAywLqSMJiRWaF5tiN3gDzwldSI34Sv59pR6Uo/00zu3iLzuy8xA= 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=LIFoTuYp; arc=none smtp.client-ip=198.175.65.14 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="LIFoTuYp" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550027; x=1810086027; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=17SJZN9erCEFmYGU07Hu1UJh0ymOBvqaeUSqVQ3irE4=; b=LIFoTuYpQc07B2rkhabUuV7i8zX7zn4Ro4/3bKFI8awsetv0W45C7/8g GLzzUA515M/KIyR0sBdnt1Z5kYN+E89DD3cjgcBLy+rgwFoctx5eng18X xRGZ3fD/gEo0LQV/Y2qGehXyIuEjUXAPYu6LdykhNQ5dw7lix3BkwCwjN Poa75/NI2XgUFFuHL2JUA6MHtJfZRt8YMVQ0kH7spcCq80eVymrrooMv1 F5o+ZgDS9QhTZizjvOWO8zspECqNVvp1BvGTUyo2LKs1R3XS+m/T5DEjG bcH5wu2EPSOw0CrJtpAPof6LmrW1kITOVMFGGcfTBV0NVxQYOOyIEMTAS A==; X-CSE-ConnectionGUID: sjn6GGZuTumvubp5NHMXYA== X-CSE-MsgGUID: Al8enClARY+Osn5H6ky2yA== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322143" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322143" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:25 -0700 X-CSE-ConnectionGUID: sWBP+CLSTMmuL5tyuG85sg== X-CSE-MsgGUID: HflqhE7WTFKmn52ugnfjLg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572785" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:25 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 09/21] KVM: VMX: Refactor instruction information decoding Date: Tue, 12 May 2026 01:14:50 +0000 Message-ID: <20260512011502.53072-10-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" KVM currently decodes the VMX instruction information field using a mix of open-coded bit manipulations and ad hoc helpers. Convert all decoding to use helpers to centralizes the decoding logic for the transition to a wider instruction information. No functional change intended. Signed-off-by: Chang S. Bae --- arch/x86/kvm/vmx/nested.c | 58 +++++++++++++++++++-------------------- arch/x86/kvm/vmx/vmx.c | 11 ++++---- arch/x86/kvm/vmx/vmx.h | 48 +++++++++++++++++++++++++++++--- 3 files changed, 78 insertions(+), 39 deletions(-) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 06c1d83a8082..bf2fe6a034aa 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -5229,7 +5229,7 @@ static void nested_vmx_triple_fault(struct kvm_vcpu *= vcpu) * #UD, #GP, or #SS. */ int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualific= ation, - u64 vmx_instruction_info, bool wr, int len, gva_t *ret) + u64 instr_info, bool wr, int len, gva_t *ret) { gva_t off; bool exn; @@ -5237,20 +5237,20 @@ int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsi= gned long exit_qualification, =20 /* * According to Vol. 3B, "Information for VM Exits Due to Instruction - * Execution", on an exit, vmx_instruction_info holds most of the - * addressing components of the operand. Only the displacement part - * is put in exit_qualification (see 3B, "Basic VM-Exit Information"). + * Execution", on an exit, instr_info holds most of the addressing + * components of the operand. Only the displacement part is put in + * exit_qualification (see 3B, "Basic VM-Exit Information"). * For how an actual address is calculated from all these components, * refer to Vol. 1, "Operand Addressing". */ - int scaling =3D vmx_instruction_info & 3; - int addr_size =3D (vmx_instruction_info >> 7) & 7; - bool is_reg =3D vmx_instruction_info & (1u << 10); - int seg_reg =3D (vmx_instruction_info >> 15) & 7; - int index_reg =3D (vmx_instruction_info >> 18) & 0xf; - bool index_is_valid =3D !(vmx_instruction_info & (1u << 22)); - int base_reg =3D (vmx_instruction_info >> 23) & 0xf; - bool base_is_valid =3D !(vmx_instruction_info & (1u << 27)); + int scaling =3D vmx_get_instr_info_scaling(instr_info); + int addr_size =3D vmx_get_instr_info_addr_size(instr_info); + bool is_reg =3D vmx_get_instr_info_is_reg(instr_info); + int seg_reg =3D vmx_get_instr_info_seg_reg(instr_info); + int index_reg =3D vmx_get_instr_info_index_reg(instr_info); + bool index_is_valid =3D vmx_get_instr_info_index_is_valid(instr_info); + int base_reg =3D vmx_get_instr_info_base_reg(instr_info); + bool base_is_valid =3D vmx_get_instr_info_base_is_valid(instr_info); =20 if (is_reg) { kvm_queue_exception(vcpu, UD_VECTOR); @@ -5659,7 +5659,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu) return 1; =20 /* Decode instruction info and find the field to read */ - field =3D kvm_register_read(vcpu, (((instr_info) >> 28) & 0xf)); + field =3D kvm_register_read(vcpu, vmx_get_instr_info_reg(instr_info)); =20 if (!nested_vmx_is_evmptr12_valid(vmx)) { /* @@ -5707,8 +5707,8 @@ static int handle_vmread(struct kvm_vcpu *vcpu) * Note that the number of bits actually copied is 32 or 64 depending * on the guest's mode (32 or 64 bit), not on the given field's length. */ - if (instr_info & BIT(10)) { - kvm_register_write(vcpu, (((instr_info) >> 3) & 0xf), value); + if (vmx_get_instr_info_is_reg(instr_info)) { + kvm_register_write(vcpu, vmx_get_instr_info_reg(instr_info), value); } else { len =3D is_64_bit_mode(vcpu) ? 8 : 4; if (get_vmx_mem_address(vcpu, exit_qualification, @@ -5781,8 +5781,8 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) get_vmcs12(vcpu)->vmcs_link_pointer =3D=3D INVALID_GPA)) return nested_vmx_failInvalid(vcpu); =20 - if (instr_info & BIT(10)) - value =3D kvm_register_read(vcpu, (((instr_info) >> 3) & 0xf)); + if (vmx_get_instr_info_is_reg(instr_info)) + value =3D kvm_register_read(vcpu, vmx_get_instr_info_reg(instr_info)); else { len =3D is_64_bit_mode(vcpu) ? 8 : 4; if (get_vmx_mem_address(vcpu, exit_qualification, @@ -5793,7 +5793,7 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) return kvm_handle_memory_failure(vcpu, r, &e); } =20 - field =3D kvm_register_read(vcpu, (((instr_info) >> 28) & 0xf)); + field =3D kvm_register_read(vcpu, vmx_get_instr_info_reg2(instr_info)); =20 offset =3D get_vmcs12_field_offset(field); if (offset < 0) @@ -5969,8 +5969,8 @@ static int handle_vmptrst(struct kvm_vcpu *vcpu) static int handle_invept(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx =3D to_vmx(vcpu); - u64 vmx_instruction_info, types; unsigned long type, roots_to_free; + u64 instr_info, types; struct kvm_mmu *mmu; gva_t gva; struct x86_exception e; @@ -5989,8 +5989,8 @@ static int handle_invept(struct kvm_vcpu *vcpu) if (!nested_vmx_check_permission(vcpu)) return 1; =20 - vmx_instruction_info =3D vmx_get_instr_info(); - gpr_index =3D vmx_get_instr_info_reg2(vmx_instruction_info); + instr_info =3D vmx_get_instr_info(); + gpr_index =3D vmx_get_instr_info_reg2(instr_info); type =3D kvm_register_read(vcpu, gpr_index); =20 types =3D (vmx->nested.msrs.ept_caps >> VMX_EPT_EXTENT_SHIFT) & 6; @@ -6002,7 +6002,7 @@ static int handle_invept(struct kvm_vcpu *vcpu) * operand is read even if it isn't needed (e.g., for type=3D=3Dglobal) */ if (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu), - vmx_instruction_info, false, sizeof(operand), &gva)) + instr_info, false, sizeof(operand), &gva)) return 1; r =3D kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e); if (r !=3D X86EMUL_CONTINUE) @@ -6049,8 +6049,8 @@ static int handle_invept(struct kvm_vcpu *vcpu) static int handle_invvpid(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx =3D to_vmx(vcpu); - u64 vmx_instruction_info; unsigned long type, types; + u64 instr_info; gva_t gva; struct x86_exception e; struct { @@ -6070,8 +6070,8 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) if (!nested_vmx_check_permission(vcpu)) return 1; =20 - vmx_instruction_info =3D vmx_get_instr_info(); - gpr_index =3D vmx_get_instr_info_reg2(vmx_instruction_info); + instr_info =3D vmx_get_instr_info(); + gpr_index =3D vmx_get_instr_info_reg2(instr_info); type =3D kvm_register_read(vcpu, gpr_index); =20 types =3D (vmx->nested.msrs.vpid_caps & @@ -6085,7 +6085,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) * operand is read even if it isn't needed (e.g., for type=3D=3Dglobal) */ if (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu), - vmx_instruction_info, false, sizeof(operand), &gva)) + instr_info, false, sizeof(operand), &gva)) return 1; r =3D kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e); if (r !=3D X86EMUL_CONTINUE) @@ -6423,16 +6423,16 @@ static bool nested_vmx_exit_handled_encls(struct kv= m_vcpu *vcpu, static bool nested_vmx_exit_handled_vmcs_access(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, gpa_t bitmap) { - u64 vmx_instruction_info; unsigned long field; + u64 instr_info; u8 b; =20 if (!nested_cpu_has_shadow_vmcs(vmcs12)) return true; =20 /* Decode instruction info and find the field to access */ - vmx_instruction_info =3D vmx_get_instr_info(); - field =3D kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf)); + instr_info =3D vmx_get_instr_info(); + field =3D kvm_register_read(vcpu, vmx_get_instr_info_reg2(instr_info)); =20 /* Out-of-range fields always cause a VM exit from L2 to L1 */ if (field >> 15) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 6bf3b79c69f3..10724b7fd405 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -6136,8 +6136,8 @@ static int handle_monitor_trap(struct kvm_vcpu *vcpu) =20 static int handle_invpcid(struct kvm_vcpu *vcpu) { - u64 vmx_instruction_info; unsigned long type; + u64 instr_info; gva_t gva; struct { u64 pcid; @@ -6150,16 +6150,15 @@ static int handle_invpcid(struct kvm_vcpu *vcpu) return 1; } =20 - vmx_instruction_info =3D vmx_get_instr_info(); - gpr_index =3D vmx_get_instr_info_reg2(vmx_instruction_info); + instr_info =3D vmx_get_instr_info(); + gpr_index =3D vmx_get_instr_info_reg2(instr_info); type =3D kvm_register_read(vcpu, gpr_index); =20 /* According to the Intel instruction reference, the memory operand * is read even if it isn't needed (e.g., for type=3D=3Dall) */ if (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu), - vmx_instruction_info, false, - sizeof(operand), &gva)) + instr_info, false, sizeof(operand), &gva)) return 1; =20 return kvm_handle_invpcid(vcpu, type, gva); @@ -6301,7 +6300,7 @@ static int handle_notify(struct kvm_vcpu *vcpu) =20 static int vmx_get_msr_imm_reg(struct kvm_vcpu *vcpu) { - return vmx_get_instr_info_reg(vmcs_read32(VMX_INSTRUCTION_INFO)); + return vmx_get_instr_info_reg(vmx_get_instr_info()); } =20 static int handle_rdmsr_imm(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index aa4190620e82..345b10d28231 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -708,14 +708,54 @@ static inline u64 vmx_get_instr_info(void) return vmcs_read32(VMX_INSTRUCTION_INFO); } =20 -static inline int vmx_get_instr_info_reg(u64 vmx_instr_info) +static inline int vmx_get_instr_info_reg(u64 instr_info) { - return (vmx_instr_info >> 3) & 0xf; + return (instr_info >> 3) & 0xf; } =20 -static inline int vmx_get_instr_info_reg2(u64 vmx_instr_info) +static inline int vmx_get_instr_info_reg2(u64 instr_info) { - return (vmx_instr_info >> 28) & 0xf; + return (instr_info >> 28) & 0xf; +} + +static inline int vmx_get_instr_info_scaling(u64 instr_info) +{ + return instr_info & 3; +} + +static inline int vmx_get_instr_info_addr_size(u64 instr_info) +{ + return (instr_info >> 7) & 7; +} + +static inline bool vmx_get_instr_info_is_reg(u64 instr_info) +{ + return !!(instr_info & BIT(10)); +} + +static inline int vmx_get_instr_info_seg_reg(u64 instr_info) +{ + return (instr_info >> 15) & 7; +} + +static inline int vmx_get_instr_info_index_reg(u64 instr_info) +{ + return (instr_info >> 18) & 0xf; +} + +static inline bool vmx_get_instr_info_index_is_valid(u64 instr_info) +{ + return !(instr_info & BIT(22)); +} + +static inline int vmx_get_instr_info_base_reg(u64 instr_info) +{ + return (instr_info >> 23) & 0xf; +} + +static inline bool vmx_get_instr_info_base_is_valid(u64 instr_info) +{ + return !(instr_info & BIT(27)); } =20 static inline bool vmx_can_use_ipiv(struct kvm_vcpu *vcpu) --=20 2.51.0 From nobody Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 CBB73314B63; Tue, 12 May 2026 01:40:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550029; cv=none; b=tpKYdsigYBFeOEHkBcq9crV9I2w/ZmOxQGkIyb4HL8zMZpjaWPxWgPr91kDk/jPz/HmUXKfvvI75T64kwvh+izT2XMV+BDH76qWC8wGOJvVZfmKzApVAJzqJIT6fDJKNxCihIAtrjJrD/gm4IJhv/Loll+jE4cFXsSFejC5qtRo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550029; c=relaxed/simple; bh=Bjyb8i8QCZsaf45fBSvmcMkyl9IEGZBeGxkiqG4yDgk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=crSt0QsGrgDPcCgaMilLYZnyMxQ5o3/Qrss6p65t3Luh9nDfQRNnN+IhxqBLvoU3IwGTZ/tOCRhYeggBCLG2P0b1EYNvnsHMeUzevW1/+n+VjfkSr6Vhm+oIwva4uhhZivQDQTk8nqBxTij6D3caLSEpfqa3XbvDO9+oL2rDgUw= 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=aHiu73Is; arc=none smtp.client-ip=198.175.65.14 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="aHiu73Is" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550028; x=1810086028; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Bjyb8i8QCZsaf45fBSvmcMkyl9IEGZBeGxkiqG4yDgk=; b=aHiu73Is0/aQgV6xw0wlVdGXh9GCQvyOfN4AbvugzjTcAfuYECygbm7N cNg8RwL1eEZZClP78Zy5wOCa72Hzpxw0itZF5gWgwy1C93IpBXYQfbARQ 1lKNxSUKnwXEsqodNQKQUodbt1qN5rqvNB2fNfq9Kw6HSbUdGU6n4yWxq UuoPcxTk6DlJ0ATl7GllWvD2uzIC/CuxWFj3ofgtHwlds6v2HMcSOcQwy 2Yxk2b+h3nmpFIPSA/7vG2Wt++hFlKPFhM3hvjyzWo2m/vGZSLxDozyD8 ONpwmN4nJulxQ317toqKtE31sq6CdHsR72vg7y2WvYVMkgMYxkdFv/BvI g==; X-CSE-ConnectionGUID: 5qifv9q/RSSZ3qRn3EWDTQ== X-CSE-MsgGUID: jTDJflVcS/K5q9o5mwYxhw== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322148" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322148" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:26 -0700 X-CSE-ConnectionGUID: Wdl5SmkTTGOyaUa4Gh/kEw== X-CSE-MsgGUID: JIKtxrFqQoyeOan+M8dUDw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572789" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:25 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 10/21] KVM: VMX: Refactor register index retrieval from exit qualification Date: Tue, 12 May 2026 01:14:51 +0000 Message-ID: <20260512011502.53072-11-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce a helper to extract the register index from the VMX exit qualification field. In addition to the VMX instruction information field, exit qualification also encodes a register index. This field will expand into the previously reserved bit for extended register IDs. This refactoring will simplify the extended register handling without code duplication. Since the VMCS exit qualification is cached in VCPU state, the helper can reference it efficiently via vmx_get_exit_qual(). No functional change intended. Signed-off-by: Chang S. Bae --- 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 bf2fe6a034aa..cc804a843e76 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -6345,7 +6345,7 @@ static bool nested_vmx_exit_handled_cr(struct kvm_vcp= u *vcpu, =20 switch ((exit_qualification >> 4) & 3) { case 0: /* mov to cr */ - reg =3D (exit_qualification >> 8) & 15; + reg =3D vmx_get_exit_qual_reg(vcpu); val =3D kvm_register_read(vcpu, reg); switch (cr) { case 0: diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 10724b7fd405..f13d56bc32d1 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -5670,7 +5670,7 @@ static int handle_cr(struct kvm_vcpu *vcpu) =20 exit_qualification =3D vmx_get_exit_qual(vcpu); cr =3D exit_qualification & 15; - reg =3D (exit_qualification >> 8) & 15; + reg =3D vmx_get_exit_qual_reg(vcpu); switch ((exit_qualification >> 4) & 3) { case 0: /* mov to cr */ val =3D kvm_register_read(vcpu, reg); diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 345b10d28231..f71ae8d2c338 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -323,6 +323,11 @@ static __always_inline unsigned long vmx_get_exit_qual= (struct kvm_vcpu *vcpu) return vt->exit_qualification; } =20 +static inline int vmx_get_exit_qual_reg(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 Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 E423F33B6F8; Tue, 12 May 2026 01:40:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550033; cv=none; b=D/4V7ds17qGTHilEv21Whaz5sOhRjpincpLHhDmk9E7BoxNqvmULBYxlOdmlGQ0S3j1dZ9vVnwhZKscsPMTBwfQQynGdBpbYR30celr+7+5AlDBxzVnjITmqoQWW+voKPnJSGsh2KGYStROVoLGpath9OgF1tLcLk6rs3neUv5s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550033; c=relaxed/simple; bh=R/ysa1ksHpyGhjHiGcrnNVZs9H+0ooHMCBcBXdycmTI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Y3Q/Rg658130WZMNczDeGQn7cVy1VedJpwd+CfX00gLKtQrtyaOzctY2z8reZD41dwP+ykf4+QusVMa+7K0fbpwHfy9+Vr306eEyKDM1W3Qsea9YqR90kN7mgw9ZLaA5QxjBW9MenYIRBWP5BQD8KQaIIbP39ul+danUNM/drFk= 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=lFDQsfNz; arc=none smtp.client-ip=198.175.65.14 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="lFDQsfNz" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550029; x=1810086029; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=R/ysa1ksHpyGhjHiGcrnNVZs9H+0ooHMCBcBXdycmTI=; b=lFDQsfNzkHKwVqS7CChz8wiWwOW66JUKvZRHQt0bJe6KkThAiNJXmA3h 1AIw57/PXKlmc7km/sym9RQ9200xuEpF9GRxIojwtPLaGPy3XG1YuFEWh SBqmlV3mJR5b1GXXowI2S/ko2hDxjI5ScGlnVLSWPtytKVbhtCzB21zjZ cjMn+BzDA+FjQ7j2+b19VH5oJiXCBftnSMU6S84n7vLPGCE050dVo/wK1 wnkAkQ6CBh9fEPDVWPcWXysWHH8eqmgAFXzOqlTObg82fBew52MWXzQ9b efigafCKPY/qL3xhsAKZVc9XxlnkNbWaQXWbcQ6R4ZuaWWfY6uuidnp/A Q==; X-CSE-ConnectionGUID: ZAirv9zMQGWCrbwAlT8WsQ== X-CSE-MsgGUID: owx2wGIqSZWzgEN5N2p/vw== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322152" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322152" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:27 -0700 X-CSE-ConnectionGUID: CM8l0GX6STmRSE0kL3AEbg== X-CSE-MsgGUID: 3M4Q4LetTQ271eNGKAkucg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572794" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:26 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 11/21] KVM: VMX: Support instruction information extension Date: Tue, 12 May 2026 01:14:52 +0000 Message-ID: <20260512011502.53072-12-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Define the VMCS field offset for the extended instruction information. Then, support 5-bit register indices retrieval from VMCS fields. Note the APX enumeration alone indicates the extension is available. However, software must not assume that previously reserved bits were zero on older implementations. Suggested-by: Paolo Bonzini Suggested-by: Sean Christopherson Signed-off-by: Chang S. Bae Link: https://lore.kernel.org/7bb14722-c036-4835-8ed9-046b4e67909e@redhat.c= om Link: https://lore.kernel.org/aakEsXJgO-3m2xca@google.com --- arch/x86/include/asm/vmx.h | 2 ++ arch/x86/kvm/vmx/vmx.h | 42 +++++++++++++++++++++++++++----------- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index ed2ded531e55..d4f23e581b84 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -276,6 +276,8 @@ enum vmcs_field { PID_POINTER_TABLE_HIGH =3D 0x00002043, GUEST_PHYSICAL_ADDRESS =3D 0x00002400, GUEST_PHYSICAL_ADDRESS_HIGH =3D 0x00002401, + EXTENDED_INSTRUCTION_INFO =3D 0x00002406, + EXTENDED_INSTRUCTION_INFO_HIGH =3D 0x00002407, VMCS_LINK_POINTER =3D 0x00002800, VMCS_LINK_POINTER_HIGH =3D 0x00002801, GUEST_IA32_DEBUGCTL =3D 0x00002802, diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index f71ae8d2c338..88c540b7f087 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -323,9 +323,18 @@ static __always_inline unsigned long vmx_get_exit_qual= (struct kvm_vcpu *vcpu) return vt->exit_qualification; } =20 +/* + * The APX enumeration guarantees the presence of the extended fields. + * The host CPUID bit alone is sufficient to rely on it. + */ +static inline bool vmx_instr_info_extended(void) +{ + return static_cpu_has(X86_FEATURE_APX); +} + static inline int vmx_get_exit_qual_reg(struct kvm_vcpu *vcpu) { - return (vmx_get_exit_qual(vcpu) >> 8) & 0xf; + return (vmx_get_exit_qual(vcpu) >> 8) & (vmx_instr_info_extended() ? 0x1f= : 0xf); } =20 static __always_inline u32 vmx_get_intr_info(struct kvm_vcpu *vcpu) @@ -707,20 +716,22 @@ static inline bool vmx_guest_state_valid(struct kvm_v= cpu *vcpu) =20 void dump_vmcs(struct kvm_vcpu *vcpu); =20 -/* A placeholder to smoothen 64-bit extension */ static inline u64 vmx_get_instr_info(void) { - return vmcs_read32(VMX_INSTRUCTION_INFO); + return vmx_instr_info_extended() ? vmcs_read64(EXTENDED_INSTRUCTION_INFO)= : + vmcs_read32(VMX_INSTRUCTION_INFO); } =20 static inline int vmx_get_instr_info_reg(u64 instr_info) { - return (instr_info >> 3) & 0xf; + return vmx_instr_info_extended() ? (instr_info >> 16) & 0x1f : + (instr_info >> 3) & 0xf; } =20 static inline int vmx_get_instr_info_reg2(u64 instr_info) { - return (instr_info >> 28) & 0xf; + return vmx_instr_info_extended() ? (instr_info >> 40) & 0x1f : + (instr_info >> 28) & 0xf; } =20 static inline int vmx_get_instr_info_scaling(u64 instr_info) @@ -730,37 +741,44 @@ static inline int vmx_get_instr_info_scaling(u64 inst= r_info) =20 static inline int vmx_get_instr_info_addr_size(u64 instr_info) { - return (instr_info >> 7) & 7; + return vmx_instr_info_extended() ? (instr_info >> 2) & 3 : + (instr_info >> 7) & 7; } =20 static inline bool vmx_get_instr_info_is_reg(u64 instr_info) { - return !!(instr_info & BIT(10)); + return vmx_instr_info_extended() ? !!(instr_info & BIT(4)) : + !!(instr_info & BIT(10)); } =20 static inline int vmx_get_instr_info_seg_reg(u64 instr_info) { - return (instr_info >> 15) & 7; + return vmx_instr_info_extended() ? (instr_info >> 7) & 7 : + (instr_info >> 15) & 7; } =20 static inline int vmx_get_instr_info_index_reg(u64 instr_info) { - return (instr_info >> 18) & 0xf; + return vmx_instr_info_extended() ? (instr_info >> 24) & 0x1f : + (instr_info >> 18) & 0xf; } =20 static inline bool vmx_get_instr_info_index_is_valid(u64 instr_info) { - return !(instr_info & BIT(22)); + return vmx_instr_info_extended() ? !(instr_info & BIT(10)) : + !(instr_info & BIT(22)); } =20 static inline int vmx_get_instr_info_base_reg(u64 instr_info) { - return (instr_info >> 23) & 0xf; + return vmx_instr_info_extended() ? (instr_info >> 32) & 0x1f : + (instr_info >> 23) & 0xf; } =20 static inline bool vmx_get_instr_info_base_is_valid(u64 instr_info) { - return !(instr_info & BIT(27)); + return vmx_instr_info_extended() ? !(instr_info & BIT(11)) : + !(instr_info & BIT(27)); } =20 static inline bool vmx_can_use_ipiv(struct kvm_vcpu *vcpu) --=20 2.51.0 From nobody Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 EBB2333BBC0; Tue, 12 May 2026 01:40:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550035; cv=none; b=BKi43Gu6QhhTluC1Speoc6eoEV6bogml6hLigWIly+rEVCFQtJuzQHFsVqZrxhvC8PHFbvlu/zNos4WUP3Lio36QgukUoIpw/Jpow9IydCyxOJwdPx8lVHp5hyBYD7GdRDwP5HknxSNe5Hw3eXWekyE6YLjRAfi54DZT3TO3ih0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550035; c=relaxed/simple; bh=nxtMVHZZLUEDQ6cY++3qOTH5T1i7LewHmWvM0ZW4ywU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=meVkFleMRFWYnMYfJj3qSxYFJZbUURe8+mvyrDg/nuliFo/Iu7Inp/ChaSsBjOoHdQtwYK1Ggadc6okRo5KDiswWzI1FX+xlepJ/C/PPm+kTdR1Zdev91RwBwluUv2CzYbgXWjEtiDJzp9ggR89ne2nPyt/Edpdj5w9Z8q/xAVY= 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=A4MXX67R; arc=none smtp.client-ip=198.175.65.14 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="A4MXX67R" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550029; x=1810086029; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=nxtMVHZZLUEDQ6cY++3qOTH5T1i7LewHmWvM0ZW4ywU=; b=A4MXX67RDGFrnCK7LrRAof6LLKKgoVKJuJPFEXh5C2OcBMsBsdJeWLYp q0ZTY/IMS7P80sNCQjmOKorIjN8DuQ5/kRcB/KiiWgUfL9VxiCfcFZkWD tHKBSXi9Qh0l4asoI1qxxBoUQ3UkmM2TSOrtd+XeDwdAP1Fw6zLxi0RP8 hzOqAL2JSwPX6GX3ttqzYvvLxCVW8DK0ZKGURQSpKGesckSpjO55TYoko eRFJ3+v0g3GiyxaMrdCj+5rdhrHqpmNRHNFaOQEPfjOMDRcgEiw5twtq2 pnHpaSD3MYXcecy6gHscuvde1bvERkos2jk5kio2cn5et8BvcWgp/RB2E w==; X-CSE-ConnectionGUID: VmzVf96yQeqVUbsnKICZhw== X-CSE-MsgGUID: ZwyCwDAvSbar4X6j33fJAw== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322156" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322156" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:27 -0700 X-CSE-ConnectionGUID: 5Rh8tu6YTLC/crSPMhGpFA== X-CSE-MsgGUID: 6yW8/76YQhOxCKhhyfLgRg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572797" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:27 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 12/21] KVM: nVMX: Propagate the extended instruction info field Date: Tue, 12 May 2026 01:14:53 +0000 Message-ID: <20260512011502.53072-13-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Define the new extended_instruction_info field in struct vmcs12 and propagate it to nested VMX. Gate the propagation on the guest APX enumeration, which aligns with VMX behavior. Thus, define the CPUID bit here too. Suggested-by: Chao Gao Signed-off-by: Chang S. Bae Link: https://lore.kernel.org/aRvOSnaUt1E+%2FpkC@intel.com --- arch/x86/kvm/reverse_cpuid.h | 2 ++ arch/x86/kvm/vmx/nested.c | 6 ++++++ arch/x86/kvm/vmx/vmcs12.c | 1 + arch/x86/kvm/vmx/vmcs12.h | 3 ++- 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h index 657f5f743ed9..de90697c4e5a 100644 --- a/arch/x86/kvm/reverse_cpuid.h +++ b/arch/x86/kvm/reverse_cpuid.h @@ -35,6 +35,7 @@ #define X86_FEATURE_AVX_VNNI_INT16 KVM_X86_FEATURE(CPUID_7_1_EDX, 10) #define X86_FEATURE_PREFETCHITI KVM_X86_FEATURE(CPUID_7_1_EDX, 14) #define X86_FEATURE_AVX10 KVM_X86_FEATURE(CPUID_7_1_EDX, 19) +#define KVM_X86_FEATURE_APX KVM_X86_FEATURE(CPUID_7_1_EDX, 21) =20 /* Intel-defined sub-features, CPUID level 0x00000007:2 (EDX) */ #define X86_FEATURE_INTEL_PSFD KVM_X86_FEATURE(CPUID_7_2_EDX, 0) @@ -144,6 +145,7 @@ static __always_inline u32 __feature_translate(int x86_= feature) KVM_X86_TRANSLATE_FEATURE(SGX1); KVM_X86_TRANSLATE_FEATURE(SGX2); KVM_X86_TRANSLATE_FEATURE(SGX_EDECCSSA); + KVM_X86_TRANSLATE_FEATURE(APX); KVM_X86_TRANSLATE_FEATURE(CONSTANT_TSC); KVM_X86_TRANSLATE_FEATURE(PERFMON_V2); KVM_X86_TRANSLATE_FEATURE(RRSBA_CTRL); diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index cc804a843e76..c1be8ef882b8 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -4761,6 +4761,12 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, st= ruct vmcs12 *vmcs12, vmcs12->vm_exit_intr_info =3D exit_intr_info; vmcs12->vm_exit_instruction_len =3D exit_insn_len; vmcs12->vmx_instruction_info =3D vmcs_read32(VMX_INSTRUCTION_INFO); + /* + * The APX enumeration guarantees the presence of the extended + * fields. This CPUID bit alone is sufficient to rely on it. + */ + if (guest_cpu_cap_has(vcpu, X86_FEATURE_APX)) + vmcs12->extended_instruction_info =3D vmcs_read64(EXTENDED_INSTRUCTION_= INFO); =20 /* * According to spec, there's no need to store the guest's diff --git a/arch/x86/kvm/vmx/vmcs12.c b/arch/x86/kvm/vmx/vmcs12.c index 1ebe67c384ad..267aa64f005e 100644 --- a/arch/x86/kvm/vmx/vmcs12.c +++ b/arch/x86/kvm/vmx/vmcs12.c @@ -53,6 +53,7 @@ static const u16 kvm_supported_vmcs12_field_offsets[] __i= nitconst =3D { FIELD64(XSS_EXIT_BITMAP, xss_exit_bitmap), FIELD64(ENCLS_EXITING_BITMAP, encls_exiting_bitmap), FIELD64(GUEST_PHYSICAL_ADDRESS, guest_physical_address), + FIELD64(EXTENDED_INSTRUCTION_INFO, extended_instruction_info), FIELD64(VMCS_LINK_POINTER, vmcs_link_pointer), FIELD64(GUEST_IA32_DEBUGCTL, guest_ia32_debugctl), FIELD64(GUEST_IA32_PAT, guest_ia32_pat), diff --git a/arch/x86/kvm/vmx/vmcs12.h b/arch/x86/kvm/vmx/vmcs12.h index 21cd1b75e4fd..25e9a41c248f 100644 --- a/arch/x86/kvm/vmx/vmcs12.h +++ b/arch/x86/kvm/vmx/vmcs12.h @@ -71,7 +71,7 @@ struct __packed vmcs12 { u64 pml_address; u64 encls_exiting_bitmap; u64 tsc_multiplier; - u64 padding64[1]; /* room for future expansion */ + u64 extended_instruction_info; /* * To allow migration of L1 (complete with its L2 guests) between * machines of different natural widths (32 or 64 bit), we cannot have @@ -261,6 +261,7 @@ static inline void vmx_check_vmcs12_offsets(void) CHECK_OFFSET(pml_address, 312); CHECK_OFFSET(encls_exiting_bitmap, 320); CHECK_OFFSET(tsc_multiplier, 328); + CHECK_OFFSET(extended_instruction_info, 336); CHECK_OFFSET(cr0_guest_host_mask, 344); CHECK_OFFSET(cr4_guest_host_mask, 352); CHECK_OFFSET(cr0_read_shadow, 360); --=20 2.51.0 From nobody Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 5D1382D595B; Tue, 12 May 2026 01:40:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550034; cv=none; b=jk6bdcVpXORe5UdFrvYHZIGBjtLEVIG4RbtnX62YS+Gx/cz4pW6rt50xwmO9uBhYQRdi0AcHUXFvukehgCwLAKcxU2PlR8RhGNjhRo8qvO4X1FtLA9VolVkpfaHqM9xRJTcnIxPMqMC07VB6HsAdT24a0zYx0pe65lkVRxHIN+k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550034; c=relaxed/simple; bh=nm3CPZ3S4tjIC9q2AAnqfmAqyR/AvkuVysL1Odtxquw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SfMM0UxysZK/bFB0O8fqMsaO7VVTez9CIbnQdQPKYf3RC69le/mk5zL0ja7nyZF9ZvRQyeKetcnZEVSS9VOV0cUWipquvrrRj08XGTeQjbMw6r8vt69xoqb1/y5SKu2zljoGu+XDiXZ+OzNWIi3SNcdKxq/zAG7abqUBDFwDTU4= 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=jvkKILQI; arc=none smtp.client-ip=198.175.65.14 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="jvkKILQI" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550030; x=1810086030; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=nm3CPZ3S4tjIC9q2AAnqfmAqyR/AvkuVysL1Odtxquw=; b=jvkKILQImPGtHdWWRfJh15yx48TnEIg7sVlre7vxaLkpLTYmy6B0AfwD nhrKhzvca60VzFOoWaS9H9AfY4Sygm7W57zkrA5D6A09Ybazm+tAvNAKN fYstpoErapJS2IEkgOF8vBKt5zjYjwR89aqfaWCA3lvLGFUGtm/Kod+ic IoI1exs7xh39pOv/vIux69BQQUvnY5ex//vJkdVeLVD951tqnf595Up0D 7EhKAH3vGGtFGT3ut01Emz07akRj0hC8qkaG3Nb00la7D8GoWitOLEtEF ymBOpZgmPSRRipySRgleFlyDDnyGhQ8fMCEu05hgVmcqkKcf5Lk0yjdpz g==; X-CSE-ConnectionGUID: ejQ8/7hfT5yeQBjJZRJRWg== X-CSE-MsgGUID: M5inW0H0R2yoFF0mGM57Qw== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322160" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322160" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:28 -0700 X-CSE-ConnectionGUID: LI4ATmyjQ0+5xZxmv0y+lA== X-CSE-MsgGUID: xPz2Cx7BRHajcNj9XXG3hw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572804" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:27 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 13/21] KVM: x86: Support EGPR accessing and tracking for emulator Date: Tue, 12 May 2026 01:14:54 +0000 Message-ID: <20260512011502.53072-14-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend the emulator context and GPR accessors to handle EGPRs before adding support for REX2-prefixed instructions. Like VCPU cache, the emulator can uniformly cache and track all GPRs. Signed-off-by: Chang S. Bae --- arch/x86/kvm/kvm_emulate.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h index 0abff36d0994..b722bf20a59b 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. @@ -315,7 +315,9 @@ typedef void (*fastop_t)(struct fastop *); * also uses _eip, RIP cannot be a register operand nor can it be an opera= nd in * a ModRM or SIB byte. */ -#ifdef CONFIG_X86_64 +#if defined(CONFIG_KVM_APX) +#define NR_EMULATOR_GPRS 32 +#elif defined(CONFIG_X86_64) #define NR_EMULATOR_GPRS 16 #else #define NR_EMULATOR_GPRS 8 @@ -375,9 +377,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; --=20 2.51.0 From nobody Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 306572EB860; Tue, 12 May 2026 01:40:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550035; cv=none; b=EIOFvpqD5++Fb83daEpAIHLpRtTFAiCD6X9SaWHkaWJ+2GkwgdFscORczuYI2Xspmiz1KdbL44T5zEEGeKbrOvpaEdjjYa/1rZrdXrgPUS7y7vPFr04nJiutCW1iB8cOE0Wfn4Moh3UAQR7JKlnFgyfQe4uUKdfJRUk27FedjXw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550035; c=relaxed/simple; bh=UyBpv6/VsxNdgdGdXiTysjUvm4KYt+++oOOOg2Pm1Ps=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mbwypM/j3auX2eYrfqJqf55y1bjQU7p1vpH7oZPQb5TxHPyEb7khBb9tGIz6hAKGtIc91z9bnaTcJ56gvQ3l50H42JzNqixXt5zCC18iLBSAf4xobCAmWPRY+d3dcMIbstyBIvtVnSS81MHiJChANBLJh+sbziUvYdeReJ4152A= 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=bCMiyNHT; arc=none smtp.client-ip=198.175.65.14 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="bCMiyNHT" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550033; x=1810086033; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=UyBpv6/VsxNdgdGdXiTysjUvm4KYt+++oOOOg2Pm1Ps=; b=bCMiyNHTcfRsQdMJjkhTW/h13SPjVbRTzeWE1PrccFk24UPOdB//ofEt DY6BRnsjp+UKOmqhCzq+Za6RaioT/G1tEeyruUlEPikD+yGuC/amkuzFL gbR1s17MzDzzafSXS58CXIUnXzYRXr89oyrABzcUb+pKQijwv6GTfhXie OE5DDYXkR42Fl0bCgH2AgZyw2kFtcZKiUE2fTPPL9NP4sqtSSg1GfpGPS D0mKYHBeRCYl5Q17+bcf2gZNvTP0Ck24IjEanxpapI2cOVpmuafuiUyEp OuhETHnVMsvaJjimOH+kt9SIHgQ4vzMUmtqUqCTf8uy94L/ulxBzQyY6F w==; X-CSE-ConnectionGUID: eWsUVVFzQa2fJqKPy27/ew== X-CSE-MsgGUID: agIirFrxTUOFKfhl9f3hRA== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322165" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322165" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:29 -0700 X-CSE-ConnectionGUID: vxupcurCRX+WAspctpMjVA== X-CSE-MsgGUID: f7tJ4T3VTTK/9WnNy3MBAw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572809" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:28 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 14/21] KVM: x86: Handle EGPR index and REX2-incompatible opcodes Date: Tue, 12 May 2026 01:14:55 +0000 Message-ID: <20260512011502.53072-15-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Prepare the emulator for REX2 handling by introducing the NoRex2 opcode flag and supporting extended register indices. For the latter, factor out common logic for calculating register IDs. REX2 does not support three-byte opcodes. Instead, the REX2.M bit selects between one- and two-byte opcode tables, which were previously distinguished by the 0x0F escape byte. Some legacy instructions in those tables never reference extended registers. When prefixed with REX, such instructions are treated as if the prefix were absent. In contrast, a REX2 prefix causes a #UD, which should be handled explicitly. Suggested-by: Paolo Bonzini Signed-off-by: Chang S. Bae Link: https://lore.kernel.org/1ebf3a23-5671-41c1-8daa-c83f2f105936@redhat.c= om --- arch/x86/kvm/emulate.c | 80 +++++++++++++++++++++++--------------- arch/x86/kvm/kvm_emulate.h | 1 + 2 files changed, 50 insertions(+), 31 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index c8c6cc0406d6..0fef9416cb4d 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -175,6 +175,7 @@ #define TwoMemOp ((u64)1 << 55) /* Instruction has two memory operand = */ #define IsBranch ((u64)1 << 56) /* Instruction is considered a branch.= */ #define ShadowStack ((u64)1 << 57) /* Instruction affects Shadow Stacks. = */ +#define NoRex2 ((u64)1 << 58) /* Instruction not present in REX2 map= s */ =20 #define DstXacc (DstAccLo | SrcAccHi | SrcWrite) =20 @@ -244,6 +245,7 @@ enum rex_bits { REX_X =3D 2, REX_R =3D 4, REX_W =3D 8, + REX_M =3D 0x80, }; =20 static void writeback_registers(struct x86_emulate_ctxt *ctxt) @@ -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; @@ -4257,7 +4268,7 @@ static const struct opcode opcode_table[256] =3D { /* 0x38 - 0x3F */ I6ALU(NoWrite, em_cmp), N, N, /* 0x40 - 0x4F */ - X8(I(DstReg, em_inc)), X8(I(DstReg, em_dec)), + X8(I(DstReg | NoRex2, em_inc)), X8(I(DstReg | NoRex2, em_dec)), /* 0x50 - 0x57 */ X8(I(SrcReg | Stack, em_push)), /* 0x58 - 0x5F */ @@ -4275,7 +4286,7 @@ static const struct opcode opcode_table[256] =3D { I2bvIP(DstDI | SrcDX | Mov | String | Unaligned, em_in, ins, check_perm_i= n), /* insb, insw/insd */ I2bvIP(SrcSI | DstDX | String, em_out, outs, check_perm_out), /* outsb, o= utsw/outsd */ /* 0x70 - 0x7F */ - X16(D(SrcImmByte | NearBranch | IsBranch)), + X16(D(SrcImmByte | NearBranch | IsBranch | NoRex2)), /* 0x80 - 0x87 */ G(ByteOp | DstMem | SrcImm, group1), G(DstMem | SrcImm, group1), @@ -4299,15 +4310,15 @@ static const struct opcode opcode_table[256] =3D { II(ImplicitOps | Stack, em_popf, popf), I(ImplicitOps, em_sahf), I(ImplicitOps, em_lahf), /* 0xA0 - 0xA7 */ - I2bv(DstAcc | SrcMem | Mov | MemAbs, em_mov), - I2bv(DstMem | SrcAcc | Mov | MemAbs | PageTable, em_mov), - I2bv(SrcSI | DstDI | Mov | String | TwoMemOp, em_mov), - I2bv(SrcSI | DstDI | String | NoWrite | TwoMemOp, em_cmp_r), + I2bv(DstAcc | SrcMem | Mov | MemAbs | NoRex2, em_mov), + I2bv(DstMem | SrcAcc | Mov | MemAbs | PageTable | NoRex2, em_mov), + I2bv(SrcSI | DstDI | Mov | String | TwoMemOp | NoRex2, em_mov), + I2bv(SrcSI | DstDI | String | NoWrite | TwoMemOp | NoRex2, em_cmp_r), /* 0xA8 - 0xAF */ - I2bv(DstAcc | SrcImm | NoWrite, em_test), - I2bv(SrcAcc | DstDI | Mov | String, em_mov), - I2bv(SrcSI | DstAcc | Mov | String, em_mov), - I2bv(SrcAcc | DstDI | String | NoWrite, em_cmp_r), + I2bv(DstAcc | SrcImm | NoWrite | NoRex2, em_test), + I2bv(SrcAcc | DstDI | Mov | String | NoRex2, em_mov), + I2bv(SrcSI | DstAcc | Mov | String | NoRex2, em_mov), + I2bv(SrcAcc | DstDI | String | NoWrite | NoRex2, em_cmp_r), /* 0xB0 - 0xB7 */ X8(I(ByteOp | DstReg | SrcImm | Mov, em_mov)), /* 0xB8 - 0xBF */ @@ -4337,17 +4348,17 @@ static const struct opcode opcode_table[256] =3D { /* 0xD8 - 0xDF */ N, E(0, &escape_d9), N, E(0, &escape_db), N, E(0, &escape_dd), N, N, /* 0xE0 - 0xE7 */ - X3(I(SrcImmByte | NearBranch | IsBranch, em_loop)), - I(SrcImmByte | NearBranch | IsBranch, em_jcxz), - I2bvIP(SrcImmUByte | DstAcc, em_in, in, check_perm_in), - I2bvIP(SrcAcc | DstImmUByte, em_out, out, check_perm_out), + X3(I(SrcImmByte | NearBranch | IsBranch | NoRex2, em_loop)), + I(SrcImmByte | NearBranch | IsBranch | NoRex2, em_jcxz), + I2bvIP(SrcImmUByte | DstAcc | NoRex2, em_in, in, check_perm_in), + I2bvIP(SrcAcc | DstImmUByte | NoRex2, em_out, out, check_perm_out), /* 0xE8 - 0xEF */ - I(SrcImm | NearBranch | IsBranch | ShadowStack, em_call), - D(SrcImm | ImplicitOps | NearBranch | IsBranch), - I(SrcImmFAddr | No64 | IsBranch, em_jmp_far), - D(SrcImmByte | ImplicitOps | NearBranch | IsBranch), - I2bvIP(SrcDX | DstAcc, em_in, in, check_perm_in), - I2bvIP(SrcAcc | DstDX, em_out, out, check_perm_out), + I(SrcImm | NearBranch | IsBranch | ShadowStack | NoRex2, em_call), + D(SrcImm | ImplicitOps | NearBranch | IsBranch | NoRex2), + I(SrcImmFAddr | No64 | IsBranch | NoRex2, em_jmp_far), + D(SrcImmByte | ImplicitOps | NearBranch | IsBranch | NoRex2), + I2bvIP(SrcDX | DstAcc | NoRex2, em_in, in, check_perm_in), + I2bvIP(SrcAcc | DstDX | NoRex2, em_out, out, check_perm_out), /* 0xF0 - 0xF7 */ N, DI(ImplicitOps, icebp), N, N, DI(ImplicitOps | Priv, hlt), D(ImplicitOps), @@ -4388,12 +4399,12 @@ static const struct opcode twobyte_table[256] =3D { N, GP(ModRM | DstMem | SrcReg | Mov | Sse | Avx, &pfx_0f_2b), N, N, N, N, /* 0x30 - 0x3F */ - II(ImplicitOps | Priv, em_wrmsr, wrmsr), - IIP(ImplicitOps, em_rdtsc, rdtsc, check_rdtsc), - II(ImplicitOps | Priv, em_rdmsr, rdmsr), - IIP(ImplicitOps, em_rdpmc, rdpmc, check_rdpmc), - I(ImplicitOps | EmulateOnUD | IsBranch | ShadowStack, em_sysenter), - I(ImplicitOps | Priv | EmulateOnUD | IsBranch | ShadowStack, em_sysexit), + II(ImplicitOps | Priv | NoRex2, em_wrmsr, wrmsr), + IIP(ImplicitOps | NoRex2, em_rdtsc, rdtsc, check_rdtsc), + II(ImplicitOps | Priv | NoRex2, em_rdmsr, rdmsr), + IIP(ImplicitOps | NoRex2, em_rdpmc, rdpmc, check_rdpmc), + I(ImplicitOps | EmulateOnUD | IsBranch | ShadowStack | NoRex2, em_sysente= r), + I(ImplicitOps | Priv | EmulateOnUD | IsBranch | ShadowStack | NoRex2, em_= sysexit), N, N, N, N, N, N, N, N, N, N, /* 0x40 - 0x4F */ @@ -4411,7 +4422,7 @@ static const struct opcode twobyte_table[256] =3D { N, N, N, N, N, N, N, GP(SrcReg | DstMem | ModRM | Mov, &pfx_0f_6f_0f_7f), /* 0x80 - 0x8F */ - X16(D(SrcImm | NearBranch | IsBranch)), + X16(D(SrcImm | NearBranch | IsBranch | NoRex2)), /* 0x90 - 0x9F */ X16(D(ByteOp | DstMem | SrcNone | ModRM| Mov)), /* 0xA0 - 0xA7 */ @@ -5004,6 +5015,13 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, v= oid *insn, int insn_len, int opcode =3D opcode_table[ctxt->b]; } =20 + /* + * Instructions marked with NoRex2 ignore a legacy REX prefix, but + * #UD should be raised when prefixed with REX2. + */ + if (ctxt->d & NoRex2 && ctxt->rex_prefix =3D=3D REX2_PREFIX) + opcode.flags =3D Undefined; + if (opcode.flags & ModRM) ctxt->modrm =3D insn_fetch(u8, ctxt); =20 diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h index b722bf20a59b..28d93cd56aef 100644 --- a/arch/x86/kvm/kvm_emulate.h +++ b/arch/x86/kvm/kvm_emulate.h @@ -329,6 +329,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 Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 369E035CB6F; Tue, 12 May 2026 01:40:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550040; cv=none; b=Kf5gqFWDvUiY1n9ucYjGpUCBo8xY7Eyq3R7jsSYzFKkcrtDC2kKPpfeTHDxFQpH9tYj4gQ2YwVmhtMhcuVkz9lY0K0rRPn7INxGpwFRHAI0d51MEaDIAapkmwOHYNLBmJRUGbQr3CNbQHRLleQ7ClXFJGstS4OCyVvyAUpj3cZ4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550040; c=relaxed/simple; bh=lB/qY73XNhWXxo81nxg83MPuSWJniQSRIaDEFvvkeTo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=dZPch3a5Qx6EF8WuCYiYyhq6+G79oEVeOIKy4a8NvuKTJd0StMD6F0UTsM/jNl/ruQDb3fn61peEJcoQ1ssobd9tx969zUsAyADaEyTXbjV+d59D0JAKJl4Fr45qFfE28feEL56GzB+7FY6+gfU67RNjNsOQvlDV1h25tyI7HU4= 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=lvJkwL3m; arc=none smtp.client-ip=198.175.65.14 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="lvJkwL3m" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550034; x=1810086034; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=lB/qY73XNhWXxo81nxg83MPuSWJniQSRIaDEFvvkeTo=; b=lvJkwL3mVcHo2yEDh65wqx52Me0o5S9jm/lLme7mCfdopyq4SmY6s3vp Qw3YmUcYHfsu0aojmNophaFN8oSwjlLrZPnv71PtsEAMGJZHMMZ247mP4 cjG4UJGBd4L2tmKLPazBg6Hs5MEiJNyppzg3ov9xKm2BAMtt0AnA0qmcZ zk1KWy14udmSbTaMGE6B7n6uTwaaWZiw0eNrGMkks8joI3M0RweplzC16 PmGxJM52PaqV0Sdgx2/S/dyLdQI1h+1fK4Ruk0UU3/564fWU3SrCHiQ6z 8xWpdHhMHoD3AmU4aCoCOXV/ZB5UNgfX+a3IxSfLPtA9+rmI7xponpaMe w==; X-CSE-ConnectionGUID: gMlRjX/wThms9MImJK6Q6Q== X-CSE-MsgGUID: d+HwkmuSQvSD/zCZhg5P5A== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322171" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322171" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:29 -0700 X-CSE-ConnectionGUID: s8zdRRArRp6cORtaSa/Kcg== X-CSE-MsgGUID: SMsKLiZBS9SnUeYEtzOG+A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572814" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:29 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 15/21] KVM: x86: Support REX2-prefixed opcode decode Date: Tue, 12 May 2026 01:14:56 +0000 Message-ID: <20260512011502.53072-16-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Extend the instruction decoder to recognize and handle the REX2 prefix, including validation of prefix sequences and correct opcode table selection. REX2 is a terminal prefix: once 0xD5 is encountered, the following byte is the opcode. When REX.M=3D0, most prefix bytes are invalid after REX2, including REX, VEX, EVEX, and another REX2. Also, REX2-prefixed instructions are only valid in 64-bit mode. All of the invalid prefix combinations after REX2 coincide with opcodes that are architecturally invalid in 64-bit mode. Thus, marking such opcodes with No64 in opcode_table[] naturally disallows those illegal prefix sequences. The 0x40=E2=80=930x4F opcode row was missing the No64 flag. While NoRex2 al= ready invalidates REX2 for these opcodes, adding No64 makes opcode attributes explicit and complete. Suggested-by: Paolo Bonzini Signed-off-by: Chang S. Bae Link: https://lore.kernel.org/CABgObfYYGTvkYpeyqLSr9JgKMDA_STSff2hXBNchLZuK= FU+MMA@mail.gmail.com --- arch/x86/kvm/emulate.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 0fef9416cb4d..efe8adca1317 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -4268,7 +4268,7 @@ static const struct opcode opcode_table[256] =3D { /* 0x38 - 0x3F */ I6ALU(NoWrite, em_cmp), N, N, /* 0x40 - 0x4F */ - X8(I(DstReg | NoRex2, em_inc)), X8(I(DstReg | NoRex2, em_dec)), + X8(I(DstReg | NoRex2 | No64, em_inc)), X8(I(DstReg | NoRex2 | No64, em_de= c)), /* 0x50 - 0x57 */ X8(I(SrcReg | Stack, em_push)), /* 0x58 - 0x5F */ @@ -4862,6 +4862,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; @@ -4915,7 +4926,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 */ @@ -4961,6 +4972,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; @@ -4983,6 +5005,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 */ @@ -5000,17 +5028,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 Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 53E75361658; Tue, 12 May 2026 01:40:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550039; cv=none; b=sAfwxDkjs9wSH5BHDGYArLlrcOGhvuU4dpXui6f3RS1DOcX72CxOXcPIpc8HKzxPTnL6NELkr0jOvCgalu4ZxrxdjXXLEtWZrERg1BJvQlpU4LpwVm1Xe2Er+WA1DSxuAQAYTkao/0lcmcyfRHuGcZSw641loTH2BUfiOQlV0aM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550039; c=relaxed/simple; bh=bq3gC4SDa9NJv2wNWIJJzCLv/ofuVSA47dA3c9nxxxE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eNDIMP5cO13hNc+iusv4VJaG2U1w4xPbgYZ9Rg+yrYoAizRICYD907UEZc9ZS9cBBWcQCnYa7Dmi4Zh4q461SQO1UejabW9tncPIKPHXMxM3xP1Od6jTOkIK127up0ICr4+ptCq4QUsPv1+eA5LBwVWsYvXAzE7ityZ6l3vrmSo= 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=ATLaedC5; arc=none smtp.client-ip=198.175.65.14 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="ATLaedC5" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550035; x=1810086035; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=bq3gC4SDa9NJv2wNWIJJzCLv/ofuVSA47dA3c9nxxxE=; b=ATLaedC5L7uwBl3Begyx44DFh4fhCa2PDBVlbP6gjb/nEW90a40Nt/1Q 6tfJpyC7LdnuWyPI/5NnWUrQJ546yVeAkn7S8uENU/DQEqL8mMnPIHrIM FtPdCmKNku0WXNxTdiNqxESadDDkTgvV2ZPYRuW6zLeN1v97dK0BCQkoU dBx+phU3wyjPgIB+j0EiBn776r3el6U31WyD7OF27WWkfB3xubGgtEccp eL1+CrVTOsIsrd0E52hIGar3kE+cASB8QKrznuNaDHw0sCtTpKO9otMej JAGAmgpcp3AeIQb4oG5SBxZ9jY4+EGm0eHLxsz1zEBMmD0btYHcB+uBnl g==; X-CSE-ConnectionGUID: KQwLk3xxRjW/LIgU1Cdy0Q== X-CSE-MsgGUID: k/ioZpV+QyWkwloRpLQezA== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322177" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322177" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:30 -0700 X-CSE-ConnectionGUID: nzERAiUeQnSQUJz5NMZWoQ== X-CSE-MsgGUID: 5Oj/urJ0QBicOaIreLNrsw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572821" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:30 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 16/21] KVM: x86: Reject EVEX-prefixed instructions Date: Tue, 12 May 2026 01:14:57 +0000 Message-ID: <20260512011502.53072-17-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Explicitly mark EVEX-prefixed opcodes (0x62) as unsupported. Signed-off-by: Chang S. Bae --- arch/x86/kvm/emulate.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index efe8adca1317..31118ae3b6a1 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -5052,6 +5052,11 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, v= oid *insn, int insn_len, int if (ctxt->d & NoRex2 && 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 Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 54445362138; Tue, 12 May 2026 01:40:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550040; cv=none; b=bHfxafS341SjZqCfhvGAg6NgaHH61ULS+V64NQS+Yd6b9qyzx4p/PxR+GH+hy2FGpEBJsqPT2Xsj0S5hzGRd/pwov3LCMmAHT4yz8nBQmH0zkNJx7OS3vqgeZcRQ2/u31VuEml0CmrHuBbcSkzDcyHPlOrFgRKVK1blOS5vPIXA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550040; c=relaxed/simple; bh=XGCinmsiaPR3O0fki8p/XHJGLGrJzZGZbj5i794FOHg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iXR3yDJvyR/snDDNhUMV8IoOFBqw/Pa40rDoLU5UvPnJMRkVsA35Oa3ub+o3A9+goaxEsA/CBCE3CkQGz8ZphtZ1RcHvdqtPlkFeBzg+9Q8yO9G7IljiCgNU3QP+fO7fsdMR1n6F67s7+YBfgRrCJFxP9L8fWxjPDDQz5SuZLiw= 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=bI+DOido; arc=none smtp.client-ip=198.175.65.14 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="bI+DOido" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550035; x=1810086035; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=XGCinmsiaPR3O0fki8p/XHJGLGrJzZGZbj5i794FOHg=; b=bI+DOidoGo504h8quVvRBKt6Y5vinRjQ7iuy56xM8WR1J9p9ERmbrjUT 4of3ho5ZiB4GI8z5/rATGaFAdgBIRr5qupaMKYa27EKoYT6o9240FywwV C4Wu8w6bg7VOVJmSzEKRfoTbNliWi17yVkzdUcS96qd2Lt9ngciBuOdKt UBG0hQZhkHvFGJo6d411BDWbtOJOkyQsHcFvU7bQ7BCi5kA2693JUozoC Ay8xBKtADhkC2Myug79Ua6l2s5vYZN37ouelQT+T9pCsNxbRt+U6/4BS0 XP80/ZRyF5hzqzWOQT/2ZV1LWvuhR8lVEO7AITmr8f4f7kpm9sN2ZrCiQ g==; X-CSE-ConnectionGUID: fQATLBoGRE6nfQYXThZCzw== X-CSE-MsgGUID: +IgFyrOwQqKSajKT0cGmtg== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322182" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322182" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:31 -0700 X-CSE-ConnectionGUID: 69oaYYO1RbWzwenvG++f6g== X-CSE-MsgGUID: y2KZahThQf6cJGDWihgArQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572825" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:30 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 17/21] KVM: x86: Guard valid XCR0.APX settings Date: Tue, 12 May 2026 01:14:58 +0000 Message-ID: <20260512011502.53072-18-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Prevent invalid XCR0.APX configurations in two cases: conflict with MPX and lack of SVM support. In the non-compacted XSAVE format, APX and MPX conflict on the same offset. Although MPX is being deprecated in practice, KVM should explicitly reject such configurations that set both bits. At this point, only VMX supports EGPRs. SVM will require corresponding extensions to handle EGPR indices. Updating the supported XCR0 mask will be done separately with CPUID exposure. Suggested-by: Paolo Bonzini Signed-off-by: Chang S. Bae Link: https://lore.kernel.org/ab3f4937-38f5-4354-8850-bf773c159bbe@redhat.c= om --- arch/x86/kvm/svm/svm.c | 7 ++++++- arch/x86/kvm/x86.c | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index b78dd8805ebb..85d4087ea927 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -5573,8 +5573,13 @@ static __init int svm_hardware_setup(void) return -EOPNOTSUPP; } =20 + /* + * APX introduces EGPRs, which require additional VMCB support. + * Disable APX until the necessary extensions are handled. + */ kvm_caps.supported_xcr0 &=3D ~(XFEATURE_MASK_BNDREGS | - XFEATURE_MASK_BNDCSR); + XFEATURE_MASK_BNDCSR | + XFEATURE_MASK_APX); =20 if (tsc_scaling) { if (!boot_cpu_has(X86_FEATURE_TSCRATEMSR)) { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 3f029f9272a2..f5f27e7b00b6 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1291,6 +1291,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 Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 BD5892C21D8; Tue, 12 May 2026 01:40:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550042; cv=none; b=Lk5ZqHPu0f/3mnXy2VEcA9SG46DYqZervke5zxjO9nC2rjp7saa9o8rfEO8k7B9zwzBkGv2RA85rkbIyS0p3YNiknsxB9XqcmKTpYPy7b6HWOYZATkEJXXJpD0QwE/9bL7/kw+yrPjHCjZgaU8S39hicYf2xn78APNaplsXqU7k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550042; c=relaxed/simple; bh=iHeLqSbW5PSKY8Pf60SklfQv9r5k5HtSoB3mqhVGP+0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ldQzE0rD8Wm54dw19jaTuDo2kVf+2lyJtAsHiRmsPFUX+ioP14dS2OSYeWFY530WpgO8o7aLpNihR6/J841+RVhmyoKhZ8wn+YQj3SB17HYeZf6TX4RuzDMj6Udy2K+k89gEQGL0zFwYaqksUyS4ux899fP6HoBLU2Ek/gNeFZM= 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=M7mwa91B; arc=none smtp.client-ip=198.175.65.14 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="M7mwa91B" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550040; x=1810086040; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=iHeLqSbW5PSKY8Pf60SklfQv9r5k5HtSoB3mqhVGP+0=; b=M7mwa91BPN43GDJBNHYu8zWC11KYQ5TedrvZ/Ublr966B8808sTRwfgR qgCGGPaQOqHgeJBnx52D7terOx2SdYNM71wEmqmN7h8Oh2BKgkPbIkRvC b5EihNnh4ouUn+SiVY6AT/Z8y++W9dyM/34PmZN1jvSME9goQitTMvxro XnkKdNdNhyo8+nQrt3kPmjVSDOao0eAXI/CtxiPCAABTkon/eyUuguIOa x6GZGv4+yYydD7Sl87E3/XkP/WAp5mVgeXNu4hAdjzpdwatG7f6bsnyD8 m07KS7yqK3lfOrf2mtTJMvkUH9PvpU26RoJWx8mapEsoA0pNEtjF5QxZz Q==; X-CSE-ConnectionGUID: goXqGNZvRbqQCNJtu8IL5w== X-CSE-MsgGUID: kmRfYrm9TK+dWbJiRZO27w== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322188" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322188" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:32 -0700 X-CSE-ConnectionGUID: bUi6CLeRRoyvAv52oqcRGg== X-CSE-MsgGUID: xxnZy0AVRzK+DwUVjsrEjQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572829" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:31 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com, Peter Fang Subject: [PATCH v4 18/21] KVM: x86: Expose APX foundation feature to guests Date: Tue, 12 May 2026 01:14:59 +0000 Message-ID: <20260512011502.53072-19-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-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 the APX xfeature bit to the list of supported XCR0 components and expose the APX feature to guests. Update the maximum supported CPUID leaf to 0x29 to include the APX leaf. On SVM, do not advertise APX, as EGPR support is not yet implemented. No APX sub-features are enumerated yet. Those will be exposed in a separate patch. Originally-by: Peter Fang Signed-off-by: Chang S. Bae --- arch/x86/kvm/cpuid.c | 11 ++++++++++- arch/x86/kvm/svm/svm.c | 1 + arch/x86/kvm/x86.c | 8 +++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 82cb7c8fbc07..21dd3dac4211 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -1061,8 +1061,12 @@ void kvm_initialize_cpu_caps(void) F(AVX_VNNI_INT16), F(PREFETCHITI), F(AVX10), + SCATTERED_F(APX), ); =20 + if (!IS_ENABLED(CONFIG_KVM_APX)) + kvm_cpu_cap_clear(X86_FEATURE_APX); + kvm_cpu_cap_init(CPUID_7_2_EDX, F(INTEL_PSFD), F(IPRED_CTRL), @@ -1441,7 +1445,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); @@ -1712,6 +1716,11 @@ static inline int __do_cpuid_func(struct kvm_cpuid_a= rray *array, u32 function) } break; } + /* APX sub-features */ + case 0x29: { + entry->eax =3D entry->ebx =3D entry->ecx =3D entry->edx =3D 0; + break; + } case KVM_CPUID_SIGNATURE: { const u32 *sigptr =3D (const u32 *)KVM_SIGNATURE; entry->eax =3D KVM_CPUID_FEATURES; diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 85d4087ea927..84496bc0508d 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -5554,6 +5554,7 @@ static __init void svm_set_cpu_caps(void) */ kvm_cpu_cap_clear(X86_FEATURE_BUS_LOCK_DETECT); kvm_cpu_cap_clear(X86_FEATURE_MSR_IMM); + kvm_cpu_cap_clear(X86_FEATURE_APX); =20 kvm_setup_xss_caps(); kvm_finalize_cpu_caps(); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index f5f27e7b00b6..fc0924389398 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -219,10 +219,16 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_nr_uret_msrs); static u32 __read_mostly kvm_uret_msrs_list[KVM_MAX_NR_USER_RETURN_MSRS]; static DEFINE_PER_CPU(struct kvm_user_return_msrs, user_return_msrs); =20 +#ifndef CONFIG_KVM_APX +#undef XFEATURE_MASK_APX +#define XFEATURE_MASK_APX 0 +#endif + #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 Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 B036E314A6B; Tue, 12 May 2026 01:40:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550042; cv=none; b=ckKTpVVd+IDpvolfDFVMQ/pMVA4N2+sLEn6aY1Vb7/p5a4C1rsjwClXu3wOyk36kqBj3qCfGO/rzd3mPfTPQktt1PKFc/cgVHWVH78fQ7TQKirLMXJLhI8daE45La4jT/1ZGh08yHnGbTcnIQdtMpwmJm+ReKax4eLmRSbD95cA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550042; c=relaxed/simple; bh=IFs7raVRlz6MfOCkvw6GAvEiddY/1kgglL22vGA0GeU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dGeMUw1Ru0Z44++dBKJ30P+9EwSR8XdtZkI+JJuAouD/FCEs+RQtoKyxG+qVM55zz/m+7i851p20cIqEPzjwAtOu4ZIXvQVZcTDfFp9Alue2hVktYdSVlxNkHosUCARyduV3TBZuLkUv1JshWchIukzxAm+xqFvpx7DlgDPjQks= 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=mv2qnfoT; arc=none smtp.client-ip=198.175.65.14 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="mv2qnfoT" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550041; x=1810086041; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=IFs7raVRlz6MfOCkvw6GAvEiddY/1kgglL22vGA0GeU=; b=mv2qnfoTZd8NnSeskGIgqJxvwtOs3wzLEDga51GB122P6s9E2OGClP5Y bU22EbPgUMpp90Kxth2avGUxx83LOLF1e9nEhjnLHPGokTpvLDDx7xFve AQuH/Ud0wSSXJy+QUJBHUopHDKFhfoIIsJLObu3OwgWM+ObJxZnRjSdvR 3GEnYpr6HRX4fAysWfAdtmt8O7kNlghFLU1uoSEVH9GbgJsYpvoLaDDk2 FoS2jSqXQ2JToy86A9PetV8AVy7B3ZKxHFa0cvvlppS1GIgP1carTJQKN hIDbruFEEYigSuiEgZ5hrQGMTvj1rZH/iWsHB27uIl46f3srUJdNZR6ue Q==; X-CSE-ConnectionGUID: kmLhvTyoQkCFI3zJM/IPug== X-CSE-MsgGUID: bn5tItu+SwK4cY0fA82zDA== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322192" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322192" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:32 -0700 X-CSE-ConnectionGUID: pFAxI7n9T7K++OihSZ1M7g== X-CSE-MsgGUID: 4s+1vI0KR5KDkVFcF0XTlw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572832" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:32 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 19/21] KVM: x86: Expose APX sub-features to guests Date: Tue, 12 May 2026 01:15:00 +0000 Message-ID: <20260512011502.53072-20-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add CPUID leaf 0x29 sub-leaf 0 to expose these APX sub-features, if the APX foundation is available: * New Conditional Instructions (NCI) * New Data Destination (NDD) * Flags Suppression (NF) Signed-off-by: Chang S. Bae --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/cpuid.c | 9 ++++++++- arch/x86/kvm/reverse_cpuid.h | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index 76c91efca722..05b7a68b2708 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -824,6 +824,7 @@ enum kvm_only_cpuid_leafs { CPUID_7_1_ECX, CPUID_1E_1_EAX, CPUID_24_1_ECX, + CPUID_29_0_EBX, NR_KVM_CPU_CAPS, =20 NKVMCAPINTS =3D NR_KVM_CPU_CAPS - NCAPINTS, diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 21dd3dac4211..e570411f3a43 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -1111,6 +1111,10 @@ void kvm_initialize_cpu_caps(void) F(AVX10_VNNI_INT), ); =20 + kvm_cpu_cap_init(CPUID_29_0_EBX, + F(APX_NCI_NDD_NF), + ); + kvm_cpu_cap_init(CPUID_8000_0001_ECX, F(LAHF_LM), F(CMP_LEGACY), @@ -1718,7 +1722,10 @@ static inline int __do_cpuid_func(struct kvm_cpuid_a= rray *array, u32 function) } /* APX sub-features */ case 0x29: { - entry->eax =3D entry->ebx =3D entry->ecx =3D entry->edx =3D 0; + if (!kvm_cpu_cap_has(X86_FEATURE_APX)) { + entry->eax =3D entry->ebx =3D entry->ecx =3D entry->edx =3D 0; + break; + } break; } case KVM_CPUID_SIGNATURE: { diff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h index de90697c4e5a..cff071ccf926 100644 --- a/arch/x86/kvm/reverse_cpuid.h +++ b/arch/x86/kvm/reverse_cpuid.h @@ -67,6 +67,9 @@ /* Intel-defined sub-features, CPUID level 0x00000024:1 (ECX) */ #define X86_FEATURE_AVX10_VNNI_INT KVM_X86_FEATURE(CPUID_24_1_ECX, 2) =20 +/* Intel-defined sub-features, CPUID level 0x00000029:0 (EBX) */ +#define X86_FEATURE_APX_NCI_NDD_NF KVM_X86_FEATURE(CPUID_29_0_EBX, 0) + /* CPUID level 0x80000007 (EDX). */ #define KVM_X86_FEATURE_CONSTANT_TSC KVM_X86_FEATURE(CPUID_8000_0007_EDX, = 8) =20 @@ -110,6 +113,7 @@ static const struct cpuid_reg reverse_cpuid[] =3D { [CPUID_7_1_ECX] =3D { 7, 1, CPUID_ECX}, [CPUID_1E_1_EAX] =3D { 0x1e, 1, CPUID_EAX}, [CPUID_24_1_ECX] =3D { 0x24, 1, CPUID_ECX}, + [CPUID_29_0_EBX] =3D { 0x29, 0, CPUID_EBX}, }; =20 /* --=20 2.51.0 From nobody Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 B23B73164A9; Tue, 12 May 2026 01:40:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550042; cv=none; b=e20Vx2P+8Mm+PFnX+R1noY/9GzpPAja+2BpCUNqHkeApTxoL/DiVZR+W4+xfsl9xd++MXkk/1MiTW27Eb3QlpIxKEjrNnej1SBU+AjAsRZp0WmT/yk7lQS0LF9iTQjYx9+eTXuibPwzPlrlHBjFg7E8p1gET6kWipY+Zj4rfznY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550042; c=relaxed/simple; bh=IODy8Aa4qLzryR6er+0d7UKmZ+K5zIK5zWnJNb0bQvg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uqeP/RsvRmgrqDQWwJ+UwbxUd8LuJ5vFRf+Sew63zdOURJK+C5d0li1IWwuXxZwsB9MZcczvTW8ghtPhTAYQevzrYWNxhqjPNOjQDL2zK5MG0t+s+x3dL3OYM1WSmIFQUCXdtOh18Yy2mSFOHqiN3s2lgM7Yeh2XDFNrpzGMLhE= 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=hnajmxbm; arc=none smtp.client-ip=198.175.65.14 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="hnajmxbm" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550041; x=1810086041; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=IODy8Aa4qLzryR6er+0d7UKmZ+K5zIK5zWnJNb0bQvg=; b=hnajmxbmuFcdzNJeojGWcT29ofejOGMPaxajXR7z2kQW7p/wE9T40nC8 xk1n6XDIU21qBAKqvFRWF2WWxm0QzsR9g6mAsCDGAAkPo0jFRzUZVRGPd FSZtqqFWpCF0YpLcU0z4/9PxdTiSInY7bWNTPT9F0fZ9skYmj6Rm3ZqsL J0i5oj209lfPCI+eNBLnJkGjuVL5JZzJjac7YrdJfZ1GSVvDeKZCRIXR4 +ejRRaVPYpkYYRMdbJxAi2ZfrkraIRvi4SiZsNPJOA5c4HhtncyCaQiKZ nQI5BV43d8kQt8H+hupWo/BksUg6dVuKXYVxJyWuTJcQPDYFtzE71AAl7 A==; X-CSE-ConnectionGUID: TJS9aDyOTFy26CP/NPcSsg== X-CSE-MsgGUID: dDyLoyDYTV6vwZ5WQLkkrA== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322198" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322198" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:33 -0700 X-CSE-ConnectionGUID: WrW7DQD5RnqLUN2qj6b6gQ== X-CSE-MsgGUID: H9RF5DMVQ1aEzPW1wYOckQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572839" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:33 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 20/21] KVM: x86: selftests: Add APX state and ABI test Date: Tue, 12 May 2026 01:15:01 +0000 Message-ID: <20260512011502.53072-21-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Test APX-specific behavior and ABI interactions as these are unique comparing to other state components: * EGPR state is saved on VM entry assembly (unlike other components). * The saved state is retained even if the guest disables APX. * EGPR state is exposed via the XSAVE ABI while not stored in the kernel XSAVE buffer. Signed-off-by: Chang S. Bae --- tools/testing/selftests/kvm/Makefile.kvm | 1 + .../selftests/kvm/include/x86/processor.h | 120 +++++++++++ tools/testing/selftests/kvm/x86/apx_test.c | 191 ++++++++++++++++++ 3 files changed, 312 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/apx_test.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index 9118a5a51b89..7fcb1b88bdd6 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -158,6 +158,7 @@ TEST_GEN_PROGS_x86 +=3D rseq_test TEST_GEN_PROGS_x86 +=3D steal_time TEST_GEN_PROGS_x86 +=3D system_counter_offset_test TEST_GEN_PROGS_x86 +=3D pre_fault_memory_test +TEST_GEN_PROGS_x86 +=3D x86/apx_test =20 # Compiled outputs used by test targets TEST_GEN_PROGS_EXTENDED_x86 +=3D x86/nx_huge_pages_test diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/te= sting/selftests/kvm/include/x86/processor.h index 77f576ee7789..4c3cd65fce81 100644 --- a/tools/testing/selftests/kvm/include/x86/processor.h +++ b/tools/testing/selftests/kvm/include/x86/processor.h @@ -90,6 +90,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 | \ @@ -177,6 +178,7 @@ struct kvm_x86_cpu_feature { #define X86_FEATURE_SPEC_CTRL KVM_X86_CPU_FEATURE(0x7, 0, EDX, 26) #define X86_FEATURE_ARCH_CAPABILITIES KVM_X86_CPU_FEATURE(0x7, 0, EDX, 29) #define X86_FEATURE_PKS KVM_X86_CPU_FEATURE(0x7, 0, ECX, 31) +#define X86_FEATURE_APX KVM_X86_CPU_FEATURE(0x7, 1, EDX, 21) #define X86_FEATURE_XTILECFG KVM_X86_CPU_FEATURE(0xD, 0, EAX, 17) #define X86_FEATURE_XTILEDATA KVM_X86_CPU_FEATURE(0xD, 0, EAX, 18) #define X86_FEATURE_XSAVES KVM_X86_CPU_FEATURE(0xD, 1, EAX, 3) @@ -859,6 +861,124 @@ static inline void write_sse_reg(int reg, const sse12= 8_t *data) } } =20 +static inline unsigned long read_egpr(int reg) +{ + unsigned long data =3D 0; + + /* mov %r16..%r31, %rax */ + switch (reg) { + case 16: + asm(".byte 0xd5, 0x48, 0x89, 0xc0" : "=3Da"(data)); + break; + case 17: + asm(".byte 0xd5, 0x48, 0x89, 0xc8" : "=3Da"(data)); + break; + case 18: + asm(".byte 0xd5, 0x48, 0x89, 0xd0" : "=3Da"(data)); + break; + case 19: + asm(".byte 0xd5, 0x48, 0x89, 0xd8" : "=3Da"(data)); + break; + case 20: + asm(".byte 0xd5, 0x48, 0x89, 0xe0" : "=3Da"(data)); + break; + case 21: + asm(".byte 0xd5, 0x48, 0x89, 0xe8" : "=3Da"(data)); + break; + case 22: + asm(".byte 0xd5, 0x48, 0x89, 0xf0" : "=3Da"(data)); + break; + case 23: + asm(".byte 0xd5, 0x48, 0x89, 0xf8" : "=3Da"(data)); + break; + case 24: + asm(".byte 0xd5, 0x4c, 0x89, 0xc0" : "=3Da"(data)); + break; + case 25: + asm(".byte 0xd5, 0x4c, 0x89, 0xc8" : "=3Da"(data)); + break; + case 26: + asm(".byte 0xd5, 0x4c, 0x89, 0xd0" : "=3Da"(data)); + break; + case 27: + asm(".byte 0xd5, 0x4c, 0x89, 0xd8" : "=3Da"(data)); + break; + case 28: + asm(".byte 0xd5, 0x4c, 0x89, 0xe0" : "=3Da"(data)); + break; + case 29: + asm(".byte 0xd5, 0x4c, 0x89, 0xe8" : "=3Da"(data)); + break; + case 30: + asm(".byte 0xd5, 0x4c, 0x89, 0xf0" : "=3Da"(data)); + break; + case 31: + asm(".byte 0xd5, 0x4c, 0x89, 0xf8" : "=3Da"(data)); + break; + default: + BUG(); + } + + return data; +} + +static inline void write_egpr(int reg, unsigned long data) +{ + /* mov %%rax, %r16...%r31*/ + switch (reg) { + case 16: + asm(".byte 0xd5, 0x18, 0x89, 0xc0" : : "a"(data)); + break; + case 17: + asm(".byte 0xd5, 0x18, 0x89, 0xc1" : : "a"(data)); + break; + case 18: + asm(".byte 0xd5, 0x18, 0x89, 0xc2" : : "a"(data)); + break; + case 19: + asm(".byte 0xd5, 0x18, 0x89, 0xc3" : : "a"(data)); + break; + case 20: + asm(".byte 0xd5, 0x18, 0x89, 0xc4" : : "a"(data)); + break; + case 21: + asm(".byte 0xd5, 0x18, 0x89, 0xc5" : : "a"(data)); + break; + case 22: + asm(".byte 0xd5, 0x18, 0x89, 0xc6" : : "a"(data)); + break; + case 23: + asm(".byte 0xd5, 0x18, 0x89, 0xc7" : : "a"(data)); + break; + case 24: + asm(".byte 0xd5, 0x19, 0x89, 0xc0" : : "a"(data)); + break; + case 25: + asm(".byte 0xd5, 0x19, 0x89, 0xc1" : : "a"(data)); + break; + case 26: + asm(".byte 0xd5, 0x19, 0x89, 0xc2" : : "a"(data)); + break; + case 27: + asm(".byte 0xd5, 0x19, 0x89, 0xc3" : : "a"(data)); + break; + case 28: + asm(".byte 0xd5, 0x19, 0x89, 0xc4" : : "a"(data)); + break; + case 29: + asm(".byte 0xd5, 0x19, 0x89, 0xc5" : : "a"(data)); + break; + case 30: + asm(".byte 0xd5, 0x19, 0x89, 0xc6" : : "a"(data)); + break; + case 31: + asm(".byte 0xd5, 0x19, 0x89, 0xc7" : : "a"(data)); + break; + default: + BUG(); + } +} + static inline void cpu_relax(void) { asm volatile("rep; nop" ::: "memory"); diff --git a/tools/testing/selftests/kvm/x86/apx_test.c b/tools/testing/sel= ftests/kvm/x86/apx_test.c new file mode 100644 index 000000000000..796ed9eb6957 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/apx_test.c @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "processor.h" + +enum stages { + GUEST_UPDATE, + USERSPACE_UPDATE, + GUEST_APXOFF, +}; + +enum egpr_ops { + EGPRS_WRITE, + EGPRS_CHECK, +}; + +#define for_each_egpr(reg) for (reg =3D 16; reg <=3D 31; reg++) + +/* + * Deterministic per-stage test values for EGPRs so that guest and + * userspace can validate state transitions. + */ +static inline unsigned long egpr_data(enum stages stage, int reg) +{ + switch (stage) { + case GUEST_UPDATE: + return 0xabcd + reg; + case USERSPACE_UPDATE: + return 0xbcde + reg; + case GUEST_APXOFF: + return 0xcdef + reg; + default: + return 0; + } +} + +/* + * Read/write or validate EGPR values either directly via registers + * (guest context) or via a provided buffer (userspace XSAVE). + */ +static bool handle_egprs(enum egpr_ops ops, unsigned long *egprs, enum sta= ges stage) +{ + unsigned long data; + int reg; + + for_each_egpr(reg) { + data =3D egpr_data(stage, reg); + + if (ops =3D=3D EGPRS_WRITE) { + if (egprs) + egprs[reg - 16] =3D data; + else + write_egpr(reg, data); + continue; + } + + if (ops !=3D EGPRS_CHECK) + return false; + + if (egprs) { + if (egprs[reg - 16] !=3D data) + return false; + continue; + } + + if (read_egpr(reg) !=3D data) + return false; + } + + return true; +} + +static void write_egprs(enum stages stage) +{ + handle_egprs(EGPRS_WRITE, NULL, stage); +} + +static bool validate_egprs(enum stages stage) +{ + return handle_egprs(EGPRS_CHECK, NULL, stage); +} + +static void test_guest_update(void) +{ + write_egprs(GUEST_UPDATE); + GUEST_SYNC(GUEST_UPDATE); + GUEST_ASSERT(validate_egprs(GUEST_UPDATE)); +} + +static void test_userspace_update(void) +{ + /* Userspace updates EGPR state via the KVM XSAVE ABI */ + GUEST_SYNC(USERSPACE_UPDATE); + GUEST_ASSERT(validate_egprs(USERSPACE_UPDATE)); +} + +static void test_guest_apxoff(void) +{ + write_egprs(GUEST_APXOFF); + /* Disable APX to verify state is preserved */ + GUEST_ASSERT(!xsetbv_safe(0, this_cpu_supported_xcr0() & ~XFEATURE_MASK_A= PX)); + GUEST_SYNC(GUEST_APXOFF); + GUEST_ASSERT(!xsetbv_safe(0, this_cpu_supported_xcr0())); + GUEST_ASSERT(validate_egprs(GUEST_APXOFF)); +} + +static void guest_code(void) +{ + set_cr4(get_cr4() | X86_CR4_OSXSAVE); + GUEST_ASSERT(!xsetbv_safe(0, this_cpu_supported_xcr0())); + + test_guest_update(); + test_userspace_update(); + test_guest_apxoff(); + + GUEST_DONE(); +} + +#define X86_PROPERTY_XSTATE_APX_OFFSET KVM_X86_CPU_PROPERTY(0xd, 19, EBX, = 0, 31) +#define XSAVE_HDR_OFFSET 512 + +static inline unsigned long *xsave_egprs(void *xsave) +{ + return xsave + kvm_cpu_property(X86_PROPERTY_XSTATE_APX_OFFSET); +} + +static inline void xstatebv_set(void *xsave, uint64_t mask) +{ + *(uint64_t *)(xsave + XSAVE_HDR_OFFSET) |=3D mask; +} + +static void write_xsave_egprs(void *xsave, enum stages stage) +{ + handle_egprs(EGPRS_WRITE, xsave_egprs(xsave), stage); + xstatebv_set(xsave, XFEATURE_MASK_APX); +} + +static bool validate_xsave_egprs(void *xsave, enum stages stage) +{ + return handle_egprs(EGPRS_CHECK, xsave_egprs(xsave), stage); +} + +int main(int argc, char *argv[]) +{ + struct kvm_xsave *xsave; + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + enum stages stage; + struct ucall uc; + int xsave_size; + + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_XSAVE)); + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_APX)); + + vm =3D vm_create_with_one_vcpu(&vcpu, guest_code); + xsave_size =3D vm_check_cap(vcpu->vm, KVM_CAP_XSAVE2); + TEST_ASSERT(xsave_size, "KVM_CAP_XSAVE2 not supported"); + xsave =3D malloc(xsave_size); + TEST_ASSERT(xsave, "Failed to allocate XSAVE buffer"); + + while (1) { + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + + switch (get_ucall(vcpu, &uc)) { + case UCALL_ABORT: + REPORT_GUEST_ASSERT(uc); + break; + case UCALL_SYNC: { + stage =3D uc.args[1]; + vcpu_xsave_get(vcpu, xsave); + if (stage =3D=3D USERSPACE_UPDATE) { + write_xsave_egprs(xsave, stage); + } else { + TEST_ASSERT(validate_xsave_egprs(xsave, stage), + "EGPR state mismatch in userspace XSAVE buffer"); + } + vcpu_xsave_set(vcpu, xsave); + break; + } + case UCALL_DONE: + goto done; + default: + TEST_FAIL("Unknown ucall %lu", uc.cmd); + } + } + +done: + free(xsave); + kvm_vm_free(vm); + return 0; +} --=20 2.51.0 From nobody Fri Jun 12 23:47:58 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 3EA3A377567; Tue, 12 May 2026 01:40:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550043; cv=none; b=bob4StwDcEdynqbZGyehtH1uY3kVCQ0iOvc+KQXDOm04z8OhU35n6lUkb/cTyEh/pcf1kBXcYCKrZegKVccuuEqKKbAUhWn4axhJjW/3ik0n/eC9WwldLBEKTP7AIUn/hiS76qWr5idqbhE2MnxloQZs/8dizQ3qlU0hYqr5Il8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778550043; c=relaxed/simple; bh=kDBtMaYWjk5NvmUllhFtCoGexQHRWExwMpcbE6sdArs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AyF5k+LdxP1Gl2owfUoxNNYBzOFEioFXMbOiAVevZBehAhQn73/SwZFn3VrY7+yyRpDZlr0FFaMwg9EFa3tzDtcrqBZGIGL1m+nKDLDcu4rDDDKR98iGjvU51MJzAZz418fDSoImIV3yHJ2brAzyIkpsO8v3ntSQOzF32hO+1R8= 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=MDsawDBx; arc=none smtp.client-ip=198.175.65.14 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="MDsawDBx" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778550042; x=1810086042; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=kDBtMaYWjk5NvmUllhFtCoGexQHRWExwMpcbE6sdArs=; b=MDsawDBxxtFJVAQXtMbC0tjsVxwWQQHv02jb+D10+XJneBUWU2WSPPTe KlRMSTBvulMj1ZckebH30Uqugg5LPLyxGyISmUiP+MqVPDxBl2RZ72Pn6 ufjH0lwZYOCe++4YySkpMyrPLVkOZfEGsatvOJz8lx93tZ7hb7EzKp9cu OuH/DyqFnAx4dBAwqD7IAjL8ID4PgMcTaZ7ex5cYYNU7ufDBGvQlfhVud 60moEXEteUwJUChvsJOAIZisfskYESD0acGi97+ZG+kDYtKMqHHVKa6P6 FoEgM9zCu0puU2h3GdtdTxmY+Ln3jy/5vvUJMdff5kM9iJgnf7SyQDK1C Q==; X-CSE-ConnectionGUID: 0QMAGANoT9GDK7EUafuECg== X-CSE-MsgGUID: pS2XXzEETfSZVc1k7yOVMQ== X-IronPort-AV: E=McAfee;i="6800,10657,11783"; a="83322203" X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="83322203" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2026 18:40:34 -0700 X-CSE-ConnectionGUID: dEJbdrG1TiGEoLvKFLLgQw== X-CSE-MsgGUID: 0yFJeiXCSmOuwkOWyUiqWQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,230,1770624000"; d="scan'208";a="234572843" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.106]) by fmviesa007.fm.intel.com with ESMTP; 11 May 2026 18:40:34 -0700 From: "Chang S. Bae" To: pbonzini@redhat.com, seanjc@google.com Cc: kvm@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, chao.gao@intel.com, chang.seok.bae@intel.com Subject: [PATCH v4 21/21] KVM: x86: selftests: Add APX state handling and XCR0 sanity checks Date: Tue, 12 May 2026 01:15:02 +0000 Message-ID: <20260512011502.53072-22-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260512011502.53072-1-chang.seok.bae@intel.com> References: <20260512011502.53072-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Now that KVM exposes the APX feature to guests, extend some existing selftests to validate XCR0 configuration and state management. Since APX repurposes the XSAVE area previously used by MPX in the non-compacted format, add a check to ensure that MPX 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 --- tools/testing/selftests/kvm/x86/state_test.c | 3 +++ .../selftests/kvm/x86/xcr0_cpuid_test.c | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/tools/testing/selftests/kvm/x86/state_test.c b/tools/testing/s= elftests/kvm/x86/state_test.c index 409c6cc9f921..7d93d62fc6a5 100644 --- a/tools/testing/selftests/kvm/x86/state_test.c +++ b/tools/testing/selftests/kvm/x86/state_test.c @@ -171,6 +171,9 @@ static void __attribute__((__flatten__)) guest_code(voi= d *arg) asm volatile ("vmovupd %0, %%zmm16" :: "m" (buffer)); } =20 + if (supported_xcr0 & XFEATURE_MASK_APX) + write_egpr(16, 0xcccccccc); + if (this_cpu_has(X86_FEATURE_MPX)) { u64 bounds[2] =3D { 10, 0xffffffffull }; u64 output[2] =3D { }; diff --git a/tools/testing/selftests/kvm/x86/xcr0_cpuid_test.c b/tools/test= ing/selftests/kvm/x86/xcr0_cpuid_test.c index 40dc9e6b3fad..f74978ef5951 100644 --- a/tools/testing/selftests/kvm/x86/xcr0_cpuid_test.c +++ b/tools/testing/selftests/kvm/x86/xcr0_cpuid_test.c @@ -46,6 +46,20 @@ do { \ __supported, (xfeatures)); \ } while (0) =20 +/* + * Verify that mutually exclusive architectural features do not overlap. + * For example, APX and MPX must never be reported as supported together. + */ +#define ASSERT_XFEATURE_CONFLICT(supported_xcr0, xfeatures, conflicts) \ +do { \ + uint64_t __supported =3D (supported_xcr0) & ((xfeatures) | (conflicts)); = \ + \ + __GUEST_ASSERT((__supported & (xfeatures)) !=3D (xfeatures) || \ + !(__supported & (conflicts)), \ + "supported =3D 0x%lx, xfeatures =3D 0x%llx, conflicts =3D 0x%llx"= , \ + __supported, (xfeatures), (conflicts)); \ +} while (0) + static void guest_code(void) { u64 initial_xcr0; @@ -79,6 +93,11 @@ static void guest_code(void) ASSERT_ALL_OR_NONE_XFEATURE(supported_xcr0, XFEATURE_MASK_XTILE); =20 + /* Check APX by ensuring MPX is not exposed concurrently */ + ASSERT_XFEATURE_CONFLICT(supported_xcr0, + XFEATURE_MASK_APX, + XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR); + vector =3D xsetbv_safe(0, XFEATURE_MASK_FP); __GUEST_ASSERT(!vector, "Expected success on XSETBV(FP), got %s", --=20 2.51.0