NT4/private/ntos/nthals/halalpha/cache.c
2020-09-30 17:12:29 +02:00

226 lines
6.1 KiB
C

/*++
Copyright (c) 1996 Digital Equipment Corporation
Module Name:
cache.c
Abstract:
Provides routine to compute the backup cache size
Author:
Bala Nagarajan 5-Jan-1996
Adopted from Mark Baxter's user level code.
Environment:
Phase 0 initialization only
Also Called from the firmware.
--*/
#include "halp.h"
#define __1KB (1024)
#define __128KB (128 * 1024)
#define THRESHOLD_RPCC_PERCENT 120 // percent value
static
ULONG
HalpTimeTheBufferAccess(
PUCHAR DataBuffer,
ULONG NumberOfAccess,
ULONG CacheSizeLimit,
ULONG CacheStride
)
/*++
Routine Description :
This function times the main loop that the HalpGetBCacheSize uses.
This is a separate function because we want to time the
access accurately with exactly one load in the loop.
Arguments:
DataBuffer - Start address of the buffer.
NumberOfAccess - Total Nubmer of Access that needs to be made
CacheSizeLimit - The Current Cache size that is being checked
CacheStride - The stride value to access the buffer.
Return Value:
The time taken to access the buffer with specified number of access.
--*/
{
ULONG MemoryLocation;
ULONG CacheSizeMask;
ULONG startRpcc;
ULONG endRpcc;
for(MemoryLocation = 0; MemoryLocation < CacheSizeLimit ;
MemoryLocation += CacheStride){
*(volatile ULONG * const)(&DataBuffer[MemoryLocation]) ;
}
CacheSizeMask = CacheSizeLimit - 1;
startRpcc = __RCC();
for ( MemoryLocation = 0;
NumberOfAccess > 0;
NumberOfAccess--, MemoryLocation += CacheStride) {
*(volatile LONG *)&(DataBuffer[MemoryLocation & CacheSizeMask] );
}
endRpcc = __RCC();
return (endRpcc - startRpcc);
}
ULONG
HalpGetBCacheSize(
ULONGLONG ContiguousPhysicalMemorySize
)
/*++
Routine Description:
This function computes the size of the direct mapped backup cache.
This code checks for cache sizes from 128KB to the physical memory
size in steps of multiple of 2. In systems that has no cache or cache
larger than physical memory (!!) this algorithm will report the cache
size to be Zero. Since the cache size
is now being used only for the Secondary Page Coloring mechanism, and
since page coloring mechanism does not make any sense in a machine
without a direct mapped backup cache, the size of the cache does not
really affect system performance in any way.
[Note: Page Coloring Mechanism is used to reduce cache conflicts
between adjacent pages of a process in a direct mapped backup cache.]
In case where the cache is larger than memory itself (!!!! How often
have you encountered such a machine??), I think the entire page
coloring mechanism can break. Because you now have more colors
than total number of pages, meaning, there are some colors which
has no pages.
Arguments:
ContiguousPhysicalMemorySize - The size of the physical memory.
Return Value:
The size of the Backup cache in Bytes.
--*/
{
ULONG CacheSizeLimit = 128*__1KB;
ULONG NumberOfAccess;
ULONG CacheStride = 32*__1KB ;
ULONG CacheSize;
ULONG BaseLineElapsedRpcc;
ULONG ThresholdRpcc;
ULONG CurSizeElapsedRpcc;
PUCHAR DataBuffer;
//
// Set DataBuffer to point to KSEG0
//
DataBuffer = (PUCHAR) KSEG0_BASE;
//
// Compute the number of access we will make for each buffer
// size. Assume that for the largest buffer size we will make
// only one pass.
// NOTE: hopefully the division will limit the number of access to
// within a ULONG.
//
NumberOfAccess = (ULONG)(ContiguousPhysicalMemorySize/CacheStride);
#if DBG
DbgPrint("HalpGetBCacheSize: Memory Size = %lu Bytes, "
"Number of Access = %lu\n",
ContiguousPhysicalMemorySize, NumberOfAccess);
#endif
//
// Compute the baseline Rpcc.
// We touch only every cachestride(32KB) memory locations.
// We do this because we want to make sure that the entire set
// of the 3-way set associative on chip 96KB secondary cache gets
// filled in. This also means that we need to make the lower limit
// on the Bcache to be something greater than the OnChip
// secondary cache.
// First we touch all the locations to bring them into the
// cache before computing the baseline
//
BaseLineElapsedRpcc = HalpTimeTheBufferAccess(DataBuffer,
NumberOfAccess,
CacheSizeLimit, CacheStride);
//
// Compute the threshold Rpcc to equal to 120% of the baseline
// Rpcc
//
ThresholdRpcc = (BaseLineElapsedRpcc * THRESHOLD_RPCC_PERCENT) / 100;
while(CacheSizeLimit <= ContiguousPhysicalMemorySize){
CurSizeElapsedRpcc = HalpTimeTheBufferAccess(DataBuffer, NumberOfAccess,
CacheSizeLimit, CacheStride);
#if DBG
DbgPrint("HalpGetBCacheSize: Size = %3ld%s"
" ElapsedRpcc = %7lu Threshold = %7lu\n",
(( CacheSizeLimit < __1MB) ?
( CacheSizeLimit/__1KB) :
( CacheSizeLimit /__1MB) ),
(( CacheSizeLimit < __1MB) ?
"KB" : "MB" ),
CurSizeElapsedRpcc,
ThresholdRpcc
);
#endif
//
// if the current elapsed Rpcc is greater than threshold rpcc
//
if(CurSizeElapsedRpcc > ThresholdRpcc ){
break;
}
CacheSize = CacheSizeLimit;
CacheSizeLimit *= 2;
}
//
// In the following case the chance that this is a cacheless machine
// is very high, so we will return CacheSize to be Zero.
//
if(CacheSizeLimit >= ContiguousPhysicalMemorySize)
CacheSize = 0;
#if DBG
DbgPrint("HalpGetBCacheSize: Cache Size = %lu Bytes\n",
CacheSize);
#endif
//
// return cache size in number of bytes.
//
return (CacheSize);
}