From patchwork Thu Mar 25 15:47:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 12164495 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7B31DC433F7 for ; Thu, 25 Mar 2021 15:47:50 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2EF43619EE for ; Thu, 25 Mar 2021 15:47:50 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2EF43619EE Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from list by lists.xenproject.org with outflank-mailman.101429.194055 (Exim 4.92) (envelope-from ) id 1lPSCp-0007jR-DI; Thu, 25 Mar 2021 15:47:31 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 101429.194055; Thu, 25 Mar 2021 15:47:31 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1lPSCp-0007jI-98; Thu, 25 Mar 2021 15:47:31 +0000 Received: by outflank-mailman (input) for mailman id 101429; Thu, 25 Mar 2021 15:47:30 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1lPSCo-0007dH-GF for xen-devel@lists.xenproject.org; Thu, 25 Mar 2021 15:47:30 +0000 Received: from esa5.hc3370-68.iphmx.com (unknown [216.71.155.168]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 57f45469-8c1e-4477-a1fa-29e94f4b75ff; Thu, 25 Mar 2021 15:47:26 +0000 (UTC) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 57f45469-8c1e-4477-a1fa-29e94f4b75ff DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1616687246; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=kR85HuAEtSi2+1CX5gncd/zpXFCfU6BegJnoHsZGfX8=; b=eOSoFdl1aBmnE5Nky8HC7DBCduwtIYICvtqcU9c56VJ+zxkb4a4pdY+/ GJE1wsdATHGqgn6Jy+VL6kqa0qwA2JZxpGVxdb3s0Nhj2763wLjb15gFo df96mchgerVt1PnrIoGLpmC2tzMTj80P5Xb2GO04JIc8psW1TTSHfNMKa c=; Authentication-Results: esa5.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none IronPort-SDR: 28IfOMmo3K9HzOIx7zzQWMVhHTAoCEwTANEpGlFfWKhQ6rbPKk/G2BJVdKIaHmdx9hwPaMSRcN gymDz0SgkjjK66OC9UiZTTSf0wOZeRKlZzAC5NMQcq6PRH+zESX+PJaAlrHbc0tmDuFv9ytCgh Htx/w/K8JUjz/fNT2tknJP9uktCZzne6/6c0e5WAzBGM8GkepoGe0agXheb4pMXY3skFKF8Syx YuMRBeSmVbpu/y8SpC6XP5If4/4p5+f0kST46au63LPAw27amEwbGuw3tDTHXKXwoTNmJxV3Ca yh4= X-SBRS: 5.1 X-MesageID: 40017829 X-Ironport-Server: esa5.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED IronPort-HdrOrdr: A9a23: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 DRPFJLhvc6b1M= X-IronPort-AV: E=Sophos;i="5.81,277,1610427600"; d="scan'208";a="40017829" From: Anthony PERARD To: CC: , Jordan Justen , Anthony PERARD , "Ard Biesheuvel" , Laszlo Ersek , Julien Grall , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Subject: [PATCH v2 6/7] OvmfPkg/XenPlatformPei: Calibrate APIC timer frequency Date: Thu, 25 Mar 2021 15:47:12 +0000 Message-ID: <20210325154713.670104-7-anthony.perard@citrix.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210325154713.670104-1-anthony.perard@citrix.com> References: <20210325154713.670104-1-anthony.perard@citrix.com> MIME-Version: 1.0 Calculate the frequency of the APIC timer that Xen provides. Even though the frequency is currently hard-coded, it isn't part of the public ABI that Xen provides and thus may change at any time. OVMF needs to determine the frequency by an other mean. Fortunately, Xen provides a way to determines the frequency of the TSC, so we can use TSC to calibrate the frequency of the APIC timer. That information is found in the shared_info page which we map and unmap once done (XenBusDxe is going to map the page somewhere else). The shared_info page is map at the highest physical address allowed as it doesn't need to be in the RAM, thus there's a call to update the page table. The calculated frequency is only logged in this patch, it will be used in a following patch. Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2490 Signed-off-by: Anthony PERARD Acked-by: Laszlo Ersek --- CC: Roger Pau Monné --- Notes: v2: - fix CamelCases - Use U64 multiplication and division helpers - don't read TscShift from the SharedInfo page again - change the location of the shared info page to be outside of the ram - check for overflow in XenDelay - check for overflow when calculating the calculating APIC frequency OvmfPkg/XenPlatformPei/XenPlatformPei.inf | 2 + OvmfPkg/XenPlatformPei/Platform.h | 5 + OvmfPkg/XenPlatformPei/Platform.c | 1 + OvmfPkg/XenPlatformPei/Xen.c | 177 ++++++++++++++++++++++ 4 files changed, 185 insertions(+) diff --git a/OvmfPkg/XenPlatformPei/XenPlatformPei.inf b/OvmfPkg/XenPlatformPei/XenPlatformPei.inf index 8790d907d3ec..5732d2188871 100644 --- a/OvmfPkg/XenPlatformPei/XenPlatformPei.inf +++ b/OvmfPkg/XenPlatformPei/XenPlatformPei.inf @@ -52,6 +52,7 @@ [LibraryClasses] DebugLib HobLib IoLib + LocalApicLib PciLib ResourcePublicationLib PeiServicesLib @@ -59,6 +60,7 @@ [LibraryClasses] MtrrLib MemEncryptSevLib PcdLib + SafeIntLib XenHypercallLib [Pcd] diff --git a/OvmfPkg/XenPlatformPei/Platform.h b/OvmfPkg/XenPlatformPei/Platform.h index e70ca58078eb..77d88fc159d7 100644 --- a/OvmfPkg/XenPlatformPei/Platform.h +++ b/OvmfPkg/XenPlatformPei/Platform.h @@ -132,6 +132,11 @@ PhysicalAddressIdentityMapping ( IN EFI_PHYSICAL_ADDRESS AddressToMap ); +VOID +CalibrateLapicTimer ( + VOID + ); + extern EFI_BOOT_MODE mBootMode; extern UINT8 mPhysMemAddressWidth; diff --git a/OvmfPkg/XenPlatformPei/Platform.c b/OvmfPkg/XenPlatformPei/Platform.c index 717fd0ab1a45..e9511eb40c62 100644 --- a/OvmfPkg/XenPlatformPei/Platform.c +++ b/OvmfPkg/XenPlatformPei/Platform.c @@ -448,6 +448,7 @@ InitializeXenPlatform ( InitializeRamRegions (); InitializeXen (); + CalibrateLapicTimer (); if (mBootMode != BOOT_ON_S3_RESUME) { ReserveEmuVariableNvStore (); diff --git a/OvmfPkg/XenPlatformPei/Xen.c b/OvmfPkg/XenPlatformPei/Xen.c index b2a7d1c21dac..7524aaa11a29 100644 --- a/OvmfPkg/XenPlatformPei/Xen.c +++ b/OvmfPkg/XenPlatformPei/Xen.c @@ -21,8 +21,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -457,3 +459,178 @@ PhysicalAddressIdentityMapping ( return EFI_SUCCESS; } + +STATIC +EFI_STATUS +MapSharedInfoPage ( + IN VOID *PagePtr + ) +{ + xen_add_to_physmap_t Parameters; + INTN ReturnCode; + + Parameters.domid = DOMID_SELF; + Parameters.space = XENMAPSPACE_shared_info; + Parameters.idx = 0; + Parameters.gpfn = (UINTN)PagePtr >> EFI_PAGE_SHIFT; + ReturnCode = XenHypercallMemoryOp (XENMEM_add_to_physmap, &Parameters); + if (ReturnCode != 0) { + return EFI_NO_MAPPING; + } + return EFI_SUCCESS; +} + +STATIC +VOID +UnmapXenPage ( + IN VOID *PagePtr + ) +{ + xen_remove_from_physmap_t Parameters; + INTN ReturnCode; + + Parameters.domid = DOMID_SELF; + Parameters.gpfn = (UINTN)PagePtr >> EFI_PAGE_SHIFT; + ReturnCode = XenHypercallMemoryOp (XENMEM_remove_from_physmap, &Parameters); + ASSERT (ReturnCode == 0); +} + + +STATIC +UINT64 +GetCpuFreq ( + IN XEN_VCPU_TIME_INFO *VcpuTime + ) +{ + UINT32 Version; + UINT32 TscToSystemMultiplier; + INT8 TscShift; + UINT64 CpuFreq; + + do { + Version = VcpuTime->Version; + MemoryFence (); + TscToSystemMultiplier = VcpuTime->TscToSystemMultiplier; + TscShift = VcpuTime->TscShift; + MemoryFence (); + } while (((Version & 1) != 0) && (Version != VcpuTime->Version)); + + CpuFreq = DivU64x32 (LShiftU64 (1000000000ULL, 32), TscToSystemMultiplier); + if (TscShift >= 0) { + CpuFreq = RShiftU64 (CpuFreq, TscShift); + } else { + CpuFreq = LShiftU64 (CpuFreq, -TscShift); + } + return CpuFreq; +} + +STATIC +VOID +XenDelay ( + IN XEN_VCPU_TIME_INFO *VcpuTimeInfo, + IN UINT64 DelayNs + ) +{ + UINT64 Tick; + UINT64 CpuFreq; + UINT64 Delay; + UINT64 DelayTick; + UINT64 NewTick; + RETURN_STATUS Status; + + Tick = AsmReadTsc (); + + CpuFreq = GetCpuFreq (VcpuTimeInfo); + Status = SafeUint64Mult (DelayNs, CpuFreq, &Delay); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "XenDelay (%ld ns): delay too big in relation to CPU freq %ld Hz\n", + DelayNs, CpuFreq)); + CpuDeadLoop (); + } + + DelayTick = DivU64x32 (Delay, 1000000000UL); + + NewTick = Tick + DelayTick; + + // + // Check for overflow + // + if (NewTick < Tick) { + // + // Overflow, wait for TSC to also overflow + // + while (AsmReadTsc () >= Tick) { + CpuPause (); + } + } + + while (AsmReadTsc () <= NewTick) { + CpuPause (); + } +} + + +/** + Calculate the frequency of the Local Apic Timer +**/ +VOID +CalibrateLapicTimer ( + VOID + ) +{ + XEN_SHARED_INFO *SharedInfo; + XEN_VCPU_TIME_INFO *VcpuTimeInfo; + UINT32 TimerTick, TimerTick2, DiffTimer; + UINT64 TscTick, TscTick2; + UINT64 Freq; + UINT64 Dividend; + EFI_STATUS Status; + + + SharedInfo = (VOID*)((1ULL << mPhysMemAddressWidth) - EFI_PAGE_SIZE); + Status = PhysicalAddressIdentityMapping ((EFI_PHYSICAL_ADDRESS)SharedInfo); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "Failed to add page table entry for Xen shared info page: %r\n", + Status)); + return; + } + + Status = MapSharedInfoPage (SharedInfo); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to map Xen's shared info page: %r\n", + Status)); + return; + } + + VcpuTimeInfo = &SharedInfo->VcpuInfo[0].Time; + + InitializeApicTimer (1, MAX_UINT32, TRUE, 0); + DisableApicTimerInterrupt (); + + TimerTick = GetApicTimerCurrentCount (); + TscTick = AsmReadTsc (); + XenDelay (VcpuTimeInfo, 1000000ULL); + TimerTick2 = GetApicTimerCurrentCount (); + TscTick2 = AsmReadTsc (); + + + DiffTimer = TimerTick - TimerTick2; + Status = SafeUint64Mult (GetCpuFreq (VcpuTimeInfo), DiffTimer, &Dividend); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "overflow while calculating APIC frequency\n")); + DEBUG ((DEBUG_ERROR, "CPU freq: %ld Hz; APIC timer tick count for 1 ms: %d\n", + GetCpuFreq (VcpuTimeInfo), DiffTimer)); + CpuDeadLoop (); + } + + Freq = DivU64x64Remainder (Dividend, TscTick2 - TscTick, NULL); + DEBUG ((DEBUG_INFO, "APIC Freq % 8lu Hz\n", Freq)); + + UnmapXenPage (SharedInfo); +}