x86defs/
cpuid.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use bitfield_struct::bitfield;
5use core::fmt::Display;
6use open_enum::open_enum;
7use zerocopy::FromBytes;
8use zerocopy::Immutable;
9use zerocopy::KnownLayout;
10
11open_enum! {
12    #[derive(FromBytes, Immutable, KnownLayout)]
13    pub enum CpuidFunction : u32 {
14        #![expect(non_upper_case_globals, reason = "TODO: rename to SHOUTING_CASE")]
15        BasicMinimum = 0x00000000,
16        VendorAndMaxFunction = 0x00000000,
17        VersionAndFeatures = 0x00000001,
18        CacheAndTlbInformation = 0x00000002,
19        CacheParameters = 0x00000004,
20        MonitorMwait = 0x00000005,
21        PowerManagement = 0x00000006,
22        ExtendedFeatures = 0x00000007,
23        DirectCacheAccessParameters = 0x00000009,
24        PerformanceMonitoring = 0x0000000A,
25        ExtendedTopologyEnumeration = 0x0000000B,
26        ExtendedStateEnumeration = 0x0000000D,
27        RdtmEnumeration = 0x0000000F,
28        RdtaEnumeration = 0x00000010,
29        SgxEnumeration = 0x00000012,
30        IptEnumeration = 0x00000014,
31        CoreCrystalClockInformation = 0x00000015,
32        NativeModelId = 0x0000001A,
33        ArchLbr = 0x0000001C,
34        TileInformation = 0x0000001D,
35        TmulInformation = 0x0000001E,
36        V2ExtendedTopologyEnumeration = 0x0000001F,
37        HistoryResetFeatures = 0x00000020,
38
39        BasicMaximum = 0x00000020,
40        IntelMaximum = 0x00000020,
41        AmdMaximum = 0x0000000D,
42        CompatBlueBasicMaximum = 0x0000000D,
43        GuestBasicMaximum = 0x0000001C,
44
45        UnimplementedMinimum = 0x40000000,
46        UnimplementedMaximum = 0x4FFFFFFF,
47
48        ExtendedMaxFunction = 0x80000000,
49        ExtendedVersionAndFeatures = 0x80000001,
50        ExtendedBrandingString1 = 0x80000002,
51        ExtendedBrandingString2 = 0x80000003,
52        ExtendedBrandingString3 = 0x80000004,
53        ExtendedL1CacheParameters = 0x80000005,
54        ExtendedL2CacheParameters = 0x80000006,
55        ExtendedPowerManagement = 0x80000007,
56        ExtendedAddressSpaceSizes = 0x80000008,
57        ExtendedIntelMaximum = 0x80000008,
58
59        Extended80000009 = 0x80000009,
60        ExtendedSvmVersionAndFeatures = 0x8000000A,
61        ExtendedTlb1GBIdentifiers = 0x80000019,
62        ExtendedOptimizationIdentifiers = 0x8000001A,
63        InstructionBasedSamplingProfiler = 0x8000001B,
64        LightweightProfilingCapabilities = 0x8000001C,
65        CacheTopologyDefinition = 0x8000001D,
66        ProcessorTopologyDefinition = 0x8000001E,
67        ExtendedSevFeatures = 0x8000001F,
68        ExtendedFeatures2 = 0x80000021,
69        ExtendedPerfmonAndDebug = 0x80000022,
70        ExtendedCpuTopology = 0x80000026,
71
72        ExtendedAmdMaximum = 0x80000026,
73        ExtendedMaximum = 0x80000026,
74    }
75}
76
77#[bitfield(u32)]
78pub struct VendorAndMaxFunctionEax {
79    pub max_function: u32,
80}
81
82#[derive(Debug, PartialEq, Eq, Copy, Clone)]
83pub struct Vendor(pub [u8; 12]);
84
85#[cfg(feature = "arbitrary")]
86impl<'a> arbitrary::Arbitrary<'a> for Vendor {
87    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
88        // 25% of the time generate a random vendor
89        if u.ratio(1, 4)? {
90            Ok(Self(u.arbitrary()?))
91        } else {
92            Ok(*u.choose(&[Self::INTEL, Self::AMD, Self::HYGON])?)
93        }
94    }
95}
96
97impl Display for Vendor {
98    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
99        if let Ok(s) = core::str::from_utf8(&self.0) {
100            f.pad(s)
101        } else {
102            core::fmt::Debug::fmt(&self.0, f)
103        }
104    }
105}
106
107impl Vendor {
108    pub const INTEL: Self = Self(*b"GenuineIntel");
109    pub const AMD: Self = Self(*b"AuthenticAMD");
110    pub const HYGON: Self = Self(*b"HygonGenuine");
111
112    pub fn from_ebx_ecx_edx(ebx: u32, ecx: u32, edx: u32) -> Self {
113        let mut vendor = [0; 12];
114        vendor[0..4].copy_from_slice(&ebx.to_ne_bytes());
115        vendor[4..8].copy_from_slice(&edx.to_ne_bytes());
116        vendor[8..12].copy_from_slice(&ecx.to_ne_bytes());
117        Self(vendor)
118    }
119
120    pub fn to_ebx_ecx_edx(self) -> (u32, u32, u32) {
121        let ebx = u32::from_ne_bytes(self.0[0..4].try_into().unwrap());
122        let edx = u32::from_ne_bytes(self.0[4..8].try_into().unwrap());
123        let ecx = u32::from_ne_bytes(self.0[8..12].try_into().unwrap());
124
125        (ebx, ecx, edx)
126    }
127
128    pub fn is_intel_compatible(&self) -> bool {
129        self == &Self::INTEL
130    }
131
132    pub fn is_amd_compatible(&self) -> bool {
133        self == &Self::AMD || self == &Self::HYGON
134    }
135}
136
137#[bitfield(u32)]
138pub struct VersionAndFeaturesEax {
139    #[bits(4)]
140    pub processor_stepping: u32,
141    #[bits(4)]
142    pub processor_model: u32,
143    #[bits(4)]
144    pub processor_family: u32,
145    #[bits(2)]
146    pub processor_type: u32,
147    #[bits(2)]
148    _reserved1: u32,
149    #[bits(4)]
150    pub extended_model: u32,
151    pub extended_family: u8,
152    #[bits(4)]
153    _reserved2: u32,
154}
155
156#[bitfield(u32)]
157pub struct VersionAndFeaturesEbx {
158    pub brand_index: u8,
159    pub clflush_line_size: u8,
160    pub lps_per_package: u8,
161    pub initial_apic_id: u8,
162}
163
164#[bitfield(u32)]
165pub struct VersionAndFeaturesEcx {
166    pub sse3: bool,
167    pub pclmulqdq: bool,
168    pub dtes64: bool,
169    pub monitor: bool,
170    pub cpl_ds: bool,
171    pub vmx: bool,
172    pub smx: bool,
173    pub est: bool,
174    pub tm2: bool,
175    pub ssse3: bool,
176    pub cnxt_id: bool,
177    pub seg_limit64_bit: bool,
178    pub fma: bool,
179    pub cx16: bool,
180    pub xtpr: bool,
181    pub pdcm: bool,
182    _reserved1: bool,
183    pub pcid: bool,
184    pub dca: bool,
185    pub sse4_1: bool,
186    pub sse4_2: bool,
187    pub x2_apic: bool,
188    pub movbe: bool,
189    pub pop_cnt: bool,
190    pub tsc_deadline_tmr: bool,
191    pub aes: bool,
192    pub xsave: bool,
193    pub os_xsave: bool,
194    pub avx: bool,
195    pub f16c: bool,
196    pub rd_rand: bool,
197    pub hypervisor_present: bool,
198}
199
200#[bitfield(u32)]
201pub struct VersionAndFeaturesEdx {
202    pub fpu: bool,
203    pub vme: bool,
204    pub de: bool,
205    pub pse: bool,
206    pub tsc: bool,
207    pub msr: bool,
208    pub pae: bool,
209    pub mce: bool,
210    pub cx8: bool,
211    pub apic: bool,
212    _reserved1: bool,
213    pub sep: bool,
214    pub mtrr: bool,
215    pub pge: bool,
216    pub mca: bool,
217    pub cmov: bool,
218    pub pat: bool,
219    pub pse36: bool,
220    pub psn: bool,
221    pub cl_fsh: bool,
222    _reserved2: bool,
223    pub ds: bool,
224    pub acpi: bool,
225    pub mmx: bool,
226    pub fxsr: bool,
227    pub sse: bool,
228    pub sse2: bool,
229    pub ss: bool,
230    pub mt_per_socket: bool,
231    pub tm: bool,
232    _reserved3: bool,
233    pub pbe: bool,
234}
235
236#[bitfield(u32)]
237pub struct ExtendedVersionAndFeaturesEax {
238    #[bits(4)]
239    pub processor_stepping: u32,
240    #[bits(4)]
241    pub processor_model: u32,
242    #[bits(4)]
243    pub processor_family: u32,
244    #[bits(2)]
245    pub processor_type: u32,
246    #[bits(2)]
247    _reserved_eax1: u32,
248    #[bits(4)]
249    pub extended_model: u32,
250    pub extended_family: u8,
251    #[bits(4)]
252    _reserved_eax2: u32,
253}
254
255#[bitfield(u32)]
256pub struct ExtendedVersionAndFeaturesEbx {
257    pub brand_id: u16,
258    #[bits(12)]
259    _reserved: u32,
260    #[bits(4)]
261    pub pkg_type: u32,
262}
263
264#[bitfield(u32)]
265pub struct ExtendedVersionAndFeaturesEcx {
266    pub lahf_sahf_available: bool,
267    pub cmp_legacy: bool,
268    pub svm: bool,
269    pub ext_apic_space: bool,
270    pub alt_mov_cr8: bool,
271    pub abm: bool,
272    pub sse4_a: bool,
273    pub mis_align_sse: bool,
274    pub prefetch: bool,
275    pub osvw: bool,
276    pub ibs: bool,
277    pub xop: bool,
278    pub skinit: bool,
279    pub wdt: bool,
280    _reserved1: bool,
281    pub lwp: bool,
282    pub fma4: bool,
283    #[bits(5)]
284    _reserved2: u32,
285    pub topology_extensions: bool,
286    pub perf_ctr_ext_core: bool,
287    pub perf_ctr_ext_df: bool,
288    #[bits(3)]
289    _reserved4: u32,
290    pub perf_ctr_ext_llc: bool,
291    pub monitor_x: bool,
292    #[bits(2)]
293    _reserved5: u32,
294}
295
296#[bitfield(u32)]
297pub struct ExtendedVersionAndFeaturesEdx {
298    pub fpu: bool,
299    pub vme: bool,
300    pub de: bool,
301    pub pse: bool,
302    pub tsc: bool,
303    pub msr: bool,
304    pub pae: bool,
305    pub mce: bool,
306    pub cx8: bool,
307    pub apic: bool,
308    _reserved1: bool,
309    pub syscall: bool,
310    pub mtrr: bool,
311    pub pge: bool,
312    pub mca: bool,
313    pub cmov: bool,
314    pub pat: bool,
315    pub pse36: bool,
316    #[bits(2)]
317    _reserved2: u32,
318    pub no_execute: bool,
319    _reserved3: bool,
320    pub amd_mmx: bool,
321    pub mmx: bool,
322    pub fxsr: bool,
323    pub fast_fxsr: bool,
324    pub page_1gb: bool,
325    pub rdtscp: bool,
326    _reserved4: bool,
327    pub long_mode: bool,
328    pub extended3d_now: bool,
329    pub amd3d_now: bool,
330}
331
332#[bitfield(u32)]
333pub struct SgxCpuidSubleafEax {
334    #[bits(4)]
335    pub sgx_type: u8, // 0 = Invalid, 1 = EPC section
336    #[bits(28)]
337    pub reserved_eax: u32,
338}
339
340#[bitfield(u32)]
341pub struct CacheParametersEax {
342    #[bits(5)]
343    pub cache_type: u32, // Type is CPUID_CACHE_TYPE
344    #[bits(3)]
345    pub cache_level: u32,
346    #[bits(1)]
347    pub self_initializing: u32,
348    #[bits(1)]
349    pub fully_associative: u32,
350    #[bits(4)]
351    pub reserved: u32,
352    #[bits(12)]
353    pub threads_sharing_cache_minus_one: u32,
354    #[bits(6)]
355    pub cores_per_socket_minus_one: u32,
356}
357
358#[bitfield(u32)]
359pub struct CacheParametersEbx {
360    #[bits(12)]
361    pub system_coherency_line_size_minus_one: u32,
362    #[bits(10)]
363    pub physical_line_partitions_minus_one: u32,
364    #[bits(10)]
365    pub ways_of_associativity_minus_one: u32,
366}
367
368#[bitfield(u32)]
369pub struct CacheParametersEcx {
370    pub number_of_sets_minus_one: u32,
371}
372#[bitfield(u32)]
373pub struct CacheParametersEdx {
374    pub wbinvd_behavior: bool,
375    pub cache_inclusiveness: bool,
376    #[bits(30)]
377    pub reserved: u32,
378}
379
380open_enum! {
381    pub enum TopologyLevelType: u8 {
382        INVALID = 0,
383        SMT = 1,
384        CORE = 2,
385        MODULE = 3,
386        TILE = 4,
387        DIE = 5,
388    }
389}
390
391#[bitfield(u32)]
392pub struct ExtendedTopologyEax {
393    #[bits(5)]
394    pub x2_apic_shift: u32,
395    #[bits(27)]
396    _reserved: u32,
397}
398
399#[bitfield(u32)]
400pub struct ExtendedTopologyEbx {
401    pub num_lps: u16,
402    _reserved: u16,
403}
404
405#[bitfield(u32)]
406pub struct ExtendedTopologyEcx {
407    pub level_number: u8,
408    pub level_type: u8,
409    _reserved: u16,
410}
411
412#[bitfield(u32)]
413pub struct ExtendedAddressSpaceSizesEax {
414    pub physical_address_size: u8,
415    pub virtual_address_size: u8,
416    pub guest_physical_address_size: u8,
417    pub reserved_eax: u8,
418}
419
420#[bitfield(u32)]
421pub struct ExtendedAddressSpaceSizesEbx {
422    pub cl_zero: bool,
423    pub inst_ret_cnt_msr: bool,
424    pub x_save_er_ptr: bool,
425    pub invlpgb: bool,
426    pub rdpru: bool,
427    _rsvd1: bool,
428    pub mbe: bool,
429    #[bits(2)]
430    _rsvd2: u8,
431    pub wbnoinvd: bool,
432    #[bits(2)]
433    _rsvd3: u8,
434    pub ibpb: bool,
435    pub int_wbinvd: bool,
436    pub ibrs: bool,
437    pub stibp: bool,
438    pub rsvd4: bool,
439    pub stibp_always_on: bool,
440    #[bits(2)]
441    _rsvd5: u8,
442    pub efer_lmsle_unsupported: bool,
443    pub nested_invlpgb: bool,
444    #[bits(2)]
445    _rsvd6: u8,
446    pub ssbd: bool,
447    pub ssbd_virt_spec_ctrl: bool,
448    pub ssbd_not_required: bool,
449    pub cppc: bool,
450    pub psfd: bool,
451    pub btc_no: bool,
452    pub ibpb_ret: bool,
453    _rsvd7: bool,
454}
455
456#[bitfield(u32)]
457pub struct ExtendedAddressSpaceSizesEcx {
458    pub nc: u8,
459    #[bits(4)]
460    pub rsvd1: u8,
461    #[bits(4)]
462    pub apic_core_id_size: u8,
463    pub rsvd2: u16,
464}
465
466#[bitfield(u32)]
467pub struct ExtendedAddressSpaceSizesEdx {
468    pub invlpgb_count_max: u16,
469    pub rdpru_max_ecx: u16,
470}
471
472#[bitfield(u32)]
473pub struct ProcessorTopologyDefinitionEax {
474    pub extended_apic_id: u32,
475}
476
477#[bitfield(u32)]
478pub struct ProcessorTopologyDefinitionEbx {
479    pub compute_unit_id: u8,
480    pub threads_per_compute_unit: u8,
481    _reserved: u16,
482}
483
484#[bitfield(u32)]
485pub struct ProcessorTopologyDefinitionEcx {
486    pub node_id: u8,
487    #[bits(3)]
488    pub nodes_per_processor: u8,
489    #[bits(21)]
490    _reserved: u32,
491}
492
493#[bitfield(u32)]
494pub struct ProcessorTopologyDefinitionEdx {
495    _reserved: u32,
496}
497
498#[bitfield(u32)]
499pub struct ExtendedStateEnumerationSubleaf0Eax {
500    pub x87: bool,
501    pub sse: bool,
502    pub avx: bool,
503    pub bndreg: bool,
504    pub bndcsr: bool,
505    pub opmask: bool,
506    pub zmmhi: bool,
507    pub zmm16_31: bool,
508    #[bits(9)]
509    reserved1: u32,
510    pub xtile_cfg: bool,
511    pub xtile_dta: bool,
512    #[bits(13)]
513    reserved2: u32,
514}
515
516#[bitfield(u32)]
517pub struct ExtendedStateEnumerationSubleaf1Eax {
518    pub xsave_opt: bool,
519    pub xsave_c: bool,
520    pub xcr1: bool,
521    pub xsave_s: bool,
522    pub xfd: bool,
523    #[bits(27)]
524    _reserved: u32,
525}
526
527#[bitfield(u32)]
528pub struct ExtendedStateEnumerationSubleafNEcx {
529    pub supervisor: bool,
530    pub aligned: bool,
531    pub xfd: bool,
532    #[bits(29)]
533    _reserved: u32,
534}
535
536#[bitfield(u32)]
537pub struct ExtendedFeatureSubleaf0Ebx {
538    pub rd_wr_fs_gs: bool,
539    pub tsc_adjust: bool,
540    pub sgx: bool,
541    pub bmi1: bool,
542    pub hle: bool,
543    pub avx2: bool,
544    _reserved0: bool,
545    pub smep: bool,
546    pub bmi2: bool,
547    pub enhanced_fast_string: bool,
548    pub inv_pcid: bool,
549    pub rtm: bool,
550    pub rdt_m: bool,
551    pub dep_x87_fpu_save: bool,
552    pub mpx: bool,
553    pub rdt_a: bool,
554    pub avx512f: bool,
555    pub avx512dq: bool,
556    pub rd_seed: bool,
557    pub adx: bool,
558    pub smap: bool,
559    pub avx512_ifma: bool,
560    _reserved3: bool,
561    pub clflushopt: bool,
562    pub clwb: bool,
563    pub ipt: bool,
564    #[bits(2)]
565    _reserved4: u32,
566    pub avx512cd: bool,
567    pub sha: bool,
568    pub avx512bw: bool,
569    pub avx512vl: bool,
570}
571
572#[bitfield(u32)]
573pub struct ExtendedFeatureSubleaf0Ecx {
574    _reserved0: bool,
575    pub avx512_vbmi: bool,
576    pub umip: bool,
577    #[bits(2)]
578    _reserved1: u32,
579    pub umwait_tpause: bool,
580    pub avx512_vbmi2: bool,
581    pub cet_ss: bool,
582    pub gfni: bool,
583    pub vaes: bool,
584    pub vpclmulqdq: bool,
585    pub avx512_vnni: bool,
586    pub avx512_bitalg: bool,
587    pub tme: bool,
588    pub avx512_vpopcntdq: bool,
589    _reserved2: bool,
590    pub la57: bool,
591    #[bits(5)]
592    _reserved3: u32,
593    pub rd_pid: bool,
594    #[bits(2)]
595    _reserved4: u32,
596    pub cldemote: bool,
597    _reserved5: bool,
598    pub movdiri: bool,
599    pub movdir64b: bool,
600    pub enqcmd: bool,
601    pub sgx_lc: bool,
602    _reserved6: bool,
603}
604
605#[bitfield(u32)]
606pub struct ExtendedFeatureSubleaf0Edx {
607    #[bits(4)]
608    _reserved0: u32,
609    pub fast_short_rep_move: bool,
610    #[bits(3)]
611    _reserved1: u32,
612    pub avx512_vp2_intersect: bool,
613    _reserved2: bool,
614    pub mb_clear: bool,
615    #[bits(3)]
616    _reserved3: u32,
617    pub serialize: bool,
618    pub hetero: bool,
619    pub tsx_ld_trk: bool,
620    _reserved4: bool,
621    pub pconfig: bool,
622    pub arch_lbr: bool,
623    pub cet_ibt: bool,
624    _reserved5: bool,
625    pub amx_bf16: bool,
626    pub avx512_fp16: bool,
627    pub amx_tile: bool,
628    pub amx_int8: bool,
629    pub ibrs: bool,
630    pub stibp: bool,
631    pub l1d_cache_flush: bool,
632    pub arch_capabilities: bool,
633    _reserved6: bool,
634    pub ssbd: bool,
635}
636
637#[bitfield(u32)]
638pub struct ExtendedFeatureSubleaf1Eax {
639    #[bits(4)]
640    _reserved0: u32,
641    pub avx_vnni: bool,
642    pub avx512_bfloat16: bool,
643    #[bits(4)]
644    _reserved1: u32,
645    pub fzlrep_movsb: bool,
646    pub fsrep_stosb: bool,
647    pub fsrep_cmpsb: bool,
648    #[bits(9)]
649    _reserved2: u32,
650    pub hreset: bool,
651    pub avx_ifma: bool,
652    _reserved3: u8,
653}
654
655#[bitfield(u32)]
656pub struct ExtendedFeatureSubleaf1Edx {
657    #[bits(4)]
658    pub _reserved1: u32,
659    pub avx_vnni_int8: bool,
660    pub avx_ne_convert: bool,
661    #[bits(26)]
662    pub _reserved2: u32,
663}
664
665#[bitfield(u32)]
666pub struct ExtendedSvmVersionAndFeaturesEax {
667    pub svm_rev: u8,
668    #[bits(24)]
669    _reserved: u32,
670}
671
672#[bitfield(u32)]
673pub struct ExtendedOptimizationIdentifiersEax {
674    pub fp128: bool,
675    pub mov_u: bool,
676    pub fp256: bool,
677    #[bits(29)]
678    _reserved: u32,
679}
680
681#[bitfield(u32)]
682pub struct ExtendedSevFeaturesEax {
683    pub sme: bool,
684    pub sev: bool,
685    pub vmpage_flush_msr_available: bool,
686    pub sev_es: bool,
687    pub sev_snp: bool,
688    pub vmpl: bool,
689    pub rmp_query: bool,
690    pub vmpl_isss: bool,
691    pub secure_tsc: bool,
692    pub tsc_aux_virtualization: bool,
693    pub coherency_enforced: bool,
694    pub req64_bit_hypervisor: bool,
695    pub restrict_injection: bool,
696    pub alternate_injection: bool,
697    pub debug_state_swap: bool,
698    pub prevent_host_ibs: bool,
699    pub vte: bool,
700    pub vmgexit_parameter: bool,
701    pub virtual_tom_msr: bool,
702    pub ibs_virtualization: bool,
703    #[bits(4)]
704    _reserved1: u32,
705    pub vmsa_register_protection: bool,
706    #[bits(4)]
707    _reserved2: u32,
708    pub nested_virt_msr_snp: bool,
709    #[bits(2)]
710    _reserved3: u32,
711}
712
713#[bitfield(u32)]
714pub struct ExtendedSevFeaturesEbx {
715    #[bits(6)]
716    pub cbit_position: u8,
717    #[bits(6)]
718    pub encryption_physical_bits_used: u8,
719    #[bits(4)]
720    pub number_of_vmpls: u8,
721    _reserved: u16,
722}