From nobody Sun Oct 5 18:17:32 2025 Received: from mail.zytor.com (terminus.zytor.com [198.137.202.136]) (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 835572E0B48; Wed, 30 Jul 2025 17:47:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.137.202.136 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753897628; cv=none; b=ciUEKcTx0PSqRlPC/ngN3dGCD7sgvwb7nepHOwRjtgDs43g/a1MayjUgGgXSYAEII1pF92OcO8g1gAMK8/I5q2uGJxnbT3bBv7LltDH/0xvCbUKjU5MTmpPZZ0AJ8YwzskEoLuZgY3B7oFezuxdYObgfpcolX8pf319X37CqSmc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753897628; c=relaxed/simple; bh=YkaTqbIa0Lhu6eQvvxFvCSIWv25wLG3CI3TsmldTmkY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DK4EdqYC1V/O0T9TS6nbf3aZhtZ2Ql8a8l4H5AUGpxf0+vBcFYSOik9TMT3/5/DmbB/K36lpz5qNeHOF8CXtPEJdwFY7bySJxb/b/H+K6Ny7UXZMRQyUiFqiPzgop31PClqSVUMD0p9ZYMQ0yzrA8pfpzs8PPQtDH/+AYgYq+To= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zytor.com; spf=pass smtp.mailfrom=zytor.com; dkim=pass (2048-bit key) header.d=zytor.com header.i=@zytor.com header.b=v81jOrED; arc=none smtp.client-ip=198.137.202.136 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zytor.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zytor.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=zytor.com header.i=@zytor.com header.b="v81jOrED" Received: from terminus.zytor.com (terminus.zytor.com [IPv6:2607:7c80:54:3:0:0:0:136]) (authenticated bits=0) by mail.zytor.com (8.18.1/8.17.1) with ESMTPSA id 56UHk6n91614815 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NO); Wed, 30 Jul 2025 10:46:30 -0700 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.zytor.com 56UHk6n91614815 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zytor.com; s=2025072201; t=1753897591; bh=AtjLVGdDRTprzlOEJ8gLfOLK0WV5tl2DOGR7MTz83Ck=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=v81jOrED/wlg+g4Wk9T47fvskf9RsIsoHwa5H0viJZ9Z6LKYJLSeMWI0PhctO8WY5 zyBAKbqaxawXTL6cjqJTLszWOyJ/dNNs5VaBIBbjw0BOk9B/FRvRt/5TFuHIX6fv2B Ni2A3FNtm8F00yvoAJ6l/qVPoEJbGVyZWWWANQ99XCdmhVS/KhYfHFoX+wksAxDWFc mptXmHgzyoDMFYdEme/Ew4KSG35Zb4Qbc2wC69/FKQHCTk2ZF/aqRmPW7wQGly9Zfe rXUAw1hggZXlMdoqkvXWDRPhKQcRPS8uRE+xjOM0oeounFWN5VXfZvzvjCA72bvah5 eLHHpU/2VCc0w== From: "Xin Li (Intel)" To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, xin@zytor.com, chao.gao@intel.com Subject: [PATCH v1 1/4] x86/cpufeatures: Add a CPU feature bit for MSR immediate form instructions Date: Wed, 30 Jul 2025 10:46:02 -0700 Message-ID: <20250730174605.1614792-2-xin@zytor.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20250730174605.1614792-1-xin@zytor.com> References: <20250730174605.1614792-1-xin@zytor.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" The immediate form of MSR access instructions are primarily motivated by performance, not code size: by having the MSR number in an immediate, it is available *much* earlier in the pipeline, which allows the hardware much more leeway about how a particular MSR is handled. Use a scattered CPU feature bit for MSR immediate form instructions. Suggested-by: Borislav Petkov (AMD) Signed-off-by: Xin Li (Intel) --- arch/x86/include/asm/cpufeatures.h | 1 + arch/x86/kernel/cpu/scattered.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpuf= eatures.h index 286d509f9363..75b43bbe2a6d 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -491,6 +491,7 @@ #define X86_FEATURE_TSA_SQ_NO (21*32+11) /* AMD CPU not vulnerable to TSA= -SQ */ #define X86_FEATURE_TSA_L1_NO (21*32+12) /* AMD CPU not vulnerable to TSA= -L1 */ #define X86_FEATURE_CLEAR_CPU_BUF_VM (21*32+13) /* Clear CPU buffers using= VERW before VMRUN */ +#define X86_FEATURE_MSR_IMM (21*32+14) /* MSR immediate form instructions= */ =20 /* * BUG word(s) diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattere= d.c index b4a1f6732a3a..5fe19bbe538e 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c @@ -27,6 +27,7 @@ static const struct cpuid_bit cpuid_bits[] =3D { { X86_FEATURE_APERFMPERF, CPUID_ECX, 0, 0x00000006, 0 }, { X86_FEATURE_EPB, CPUID_ECX, 3, 0x00000006, 0 }, { X86_FEATURE_INTEL_PPIN, CPUID_EBX, 0, 0x00000007, 1 }, + { X86_FEATURE_MSR_IMM, CPUID_ECX, 5, 0x00000007, 1 }, { X86_FEATURE_APX, CPUID_EDX, 21, 0x00000007, 1 }, { X86_FEATURE_RRSBA_CTRL, CPUID_EDX, 2, 0x00000007, 2 }, { X86_FEATURE_BHI_CTRL, CPUID_EDX, 4, 0x00000007, 2 }, --=20 2.50.1 From nobody Sun Oct 5 18:17:32 2025 Received: from mail.zytor.com (terminus.zytor.com [198.137.202.136]) (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 C02852DCF64; Wed, 30 Jul 2025 17:47:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.137.202.136 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753897628; cv=none; b=SxyAhNhzxS81KHLTtq2+Ghy38kVI7c/pz8pc+2OmOyhkaKii2e3el4v5iuO5D+8iOkZ0cd2sZoV68JconM0oWkD7O6AirdD0EFdBtV8VA10RBDH64cZuPy9yQOOBK57cFoMNxKfuzvVnlNSKuPr9EMdsNWXBBRoCU6sN1NMbg0o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753897628; c=relaxed/simple; bh=0Kc7jvARdLyXdBvQ6trNh3aGtpd2HrUi9jADvEjuC+E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hkswIqsUIkTe3IfiHcTz8sXUUrcqo2zKcEtaOYRZDLCPfi5y2dH+R5D5BzzEt1OYe6HR9FgHDucYdGcsSxjJildgdejk+3a0sPQ9WW1V6HP6LSfgsT/1t0PBBbmkKXxBA21INmiST9J3Y9c94Kfrn8YCEEQct/haSx+kUqesvNM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zytor.com; spf=pass smtp.mailfrom=zytor.com; dkim=pass (2048-bit key) header.d=zytor.com header.i=@zytor.com header.b=QxTfTGBR; arc=none smtp.client-ip=198.137.202.136 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zytor.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zytor.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=zytor.com header.i=@zytor.com header.b="QxTfTGBR" Received: from terminus.zytor.com (terminus.zytor.com [IPv6:2607:7c80:54:3:0:0:0:136]) (authenticated bits=0) by mail.zytor.com (8.18.1/8.17.1) with ESMTPSA id 56UHk6nA1614815 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NO); Wed, 30 Jul 2025 10:46:31 -0700 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.zytor.com 56UHk6nA1614815 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zytor.com; s=2025072201; t=1753897591; bh=2zF97TfTyDzxj7Meh54oh9Ub3fo+pB2wdmcB/Olws2w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QxTfTGBRMfI1qBGB5i3atkV5F3beDhlw+p8rjk33wM1js2ftX2kM7tMbiuq4Z2jO+ v3zuk4bhutgl7StYC2DQkSRwFelu8u3TEWFp5s7P3leOAFN6+FrI4ufDXz9MYfkIJh PH2J6glXOG2k7cVA5rgar6bPeQXeGH8e4WmJkSOd+7ZWE0pmgKFCK/Zh8d1+wHj0I3 InRQQj0eRUya4H5bpxSIc2MWYIy3CoX8RuSOaHjFf3CRVaTDXSnbkCmCNjrNN/Qdvd 01rRoqgXjdN9/dmZjW9Ii9F42sW9iQsmFAlwRb+Xj/vyg0L8fBiiEovJ3jodCJ9DAj oN7OVI7jsSzWQ== From: "Xin Li (Intel)" To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, xin@zytor.com, chao.gao@intel.com Subject: [PATCH v1 2/4] KVM: x86: Introduce MSR read/write emulation helpers Date: Wed, 30 Jul 2025 10:46:03 -0700 Message-ID: <20250730174605.1614792-3-xin@zytor.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20250730174605.1614792-1-xin@zytor.com> References: <20250730174605.1614792-1-xin@zytor.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 helper functions to centralize guest MSR read and write emulation. This change consolidates the MSR emulation logic and makes it easier to extend support for new MSR-related VM exit reasons introduced with the immediate form of MSR instructions. Signed-off-by: Xin Li (Intel) --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/x86.c | 67 +++++++++++++++++++++++---------- 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index f19a76d3ca0e..a854d9a166fe 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -201,6 +201,7 @@ enum kvm_reg { VCPU_EXREG_SEGMENTS, VCPU_EXREG_EXIT_INFO_1, VCPU_EXREG_EXIT_INFO_2, + VCPU_EXREG_EDX_EAX, }; =20 enum { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index a1c49bc681c4..5086c3b30345 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2024,54 +2024,71 @@ static int kvm_msr_user_space(struct kvm_vcpu *vcpu= , u32 index, return 1; } =20 -int kvm_emulate_rdmsr(struct kvm_vcpu *vcpu) +static int kvm_emulate_get_msr(struct kvm_vcpu *vcpu, u32 msr, int reg) { - u32 ecx =3D kvm_rcx_read(vcpu); u64 data; int r; =20 - r =3D kvm_get_msr_with_filter(vcpu, ecx, &data); + r =3D kvm_get_msr_with_filter(vcpu, msr, &data); =20 if (!r) { - trace_kvm_msr_read(ecx, data); + trace_kvm_msr_read(msr, data); =20 - kvm_rax_write(vcpu, data & -1u); - kvm_rdx_write(vcpu, (data >> 32) & -1u); + if (reg =3D=3D VCPU_EXREG_EDX_EAX) { + kvm_rax_write(vcpu, data & -1u); + kvm_rdx_write(vcpu, (data >> 32) & -1u); + } else { + kvm_register_write(vcpu, reg, data); + } } else { /* MSR read failed? See if we should ask user space */ - if (kvm_msr_user_space(vcpu, ecx, KVM_EXIT_X86_RDMSR, 0, + if (kvm_msr_user_space(vcpu, msr, KVM_EXIT_X86_RDMSR, 0, complete_fast_rdmsr, r)) return 0; - trace_kvm_msr_read_ex(ecx); + trace_kvm_msr_read_ex(msr); } =20 return kvm_x86_call(complete_emulated_msr)(vcpu, r); } + +int kvm_emulate_rdmsr(struct kvm_vcpu *vcpu) +{ + return kvm_emulate_get_msr(vcpu, kvm_rcx_read(vcpu), VCPU_EXREG_EDX_EAX); +} EXPORT_SYMBOL_GPL(kvm_emulate_rdmsr); =20 -int kvm_emulate_wrmsr(struct kvm_vcpu *vcpu) +static int kvm_emulate_set_msr(struct kvm_vcpu *vcpu, u32 msr, int reg) { - u32 ecx =3D kvm_rcx_read(vcpu); - u64 data =3D kvm_read_edx_eax(vcpu); + u64 data; int r; =20 - r =3D kvm_set_msr_with_filter(vcpu, ecx, data); + if (reg =3D=3D VCPU_EXREG_EDX_EAX) + data =3D kvm_read_edx_eax(vcpu); + else + data =3D kvm_register_read(vcpu, reg); + + r =3D kvm_set_msr_with_filter(vcpu, msr, data); =20 if (!r) { - trace_kvm_msr_write(ecx, data); + trace_kvm_msr_write(msr, data); } else { /* MSR write failed? See if we should ask user space */ - if (kvm_msr_user_space(vcpu, ecx, KVM_EXIT_X86_WRMSR, data, + if (kvm_msr_user_space(vcpu, msr, KVM_EXIT_X86_WRMSR, data, complete_fast_msr_access, r)) return 0; /* Signal all other negative errors to userspace */ if (r < 0) return r; - trace_kvm_msr_write_ex(ecx, data); + trace_kvm_msr_write_ex(msr, data); } =20 return kvm_x86_call(complete_emulated_msr)(vcpu, r); } + +int kvm_emulate_wrmsr(struct kvm_vcpu *vcpu) +{ + return kvm_emulate_set_msr(vcpu, kvm_rcx_read(vcpu), VCPU_EXREG_EDX_EAX); +} EXPORT_SYMBOL_GPL(kvm_emulate_wrmsr); =20 int kvm_emulate_as_nop(struct kvm_vcpu *vcpu) @@ -2163,9 +2180,8 @@ static int handle_fastpath_set_tscdeadline(struct kvm= _vcpu *vcpu, u64 data) return 0; } =20 -fastpath_t handle_fastpath_set_msr_irqoff(struct kvm_vcpu *vcpu) +static fastpath_t handle_set_msr_irqoff(struct kvm_vcpu *vcpu, u32 msr, in= t reg) { - u32 msr =3D kvm_rcx_read(vcpu); u64 data; fastpath_t ret; bool handled; @@ -2174,11 +2190,19 @@ fastpath_t handle_fastpath_set_msr_irqoff(struct kv= m_vcpu *vcpu) =20 switch (msr) { case APIC_BASE_MSR + (APIC_ICR >> 4): - data =3D kvm_read_edx_eax(vcpu); + if (reg =3D=3D VCPU_EXREG_EDX_EAX) + data =3D kvm_read_edx_eax(vcpu); + else + data =3D kvm_register_read(vcpu, reg); + handled =3D !handle_fastpath_set_x2apic_icr_irqoff(vcpu, data); break; case MSR_IA32_TSC_DEADLINE: - data =3D kvm_read_edx_eax(vcpu); + if (reg =3D=3D VCPU_EXREG_EDX_EAX) + data =3D kvm_read_edx_eax(vcpu); + else + data =3D kvm_register_read(vcpu, reg); + handled =3D !handle_fastpath_set_tscdeadline(vcpu, data); break; default: @@ -2200,6 +2224,11 @@ fastpath_t handle_fastpath_set_msr_irqoff(struct kvm= _vcpu *vcpu) =20 return ret; } + +fastpath_t handle_fastpath_set_msr_irqoff(struct kvm_vcpu *vcpu) +{ + return handle_set_msr_irqoff(vcpu, kvm_rcx_read(vcpu), VCPU_EXREG_EDX_EAX= ); +} EXPORT_SYMBOL_GPL(handle_fastpath_set_msr_irqoff); =20 /* --=20 2.50.1 From nobody Sun Oct 5 18:17:32 2025 Received: from mail.zytor.com (terminus.zytor.com [198.137.202.136]) (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 07A2B2DA75B; Wed, 30 Jul 2025 17:47:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.137.202.136 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753897627; cv=none; b=eM00idzpiYgGJA/7TbgP9u2kNifOJ66hGUMT6Q5HFcUxHWSvEiEgpnwboIYx92JoeiwxWPsuhUoHjobvK9OEiG/t8zGNJg3sf2FAtIHr4ra/KYPl9VgvYyB/Hup0u8gUVpWtJ7t9u4O0RceaS9xm2OZFpmli/A5zmidKwVgPCDg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753897627; c=relaxed/simple; bh=YBJus5C8l5AMo62+7/2sG3d8ceo/0qQLJ1V6dkpFBaw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=S7FOKeDii781uHKJbtoEHZrEtWbxTuaBTRionVNvup576E+9DZu5j1R85L4BtSIIO3RHRAOxzq2qiGyv6VxKCganbQhoXsT0DQH1S8+Cmm4INmKE1nWozSStHlzAStUyimJHNyBni/MbqF52QVI9od+V2hVFmUeppz4oh+4cQDA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zytor.com; spf=pass smtp.mailfrom=zytor.com; dkim=pass (2048-bit key) header.d=zytor.com header.i=@zytor.com header.b=o2LoQHDL; arc=none smtp.client-ip=198.137.202.136 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zytor.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zytor.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=zytor.com header.i=@zytor.com header.b="o2LoQHDL" Received: from terminus.zytor.com (terminus.zytor.com [IPv6:2607:7c80:54:3:0:0:0:136]) (authenticated bits=0) by mail.zytor.com (8.18.1/8.17.1) with ESMTPSA id 56UHk6nB1614815 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NO); Wed, 30 Jul 2025 10:46:32 -0700 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.zytor.com 56UHk6nB1614815 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zytor.com; s=2025072201; t=1753897592; bh=SZMIKmky2zV5qXb0yssonRrDBOK8LL684EUF4Rj+HaY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=o2LoQHDLwJzb5swEyLMdRQtcHydVM44dg9fAe37C8+Ab9ll/DUAaevydDbA3v8wTs ZlMKCoPHlBtMTFkhm3A1uelx+5spnpIMvr8LdFDy0SVXJy9fd6GZAyFj3LNGpgzqAp +hdho1x1BU1oCuEwhZrBJQGvnTEWqh6XdQkOQNrCZkR7KhLyMA+QefMrxOTGwILv4X 358GM4M3dv+c3vZnf9p9u+wuAVoO8gHCYIwLW1RUWKS98EvTipZQUre1g8xY34pBUE 9T7eQC1HjEqMdPlaD6xuPjduwEbuLDBDoh6GfM4XoVy8f4NzupZDyzkJVtXXo6xzFQ Y8ORGDhpPLTtg== From: "Xin Li (Intel)" To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, xin@zytor.com, chao.gao@intel.com Subject: [PATCH v1 3/4] KVM: VMX: Handle the immediate form of MSR instructions Date: Wed, 30 Jul 2025 10:46:04 -0700 Message-ID: <20250730174605.1614792-4-xin@zytor.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20250730174605.1614792-1-xin@zytor.com> References: <20250730174605.1614792-1-xin@zytor.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" Handle two newly introduced VM exit reasons associated with the immediate form of MSR instructions. For proper virtualization of the immediate form of MSR instructions, Intel VMX architecture adds the following changes: 1) The immediate form of RDMSR uses VM exit reason 84. 2) The immediate form of WRMSRNS uses VM exit reason 85. 3) For both VM exit reasons 84 and 85, the exit qualification is set to the MSR address causing the VM exit. 4) Bits 3 ~ 6 of the VM exit instruction information field represent the operand register used in the immediate form of MSR instruction. 5) The VM-exit instruction length field records the size of the immediate form of the MSR instruction. Add code to properly virtualize the immediate form of MSR instructions. Signed-off-by: Xin Li (Intel) --- arch/x86/include/asm/kvm_host.h | 3 +++ arch/x86/include/uapi/asm/vmx.h | 6 +++++- arch/x86/kvm/vmx/vmx.c | 26 ++++++++++++++++++++++++++ arch/x86/kvm/vmx/vmx.h | 5 +++++ arch/x86/kvm/x86.c | 29 ++++++++++++++++++++++++++++- arch/x86/kvm/x86.h | 1 + 6 files changed, 68 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index a854d9a166fe..f8d85efd47b6 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -979,6 +979,7 @@ struct kvm_vcpu_arch { unsigned long guest_debug_dr7; u64 msr_platform_info; u64 msr_misc_features_enables; + int rdmsr_reg; =20 u64 mcg_cap; u64 mcg_status; @@ -2156,7 +2157,9 @@ int __kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u= 64 *data, bool host_initiat int kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data); int kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data); int kvm_emulate_rdmsr(struct kvm_vcpu *vcpu); +int kvm_emulate_rdmsr_imm(struct kvm_vcpu *vcpu, u32 msr, int reg); int kvm_emulate_wrmsr(struct kvm_vcpu *vcpu); +int kvm_emulate_wrmsr_imm(struct kvm_vcpu *vcpu, u32 msr, int reg); int kvm_emulate_as_nop(struct kvm_vcpu *vcpu); int kvm_emulate_invd(struct kvm_vcpu *vcpu); int kvm_emulate_mwait(struct kvm_vcpu *vcpu); diff --git a/arch/x86/include/uapi/asm/vmx.h b/arch/x86/include/uapi/asm/vm= x.h index f0f4a4cf84a7..9792e329343e 100644 --- a/arch/x86/include/uapi/asm/vmx.h +++ b/arch/x86/include/uapi/asm/vmx.h @@ -94,6 +94,8 @@ #define EXIT_REASON_BUS_LOCK 74 #define EXIT_REASON_NOTIFY 75 #define EXIT_REASON_TDCALL 77 +#define EXIT_REASON_MSR_READ_IMM 84 +#define EXIT_REASON_MSR_WRITE_IMM 85 =20 #define VMX_EXIT_REASONS \ { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \ @@ -158,7 +160,9 @@ { EXIT_REASON_TPAUSE, "TPAUSE" }, \ { EXIT_REASON_BUS_LOCK, "BUS_LOCK" }, \ { EXIT_REASON_NOTIFY, "NOTIFY" }, \ - { EXIT_REASON_TDCALL, "TDCALL" } + { EXIT_REASON_TDCALL, "TDCALL" }, \ + { EXIT_REASON_MSR_READ_IMM, "MSR_READ_IMM" }, \ + { EXIT_REASON_MSR_WRITE_IMM, "MSR_WRITE_IMM" } =20 #define VMX_EXIT_REASON_FLAGS \ { VMX_EXIT_REASONS_FAILED_VMENTRY, "FAILED_VMENTRY" } diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index aa157fe5b7b3..7129e7b1ef03 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -6003,6 +6003,22 @@ static int handle_notify(struct kvm_vcpu *vcpu) return 1; } =20 +static int handle_rdmsr_imm(struct kvm_vcpu *vcpu) +{ + u32 msr =3D vmx_get_exit_qual(vcpu); + int reg =3D vmx_get_instr_info_reg(vmcs_read32(VMX_INSTRUCTION_INFO)); + + return kvm_emulate_rdmsr_imm(vcpu, msr, reg); +} + +static int handle_wrmsr_imm(struct kvm_vcpu *vcpu) +{ + u32 msr =3D vmx_get_exit_qual(vcpu); + int reg =3D vmx_get_instr_info_reg(vmcs_read32(VMX_INSTRUCTION_INFO)); + + return kvm_emulate_wrmsr_imm(vcpu, msr, reg); +} + /* * The exit handlers return 1 if the exit was handled fully and guest exec= ution * may resume. Otherwise they set the kvm_run parameter to indicate what = needs @@ -6061,6 +6077,8 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu= *vcpu) =3D { [EXIT_REASON_ENCLS] =3D handle_encls, [EXIT_REASON_BUS_LOCK] =3D handle_bus_lock_vmexit, [EXIT_REASON_NOTIFY] =3D handle_notify, + [EXIT_REASON_MSR_READ_IMM] =3D handle_rdmsr_imm, + [EXIT_REASON_MSR_WRITE_IMM] =3D handle_wrmsr_imm, }; =20 static const int kvm_vmx_max_exit_handlers =3D @@ -6495,6 +6513,8 @@ static int __vmx_handle_exit(struct kvm_vcpu *vcpu, f= astpath_t exit_fastpath) #ifdef CONFIG_MITIGATION_RETPOLINE if (exit_reason.basic =3D=3D EXIT_REASON_MSR_WRITE) return kvm_emulate_wrmsr(vcpu); + else if (exit_reason.basic =3D=3D EXIT_REASON_MSR_WRITE_IMM) + return handle_wrmsr_imm(vcpu); else if (exit_reason.basic =3D=3D EXIT_REASON_PREEMPTION_TIMER) return handle_preemption_timer(vcpu); else if (exit_reason.basic =3D=3D EXIT_REASON_INTERRUPT_WINDOW) @@ -7171,6 +7191,12 @@ static fastpath_t vmx_exit_handlers_fastpath(struct = kvm_vcpu *vcpu, switch (vmx_get_exit_reason(vcpu).basic) { case EXIT_REASON_MSR_WRITE: return handle_fastpath_set_msr_irqoff(vcpu); + case EXIT_REASON_MSR_WRITE_IMM: { + u32 msr =3D vmx_get_exit_qual(vcpu); + int reg =3D vmx_get_instr_info_reg(vmcs_read32(VMX_INSTRUCTION_INFO)); + + return handle_fastpath_set_msr_imm_irqoff(vcpu, msr, reg); + } case EXIT_REASON_PREEMPTION_TIMER: return handle_fastpath_preemption_timer(vcpu, force_immediate_exit); case EXIT_REASON_HLT: diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index d3389baf3ab3..24d65dac5e89 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -706,6 +706,11 @@ static inline bool vmx_guest_state_valid(struct kvm_vc= pu *vcpu) =20 void dump_vmcs(struct kvm_vcpu *vcpu); =20 +static inline int vmx_get_instr_info_reg(u32 vmx_instr_info) +{ + return (vmx_instr_info >> 3) & 0xf; +} + static inline int vmx_get_instr_info_reg2(u32 vmx_instr_info) { return (vmx_instr_info >> 28) & 0xf; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 5086c3b30345..ed41d583aaae 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1962,9 +1962,14 @@ EXPORT_SYMBOL_GPL(kvm_set_msr); =20 static void complete_userspace_rdmsr(struct kvm_vcpu *vcpu) { - if (!vcpu->run->msr.error) { + if (vcpu->run->msr.error) + return; + + if (vcpu->arch.rdmsr_reg =3D=3D VCPU_EXREG_EDX_EAX) { kvm_rax_write(vcpu, (u32)vcpu->run->msr.data); kvm_rdx_write(vcpu, vcpu->run->msr.data >> 32); + } else { + kvm_register_write(vcpu, vcpu->arch.rdmsr_reg, vcpu->run->msr.data); } } =20 @@ -2041,6 +2046,8 @@ static int kvm_emulate_get_msr(struct kvm_vcpu *vcpu,= u32 msr, int reg) kvm_register_write(vcpu, reg, data); } } else { + vcpu->arch.rdmsr_reg =3D reg; + /* MSR read failed? See if we should ask user space */ if (kvm_msr_user_space(vcpu, msr, KVM_EXIT_X86_RDMSR, 0, complete_fast_rdmsr, r)) @@ -2057,6 +2064,12 @@ int kvm_emulate_rdmsr(struct kvm_vcpu *vcpu) } EXPORT_SYMBOL_GPL(kvm_emulate_rdmsr); =20 +int kvm_emulate_rdmsr_imm(struct kvm_vcpu *vcpu, u32 msr, int reg) +{ + return kvm_emulate_get_msr(vcpu, msr, reg); +} +EXPORT_SYMBOL_GPL(kvm_emulate_rdmsr_imm); + static int kvm_emulate_set_msr(struct kvm_vcpu *vcpu, u32 msr, int reg) { u64 data; @@ -2091,6 +2104,12 @@ int kvm_emulate_wrmsr(struct kvm_vcpu *vcpu) } EXPORT_SYMBOL_GPL(kvm_emulate_wrmsr); =20 +int kvm_emulate_wrmsr_imm(struct kvm_vcpu *vcpu, u32 msr, int reg) +{ + return kvm_emulate_set_msr(vcpu, msr, reg); +} +EXPORT_SYMBOL_GPL(kvm_emulate_wrmsr_imm); + int kvm_emulate_as_nop(struct kvm_vcpu *vcpu) { return kvm_skip_emulated_instruction(vcpu); @@ -2231,6 +2250,12 @@ fastpath_t handle_fastpath_set_msr_irqoff(struct kvm= _vcpu *vcpu) } EXPORT_SYMBOL_GPL(handle_fastpath_set_msr_irqoff); =20 +fastpath_t handle_fastpath_set_msr_imm_irqoff(struct kvm_vcpu *vcpu, u32 m= sr, int reg) +{ + return handle_set_msr_irqoff(vcpu, msr, reg); +} +EXPORT_SYMBOL_GPL(handle_fastpath_set_msr_imm_irqoff); + /* * Adapt set_msr() to msr_io()'s calling convention */ @@ -8387,6 +8412,8 @@ static int emulator_get_msr_with_filter(struct x86_em= ulate_ctxt *ctxt, return X86EMUL_UNHANDLEABLE; =20 if (r) { + vcpu->arch.rdmsr_reg =3D VCPU_EXREG_EDX_EAX; + if (kvm_msr_user_space(vcpu, msr_index, KVM_EXIT_X86_RDMSR, 0, complete_emulated_rdmsr, r)) return X86EMUL_IO_NEEDED; diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index bcfd9b719ada..f8d117a17c46 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -438,6 +438,7 @@ int x86_decode_emulated_instruction(struct kvm_vcpu *vc= pu, int emulation_type, int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, int emulation_type, void *insn, int insn_len); fastpath_t handle_fastpath_set_msr_irqoff(struct kvm_vcpu *vcpu); +fastpath_t handle_fastpath_set_msr_imm_irqoff(struct kvm_vcpu *vcpu, u32 m= sr, int reg); fastpath_t handle_fastpath_hlt(struct kvm_vcpu *vcpu); =20 extern struct kvm_caps kvm_caps; --=20 2.50.1 From nobody Sun Oct 5 18:17:32 2025 Received: from mail.zytor.com (terminus.zytor.com [198.137.202.136]) (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 079BA1D61BC; Wed, 30 Jul 2025 17:47:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.137.202.136 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753897627; cv=none; b=SxUo+dC3nQrrZYKZg5udPKKfEJItSDS3OtAm4gtYIZILbvcl2EL6YR7t1q35zEFMM2JXCJV7IF/sPvI2Fu9NdFuZDLKu/orpSkT3+PNJLBTyrqa8FCXLMcqoA79UWG7x4/fjo9CV1Jzydiv87Lzy8eyfyFdKWrrRYHC+xpQWUYg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753897627; c=relaxed/simple; bh=aaJMFoE37sgh+wzwzWl7WM582mW1fTk3P3KpLRSZlUg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=m7o2j+Nfr87PNNWLP9ZcQq22+ZrxIOhxCMFzPcJCc2O3Q/+LbvnioqFeTO+CtZzlkRLnu4eYCzEEbtVVZGt6En5sbKqxxug4RjgbGOZmruQNFm0j/BNQ1ycK/1Af+q2YYY3XTp04MlRAVYOewT6HCGpP7KNQH530TKpvSnac2Dk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zytor.com; spf=pass smtp.mailfrom=zytor.com; dkim=pass (2048-bit key) header.d=zytor.com header.i=@zytor.com header.b=hwNAxNs6; arc=none smtp.client-ip=198.137.202.136 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zytor.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zytor.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=zytor.com header.i=@zytor.com header.b="hwNAxNs6" Received: from terminus.zytor.com (terminus.zytor.com [IPv6:2607:7c80:54:3:0:0:0:136]) (authenticated bits=0) by mail.zytor.com (8.18.1/8.17.1) with ESMTPSA id 56UHk6nC1614815 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NO); Wed, 30 Jul 2025 10:46:32 -0700 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.zytor.com 56UHk6nC1614815 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zytor.com; s=2025072201; t=1753897593; bh=eHxfJAy9AKvLAEmlOqmd8PluQcEtX+QucQ1qvOJZ5Yg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hwNAxNs6zzacAi8vw8nrlsL0988mIY3QNmkVk/vW131nWyQNbzzgIYXazB65qhIqZ 3z4Ol83WiBzpyRH9n0Ndpzu+dQsV5cXUYYDzXZss1jxqN+fXsLtoX/ywxR/geKahNx pbaFXxGKWCEtzTDO8r9+bfh3ETI6SdrMdh4VxVYAHwFWaSMByQTIzzja8cumCs/BB1 fLiu2rNqMfgaeo9c0szkkyUMWuTYcih+G8YzGfkpH9JTWlF+MwuDgZ9LKQDRT4RRhg cUHKz+gOnTCw0cj58pe1+mRwiUAn1u+PmJCcYI+mIgIXBA+veK8CwSwdZjX2Jt4/uZ 9T2KqCEJVrT3g== From: "Xin Li (Intel)" To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, xin@zytor.com, chao.gao@intel.com Subject: [PATCH v1 4/4] KVM: x86: Advertise support for the immediate form of MSR instructions Date: Wed, 30 Jul 2025 10:46:05 -0700 Message-ID: <20250730174605.1614792-5-xin@zytor.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20250730174605.1614792-1-xin@zytor.com> References: <20250730174605.1614792-1-xin@zytor.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" Advertise support for the immediate form of MSR instructions to userspace if the instructions are supported by the underlying CPU. The immediate form of MSR access instructions are primarily motivated by performance, not code size: by having the MSR number in an immediate, it is available *much* earlier in the pipeline, which allows the hardware much more leeway about how a particular MSR is handled. Signed-off-by: Xin Li (Intel) --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/cpuid.c | 6 +++++- arch/x86/kvm/reverse_cpuid.h | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index f8d85efd47b6..9ca7ec17c1c5 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -772,6 +772,7 @@ enum kvm_only_cpuid_leafs { CPUID_7_2_EDX, CPUID_24_0_EBX, CPUID_8000_0021_ECX, + CPUID_7_1_ECX, 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 e2836a255b16..eaaa9203d4d9 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -985,6 +985,10 @@ void kvm_set_cpu_caps(void) F(LAM), ); =20 + kvm_cpu_cap_init(CPUID_7_1_ECX, + SCATTERED_F(MSR_IMM), + ); + kvm_cpu_cap_init(CPUID_7_1_EDX, F(AVX_VNNI_INT8), F(AVX_NE_CONVERT), @@ -1411,9 +1415,9 @@ static inline int __do_cpuid_func(struct kvm_cpuid_ar= ray *array, u32 function) goto out; =20 cpuid_entry_override(entry, CPUID_7_1_EAX); + cpuid_entry_override(entry, CPUID_7_1_ECX); cpuid_entry_override(entry, CPUID_7_1_EDX); entry->ebx =3D 0; - entry->ecx =3D 0; } if (max_idx >=3D 2) { entry =3D do_host_cpuid(array, function, 2); diff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h index c53b92379e6e..743ab25ba787 100644 --- a/arch/x86/kvm/reverse_cpuid.h +++ b/arch/x86/kvm/reverse_cpuid.h @@ -25,6 +25,9 @@ #define KVM_X86_FEATURE_SGX2 KVM_X86_FEATURE(CPUID_12_EAX, 1) #define KVM_X86_FEATURE_SGX_EDECCSSA KVM_X86_FEATURE(CPUID_12_EAX, 11) =20 +/* Intel-defined sub-features, CPUID level 0x00000007:1 (ECX) */ +#define KVM_X86_FEATURE_MSR_IMM KVM_X86_FEATURE(CPUID_7_1_ECX, 5) + /* Intel-defined sub-features, CPUID level 0x00000007:1 (EDX) */ #define X86_FEATURE_AVX_VNNI_INT8 KVM_X86_FEATURE(CPUID_7_1_EDX, 4) #define X86_FEATURE_AVX_NE_CONVERT KVM_X86_FEATURE(CPUID_7_1_EDX, 5) @@ -87,6 +90,7 @@ static const struct cpuid_reg reverse_cpuid[] =3D { [CPUID_7_2_EDX] =3D { 7, 2, CPUID_EDX}, [CPUID_24_0_EBX] =3D { 0x24, 0, CPUID_EBX}, [CPUID_8000_0021_ECX] =3D {0x80000021, 0, CPUID_ECX}, + [CPUID_7_1_ECX] =3D { 7, 1, CPUID_ECX}, }; =20 /* @@ -128,6 +132,7 @@ static __always_inline u32 __feature_translate(int x86_= feature) KVM_X86_TRANSLATE_FEATURE(BHI_CTRL); KVM_X86_TRANSLATE_FEATURE(TSA_SQ_NO); KVM_X86_TRANSLATE_FEATURE(TSA_L1_NO); + KVM_X86_TRANSLATE_FEATURE(MSR_IMM); default: return x86_feature; } --=20 2.50.1