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