1use 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 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, #[bits(28)]
337 pub reserved_eax: u32,
338}
339
340#[bitfield(u32)]
341pub struct CacheParametersEax {
342 #[bits(5)]
343 pub cache_type: u32, #[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}