1 /*==============================================================================
2 Copyright(c) 2017 Intel Corporation
3 
4 Permission is hereby granted, free of charge, to any person obtaining a
5 copy of this software and associated documentation files(the "Software"),
6 to deal in the Software without restriction, including without limitation
7 the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 and / or sell copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following conditions:
10 
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
21 ============================================================================*/
22 
23 #include "Internal/Common/GmmLibInc.h"
24 #include "External/Common/GmmCachePolicy.h"
25 
26 //=============================================================================
27 //
28 // Function: __GmmGen9InitCachePolicy
29 //
30 // Desc: This function initializes the cache policy
31 //
32 // Parameters: pCachePolicy  -> Ptr to array to be populated with the
33 //             mapping of usages -> cache settings.
34 //
35 // Return: GMM_STATUS
36 //
37 //-----------------------------------------------------------------------------
InitCachePolicy()38 GMM_STATUS GmmLib::GmmGen9CachePolicy::InitCachePolicy()
39 {
40     __GMM_ASSERTPTR(pCachePolicy, GMM_ERROR);
41 
42 #if defined(GMM_DYNAMIC_MOCS_TABLE)
43 #define DEFINE_CACHE_ELEMENT(usage, llc, ellc, l3, age, i915) DEFINE_CP_ELEMENT(usage, llc, ellc, l3, 0, age, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
44 #else
45 // i915 only supports three GEN9 MOCS entires:
46 //     MOCS[0]...LLC=0, ELLC=0, L3=0, AGE=0
47 //     MOCS[1]...<N/A for GmmLib Purposes>
48 //     MOCS[2]...LLC=1, ELLC=1, L3=1, AGE=3
49 #define DEFINE_CACHE_ELEMENT(usage, llc, ellc, l3, age, i915)                           \
50     do                                                                                  \
51     {                                                                                   \
52         if((i915) == 0)                                                                 \
53         {                                                                               \
54             DEFINE_CP_ELEMENT(usage, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);\
55         }                                                                               \
56         else if((i915) == 2)                                                            \
57         {                                                                               \
58             DEFINE_CP_ELEMENT(usage, 1, 1, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);\
59         }                                                                               \
60         else                                                                            \
61         {                                                                               \
62             GMM_ASSERTDPF(0, "Invalid i915 MOCS specified");                            \
63         }                                                                               \
64     } while(0) ////////////////////////////////////////////////////////////////
65 #endif
66 #include "GmmGen9CachePolicy.h"
67 
68 #define TC_LLC (1)
69 #define TC_ELLC (0)
70 #define TC_LLC_ELLC (2)
71 
72 #define LeCC_UNCACHEABLE (0x1)
73 #define LeCC_WB_CACHEABLE (0x3)
74 
75 #define L3_UNCACHEABLE (0x1)
76 #define L3_WB_CACHEABLE (0x3)
77 
78 #define DISABLE_SKIP_CACHING_CONTROL (0x0)
79 #define ENABLE_SKIP_CACHING_CONTROL (0x1)
80 
81     {
82         uint32_t                      CurrentMaxIndex        = 0;
83         GMM_CACHE_POLICY_TBL_ELEMENT *pCachePolicyTblElement = pGmmLibContext->GetCachePolicyTlbElement();
84 
85         bool LLC = (pGmmLibContext->GetGtSysInfo()->LLCCacheSizeInKb > 0); // aka "Core -vs- Atom".
86 
87 #if defined(_WIN32)
88         {
89             pCachePolicyTblElement[0].L3.Cacheability   = L3_UNCACHEABLE;
90             pCachePolicyTblElement[0].LeCC.Cacheability = LeCC_UNCACHEABLE;
91             pCachePolicyTblElement[0].LeCC.TargetCache  = LLC ? TC_LLC_ELLC : TC_ELLC; // No LLC for Broxton, GLK - keep clear configuration for LLC
92         }
93 #else
94         {
95 #define I915_GEN9_MOCS_ENTRIES 3
96             GMM_CACHE_POLICY_TBL_ELEMENT *pEntry = pCachePolicyTblElement;
97             C_ASSERT(I915_GEN9_MOCS_ENTRIES <= GMM_GEN9_MAX_NUMBER_MOCS_INDEXES);
98 
99             // I915_MOCS_UNCACHED(0)...
100             pEntry[0].L3.Cacheability   = L3_UNCACHEABLE;
101             pEntry[0].LeCC.Cacheability = LeCC_UNCACHEABLE;
102             pEntry[0].LeCC.TargetCache  = TC_LLC_ELLC;
103 
104             // I915_MOCS_PTE(1)...
105             pEntry[1] = pEntry[0]; // Unused by GmmLib clients, so set to UC.
106             CurrentMaxIndex++;
107 
108             // I915_MOCS_CACHED(2)...
109             pEntry[2].L3.Cacheability   = L3_WB_CACHEABLE;
110             pEntry[2].LeCC.Cacheability = LLC ? LeCC_WB_CACHEABLE : LeCC_UNCACHEABLE;
111             pEntry[2].LeCC.TargetCache  = TC_LLC_ELLC;
112             pEntry[2].LeCC.LRUM         = 3;
113             CurrentMaxIndex++;
114         }
115 #endif
116 
117         // Process the cache policy and fill in the look up table
118         for(uint32_t Usage = 0; Usage < GMM_RESOURCE_USAGE_MAX; Usage++)
119         {
120             bool                         CachePolicyError = false;
121             uint64_t                     PTEValue         = 0;
122             int32_t                      CPTblIdx         = -1;
123             uint32_t                     j                = 0;
124             GMM_CACHE_POLICY_TBL_ELEMENT UsageEle         = {0};
125             UsageEle.LeCC.Reserved                        = 0; // Reserved bits zeroe'd, this is so we
126                                                                // we can compare the unioned LeCC.DwordValue.
127             UsageEle.LeCC.SCF = pCachePolicy[Usage].SCF;
128             UsageEle.LeCC.PFM = 0; // TODO: decide what the page faulting mode should be
129             UsageEle.LeCC.SCC = 0;
130             UsageEle.LeCC.ESC = 0;
131             if(pCachePolicy[Usage].LeCC_SCC)
132             {
133                 UsageEle.LeCC.SCC = pCachePolicy[Usage].LeCC_SCC;
134                 UsageEle.LeCC.ESC = ENABLE_SKIP_CACHING_CONTROL;
135             }
136             UsageEle.LeCC.AOM  = pCachePolicy[Usage].AOM;
137             UsageEle.LeCC.LRUM = pCachePolicy[Usage].AGE;
138 
139             // default to LLC/ELLC target cache.
140             UsageEle.LeCC.TargetCache  = TC_LLC_ELLC;
141             UsageEle.LeCC.Cacheability = LeCC_WB_CACHEABLE;
142 
143             if(pGmmLibContext->GetPlatformInfo().Platform.eProductFamily == IGFX_BROXTON ||
144                pGmmLibContext->GetPlatformInfo().Platform.eProductFamily == IGFX_GEMINILAKE)
145             {
146                 UsageEle.LeCC.AOM          = 0;
147                 UsageEle.LeCC.Cacheability = LeCC_UNCACHEABLE; // To avoid side effects use 01b even though 01b(UC) 11b(WB) are equivalent option
148 
149 #if defined(GMM_DYNAMIC_MOCS_TABLE)
150                 UsageEle.LeCC.TargetCache = TC_LLC; // No LLC for Broxton, but we still set it to LLC since it is needed for IA coherency cases
151                 UsageEle.LeCC.LRUM         = 0;
152 #else
153                 UsageEle.LeCC.TargetCache = TC_LLC_ELLC; // To match I915_GEN9_MOCS[0]
154 #endif
155             }
156             else
157             {
158                 if(pCachePolicy[Usage].LLC && pCachePolicy[Usage].ELLC)
159                 {
160                     UsageEle.LeCC.TargetCache = TC_LLC_ELLC;
161                 }
162                 else if(pCachePolicy[Usage].LLC)
163                 {
164                     UsageEle.LeCC.TargetCache = TC_LLC;
165                 }
166                 else if(pCachePolicy[Usage].ELLC)
167                 {
168                     UsageEle.LeCC.TargetCache = TC_ELLC;
169                 }
170                 else
171                 {
172                     UsageEle.LeCC.Cacheability = LeCC_UNCACHEABLE;
173                 }
174             }
175 
176             UsageEle.L3.Reserved = 0; // Reserved bits zeroe'd, this is so we
177                                       // we can compare the unioned L3.UshortValue.
178             UsageEle.L3.ESC          = DISABLE_SKIP_CACHING_CONTROL;
179             UsageEle.L3.SCC          = 0;
180             UsageEle.L3.Cacheability = pCachePolicy[Usage].L3 ? L3_WB_CACHEABLE : L3_UNCACHEABLE;
181             if(pCachePolicy[Usage].L3_SCC)
182             {
183                 UsageEle.L3.ESC = ENABLE_SKIP_CACHING_CONTROL;
184                 UsageEle.L3.SCC = (uint16_t)pCachePolicy[Usage].L3_SCC;
185             }
186             for(j = 0; j <= CurrentMaxIndex; j++)
187             {
188                 GMM_CACHE_POLICY_TBL_ELEMENT *TblEle = &pCachePolicyTblElement[j];
189                 if(TblEle->LeCC.DwordValue == UsageEle.LeCC.DwordValue &&
190                    TblEle->L3.UshortValue == UsageEle.L3.UshortValue)
191                 {
192                     CPTblIdx = j;
193                     break;
194                 }
195             }
196 
197             // Didn't find the caching settings in one of the already programmed lookup table entries.
198             // Need to add a new lookup table entry.
199             if(CPTblIdx == -1)
200             {
201                 if(CurrentMaxIndex < GMM_GEN9_MAX_NUMBER_MOCS_INDEXES - 1)
202                 {
203                     GMM_CACHE_POLICY_TBL_ELEMENT *TblEle = &(pCachePolicyTblElement[++CurrentMaxIndex]);
204                     CPTblIdx                             = CurrentMaxIndex;
205 
206                     TblEle->LeCC.DwordValue = UsageEle.LeCC.DwordValue;
207                     TblEle->L3.UshortValue  = UsageEle.L3.UshortValue;
208                 }
209                 else
210                 {
211                     // Too many unique caching combinations to program the
212                     // MOCS lookup table.
213                     CachePolicyError = true;
214                     GMM_ASSERTDPF(
215                     "Cache Policy Init Error: Invalid Cache Programming, too many unique caching combinations"
216                     "(we only support GMM_GEN_MAX_NUMBER_MOCS_INDEXES = %d)",
217                     GMM_GEN9_MAX_NUMBER_MOCS_INDEXES);
218                     // Set cache policy index to uncached.
219                     CPTblIdx = 0;
220                 }
221             }
222 
223             if(!GetUsagePTEValue(pCachePolicy[Usage], Usage, &PTEValue))
224             {
225                 CachePolicyError = true;
226             }
227 
228             pCachePolicy[Usage].PTE.DwordValue     = PTEValue & 0xFFFFFFFF;
229             pCachePolicy[Usage].PTE.HighDwordValue = 0;
230             pCachePolicy[Usage].MemoryObjectOverride.Gen9.Index = CPTblIdx;
231 
232             pCachePolicy[Usage].Override = ALWAYS_OVERRIDE;
233 
234             if(CachePolicyError)
235             {
236                 GMM_ASSERTDPF("Cache Policy Init Error: Invalid Cache Programming - Element %d", Usage);
237             }
238         }
239         CurrentMaxMocsIndex      = CurrentMaxIndex;
240         CurrentMaxL1HdcMocsIndex = 0;
241     }
242 
243     return GMM_SUCCESS;
244 }
245 
246 /////////////////////////////////////////////////////////////////////////////////////
247 ///  Initializes the Gfx PAT tables for AdvCtx and Gfx MMIO/Private PAT
248 ///    PAT0 = WB_COHERENT or UC depending on WaGttPat0WB
249 ///    PAT1 = UC or WB_COHERENT depending on WaGttPat0WB
250 ///    PAT2 = WB_MOCSLESS, with TC = eLLC+LLC
251 ///    PAT3 = WB
252 ///    PAT4 = WT
253 ///    PAT5 = WC
254 ///    PAT6 = WC
255 ///    PAT7 = WC
256 ///  HLD says to set to PAT0/1 to WC, but since we don't have a WC in GPU,
257 ///  WC option is same as UC. Hence setting PAT0 or PAT1 to UC.
258 ///  Unused PAT's (5,6,7) are set to WC.
259 ///
260 /// @return        GMM_STATUS
261 /////////////////////////////////////////////////////////////////////////////////////
SetupPAT()262 GMM_STATUS GmmLib::GmmGen9CachePolicy::SetupPAT()
263 {
264     GMM_STATUS Status = GMM_SUCCESS;
265 #if(defined(__GMM_KMD__))
266     uint32_t i = 0;
267 
268     GMM_GFX_MEMORY_TYPE GfxMemType = GMM_GFX_UC_WITH_FENCE;
269     // No optional selection on Age or Target Cache because for an SVM-OS Age and
270     // Target Cache would not work [for an SVM-OS the Page Table is shared with IA
271     // and we don't have control of the PAT Idx]. If there is a strong ask from D3D
272     // or the performance analysis team, Age could be added.
273     // Add Class of Service when required.
274     GMM_GFX_TARGET_CACHE GfxTargetCache             = GMM_GFX_TC_ELLC_LLC;
275     uint8_t              Age                        = 1;
276     uint8_t              ServiceClass               = 0;
277     int32_t *            pPrivatePATTableMemoryType = NULL;
278 
279     pPrivatePATTableMemoryType = pGmmLibContext->GetPrivatePATTableMemoryType();
280 
281     __GMM_ASSERT(pGmmLibContext->GetSkuTable().FtrIA32eGfxPTEs);
282 
283     for(i = 0; i < GMM_NUM_GFX_PAT_TYPES; i++)
284     {
285         pPrivatePATTableMemoryType[i] = -1;
286     }
287 
288     // Set values for GmmGlobalInfo PrivatePATTable
289     for(i = 0; i < GMM_NUM_PAT_ENTRIES; i++)
290     {
291         GMM_PRIVATE_PAT PAT = {0};
292 
293         if(pGmmLibContext->GetSkuTable().FtrMemTypeMocsDeferPAT)
294         {
295             GfxTargetCache = GMM_GFX_TC_ELLC_ONLY;
296         }
297         else
298         {
299             GfxTargetCache = GMM_GFX_TC_ELLC_LLC;
300         }
301 
302         switch(i)
303         {
304             case PAT0:
305                 if(pGmmLibContext->GetWaTable().WaGttPat0)
306                 {
307                     if(pGmmLibContext->GetWaTable().WaGttPat0WB)
308                     {
309                         GfxMemType = GMM_GFX_WB;
310                         if(GFX_IS_ATOM_PLATFORM(pGmmLibContext))
311                         {
312                             PAT.PreGen10.Snoop = 1;
313                         }
314                         pPrivatePATTableMemoryType[GMM_GFX_PAT_WB_COHERENT] = PAT0;
315                     }
316                     else
317                     {
318                         GfxMemType                                 = GMM_GFX_UC_WITH_FENCE;
319                         pPrivatePATTableMemoryType[GMM_GFX_PAT_UC] = PAT0;
320                     }
321                 }
322                 else // if GTT is not tied to PAT0 then WaGttPat0WB is NA
323                 {
324                     GfxMemType = GMM_GFX_WB;
325                     if(GFX_IS_ATOM_PLATFORM(pGmmLibContext))
326                     {
327                         PAT.PreGen10.Snoop = 1;
328                     }
329                     pPrivatePATTableMemoryType[GMM_GFX_PAT_WB_COHERENT] = PAT0;
330                 }
331                 break;
332 
333             case PAT1:
334                 if(pGmmLibContext->GetWaTable().WaGttPat0 && !pGmmLibContext->GetWaTable().WaGttPat0WB)
335                 {
336                     GfxMemType = GMM_GFX_WB;
337                     if(GFX_IS_ATOM_PLATFORM(pGmmLibContext))
338                     {
339                         PAT.PreGen10.Snoop = 1;
340                     }
341                     pPrivatePATTableMemoryType[GMM_GFX_PAT_WB_COHERENT] = PAT1;
342                 }
343                 else
344                 {
345                     GfxMemType                                 = GMM_GFX_UC_WITH_FENCE;
346                     pPrivatePATTableMemoryType[GMM_GFX_PAT_UC] = PAT1;
347                 }
348                 break;
349 
350             case PAT2:
351                 // This PAT idx shall be used for MOCS'Less resources like Page Tables
352                 // Page Tables have TC hardcoded to eLLC+LLC in Adv Ctxt. Hence making this to have same in Leg Ctxt.
353                 // For BDW-H, due to Perf issue, TC has to be eLLC only for Page Tables when eDRAM is present.
354                 GfxMemType                                          = GMM_GFX_WB;
355                 GfxTargetCache                                      = GMM_GFX_TC_ELLC_LLC;
356                 pPrivatePATTableMemoryType[GMM_GFX_PAT_WB_MOCSLESS] = PAT2;
357                 break;
358 
359             case PAT3:
360                 GfxMemType                                 = GMM_GFX_WB;
361                 pPrivatePATTableMemoryType[GMM_GFX_PAT_WB] = PAT3;
362                 break;
363 
364             case PAT4:
365                 GfxMemType                                 = GMM_GFX_WT;
366                 pPrivatePATTableMemoryType[GMM_GFX_PAT_WT] = PAT4;
367                 break;
368 
369             case PAT5:
370             case PAT6:
371             case PAT7:
372                 GfxMemType                                 = GMM_GFX_WC;
373                 pPrivatePATTableMemoryType[GMM_GFX_PAT_WC] = PAT5;
374                 break;
375 
376             default:
377                 __GMM_ASSERT(0);
378                 Status = GMM_ERROR;
379         }
380 
381         PAT.PreGen10.MemoryType  = GfxMemType;
382         PAT.PreGen10.TargetCache = GfxTargetCache;
383         PAT.PreGen10.Age         = Age;
384 
385         SetPrivatePATEntry(i, PAT);
386     }
387 
388 #else
389     Status                                = GMM_ERROR;
390 #endif
391     return Status;
392 }
393