summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halalpha/cache.c
blob: c9d997f70162de30a86384f1d9cb2a4279ae6454 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/*++

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);
}