[NTOSKRNL:CC] Implement Extarnal Cache Directives
Implemented:: CcDeductDirtyPagesFromExternalCache CcAddDirtyPagesToExternalCache:: Exported CcAddExternalCache CcRegisterExternalCache:: Exported CcRemoveExternalCache CcUnregisterExternalCache :: Exported
This commit is contained in:
		
				
					committed by
					
						 CodingWorkshop Signing Team
						CodingWorkshop Signing Team
					
				
			
			
				
	
				
						parent
						
							d0d6097d57
						
					
				
				
					commit
					08d017171d
				
			
							
								
								
									
										210
									
								
								NTOSKRNL/CC/ccexternalcache.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								NTOSKRNL/CC/ccexternalcache.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,210 @@ | ||||
| /* | ||||
|  * PROJECT: Alcyone System Kernel | ||||
|  * LICENSE: BSD Clause 3 | ||||
|  * PURPOSE: Cache Controller:: External Cache Compatibility Layer  | ||||
|  * NT KERNEL: 5.11.9360 | ||||
|  * COPYRIGHT:  2023-2029 Dibymartanda Samanta <> | ||||
|  */  | ||||
|  | ||||
|  NOTE::Alcyone will not notify,in case of Empty External Cache at the moment, feature is planned for threadpool revamp | ||||
|  | ||||
| /* Move Typedef later cctypes.hpp */ | ||||
| typedef struct alignas(24) _DIRTY_PAGE_STATISTICS { | ||||
|     ULONGLONG DirtyPages;                                                   // 0x0 | ||||
|     ULONGLONG DirtyPagesLastScan;                                           // 0x8 | ||||
|     ULONG DirtyPagesScheduledLastScan;                                      // 0x10 | ||||
| } DIRTY_PAGE_STATISTICS, *PDIRTY_PAGE_STATISTICS;                           // 0x18 bytes (sizeof) | ||||
|  | ||||
| typedef struct alignas(30) _CC_EXTERNAL_CACHE_INFO { | ||||
|     VOID (*Callback)(VOID* arg1, ULONGLONG arg2, ULONG arg3);               // 0x0 | ||||
|     struct _DIRTY_PAGE_STATISTICS DirtyPageStatistics;                      // 0x8 | ||||
|     struct _LIST_ENTRY Links;                                               // 0x20 | ||||
| } CC_EXTERNAL_CACHE_INFO, *PCC_EXTERNAL_CACHE_INFO;                         // 0x30 bytes (sizeof) | ||||
|  | ||||
| VOID | ||||
| NTAPI | ||||
| CcDeductDirtyPagesFromExternalCache( | ||||
|     IN PCC_EXTERNAL_CACHE_INFO ExternalCacheContext, | ||||
|     IN ULONG Pages | ||||
|     ) | ||||
| { | ||||
|     KIRQL OldIrql ={0}; | ||||
|     ULONG PagesToDeduct = {0};  | ||||
|  | ||||
|  | ||||
|     if (Pages > 0) | ||||
|     { | ||||
|         /* Acquire the master lock */ | ||||
|         KeAcquireQueuedSpinLock(LockQueueMasterLock, &OldIrql); | ||||
|  | ||||
|         /* Calculate the number of pages to deduct */ | ||||
|         PagesToDeduct = min(Pages, ExternalCacheContext->DirtyPageStatistics.DirtyPages); | ||||
|  | ||||
|         /* Deduct the pages from the external cache context */ | ||||
|         ExternalCacheContext->DirtyPageStatistics.DirtyPages -= PagesToDeduct; | ||||
|           | ||||
|         /* Deduct the pages from the global statistics */ | ||||
|          CcTotalDirtyPages -= PagesToDeduct; | ||||
|  | ||||
|         /* Release the master lock */ | ||||
|         KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); | ||||
|     } | ||||
|  | ||||
|     /* Check if there are any deferred writes and post them if necessary */ | ||||
|     if (!IsListEmpty(&CcDeferredWrites)) | ||||
|     { | ||||
|         CcPostDeferredWrites(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| VOID | ||||
| NTAPI | ||||
| CcAddExternalCache( | ||||
|     IN PCC_EXTERNAL_CACHE_INFO CacheInfo | ||||
|     ) | ||||
| { | ||||
|      | ||||
|      | ||||
|     KLOCK_QUEUE_HANDLE LockHandle ={0}; | ||||
|  | ||||
|     /* Acquire the external cache list lock */ | ||||
|     KeAcquireInStackQueuedSpinLock(&CcExternalCacheListLock,&LockHandle); | ||||
|  | ||||
|     /* Insert the new cache info at the end of the list */ | ||||
|     InsertTailList(&CcExternalCacheList, &CacheInfo->Links); | ||||
|  | ||||
|     /* Increment the number of external caches */ | ||||
|     if (_InterlockedIncrement(&CcNumberOfExternalCaches) <= 0) | ||||
|     { | ||||
|         /* Overflow occurred, bug check */ | ||||
|         KeBugCheckEx(CACHE_MANAGER,0,STATUS_INTEGER_OVERFLOW,0,0); | ||||
|     } | ||||
|  | ||||
|     /* Release the external cache list lock */ | ||||
|     KeReleaseInStackQueuedSpinLock(&LockHandle); | ||||
| } | ||||
|  | ||||
| VOID | ||||
| NTAPI | ||||
| CcRemoveExternalCache( | ||||
|     IN PCC_EXTERNAL_CACHE_INFO CacheInfo | ||||
|     ) | ||||
| { | ||||
|      | ||||
|  | ||||
|  | ||||
|     KLOCK_QUEUE_HANDLE LockHandle ={0}; | ||||
|  | ||||
|     /* Acquire the external cache list lock */ | ||||
|     KeAcquireInStackQueuedSpinLock(&CcExternalCacheListLock,&LockHandle); | ||||
|   | ||||
|     /* Remove the entry from the list */ | ||||
|     RemoveTailList(&CacheInfo->Links.Blink); | ||||
|  | ||||
|     /* Decrement the number of external caches */ | ||||
|     if (_InterlockedDecrement(&CcNumberOfExternalCaches) < 0) | ||||
|     { | ||||
|         /* Underflow occurred, bug check */ | ||||
|         KeBugCheckEx(CACHE_MANAGER,0,STATUS_INTEGER_OVERFLOW,0,0); | ||||
|     } | ||||
|  | ||||
|     /* Release the external cache list lock */ | ||||
|     KeReleaseInStackQueuedSpinLock(&LockHandle); | ||||
| } | ||||
|  | ||||
|  | ||||
| /*Exported */ | ||||
| VOID | ||||
| NTAPI | ||||
| CcAddDirtyPagesToExternalCache( | ||||
|     IN PCC_EXTERNAL_CACHE_INFO ExternalCacheContext, | ||||
|     IN ULONG Pages | ||||
|     ) | ||||
| { | ||||
|     KIRQL OldIrql ={0}; | ||||
|  | ||||
|  | ||||
|     /* Only proceed if there are pages to add */ | ||||
|     if (Pages == 0) | ||||
|     { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     /* Acquire the master lock */ | ||||
|     KeAcquireQueuedSpinLock(LockQueueMasterLock, &OldIrql); | ||||
|  | ||||
|     /* If this is the first dirty page, schedule a lazy write scan */ | ||||
|     if (ExternalCacheContext->DirtyPageStatistics.DirtyPages == 0) | ||||
|     { | ||||
|         CcScheduleLazyWriteScan(FALSE, NULL); | ||||
|     } | ||||
|  | ||||
|     /* Increment the dirty page count */ | ||||
|     ExternalCacheContext->DirtyPageStatistics.DirtyPages += Pages; | ||||
|  | ||||
|     /* Charge the dirty pages */ | ||||
|     CcChargeDirtyPages(NULL, NULL, NULL, Pages); | ||||
|  | ||||
|     /* Release the master lock */ | ||||
|     KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); | ||||
| } | ||||
|  | ||||
| VOID | ||||
| NTAPI | ||||
| CcUnregisterExternalCache( | ||||
|     IN PCC_EXTERNAL_CACHE_INFO ExternalCacheContext | ||||
|     ) | ||||
| { | ||||
|     | ||||
|  | ||||
|     /* Remove the external cache from the list */ | ||||
|     CcRemoveExternalCache(ExternalCacheContext); | ||||
|  | ||||
|     /* Deduct any remaining dirty pages */ | ||||
|     if (ExternalCacheContext->DirtyPageStatistics.DirtyPages > 0) | ||||
|     { | ||||
|         CcDeductDirtyPagesFromExternalCache(ExternalCacheContext,ExternalCacheContext->DirtyPageStatistics.DirtyPages); | ||||
|     } | ||||
|  | ||||
|     /* Free the external cache context */ | ||||
|     ExFreePoolWithTag(ExternalCacheContext, CC_EXTERNAL_CACHE_INFO_TAG); | ||||
| } | ||||
|  | ||||
| NTSTATUS | ||||
| NTAPI | ||||
| CcRegisterExternalCache( | ||||
|     IN PCC_EXTERNAL_CACHE_CALLBACK Callback, | ||||
|     OUT PVOID *ExternalCacheContext | ||||
|     ) | ||||
| { | ||||
|     NTSTATUS Status = STATUS_SUCCESS; | ||||
|     PCC_EXTERNAL_CACHE_INFO CacheInfo; | ||||
|  | ||||
|  | ||||
|     /* Ensure the Cache Manager is initialized */ | ||||
|     if (!CcInitializationComplete) | ||||
|     { | ||||
|         KeBugCheckEx(CACHE_MANAGER,0,STATUS_UNSUCCESSFUL,0,0); | ||||
|     } | ||||
|  | ||||
|     /* Allocate memory for the external cache info structure */ | ||||
|     CacheInfo = ExAllocatePoolWithTag(NonPagedPool, | ||||
|                                       sizeof(CC_EXTERNAL_CACHE_INFO), | ||||
|                                       CC_EXTERNAL_CACHE_INFO_TAG); | ||||
|     if (CacheInfo == NULL) | ||||
|     { | ||||
|         return STATUS_INSUFFICIENT_RESOURCES; | ||||
|     } | ||||
|  | ||||
|     /* Initialize the cache info structure */ | ||||
|     RtlZeroMemory(CacheInfo, sizeof(CC_EXTERNAL_CACHE_INFO)); | ||||
|     CacheInfo->Callback = Callback; | ||||
|  | ||||
|     /* Add the external cache to the list */ | ||||
|     CcAddExternalCache(CacheInfo); | ||||
|  | ||||
|     /* Return the cache info as the context */ | ||||
|     *ExternalCacheContext = CacheInfo; | ||||
|  | ||||
|     return Status; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user