From nobody Mon Feb 9 19:05:19 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+100708+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+100708+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1678062135; cv=none; d=zohomail.com; s=zohoarc; b=NxmPeAPl7X8+4c3G9W8flLwXsHfTqvCPZuJUJDSu1KriRkFA/92jjmW9rtdYDB/2zR4bktH0H1EvgHhNSMYWsQJ/xgpNnMfu/+TVxMN68mLdgxX2lshmWZIFqTEs72KAkXwFx7CEP/144ztovSuzqmXGrb5a0g8OpPV+I/4I/3E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1678062135; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=Mq9cZqfCQAa3V19USoTbHuMqe55ofoDRgEMfrRn65z8=; b=nfA+vDcclmrlPnU3a7JRXW0VdlZo28T68D2y7qPaRQNC1ufoh/kSU+3d7IlueGcLOnLWzXZid81qjAIZKDsvNxVbhhSc0aHdT/OZbScNbmMR2EczdMTmMYplz56Xrr0MoYwxkvuOj5mB7Q3apDI451zKsSof6YQrzij6882Nqk8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+100708+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1678062135831272.3793264649295; Sun, 5 Mar 2023 16:22:15 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id YDi6YY1788612xhAnnxRstYf; Sun, 05 Mar 2023 16:22:15 -0800 X-Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by mx.groups.io with SMTP id smtpd.web10.22191.1678062132259075315 for ; Sun, 05 Mar 2023 16:22:13 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10640"; a="337758121" X-IronPort-AV: E=Sophos;i="5.98,236,1673942400"; d="scan'208";a="337758121" X-Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2023 16:22:11 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10640"; a="669263326" X-IronPort-AV: E=Sophos;i="5.98,236,1673942400"; d="scan'208";a="669263326" X-Received: from nldesimo-desk.amr.corp.intel.com ([10.24.12.177]) by orsmga007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Mar 2023 16:22:11 -0800 From: "Nate DeSimone" To: devel@edk2.groups.io Cc: Andrew Fish , Ray Ni , Michael D Kinney , Chasel Chiu Subject: [edk2-devel] [PATCH v1 6/6] EmulatorPkg: Add EmuCacheMaintenanceLib Date: Sun, 5 Mar 2023 16:22:05 -0800 Message-Id: <20230306002205.1640-7-nathaniel.l.desimone@intel.com> In-Reply-To: <20230306002205.1640-1-nathaniel.l.desimone@intel.com> References: <20230306002205.1640-1-nathaniel.l.desimone@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: 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,nathaniel.l.desimone@intel.com X-Gm-Message-State: Lgf2QKGQw26nUGyUn8Aqm1Pjx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1678062135; bh=2hFO35lXM2LIWXLSWG4U0WgsHxgGiOvSY/U5JsZ+o/Y=; h=Cc:Date:From:Reply-To:Subject:To; b=Nexqh+mrqQm/ekDS4A4ABoijb1USySijY9ft5Dx5nEaq9NJ+0BOV4PKV0BhWD05yywz lU7waIQiIineOdZ3riBE74DhPRVQ7LVZudDiOc3bN+CO0CyxgfKueVM2AqSrwfDe6XYoY 3lUavtLVjLCwTFh+WACnz+6vxT5BUGFhi6o= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1678062136128100012 Content-Type: text/plain; charset="utf-8" Adds new implementation of CacheMaintenanceLib that uses the GCC intrinsic __builtin__clear_cache() to clear processor caches. This is required on machine types that use a syscall to access the cache controller. Cc: Andrew Fish Cc: Ray Ni Cc: Michael D Kinney Cc: Chasel Chiu Signed-off-by: Nate DeSimone --- EmulatorPkg/EmulatorPkg.dec | 4 +- EmulatorPkg/EmulatorPkg.dsc | 7 + EmulatorPkg/Include/Protocol/EmuCache.h | 217 +++++++++++ .../DxeEmuCacheMaintenanceLib.c | 337 +++++++++++++++++ .../DxeEmuCacheMaintenanceLib.inf | 37 ++ .../PeiEmuCacheMaintenanceLib.c | 344 ++++++++++++++++++ .../PeiEmuCacheMaintenanceLib.inf | 39 ++ EmulatorPkg/Unix/Host/CacheMaintenance.c | 284 +++++++++++++++ EmulatorPkg/Unix/Host/Host.c | 5 +- EmulatorPkg/Unix/Host/Host.h | 2 + EmulatorPkg/Unix/Host/Host.inf | 2 + 11 files changed, 1276 insertions(+), 2 deletions(-) create mode 100644 EmulatorPkg/Include/Protocol/EmuCache.h create mode 100644 EmulatorPkg/Library/DxeEmuCacheMaintenanceLib/DxeEmuCac= heMaintenanceLib.c create mode 100644 EmulatorPkg/Library/DxeEmuCacheMaintenanceLib/DxeEmuCac= heMaintenanceLib.inf create mode 100644 EmulatorPkg/Library/PeiEmuCacheMaintenanceLib/PeiEmuCac= heMaintenanceLib.c create mode 100644 EmulatorPkg/Library/PeiEmuCacheMaintenanceLib/PeiEmuCac= heMaintenanceLib.inf create mode 100644 EmulatorPkg/Unix/Host/CacheMaintenance.c diff --git a/EmulatorPkg/EmulatorPkg.dec b/EmulatorPkg/EmulatorPkg.dec index fe81652b04..adf615f796 100644 --- a/EmulatorPkg/EmulatorPkg.dec +++ b/EmulatorPkg/EmulatorPkg.dec @@ -2,7 +2,7 @@ # # This is the Emu Emulation Environment Platform # -# Copyright (c) 2008 - 2022, Intel Corporation. All rights reserved.
+# Copyright (c) 2008 - 2023, Intel Corporation. All rights reserved.
# Portions copyright (c) 2011, Apple Inc. All rights reserved. # (C) Copyright 2020 Hewlett Packard Enterprise Development LP
# @@ -37,6 +37,7 @@ gEmuThreadThunkProtocolGuid =3D { 0x3B1E4B7C, 0x09D8, 0x944F, { 0xA4,= 0x08, 0x13, 0x09, 0xEB, 0x8B, 0x44, 0x27 } } gEmuBlockIoProtocolGuid =3D { 0x6888A4AE, 0xAFCE, 0xE84B, { 0x91,= 0x02, 0xF7, 0xB9, 0xDA, 0xE6, 0xA0, 0x30 } } gEmuSnpProtocolGuid =3D { 0xFD5FBE54, 0x8C35, 0xB345, { 0x8A,= 0x0F, 0x7A, 0xC8, 0xA5, 0xFD, 0x05, 0x21 } } + gEmuCacheThunkProtocolGuid =3D { 0x8816732A, 0xF6DE, 0x466A, { 0x8E,= 0x47, 0x1C, 0xE0, 0xEE, 0x1F, 0xB3, 0x3A } } =20 [Ppis] gEmuThunkPpiGuid =3D { 0xE113F896, 0x75CF, 0xF640, { 0x81,= 0x7F, 0xC8, 0x5A, 0x79, 0xE8, 0xAE, 0x67 } } @@ -109,6 +110,7 @@ gEmulatorPkgTokenSpaceGuid.PcdEmuGop|L"GOP Window"|VOID*|0x00001018 gEmulatorPkgTokenSpaceGuid.PcdEmuFileSystem|L"."|VOID*|0x00001004 gEmulatorPkgTokenSpaceGuid.PcdEmuSerialPort|L"/dev/ttyS0"|VOID*|0x000010= 02 + gEmulatorPkgTokenSpaceGuid.PcdEmuCache|L"CacheCtl"|VOID*|0x0000101d =20 # # On Unix host, this is the network interface name on host system that w= ill diff --git a/EmulatorPkg/EmulatorPkg.dsc b/EmulatorPkg/EmulatorPkg.dsc index 62d853e470..601c2d7988 100644 --- a/EmulatorPkg/EmulatorPkg.dsc +++ b/EmulatorPkg/EmulatorPkg.dsc @@ -187,6 +187,9 @@ [LibraryClasses.common.PEIM] PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf =20 +[LibraryClasses.ARM.PEIM, LibraryClasses.ARM.PEI_CORE] + CacheMaintenanceLib|EmulatorPkg/Library/PeiEmuCacheMaintenanceLib/PeiEmu= CacheMaintenanceLib.inf + [LibraryClasses.common.DXE_CORE] HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeC= oreMemoryAllocationLib.inf @@ -217,6 +220,9 @@ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeRepor= tStatusCodeLib.inf TimerLib|EmulatorPkg/Library/DxeTimerLib/DxeTimerLib.inf =20 +[LibraryClasses.ARM.DXE_CORE, LibraryClasses.ARM.DXE_RUNTIME_DRIVER, Libra= ryClasses.ARM.UEFI_DRIVER, LibraryClasses.ARM.DXE_DRIVER, LibraryClasses.AR= M.UEFI_APPLICATION] + CacheMaintenanceLib|EmulatorPkg/Library/DxeEmuCacheMaintenanceLib/DxeEmu= CacheMaintenanceLib.inf + [PcdsFeatureFlag] gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreImageLoaderSearchTeSectionFirst= |FALSE =20 @@ -269,6 +275,7 @@ gEmulatorPkgTokenSpaceGuid.PcdEmuFileSystem|L"." gEmulatorPkgTokenSpaceGuid.PcdEmuSerialPort|L"/dev/ttyS0" gEmulatorPkgTokenSpaceGuid.PcdEmuNetworkInterface|L"en0" + gEmulatorPkgTokenSpaceGuid.PcdEmuCache|L"CacheCtl" =20 gEmulatorPkgTokenSpaceGuid.PcdEmuCpuModel|L"Intel(R) Processor Model" gEmulatorPkgTokenSpaceGuid.PcdEmuCpuSpeed|L"3000" diff --git a/EmulatorPkg/Include/Protocol/EmuCache.h b/EmulatorPkg/Include/= Protocol/EmuCache.h new file mode 100644 index 0000000000..3c05e7807c --- /dev/null +++ b/EmulatorPkg/Include/Protocol/EmuCache.h @@ -0,0 +1,217 @@ +/** @file + Invoke syscalls for cache maintenance on platforms that require kernel + mode to manage the cache. ARM and RISC-V for example. + + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __EMU_CACHE__ +#define __EMU_CACHE__ + +typedef struct _EMU_CACHE_THUNK_PROTOCOL EMU_CACHE_THUNK_PROTOCOL; + +/** + Invalidates the entire instruction cache in cache coherency domain of the + calling CPU. + +**/ +typedef +VOID +(EFIAPI *EMU_CACHE_PROTOCOL_INVALIDATE_INSTRUCTION_CACHE) ( + VOID + ); + +/** + Invalidates a range of instruction cache lines in the cache coherency do= main + of the calling CPU. + + Invalidates the instruction cache lines specified by Address and Length.= If + Address is not aligned on a cache line boundary, then entire instruction + cache line containing Address is invalidated. If Address + Length is not + aligned on a cache line boundary, then the entire instruction cache line + containing Address + Length -1 is invalidated. This function may choose = to + invalidate the entire instruction cache if that is more efficient than + invalidating the specified range. If Length is 0, then no instruction ca= che + lines are invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the instruction cache lines to + invalidate. If the CPU is in a physical addressing mode,= then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + + @param Length The number of bytes to invalidate from the instruction c= ache. + + @return Address. + +**/ +typedef +VOID * +(EFIAPI *EMU_CACHE_PROTOCOL_INVALIDATE_INSTRUCTION_CACHE_RANGE)( + IN VOID *Address, + IN UINTN Length + ); + +/** + Writes Back and Invalidates the entire data cache in cache coherency dom= ain + of the calling CPU. + + Writes Back and Invalidates the entire data cache in cache coherency dom= ain + of the calling CPU. This function guarantees that all dirty cache lines = are + written back to system memory, and also invalidates all the data cache l= ines + in the cache coherency domain of the calling CPU. + +**/ +typedef +VOID +(EFIAPI *EMU_CACHE_PROTOCOL_WRITE_BACK_INVALIDATE_DATA_CACHE)( + VOID + ); + +/** + Writes Back and Invalidates a range of data cache lines in the cache + coherency domain of the calling CPU. + + Writes Back and Invalidate the data cache lines specified by Address and + Length. If Address is not aligned on a cache line boundary, then entire = data + cache line containing Address is written back and invalidated. If Addres= s + + Length is not aligned on a cache line boundary, then the entire data cac= he + line containing Address + Length -1 is written back and invalidated. This + function may choose to write back and invalidate the entire data cache if + that is more efficient than writing back and invalidating the specified + range. If Length is 0, then no data cache lines are written back and + invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back a= nd + invalidate. If the CPU is in a physical addressing mode,= then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + @param Length The number of bytes to write back and invalidate from the + data cache. + + @return Address of cache invalidation. + +**/ +typedef +VOID * +(EFIAPI *EMU_CACHE_PROTOCOL_WRITE_BACK_INVALIDATE_DATA_CACHE_RANGE)( + IN VOID *Address, + IN UINTN Length + ); + +/** + Writes Back the entire data cache in cache coherency domain of the calli= ng + CPU. + + Writes Back the entire data cache in cache coherency domain of the calli= ng + CPU. This function guarantees that all dirty cache lines are written bac= k to + system memory. This function may also invalidate all the data cache line= s in + the cache coherency domain of the calling CPU. + +**/ +typedef +VOID +(EFIAPI *EMU_CACHE_PROTOCOL_WRITE_BACK_DATA_CACHE)( + VOID + ); + +/** + Writes Back a range of data cache lines in the cache coherency domain of= the + calling CPU. + + Writes Back the data cache lines specified by Address and Length. If Add= ress + is not aligned on a cache line boundary, then entire data cache line + containing Address is written back. If Address + Length is not aligned o= n a + cache line boundary, then the entire data cache line containing Address + + Length -1 is written back. This function may choose to write back the en= tire + data cache if that is more efficient than writing back the specified ran= ge. + If Length is 0, then no data cache lines are written back. This function= may + also invalidate all the data cache lines in the specified range of the c= ache + coherency domain of the calling CPU. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back. = If + the CPU is in a physical addressing mode, then Address i= s a + physical address. If the CPU is in a virtual addressing + mode, then Address is a virtual address. + @param Length The number of bytes to write back from the data cache. + + @return Address of cache written in main memory. + +**/ +typedef +VOID * +(EFIAPI *EMU_CACHE_PROTOCOL_WRITE_BACK_DATA_CACHE_RANGE)( + IN VOID *Address, + IN UINTN Length + ); + +/** + Invalidates the entire data cache in cache coherency domain of the calli= ng + CPU. + + Invalidates the entire data cache in cache coherency domain of the calli= ng + CPU. This function must be used with care because dirty cache lines are = not + written back to system memory. It is typically used for cache diagnostic= s. If + the CPU does not support invalidation of the entire data cache, then a w= rite + back and invalidate operation should be performed on the entire data cac= he. + +**/ +typedef +VOID +(EFIAPI *EMU_CACHE_PROTOCOL_INVALIDATE_DATA_CACHE)( + VOID + ); + +/** + Invalidates a range of data cache lines in the cache coherency domain of= the + calling CPU. + + Invalidates the data cache lines specified by Address and Length. If Add= ress + is not aligned on a cache line boundary, then entire data cache line + containing Address is invalidated. If Address + Length is not aligned on= a + cache line boundary, then the entire data cache line containing Address + + Length -1 is invalidated. This function must never invalidate any cache = lines + outside the specified range. If Length is 0, the no data cache lines are + invalidated. Address is returned. This function must be used with care + because dirty cache lines are not written back to system memory. It is + typically used for cache diagnostics. If the CPU does not support + invalidation of a data cache range, then a write back and invalidate + operation should be performed on the data cache range. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to invalidate. = If + the CPU is in a physical addressing mode, then Address i= s a + physical address. If the CPU is in a virtual addressing = mode, + then Address is a virtual address. + @param Length The number of bytes to invalidate from the data cache. + + @return Address. + +**/ +typedef +VOID * +(EFIAPI *EMU_CACHE_INVALIDATE_DATA_CACHE_RANGE)( + IN VOID *Address, + IN UINTN Length + ); + +struct _EMU_CACHE_THUNK_PROTOCOL { + EMU_CACHE_PROTOCOL_INVALIDATE_INSTRUCTION_CACHE InvalidateIn= structionCache; + EMU_CACHE_PROTOCOL_INVALIDATE_INSTRUCTION_CACHE_RANGE InvalidateIn= structionCacheRange; + EMU_CACHE_PROTOCOL_WRITE_BACK_INVALIDATE_DATA_CACHE WriteBackInv= alidateDataCache; + EMU_CACHE_PROTOCOL_WRITE_BACK_INVALIDATE_DATA_CACHE_RANGE WriteBackInv= alidateDataCacheRange; + EMU_CACHE_PROTOCOL_WRITE_BACK_DATA_CACHE WriteBackDat= aCache; + EMU_CACHE_PROTOCOL_WRITE_BACK_DATA_CACHE_RANGE WriteBackDat= aCacheRange; + EMU_CACHE_PROTOCOL_INVALIDATE_DATA_CACHE InvalidateDa= taCache; + EMU_CACHE_INVALIDATE_DATA_CACHE_RANGE InvalidateDa= taCacheRange; +}; + +#endif diff --git a/EmulatorPkg/Library/DxeEmuCacheMaintenanceLib/DxeEmuCacheMaint= enanceLib.c b/EmulatorPkg/Library/DxeEmuCacheMaintenanceLib/DxeEmuCacheMain= tenanceLib.c new file mode 100644 index 0000000000..2db07b5bd0 --- /dev/null +++ b/EmulatorPkg/Library/DxeEmuCacheMaintenanceLib/DxeEmuCacheMaintenanceL= ib.c @@ -0,0 +1,337 @@ +/** @file + Instance of Cache Maintenance Library using emulator thunks to OS syscal= ls + + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +EFI_STATUS +EFIAPI +DxeGetCacheThunkProtocol ( + OUT EMU_CACHE_THUNK_PROTOCOL **EmuCache + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + EMU_THUNK_PROTOCOL *Thunk; + EMU_IO_THUNK_PROTOCOL *EmuIoThunk; + EFI_STATUS Status; + + // + // Get Unix Thunk Protocol so we can retrieve I/O Thunk Protocols + // + GuidHob =3D GetFirstGuidHob (&gEmuThunkProtocolGuid); + if (GuidHob =3D=3D NULL) { + return EFI_NOT_FOUND; + } + + Thunk =3D (EMU_THUNK_PROTOCOL *)(*(UINTN *)(GET_GUID_HOB_DATA (GuidHob))= ); + if (Thunk =3D=3D NULL) { + return EFI_NOT_FOUND; + } + + // + // Locate the I/O Thunk Protocol representing the Cache Thunk Protocol + // + for (Status =3D EFI_SUCCESS, EmuIoThunk =3D NULL; !EFI_ERROR (Status); )= { + Status =3D Thunk->GetNextProtocol (FALSE, &EmuIoThunk); + if (EFI_ERROR (Status)) { + break; + } + + if (EmuIoThunk->Instance =3D=3D 0) { + if (CompareGuid (EmuIoThunk->Protocol, &gEmuCacheThunkProtocolGuid))= { + // + // Open the I/O Thunk Protocol to retrieve the Cache Thunk Protocol + // + Status =3D EmuIoThunk->Open (EmuIoThunk); + if (EFI_ERROR (Status)) { + return Status; + } + *EmuCache =3D (EMU_CACHE_THUNK_PROTOCOL *) EmuIoThunk->Interface; + return EFI_SUCCESS; + } + } + } + + return EFI_NOT_FOUND; +} + +/** + Invalidates the entire instruction cache in cache coherency domain of the + calling CPU. + +**/ +VOID +EFIAPI +InvalidateInstructionCache ( + VOID + ) +{ + EMU_CACHE_THUNK_PROTOCOL *EmuCache; + EFI_STATUS Status; + + Status =3D DxeGetCacheThunkProtocol (&EmuCache); + if (!EFI_ERROR (Status) && EmuCache !=3D NULL) { + EmuCache->InvalidateInstructionCache (); + } +} + +/** + Invalidates a range of instruction cache lines in the cache coherency do= main + of the calling CPU. + + Invalidates the instruction cache lines specified by Address and Length.= If + Address is not aligned on a cache line boundary, then entire instruction + cache line containing Address is invalidated. If Address + Length is not + aligned on a cache line boundary, then the entire instruction cache line + containing Address + Length -1 is invalidated. This function may choose = to + invalidate the entire instruction cache if that is more efficient than + invalidating the specified range. If Length is 0, then no instruction ca= che + lines are invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the instruction cache lines to + invalidate. If the CPU is in a physical addressing mode,= then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + + @param Length The number of bytes to invalidate from the instruction c= ache. + + @return Address. + +**/ +VOID * +EFIAPI +InvalidateInstructionCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + EMU_CACHE_THUNK_PROTOCOL *EmuCache; + EFI_STATUS Status; + + Status =3D DxeGetCacheThunkProtocol (&EmuCache); + if (!EFI_ERROR (Status) && EmuCache !=3D NULL) { + return EmuCache->InvalidateInstructionCacheRange (Address, Length); + } + return NULL; +} + +/** + Writes Back and Invalidates the entire data cache in cache coherency dom= ain + of the calling CPU. + + Writes Back and Invalidates the entire data cache in cache coherency dom= ain + of the calling CPU. This function guarantees that all dirty cache lines = are + written back to system memory, and also invalidates all the data cache l= ines + in the cache coherency domain of the calling CPU. + +**/ +VOID +EFIAPI +WriteBackInvalidateDataCache ( + VOID + ) +{ + EMU_CACHE_THUNK_PROTOCOL *EmuCache; + EFI_STATUS Status; + + Status =3D DxeGetCacheThunkProtocol (&EmuCache); + if (!EFI_ERROR (Status) && EmuCache !=3D NULL) { + EmuCache->WriteBackInvalidateDataCache (); + } +} + +/** + Writes Back and Invalidates a range of data cache lines in the cache + coherency domain of the calling CPU. + + Writes Back and Invalidate the data cache lines specified by Address and + Length. If Address is not aligned on a cache line boundary, then entire = data + cache line containing Address is written back and invalidated. If Addres= s + + Length is not aligned on a cache line boundary, then the entire data cac= he + line containing Address + Length -1 is written back and invalidated. This + function may choose to write back and invalidate the entire data cache if + that is more efficient than writing back and invalidating the specified + range. If Length is 0, then no data cache lines are written back and + invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back a= nd + invalidate. If the CPU is in a physical addressing mode,= then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + @param Length The number of bytes to write back and invalidate from the + data cache. + + @return Address of cache invalidation. + +**/ +VOID * +EFIAPI +WriteBackInvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + EMU_CACHE_THUNK_PROTOCOL *EmuCache; + EFI_STATUS Status; + + Status =3D DxeGetCacheThunkProtocol (&EmuCache); + if (!EFI_ERROR (Status) && EmuCache !=3D NULL) { + return EmuCache->WriteBackInvalidateDataCacheRange (Address, Length); + } + return NULL; +} + +/** + Writes Back the entire data cache in cache coherency domain of the calli= ng + CPU. + + Writes Back the entire data cache in cache coherency domain of the calli= ng + CPU. This function guarantees that all dirty cache lines are written bac= k to + system memory. This function may also invalidate all the data cache line= s in + the cache coherency domain of the calling CPU. + +**/ +VOID +EFIAPI +WriteBackDataCache ( + VOID + ) +{ + EMU_CACHE_THUNK_PROTOCOL *EmuCache; + EFI_STATUS Status; + + Status =3D DxeGetCacheThunkProtocol (&EmuCache); + if (!EFI_ERROR (Status) && EmuCache !=3D NULL) { + EmuCache->WriteBackDataCache (); + } +} + +/** + Writes Back a range of data cache lines in the cache coherency domain of= the + calling CPU. + + Writes Back the data cache lines specified by Address and Length. If Add= ress + is not aligned on a cache line boundary, then entire data cache line + containing Address is written back. If Address + Length is not aligned o= n a + cache line boundary, then the entire data cache line containing Address + + Length -1 is written back. This function may choose to write back the en= tire + data cache if that is more efficient than writing back the specified ran= ge. + If Length is 0, then no data cache lines are written back. This function= may + also invalidate all the data cache lines in the specified range of the c= ache + coherency domain of the calling CPU. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back. = If + the CPU is in a physical addressing mode, then Address i= s a + physical address. If the CPU is in a virtual addressing + mode, then Address is a virtual address. + @param Length The number of bytes to write back from the data cache. + + @return Address of cache written in main memory. + +**/ +VOID * +EFIAPI +WriteBackDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + EMU_CACHE_THUNK_PROTOCOL *EmuCache; + EFI_STATUS Status; + + Status =3D DxeGetCacheThunkProtocol (&EmuCache); + if (!EFI_ERROR (Status) && EmuCache !=3D NULL) { + return EmuCache->WriteBackDataCacheRange (Address, Length); + } + return NULL; +} + +/** + Invalidates the entire data cache in cache coherency domain of the calli= ng + CPU. + + Invalidates the entire data cache in cache coherency domain of the calli= ng + CPU. This function must be used with care because dirty cache lines are = not + written back to system memory. It is typically used for cache diagnostic= s. If + the CPU does not support invalidation of the entire data cache, then a w= rite + back and invalidate operation should be performed on the entire data cac= he. + +**/ +VOID +EFIAPI +InvalidateDataCache ( + VOID + ) +{ + EMU_CACHE_THUNK_PROTOCOL *EmuCache; + EFI_STATUS Status; + + Status =3D DxeGetCacheThunkProtocol (&EmuCache); + if (!EFI_ERROR (Status) && EmuCache !=3D NULL) { + EmuCache->InvalidateDataCache (); + } +} + +/** + Invalidates a range of data cache lines in the cache coherency domain of= the + calling CPU. + + Invalidates the data cache lines specified by Address and Length. If Add= ress + is not aligned on a cache line boundary, then entire data cache line + containing Address is invalidated. If Address + Length is not aligned on= a + cache line boundary, then the entire data cache line containing Address + + Length -1 is invalidated. This function must never invalidate any cache = lines + outside the specified range. If Length is 0, the no data cache lines are + invalidated. Address is returned. This function must be used with care + because dirty cache lines are not written back to system memory. It is + typically used for cache diagnostics. If the CPU does not support + invalidation of a data cache range, then a write back and invalidate + operation should be performed on the data cache range. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to invalidate. = If + the CPU is in a physical addressing mode, then Address i= s a + physical address. If the CPU is in a virtual addressing = mode, + then Address is a virtual address. + @param Length The number of bytes to invalidate from the data cache. + + @return Address. + +**/ +VOID * +EFIAPI +InvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + EMU_CACHE_THUNK_PROTOCOL *EmuCache; + EFI_STATUS Status; + + Status =3D DxeGetCacheThunkProtocol (&EmuCache); + if (!EFI_ERROR (Status) && EmuCache !=3D NULL) { + return EmuCache->InvalidateDataCacheRange (Address, Length); + } + return NULL; +} diff --git a/EmulatorPkg/Library/DxeEmuCacheMaintenanceLib/DxeEmuCacheMaint= enanceLib.inf b/EmulatorPkg/Library/DxeEmuCacheMaintenanceLib/DxeEmuCacheMa= intenanceLib.inf new file mode 100644 index 0000000000..e71fa218d5 --- /dev/null +++ b/EmulatorPkg/Library/DxeEmuCacheMaintenanceLib/DxeEmuCacheMaintenanceL= ib.inf @@ -0,0 +1,37 @@ +## @file +# Instance of Cache Maintenance Library using emulator thunks to OS sysca= lls +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D DxeEmuCacheMaintenanceLib + FILE_GUID =3D 4ee4f13e-3aab-4654-9af9-36e0fa53107f + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.1 + LIBRARY_CLASS =3D CacheMaintenanceLib|DXE_CORE DXE_DRIV= ER DXE_RUNTIME_DRIVER UEFI_DRIVER UEFI_APPLICATION + +# +# VALID_ARCHITECTURES =3D IA32 X64 ARM +# + +[Sources] + DxeEmuCacheMaintenanceLib.c + +[Packages] + MdePkg/MdePkg.dec + EmulatorPkg/EmulatorPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + BaseMemoryLib + HobLib + +[Protocols] + gEmuThunkProtocolGuid + gEmuCacheThunkProtocolGuid diff --git a/EmulatorPkg/Library/PeiEmuCacheMaintenanceLib/PeiEmuCacheMaint= enanceLib.c b/EmulatorPkg/Library/PeiEmuCacheMaintenanceLib/PeiEmuCacheMain= tenanceLib.c new file mode 100644 index 0000000000..0abf63cd21 --- /dev/null +++ b/EmulatorPkg/Library/PeiEmuCacheMaintenanceLib/PeiEmuCacheMaintenanceL= ib.c @@ -0,0 +1,344 @@ +/** @file + Instance of Cache Maintenance Library using emulator thunks to OS syscal= ls + + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +EFI_STATUS +EFIAPI +PeiGetCacheThunkProtocol ( + OUT EMU_CACHE_THUNK_PROTOCOL **EmuCache + ) +{ + EMU_THUNK_PPI *ThunkPpi; + EMU_THUNK_PROTOCOL *Thunk; + EMU_IO_THUNK_PROTOCOL *EmuIoThunk; + EFI_STATUS Status; + + // + // Locate Unix Thunk Ppi + // + Status =3D PeiServicesLocatePpi ( + &gEmuThunkPpiGuid, + 0, + NULL, + (VOID **)&ThunkPpi + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the Unix Thunk Protocol so we can retrieve I/O Thunk Protocols + // + Thunk =3D (EMU_THUNK_PROTOCOL *)ThunkPpi->Thunk (); + if (Thunk =3D=3D NULL) { + return EFI_NOT_FOUND; + } + + // + // Locate the I/O Thunk Protocol representing the Cache Thunk Protocol + // + for (Status =3D EFI_SUCCESS, EmuIoThunk =3D NULL; !EFI_ERROR (Status); )= { + Status =3D Thunk->GetNextProtocol (FALSE, &EmuIoThunk); + if (EFI_ERROR (Status)) { + break; + } + + if (EmuIoThunk->Instance =3D=3D 0) { + if (CompareGuid (EmuIoThunk->Protocol, &gEmuCacheThunkProtocolGuid))= { + // + // Open the I/O Thunk Protocol to retrieve the Cache Thunk Protocol + // + Status =3D EmuIoThunk->Open (EmuIoThunk); + if (EFI_ERROR (Status)) { + return Status; + } + *EmuCache =3D (EMU_CACHE_THUNK_PROTOCOL *) EmuIoThunk->Interface; + return EFI_SUCCESS; + } + } + } + + return EFI_NOT_FOUND; +} + +/** + Invalidates the entire instruction cache in cache coherency domain of the + calling CPU. + +**/ +VOID +EFIAPI +InvalidateInstructionCache ( + VOID + ) +{ + EMU_CACHE_THUNK_PROTOCOL *EmuCache; + EFI_STATUS Status; + + Status =3D PeiGetCacheThunkProtocol (&EmuCache); + if (!EFI_ERROR (Status) && EmuCache !=3D NULL) { + EmuCache->InvalidateInstructionCache (); + } +} + +/** + Invalidates a range of instruction cache lines in the cache coherency do= main + of the calling CPU. + + Invalidates the instruction cache lines specified by Address and Length.= If + Address is not aligned on a cache line boundary, then entire instruction + cache line containing Address is invalidated. If Address + Length is not + aligned on a cache line boundary, then the entire instruction cache line + containing Address + Length -1 is invalidated. This function may choose = to + invalidate the entire instruction cache if that is more efficient than + invalidating the specified range. If Length is 0, then no instruction ca= che + lines are invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the instruction cache lines to + invalidate. If the CPU is in a physical addressing mode,= then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + + @param Length The number of bytes to invalidate from the instruction c= ache. + + @return Address. + +**/ +VOID * +EFIAPI +InvalidateInstructionCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + EMU_CACHE_THUNK_PROTOCOL *EmuCache; + EFI_STATUS Status; + + Status =3D PeiGetCacheThunkProtocol (&EmuCache); + if (!EFI_ERROR (Status) && EmuCache !=3D NULL) { + return EmuCache->InvalidateInstructionCacheRange (Address, Length); + } + return NULL; +} + +/** + Writes Back and Invalidates the entire data cache in cache coherency dom= ain + of the calling CPU. + + Writes Back and Invalidates the entire data cache in cache coherency dom= ain + of the calling CPU. This function guarantees that all dirty cache lines = are + written back to system memory, and also invalidates all the data cache l= ines + in the cache coherency domain of the calling CPU. + +**/ +VOID +EFIAPI +WriteBackInvalidateDataCache ( + VOID + ) +{ + EMU_CACHE_THUNK_PROTOCOL *EmuCache; + EFI_STATUS Status; + + Status =3D PeiGetCacheThunkProtocol (&EmuCache); + if (!EFI_ERROR (Status) && EmuCache !=3D NULL) { + EmuCache->WriteBackInvalidateDataCache (); + } +} + +/** + Writes Back and Invalidates a range of data cache lines in the cache + coherency domain of the calling CPU. + + Writes Back and Invalidate the data cache lines specified by Address and + Length. If Address is not aligned on a cache line boundary, then entire = data + cache line containing Address is written back and invalidated. If Addres= s + + Length is not aligned on a cache line boundary, then the entire data cac= he + line containing Address + Length -1 is written back and invalidated. This + function may choose to write back and invalidate the entire data cache if + that is more efficient than writing back and invalidating the specified + range. If Length is 0, then no data cache lines are written back and + invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back a= nd + invalidate. If the CPU is in a physical addressing mode,= then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + @param Length The number of bytes to write back and invalidate from the + data cache. + + @return Address of cache invalidation. + +**/ +VOID * +EFIAPI +WriteBackInvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + EMU_CACHE_THUNK_PROTOCOL *EmuCache; + EFI_STATUS Status; + + Status =3D PeiGetCacheThunkProtocol (&EmuCache); + if (!EFI_ERROR (Status) && EmuCache !=3D NULL) { + return EmuCache->WriteBackInvalidateDataCacheRange (Address, Length); + } + return NULL; +} + +/** + Writes Back the entire data cache in cache coherency domain of the calli= ng + CPU. + + Writes Back the entire data cache in cache coherency domain of the calli= ng + CPU. This function guarantees that all dirty cache lines are written bac= k to + system memory. This function may also invalidate all the data cache line= s in + the cache coherency domain of the calling CPU. + +**/ +VOID +EFIAPI +WriteBackDataCache ( + VOID + ) +{ + EMU_CACHE_THUNK_PROTOCOL *EmuCache; + EFI_STATUS Status; + + Status =3D PeiGetCacheThunkProtocol (&EmuCache); + if (!EFI_ERROR (Status) && EmuCache !=3D NULL) { + EmuCache->WriteBackDataCache (); + } +} + +/** + Writes Back a range of data cache lines in the cache coherency domain of= the + calling CPU. + + Writes Back the data cache lines specified by Address and Length. If Add= ress + is not aligned on a cache line boundary, then entire data cache line + containing Address is written back. If Address + Length is not aligned o= n a + cache line boundary, then the entire data cache line containing Address + + Length -1 is written back. This function may choose to write back the en= tire + data cache if that is more efficient than writing back the specified ran= ge. + If Length is 0, then no data cache lines are written back. This function= may + also invalidate all the data cache lines in the specified range of the c= ache + coherency domain of the calling CPU. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back. = If + the CPU is in a physical addressing mode, then Address i= s a + physical address. If the CPU is in a virtual addressing + mode, then Address is a virtual address. + @param Length The number of bytes to write back from the data cache. + + @return Address of cache written in main memory. + +**/ +VOID * +EFIAPI +WriteBackDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + EMU_CACHE_THUNK_PROTOCOL *EmuCache; + EFI_STATUS Status; + + Status =3D PeiGetCacheThunkProtocol (&EmuCache); + if (!EFI_ERROR (Status) && EmuCache !=3D NULL) { + return EmuCache->WriteBackDataCacheRange (Address, Length); + } + return NULL; +} + +/** + Invalidates the entire data cache in cache coherency domain of the calli= ng + CPU. + + Invalidates the entire data cache in cache coherency domain of the calli= ng + CPU. This function must be used with care because dirty cache lines are = not + written back to system memory. It is typically used for cache diagnostic= s. If + the CPU does not support invalidation of the entire data cache, then a w= rite + back and invalidate operation should be performed on the entire data cac= he. + +**/ +VOID +EFIAPI +InvalidateDataCache ( + VOID + ) +{ + EMU_CACHE_THUNK_PROTOCOL *EmuCache; + EFI_STATUS Status; + + Status =3D PeiGetCacheThunkProtocol (&EmuCache); + if (!EFI_ERROR (Status) && EmuCache !=3D NULL) { + EmuCache->InvalidateDataCache (); + } +} + +/** + Invalidates a range of data cache lines in the cache coherency domain of= the + calling CPU. + + Invalidates the data cache lines specified by Address and Length. If Add= ress + is not aligned on a cache line boundary, then entire data cache line + containing Address is invalidated. If Address + Length is not aligned on= a + cache line boundary, then the entire data cache line containing Address + + Length -1 is invalidated. This function must never invalidate any cache = lines + outside the specified range. If Length is 0, the no data cache lines are + invalidated. Address is returned. This function must be used with care + because dirty cache lines are not written back to system memory. It is + typically used for cache diagnostics. If the CPU does not support + invalidation of a data cache range, then a write back and invalidate + operation should be performed on the data cache range. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to invalidate. = If + the CPU is in a physical addressing mode, then Address i= s a + physical address. If the CPU is in a virtual addressing = mode, + then Address is a virtual address. + @param Length The number of bytes to invalidate from the data cache. + + @return Address. + +**/ +VOID * +EFIAPI +InvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + EMU_CACHE_THUNK_PROTOCOL *EmuCache; + EFI_STATUS Status; + + Status =3D PeiGetCacheThunkProtocol (&EmuCache); + if (!EFI_ERROR (Status) && EmuCache !=3D NULL) { + return EmuCache->InvalidateDataCacheRange (Address, Length); + } + return NULL; +} diff --git a/EmulatorPkg/Library/PeiEmuCacheMaintenanceLib/PeiEmuCacheMaint= enanceLib.inf b/EmulatorPkg/Library/PeiEmuCacheMaintenanceLib/PeiEmuCacheMa= intenanceLib.inf new file mode 100644 index 0000000000..4e8b05e8a7 --- /dev/null +++ b/EmulatorPkg/Library/PeiEmuCacheMaintenanceLib/PeiEmuCacheMaintenanceL= ib.inf @@ -0,0 +1,39 @@ +## @file +# Instance of Cache Maintenance Library using emulator thunks to OS sysca= lls +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D PeiEmuCacheMaintenanceLib + FILE_GUID =3D 00b3e408-f999-4cf4-ba95-166678fc867c + MODULE_TYPE =3D PEIM + VERSION_STRING =3D 1.1 + LIBRARY_CLASS =3D CacheMaintenanceLib|PEI_CORE PEIM + +# +# VALID_ARCHITECTURES =3D IA32 X64 ARM +# + +[Sources] + PeiEmuCacheMaintenanceLib.c + +[Packages] + MdePkg/MdePkg.dec + EmulatorPkg/EmulatorPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + BaseMemoryLib + PeiServicesLib + +[Ppis] + gEmuThunkPpiGuid # PPI ALWAYS_CONSUMED + +[Protocols] + gEmuCacheThunkProtocolGuid diff --git a/EmulatorPkg/Unix/Host/CacheMaintenance.c b/EmulatorPkg/Unix/Ho= st/CacheMaintenance.c new file mode 100644 index 0000000000..13dccda9bb --- /dev/null +++ b/EmulatorPkg/Unix/Host/CacheMaintenance.c @@ -0,0 +1,284 @@ +/** @file + Invoke syscalls for cache maintenance on platforms that require kernel + mode to manage the instruction cache. ARM and RISC-V for example. + + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Host.h" + +extern UINTN gSystemMemoryCount; +extern EMU_SYSTEM_MEMORY *gSystemMemory; + +/** + Invalidates a range of instruction cache lines in the cache coherency do= main + of the calling CPU. + + Invalidates the instruction cache lines specified by Address and Length.= If + Address is not aligned on a cache line boundary, then entire instruction + cache line containing Address is invalidated. If Address + Length is not + aligned on a cache line boundary, then the entire instruction cache line + containing Address + Length -1 is invalidated. This function may choose = to + invalidate the entire instruction cache if that is more efficient than + invalidating the specified range. If Length is 0, then no instruction ca= che + lines are invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the instruction cache lines to + invalidate. If the CPU is in a physical addressing mode,= then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + + @param Length The number of bytes to invalidate from the instruction c= ache. + + @return Address. + +**/ +VOID * +EFIAPI +EmuInvalidateInstructionCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + __builtin___clear_cache ((char*)Address, ((char*)Address) + Length); + + return Address; +} + +/** + Invalidates the entire instruction cache in cache coherency domain of the + calling CPU. + +**/ +VOID +EFIAPI +EmuInvalidateInstructionCache ( + VOID + ) +{ + UINTN Index; + + if (gSystemMemory !=3D NULL) { + for (Index =3D 0; Index < gSystemMemoryCount; Index++) { + if (gSystemMemory[Index].Memory !=3D 0) { + EmuInvalidateInstructionCacheRange ((VOID *)(UINTN)gSystemMemory[I= ndex].Memory, gSystemMemory[Index].Size); + } + } + } +} + +/** + Writes Back and Invalidates the entire data cache in cache coherency dom= ain + of the calling CPU. + + Writes Back and Invalidates the entire data cache in cache coherency dom= ain + of the calling CPU. This function guarantees that all dirty cache lines = are + written back to system memory, and also invalidates all the data cache l= ines + in the cache coherency domain of the calling CPU. + +**/ +VOID +EFIAPI +EmuWriteBackInvalidateDataCache ( + VOID + ) +{ + EmuInvalidateInstructionCache (); +} + +/** + Writes Back and Invalidates a range of data cache lines in the cache + coherency domain of the calling CPU. + + Writes Back and Invalidate the data cache lines specified by Address and + Length. If Address is not aligned on a cache line boundary, then entire = data + cache line containing Address is written back and invalidated. If Addres= s + + Length is not aligned on a cache line boundary, then the entire data cac= he + line containing Address + Length -1 is written back and invalidated. This + function may choose to write back and invalidate the entire data cache if + that is more efficient than writing back and invalidating the specified + range. If Length is 0, then no data cache lines are written back and + invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back a= nd + invalidate. If the CPU is in a physical addressing mode,= then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + @param Length The number of bytes to write back and invalidate from the + data cache. + + @return Address of cache invalidation. + +**/ +VOID * +EFIAPI +EmuWriteBackInvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + return EmuInvalidateInstructionCacheRange (Address, Length); +} + +/** + Writes Back the entire data cache in cache coherency domain of the calli= ng + CPU. + + Writes Back the entire data cache in cache coherency domain of the calli= ng + CPU. This function guarantees that all dirty cache lines are written bac= k to + system memory. This function may also invalidate all the data cache line= s in + the cache coherency domain of the calling CPU. + +**/ +VOID +EFIAPI +EmuWriteBackDataCache ( + VOID + ) +{ + EmuWriteBackInvalidateDataCache (); +} + +/** + Writes Back a range of data cache lines in the cache coherency domain of= the + calling CPU. + + Writes Back the data cache lines specified by Address and Length. If Add= ress + is not aligned on a cache line boundary, then entire data cache line + containing Address is written back. If Address + Length is not aligned o= n a + cache line boundary, then the entire data cache line containing Address + + Length -1 is written back. This function may choose to write back the en= tire + data cache if that is more efficient than writing back the specified ran= ge. + If Length is 0, then no data cache lines are written back. This function= may + also invalidate all the data cache lines in the specified range of the c= ache + coherency domain of the calling CPU. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back. = If + the CPU is in a physical addressing mode, then Address i= s a + physical address. If the CPU is in a virtual addressing + mode, then Address is a virtual address. + @param Length The number of bytes to write back from the data cache. + + @return Address of cache written in main memory. + +**/ +VOID * +EFIAPI +EmuWriteBackDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + return EmuWriteBackInvalidateDataCacheRange (Address, Length); +} + +/** + Invalidates the entire data cache in cache coherency domain of the calli= ng + CPU. + + Invalidates the entire data cache in cache coherency domain of the calli= ng + CPU. This function must be used with care because dirty cache lines are = not + written back to system memory. It is typically used for cache diagnostic= s. If + the CPU does not support invalidation of the entire data cache, then a w= rite + back and invalidate operation should be performed on the entire data cac= he. + +**/ +VOID +EFIAPI +EmuInvalidateDataCache ( + VOID + ) +{ + EmuWriteBackInvalidateDataCache (); +} + +/** + Invalidates a range of data cache lines in the cache coherency domain of= the + calling CPU. + + Invalidates the data cache lines specified by Address and Length. If Add= ress + is not aligned on a cache line boundary, then entire data cache line + containing Address is invalidated. If Address + Length is not aligned on= a + cache line boundary, then the entire data cache line containing Address + + Length -1 is invalidated. This function must never invalidate any cache = lines + outside the specified range. If Length is 0, the no data cache lines are + invalidated. Address is returned. This function must be used with care + because dirty cache lines are not written back to system memory. It is + typically used for cache diagnostics. If the CPU does not support + invalidation of a data cache range, then a write back and invalidate + operation should be performed on the data cache range. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to invalidate. = If + the CPU is in a physical addressing mode, then Address i= s a + physical address. If the CPU is in a virtual addressing = mode, + then Address is a virtual address. + @param Length The number of bytes to invalidate from the data cache. + + @return Address. + +**/ +VOID * +EFIAPI +EmuInvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + return EmuWriteBackInvalidateDataCacheRange (Address, Length); +} + +EMU_CACHE_THUNK_PROTOCOL gEmuCacheThunk =3D { + EmuInvalidateInstructionCache, + EmuInvalidateInstructionCacheRange, + EmuWriteBackInvalidateDataCache, + EmuWriteBackInvalidateDataCacheRange, + EmuWriteBackDataCache, + EmuWriteBackDataCacheRange, + EmuInvalidateDataCache, + EmuInvalidateDataCacheRange +}; + +EFI_STATUS +EFIAPI +CacheOpen ( + IN EMU_IO_THUNK_PROTOCOL *This + ) +{ + if (This->Instance !=3D 0) { + // Only single instance is supported + return EFI_NOT_FOUND; + } + + This->Interface =3D &gEmuCacheThunk; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +CacheClose ( + IN EMU_IO_THUNK_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + +EMU_IO_THUNK_PROTOCOL gCacheThunkIo =3D { + &gEmuCacheThunkProtocolGuid, + NULL, + NULL, + 0, + CacheOpen, + CacheClose, + NULL +}; diff --git a/EmulatorPkg/Unix/Host/Host.c b/EmulatorPkg/Unix/Host/Host.c index 1f29dd00a3..06241c7127 100644 --- a/EmulatorPkg/Unix/Host/Host.c +++ b/EmulatorPkg/Unix/Host/Host.c @@ -1,6 +1,6 @@ /*++ @file =20 -Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.
Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent =20 @@ -165,6 +165,9 @@ main ( // Emulator other Thunks // AddThunkProtocol (&gPthreadThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuApCount),= FALSE); +#if defined (MDE_CPU_ARM) + AddThunkProtocol (&gCacheThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuCache), FAL= SE); +#endif =20 // EmuSecLibConstructor (); =20 diff --git a/EmulatorPkg/Unix/Host/Host.h b/EmulatorPkg/Unix/Host/Host.h index 0c81cdfc01..95d482d8d2 100644 --- a/EmulatorPkg/Unix/Host/Host.h +++ b/EmulatorPkg/Unix/Host/Host.h @@ -115,6 +115,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include =20 #include #include @@ -356,5 +357,6 @@ extern EMU_IO_THUNK_PROTOCOL gPosixFileSystemThunkIo; extern EMU_IO_THUNK_PROTOCOL gPthreadThunkIo; extern EMU_IO_THUNK_PROTOCOL gBlockIoThunkIo; extern EMU_IO_THUNK_PROTOCOL gSnpThunkIo; +extern EMU_IO_THUNK_PROTOCOL gCacheThunkIo; =20 #endif diff --git a/EmulatorPkg/Unix/Host/Host.inf b/EmulatorPkg/Unix/Host/Host.inf index effd0a3217..6cb6e12b00 100644 --- a/EmulatorPkg/Unix/Host/Host.inf +++ b/EmulatorPkg/Unix/Host/Host.inf @@ -80,6 +80,7 @@ gEmuThreadThunkProtocolGuid gEmuBlockIoProtocolGuid gEmuSnpProtocolGuid + gEmuCacheThunkProtocolGuid gEfiSimpleFileSystemProtocolGuid =20 [Guids] @@ -99,6 +100,7 @@ gEmulatorPkgTokenSpaceGuid.PcdEmuGop|L"GOP Window" gEmulatorPkgTokenSpaceGuid.PcdEmuFileSystem gEmulatorPkgTokenSpaceGuid.PcdEmuSerialPort + gEmulatorPkgTokenSpaceGuid.PcdEmuCache gEmulatorPkgTokenSpaceGuid.PcdEmuNetworkInterface gEmulatorPkgTokenSpaceGuid.PcdNetworkPacketFilterSize =20 --=20 2.30.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#100708): https://edk2.groups.io/g/devel/message/100708 Mute This Topic: https://groups.io/mt/97414912/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-