1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2014-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 /******************* CPU Information Gather Routines ***********************\
25 *                                                                           *
26 *   One time initialization code to setup the Processor type                *
27 *                                                                           *
28 \***************************************************************************/
29 
30 #include "cpuopsys.h"
31 
32 #include "Nvcm.h"
33 #include "os/os.h"
34 #include "core/system.h"
35 
36 #include "ctrl/ctrl0000/ctrl0000system.h"
37 
38 
39 #if NVCPU_IS_AARCH64
40 
41 #include "cpu_arm_def.h"
42 
43 #if defined(__GNUC__)
44 
45 #define CP_READ_REGISTER(reg)                                   \
46     ({                                                          \
47         NvU32 __res;                                            \
48                                                                 \
49         asm("mrs %0, " reg "\r\t"                               \
50             : "=r" (__res)                                      \
51            );                                                   \
52                                                                 \
53         __res;                                                  \
54     })
55 
56 #define CP_WRITE_REGISTER(reg, val)                             \
57     ({                                                          \
58         asm("msr " reg ", %0\r\t"                               \
59             :                                                   \
60             : "r" (val)                                         \
61            );                                                   \
62     })
63 
64 #endif //end defined(__GNUC__)
65 
DecodeAarch64Cache(OBJSYS * pSys)66 static void DecodeAarch64Cache(OBJSYS *pSys)
67 {
68     NvU32 val, field, numsets, assoc, linesize;
69 
70     // Select level 1 data cache
71     CP_WRITE_CSSELR_REGISTER(CP_CSSELR_DATA_CACHE);
72 
73     // Retrieve data cache information
74     val = CP_READ_CCSIDR_REGISTER();
75 
76     field    = GET_BITMASK(CCSIDR_CACHE_NUM_SETS, val);
77     numsets  = field + 1;
78     field    = GET_BITMASK(CCSIDR_CACHE_ASSOCIATIVITY, val);
79     assoc    = field + 1;
80     field    = GET_BITMASK(CCSIDR_CACHE_LINE_SIZE, val);
81     linesize = 1 << (field + 4);
82 
83     pSys->cpuInfo.dataCacheLineSize = linesize;
84     pSys->cpuInfo.l1DataCacheSize   = (numsets * assoc * linesize) >> 10;
85 
86     // Select level 2 data cache
87     CP_WRITE_CSSELR_REGISTER(CP_CSSELR_DATA_CACHE_LEVEL2);
88 
89     // Retrieve data cache information
90     val = CP_READ_CCSIDR_REGISTER();
91 
92     field    = GET_BITMASK(CCSIDR_CACHE_NUM_SETS, val);
93     numsets  = field + 1;
94     field    = GET_BITMASK(CCSIDR_CACHE_ASSOCIATIVITY, val);
95     assoc    = field + 1;
96     field    = GET_BITMASK(CCSIDR_CACHE_LINE_SIZE, val);
97     linesize = 1 << (field + 4);
98 
99     pSys->cpuInfo.l2DataCacheSize = (numsets * assoc * linesize) >> 10;
100 }
101 
102 /*
103  * ID the CPU.
104  */
RmInitCpuInfo(void)105 void RmInitCpuInfo(void)
106 {
107 #define AARCH64_VENDOR_PART_NUMBER(v, p) \
108         (((v)<<16)|(p))
109 #define AARCH64_VENDOR_PART(v, p) \
110         AARCH64_VENDOR_PART_NUMBER(CP_MIDR_IMPLEMENTER_##v, CP_MIDR_PRIMARY_PART_NUM_##p)
111 
112     OBJSYS *pSys = SYS_GET_INSTANCE();
113 
114     if (pSys->cpuInfo.bInitialized)
115     {
116         return;
117     }
118 
119     // Init structure to default
120     portMemSet(&pSys->cpuInfo, 0, sizeof(pSys->cpuInfo));
121 
122     // ARM has the equivalent of a fence instruction (DSB)
123 
124     // Leave this here for MODS
125     pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_UNKNOWN;
126     pSys->cpuInfo.caps = (NV0000_CTRL_SYSTEM_CPU_CAP_SFENCE |
127                           NV0000_CTRL_SYSTEM_CPU_CAP_WRITE_COMBINING);
128 
129     // Calculate the frequency
130     pSys->cpuInfo.clock = osGetCpuFrequency();
131 
132     // Number of core is available from SCU configuration.
133     pSys->cpuInfo.numPhysicalCpus = osGetCpuCount();
134 
135     // There is no hyper-threading on ARM
136     pSys->cpuInfo.numLogicalCpus = pSys->cpuInfo.numPhysicalCpus;
137     pSys->cpuInfo.maxLogicalCpus = pSys->cpuInfo.numPhysicalCpus;
138 
139     // Zero out the vendor-specific family, model & stepping
140     pSys->cpuInfo.family = 0;
141     pSys->cpuInfo.model  = 0;
142     pSys->cpuInfo.stepping = 0;
143 
144     NvU32 val;
145     NvU32 impl;
146     NvU32 part;
147 
148     // Retrieve Main ID register
149     val = CP_READ_MIDR_REGISTER();
150 
151     impl = GET_BITMASK(MIDR_IMPLEMENTER, val);
152     part = GET_BITMASK(MIDR_PRIMARY_PART_NUM, val);
153 
154     switch(AARCH64_VENDOR_PART_NUMBER(impl, part))
155     {
156         case AARCH64_VENDOR_PART(NVIDIA, DENVER_1):
157             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_NV_DENVER_1_0;
158             break;
159         case AARCH64_VENDOR_PART(NVIDIA, DENVER_2):
160             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_NV_DENVER_2_0;
161             break;
162 
163         case AARCH64_VENDOR_PART(NVIDIA, CARMEL):
164             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_ARMV8A_GENERIC;
165             break;
166         /*
167          * Applied Micro is now Ampere computing, and the Ampere eMag
168          * vendor/part ids are the same as AMCC XGENE
169          */
170         case AARCH64_VENDOR_PART(AMCC, XGENE):
171         case AARCH64_VENDOR_PART(ARM, CORTEX_A76):
172         case AARCH64_VENDOR_PART(MARVELL, THUNDER_X2):
173         case AARCH64_VENDOR_PART(HUAWEI, KUNPENG_920):
174         case AARCH64_VENDOR_PART(ARM, BLUEFIELD):
175         case AARCH64_VENDOR_PART(ARM, BLUEFIELD3):
176         // The Neoverse N1 is the same as Gravitron
177         case AARCH64_VENDOR_PART(ARM, GRAVITRON2):
178         case AARCH64_VENDOR_PART(FUJITSU, A64FX):
179         case AARCH64_VENDOR_PART(PHYTIUM, FT2000):
180         case AARCH64_VENDOR_PART(PHYTIUM, S2500):
181         case AARCH64_VENDOR_PART(AMPERE, ALTRA):
182         case AARCH64_VENDOR_PART(MARVELL, OCTEON_CN96XX):
183         case AARCH64_VENDOR_PART(MARVELL, OCTEON_CN98XX):
184         case AARCH64_VENDOR_PART(ARM, CORTEX_A57):
185             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_ARMV8A_GENERIC;
186             break;
187         case AARCH64_VENDOR_PART(ARM, NEOVERSE_N2):
188         case AARCH64_VENDOR_PART(ARM, NEOVERSE_V2):
189         case AARCH64_VENDOR_PART(AMPERE_2, AMPEREONE):
190             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_ARMV9A_GENERIC;
191             break;
192         default:
193             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_ARMV8A_GENERIC;
194             portDbgPrintf(
195                 "NVRM: CPUID: unknown implementer/part 0x%x/0x%x.\n", impl, part);
196             portDbgPrintf(
197                 "The NVIDIA GPU driver for AArch64 has not been qualified on this CPU\n"
198                 "and therefore it is not recommended or intended for use in any production\n"
199                 "environment.\n");
200             break;
201     }
202     DecodeAarch64Cache(pSys);
203 
204     // Host native page size
205 #ifdef PAGE_SIZE
206     pSys->cpuInfo.hostPageSize = PAGE_SIZE;
207 #else
208     pSys->cpuInfo.hostPageSize = 4096;
209 #endif
210 
211     pSys->cpuInfo.bInitialized = NV_TRUE;
212 #undef AARCH64_VENDOR_PART
213 #undef AARCH64_VENDOR_PART_NUMBER
214 }
215 
216 #endif // NVCPU_IS_AARCH64
217 
218 
219 /***************************************************************************/
220 
221 
222 #if NVCPU_IS_ARM
223 
224 #include "cpu_arm_def.h"
225 
226 #if defined(__GNUC__)
227 
228     #define CP_READ_REGISTER(reg)                                   \
229         ({                                                          \
230             NvU32 __res;                                            \
231                                                                     \
232             asm("mrc p15, " reg ", %0, c0, c0, 0\r\t"               \
233                 : "=r" (__res)                                      \
234                 :                                                   \
235                 : "cc");                                            \
236                                                                     \
237             __res;                                                  \
238         })
239 
240     #define CP_WRITE_REGISTER(reg, val)                             \
241         ({                                                          \
242             asm("mcr p15, " reg ", %0, c0, c0, 0\r\t"               \
243                 :                                                   \
244                 : "r"(val));                                        \
245         })
246 
247 #endif //end defined(__GNUC__)
248 
249 /*
250  * Documentation:
251  *
252  * https://developer.arm.com/documentation/ddi0388/f/CIHHDACH
253  */
DecodeCortexA9Cache(OBJSYS * pSys)254 static void DecodeCortexA9Cache(OBJSYS *pSys)
255 {
256     NvU32 val, field;
257 
258     // Select data cache
259     CP_WRITE_CSSELR_REGISTER(CP_CSSELR_DATA_CACHE);
260 
261     // Retrieve data cache information
262     val = CP_READ_CCSIDR_REGISTER();
263 
264     // L1 Data Cache Size (from KB to KB)
265     field = GET_BITMASK(CCSIDR_CACHE_NUM_SETS, val);
266 
267     if (field == CP_CCSIDR_CACHE_NUM_SETS_16KB)
268     {
269         pSys->cpuInfo.l1DataCacheSize = 16;
270     }
271     else if (field == CP_CCSIDR_CACHE_NUM_SETS_32KB)
272     {
273         pSys->cpuInfo.l1DataCacheSize = 32;
274     }
275     else if (field == CP_CCSIDR_CACHE_NUM_SETS_64KB)
276     {
277         pSys->cpuInfo.l1DataCacheSize = 64;
278     }
279     else
280     {
281         NV_PRINTF(LEVEL_ERROR, "CPUID: Couldn't find L1DataCacheSize.\n");
282     }
283 
284     // There is only one level of cache in the Cortex-A9 processor
285     pSys->cpuInfo.l2DataCacheSize = 0;
286 
287     // Data Cache Line (from W to B)
288     field = GET_BITMASK(CCSIDR_CACHE_LINE_SIZE, val);
289 
290     if (field & CP_CCSIDR_CACHE_LINE_SIZE_8W)
291     {
292         pSys->cpuInfo.dataCacheLineSize = 8 * 4;
293     }
294     else
295     {
296         NV_PRINTF(LEVEL_ERROR, "CPUID: Couldn't find DataCacheLineSize.\n");
297     }
298 }
299 
DecodeCortexA15CacheSize(NvU32 field)300 static NvU32 DecodeCortexA15CacheSize(NvU32 field)
301 {
302     switch(field)
303     {
304         case CP_CCSIDR_CACHE_NUM_SETS_A15_32KB:
305             return 32;
306         case CP_CCSIDR_CACHE_NUM_SETS_A15_512KB:
307             return 512;
308         case CP_CCSIDR_CACHE_NUM_SETS_A15_1024KB:
309             return 1024;
310         case CP_CCSIDR_CACHE_NUM_SETS_A15_2048KB:
311             return 2048;
312         case CP_CCSIDR_CACHE_NUM_SETS_A15_4096KB:
313             return 4096;
314         default:
315             NV_PRINTF(LEVEL_ERROR, "CPUID: Couldn't find DataCacheSize.\n");
316             return 0;
317     }
318 }
319 
DecodeCortexA15Cache(OBJSYS * pSys)320 static void DecodeCortexA15Cache(OBJSYS *pSys)
321 {
322     NvU32 val, field;
323 
324     // Select level 1 data cache
325     CP_WRITE_CSSELR_REGISTER(CP_CSSELR_DATA_CACHE);
326 
327     // Retrieve data cache information
328     val = CP_READ_CCSIDR_REGISTER();
329 
330     // L1 Data Cache Size (from KB to KB)
331     field = GET_BITMASK(CCSIDR_CACHE_NUM_SETS, val);
332 
333     pSys->cpuInfo.l1DataCacheSize = DecodeCortexA15CacheSize(field);
334 
335     // Data Cache Line (from W to B)
336     field = GET_BITMASK(CCSIDR_CACHE_LINE_SIZE, val);
337 
338     // line size = 2 ** (field + 2) words
339     pSys->cpuInfo.dataCacheLineSize = 4 * (1 << (field + 2));
340 
341     // Select level 2 data cache
342     CP_WRITE_CSSELR_REGISTER(CP_CSSELR_DATA_CACHE_LEVEL2);
343 
344     // Retrieve data cache information
345     val = CP_READ_CCSIDR_REGISTER();
346 
347     // L2 Data Cache Size (from KB to KB)
348     field = GET_BITMASK(CCSIDR_CACHE_NUM_SETS, val);
349 
350     pSys->cpuInfo.l2DataCacheSize = DecodeCortexA15CacheSize(field);
351 }
352 
353 /*
354  * ID the CPU.
355  */
RmInitCpuInfo(void)356 void RmInitCpuInfo(void)
357 {
358     OBJSYS *pSys = SYS_GET_INSTANCE();
359 
360     if (pSys->cpuInfo.bInitialized)
361     {
362         return;
363     }
364 
365     // Init structure to default
366     portMemSet(&pSys->cpuInfo, 0, sizeof(pSys->cpuInfo));
367 
368     // ARM has the equivalent of a fence instruction (DSB)
369 
370     // Leave this here for MODS
371     pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_UNKNOWN;
372     pSys->cpuInfo.caps = (NV0000_CTRL_SYSTEM_CPU_CAP_SFENCE |
373                           NV0000_CTRL_SYSTEM_CPU_CAP_WRITE_COMBINING);
374 
375     // Calculate the frequency
376     pSys->cpuInfo.clock = osGetCpuFrequency();
377 
378     // Number of core is available from SCU configuration.
379     pSys->cpuInfo.numPhysicalCpus = osGetCpuCount();
380     pSys->cpuInfo.maxLogicalCpus = pSys->cpuInfo.numPhysicalCpus;
381 
382     // There is no hyper-threading on ARM
383     pSys->cpuInfo.numLogicalCpus = pSys->cpuInfo.numPhysicalCpus;
384 
385     // Zero out the vendor-specific family, model & stepping
386     pSys->cpuInfo.family = 0;
387     pSys->cpuInfo.model  = 0;
388     pSys->cpuInfo.stepping = 0;
389 
390     NvU32 val;
391     NvU32 field;
392 
393     // Retrieve Main ID register
394     val = CP_READ_MIDR_REGISTER();
395 
396     field = GET_BITMASK(MIDR_PRIMARY_PART_NUM, val);
397 
398     switch(field)
399     {
400         case CP_MIDR_PRIMARY_PART_NUM_A9:
401             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_ARM_A9;
402             DecodeCortexA9Cache(pSys);
403             break;
404         case CP_MIDR_PRIMARY_PART_NUM_A15:
405             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_ARM_A15;
406             DecodeCortexA15Cache(pSys);
407             break;
408         default:
409             // Narrow down to an unknown arm cpu
410             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_ARM_UNKNOWN;
411             NV_PRINTF(LEVEL_ERROR, "CPUID: unknown part number 0x%x.\n",
412                       field);
413             break;
414     }
415 
416     // Host native page size
417 #ifdef PAGE_SIZE
418     pSys->cpuInfo.hostPageSize = PAGE_SIZE;
419 #else
420     pSys->cpuInfo.hostPageSize = 4096;
421 #endif
422 
423     pSys->cpuInfo.bInitialized = NV_TRUE;
424 }
425 
426 #endif // NVCPU_IS_ARM
427 
428 
429 /***************************************************************************/
430 
431 
432 #if NVCPU_IS_PPC64LE
433 
434 /*
435  * ID the CPU.
436  */
RmInitCpuInfo(void)437 void RmInitCpuInfo(void)
438 {
439     OBJSYS    *pSys = SYS_GET_INSTANCE();
440 
441     pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_POWERN;
442     pSys->cpuInfo.caps = 0;
443 
444     // Zero out the vendor-specific family, model & stepping
445     pSys->cpuInfo.family = 0;
446     pSys->cpuInfo.model  = 0;
447     pSys->cpuInfo.stepping = 0;
448 
449     // Calculate the frequency
450     pSys->cpuInfo.clock = osGetCpuFrequency();
451 
452     // Number of CPUs.
453     // Should maybe take into account SMT, etc.
454     pSys->cpuInfo.numPhysicalCpus = osGetCpuCount();
455     pSys->cpuInfo.numLogicalCpus = pSys->cpuInfo.numPhysicalCpus;
456     pSys->cpuInfo.maxLogicalCpus = pSys->cpuInfo.numPhysicalCpus;
457 
458     // host native page size
459     pSys->cpuInfo.hostPageSize = 64 * 1024;
460 
461     return;
462 }
463 
464 #endif // NVCPU_IS_PPC64LE
465 
466 
467 /***************************************************************************/
468 
469 
470 #if NVCPU_IS_RISCV64
471 
472 /*
473  * ID the CPU. (stub)
474  */
RmInitCpuInfo(void)475 void RmInitCpuInfo(
476     void
477 )
478 {
479     OBJSYS    *pSys = SYS_GET_INSTANCE();
480 
481     // XXX
482     pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_UNKNOWN;
483 
484     // Zero out the vendor-specific family, model & stepping
485     pSys->cpuInfo.family = 0;
486     pSys->cpuInfo.model  = 0;
487     pSys->cpuInfo.stepping = 0;
488 
489     // Calculate the frequency
490     pSys->cpuInfo.clock = 1;
491 
492     // host native page size
493     pSys->cpuInfo.hostPageSize = 4096;
494 }
495 
496 #endif // NVCPU_IS_RISCV64
497 
498 
499 /***************************************************************************/
500 
501 
502 #if NVCPU_IS_X86 || NVCPU_IS_X86_64
503 
504 #include "platform/cpu.h"
505 
506 #if defined(_M_IX86) || defined(NVCPU_X86) || defined(AMD64) || defined(NVCPU_X86_64)
507 
508 // bits returned in EDX register by CPUID instruction with EAX=1
509 #define CPU_STD_TSC                 NVBIT(4)
510 #define CPU_STD_CMOV                NVBIT(15)   // Supports conditional move instructions.
511 #define CPU_STD_CLFSH               NVBIT(19)   // Supports CLFLUSH instruction.
512 #define CPU_STD_MMX                 NVBIT(23)
513 #define CPU_STD_FXSR                NVBIT(24)   // Indicates CR4.OSFXSR is available.
514 #define CPU_STD_SSE                 NVBIT(25)   // Katmai
515 #define CPU_STD_SSE2                NVBIT(26)   // Willamette NI
516 
517 // bits returned in ECX register by CPUID instruction with EAX=1
518 #define CPU_STD2_SSE3               NVBIT(0)
519 #define CPU_STD2_SSE41              NVBIT(19)
520 #define CPU_STD2_SSE42              NVBIT(20)
521 #define CPU_STD2_OSXSAVE            NVBIT(27)   // Indicates the OS supports XSAVE/XRESTOR
522 #define CPU_STD2_AVX                NVBIT(28)
523 
524 // "Extended Feature Flags" - bits returned in EDX register by CPUID
525 // instruction with EAX=0x80000001
526 #define CPU_EXT_3DNOW               NVBIT(31)   // 3DNow
527 #define CPU_EXT_AMD_3DNOW_EXT       NVBIT(30)   // 3DNow, with Extensions (AMD specific)
528 #define CPU_EXT_AMD_MMX_EXT         NVBIT(22)   // MMX, with Extensions (AMD specific)
529 
530 // "Structured Extended Feature Identifiers" - bits returned in EBX
531 // register by CPUID instruction with EAX=7
532 #define CPU_EXT2_ERMS               NVBIT(9)
533 
534 /*
535  * Identify chip foundry.
536  *      IS_INTEL   = "GenuineIntel"
537  *      IS_AMD     = "AuthenticAMD"
538  *      IS_WINCHIP = "CentaurHauls"
539  *      IS_CYRIX   = "CyrixInstead"
540  *      IS_TRANSM  = "GenuineTMx86"  // Transmeta
541  */
542 #define IS_INTEL(fndry)     (((fndry).StrID[0]==0x756E6547)&&((fndry).StrID[1]==0x49656E69)&&((fndry).StrID[2]==0x6C65746E))
543 #define IS_AMD(fndry)       (((fndry).StrID[0]==0x68747541)&&((fndry).StrID[1]==0x69746E65)&&((fndry).StrID[2]==0x444D4163))
544 #define IS_WINCHIP(fndry)   (((fndry).StrID[0]==0x746E6543)&&((fndry).StrID[1]==0x48727561)&&((fndry).StrID[2]==0x736C7561))
545 #define IS_CYRIX(fndry)     (((fndry).StrID[0]==0x69727943)&&((fndry).StrID[1]==0x736E4978)&&((fndry).StrID[2]==0x64616574))
546 #define IS_TRANSM(fndry)    (((fndry).StrID[0]==0x756E6547)&&((fndry).StrID[1]==0x54656E69)&&((fndry).StrID[2]==0x3638784D))
547 
548 // CPUID Info
549 // Used internally in this source.
550 
551 typedef struct _def_CPUID_info
552 {
553     union
554     {
555         NvU8 String[12];
556         NvU32 StrID[3];
557     } Foundry;
558 
559     NvU32 StandardFeatures;
560     NvU32 ExtendedFeatures;
561 
562     NvU16 Family;
563     NvU16 ExtFamily;
564     NvU16 DisplayedFamily;
565     NvU8 Model;
566     NvU8 ExtModel;
567     NvU8 DisplayedModel;
568     NvU8 Stepping;
569     NvU32 BrandId;
570 } CPUIDINFO, *PCPUIDINFO;
571 
572 // Forward refernces.
573 //
574 
575 static void getCpuCounts(OBJSYS *pSys, PCPUIDINFO pCpuidInfo);
576 static NvBool getEmbeddedProcessorName(char *pName, NvU32 size);
577 static void cpuidInfoAMD(OBJSYS *pSys, PCPUIDINFO pCpuidInfo);
578 static void cpuidInfoIntel(OBJSYS *pSys, PCPUIDINFO pCpuidInfo);
579 
580 #if defined(_M_IX86) || defined(NVCPU_X86)
581 static void cpuidInfoWinChip(OBJSYS *pSys, PCPUIDINFO pCpuidInfo);
582 static void cpuidInfoCyrix(OBJSYS *pSys, PCPUIDINFO pCpuidInfo);
583 static void cpuidInfoTransmeta(OBJSYS *pSys, PCPUIDINFO pCpuidInfo);
584 #endif
585 
586 
587 /*
588  * ID the CPU.
589  */
590 
RmInitCpuInfo(void)591 void RmInitCpuInfo(void)
592 {
593     OBJSYS    *pSys = SYS_GET_INSTANCE();
594     CPUIDINFO  cpuinfo;
595     NvU32      eax, ebx, ecx, edx;
596     OBJOS     *pOS = SYS_GET_OS(pSys);
597 
598     // Do this only once.
599     if (pSys->cpuInfo.bInitialized)
600         return;
601 
602     // Initialize the processor structure to default values.
603     //
604     pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_UNKNOWN;
605     pSys->cpuInfo.caps = 0;
606     pSys->cpuInfo.clock = 0;
607     pSys->cpuInfo.dataCacheLineSize = 0;
608     pSys->cpuInfo.l1DataCacheSize = 0;
609     pSys->cpuInfo.l2DataCacheSize = 0;
610     pSys->cpuInfo.coresOnDie = 0;
611     pSys->cpuInfo.platformID = 0;
612     portMemSet(pSys->cpuInfo.name, 0, sizeof(pSys->cpuInfo.name));
613 
614     // Init internal structure to default.
615     //
616     portMemSet(&cpuinfo, 0, sizeof(cpuinfo));
617 
618     // Get CPUID stuff for all processors.  We will figure out what to do with it later.
619 
620     // if pOS->osNv_cpuid returns 0, then this cpu does not support cpuid instruction
621     // We just worry about this on the first call...
622     if ( ! pOS->osNv_cpuid(pOS, 0, 0, &eax, &cpuinfo.Foundry.StrID[0],
623             &cpuinfo.Foundry.StrID[2], &cpuinfo.Foundry.StrID[1]))
624         goto Exit;
625 
626     pOS->osNv_cpuid(pOS, 1, 0, &eax, &ebx, &ecx, &edx);
627     cpuinfo.Family = (NvU16)((eax >> 8) & 0x0F);
628     cpuinfo.ExtFamily = (NvU16)((eax >> 20) & 0xFF);
629     if (cpuinfo.Family != 0xF)
630     {
631         cpuinfo.DisplayedFamily = cpuinfo.Family;
632     }
633     else
634     {
635         cpuinfo.DisplayedFamily = cpuinfo.ExtFamily + cpuinfo.Family;
636     }
637 
638     cpuinfo.Model = (NvU8)((eax >> 4) & 0x0F);
639     cpuinfo.ExtModel = (NvU8)((eax >> 16) & 0x0F);
640     if (cpuinfo.Family == 6 || cpuinfo.Family == 0xF)
641     {
642         cpuinfo.DisplayedModel = (cpuinfo.ExtModel << 4) + cpuinfo.Model;
643     }
644     else
645     {
646         cpuinfo.DisplayedModel = cpuinfo.Model;
647     }
648 
649     cpuinfo.Stepping = (NvU8)(eax & 0x0F);
650     cpuinfo.StandardFeatures = edx;
651     cpuinfo.BrandId = ((ebx & 0xE0) << 3) | (ebx & 0x1F); // 8bit brandID in 12 bit format
652 
653     // Decode the standard features.  Assume that all CPU vendors use the
654     // standard feature bits to mean the same thing.  Non-Intel vendors use
655     // the extended CPUID to provide non-standard freture bits, so this
656     // should be OK.
657 
658     if (cpuinfo.StandardFeatures & CPU_STD_MMX)
659         pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_MMX;
660 
661     if (cpuinfo.StandardFeatures & CPU_STD_CMOV)
662         pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_CMOV;
663 
664     if (cpuinfo.StandardFeatures & CPU_STD_CLFSH)
665         pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_CLFLUSH;
666 
667     // Check for Streaming SIMD extensions (Katmai)
668     if (cpuinfo.StandardFeatures & CPU_STD_SSE)
669     {
670 
671         // SFENCE is an SSE instruction, but it does not require CR4.OSFXSR.
672         pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_SFENCE;
673 
674         if (cpuinfo.StandardFeatures & CPU_STD_FXSR)
675         {
676             NvBool check_osfxsr;
677             NvBool check_osxsave;
678             // Before setting the NV0000_CTRL_SYSTEM_CPU_CAP_SSE bit, we'll
679             // also check that CR4.OSFXSR (bit 9) is set, which means the OS
680             // is prepared to switch the additional SSE FP state for us.
681             // CPU_STD_FXSR indicates that CR4.OSFXSR is valid.
682             check_osfxsr = ((cpuinfo.StandardFeatures & CPU_STD_FXSR) != 0) &&
683                            ((pOS->osNv_rdcr4(pOS) & 0x200) != 0);
684 
685             // For NV0000_CTRL_SYSTEM_CPU_CAP_AVX bit, we need:
686             // - CPU_STD2_OSXSAVE - CR4.OSXSAVE is valid
687             // - CR4.OSXSAVE (bit 18) - The OS will the additional FP state
688             //     specified by XCR0
689             // - XCR0 - bits 1 and 2 indicate SSE and AVX support respectively
690             check_osxsave = ((ecx & CPU_STD2_OSXSAVE) != 0) &&
691                             ((pOS->osNv_rdcr4(pOS) & (1<<18)) != 0) &&
692                             ((pOS->osNv_rdxcr0(pOS) & 0x6) != 0);
693             if(check_osfxsr)
694             {
695                 pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_SSE;
696 
697                 // supports SSE2 (Willamette NI) instructions
698                 if (cpuinfo.StandardFeatures & CPU_STD_SSE2)
699                     pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_SSE2;
700 
701                 // Prescott New Instructions
702                 if (ecx & CPU_STD2_SSE3)
703                     pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_SSE3;
704 
705                 // Penryn subset of SSE4
706                 if (ecx & CPU_STD2_SSE41)
707                     pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_SSE41;
708 
709                 // Nehalem subset of SSE4
710                 if (ecx & CPU_STD2_SSE42)
711                     pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_SSE42;
712             }
713 
714             // If the OS setup XSAVE / XRESTOR (and set the AVX bit)
715             //   enable AVX
716             if (check_osxsave)
717             {
718                 if (ecx & CPU_STD2_AVX)
719                     pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_AVX;
720             }
721         }
722     }
723 
724     if (pOS->osNv_cpuid(pOS, 7, 0, &eax, &ebx, &ecx, &edx))
725     {
726         if (ebx & CPU_EXT2_ERMS)
727         {
728             pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_ERMS;
729         }
730     }
731 
732     // Calculate the frequency
733     if (cpuinfo.StandardFeatures & CPU_STD_TSC)
734         pSys->cpuInfo.clock = osGetCpuFrequency();
735 
736     // Get the extended features (if they exist).
737     if (pOS->osNv_cpuid(pOS, 0x80000000, 0, &eax, &ebx, &ecx, &edx) && eax >= 0x80000001)
738     {
739         if (pOS->osNv_cpuid(pOS, 0x80000001, 0, &eax, &ebx, &ecx, &edx))
740         {
741             cpuinfo.ExtendedFeatures = edx;
742             // if 8 bit brandId is 0
743             if (!cpuinfo.BrandId)
744             {
745                 // Check for 12 bit brand ID
746                 cpuinfo.BrandId = (ebx & 0xfff);
747             }
748         }
749    }
750 
751     // Get the embedded processor name (if there is one).
752     getEmbeddedProcessorName(pSys->cpuInfo.name, sizeof(pSys->cpuInfo.name));
753 
754     if (IS_INTEL(cpuinfo.Foundry))
755         cpuidInfoIntel(pSys, &cpuinfo);
756     else if (IS_AMD(cpuinfo.Foundry))
757         cpuidInfoAMD(pSys, &cpuinfo);
758 #if defined(_M_IX86) || defined(NVCPU_X86)
759     else if (IS_WINCHIP(cpuinfo.Foundry))
760         cpuidInfoWinChip(pSys, &cpuinfo);
761     else if (IS_CYRIX(cpuinfo.Foundry))
762         cpuidInfoCyrix(pSys, &cpuinfo);
763     else if (IS_TRANSM(cpuinfo.Foundry))
764         cpuidInfoTransmeta(pSys, &cpuinfo);
765 #endif
766     else
767     {
768         // We are clueless.  If the processor had an embedded name, its already in there.
769         // If not, use the foundary name as the processor name.
770         if (pSys->cpuInfo.name[0] == 0)
771             portMemCopy(pSys->cpuInfo.name, sizeof(cpuinfo.Foundry.String), cpuinfo.Foundry.String, sizeof(cpuinfo.Foundry.String));
772     }
773 
774     // Pick up the vendor-specific family & model
775     pSys->cpuInfo.family = cpuinfo.DisplayedFamily;
776     pSys->cpuInfo.model  = cpuinfo.DisplayedModel;
777 
778 #if defined(AMD64) || defined(NVCPU_X86_64)
779     // The WinXP AMD-64 does not context switch the x87/MMX/3DNow registers.  We have to zap the bits
780     // even though the CPU supports them.
781     // The OS should somehow tell us this, like CR4.OSFXSR above.  Need to find a better way...
782 
783     pSys->cpuInfo.caps &= ~(NV0000_CTRL_SYSTEM_CPU_CAP_MMX |
784                             NV0000_CTRL_SYSTEM_CPU_CAP_MMX_EXT |
785                             NV0000_CTRL_SYSTEM_CPU_CAP_3DNOW |
786                             NV0000_CTRL_SYSTEM_CPU_CAP_3DNOW_EXT);
787 #endif
788 
789     pSys->cpuInfo.stepping = cpuinfo.Stepping;
790     pSys->cpuInfo.brandId = cpuinfo.BrandId;
791 
792  Exit:
793 
794     // set physical/logical processor counts
795     getCpuCounts(pSys, &cpuinfo);
796 
797     // host page size used when allocated host-page-aligned objects in heap
798 #ifdef PAGE_SIZE
799     pSys->cpuInfo.hostPageSize = PAGE_SIZE;
800 #else
801     pSys->cpuInfo.hostPageSize = 4096;
802 #endif
803 
804     pSys->cpuInfo.bInitialized = NV_TRUE;
805 }
806 
807 //
808 // This routine determines the number of physical processors enabled
809 // on the system as well as the number of logical processors per
810 // physical processors.  Intel's HyperThreading technology can yield
811 // a logical processor count of > 1 per physical processor.
812 //
813 // This code was more or less lifted from some Intel sample code.
814 //
815 
816 #define INTEL_HT_BIT             0x10000000      // EDX[28]
817 #define INTEL_CORE_CNT           0xFC000000      // EAX[31:26]
818 #define INTEL_LOGICAL_CNT        0x00FF0000      // EBX[23:16]
819 #define INTEL_LOGICAL_CNT_LEAFB  0x0000FFFF      // EBX[15:0]
820 #define AMD_HT_BIT               0x10000000      // EDX[28]
821 #define AMD_LOGICAL_CNT          0x00FF0000      // EBX[23:16]
822 
823 static void
getCpuCounts(OBJSYS * pSys,PCPUIDINFO pCpuidInfo)824 getCpuCounts(OBJSYS *pSys, PCPUIDINFO pCpuidInfo)
825 {
826     OBJOS *pOS = SYS_GET_OS(pSys);
827     NvU32  numPhysicalCpus, numLogicalCpus, maxLogicalCpus;
828     NvU32  eax = 0;
829     NvU32  ebx = 0;
830     NvU32  ecx = 0;
831     NvU32  edx = 0;
832 
833     //
834     // First use OS call to get number of logical CPUs.
835     //
836     numLogicalCpus = osGetCpuCount();
837 
838     //
839     // Assume the number of physical CPUs is the same as the number of logical CPUs.
840     //
841     numPhysicalCpus = numLogicalCpus;
842     maxLogicalCpus = numLogicalCpus;
843 
844     // There is no reliable way to tell if hyper-threading is enabled.  So, if
845     // there is more than 1 logical CPUs AND the CPU is hyperthreading capable,
846     // then assume that HT is enabled.
847     //
848     // This should give the right answer for most cases.  Some HT capable dual
849     // CPU systems with HT disabled will be detected as single GPU systems with
850     // HT enabled.  While less than ideal, this should be OK, since logical CPUs
851     // is 2 in both cases.
852     //
853 #if defined(_M_IX86) || defined(NVCPU_X86) || defined(NVCPU_X86_64)
854     if (IS_INTEL(pCpuidInfo->Foundry))
855     {
856         NvBool cpuHasLeafB = NV_FALSE;
857 
858         pOS->osNv_cpuid(pOS, 0, 0, &eax, &ebx, &ecx, &edx);
859         if (eax >= 0xB)
860         {
861             pOS->osNv_cpuid(pOS, 0xB, 0, &eax, &ebx, &ecx, &edx);
862             if (ebx != 0)
863             {
864                 cpuHasLeafB = NV_TRUE;
865             }
866         }
867 
868         pOS->osNv_cpuid(pOS, 1, 0, &eax, &ebx, &ecx, &edx);
869 
870         if (edx & INTEL_HT_BIT)
871         {
872             NvU32 CpuHT;
873 
874             if (cpuHasLeafB)
875             {
876                 pOS->osNv_cpuid(pOS, 0xB, 0, &eax, &ebx, &ecx, &edx);
877                 CpuHT = (ebx & INTEL_LOGICAL_CNT_LEAFB);
878                 pOS->osNv_cpuid(pOS, 0xB, 1, &eax, &ebx, &ecx, &edx);
879                 maxLogicalCpus = (ebx & INTEL_LOGICAL_CNT_LEAFB);
880                 numPhysicalCpus = maxLogicalCpus/CpuHT;
881             }
882             else
883             {
884                 pOS->osNv_cpuid(pOS, 0, 0, &eax, &ebx, &ecx, &edx);
885                 if (eax >=4)
886                 {
887                     pOS->osNv_cpuid(pOS, 4, 0, &eax, &ebx, &ecx, &edx);
888                     numPhysicalCpus = ((eax & INTEL_CORE_CNT) >> 26) + 1;
889                     pOS->osNv_cpuid(pOS, 1, 0, &eax, &ebx, &ecx, &edx);
890                     maxLogicalCpus = (ebx & INTEL_LOGICAL_CNT) >> 16;
891                     CpuHT = maxLogicalCpus/numPhysicalCpus;
892                 }
893             }
894 
895             if (numPhysicalCpus > numLogicalCpus)
896                 numPhysicalCpus = numLogicalCpus;
897 
898             if (numPhysicalCpus < 1)
899                 numPhysicalCpus = 1;
900 
901             pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_HT_CAPABLE;
902         }
903     }
904     else if(IS_AMD(pCpuidInfo->Foundry))
905     {
906         pOS->osNv_cpuid(pOS, 1, 0, &eax, &ebx, &ecx, &edx);
907         if( edx & AMD_HT_BIT )
908         {
909             maxLogicalCpus = (ebx & AMD_LOGICAL_CNT) >> 16;
910         }
911     }
912 
913     NV_PRINTF(LEVEL_INFO, "RmInitCpuCounts: physical 0x%x logical 0x%x\n",
914               numPhysicalCpus, numLogicalCpus);
915 #endif
916 
917     if(maxLogicalCpus < numLogicalCpus)
918         maxLogicalCpus = numLogicalCpus;
919 
920 #if NVCPU_IS_FAMILY_X86
921     // bug1974464: Ryzen physical CPU count is getting misreported
922     if (IS_AMD(pCpuidInfo->Foundry) && (pCpuidInfo->DisplayedFamily == 0x17))
923     {
924         numPhysicalCpus = NV_MAX(maxLogicalCpus/2, 1);
925     }
926 #endif
927 
928     pSys->cpuInfo.numPhysicalCpus = numPhysicalCpus;
929     pSys->cpuInfo.numLogicalCpus = numLogicalCpus;
930     pSys->cpuInfo.maxLogicalCpus = maxLogicalCpus;
931 
932     return;
933 }
934 
935 
936 // getEmbeddedProcessorName
937 //
938 // All processors that have extended CPUID info up through 0x80000004 have an embedded name.
939 //
getEmbeddedProcessorName(char * pName,NvU32 size)940 static NvBool getEmbeddedProcessorName(char *pName, NvU32 size)
941 {
942     NvU32       op, eax, ebx, ecx, edx;
943     char       *p       = pName;
944     OBJSYS     *pSys    = SYS_GET_INSTANCE();
945     OBJOS      *pOS     = SYS_GET_OS(pSys);
946     const NvU32 maxSize = 48; // max 48 bytes on x86 CPUs
947 
948     NV_ASSERT_OR_RETURN(size >= maxSize, 0);
949 
950     pName[size > maxSize ? maxSize : size-1] = 0;  // Make sure it has a zero at the end.
951 
952     // Is there is a enough data?  If not bail.
953     if (pOS->osNv_cpuid(pOS, 0x80000000, 0, &eax, &ebx, &ecx, &edx) == 0 || eax < 0x80000004)
954         return NV_FALSE;
955 
956     // Yes, get 48 bytes of CPU name.
957     for (op = 0x80000002; op < 0x80000005; op++, p += 16)
958         pOS->osNv_cpuid(pOS, op, 0, (NvU32 *)&p[0], (NvU32 *)&p[4], (NvU32 *)&p[8], (NvU32 *)&p[12]);
959 
960     // Kill leading spaces. (Intel's string is right justified.)
961     if (*pName == ' ')
962     {
963         p = pName;
964         while (*p == ' ')
965             p++;
966         do
967             *(pName++) = *(p++);
968         while (*p);
969     }
970 
971     return NV_TRUE;
972 }
973 
974 
975 // Decode Prescott style cache descriptors.
976 //
DecodePrescottCache(OBJSYS * pSys)977 static NvBool DecodePrescottCache(OBJSYS *pSys)
978 {
979     NvU32   eax, ebx, ecx, edx;
980     OBJOS  *pOS = SYS_GET_OS(pSys);
981 
982     // Decode the cache desciptors.
983 
984     if (pOS->osNv_cpuid(pOS, 0, 0, &eax, &ebx, &ecx, &edx))
985     {
986         if (eax >= 4 && eax < 0x80000000)     // CPU support new (Prescott) cache descrtiptors?
987         {
988             // From Prescot New Instructions Software Developers Guide 252490-003
989 
990             NvU32 uLevel;
991             NvU32 uLineSize;
992             NvU32 uCacheSize;
993             int i;
994 
995             // Loop over the cache descriptors by incrementing sub-function.  This will never get
996             // get run on pre-Prescott CPUs since they do not support CPUID 4, but limit number of
997             // cache descriptors to 20 just in case, so it does not get in an infinite loop.
998             //
999             for (i = 0; i < 20; i++)
1000             {
1001                 pOS->osNv_cpuid(pOS, 4, i, &eax, &ebx, &ecx, &edx);
1002 
1003                 if (i == 0)
1004                 {
1005                     pSys->cpuInfo.coresOnDie = (eax >> 26) + 1;// eax[31:26] Processor cores on the chip
1006                 }
1007 
1008                 switch (eax & 0x1f)      // Cache type.
1009                 {
1010                     case 0:              // No more cache descriptors.
1011                         i = 100;         // Break out of loop.
1012                         break;
1013 
1014                     case 1:              // Data cache.
1015                     case 3:              // Unified cache.
1016                         uLevel =     (eax >> 5) & 0x7;             // eax[7:5]    Cache level
1017                         uLineSize =  (ebx & 0xfff) + 1;            // ebx[11:0]   System Coherency Line Size
1018 
1019                         uCacheSize = uLineSize                     // ebx[11:0]   System Coherency Line Size
1020                                      * (((ebx >> 12) & 0x3FF) + 1) // ebx[21:12]  Physical line partitions
1021                                      * (((ebx >> 22) & 0x3FF) + 1) // ebx[21:12]  Ways of associativity
1022                                      * (ecx + 1)                   // ecx[31:0]   Number of sets
1023                                      / 1024;                       // Put it in KB.
1024 
1025                         pSys->cpuInfo.dataCacheLineSize = uLineSize;
1026 
1027                         if (uLevel == 1)
1028                             pSys->cpuInfo.l1DataCacheSize = uCacheSize;
1029                         else if (pSys->cpuInfo.l2DataCacheSize < uCacheSize)
1030                             pSys->cpuInfo.l2DataCacheSize = uCacheSize;
1031                         break;
1032 
1033                     default:             // Instruction of unknown cache type.
1034                         break;           // Do nothing.
1035                 }
1036             }
1037 
1038             return NV_TRUE;
1039         }
1040     }
1041 
1042     return NV_FALSE;
1043 }
1044 
1045 #if defined(_M_IX86) || defined(NVCPU_X86)
DecodeIntelCacheEntry(OBJSYS * pSys,NvU8 cacheEntry)1046 static void DecodeIntelCacheEntry(OBJSYS *pSys, NvU8 cacheEntry)
1047 {
1048     // From Intel's AP-485 (11/03).
1049     //
1050     // 00h Null
1051     // 01h Instruction TLB: 4K-byte Pages, 4-way set associative, 32 entries
1052     // 02h Instruction TLB: 4M-byte Pages, fully associative, 2 entries
1053     // 03h Data TLB: 4K-byte Pages, 4-way set associative, 64 entries
1054     // 04h Data TLB: 4M-byte Pages, 4-way set associative, 8 entries
1055     // 06h 1st-level instruction cache: 8K-bytes, 4-way set associative, 32 byte line size
1056     // 08h 1st-level instruction cache: 16K-bytes, 4-way set associative, 32 byte line size
1057     // 0Ah 1st-level data cache: 8K-bytes, 2-way set associative, 32 byte line size
1058     // 0Ch 1st-level data cache: 16K-bytes, 4-way set associative, 32 byte line size
1059     // 22h 3rd-level cache: 512K-bytes, 4-way set associative, sectored cache, 64-byte line size
1060     // 23h 3rd-level cache: 1M-bytes, 8-way set associative, sectored cache, 64-byte line size
1061     // 25h 3rd-level cache: 2MB, 8-way set associative, sectored cache, 64-byte line size
1062     // 29h 3rd-level cache: 4MB, 8-way set associative, sectored cache, 64-byte line size
1063     // 2Ch 1st-level data cache: 32K-bytes, 8-way set associative, 64-byte line size
1064     // 30h 1st-level instruction cache: 32K-bytes, 8-way set associative, 64-byte line size
1065     // 39h 2nd-level cache: 128K-bytes, 4-way set associative, sectored cache, 64-byte line size
1066     // 3Bh 2nd-level cache: 128KB, 2-way set associative, sectored cache, 64-byte line size
1067     // 3Ch 2nd-level cache: 256K-bytes, 4-way set associative, sectored cache, 64-byte line size
1068     // 40h No 2nd-level cache or, if processor contains a valid 2nd-level cache, no3rd-level cache
1069     // 41h 2nd-level cache: 128K-bytes, 4-way set associative, 32 byte line size
1070     // 42h 2nd-level cache: 256K-bytes, 4-way set associative, 32 byte line size
1071     // 43h 2nd-level cache: 512K-bytes, 4-way set associative, 32 byte line size
1072     // 44h 2nd-level cache: 1M-bytes, 4-way set associative, 32 byte line size
1073     // 45h 2nd-level cache: 2M-bytes, 4-way set associative, 32 byte line size
1074     // 50h Instruction TLB: 4K, 2M or 4M pages, fully associative, 64 entries
1075     // 51h Instruction TLB: 4K, 2M or 4M pages, fully associative, 128 entries
1076     // 52h Instruction TLB: 4K, 2M or 4M pages, fully associative, 256 entries
1077     // 5Bh Data TLB: 4K or 4M pages, fully associative, 64 entries
1078     // 5Ch Data TLB: 4K or 4M pages, fully associative, 128 entries
1079     // 5Dh Data TLB: 4K or 4M pages, fully associative, 256 entries
1080     // 66h 1st-level data cache: 8K-bytes, 4-way set associative, sectored cache, 64-byte line size
1081     // 67h 1st-level data cache: 16K-bytes, 4-way set associative, sectored cache, 64-byte line size
1082     // 68h 1st-level data cache: 32K-bytes, 4 way set associative, sectored cache, 64-byte line size
1083     // 70h Trace cache: 12K-uops, 8-way set associative
1084     // 71h Trace cache: 16K-uops, 8-way set associative
1085     // 72h Trace cache: 32K-uops, 8-way set associative
1086     // 79h 2nd-level cache: 128K-bytes, 8-way set associative, sectored cache, 64-byte line size
1087     // 7Ah 2nd-level cache: 256K-bytes, 8-way set associative, sectored cache, 64-byte line size
1088     // 7Bh 2nd-level cache: 512K-bytes, 8-way set associative, sectored cache, 64-byte line size
1089     // 7Ch 2nd-level cache: 1M-bytes, 8-way set associative, sectored cache, 64-byte line size
1090     // 82h 2nd-level cache: 256K-bytes, 8-way set associative, 32 byte line size
1091     // 83h 2nd-level cache: 512K-bytes, 8-way set associative, 32 byte line size
1092     // 84h 2nd-level cache: 1M-bytes, 8-way set associative, 32 byte line size
1093     // 85h 2nd-level cache: 2M-bytes, 8-way set associative, 32 byte line size
1094     // 86h 2nd-level cache: 512K-bytes, 4-way set associative, 64 byte line size
1095     // 87h 2nd-level cache: 1M-bytes, 8-way set associative, 64 byte line size
1096     // B0h Instruction TLB: 4K-byte Pages, 4-way set associative, 128 entries
1097     // B3h Data TLB: 4K-byte Pages, 4-way set associative, 128 entries
1098     //
1099     // From Intel via Michael Diamond (under NDA):
1100     // Fixes bug 75982 - Reporting incorrect cache info on Banias mobile platform.
1101     //
1102     // 7D 2M; 8 way; 64 byte line size; unified on-die
1103     // 78 1M; 8 way; 64 byte line size, unified on-die
1104     //
1105     // Note: Newer GPUs have added an additional cache level.  What used to be L2 is
1106     // now L3.  Set the L2 cache to the largest L2 or L3 descriptor found.
1107 
1108     switch (cacheEntry)
1109     {
1110         case 0x0A: // 1st-level data cache: 8K-bytes, 2-way set associative, 32 byte line size
1111             pSys->cpuInfo.l1DataCacheSize = 8;
1112             pSys->cpuInfo.dataCacheLineSize = 32;
1113             break;
1114 
1115         case 0x0C: // 1st-level data cache: 16K-bytes, 4-way set associative, 32 byte line size
1116             pSys->cpuInfo.l1DataCacheSize = 16;
1117             pSys->cpuInfo.dataCacheLineSize = 32;
1118             break;
1119 
1120         case 0x66: // 1st-level data cache: 8K-bytes, 4-way set associative, sectored cache, 64-byte line size
1121             pSys->cpuInfo.l1DataCacheSize = 8;
1122             pSys->cpuInfo.dataCacheLineSize = 64;
1123             break;
1124 
1125         case 0x67: // 1st-level data cache: 16K-bytes, 4-way set associative, sectored cache, 64-byte line size
1126             pSys->cpuInfo.l1DataCacheSize = 16;
1127             pSys->cpuInfo.dataCacheLineSize = 64;
1128             break;
1129 
1130         case 0x2C: // 1st-level data cache: 32K-bytes, 8-way set associative, 64-byte line size
1131         case 0x68: // 1st-level data cache: 32K-bytes, 4 way set associative, sectored cache, 64-byte line size
1132             pSys->cpuInfo.l1DataCacheSize = 32;
1133             pSys->cpuInfo.dataCacheLineSize = 64;
1134             break;
1135 
1136         case 0x41: // 2nd-level cache: 128K-bytes, 4-way set associative, 32 byte line size
1137             pSys->cpuInfo.dataCacheLineSize = 32;
1138             if (pSys->cpuInfo.l2DataCacheSize < 128)
1139                 pSys->cpuInfo.l2DataCacheSize = 128;
1140             break;
1141 
1142         case 0x39: // 2nd-level cache: 128K-bytes, 4-way set associative, sectored cache, 64-byte line size
1143         case 0x3B: // 2nd-level cache: 128KB, 2-way set associative, sectored cache, 64-byte line size
1144         case 0x79: // 2nd-level cache: 128K-bytes, 8-way set associative, sectored cache, 64-byte line size
1145             pSys->cpuInfo.dataCacheLineSize = 64;
1146             if (pSys->cpuInfo.l2DataCacheSize < 128)
1147                 pSys->cpuInfo.l2DataCacheSize = 128;
1148             break;
1149 
1150         case 0x42: // 2nd-level cache: 256K-bytes, 4-way set associative, 32 byte line size
1151         case 0x82: // 2nd-level cache: 256K-bytes, 8-way set associative, 32 byte line size
1152             pSys->cpuInfo.dataCacheLineSize = 32;
1153             if (pSys->cpuInfo.l2DataCacheSize < 256)
1154                 pSys->cpuInfo.l2DataCacheSize = 256;
1155             break;
1156 
1157         case 0x3C: // 2nd-level cache: 256K-bytes, 4-way set associative, sectored cache, 64-byte line size
1158         case 0x7A: // 2nd-level cache: 256K-bytes, 8-way set associative, sectored cache, 64-byte line size
1159             pSys->cpuInfo.dataCacheLineSize = 64;
1160             if (pSys->cpuInfo.l2DataCacheSize < 256)
1161                 pSys->cpuInfo.l2DataCacheSize = 256;
1162             break;
1163 
1164         case 0x43: // 2nd-level cache: 512K-bytes, 4-way set associative, 32 byte line size
1165         case 0x83: // 2nd-level cache: 512K-bytes, 8-way set associative, 32 byte line size
1166             pSys->cpuInfo.dataCacheLineSize = 32;
1167             if (pSys->cpuInfo.l2DataCacheSize < 512)
1168                 pSys->cpuInfo.l2DataCacheSize = 512;
1169             break;
1170 
1171         case 0x22: // 3rd-level cache: 512K-bytes, 4-way set associative, sectored cache, 64-byte line size
1172         case 0x7B: // 2nd-level cache: 512K-bytes, 8-way set associative, sectored cache, 64-byte line size
1173         case 0x86: // 2nd-level cache: 512K-bytes, 4-way set associative, 64 byte line size
1174             pSys->cpuInfo.dataCacheLineSize = 64;
1175             if (pSys->cpuInfo.l2DataCacheSize < 512)
1176                 pSys->cpuInfo.l2DataCacheSize = 512;
1177             break;
1178 
1179         case 0x44: // 2nd-level cache: 1M-bytes, 4-way set associative, 32 byte line size
1180         case 0x84: // 2nd-level cache: 1M-bytes, 8-way set associative, 32 byte line size
1181             pSys->cpuInfo.dataCacheLineSize = 32;
1182             if (pSys->cpuInfo.l2DataCacheSize < 1024)
1183                 pSys->cpuInfo.l2DataCacheSize = 1024;
1184             break;
1185 
1186         case 0x23: // 3rd-level cache: 1M-bytes, 8-way set associative, sectored cache, 64-byte line size
1187         case 0x78: // 1M; 8 way; 64 byte line size, unified on-die
1188         case 0x7C: // 2nd-level cache: 1M-bytes, 8-way set associative, sectored cache, 64-byte line size
1189         case 0x87: // 2nd-level cache: 1M-bytes, 8-way set associative, 64 byte line size
1190             pSys->cpuInfo.dataCacheLineSize = 64;
1191             if (pSys->cpuInfo.l2DataCacheSize < 1024)
1192                 pSys->cpuInfo.l2DataCacheSize = 1024;
1193             break;
1194 
1195         case 0x45: // 2nd-level cache: 2M-bytes, 4-way set associative, 32 byte line size
1196         case 0x85: // 2nd-level cache: 2M-bytes, 8-way set associative, 32 byte line size
1197             pSys->cpuInfo.dataCacheLineSize = 32;
1198             if (pSys->cpuInfo.l2DataCacheSize < 2048)
1199                 pSys->cpuInfo.l2DataCacheSize = 2048;
1200             break;
1201 
1202         case 0x25: // 3rd-level cache: 2MB, 8-way set associative, sectored cache, 64-byte line size
1203         case 0x7D: // 2M; 8 way; 64 byte line size; unified on-die
1204             pSys->cpuInfo.dataCacheLineSize = 64;
1205             if (pSys->cpuInfo.l2DataCacheSize < 2048)
1206                 pSys->cpuInfo.l2DataCacheSize = 2048;
1207             break;
1208 
1209         case 0x29: // 3rd-level cache: 4MB, 8-way set associative, sectored cache, 64-byte line size
1210             pSys->cpuInfo.dataCacheLineSize = 64;
1211             if (pSys->cpuInfo.l2DataCacheSize < 4096)
1212                 pSys->cpuInfo.l2DataCacheSize = 4096;
1213             break;
1214     }
1215 }
1216 
DecodeIntelCacheRegister(OBJSYS * pSys,NvU32 cacheRegister)1217 static void DecodeIntelCacheRegister(OBJSYS *pSys, NvU32 cacheRegister /* punny, huh? */)
1218 {
1219     if ((cacheRegister & NVBIT(31)) == 0)  // If bit 31 is set, it is reserved.
1220     {
1221         DecodeIntelCacheEntry(pSys, (NvU8)(cacheRegister >> 24));
1222         DecodeIntelCacheEntry(pSys, (NvU8)(cacheRegister >> 16));
1223         DecodeIntelCacheEntry(pSys, (NvU8)(cacheRegister >> 8));
1224         DecodeIntelCacheEntry(pSys, (NvU8)cacheRegister);
1225     }
1226 }
1227 #endif
1228 
cpuidInfoIntel(OBJSYS * pSys,PCPUIDINFO pCpuidInfo)1229 static void cpuidInfoIntel(OBJSYS *pSys, PCPUIDINFO pCpuidInfo)
1230 {
1231     NvU32   eax, ebx, ecx, edx;
1232     OBJOS  *pOS = SYS_GET_OS(pSys);
1233 
1234     if (pCpuidInfo->Family == 5)
1235     {
1236         if (pCpuidInfo->Model == 4)
1237             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_P55;
1238         else
1239             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_P5;
1240     }
1241     else if (pCpuidInfo->Family == 6)
1242     {
1243         switch (pCpuidInfo->DisplayedModel)
1244         {
1245             case 1:                                    // Pentium Pro
1246                 pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_P6;
1247                 break;
1248 
1249             case 3:                                    // Pentium II
1250                 pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_P2;
1251                 break;
1252 
1253             case 5:                                    // Pentium II, Pentium II Xeon, or Celeron
1254                 pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_P2XC;
1255                 break;
1256 
1257             case 6:                                    // Pentium II Celeron-A
1258                 pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_CELA;
1259                 break;
1260 
1261             case 7:                                    // Pentium III or Pentium III Xeon (Katmai)
1262                 pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_P3;
1263                 break;
1264 
1265             case 15:                                   // Conroe, Core2 Duo
1266                 pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_CORE2;
1267                 break;
1268 
1269             case 22:                                   // Celeron model 16h (65nm)
1270                 pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_CELN_M16H;
1271                 break;
1272 
1273             case 23:                                   // Intel Core2 Extreme/Intel Xeon model 17h (45nm)
1274                 pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_CORE2_EXTRM;
1275                 break;
1276 
1277             case 28:
1278                 pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_ATOM;
1279                 break;
1280 
1281             case 143:                                  // Intel Xeon Sapphire Rapids(SPR) model 143
1282                 pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_XEON_SPR;
1283                 break;
1284 
1285             case 8:                                    // Pentium III, Pentium III Xeon, or Celeron (Coppermine, 0.18 micron)
1286             case 10:                                   // Pentium III Xeon (Tualatin, 0.13 micron)
1287             case 11:                                   // Pentium III, or Celeron (Tualatin, 0.13 micron)
1288             default:                                   // If it is a new family 6, it is a Pentium III of some type.
1289                 pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_P3_INTL2;
1290                 break;
1291         }
1292         // Flag processors that may be affected by bug 124888.  At this time,
1293         // we believe these are Pentium III and Pentium M processors.  The
1294         // model numbers for these processors in Family 6 are:
1295         //   7 - Pentium III or Pentium III Xeon
1296         //   8 - Pentium III, Pentium III Xeon, or Celeron
1297         //   9 - Pentium M
1298         //  10 - Pentium III Xeon
1299         //  11 - Pentium III
1300         //  12 - ???
1301         //  13 - Pentium M ("Dothan")
1302         //  14 - ???
1303         //  15 - Core 2 (bug 272047)
1304         if (pCpuidInfo->Model >= 7)
1305         {
1306             pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_NEEDS_WAR_124888;
1307         }
1308     }
1309     else if (pCpuidInfo->Family == 0x0F)
1310     {
1311         // Model 0 & 1 == Pentium 4 or Pentium 4 Xeon (Willamette, 423 or 478-pin packages, 0.18 micron)
1312         // Model 2 == Pentium 4 or Pentium 4 Xeon (Northwood, 478-pin package for brookdale, 0.13 micron)
1313         //
1314         // Be careful if you change this.  Both D3D and OpenGL are enabling
1315         // performance options based on NV0000_CTRL_SYSTEM_CPU_TYPE_P4.
1316         //
1317         pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_P4;
1318 
1319         // The first P4s (pre-Northwood ones) have a performance problem
1320         // when mixing write combined and cached writes. This is fixed
1321         // with model revision 2.
1322         if ((pCpuidInfo->Model == 0) || (pCpuidInfo->Model == 1))
1323         {
1324             pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_NEEDS_WC_WORKAROUND;
1325         }
1326     }
1327 
1328     if (pCpuidInfo->Family == 0xF || (pCpuidInfo->Family == 6 && pCpuidInfo->Model >= 7))
1329     {
1330         if (pOS->osNv_cpuid(pOS, 0x17, 0, &eax, &ebx, &ecx, &edx))
1331             pSys->cpuInfo.platformID = (edx >> 18) & 7;        // edx[20:18]   PlatformID (package type)
1332     }
1333 
1334     // Decode the cache desciptors.
1335     if (!DecodePrescottCache(pSys))
1336     {
1337 #if defined(_M_IX86) || defined(NVCPU_X86)
1338 
1339         // Prescott style cache descriptors are not supported.  Fall back to older style.
1340         //
1341         if (pOS->osNv_cpuid(pOS, 0, 0, &eax, &ebx, &ecx, &edx))
1342         {
1343             if (eax >= 2)                    // CPU support old cache descrtiptors?
1344             {
1345                 pOS->osNv_cpuid(pOS, 2, 0, &eax, &ebx, &ecx, &edx);
1346 
1347                 if ((eax & 0xff) == 1)  // AL contains number of times CPU must be called.  This will be 1 forever.
1348                 {
1349                     DecodeIntelCacheRegister(pSys, eax & 0xffffff00);
1350                     DecodeIntelCacheRegister(pSys, ebx);
1351                     DecodeIntelCacheRegister(pSys, ecx);
1352                     DecodeIntelCacheRegister(pSys, edx);
1353                 }
1354             }
1355         }
1356 #endif
1357     }
1358 }
1359 
cpuidInfoAMD(OBJSYS * pSys,PCPUIDINFO pCpuidInfo)1360 static void cpuidInfoAMD(OBJSYS *pSys, PCPUIDINFO pCpuidInfo)
1361 {
1362     NvU32   eax = 0;
1363     NvU32   ebx = 0;
1364     NvU32   ecx = 0;
1365     NvU32   edx = 0;
1366 
1367     OBJOS  *pOS = SYS_GET_OS(pSys);
1368     NvU32 largestExtendedFunctionNumberSupported = 0x80000000;
1369 
1370     if (pCpuidInfo->Family == 5)                // K5, K6, K6-2 with 3DNow, K6-3
1371     {
1372         if (pCpuidInfo->Model < 6)
1373             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_K5;
1374         else if (pCpuidInfo->Model < 8)
1375             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_K6;
1376         else if (pCpuidInfo->Model == 8)
1377             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_K62;
1378         else if (pCpuidInfo->Model == 9)
1379             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_K63;
1380     }
1381     else if (pCpuidInfo->Family == 6)           // K7
1382     {
1383         // Family 6 is a mixture of Athlon and Duron processors.  Just set the
1384         // processor type to Athlon.  The processor name will show the branding.
1385         pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_K7;
1386     }
1387     else if (pCpuidInfo->Family == 15)          // K8
1388     {
1389         // If family is 15, we need to use AMD's extended family/model information.
1390         pOS->osNv_cpuid(pOS, 1, 0, &eax, &ebx, &ecx, &edx);
1391         pCpuidInfo->Family = (NvU16)(((eax >> 8) & 0x0F) + ((eax >> 16) & 0xFF0));  // 27:20 concat 11:8
1392         pCpuidInfo->Model  = (NvU8) (((eax >> 4) & 0x0F) + ((eax >> 12) & 0xF0));   // 19:16 concat 7:4
1393 
1394         // Differentiate K8, K10, K11, RYZEN, etc
1395         switch( pCpuidInfo->Family & 0xFF0)
1396         {
1397             case 0x000:
1398                 pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_K8;
1399                 break;
1400             case 0x010:
1401                 pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_K10;
1402                 break;
1403             case 0x020:
1404                 pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_K11;
1405                 break;
1406             case 0x080:
1407                 // Zen, Zen+, Zen 2
1408             case 0x0A0:
1409                 // Zen 3, Zen 4
1410                 pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_RYZEN;
1411                 break;
1412             default:
1413                 NV_PRINTF(LEVEL_ERROR,
1414                           "Unrecognized AMD processor in cpuidInfoAMD\n");
1415                 pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_K8;
1416                 break;
1417         }
1418     }
1419 
1420     if (pCpuidInfo->ExtendedFeatures & CPU_EXT_3DNOW)
1421         pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_3DNOW;      // 3DNow
1422 
1423     if (pCpuidInfo->ExtendedFeatures & CPU_EXT_AMD_3DNOW_EXT)
1424         pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_3DNOW_EXT;  // 3DNow, with Extensions (AMD specific)
1425 
1426     if (pCpuidInfo->ExtendedFeatures & CPU_EXT_AMD_MMX_EXT)
1427     {
1428         pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_MMX_EXT;    // MMX, with Extensions (AMD specific)
1429         pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_SFENCE;
1430     }
1431 
1432     // Get the cache info.
1433     if (pOS->osNv_cpuid(pOS, 0x80000000, 0, &eax, &ebx, &ecx, &edx))
1434     {
1435         largestExtendedFunctionNumberSupported = eax;
1436 
1437         if (largestExtendedFunctionNumberSupported >= 0x80000006)
1438         {
1439             // L1 cache
1440             if (pOS->osNv_cpuid(pOS, 0x80000005, 0, &eax, &ebx, &ecx, &edx))
1441             {
1442                 pSys->cpuInfo.dataCacheLineSize = ecx & 0xff;
1443                 pSys->cpuInfo.l1DataCacheSize = ecx >> 24;
1444             }
1445 
1446             // L2 cache
1447             if (pOS->osNv_cpuid(pOS, 0x80000006, 0, &eax, &ebx, &ecx, &edx))
1448                 pSys->cpuInfo.l2DataCacheSize = ecx >> 16;
1449         }
1450 
1451         // Get the SEV capability info
1452         if ((largestExtendedFunctionNumberSupported >= 0x8000001f) &&
1453             pOS->osNv_cpuid(pOS, 0x8000001f, 0, &eax, &ebx, &ecx, &edx))
1454         {
1455             //
1456             // EAX[1] stores capability info
1457             // ECX[31:0] stores # of encrypted guests supported simultaneously
1458             //
1459             if (eax & 0x2)
1460             {
1461                 pSys->cpuInfo.bSEVCapable = NV_TRUE;
1462                 pSys->cpuInfo.maxEncryptedGuests = ecx;
1463             }
1464         }
1465     }
1466 }
1467 
1468 
1469 #if defined(_M_IX86) || defined(NVCPU_X86)
1470 
cpuidInfoWinChip(OBJSYS * pSys,PCPUIDINFO pCpuidInfo)1471 static void cpuidInfoWinChip(OBJSYS *pSys, PCPUIDINFO pCpuidInfo)
1472 {
1473     if (pCpuidInfo->Family == 5)                // Winchip C6, Winchip2 w/ 3DNow
1474     {
1475         if (pCpuidInfo->Model == 4)
1476             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_C6;
1477         if (pCpuidInfo->Model == 8)
1478             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_C62;
1479     }
1480 
1481     if (pCpuidInfo->ExtendedFeatures & CPU_EXT_3DNOW)
1482         pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_3DNOW;
1483 }
1484 
cpuidInfoCyrix(OBJSYS * pSys,PCPUIDINFO pCpuidInfo)1485 static void cpuidInfoCyrix(OBJSYS *pSys, PCPUIDINFO pCpuidInfo)
1486 {
1487     if (pCpuidInfo->Family == 4)                // MediaGX
1488         pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_GX;
1489     if (pCpuidInfo->Family == 5)                // Cyrix 6x86 or MediaGX w/ MMX
1490     {
1491         if (pCpuidInfo->Model == 2)
1492             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_M1;
1493         if (pCpuidInfo->Model == 4)
1494             pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_MGX;
1495     }
1496     if (pCpuidInfo->Family == 6)                // Cyrix MII
1497         pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_M2;
1498 
1499     if (pCpuidInfo->ExtendedFeatures & CPU_EXT_3DNOW)
1500         pSys->cpuInfo.caps |= NV0000_CTRL_SYSTEM_CPU_CAP_3DNOW;
1501 }
1502 
cpuidInfoTransmeta(OBJSYS * pSys,PCPUIDINFO pCpuidInfo)1503 static void cpuidInfoTransmeta(OBJSYS *pSys, PCPUIDINFO pCpuidInfo)
1504 {
1505     NvU32 eax, ebx, ecx, edx;
1506     OBJOS *pOS = SYS_GET_OS(pSys);
1507 
1508     //
1509     // Transmeta allows the OEM to program the foundry, family, model, and stepping.  Arrrrgh...
1510     // If this turns out to be a problem, we will need to use one of the extended CPUID calls to
1511     // get the real info.
1512     //
1513 
1514     // Docs were not real clear on which family/model.  Just assume it's a Crusoe
1515     pSys->cpuInfo.type = NV0000_CTRL_SYSTEM_CPU_TYPE_TM_CRUSOE;
1516 
1517     //
1518     // Get the cache info.  From preliminary TM8000 programming and config guide, 2/19/03
1519     // This appears to match AMD's cache CPUID definitions.
1520     //
1521     if (pOS->osNv_cpuid(pOS, 0x80000000, 0, &eax, &ebx, &ecx, &edx) && eax >= 0x80000006)
1522     {
1523         // L1 Cache
1524         if (pOS->osNv_cpuid(pOS, 0x80000005, 0, &eax, &ebx, &ecx, &edx))
1525         {
1526             pSys->cpuInfo.dataCacheLineSize = ecx & 0xff;
1527             pSys->cpuInfo.l1DataCacheSize = ecx >> 24;
1528         }
1529 
1530         // L2 Cache
1531         if (pOS->osNv_cpuid(pOS, 0x80000006, 0, &eax, &ebx, &ecx, &edx))
1532             pSys->cpuInfo.l2DataCacheSize = ecx >> 16;
1533     }
1534 }
1535 
1536 #endif // defined(_M_IX86) || defined(NVCPU_X86)
1537 
1538 #endif // defined(_M_IX86) || defined(NVCPU_X86) || defined(AMD64) || defined(NVCPU_X86_64)
1539 
1540 #endif // NVCPU_IS_X86 || NVCPU_IS_X86_64
1541