From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by spool.mail.gandi.net (Postfix) with ESMTPS id 4B9E3740035 for ; Tue, 16 Jan 2024 05:51:05 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=xuTYYQd6x1Nr5Uw6RlVM+RRDWTQw44zVG3bxkANq2CA=; c=relaxed/simple; d=groups.io; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding; s=20140610; t=1705384264; v=1; b=RLTt6+SZEuvVy+373rpR7dMIM2zri76G+cTumtYLnWsKxaZRVRDKQr6HAZWxtkSLdMkAMJ4M JW6qpyYgpmZeoYD9AbHa3sVIDbqi6Fg8LhrziTZCzy55OZ9GPuo6YECJfQs1nITykHLf2rv1csl 6MaH2AWYtEXDgDNAyPjx2TLs= X-Received: by 127.0.0.2 with SMTP id XhrdYY7687511xb62XitPE3N; Mon, 15 Jan 2024 21:51:04 -0800 X-Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) by mx.groups.io with SMTP id smtpd.web11.72208.1705305855278622364 for ; Mon, 15 Jan 2024 00:04:23 -0800 X-IronPort-AV: E=McAfee;i="6600,9927,10953"; a="6313733" X-IronPort-AV: E=Sophos;i="6.04,196,1695711600"; d="scan'208";a="6313733" X-Received: from orviesa002.jf.intel.com ([10.64.159.142]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Jan 2024 00:04:24 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.04,196,1695711600"; d="scan'208";a="25402247" X-Received: from ray-dev.ccr.corp.intel.com ([10.239.158.139]) by orviesa002.jf.intel.com with ESMTP; 15 Jan 2024 00:04:22 -0800 From: "Ni, Ray" To: devel@edk2.groups.io Cc: Michael D Kinney , Nate DeSimone , Laszlo Ersek , Rahul Kumar , Gerd Hoffmann Subject: [edk2-devel] [PATCH 4/6] UefiCpuPkg/LocalApicTimerDxe: Enhance Timer Frequency calculation logic Date: Mon, 15 Jan 2024 16:03:23 +0800 Message-Id: <20240115080325.147-5-ray.ni@intel.com> In-Reply-To: <20240115080325.147-1-ray.ni@intel.com> References: <20240115080325.147-1-ray.ni@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ray.ni@intel.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: Ft2DYFcE8CBTvdGw7IUv6g3kx7686176AA= Content-Transfer-Encoding: quoted-printable X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20140610 header.b=RLTt6+SZ; dmarc=fail reason="SPF not aligned (relaxed), DKIM not aligned (relaxed)" header.from=intel.com (policy=none); spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce@groups.io Old logic is simply to get the APIC Timer Frequency from PcdFSBClock. New logic follows the SDM to firstly get the crystal clock frequency from CPUID.0x15 leaf. If CPUID.0x15 is not supported, the crystal clock frequency is retrieved from PcdCpuCoreCrystalClockFrequency. Then the new logic finds a proper divisor that could support longer timer period. Usually divisor 1 is good enough. But when the timer period is very long, divisor 4, 8, or even 128 could be used. Signed-off-by: Ray Ni Cc: Michael D Kinney Cc: Nate DeSimone Cc: Laszlo Ersek Cc: Rahul Kumar Cc: Gerd Hoffmann --- .../LocalApicTimerDxe/LocalApicTimerDxe.c | 120 +++++++++++++++--- .../LocalApicTimerDxe/LocalApicTimerDxe.h | 4 +- .../LocalApicTimerDxe/LocalApicTimerDxe.inf | 2 +- 3 files changed, 107 insertions(+), 19 deletions(-) diff --git a/UefiCpuPkg/LocalApicTimerDxe/LocalApicTimerDxe.c b/UefiCpuPkg/= LocalApicTimerDxe/LocalApicTimerDxe.c index f36a0e6bf3..babf2476e3 100644 --- a/UefiCpuPkg/LocalApicTimerDxe/LocalApicTimerDxe.c +++ b/UefiCpuPkg/LocalApicTimerDxe/LocalApicTimerDxe.c @@ -128,6 +128,50 @@ TimerDriverRegisterHandler ( return EFI_SUCCESS;=0D }=0D =0D +/**=0D + Return the Crystal Clock Frequency in Hz.=0D +=0D + If CPUID.0x15 is supported, the Crystal Clock Frequency is retrieved fro= m CPUID.0x15.ECX.=0D + Otherwise, the Crystal Clock Frequency is retrieved from PcdCpuCoreCryst= alClockFrequency.=0D +=0D + @return the Crystal Clock Frequency in Hz.=0D +**/=0D +UINT64=0D +GetCoreXtalClockFrequency (=0D + VOID=0D + )=0D +{=0D + UINT32 MaxLeaf;=0D + UINT32 RegEax;=0D + UINT32 RegEbx;=0D + UINT32 CoreXtalClockFrequency;=0D +=0D + CoreXtalClockFrequency =3D 0;=0D + AsmCpuid (CPUID_SIGNATURE, &MaxLeaf, NULL, NULL, NULL);=0D + if (MaxLeaf >=3D CPUID_TIME_STAMP_COUNTER) {=0D + //=0D + // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clo= ck Information=0D + // EBX returns 0 if not supported. ECX, if non zero, provides Core Xta= l Frequency in hertz.=0D + // TSC frequency =3D (ECX, Core Xtal Frequency) * EBX/EAX.=0D + //=0D + AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, (UINT32 *)&CoreX= talClockFrequency, NULL);=0D +=0D + //=0D + // If EAX or EBX returns 0, the Crystal ratio is not enumerated.=0D + //=0D + if ((RegEax =3D=3D 0) || (RegEbx =3D=3D 0)) {=0D + CoreXtalClockFrequency =3D 0;=0D + }=0D + }=0D +=0D + if (CoreXtalClockFrequency !=3D 0) {=0D + return CoreXtalClockFrequency;=0D + } else {=0D + DEBUG ((DEBUG_INFO, "%a: Using PcdCpuCoreCrystalClockFrequency (%ld)\n= ", __func__, PcdGet64 (PcdCpuCoreCrystalClockFrequency)));=0D + return PcdGet64 (PcdCpuCoreCrystalClockFrequency);=0D + }=0D +}=0D +=0D /**=0D =0D This function adjusts the period of timer interrupts to the value specif= ied=0D @@ -163,9 +207,13 @@ TimerDriverSetTimerPeriod ( IN UINT64 TimerPeriod=0D )=0D {=0D - UINT64 TimerCount;=0D - UINT32 TimerFrequency;=0D - UINT32 DivideValue =3D 1;=0D + UINT64 InitialCount;=0D + UINT64 CoreXtalClockFrequency;=0D + UINT64 ApicTimerFrequency;=0D + UINT8 Divisor;=0D + UINT32 TimerPeriodDivisor;=0D +=0D + DEBUG ((DEBUG_INFO, "%a: TimerPeriod =3D %d (100ns)\n", __func__, TimerP= eriod));=0D =0D if (TimerPeriod =3D=3D 0) {=0D //=0D @@ -173,29 +221,67 @@ TimerDriverSetTimerPeriod ( //=0D DisableApicTimerInterrupt ();=0D } else {=0D - TimerFrequency =3D PcdGet32 (PcdFSBClock) / (UINT32)DivideValue;=0D + CoreXtalClockFrequency =3D GetCoreXtalClockFrequency ();=0D + //=0D + // Find a good Divisor that can support the TimerPeriod.=0D + //=0D + for (Divisor =3D 1; Divisor <=3D 128; Divisor *=3D 2) {=0D + ApicTimerFrequency =3D DivU64x32 (CoreXtalClockFrequency, Divisor);= =0D +=0D + //=0D + // TimerPeriod=0D + // InitialCount =3D ---------------- * ApicTimerFrequency=0D + // 10 * 1000 * 1000=0D + //=0D + // So,=0D + //=0D + // InitialCount * 10 * 1000 * 1000=0D + // ApicTimerFrequency =3D ------------------------------=0D + // TimerPeriod=0D + //=0D + // Because InitialCount is a UINT32, the maximum ApicTimerFrequency = is:=0D + //=0D + // MAX_UINT32 * 10 * 1000 * 1000=0D + // ------------------------------=0D + // TimerPeriod=0D + //=0D + if (ApicTimerFrequency <=3D DivU64x64Remainder (MultU64x32 (MAX_UINT= 32, 10 * 1000 * 1000), TimerPeriod, NULL)) {=0D + break;=0D + }=0D + }=0D +=0D + DEBUG ((=0D + DEBUG_INFO,=0D + "%a: ApicTimerFrequency (%d) =3D CoreXtalClockFrequency (%d) / Divis= or (%d)\n",=0D + __func__,=0D + ApicTimerFrequency,=0D + CoreXtalClockFrequency,=0D + Divisor=0D + ));=0D =0D //=0D - // Convert TimerPeriod into local APIC counts=0D + // Convert TimerPeriod (in 100ns) into local APIC counts=0D + // TimerPeriod=0D + // InitialCount =3D ---------------- * ApicTimerFrequency=0D + // 10 * 1000 * 1000=0D //=0D - // TimerPeriod is in 100ns=0D - // TimerPeriod/10000000 will be in seconds.=0D - TimerCount =3D DivU64x32 (=0D - MultU64x32 (TimerPeriod, TimerFrequency),=0D - 10000000=0D - );=0D + TimerPeriodDivisor =3D 10 * 1000 * 1000;=0D =0D - // Check for overflow=0D - if (TimerCount > MAX_UINT32) {=0D - TimerCount =3D MAX_UINT32;=0D - /* TimerPeriod =3D (MAX_UINT32 / TimerFrequency) * 10000000; */=0D - TimerPeriod =3D 429496730;=0D + //=0D + // If TimerPeriod * ApicTimerFrequency > MAX_UINT64, divide TimerPerio= d by 10 until the result <=3D MAX_UINT64.=0D + //=0D + while (TimerPeriod > DivU64x64Remainder (MAX_UINT64, ApicTimerFrequenc= y, NULL)) {=0D + TimerPeriod =3D DivU64x32 (TimerPeriod, 10);=0D + TimerPeriodDivisor /=3D 10;=0D }=0D =0D + InitialCount =3D DivU64x64Remainder (MultU64x64 (TimerPeriod, ApicTime= rFrequency), TimerPeriodDivisor, NULL);=0D + DEBUG ((DEBUG_INFO, "%a: InitialCount =3D %d\n", __func__, InitialCoun= t));=0D +=0D //=0D // Program the timer with the new count value=0D //=0D - InitializeApicTimer (DivideValue, (UINT32)TimerCount, TRUE, LOCAL_APIC= _TIMER_VECTOR);=0D + InitializeApicTimer (Divisor, (UINT32)InitialCount, TRUE, LOCAL_APIC_T= IMER_VECTOR);=0D =0D //=0D // Enable timer interrupt=0D diff --git a/UefiCpuPkg/LocalApicTimerDxe/LocalApicTimerDxe.h b/UefiCpuPkg/= LocalApicTimerDxe/LocalApicTimerDxe.h index 93706995f8..d7f38a3dc3 100644 --- a/UefiCpuPkg/LocalApicTimerDxe/LocalApicTimerDxe.h +++ b/UefiCpuPkg/LocalApicTimerDxe/LocalApicTimerDxe.h @@ -1,7 +1,7 @@ /** @file=0D Private data structures=0D =0D -Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
=0D +Copyright (c) 2005 - 2024, Intel Corporation. All rights reserved.
=0D Copyright (c) 2019, Citrix Systems, Inc.=0D =0D SPDX-License-Identifier: BSD-2-Clause-Patent=0D @@ -16,12 +16,14 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include =0D =0D #include =0D +#include =0D =0D #include =0D #include =0D #include =0D #include =0D #include =0D +#include =0D =0D // The default timer tick duration is set to 10 ms =3D 100000 100 ns units= =0D //=0D diff --git a/UefiCpuPkg/LocalApicTimerDxe/LocalApicTimerDxe.inf b/UefiCpuPk= g/LocalApicTimerDxe/LocalApicTimerDxe.inf index 874d58fa17..a468f09566 100644 --- a/UefiCpuPkg/LocalApicTimerDxe/LocalApicTimerDxe.inf +++ b/UefiCpuPkg/LocalApicTimerDxe/LocalApicTimerDxe.inf @@ -37,6 +37,6 @@ gEfiCpuArchProtocolGuid ## CONSUMES=0D gEfiTimerArchProtocolGuid ## PRODUCES=0D [Pcd]=0D - gEfiMdePkgTokenSpaceGuid.PcdFSBClock ## CONSUMES=0D + gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency ## CONSUMES=0D [Depex]=0D gEfiCpuArchProtocolGuid=0D --=20 2.39.1.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#113803): https://edk2.groups.io/g/devel/message/113803 Mute This Topic: https://groups.io/mt/103734964/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/leave/12367111/7686176/1913456212/xyzzy [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=-