From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.17]) (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 47E913BE146; Thu, 5 Mar 2026 17:44:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.17 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732674; cv=none; b=Drj5+OSXK8kOH8SiMenn4+WIXE6wW3ENtaB/r0DxNMvHCTnPCqATq6+kH0LdEdg3fG+fKstl0sT0jZBLZ1R32e70n11/mOnpwLj/dC1AH0t/jSnK+vSjOV9zdjtzILT04gWJPm2aUzJAOIfGNEd4+fN1Dj4hTIogkkZVg/hlyQY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732674; c=relaxed/simple; bh=zXjCzbLVKWGoKD9CpmDEyJwKzLu+XjEZnAgUQdMsLuA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=avbGDsiDxZeJ52JLEcRavAGPmPN/2T4dWMv1QAvHDOwMgsR12z9EHXMIUWDcylfR+uXufW0zUZKLl3T6hGYYhCtSB08easX0VmfNDTGN4Xujwa9Ae0VCwra3jWVdW64maY1cDo71BbJmSdzK4o3gHw7i71w4s4pzm3ewB7JYkdY= 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=mKlvqx1M; arc=none smtp.client-ip=198.175.65.17 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="mKlvqx1M" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732673; x=1804268673; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=zXjCzbLVKWGoKD9CpmDEyJwKzLu+XjEZnAgUQdMsLuA=; b=mKlvqx1ML+XKSU1xxBs+DbQmiR9tf/Bp01ArtON8K++uAPV5rxapJWAK NDr+S0+iOkPHjPHQutLzOlqvDLzB0gl+VsNxgxBE5dE5cHUa8QTHv/lXW EVcPvInTI+aCBeCdOM4mck/tCZrE+m9Gh7+AipmGYB93zzdj6pq5Z4cqH SgLa86m0yppUTAogNW7LFFc8NQulMIPXu0bx8EuHZuHFn4r5nxAqVP1DN Lqcxa9FK8n4gDeE5bc8mpDVxOrQhG9Wcbs420tbuIJ/f9rNO+zzYV6Rhb 7XNAIHdDb63FYQMqPMkX4iyMsq02RkOpgx20XqN8bHo+GCABs4onP9+pu w==; X-CSE-ConnectionGUID: FaLoEQr8TxixzGcjAYzaBQ== X-CSE-MsgGUID: 9Fc5k34/SQmd0irE/dUNxg== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="73798200" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="73798200" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa109.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:33 -0800 X-CSE-ConnectionGUID: eHi2tnhaS3Sk9Sv04u977Q== X-CSE-MsgGUID: oR6L9rMfS/+YqecgGRgE6g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="215527242" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by fmviesa006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:32 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org, Yang Zhong Subject: [PATCH v2 01/36] KVM: VMX: Detect APIC timer virtualization bit Date: Thu, 5 Mar 2026 09:43:41 -0800 Message-ID: <2a5757c34954ed3f90db2aec0aab5966f829018e.1772732517.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Yang Zhong Detect the APIC timer virtualization feature by setting the bit (bit 8) in the tertiary processor-based VM-execution controls. Additionally, define the new related VMCS fields necessary for managing this feature. Do not enable the feature bit in the tertiary VM exec control yet until the supporting logic is implemented. Signed-off-by: Yang Zhong Signed-off-by: Isaku Yamahata --- Changes: v1 -> v2: - Change KVM_OPTIONAL_VMX_TERTIARY_VM_EXEC_CONTROL to include apic timer virt bit to avoid compile time errors. Clear the bit when adjust_vmx_controls64() is called instead. --- arch/x86/include/asm/vmx.h | 6 ++++++ arch/x86/include/asm/vmxfeatures.h | 1 + arch/x86/kvm/vmx/vmx.c | 20 +++++++++++++++++++- arch/x86/kvm/vmx/vmx.h | 3 ++- 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 37080382df54..a9fe10cf1b4d 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -96,6 +96,7 @@ struct vmcs { * Definitions of Tertiary Processor-Based VM-Execution Controls. */ #define TERTIARY_EXEC_IPI_VIRT VMCS_CONTROL_BIT(IPI_VIRT) +#define TERTIARY_EXEC_GUEST_APIC_TIMER VMCS_CONTROL_BIT(GUEST_APIC_TIMER) =20 #define PIN_BASED_EXT_INTR_MASK VMCS_CONTROL_BIT(INTR_EXIT= ING) #define PIN_BASED_NMI_EXITING VMCS_CONTROL_BIT(NMI_EXITI= NG) @@ -204,6 +205,7 @@ enum vmcs_field { VIRTUAL_PROCESSOR_ID =3D 0x00000000, POSTED_INTR_NV =3D 0x00000002, LAST_PID_POINTER_INDEX =3D 0x00000008, + GUEST_APIC_TIMER_VECTOR =3D 0x0000000a, GUEST_ES_SELECTOR =3D 0x00000800, GUEST_CS_SELECTOR =3D 0x00000802, GUEST_SS_SELECTOR =3D 0x00000804, @@ -274,6 +276,8 @@ enum vmcs_field { SHARED_EPT_POINTER =3D 0x0000203C, PID_POINTER_TABLE =3D 0x00002042, PID_POINTER_TABLE_HIGH =3D 0x00002043, + GUEST_DEADLINE_VIR =3D 0x0000204e, + GUEST_DEADLINE_VIR_HIGH =3D 0x0000204f, GUEST_PHYSICAL_ADDRESS =3D 0x00002400, GUEST_PHYSICAL_ADDRESS_HIGH =3D 0x00002401, VMCS_LINK_POINTER =3D 0x00002800, @@ -298,6 +302,8 @@ enum vmcs_field { GUEST_BNDCFGS_HIGH =3D 0x00002813, GUEST_IA32_RTIT_CTL =3D 0x00002814, GUEST_IA32_RTIT_CTL_HIGH =3D 0x00002815, + GUEST_DEADLINE_PHY =3D 0x00002830, + GUEST_DEADLINE_PHY_HIGH =3D 0x00002831, HOST_IA32_PAT =3D 0x00002c00, HOST_IA32_PAT_HIGH =3D 0x00002c01, HOST_IA32_EFER =3D 0x00002c02, diff --git a/arch/x86/include/asm/vmxfeatures.h b/arch/x86/include/asm/vmxf= eatures.h index 09b1d7e607c1..f2eb4243bae4 100644 --- a/arch/x86/include/asm/vmxfeatures.h +++ b/arch/x86/include/asm/vmxfeatures.h @@ -90,4 +90,5 @@ =20 /* Tertiary Processor-Based VM-Execution Controls, word 3 */ #define VMX_FEATURE_IPI_VIRT ( 3*32+ 4) /* "ipi_virt" Enable IPI virtual= ization */ +#define VMX_FEATURE_GUEST_APIC_TIMER ( 3*32+ 8) /* Enable virtual APIC ts= c deadline */ #endif /* _ASM_X86_VMXFEATURES_H */ diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 9302c16571cd..4ccb2e42322d 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -2791,9 +2791,20 @@ static int setup_vmcs_config(struct vmcs_config *vmc= s_conf, =20 if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS) _cpu_based_3rd_exec_control =3D - adjust_vmx_controls64(KVM_OPTIONAL_VMX_TERTIARY_VM_EXEC_CONTROL, + adjust_vmx_controls64(KVM_OPTIONAL_VMX_TERTIARY_VM_EXEC_CONTROL + /* + * Disable apic timer + * virtualization until the logic + * is imlemented. + * Once it's supported, add + * TERTIARY_EXEC_GUEST_APIC_TIMER. + */ + & ~TERTIARY_EXEC_GUEST_APIC_TIMER, MSR_IA32_VMX_PROCBASED_CTLS3); =20 + if (!(_cpu_based_2nd_exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY)) + _cpu_based_3rd_exec_control &=3D ~TERTIARY_EXEC_GUEST_APIC_TIMER; + if (adjust_vmx_controls(KVM_REQUIRED_VMX_VM_EXIT_CONTROLS, KVM_OPTIONAL_VMX_VM_EXIT_CONTROLS, MSR_IA32_VMX_EXIT_CTLS, @@ -4636,6 +4647,13 @@ static u64 vmx_tertiary_exec_control(struct vcpu_vmx= *vmx) if (!enable_ipiv || !kvm_vcpu_apicv_active(&vmx->vcpu)) exec_control &=3D ~TERTIARY_EXEC_IPI_VIRT; =20 + /* + * APIC timer virtualization is supported only for TSC deadline mode. + * Disable for one-shot/periodic mode. Dynamically set/clear the bit + * on the guest timer mode change. Disable on reset state. + */ + exec_control &=3D ~TERTIARY_EXEC_GUEST_APIC_TIMER; + return exec_control; } =20 diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 70bfe81dea54..9a61f6bd8cc0 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -575,7 +575,8 @@ static inline u8 vmx_get_rvi(void) =20 #define KVM_REQUIRED_VMX_TERTIARY_VM_EXEC_CONTROL 0 #define KVM_OPTIONAL_VMX_TERTIARY_VM_EXEC_CONTROL \ - (TERTIARY_EXEC_IPI_VIRT) + (TERTIARY_EXEC_IPI_VIRT | \ + TERTIARY_EXEC_GUEST_APIC_TIMER) =20 #define BUILD_CONTROLS_SHADOW(lname, uname, bits) \ static inline void lname##_controls_set(struct vcpu_vmx *vmx, u##bits val)= \ --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.17]) (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 946B53D34AA; Thu, 5 Mar 2026 17:44:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.17 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732676; cv=none; b=VT7crFUu3dpXFPMYV1T7XBOLQ+udOmKnP/pBm2TAO1kPVRorfoMNW5tUAwstPxTShLpYsa8FcA0BdbYQ1H/ZxF0QlqZRWi1WYoEzPtAV55WIz4j5lv83rHqFgEaJhXP8PH5qQyMuxq4bRBXt3t8f0mv/wtib0YrGLhTYLYsjhPE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732676; c=relaxed/simple; bh=AndZdF2dnr4dl7StGRCBgKDGf0RD400+CZHrbT41vT0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mrD+FiCbqeT8pTxb7EslfhOLHd3vJrKUiREE+xEGdK5bR1BdW+Y5pikDAq50z38DrJqYrKe8IvHQxzD0GaBFzubY+OCPjw27tb9Qr9jeStmT9Hf4beKfGywoNvD9MnfdWoXPMNb0oecBNuiihGvbZ43Ap70/bh8FFdXtCh+AHsk= 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=fVGZPlpW; arc=none smtp.client-ip=198.175.65.17 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="fVGZPlpW" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732674; x=1804268674; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=AndZdF2dnr4dl7StGRCBgKDGf0RD400+CZHrbT41vT0=; b=fVGZPlpW6Em6DLCUr23RMBr6rwtu12WsLqUK9OqFnEwDOKwEvMqy2z89 ERaD1tOZJxrJvLR3Dp8hEl7i2ododS3FrioID1VhH/hnI0DtwGrfo6Aar kMrrt6WrHvGVXnx+toXHmehia2s2Ht17OjwEeZSaK8gMyRQjkfsbDCZTQ g/gIrOFhnA0FcHMl9KaPZZ1EgIVPt+WLB7831zk8l76Q9AOU7194mkcEn iLVxLj/YadZTV5RA991uUJs+FC/OAIxDISjg4wDdTBDB+iBYL3MRb7kap pMbohbeO63Y6v3JJz96WkIRMEmgdrHs8IfR7ki7na72SBrB8zNWHIr/zr g==; X-CSE-ConnectionGUID: CXu/IdQxTlWCaxAW0Qfqiw== X-CSE-MsgGUID: R2Bo+4odRoqKjC4wzMkqmQ== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="73798204" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="73798204" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa109.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:33 -0800 X-CSE-ConnectionGUID: 28hV1UAVTSy2MCJA/ScLuA== X-CSE-MsgGUID: di7V6GA2RA6PA3/7jUZHTg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="215527245" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by fmviesa006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:33 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org, Yang Zhong Subject: [PATCH v2 02/36] KVM: x86: Implement APIC virt timer helpers with callbacks Date: Thu, 5 Mar 2026 09:43:42 -0800 Message-ID: <727502c8f79850fae6a8a476a624e5902861db39.1772732517.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Yang Zhong Add an additional APIC emulation mode for APIC timer virtualization. When the guest programs the local APIC timer mode, switch to this new emulation mode using the newly added hooks when APIC timer virtualization is available. Add five x86 KVM callbacks for APIC timer virtualization. These callbacks are analogous to those used for the preemption timer and will be invoked by kvm/lapic. These helpers start/stop the timer once the APIC virt timer feature is enabled and the guest sets the MSR_IA32_TSC_DEADLINE. Upon updating the TSC deadline mode in the APIC_LVTT register, KVM's LAPIC will initiate the APIC virt timer instead of the preemption timer. Signed-off-by: Yang Zhong Co-developed-by: Isaku Yamahata Signed-off-by: Isaku Yamahata --- arch/x86/include/asm/kvm-x86-ops.h | 5 ++ arch/x86/include/asm/kvm_host.h | 6 +++ arch/x86/kvm/lapic.c | 82 +++++++++++++++++++++++++++++- arch/x86/kvm/lapic.h | 1 + 4 files changed, 92 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-= x86-ops.h index de709fb5bd76..09f664aa72c1 100644 --- a/arch/x86/include/asm/kvm-x86-ops.h +++ b/arch/x86/include/asm/kvm-x86-ops.h @@ -118,6 +118,11 @@ KVM_X86_OP_OPTIONAL_RET0(dy_apicv_has_pending_interrup= t) KVM_X86_OP_OPTIONAL(protected_apic_has_interrupt) KVM_X86_OP_OPTIONAL(set_hv_timer) KVM_X86_OP_OPTIONAL(cancel_hv_timer) +KVM_X86_OP_OPTIONAL(can_use_apic_virt_timer) +KVM_X86_OP_OPTIONAL(set_apic_virt_timer) +KVM_X86_OP_OPTIONAL(cancel_apic_virt_timer) +KVM_X86_OP_OPTIONAL(set_guest_tsc_deadline_virt) +KVM_X86_OP_OPTIONAL(get_guest_tsc_deadline_virt) KVM_X86_OP(setup_mce) #ifdef CONFIG_KVM_SMM KVM_X86_OP(smi_allowed) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index c94556fefb75..345ea21b45f8 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1934,6 +1934,12 @@ struct kvm_x86_ops { int (*set_hv_timer)(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc, bool *expired); void (*cancel_hv_timer)(struct kvm_vcpu *vcpu); + bool (*can_use_apic_virt_timer)(struct kvm_vcpu *vcpu); + void (*set_apic_virt_timer)(struct kvm_vcpu *vcpu, u16 vector); + void (*cancel_apic_virt_timer)(struct kvm_vcpu *vcpu); + void (*set_guest_tsc_deadline_virt)(struct kvm_vcpu *vcpu, + u64 tscdeadline); + u64 (*get_guest_tsc_deadline_virt)(struct kvm_vcpu *vcpu); =20 void (*setup_mce)(struct kvm_vcpu *vcpu); =20 diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 9381c58d4c85..0d91834d972c 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -188,7 +188,8 @@ static inline u32 kvm_x2apic_id(struct kvm_lapic *apic) static bool kvm_can_post_timer_interrupt(struct kvm_vcpu *vcpu) { return pi_inject_timer && kvm_vcpu_apicv_active(vcpu) && - (kvm_mwait_in_guest(vcpu->kvm) || kvm_hlt_in_guest(vcpu->kvm)); + (kvm_mwait_in_guest(vcpu->kvm) || kvm_hlt_in_guest(vcpu->kvm)) && + !vcpu->arch.apic->lapic_timer.apic_virt_timer_in_use; } =20 static bool kvm_can_use_hv_timer(struct kvm_vcpu *vcpu) @@ -1864,17 +1865,82 @@ static void limit_periodic_timer_frequency(struct k= vm_lapic *apic) } =20 static void cancel_hv_timer(struct kvm_lapic *apic); +static void cancel_apic_virt_timer(struct kvm_lapic *apic); =20 -static void cancel_apic_timer(struct kvm_lapic *apic) +static void __cancel_apic_timer(struct kvm_lapic *apic) { hrtimer_cancel(&apic->lapic_timer.timer); preempt_disable(); if (apic->lapic_timer.hv_timer_in_use) cancel_hv_timer(apic); + else if (apic->lapic_timer.apic_virt_timer_in_use) + cancel_apic_virt_timer(apic); preempt_enable(); +} + +static void cancel_apic_timer(struct kvm_lapic *apic) +{ + __cancel_apic_timer(apic); atomic_set(&apic->lapic_timer.pending, 0); } =20 +static void start_apic_timer(struct kvm_lapic *apic); + +static void cancel_apic_virt_timer(struct kvm_lapic *apic) +{ + struct kvm_vcpu *vcpu =3D apic->vcpu; + + apic->lapic_timer.tscdeadline =3D kvm_x86_call(get_guest_tsc_deadline_vir= t)(vcpu); + kvm_x86_call(set_guest_tsc_deadline_virt)(vcpu, 0); + + kvm_x86_call(cancel_apic_virt_timer)(vcpu); + apic->lapic_timer.apic_virt_timer_in_use =3D false; +} + +static void apic_cancel_apic_virt_timer(struct kvm_lapic *apic) +{ + if (!apic->lapic_timer.apic_virt_timer_in_use) + return; + + cancel_apic_virt_timer(apic); + start_apic_timer(apic); +} + +static void apic_set_apic_virt_timer(struct kvm_lapic *apic) +{ + struct kvm_timer *ktimer =3D &apic->lapic_timer; + struct kvm_vcpu *vcpu =3D apic->vcpu; + u8 vector; + u32 reg; + + if (apic->lapic_timer.apic_virt_timer_in_use) + return; + + reg =3D kvm_lapic_get_reg(apic, APIC_LVTT); + vector =3D reg & APIC_VECTOR_MASK; + + __cancel_apic_timer(apic); + kvm_x86_call(set_apic_virt_timer)(vcpu, vector); + kvm_x86_call(set_guest_tsc_deadline_virt)(vcpu, ktimer->tscdeadline); + ktimer->apic_virt_timer_in_use =3D true; +} + +static bool kvm_can_use_apic_virt_timer(struct kvm_vcpu *vcpu) +{ + return kvm_x86_ops.can_use_apic_virt_timer && + lapic_in_kernel(vcpu) && + apic_lvt_enabled(vcpu->arch.apic, APIC_LVTT) && + kvm_x86_call(can_use_apic_virt_timer)(vcpu); +} + +static void apic_update_apic_virt_timer(struct kvm_lapic *apic) +{ + if (kvm_can_use_apic_virt_timer(apic->vcpu)) + apic_set_apic_virt_timer(apic); + else + apic_cancel_apic_virt_timer(apic); +} + static void apic_update_lvtt(struct kvm_lapic *apic) { u32 timer_mode =3D kvm_lapic_get_reg(apic, APIC_LVTT) & @@ -1887,10 +1953,19 @@ static void apic_update_lvtt(struct kvm_lapic *apic) kvm_lapic_set_reg(apic, APIC_TMICT, 0); apic->lapic_timer.period =3D 0; apic->lapic_timer.tscdeadline =3D 0; + + if (apic->lapic_timer.apic_virt_timer_in_use) + kvm_x86_call(set_guest_tsc_deadline_virt)(apic->vcpu, 0); } apic->lapic_timer.timer_mode =3D timer_mode; limit_periodic_timer_frequency(apic); } + + /* + * Update on not only timer mode change, but also mask change + * for the case of timer_mode =3D TSCDEADLINE, mask =3D 1. + */ + apic_update_apic_virt_timer(apic); } =20 /* @@ -2312,6 +2387,9 @@ static void restart_apic_timer(struct kvm_lapic *apic) if (!apic_lvtt_period(apic) && atomic_read(&apic->lapic_timer.pending)) goto out; =20 + if (apic->lapic_timer.apic_virt_timer_in_use) + goto out; + if (!start_hv_timer(apic)) start_sw_timer(apic); out: diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index 274885af4ebc..ba1090f9a3c8 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -57,6 +57,7 @@ struct kvm_timer { u32 timer_advance_ns; atomic_t pending; /* accumulated triggered timers */ bool hv_timer_in_use; + bool apic_virt_timer_in_use; }; =20 struct kvm_lapic { --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 45AA53CB2E7; Thu, 5 Mar 2026 17:44:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732675; cv=none; b=XUlhY46ftzHypNN2qzILw2yVSw9G4hbIykES6HmbKqgoldShiK4UBg0MUvkFwkf4oLlk7aXWCnULRNuzMwOFjqzEssMleIC1f6hBdsOCNouMkwxHjUX7/llAR1DKDDjSV5CgysRCz8lcJ/3H5esm9tgndjwVWe+NL352DI2rSew= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732675; c=relaxed/simple; bh=Y5oFD1dFQoDoxlnAH522ekzm2CBreC7DXdzIfJhmY+c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bebHrscZWKs/x/7eWN5lBVDrUDJtG4YlAl9fUwmOih/r5o2q5dg+I9ZyfQZJn73UKKuot3ZqLL2/BZNBaJvJAMZQD0ZtDqXvzKEfKKetsQqifIjHS5hZ/JNSP3A3vW5GjjHTfbOCOZnBounyTzJOWDV0ggua8OON8pNrXHNZzwE= 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=baGCU8Oy; arc=none smtp.client-ip=198.175.65.15 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="baGCU8Oy" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732674; x=1804268674; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Y5oFD1dFQoDoxlnAH522ekzm2CBreC7DXdzIfJhmY+c=; b=baGCU8OyEXiMXJJY2LsZCuhtwV9oepTLV3n0GQAvzpVnY/KErnp+Zg46 DcMrYl0VsXbqZLwATIDZCGP60hMb4WxSFlnDyjrDzSgOhrqnHSmhO9AnW t1DgJCW75KRq+Tgh/J2P7Dr6IVcCkAIrTGm6kjNaFNDAyqHemlb0jaKeH e7QswhZf7+vVD0+FQ4ZVKBZ0IhoCSbQhYu7UZb688o1Qq6pHPL190BQWp HHLzR9whwR1jGU299gXX0Mw82UYuzo/yU2qATHVJOyQ0+Ft76RoHuLWoN b5hGVSQnhGdDlY6LQqrU9C0Kmvh6zqm7CIFRSaaB0uq/ynbHxOtqiqszj A==; X-CSE-ConnectionGUID: 5J+Dbkn+QR+j1L6iU4CoHA== X-CSE-MsgGUID: rVll0GyjSiWB1/n9UZMq9g== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77431544" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77431544" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:34 -0800 X-CSE-ConnectionGUID: 4xmyJKVBQgKBtXyx18s1MQ== X-CSE-MsgGUID: 0hcfeRzsR4en7dREdIY3TA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="223447846" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:33 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org, Yang Zhong Subject: [PATCH v2 03/36] KVM: x86/lapic: Start/stop sw/hv timer on vCPU un/block Date: Thu, 5 Mar 2026 09:43:43 -0800 Message-ID: <2361bfeb235613efc6d2532970bf3e5dcc93a384.1772732517.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Yang Zhong Switch to use software timer when a vCPU is blocked by instructions such as HLT similar to the hv timer case. The guest deadline shadow field is read to obtain the guest_tsc value, which is then used to program an hrtimer for the duration of the vCPU block. Upon completion of the block, if the LAPIC timer has pending interrupts, the LAPIC timer is transitioned to APIC virt timer mode to continue providing timer services to the guest. Set the guest TSC deadline to 0 when injecting a timer interrupt, as the TSC deadline is cleared to zero when a timer interrupt is injected. Do so when injecting a timer interrupt to the vCPU. Signed-off-by: Yang Zhong Co-developed-by: Isaku Yamahata Signed-off-by: Isaku Yamahata --- Changes: v1 -> v2: - Add inkernel apic check as apic timer virtualizaion requires it. --- arch/x86/kvm/lapic.c | 20 +++++++++++++++++--- arch/x86/kvm/lapic.h | 9 +++++++++ arch/x86/kvm/x86.c | 7 +++++-- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 0d91834d972c..ab59722e291e 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -2089,6 +2089,8 @@ static void kvm_apic_inject_pending_timer_irqs(struct= kvm_lapic *apic) kvm_apic_local_deliver(apic, APIC_LVTT); if (apic_lvtt_tscdeadline(apic)) { ktimer->tscdeadline =3D 0; + if (apic->lapic_timer.apic_virt_timer_in_use) + kvm_x86_call(set_guest_tsc_deadline_virt)(apic->vcpu, 0); } else if (apic_lvtt_oneshot(apic)) { ktimer->tscdeadline =3D 0; ktimer->target_expiration =3D 0; @@ -2368,8 +2370,10 @@ static void start_sw_timer(struct kvm_lapic *apic) struct kvm_timer *ktimer =3D &apic->lapic_timer; =20 WARN_ON(preemptible()); - if (apic->lapic_timer.hv_timer_in_use) + if (apic->lapic_timer.hv_timer_in_use) { cancel_hv_timer(apic); + trace_kvm_hv_timer_state(apic->vcpu->vcpu_id, false); + } if (!apic_lvtt_period(apic) && atomic_read(&ktimer->pending)) return; =20 @@ -2377,7 +2381,6 @@ static void start_sw_timer(struct kvm_lapic *apic) start_sw_period(apic); else if (apic_lvtt_tscdeadline(apic)) start_sw_tscdeadline(apic); - trace_kvm_hv_timer_state(apic->vcpu->vcpu_id, false); } =20 static void restart_apic_timer(struct kvm_lapic *apic) @@ -2422,13 +2425,24 @@ void kvm_lapic_switch_to_hv_timer(struct kvm_vcpu *= vcpu) restart_apic_timer(vcpu->arch.apic); } =20 +void kvm_lapic_switch_to_apic_virt_timer(struct kvm_vcpu *vcpu) +{ + hrtimer_cancel(&vcpu->arch.apic->lapic_timer.timer); +} + void kvm_lapic_switch_to_sw_timer(struct kvm_vcpu *vcpu) { struct kvm_lapic *apic =3D vcpu->arch.apic; =20 preempt_disable(); + + if (apic->lapic_timer.apic_virt_timer_in_use) + apic->lapic_timer.tscdeadline =3D + kvm_x86_call(get_guest_tsc_deadline_virt)(vcpu); + /* Possibly the TSC deadline timer is not enabled yet */ - if (apic->lapic_timer.hv_timer_in_use) + if (apic->lapic_timer.hv_timer_in_use || + apic->lapic_timer.apic_virt_timer_in_use) start_sw_timer(apic); preempt_enable(); } diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index ba1090f9a3c8..5e96299c31f7 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -250,10 +250,19 @@ bool kvm_intr_is_single_vcpu(struct kvm *kvm, struct = kvm_lapic_irq *irq, struct kvm_vcpu **dest_vcpu); void kvm_lapic_switch_to_sw_timer(struct kvm_vcpu *vcpu); void kvm_lapic_switch_to_hv_timer(struct kvm_vcpu *vcpu); +void kvm_lapic_switch_to_apic_virt_timer(struct kvm_vcpu *vcpu); void kvm_lapic_expired_hv_timer(struct kvm_vcpu *vcpu); bool kvm_lapic_hv_timer_in_use(struct kvm_vcpu *vcpu); void kvm_lapic_restart_hv_timer(struct kvm_vcpu *vcpu); =20 +static inline bool kvm_lapic_apic_virt_timer_in_use(struct kvm_vcpu *vcpu) +{ + if (!lapic_in_kernel(vcpu)) + return false; + + return vcpu->arch.apic->lapic_timer.apic_virt_timer_in_use; +} + static inline enum lapic_mode kvm_apic_mode(u64 apic_base) { return apic_base & (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 879cdeb6adde..1922e8699101 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -11661,7 +11661,7 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) /* Called within kvm->srcu read side. */ static inline int vcpu_block(struct kvm_vcpu *vcpu) { - bool hv_timer; + bool hv_timer, virt_timer; =20 if (!kvm_arch_vcpu_runnable(vcpu)) { /* @@ -11672,7 +11672,8 @@ static inline int vcpu_block(struct kvm_vcpu *vcpu) * timer before blocking. */ hv_timer =3D kvm_lapic_hv_timer_in_use(vcpu); - if (hv_timer) + virt_timer =3D kvm_lapic_apic_virt_timer_in_use(vcpu); + if (hv_timer || virt_timer) kvm_lapic_switch_to_sw_timer(vcpu); =20 kvm_vcpu_srcu_read_unlock(vcpu); @@ -11684,6 +11685,8 @@ static inline int vcpu_block(struct kvm_vcpu *vcpu) =20 if (hv_timer) kvm_lapic_switch_to_hv_timer(vcpu); + else if (virt_timer) + kvm_lapic_switch_to_apic_virt_timer(vcpu); =20 /* * If the vCPU is not runnable, a signal or another host event --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 5BF6D3E5592; Thu, 5 Mar 2026 17:44:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732677; cv=none; b=A789GpREYRKniVXyBEFcabspUcaThwVYBScnsS6xONofE4GYeWJzjNICyF22CVuv0JnOkeGkwqUjliF3CEbJxFD4oQJNWrCaAIw/ppJSUsXfSI/l/wWDCNCteo572tLo/00gBvus2Ji5B7mOYtfvVABSmd9owprgLF8KXzNf2rI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732677; c=relaxed/simple; bh=xB2Kfqn84lfYRfoS8Qtq4/aK7PLAYxPYq1braCsQrkg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bsXVhwrn1xHJgXlUKmR0BvdIri6Zyk0br8nB4NBWteSHal5Nni0zJrW+Mo2kkGLUQfHlQW9sLoI6mlsRABw9PKbRzCh0MvuKbXdscgHophdGPqmo8M1HxgcwdbDIid6PPQMxP0Inq3gdr4DEiLDArzjIQN+cSv/EVX2ZnemZr2Y= 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=KgLSfh+5; arc=none smtp.client-ip=198.175.65.15 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="KgLSfh+5" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732676; x=1804268676; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=xB2Kfqn84lfYRfoS8Qtq4/aK7PLAYxPYq1braCsQrkg=; b=KgLSfh+5g2rsvt3fKV9ie2JxlKEefudeeiIQ0PiyR4gJ9l2M/h+fQwqt uT0xduG67JArRAzHe2oCnYbEQlM5C8dsmhXe7yrvALIcI9lakxwLzF1Et Y1V2IPoBdecDGmW1mR3a1VW1iwB2/uETCO1GLJCafVP8qs5/cm27sGuuO 5rWY7gUjK+PajEFm4fqBYYkCGSCzjTvIifzYBTDzd/RsbwyXe92WG2Q3i hzIjBz2dOxya3Wf8kpP/6sAGNm0FmN+XacuovOiavQ+/g4Q/dN9h5aJw7 hnyCCNdyD35rZgxCCO1uejtrNEmQlqsDmGv7WM6mo5HGhGknA+U489wTl Q==; X-CSE-ConnectionGUID: NT/W91gxRSahBVFInqsTcA== X-CSE-MsgGUID: afFbghvJR5KfawJRPNwPxw== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77431548" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77431548" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:34 -0800 X-CSE-ConnectionGUID: dXOB0RGwRHCLoBCHodR6cw== X-CSE-MsgGUID: 768vz48QRYKESR4DVzZsPw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="223447850" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:34 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 04/36] KVM: x86/lapic: Wire DEADLINE MSR update to guest virtual TSC deadline Date: Thu, 5 Mar 2026 09:43:44 -0800 Message-ID: <3f740669e391708e4420d91bd7f7d61a40b84463.1772732517.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Wire userpace read/write (KVM_GET_MSRS, KVM_SET_MSRS) of TSCDEADLINE MSR to the vendor backend to update the VMCS field of GUEST TSCDEADLINE and GUEST TSCDEADLINE shadow. Signed-off-by: Isaku Yamahata --- arch/x86/kvm/lapic.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index ab59722e291e..10aa7040686f 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -2802,6 +2802,10 @@ u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *v= cpu) if (!kvm_apic_present(vcpu) || !apic_lvtt_tscdeadline(apic)) return 0; =20 + if (apic->lapic_timer.apic_virt_timer_in_use) + apic->lapic_timer.tscdeadline =3D + kvm_x86_call(get_guest_tsc_deadline_virt)(vcpu); + return apic->lapic_timer.tscdeadline; } =20 @@ -2814,6 +2818,8 @@ void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *v= cpu, u64 data) =20 hrtimer_cancel(&apic->lapic_timer.timer); apic->lapic_timer.tscdeadline =3D data; + if (apic->lapic_timer.apic_virt_timer_in_use) + kvm_x86_call(set_guest_tsc_deadline_virt)(vcpu, data); start_apic_timer(apic); } =20 --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 810073E5EC4; Thu, 5 Mar 2026 17:44:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732677; cv=none; b=p7+LNa7kxBxlnegPId2RjihYPYTcnRx1wZsD5plDKAioz0sjGxTODOmObYexSfUxMh1blRo+9FUF8XYFwMWlRS+w2eWxgN92lMHAfWThYq9HCqfeIRoParWzeqRDwuxI97nHJ94R4Fx1v5KW3KsFvb+PtVt7+wWOv1lAhD85Vko= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732677; c=relaxed/simple; bh=Yow8OIG86TjnCjM50N/U6/GhpCYIQvgvpKOXPwEOWGE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Szx/l+ZzAwV3i7PRJ92SareRzM0+QFMwbgKzES09fVKwUspqzdHNMAEdSKOYLWFIBCfjwHrJm1FWp8cDMJCuuxJEySJ/6KhrNbZlEO9vriT4YNESxtdrRV7CiFb2OUThZjFJnlA6i62TsaT0jzNKTUiGCS6LEGPf8I7yhO0Sgo8= 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=OLu3ZWuk; arc=none smtp.client-ip=198.175.65.15 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="OLu3ZWuk" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732676; x=1804268676; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Yow8OIG86TjnCjM50N/U6/GhpCYIQvgvpKOXPwEOWGE=; b=OLu3ZWuk7QLpwhJ/tkr6aWSctbETXK77UuQZOBdHYzh9UUMF3sk2MTK3 SHzRrHOcyGsV3YPiaTMlX14L5NPWwCfxEK9cZ3AldZE2UDX1DFl67Uw1G Vx1Fmj7+v5W+IHmN27E6JcsK7oxgijd/DLZr/AwRJGUoWDeUn2Nyr284V sRJAS3zePeZwaHb/ikbbihlxaUnDPCiqX/X1abhpG1/fKdbd0mW7dBd/L ydp3JSjmdsDM+Qludhdn7+coAI6K8JizheIQ7UNlGOckU3rKSeBsdyQHd qoAVnM+h2oKX4xLWV2J23MXhVv8tbWIvnFR9lAXfF5aUUAszofvxioJTU A==; X-CSE-ConnectionGUID: PcR7PbocTtiAefMFsSPT9Q== X-CSE-MsgGUID: xRnhXS4SQ2yPeOzyhiyMlQ== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77431553" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77431553" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:34 -0800 X-CSE-ConnectionGUID: Rx5TImDLS1S9qWNQNjsutg== X-CSE-MsgGUID: Dxx303+dTtGs4Yr7CpGvow== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="223447853" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:34 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org, Yang Zhong Subject: [PATCH v2 05/36] KVM: x86/lapic: Add a trace point for guest virtual timer Date: Thu, 5 Mar 2026 09:43:45 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Yang Zhong Add a trace point for changing the guest virtual timer, similar to the hv timer case. Signed-off-by: Yang Zhong Co-developed-by: Isaku Yamahata Signed-off-by: Isaku Yamahata --- arch/x86/kvm/lapic.c | 5 +++++ arch/x86/kvm/trace.h | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 10aa7040686f..abbd51c4da7f 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1895,6 +1895,9 @@ static void cancel_apic_virt_timer(struct kvm_lapic *= apic) =20 kvm_x86_call(cancel_apic_virt_timer)(vcpu); apic->lapic_timer.apic_virt_timer_in_use =3D false; + + trace_kvm_apic_virt_timer_state(vcpu->vcpu_id, + apic->lapic_timer.apic_virt_timer_in_use); } =20 static void apic_cancel_apic_virt_timer(struct kvm_lapic *apic) @@ -1923,6 +1926,8 @@ static void apic_set_apic_virt_timer(struct kvm_lapic= *apic) kvm_x86_call(set_apic_virt_timer)(vcpu, vector); kvm_x86_call(set_guest_tsc_deadline_virt)(vcpu, ktimer->tscdeadline); ktimer->apic_virt_timer_in_use =3D true; + + trace_kvm_apic_virt_timer_state(vcpu->vcpu_id, ktimer->apic_virt_timer_in= _use); } =20 static bool kvm_can_use_apic_virt_timer(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h index e7fdbe9efc90..ca9456955254 100644 --- a/arch/x86/kvm/trace.h +++ b/arch/x86/kvm/trace.h @@ -1649,6 +1649,22 @@ TRACE_EVENT(kvm_hv_timer_state, __entry->hv_timer_in_use) ); =20 +TRACE_EVENT(kvm_apic_virt_timer_state, + TP_PROTO(unsigned int vcpu_id, unsigned int apic_virt_timer_in_use), + TP_ARGS(vcpu_id, apic_virt_timer_in_use), + TP_STRUCT__entry( + __field(unsigned int, vcpu_id) + __field(unsigned int, apic_virt_timer_in_use) + ), + TP_fast_assign( + __entry->vcpu_id =3D vcpu_id; + __entry->apic_virt_timer_in_use =3D apic_virt_timer_in_use; + ), + TP_printk("vcpu_id %x apic_virt_timer %x", + __entry->vcpu_id, + __entry->apic_virt_timer_in_use) +); + /* * Tracepoint for kvm_hv_flush_tlb. */ --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 918263E5ECA; Thu, 5 Mar 2026 17:44:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732677; cv=none; b=LC6d5PyaPS/+gF+Xcx+AyWS0UIjrEYdbRnPWhixp18aRCuu2Rc9kuSEYa0+or6fzFD8LumvYpGYKEHiz1iW+jQIlzwlU7O2rZBJ0funviL7/n9ziI+MkDPiwA/ykqL2Cl+40GewMBytaEbA+iHDlWTW0L7vfxmhQu7RLogg9No0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732677; c=relaxed/simple; bh=08yovv4kHpvB18sUdnUiqahcaPf2xrtmKjUIG/qy/84=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=b6XUQc0ni/SyB6LmJAaYgxCRDX6az0sjrH2s5Nw4MIvK+uLNCECjoEBfbzcig274uBKQK8/V8WzMBN1aRa9YC2XS4u5akmtUscZPFakEETJID1HGtyH7bO5t62eISSGk2Yk/ZjbEF1UJ/F79+9ZK4Cc9//OCjkV4ySQb7TVO+k8= 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=SSWES8Ww; arc=none smtp.client-ip=198.175.65.15 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="SSWES8Ww" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732676; x=1804268676; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=08yovv4kHpvB18sUdnUiqahcaPf2xrtmKjUIG/qy/84=; b=SSWES8Ww4Clo0LpVrJPeppuqfJ3npcjGJmthzO2k6CkMCnenLl20OUCm h66wvXNWgngkeVhPRlxCaIW7X2eOnJBQUnckQ8wIA2pbGJWhNO1Uw82yG 72SNtya3soYFdK2F+l4U/SIkIlSernoqq+fdSiuK3+HFLHLho1oGDCLZp nfmNLyovH545wC8VHGaPd1uupEr10Z6/mbKjzCBMigMLs3IHej0G0r2fG 5fBFuyl8fGFyNP7Hpj+5sFHv3kfwNACnX/32MS1iWe/fbUE/T6/rQi3Rd qGwSPtL3rFndZy3rRx6KmsmOrfLJ5X/skHl7Ixw9osnRnLHZoKgg75jls A==; X-CSE-ConnectionGUID: Letf9nEZT5Cgw+fY5c/9Dw== X-CSE-MsgGUID: oWzqppd0QGqPP/UIfvgaWw== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77431558" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77431558" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:35 -0800 X-CSE-ConnectionGUID: J7zvM55GTB2ZQKjv5n9KSQ== X-CSE-MsgGUID: 9Cgu3wgjTF2q9alRznE3iw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="223447857" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:34 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org, Yang Zhong Subject: [PATCH v2 06/36] KVM: VMX: Implement the hooks for VMX guest virtual deadline timer Date: Thu, 5 Mar 2026 09:43:46 -0800 Message-ID: <865b011e272dce6995119cbe41cdbd367bc2d8ad.1772732517.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Yang Zhong Implement the hooks for the VMX backend for APIC timer virtualization to access the related VMCS fields. Signed-off-by: Yang Zhong Co-developed-by: Isaku Yamahata Signed-off-by: Isaku Yamahata --- Changes: v1 -> v2: Move kvm_cpu_apicv_active() before kvm_lapic_lvtt_timer_mode() as it checks in-kernel apic check. --- arch/x86/kvm/lapic.h | 5 ++ arch/x86/kvm/vmx/capabilities.h | 6 +++ arch/x86/kvm/vmx/main.c | 5 ++ arch/x86/kvm/vmx/vmx.c | 83 ++++++++++++++++++++++++++++++++- arch/x86/kvm/vmx/x86_ops.h | 5 ++ 5 files changed, 103 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index 5e96299c31f7..2f510503f5b3 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -237,6 +237,11 @@ static inline int kvm_lapic_latched_init(struct kvm_vc= pu *vcpu) return lapic_in_kernel(vcpu) && test_bit(KVM_APIC_INIT, &vcpu->arch.apic-= >pending_events); } =20 +static inline int kvm_lapic_lvtt_timer_mode(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.apic->lapic_timer.timer_mode; +} + bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector); =20 bool kvm_lapic_suppress_eoi_broadcast(struct kvm_lapic *apic); diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilitie= s.h index 4e371c93ae16..c5cb098f579b 100644 --- a/arch/x86/kvm/vmx/capabilities.h +++ b/arch/x86/kvm/vmx/capabilities.h @@ -90,6 +90,12 @@ static inline bool cpu_has_vmx_preemption_timer(void) PIN_BASED_VMX_PREEMPTION_TIMER; } =20 +static inline bool cpu_has_vmx_apic_timer_virt(void) +{ + return vmcs_config.cpu_based_3rd_exec_ctrl & + TERTIARY_EXEC_GUEST_APIC_TIMER; +} + static inline bool cpu_has_vmx_posted_intr(void) { return vmcs_config.pin_based_exec_ctrl & PIN_BASED_POSTED_INTR; diff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c index dbebddf648be..ed20c859def3 100644 --- a/arch/x86/kvm/vmx/main.c +++ b/arch/x86/kvm/vmx/main.c @@ -994,6 +994,11 @@ struct kvm_x86_ops vt_x86_ops __initdata =3D { #ifdef CONFIG_X86_64 .set_hv_timer =3D vt_op(set_hv_timer), .cancel_hv_timer =3D vt_op(cancel_hv_timer), + .can_use_apic_virt_timer =3D vmx_can_use_apic_virt_timer, + .set_apic_virt_timer =3D vmx_set_apic_virt_timer, + .cancel_apic_virt_timer =3D vmx_cancel_apic_virt_timer, + .set_guest_tsc_deadline_virt =3D vmx_set_guest_tsc_deadline_virt, + .get_guest_tsc_deadline_virt =3D vmx_get_guest_tsc_deadline_virt, #endif =20 .setup_mce =3D vt_op(setup_mce), diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 4ccb2e42322d..b70641bfecab 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -2802,7 +2802,8 @@ static int setup_vmcs_config(struct vmcs_config *vmcs= _conf, & ~TERTIARY_EXEC_GUEST_APIC_TIMER, MSR_IA32_VMX_PROCBASED_CTLS3); =20 - if (!(_cpu_based_2nd_exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY)) + if (!IS_ENABLED(CONFIG_X86_64) || + !(_cpu_based_2nd_exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY)) _cpu_based_3rd_exec_control &=3D ~TERTIARY_EXEC_GUEST_APIC_TIMER; =20 if (adjust_vmx_controls(KVM_REQUIRED_VMX_VM_EXIT_CONTROLS, @@ -8364,6 +8365,86 @@ void vmx_cancel_hv_timer(struct kvm_vcpu *vcpu) { to_vmx(vcpu)->hv_deadline_tsc =3D -1; } + +bool vmx_can_use_apic_virt_timer(struct kvm_vcpu *vcpu) +{ + if (vcpu->kvm->arch.vm_type !=3D KVM_X86_DEFAULT_VM) + return false; + + return cpu_has_vmx_apic_timer_virt() && + /* SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY and in-kernel apic */ + kvm_vcpu_apicv_active(vcpu) && + /* VMX guest virtual timer supports only TSC deadline mode. */ + kvm_lapic_lvtt_timer_mode(vcpu) =3D=3D APIC_LVT_TIMER_TSCDEADLINE && + /* KVM doesn't use RDTSC existing. Safeguard. */ + !(exec_controls_get(to_vmx(vcpu)) & CPU_BASED_RDTSC_EXITING); +} + +void vmx_set_apic_virt_timer(struct kvm_vcpu *vcpu, u16 vector) +{ + vmcs_write16(GUEST_APIC_TIMER_VECTOR, vector); + vmx_disable_intercept_for_msr(vcpu, MSR_IA32_TSC_DEADLINE, MSR_TYPE_RW); + tertiary_exec_controls_setbit(to_vmx(vcpu), TERTIARY_EXEC_GUEST_APIC_TIME= R); +} + +void vmx_cancel_apic_virt_timer(struct kvm_vcpu *vcpu) +{ + vmx_enable_intercept_for_msr(vcpu, MSR_IA32_TSC_DEADLINE, MSR_TYPE_RW); + tertiary_exec_controls_clearbit(to_vmx(vcpu), TERTIARY_EXEC_GUEST_APIC_TI= MER); +} + +static u64 vmx_calc_deadline_l1_to_host(struct kvm_vcpu *vcpu, u64 l1_tsc) +{ + u64 host_tsc_now =3D rdtsc(); + u64 l1_tsc_now =3D kvm_read_l1_tsc(vcpu, host_tsc_now); + u64 host_tsc; + + /* 0 means that timer is disarmed. */ + if (!l1_tsc) + return 0; + + host_tsc =3D l1_tsc - vcpu->arch.l1_tsc_offset; + if (vcpu->arch.l1_tsc_scaling_ratio !=3D kvm_caps.default_tsc_scaling_rat= io) + if (u64_shl_div_u64(l1_tsc, + kvm_caps.tsc_scaling_ratio_frac_bits, + vcpu->arch.l1_tsc_scaling_ratio, + &host_tsc)) + host_tsc =3D ~0ull; + + /* + * Clamp the result on overflow. + * TSC deadline isn't supposed to overflow in practice. + * ~0ull is considered that the timer is armed, but won't fire in + * practical time frame. + */ + if (l1_tsc > l1_tsc_now && host_tsc <=3D host_tsc_now) + host_tsc =3D ~0ull; + /* + * Clamp the result on underflow. + * The past value means fire the timer immediately. + * Pick the obvious past value. + */ + if (l1_tsc <=3D l1_tsc_now && host_tsc > host_tsc_now) + host_tsc =3D 1ull; + + if (!host_tsc) + host_tsc =3D 1ull; + + return host_tsc; +} + +void vmx_set_guest_tsc_deadline_virt(struct kvm_vcpu *vcpu, + u64 guest_deadline_virt) +{ + vmcs_write64(GUEST_DEADLINE_VIR, guest_deadline_virt); + vmcs_write64(GUEST_DEADLINE_PHY, + vmx_calc_deadline_l1_to_host(vcpu, guest_deadline_virt)); +} + +u64 vmx_get_guest_tsc_deadline_virt(struct kvm_vcpu *vcpu) +{ + return vmcs_read64(GUEST_DEADLINE_VIR); +} #endif =20 void vmx_update_cpu_dirty_logging(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/vmx/x86_ops.h b/arch/x86/kvm/vmx/x86_ops.h index d09abeac2b56..364050e0427c 100644 --- a/arch/x86/kvm/vmx/x86_ops.h +++ b/arch/x86/kvm/vmx/x86_ops.h @@ -117,6 +117,11 @@ void vmx_update_cpu_dirty_logging(struct kvm_vcpu *vcp= u); int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc, bool *expired); void vmx_cancel_hv_timer(struct kvm_vcpu *vcpu); +bool vmx_can_use_apic_virt_timer(struct kvm_vcpu *vcpu); +void vmx_set_apic_virt_timer(struct kvm_vcpu *vcpu, u16 vector); +void vmx_cancel_apic_virt_timer(struct kvm_vcpu *vcpu); +void vmx_set_guest_tsc_deadline_virt(struct kvm_vcpu *vcpu, u64 guest_dead= line_tsc); +u64 vmx_get_guest_tsc_deadline_virt(struct kvm_vcpu *vcpu); #endif void vmx_setup_mce(struct kvm_vcpu *vcpu); =20 --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 1A9293E715F; Thu, 5 Mar 2026 17:44:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732680; cv=none; b=mUZ9x7NuUFVil6bW5EUvMvjRB47MRepoLy7Om0Byn/Fe79nvrqECOH4cvsvtSeVhLZ8jcH+AyjZQZeuQ5CODRTOaDiaA+HSyjgifJ7ciIh1qADnLsGkDFkq0fenzFVFKHhnXUnwOURehmZlKUNDr4wx3Sj5/0YsvBSHE6bW5bhc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732680; c=relaxed/simple; bh=6fASWB4q17PZAgMEt8O+x+XB/ZHizq2q9RpwGbdu54k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ByuoDp9PZeUFM1Mnq7aSpwRDC2N3Cq2xwcChOfuCCVFoUFN66b43rJBDXAczHwJrfJfNaJnMbrQ/03YTZb5xI8EE3phhVqJo4JYfR9c/oXB4gQqTzQ9urzeqLu8USw4+fkeydp57xJGJGG8tDNgFNAOrsrmlfqTamJrTV5bVg+M= 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=dfMHoeUQ; arc=none smtp.client-ip=198.175.65.15 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="dfMHoeUQ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732677; x=1804268677; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=6fASWB4q17PZAgMEt8O+x+XB/ZHizq2q9RpwGbdu54k=; b=dfMHoeUQJS62NHRZUQaRsyzvheJV2QRqnRWfD8TcBswmLnhW/K2xi3Gh dWfhTcWkuGrotZGjWbM5HGzUwNP+EYlDNNfqiS2v/bs7Sjqd80EO6Jl7L XT2YnxaSzHI3WDyleiRHRxMcHe3QCRlSdWQZ3wGmbMvo6yEuWDVbrRtA1 gz2Xry7yjDdF6O2rvHdDFHyikD/hXqnV3g/F80ZrJ10LvQjvIVtYAghii VqVOg0pTzLalgkqaHqWLN0TLe1tOg0chQ5sXF4Hnq48eikvBWOte136CM vpC6ysOIeih9n3DauWFf/boR1cS3hPKAT3/FfDT+ULbTtwt0wCLZAO/RH Q==; X-CSE-ConnectionGUID: Pd2JdE5URNynOIkNSP/kMA== X-CSE-MsgGUID: C2XXJ/w3RWie29t9wnWZbA== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77431561" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77431561" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:35 -0800 X-CSE-ConnectionGUID: uh6MmmQjT3y+CySPVFFI4A== X-CSE-MsgGUID: 6T6ter9lTo6ib57WiuNP9Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="223447861" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:35 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 07/36] KVM: VMX: Update APIC timer virtualization on apicv changed Date: Thu, 5 Mar 2026 09:43:47 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata VMX APIC timer virtualization requires the virtual-interrupt delivery. It's part of KVM apicv, and when apicv state is changed, the refresh_apicv_exec_ctrl() callback is invoked. Export a lapic function to update which timer to use for APIC timer emulation and make the VMX backend call it. Signed-off-by: Isaku Yamahata -- Changes v1 -> v2: - Use EXPORT_SYMBOL_FOR_KVM_INTERNAL() instead of EXPORT_SYMBOL_GPL(). - Add in-kernel apic check. Signed-off-by: Isaku Yamahata --- arch/x86/kvm/lapic.c | 9 +++++++++ arch/x86/kvm/lapic.h | 1 + arch/x86/kvm/vmx/vmx.c | 2 ++ 3 files changed, 12 insertions(+) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index abbd51c4da7f..a3c1a81e63e2 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1946,6 +1946,15 @@ static void apic_update_apic_virt_timer(struct kvm_l= apic *apic) apic_cancel_apic_virt_timer(apic); } =20 +void kvm_update_apic_virt_timer(struct kvm_vcpu *vcpu) +{ + if (!lapic_in_kernel(vcpu)) + return; + + apic_update_apic_virt_timer(vcpu->arch.apic); +} +EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_update_apic_virt_timer); + static void apic_update_lvtt(struct kvm_lapic *apic) { u32 timer_mode =3D kvm_lapic_get_reg(apic, APIC_LVTT) & diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index 2f510503f5b3..0571b7438328 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -259,6 +259,7 @@ void kvm_lapic_switch_to_apic_virt_timer(struct kvm_vcp= u *vcpu); void kvm_lapic_expired_hv_timer(struct kvm_vcpu *vcpu); bool kvm_lapic_hv_timer_in_use(struct kvm_vcpu *vcpu); void kvm_lapic_restart_hv_timer(struct kvm_vcpu *vcpu); +void kvm_update_apic_virt_timer(struct kvm_vcpu *vcpu); =20 static inline bool kvm_lapic_apic_virt_timer_in_use(struct kvm_vcpu *vcpu) { diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index b70641bfecab..5d36f2b632e9 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -4591,6 +4591,8 @@ void vmx_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcp= u) kvm_vcpu_apicv_active(vcpu)); =20 vmx_update_msr_bitmap_x2apic(vcpu); + + kvm_update_apic_virt_timer(vcpu); } =20 static u32 vmx_exec_control(struct vcpu_vmx *vmx) --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.17]) (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 7FF4A3E7145; Thu, 5 Mar 2026 17:44:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.17 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732678; cv=none; b=Yx0xstz8NdyNGR8kWr/IAPoS7+lST6Vxpbm6ilO0DjPZtUxvoJe5Xc1Bu9nHGkjBzm+F8ynM7rVen61+LQjQSfAyZC43XNGlk9glGlKDziPxaT5DrFj6lrWgQpVJZZv9LOoy39mKU3Bz3CIA95QtFqfQv1fPE2leutlQ8kqTAuw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732678; c=relaxed/simple; bh=KiZ6mxChNOoAxPa9NRJAAiG7+zC6bTu4ZfRSLi+aGFE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pwVmZ/PriEiTZV52SAgzcIPcF9tuNje+NjzV9VPPr65dcLEfrC1/AZOUX1hNI/KpAqSEfjdPOfTDOS5hWVuQLKk7LTtljPtmhEeVHEIW+46vX4UdrJpDKJ2GC+UfT+Qy4r4meY3dgS4ZGNEpqXzhCddIA8Ox3E3ZlETdtaCT8FM= 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=HEbF0w7B; arc=none smtp.client-ip=198.175.65.17 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="HEbF0w7B" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732676; x=1804268676; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=KiZ6mxChNOoAxPa9NRJAAiG7+zC6bTu4ZfRSLi+aGFE=; b=HEbF0w7BKINZrj9zdWZ6gzqY8Ld1lFNIAZYl11BFMWPWoZ+bunIiZKHY Y5vP3WdYYPx85zN6ca5ovvWlUDJTmkPWKAAi5pfJio1E6pWG9s+hQT7nu mukAuLY2s8p91mWr0GWPyBNHiXe8tKv4JnVtlW8+Q4lM9cDRLIf5o6ATG 98t63BBsMHzFO4IagQ8huRujOwLXuC+zJz9n+1JiW0dcivC2Bx1UHdgMY ZqYezEJxAERZb7aQ9pfX0lH/ETNfNWTLfEft8k97B9W1d6gDYousQbcJw ZCmqEQ+fH+5sxrXVFJrpAt3WPxUJsZxWJXVAEryb9oA0YJgUwt/f5uXwV Q==; X-CSE-ConnectionGUID: EMEqXVJlQDuFypaVWU4aXQ== X-CSE-MsgGUID: Oliy7TI6S3y860YB1J5ZfA== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="73798213" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="73798213" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa109.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:35 -0800 X-CSE-ConnectionGUID: mwh/N/jnS02BZtwxnQBE9w== X-CSE-MsgGUID: 1pWExwllQX6dF9Kl36aAeg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="215527254" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by fmviesa006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:35 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 08/36] KVM: nVMX: Disallow/allow guest APIC timer virtualization switch to/from L2 Date: Thu, 5 Mar 2026 09:43:48 -0800 Message-ID: <242a86c98c9b3e8306aa39b01563a98c7ab87ecc.1772732517.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Disable guest APIC timer virtualization on nested VMEnter, enable it on nested vmexit. With VMX APIC timer virtualization, the CPU directly injects a guest timer interrupt without VMExit. When the L1 APIC timer fires while running the nested (L2) vCPU, KVM should emulate VMExit from L2 to L1. Switch to the hv timer (preemption timer) or the sw timer when VMEntering from L1 to L2, switch to guest APIC timer virtualization when VM exiting from L2 to L1. Signed-off-by: Isaku Yamahata -- Changes v1->v2: - Use EXPORT_SYMBOL_FOR_KVM_INTERNAL() instead of EXPORT_SYMBOL_GPL(). - Add in-kernel apic check. Signed-off-by: Isaku Yamahata --- arch/x86/kvm/lapic.c | 35 +++++++++++++++++++++++++++++++++++ arch/x86/kvm/lapic.h | 2 ++ arch/x86/kvm/vmx/nested.c | 13 +++++++++++++ arch/x86/kvm/vmx/vmx.c | 5 +++++ 4 files changed, 55 insertions(+) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index a3c1a81e63e2..03667ca6357e 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1909,6 +1909,41 @@ static void apic_cancel_apic_virt_timer(struct kvm_l= apic *apic) start_apic_timer(apic); } =20 +void kvm_sync_apic_virt_timer(struct kvm_vcpu *vcpu) +{ + struct kvm_lapic *apic =3D vcpu->arch.apic; + + WARN_ON_ONCE(is_guest_mode(vcpu)); + + if (!lapic_in_kernel(vcpu)) + return; + + if (!apic->lapic_timer.apic_virt_timer_in_use) + return; + + apic->lapic_timer.tscdeadline =3D kvm_x86_call(get_guest_tsc_deadline_vir= t)(vcpu); +} +EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_sync_apic_virt_timer); + +void kvm_cancel_apic_virt_timer(struct kvm_vcpu *vcpu) +{ + struct kvm_lapic *apic =3D vcpu->arch.apic; + + WARN_ON_ONCE(!is_guest_mode(vcpu)); + + if (!lapic_in_kernel(vcpu)) + return; + + if (!apic->lapic_timer.apic_virt_timer_in_use) + return; + + apic->lapic_timer.apic_virt_timer_in_use =3D false; + trace_kvm_apic_virt_timer_state(vcpu->vcpu_id, false); + + start_apic_timer(apic); +} +EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_cancel_apic_virt_timer); + static void apic_set_apic_virt_timer(struct kvm_lapic *apic) { struct kvm_timer *ktimer =3D &apic->lapic_timer; diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index 0571b7438328..8e7ee5f3a01d 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -260,6 +260,8 @@ void kvm_lapic_expired_hv_timer(struct kvm_vcpu *vcpu); bool kvm_lapic_hv_timer_in_use(struct kvm_vcpu *vcpu); void kvm_lapic_restart_hv_timer(struct kvm_vcpu *vcpu); void kvm_update_apic_virt_timer(struct kvm_vcpu *vcpu); +void kvm_sync_apic_virt_timer(struct kvm_vcpu *vcpu); +void kvm_cancel_apic_virt_timer(struct kvm_vcpu *vcpu); =20 static inline bool kvm_lapic_apic_virt_timer_in_use(struct kvm_vcpu *vcpu) { diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 101588914cbb..c475b8c94807 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -3656,6 +3656,8 @@ enum nvmx_vmentry_status nested_vmx_enter_non_root_mo= de(struct kvm_vcpu *vcpu, if (!enable_ept) vmcs_writel(GUEST_CR3, vcpu->arch.cr3); =20 + kvm_sync_apic_virt_timer(vcpu); + vmx_switch_vmcs(vcpu, &vmx->nested.vmcs02); =20 prepare_vmcs02_early(vmx, &vmx->vmcs01, vmcs12); @@ -3731,6 +3733,14 @@ enum nvmx_vmentry_status nested_vmx_enter_non_root_m= ode(struct kvm_vcpu *vcpu, vmx_start_preemption_timer(vcpu, timer_value); } =20 + /* + * Disable apic virtual timer for L1 to use sw timer (hr timer) or + * hypervisor timer (VMX preemption timer). + * When L1 timer interrupt occurs during running L2, KVM emulates + * VMExit from L2 to L1. Not directly injecting the interrupt into L2. + */ + kvm_cancel_apic_virt_timer(vcpu); + /* * Note no nested_vmx_succeed or nested_vmx_fail here. At this point * we are no longer running L1, and VMLAUNCH/VMRESUME has not yet @@ -5158,6 +5168,9 @@ void __nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 v= m_exit_reason, /* in case we halted in L2 */ kvm_set_mp_state(vcpu, KVM_MP_STATE_RUNNABLE); =20 + /* If apic virtual timer is supported, switch back to it. */ + kvm_update_apic_virt_timer(vcpu); + if (likely(!vmx->fail)) { if (vm_exit_reason !=3D -1) trace_kvm_nested_vmexit_inject(vmcs12->vm_exit_reason, diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 5d36f2b632e9..9d5a493b6fe5 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -8373,6 +8373,9 @@ bool vmx_can_use_apic_virt_timer(struct kvm_vcpu *vcp= u) if (vcpu->kvm->arch.vm_type !=3D KVM_X86_DEFAULT_VM) return false; =20 + if (is_guest_mode(vcpu)) + return false; + return cpu_has_vmx_apic_timer_virt() && /* SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY and in-kernel apic */ kvm_vcpu_apicv_active(vcpu) && @@ -8384,6 +8387,8 @@ bool vmx_can_use_apic_virt_timer(struct kvm_vcpu *vcp= u) =20 void vmx_set_apic_virt_timer(struct kvm_vcpu *vcpu, u16 vector) { + WARN_ON_ONCE(is_guest_mode(vcpu)); + vmcs_write16(GUEST_APIC_TIMER_VECTOR, vector); vmx_disable_intercept_for_msr(vcpu, MSR_IA32_TSC_DEADLINE, MSR_TYPE_RW); tertiary_exec_controls_setbit(to_vmx(vcpu), TERTIARY_EXEC_GUEST_APIC_TIME= R); --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.17]) (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 8CF8B3D3CFD; Thu, 5 Mar 2026 17:44:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.17 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732678; cv=none; b=Eo3pcRKyXrcqFZyzoTyuH3fV18cGa1ADuqCE2LGpFKYgyBXNtSHnTSuya5U5eE0B2udTkRlsYluJzS/GO8DZIMA73NHKcDKMNVX46QuK8AITFmN3EAFANS5VITawN9i8MEb+xCiv+42/pHH+iVdGGD56EY11jSeGo39qurU95j4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732678; c=relaxed/simple; bh=AYSF4woZnUUExmVQAgqaWWHMhnv4Eg3Hbzpmjm5Vdos=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AGeKySGgaDC0Gi1iV848udYOZxj35dLkwlzSz6Spq0OWYi/5YNyeHZQD+HFC0FC0vFtAObO+eZ1dpYHELAD0m6FOTlIdWqYY4gifSnGW5flojVbVc1w4ASL4ykNgqhAje46QyQXknffpBpEHrehmGQpta4m+johtAL15jUyj3oY= 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=EENc5Y/M; arc=none smtp.client-ip=198.175.65.17 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="EENc5Y/M" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732676; x=1804268676; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=AYSF4woZnUUExmVQAgqaWWHMhnv4Eg3Hbzpmjm5Vdos=; b=EENc5Y/MzEKz46FFQnqurenIIqZtjr4ofv/PCoQc9uOySyRhmpOnsdjC 7hn1RtjjFsd2rOOcCpFlBMTSYElY33AnBn/S0vl98PolQE80tEzYAN3yn QotgOhq416WpqJ3EkVYBBnZAskA0Ao2uHRPeUcUypMNezIOgVpm/uUrds N9Z6VWxN7O1/0CaZvg85ydIT00+xjwo6WJibIHcvlyLCAmPjeO1o6VkJ5 x460nDGCr47uz2gWHqmjSn92GZibYfFOf00yfD40e6u66DIU8BAvqf8s4 7hfbgjDGWmy/aSpWaj6zBAmhk4fcaZtWGJSo6jSjybFP+zO23ysEDeAKz Q==; X-CSE-ConnectionGUID: 7G5lMH5mSlyi0+nDew32mw== X-CSE-MsgGUID: Rs1or19/QeidGXTo7Kl96w== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="73798219" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="73798219" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa109.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:36 -0800 X-CSE-ConnectionGUID: XKhphNWuQviog9D1H35mAg== X-CSE-MsgGUID: A6/I9Lt9QhKh1lVlf4mb4w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="215527258" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by fmviesa006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:35 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 09/36] KVM: nVMX: Pass struct msr_data to VMX MSRs emulation Date: Thu, 5 Mar 2026 09:43:49 -0800 Message-ID: <7c23de0a19fbd6c452e3a8a50322972f421b734c.1772732517.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Pass struct msr_data, which has host_initiated member in addition to msr_index and data to vmx_set/get_vmx_msr(). Processor-based tertiary control access depends on which initiated the operation, the host or the guest. For host-initiated access (KVM_GET_MSRS, KVM_SET_MSRS), if the host supports processor-based tertiary controls, allow access. If guest-initiated access (emulation for guest rdmsr/wrmsr), allow/disallow based on guest tertiary controls is advertised to the guest (guest processor-based control high & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS). Prepare to add the check. No functional change intended. Signed-off-by: Isaku Yamahata --- arch/x86/kvm/vmx/nested.c | 9 +++++++-- arch/x86/kvm/vmx/nested.h | 4 ++-- arch/x86/kvm/vmx/vmx.c | 18 ++++++++++++++---- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index c475b8c94807..5f0ac8acd768 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -1475,9 +1475,11 @@ static int vmx_restore_fixed0_msr(struct vcpu_vmx *v= mx, u32 msr_index, u64 data) * * Returns 0 on success, non-0 otherwise. */ -int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) +int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) { struct vcpu_vmx *vmx =3D to_vmx(vcpu); + u32 msr_index =3D msr_info->index; + u64 data =3D msr_info->data; =20 /* * Don't allow changes to the VMX capability MSRs while the vCPU @@ -1540,8 +1542,11 @@ int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_i= ndex, u64 data) } =20 /* Returns 0 on success, non-0 otherwise. */ -int vmx_get_vmx_msr(struct nested_vmx_msrs *msrs, u32 msr_index, u64 *pdat= a) +int vmx_get_vmx_msr(struct nested_vmx_msrs *msrs, struct msr_data *msr_inf= o) { + u32 msr_index =3D msr_info->index; + u64 *pdata =3D &msr_info->data; + switch (msr_index) { case MSR_IA32_VMX_BASIC: *pdata =3D msrs->basic; diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h index b844c5d59025..d0257447b7cb 100644 --- a/arch/x86/kvm/vmx/nested.h +++ b/arch/x86/kvm/vmx/nested.h @@ -47,8 +47,8 @@ static inline void nested_vmx_vmexit(struct kvm_vcpu *vcp= u, u32 vm_exit_reason, } =20 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 vmx_set_vmx_msr(struct kvm_vcpu *vcpu, struct msr_data *msr); +int vmx_get_vmx_msr(struct nested_vmx_msrs *msrs, struct msr_data *msr); 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); bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port, diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 9d5a493b6fe5..9177b693df1b 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -2070,11 +2070,22 @@ static inline bool is_vmx_feature_control_msr_valid= (struct vcpu_vmx *vmx, =20 int vmx_get_feature_msr(u32 msr, u64 *data) { + struct msr_data msr_info; + int r; + switch (msr) { case KVM_FIRST_EMULATED_VMX_MSR ... KVM_LAST_EMULATED_VMX_MSR: if (!nested) return 1; - return vmx_get_vmx_msr(&vmcs_config.nested, msr, data); + + msr_info =3D (struct msr_data) { + .index =3D msr, + .host_initiated =3D true, + }; + r =3D vmx_get_vmx_msr(&vmcs_config.nested, &msr_info); + if (!r) + *data =3D msr_info.data; + return r; default: return KVM_MSR_RET_UNSUPPORTED; } @@ -2159,8 +2170,7 @@ int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_dat= a *msr_info) case KVM_FIRST_EMULATED_VMX_MSR ... KVM_LAST_EMULATED_VMX_MSR: if (!guest_cpu_cap_has(vcpu, X86_FEATURE_VMX)) return 1; - if (vmx_get_vmx_msr(&vmx->nested.msrs, msr_info->index, - &msr_info->data)) + if (vmx_get_vmx_msr(&vmx->nested.msrs, msr_info)) return 1; #ifdef CONFIG_KVM_HYPERV /* @@ -2487,7 +2497,7 @@ int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_dat= a *msr_info) return 1; /* they are read-only */ if (!guest_cpu_cap_has(vcpu, X86_FEATURE_VMX)) return 1; - return vmx_set_vmx_msr(vcpu, msr_index, data); + return vmx_set_vmx_msr(vcpu, msr_info); case MSR_IA32_RTIT_CTL: if (!vmx_pt_mode_is_host_guest() || vmx_rtit_ctl_check(vcpu, data) || --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 5A6173E7165; Thu, 5 Mar 2026 17:44:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732679; cv=none; b=tK9BxdkJlHSot07nx5hKr0G+ah/ZALQBw689vSDVHmClv8Mq1q04WogA6YluXf8A9ozxzNUj8zQJCYxZ+4yA5oOurcL8XdrpH0zH4YhKoO8wbq/o8pJ9ZQfG5T1yk7VLyk87gTyH65N9zMDaOhI1Via244Z6lwWvBwzpr+mU0bY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732679; c=relaxed/simple; bh=GYO3BcEy0W4OwMj5OBUNmbyKGduNT0dfVKh7yWRCh0U=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dSzI3JP96N6nBYAH/Wp8+FS5udhVKV8Eb0ztvI2egG6jQwYLq6zQEEro2Qn7jfThzjoY1IrHVgHe6s8aBq1J/0yOTa40QjD6rBzXLfj0wW20RubS5bhGSTsYZLfYUbyWBn7ODOjLstqHnpO/8aebPw7WaCSBlXhyXW3XldkwhAw= 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=NxE3PNmD; arc=none smtp.client-ip=198.175.65.15 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="NxE3PNmD" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732678; x=1804268678; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=GYO3BcEy0W4OwMj5OBUNmbyKGduNT0dfVKh7yWRCh0U=; b=NxE3PNmDszupo14OdVzGiXPRg9qv+6nRjZIxjNVx4axKcXWEqtBnTa/Z aXHqUJAcAqD7D8E5Fej0jjt0tDjexy7T4RjdLxuqNjPBDpDZOYNjy7jSg xwYrEVVFmcgcwWRYp22skezKoU6vx5W7IiDdbvaGzdegK93sy+xYcoflL /DNFw37qFx3Nh8yzGgjvF2Zrz4AdAUPZJfZHsWs64KWrF8YPBtpO8fKFQ 7k5GwxEJG2zajz9mj3Nw3hFXBUwC+HEUV8cmAqTVcXO2z7dNkYZqNDVTy fryCfiYfMUdxt4SyJk+LbPqC+JIi45IRbg89EH8G+CLhB2tB1lWq5sqAV g==; X-CSE-ConnectionGUID: 5S/pC2a6S2eWOMADzBpXnA== X-CSE-MsgGUID: 4NboIcsPTbixRK3WHyUsPA== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77431565" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77431565" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:36 -0800 X-CSE-ConnectionGUID: h4z0xLY+ToyyoNg35eJQKQ== X-CSE-MsgGUID: NrMiyqIGQGu7PXt2j+XoGQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="223447867" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:36 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org, syzbot+ci66a37fb2e2f8de71@syzkaller.appspotmail.com Subject: [PATCH v2 10/36] KVM: nVMX: Supports VMX tertiary controls and GUEST_APIC_TIMER bit Date: Thu, 5 Mar 2026 09:43:50 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Emulate MSR_IA32_VMX_PROCBASED_CTLS3 to advertise APIC timer virtualization feature to the L2 guest. Reported-by: syzbot+ci66a37fb2e2f8de71@syzkaller.appspotmail.com Closes: https://lore.kernel.org/kvm/6982f952.050a0220.3b3015.0012.GAE@googl= e.com/ Signed-off-by: Isaku Yamahata --- Changes: v1 -> v2: - When in-kernel lapic is disabled, disable nested apic timer virtualization. - disable apic timer virtualization bit in nested tertiary vm exec control when in-kernel lapic is disabled. --- arch/x86/kvm/vmx/capabilities.h | 1 + arch/x86/kvm/vmx/hyperv.c | 7 +++++ arch/x86/kvm/vmx/nested.c | 48 +++++++++++++++++++++++++++++++++ arch/x86/kvm/vmx/nested.h | 11 ++++++++ arch/x86/kvm/vmx/vmx.c | 6 ++++- arch/x86/kvm/x86.h | 2 +- 6 files changed, 73 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilitie= s.h index c5cb098f579b..8d67be77f02c 100644 --- a/arch/x86/kvm/vmx/capabilities.h +++ b/arch/x86/kvm/vmx/capabilities.h @@ -47,6 +47,7 @@ struct nested_vmx_msrs { u64 cr4_fixed1; u64 vmcs_enum; u64 vmfunc_controls; + u64 tertiary_ctls; }; =20 struct vmcs_config { diff --git a/arch/x86/kvm/vmx/hyperv.c b/arch/x86/kvm/vmx/hyperv.c index fa41d036acd4..2731c2e4b0e5 100644 --- a/arch/x86/kvm/vmx/hyperv.c +++ b/arch/x86/kvm/vmx/hyperv.c @@ -141,6 +141,13 @@ void nested_evmcs_filter_control_msr(struct kvm_vcpu *= vcpu, u32 msr_index, u64 * case MSR_IA32_VMX_PROCBASED_CTLS2: ctl_high &=3D evmcs_get_supported_ctls(EVMCS_2NDEXEC); break; + case MSR_IA32_VMX_PROCBASED_CTLS3: + /* + * tertiary procbased controls are 64-bit. 0 means unsupported, + * 1 supported. + */ + *pdata &=3D evmcs_get_supported_ctls(EVMCS_3RDEXEC); + return; case MSR_IA32_VMX_TRUE_PINBASED_CTLS: case MSR_IA32_VMX_PINBASED_CTLS: ctl_high &=3D evmcs_get_supported_ctls(EVMCS_PINCTRL); diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 5f0ac8acd768..be6b92b3c66a 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -218,6 +218,11 @@ static inline bool vmx_control_verify(u32 control, u32= low, u32 high) return fixed_bits_valid(control, low, high); } =20 +static inline bool vmx_control64_verify(u64 control, u64 msr) +{ + return !(control & ~msr); +} + static inline u64 vmx_control_msr(u32 low, u32 high) { return low | ((u64)high << 32); @@ -1511,6 +1516,25 @@ int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, struct ms= r_data *msr_info) case MSR_IA32_VMX_TRUE_ENTRY_CTLS: case MSR_IA32_VMX_PROCBASED_CTLS2: return vmx_restore_control_msr(vmx, msr_index, data); + case MSR_IA32_VMX_PROCBASED_CTLS3: { + u64 ctls3; + + if (!__nested_cpu_supports_tertiary_ctls(&vmcs_config.nested)) + return -EINVAL; + + /* read-only for guest. */ + if (!msr_info->host_initiated) + return -EINVAL; + + ctls3 =3D vmcs_config.nested.tertiary_ctls; + if (!nested_cpu_can_support_apic_virt_timer(vcpu)) + ctls3 &=3D ~TERTIARY_EXEC_GUEST_APIC_TIMER; + + if (!vmx_control64_verify(data, ctls3)) + return -EINVAL; + vmx->nested.msrs.tertiary_ctls =3D data; + return 0; + } case MSR_IA32_VMX_MISC: return vmx_restore_vmx_misc(vmx, data); case MSR_IA32_VMX_CR0_FIXED0: @@ -1608,6 +1632,16 @@ int vmx_get_vmx_msr(struct nested_vmx_msrs *msrs, st= ruct msr_data *msr_info) msrs->secondary_ctls_low, msrs->secondary_ctls_high); break; + case MSR_IA32_VMX_PROCBASED_CTLS3: + if (!__nested_cpu_supports_tertiary_ctls(&vmcs_config.nested)) + return KVM_MSR_RET_UNSUPPORTED; + + if (!msr_info->host_initiated && + !__nested_cpu_supports_tertiary_ctls(msrs)) + return -EINVAL; + + *pdata =3D msrs->tertiary_ctls; + break; case MSR_IA32_VMX_EPT_VPID_CAP: *pdata =3D msrs->ept_caps | ((u64)msrs->vpid_caps << 32); @@ -7285,6 +7319,18 @@ static void nested_vmx_setup_secondary_ctls(u32 ept_= caps, msrs->secondary_ctls_high |=3D SECONDARY_EXEC_ENCLS_EXITING; } =20 +static void nested_vmx_setup_tertiary_ctls(struct vmcs_config *vmcs_conf, + struct nested_vmx_msrs *msrs) +{ + msrs->tertiary_ctls =3D vmcs_conf->cpu_based_3rd_exec_ctrl; + + msrs->tertiary_ctls &=3D TERTIARY_EXEC_GUEST_APIC_TIMER; + + if (msrs->tertiary_ctls) + msrs->procbased_ctls_high |=3D + CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; +} + static void nested_vmx_setup_misc_data(struct vmcs_config *vmcs_conf, struct nested_vmx_msrs *msrs) { @@ -7373,6 +7419,8 @@ void nested_vmx_setup_ctls_msrs(struct vmcs_config *v= mcs_conf, u32 ept_caps) =20 nested_vmx_setup_secondary_ctls(ept_caps, vmcs_conf, msrs); =20 + nested_vmx_setup_tertiary_ctls(vmcs_conf, msrs); + nested_vmx_setup_misc_data(vmcs_conf, msrs); =20 nested_vmx_setup_basic(msrs); diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h index d0257447b7cb..8c25054a710e 100644 --- a/arch/x86/kvm/vmx/nested.h +++ b/arch/x86/kvm/vmx/nested.h @@ -152,6 +152,17 @@ static inline bool nested_cpu_has_vmx_shadow_vmcs(stru= ct kvm_vcpu *vcpu) SECONDARY_EXEC_SHADOW_VMCS; } =20 +static inline bool __nested_cpu_supports_tertiary_ctls(struct nested_vmx_m= srs *msrs) +{ + return msrs->procbased_ctls_high & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; +} + +/* APIC TIMER VIRTUALIZATION requires in-kernel lapic. */ +static inline bool nested_cpu_can_support_apic_virt_timer(struct kvm_vcpu = *vcpu) +{ + return cpu_has_vmx_apic_timer_virt() && lapic_in_kernel(vcpu); +} + static inline bool nested_cpu_has(struct vmcs12 *vmcs12, u32 bit) { return vmcs12->cpu_based_vm_exec_control & bit; diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 9177b693df1b..25f31103cb21 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -4985,9 +4985,13 @@ static void __vmx_vcpu_reset(struct kvm_vcpu *vcpu) init_vmcs(vmx); =20 if (nested && - kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_STUFF_FEATURE_MSRS)) + kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_STUFF_FEATURE_MSRS)) { memcpy(&vmx->nested.msrs, &vmcs_config.nested, sizeof(vmx->nested.msrs)); =20 + if (!nested_cpu_can_support_apic_virt_timer(vcpu)) + vmx->nested.msrs.tertiary_ctls &=3D ~TERTIARY_EXEC_GUEST_APIC_TIMER; + } + vcpu_setup_sgx_lepubkeyhash(vcpu); =20 vmx->nested.posted_intr_nv =3D -1; diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 44a28d343d40..1de31aae9c6c 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -92,7 +92,7 @@ do { \ * associated feature that KVM supports for nested virtualization. */ #define KVM_FIRST_EMULATED_VMX_MSR MSR_IA32_VMX_BASIC -#define KVM_LAST_EMULATED_VMX_MSR MSR_IA32_VMX_VMFUNC +#define KVM_LAST_EMULATED_VMX_MSR MSR_IA32_VMX_PROCBASED_CTLS3 =20 #define KVM_DEFAULT_PLE_GAP 128 #define KVM_VMX_DEFAULT_PLE_WINDOW 4096 --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 C805A3E8C6F; Thu, 5 Mar 2026 17:44:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732681; cv=none; b=Ox69a8mSFPBja8bxUs/JKGtv2T8es2ue7fEFX9k7mkO3wB2umN0Df1+PDbz/s2FQ0EW9xx5Z3TU+3vPRnD70+GJ42kOTusnbPnW50W6gAx0DQZAXHRuLqmCjpJMCciC9kAaX4Ma3lFRQheUr/TBQFJtxId2O/Otn5rGFQsYrTjs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732681; c=relaxed/simple; bh=kSruFzXc1Zum96mNVfzSPzNRNnCqz3iLxx8kTs52I20=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZA3RrgQVztSqSsdAYiXq8ZMGCumZiD60VeUd5Q+yn11v2LNFyDwJmVJNBdRCi1ajtl1Pda5pMPzGg0mGkFIMWiYU3LIeZVM5u+un9ItAiVRXM96tiqH16THziQ3K3HKxjJBnTLju1iE56lefHJnDvLFI6PSgZUCKyON3MuXI2WM= 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=aaxebCE3; arc=none smtp.client-ip=198.175.65.15 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="aaxebCE3" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732678; x=1804268678; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=kSruFzXc1Zum96mNVfzSPzNRNnCqz3iLxx8kTs52I20=; b=aaxebCE3Jgjh4qp24adqSiUimOWtF/91MEyLyp3vZLz+qykFKfJlHxJe jko723CLK8OD5whKdiD2moc9ioe5TDbk92KhRfx7iQfyJQmFljs6AyE7/ DI+AxhKfwu3iiIPN3oVEvTQC+beiNBCZJTYh7huOQD7d8Itoyg3PmW4ev VHg+DscCIsvY82RYKRorAZ8SruTcpTNYYXxS/wfYRq5L7XImEdIDyKvgs TFVBB9rJKyKSUjKehhSsSguHPYgE5lBi09WACYY2z7Ik31P+adJF55Osf 31Stal62FqkGXl8YhjaDGigM7tMqHAxa9vbyam2gYwJc6wi2oJWu593lF A==; X-CSE-ConnectionGUID: Wtr4i5GYRUKIE4T0+ZjTPA== X-CSE-MsgGUID: PiiHdOHRQ8OEx+0nRGbDOg== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77431570" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77431570" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:37 -0800 X-CSE-ConnectionGUID: 49uCp5y9Q3eDjhM4KFggQg== X-CSE-MsgGUID: MvTPDXUKRr6v8ZY0d9jMaQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="223447871" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:36 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 11/36] KVM: nVMX: Add alignment check for struct vmcs12 Date: Thu, 5 Mar 2026 09:43:51 -0800 Message-ID: <7112ca5bb871e809e469aa03b586f8b220d2d827.1772732517.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata As struct vmcs12 has __packed attributes and it has manual alignment, it's easy to add unaligned member without any warnings. Add alignment check to avoid accidental misalignment. Signed-off-by: Isaku Yamahata --- arch/x86/kvm/vmx/vmcs12.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx/vmcs12.h b/arch/x86/kvm/vmx/vmcs12.h index 21cd1b75e4fd..8c9d4c22b960 100644 --- a/arch/x86/kvm/vmx/vmcs12.h +++ b/arch/x86/kvm/vmx/vmcs12.h @@ -217,7 +217,8 @@ struct __packed vmcs12 { * although appending fields and/or filling gaps is obviously allowed. */ #define CHECK_OFFSET(field, loc) \ - ASSERT_STRUCT_OFFSET(struct vmcs12, field, loc) + ASSERT_STRUCT_OFFSET(struct vmcs12, field, loc); \ + static_assert(loc % __alignof(((struct vmcs12 *)0)->field) =3D=3D 0) =20 static inline void vmx_check_vmcs12_offsets(void) { --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 7BF7F3EBF35; Thu, 5 Mar 2026 17:44:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732681; cv=none; b=Zbhg26JifdrNU3CBUmLm5d/YtcedlUCqW6iBtGvgpFOSix6OAwgfZzxVrCN1PznOPIzczRTmladuu7Gt1KE0OZD/AYP68uHChLPsu7WtqmbJlzfZ6vZksh2I+ES+4tN1yvxfOR0axLQhxkBS5R0q+w/hmMFKdw36ZG1OWILS98s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732681; c=relaxed/simple; bh=1aenzwDGDxj7/Xy0K7xK2VZ8ll7V/R5F1ZAMykoI7BM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WifR8ZOnzyX6/TR15s3y7l55kZLVzzImSO8UaqQ6XtoiVeyHhzFHg6TjA6erEjG4JRrulwNAl2jd3aUBylRa+NPpz8IoGfkjyCx9iCZoCaKqIwwszHurknotEK8lX7i6G4fvuYH64jErcn4Rd8TTMS2vo0GiWeNDoDAEIP8MaSE= 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=X4NwnYXR; arc=none smtp.client-ip=198.175.65.15 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="X4NwnYXR" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732680; x=1804268680; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=1aenzwDGDxj7/Xy0K7xK2VZ8ll7V/R5F1ZAMykoI7BM=; b=X4NwnYXR/chAu7rRuf6GoHH1FXyLBQ8M/Cp7jJpHThgzRj/NQrBfx4jl X+rwjpOAgmKdlrRvtXSMvKJTVYxnNewECpWADCNS74jvzWCnkS+micCVI KQovzI4x4lnv8VbkSTYFG/2UHKHWERcxDZBWjHRZtmOSVK0RwOpcDCPJo avCRtYe5T/IHZOkvE2m1LdvCp71dd3BqDf7vugPs/Of/m0Pch4sti+2YJ /xqULQ3wNxH1JpH2Amsk0RLFNIFe4D+Ms+CTzDN7nWdzsEvXwtLTV06n5 u8pwaNloxgqSA2dzAXcqH+bh5pG4XPCZ2MFn+2gHNd/HgcYl0Jz+8VKeh w==; X-CSE-ConnectionGUID: b5dDoaVyTA2stI8wj/0Psg== X-CSE-MsgGUID: kwecv7DPTuecj4Z5OOT8Yg== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77431574" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77431574" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:37 -0800 X-CSE-ConnectionGUID: TI3CSsrbTZCmStv+UxZP4Q== X-CSE-MsgGUID: z8MdqYnZRdiexiuXckp1jA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="223447877" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:37 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 12/36] KVM: nVMX: Add tertiary VM-execution control VMCS support Date: Thu, 5 Mar 2026 09:43:52 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Support tertiary processor-based VM-execution control VMCS field. Signed-off-by: Isaku Yamahata --- arch/x86/kvm/vmx/hyperv.c | 10 ++++++++++ arch/x86/kvm/vmx/nested.c | 17 +++++++++++++++++ arch/x86/kvm/vmx/nested.h | 7 +++++++ arch/x86/kvm/vmx/vmcs12.c | 1 + arch/x86/kvm/vmx/vmcs12.h | 3 ++- 5 files changed, 37 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx/hyperv.c b/arch/x86/kvm/vmx/hyperv.c index 2731c2e4b0e5..70e210472681 100644 --- a/arch/x86/kvm/vmx/hyperv.c +++ b/arch/x86/kvm/vmx/hyperv.c @@ -166,6 +166,12 @@ static bool nested_evmcs_is_valid_controls(enum evmcs_= ctrl_type ctrl_type, return !(val & ~evmcs_get_supported_ctls(ctrl_type)); } =20 +static bool nested_evmcs_is_valid_controls64(enum evmcs_ctrl_type ctrl_typ= e, + u64 val) +{ + return !(val & ~evmcs_get_supported_ctls(ctrl_type)); +} + int nested_evmcs_check_controls(struct vmcs12 *vmcs12) { if (CC(!nested_evmcs_is_valid_controls(EVMCS_PINCTRL, @@ -188,6 +194,10 @@ int nested_evmcs_check_controls(struct vmcs12 *vmcs12) vmcs12->vm_entry_controls))) return -EINVAL; =20 + if (CC(!nested_evmcs_is_valid_controls64(EVMCS_3RDEXEC, + vmcs12->tertiary_vm_exec_control))) + return -EINVAL; + /* * VM-Func controls are 64-bit, but KVM currently doesn't support any * controls in bits 63:32, i.e. dropping those bits on the consistency diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index be6b92b3c66a..1bd5e164e285 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -1815,6 +1815,7 @@ static void copy_enlightened_to_vmcs12(struct vcpu_vm= x *vmx, u32 hv_clean_fields vmcs12->vm_exit_controls =3D evmcs->vm_exit_controls; vmcs12->secondary_vm_exec_control =3D evmcs->secondary_vm_exec_control; + vmcs12->tertiary_vm_exec_control =3D 0; } =20 if (unlikely(!(hv_clean_fields & @@ -2511,6 +2512,17 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vm= x, struct loaded_vmcs *vmcs0 secondary_exec_controls_set(vmx, exec_control); } =20 + /* + * TERTIARY EXEC CONTROLS + */ + if (cpu_has_tertiary_exec_ctrls()) { + u64 ctls =3D 0; + + /* guest apic timer virtualization will come */ + + tertiary_exec_controls_set(vmx, ctls); + } + /* * ENTRY CONTROLS * @@ -2969,6 +2981,11 @@ static int nested_check_vm_execution_controls(struct= kvm_vcpu *vcpu, vmx->nested.msrs.secondary_ctls_high))) return -EINVAL; =20 + if (nested_cpu_has(vmcs12, CPU_BASED_ACTIVATE_TERTIARY_CONTROLS) && + CC(!vmx_control64_verify(vmcs12->tertiary_vm_exec_control, + vmx->nested.msrs.tertiary_ctls))) + return -EINVAL; + if (CC(vmcs12->cr3_target_count > nested_cpu_vmx_misc_cr3_count(vcpu)) || nested_vmx_check_io_bitmap_controls(vcpu, vmcs12) || nested_vmx_check_msr_bitmap_controls(vcpu, vmcs12) || diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h index 8c25054a710e..52bf035bcc03 100644 --- a/arch/x86/kvm/vmx/nested.h +++ b/arch/x86/kvm/vmx/nested.h @@ -175,6 +175,13 @@ static inline bool nested_cpu_has2(struct vmcs12 *vmcs= 12, u32 bit) (vmcs12->secondary_vm_exec_control & bit); } =20 +static inline bool nested_cpu_has3(struct vmcs12 *vmcs12, u64 bit) +{ + return (vmcs12->cpu_based_vm_exec_control & + CPU_BASED_ACTIVATE_TERTIARY_CONTROLS) && + (vmcs12->tertiary_vm_exec_control & bit); +} + static inline bool nested_cpu_has_preemption_timer(struct vmcs12 *vmcs12) { return vmcs12->pin_based_vm_exec_control & diff --git a/arch/x86/kvm/vmx/vmcs12.c b/arch/x86/kvm/vmx/vmcs12.c index 1ebe67c384ad..e2e2a99c8aa9 100644 --- a/arch/x86/kvm/vmx/vmcs12.c +++ b/arch/x86/kvm/vmx/vmcs12.c @@ -38,6 +38,7 @@ static const u16 kvm_supported_vmcs12_field_offsets[] __i= nitconst =3D { FIELD64(PML_ADDRESS, pml_address), FIELD64(TSC_OFFSET, tsc_offset), FIELD64(TSC_MULTIPLIER, tsc_multiplier), + FIELD64(TERTIARY_VM_EXEC_CONTROL, tertiary_vm_exec_control), FIELD64(VIRTUAL_APIC_PAGE_ADDR, virtual_apic_page_addr), FIELD64(APIC_ACCESS_ADDR, apic_access_addr), FIELD64(POSTED_INTR_DESC_ADDR, posted_intr_desc_addr), diff --git a/arch/x86/kvm/vmx/vmcs12.h b/arch/x86/kvm/vmx/vmcs12.h index 8c9d4c22b960..b7d30a2cf23f 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 tertiary_vm_exec_control; /* * To allow migration of L1 (complete with its L2 guests) between * machines of different natural widths (32 or 64 bit), we cannot have @@ -262,6 +262,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(tertiary_vm_exec_control, 336); CHECK_OFFSET(cr0_guest_host_mask, 344); CHECK_OFFSET(cr4_guest_host_mask, 352); CHECK_OFFSET(cr0_read_shadow, 360); --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 2C6F53ED5A2; Thu, 5 Mar 2026 17:44:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732681; cv=none; b=t6mCq7mdRaiiLNlR0P+OJHzTv4sLUOoxQUVQJCWeJKQV96TOiu8z8g8T52/t+mwZQ837OHgmY0I7AHC6kobugLbQ0xop2RON5YJeF+rENNBWiKb+yP3H9gq1YeyWRFBA8oQS3I4kIytnFvyqSIa9ZfchkM8ny6lq2M+mbPZMeIs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732681; c=relaxed/simple; bh=1Opn2f6DMZ4y5pqtubhiSso/f/rsTDueXc5LKTv0leM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=d6S0dhEkJVz6gC80aIc8clq+004MwUXLJP9NsLCBMYndozAeF1s9mklIrNS3KjkztJmju1e8C1fCnjR570adSyFHrCluY11jsb/QEnn/1RlC7Ylsl2eqEe9dnj9JWmd9ClsKMPt5bhbVycspCIKBE2E6XGY2sEJ8hJntgSMm4EU= 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=QKlvR77e; arc=none smtp.client-ip=198.175.65.15 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="QKlvR77e" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732680; x=1804268680; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=1Opn2f6DMZ4y5pqtubhiSso/f/rsTDueXc5LKTv0leM=; b=QKlvR77eTZsPdyfW2pGJCHLhg5z8ZFArhigcDobeW+Lw3gU4mQ+e0OSs V0L7KTyvlNVa5LUg7kdWh/zMH9TNHmtxqOaNVrAvbP2lHq09EVPVnRbN3 WDQ5AFOrcJr/iO6cePBLctsWb7wAS2DK3j8axh5mX/BJeAFOEIPPmC1fw os32vGV43HvQI6exeOPss1d2LikDz+Hu67cM849f1X7Kf3yUStOBFNCpn 0xdIYYpMhQEldRyWXq7CC/jjlKJakKAlOo3rJswgNESrQV9x6jVuHMlDC grcDOSAoIHVaVEg2H8oQ9+mL1CSJfAF13H3UDRFtz0UjTi7GkeQ21AYvR A==; X-CSE-ConnectionGUID: oN2f2LVCTlu1UqpkC7EylQ== X-CSE-MsgGUID: u2E2VtbSSh6XQi/FVKgQ6Q== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77431578" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77431578" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:38 -0800 X-CSE-ConnectionGUID: lof77IP7TMCxsd1noR2VXA== X-CSE-MsgGUID: fS3eNfvcRkKBphd1MRG0OQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="223447882" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:37 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 13/36] KVM: nVMX: Update intercept on TSC deadline MSR Date: Thu, 5 Mar 2026 09:43:53 -0800 Message-ID: <8987d935f9531f4afebccc6bb9d330fdb4812d80.1772732517.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata When APIC timer virtualization is enabled, the hardware handles the access to the guest TSC deadline MSR, not by the VMM. Disable/enable MSR intercept on TSC DEADLINE MSR based on the APIC timer virtualization bit of tertiary processor-based execution control. Signed-off-by: Isaku Yamahata --- arch/x86/kvm/vmx/nested.c | 22 ++++++++++++++++++++++ arch/x86/kvm/vmx/nested.h | 5 +++++ 2 files changed, 27 insertions(+) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 1bd5e164e285..8bb8734cc690 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -598,6 +598,26 @@ static inline void enable_x2apic_msr_intercepts(unsign= ed long *msr_bitmap) } } =20 +static inline void prepare_tsc_deadline_msr_intercepts(struct vmcs12 *vmcs= 12, + unsigned long *msr_bitmap_l1, + unsigned long *msr_bitmap_l0) +{ + if (nested_cpu_has_guest_apic_timer(vmcs12)) { + if (vmx_test_msr_bitmap_read(msr_bitmap_l1, MSR_IA32_TSC_DEADLINE)) + vmx_set_msr_bitmap_read(msr_bitmap_l0, MSR_IA32_TSC_DEADLINE); + else + vmx_clear_msr_bitmap_read(msr_bitmap_l0, MSR_IA32_TSC_DEADLINE); + + if (vmx_test_msr_bitmap_write(msr_bitmap_l1, MSR_IA32_TSC_DEADLINE)) + vmx_set_msr_bitmap_write(msr_bitmap_l0, MSR_IA32_TSC_DEADLINE); + else + vmx_clear_msr_bitmap_write(msr_bitmap_l0, MSR_IA32_TSC_DEADLINE); + } else { + vmx_set_msr_bitmap_read(msr_bitmap_l0, MSR_IA32_TSC_DEADLINE); + vmx_set_msr_bitmap_write(msr_bitmap_l0, MSR_IA32_TSC_DEADLINE); + } +} + #define BUILD_NVMX_MSR_INTERCEPT_HELPER(rw) \ static inline \ void nested_vmx_set_msr_##rw##_intercept(struct vcpu_vmx *vmx, \ @@ -745,6 +765,8 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct= kvm_vcpu *vcpu, } } =20 + prepare_tsc_deadline_msr_intercepts(vmcs12, msr_bitmap_l1, msr_bitmap_l0); + /* * Always check vmcs01's bitmap to honor userspace MSR filters and any * other runtime changes to vmcs01's bitmap, e.g. dynamic pass-through. diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h index 52bf035bcc03..6df2cfb20d87 100644 --- a/arch/x86/kvm/vmx/nested.h +++ b/arch/x86/kvm/vmx/nested.h @@ -286,6 +286,11 @@ static inline bool nested_cpu_has_encls_exit(struct vm= cs12 *vmcs12) return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENCLS_EXITING); } =20 +static inline bool nested_cpu_has_guest_apic_timer(struct vmcs12 *vmcs12) +{ + return nested_cpu_has3(vmcs12, TERTIARY_EXEC_GUEST_APIC_TIMER); +} + /* * if fixed0[i] =3D=3D 1: val[i] must be 1 * if fixed1[i] =3D=3D 0: val[i] must be 0 --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.17]) (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 678C73EB7F4; Thu, 5 Mar 2026 17:44:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.17 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732681; cv=none; b=ldc065gWmqttXQwFZqhTibSps+Olm7oL5jdDHmgTcFLMwGWStmDFhCi7/R8FiwQUXJ8Qd8QU9BX1DD4wKGe3yDjxfLmbQ3LoNAkd4hmYrpE4hf1Holu1JMNY97cmWvrpfO9UMHHbE+/CYVrcwMogJBVagirr51FJKiRnQoGz5fw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732681; c=relaxed/simple; bh=SVDXXF4WPsle4mwAe9qI2MJAYY6sFp0MwEwxBr4EPjw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Yb3I+yWNnQg1q9modF6z7DfNjZcpVdkzzSU+P1RlSnBLJL8TnqH4D+7Oy+tQbnwAo4X6Qupk0/kLFa3XxLVfyZr1sJjLTQ6/PFDQjay0T4aipe+ZNuByTKKcd0OdcmouBtjh1Xa5xUrY3kHpsU9X96Y52TWOYuHcou0smuAqzNs= 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=CeRZ9ycV; arc=none smtp.client-ip=198.175.65.17 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="CeRZ9ycV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732678; x=1804268678; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=SVDXXF4WPsle4mwAe9qI2MJAYY6sFp0MwEwxBr4EPjw=; b=CeRZ9ycVi4nta9wM/yBfjUPGOOOZaQiQz8bebgnaFHMUOT8nwIY4ZbX4 jLHbE11VdxwHqYBA5e3AXty+tJNYgyxUJxIkuZL1i6OcP5Wml2eD9RQ/u lqf2ZO2VTRQji7C2wdK7N/IMDOLzHitTUUgZ7TV8h1I/hWgkwoKx2PiMO FbtC0KmDTIDniRLwi4iw0skNuM589nt2s3lXkBmefD9wLiUkU6/aQsa4m t0Gq2Ar+fThtNGM+6VmiaCcjlPzpVmlMFExHbkeXCPlkYNcOHsmF5GJKY d610nOROeki9rFCmq1QhA7y6P4SP7jtSckE1EJZhBL4VZfe2ZiUjHO5qF A==; X-CSE-ConnectionGUID: lWMscCx9RXegsTtivtoCtA== X-CSE-MsgGUID: wpbZU6kNTxSVrd9MUQo86g== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="73798226" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="73798226" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa109.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:38 -0800 X-CSE-ConnectionGUID: kxQeCATPTqWEM9ZrMyyk7g== X-CSE-MsgGUID: Z9gGzkT2Qj+6etMhwy9fgA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="215527262" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by fmviesa006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:37 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 14/36] KVM: nVMX: Handle virtual timer vector VMCS field Date: Thu, 5 Mar 2026 09:43:54 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Support virtual timer vector VMCS field. Opportunistically add a size check of struct vmcs12. Signed-off-by: Isaku Yamahata --- Changes: v1 -> v2: - update for 5fdf86e7353c ("KVM: nVMX: Disallow access to vmcs12 fields that aren't supported by "hardware"") to use cpu_has_vmcs12_field(). --- arch/x86/kvm/vmx/nested.c | 6 +++++- arch/x86/kvm/vmx/vmcs12.c | 5 +++++ arch/x86/kvm/vmx/vmcs12.h | 2 ++ arch/x86/kvm/vmx/vmcs_shadow_fields.h | 1 + 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 8bb8734cc690..b7561f8f4565 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -2540,7 +2540,8 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx= , struct loaded_vmcs *vmcs0 if (cpu_has_tertiary_exec_ctrls()) { u64 ctls =3D 0; =20 - /* guest apic timer virtualization will come */ + if (nested_cpu_has_guest_apic_timer(vmcs12)) + ctls |=3D TERTIARY_EXEC_GUEST_APIC_TIMER; =20 tertiary_exec_controls_set(vmx, ctls); } @@ -2734,6 +2735,9 @@ static void prepare_vmcs02_rare(struct vcpu_vmx *vmx,= struct vmcs12 *vmcs12) vmcs_write64(EOI_EXIT_BITMAP3, vmcs12->eoi_exit_bitmap3); } =20 + if (nested_cpu_has_guest_apic_timer(vmcs12)) + vmcs_write16(GUEST_APIC_TIMER_VECTOR, vmcs12->virtual_timer_vector); + /* * If vmcs12 is configured to save TSC on exit via the auto-store list, * append the MSR to vmcs02's auto-store list so that KVM effectively diff --git a/arch/x86/kvm/vmx/vmcs12.c b/arch/x86/kvm/vmx/vmcs12.c index e2e2a99c8aa9..dac796fc20f2 100644 --- a/arch/x86/kvm/vmx/vmcs12.c +++ b/arch/x86/kvm/vmx/vmcs12.c @@ -3,6 +3,8 @@ =20 #include "vmcs12.h" =20 +static_assert(sizeof(struct vmcs12) <=3D VMCS12_SIZE); + #define VMCS12_OFFSET(x) offsetof(struct vmcs12, x) #define FIELD(number, name) [ENC_TO_VMCS12_IDX(number)] =3D VMCS12_OFFSET(= name) #define FIELD64(number, name) \ @@ -22,6 +24,7 @@ static const u16 kvm_supported_vmcs12_field_offsets[] __i= nitconst =3D { FIELD(GUEST_TR_SELECTOR, guest_tr_selector), FIELD(GUEST_INTR_STATUS, guest_intr_status), FIELD(GUEST_PML_INDEX, guest_pml_index), + FIELD(GUEST_APIC_TIMER_VECTOR, virtual_timer_vector), FIELD(HOST_ES_SELECTOR, host_es_selector), FIELD(HOST_CS_SELECTOR, host_cs_selector), FIELD(HOST_SS_SELECTOR, host_ss_selector), @@ -204,6 +207,8 @@ static __init bool cpu_has_vmcs12_field(unsigned int id= x) case HOST_SSP: case HOST_INTR_SSP_TABLE: return cpu_has_load_cet_ctrl(); + case GUEST_APIC_TIMER_VECTOR: + return cpu_has_vmx_apic_timer_virt(); =20 /* KVM always emulates PML and the VMX preemption timer in software. */ case GUEST_PML_INDEX: diff --git a/arch/x86/kvm/vmx/vmcs12.h b/arch/x86/kvm/vmx/vmcs12.h index b7d30a2cf23f..7a20d6661da0 100644 --- a/arch/x86/kvm/vmx/vmcs12.h +++ b/arch/x86/kvm/vmx/vmcs12.h @@ -191,6 +191,7 @@ struct __packed vmcs12 { u16 host_gs_selector; u16 host_tr_selector; u16 guest_pml_index; + u16 virtual_timer_vector; }; =20 /* @@ -374,6 +375,7 @@ static inline void vmx_check_vmcs12_offsets(void) CHECK_OFFSET(host_gs_selector, 992); CHECK_OFFSET(host_tr_selector, 994); CHECK_OFFSET(guest_pml_index, 996); + CHECK_OFFSET(virtual_timer_vector, 998); } =20 extern u16 vmcs12_field_offsets[] __ro_after_init; diff --git a/arch/x86/kvm/vmx/vmcs_shadow_fields.h b/arch/x86/kvm/vmx/vmcs_= shadow_fields.h index cad128d1657b..db1558d11c4c 100644 --- a/arch/x86/kvm/vmx/vmcs_shadow_fields.h +++ b/arch/x86/kvm/vmx/vmcs_shadow_fields.h @@ -34,6 +34,7 @@ BUILD_BUG_ON(1) /* 16-bits */ SHADOW_FIELD_RW(GUEST_INTR_STATUS, guest_intr_status) SHADOW_FIELD_RW(GUEST_PML_INDEX, guest_pml_index) +SHADOW_FIELD_RO(GUEST_APIC_TIMER_VECTOR, virtual_timer_vector) SHADOW_FIELD_RW(HOST_FS_SELECTOR, host_fs_selector) SHADOW_FIELD_RW(HOST_GS_SELECTOR, host_gs_selector) =20 --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.17]) (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 8064D3EB7F8; Thu, 5 Mar 2026 17:44:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.17 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732680; cv=none; b=XbJnsuemjx5+9avoZakLeinIuQPsYysqkfGlBL8Na19V8rgiOKoBfVhnjpMNw9OaHubL+vHuN1kMaVIv+nNrfLbaQdBB404rZRj2xEeMBWpfTHlEb6a9mNM5T/gDJFb12inBovqTxNSX+D6xS/OERIIUPJXN/oXg7HYSkbG87oU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732680; c=relaxed/simple; bh=eT6RD0SBGKCyF9wMnFs4nMq6bepuJAhSEWVNSCsxUn8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RsWZT/q+/nvdOSoOSVgCGUUHtnKB7ZWYYwCe0G2UAldRmdCMJ3krAMeq4XFWDKnvMd9WR0osfKo8XTy0FewccgJOfpkBqbUYJImbFR5O9UAaMzDsmw72gwhqS1aEUdFLuR2Zyvctd3IJe4phGM/oSdbMLsWsJWuu1t5KevYCyxA= 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=MFiCFOwz; arc=none smtp.client-ip=198.175.65.17 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="MFiCFOwz" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732678; x=1804268678; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=eT6RD0SBGKCyF9wMnFs4nMq6bepuJAhSEWVNSCsxUn8=; b=MFiCFOwzOR5Ux+rjEsHGE1xozaQQ3Vluimtqa093mUizMuCWd8b1x16X Ks9yurXkMKLYeetrM4ytug/3sbfbnZRaVVcxMHnsXpKdPqT+SNrEOP88+ aIYWYRwYUrNAqExJBx9d0h84ZddMy47UnJRcqjL/TNQ4G3dOtfsR+jVfJ z4uY9WlORv06fm3ShHao+aktWFL1VUNbBHK731o0YgP8IqOn/EoX7dvbZ ZQMkAmqkJ4dFtfAd0g4t5KyYbTAab/QGZAEgReHsmCkZXAAG1mDBc0dA6 HNRWePWj2Rc2z6Bn/STANg0+HNGAp1EDm6sJ4c9yY2jsgTmXmH7Xsp8r3 Q==; X-CSE-ConnectionGUID: 9B6Y1ljBQ4yIKiY6EshUQA== X-CSE-MsgGUID: qFVkyImLTtWX0KCn5LtrbQ== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="73798230" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="73798230" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa109.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:38 -0800 X-CSE-ConnectionGUID: k7MJz65HR/WGiH8UQmJWwA== X-CSE-MsgGUID: X8pU8Gw4TZGHbK7c+fJROw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="215527265" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by fmviesa006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:38 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 15/36] KVM: VMX: Make vmx_calc_deadline_l1_to_host() non-static Date: Thu, 5 Mar 2026 09:43:55 -0800 Message-ID: <59869f2d4dd95c00df4f78083509d39fc275ba3e.1772732517.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Remove static from vmx_calc_deadline_l1_to_host() and declare it in vmx.h. As nVMX APIC timer virtualization will use vmx_calc_deadline_l1_to_host(), make it available to nested.c. Make u64_shl_div_u64() usable for X86_32 as vmx_calc_deadline_l1_to_host() is used for both X86_32 and X86_64. Without this change, ARCH=3Di386 fails to compile. Signed-off-by: Isaku Yamahata --- arch/x86/kvm/vmx/vmx.c | 41 ++++++++++++++++++++++++----------------- arch/x86/kvm/vmx/vmx.h | 2 ++ 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 25f31103cb21..bac3f33f7d73 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -8318,25 +8318,32 @@ int vmx_check_intercept(struct kvm_vcpu *vcpu, return X86EMUL_INTERCEPTED; } =20 -#ifdef CONFIG_X86_64 /* (a << shift) / divisor, return 1 if overflow otherwise 0 */ static inline int u64_shl_div_u64(u64 a, unsigned int shift, u64 divisor, u64 *result) { - u64 low =3D a << shift, high =3D a >> (64 - shift); + u64 high =3D a >> (64 - shift); +#ifdef CONFIG_X86_64 + u64 low =3D a << shift; +#endif =20 /* To avoid the overflow on divq */ if (high >=3D divisor) return 1; =20 +#ifdef CONFIG_X86_64 /* Low hold the result, high hold rem which is discarded */ asm("divq %2\n\t" : "=3Da" (low), "=3Dd" (high) : "rm" (divisor), "0" (low), "1" (high)); *result =3D low; +#else + *result =3D mul_u64_u64_div_u64(a, 1ULL << shift, divisor); +#endif =20 return 0; } =20 +#ifdef CONFIG_X86_64 int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc, bool *expired) { @@ -8414,7 +8421,21 @@ void vmx_cancel_apic_virt_timer(struct kvm_vcpu *vcp= u) tertiary_exec_controls_clearbit(to_vmx(vcpu), TERTIARY_EXEC_GUEST_APIC_TI= MER); } =20 -static u64 vmx_calc_deadline_l1_to_host(struct kvm_vcpu *vcpu, u64 l1_tsc) +void vmx_set_guest_tsc_deadline_virt(struct kvm_vcpu *vcpu, + u64 guest_deadline_virt) +{ + vmcs_write64(GUEST_DEADLINE_VIR, guest_deadline_virt); + vmcs_write64(GUEST_DEADLINE_PHY, + vmx_calc_deadline_l1_to_host(vcpu, guest_deadline_virt)); +} + +u64 vmx_get_guest_tsc_deadline_virt(struct kvm_vcpu *vcpu) +{ + return vmcs_read64(GUEST_DEADLINE_VIR); +} +#endif + +u64 vmx_calc_deadline_l1_to_host(struct kvm_vcpu *vcpu, u64 l1_tsc) { u64 host_tsc_now =3D rdtsc(); u64 l1_tsc_now =3D kvm_read_l1_tsc(vcpu, host_tsc_now); @@ -8454,20 +8475,6 @@ static u64 vmx_calc_deadline_l1_to_host(struct kvm_v= cpu *vcpu, u64 l1_tsc) return host_tsc; } =20 -void vmx_set_guest_tsc_deadline_virt(struct kvm_vcpu *vcpu, - u64 guest_deadline_virt) -{ - vmcs_write64(GUEST_DEADLINE_VIR, guest_deadline_virt); - vmcs_write64(GUEST_DEADLINE_PHY, - vmx_calc_deadline_l1_to_host(vcpu, guest_deadline_virt)); -} - -u64 vmx_get_guest_tsc_deadline_virt(struct kvm_vcpu *vcpu) -{ - return vmcs_read64(GUEST_DEADLINE_VIR); -} -#endif - void vmx_update_cpu_dirty_logging(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx =3D to_vmx(vcpu); diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 9a61f6bd8cc0..6f1caf3ef5b7 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -394,6 +394,8 @@ static inline void vmx_enable_intercept_for_msr(struct = kvm_vcpu *vcpu, u64 vmx_get_l2_tsc_offset(struct kvm_vcpu *vcpu); u64 vmx_get_l2_tsc_multiplier(struct kvm_vcpu *vcpu); =20 +u64 vmx_calc_deadline_l1_to_host(struct kvm_vcpu *vcpu, u64 l1_tsc); + gva_t vmx_get_untagged_addr(struct kvm_vcpu *vcpu, gva_t gva, unsigned int= flags); =20 void vmx_update_cpu_dirty_logging(struct kvm_vcpu *vcpu); --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 8F5B23EFD1B; Thu, 5 Mar 2026 17:44:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732683; cv=none; b=mek5L0wQeif8mr0CE5i4uYC4+RVaOdle901Xe6wy/YLtLgVgvX3cR3JXRYGhQb/Trpkwi3NAtsQX9g+PSmCdoLX2kK8tXPsA/62d9HJePBGRBgbioFrNjg52mHIuqqljBHtysFBWKQC29Q16jnotbAGduJTGD5qB8aQFfH3Wl4c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732683; c=relaxed/simple; bh=huoyecPz/KqXQIsJELqEpkmIqLLtCWXKLwItJRSV4Ww=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fYmNJMQiZgQtx0szYmPCRcgV2EfS54sEf+Kq62tRK0noVjMZN4BzJgCcFoD+Gp2y+NELsmTK3qnBDEGeBOTsZFlgmptCl04KDT/JMKytvzoSsC1pf8Rj4AdhMlTZTy+ti+TzGI+iPje042j6l/NFw9SUTtLQlAkld0vmqHaqFR0= 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=T3p9JFcF; arc=none smtp.client-ip=198.175.65.15 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="T3p9JFcF" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732682; x=1804268682; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=huoyecPz/KqXQIsJELqEpkmIqLLtCWXKLwItJRSV4Ww=; b=T3p9JFcFdpfuF135KJKs3N72BCQWlj7TXfgZ8cpI/+7+j/+nBBx6n4z8 S8u1I5MC6JQV7PRzrVRwsPo2GZe4bq3yPzbWV/CKMiFTOcELrLyc3aj5l TlHgocjN0lTgORseVkdeuou0Ew26lwyi08tbSqm0qmFNhNM8nrAFBh3rb DHGCCZiL3fB04DjJMOugcmUssk2PX4R7Z09E+g/4UC5e94u1e/hsnpgno wXOsEf7QZ8R5Z01hs2eytM+WlPO/4NG55ChfSlBgH5LuCZ1x02YxAExDy lAu4EaDIHndWiYlmuRiA5MHnhNgm+PHrDCEl3JjqWLBeTXrWHIKz1vlAl Q==; X-CSE-ConnectionGUID: GznQX1t/RSWziGaHCbeHcg== X-CSE-MsgGUID: mGNGYQneTsq2Kp6gwthNjQ== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77431583" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77431583" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:39 -0800 X-CSE-ConnectionGUID: 43bUw0QRTcyiNNbpraHERg== X-CSE-MsgGUID: 74Vlv3WxSmGfw9VvEzNlsw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="223447891" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:38 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 16/36] KVM: nVMX: Enable guest deadline and its shadow VMCS field Date: Thu, 5 Mar 2026 09:43:56 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Support the guest deadline and the guest deadline shadow VMCS field. Signed-off-by: Isaku Yamahata --- Changes: v1 -> v2: - the offsets of vmcs fields changed due to rebase. --- arch/x86/kvm/vmx/nested.c | 48 +++++++++++++++++++++++++++++++++++++++ arch/x86/kvm/vmx/vmcs12.c | 2 ++ arch/x86/kvm/vmx/vmcs12.h | 5 ++++ arch/x86/kvm/vmx/vmx.h | 2 ++ 4 files changed, 57 insertions(+) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index b7561f8f4565..3f1318736205 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -2768,6 +2768,22 @@ static void prepare_vmcs02_rare(struct vcpu_vmx *vmx= , struct vmcs12 *vmcs12) set_cr4_guest_host_mask(vmx); } =20 +static void nested_guest_apic_timer(struct kvm_vcpu *vcpu, struct vmcs12 *= vmcs12) +{ + u64 guest_deadline_shadow =3D vmcs12->guest_deadline_shadow; + u64 guest_deadline =3D vmcs12->guest_deadline; + struct vcpu_vmx *vmx =3D to_vmx(vcpu); + + if (!vmx->nested.guest_deadline_dirty) + return; + + guest_deadline =3D vmx_calc_deadline_l1_to_host(vcpu, guest_deadline); + + vmcs_write64(GUEST_DEADLINE_PHY, guest_deadline); + vmcs_write64(GUEST_DEADLINE_VIR, guest_deadline_shadow); + vmx->nested.guest_deadline_dirty =3D false; +} + /* * prepare_vmcs02 is called when the L1 guest hypervisor runs its nested * L2 guest. L1 has a vmcs for L2 (vmcs12), and this function "merges" it @@ -2845,6 +2861,9 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, stru= ct vmcs12 *vmcs12, if (kvm_caps.has_tsc_control) vmcs_write64(TSC_MULTIPLIER, vcpu->arch.tsc_scaling_ratio); =20 + if (nested_cpu_has_guest_apic_timer(vmcs12)) + nested_guest_apic_timer(vcpu, vmcs12); + nested_vmx_transition_tlb_flush(vcpu, vmcs12, true); =20 if (nested_cpu_has_ept(vmcs12)) @@ -4635,6 +4654,8 @@ static bool is_vmcs12_ext_field(unsigned long field) case GUEST_IDTR_BASE: case GUEST_PENDING_DBG_EXCEPTIONS: case GUEST_BNDCFGS: + case GUEST_DEADLINE_PHY: + case GUEST_DEADLINE_VIR: return true; default: break; @@ -4685,6 +4706,24 @@ static void sync_vmcs02_to_vmcs12_rare(struct kvm_vc= pu *vcpu, vmcs12->guest_pending_dbg_exceptions =3D vmcs_readl(GUEST_PENDING_DBG_EXCEPTIONS); =20 + if (nested_cpu_has_guest_apic_timer(vmcs12)) { + u64 guest_deadline_shadow =3D vmcs_read64(GUEST_DEADLINE_VIR); + u64 guest_deadline =3D vmcs_read64(GUEST_DEADLINE_PHY); + + if (guest_deadline) { + guest_deadline =3D kvm_read_l1_tsc(vcpu, guest_deadline); + if (!guest_deadline) + guest_deadline =3D 1; + } + + vmcs12->guest_deadline =3D guest_deadline; + vmcs12->guest_deadline_shadow =3D guest_deadline_shadow; + } else if (vmx->nested.msrs.tertiary_ctls & TERTIARY_EXEC_GUEST_APIC_TIME= R) { + vmcs12->guest_deadline =3D 0; + vmcs12->guest_deadline_shadow =3D 0; + } + vmx->nested.guest_deadline_dirty =3D false; + vmx->nested.need_sync_vmcs02_to_vmcs12_rare =3D false; } =20 @@ -5933,6 +5972,13 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) vmx->nested.dirty_vmcs12 =3D true; } =20 + if (!is_guest_mode(vcpu) && + (field =3D=3D GUEST_DEADLINE_PHY || + field =3D=3D GUEST_DEADLINE_PHY_HIGH || + field =3D=3D GUEST_DEADLINE_VIR || + field =3D=3D GUEST_DEADLINE_VIR_HIGH)) + vmx->nested.guest_deadline_dirty =3D true; + return nested_vmx_succeed(vcpu); } =20 @@ -5947,6 +5993,7 @@ static void set_current_vmptr(struct vcpu_vmx *vmx, g= pa_t vmptr) } vmx->nested.dirty_vmcs12 =3D true; vmx->nested.force_msr_bitmap_recalc =3D true; + vmx->nested.guest_deadline_dirty =3D true; } =20 /* Emulate the VMPTRLD instruction */ @@ -7124,6 +7171,7 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu, =20 vmx->nested.dirty_vmcs12 =3D true; vmx->nested.force_msr_bitmap_recalc =3D true; + vmx->nested.guest_deadline_dirty =3D true; ret =3D nested_vmx_enter_non_root_mode(vcpu, false); if (ret) goto error_guest_mode; diff --git a/arch/x86/kvm/vmx/vmcs12.c b/arch/x86/kvm/vmx/vmcs12.c index dac796fc20f2..d2098767dd7a 100644 --- a/arch/x86/kvm/vmx/vmcs12.c +++ b/arch/x86/kvm/vmx/vmcs12.c @@ -70,6 +70,8 @@ static const u16 kvm_supported_vmcs12_field_offsets[] __i= nitconst =3D { FIELD64(HOST_IA32_PAT, host_ia32_pat), FIELD64(HOST_IA32_EFER, host_ia32_efer), FIELD64(HOST_IA32_PERF_GLOBAL_CTRL, host_ia32_perf_global_ctrl), + FIELD64(GUEST_DEADLINE_PHY, guest_deadline), + FIELD64(GUEST_DEADLINE_VIR, guest_deadline_shadow), FIELD(PIN_BASED_VM_EXEC_CONTROL, pin_based_vm_exec_control), FIELD(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control), FIELD(EXCEPTION_BITMAP, exception_bitmap), diff --git a/arch/x86/kvm/vmx/vmcs12.h b/arch/x86/kvm/vmx/vmcs12.h index 7a20d6661da0..0846033b6759 100644 --- a/arch/x86/kvm/vmx/vmcs12.h +++ b/arch/x86/kvm/vmx/vmcs12.h @@ -192,6 +192,9 @@ struct __packed vmcs12 { u16 host_tr_selector; u16 guest_pml_index; u16 virtual_timer_vector; + + u64 guest_deadline; + u64 guest_deadline_shadow; }; =20 /* @@ -376,6 +379,8 @@ static inline void vmx_check_vmcs12_offsets(void) CHECK_OFFSET(host_tr_selector, 994); CHECK_OFFSET(guest_pml_index, 996); CHECK_OFFSET(virtual_timer_vector, 998); + CHECK_OFFSET(guest_deadline, 1000); + CHECK_OFFSET(guest_deadline_shadow, 1008); } =20 extern u16 vmcs12_field_offsets[] __ro_after_init; diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 6f1caf3ef5b7..fbbbae46e0b2 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -163,6 +163,8 @@ struct nested_vmx { bool has_preemption_timer_deadline; bool preemption_timer_expired; =20 + bool guest_deadline_dirty; + /* * Used to snapshot MSRs that are conditionally loaded on VM-Enter in * order to propagate the guest's pre-VM-Enter value into vmcs02. For --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.17]) (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 4D9243EBF16; Thu, 5 Mar 2026 17:44:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.17 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732681; cv=none; b=FzdCKFrFEiAFdTG5FpX1GX5PEut+AQPpmSvbnIxtsw8VE+5Qjs6JLlp5JMZtWd9o3eBRxL5Mfei6yBefTMxr8uyslWadOdBoPlpeyAotvekeLNgKJ1G/20UuNOt6dOp3UWeylcAreKM2SzfDaqNChK7PTS9BVL768eiHlfuqeQY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732681; c=relaxed/simple; bh=wXZavH4PFskMoph6+sp6WaxRRQcx0bbNdaC4hw/pmB4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Q882GOgIdQgR+rbqczYUo1UjlFvKvR4dne0yksYyKifyj6IXbSTIDGzSsyPvKD0Rqu2yrcin9l1xB/Eq92GZ0bcrr337LiuuIS50d4X3NGvCRyjZlPLbCn0kyxAM/aT4+kFMkr62Kc+OSpH7fIe0Zln5EOGgkvpTCvaXKlDPgJI= 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=eoyDarV2; arc=none smtp.client-ip=198.175.65.17 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="eoyDarV2" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732679; x=1804268679; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=wXZavH4PFskMoph6+sp6WaxRRQcx0bbNdaC4hw/pmB4=; b=eoyDarV2OLTIfADJCUFEb81SSJ72XfEtR3JlXjltIaIA0SgsITFwCMXr /yy4siHBTwtfzUFf8O6AJejVJTl4ma8N8F6+EzV6Gm/XAZvNp2/z930F6 FaU+jWq5VLijvPHXIluMa/dcf6UqMPiZkKKe3Rmk8E/wzyJis1Lg3dByU x6i+4eDKLU6titT6OLwpfQVAEyVduYfvlPBn31G8yyFTMVlZMACegDbyI vQPqWpGI5PrDKoGgjP+AIFWDb+OheMtQ1Q8V/DnjV5E8xqrYpTFnpCj6U h+m2O0jGmyB0FVLtsJ0lOIzNH0c7pipzIERi/yv8350e8Q6n9KhucwhDB A==; X-CSE-ConnectionGUID: oByQ+lkAS8SUgwwJrq2DKA== X-CSE-MsgGUID: ShUYAmOhQuGh/EetOk9gpA== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="73798235" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="73798235" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa109.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:39 -0800 X-CSE-ConnectionGUID: 0Zoys+SbT2Kfet9GNXhITQ== X-CSE-MsgGUID: WHXnxA1STpucYuiqLWfsgA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="215527274" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by fmviesa006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:39 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 17/36] KVM: nVMX: Add VM entry checks related to APIC timer virtualization Date: Thu, 5 Mar 2026 09:43:57 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Add checks of VMX controls for APIC timer virtualization on VM entries. The spec adds some checks on VMX controls related to the APIC timer virtualization on VM entry. Signed-off-by: Isaku Yamahata --- arch/x86/kvm/vmx/nested.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 3f1318736205..65f7260d02df 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -3069,6 +3069,12 @@ static int nested_check_vm_execution_controls(struct= kvm_vcpu *vcpu, CC(!vmcs12->tsc_multiplier)) return -EINVAL; =20 + if (nested_cpu_has_guest_apic_timer(vmcs12) && + (CC(!nested_cpu_has_vid(vmcs12)) || + CC(nested_cpu_has(vmcs12, CPU_BASED_RDTSC_EXITING)) || + CC(vmcs12->virtual_timer_vector > 255))) + return -EINVAL; + return 0; } =20 --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.12]) (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 EB1043EDAC6; Thu, 5 Mar 2026 17:44:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732682; cv=none; b=CLgomu0DA/nzscLvi8YPQloefaJ2E7Kv0r8f86pnkEookVMw6kTGY+Sk3NYnrfwOHZ4WB6o8m8k0L44J6ZJFs+OOoB9clPru3890MZH329gNuufayoKLSMg9DjSFCzdSljicGznaYHtSzKeF16j+t8ILfZkiLf4wgFSoiaXstgE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732682; c=relaxed/simple; bh=mS5f5qZhqIx+pvSLY1xFCXbeyKKMW1F2yxVwlPCOzrQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eW/aqzhOeYmKSVTi7EXIRlxTAGIxdhAb2ws6HaNc5BGldS7ienBRWXprf130+nthmWA2+qoz6XFQX1fm5MJetTx5Ty5AddS0hzkzTF5OzPWhQp2C0LMu+2vQLEPDsFCR16Qv/n1p78Fsa2tgmcjlv8BAXB9nucrA+Kc3n9x+MFU= 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=aVFf4cyy; arc=none smtp.client-ip=192.198.163.12 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="aVFf4cyy" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732681; x=1804268681; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=mS5f5qZhqIx+pvSLY1xFCXbeyKKMW1F2yxVwlPCOzrQ=; b=aVFf4cyyhJWGJcdLr2S/9FokA1BUjjxq/NTICBvckFZVESL0bnyQOnbR 9Mv55pJOEVlOqZ0WfJPhutalGrxYz2lIYS/G2GZ+poh1Wt8WHIStEMEFh tI7eFWCNcWDGL1yDKQQ3T+ypxcSo1Rmz68QXoMliRHWRTfNqbpgp+xNTE 2r9MsMhzjOqhfgogzAEZ94CwxXcbYf0XVWoqwGzc52EICS81jjuFEKnZ1 STqIexBgJxkOfL7PUdPM2yWtJBmcBp+9H+kUVVQuHXFQlS+oBPrSiSkGQ CLNNO0AxVX3p4gWHb7/3TlOKMbycrlg9OVWMFh/2Z88PAhc1yi6YSeZvA Q==; X-CSE-ConnectionGUID: fBE/8CkJQv6rl7clSvxcGw== X-CSE-MsgGUID: rLmm0/DZQ+SiXwlZNr8kZw== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77701110" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77701110" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:40 -0800 X-CSE-ConnectionGUID: pY/28CaAQCWo0vitQB3Pwg== X-CSE-MsgGUID: yVR/FqEfSYmSsBmg3Z1kRg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="256647594" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:40 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 18/36] KVM: nVMX: Add check vmread/vmwrite on tertiary control Date: Thu, 5 Mar 2026 09:43:58 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Make the access to the tertiary processor-based VM control an error if the guest VMX true processor-based controls don't report it. Without this patch, the KVM unit test_vmread_vmwrite() fails because vmread()/vmwrite() can succeeds with the index beyond MSR_IA32_VMX_VMCS_ENUM when the tertiary processor-based VM-executing controls aren't advertised to the guest. Signed-off-by: Isaku Yamahata --- arch/x86/kvm/vmx/nested.c | 20 ++++++++++++++++++++ arch/x86/kvm/vmx/nested.h | 5 +++++ 2 files changed, 25 insertions(+) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 65f7260d02df..562b5ffc6433 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -5768,6 +5768,16 @@ static int handle_vmresume(struct kvm_vcpu *vcpu) return nested_vmx_run(vcpu, false); } =20 +static bool is_vmcs_field_valid(struct kvm_vcpu *vcpu, unsigned long field) +{ + if (!nested_cpu_supports_tertiary_ctls(vcpu) && + (field =3D=3D TERTIARY_VM_EXEC_CONTROL || + field =3D=3D TERTIARY_VM_EXEC_CONTROL_HIGH)) + return false; + + return true; +} + static int handle_vmread(struct kvm_vcpu *vcpu) { struct vmcs12 *vmcs12 =3D is_guest_mode(vcpu) ? get_shadow_vmcs12(vcpu) @@ -5798,6 +5808,9 @@ static int handle_vmread(struct kvm_vcpu *vcpu) get_vmcs12(vcpu)->vmcs_link_pointer =3D=3D INVALID_GPA)) return nested_vmx_failInvalid(vcpu); =20 + if (!is_vmcs_field_valid(vcpu, field)) + return nested_vmx_fail(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); + offset =3D get_vmcs12_field_offset(field); if (offset < 0) return nested_vmx_fail(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); @@ -5922,6 +5935,9 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) =20 field =3D kvm_register_read(vcpu, (((instr_info) >> 28) & 0xf)); =20 + if (!is_vmcs_field_valid(vcpu, field)) + return nested_vmx_fail(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); + offset =3D get_vmcs12_field_offset(field); if (offset < 0) return nested_vmx_fail(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); @@ -7170,6 +7186,10 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcp= u, kvm_state->hdr.vmx.preemption_timer_deadline; } =20 + if (!nested_cpu_supports_tertiary_ctls(vcpu) && + vmcs12->tertiary_vm_exec_control) + goto error_guest_mode; + if (nested_vmx_check_controls(vcpu, vmcs12) || nested_vmx_check_host_state(vcpu, vmcs12) || nested_vmx_check_guest_state(vcpu, vmcs12, &ignored)) diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h index 6df2cfb20d87..1100a8114dd9 100644 --- a/arch/x86/kvm/vmx/nested.h +++ b/arch/x86/kvm/vmx/nested.h @@ -157,6 +157,11 @@ static inline bool __nested_cpu_supports_tertiary_ctls= (struct nested_vmx_msrs *m return msrs->procbased_ctls_high & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; } =20 +static inline bool nested_cpu_supports_tertiary_ctls(struct kvm_vcpu *vcpu) +{ + return __nested_cpu_supports_tertiary_ctls(&to_vmx(vcpu)->nested.msrs); +} + /* APIC TIMER VIRTUALIZATION requires in-kernel lapic. */ static inline bool nested_cpu_can_support_apic_virt_timer(struct kvm_vcpu = *vcpu) { --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.12]) (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 9B2BD3EFD2D; Thu, 5 Mar 2026 17:44:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732683; cv=none; b=sLFgNQ/BDyZlHEURkmwMCYo/teWAXRSAnRvc9S/+Fwxn+7TcbHsHsNWceJwALe07ZYy4cvRKcjaz9mF3sWlPSBOr6LuEX06fa2s0Veu3oY22SQtaoUh4gk8KMZQQt2kaHg1tBL3Fzio1OasbOXwsE5tXZ+R4OVTD3WdL0C3VvE0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732683; c=relaxed/simple; bh=QdD5jenTwR29sa1dIqsfwFdRih7W65ynbtkxRigqKE0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nzDpPpQcKH1zMXgeATwHC9MWn4II8jF9sE8qSfRILquYY//QeFecbKW+Z+ONAmyaGjD1dDwL4QVUfGq/el+CjsZBStvfZmPKKqhWfasedxPhOfF5ANczEe9zSnX9YM9AxEz795PkjexpOpVFWWCZPrFtpEu0PO13VXdwkGE8I7w= 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=kBqfmAgT; arc=none smtp.client-ip=192.198.163.12 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="kBqfmAgT" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732682; x=1804268682; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=QdD5jenTwR29sa1dIqsfwFdRih7W65ynbtkxRigqKE0=; b=kBqfmAgT0WM6I7f2xHY+95KJUE0W1Hcj6idYxJTpHOxjzalqPVPjKCcF zj+gh+wKlOTesdRmeHJiTB7/EP4yeL95Tg9IGnxMInK2mvXgZEqAr+3Pt LaHENLw++lZNlbcie3RBeLAFnaTi41o0vFJhuLjKLBWgoj1SuNsJSe98u No+FQz4F49Xhvclht8g41SstaLd5v2Y6xRTqmdihgvAN1+4a0EyY6Jv/t oOGhX3afh4BhKVi43jmWmX0wRPVXaU4Wa70j4UK7P0W7Adflg0PFkIr9L 9qFMMbPa152eraBjqNksEGKj7xAzLoRYrhxquK0YCsU6z9UqYMtKLrVoq Q==; X-CSE-ConnectionGUID: ill+ReKzRm+rYAvrJgIfkQ== X-CSE-MsgGUID: qbCJ0v1IRau5+ykTrhjAow== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77701116" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77701116" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:41 -0800 X-CSE-ConnectionGUID: Ay5G3H1mTzypGVJQUzKJFg== X-CSE-MsgGUID: RX4o2c5/T+OiqCHEU3FtKg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="256647601" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:41 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 19/36] KVM: nVMX: Add check VMCS index for guest timer virtualization Date: Thu, 5 Mar 2026 09:43:59 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Make vmread/vmwrite to the VMCS fields an error if the guest MSR_IA32_VMX_PROCBASED_CTLS3 doesn't advertise APIC timer virtualization. Without this check, test_vmwrite_vmread of the KVM unit test fails. Signed-off-by: Isaku Yamahata --- arch/x86/kvm/vmx/nested.c | 14 ++++++++++++++ arch/x86/kvm/vmx/nested.h | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 562b5ffc6433..3cd29b005afe 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -5775,6 +5775,14 @@ static bool is_vmcs_field_valid(struct kvm_vcpu *vcp= u, unsigned long field) field =3D=3D TERTIARY_VM_EXEC_CONTROL_HIGH)) return false; =20 + if (!nested_cpu_supports_guest_apic_timer(vcpu) && + (field =3D=3D GUEST_APIC_TIMER_VECTOR || + field =3D=3D GUEST_DEADLINE_VIR || + field =3D=3D GUEST_DEADLINE_VIR_HIGH || + field =3D=3D GUEST_DEADLINE_PHY || + field =3D=3D GUEST_DEADLINE_PHY_HIGH)) + return false; + return true; } =20 @@ -7190,6 +7198,12 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcp= u, vmcs12->tertiary_vm_exec_control) goto error_guest_mode; =20 + if (!nested_cpu_supports_guest_apic_timer(vcpu) && + (vmcs12->virtual_timer_vector || + vmcs12->guest_deadline || + vmcs12->guest_deadline_shadow)) + goto error_guest_mode; + if (nested_vmx_check_controls(vcpu, vmcs12) || nested_vmx_check_host_state(vcpu, vmcs12) || nested_vmx_check_guest_state(vcpu, vmcs12, &ignored)) diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h index 1100a8114dd9..d5d624150aca 100644 --- a/arch/x86/kvm/vmx/nested.h +++ b/arch/x86/kvm/vmx/nested.h @@ -291,6 +291,13 @@ static inline bool nested_cpu_has_encls_exit(struct vm= cs12 *vmcs12) return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENCLS_EXITING); } =20 +static inline bool nested_cpu_supports_guest_apic_timer(struct kvm_vcpu *v= cpu) +{ + return nested_cpu_supports_tertiary_ctls(vcpu) && + to_vmx(vcpu)->nested.msrs.tertiary_ctls & + TERTIARY_EXEC_GUEST_APIC_TIMER; +} + static inline bool nested_cpu_has_guest_apic_timer(struct vmcs12 *vmcs12) { return nested_cpu_has3(vmcs12, TERTIARY_EXEC_GUEST_APIC_TIMER); --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.12]) (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 C38E23FFAC7; Thu, 5 Mar 2026 17:44:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732684; cv=none; b=seMs+94K1lJvKmH7k0lXq7Z146KWD+OTem7NultykBtsSgiXW2IoNTD3kOiIJ3zwVmTMzMtj6JZ3bQPOoEKxOzj/4v4Z3unJQoNiWzY9Xij6NSeIePeJCSLjKCnVkLs/mjcfqE7QetVeTuxQtlLu1v1wS8vb1xOvYHSUBNMLGFQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732684; c=relaxed/simple; bh=HDc12PQVv3ZBF2lEZk6jS6/6hE2E9STlZ/ISpWqGmls=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RhVrMBEL+HDi09rLa7JvXaukabApbNk3lPwOP+orJWaY7acpM9rxAEgFnH4hZFRzIsTwXGt04MjX/NIc4BkOWxdr4K3V2XITGxDcXa8CQf/nq6ugCu7fzxNCBwihq2PDPX46mXLH6DBReeqOy0K7BZnjuOYWhWMaXYmSJrShMVI= 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=VdDshT8c; arc=none smtp.client-ip=192.198.163.12 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="VdDshT8c" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732683; x=1804268683; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=HDc12PQVv3ZBF2lEZk6jS6/6hE2E9STlZ/ISpWqGmls=; b=VdDshT8cSY5X7/YmRvbMV21xhEPMtczViAcPzd5vJ+4S/7U8w/MRcJqo 5SRfWQlX6BEjef50BYZIi/7Y9vUUM+AKuagzJZBU28tUfSddHEjyKNf50 wB/4ceiXp9r0WhWQcGCGqU9Efm//95zboaLhU+k1ieEf8wSMUVCeWR4Q3 inYSzkc3HmCJjhIul1SXKrMpaXwE9uS6ZNTCtKKn69tzgyo9oBMP4fGMO HXSb/lInc35ryt/22swE2XiP3bQD7FWOPCnjjJJz1NvebzqNm2mcvlrUB F5q6EDR6W1tfwhctcuSO8fAA1aykia4Kj5fa8WT5oBK2dDUmqq97oh8jA Q==; X-CSE-ConnectionGUID: 79kN3D2QRXmjJg3igynDfw== X-CSE-MsgGUID: m7aU8yvWSTG4D2Jdd+l2Ig== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77701121" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77701121" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:42 -0800 X-CSE-ConnectionGUID: D1BecQheSPyJrhw2SugkEg== X-CSE-MsgGUID: JXlxc26jQNyVBIzmHQIaeg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="256647609" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:42 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 20/36] KVM: VMX: Advertise tertiary controls to the user space Date: Thu, 5 Mar 2026 09:44:00 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Make KVM_GET_MSR_INDEX_LIST, KVM_GET_MSR_FEATURE_INDEX_LIST, KVM_GET_MSRS to advertise MSR_IA32_VMX_PROCBASED_CTLS3 to the user space VMM like QEMU. Signed-off-by: Isaku Yamahata --- arch/x86/kvm/vmx/vmx.c | 3 +++ arch/x86/kvm/x86.c | 1 + 2 files changed, 4 insertions(+) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index bac3f33f7d73..8c2ab0164714 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -7214,6 +7214,9 @@ bool vmx_has_emulated_msr(struct kvm *kvm, u32 index) */ return enable_unrestricted_guest || emulate_invalid_guest_state; case KVM_FIRST_EMULATED_VMX_MSR ... KVM_LAST_EMULATED_VMX_MSR: + if (index =3D=3D MSR_IA32_VMX_PROCBASED_CTLS3 && + !__nested_cpu_supports_tertiary_ctls(&vmcs_config.nested)) + return false; return nested; case MSR_AMD64_VIRT_SPEC_CTRL: case MSR_AMD64_TSC_RATIO: diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 1922e8699101..8a1ec0a39624 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -457,6 +457,7 @@ static const u32 emulated_msrs_all[] =3D { MSR_IA32_VMX_PROCBASED_CTLS2, MSR_IA32_VMX_EPT_VPID_CAP, MSR_IA32_VMX_VMFUNC, + MSR_IA32_VMX_PROCBASED_CTLS3, =20 MSR_K7_HWCR, MSR_KVM_POLL_CONTROL, --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.12]) (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 71FB9411632; Thu, 5 Mar 2026 17:44:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732685; cv=none; b=Tn3Osde07KTr3gU1+W9RhkzENk98Bf8J7WameK5kGtlOoqPEO6I/b0uc5d3lNt/zwHL4VpGFJfguUrpY/5DvQvELEBugSiqtTCkm+Y+Jfnxd//MT9UbzJGHGVd3c4jNeztv0Q2yLFOPwTEoQtSOgy42lSTllDeYdafmwCG/BpM4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732685; c=relaxed/simple; bh=veZLFw252ZuZG/1W+qVgSJzBNoneJh//dkRFwAcadfo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mzW1tjGe9u/vstsSyhiYc/wnW5vCNum8YC+aNKwdkkBE5J+bFeu7j0xZs16lmUdROyBV6DwiixAFiPegBGrUk/JuJfljoqkeTSJ3KLNaPrJNnfbAaBa5kqg4OhJxR1BJDNGO27mGeN8gk1W8tyi1h5HQe1K5h+kbUbhsTLkTAw4= 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=gI+XYczt; arc=none smtp.client-ip=192.198.163.12 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="gI+XYczt" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732684; x=1804268684; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=veZLFw252ZuZG/1W+qVgSJzBNoneJh//dkRFwAcadfo=; b=gI+XYczt4MmWOTTdWthWcdDQlu/43EmQVVinwf5c3nrfKIaIS1kK2+KQ nz9zKaS0Dn78rO7qHE7eCyTVcYUBA2+WuABWR96RYCk3RWDrCCDu+tr9K Yv8lEP1mvRJ4p35frxbPdXJ8ZPSESMOBAwtmaYCxKaSYkt2edf0oMWwqN aY1S3c6d2vYSQn2u+j1xPQVJ/GoweEhApghBhfMcxSiTXNNporn3VStAt DHli6Hl2BYjtiYO52U+GUFW2KWYrMSoQRrpW+3Dt2LpwCEavXnaDaj7CG P1dueohryC2NaRTNuH0fW/FVe2EFxPUiIh4SPug1lHm64+krH2jxEgg2d g==; X-CSE-ConnectionGUID: gq5MYFKvRA26F7XRm/ioMg== X-CSE-MsgGUID: aSsLhDE5Sheh4gx+MUpvfQ== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77701127" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77701127" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:43 -0800 X-CSE-ConnectionGUID: i5rKjPoWT520bQQ3U1osNw== X-CSE-MsgGUID: GLSzLUnMQySJbIFIUKMrNg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="256647619" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:43 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org, Yang Zhong Subject: [PATCH v2 21/36] KVM: VMX: dump_vmcs() support the guest virt timer Date: Thu, 5 Mar 2026 09:44:01 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Yang Zhong Add three VMCS fields from the guest virt timer into dump_vmcs(). Signed-off-by: Yang Zhong Signed-off-by: Isaku Yamahata --- arch/x86/kvm/vmx/vmx.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 8c2ab0164714..e665fc7f3377 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -6594,6 +6594,12 @@ void dump_vmcs(struct kvm_vcpu *vcpu) vmx_dump_msrs("guest autoload", &vmx->msr_autoload.guest); if (vmcs_read32(VM_EXIT_MSR_STORE_COUNT) > 0) vmx_dump_msrs("autostore", &vmx->msr_autostore); + if (tertiary_exec_control & TERTIARY_EXEC_GUEST_APIC_TIMER) { + pr_err("DeadlinePhy =3D 0x%016llx\n", vmcs_read64(GUEST_DEADLINE_PHY)); + pr_err("DeadlineVir =3D 0x%016llx\n", vmcs_read64(GUEST_DEADLINE_VIR)); + pr_err("GuestApicTimerVector =3D 0x%04x\n", + vmcs_read16(GUEST_APIC_TIMER_VECTOR)); + } =20 if (vmentry_ctl & VM_ENTRY_LOAD_CET_STATE) pr_err("S_CET =3D 0x%016lx, SSP =3D 0x%016lx, SSP TABLE =3D 0x%016lx\n", --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.12]) (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 AD472428823; Thu, 5 Mar 2026 17:44:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732692; cv=none; b=ZUM7g18QxUWzP16cS+REzwBWnYDvxrJ1iLK4V4yHujy07jmqOnYUSesUf4ciBxQcAR/24eG8PJZwQ+7htyk7tOSbhjbYY93x1zumgtz4fUAqpm5Kk1SXdNHI4uYb+ogRK1B3FtaUMzCb0U/YOit9+1eJcm905zgDtQ+7I+yi0bQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732692; c=relaxed/simple; bh=DpdvT4loSRtnqsfH5MCvFkTqHKXLyWdscTJIsNn82z0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ug/gmJE1FeM7S9Aa8qXbYOmC/LZoPasrE/AN0XBn3fGo3RX10D+ohZyg2v5FjNw9Bog9QYgexNSLHxSgpwgo7yM27+AEqXeVDODyZEsNookdDZyz/zf6o9R4g06zlrK5TZ2UYLvxiORD5IDpsTnPkQ0wqrxFmPR3g4g5xWmJ9FU= 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=XHexieip; arc=none smtp.client-ip=198.175.65.12 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="XHexieip" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732690; x=1804268690; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=DpdvT4loSRtnqsfH5MCvFkTqHKXLyWdscTJIsNn82z0=; b=XHexieipkYAmqwtNIOkygGim3dlflrRNVtTfqTuDiiwPscNjjrG1O8Cu f7vGC+nj/wDwb0bkExxePCcRJlvsnGsyHhLxvLQ76M82zpALIIjfZW5B8 ZFIcAR4dD7e8R85aCJYvDncFaA4G8ohJDfJL99pzjEaERQjTZ9YgBGPk8 Z4l8viFoKvc8/EcE16GqFny0VHa4u5JZHyTIcI7Hkl5r/vXyK3J2yLQtH frQpI6pFMV2ym8DY144HHpExBF/lw1At1NQCl38PUG4Vp9sLIkIagLWP6 j0BX91oLXNKxfDbnjTDuXmrzVNNjnkCxMXQs8aYMq7AB68Xo6vQixdA11 Q==; X-CSE-ConnectionGUID: xvX6Bre6SZ6x28QzwbWIbA== X-CSE-MsgGUID: 5TKVszEmRgW+kZuI4MFZnw== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="85301946" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="85301946" Received: from orviesa003.jf.intel.com ([10.64.159.143]) by orvoesa104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:47 -0800 X-CSE-ConnectionGUID: ZO75T+yNS26b3/26mqgKPg== X-CSE-MsgGUID: w0SNUiuzRGCiEqHZ+rEwKQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="222896514" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by ORVIESA003-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:43 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 22/36] KVM: VMX: Enable APIC timer virtualization Date: Thu, 5 Mar 2026 09:44:02 -0800 Message-ID: <9a50051868ffc58a831e784f6fefe31968f062fc.1772732517.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Don't clear TERTIARY_EXEC_GUEST_APIC_TIMER bit unconditionally from KVM_OPTIONAL_VMX_TERTIARY_VM_EXEC_CONTROL when calculating supported bit. Signed-off-by: Isaku Yamahata --- Changes: v1 -> v2: - Move the bit disable to the caller of adjust_vmx_controls64() to avoid compile time error because KVM_OPTIONAL_VMX_TERTIARY_VM_EXEC_CONTROL is used for compile time check. --- arch/x86/kvm/vmx/vmx.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index e665fc7f3377..b3974125a902 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -2801,15 +2801,7 @@ static int setup_vmcs_config(struct vmcs_config *vmc= s_conf, =20 if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS) _cpu_based_3rd_exec_control =3D - adjust_vmx_controls64(KVM_OPTIONAL_VMX_TERTIARY_VM_EXEC_CONTROL - /* - * Disable apic timer - * virtualization until the logic - * is imlemented. - * Once it's supported, add - * TERTIARY_EXEC_GUEST_APIC_TIMER. - */ - & ~TERTIARY_EXEC_GUEST_APIC_TIMER, + adjust_vmx_controls64(KVM_OPTIONAL_VMX_TERTIARY_VM_EXEC_CONTROL, MSR_IA32_VMX_PROCBASED_CTLS3); =20 if (!IS_ENABLED(CONFIG_X86_64) || --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.12]) (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 0134F3FFAC7; Thu, 5 Mar 2026 17:44:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732689; cv=none; b=OjqFYowc2TV9l02osAJBX1KRdGg3X1v9/ZyYApu++Dfn1RFAMDlF/dFkcwSZBHa8lvUZF1I+uIl3DCGHHEYsAFH6kax8bKCSLDZsHZnCp6wF29elrInwHcsSHEm5K6eBulPROHa8+BtQMHMQmNb2mZMdO1WetVKXzb/URIL9vM8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732689; c=relaxed/simple; bh=1Ct/a9/bBoOc/zftIrXLz+ZeBhZv/LgEZuxduIZrBiQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=C4G6GJl7QIUlLR//SNAc2wgQUgnzgHM602dmEn6i/D37TK0zqTI/jrho1GfRiTunGl2GqNJSNlsRC1+u1CBOX1pth5AMrXDoPCJ6o5ZlYJI/ZSMsAeQUhWmOh4ZZVwQUzROYdRpwcoQfAVaDgbAFP6bU2o0tLpkvZ+NwaEFL/bE= 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=N+R5Cx/a; arc=none smtp.client-ip=198.175.65.12 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="N+R5Cx/a" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732688; x=1804268688; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=1Ct/a9/bBoOc/zftIrXLz+ZeBhZv/LgEZuxduIZrBiQ=; b=N+R5Cx/aHsPvFOKJUWc4854HLaHZRJIsVWS1RZVC6bp6ldTHYL2foUlF Fo0XEv3E35aua1ah6ECFcD6bGl/H4516nS2So8ufnVzf6vVlWF49VPKZJ GbgX2rs1TnvOuVIRRHLfqmqkowUdtj6S6+7YxQHj+AXusUNsBRVLsXVPB Z7pNooVadt50vLb7DMLTX3Un1d3uBi1V8k0N44xuqPkVOOF1qTYptaTZz sBcued4U40VVjDK+HfxfiT83/0tzTj41MHibz6lbPda3/hizKly2hoh1h kSFvdIbaToB2Q2TGUylOAHqWO5DikMz9VGUukDPfPjestq9/wAByqJG11 w==; X-CSE-ConnectionGUID: GoMFQoT0SmqhkxBHghFdJg== X-CSE-MsgGUID: K3qLwgudSreoMREb15GidQ== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="85301949" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="85301949" Received: from orviesa003.jf.intel.com ([10.64.159.143]) by orvoesa104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:47 -0800 X-CSE-ConnectionGUID: ZuVXfMIWRbO7LtRsw0M08g== X-CSE-MsgGUID: GSWJsuRFRICVdEsYn+RMcw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="222896518" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by ORVIESA003-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:44 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org, Yang Zhong Subject: [PATCH v2 23/36] KVM: VMX: Introduce module parameter for APIC virt timer support Date: Thu, 5 Mar 2026 09:44:03 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Yang Zhong Introduce a new module parameter, apic_timer_virt, to control the virtualization of the APIC timer in KVM. The primary improvement offered by APIC timer virtualization over the preemption timer is the passthrough of MSR_IA32_TSC_DEADLINE to the VM. This passthrough capability reduces the number of VM exits triggered by MSR write operations, thereby enhancing the performance of the virtual machine. The apic_timer_virt parameter is set to true by default on processor platforms that support APIC timer virtualization. On platforms that do not support this feature, the parameter will indicate that APIC timer virtualization is not available. Signed-off-by: Yang Zhong Signed-off-by: Isaku Yamahata --- arch/x86/kvm/vmx/vmx.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index b3974125a902..0271514162df 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -119,6 +119,9 @@ module_param(enable_ipiv, bool, 0444); =20 module_param(enable_device_posted_irqs, bool, 0444); =20 +static bool __read_mostly enable_apic_timer_virt =3D true; +module_param_named(apic_timer_virt, enable_apic_timer_virt, bool, 0444); + /* * If nested=3D1, nested virtualization is supported, i.e., guests may use * VMX and be a hypervisor for its own guests. If nested=3D0, guests may n= ot @@ -2804,7 +2807,7 @@ static int setup_vmcs_config(struct vmcs_config *vmcs= _conf, adjust_vmx_controls64(KVM_OPTIONAL_VMX_TERTIARY_VM_EXEC_CONTROL, MSR_IA32_VMX_PROCBASED_CTLS3); =20 - if (!IS_ENABLED(CONFIG_X86_64) || + if (!IS_ENABLED(CONFIG_X86_64) || !enable_apic_timer_virt || !(_cpu_based_2nd_exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY)) _cpu_based_3rd_exec_control &=3D ~TERTIARY_EXEC_GUEST_APIC_TIMER; =20 @@ -8835,6 +8838,9 @@ __init int vmx_hardware_setup(void) if (!cpu_has_vmx_preemption_timer()) enable_preemption_timer =3D false; =20 + if (!cpu_has_vmx_apic_timer_virt()) + enable_apic_timer_virt =3D false; + if (enable_preemption_timer) { u64 use_timer_freq =3D 5000ULL * 1000 * 1000; =20 --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.12]) (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 2B9423EB7E6; Thu, 5 Mar 2026 17:44:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732692; cv=none; b=lmgh4NYZZfUTnrR1ISA+XvZKALdrCSVSP6B32Zj8QrYhI/Nff0oMXams5Y7vLPeW8obsxwd9rxx+qHKeiOWcxC1+pcjvy0Y0IgXJ7VgfIiiAmUzwDxbQN5QyoZ1ISRXxKduTYPXO8aUwXvHn4xcuOz8m0zn/46NMA6Qzf4GCpZM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732692; c=relaxed/simple; bh=yBvXSCWCFU+Hikr0EvHDTy04mJGDwR9u1MTzGHv1i38=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HOEWkaFSpBIsk4R/XbEjNNIV6PJnWOXvKR4VOpqcrv9hOzcPlQjZiw+Q8R5kXUS3xZMKYDMu0AnpCDKIxb5RK+WOQkvnowAPASJJYIFaARz6ycx+O6q9/ILprpcgbnnXdBpfOqYl18pkDB3XykYHKaErJkS72vXiOJmo0024IAI= 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=RPbYZlkA; arc=none smtp.client-ip=198.175.65.12 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="RPbYZlkA" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732691; x=1804268691; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=yBvXSCWCFU+Hikr0EvHDTy04mJGDwR9u1MTzGHv1i38=; b=RPbYZlkAYYufAmWA33fCI77A4j1SZi5IQLtOYMgXfrbvFn7aED5bSU/3 Qlmeodpdkg9thLkqqtRZ7rYYIWnGp0Ei1cXiIDFKgVWde0qmKEeC577nC 5csDaZYEuLA1Shtav54uPVYiAmagi/Orfp8MGKwmgYp6QAvwthDyRhLI3 IDF7y1iL7ar3G9YdMsfKIUKWsnGHS9eV2rojT/0bjTzC0l+Gkpn99JClV ksc80bfowcQXqK/m/sojJUPXHx1UzCJ5S2hVXz3GOwsOyQtZ0ZUo87lIr 6dbPG+QUOaDg8gTlgiLmhS2s3+nkq4STTEOoSuf+8j3zuBaOCzJSttjSq A==; X-CSE-ConnectionGUID: bZQCNbf/THS2IaB+h77cwQ== X-CSE-MsgGUID: DuGRrEjHT/SDTMSK+kPXQw== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="85301952" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="85301952" Received: from orviesa003.jf.intel.com ([10.64.159.143]) by orvoesa104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:47 -0800 X-CSE-ConnectionGUID: fYxSK8FxQNKPL88aIDF7EA== X-CSE-MsgGUID: syGH3bWwQOCnRLiU4dfKmA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="222896521" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by ORVIESA003-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:45 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 24/36] KVM: nVMX: Introduce module parameter for nested APIC timer virtualization Date: Thu, 5 Mar 2026 09:44:04 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Introduce a new module parameter, nested_apic_timer_virt, to control the nested virtualization of the APIC timer in KVM. The nested_apic_timer_virt parameter is set to true by default on processor platforms that support APIC timer virtualization. On platforms that do not support this feature, the parameter will indicate that APIC timer virtualization is not available. Signed-off-by: Isaku Yamahata --- Changes: v1 -> v2: - use 0444 instead of S_IRUGO. --- arch/x86/kvm/vmx/capabilities.h | 1 + arch/x86/kvm/vmx/nested.c | 13 ++++++++++++- arch/x86/kvm/vmx/vmx.c | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilitie= s.h index 8d67be77f02c..861334e15c01 100644 --- a/arch/x86/kvm/vmx/capabilities.h +++ b/arch/x86/kvm/vmx/capabilities.h @@ -15,6 +15,7 @@ extern bool __read_mostly enable_ept; extern bool __read_mostly enable_unrestricted_guest; extern bool __read_mostly enable_ept_ad_bits; extern bool __read_mostly enable_pml; +extern bool __read_mostly enable_apic_timer_virt; extern int __read_mostly pt_mode; =20 #define PT_MODE_SYSTEM 0 diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 3cd29b005afe..60c7256298ce 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -27,6 +27,10 @@ module_param_named(enable_shadow_vmcs, enable_shadow_vmc= s, bool, S_IRUGO); static bool __ro_after_init warn_on_missed_cc; module_param(warn_on_missed_cc, bool, 0444); =20 +static bool __read_mostly enable_nested_apic_timer_virt =3D true; +module_param_named(nested_apic_timer_virt, enable_nested_apic_timer_virt, = bool, + 0444); + #define CC KVM_NESTED_VMENTER_CONSISTENCY_CHECK =20 /* @@ -7453,13 +7457,20 @@ static void nested_vmx_setup_secondary_ctls(u32 ept= _caps, static void nested_vmx_setup_tertiary_ctls(struct vmcs_config *vmcs_conf, struct nested_vmx_msrs *msrs) { - msrs->tertiary_ctls =3D vmcs_conf->cpu_based_3rd_exec_ctrl; + enable_nested_apic_timer_virt &=3D enable_apic_timer_virt; =20 + msrs->tertiary_ctls =3D vmcs_conf->cpu_based_3rd_exec_ctrl; msrs->tertiary_ctls &=3D TERTIARY_EXEC_GUEST_APIC_TIMER; =20 + if (!enable_nested_apic_timer_virt) + msrs->tertiary_ctls &=3D ~TERTIARY_EXEC_GUEST_APIC_TIMER; + if (msrs->tertiary_ctls) msrs->procbased_ctls_high |=3D CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; + + if (!(msrs->tertiary_ctls & TERTIARY_EXEC_GUEST_APIC_TIMER)) + enable_nested_apic_timer_virt =3D false; } =20 static void nested_vmx_setup_misc_data(struct vmcs_config *vmcs_conf, diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 0271514162df..4d5414af750b 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -119,7 +119,7 @@ module_param(enable_ipiv, bool, 0444); =20 module_param(enable_device_posted_irqs, bool, 0444); =20 -static bool __read_mostly enable_apic_timer_virt =3D true; +bool __read_mostly enable_apic_timer_virt =3D true; module_param_named(apic_timer_virt, enable_apic_timer_virt, bool, 0444); =20 /* --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.12]) (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 BD7EC3E5590; Thu, 5 Mar 2026 17:44:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732689; cv=none; b=bOzRPEAfiE629MDbrcpJv6JJtFtcFOhU+eUKmvtYPaLFPicdHT7K7UVBB/DjdDuQjlB5CM/iibnYMwemkl1jdg9ZWYDeuAME5C5iPezmkApKCVSWk6KLzrmM+BQDscmEGIp8QsIM26b9l5pK3LOotJa26p1wvLLynQE0SRVuzzk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732689; c=relaxed/simple; bh=Cg8yTdzn0rVU0yuzC7yjQWzMKwtPf0ak3PApZmuzZ08=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hnilIWDwumx3Aaki35WVL+zk/hhF8JUvWy2LA7PjaXzJ9FkyZCMdkIKfFZlCempSYQNlmJ/F6ML8ZlcUvsAsgu4b1CFFKgTpkwLnFMj9qH9WgFII5ucTbmF6caBJqDm3ERj221s9Jij81ECjEILW3tqr9Kgs5Q5ew0nD0SmzmeY= 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=jn4PDc+h; arc=none smtp.client-ip=192.198.163.12 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="jn4PDc+h" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732687; x=1804268687; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Cg8yTdzn0rVU0yuzC7yjQWzMKwtPf0ak3PApZmuzZ08=; b=jn4PDc+hM2bwwABHH6mKGB+j7WEJGBiD6VFL4gIzxCa2K/tS72plFnGp OmIRPBDVAlh9M8SB7NinIO9CZglRYwjrxyA3l0BHhzDPNypxR7+Rp8ysX DtQ3IBger42tY+Jm+PTozs+HI7gxpIY9Qw9ABUKhQObS9ZlnN/zuUysr9 /n67kPapj6+g6A6Na8NYwkfUscII8oN4sR8TGgvkozWy2uLkPifEaqo5M Cobu9TsFcpfJUUTN/hXa4+rSUtWvN4Hq4HckujnOcGuWo2xw8RzdZdR8n aloYFO3IHm8+Mvqr5ybKtFx55bVxm4NUC8/Q+WNs2GOvplnxm5VUucMdw A==; X-CSE-ConnectionGUID: 9QqMZ4m7R/SSNSa/lX0HAw== X-CSE-MsgGUID: JOHX32M2Ra6n32Fkk08WgA== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77701130" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77701130" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:47 -0800 X-CSE-ConnectionGUID: AiEgxAPoQ5iMy8144HaTgQ== X-CSE-MsgGUID: AJ3zKXkDRjasoYeIVUlvsw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="256647639" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:47 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 25/36] KVM: selftests: Add a test to measure local timer latency Date: Thu, 5 Mar 2026 09:44:05 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata A test case to measure local timer latency and to confirm that VMExit doesn't happen on TSC DEADLINE MSR on the platform that supports VMX APIC timer virtualization. Or VMExit happens on the platform without the feature. This is inspired by kvm-unit-test x86/tscdeadline_latency.c. The original test records all latency, but this records only the max/min/avg of the latency for simplicity. It sets the local APIC timer (APIC oneshot or TSC deadline) and the timer interrupt handler records the delay from the timer value. Signed-off-by: Isaku Yamahata --- Changes: v1 -> v2: - format fix in print_exit_stats() and help(). - static char * =3D> static const char * const for checkpatch. - use safe_halt(), sti(), cli() instead of inline assembly. --- tools/testing/selftests/kvm/Makefile.kvm | 1 + .../testing/selftests/kvm/x86/timer_latency.c | 578 ++++++++++++++++++ 2 files changed, 579 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/timer_latency.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index ba87cd31872b..3c2a5470c2ca 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -145,6 +145,7 @@ TEST_GEN_PROGS_x86 +=3D x86/max_vcpuid_cap_test TEST_GEN_PROGS_x86 +=3D x86/triple_fault_event_test TEST_GEN_PROGS_x86 +=3D x86/recalc_apic_map_test TEST_GEN_PROGS_x86 +=3D x86/aperfmperf_test +TEST_GEN_PROGS_x86 +=3D x86/timer_latency TEST_GEN_PROGS_x86 +=3D access_tracking_perf_test TEST_GEN_PROGS_x86 +=3D coalesced_io_test TEST_GEN_PROGS_x86 +=3D dirty_log_perf_test diff --git a/tools/testing/selftests/kvm/x86/timer_latency.c b/tools/testin= g/selftests/kvm/x86/timer_latency.c new file mode 100644 index 000000000000..7c2e8225f299 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/timer_latency.c @@ -0,0 +1,578 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2026 Intel Corporation + * + * Measure timer interrupt latency between time set to the local timer and + * interrupt arrival time. Optionally print out max/min/avg of the latenc= y. + */ + +#include +#include +#include +#include +#include + +#include "kvm_util.h" +#include "processor.h" +#include "apic.h" + +#define LOCAL_TIMER_VECTOR 0xec + +#define TEST_DURATION_DEFAULT_IN_SEC 10 + +/* Random number in ns, appropriate for timer interrupt */ +#define DEFAULT_TIMER_INC_NS 10000 + +/* Twice 100Hz scheduler tick for nested virtualization. */ +#define DEFAULT_ALLOWED_TIMER_LATENCY_NS (20 * 1000 * 1000) + +struct options { + bool use_oneshot_timer; + bool use_x2apic; + bool use_poll; + + uint64_t timer_inc_ns; + uint64_t allowed_timer_latency_ns; + + bool print_result; +}; + +static struct options options =3D { + .use_x2apic =3D true, + .timer_inc_ns =3D DEFAULT_TIMER_INC_NS, + .allowed_timer_latency_ns =3D DEFAULT_ALLOWED_TIMER_LATENCY_NS, +}; + +enum event_type { + EVENT_TIMER_HANDLER, + EVENT_HLT_WAKEUP, + EVENT_MAX, +}; + +struct test_sample { + uint64_t time_stamp; + enum event_type etype; + uint32_t latency; +}; + +struct test_latency_stat { + uint64_t sum; + uint64_t count; + uint32_t min; + uint32_t max; +}; + +struct test_shared_data { + atomic_bool stop_test; + atomic_bool terminated; + uint64_t tsc_khz; + uint64_t apic_bus_cycle_ns; + uint64_t allowed_timer_latency_tsc; + + uint64_t timer_inc; + + uint64_t hlt_count; + uint64_t timer_interrupt_set; + uint64_t timer_interrupt_received; + + struct test_latency_stat latency_stat[EVENT_MAX]; +}; + +#define GUEST_ASSERT_LATENCY(latency_tsc) \ + __GUEST_ASSERT((latency_tsc) <=3D data->allowed_timer_latency_tsc, \ + "too large timer latency %ld ns " \ + "(requires %ld ns) %ld khz tsc", \ + tsc_to_ns(data, latency_tsc), \ + options.allowed_timer_latency_ns, \ + data->tsc_khz) + +static struct test_shared_data shared_data; + +static u64 tsc_to_ns(struct test_shared_data *data, u64 tsc_delta) +{ + return tsc_delta * NSEC_PER_SEC / (data->tsc_khz * 1000); +} + +static u64 ns_to_tsc(struct test_shared_data *data, u64 ns) +{ + return ns * (data->tsc_khz * 1000) / NSEC_PER_SEC; +} + +static void latency_init(struct test_latency_stat *stat) +{ + stat->sum =3D 0; + stat->count =3D 0; + stat->min =3D -1; + stat->max =3D 0; +} + +static void shared_data_init(struct test_shared_data *data) +{ + int i; + + memset(data, 0, sizeof(*data)); + + for (i =3D 0; i < ARRAY_SIZE(data->latency_stat); i++) + latency_init(data->latency_stat + i); +} + +static void stop_test(struct kvm_vm *vm, struct test_shared_data *data) +{ + atomic_store(&data->stop_test, true); + sync_global_to_guest(vm, data->stop_test); +} + +static void guest_apic_enable(void) +{ + if (options.use_x2apic) + x2apic_enable(); + else + xapic_enable(); +} + +static void guest_apic_write_reg(unsigned int reg, uint64_t val) +{ + if (options.use_x2apic) + x2apic_write_reg(reg, val); + else + xapic_write_reg(reg, val); +} + +static void record_sample(struct test_shared_data *data, enum event_type e= type, + uint64_t ts, uint64_t latency) +{ + struct test_latency_stat *stat; + + stat =3D &data->latency_stat[etype]; + + stat->count++; + stat->sum +=3D latency; + + if (stat->min > latency) + stat->min =3D latency; + if (stat->max < latency) + stat->max =3D latency; + + if (etype =3D=3D EVENT_TIMER_HANDLER && + latency > data->allowed_timer_latency_tsc) { + if (options.use_poll) { + GUEST_PRINTF("latency is too high %ld ns (> %ld ns)\n", + tsc_to_ns(data, latency), + options.allowed_timer_latency_ns); + } else + GUEST_ASSERT_LATENCY(latency); + } +} + +static atomic_bool timer_interrupted; +static atomic_uint_fast64_t timer_tsc; + +static inline bool tsc_before(u64 a, u64 b) +{ + return (s64)(a - b) < 0; +} + +static void guest_timer_interrupt_handler(struct ex_regs *regs) +{ + uint64_t now =3D rdtsc(); + uint64_t timer_tsc__ =3D atomic_load(&timer_tsc); + + __GUEST_ASSERT(!atomic_load(&timer_interrupted), + "timer handler is called multiple times per timer"); + __GUEST_ASSERT(tsc_before(timer_tsc__, now), + "timer is fired before armed time timer_tsc 0x%lx now 0x%lx", + timer_tsc__, now); + + record_sample(&shared_data, EVENT_TIMER_HANDLER, now, now - timer_tsc__); + + shared_data.timer_interrupt_received++; + atomic_store(&timer_interrupted, true); + guest_apic_write_reg(APIC_EOI, 0); +} + +static void __set_timer(struct test_shared_data *data, + uint64_t next_tsc, uint64_t apic_inc) +{ + if (options.use_oneshot_timer) + guest_apic_write_reg(APIC_TMICT, apic_inc); + else + wrmsr(MSR_IA32_TSC_DEADLINE, next_tsc); +} + +static void set_timer(struct test_shared_data *data, + uint64_t next_tsc, uint64_t apic_inc) +{ + atomic_store(&timer_tsc, next_tsc); + data->timer_interrupt_set++; + __set_timer(data, next_tsc, apic_inc); +} + +static u64 to_apic_bus_cycle(struct test_shared_data *data, u64 tsc_delta) +{ + u64 ret; + + if (!tsc_delta) + return 0; + + ret =3D tsc_to_ns(data, tsc_delta) / data->apic_bus_cycle_ns; + if (!ret) + ret++; + + return ret; +} + +static void hlt_loop(struct test_shared_data *data) +{ + uint64_t inc, now, prev_tsc, next_tsc; + + cli(); + guest_apic_enable(); + + inc =3D data->timer_inc; + + /* DIVISOR =3D 1 for oneshot timer case */ + guest_apic_write_reg(APIC_TDCR, 0xb); + guest_apic_write_reg(APIC_LVTT, + (options.use_oneshot_timer ? + APIC_LVT_TIMER_ONESHOT : + APIC_LVT_TIMER_TSCDEADLINE) | + LOCAL_TIMER_VECTOR); + + next_tsc =3D rdtsc() + inc; + if (!next_tsc) + next_tsc++; + atomic_store(&timer_interrupted, false); + set_timer(data, next_tsc, to_apic_bus_cycle(data, inc)); + + while (!atomic_load(&data->stop_test)) { + prev_tsc =3D rdtsc(); + + if (options.use_poll) { + sti(); + while (!atomic_load(&timer_interrupted) && + rdtsc() < next_tsc + data->allowed_timer_latency_tsc) + cpu_relax(); + cli(); + } else { + /* "sti; hlt; cli" */ + safe_halt(); + cli(); + } + + now =3D rdtsc(); + + record_sample(data, EVENT_HLT_WAKEUP, now, now - prev_tsc); + data->hlt_count++; + + if (atomic_load(&timer_interrupted)) { + while (next_tsc <=3D now) + next_tsc +=3D inc; + if (!next_tsc) + next_tsc++; + + atomic_store(&timer_interrupted, false); + set_timer(data, next_tsc, + to_apic_bus_cycle(data, next_tsc - now)); + } else { + uint64_t latency =3D now - next_tsc; + + GUEST_ASSERT_LATENCY(latency); + } + } + + /* Wait for the interrupt to arrive. */ + now =3D rdtsc(); + next_tsc =3D now + inc * 2; + sti(); + while (now < next_tsc || !atomic_load(&timer_interrupted)) { + cpu_relax(); + now =3D rdtsc(); + } + cli(); + + /* Stop timer explicitly just in case. */ + __set_timer(data, 0, 0); +} + +static void guest_code(void) +{ + struct test_shared_data *data =3D &shared_data; + + hlt_loop(data); + + __GUEST_ASSERT(data->timer_interrupt_set =3D=3D data->timer_interrupt_rec= eived, + "timer interrupt lost set %ld received %ld", + data->timer_interrupt_set, data->timer_interrupt_received); + + GUEST_DONE(); +} + +static void __run_vcpu(struct kvm_vcpu *vcpu) +{ + struct ucall uc; + + for (;;) { + vcpu_run(vcpu); + + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + + switch (get_ucall(vcpu, &uc)) { + case UCALL_DONE: + pr_info("vcpu id %d passed\n", vcpu->id); + return; + case UCALL_ABORT: + REPORT_GUEST_ASSERT(uc); + return; + case UCALL_PRINTF: + pr_info("%s", uc.buffer); + continue; + default: + TEST_FAIL("Unexpected ucall cmd: %ld", uc.cmd); + return; + } + + return; + } +} + +static void *run_vcpu(void *args) +{ + struct kvm_vcpu *vcpu =3D args; + + __run_vcpu(vcpu); + + return NULL; +} + +static void print_result_type(struct test_shared_data *data, + enum event_type etype, const char *event_name) +{ + struct test_latency_stat *stat =3D &data->latency_stat[etype]; + uint64_t avg =3D 0; + + if (stat->count) + avg =3D stat->sum / stat->count; + + pr_info("%s latency (%ld samples)\tmin %ld avg %ld max %ld ns\n", + event_name, stat->count, + tsc_to_ns(data, stat->min), tsc_to_ns(data, avg), + tsc_to_ns(data, stat->max)); +} + +static void print_result(struct test_shared_data *data) +{ + pr_info("guest timer: %s timer period %ld ns\n", + options.use_oneshot_timer ? + "APIC oneshot timer" : "tsc deadline", + options.timer_inc_ns); + + pr_info("tsc_khz %ld apic_bus_cycle_ns %ld\n", + data->tsc_khz, data->apic_bus_cycle_ns); + + pr_info("hlt %ld timer set %ld received %ld\n", + data->hlt_count, + data->timer_interrupt_set, data->timer_interrupt_received); + + print_result_type(data, EVENT_TIMER_HANDLER, "timer interrupt"); + print_result_type(data, EVENT_HLT_WAKEUP, "halt wakeup"); +} + +static void print_exit_stats(struct kvm_vcpu *vcpu) +{ + static const char * const stat_name[] =3D { + "exits", + "halt_exits", + "irq_exits", + "inject_tscdeadline" + }; + uint64_t data; + int i; + + for (i =3D 0; i < ARRAY_SIZE(stat_name); i++) { + kvm_get_stat(&vcpu->stats, stat_name[i], &data, 1); + pr_info("%s: %ld ", stat_name[i], data); + } + pr_info("\n"); +} + +static void setup_timer_freq(struct kvm_vm *vm, + struct test_shared_data *data) +{ + data->tsc_khz =3D __vm_ioctl(vm, KVM_GET_TSC_KHZ, NULL); + TEST_ASSERT(data->tsc_khz > 0, "KVM_GET_TSC_KHZ failed.."); + + data->apic_bus_cycle_ns =3D kvm_check_cap(KVM_CAP_X86_APIC_BUS_CYCLES_NS); + if (options.use_oneshot_timer) + data->timer_inc =3D options.timer_inc_ns * data->apic_bus_cycle_ns; + else + data->timer_inc =3D ns_to_tsc(data, options.timer_inc_ns); + + data->allowed_timer_latency_tsc =3D + ns_to_tsc(data, options.allowed_timer_latency_ns); +} + +static void setup(struct kvm_vm **vm__, struct kvm_vcpu **vcpu__) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + vm =3D vm_create_with_one_vcpu(&vcpu, guest_code); + vm_install_exception_handler(vm, LOCAL_TIMER_VECTOR, + guest_timer_interrupt_handler); + setup_timer_freq(vm, &shared_data); + + if (!options.use_oneshot_timer) + vcpu_set_cpuid_feature(vcpu, X86_FEATURE_TSC_DEADLINE_TIMER); + + sync_global_to_guest(vm, options); + sync_global_to_guest(vm, shared_data); + + *vm__ =3D vm; + *vcpu__ =3D vcpu; +} + +static void print_stats(struct kvm_vm *vm, struct kvm_vcpu *vcpu) +{ + if (options.print_result) { + sync_global_from_guest(vm, *&shared_data); + print_result(&shared_data); + print_exit_stats(vcpu); + } +} + +static void sigterm_handler(int signum, siginfo_t *info, void *arg_) +{ + atomic_store(&shared_data.terminated, true); +} + +static int run_test(unsigned int duration) +{ + struct kvm_vcpu *vcpu; + struct sigaction sa; + struct kvm_vm *vm; + pthread_t thread; + int r; + + shared_data_init(&shared_data); + + setup(&vm, &vcpu); + + sa =3D (struct sigaction) { + .sa_sigaction =3D sigterm_handler, + }; + sigemptyset(&sa.sa_mask); + r =3D sigaction(SIGTERM, &sa, NULL); + TEST_ASSERT(!r, "sigaction"); + + r =3D pthread_create(&thread, NULL, run_vcpu, vcpu); + TEST_ASSERT(!r, "pthread_create"); + + while (duration > 0 && !atomic_load(&shared_data.terminated)) { + duration =3D sleep(duration); + TEST_ASSERT(duration >=3D 0, "sleep"); + } + + if (atomic_load(&shared_data.terminated)) { + pr_info("terminated\n"); + print_stats(vm, vcpu); + return -EINTR; + } + + stop_test(vm, &shared_data); + + r =3D pthread_join(thread, NULL); + TEST_ASSERT(!r, "pthread_join"); + + print_stats(vm, vcpu); + + kvm_vm_free(vm); + return 0; +} + +static void help(const char *name) +{ + puts(""); + printf("usage: %s ", name); + printf("[-h] [-l] [-d duration_in_sec] [-a allowed_timer_latency] "); + printf("[-p period_in_ns] [-o] [-O] [-x] [-X]\n"); + puts(""); + printf("-h: Display this message."); + printf("-l: use idle loop instead of hlt\n"); + printf("-d: specify test to run in second (default %d sec)\n", + TEST_DURATION_DEFAULT_IN_SEC); + printf("-p: timer period in ns (default %d nsec)\n", + DEFAULT_TIMER_INC_NS); + printf("-a: allowed timer latency in ns (default %d nsec)\n", + DEFAULT_ALLOWED_TIMER_LATENCY_NS); + printf("-o: use APIC oneshot timer instead of TSC deadline timer\n"); + printf("-t: use TSC deadline timer instead of APIC oneshot timer (default= )\n"); + printf("-P: print result stat\n"); + printf("-x: use xAPIC mode\n"); + printf("-X: use x2APIC mode (default)\n"); + puts(""); + + exit(EXIT_SUCCESS); +} + +int main(int argc, char **argv) +{ + int opt; + unsigned int duration =3D TEST_DURATION_DEFAULT_IN_SEC; + + while ((opt =3D getopt(argc, argv, "hld:p:a:otxXP")) !=3D -1) { + switch (opt) { + case 'l': + options.use_poll =3D true; + break; + + case 'd': + duration =3D atoi_non_negative("test duration in sec", optarg); + break; + case 'p': + options.timer_inc_ns =3D + atoi_non_negative("timer period in nsec", optarg); + break; + case 'a': + options.allowed_timer_latency_ns =3D + atoi_non_negative("allowed timer latency in nsec", + optarg); + break; + + + case 'x': + options.use_x2apic =3D false; + break; + case 'X': + options.use_x2apic =3D true; + break; + + case 'o': + options.use_oneshot_timer =3D true; + break; + case 't': + options.use_oneshot_timer =3D false; + break; + + case 'P': + options.print_result =3D true; + break; + + case 'h': + default: + help(argv[0]); + break; + } + } + + TEST_REQUIRE(kvm_has_cap(KVM_CAP_GET_TSC_KHZ)); + TEST_REQUIRE(kvm_has_cap(KVM_CAP_VM_TSC_CONTROL)); + if (!options.use_oneshot_timer) + TEST_REQUIRE(kvm_has_cap(KVM_CAP_TSC_DEADLINE_TIMER)); + TEST_REQUIRE(kvm_has_cap(KVM_CAP_X86_APIC_BUS_CYCLES_NS)); + if (options.use_x2apic) + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_X2APIC)); + + run_test(duration); + + return 0; +} --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.12]) (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 5EC173E7176; Thu, 5 Mar 2026 17:44:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732690; cv=none; b=eKZj9ASaoatlk25O8DrSHQAccSkLfx+u/KzjozhVWa12ewuoO+6dcbGYFF4bWA0PCcT4L8R+QkemGHOAp6dlar1920Rn1nd1/BML0jT7s1zpMyS8jTcO3kJmFU9wIyAyRqGwI55RjxCdNGVebQ76MVZ4d8iWAmyIY9jbBXMmDsg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732690; c=relaxed/simple; bh=wn1c0mMi0EQMu1HoAaIYunIacKiukKqa9rHPqNsGVBo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iFdX6d9s/TY6xMYYzRxg/OW3fJHXa646VitWqk0uC5LmyJOyC/Xu0RhHcM98aQbleOQdkpYA55nlc4yawk8AfzyzHIXvwcKK+pRW6SxoIIFbgkzCZTAYvgmhthp3FaVYKzYOtt6FKtXNtMojkMyc4ardSyKFePT1XAqc4e+fnx4= 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=ImdzyLjN; arc=none smtp.client-ip=192.198.163.12 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="ImdzyLjN" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732689; x=1804268689; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=wn1c0mMi0EQMu1HoAaIYunIacKiukKqa9rHPqNsGVBo=; b=ImdzyLjNEgH/ZCO/FQe8mZcAZd8rdAnzdmzZ4kAqbyC3NkGWW5RQ5l1D wJ34YSlSI/O2ZrhqYR5oKhvWA6HNZp5s1ovWaTlrBf1oba3JujWOLjl3X /06Nv8F1e3O4WOQFpm2dSivBl5WsKu+sLEkScH6RX6rtGQ+oxXnaxCWVl AE4/ttlWcMI/jCk7yFGRIJUdQVu6/URrRBuMQW5E+wA9Mu8v3ilRXQa/q qPbvqDVfTdEOoSg2VkUwIyW4e/BxvltvwmK/4yRreITPK+9/UtCPAnsJD RmjzDbJ+M600704lLS/bt8vMKlhPFxk5U2SMYsce2JI/tfg2MqjcvIRyQ w==; X-CSE-ConnectionGUID: gEn7gd3lRhy0nmeK51B73g== X-CSE-MsgGUID: BEe8R4LvT/ae8BgrjxF0bQ== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77701134" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77701134" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:48 -0800 X-CSE-ConnectionGUID: x0tobNUMSZ2PhuEeYNwGvg== X-CSE-MsgGUID: fwG/PlbjQMqos6fng9N1TA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="256647649" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:48 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 26/36] KVM: selftests: Add nVMX support to timer_latency test case Date: Thu, 5 Mar 2026 09:44:06 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Support nVMX for the timer_latency test case to exercise the nVMX APIC timer virtualization. Signed-off-by: Isaku Yamahata --- tools/testing/selftests/kvm/include/x86/vmx.h | 10 ++ .../testing/selftests/kvm/x86/timer_latency.c | 132 +++++++++++++++++- 2 files changed, 139 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86/vmx.h b/tools/testing/= selftests/kvm/include/x86/vmx.h index 92b918700d24..4be103c7b367 100644 --- a/tools/testing/selftests/kvm/include/x86/vmx.h +++ b/tools/testing/selftests/kvm/include/x86/vmx.h @@ -24,6 +24,7 @@ #define CPU_BASED_RDTSC_EXITING 0x00001000 #define CPU_BASED_CR3_LOAD_EXITING 0x00008000 #define CPU_BASED_CR3_STORE_EXITING 0x00010000 +#define CPU_BASED_ACTIVATE_TERTIARY_CONTROLS 0x00020000 #define CPU_BASED_CR8_LOAD_EXITING 0x00080000 #define CPU_BASED_CR8_STORE_EXITING 0x00100000 #define CPU_BASED_TPR_SHADOW 0x00200000 @@ -63,6 +64,12 @@ #define SECONDARY_ENABLE_XSAV_RESTORE 0x00100000 #define SECONDARY_EXEC_TSC_SCALING 0x02000000 =20 +/* + * Definitions of Tertiary Processor-Based VM-Execution Controls. + * It's 64 bit unlike primary/secondary processor based vm-execution contr= ols. + */ +#define TERTIARY_EXEC_GUEST_APIC_TIMER 0x0000000000000100ULL + #define PIN_BASED_EXT_INTR_MASK 0x00000001 #define PIN_BASED_NMI_EXITING 0x00000008 #define PIN_BASED_VIRTUAL_NMIS 0x00000020 @@ -104,6 +111,7 @@ enum vmcs_field { VIRTUAL_PROCESSOR_ID =3D 0x00000000, POSTED_INTR_NV =3D 0x00000002, + GUEST_APIC_TIMER_VECTOR =3D 0x0000000a, GUEST_ES_SELECTOR =3D 0x00000800, GUEST_CS_SELECTOR =3D 0x00000802, GUEST_SS_SELECTOR =3D 0x00000804, @@ -163,6 +171,8 @@ enum vmcs_field { ENCLS_EXITING_BITMAP_HIGH =3D 0x0000202F, TSC_MULTIPLIER =3D 0x00002032, TSC_MULTIPLIER_HIGH =3D 0x00002033, + TERTIARY_VM_EXEC_CONTROL =3D 0x00002034, + TERTIARY_VM_EXEC_CONTROL_HIGH =3D 0x00002035, GUEST_PHYSICAL_ADDRESS =3D 0x00002400, GUEST_PHYSICAL_ADDRESS_HIGH =3D 0x00002401, VMCS_LINK_POINTER =3D 0x00002800, diff --git a/tools/testing/selftests/kvm/x86/timer_latency.c b/tools/testin= g/selftests/kvm/x86/timer_latency.c index 7c2e8225f299..17f41a0d15da 100644 --- a/tools/testing/selftests/kvm/x86/timer_latency.c +++ b/tools/testing/selftests/kvm/x86/timer_latency.c @@ -15,6 +15,10 @@ #include "kvm_util.h" #include "processor.h" #include "apic.h" +#include "vmx.h" + +#define L2_GUEST_STACK_SIZE 256 +static unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; =20 #define LOCAL_TIMER_VECTOR 0xec =20 @@ -30,6 +34,7 @@ struct options { bool use_oneshot_timer; bool use_x2apic; bool use_poll; + bool nested; =20 uint64_t timer_inc_ns; uint64_t allowed_timer_latency_ns; @@ -307,6 +312,65 @@ static void guest_code(void) GUEST_DONE(); } =20 +static void l1_guest_code(struct vmx_pages *vmx_pages) +{ + union vmx_ctrl_msr ctls_msr, ctls2_msr; + uint64_t pin, ctls, ctls2, ctls3; + + GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); + GUEST_ASSERT(load_vmcs(vmx_pages)); + prepare_vmcs(vmx_pages, guest_code, + &l2_guest_stack[L2_GUEST_STACK_SIZE]); + + /* Check prerequisites */ + GUEST_ASSERT(!rdmsr_safe(MSR_IA32_VMX_PROCBASED_CTLS, &ctls_msr.val)); + GUEST_ASSERT(ctls_msr.clr & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS); + GUEST_ASSERT(ctls_msr.clr & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS); + + GUEST_ASSERT(!rdmsr_safe(MSR_IA32_VMX_PROCBASED_CTLS2, &ctls2_msr.val)); + GUEST_ASSERT(ctls2_msr.clr & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY); + + GUEST_ASSERT(!rdmsr_safe(MSR_IA32_VMX_PROCBASED_CTLS3, &ctls3)); + GUEST_ASSERT(ctls3 & TERTIARY_EXEC_GUEST_APIC_TIMER); + + /* + * SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY requires + * PIN_BASED_EXT_INTR_MASK + */ + pin =3D vmreadz(PIN_BASED_VM_EXEC_CONTROL); + pin |=3D PIN_BASED_EXT_INTR_MASK; + GUEST_ASSERT(!vmwrite(PIN_BASED_VM_EXEC_CONTROL, pin)); + + ctls =3D vmreadz(CPU_BASED_VM_EXEC_CONTROL); + ctls |=3D CPU_BASED_USE_MSR_BITMAPS | CPU_BASED_TPR_SHADOW | + CPU_BASED_ACTIVATE_SECONDARY_CONTROLS | + CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; + GUEST_ASSERT(!vmwrite(CPU_BASED_VM_EXEC_CONTROL, ctls)); + + /* guest apic timer requires virtual interrutp delivery */ + ctls2 =3D vmreadz(SECONDARY_VM_EXEC_CONTROL); + ctls2 |=3D SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | + SECONDARY_EXEC_APIC_REGISTER_VIRT | + SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY; + vmwrite(SECONDARY_VM_EXEC_CONTROL, ctls2); + + ctls3 =3D vmreadz(TERTIARY_VM_EXEC_CONTROL); + ctls3 |=3D TERTIARY_EXEC_GUEST_APIC_TIMER; + GUEST_ASSERT(!vmwrite(TERTIARY_VM_EXEC_CONTROL, ctls3)); + + /* + * We don't emulate apic registers(including APIC_LVTT) for simplicity. + * Directly set vector for timer interrupt instead. + */ + GUEST_ASSERT(!vmwrite(GUEST_APIC_TIMER_VECTOR, LOCAL_TIMER_VECTOR)); + + /* launch L2 */ + GUEST_ASSERT(!vmlaunch()); + GUEST_ASSERT_EQ(vmreadz(VM_EXIT_REASON), EXIT_REASON_VMCALL); + + GUEST_DONE(); +} + static void __run_vcpu(struct kvm_vcpu *vcpu) { struct ucall uc; @@ -411,12 +475,40 @@ static void setup_timer_freq(struct kvm_vm *vm, ns_to_tsc(data, options.allowed_timer_latency_ns); } =20 +static void clear_msr_bitmap(struct vmx_pages *vmx, int msr) +{ + clear_bit(msr, vmx->msr_hva); + clear_bit(msr, vmx->msr_hva + 2048); +} + static void setup(struct kvm_vm **vm__, struct kvm_vcpu **vcpu__) { struct kvm_vcpu *vcpu; struct kvm_vm *vm; =20 - vm =3D vm_create_with_one_vcpu(&vcpu, guest_code); + if (options.nested) { + vm_vaddr_t vmx_pages_gva =3D 0; + struct vmx_pages *vmx; + + vm =3D vm_create_with_one_vcpu(&vcpu, l1_guest_code); + + vmx =3D vcpu_alloc_vmx(vm, &vmx_pages_gva); + memset(vmx->msr_hva, 0xff, 4096); + + /* Allow nested apic timer virtualization. */ + clear_msr_bitmap(vmx, MSR_IA32_TSC_DEADLINE); + + /* Rely on x2apic virtualization. */ + clear_msr_bitmap(vmx, MSR_IA32_APICBASE); + clear_msr_bitmap(vmx, APIC_BASE_MSR + (APIC_TDCR >> 4)); + clear_msr_bitmap(vmx, APIC_BASE_MSR + (APIC_LVTT >> 4)); + clear_msr_bitmap(vmx, APIC_BASE_MSR + (APIC_SPIV >> 4)); + clear_msr_bitmap(vmx, APIC_BASE_MSR + (APIC_EOI >> 4)); + + vcpu_args_set(vcpu, 1, vmx_pages_gva); + } else + vm =3D vm_create_with_one_vcpu(&vcpu, guest_code); + vm_install_exception_handler(vm, LOCAL_TIMER_VECTOR, guest_timer_interrupt_handler); setup_timer_freq(vm, &shared_data); @@ -509,6 +601,8 @@ static void help(const char *name) printf("-P: print result stat\n"); printf("-x: use xAPIC mode\n"); printf("-X: use x2APIC mode (default)\n"); + printf("-n: Only measure nested VM (L2)\n"); + printf("-N: Don't measure nested VM (L2)\n"); puts(""); =20 exit(EXIT_SUCCESS); @@ -518,8 +612,10 @@ int main(int argc, char **argv) { int opt; unsigned int duration =3D TEST_DURATION_DEFAULT_IN_SEC; + bool nested_only =3D false; + bool no_nest =3D false; =20 - while ((opt =3D getopt(argc, argv, "hld:p:a:otxXP")) !=3D -1) { + while ((opt =3D getopt(argc, argv, "hld:p:a:otxXPnN")) !=3D -1) { switch (opt) { case 'l': options.use_poll =3D true; @@ -557,6 +653,15 @@ int main(int argc, char **argv) options.print_result =3D true; break; =20 + case 'n': + nested_only =3D true; + no_nest =3D false; + break; + case 'N': + nested_only =3D false; + no_nest =3D true; + break; + case 'h': default: help(argv[0]); @@ -572,7 +677,28 @@ int main(int argc, char **argv) if (options.use_x2apic) TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_X2APIC)); =20 - run_test(duration); + if (!nested_only) { + options.nested =3D false; + run_test(duration); + } + + if (!no_nest) { + union vmx_ctrl_msr ctls; + uint64_t ctls3; + + ctls.val =3D kvm_get_feature_msr(MSR_IA32_VMX_TRUE_PROCBASED_CTLS); + TEST_REQUIRE(ctls.clr & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS); + + ctls3 =3D kvm_get_feature_msr(MSR_IA32_VMX_PROCBASED_CTLS3); + TEST_REQUIRE(ctls3 & TERTIARY_EXEC_GUEST_APIC_TIMER); + + /* L1 doesn't emulate HLT and memory-mapped APIC. */ + options.use_poll =3D true; + options.use_oneshot_timer =3D false; + + options.nested =3D true; + run_test(duration); + } =20 return 0; } --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.12]) (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 D631742F54F; Thu, 5 Mar 2026 17:44:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732695; cv=none; b=O3b1adFkBX6qrQwOkXtFu1o6Q9e6tivFkUCjfwFSSXGQvvnjfttUfJPjRIbaw/yZDstvV6HS25Zc5gCUi5VofhJ18pvIfcPx7eR6JW8FkbUVBcAmA9Vt8tgVfugJKfufY7MYNe+mUTle8w77i2HKkfpVVR1Ugb9jDVtGg5A+eoE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732695; c=relaxed/simple; bh=Xp9vVVC9VmSIjmyuA7qa6qei/ZbOzg/Sj/hvegc3Ao8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CokNIpctnGpIifoPslcUefiJk5kH6N7ejk+v38wS/IpuNOfxFIsDb5aJTfO0SwjOzYWKxfVo7JdOmqVUaZvdY8DXF4waJV8lcKQGITcWX0+MSwRQFoUUqCC4hS7hlvdG7+R9s0GqQnjlN/XlnowNG8E2OuFJGIj+9Xj3au8F7cQ= 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=X6ynK1/E; arc=none smtp.client-ip=198.175.65.12 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="X6ynK1/E" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732692; x=1804268692; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Xp9vVVC9VmSIjmyuA7qa6qei/ZbOzg/Sj/hvegc3Ao8=; b=X6ynK1/ENyq7Ol2PDeohMzJEcOzna/gNtxZ3mmZuyLRwt1sAHHJHIuAV tiIlD5iWQBCffv4uhL/JrQlTEqPUmyePdaLkFq1/xfzmztCTXUUKleuA6 sIBg9w7TRsWrXMKJHBQKzHZGfy16w08h9yhntsaqsDdXmA5Ldljvy4+XJ rpzpsuk2BfzhwUBwcc+y9CQu2FgxYRQE2vPpDbSDVf8POWdxfF5Ul9oMb u87e4NBqsi742RSMS5RWzHXlDn5J9UwzS61aRN+c+hrttXB1PAxp0ctWd HyiNdrldDrsS/2VTk2XPiDzSrkYwfZgPNDC20QTKaOL7m+tSSm8HCDdnt g==; X-CSE-ConnectionGUID: tj1mA6V6Qkymp91SQimaUw== X-CSE-MsgGUID: vZToPptaRgCJEkJRUFaQbw== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="85301956" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="85301956" Received: from orviesa003.jf.intel.com ([10.64.159.143]) by orvoesa104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:50 -0800 X-CSE-ConnectionGUID: 5cvMxudgT1aSgr3LDBmKnw== X-CSE-MsgGUID: REg7F8XTT2yTbKlTU/pxpA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="222896527" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by ORVIESA003-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:48 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 27/36] KVM: selftests: Add test for nVMX MSR_IA32_VMX_PROCBASED_CTLS3 Date: Thu, 5 Mar 2026 09:44:07 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Add test case for nVMX MSR_IA32_VMX_PROCBASED_CTLS3 emulation. Test if the access to MSR_IA32_VMX_PROCBASED_CTLS3 to succeed or fail, depending on whether the vCPU supports it or not. Signed-off-by: Isaku Yamahata --- .../testing/selftests/kvm/x86/vmx_msrs_test.c | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/tools/testing/selftests/kvm/x86/vmx_msrs_test.c b/tools/testin= g/selftests/kvm/x86/vmx_msrs_test.c index 90720b6205f4..3ec5b73b4f2f 100644 --- a/tools/testing/selftests/kvm/x86/vmx_msrs_test.c +++ b/tools/testing/selftests/kvm/x86/vmx_msrs_test.c @@ -48,6 +48,11 @@ static void vmx_fixed0and1_msr_test(struct kvm_vcpu *vcp= u, uint32_t msr_index) =20 static void vmx_save_restore_msrs_test(struct kvm_vcpu *vcpu) { + union vmx_ctrl_msr ctls; + const struct kvm_msr_list *feature_list; + bool ctl3_found =3D false; + int i; + vcpu_set_msr(vcpu, MSR_IA32_VMX_VMCS_ENUM, 0); vcpu_set_msr(vcpu, MSR_IA32_VMX_VMCS_ENUM, -1ull); =20 @@ -65,6 +70,54 @@ static void vmx_save_restore_msrs_test(struct kvm_vcpu *= vcpu) vmx_fixed0and1_msr_test(vcpu, MSR_IA32_VMX_TRUE_EXIT_CTLS); vmx_fixed0and1_msr_test(vcpu, MSR_IA32_VMX_TRUE_ENTRY_CTLS); vmx_fixed1_msr_test(vcpu, MSR_IA32_VMX_VMFUNC, -1ull); + + ctls.val =3D kvm_get_feature_msr(MSR_IA32_VMX_PROCBASED_CTLS); + TEST_ASSERT(!(ctls.set & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS), + "CPU_BASED_ACTIVATE_TERTIARY_CONTROLS should be cleared."); + + feature_list =3D kvm_get_feature_msr_index_list(); + for (i =3D 0; i < feature_list->nmsrs; i++) { + if (feature_list->indices[i] =3D=3D MSR_IA32_VMX_PROCBASED_CTLS3) { + ctl3_found =3D true; + break; + } + } + + if (ctls.clr & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS) { + uint64_t kvm_ctls3, ctls3; + + TEST_ASSERT(ctl3_found, + "MSR_IA32_VMX_PROCBASED_CTLS3 was not in feature msr index list."); + + kvm_ctls3 =3D kvm_get_feature_msr(MSR_IA32_VMX_PROCBASED_CTLS3); + ctls3 =3D vcpu_get_msr(vcpu, MSR_IA32_VMX_PROCBASED_CTLS3); + TEST_ASSERT(kvm_ctls3 =3D=3D ctls3, + "msr values for kvm and vcpu must match."); + + vcpu_set_msr(vcpu, MSR_IA32_VMX_PROCBASED_CTLS3, 0); + vcpu_set_msr(vcpu, MSR_IA32_VMX_PROCBASED_CTLS3, ctls3); + vmx_fixed1_msr_test(vcpu, MSR_IA32_VMX_PROCBASED_CTLS3, ctls3); + + /* + * The kvm host should be able to get/set + * MSR_IA32_VMX_PROCBASED_CTLS3 irrespective to the bit + * CPU_BASED_ACTIVATE_TERTIARY_CONTROLS of + * MSR_IA32_VMX_TRUE_PROCBASED_CTLS. + */ + ctls.val =3D vcpu_get_msr(vcpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS); + vcpu_set_msr(vcpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS, + ctls.set & ~CPU_BASED_ACTIVATE_TERTIARY_CONTROLS); + vcpu_set_msr(vcpu, MSR_IA32_VMX_PROCBASED_CTLS3, 0); + vcpu_set_msr(vcpu, MSR_IA32_VMX_PROCBASED_CTLS3, ctls3); + vmx_fixed1_msr_test(vcpu, MSR_IA32_VMX_PROCBASED_CTLS3, ctls3); + vcpu_set_msr(vcpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS, ctls.val); + } else { + TEST_ASSERT(!ctl3_found, + "MSR_IA32_VMX_PROCBASED_CTLS3 was in feature msr index list."); + + TEST_ASSERT(!_vcpu_set_msr(vcpu, MSR_IA32_VMX_PROCBASED_CTLS3, 0), + "setting MSR_IA32_VMX_PROCBASED_CTLS3 didn't fail."); + } } =20 static void __ia32_feature_control_msr_test(struct kvm_vcpu *vcpu, --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.12]) (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 DDBAF42F561; Thu, 5 Mar 2026 17:44:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732697; cv=none; b=sAD4h8yrPPw7Gx0gfNdvyui2sBHyTdMhwhX1LRudrDRYxV/3g2eT40yJ860EuOEv258jTrVibkDKF88KZXhI6ujW5LD4tmRSQ8jp20hsqtWJqq91/c3+wnaiZe0mJkmwmAqxyi3jw8KuFT19weiM4Rd50Xlw5facwpWFWxqbSVo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732697; c=relaxed/simple; bh=zshUvpKmzz3SENkRLcVwh5m3fL3cvqsdLUmGu1zQKY8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=W5qNQPYE0Ih0Bvq5JjK/SPfNB8YkqbK0EDjKbs/k5shWd41myD2tVMxcw0dm6H7ZJ2HmrlYOABfEusyqXQM6kJ6E7En7psa9rIQOaaT81Adnsgoy9H8UgzZefCSZiUtupNCxzu+R9Vud6r9tlKoUThoAKJ0Bb5NFZfeLYdfzE5M= 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=gCOIktax; arc=none smtp.client-ip=198.175.65.12 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="gCOIktax" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732692; x=1804268692; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=zshUvpKmzz3SENkRLcVwh5m3fL3cvqsdLUmGu1zQKY8=; b=gCOIktaxHI+bgTVouP4PAnKtRLiSLt1UGrrb3SRORgEpv5tvRA5dVB7o zxkVLxKuWJ7BV5IMDS40iNwHWV9kQ8wx16ZyUFJUDa/vrWjw2Iuv/AtQQ TuVj2rWiiaXDes01rd++f7VO5DMv0+sLP3cyOQdQebyGQhwUFKKwWfV9O VZcQVgQeC0DH6bA0u+369R3+gppUoaMblXHQkzwQtM5eyr6afsCfadK1V DjAbsoQ8fr9D6oaqOeYNUSuDdTxZO5uv9RA4uJoo5umXXuZ5g7nOCr5hV UZb+tkutW3JD18a5+4Q5xyWQde8LBLEzixS2uaDUYblxr5CabKdhSzfQH w==; X-CSE-ConnectionGUID: +TkPqOzkSmOq/d3p9OeYJQ== X-CSE-MsgGUID: OaewdEx7Qqyg1hq2+SX2Hw== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="85301961" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="85301961" Received: from orviesa003.jf.intel.com ([10.64.159.143]) by orvoesa104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:50 -0800 X-CSE-ConnectionGUID: FIuvQipAQYeLjs6dVl/RaA== X-CSE-MsgGUID: ugB+JbBYSa26W+p8upaKHA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="222896533" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by ORVIESA003-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:49 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 28/36] KVM: selftests: Add test vmx_set_nested_state_test with EVMCS disabled Date: Thu, 5 Mar 2026 09:44:08 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Hyper-V EVMCS capability, KVM_CAP_HYPERV_ENLIGHTENED_VMCS, is optional. To increase test coverage, when Hyper-V EVMCS is supported, additionally run tests with EVMCS disabled. Signed-off-by: Isaku Yamahata --- .../selftests/kvm/x86/nested_set_state_test.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tools/testing/selftests/kvm/x86/nested_set_state_test.c b/tool= s/testing/selftests/kvm/x86/nested_set_state_test.c index 0f2102b43629..9651282df4d3 100644 --- a/tools/testing/selftests/kvm/x86/nested_set_state_test.c +++ b/tools/testing/selftests/kvm/x86/nested_set_state_test.c @@ -401,6 +401,19 @@ int main(int argc, char *argv[]) else test_svm_nested_state(vcpu); =20 + if (kvm_cpu_has(X86_FEATURE_VMX) && have_evmcs) { + /* + * KVM_CAP_HYPERV_ENLIGHTENED_VMCS can be only enabled. + * Because There is no way to disable it, re-create vm and vcpu. + */ + have_evmcs =3D false; + kvm_vm_free(vm); + vm =3D vm_create_with_one_vcpu(&vcpu, NULL); + vcpu_clear_cpuid_feature(vcpu, X86_FEATURE_VMX); + + test_vmx_nested_state(vcpu); + } + kvm_vm_free(vm); return 0; } --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.12]) (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 262DC42B726; Thu, 5 Mar 2026 17:44:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732692; cv=none; b=Je5bF5lPoweFZDrwkb/ArfLCqA73HAR183sdb6NqiFM/vtPAF7ZwcJganMDV5tZsecJYMBw8yoarwP1Z7U4ocutOolbVU4ChC8FHKm4RF9vfaX7/1YKI+9eiJfbyb/yqoHF6i4ZcdNRgh8oOIWi64+V+Uef4dLZa8bi0lU9puoA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732692; c=relaxed/simple; bh=spcndoUGI5XlK+jmdgdjo62MVw2tY3NFyl+mMfxYVqs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HWRv/b0+MvaC5R5EkL92hVRXre45sUv+N177Vs4tJXI2Uk1CzJaRK1b6a6THqhOlBLMeEyL4bqzbNX8LqR5j5b6htFP7AD7AuDZZXlVIqBw5Z2AZy6mfc2D4IvW0DSgOnvAk03MUBOncIlCSID8q+2raW7XpBBeBXp9Z0EkYYT4= 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=TjIkdH++; arc=none smtp.client-ip=192.198.163.12 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="TjIkdH++" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732691; x=1804268691; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=spcndoUGI5XlK+jmdgdjo62MVw2tY3NFyl+mMfxYVqs=; b=TjIkdH++le2LEn/wfHFJc0QYMuSaD977X5XCrg5SkAwom5lVTB2KGAW+ SgOQpgC5j6i78B/UNtePyStXiyXGnfcDX3hF1OWfoF92KlXrD/wdSqIhc WXZ+JkjuoDJC2LkBsPwjqwKod6LNdYpXxQ7b3H83JXbUaXraldgQoV4WG 1ECgcMPf1d/pcxWWL2Y/UHLd3d1ZmNpSNhie1m74atgJjNdx3OyPgNPx2 s2Zl1IhJVYtPxYMkoyNu2toFkcEFwfrUxrMNilxwCJQx+hGxNtS+FNlzi MpmbNlBrF1rSRekoSuZUpWrWqmwL6Inw2Wv3E7tlJEJ+cNKgeZ3NemEAt A==; X-CSE-ConnectionGUID: d+342vkIQEq1GU9mPQJT8A== X-CSE-MsgGUID: tPNJNpPDSk+REsEguHAN0w== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77701140" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77701140" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:51 -0800 X-CSE-ConnectionGUID: 2dDjGYQLT1mFQvFSfx/Ssg== X-CSE-MsgGUID: LdFyQG0lTO+j6WL3rwMnrA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="256647666" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:51 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 29/36] KVM: selftests: Add tests nested state of APIC timer virtualization Date: Thu, 5 Mar 2026 09:44:09 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Test vmread/vmwrite for the following VMCS fields related to apic timer virtualization in vmx_set_nested_state_test. - TERTIARY_EXEC_GUEST_APIC_TIMER bit in TERTIARY_VM_EXEC_CONTROL - VIRTUAL_TIMER_VECTOR_OFFSET - GUEST_DEADLINE_OFFSET - GUEST_DEADLINE_SHADOW_OFFSET Signed-off-by: Isaku Yamahata --- Changes: v1 -> v2: - format fixes. --- tools/testing/selftests/kvm/include/x86/vmx.h | 4 + .../selftests/kvm/x86/nested_set_state_test.c | 237 ++++++++++++++++++ 2 files changed, 241 insertions(+) diff --git a/tools/testing/selftests/kvm/include/x86/vmx.h b/tools/testing/= selftests/kvm/include/x86/vmx.h index 4be103c7b367..7a8fcf6f58ff 100644 --- a/tools/testing/selftests/kvm/include/x86/vmx.h +++ b/tools/testing/selftests/kvm/include/x86/vmx.h @@ -173,6 +173,8 @@ enum vmcs_field { TSC_MULTIPLIER_HIGH =3D 0x00002033, TERTIARY_VM_EXEC_CONTROL =3D 0x00002034, TERTIARY_VM_EXEC_CONTROL_HIGH =3D 0x00002035, + GUEST_DEADLINE_VIR =3D 0x0000204e, + GUEST_DEADLINE_VIR_HIGH =3D 0x0000204f, GUEST_PHYSICAL_ADDRESS =3D 0x00002400, GUEST_PHYSICAL_ADDRESS_HIGH =3D 0x00002401, VMCS_LINK_POINTER =3D 0x00002800, @@ -195,6 +197,8 @@ enum vmcs_field { GUEST_PDPTR3_HIGH =3D 0x00002811, GUEST_BNDCFGS =3D 0x00002812, GUEST_BNDCFGS_HIGH =3D 0x00002813, + GUEST_DEADLINE_PHY =3D 0x00002830, + GUEST_DEADLINE_PHY_HIGH =3D 0x00002831, HOST_IA32_PAT =3D 0x00002c00, HOST_IA32_PAT_HIGH =3D 0x00002c01, HOST_IA32_EFER =3D 0x00002c02, diff --git a/tools/testing/selftests/kvm/x86/nested_set_state_test.c b/tool= s/testing/selftests/kvm/x86/nested_set_state_test.c index 9651282df4d3..ed668a006c06 100644 --- a/tools/testing/selftests/kvm/x86/nested_set_state_test.c +++ b/tools/testing/selftests/kvm/x86/nested_set_state_test.c @@ -24,6 +24,8 @@ #define VMCS12_REVISION 0x11e57ed0 =20 bool have_evmcs; +bool have_procbased_tertiary_ctls; +bool have_apic_timer_virtualization; =20 void test_nested_state(struct kvm_vcpu *vcpu, struct kvm_nested_state *sta= te) { @@ -84,6 +86,233 @@ void set_default_vmx_state(struct kvm_nested_state *sta= te, int size) set_revision_id_for_vmcs12(state, VMCS12_REVISION); } =20 +/* Those values are taken from arch/x86/kvm/vmx/vmcs12.h */ +#define VMCS_LINK_POINTER_OFFSET 176 +#define TERTIARY_VM_EXEC_CONTROL_OFFSET 336 +#define GUEST_CR0_OFFSET 424 +#define GUEST_CR4_OFFSET 440 +#define HOST_CR0_OFFSET 584 +#define HOST_CR4_OFFSET 600 +#define PIN_BASED_VM_EXEC_CONTROL_OFFSET 744 +#define CPU_BASED_VM_EXEC_CONTROL_OFFSET 748 +#define VM_EXIT_CONTROLS_OFFSET 768 +#define VM_ENTRY_CONTROLS_OFFSET 780 +#define SECONDARY_VM_EXEC_CONTROL_OFFSET 804 +#define HOST_CS_SELECTOR_OFFSET 984 +#define HOST_SS_SELECTOR_OFFSET 986 +#define HOST_TR_SELECTOR_OFFSET 994 +#define VIRTUAL_TIMER_VECTOR_OFFSET 998 +#define GUEST_DEADLINE_OFFSET 1000 +#define GUEST_DEADLINE_SHADOW_OFFSET 1008 + +#define KERNEL_CS 0x8 +#define KERNEL_DS 0x10 +#define KERNEL_TSS 0x18 + +/* vcpu with vmxon=3Dfalse is needed to be able to set VMX MSRs. */ +static void nested_vmxoff(struct kvm_vcpu *vcpu, struct kvm_nested_state *= state, + int state_sz) +{ + set_default_vmx_state(state, state_sz); + state->flags =3D 0; + state->hdr.vmx.vmxon_pa =3D -1ull; + state->hdr.vmx.vmcs12_pa =3D -1ull; + test_nested_state(vcpu, state); +} + +static void get_control(struct kvm_vcpu *vcpu, uint32_t msr_index, + uint32_t *fixed0, uint32_t *fixed1) +{ + uint64_t ctls; + + ctls =3D vcpu_get_msr(vcpu, msr_index); + + *fixed0 =3D ctls & 0xffffffff; + *fixed1 =3D ctls >> 32; +} + +static uint32_t *init_control(struct kvm_vcpu *vcpu, + struct kvm_nested_state *state, + uint32_t msr_index, size_t offset) +{ + uint32_t fixed0, fixed1, *vmcs32; + + get_control(vcpu, msr_index, &fixed0, &fixed1); + vmcs32 =3D (uint32_t *)&state->data.vmx->vmcs12[offset]; + + *vmcs32 =3D fixed0; + *vmcs32 &=3D fixed1; + + return vmcs32; +} + +void set_guest_vmx_state(struct kvm_vcpu *vcpu, struct kvm_nested_state *s= tate, + int size) +{ + unsigned long cr0, cr4; + uint32_t *vmcs32; + uint64_t *vmcs64; + + set_default_vmx_state(state, size); + state->flags |=3D KVM_STATE_NESTED_GUEST_MODE; + + /* control */ + init_control(vcpu, state, MSR_IA32_VMX_TRUE_PINBASED_CTLS, + PIN_BASED_VM_EXEC_CONTROL_OFFSET); + + vmcs32 =3D init_control(vcpu, state, MSR_IA32_VMX_TRUE_PROCBASED_CTLS, + CPU_BASED_VM_EXEC_CONTROL_OFFSET); + *vmcs32 |=3D CPU_BASED_ACTIVATE_SECONDARY_CONTROLS; + *vmcs32 &=3D ~CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; + + init_control(vcpu, state, MSR_IA32_VMX_PROCBASED_CTLS2, + SECONDARY_VM_EXEC_CONTROL_OFFSET); + + vmcs32 =3D init_control(vcpu, state, MSR_IA32_VMX_TRUE_EXIT_CTLS, + VM_EXIT_CONTROLS_OFFSET); + *vmcs32 |=3D VM_EXIT_HOST_ADDR_SPACE_SIZE; + + init_control(vcpu, state, MSR_IA32_VMX_TRUE_ENTRY_CTLS, + VM_ENTRY_CONTROLS_OFFSET); + + vmcs64 =3D (uint64_t *)&state->data.vmx->vmcs12[VMCS_LINK_POINTER_OFFSET]; + *vmcs64 =3D -1ull; + + /* host state */ + cr0 =3D vcpu_get_msr(vcpu, MSR_IA32_VMX_CR0_FIXED0); + cr0 &=3D vcpu_get_msr(vcpu, MSR_IA32_VMX_CR0_FIXED1); + cr0 |=3D X86_CR0_PG; + *(unsigned long *)&state->data.vmx->vmcs12[HOST_CR0_OFFSET] =3D cr0; + + cr4 =3D vcpu_get_msr(vcpu, MSR_IA32_VMX_CR4_FIXED0); + cr4 &=3D vcpu_get_msr(vcpu, MSR_IA32_VMX_CR4_FIXED1); + cr4 |=3D X86_CR4_PAE | X86_CR4_VMXE; + *(unsigned long *)&state->data.vmx->vmcs12[HOST_CR4_OFFSET] =3D cr4; + + *(unsigned long *)&state->data.vmx->vmcs12[HOST_CS_SELECTOR_OFFSET] =3D K= ERNEL_CS; + *(unsigned long *)&state->data.vmx->vmcs12[HOST_TR_SELECTOR_OFFSET] =3D K= ERNEL_TSS; + *(unsigned long *)&state->data.vmx->vmcs12[HOST_SS_SELECTOR_OFFSET] =3D K= ERNEL_DS; + + /* guest state */ + cr0 =3D vcpu_get_msr(vcpu, MSR_IA32_VMX_CR0_FIXED0); + cr0 &=3D vcpu_get_msr(vcpu, MSR_IA32_VMX_CR0_FIXED1); + *(unsigned long *)&state->data.vmx->vmcs12[GUEST_CR0_OFFSET] =3D cr0; + + cr4 =3D vcpu_get_msr(vcpu, MSR_IA32_VMX_CR4_FIXED0); + cr4 &=3D vcpu_get_msr(vcpu, MSR_IA32_VMX_CR4_FIXED1); + *(unsigned long *)&state->data.vmx->vmcs12[GUEST_CR4_OFFSET] =3D cr4; + +} + +static void test_tertiary_ctls(struct kvm_vcpu *vcpu, + struct kvm_nested_state *state, + int state_sz) +{ + union vmx_ctrl_msr msr; + uint16_t *vmcs16; + uint32_t *vmcs32; + uint64_t *vmcs64; + uint64_t ctls; + + nested_vmxoff(vcpu, state, state_sz); + + msr.val =3D vcpu_get_msr(vcpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS); + msr.clr |=3D CPU_BASED_ACTIVATE_SECONDARY_CONTROLS; + msr.clr |=3D CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; + vcpu_set_msr(vcpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS, msr.val); + + ctls =3D vcpu_get_msr(vcpu, MSR_IA32_VMX_PROCBASED_CTLS3); + ctls |=3D TERTIARY_EXEC_GUEST_APIC_TIMER; + vcpu_set_msr(vcpu, MSR_IA32_VMX_PROCBASED_CTLS3, ctls); + + set_default_vmx_state(state, state_sz); + test_nested_state(vcpu, state); + + vmcs32 =3D (uint32_t *)&state->data.vmx->vmcs12[PIN_BASED_VM_EXEC_CONTROL= _OFFSET]; + *vmcs32 |=3D PIN_BASED_EXT_INTR_MASK; + + vmcs32 =3D (uint32_t *)&state->data.vmx->vmcs12[CPU_BASED_VM_EXEC_CONTROL= _OFFSET]; + *vmcs32 |=3D CPU_BASED_TPR_SHADOW | CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; + + vmcs32 =3D (uint32_t *)&state->data.vmx->vmcs12[SECONDARY_VM_EXEC_CONTROL= _OFFSET]; + *vmcs32 |=3D SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY; + + vmcs64 =3D (uint64_t *)&state->data.vmx->vmcs12[TERTIARY_VM_EXEC_CONTROL_= OFFSET]; + *vmcs64 |=3D TERTIARY_EXEC_GUEST_APIC_TIMER; + + vmcs16 =3D (uint16_t *)&state->data.vmx->vmcs12[VIRTUAL_TIMER_VECTOR_OFFS= ET]; + *vmcs16 =3D 128; + + vmcs64 =3D (uint64_t *)&state->data.vmx->vmcs12[GUEST_DEADLINE_OFFSET]; + /* random non-zero value */ + *vmcs64 =3D 0xffff; + + vmcs64 =3D (uint64_t *)&state->data.vmx->vmcs12[GUEST_DEADLINE_SHADOW_OFF= SET]; + *vmcs64 =3D 0xffff; + + test_nested_state(vcpu, state); +} + +static void test_tertiary_ctls_disabled(struct kvm_vcpu *vcpu, + struct kvm_nested_state *state, + int state_sz) +{ + union vmx_ctrl_msr msr; + uint16_t *vmcs16; + uint32_t *vmcs32; + uint64_t *vmcs64; + + nested_vmxoff(vcpu, state, state_sz); + + msr.val =3D kvm_get_feature_msr(MSR_IA32_VMX_TRUE_PROCBASED_CTLS); + if (msr.clr & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS) { + msr.val =3D vcpu_get_msr(vcpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS); + msr.clr &=3D ~CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; + vcpu_set_msr(vcpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS, msr.val); + vcpu_set_msr(vcpu, MSR_IA32_VMX_PROCBASED_CTLS3, 0); + } + + set_guest_vmx_state(vcpu, state, state_sz); + test_nested_state(vcpu, state); + + set_guest_vmx_state(vcpu, state, state_sz); + vmcs32 =3D (uint32_t *)&state->data.vmx->vmcs12[CPU_BASED_VM_EXEC_CONTROL= _OFFSET]; + *vmcs32 |=3D CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; + test_nested_state_expect_einval(vcpu, state); + + set_guest_vmx_state(vcpu, state, state_sz); + vmcs64 =3D (uint64_t *)&state->data.vmx->vmcs12[TERTIARY_VM_EXEC_CONTROL_= OFFSET]; + *vmcs64 |=3D TERTIARY_EXEC_GUEST_APIC_TIMER; + test_nested_state_expect_einval(vcpu, state); + + set_guest_vmx_state(vcpu, state, state_sz); + vmcs16 =3D (uint16_t *)&state->data.vmx->vmcs12[VIRTUAL_TIMER_VECTOR_OFFS= ET]; + *vmcs16 =3D 128; + test_nested_state_expect_einval(vcpu, state); + + set_guest_vmx_state(vcpu, state, state_sz); + vmcs64 =3D (uint64_t *)&state->data.vmx->vmcs12[GUEST_DEADLINE_OFFSET]; + *vmcs64 =3D 0xffff; + test_nested_state_expect_einval(vcpu, state); + + set_guest_vmx_state(vcpu, state, state_sz); + vmcs64 =3D (uint64_t *)&state->data.vmx->vmcs12[GUEST_DEADLINE_SHADOW_OFF= SET]; + *vmcs64 =3D 0xffff; + test_nested_state_expect_einval(vcpu, state); +} + +static void test_vmx_tertiary_ctls(struct kvm_vcpu *vcpu, + struct kvm_nested_state *state, + int state_sz) +{ + vcpu_set_cpuid_feature(vcpu, X86_FEATURE_VMX); + + if (have_procbased_tertiary_ctls) + test_tertiary_ctls(vcpu, state, state_sz); + + test_tertiary_ctls_disabled(vcpu, state, state_sz); +} + void test_vmx_nested_state(struct kvm_vcpu *vcpu) { /* Add a page for VMCS12. */ @@ -343,6 +572,8 @@ void test_svm_nested_state(struct kvm_vcpu *vcpu) TEST_ASSERT_EQ(state->hdr.svm.vmcb_pa, 0); TEST_ASSERT_EQ(state->flags, KVM_STATE_NESTED_GIF_SET); =20 + test_vmx_tertiary_ctls(vcpu, state, state_sz); + free(state); } =20 @@ -353,6 +584,12 @@ int main(int argc, char *argv[]) struct kvm_vcpu *vcpu; =20 have_evmcs =3D kvm_check_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS); + have_procbased_tertiary_ctls =3D + (kvm_get_feature_msr(MSR_IA32_VMX_TRUE_PROCBASED_CTLS) >> 32) & + CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; + have_apic_timer_virtualization =3D have_procbased_tertiary_ctls && + (kvm_get_feature_msr(MSR_IA32_VMX_PROCBASED_CTLS3) & + TERTIARY_EXEC_GUEST_APIC_TIMER); =20 TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX) || kvm_cpu_has(X86_FEATURE_SVM)); --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.12]) (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 AEC0047CC8B; Thu, 5 Mar 2026 17:45:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732704; cv=none; b=ae7DW4GqZGguOJ0K6BUfEuGF18Y9JbBntYwVwrnrmlur3gYv4eO3WVuL0NFkQVEQ0Bpq1VACjhI7Ka7yxofzlVROInBN4+U7iyP+dcIS+DYt+mZ1AbnGvsn6NYHWdGXz65WQBENZhoj4oEoPit/7ByJlynLXHak2gPkRlvhg16U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732704; c=relaxed/simple; bh=Uw3s4NmHni8ahTubZkhn9lWtC20CWHgztRwkKIZC7ZE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dXqAHM8c3yUG8kSAs3qmyKGfHWii+jBEBAbh1ZCBIjpxzLg8ulhcu/E7oFmewEc0hI5ervQVk3fwHEBSKI4uv7SlnlRjvDyg74A7mqUtRvCIuxztbKYPNz+ICqMpg7lorX9uI7KKUm4T+a2rHC2kAGJ3AEtC0NvMeqP2BNx1yuw= 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=NoJYSaZ+; arc=none smtp.client-ip=198.175.65.12 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="NoJYSaZ+" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732701; x=1804268701; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Uw3s4NmHni8ahTubZkhn9lWtC20CWHgztRwkKIZC7ZE=; b=NoJYSaZ+xO6DOE3I1VETYx8fIIBl/LCNLCWnHJTrztPe/VNQ4bkC4OPv yEmvhasTloAy2V0tbkM2AFtgvpNJLMaNLYQE2aDClozcJHTUKwpOGsg27 a/1NArzT/ot8pKoQf923LXjREBxnn8QkhpuZnYVw6b48I0V2VkEke8AmC sQQKRA0OPOupYc7rPZ1KaYbBIE2j9kuWrl4jQp1q/UZDXQYd9kIEvR+ic VYBqzUTqKNMoEche7sXB/yQ7UtKsXprrKHbyqTVD4z/N9tyqUjJ27hhg2 6Vjnn5xI7EIrfa4zIulkVPQ2rYYZs6UCzIBOuqFf3xk/8/p0ulUmJF1O2 A==; X-CSE-ConnectionGUID: MNxd6PQER0y3bo1qtjstRA== X-CSE-MsgGUID: J62R6ropRZWz1XnlB2KMkA== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="85301971" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="85301971" Received: from orviesa003.jf.intel.com ([10.64.159.143]) by orvoesa104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:51 -0800 X-CSE-ConnectionGUID: 2nn/WEPERHyLYL1VxhquRQ== X-CSE-MsgGUID: tCP05uaPSquRgmPumXEFVw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="222896543" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by ORVIESA003-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:51 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 30/36] KVM: selftests: Add VMCS access test to APIC timer virtualization Date: Thu, 5 Mar 2026 09:44:10 -0800 Message-ID: <93961bad80c96dd4e71d3a632db07928e4bd9606.1772732517.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Add test case for VMCS access of nVMX APIC timer virtualization. It tests nVMX emulation of a tertiary processor-based VM executing controls MSR, tertiary processor-base VM execution controls, and related VMCS fields by L1 vCPU and L2 vCPU. Signed-off-by: Isaku Yamahata --- tools/testing/selftests/kvm/Makefile.kvm | 1 + .../testing/selftests/kvm/include/x86/apic.h | 1 + .../kvm/x86/vmx_apic_timer_virt_vmcs_test.c | 464 ++++++++++++++++++ 3 files changed, 466 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/vmx_apic_timer_virt_vmc= s_test.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index 3c2a5470c2ca..f0023bab1cd7 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -146,6 +146,7 @@ TEST_GEN_PROGS_x86 +=3D x86/triple_fault_event_test TEST_GEN_PROGS_x86 +=3D x86/recalc_apic_map_test TEST_GEN_PROGS_x86 +=3D x86/aperfmperf_test TEST_GEN_PROGS_x86 +=3D x86/timer_latency +TEST_GEN_PROGS_x86 +=3D x86/vmx_apic_timer_virt_vmcs_test TEST_GEN_PROGS_x86 +=3D access_tracking_perf_test TEST_GEN_PROGS_x86 +=3D coalesced_io_test TEST_GEN_PROGS_x86 +=3D dirty_log_perf_test diff --git a/tools/testing/selftests/kvm/include/x86/apic.h b/tools/testing= /selftests/kvm/include/x86/apic.h index 5ca6bacbd70e..b47e905aa4e8 100644 --- a/tools/testing/selftests/kvm/include/x86/apic.h +++ b/tools/testing/selftests/kvm/include/x86/apic.h @@ -35,6 +35,7 @@ #define APIC_SPIV_FOCUS_DISABLED (1 << 9) #define APIC_SPIV_APIC_ENABLED (1 << 8) #define APIC_ISR 0x100 +#define APIC_ISR_NR 0x8 #define APIC_IRR 0x200 #define APIC_ICR 0x300 #define APIC_LVTCMCI 0x2f0 diff --git a/tools/testing/selftests/kvm/x86/vmx_apic_timer_virt_vmcs_test.= c b/tools/testing/selftests/kvm/x86/vmx_apic_timer_virt_vmcs_test.c new file mode 100644 index 000000000000..cd440b636585 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/vmx_apic_timer_virt_vmcs_test.c @@ -0,0 +1,464 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2025 Intel Corporation + * + * Tested vmread()/vmwrite() related to APIC timer virtualization in L1 + * emulated by KVM. + */ + +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" +#include "vmx.h" + +#include +#include +#include + +bool have_procbased_tertiary_ctls; +bool have_apic_timer_virtualization; + +#define L2_GUEST_STACK_SIZE 256 +static unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; + +/* Any value [32, 255] for timer vector is okay. */ +#define TIMER_VECTOR 0xec + +static bool update_l2_tsc_deadline; +static uint64_t l2_tsc_deadline; + +static void guest_timer_interrupt_handler(struct ex_regs *regs) +{ + x2apic_write_reg(APIC_EOI, 0); +} + +static void l2_guest_code(void) +{ + cli(); + x2apic_enable(); + wrmsr(MSR_IA32_TSC_DEADLINE, 0); + x2apic_write_reg(APIC_LVTT, APIC_LVT_TIMER_TSCDEADLINE | TIMER_VECTOR); + + vmcall(); + + while (true) { + /* reap pending timer interrupt. */ + sti_nop_cli(); + + if (update_l2_tsc_deadline) + GUEST_ASSERT(!wrmsr_safe(MSR_IA32_TSC_DEADLINE, l2_tsc_deadline)); + + vmcall(); + } + + GUEST_FAIL("should not reached."); +} + +static void setup_l2(struct vmx_pages *vmx_pages) +{ + uint64_t ctls, msr_val; + int r; + + GUEST_ASSERT(!rdmsr_safe(MSR_IA32_VMX_TRUE_PROCBASED_CTLS, + &msr_val)); + GUEST_ASSERT_EQ(have_procbased_tertiary_ctls, + !!((msr_val >> 32) & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS)); + + r =3D rdmsr_safe(MSR_IA32_VMX_PROCBASED_CTLS3, &msr_val); + GUEST_ASSERT(have_procbased_tertiary_ctls =3D=3D !r); + if (r) + msr_val =3D 0; + GUEST_ASSERT_EQ(have_apic_timer_virtualization, + !!(msr_val & TERTIARY_EXEC_GUEST_APIC_TIMER)); + + GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); + GUEST_ASSERT(load_vmcs(vmx_pages)); + prepare_vmcs(vmx_pages, l2_guest_code, + &l2_guest_stack[L2_GUEST_STACK_SIZE]); + + GUEST_ASSERT(!vmread(PIN_BASED_VM_EXEC_CONTROL, &ctls)); + ctls |=3D PIN_BASED_EXT_INTR_MASK; + GUEST_ASSERT(!vmwrite(PIN_BASED_VM_EXEC_CONTROL, ctls)); + + GUEST_ASSERT(!vmread(CPU_BASED_VM_EXEC_CONTROL, &ctls)); + ctls |=3D CPU_BASED_USE_MSR_BITMAPS | CPU_BASED_TPR_SHADOW | + CPU_BASED_ACTIVATE_SECONDARY_CONTROLS; + if (have_procbased_tertiary_ctls) + ctls |=3D CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; + GUEST_ASSERT(!vmwrite(CPU_BASED_VM_EXEC_CONTROL, ctls)); + + GUEST_ASSERT(!vmread(SECONDARY_VM_EXEC_CONTROL, &ctls)); + ctls |=3D SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | + SECONDARY_EXEC_APIC_REGISTER_VIRT | + SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY; + GUEST_ASSERT(!vmwrite(SECONDARY_VM_EXEC_CONTROL, ctls)); + + if (have_procbased_tertiary_ctls) { + GUEST_ASSERT(!vmread(TERTIARY_VM_EXEC_CONTROL, &ctls)); + + ctls &=3D ~TERTIARY_EXEC_GUEST_APIC_TIMER; + GUEST_ASSERT(!vmwrite(TERTIARY_VM_EXEC_CONTROL, ctls)); + } else { + GUEST_ASSERT(vmread(TERTIARY_VM_EXEC_CONTROL, &ctls)); + ctls =3D 0; + } + + ctls |=3D TERTIARY_EXEC_GUEST_APIC_TIMER; + GUEST_ASSERT_EQ(have_procbased_tertiary_ctls, + !vmwrite(TERTIARY_VM_EXEC_CONTROL, ctls)); + if (have_procbased_tertiary_ctls && !have_apic_timer_virtualization) { + ctls &=3D ~TERTIARY_EXEC_GUEST_APIC_TIMER; + GUEST_ASSERT(!vmwrite(TERTIARY_VM_EXEC_CONTROL, ctls)); + } + + GUEST_ASSERT_EQ(have_apic_timer_virtualization, + !vmwrite(GUEST_APIC_TIMER_VECTOR, TIMER_VECTOR)); +} + +static void skip_guest_instruction(void) +{ + uint64_t guest_rip, length; + + GUEST_ASSERT(!vmread(GUEST_RIP, &guest_rip)); + GUEST_ASSERT(!vmread(VM_EXIT_INSTRUCTION_LEN, &length)); + + GUEST_ASSERT(!vmwrite(GUEST_RIP, guest_rip + length)); + GUEST_ASSERT(!vmwrite(VM_EXIT_INSTRUCTION_LEN, 0)); +} + +static void l2_load_vmlaunch(struct vmx_pages *vmx_pages) +{ + GUEST_ASSERT(load_vmcs(vmx_pages)); + skip_guest_instruction(); + GUEST_ASSERT(!vmlaunch()); + GUEST_ASSERT_EQ(vmreadz(VM_EXIT_REASON), EXIT_REASON_VMCALL); +} + +struct vmcs_guest_deadline { + uint64_t vir; + uint64_t phy; +}; + +struct deadline_test { + struct vmcs_guest_deadline set; + struct vmcs_guest_deadline result; +}; + +static void test_vmclear_vmptrld(struct vmx_pages *vmx_pages) +{ + struct deadline_test tests[] =3D { + { + .set =3D { + .vir =3D ~0ull, + .phy =3D ~0ull, + }, + .result =3D { + .vir =3D ~0ull, + .phy =3D ~0ull, + } + }, + { + .set =3D { + .vir =3D ~0ull, + .phy =3D 0, + }, + .result =3D { + .vir =3D ~0ull, + .phy =3D 0, + } + }, + { + .set =3D { + .vir =3D ~0ull, + .phy =3D 1, + }, + .result =3D { + .vir =3D 0, + .phy =3D 0, + } + }, + { + .set =3D { + .vir =3D 0, + .phy =3D ~0ull, + }, + .result =3D { + .vir =3D 0, + .phy =3D ~0ull, + } + }, + { + .set =3D { + .vir =3D 1, + .phy =3D ~0ull, + }, + .result =3D { + .vir =3D 1, + .phy =3D ~0ull, + } + }, + { + .set =3D { + .vir =3D 1, + .phy =3D 1, + }, + .result =3D { + .vir =3D 0, + .phy =3D 0, + } + }, + { + .set =3D { + .vir =3D 1, + .phy =3D 0, + }, + .result =3D { + .vir =3D 1, + .phy =3D 0, + } + }, + { + .set =3D { + .vir =3D 0, + .phy =3D 1, + }, + .result =3D { + .vir =3D 0, + .phy =3D 0, + } + }, + }; + int i; + + if (!have_apic_timer_virtualization) + return; + + update_l2_tsc_deadline =3D false; + + /* + * Test if KVM properly store/load TIMER_VECTOR, guest deadline of + * vmcs area to/from memory. + * Enforce KVM to store nested vmcs to memory and load it again. + * load_vmcs() issues vmclear(), and then vmptrld() + */ + l2_load_vmlaunch(vmx_pages); + GUEST_ASSERT_EQ(vmreadz(GUEST_APIC_TIMER_VECTOR), TIMER_VECTOR); + + for (i =3D 0; i < ARRAY_SIZE(tests); i++) { + struct deadline_test *test =3D &tests[i]; + uint64_t vir, phy, val; + + GUEST_ASSERT(!vmwrite(GUEST_DEADLINE_VIR, test->set.vir)); + GUEST_ASSERT(!vmread(GUEST_DEADLINE_VIR, &val)); + GUEST_ASSERT_EQ(test->set.vir, val); + + GUEST_ASSERT(!vmwrite(GUEST_DEADLINE_PHY, test->set.phy)); + GUEST_ASSERT(!vmread(GUEST_DEADLINE_PHY, &val)); + GUEST_ASSERT_EQ(test->set.phy, val); + + l2_load_vmlaunch(vmx_pages); + + GUEST_ASSERT(!vmread(GUEST_DEADLINE_VIR, &vir)); + GUEST_ASSERT(!vmread(GUEST_DEADLINE_PHY, &phy)); + + GUEST_ASSERT_EQ(vir, test->result.vir); + GUEST_ASSERT_EQ(!!phy, !!test->result.phy); + } +} + +static void test_ctls(void) +{ + uint64_t ctls; + + update_l2_tsc_deadline =3D false; + + GUEST_ASSERT_EQ(!vmwrite(GUEST_APIC_TIMER_VECTOR, TIMER_VECTOR), + have_apic_timer_virtualization); + GUEST_ASSERT_EQ(!vmwrite(GUEST_DEADLINE_VIR, 0), + have_apic_timer_virtualization); + GUEST_ASSERT_EQ(!vmwrite(GUEST_DEADLINE_PHY, 0), + have_apic_timer_virtualization); + + if (!have_procbased_tertiary_ctls) { + GUEST_ASSERT(!vmread(CPU_BASED_VM_EXEC_CONTROL, &ctls)); + ctls |=3D CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; + GUEST_ASSERT(!vmwrite(CPU_BASED_VM_EXEC_CONTROL, ctls)); + + skip_guest_instruction(); + GUEST_ASSERT(vmresume()); + + ctls &=3D ~CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; + GUEST_ASSERT(!vmwrite(CPU_BASED_VM_EXEC_CONTROL, ctls)); + } + + if (have_procbased_tertiary_ctls && !have_apic_timer_virtualization) { + GUEST_ASSERT(!vmread(TERTIARY_VM_EXEC_CONTROL, &ctls)); + ctls |=3D TERTIARY_EXEC_GUEST_APIC_TIMER; + GUEST_ASSERT(!vmwrite(TERTIARY_VM_EXEC_CONTROL, ctls)); + + skip_guest_instruction(); + GUEST_ASSERT(vmresume()); + + ctls &=3D ~TERTIARY_EXEC_GUEST_APIC_TIMER; + GUEST_ASSERT(!vmwrite(TERTIARY_VM_EXEC_CONTROL, ctls)); + } +} + +static void test_l2_set_deadline(void) +{ + uint64_t deadlines[] =3D { + 0, + 1, + 2, + + rdtsc() / 2, + rdtsc(), + rdtsc() * 2, + + ~0ull / 2 - 1, + ~0ull / 2, + ~0ull / 2 + 1, + + ~0ull - 1, + ~0ull - 2, + ~0ull, + }; + int i; + + update_l2_tsc_deadline =3D true; + + for (i =3D 0; i < ARRAY_SIZE(deadlines); i++) { + uint64_t phy, vir; + + l2_tsc_deadline =3D deadlines[i]; + + skip_guest_instruction(); + GUEST_ASSERT(!vmresume()); + GUEST_ASSERT_EQ(vmreadz(VM_EXIT_REASON), EXIT_REASON_VMCALL); + + GUEST_ASSERT(!vmread(GUEST_DEADLINE_VIR, &vir)); + GUEST_ASSERT(!vmread(GUEST_DEADLINE_PHY, &phy)); + + GUEST_ASSERT(!vir || vir =3D=3D l2_tsc_deadline); + } +} + +static void l1_guest_code(struct vmx_pages *vmx_pages) +{ + setup_l2(vmx_pages); + + GUEST_ASSERT_EQ(have_apic_timer_virtualization, + !vmwrite(GUEST_DEADLINE_VIR, ~0ull)); + GUEST_ASSERT_EQ(have_apic_timer_virtualization, + !vmwrite(GUEST_DEADLINE_PHY, ~0ull)); + + test_vmclear_vmptrld(vmx_pages); + + update_l2_tsc_deadline =3D false; + l2_load_vmlaunch(vmx_pages); + test_ctls(); + + if (have_apic_timer_virtualization) { + update_l2_tsc_deadline =3D false; + l2_load_vmlaunch(vmx_pages); + + test_l2_set_deadline(); + } + + GUEST_DONE(); +} + +static void run_vcpu(struct kvm_vcpu *vcpu) +{ + bool done =3D false; + + while (!done) { + struct ucall uc; + + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + + switch (get_ucall(vcpu, &uc)) { + case UCALL_ABORT: + REPORT_GUEST_ASSERT(uc); + /* NOT REACHED */ + case UCALL_PRINTF: + pr_info("%s", uc.buffer); + break; + case UCALL_DONE: + done =3D true; + break; + default: + TEST_ASSERT(false, "Unknown ucall %lu", uc.cmd); + } + } +} + +static void test_apic_virtualization_vmcs(void) +{ + vm_vaddr_t vmx_pages_gva; + + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + uint64_t ctls, ctls3; + + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX)); + + vm =3D vm_create_with_one_vcpu(&vcpu, l1_guest_code); + vcpu_alloc_vmx(vm, &vmx_pages_gva); + vcpu_args_set(vcpu, 1, vmx_pages_gva); + + vcpu_set_cpuid_feature(vcpu, X86_FEATURE_TSC_DEADLINE_TIMER); + + ctls =3D vcpu_get_msr(vcpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS); + if (have_procbased_tertiary_ctls) { + ctls |=3D (uint64_t)CPU_BASED_ACTIVATE_TERTIARY_CONTROLS << 32; + vcpu_set_msr(vcpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS, ctls); + + ctls3 =3D vcpu_get_msr(vcpu, MSR_IA32_VMX_PROCBASED_CTLS3); + if (have_apic_timer_virtualization) + ctls3 |=3D TERTIARY_EXEC_GUEST_APIC_TIMER; + else + ctls3 &=3D ~TERTIARY_EXEC_GUEST_APIC_TIMER; + vcpu_set_msr(vcpu, MSR_IA32_VMX_PROCBASED_CTLS3, ctls3); + } else { + ctls &=3D ~((uint64_t)CPU_BASED_ACTIVATE_TERTIARY_CONTROLS << 32); + vcpu_set_msr(vcpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS, ctls); + } + + /* For L2. */ + vm_install_exception_handler(vm, TIMER_VECTOR, + guest_timer_interrupt_handler); + + sync_global_to_guest(vm, have_procbased_tertiary_ctls); + sync_global_to_guest(vm, have_apic_timer_virtualization); + run_vcpu(vcpu); + + kvm_vm_free(vm); +} + +int main(int argc, char *argv[]) +{ + have_procbased_tertiary_ctls =3D + (kvm_get_feature_msr(MSR_IA32_VMX_TRUE_PROCBASED_CTLS) >> 32) & + CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; + have_apic_timer_virtualization =3D have_procbased_tertiary_ctls && + (kvm_get_feature_msr(MSR_IA32_VMX_PROCBASED_CTLS3) & + TERTIARY_EXEC_GUEST_APIC_TIMER); + + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX)); + + test_apic_virtualization_vmcs(); + + if (have_apic_timer_virtualization) { + have_apic_timer_virtualization =3D false; + test_apic_virtualization_vmcs(); + } + + if (have_procbased_tertiary_ctls) { + have_procbased_tertiary_ctls =3D false; + test_apic_virtualization_vmcs(); + } + + return 0; +} --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.12]) (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 3C1C847DF97; Thu, 5 Mar 2026 17:45:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732706; cv=none; b=kt4wOkwVUz2YNeol9++RRxQaUhQ8IkEbU9m8nhSPllwl1+k+vZd4cOmXrdqbfUJrZ9W0yzAU9lSmwl/CyP/LXx634YFFTosETOVNnVYUOG9W6hWEu+SGfaY8PUzX5il4FU0qvBRsf7Y4xHf/E+EJdxItBd8ywVr9+FFTVwSlthY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732706; c=relaxed/simple; bh=8YJ2FKnXboCtX8fNqYAUAygCHVrbqcpCQXjFPwTg67o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jIgD8YC7g90I5VDaaW3Gn2XR/MH5NLDFyOzTf02dLwnVEwlRrYq3ea7TL8CajDin6x/CNSQj2F0dlRbKw5G0tA6AWmeCG9Zj1ZH6TM7Uh402FeC7mF7nt5y89CQ3Zem0d11HD5BriyawSNBgmuyJi0B89x6tSz2FbFqeumc2bVc= 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=kfXnihBd; arc=none smtp.client-ip=198.175.65.12 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="kfXnihBd" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732705; x=1804268705; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=8YJ2FKnXboCtX8fNqYAUAygCHVrbqcpCQXjFPwTg67o=; b=kfXnihBdfugpRXLpHtEOTTJMInUZp2LWIayc+zp5x8eqfu4fmq4S53Ee K1aPxzcH+XaCaUO5ZA6ZALQJoGgMkt/D+XQQhNWVRosrGrp72Vfo9UxxG QJiRfZDNh1ARbFOPCfjbw8wbDpAWK/1z6u71K8A26tyASrSM75tnyO8R8 BFo387nIdS+DvFkG+VmMUg9dlcyWfnT/y9bJiPbrtScLRN58wl/oACtm4 fWCM2Br/0uqQ1el09HTttyS8HCnyOs8LiGQPYjonXkxFAavhXJtnuqQot flUWVS2RYjRrrW4ZNmJXpsVT50aj7StzHhAG6uOQaYiN7qQJf2WCCbDAb A==; X-CSE-ConnectionGUID: bahDTtt5QZas/G6LgXRInA== X-CSE-MsgGUID: tfV6aF+uR3eUFGGQR4dRAw== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="85301980" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="85301980" Received: from orviesa003.jf.intel.com ([10.64.159.143]) by orvoesa104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:52 -0800 X-CSE-ConnectionGUID: FMyYb2zeTcShiRckjReY1w== X-CSE-MsgGUID: 5GET/YLnTUa9Qm5HOvNlVQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="222896548" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by ORVIESA003-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:52 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 31/36] KVM: selftests: Add serialize() helper and X86_FEATURE_SERIALIZE Date: Thu, 5 Mar 2026 09:44:11 -0800 Message-ID: <69230e737e4150f4e9e0cafca755d1149c620c0d.1772732517.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata As the following test cases use serialize instruction, add feature definition and a helper function for it. Signed-off-by: Isaku Yamahata -- Changes v2: - newly added --- tools/testing/selftests/kvm/include/x86/processor.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/te= sting/selftests/kvm/include/x86/processor.h index da94ebf16821..88e5acc1c03e 100644 --- a/tools/testing/selftests/kvm/include/x86/processor.h +++ b/tools/testing/selftests/kvm/include/x86/processor.h @@ -172,6 +172,7 @@ struct kvm_x86_cpu_feature { #define X86_FEATURE_RDPID KVM_X86_CPU_FEATURE(0x7, 0, ECX, 22) #define X86_FEATURE_SGX_LC KVM_X86_CPU_FEATURE(0x7, 0, ECX, 30) #define X86_FEATURE_SHSTK KVM_X86_CPU_FEATURE(0x7, 0, ECX, 7) +#define X86_FEATURE_SERIALIZE KVM_X86_CPU_FEATURE(0x7, 0, EDX, 14) #define X86_FEATURE_IBT KVM_X86_CPU_FEATURE(0x7, 0, EDX, 20) #define X86_FEATURE_AMX_TILE KVM_X86_CPU_FEATURE(0x7, 0, EDX, 24) #define X86_FEATURE_SPEC_CTRL KVM_X86_CPU_FEATURE(0x7, 0, EDX, 26) @@ -1433,6 +1434,12 @@ static inline void cli(void) asm volatile ("cli"); } =20 +static inline void serialize(void) +{ + /* serialize instruction. binutils >=3D 2.35 */ + kvm_asm_safe(".byte 0x0f, 0x01, 0xe8"); +} + void __vm_xsave_require_permission(uint64_t xfeature, const char *name); =20 #define vm_xsave_require_permission(xfeature) \ --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.12]) (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 6DDA34301CC; Thu, 5 Mar 2026 17:44:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732700; cv=none; b=LlXK/O9hNdFrlfeQ9l7+qFQ/3TXJJL4uKhtAkv/NwXnkf+WzvSBpuA8+CSi9mGQaxL0T68Pcun5LmkHep9RVZR+dUnUX251xY4drkEJkNJmpWx6FXimQTqa+nCZVqZCW86mn+0OiD6mawhBQuagU1rjvhIn7VKXB6ad3jSx79/Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732700; c=relaxed/simple; bh=dWLBpucUmsronW0lUyENxbo4bN8m5VbkFlRPqfDok1Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Kj3/sH1aFKECTe6bn9K6NuutvbYceq420For0SbUZrE59yyo8pUvXK3Fs7NTt05g8dqWGY/1I7P7tVtcY01Uk4NANX2zp1+qqwGPQVpPxe6nB+zUBefU622V6jgMQ1E5KxTNyAdfbzKTG+KYo1s0qOWNzS7ZAMnG0pN3bQUkVqY= 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=QDEWJw4t; arc=none smtp.client-ip=192.198.163.12 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="QDEWJw4t" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732694; x=1804268694; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=dWLBpucUmsronW0lUyENxbo4bN8m5VbkFlRPqfDok1Q=; b=QDEWJw4tJYz16SsqmoPgeO4XyjJfp5KS0nwiDJgkZT9Ex2fIv3acnofq c76HOORBZtuViKsGfAe2pKdUfZDWnhbVP3I7EeAUPZ/VzITbiUew/a70R jSwdstJrCStFMyOWcVzV+oIUtQ55HGn2cacsyLYLfMD1zlBIA1/DCSS8D SlKDO6nGURTaVBg8JZULQeVnl8PXN78cn991c3wXhcQtZheO5gC+L77F+ 8r8S92S60rnO0c2ProdOXeyrB1go6Ny/lvMDyUZyI9bERNB5U8DsSj6jT Z8hpDQiXbL59AObFlqEt6Z843vpufQscuRVUDyP0H2F/KgijowLikOTWu A==; X-CSE-ConnectionGUID: Jl0zst6JRM+usUGRuETk3Q== X-CSE-MsgGUID: XFtMCUfVQ/2dVoK1i31dQA== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77701145" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77701145" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:53 -0800 X-CSE-ConnectionGUID: Vo2oajuFQC2bQ7gvV8OQow== X-CSE-MsgGUID: hBXIS251RdKoGzCdim8g/g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="256647686" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:53 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 32/36] KVM: selftests: Test cases for L1 APIC timer virtualization Date: Thu, 5 Mar 2026 09:44:12 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Test nVMX APIC timer virtualization for L1 to see how KVM in L0 works. It exercises KVM TSC deadline conversion between L0 and L1. Signed-off-by: Isaku Yamahata --- Changes: v1 -> v2: - Add check serialize instruction support. - Eliminate unused variable warnings. - Add serialize() after disabling deadline timer. --- tools/testing/selftests/kvm/Makefile.kvm | 1 + .../kvm/x86/vmx_apic_timer_virt_test.c | 317 ++++++++++++++++++ 2 files changed, 318 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/vmx_apic_timer_virt_tes= t.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index f0023bab1cd7..424ae9a56481 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -146,6 +146,7 @@ TEST_GEN_PROGS_x86 +=3D x86/triple_fault_event_test TEST_GEN_PROGS_x86 +=3D x86/recalc_apic_map_test TEST_GEN_PROGS_x86 +=3D x86/aperfmperf_test TEST_GEN_PROGS_x86 +=3D x86/timer_latency +TEST_GEN_PROGS_x86 +=3D x86/vmx_apic_timer_virt_test TEST_GEN_PROGS_x86 +=3D x86/vmx_apic_timer_virt_vmcs_test TEST_GEN_PROGS_x86 +=3D access_tracking_perf_test TEST_GEN_PROGS_x86 +=3D coalesced_io_test diff --git a/tools/testing/selftests/kvm/x86/vmx_apic_timer_virt_test.c b/t= ools/testing/selftests/kvm/x86/vmx_apic_timer_virt_test.c new file mode 100644 index 000000000000..3eb544363570 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/vmx_apic_timer_virt_test.c @@ -0,0 +1,317 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2025 Intel Corporation + * + * Test timer expiration conversion and exercise various LVTT mode. + */ + +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" +#include "vmx.h" + +#include +#include +#include + +#include + +static uint64_t host_tsc_khz; +static uint64_t max_guest_tsc_khz; + +/* Any value [32, 255] for timer vector is okay. */ +#define TIMER_VECTOR 0xec + +static atomic_int timer_interrupted; + +static void guest_timer_interrupt_handler(struct ex_regs *regs) +{ + atomic_fetch_add(&timer_interrupted, 1); + x2apic_write_reg(APIC_EOI, 0); +} + +static void reap_interrupt(void) +{ + GUEST_ASSERT(!wrmsr_safe(MSR_IA32_TSC_DEADLINE, 0)); + serialize(); + sti_nop_cli(); +} + +static void deadline_write_test(bool do_interrupt, bool mask, + uint64_t deadlines[], size_t nr_deadlines) +{ + int i; + + for (i =3D 0; i < nr_deadlines; i++) { + uint64_t deadline =3D deadlines[i]; + uint64_t val; + + reap_interrupt(); + + atomic_store(&timer_interrupted, 0); + sti(); + GUEST_ASSERT(!wrmsr_safe(MSR_IA32_TSC_DEADLINE, deadline)); + /* serialize to wait for timer interrupt to fire. */ + serialize(); + cli(); + + GUEST_ASSERT(!rdmsr_safe(MSR_IA32_TSC_DEADLINE, &val)); + + if (do_interrupt) { + GUEST_ASSERT(val =3D=3D 0); + if (mask || deadline =3D=3D 0) + GUEST_ASSERT_EQ(atomic_load(&timer_interrupted), 0); + else + GUEST_ASSERT_EQ(atomic_load(&timer_interrupted), 1); + } else { + GUEST_ASSERT_EQ(val, deadline); + GUEST_ASSERT_EQ(atomic_load(&timer_interrupted), 0); + } + } +} + +static void deadline_write_hlt_test(uint64_t deadlines[], size_t nr_deadli= nes) +{ + int i; + + for (i =3D 0; i < nr_deadlines; i++) { + uint64_t deadline =3D deadlines[i]; + uint64_t val; + + reap_interrupt(); + + GUEST_ASSERT(deadline); + + atomic_store(&timer_interrupted, 0); + GUEST_ASSERT(!wrmsr_safe(MSR_IA32_TSC_DEADLINE, deadline)); + + GUEST_ASSERT(!rdmsr_safe(MSR_IA32_TSC_DEADLINE, &val)); + GUEST_ASSERT(val =3D=3D deadline || val =3D=3D 0); + GUEST_ASSERT_EQ(atomic_load(&timer_interrupted), 0); + + asm volatile ("sti; hlt; nop; cli" + /* L1 exit handler doesn't preserve GP registers. */ + : : : "cc", "memory", + "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", + "r15"); + + GUEST_ASSERT(!rdmsr_safe(MSR_IA32_TSC_DEADLINE, &val)); + GUEST_ASSERT_EQ(val, 0); + GUEST_ASSERT_EQ(atomic_load(&timer_interrupted), 1); + } +} + +static void deadline_no_int_test(void) +{ + uint64_t tsc =3D rdtsc(); + uint64_t deadlines[] =3D { + 0ull, + /* big values > tsc. */ + max(~0ull - tsc, ~0ull / 2 + tsc / 2), + ~0ull - 1, + ~0ull - 2, + ~0ull, + }; + + deadline_write_test(false, false, deadlines, ARRAY_SIZE(deadlines)); +} + +static void __deadline_int_test(bool do_interrupt, bool mask) +{ + uint64_t tsc =3D rdtsc(); + uint64_t deadlines[] =3D { + 0ull, + 1ull, + 2ull, + /* 1 msec past. tsc /2 is to avoid underflow. */ + min(tsc - guest_tsc_khz, tsc / 2 + 1), + tsc, + }; + + deadline_write_test(do_interrupt, mask, deadlines, ARRAY_SIZE(deadlines)); +} + +static void deadline_int_test(void) +{ + __deadline_int_test(true, false); +} + +static void deadline_int_mask_test(void) +{ + __deadline_int_test(true, true); +} + +static void deadline_hlt_test(void) +{ + uint64_t tsc =3D rdtsc(); + /* 1 msec future. */ + uint64_t future =3D tsc + guest_tsc_khz; + uint64_t deadlines[] =3D { + 1ull, + 2ull, + /* pick a positive value between [0, tsc]. */ + tsc > guest_tsc_khz ? tsc - guest_tsc_khz : tsc / 2 + 1, + tsc, + /* If overflow, pick near future value > tsc. */ + future > tsc ? future : ~0ull / 2 + tsc / 2, + }; + + deadline_write_hlt_test(deadlines, ARRAY_SIZE(deadlines)); +} + +static void guest_code(void) +{ + x2apic_enable(); + + x2apic_write_reg(APIC_LVTT, APIC_LVT_TIMER_TSCDEADLINE | TIMER_VECTOR); + deadline_no_int_test(); + deadline_int_test(); + deadline_hlt_test(); + + x2apic_write_reg(APIC_LVTT, APIC_LVT_TIMER_TSCDEADLINE | + APIC_LVT_MASKED | TIMER_VECTOR); + deadline_no_int_test(); + deadline_int_mask_test(); + + GUEST_DONE(); +} + +static void run_vcpu(struct kvm_vcpu *vcpu) +{ + bool done =3D false; + + while (!done) { + struct ucall uc; + + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + + switch (get_ucall(vcpu, &uc)) { + case UCALL_ABORT: + REPORT_GUEST_ASSERT(uc); + /* NOT REACHED */ + case UCALL_SYNC: + break; + case UCALL_PRINTF: + pr_info("%s", uc.buffer); + break; + case UCALL_DONE: + done =3D true; + break; + default: + TEST_FAIL("Unknown ucall %lu", uc.cmd); + } + } +} + +static int test_tsc_deadline(bool tsc_offset, uint64_t guest_tsc_khz__) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + vm =3D vm_create_with_one_vcpu(&vcpu, guest_code); + + if (guest_tsc_khz__) { + int ret; + + ret =3D __vcpu_ioctl(vcpu, KVM_SET_TSC_KHZ, (void *)guest_tsc_khz__); + if (ret) { + kvm_vm_free(vm); + return ret; + } + + guest_tsc_khz =3D guest_tsc_khz__; + } + + if (tsc_offset) { + uint64_t offset; + + __TEST_REQUIRE(!__vcpu_has_device_attr(vcpu, KVM_VCPU_TSC_CTRL, + KVM_VCPU_TSC_OFFSET), + "KVM_VCPU_TSC_OFFSET not supported; skipping test"); + + /* + * Make the conversion guest deadline virt(L1) =3D> phy (l0) + * can overflow/underflow. + */ + offset =3D -rdtsc(); + vcpu_device_attr_set(vcpu, KVM_VCPU_TSC_CTRL, + KVM_VCPU_TSC_OFFSET, &offset); + } + + vcpu_set_cpuid_feature(vcpu, X86_FEATURE_TSC_DEADLINE_TIMER); + vm_install_exception_handler(vm, TIMER_VECTOR, + guest_timer_interrupt_handler); + + sync_global_to_guest(vm, host_tsc_khz); + sync_global_to_guest(vm, guest_tsc_khz); + run_vcpu(vcpu); + + kvm_vm_free(vm); + + return 0; +} + +static void test(void) +{ + uint64_t guest_tsc_khz__; + int r; + + test_tsc_deadline(false, 0); + test_tsc_deadline(true, 0); + + for (guest_tsc_khz__ =3D host_tsc_khz; guest_tsc_khz__ > 0; + guest_tsc_khz__ >>=3D 1) { + r =3D test_tsc_deadline(false, guest_tsc_khz__); + if (r) + break; + + test_tsc_deadline(true, guest_tsc_khz__); + } + + for (guest_tsc_khz__ =3D host_tsc_khz; guest_tsc_khz__ < max_guest_tsc_kh= z; + guest_tsc_khz__ <<=3D 1) { + r =3D test_tsc_deadline(false, guest_tsc_khz__); + if (r) + break; + + test_tsc_deadline(true, guest_tsc_khz__); + } + + test_tsc_deadline(false, max_guest_tsc_khz); + test_tsc_deadline(true, max_guest_tsc_khz); +} + +int main(int argc, char *argv[]) +{ + uint32_t eax_denominator, ebx_numerator, ecx_hz, edx; + + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_X2APIC)); + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SERIALIZE)); + TEST_REQUIRE(kvm_has_cap(KVM_CAP_TSC_CONTROL)); + + cpuid(0x15, &eax_denominator, &ebx_numerator, &ecx_hz, &edx); + TEST_REQUIRE(ebx_numerator > 0); + TEST_REQUIRE(eax_denominator > 0); + + if (ecx_hz > 0) + host_tsc_khz =3D ecx_hz * ebx_numerator / eax_denominator / 1000; + else { + uint32_t eax_base_mhz, ebx, ecx; + + cpuid(0x16, &eax_base_mhz, &ebx, &ecx, &edx); + host_tsc_khz =3D eax_base_mhz * 1000 * ebx_numerator / + eax_denominator; + } + TEST_REQUIRE(host_tsc_khz > 0); + + /* See arch/x86/kvm/{x86.c, vmx/vmx.c}. There is no way for userspace to = retrieve it. */ +#define KVM_VMX_TSC_MULTIPLIER_MAX 0xffffffffffffffffULL + max_guest_tsc_khz =3D min((uint64_t)0x7fffffffULL, + mul_u64_u32_shr(KVM_VMX_TSC_MULTIPLIER_MAX, host_tsc_khz, 48)); + + test(); + + return 0; +} --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.12]) (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 A1B57438FF9; Thu, 5 Mar 2026 17:44:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732700; cv=none; b=RQ4qjiB+afd1qogMzyxOgkqxH9a7vIzq0qhbF59OLiYZlX6lSCkJqSKY7V509QlkvkSkoFRJQ5wvx/dIIv/jKV9Tp9EyOpX/FvmrYxfQJWknwW1ySU1kOZWwww1LNaTBm1QupRD88A5SPotwRDIWpSLzJu9U8W90rX62aCekmkA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732700; c=relaxed/simple; bh=nL3oFzrlfSMxpuut0on0gxF6pM5Gl8ZNnOb/qRUnp3k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=N5fZZkOAmJcLDQjnK/0NxiCu3iZpQRmc187O/bHKtpamu5PQHG1JqDXy/uMHgSfXeocupy1MeUfIk/rumrH5SO+3OL1aazM3CdCIzF8N2sr5RabSpgSZTns536pUY3oMqUHxXsZ10lg4kyfWr4h1+p06KhyaUbJxd3hK1difpCw= 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=lbPo3t3g; arc=none smtp.client-ip=192.198.163.12 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="lbPo3t3g" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732695; x=1804268695; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=nL3oFzrlfSMxpuut0on0gxF6pM5Gl8ZNnOb/qRUnp3k=; b=lbPo3t3gy+qD5n629DqOq44ZgwW+ion1UMCtAwbb4lRaSGJThLyp1CCz EnjliLd2WTahOosyZp+TLBAh7fSqcyh02OYmMIs2BjzWMgil3nbatL0BF zaCbmx1xMxx4bkeebOfYhBwybfED/tKhS2kKSNnS4e+0HeVrdPV6bCIfG Eu7omfMxvF940YlAChLx/LstAJ35QCe/PRLEhJv5ydG50X7epXQpft3Ws LlM5F1iOBpO8xJnP7uv6Yk/0617Se17WlmSt7soj8/CJj89EhQlZcJIh/ GrJzjGPimzYNJ83GmZeaadYv028H1VY8RH9dHcBvopZdNAs5B3LlG4RDb Q==; X-CSE-ConnectionGUID: aGdUp7jFTyWO6EbREsk4FA== X-CSE-MsgGUID: P0yFHGkNQ5+QaB5qrZ5I7g== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77701150" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77701150" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:54 -0800 X-CSE-ConnectionGUID: 7IhUO+paQtCCaJp7smhynA== X-CSE-MsgGUID: pW5ItRRoT3GU2AXhRuJK6w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="256647693" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:54 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 33/36] KVM: selftests: Add tests for nVMX to vmx_apic_timer_virt Date: Thu, 5 Mar 2026 09:44:13 -0800 Message-ID: <3ad6662c156f05747f3ff8e6d0d29b80be62e112.1772732517.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Support nVMX for vmx_apic_timer_virt. Signed-off-by: Isaku Yamahata --- Changes: v1 -> v2: - Fix compile error. --- .../kvm/x86/vmx_apic_timer_virt_test.c | 209 +++++++++++++++++- 1 file changed, 201 insertions(+), 8 deletions(-) diff --git a/tools/testing/selftests/kvm/x86/vmx_apic_timer_virt_test.c b/t= ools/testing/selftests/kvm/x86/vmx_apic_timer_virt_test.c index 3eb544363570..2779d0cac7ee 100644 --- a/tools/testing/selftests/kvm/x86/vmx_apic_timer_virt_test.c +++ b/tools/testing/selftests/kvm/x86/vmx_apic_timer_virt_test.c @@ -16,6 +16,15 @@ =20 #include =20 +static bool nested; + +#define L2_GUEST_STACK_SIZE 256 +static unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; + +static uint64_t l2_tsc_offset; +static uint64_t l2_tsc_multiplier; +static uint64_t l2_tsc_khz; + static uint64_t host_tsc_khz; static uint64_t max_guest_tsc_khz; =20 @@ -144,14 +153,15 @@ static void deadline_int_mask_test(void) =20 static void deadline_hlt_test(void) { + uint64_t tsc_khz =3D nested ? l2_tsc_khz : guest_tsc_khz; uint64_t tsc =3D rdtsc(); /* 1 msec future. */ - uint64_t future =3D tsc + guest_tsc_khz; + uint64_t future =3D tsc + tsc_khz + 1; uint64_t deadlines[] =3D { 1ull, 2ull, /* pick a positive value between [0, tsc]. */ - tsc > guest_tsc_khz ? tsc - guest_tsc_khz : tsc / 2 + 1, + tsc > tsc_khz ? tsc - tsc_khz : tsc / 2 + 1, tsc, /* If overflow, pick near future value > tsc. */ future > tsc ? future : ~0ull / 2 + tsc / 2, @@ -169,10 +179,134 @@ static void guest_code(void) deadline_int_test(); deadline_hlt_test(); =20 - x2apic_write_reg(APIC_LVTT, APIC_LVT_TIMER_TSCDEADLINE | - APIC_LVT_MASKED | TIMER_VECTOR); - deadline_no_int_test(); - deadline_int_mask_test(); + /* L1 doesn't emulate LVTT entry so that mask is not supported. */ + if (!nested) { + x2apic_write_reg(APIC_LVTT, APIC_LVT_TIMER_TSCDEADLINE | + APIC_LVT_MASKED | TIMER_VECTOR); + deadline_no_int_test(); + deadline_int_mask_test(); + } + + if (nested) + vmcall(); + else + GUEST_DONE(); +} + +static void skip_guest_instruction(void) +{ + uint64_t guest_rip, length; + + GUEST_ASSERT(!vmread(GUEST_RIP, &guest_rip)); + GUEST_ASSERT(!vmread(VM_EXIT_INSTRUCTION_LEN, &length)); + + GUEST_ASSERT(!vmwrite(GUEST_RIP, guest_rip + length)); + GUEST_ASSERT(!vmwrite(VM_EXIT_INSTRUCTION_LEN, 0)); +} + +static void l1_guest_code(struct vmx_pages *vmx_pages) +{ + union vmx_ctrl_msr ctls_msr, ctls2_msr; + uint64_t pin, ctls, ctls2, ctls3; + bool launch, done; + + GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); + GUEST_ASSERT(load_vmcs(vmx_pages)); + prepare_vmcs(vmx_pages, guest_code, + &l2_guest_stack[L2_GUEST_STACK_SIZE]); + + /* Check prerequisites */ + GUEST_ASSERT(!rdmsr_safe(MSR_IA32_VMX_PROCBASED_CTLS, &ctls_msr.val)); + GUEST_ASSERT(ctls_msr.clr & CPU_BASED_HLT_EXITING); + GUEST_ASSERT(ctls_msr.clr & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS); + GUEST_ASSERT(ctls_msr.clr & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS); + + GUEST_ASSERT(!rdmsr_safe(MSR_IA32_VMX_PROCBASED_CTLS2, &ctls2_msr.val)); + GUEST_ASSERT(ctls2_msr.clr & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY); + + GUEST_ASSERT(!rdmsr_safe(MSR_IA32_VMX_PROCBASED_CTLS3, &ctls3)); + GUEST_ASSERT(ctls3 & TERTIARY_EXEC_GUEST_APIC_TIMER); + + pin =3D vmreadz(PIN_BASED_VM_EXEC_CONTROL); + pin |=3D PIN_BASED_EXT_INTR_MASK; + GUEST_ASSERT(!vmwrite(PIN_BASED_VM_EXEC_CONTROL, pin)); + + ctls =3D vmreadz(CPU_BASED_VM_EXEC_CONTROL); + ctls |=3D CPU_BASED_HLT_EXITING | CPU_BASED_USE_TSC_OFFSETTING | + CPU_BASED_USE_MSR_BITMAPS | CPU_BASED_TPR_SHADOW | + CPU_BASED_ACTIVATE_SECONDARY_CONTROLS | + CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; + GUEST_ASSERT(!vmwrite(CPU_BASED_VM_EXEC_CONTROL, ctls)); + + /* guest apic timer requires virtual interrutp delivery */ + ctls2 =3D vmreadz(SECONDARY_VM_EXEC_CONTROL); + ctls2 |=3D SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | + SECONDARY_EXEC_APIC_REGISTER_VIRT | + SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY; + vmwrite(SECONDARY_VM_EXEC_CONTROL, ctls2); + + ctls3 =3D vmreadz(TERTIARY_VM_EXEC_CONTROL); + ctls3 |=3D TERTIARY_EXEC_GUEST_APIC_TIMER; + GUEST_ASSERT(!vmwrite(TERTIARY_VM_EXEC_CONTROL, ctls3)); + + /* + * We don't emulate apic registers(including APIC_LVTT) for simplicity. + * Directly set vector for timer interrupt instead. + */ + GUEST_ASSERT(!vmwrite(GUEST_APIC_TIMER_VECTOR, TIMER_VECTOR)); + + GUEST_ASSERT(!vmwrite(TSC_OFFSET, l2_tsc_offset)); + if (l2_tsc_multiplier) { + GUEST_ASSERT(!vmwrite(TSC_MULTIPLIER, l2_tsc_multiplier)); + + GUEST_ASSERT(!vmread(SECONDARY_VM_EXEC_CONTROL, &ctls2)); + ctls2 |=3D SECONDARY_EXEC_TSC_SCALING; + GUEST_ASSERT(!vmwrite(SECONDARY_VM_EXEC_CONTROL, ctls2)); + } else { + GUEST_ASSERT(!vmread(SECONDARY_VM_EXEC_CONTROL, &ctls2)); + ctls2 &=3D ~SECONDARY_EXEC_TSC_SCALING; + GUEST_ASSERT(!vmwrite(SECONDARY_VM_EXEC_CONTROL, ctls2)); + } + + /* launch L2 */ + launch =3D true; + done =3D false; + + while (!done) { + uint64_t reason; + + if (launch) { + GUEST_ASSERT(!vmlaunch()); + launch =3D false; + } else + GUEST_ASSERT(!vmresume()); + + GUEST_ASSERT(!vmread(VM_EXIT_REASON, &reason)); + + switch (reason) { + case EXIT_REASON_HLT: { + uint64_t phy, tsc; + + skip_guest_instruction(); + GUEST_ASSERT(!vmread(GUEST_DEADLINE_PHY, &phy)); + + /* Don't wait for more than 1 sec. */ + tsc =3D rdtsc(); + if (tsc < phy && tsc < ~0ULL - guest_tsc_khz) + GUEST_ASSERT(tsc + guest_tsc_khz * 1000 >=3D tsc); + + while (tsc <=3D phy) + tsc =3D rdtsc(); + break; + } + case EXIT_REASON_VMCALL: + done =3D true; + break; + default: + GUEST_FAIL("unexpected exit reason 0x%lx", reason); + break; + } + } =20 GUEST_DONE(); } @@ -210,9 +344,17 @@ static int test_tsc_deadline(bool tsc_offset, uint64_t= guest_tsc_khz__) struct kvm_vcpu *vcpu; struct kvm_vm *vm; =20 - vm =3D vm_create_with_one_vcpu(&vcpu, guest_code); + if (nested) { + vm_vaddr_t vmx_pages_gva =3D 0; + + vm =3D vm_create_with_one_vcpu(&vcpu, l1_guest_code); + vcpu_alloc_vmx(vm, &vmx_pages_gva); + vcpu_args_set(vcpu, 1, vmx_pages_gva); + } else + vm =3D vm_create_with_one_vcpu(&vcpu, guest_code); =20 if (guest_tsc_khz__) { + uint64_t l1_tsc_multiplier; int ret; =20 ret =3D __vcpu_ioctl(vcpu, KVM_SET_TSC_KHZ, (void *)guest_tsc_khz__); @@ -222,7 +364,34 @@ static int test_tsc_deadline(bool tsc_offset, uint64_t= guest_tsc_khz__) } =20 guest_tsc_khz =3D guest_tsc_khz__; - } + + /* + * Pick same to L1 tsc multplier. Any value to exercise + * corner cases is okay. + */ + l1_tsc_multiplier =3D ((__uint128_t)guest_tsc_khz__ * + (1ULL << 48)) / host_tsc_khz; + l2_tsc_multiplier =3D l1_tsc_multiplier; + /* + * l1_multiplier * l2_multiplier needs to be represented in + * the host. + */ + if ((__uint128_t)l1_tsc_multiplier * l2_tsc_multiplier > + ((__uint128_t)1ULL << (63 + 48))) { + + l2_tsc_multiplier =3D ((__uint128_t)1ULL << (63 + 48)) / + l1_tsc_multiplier; + if (!l2_tsc_multiplier) + l1_tsc_multiplier =3D 1; + } + + l2_tsc_khz =3D ((__uint128_t)l2_tsc_multiplier * guest_tsc_khz__) >> 48; + if (!l2_tsc_khz) { + l2_tsc_multiplier =3D 1ULL << 48; + l2_tsc_khz =3D guest_tsc_khz__; + } + } else + l2_tsc_khz =3D host_tsc_khz; =20 if (tsc_offset) { uint64_t offset; @@ -238,6 +407,9 @@ static int test_tsc_deadline(bool tsc_offset, uint64_t = guest_tsc_khz__) offset =3D -rdtsc(); vcpu_device_attr_set(vcpu, KVM_VCPU_TSC_CTRL, KVM_VCPU_TSC_OFFSET, &offset); + + /* Pick a non-zero value */ + l2_tsc_offset =3D offset; } =20 vcpu_set_cpuid_feature(vcpu, X86_FEATURE_TSC_DEADLINE_TIMER); @@ -246,10 +418,18 @@ static int test_tsc_deadline(bool tsc_offset, uint64_= t guest_tsc_khz__) =20 sync_global_to_guest(vm, host_tsc_khz); sync_global_to_guest(vm, guest_tsc_khz); + sync_global_to_guest(vm, nested); + sync_global_to_guest(vm, l2_tsc_offset); + sync_global_to_guest(vm, l2_tsc_multiplier); + sync_global_to_guest(vm, l2_tsc_khz); run_vcpu(vcpu); =20 kvm_vm_free(vm); =20 + l2_tsc_offset =3D 0; + l2_tsc_multiplier =3D 0; + l2_tsc_khz =3D 0; + return 0; } =20 @@ -286,6 +466,8 @@ static void test(void) int main(int argc, char *argv[]) { uint32_t eax_denominator, ebx_numerator, ecx_hz, edx; + union vmx_ctrl_msr ctls; + uint64_t ctls3; =20 TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_X2APIC)); TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SERIALIZE)); @@ -313,5 +495,16 @@ int main(int argc, char *argv[]) =20 test(); =20 + ctls.val =3D kvm_get_feature_msr(MSR_IA32_VMX_TRUE_PROCBASED_CTLS); + if (ctls.clr & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS) + ctls3 =3D kvm_get_feature_msr(MSR_IA32_VMX_PROCBASED_CTLS3); + else + ctls3 =3D 0; + if (kvm_cpu_has(X86_FEATURE_VMX) && + ctls3 & TERTIARY_EXEC_GUEST_APIC_TIMER) { + nested =3D true; + test(); + } + return 0; } --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.12]) (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 AEE3B3EB819; Thu, 5 Mar 2026 17:44:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732697; cv=none; b=caXB428RzyXhlkVZEFJ7qfxpZ2XxoqmDhLO0QINQOAf31Wh+5QHiakJ+nbs16GO5/ExwITt1k/YwIJ/8E41MWwsloMAA/vlpWV9DC0xyY79Unh2ZBmBTuYuYGSTR8hq/T8EKarrtFrj/fN+LJe1DcIveLuo4i4RXbHwnW6NUIQk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732697; c=relaxed/simple; bh=FMWxjFCblL92ZgWxMifGSelJ5wPyhBSh9S4BSW9hSkM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=i2jgjJugYhwCFOS5Aftt80Ag8Y2VfdvYGQhZE5ELscXq9yC2Z9lfadaoJG8wlqfH+sIamrC6r93Bg2BBChSAeg3fXSoD9BB0CXgHfkCuyo87V3Dr3KJa3jiHUh4YYSxW6WzkKejkXONUd7OVHVym0PUuDVdqOQDDte9s/Khidtk= 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=hi03cx9p; arc=none smtp.client-ip=192.198.163.12 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="hi03cx9p" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732696; x=1804268696; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=FMWxjFCblL92ZgWxMifGSelJ5wPyhBSh9S4BSW9hSkM=; b=hi03cx9pLdL7PzSdVBVlHaep5AF8+Y01f71axRyEEr1Voc4VlI6yHD6g HQZ/4IjIF5Xw2KtwqJG2cQZeWgSsQA5Ifrp1cgiq+iqcXCINn3kIobSPO 8TYGV1fUYoF2NxPDlsj5xaUHZHuXcSX1RoTR1v4ObkFPwZOUK1hqiznPi 99hsfhr6j5S3e+CWEMeH3jWq/Mv/4lr7R4JyPYDvQ3r92FVw6N4uUU8dm rPl3/4xSu+houYuiXBC4kf4qewoQ69O1kmqoyMy0JZhfCTu+fUZ5+DgXk YYcrqIsCEsgqDaBdYyAjp32IUjeefviLThvOQrKp/hbcmoBe2lAhH7L0d g==; X-CSE-ConnectionGUID: G7g3lI/OSAuURcrmgyQnpA== X-CSE-MsgGUID: +iJcCx4UTOiGPx+13zvTSA== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77701154" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77701154" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:55 -0800 X-CSE-ConnectionGUID: J/ZL7bbLRx+Ba+U+Lj423Q== X-CSE-MsgGUID: PabPas1QS2yTIHBXJJMglg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="256647699" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:55 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 34/36] KVM: selftests: Add a global option to disable in-kernel irqchip Date: Thu, 5 Mar 2026 09:44:14 -0800 Message-ID: <65c95008d3f3994fb220df26e661ef7d570b9a07.1772732517.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata For test cases with in-kernel irqchip/apic disabled. Signed-off-by: Isaku Yamahata -- Changes v1 -> v2: - Newly added. --- tools/testing/selftests/kvm/include/x86/kvm_util_arch.h | 1 + tools/testing/selftests/kvm/lib/x86/processor.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/include/x86/kvm_util_arch.h b/tool= s/testing/selftests/kvm/include/x86/kvm_util_arch.h index be35d26bb320..fe502956b2ad 100644 --- a/tools/testing/selftests/kvm/include/x86/kvm_util_arch.h +++ b/tools/testing/selftests/kvm/include/x86/kvm_util_arch.h @@ -9,6 +9,7 @@ #include "test_util.h" =20 extern bool is_forced_emulation_enabled; +extern bool disable_inkernel_irqchip; =20 struct pte_masks { uint64_t present; diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testin= g/selftests/kvm/lib/x86/processor.c index f4e8649071b6..2342ea227638 100644 --- a/tools/testing/selftests/kvm/lib/x86/processor.c +++ b/tools/testing/selftests/kvm/lib/x86/processor.c @@ -27,6 +27,7 @@ bool host_cpu_is_hygon; bool host_cpu_is_amd_compatible; bool is_forced_emulation_enabled; uint64_t guest_tsc_khz; +bool disable_inkernel_irqchip; =20 const char *ex_str(int vector) { @@ -789,7 +790,8 @@ void kvm_arch_vm_post_create(struct kvm_vm *vm, unsigne= d int nr_vcpus) TEST_ASSERT(kvm_has_cap(KVM_CAP_GET_TSC_KHZ), "Require KVM_GET_TSC_KHZ to provide udelay() to guest."); =20 - vm_create_irqchip(vm); + if (!disable_inkernel_irqchip) + vm_create_irqchip(vm); vm_init_descriptor_tables(vm); =20 sync_global_to_guest(vm, host_cpu_is_intel); @@ -798,6 +800,7 @@ void kvm_arch_vm_post_create(struct kvm_vm *vm, unsigne= d int nr_vcpus) sync_global_to_guest(vm, host_cpu_is_amd_compatible); sync_global_to_guest(vm, is_forced_emulation_enabled); sync_global_to_guest(vm, pmu_errata_mask); + sync_global_to_guest(vm, disable_inkernel_irqchip); =20 if (is_sev_vm(vm)) { struct kvm_sev_init init =3D { 0 }; --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.12]) (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 848F447DFA8; Thu, 5 Mar 2026 17:45:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732707; cv=none; b=BB5njfHgQk5CxpPAw8mOz4TxuMk1Z02wITM4W84gVNkSEWKCiegpsFUtkjTOlZeKFXGIL88NbOtPslB+Hnvohzlt3wHxXATab3/TcOsvtzm5VWtYUv9LnYAlN/JDfgnApiUPAGjLmN45yfkk75YxG2iy+WXwUflxcXWYmYKPM0U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732707; c=relaxed/simple; bh=kQ0CuBb7Q7+35jEaO5dVDxI7MgYm7NKrH5dxieMJ5jk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BfzMMvvzLk9TByytTRzxmlQfkz7PFWrLOYZ1WKb8hCUgtVJwib9flyy87SBJeRinVzpvKYU+uWlIvUs2ws1AmVdu2O5BoupUzV3Ux9FPcpxem69LWDo310jBUQ2FqNfutHyZW6fHXcC+Z/yesOC0PnBRsDlX3I+fpHAqTZ8R5BA= 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=CN7l5v3e; arc=none smtp.client-ip=198.175.65.12 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="CN7l5v3e" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732705; x=1804268705; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=kQ0CuBb7Q7+35jEaO5dVDxI7MgYm7NKrH5dxieMJ5jk=; b=CN7l5v3ethOPoYwBb9MCNgbAk4r5aX5BE6MfjXH0zYZWIDxoTmZiQAPN MoxnZjHcbER48NgmE0aDlLrMj5OWMSSWvItRimjmVYmJEFx4i48t3TEan q3Y+8RfRouBfGaoApBsOBeV4yxEusPPjNTrndKiIBhRdtEAQhc6CNHmt9 ONna7ZWRMT5XOqb4zubJFyrxYnhqjcR3N5UvXb9J6rzHk7Egz/i/0TGgX 2Nqbuy5mKLHwVu36p3kexu4nm+ow/Qi1SPoUd3LmZ47X+n6V2PNrhj8dl Y3Mh/LLqiX4Yzv3jZx3NDe6FoyS+RRta3bTfq8Uy6VHJwKOqF01NAYFe6 A==; X-CSE-ConnectionGUID: aV0DfMm6SayrTMpN9HL6tQ== X-CSE-MsgGUID: otYmvnnzSo6PLWPFmgXsdQ== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="85301990" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="85301990" Received: from orviesa003.jf.intel.com ([10.64.159.143]) by orvoesa104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:56 -0800 X-CSE-ConnectionGUID: xxhPB5U8S6OGiz1F5I2KUA== X-CSE-MsgGUID: WCLlac57QqiMSE0Q+unE+w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="222896557" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by ORVIESA003-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:55 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org, syzbot+ci66a37fb2e2f8de71@syzkaller.appspotmail.com Subject: [PATCH v2 35/36] KVM: selftests: Test VMX apic timer virt with inkernel apic disable Date: Thu, 5 Mar 2026 09:44:15 -0800 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Add a test case to excercize APIC timer virtuliazation support with inkernel APIC disabled as Syzbot reported GP fault if inkernel APIC is disabled. Reported-by: syzbot+ci66a37fb2e2f8de71@syzkaller.appspotmail.com Signed-off-by: Isaku Yamahata -- Changes v1 -> v2: - Newly added. --- tools/testing/selftests/kvm/Makefile.kvm | 1 + .../kvm/x86/vmx_tertiary_ctls_test.c | 168 ++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/vmx_tertiary_ctls_test.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index 424ae9a56481..928b665f8086 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -148,6 +148,7 @@ TEST_GEN_PROGS_x86 +=3D x86/aperfmperf_test TEST_GEN_PROGS_x86 +=3D x86/timer_latency TEST_GEN_PROGS_x86 +=3D x86/vmx_apic_timer_virt_test TEST_GEN_PROGS_x86 +=3D x86/vmx_apic_timer_virt_vmcs_test +TEST_GEN_PROGS_x86 +=3D x86/vmx_tertiary_ctls_test TEST_GEN_PROGS_x86 +=3D access_tracking_perf_test TEST_GEN_PROGS_x86 +=3D coalesced_io_test TEST_GEN_PROGS_x86 +=3D dirty_log_perf_test diff --git a/tools/testing/selftests/kvm/x86/vmx_tertiary_ctls_test.c b/too= ls/testing/selftests/kvm/x86/vmx_tertiary_ctls_test.c new file mode 100644 index 000000000000..9ef120e00d6d --- /dev/null +++ b/tools/testing/selftests/kvm/x86/vmx_tertiary_ctls_test.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * VMX tertiary controls test + * + * Copyright (C) 2026 Intel Corporation + */ +#include "kvm_util.h" +#include "vmx.h" + +static bool has_guest_apic_timer_virt =3D true; +#define TIMER_VECTOR 0xec + +#define L2_GUEST_STACK_SIZE 64 +static unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; + +static void l2_guest_code(void) +{ + vmcall(); + + /* L1 stops L2 vcpu at above vmcall(). */ + GUEST_FAIL("L2 should not reach here."); +} + +static void setup_l2(struct vmx_pages *vmx_pages) +{ + uint64_t ctls; + + GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); + GUEST_ASSERT(load_vmcs(vmx_pages)); + prepare_vmcs(vmx_pages, l2_guest_code, + &l2_guest_stack[L2_GUEST_STACK_SIZE]); + + GUEST_ASSERT(!vmread(PIN_BASED_VM_EXEC_CONTROL, &ctls)); + ctls |=3D PIN_BASED_EXT_INTR_MASK; + GUEST_ASSERT(!vmwrite(PIN_BASED_VM_EXEC_CONTROL, ctls)); + + GUEST_ASSERT(!vmread(CPU_BASED_VM_EXEC_CONTROL, &ctls)); + ctls |=3D CPU_BASED_USE_MSR_BITMAPS | CPU_BASED_TPR_SHADOW | + CPU_BASED_ACTIVATE_SECONDARY_CONTROLS; + ctls |=3D CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; + GUEST_ASSERT(!vmwrite(CPU_BASED_VM_EXEC_CONTROL, ctls)); + + GUEST_ASSERT(!vmread(SECONDARY_VM_EXEC_CONTROL, &ctls)); + ctls |=3D SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | + SECONDARY_EXEC_APIC_REGISTER_VIRT | + SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY; + GUEST_ASSERT(!vmwrite(SECONDARY_VM_EXEC_CONTROL, ctls)); + + GUEST_ASSERT(!vmread(TERTIARY_VM_EXEC_CONTROL, &ctls)); + ctls |=3D TERTIARY_EXEC_GUEST_APIC_TIMER; + /* + * vmwrite() succeeds even if unsuported bit is set. + * follwoing vmenter will fail instead. + */ + GUEST_ASSERT(!vmwrite(TERTIARY_VM_EXEC_CONTROL, ctls)); + + if (has_guest_apic_timer_virt) { + GUEST_ASSERT(!vmwrite(GUEST_DEADLINE_VIR, 0)); + GUEST_ASSERT(!vmwrite(GUEST_DEADLINE_PHY, 0)); + GUEST_ASSERT(!vmwrite(GUEST_APIC_TIMER_VECTOR, TIMER_VECTOR)); + } else { + GUEST_ASSERT(vmwrite(GUEST_DEADLINE_VIR, 0)); + GUEST_ASSERT(vmwrite(GUEST_DEADLINE_PHY, 0)); + GUEST_ASSERT(vmwrite(GUEST_APIC_TIMER_VECTOR, TIMER_VECTOR)); + } +} + +static void l1_guest_code(struct vmx_pages *vmx_pages) +{ + /* Prepare the VMCS for L2 execution. */ + setup_l2(vmx_pages); + + /* Run L2 */ + if (!has_guest_apic_timer_virt) { + uint64_t ctls3; + + GUEST_ASSERT(vmlaunch()); + + GUEST_ASSERT(!vmread(TERTIARY_VM_EXEC_CONTROL, &ctls3)); + ctls3 &=3D ~TERTIARY_EXEC_GUEST_APIC_TIMER; + GUEST_ASSERT(!vmwrite(TERTIARY_VM_EXEC_CONTROL, ctls3)); + } + GUEST_ASSERT(!vmlaunch()); + GUEST_ASSERT(vmreadz(VM_EXIT_REASON) =3D=3D EXIT_REASON_VMCALL); + + GUEST_DONE(); +} + +static void vmx_tertiary_controls_test(void) +{ + uint64_t ctls, ctls3, r; + struct kvm_vcpu *vcpu; + vm_vaddr_t guest_gva; + struct kvm_vm *vm; + bool done; + + vm =3D vm_create_with_one_vcpu(&vcpu, l1_guest_code); + vcpu_alloc_vmx(vm, &guest_gva); + vcpu_args_set(vcpu, 1, guest_gva); + + ctls =3D vcpu_get_msr(vcpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS); + ctls |=3D (uint64_t)CPU_BASED_ACTIVATE_TERTIARY_CONTROLS << 32; + vcpu_set_msr(vcpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS, ctls); + + ctls3 =3D vcpu_get_msr(vcpu, MSR_IA32_VMX_PROCBASED_CTLS3); + ctls3 |=3D TERTIARY_EXEC_GUEST_APIC_TIMER; + + r =3D _vcpu_set_msr(vcpu, MSR_IA32_VMX_PROCBASED_CTLS3, ctls3); + if (has_guest_apic_timer_virt) + TEST_ASSERT_MSR(r =3D=3D 1, + "KVM_SET_MSR on %s failed value =3D 0x%lx", + MSR_IA32_VMX_PROCBASED_CTLS3, + "MSR_IA32_VMX_PROCBASED_CTLS3", + ctls3); + else { + TEST_ASSERT_MSR(r !=3D 1, + "KVM_SET_MSR on %s should fail value =3D 0x%lx", + MSR_IA32_VMX_PROCBASED_CTLS3, + "MSR_IA32_VMX_PROCBASED_CTLS3", + ctls3); + } + sync_global_to_guest(vm, has_guest_apic_timer_virt); + + done =3D false; + while (!done) { + struct ucall uc; + + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + + switch (get_ucall(vcpu, &uc)) { + case UCALL_ABORT: + REPORT_GUEST_ASSERT(uc); + /* NOT REACHED */ + case UCALL_DONE: + done =3D true; + break; + default: + TEST_ASSERT(false, "Unknown ucall %lu", uc.cmd); + } + } + + kvm_vm_free(vm); +} + +int main(void) +{ + union vmx_ctrl_msr ctls; + uint64_t ctls3; + + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX)); + + ctls.val =3D kvm_get_feature_msr(MSR_IA32_VMX_TRUE_PROCBASED_CTLS); + TEST_REQUIRE(ctls.clr & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS); + + ctls3 =3D kvm_get_feature_msr(MSR_IA32_VMX_PROCBASED_CTLS3); + has_guest_apic_timer_virt =3D ctls3 & TERTIARY_EXEC_GUEST_APIC_TIMER; + + disable_inkernel_irqchip =3D false; + vmx_tertiary_controls_test(); + + /* nested apic timer virtualization requires in-kernel apic */ + disable_inkernel_irqchip =3D true; + has_guest_apic_timer_virt =3D false; + vmx_tertiary_controls_test(); + + return 0; +} --=20 2.45.2 From nobody Thu Apr 2 06:14:18 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.12]) (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 4263B4508F2; Thu, 5 Mar 2026 17:44:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732702; cv=none; b=S5PXclRS07i1tcrdiaW9mxF8lvc9GCN56V5v7xhkWl5slsuUwVKVb0kbX/o8jL8YmeSjzus/TEf6GHuY+ydcpDloHh9ZSKQMZEbcTuUB022ZMGf7sOficz7ca/CY8kj1Y8ESmKXB5tKA8ySnkeVqehrUQ9ZaSLGUjNyvZDQRZs8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772732702; c=relaxed/simple; bh=nVMEQc7hnfHWhWlWMR74SIkVL/5f832Ezi9L3urEKwQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XKwnJ5Iu07P2AmXMISBVHpzspEGuSXf/rcsdbiUC0JKP1CkK1fb52ZIzE4b2Eb+cNgGsnTVS27vCinrjl6CnTqSFTyHJ92G4iMwfVAyYVi21lRVsx0jC2Nu0WES4xtt1Bc7oBFFJXYuKXjhQ97/B/AoKNyDxOq5z1JEYr/LfBx0= 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=EWldZcfF; arc=none smtp.client-ip=192.198.163.12 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="EWldZcfF" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1772732697; x=1804268697; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=nVMEQc7hnfHWhWlWMR74SIkVL/5f832Ezi9L3urEKwQ=; b=EWldZcfFCwb5lwfIgt/nwJkTIObHkTvRGstfgYpeYb/KKcCbFhB5J5nM Idd3w5ceAIC8jko1c783je9i9TSnYYkY8FbfDAu8YJQxPrDwTAtQIOmk9 TPrz5gnhak152xFs4rKVq5t8BkD6TydOQxHGCBak7riElYqTlejmOouDP E95GSzml/aipFdA5xgNvuAdkIIsdUjs62cWTZdpC5lAbA++Snd8LqcMeW 8xGx767HsL8nLhw8rqLhMnnnVsPa3izGwaOo9ryRPqyzduOYQ46MdhfK9 C/jH3e7h9qlzfW5kPtnhqfhq8YR7POBJHFNfz+YE6SepPQ/kKZQKzS1gv w==; X-CSE-ConnectionGUID: TKn/zxSPRJunDoR9VUpbBw== X-CSE-MsgGUID: iuIaOAMnR8C/Wa5StAwkPA== X-IronPort-AV: E=McAfee;i="6800,10657,11720"; a="77701158" X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="77701158" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:57 -0800 X-CSE-ConnectionGUID: 3s/l5F0/Q0GPKHoKEWfkzg== X-CSE-MsgGUID: j36PFEJyQA6UkUyDpCRJWw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,103,1770624000"; d="scan'208";a="256647704" Received: from mdroper-mobl2.amr.corp.intel.com (HELO localhost) ([10.124.220.244]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2026 09:44:57 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , Sean Christopherson , linux-kernel@vger.kernel.org Subject: [PATCH v2 36/36] Documentation: KVM: x86: Update documentation of struct vmcs12 Date: Thu, 5 Mar 2026 09:44:16 -0800 Message-ID: <439849b2347a9352ab5767d0a78d9273fd20e407.1772732517.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: 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: Isaku Yamahata Update struct vmcs12 in the documentation to match the current implementation. Signed-off-by: Isaku Yamahata --- Documentation/virt/kvm/x86/nested-vmx.rst | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Documentation/virt/kvm/x86/nested-vmx.rst b/Documentation/virt= /kvm/x86/nested-vmx.rst index ac2095d41f02..0269a89a1beb 100644 --- a/Documentation/virt/kvm/x86/nested-vmx.rst +++ b/Documentation/virt/kvm/x86/nested-vmx.rst @@ -113,7 +113,15 @@ struct shadow_vmcs is ever changed. u64 guest_pdptr3; u64 host_ia32_pat; u64 host_ia32_efer; - u64 padding64[8]; /* room for future expansion */ + u64 host_ia32_perf_global_ctrl; + u64 vmread_bitmap; + u64 vmwrite_bitmap; + u64 vm_function_control; + u64 eptp_list_address; + u64 pml_address; + u64 encls_exiting_bitmap; + u64 tsc_multiplier; + u64 tertiary_vm_exec_control; natural_width cr0_guest_host_mask; natural_width cr4_guest_host_mask; natural_width cr0_read_shadow; @@ -217,6 +225,10 @@ struct shadow_vmcs is ever changed. u16 host_fs_selector; u16 host_gs_selector; u16 host_tr_selector; + u16 guest_pml_index; + u16 virtual_timer_vector; + u64 guest_deadline; + u64 guest_deadline_shadow; }; =20 =20 --=20 2.45.2