The OpenD Programming Language

1 /++
2 $(H2 Intel 64 and IA-32 CPUID Information)
3 
4 $(GREEN This module is available for betterC compilation mode.)
5 
6 References:
7     Intel® 64 and IA-32 Architectures Software Developer’s Manual
8 
9 License:   $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
10 
11 Authors:   Ilia Ki
12 +/
13 module cpuid.intel;
14 
15 version(X86)
16     version = X86_Any;
17 else
18 version(X86_64)
19     version = X86_Any;
20 
21 version(X86_Any):
22 
23 public import cpuid.x86_any;
24 
25 /++
26 TLB and Cache information.
27 
28 For convinient Cache information see also $(MREF Leaf4Information).
29 
30 Specification: Intel
31 +/
32 struct Leaf2Information
33 {
34     /// Level-1 instuciton cache
35     Cache il1;
36     /// Level-2 data cache
37     Cache l1;
38     /// Level-2 unified cache
39     Cache l2;
40     /// Level-2 unified cache
41     Cache l3;
42     /// Intruction TLB
43     Tlb itlb;
44     /// Intruction TLB, huge pages
45     Tlb hitlb;
46     /// Data TLB
47     Tlb dtlb;
48     /// Data TLB, huge pages
49     Tlb hdtlb;
50     /// Data TLB, giant pages
51     Tlb gdtlb;
52     /// Data TLB1
53     Tlb dtlb1;
54     /// Data TLB1, huge pages
55     Tlb hdtlb1;
56     /// Second-level unified TLB
57     Tlb utlb;
58     /// Second-level unified TLB, huge pages
59     Tlb hutlb;
60     /// Second-level unified TLB, giant pages
61     Tlb gutlb;
62     /// prefetch line size
63     int prefetch;
64     /// Cache trace
65     int trace;
66     /// `true` if CPUID leaf 2 does not report cache descriptor information. use CPUID leaf 4 to query cache parameters.
67     bool noCacheInfo;
68     // No 2nd-level cache or, if processor contains a valid 2nd-level cache, no 3rd-level cache
69     bool noL2Or3;
70 
71     /+
72     Dencoding of CPUID Leaf 2 Descriptors.
73 
74     Note: 
75 
76     Specification: Intel
77     +/
78     nothrow @nogc pure
79     this()(CpuInfo info)
80     {
81         version(BigEndian) static assert(0, "Leaf2Information is not implemented for BigEndian.");
82 
83         foreach(i, b; (*(cast(ubyte[16]*)&info))[1..$])
84         switch(b)
85         {
86             default:
87                 break;
88             case 0x00:
89                 // General     Null descriptor, this byte contains no information
90                 break;
91             case 0x01:
92                 itlb.page = 4;
93                 itlb.associative = 4;
94                 itlb.entries = 32;
95                 break;
96             case 0x02:
97                 hitlb.page = 4 * 1024;
98                 hitlb.associative = hitlb.associative.max;
99                 hitlb.entries = 2;
100                 break;
101             case 0x03:
102                 dtlb.page = 4;
103                 dtlb.associative = 4;
104                 dtlb.entries = 64;
105                 break;
106             case 0x04:
107                 hdtlb.page = 4 * 1024;
108                 hdtlb.associative = 4;
109                 hdtlb.entries = 8;
110                 break;
111             case 0x05:
112                 hdtlb1.page = 4 * 1024;
113                 hdtlb1.associative = 4;
114                 hdtlb1.entries = 32;
115                 break;
116             case 0x06:
117                 il1.size = 8;
118                 il1.associative = 4;
119                 il1.line = 32;
120                 break;
121             case 0x08:
122                 il1.size = 16;
123                 il1.associative = 4;
124                 il1.line = 32;
125                 break;
126             case 0x09:
127                 il1.size = 32;
128                 il1.associative = 4;
129                 il1.line = 64;
130                 break;
131             case 0x0A:
132                 l1.size = 8;
133                 l1.associative = 2;
134                 l1.line = 32;
135                 break;
136             case 0x0B:
137                 hitlb.page = 4 * 1024;
138                 hitlb.associative = 4;
139                 hitlb.entries = 4;
140                 break;
141             case 0x0C:
142                 l1.size = 16;
143                 l1.associative = 4;
144                 l1.line = 32;
145                 break;
146             case 0x0D:
147                 l1.size = 16;
148                 l1.associative = 4;
149                 l1.line = 64;
150                 break;
151             case 0x0E:
152                 l1.size = 24;
153                 l1.associative = 6;
154                 l1.line = 64;
155                 break;
156             case 0x1D:
157                 l2.size = 128;
158                 l2.associative = 2;
159                 l2.line = 64;
160                 break;
161             case 0x21:
162                 l2.size = 256;
163                 l2.associative = 8;
164                 l2.line = 64;
165                 break;
166             case 0x22:
167                 l3.size = 512;
168                 l3.associative = 4;
169                 l3.line = 64;
170                 break;
171             case 0x23:
172                 l3.size = 1 * 1024;
173                 l3.associative = 8;
174                 l3.line = 64;
175                 break;
176             case 0x24:
177                 l2.size = 1 * 1024;
178                 l2.associative = 16;
179                 l2.line = 64;
180                 break;
181             case 0x25:
182                 l3.size = 2 * 1024;
183                 l3.associative = 8;
184                 l3.line = 64;
185                 break;
186             case 0x29:
187                 l3.size = 4 * 1024;
188                 l3.associative = 8;
189                 l3.line = 64;
190                 break;
191             case 0x2C:
192                 l1.size = 32;
193                 l1.associative = 8;
194                 l1.line = 64;
195                 break;
196             case 0x30:
197                 il1.size = 32;
198                 il1.associative = 8;
199                 il1.line = 64;
200                 break;
201             case 0x40:
202                 noL2Or3 = true;
203                 break;
204             case 0x41:
205                 l2.size = 128;
206                 l2.associative = 4;
207                 l2.line = 32;
208                 break;
209             case 0x42:
210                 l2.size = 256;
211                 l2.associative = 4;
212                 l2.line = 32;
213                 break;
214             case 0x43:
215                 l2.size = 512;
216                 l2.associative = 4;
217                 l2.line = 32;
218                 break;
219             case 0x44:
220                 l2.size = 1 * 1024;
221                 l2.associative = 4;
222                 l2.line = 32;
223                 break;
224             case 0x45:
225                 l2.size = 2 * 1024;
226                 l2.associative = 4;
227                 l2.line = 32;
228                 break;
229             case 0x46:
230                 l3.size = 4 * 1024;
231                 l3.associative = 4;
232                 l3.line = 64;
233                 break;
234             case 0x47:
235                 l3.size = 8 * 1024;
236                 l3.associative = 8;
237                 l3.line = 64;
238                 break;
239             case 0x48:
240                 l2.size = 3 * 1024;
241                 l2.associative = 12;
242                 l2.line = 64;
243                 break;
244             case 0x49:
245                 if(family == 0x0F && model == 0x06)
246                 {
247                     l3.size = 4 * 1024;
248                     l3.associative = 16;
249                     l3.line = 64;
250                     break;
251                 }
252                 l2.size = 4 * 1024;
253                 l2.associative = 16;
254                 l2.line = 64;
255                 break;
256             case 0x4A:
257                 l3.size = 6 * 1024;
258                 l3.associative = 12;
259                 l3.line = 64;
260                 break;
261             case 0x4B:
262                 l3.size = 8 * 1024;
263                 l3.associative = 16;
264                 l3.line = 64;
265                 break;
266             case 0x4C:
267                 l3.size = 12 * 1024;
268                 l3.associative = 12;
269                 l3.line = 64;
270                 break;
271             case 0x4D:
272                 l3.size = 16 * 1024;
273                 l3.associative = 16;
274                 l3.line = 64;
275                 break;
276             case 0x4E:
277                 l2.size = 6 * 1024;
278                 l2.associative = 24;
279                 l2.line = 64;
280                 break;
281             case 0x4F:
282                 itlb.page = 4;
283                 itlb.associative = 1;
284                 itlb.entries = 32;
285                 break;
286             case 0x50:
287                 itlb.page = 4;
288                 itlb.associative = 1;
289                 itlb.entries = 64;
290                 hitlb.page = 2 * 1024;
291                 hitlb.associative = 1;
292                 hitlb.entries = 64;
293                 break;
294             case 0x51:
295                 itlb.page = 4;
296                 itlb.associative = 1;
297                 itlb.entries = 128;
298                 hitlb.page = 2 * 1024;
299                 hitlb.associative = 1;
300                 hitlb.entries = 128;
301                 break;
302             case 0x52:
303                 itlb.page = 4;
304                 itlb.associative = 1;
305                 itlb.entries = 256;
306                 hitlb.page = 2 * 1024;
307                 hitlb.associative = 1;
308                 hitlb.entries = 256;
309                 break;
310             case 0x55:
311                 itlb.page = 2 * 1024;
312                 itlb.associative = itlb.associative.max;
313                 itlb.entries = 7;
314                 break;
315             case 0x56:
316                 hdtlb.page = 4 * 1024;
317                 hdtlb.associative = 4;
318                 hdtlb.entries = 16;
319                 break;
320             case 0x57:
321                 dtlb.page = 4;
322                 dtlb.associative = 4;
323                 dtlb.entries = 16;
324                 break;
325             case 0x59:
326                 dtlb.page = 4;
327                 dtlb.associative = dtlb.associative.max;
328                 dtlb.entries = 16;
329                 break;
330             case 0x5A:
331                 hdtlb.page = 2 * 1024;
332                 hdtlb.associative = 4;
333                 hdtlb.entries = 32;
334                 break;
335             case 0x5B:
336                 dtlb.page = 4;
337                 dtlb.associative = 1;
338                 dtlb.entries = 64;
339                 hdtlb.page = 4 * 1024;
340                 hdtlb.associative = 1;
341                 hdtlb.entries = 64;
342                 break;
343             case 0x5C:
344                 dtlb.page = 4;
345                 dtlb.associative = 1;
346                 dtlb.entries = 128;
347                 hdtlb.page = 4 * 1024;
348                 hdtlb.associative = 1;
349                 hdtlb.entries = 128;
350                 break;
351             case 0x5D:
352                 dtlb.page = 4;
353                 dtlb.associative = 1;
354                 dtlb.entries = 256;
355                 hdtlb.page = 4 * 1024;
356                 hdtlb.associative = 1;
357                 hdtlb.entries = 256;
358                 break;
359             case 0x60:
360                 l1.size = 16;
361                 l1.associative = 8;
362                 l1.line = 64;
363                 break;
364             case 0x61:
365                 itlb.page = 4;
366                 itlb.associative = itlb.associative.max;
367                 itlb.entries = 48;
368                 break;
369             case 0x63:
370                 hdtlb.page = 2 * 1024;
371                 hdtlb.associative = 4;
372                 hdtlb.entries = 32;
373                 gdtlb.page = 1024 * 1024;
374                 gdtlb.associative = 4;
375                 gdtlb.entries = 4;
376                 break;
377             case 0x64:
378                 dtlb.page = 4;
379                 dtlb.associative = 4;
380                 dtlb.entries = 512;
381                 break;
382             case 0x66:
383                 l1.size = 8;
384                 l1.associative = 4;
385                 l1.line = 64;
386                 break;
387             case 0x67:
388                 l1.size = 16;
389                 l1.associative = 4;
390                 l1.line = 64;
391                 break;
392             case 0x68:
393                 l1.size = 32;
394                 l1.associative = 4;
395                 l1.line = 64;
396                 break;
397             case 0x6A:
398                 dtlb.page = 4;
399                 dtlb.associative = 8;
400                 dtlb.entries = 64;
401                 break;
402             case 0x6B:
403                 dtlb.page = 4;
404                 dtlb.associative = 8;
405                 dtlb.entries = 256;
406                 break;
407             case 0x6C:
408                 hdtlb.page = 2 * 1024;
409                 hdtlb.associative = 8;
410                 hdtlb.entries = 128;
411                 break;
412             case 0x6D:
413                 gdtlb.page = 1024 * 1024;
414                 gdtlb.associative = gdtlb.associative.max;
415                 gdtlb.entries = 16;
416                 break;
417             case 0x70:
418                 trace = 12;
419                 break;
420             case 0x71:
421                 trace = 16;
422                 break;
423             case 0x72:
424                 trace = 32;
425                 break;
426             case 0x76:
427                 itlb.page = 2 * 1024;
428                 itlb.associative = itlb.associative.max;
429                 itlb.entries = 8;
430                 break;
431             case 0x78:
432                 l2.size = 1 * 1024;
433                 l2.associative = 4;
434                 l2.line = 6;
435                 break;
436             case 0x79:
437                 l2.size = 128;
438                 l2.associative = 8;
439                 l2.line = 64;
440                 break;
441             case 0x7A:
442                 l2.size = 256;
443                 l2.associative = 8;
444                 l2.line = 64;
445                 break;
446             case 0x7B:
447                 l2.size = 512;
448                 l2.associative = 8;
449                 l2.line = 64;
450                 break;
451             case 0x7C:
452                 l2.size = 1 * 1024;
453                 l2.associative = 8;
454                 l2.line = 64;
455                 break;
456             case 0x7D:
457                 l2.size = 2 * 1024;
458                 l2.associative = 8;
459                 l2.line = 6;
460                 break;
461             case 0x7F:
462                 l2.size = 512;
463                 l2.associative = 2;
464                 l2.line = 64;
465                 break;
466             case 0x80:
467                 l2.size = 512;
468                 l2.associative = 8;
469                 l2.line = 64;
470                 break;
471             case 0x82:
472                 l2.size = 256;
473                 l2.associative = 8;
474                 l2.line = 32;
475                 break;
476             case 0x83:
477                 l2.size = 512;
478                 l2.associative = 8;
479                 l2.line = 32;
480                 break;
481             case 0x84:
482                 l2.size = 1 * 1024;
483                 l2.associative = 8;
484                 l2.line = 32;
485                 break;
486             case 0x85:
487                 l2.size = 2 * 1024;
488                 l2.associative = 8;
489                 l2.line = 32;
490                 break;
491             case 0x86:
492                 l2.size = 512;
493                 l2.associative = 4;
494                 l2.line = 64;
495                 break;
496             case 0x87:
497                 l2.size = 1 * 1024;
498                 l2.associative = 8;
499                 l2.line = 64;
500                 break;
501             case 0xA0:
502                 dtlb.page = 4;
503                 dtlb.associative = dtlb.associative.max;
504                 dtlb.entries = 32;
505                 break;
506             case 0xB0:
507                 itlb.page = 4;
508                 itlb.associative = 4;
509                 itlb.entries = 128;
510                 break;
511             case 0xB1:
512                 itlb.page = 2 * 1024;
513                 itlb.associative = 4;
514                 itlb.entries = 8;
515                 break;
516             case 0xB2:
517                 itlb.page = 4;
518                 itlb.associative = 4;
519                 itlb.entries = 64;
520                 break;
521             case 0xB3:
522                 dtlb.page = 4;
523                 dtlb.associative = 4;
524                 dtlb.entries = 128;
525                 break;
526             case 0xB4:
527                 dtlb1.page = 4;
528                 dtlb1.associative = 4;
529                 dtlb1.entries = 256;
530                 break;
531             case 0xB5:
532                 itlb.page = 4;
533                 itlb.associative = 8;
534                 itlb.entries = 64;
535                 break;
536             case 0xB6:
537                 itlb.page = 4;
538                 itlb.associative = 8;
539                 itlb.entries = 128;
540                 break;
541             case 0xBA:
542                 dtlb1.page = 4;
543                 dtlb1.associative = 4;
544                 dtlb1.entries = 64;
545                 break;
546             case 0xC0:
547                 dtlb.page = 4;
548                 dtlb.associative = 4;
549                 dtlb.entries = 8;
550                 hdtlb.page = 4 * 1024;
551                 hdtlb.associative = 4;
552                 hdtlb.entries = 8;
553                 break;
554             case 0xC1:
555                 utlb.page = 4;
556                 utlb.associative = 8;
557                 utlb.entries = 1024;
558                 hutlb.page = 2 * 1024;
559                 hutlb.associative = 8;
560                 hutlb.entries = 1024;
561                 break;
562             case 0xC2:
563                 dtlb.page = 4;
564                 dtlb.associative = 4;
565                 dtlb.entries = 16;
566                 hdtlb.page = 2 * 1024;
567                 hdtlb.associative = 4;
568                 hdtlb.entries = 16;
569                 break;
570             case 0xC3:
571                 utlb.page = 4;
572                 utlb.associative = 6;
573                 utlb.entries = 1536;
574                 hutlb.page = 2 * 1024;
575                 hutlb.associative = 6;
576                 hutlb.entries = 1536;
577                 gutlb.page = 1024 * 1024;
578                 gutlb.associative = 4;
579                 gutlb.entries = 16;
580                 break;
581             case 0xC4:
582                 hdtlb.page = 2 * 1024;
583                 hdtlb.associative = 4;
584                 hdtlb.entries = 32;
585                 break;
586             case 0xCA:
587                 utlb.page = 4;
588                 utlb.associative = 4;
589                 utlb.entries = 512;
590                 break;
591             case 0xD0:
592                 l3.size = 512;
593                 l3.associative = 4;
594                 l3.line = 64;
595                 break;
596             case 0xD1:
597                 l3.size = 1 * 1024;
598                 l3.associative = 4;
599                 l3.line = 64;
600                 break;
601             case 0xD2:
602                 l3.size = 2 * 1024;
603                 l3.associative = 4;
604                 l3.line = 64;
605                 break;
606             case 0xD6:
607                 l3.size = 1 * 1024;
608                 l3.associative = 8;
609                 l3.line = 64;
610                 break;
611             case 0xD7:
612                 l3.size = 2 * 1024;
613                 l3.associative = 8;
614                 l3.line = 64;
615                 break;
616             case 0xD8:
617                 l3.size = 4 * 1024;
618                 l3.associative = 8;
619                 l3.line = 64;
620                 break;
621             case 0xDC:
622                 l3.size = 1536;
623                 l3.associative = 12;
624                 l3.line = 64;
625                 break;
626             case 0xDD:
627                 l3.size = 3 * 1024;
628                 l3.associative = 12;
629                 l3.line = 64;
630                 break;
631             case 0xDE:
632                 l3.size = 6 * 1024;
633                 l3.associative = 12;
634                 l3.line = 64;
635                 break;
636             case 0xE2:
637                 l3.size = 2 * 1024;
638                 l3.associative = 16;
639                 l3.line = 64;
640                 break;
641             case 0xE3:
642                 l3.size = 4 * 1024;
643                 l3.associative = 16;
644                 l3.line = 64;
645                 break;
646             case 0xE4:
647                 l3.size = 8 * 1024;
648                 l3.associative = 16;
649                 l3.line = 64;
650                 break;
651             case 0xEA:
652                 l3.size = 12 * 1024;
653                 l3.associative = 24;
654                 l3.line = 64;
655                 break;
656             case 0xEB:
657                 l3.size = 18 * 1024;
658                 l3.associative = 24;
659                 l3.line = 64;
660                 break;
661             case 0xEC:
662                 l3.size = 24 * 1024;
663                 l3.associative = 24;
664                 l3.line = 64;
665                 break;
666             case 0xF0:
667                 // Prefetch    64-B prefetching
668                 prefetch = 64;
669                 break;
670             case 0xF1:
671                 // Prefetch    128-B prefetching
672                 prefetch = 128;
673                 break;
674             case 0xFF:
675                 // General     CPUID leaf 2 does not report cache descriptor information, use CPUID leaf 4 to query cache parameters
676                 noCacheInfo = true;
677                 break;
678         }
679     }
680 }
681 
682 
683 /////
684 unittest
685 {
686     auto leaf2 = Leaf2Information(_cpuid(2));
687 }
688 
689 /++
690 Deterministic Cache Parameters for Each Level.
691 
692 ** - Add one to the return value to get the result.
693 
694 Specification: Intel
695 +/
696 union Leaf4Information
697 {
698     import mir.bitmanip: bitfields;
699 
700     /// CPUID payload
701     CpuInfo info;
702 
703     ///
704     struct
705     {
706         ///
707         enum Type
708         {
709             ///
710             noMoreCaches,
711             ///
712             data,
713             ///
714             instruction,
715             ///
716             unified,
717         }
718 
719         version(D_Ddoc)
720         {
721             @trusted @property pure nothrow @nogc const:
722             /// Cache Type Field.
723             Type type();
724             /// Cache Level (starts at 1).
725             uint level();
726             /// Self Initializing cache level (does not need SW initialization).
727             bool selfInitializing();
728             /// Fully Associative cache.
729             bool fullyAssociative();
730             /// Maximum number of addressable IDs for logical processors sharing this cache. **
731             uint maxThreadsPerCache();
732             /// Maximum number of addressable IDs for processor cores in the physical package **
733             uint maxCorePerCPU();
734             /// System Coherency Line Size **.
735             uint l();
736             /// Physical Line partitions **.
737             uint p();
738             /// Ways of associativity **.
739             uint w();
740             /// Number of Sets **.
741             uint s;
742             ///  Write-Back Invalidate/Invalidate.
743             /// `false` if WBINVD/INVD from threads sharing this cache acts upon lower level caches for threads sharing this cache.
744             /// `true` if WBINVD/INVD is not guaranteed to act upon lower level caches of non-originating threads sharing this cache.
745             bool invalidate();
746             /// `true` - Cache is not inclusive of lower cache levels. `false` - Cache is inclusive of lower cache levels.
747             bool inclusive();
748             /// `false` - Direct mapped cache. `true` A complex function is used to index the cache, potentially using all address bits.
749             bool complex();
750         }
751         else
752         {
753             @trusted @property pure nothrow @nogc:
754             /// EAX
755             mixin(bitfields!(
756                 Type, "type", 5,
757                 uint, "level", 3,
758                 bool, "selfInitializing", 1,
759                 bool, "fullyAssociative", 1,
760                 uint, "", 4,
761                 uint, "maxThreadsPerCache", 12,
762                 uint, "maxCorePerCPU", 6,
763                 ));
764 
765             /// EBX
766             mixin(bitfields!(
767                 uint, "l", 12,
768                 uint, "p", 10,
769                 uint, "w", 10,
770                 ));
771 
772             /// Number of Sets**.
773             uint s;
774 
775             /// EDX
776             mixin(bitfields!(
777                 bool, "invalidate", 1,
778                 bool, "inclusive", 1,
779                 bool, "complex", 1,
780                 uint, "",  29,
781                 ));
782         }
783 
784         /// Compute cache size in KBs.
785         pure nothrow @nogc
786         uint size()() @property
787         {
788             return cast(uint) (
789                 size_t(l + 1) * 
790                 size_t(p + 1) * 
791                 size_t(w + 1) * 
792                 size_t(s + 1) >> 10);
793         }
794 
795         ///
796         pure nothrow @nogc
797         void fill()(ref Cache cache) @property
798         {
799             cache.size = size;
800             cache.line = cast(typeof(cache.line))(l + 1);
801             cache.inclusive = inclusive;
802             cache.associative = cast(typeof(cache.associative)) (w + 1);
803             if(fullyAssociative)
804                 cache.associative = cache.associative.max;
805         }
806     }
807 }
808 
809 ///
810 unittest
811 {
812     if(maxBasicLeaf >= 4 && vendorIndex == VendorIndex.intel)
813     {
814         Cache cache = void;
815         Leaf4Information leaf4 = void;
816         foreach(ecx; 0..12)
817         {
818             leaf4.info = _cpuid(4, ecx);
819             if(!leaf4.type)
820                 break;
821             leaf4.fill(cache);
822             debug(cpuid) import std.stdio;
823             debug(cpuid) writefln("Cache #%s has type '%s' and %s KB size", ecx, leaf4.type, leaf4.size);
824         }
825     }
826 }