226 lines
6.1 KiB
C
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);
|
|
}
|
|
|