1 #![no_std]
2 #![crate_name = "raw_cpuid"]
3 #![crate_type = "lib"]
4
5 #[cfg(test)]
6 #[macro_use]
7 extern crate std;
8
9 #[cfg(test)]
10 mod tests;
11 #[cfg(feature = "serialize")]
12 #[macro_use]
13 extern crate serde_derive;
14
15 #[macro_use]
16 extern crate bitflags;
17
18 /// Provides `cpuid` on stable by linking against a C implementation.
19 #[cfg(not(feature = "use_arch"))]
20 pub mod native_cpuid {
21 use super::CpuIdResult;
22
23 extern "C" {
cpuid(a: *mut u32, b: *mut u32, c: *mut u32, d: *mut u32)24 fn cpuid(a: *mut u32, b: *mut u32, c: *mut u32, d: *mut u32);
25 }
26
cpuid_count(mut eax: u32, mut ecx: u32) -> CpuIdResult27 pub fn cpuid_count(mut eax: u32, mut ecx: u32) -> CpuIdResult {
28 let mut ebx = 0u32;
29 let mut edx = 0u32;
30
31 unsafe {
32 cpuid(&mut eax, &mut ebx, &mut ecx, &mut edx);
33 }
34
35 CpuIdResult { eax, ebx, ecx, edx }
36 }
37 }
38
39 /// Uses Rust's `cpuid` function from the `arch` module.
40 #[cfg(feature = "use_arch")]
41 pub mod native_cpuid {
42 use super::CpuIdResult;
43
44 #[cfg(target_arch = "x86")]
45 use core::arch::x86 as arch;
46 #[cfg(target_arch = "x86_64")]
47 use core::arch::x86_64 as arch;
48
cpuid_count(a: u32, c: u32) -> CpuIdResult49 pub fn cpuid_count(a: u32, c: u32) -> CpuIdResult {
50 let result = unsafe { self::arch::__cpuid_count(a, c) };
51
52 CpuIdResult {
53 eax: result.eax,
54 ebx: result.ebx,
55 ecx: result.ecx,
56 edx: result.edx,
57 }
58 }
59 }
60
61 use core::cmp::min;
62 use core::fmt;
63 use core::mem::transmute;
64 use core::slice;
65 use core::str;
66
67 #[cfg(not(test))]
68 mod std {
69 pub use core::ops;
70 pub use core::option;
71 }
72
73 /// Macro which queries cpuid directly.
74 ///
75 /// First parameter is cpuid leaf (EAX register value),
76 /// second optional parameter is the subleaf (ECX register value).
77 #[macro_export]
78 macro_rules! cpuid {
79 ($eax:expr) => {
80 $crate::native_cpuid::cpuid_count($eax as u32, 0)
81 };
82
83 ($eax:expr, $ecx:expr) => {
84 $crate::native_cpuid::cpuid_count($eax as u32, $ecx as u32)
85 };
86 }
87
as_bytes(v: &u32) -> &[u8]88 fn as_bytes(v: &u32) -> &[u8] {
89 let start = v as *const u32 as *const u8;
90 unsafe { slice::from_raw_parts(start, 4) }
91 }
92
get_bits(r: u32, from: u32, to: u32) -> u3293 fn get_bits(r: u32, from: u32, to: u32) -> u32 {
94 assert!(from <= 31);
95 assert!(to <= 31);
96 assert!(from <= to);
97
98 let mask = match to {
99 31 => 0xffffffff,
100 _ => (1 << (to + 1)) - 1,
101 };
102
103 (r & mask) >> from
104 }
105
106 macro_rules! check_flag {
107 ($doc:meta, $fun:ident, $flags:ident, $flag:expr) => (
108 #[$doc]
109 pub fn $fun(&self) -> bool {
110 self.$flags.contains($flag)
111 }
112 )
113 }
114
115 macro_rules! is_bit_set {
116 ($field:expr, $bit:expr) => {
117 $field & (1 << $bit) > 0
118 };
119 }
120
121 macro_rules! check_bit_fn {
122 ($doc:meta, $fun:ident, $field:ident, $bit:expr) => (
123 #[$doc]
124 pub fn $fun(&self) -> bool {
125 is_bit_set!(self.$field, $bit)
126 }
127 )
128 }
129
130 /// Main type used to query for information about the CPU we're running on.
131 #[derive(Debug, Default)]
132 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
133 pub struct CpuId {
134 max_eax_value: u32,
135 }
136
137 /// Low-level data-structure to store result of cpuid instruction.
138 #[derive(Copy, Clone, Debug, Default)]
139 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
140 pub struct CpuIdResult {
141 /// Return value EAX register
142 pub eax: u32,
143 /// Return value EBX register
144 pub ebx: u32,
145 /// Return value ECX register
146 pub ecx: u32,
147 /// Return value EDX register
148 pub edx: u32,
149 }
150
151 const EAX_VENDOR_INFO: u32 = 0x0;
152 const EAX_FEATURE_INFO: u32 = 0x1;
153 const EAX_CACHE_INFO: u32 = 0x2;
154 const EAX_PROCESSOR_SERIAL: u32 = 0x3;
155 const EAX_CACHE_PARAMETERS: u32 = 0x4;
156 const EAX_MONITOR_MWAIT_INFO: u32 = 0x5;
157 const EAX_THERMAL_POWER_INFO: u32 = 0x6;
158 const EAX_STRUCTURED_EXTENDED_FEATURE_INFO: u32 = 0x7;
159 const EAX_DIRECT_CACHE_ACCESS_INFO: u32 = 0x9;
160 const EAX_PERFORMANCE_MONITOR_INFO: u32 = 0xA;
161 const EAX_EXTENDED_TOPOLOGY_INFO: u32 = 0xB;
162 const EAX_EXTENDED_STATE_INFO: u32 = 0xD;
163 const EAX_RDT_MONITORING: u32 = 0xF;
164 const EAX_RDT_ALLOCATION: u32 = 0x10;
165 const EAX_SGX: u32 = 0x12;
166 const EAX_TRACE_INFO: u32 = 0x14;
167 const EAX_TIME_STAMP_COUNTER_INFO: u32 = 0x15;
168 const EAX_FREQUENCY_INFO: u32 = 0x16;
169 const EAX_SOC_VENDOR_INFO: u32 = 0x17;
170 const EAX_DETERMINISTIC_ADDRESS_TRANSLATION_INFO: u32 = 0x18;
171 const EAX_HYPERVISOR_INFO: u32 = 0x40000000;
172 const EAX_EXTENDED_FUNCTION_INFO: u32 = 0x80000000;
173 const EAX_MEMORY_ENCRYPTION_INFO: u32 = 0x8000001F;
174
175 impl CpuId {
176 /// Return new CPUID struct.
new() -> CpuId177 pub fn new() -> CpuId {
178 let res = cpuid!(EAX_VENDOR_INFO);
179 CpuId {
180 max_eax_value: res.eax,
181 }
182 }
183
leaf_is_supported(&self, val: u32) -> bool184 fn leaf_is_supported(&self, val: u32) -> bool {
185 val <= self.max_eax_value
186 }
187
188 /// Return information about vendor.
189 /// This is typically a ASCII readable string such as
190 /// GenuineIntel for Intel CPUs or AuthenticAMD for AMD CPUs.
get_vendor_info(&self) -> Option<VendorInfo>191 pub fn get_vendor_info(&self) -> Option<VendorInfo> {
192 if self.leaf_is_supported(EAX_VENDOR_INFO) {
193 let res = cpuid!(EAX_VENDOR_INFO);
194 Some(VendorInfo {
195 ebx: res.ebx,
196 ecx: res.ecx,
197 edx: res.edx,
198 })
199 } else {
200 None
201 }
202 }
203
204 /// Query a set of features that are available on this CPU.
get_feature_info(&self) -> Option<FeatureInfo>205 pub fn get_feature_info(&self) -> Option<FeatureInfo> {
206 if self.leaf_is_supported(EAX_FEATURE_INFO) {
207 let res = cpuid!(EAX_FEATURE_INFO);
208 Some(FeatureInfo {
209 eax: res.eax,
210 ebx: res.ebx,
211 edx_ecx: FeatureInfoFlags {
212 bits: (((res.edx as u64) << 32) | (res.ecx as u64)),
213 },
214 })
215 } else {
216 None
217 }
218 }
219
220 /// Query basic information about caches. This will just return an index
221 /// into a static table of cache descriptions (see `CACHE_INFO_TABLE`).
get_cache_info(&self) -> Option<CacheInfoIter>222 pub fn get_cache_info(&self) -> Option<CacheInfoIter> {
223 if self.leaf_is_supported(EAX_CACHE_INFO) {
224 let res = cpuid!(EAX_CACHE_INFO);
225 Some(CacheInfoIter {
226 current: 1,
227 eax: res.eax,
228 ebx: res.ebx,
229 ecx: res.ecx,
230 edx: res.edx,
231 })
232 } else {
233 None
234 }
235 }
236
237 /// Retrieve serial number of processor.
get_processor_serial(&self) -> Option<ProcessorSerial>238 pub fn get_processor_serial(&self) -> Option<ProcessorSerial> {
239 if self.leaf_is_supported(EAX_PROCESSOR_SERIAL) {
240 let res = cpuid!(EAX_PROCESSOR_SERIAL);
241 Some(ProcessorSerial {
242 ecx: res.ecx,
243 edx: res.edx,
244 })
245 } else {
246 None
247 }
248 }
249
250 /// Retrieve more elaborate information about caches (as opposed
251 /// to `get_cache_info`). This will tell us about associativity,
252 /// set size, line size etc. for each level of the cache hierarchy.
get_cache_parameters(&self) -> Option<CacheParametersIter>253 pub fn get_cache_parameters(&self) -> Option<CacheParametersIter> {
254 if self.leaf_is_supported(EAX_CACHE_PARAMETERS) {
255 Some(CacheParametersIter { current: 0 })
256 } else {
257 None
258 }
259 }
260
261 /// Information about how monitor/mwait works on this CPU.
get_monitor_mwait_info(&self) -> Option<MonitorMwaitInfo>262 pub fn get_monitor_mwait_info(&self) -> Option<MonitorMwaitInfo> {
263 if self.leaf_is_supported(EAX_MONITOR_MWAIT_INFO) {
264 let res = cpuid!(EAX_MONITOR_MWAIT_INFO);
265 Some(MonitorMwaitInfo {
266 eax: res.eax,
267 ebx: res.ebx,
268 ecx: res.ecx,
269 edx: res.edx,
270 })
271 } else {
272 None
273 }
274 }
275
276 /// Query information about thermal and power management features of the CPU.
get_thermal_power_info(&self) -> Option<ThermalPowerInfo>277 pub fn get_thermal_power_info(&self) -> Option<ThermalPowerInfo> {
278 if self.leaf_is_supported(EAX_THERMAL_POWER_INFO) {
279 let res = cpuid!(EAX_THERMAL_POWER_INFO);
280 Some(ThermalPowerInfo {
281 eax: ThermalPowerFeaturesEax { bits: res.eax },
282 ebx: res.ebx,
283 ecx: ThermalPowerFeaturesEcx { bits: res.ecx },
284 edx: res.edx,
285 })
286 } else {
287 None
288 }
289 }
290
291 /// Find out about more features supported by this CPU.
get_extended_feature_info(&self) -> Option<ExtendedFeatures>292 pub fn get_extended_feature_info(&self) -> Option<ExtendedFeatures> {
293 if self.leaf_is_supported(EAX_STRUCTURED_EXTENDED_FEATURE_INFO) {
294 let res = cpuid!(EAX_STRUCTURED_EXTENDED_FEATURE_INFO);
295 assert!(res.eax == 0);
296 Some(ExtendedFeatures {
297 eax: res.eax,
298 ebx: ExtendedFeaturesEbx { bits: res.ebx },
299 ecx: ExtendedFeaturesEcx { bits: res.ecx },
300 edx: res.edx,
301 })
302 } else {
303 None
304 }
305 }
306
307 /// Direct cache access info.
get_direct_cache_access_info(&self) -> Option<DirectCacheAccessInfo>308 pub fn get_direct_cache_access_info(&self) -> Option<DirectCacheAccessInfo> {
309 if self.leaf_is_supported(EAX_DIRECT_CACHE_ACCESS_INFO) {
310 let res = cpuid!(EAX_DIRECT_CACHE_ACCESS_INFO);
311 Some(DirectCacheAccessInfo { eax: res.eax })
312 } else {
313 None
314 }
315 }
316
317 /// Info about performance monitoring (how many counters etc.).
get_performance_monitoring_info(&self) -> Option<PerformanceMonitoringInfo>318 pub fn get_performance_monitoring_info(&self) -> Option<PerformanceMonitoringInfo> {
319 if self.leaf_is_supported(EAX_PERFORMANCE_MONITOR_INFO) {
320 let res = cpuid!(EAX_PERFORMANCE_MONITOR_INFO);
321 Some(PerformanceMonitoringInfo {
322 eax: res.eax,
323 ebx: PerformanceMonitoringFeaturesEbx { bits: res.ebx },
324 ecx: res.ecx,
325 edx: res.edx,
326 })
327 } else {
328 None
329 }
330 }
331
332 /// Information about topology (how many cores and what kind of cores).
get_extended_topology_info(&self) -> Option<ExtendedTopologyIter>333 pub fn get_extended_topology_info(&self) -> Option<ExtendedTopologyIter> {
334 if self.leaf_is_supported(EAX_EXTENDED_TOPOLOGY_INFO) {
335 Some(ExtendedTopologyIter { level: 0 })
336 } else {
337 None
338 }
339 }
340
341 /// Information for saving/restoring extended register state.
get_extended_state_info(&self) -> Option<ExtendedStateInfo>342 pub fn get_extended_state_info(&self) -> Option<ExtendedStateInfo> {
343 if self.leaf_is_supported(EAX_EXTENDED_STATE_INFO) {
344 let res = cpuid!(EAX_EXTENDED_STATE_INFO, 0);
345 let res1 = cpuid!(EAX_EXTENDED_STATE_INFO, 1);
346 Some(ExtendedStateInfo {
347 eax: ExtendedStateInfoXCR0Flags { bits: res.eax },
348 ebx: res.ebx,
349 ecx: res.ecx,
350 edx: res.edx,
351 eax1: res1.eax,
352 ebx1: res1.ebx,
353 ecx1: ExtendedStateInfoXSSFlags { bits: res1.ecx },
354 edx1: res1.edx,
355 })
356 } else {
357 None
358 }
359 }
360
361 /// Quality of service informations.
get_rdt_monitoring_info(&self) -> Option<RdtMonitoringInfo>362 pub fn get_rdt_monitoring_info(&self) -> Option<RdtMonitoringInfo> {
363 let res = cpuid!(EAX_RDT_MONITORING, 0);
364
365 if self.leaf_is_supported(EAX_RDT_MONITORING) {
366 Some(RdtMonitoringInfo {
367 ebx: res.ebx,
368 edx: res.edx,
369 })
370 } else {
371 None
372 }
373 }
374
375 /// Quality of service enforcement information.
get_rdt_allocation_info(&self) -> Option<RdtAllocationInfo>376 pub fn get_rdt_allocation_info(&self) -> Option<RdtAllocationInfo> {
377 let res = cpuid!(EAX_RDT_ALLOCATION, 0);
378
379 if self.leaf_is_supported(EAX_RDT_ALLOCATION) {
380 Some(RdtAllocationInfo { ebx: res.ebx })
381 } else {
382 None
383 }
384 }
385
get_sgx_info(&self) -> Option<SgxInfo>386 pub fn get_sgx_info(&self) -> Option<SgxInfo> {
387 // Leaf 12H sub-leaf 0 (ECX = 0) is supported if CPUID.(EAX=07H, ECX=0H):EBX[SGX] = 1.
388 self.get_extended_feature_info().and_then(|info| {
389 if self.leaf_is_supported(EAX_SGX) && info.has_sgx() {
390 let res = cpuid!(EAX_SGX, 0);
391 let res1 = cpuid!(EAX_SGX, 1);
392 Some(SgxInfo {
393 eax: res.eax,
394 ebx: res.ebx,
395 ecx: res.ecx,
396 edx: res.edx,
397 eax1: res1.eax,
398 ebx1: res1.ebx,
399 ecx1: res1.ecx,
400 edx1: res1.edx,
401 })
402 } else {
403 None
404 }
405 })
406 }
407
408 /// Intel Processor Trace Enumeration Information.
get_processor_trace_info(&self) -> Option<ProcessorTraceInfo>409 pub fn get_processor_trace_info(&self) -> Option<ProcessorTraceInfo> {
410 let res = cpuid!(EAX_TRACE_INFO, 0);
411 if self.leaf_is_supported(EAX_TRACE_INFO) {
412 let res1 = if res.eax >= 1 {
413 Some(cpuid!(EAX_TRACE_INFO, 1))
414 } else {
415 None
416 };
417
418 Some(ProcessorTraceInfo {
419 eax: res.eax,
420 ebx: res.ebx,
421 ecx: res.ecx,
422 edx: res.edx,
423 leaf1: res1,
424 })
425 } else {
426 None
427 }
428 }
429
430 /// Time Stamp Counter/Core Crystal Clock Information.
get_tsc_info(&self) -> Option<TscInfo>431 pub fn get_tsc_info(&self) -> Option<TscInfo> {
432 let res = cpuid!(EAX_TIME_STAMP_COUNTER_INFO, 0);
433 if self.leaf_is_supported(EAX_TIME_STAMP_COUNTER_INFO) {
434 Some(TscInfo {
435 eax: res.eax,
436 ebx: res.ebx,
437 ecx: res.ecx,
438 })
439 } else {
440 None
441 }
442 }
443
444 /// Processor Frequency Information.
get_processor_frequency_info(&self) -> Option<ProcessorFrequencyInfo>445 pub fn get_processor_frequency_info(&self) -> Option<ProcessorFrequencyInfo> {
446 let res = cpuid!(EAX_FREQUENCY_INFO, 0);
447 if self.leaf_is_supported(EAX_FREQUENCY_INFO) {
448 Some(ProcessorFrequencyInfo {
449 eax: res.eax,
450 ebx: res.ebx,
451 ecx: res.ecx,
452 })
453 } else {
454 None
455 }
456 }
457
deterministic_address_translation_info(&self) -> Option<DatIter>458 pub fn deterministic_address_translation_info(&self) -> Option<DatIter> {
459 if self.leaf_is_supported(EAX_DETERMINISTIC_ADDRESS_TRANSLATION_INFO) {
460 let res = cpuid!(EAX_DETERMINISTIC_ADDRESS_TRANSLATION_INFO, 0);
461 Some(DatIter {
462 current: 0,
463 count: res.eax,
464 })
465 } else {
466 None
467 }
468 }
469
get_soc_vendor_info(&self) -> Option<SoCVendorInfo>470 pub fn get_soc_vendor_info(&self) -> Option<SoCVendorInfo> {
471 let res = cpuid!(EAX_SOC_VENDOR_INFO, 0);
472 if self.leaf_is_supported(EAX_SOC_VENDOR_INFO) {
473 Some(SoCVendorInfo {
474 eax: res.eax,
475 ebx: res.ebx,
476 ecx: res.ecx,
477 edx: res.edx,
478 })
479 } else {
480 None
481 }
482 }
483
get_hypervisor_info(&self) -> Option<HypervisorInfo>484 pub fn get_hypervisor_info(&self) -> Option<HypervisorInfo> {
485 let res = cpuid!(EAX_HYPERVISOR_INFO);
486 if res.eax > 0 {
487 Some(HypervisorInfo { res: res })
488 } else {
489 None
490 }
491 }
492
493 /// Extended functionality of CPU described here (including more supported features).
494 /// This also contains a more detailed CPU model identifier.
get_extended_function_info(&self) -> Option<ExtendedFunctionInfo>495 pub fn get_extended_function_info(&self) -> Option<ExtendedFunctionInfo> {
496 let res = cpuid!(EAX_EXTENDED_FUNCTION_INFO);
497
498 if res.eax == 0 {
499 return None;
500 }
501
502 let mut ef = ExtendedFunctionInfo {
503 max_eax_value: res.eax - EAX_EXTENDED_FUNCTION_INFO,
504 data: [
505 CpuIdResult {
506 eax: res.eax,
507 ebx: res.ebx,
508 ecx: res.ecx,
509 edx: res.edx,
510 },
511 CpuIdResult {
512 eax: 0,
513 ebx: 0,
514 ecx: 0,
515 edx: 0,
516 },
517 CpuIdResult {
518 eax: 0,
519 ebx: 0,
520 ecx: 0,
521 edx: 0,
522 },
523 CpuIdResult {
524 eax: 0,
525 ebx: 0,
526 ecx: 0,
527 edx: 0,
528 },
529 CpuIdResult {
530 eax: 0,
531 ebx: 0,
532 ecx: 0,
533 edx: 0,
534 },
535 CpuIdResult {
536 eax: 0,
537 ebx: 0,
538 ecx: 0,
539 edx: 0,
540 },
541 CpuIdResult {
542 eax: 0,
543 ebx: 0,
544 ecx: 0,
545 edx: 0,
546 },
547 CpuIdResult {
548 eax: 0,
549 ebx: 0,
550 ecx: 0,
551 edx: 0,
552 },
553 CpuIdResult {
554 eax: 0,
555 ebx: 0,
556 ecx: 0,
557 edx: 0,
558 },
559 ],
560 };
561
562 let max_eax_value = min(ef.max_eax_value + 1, ef.data.len() as u32);
563 for i in 1..max_eax_value {
564 ef.data[i as usize] = cpuid!(EAX_EXTENDED_FUNCTION_INFO + i);
565 }
566
567 Some(ef)
568 }
569
get_memory_encryption_info(&self) -> Option<MemoryEncryptionInfo>570 pub fn get_memory_encryption_info(&self) -> Option<MemoryEncryptionInfo> {
571 let res = cpuid!(EAX_EXTENDED_FUNCTION_INFO);
572 if res.eax < EAX_MEMORY_ENCRYPTION_INFO {
573 return None;
574 }
575
576 let res = cpuid!(EAX_MEMORY_ENCRYPTION_INFO);
577 Some(MemoryEncryptionInfo {
578 eax: MemoryEncryptionInfoEax { bits: res.eax },
579 ebx: res.ebx,
580 ecx: res.ecx,
581 edx: res.edx,
582 })
583 }
584 }
585
586 #[derive(Debug, Default)]
587 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
588 pub struct VendorInfo {
589 ebx: u32,
590 edx: u32,
591 ecx: u32,
592 }
593
594 impl VendorInfo {
595 /// Return vendor identification as human readable string.
as_string<'a>(&'a self) -> &'a str596 pub fn as_string<'a>(&'a self) -> &'a str {
597 unsafe {
598 let brand_string_start = self as *const VendorInfo as *const u8;
599 let slice = slice::from_raw_parts(brand_string_start, 3 * 4);
600 let byte_array: &'a [u8] = transmute(slice);
601 str::from_utf8_unchecked(byte_array)
602 }
603 }
604 }
605
606 /// Used to iterate over cache information contained in cpuid instruction.
607 #[derive(Debug, Default)]
608 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
609 pub struct CacheInfoIter {
610 current: u32,
611 eax: u32,
612 ebx: u32,
613 ecx: u32,
614 edx: u32,
615 }
616
617 impl Iterator for CacheInfoIter {
618 type Item = CacheInfo;
619
620 /// Iterate over all cache information.
next(&mut self) -> Option<CacheInfo>621 fn next(&mut self) -> Option<CacheInfo> {
622 // Every byte of the 4 register values returned by cpuid
623 // can contain information about a cache (except the
624 // very first one).
625 if self.current >= 4 * 4 {
626 return None;
627 }
628 let reg_index = self.current % 4;
629 let byte_index = self.current / 4;
630
631 let reg = match reg_index {
632 0 => self.eax,
633 1 => self.ebx,
634 2 => self.ecx,
635 3 => self.edx,
636 _ => unreachable!(),
637 };
638
639 let byte = as_bytes(®)[byte_index as usize];
640 if byte == 0 {
641 self.current += 1;
642 return self.next();
643 }
644
645 for cache_info in CACHE_INFO_TABLE.iter() {
646 if cache_info.num == byte {
647 self.current += 1;
648 return Some(*cache_info);
649 }
650 }
651
652 None
653 }
654 }
655
656 /// What type of cache are we dealing with?
657 #[derive(Copy, Clone, Debug)]
658 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
659 pub enum CacheInfoType {
660 General,
661 Cache,
662 TLB,
663 STLB,
664 DTLB,
665 Prefetch,
666 }
667
668 impl Default for CacheInfoType {
default() -> CacheInfoType669 fn default() -> CacheInfoType {
670 CacheInfoType::General
671 }
672 }
673
674 /// Describes any kind of cache (TLB, Data and Instruction caches plus prefetchers).
675 #[derive(Copy, Clone, Debug, Default)]
676 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
677 pub struct CacheInfo {
678 /// Number as retrieved from cpuid
679 pub num: u8,
680 /// Cache type
681 pub typ: CacheInfoType,
682 }
683
684 impl CacheInfo {
685 /// Description of the cache (from Intel Manual)
desc(&self) -> &'static str686 pub fn desc(&self) -> &'static str {
687 match self.num {
688 0x00 => "Null descriptor, this byte contains no information",
689 0x01 => "Instruction TLB: 4 KByte pages, 4-way set associative, 32 entries",
690 0x02 => "Instruction TLB: 4 MByte pages, fully associative, 2 entries",
691 0x03 => "Data TLB: 4 KByte pages, 4-way set associative, 64 entries",
692 0x04 => "Data TLB: 4 MByte pages, 4-way set associative, 8 entries",
693 0x05 => "Data TLB1: 4 MByte pages, 4-way set associative, 32 entries",
694 0x06 => "1st-level instruction cache: 8 KBytes, 4-way set associative, 32 byte line size",
695 0x08 => "1st-level instruction cache: 16 KBytes, 4-way set associative, 32 byte line size",
696 0x09 => "1st-level instruction cache: 32KBytes, 4-way set associative, 64 byte line size",
697 0x0A => "1st-level data cache: 8 KBytes, 2-way set associative, 32 byte line size",
698 0x0B => "Instruction TLB: 4 MByte pages, 4-way set associative, 4 entries",
699 0x0C => "1st-level data cache: 16 KBytes, 4-way set associative, 32 byte line size",
700 0x0D => "1st-level data cache: 16 KBytes, 4-way set associative, 64 byte line size",
701 0x0E => "1st-level data cache: 24 KBytes, 6-way set associative, 64 byte line size",
702 0x1D => "2nd-level cache: 128 KBytes, 2-way set associative, 64 byte line size",
703 0x21 => "2nd-level cache: 256 KBytes, 8-way set associative, 64 byte line size",
704 0x22 => "3rd-level cache: 512 KBytes, 4-way set associative, 64 byte line size, 2 lines per sector",
705 0x23 => "3rd-level cache: 1 MBytes, 8-way set associative, 64 byte line size, 2 lines per sector",
706 0x24 => "2nd-level cache: 1 MBytes, 16-way set associative, 64 byte line size",
707 0x25 => "3rd-level cache: 2 MBytes, 8-way set associative, 64 byte line size, 2 lines per sector",
708 0x29 => "3rd-level cache: 4 MBytes, 8-way set associative, 64 byte line size, 2 lines per sector",
709 0x2C => "1st-level data cache: 32 KBytes, 8-way set associative, 64 byte line size",
710 0x30 => "1st-level instruction cache: 32 KBytes, 8-way set associative, 64 byte line size",
711 0x40 => "No 2nd-level cache or, if processor contains a valid 2nd-level cache, no 3rd-level cache",
712 0x41 => "2nd-level cache: 128 KBytes, 4-way set associative, 32 byte line size",
713 0x42 => "2nd-level cache: 256 KBytes, 4-way set associative, 32 byte line size",
714 0x43 => "2nd-level cache: 512 KBytes, 4-way set associative, 32 byte line size",
715 0x44 => "2nd-level cache: 1 MByte, 4-way set associative, 32 byte line size",
716 0x45 => "2nd-level cache: 2 MByte, 4-way set associative, 32 byte line size",
717 0x46 => "3rd-level cache: 4 MByte, 4-way set associative, 64 byte line size",
718 0x47 => "3rd-level cache: 8 MByte, 8-way set associative, 64 byte line size",
719 0x48 => "2nd-level cache: 3MByte, 12-way set associative, 64 byte line size",
720 0x49 => "3rd-level cache: 4MB, 16-way set associative, 64-byte line size (Intel Xeon processor MP, Family 0FH, Model 06H); 2nd-level cache: 4 MByte, 16-way set ssociative, 64 byte line size",
721 0x4A => "3rd-level cache: 6MByte, 12-way set associative, 64 byte line size",
722 0x4B => "3rd-level cache: 8MByte, 16-way set associative, 64 byte line size",
723 0x4C => "3rd-level cache: 12MByte, 12-way set associative, 64 byte line size",
724 0x4D => "3rd-level cache: 16MByte, 16-way set associative, 64 byte line size",
725 0x4E => "2nd-level cache: 6MByte, 24-way set associative, 64 byte line size",
726 0x4F => "Instruction TLB: 4 KByte pages, 32 entries",
727 0x50 => "Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 64 entries",
728 0x51 => "Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 128 entries",
729 0x52 => "Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 256 entries",
730 0x55 => "Instruction TLB: 2-MByte or 4-MByte pages, fully associative, 7 entries",
731 0x56 => "Data TLB0: 4 MByte pages, 4-way set associative, 16 entries",
732 0x57 => "Data TLB0: 4 KByte pages, 4-way associative, 16 entries",
733 0x59 => "Data TLB0: 4 KByte pages, fully associative, 16 entries",
734 0x5A => "Data TLB0: 2-MByte or 4 MByte pages, 4-way set associative, 32 entries",
735 0x5B => "Data TLB: 4 KByte and 4 MByte pages, 64 entries",
736 0x5C => "Data TLB: 4 KByte and 4 MByte pages,128 entries",
737 0x5D => "Data TLB: 4 KByte and 4 MByte pages,256 entries",
738 0x60 => "1st-level data cache: 16 KByte, 8-way set associative, 64 byte line size",
739 0x61 => "Instruction TLB: 4 KByte pages, fully associative, 48 entries",
740 0x63 => "Data TLB: 2 MByte or 4 MByte pages, 4-way set associative, 32 entries and a separate array with 1 GByte pages, 4-way set associative, 4 entries",
741 0x64 => "Data TLB: 4 KByte pages, 4-way set associative, 512 entries",
742 0x66 => "1st-level data cache: 8 KByte, 4-way set associative, 64 byte line size",
743 0x67 => "1st-level data cache: 16 KByte, 4-way set associative, 64 byte line size",
744 0x68 => "1st-level data cache: 32 KByte, 4-way set associative, 64 byte line size",
745 0x6A => "uTLB: 4 KByte pages, 8-way set associative, 64 entries",
746 0x6B => "DTLB: 4 KByte pages, 8-way set associative, 256 entries",
747 0x6C => "DTLB: 2M/4M pages, 8-way set associative, 128 entries",
748 0x6D => "DTLB: 1 GByte pages, fully associative, 16 entries",
749 0x70 => "Trace cache: 12 K-μop, 8-way set associative",
750 0x71 => "Trace cache: 16 K-μop, 8-way set associative",
751 0x72 => "Trace cache: 32 K-μop, 8-way set associative",
752 0x76 => "Instruction TLB: 2M/4M pages, fully associative, 8 entries",
753 0x78 => "2nd-level cache: 1 MByte, 4-way set associative, 64byte line size",
754 0x79 => "2nd-level cache: 128 KByte, 8-way set associative, 64 byte line size, 2 lines per sector",
755 0x7A => "2nd-level cache: 256 KByte, 8-way set associative, 64 byte line size, 2 lines per sector",
756 0x7B => "2nd-level cache: 512 KByte, 8-way set associative, 64 byte line size, 2 lines per sector",
757 0x7C => "2nd-level cache: 1 MByte, 8-way set associative, 64 byte line size, 2 lines per sector",
758 0x7D => "2nd-level cache: 2 MByte, 8-way set associative, 64byte line size",
759 0x7F => "2nd-level cache: 512 KByte, 2-way set associative, 64-byte line size",
760 0x80 => "2nd-level cache: 512 KByte, 8-way set associative, 64-byte line size",
761 0x82 => "2nd-level cache: 256 KByte, 8-way set associative, 32 byte line size",
762 0x83 => "2nd-level cache: 512 KByte, 8-way set associative, 32 byte line size",
763 0x84 => "2nd-level cache: 1 MByte, 8-way set associative, 32 byte line size",
764 0x85 => "2nd-level cache: 2 MByte, 8-way set associative, 32 byte line size",
765 0x86 => "2nd-level cache: 512 KByte, 4-way set associative, 64 byte line size",
766 0x87 => "2nd-level cache: 1 MByte, 8-way set associative, 64 byte line size",
767 0xA0 => "DTLB: 4k pages, fully associative, 32 entries",
768 0xB0 => "Instruction TLB: 4 KByte pages, 4-way set associative, 128 entries",
769 0xB1 => "Instruction TLB: 2M pages, 4-way, 8 entries or 4M pages, 4-way, 4 entries",
770 0xB2 => "Instruction TLB: 4KByte pages, 4-way set associative, 64 entries",
771 0xB3 => "Data TLB: 4 KByte pages, 4-way set associative, 128 entries",
772 0xB4 => "Data TLB1: 4 KByte pages, 4-way associative, 256 entries",
773 0xB5 => "Instruction TLB: 4KByte pages, 8-way set associative, 64 entries",
774 0xB6 => "Instruction TLB: 4KByte pages, 8-way set associative, 128 entries",
775 0xBA => "Data TLB1: 4 KByte pages, 4-way associative, 64 entries",
776 0xC0 => "Data TLB: 4 KByte and 4 MByte pages, 4-way associative, 8 entries",
777 0xC1 => "Shared 2nd-Level TLB: 4 KByte/2MByte pages, 8-way associative, 1024 entries",
778 0xC2 => "DTLB: 2 MByte/$MByte pages, 4-way associative, 16 entries",
779 0xC3 => "Shared 2nd-Level TLB: 4 KByte /2 MByte pages, 6-way associative, 1536 entries. Also 1GBbyte pages, 4-way, 16 entries.",
780 0xC4 => "DTLB: 2M/4M Byte pages, 4-way associative, 32 entries",
781 0xCA => "Shared 2nd-Level TLB: 4 KByte pages, 4-way associative, 512 entries",
782 0xD0 => "3rd-level cache: 512 KByte, 4-way set associative, 64 byte line size",
783 0xD1 => "3rd-level cache: 1 MByte, 4-way set associative, 64 byte line size",
784 0xD2 => "3rd-level cache: 2 MByte, 4-way set associative, 64 byte line size",
785 0xD6 => "3rd-level cache: 1 MByte, 8-way set associative, 64 byte line size",
786 0xD7 => "3rd-level cache: 2 MByte, 8-way set associative, 64 byte line size",
787 0xD8 => "3rd-level cache: 4 MByte, 8-way set associative, 64 byte line size",
788 0xDC => "3rd-level cache: 1.5 MByte, 12-way set associative, 64 byte line size",
789 0xDD => "3rd-level cache: 3 MByte, 12-way set associative, 64 byte line size",
790 0xDE => "3rd-level cache: 6 MByte, 12-way set associative, 64 byte line size",
791 0xE2 => "3rd-level cache: 2 MByte, 16-way set associative, 64 byte line size",
792 0xE3 => "3rd-level cache: 4 MByte, 16-way set associative, 64 byte line size",
793 0xE4 => "3rd-level cache: 8 MByte, 16-way set associative, 64 byte line size",
794 0xEA => "3rd-level cache: 12MByte, 24-way set associative, 64 byte line size",
795 0xEB => "3rd-level cache: 18MByte, 24-way set associative, 64 byte line size",
796 0xEC => "3rd-level cache: 24MByte, 24-way set associative, 64 byte line size",
797 0xF0 => "64-Byte prefetching",
798 0xF1 => "128-Byte prefetching",
799 0xFE => "CPUID leaf 2 does not report TLB descriptor information; use CPUID leaf 18H to query TLB and other address translation parameters.",
800 0xFF => "CPUID leaf 2 does not report cache descriptor information, use CPUID leaf 4 to query cache parameters",
801 _ => "Unknown cache type!"
802 }
803 }
804 }
805
806 impl fmt::Display for CacheInfo {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result807 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
808 let typ = match self.typ {
809 CacheInfoType::General => "N/A",
810 CacheInfoType::Cache => "Cache",
811 CacheInfoType::TLB => "TLB",
812 CacheInfoType::STLB => "STLB",
813 CacheInfoType::DTLB => "DTLB",
814 CacheInfoType::Prefetch => "Prefetcher",
815 };
816
817 write!(f, "{:x}:\t {}: {}", self.num, typ, self.desc())
818 }
819 }
820
821 /// This table is taken from Intel manual (Section CPUID instruction).
822 pub const CACHE_INFO_TABLE: [CacheInfo; 108] = [
823 CacheInfo {
824 num: 0x00,
825 typ: CacheInfoType::General,
826 },
827 CacheInfo {
828 num: 0x01,
829 typ: CacheInfoType::TLB,
830 },
831 CacheInfo {
832 num: 0x02,
833 typ: CacheInfoType::TLB,
834 },
835 CacheInfo {
836 num: 0x03,
837 typ: CacheInfoType::TLB,
838 },
839 CacheInfo {
840 num: 0x04,
841 typ: CacheInfoType::TLB,
842 },
843 CacheInfo {
844 num: 0x05,
845 typ: CacheInfoType::TLB,
846 },
847 CacheInfo {
848 num: 0x06,
849 typ: CacheInfoType::Cache,
850 },
851 CacheInfo {
852 num: 0x08,
853 typ: CacheInfoType::Cache,
854 },
855 CacheInfo {
856 num: 0x09,
857 typ: CacheInfoType::Cache,
858 },
859 CacheInfo {
860 num: 0x0A,
861 typ: CacheInfoType::Cache,
862 },
863 CacheInfo {
864 num: 0x0B,
865 typ: CacheInfoType::TLB,
866 },
867 CacheInfo {
868 num: 0x0C,
869 typ: CacheInfoType::Cache,
870 },
871 CacheInfo {
872 num: 0x0D,
873 typ: CacheInfoType::Cache,
874 },
875 CacheInfo {
876 num: 0x0E,
877 typ: CacheInfoType::Cache,
878 },
879 CacheInfo {
880 num: 0x21,
881 typ: CacheInfoType::Cache,
882 },
883 CacheInfo {
884 num: 0x22,
885 typ: CacheInfoType::Cache,
886 },
887 CacheInfo {
888 num: 0x23,
889 typ: CacheInfoType::Cache,
890 },
891 CacheInfo {
892 num: 0x24,
893 typ: CacheInfoType::Cache,
894 },
895 CacheInfo {
896 num: 0x25,
897 typ: CacheInfoType::Cache,
898 },
899 CacheInfo {
900 num: 0x29,
901 typ: CacheInfoType::Cache,
902 },
903 CacheInfo {
904 num: 0x2C,
905 typ: CacheInfoType::Cache,
906 },
907 CacheInfo {
908 num: 0x30,
909 typ: CacheInfoType::Cache,
910 },
911 CacheInfo {
912 num: 0x40,
913 typ: CacheInfoType::Cache,
914 },
915 CacheInfo {
916 num: 0x41,
917 typ: CacheInfoType::Cache,
918 },
919 CacheInfo {
920 num: 0x42,
921 typ: CacheInfoType::Cache,
922 },
923 CacheInfo {
924 num: 0x43,
925 typ: CacheInfoType::Cache,
926 },
927 CacheInfo {
928 num: 0x44,
929 typ: CacheInfoType::Cache,
930 },
931 CacheInfo {
932 num: 0x45,
933 typ: CacheInfoType::Cache,
934 },
935 CacheInfo {
936 num: 0x46,
937 typ: CacheInfoType::Cache,
938 },
939 CacheInfo {
940 num: 0x47,
941 typ: CacheInfoType::Cache,
942 },
943 CacheInfo {
944 num: 0x48,
945 typ: CacheInfoType::Cache,
946 },
947 CacheInfo {
948 num: 0x49,
949 typ: CacheInfoType::Cache,
950 },
951 CacheInfo {
952 num: 0x4A,
953 typ: CacheInfoType::Cache,
954 },
955 CacheInfo {
956 num: 0x4B,
957 typ: CacheInfoType::Cache,
958 },
959 CacheInfo {
960 num: 0x4C,
961 typ: CacheInfoType::Cache,
962 },
963 CacheInfo {
964 num: 0x4D,
965 typ: CacheInfoType::Cache,
966 },
967 CacheInfo {
968 num: 0x4E,
969 typ: CacheInfoType::Cache,
970 },
971 CacheInfo {
972 num: 0x4F,
973 typ: CacheInfoType::TLB,
974 },
975 CacheInfo {
976 num: 0x50,
977 typ: CacheInfoType::TLB,
978 },
979 CacheInfo {
980 num: 0x51,
981 typ: CacheInfoType::TLB,
982 },
983 CacheInfo {
984 num: 0x52,
985 typ: CacheInfoType::TLB,
986 },
987 CacheInfo {
988 num: 0x55,
989 typ: CacheInfoType::TLB,
990 },
991 CacheInfo {
992 num: 0x56,
993 typ: CacheInfoType::TLB,
994 },
995 CacheInfo {
996 num: 0x57,
997 typ: CacheInfoType::TLB,
998 },
999 CacheInfo {
1000 num: 0x59,
1001 typ: CacheInfoType::TLB,
1002 },
1003 CacheInfo {
1004 num: 0x5A,
1005 typ: CacheInfoType::TLB,
1006 },
1007 CacheInfo {
1008 num: 0x5B,
1009 typ: CacheInfoType::TLB,
1010 },
1011 CacheInfo {
1012 num: 0x5C,
1013 typ: CacheInfoType::TLB,
1014 },
1015 CacheInfo {
1016 num: 0x5D,
1017 typ: CacheInfoType::TLB,
1018 },
1019 CacheInfo {
1020 num: 0x60,
1021 typ: CacheInfoType::Cache,
1022 },
1023 CacheInfo {
1024 num: 0x61,
1025 typ: CacheInfoType::TLB,
1026 },
1027 CacheInfo {
1028 num: 0x63,
1029 typ: CacheInfoType::TLB,
1030 },
1031 CacheInfo {
1032 num: 0x66,
1033 typ: CacheInfoType::Cache,
1034 },
1035 CacheInfo {
1036 num: 0x67,
1037 typ: CacheInfoType::Cache,
1038 },
1039 CacheInfo {
1040 num: 0x68,
1041 typ: CacheInfoType::Cache,
1042 },
1043 CacheInfo {
1044 num: 0x6A,
1045 typ: CacheInfoType::Cache,
1046 },
1047 CacheInfo {
1048 num: 0x6B,
1049 typ: CacheInfoType::Cache,
1050 },
1051 CacheInfo {
1052 num: 0x6C,
1053 typ: CacheInfoType::Cache,
1054 },
1055 CacheInfo {
1056 num: 0x6D,
1057 typ: CacheInfoType::Cache,
1058 },
1059 CacheInfo {
1060 num: 0x70,
1061 typ: CacheInfoType::Cache,
1062 },
1063 CacheInfo {
1064 num: 0x71,
1065 typ: CacheInfoType::Cache,
1066 },
1067 CacheInfo {
1068 num: 0x72,
1069 typ: CacheInfoType::Cache,
1070 },
1071 CacheInfo {
1072 num: 0x76,
1073 typ: CacheInfoType::TLB,
1074 },
1075 CacheInfo {
1076 num: 0x78,
1077 typ: CacheInfoType::Cache,
1078 },
1079 CacheInfo {
1080 num: 0x79,
1081 typ: CacheInfoType::Cache,
1082 },
1083 CacheInfo {
1084 num: 0x7A,
1085 typ: CacheInfoType::Cache,
1086 },
1087 CacheInfo {
1088 num: 0x7B,
1089 typ: CacheInfoType::Cache,
1090 },
1091 CacheInfo {
1092 num: 0x7C,
1093 typ: CacheInfoType::Cache,
1094 },
1095 CacheInfo {
1096 num: 0x7D,
1097 typ: CacheInfoType::Cache,
1098 },
1099 CacheInfo {
1100 num: 0x7F,
1101 typ: CacheInfoType::Cache,
1102 },
1103 CacheInfo {
1104 num: 0x80,
1105 typ: CacheInfoType::Cache,
1106 },
1107 CacheInfo {
1108 num: 0x82,
1109 typ: CacheInfoType::Cache,
1110 },
1111 CacheInfo {
1112 num: 0x83,
1113 typ: CacheInfoType::Cache,
1114 },
1115 CacheInfo {
1116 num: 0x84,
1117 typ: CacheInfoType::Cache,
1118 },
1119 CacheInfo {
1120 num: 0x85,
1121 typ: CacheInfoType::Cache,
1122 },
1123 CacheInfo {
1124 num: 0x86,
1125 typ: CacheInfoType::Cache,
1126 },
1127 CacheInfo {
1128 num: 0x87,
1129 typ: CacheInfoType::Cache,
1130 },
1131 CacheInfo {
1132 num: 0xB0,
1133 typ: CacheInfoType::TLB,
1134 },
1135 CacheInfo {
1136 num: 0xB1,
1137 typ: CacheInfoType::TLB,
1138 },
1139 CacheInfo {
1140 num: 0xB2,
1141 typ: CacheInfoType::TLB,
1142 },
1143 CacheInfo {
1144 num: 0xB3,
1145 typ: CacheInfoType::TLB,
1146 },
1147 CacheInfo {
1148 num: 0xB4,
1149 typ: CacheInfoType::TLB,
1150 },
1151 CacheInfo {
1152 num: 0xB5,
1153 typ: CacheInfoType::TLB,
1154 },
1155 CacheInfo {
1156 num: 0xB6,
1157 typ: CacheInfoType::TLB,
1158 },
1159 CacheInfo {
1160 num: 0xBA,
1161 typ: CacheInfoType::TLB,
1162 },
1163 CacheInfo {
1164 num: 0xC0,
1165 typ: CacheInfoType::TLB,
1166 },
1167 CacheInfo {
1168 num: 0xC1,
1169 typ: CacheInfoType::STLB,
1170 },
1171 CacheInfo {
1172 num: 0xC2,
1173 typ: CacheInfoType::DTLB,
1174 },
1175 CacheInfo {
1176 num: 0xCA,
1177 typ: CacheInfoType::STLB,
1178 },
1179 CacheInfo {
1180 num: 0xD0,
1181 typ: CacheInfoType::Cache,
1182 },
1183 CacheInfo {
1184 num: 0xD1,
1185 typ: CacheInfoType::Cache,
1186 },
1187 CacheInfo {
1188 num: 0xD2,
1189 typ: CacheInfoType::Cache,
1190 },
1191 CacheInfo {
1192 num: 0xD6,
1193 typ: CacheInfoType::Cache,
1194 },
1195 CacheInfo {
1196 num: 0xD7,
1197 typ: CacheInfoType::Cache,
1198 },
1199 CacheInfo {
1200 num: 0xD8,
1201 typ: CacheInfoType::Cache,
1202 },
1203 CacheInfo {
1204 num: 0xDC,
1205 typ: CacheInfoType::Cache,
1206 },
1207 CacheInfo {
1208 num: 0xDD,
1209 typ: CacheInfoType::Cache,
1210 },
1211 CacheInfo {
1212 num: 0xDE,
1213 typ: CacheInfoType::Cache,
1214 },
1215 CacheInfo {
1216 num: 0xE2,
1217 typ: CacheInfoType::Cache,
1218 },
1219 CacheInfo {
1220 num: 0xE3,
1221 typ: CacheInfoType::Cache,
1222 },
1223 CacheInfo {
1224 num: 0xE4,
1225 typ: CacheInfoType::Cache,
1226 },
1227 CacheInfo {
1228 num: 0xEA,
1229 typ: CacheInfoType::Cache,
1230 },
1231 CacheInfo {
1232 num: 0xEB,
1233 typ: CacheInfoType::Cache,
1234 },
1235 CacheInfo {
1236 num: 0xEC,
1237 typ: CacheInfoType::Cache,
1238 },
1239 CacheInfo {
1240 num: 0xF0,
1241 typ: CacheInfoType::Prefetch,
1242 },
1243 CacheInfo {
1244 num: 0xF1,
1245 typ: CacheInfoType::Prefetch,
1246 },
1247 CacheInfo {
1248 num: 0xFE,
1249 typ: CacheInfoType::General,
1250 },
1251 CacheInfo {
1252 num: 0xFF,
1253 typ: CacheInfoType::General,
1254 },
1255 ];
1256
1257 impl fmt::Display for VendorInfo {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1258 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1259 write!(f, "{}", self.as_string())
1260 }
1261 }
1262
1263 #[derive(Debug, Default)]
1264 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
1265 pub struct ProcessorSerial {
1266 ecx: u32,
1267 edx: u32,
1268 }
1269
1270 impl ProcessorSerial {
1271 /// Bits 00-31 of 96 bit processor serial number.
1272 /// (Available in Pentium III processor only; otherwise, the value in this register is reserved.)
serial_lower(&self) -> u321273 pub fn serial_lower(&self) -> u32 {
1274 self.ecx
1275 }
1276
1277 /// Bits 32-63 of 96 bit processor serial number.
1278 /// (Available in Pentium III processor only; otherwise, the value in this register is reserved.)
serial_middle(&self) -> u321279 pub fn serial_middle(&self) -> u32 {
1280 self.edx
1281 }
1282 }
1283
1284 #[derive(Debug, Default)]
1285 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
1286 pub struct FeatureInfo {
1287 eax: u32,
1288 ebx: u32,
1289 edx_ecx: FeatureInfoFlags,
1290 }
1291
1292 impl FeatureInfo {
1293 /// Version Information: Extended Family
extended_family_id(&self) -> u81294 pub fn extended_family_id(&self) -> u8 {
1295 get_bits(self.eax, 20, 27) as u8
1296 }
1297
1298 /// Version Information: Extended Model
extended_model_id(&self) -> u81299 pub fn extended_model_id(&self) -> u8 {
1300 get_bits(self.eax, 16, 19) as u8
1301 }
1302
1303 /// Version Information: Family
family_id(&self) -> u81304 pub fn family_id(&self) -> u8 {
1305 get_bits(self.eax, 8, 11) as u8
1306 }
1307
1308 /// Version Information: Model
model_id(&self) -> u81309 pub fn model_id(&self) -> u8 {
1310 get_bits(self.eax, 4, 7) as u8
1311 }
1312
1313 /// Version Information: Stepping ID
stepping_id(&self) -> u81314 pub fn stepping_id(&self) -> u8 {
1315 get_bits(self.eax, 0, 3) as u8
1316 }
1317
1318 /// Brand Index
brand_index(&self) -> u81319 pub fn brand_index(&self) -> u8 {
1320 get_bits(self.ebx, 0, 7) as u8
1321 }
1322
1323 /// CLFLUSH line size (Value ∗ 8 = cache line size in bytes)
cflush_cache_line_size(&self) -> u81324 pub fn cflush_cache_line_size(&self) -> u8 {
1325 get_bits(self.ebx, 8, 15) as u8
1326 }
1327
1328 /// Initial APIC ID
initial_local_apic_id(&self) -> u81329 pub fn initial_local_apic_id(&self) -> u8 {
1330 get_bits(self.ebx, 24, 31) as u8
1331 }
1332
1333 /// Maximum number of addressable IDs for logical processors in this physical package.
max_logical_processor_ids(&self) -> u81334 pub fn max_logical_processor_ids(&self) -> u8 {
1335 get_bits(self.ebx, 16, 23) as u8
1336 }
1337
1338 check_flag!(
1339 doc = "Streaming SIMD Extensions 3 (SSE3). A value of 1 indicates the processor \
1340 supports this technology.",
1341 has_sse3,
1342 edx_ecx,
1343 FeatureInfoFlags::SSE3
1344 );
1345
1346 check_flag!(
1347 doc = "PCLMULQDQ. A value of 1 indicates the processor supports the PCLMULQDQ \
1348 instruction",
1349 has_pclmulqdq,
1350 edx_ecx,
1351 FeatureInfoFlags::PCLMULQDQ
1352 );
1353
1354 check_flag!(
1355 doc = "64-bit DS Area. A value of 1 indicates the processor supports DS area \
1356 using 64-bit layout",
1357 has_ds_area,
1358 edx_ecx,
1359 FeatureInfoFlags::DTES64
1360 );
1361
1362 check_flag!(
1363 doc = "MONITOR/MWAIT. A value of 1 indicates the processor supports this feature.",
1364 has_monitor_mwait,
1365 edx_ecx,
1366 FeatureInfoFlags::MONITOR
1367 );
1368
1369 check_flag!(
1370 doc = "CPL Qualified Debug Store. A value of 1 indicates the processor supports \
1371 the extensions to the Debug Store feature to allow for branch message \
1372 storage qualified by CPL.",
1373 has_cpl,
1374 edx_ecx,
1375 FeatureInfoFlags::DSCPL
1376 );
1377
1378 check_flag!(
1379 doc = "Virtual Machine Extensions. A value of 1 indicates that the processor \
1380 supports this technology.",
1381 has_vmx,
1382 edx_ecx,
1383 FeatureInfoFlags::VMX
1384 );
1385
1386 check_flag!(
1387 doc = "Safer Mode Extensions. A value of 1 indicates that the processor supports \
1388 this technology. See Chapter 5, Safer Mode Extensions Reference.",
1389 has_smx,
1390 edx_ecx,
1391 FeatureInfoFlags::SMX
1392 );
1393
1394 check_flag!(
1395 doc = "Enhanced Intel SpeedStep® technology. A value of 1 indicates that the \
1396 processor supports this technology.",
1397 has_eist,
1398 edx_ecx,
1399 FeatureInfoFlags::EIST
1400 );
1401
1402 check_flag!(
1403 doc = "Thermal Monitor 2. A value of 1 indicates whether the processor supports \
1404 this technology.",
1405 has_tm2,
1406 edx_ecx,
1407 FeatureInfoFlags::TM2
1408 );
1409
1410 check_flag!(
1411 doc = "A value of 1 indicates the presence of the Supplemental Streaming SIMD \
1412 Extensions 3 (SSSE3). A value of 0 indicates the instruction extensions \
1413 are not present in the processor",
1414 has_ssse3,
1415 edx_ecx,
1416 FeatureInfoFlags::SSSE3
1417 );
1418
1419 check_flag!(
1420 doc = "L1 Context ID. A value of 1 indicates the L1 data cache mode can be set \
1421 to either adaptive mode or shared mode. A value of 0 indicates this \
1422 feature is not supported. See definition of the IA32_MISC_ENABLE MSR Bit \
1423 24 (L1 Data Cache Context Mode) for details.",
1424 has_cnxtid,
1425 edx_ecx,
1426 FeatureInfoFlags::CNXTID
1427 );
1428
1429 check_flag!(
1430 doc = "A value of 1 indicates the processor supports FMA extensions using YMM \
1431 state.",
1432 has_fma,
1433 edx_ecx,
1434 FeatureInfoFlags::FMA
1435 );
1436
1437 check_flag!(
1438 doc = "CMPXCHG16B Available. A value of 1 indicates that the feature is \
1439 available. See the CMPXCHG8B/CMPXCHG16B Compare and Exchange Bytes \
1440 section. 14",
1441 has_cmpxchg16b,
1442 edx_ecx,
1443 FeatureInfoFlags::CMPXCHG16B
1444 );
1445
1446 check_flag!(
1447 doc = "Perfmon and Debug Capability: A value of 1 indicates the processor \
1448 supports the performance and debug feature indication MSR \
1449 IA32_PERF_CAPABILITIES.",
1450 has_pdcm,
1451 edx_ecx,
1452 FeatureInfoFlags::PDCM
1453 );
1454
1455 check_flag!(
1456 doc = "Process-context identifiers. A value of 1 indicates that the processor \
1457 supports PCIDs and the software may set CR4.PCIDE to 1.",
1458 has_pcid,
1459 edx_ecx,
1460 FeatureInfoFlags::PCID
1461 );
1462
1463 check_flag!(
1464 doc = "A value of 1 indicates the processor supports the ability to prefetch \
1465 data from a memory mapped device.",
1466 has_dca,
1467 edx_ecx,
1468 FeatureInfoFlags::DCA
1469 );
1470
1471 check_flag!(
1472 doc = "A value of 1 indicates that the processor supports SSE4.1.",
1473 has_sse41,
1474 edx_ecx,
1475 FeatureInfoFlags::SSE41
1476 );
1477
1478 check_flag!(
1479 doc = "A value of 1 indicates that the processor supports SSE4.2.",
1480 has_sse42,
1481 edx_ecx,
1482 FeatureInfoFlags::SSE42
1483 );
1484
1485 check_flag!(
1486 doc = "A value of 1 indicates that the processor supports x2APIC feature.",
1487 has_x2apic,
1488 edx_ecx,
1489 FeatureInfoFlags::X2APIC
1490 );
1491
1492 check_flag!(
1493 doc = "A value of 1 indicates that the processor supports MOVBE instruction.",
1494 has_movbe,
1495 edx_ecx,
1496 FeatureInfoFlags::MOVBE
1497 );
1498
1499 check_flag!(
1500 doc = "A value of 1 indicates that the processor supports the POPCNT instruction.",
1501 has_popcnt,
1502 edx_ecx,
1503 FeatureInfoFlags::POPCNT
1504 );
1505
1506 check_flag!(
1507 doc = "A value of 1 indicates that the processors local APIC timer supports \
1508 one-shot operation using a TSC deadline value.",
1509 has_tsc_deadline,
1510 edx_ecx,
1511 FeatureInfoFlags::TSC_DEADLINE
1512 );
1513
1514 check_flag!(
1515 doc = "A value of 1 indicates that the processor supports the AESNI instruction \
1516 extensions.",
1517 has_aesni,
1518 edx_ecx,
1519 FeatureInfoFlags::AESNI
1520 );
1521
1522 check_flag!(
1523 doc = "A value of 1 indicates that the processor supports the XSAVE/XRSTOR \
1524 processor extended states feature, the XSETBV/XGETBV instructions, and \
1525 XCR0.",
1526 has_xsave,
1527 edx_ecx,
1528 FeatureInfoFlags::XSAVE
1529 );
1530
1531 check_flag!(
1532 doc = "A value of 1 indicates that the OS has enabled XSETBV/XGETBV instructions \
1533 to access XCR0, and support for processor extended state management using \
1534 XSAVE/XRSTOR.",
1535 has_oxsave,
1536 edx_ecx,
1537 FeatureInfoFlags::OSXSAVE
1538 );
1539
1540 check_flag!(
1541 doc = "A value of 1 indicates the processor supports the AVX instruction \
1542 extensions.",
1543 has_avx,
1544 edx_ecx,
1545 FeatureInfoFlags::AVX
1546 );
1547
1548 check_flag!(
1549 doc = "A value of 1 indicates that processor supports 16-bit floating-point \
1550 conversion instructions.",
1551 has_f16c,
1552 edx_ecx,
1553 FeatureInfoFlags::F16C
1554 );
1555
1556 check_flag!(
1557 doc = "A value of 1 indicates that processor supports RDRAND instruction.",
1558 has_rdrand,
1559 edx_ecx,
1560 FeatureInfoFlags::RDRAND
1561 );
1562
1563 check_flag!(
1564 doc = "Floating Point Unit On-Chip. The processor contains an x87 FPU.",
1565 has_fpu,
1566 edx_ecx,
1567 FeatureInfoFlags::FPU
1568 );
1569
1570 check_flag!(
1571 doc = "Virtual 8086 Mode Enhancements. Virtual 8086 mode enhancements, including \
1572 CR4.VME for controlling the feature, CR4.PVI for protected mode virtual \
1573 interrupts, software interrupt indirection, expansion of the TSS with the \
1574 software indirection bitmap, and EFLAGS.VIF and EFLAGS.VIP flags.",
1575 has_vme,
1576 edx_ecx,
1577 FeatureInfoFlags::VME
1578 );
1579
1580 check_flag!(
1581 doc = "Debugging Extensions. Support for I/O breakpoints, including CR4.DE for \
1582 controlling the feature, and optional trapping of accesses to DR4 and DR5.",
1583 has_de,
1584 edx_ecx,
1585 FeatureInfoFlags::DE
1586 );
1587
1588 check_flag!(
1589 doc = "Page Size Extension. Large pages of size 4 MByte are supported, including \
1590 CR4.PSE for controlling the feature, the defined dirty bit in PDE (Page \
1591 Directory Entries), optional reserved bit trapping in CR3, PDEs, and PTEs.",
1592 has_pse,
1593 edx_ecx,
1594 FeatureInfoFlags::PSE
1595 );
1596
1597 check_flag!(
1598 doc = "Time Stamp Counter. The RDTSC instruction is supported, including CR4.TSD \
1599 for controlling privilege.",
1600 has_tsc,
1601 edx_ecx,
1602 FeatureInfoFlags::TSC
1603 );
1604
1605 check_flag!(
1606 doc = "Model Specific Registers RDMSR and WRMSR Instructions. The RDMSR and \
1607 WRMSR instructions are supported. Some of the MSRs are implementation \
1608 dependent.",
1609 has_msr,
1610 edx_ecx,
1611 FeatureInfoFlags::MSR
1612 );
1613
1614 check_flag!(
1615 doc = "Physical Address Extension. Physical addresses greater than 32 bits are \
1616 supported: extended page table entry formats, an extra level in the page \
1617 translation tables is defined, 2-MByte pages are supported instead of 4 \
1618 Mbyte pages if PAE bit is 1.",
1619 has_pae,
1620 edx_ecx,
1621 FeatureInfoFlags::PAE
1622 );
1623
1624 check_flag!(
1625 doc = "Machine Check Exception. Exception 18 is defined for Machine Checks, \
1626 including CR4.MCE for controlling the feature. This feature does not \
1627 define the model-specific implementations of machine-check error logging, \
1628 reporting, and processor shutdowns. Machine Check exception handlers may \
1629 have to depend on processor version to do model specific processing of \
1630 the exception, or test for the presence of the Machine Check feature.",
1631 has_mce,
1632 edx_ecx,
1633 FeatureInfoFlags::MCE
1634 );
1635
1636 check_flag!(
1637 doc = "CMPXCHG8B Instruction. The compare-and-exchange 8 bytes (64 bits) \
1638 instruction is supported (implicitly locked and atomic).",
1639 has_cmpxchg8b,
1640 edx_ecx,
1641 FeatureInfoFlags::CX8
1642 );
1643
1644 check_flag!(
1645 doc = "APIC On-Chip. The processor contains an Advanced Programmable Interrupt \
1646 Controller (APIC), responding to memory mapped commands in the physical \
1647 address range FFFE0000H to FFFE0FFFH (by default - some processors permit \
1648 the APIC to be relocated).",
1649 has_apic,
1650 edx_ecx,
1651 FeatureInfoFlags::APIC
1652 );
1653
1654 check_flag!(
1655 doc = "SYSENTER and SYSEXIT Instructions. The SYSENTER and SYSEXIT and \
1656 associated MSRs are supported.",
1657 has_sysenter_sysexit,
1658 edx_ecx,
1659 FeatureInfoFlags::SEP
1660 );
1661
1662 check_flag!(
1663 doc = "Memory Type Range Registers. MTRRs are supported. The MTRRcap MSR \
1664 contains feature bits that describe what memory types are supported, how \
1665 many variable MTRRs are supported, and whether fixed MTRRs are supported.",
1666 has_mtrr,
1667 edx_ecx,
1668 FeatureInfoFlags::MTRR
1669 );
1670
1671 check_flag!(
1672 doc = "Page Global Bit. The global bit is supported in paging-structure entries \
1673 that map a page, indicating TLB entries that are common to different \
1674 processes and need not be flushed. The CR4.PGE bit controls this feature.",
1675 has_pge,
1676 edx_ecx,
1677 FeatureInfoFlags::PGE
1678 );
1679
1680 check_flag!(
1681 doc = "Machine Check Architecture. A value of 1 indicates the Machine Check \
1682 Architecture of reporting machine errors is supported. The MCG_CAP MSR \
1683 contains feature bits describing how many banks of error reporting MSRs \
1684 are supported.",
1685 has_mca,
1686 edx_ecx,
1687 FeatureInfoFlags::MCA
1688 );
1689
1690 check_flag!(
1691 doc = "Conditional Move Instructions. The conditional move instruction CMOV is \
1692 supported. In addition, if x87 FPU is present as indicated by the \
1693 CPUID.FPU feature bit, then the FCOMI and FCMOV instructions are supported",
1694 has_cmov,
1695 edx_ecx,
1696 FeatureInfoFlags::CMOV
1697 );
1698
1699 check_flag!(
1700 doc = "Page Attribute Table. Page Attribute Table is supported. This feature \
1701 augments the Memory Type Range Registers (MTRRs), allowing an operating \
1702 system to specify attributes of memory accessed through a linear address \
1703 on a 4KB granularity.",
1704 has_pat,
1705 edx_ecx,
1706 FeatureInfoFlags::PAT
1707 );
1708
1709 check_flag!(
1710 doc = "36-Bit Page Size Extension. 4-MByte pages addressing physical memory \
1711 beyond 4 GBytes are supported with 32-bit paging. This feature indicates \
1712 that upper bits of the physical address of a 4-MByte page are encoded in \
1713 bits 20:13 of the page-directory entry. Such physical addresses are \
1714 limited by MAXPHYADDR and may be up to 40 bits in size.",
1715 has_pse36,
1716 edx_ecx,
1717 FeatureInfoFlags::PSE36
1718 );
1719
1720 check_flag!(
1721 doc = "Processor Serial Number. The processor supports the 96-bit processor \
1722 identification number feature and the feature is enabled.",
1723 has_psn,
1724 edx_ecx,
1725 FeatureInfoFlags::PSN
1726 );
1727
1728 check_flag!(
1729 doc = "CLFLUSH Instruction. CLFLUSH Instruction is supported.",
1730 has_clflush,
1731 edx_ecx,
1732 FeatureInfoFlags::CLFSH
1733 );
1734
1735 check_flag!(
1736 doc = "Debug Store. The processor supports the ability to write debug \
1737 information into a memory resident buffer. This feature is used by the \
1738 branch trace store (BTS) and processor event-based sampling (PEBS) \
1739 facilities (see Chapter 23, Introduction to Virtual-Machine Extensions, \
1740 in the Intel® 64 and IA-32 Architectures Software Developers Manual, \
1741 Volume 3C).",
1742 has_ds,
1743 edx_ecx,
1744 FeatureInfoFlags::DS
1745 );
1746
1747 check_flag!(
1748 doc = "Thermal Monitor and Software Controlled Clock Facilities. The processor \
1749 implements internal MSRs that allow processor temperature to be monitored \
1750 and processor performance to be modulated in predefined duty cycles under \
1751 software control.",
1752 has_acpi,
1753 edx_ecx,
1754 FeatureInfoFlags::ACPI
1755 );
1756
1757 check_flag!(
1758 doc = "Intel MMX Technology. The processor supports the Intel MMX technology.",
1759 has_mmx,
1760 edx_ecx,
1761 FeatureInfoFlags::MMX
1762 );
1763
1764 check_flag!(
1765 doc = "FXSAVE and FXRSTOR Instructions. The FXSAVE and FXRSTOR instructions are \
1766 supported for fast save and restore of the floating point context. \
1767 Presence of this bit also indicates that CR4.OSFXSR is available for an \
1768 operating system to indicate that it supports the FXSAVE and FXRSTOR \
1769 instructions.",
1770 has_fxsave_fxstor,
1771 edx_ecx,
1772 FeatureInfoFlags::FXSR
1773 );
1774
1775 check_flag!(
1776 doc = "SSE. The processor supports the SSE extensions.",
1777 has_sse,
1778 edx_ecx,
1779 FeatureInfoFlags::SSE
1780 );
1781
1782 check_flag!(
1783 doc = "SSE2. The processor supports the SSE2 extensions.",
1784 has_sse2,
1785 edx_ecx,
1786 FeatureInfoFlags::SSE2
1787 );
1788
1789 check_flag!(
1790 doc = "Self Snoop. The processor supports the management of conflicting memory \
1791 types by performing a snoop of its own cache structure for transactions \
1792 issued to the bus.",
1793 has_ss,
1794 edx_ecx,
1795 FeatureInfoFlags::SS
1796 );
1797
1798 check_flag!(
1799 doc = "Max APIC IDs reserved field is Valid. A value of 0 for HTT indicates \
1800 there is only a single logical processor in the package and software \
1801 should assume only a single APIC ID is reserved. A value of 1 for HTT \
1802 indicates the value in CPUID.1.EBX\\[23:16\\] (the Maximum number of \
1803 addressable IDs for logical processors in this package) is valid for the \
1804 package.",
1805 has_htt,
1806 edx_ecx,
1807 FeatureInfoFlags::HTT
1808 );
1809
1810 check_flag!(
1811 doc = "Thermal Monitor. The processor implements the thermal monitor automatic \
1812 thermal control circuitry (TCC).",
1813 has_tm,
1814 edx_ecx,
1815 FeatureInfoFlags::TM
1816 );
1817
1818 check_flag!(
1819 doc = "Pending Break Enable. The processor supports the use of the FERR#/PBE# \
1820 pin when the processor is in the stop-clock state (STPCLK# is asserted) \
1821 to signal the processor that an interrupt is pending and that the \
1822 processor should return to normal operation to handle the interrupt. Bit \
1823 10 (PBE enable) in the IA32_MISC_ENABLE MSR enables this capability.",
1824 has_pbe,
1825 edx_ecx,
1826 FeatureInfoFlags::PBE
1827 );
1828 }
1829
1830 bitflags! {
1831 #[derive(Default)]
1832 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
1833 struct FeatureInfoFlags: u64 {
1834
1835 // ECX flags
1836
1837 /// Streaming SIMD Extensions 3 (SSE3). A value of 1 indicates the processor supports this technology.
1838 const SSE3 = 1 << 0;
1839 /// PCLMULQDQ. A value of 1 indicates the processor supports the PCLMULQDQ instruction
1840 const PCLMULQDQ = 1 << 1;
1841 /// 64-bit DS Area. A value of 1 indicates the processor supports DS area using 64-bit layout
1842 const DTES64 = 1 << 2;
1843 /// MONITOR/MWAIT. A value of 1 indicates the processor supports this feature.
1844 const MONITOR = 1 << 3;
1845 /// CPL Qualified Debug Store. A value of 1 indicates the processor supports the extensions to the Debug Store feature to allow for branch message storage qualified by CPL.
1846 const DSCPL = 1 << 4;
1847 /// Virtual Machine Extensions. A value of 1 indicates that the processor supports this technology.
1848 const VMX = 1 << 5;
1849 /// Safer Mode Extensions. A value of 1 indicates that the processor supports this technology. See Chapter 5, Safer Mode Extensions Reference.
1850 const SMX = 1 << 6;
1851 /// Enhanced Intel SpeedStep® technology. A value of 1 indicates that the processor supports this technology.
1852 const EIST = 1 << 7;
1853 /// Thermal Monitor 2. A value of 1 indicates whether the processor supports this technology.
1854 const TM2 = 1 << 8;
1855 /// A value of 1 indicates the presence of the Supplemental Streaming SIMD Extensions 3 (SSSE3). A value of 0 indicates the instruction extensions are not present in the processor
1856 const SSSE3 = 1 << 9;
1857 /// L1 Context ID. A value of 1 indicates the L1 data cache mode can be set to either adaptive mode or shared mode. A value of 0 indicates this feature is not supported. See definition of the IA32_MISC_ENABLE MSR Bit 24 (L1 Data Cache Context Mode) for details.
1858 const CNXTID = 1 << 10;
1859 /// A value of 1 indicates the processor supports FMA extensions using YMM state.
1860 const FMA = 1 << 12;
1861 /// CMPXCHG16B Available. A value of 1 indicates that the feature is available. See the CMPXCHG8B/CMPXCHG16B Compare and Exchange Bytes section. 14
1862 const CMPXCHG16B = 1 << 13;
1863 /// Perfmon and Debug Capability: A value of 1 indicates the processor supports the performance and debug feature indication MSR IA32_PERF_CAPABILITIES.
1864 const PDCM = 1 << 15;
1865 /// Process-context identifiers. A value of 1 indicates that the processor supports PCIDs and the software may set CR4.PCIDE to 1.
1866 const PCID = 1 << 17;
1867 /// A value of 1 indicates the processor supports the ability to prefetch data from a memory mapped device.
1868 const DCA = 1 << 18;
1869 /// A value of 1 indicates that the processor supports SSE4.1.
1870 const SSE41 = 1 << 19;
1871 /// A value of 1 indicates that the processor supports SSE4.2.
1872 const SSE42 = 1 << 20;
1873 /// A value of 1 indicates that the processor supports x2APIC feature.
1874 const X2APIC = 1 << 21;
1875 /// A value of 1 indicates that the processor supports MOVBE instruction.
1876 const MOVBE = 1 << 22;
1877 /// A value of 1 indicates that the processor supports the POPCNT instruction.
1878 const POPCNT = 1 << 23;
1879 /// A value of 1 indicates that the processors local APIC timer supports one-shot operation using a TSC deadline value.
1880 const TSC_DEADLINE = 1 << 24;
1881 /// A value of 1 indicates that the processor supports the AESNI instruction extensions.
1882 const AESNI = 1 << 25;
1883 /// A value of 1 indicates that the processor supports the XSAVE/XRSTOR processor extended states feature, the XSETBV/XGETBV instructions, and XCR0.
1884 const XSAVE = 1 << 26;
1885 /// A value of 1 indicates that the OS has enabled XSETBV/XGETBV instructions to access XCR0, and support for processor extended state management using XSAVE/XRSTOR.
1886 const OSXSAVE = 1 << 27;
1887 /// A value of 1 indicates the processor supports the AVX instruction extensions.
1888 const AVX = 1 << 28;
1889 /// A value of 1 indicates that processor supports 16-bit floating-point conversion instructions.
1890 const F16C = 1 << 29;
1891 /// A value of 1 indicates that processor supports RDRAND instruction.
1892 const RDRAND = 1 << 30;
1893
1894
1895 // EDX flags
1896
1897 /// Floating Point Unit On-Chip. The processor contains an x87 FPU.
1898 const FPU = 1 << (32 + 0);
1899 /// Virtual 8086 Mode Enhancements. Virtual 8086 mode enhancements, including CR4.VME for controlling the feature, CR4.PVI for protected mode virtual interrupts, software interrupt indirection, expansion of the TSS with the software indirection bitmap, and EFLAGS.VIF and EFLAGS.VIP flags.
1900 const VME = 1 << (32 + 1);
1901 /// Debugging Extensions. Support for I/O breakpoints, including CR4.DE for controlling the feature, and optional trapping of accesses to DR4 and DR5.
1902 const DE = 1 << (32 + 2);
1903 /// Page Size Extension. Large pages of size 4 MByte are supported, including CR4.PSE for controlling the feature, the defined dirty bit in PDE (Page Directory Entries), optional reserved bit trapping in CR3, PDEs, and PTEs.
1904 const PSE = 1 << (32 + 3);
1905 /// Time Stamp Counter. The RDTSC instruction is supported, including CR4.TSD for controlling privilege.
1906 const TSC = 1 << (32 + 4);
1907 /// Model Specific Registers RDMSR and WRMSR Instructions. The RDMSR and WRMSR instructions are supported. Some of the MSRs are implementation dependent.
1908 const MSR = 1 << (32 + 5);
1909 /// Physical Address Extension. Physical addresses greater than 32 bits are supported: extended page table entry formats, an extra level in the page translation tables is defined, 2-MByte pages are supported instead of 4 Mbyte pages if PAE bit is 1.
1910 const PAE = 1 << (32 + 6);
1911 /// Machine Check Exception. Exception 18 is defined for Machine Checks, including CR4.MCE for controlling the feature. This feature does not define the model-specific implementations of machine-check error logging, reporting, and processor shutdowns. Machine Check exception handlers may have to depend on processor version to do model specific processing of the exception, or test for the presence of the Machine Check feature.
1912 const MCE = 1 << (32 + 7);
1913 /// CMPXCHG8B Instruction. The compare-and-exchange 8 bytes (64 bits) instruction is supported (implicitly locked and atomic).
1914 const CX8 = 1 << (32 + 8);
1915 /// APIC On-Chip. The processor contains an Advanced Programmable Interrupt Controller (APIC), responding to memory mapped commands in the physical address range FFFE0000H to FFFE0FFFH (by default - some processors permit the APIC to be relocated).
1916 const APIC = 1 << (32 + 9);
1917 /// SYSENTER and SYSEXIT Instructions. The SYSENTER and SYSEXIT and associated MSRs are supported.
1918 const SEP = 1 << (32 + 11);
1919 /// Memory Type Range Registers. MTRRs are supported. The MTRRcap MSR contains feature bits that describe what memory types are supported, how many variable MTRRs are supported, and whether fixed MTRRs are supported.
1920 const MTRR = 1 << (32 + 12);
1921 /// Page Global Bit. The global bit is supported in paging-structure entries that map a page, indicating TLB entries that are common to different processes and need not be flushed. The CR4.PGE bit controls this feature.
1922 const PGE = 1 << (32 + 13);
1923 /// Machine Check Architecture. The Machine Check exArchitecture, which provides a compatible mechanism for error reporting in P6 family, Pentium 4, Intel Xeon processors, and future processors, is supported. The MCG_CAP MSR contains feature bits describing how many banks of error reporting MSRs are supported.
1924 const MCA = 1 << (32 + 14);
1925 /// Conditional Move Instructions. The conditional move instruction CMOV is supported. In addition, if x87 FPU is present as indicated by the CPUID.FPU feature bit, then the FCOMI and FCMOV instructions are supported
1926 const CMOV = 1 << (32 + 15);
1927 /// Page Attribute Table. Page Attribute Table is supported. This feature augments the Memory Type Range Registers (MTRRs), allowing an operating system to specify attributes of memory accessed through a linear address on a 4KB granularity.
1928 const PAT = 1 << (32 + 16);
1929 /// 36-Bit Page Size Extension. 4-MByte pages addressing physical memory beyond 4 GBytes are supported with 32-bit paging. This feature indicates that upper bits of the physical address of a 4-MByte page are encoded in bits 20:13 of the page-directory entry. Such physical addresses are limited by MAXPHYADDR and may be up to 40 bits in size.
1930 const PSE36 = 1 << (32 + 17);
1931 /// Processor Serial Number. The processor supports the 96-bit processor identification number feature and the feature is enabled.
1932 const PSN = 1 << (32 + 18);
1933 /// CLFLUSH Instruction. CLFLUSH Instruction is supported.
1934 const CLFSH = 1 << (32 + 19);
1935 /// Debug Store. The processor supports the ability to write debug information into a memory resident buffer. This feature is used by the branch trace store (BTS) and precise event-based sampling (PEBS) facilities (see Chapter 23, Introduction to Virtual-Machine Extensions, in the Intel® 64 and IA-32 Architectures Software Developers Manual, Volume 3C).
1936 const DS = 1 << (32 + 21);
1937 /// Thermal Monitor and Software Controlled Clock Facilities. The processor implements internal MSRs that allow processor temperature to be monitored and processor performance to be modulated in predefined duty cycles under software control.
1938 const ACPI = 1 << (32 + 22);
1939 /// Intel MMX Technology. The processor supports the Intel MMX technology.
1940 const MMX = 1 << (32 + 23);
1941 /// FXSAVE and FXRSTOR Instructions. The FXSAVE and FXRSTOR instructions are supported for fast save and restore of the floating point context. Presence of this bit also indicates that CR4.OSFXSR is available for an operating system to indicate that it supports the FXSAVE and FXRSTOR instructions.
1942 const FXSR = 1 << (32 + 24);
1943 /// SSE. The processor supports the SSE extensions.
1944 const SSE = 1 << (32 + 25);
1945 /// SSE2. The processor supports the SSE2 extensions.
1946 const SSE2 = 1 << (32 + 26);
1947 /// Self Snoop. The processor supports the management of conflicting memory types by performing a snoop of its own cache structure for transactions issued to the bus.
1948 const SS = 1 << (32 + 27);
1949 /// Max APIC IDs reserved field is Valid. A value of 0 for HTT indicates there is only a single logical processor in the package and software should assume only a single APIC ID is reserved. A value of 1 for HTT indicates the value in CPUID.1.EBX[23:16] (the Maximum number of addressable IDs for logical processors in this package) is valid for the package.
1950 const HTT = 1 << (32 + 28);
1951 /// Thermal Monitor. The processor implements the thermal monitor automatic thermal control circuitry (TCC).
1952 const TM = 1 << (32 + 29);
1953 /// Pending Break Enable. The processor supports the use of the FERR#/PBE# pin when the processor is in the stop-clock state (STPCLK# is asserted) to signal the processor that an interrupt is pending and that the processor should return to normal operation to handle the interrupt. Bit 10 (PBE enable) in the IA32_MISC_ENABLE MSR enables this capability.
1954 const PBE = 1 << (32 + 31);
1955 }
1956 }
1957
1958 #[derive(Debug, Default)]
1959 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
1960 pub struct CacheParametersIter {
1961 current: u32,
1962 }
1963
1964 impl Iterator for CacheParametersIter {
1965 type Item = CacheParameter;
1966
1967 /// Iterate over all caches for this CPU.
1968 /// Note: cpuid is called every-time we this function to get information
1969 /// about next cache.
next(&mut self) -> Option<CacheParameter>1970 fn next(&mut self) -> Option<CacheParameter> {
1971 let res = cpuid!(EAX_CACHE_PARAMETERS, self.current);
1972 let cp = CacheParameter {
1973 eax: res.eax,
1974 ebx: res.ebx,
1975 ecx: res.ecx,
1976 edx: res.edx,
1977 };
1978
1979 match cp.cache_type() {
1980 CacheType::Null => None,
1981 CacheType::Reserved => None,
1982 _ => {
1983 self.current += 1;
1984 Some(cp)
1985 }
1986 }
1987 }
1988 }
1989
1990 #[derive(Copy, Clone, Debug, Default)]
1991 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
1992 pub struct CacheParameter {
1993 eax: u32,
1994 ebx: u32,
1995 ecx: u32,
1996 edx: u32,
1997 }
1998
1999 #[derive(PartialEq, Eq, Debug)]
2000 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
2001 pub enum CacheType {
2002 /// Null - No more caches
2003 Null = 0,
2004 /// Data cache
2005 Data,
2006 /// Instruction cache
2007 Instruction,
2008 /// Data and Instruction cache
2009 Unified,
2010 /// 4-31 = Reserved
2011 Reserved,
2012 }
2013
2014 impl Default for CacheType {
default() -> CacheType2015 fn default() -> CacheType {
2016 CacheType::Null
2017 }
2018 }
2019
2020 impl CacheParameter {
2021 /// Cache Type
cache_type(&self) -> CacheType2022 pub fn cache_type(&self) -> CacheType {
2023 let typ = get_bits(self.eax, 0, 4) as u8;
2024 match typ {
2025 0 => CacheType::Null,
2026 1 => CacheType::Data,
2027 2 => CacheType::Instruction,
2028 3 => CacheType::Unified,
2029 _ => CacheType::Reserved,
2030 }
2031 }
2032
2033 /// Cache Level (starts at 1)
level(&self) -> u82034 pub fn level(&self) -> u8 {
2035 get_bits(self.eax, 5, 7) as u8
2036 }
2037
2038 /// Self Initializing cache level (does not need SW initialization).
is_self_initializing(&self) -> bool2039 pub fn is_self_initializing(&self) -> bool {
2040 get_bits(self.eax, 8, 8) == 1
2041 }
2042
2043 /// Fully Associative cache
is_fully_associative(&self) -> bool2044 pub fn is_fully_associative(&self) -> bool {
2045 get_bits(self.eax, 9, 9) == 1
2046 }
2047
2048 /// Maximum number of addressable IDs for logical processors sharing this cache
max_cores_for_cache(&self) -> usize2049 pub fn max_cores_for_cache(&self) -> usize {
2050 (get_bits(self.eax, 14, 25) + 1) as usize
2051 }
2052
2053 /// Maximum number of addressable IDs for processor cores in the physical package
max_cores_for_package(&self) -> usize2054 pub fn max_cores_for_package(&self) -> usize {
2055 (get_bits(self.eax, 26, 31) + 1) as usize
2056 }
2057
2058 /// System Coherency Line Size (Bits 11-00)
coherency_line_size(&self) -> usize2059 pub fn coherency_line_size(&self) -> usize {
2060 (get_bits(self.ebx, 0, 11) + 1) as usize
2061 }
2062
2063 /// Physical Line partitions (Bits 21-12)
physical_line_partitions(&self) -> usize2064 pub fn physical_line_partitions(&self) -> usize {
2065 (get_bits(self.ebx, 12, 21) + 1) as usize
2066 }
2067
2068 /// Ways of associativity (Bits 31-22)
associativity(&self) -> usize2069 pub fn associativity(&self) -> usize {
2070 (get_bits(self.ebx, 22, 31) + 1) as usize
2071 }
2072
2073 /// Number of Sets (Bits 31-00)
sets(&self) -> usize2074 pub fn sets(&self) -> usize {
2075 (self.ecx + 1) as usize
2076 }
2077
2078 /// Write-Back Invalidate/Invalidate (Bit 0)
2079 /// False: WBINVD/INVD from threads sharing this cache acts upon lower level caches for threads sharing this cache.
2080 /// True: WBINVD/INVD is not guaranteed to act upon lower level caches of non-originating threads sharing this cache.
is_write_back_invalidate(&self) -> bool2081 pub fn is_write_back_invalidate(&self) -> bool {
2082 get_bits(self.edx, 0, 0) == 1
2083 }
2084
2085 /// Cache Inclusiveness (Bit 1)
2086 /// False: Cache is not inclusive of lower cache levels.
2087 /// True: Cache is inclusive of lower cache levels.
is_inclusive(&self) -> bool2088 pub fn is_inclusive(&self) -> bool {
2089 get_bits(self.edx, 1, 1) == 1
2090 }
2091
2092 /// Complex Cache Indexing (Bit 2)
2093 /// False: Direct mapped cache.
2094 /// True: A complex function is used to index the cache, potentially using all address bits.
has_complex_indexing(&self) -> bool2095 pub fn has_complex_indexing(&self) -> bool {
2096 get_bits(self.edx, 2, 2) == 1
2097 }
2098 }
2099
2100 #[derive(Debug, Default)]
2101 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
2102 pub struct MonitorMwaitInfo {
2103 eax: u32,
2104 ebx: u32,
2105 ecx: u32,
2106 edx: u32,
2107 }
2108
2109 impl MonitorMwaitInfo {
2110 /// Smallest monitor-line size in bytes (default is processor's monitor granularity)
smallest_monitor_line(&self) -> u162111 pub fn smallest_monitor_line(&self) -> u16 {
2112 get_bits(self.eax, 0, 15) as u16
2113 }
2114
2115 /// Largest monitor-line size in bytes (default is processor's monitor granularity
largest_monitor_line(&self) -> u162116 pub fn largest_monitor_line(&self) -> u16 {
2117 get_bits(self.ebx, 0, 15) as u16
2118 }
2119
2120 /// Enumeration of Monitor-Mwait extensions (beyond EAX and EBX registers) supported
extensions_supported(&self) -> bool2121 pub fn extensions_supported(&self) -> bool {
2122 get_bits(self.ecx, 0, 0) == 1
2123 }
2124
2125 /// Supports treating interrupts as break-event for MWAIT, even when interrupts disabled
interrupts_as_break_event(&self) -> bool2126 pub fn interrupts_as_break_event(&self) -> bool {
2127 get_bits(self.ecx, 1, 1) == 1
2128 }
2129
2130 /// Number of C0 sub C-states supported using MWAIT (Bits 03 - 00)
supported_c0_states(&self) -> u162131 pub fn supported_c0_states(&self) -> u16 {
2132 get_bits(self.edx, 0, 3) as u16
2133 }
2134
2135 /// Number of C1 sub C-states supported using MWAIT (Bits 07 - 04)
supported_c1_states(&self) -> u162136 pub fn supported_c1_states(&self) -> u16 {
2137 get_bits(self.edx, 4, 7) as u16
2138 }
2139
2140 /// Number of C2 sub C-states supported using MWAIT (Bits 11 - 08)
supported_c2_states(&self) -> u162141 pub fn supported_c2_states(&self) -> u16 {
2142 get_bits(self.edx, 8, 11) as u16
2143 }
2144
2145 /// Number of C3 sub C-states supported using MWAIT (Bits 15 - 12)
supported_c3_states(&self) -> u162146 pub fn supported_c3_states(&self) -> u16 {
2147 get_bits(self.edx, 12, 15) as u16
2148 }
2149
2150 /// Number of C4 sub C-states supported using MWAIT (Bits 19 - 16)
supported_c4_states(&self) -> u162151 pub fn supported_c4_states(&self) -> u16 {
2152 get_bits(self.edx, 16, 19) as u16
2153 }
2154
2155 /// Number of C5 sub C-states supported using MWAIT (Bits 23 - 20)
supported_c5_states(&self) -> u162156 pub fn supported_c5_states(&self) -> u16 {
2157 get_bits(self.edx, 20, 23) as u16
2158 }
2159
2160 /// Number of C6 sub C-states supported using MWAIT (Bits 27 - 24)
supported_c6_states(&self) -> u162161 pub fn supported_c6_states(&self) -> u16 {
2162 get_bits(self.edx, 24, 27) as u16
2163 }
2164
2165 /// Number of C7 sub C-states supported using MWAIT (Bits 31 - 28)
supported_c7_states(&self) -> u162166 pub fn supported_c7_states(&self) -> u16 {
2167 get_bits(self.edx, 28, 31) as u16
2168 }
2169 }
2170
2171 #[derive(Debug, Default)]
2172 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
2173 pub struct ThermalPowerInfo {
2174 eax: ThermalPowerFeaturesEax,
2175 ebx: u32,
2176 ecx: ThermalPowerFeaturesEcx,
2177 edx: u32,
2178 }
2179
2180 impl ThermalPowerInfo {
2181 /// Number of Interrupt Thresholds in Digital Thermal Sensor
dts_irq_threshold(&self) -> u82182 pub fn dts_irq_threshold(&self) -> u8 {
2183 get_bits(self.ebx, 0, 3) as u8
2184 }
2185
2186 check_flag!(
2187 doc = "Digital temperature sensor is supported if set.",
2188 has_dts,
2189 eax,
2190 ThermalPowerFeaturesEax::DTS
2191 );
2192
2193 check_flag!(
2194 doc = "Intel Turbo Boost Technology Available (see description of \
2195 IA32_MISC_ENABLE\\[38\\]).",
2196 has_turbo_boost,
2197 eax,
2198 ThermalPowerFeaturesEax::TURBO_BOOST
2199 );
2200
2201 check_flag!(
2202 doc = "ARAT. APIC-Timer-always-running feature is supported if set.",
2203 has_arat,
2204 eax,
2205 ThermalPowerFeaturesEax::ARAT
2206 );
2207
2208 check_flag!(
2209 doc = "PLN. Power limit notification controls are supported if set.",
2210 has_pln,
2211 eax,
2212 ThermalPowerFeaturesEax::PLN
2213 );
2214
2215 check_flag!(
2216 doc = "ECMD. Clock modulation duty cycle extension is supported if set.",
2217 has_ecmd,
2218 eax,
2219 ThermalPowerFeaturesEax::ECMD
2220 );
2221
2222 check_flag!(
2223 doc = "PTM. Package thermal management is supported if set.",
2224 has_ptm,
2225 eax,
2226 ThermalPowerFeaturesEax::PTM
2227 );
2228
2229 check_flag!(
2230 doc = "HWP. HWP base registers (IA32_PM_ENABLE[bit 0], IA32_HWP_CAPABILITIES, \
2231 IA32_HWP_REQUEST, IA32_HWP_STATUS) are supported if set.",
2232 has_hwp,
2233 eax,
2234 ThermalPowerFeaturesEax::HWP
2235 );
2236
2237 check_flag!(
2238 doc = "HWP Notification. IA32_HWP_INTERRUPT MSR is supported if set.",
2239 has_hwp_notification,
2240 eax,
2241 ThermalPowerFeaturesEax::HWP_NOTIFICATION
2242 );
2243
2244 check_flag!(
2245 doc = "HWP Activity Window. IA32_HWP_REQUEST[bits 41:32] is supported if set.",
2246 has_hwp_activity_window,
2247 eax,
2248 ThermalPowerFeaturesEax::HWP_ACTIVITY_WINDOW
2249 );
2250
2251 check_flag!(
2252 doc =
2253 "HWP Energy Performance Preference. IA32_HWP_REQUEST[bits 31:24] is supported if set.",
2254 has_hwp_energy_performance_preference,
2255 eax,
2256 ThermalPowerFeaturesEax::HWP_ENERGY_PERFORMANCE_PREFERENCE
2257 );
2258
2259 check_flag!(
2260 doc = "HWP Package Level Request. IA32_HWP_REQUEST_PKG MSR is supported if set.",
2261 has_hwp_package_level_request,
2262 eax,
2263 ThermalPowerFeaturesEax::HWP_PACKAGE_LEVEL_REQUEST
2264 );
2265
2266 check_flag!(
2267 doc = "HDC. HDC base registers IA32_PKG_HDC_CTL, IA32_PM_CTL1, IA32_THREAD_STALL \
2268 MSRs are supported if set.",
2269 has_hdc,
2270 eax,
2271 ThermalPowerFeaturesEax::HDC
2272 );
2273
2274 check_flag!(
2275 doc = "Intel® Turbo Boost Max Technology 3.0 available.",
2276 has_turbo_boost3,
2277 eax,
2278 ThermalPowerFeaturesEax::TURBO_BOOST_3
2279 );
2280
2281 check_flag!(
2282 doc = "HWP Capabilities. Highest Performance change is supported if set.",
2283 has_hwp_capabilities,
2284 eax,
2285 ThermalPowerFeaturesEax::HWP_CAPABILITIES
2286 );
2287
2288 check_flag!(
2289 doc = "HWP PECI override is supported if set.",
2290 has_hwp_peci_override,
2291 eax,
2292 ThermalPowerFeaturesEax::HWP_PECI_OVERRIDE
2293 );
2294
2295 check_flag!(
2296 doc = "Flexible HWP is supported if set.",
2297 has_flexible_hwp,
2298 eax,
2299 ThermalPowerFeaturesEax::FLEXIBLE_HWP
2300 );
2301
2302 check_flag!(
2303 doc = "Fast access mode for the IA32_HWP_REQUEST MSR is supported if set.",
2304 has_hwp_fast_access_mode,
2305 eax,
2306 ThermalPowerFeaturesEax::HWP_REQUEST_MSR_FAST_ACCESS
2307 );
2308
2309 check_flag!(
2310 doc = "Ignoring Idle Logical Processor HWP request is supported if set.",
2311 has_ignore_idle_processor_hwp_request,
2312 eax,
2313 ThermalPowerFeaturesEax::IGNORE_IDLE_PROCESSOR_HWP_REQUEST
2314 );
2315
2316 check_flag!(
2317 doc = "Hardware Coordination Feedback Capability (Presence of IA32_MPERF and \
2318 IA32_APERF). The capability to provide a measure of delivered processor \
2319 performance (since last reset of the counters), as a percentage of \
2320 expected processor performance at frequency specified in CPUID Brand \
2321 String Bits 02 - 01",
2322 has_hw_coord_feedback,
2323 ecx,
2324 ThermalPowerFeaturesEcx::HW_COORD_FEEDBACK
2325 );
2326
2327 check_flag!(
2328 doc = "The processor supports performance-energy bias preference if \
2329 CPUID.06H:ECX.SETBH[bit 3] is set and it also implies the presence of a \
2330 new architectural MSR called IA32_ENERGY_PERF_BIAS (1B0H)",
2331 has_energy_bias_pref,
2332 ecx,
2333 ThermalPowerFeaturesEcx::ENERGY_BIAS_PREF
2334 );
2335 }
2336
2337 bitflags! {
2338 #[derive(Default)]
2339 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
2340 struct ThermalPowerFeaturesEax: u32 {
2341 /// Digital temperature sensor is supported if set. (Bit 00)
2342 const DTS = 1 << 0;
2343 /// Intel Turbo Boost Technology Available (see description of IA32_MISC_ENABLE[38]). (Bit 01)
2344 const TURBO_BOOST = 1 << 1;
2345 /// ARAT. APIC-Timer-always-running feature is supported if set. (Bit 02)
2346 const ARAT = 1 << 2;
2347 /// Bit 3: Reserved.
2348 const RESERVED_3 = 1 << 3;
2349 /// PLN. Power limit notification controls are supported if set. (Bit 04)
2350 const PLN = 1 << 4;
2351 /// ECMD. Clock modulation duty cycle extension is supported if set. (Bit 05)
2352 const ECMD = 1 << 5;
2353 /// PTM. Package thermal management is supported if set. (Bit 06)
2354 const PTM = 1 << 6;
2355 /// Bit 07: HWP. HWP base registers (IA32_PM_ENABLE[bit 0], IA32_HWP_CAPABILITIES, IA32_HWP_REQUEST, IA32_HWP_STATUS) are supported if set.
2356 const HWP = 1 << 7;
2357 /// Bit 08: HWP_Notification. IA32_HWP_INTERRUPT MSR is supported if set.
2358 const HWP_NOTIFICATION = 1 << 8;
2359 /// Bit 09: HWP_Activity_Window. IA32_HWP_REQUEST[bits 41:32] is supported if set.
2360 const HWP_ACTIVITY_WINDOW = 1 << 9;
2361 /// Bit 10: HWP_Energy_Performance_Preference. IA32_HWP_REQUEST[bits 31:24] is supported if set.
2362 const HWP_ENERGY_PERFORMANCE_PREFERENCE = 1 << 10;
2363 /// Bit 11: HWP_Package_Level_Request. IA32_HWP_REQUEST_PKG MSR is supported if set.
2364 const HWP_PACKAGE_LEVEL_REQUEST = 1 << 11;
2365 /// Bit 12: Reserved.
2366 const RESERVED_12 = 1 << 12;
2367 /// Bit 13: HDC. HDC base registers IA32_PKG_HDC_CTL, IA32_PM_CTL1, IA32_THREAD_STALL MSRs are supported if set.
2368 const HDC = 1 << 13;
2369 /// Bit 14: Intel® Turbo Boost Max Technology 3.0 available.
2370 const TURBO_BOOST_3 = 1 << 14;
2371 /// Bit 15: HWP Capabilities. Highest Performance change is supported if set.
2372 const HWP_CAPABILITIES = 1 << 15;
2373 /// Bit 16: HWP PECI override is supported if set.
2374 const HWP_PECI_OVERRIDE = 1 << 16;
2375 /// Bit 17: Flexible HWP is supported if set.
2376 const FLEXIBLE_HWP = 1 << 17;
2377 /// Bit 18: Fast access mode for the IA32_HWP_REQUEST MSR is supported if set.
2378 const HWP_REQUEST_MSR_FAST_ACCESS = 1 << 18;
2379 /// Bit 19: Reserved.
2380 const RESERVED_19 = 1 << 19;
2381 /// Bit 20: Ignoring Idle Logical Processor HWP request is supported if set.
2382 const IGNORE_IDLE_PROCESSOR_HWP_REQUEST = 1 << 20;
2383 // Bits 31 - 21: Reserved
2384 }
2385 }
2386
2387 bitflags! {
2388 #[derive(Default)]
2389 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
2390 struct ThermalPowerFeaturesEcx: u32 {
2391 /// Hardware Coordination Feedback Capability (Presence of IA32_MPERF and IA32_APERF). The capability to provide a measure of delivered processor performance (since last reset of the counters), as a percentage of expected processor performance at frequency specified in CPUID Brand String Bits 02 - 01
2392 const HW_COORD_FEEDBACK = 1 << 0;
2393
2394 /// The processor supports performance-energy bias preference if CPUID.06H:ECX.SETBH[bit 3] is set and it also implies the presence of a new architectural MSR called IA32_ENERGY_PERF_BIAS (1B0H)
2395 const ENERGY_BIAS_PREF = 1 << 3;
2396 }
2397 }
2398
2399 #[derive(Debug, Default)]
2400 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
2401 pub struct ExtendedFeatures {
2402 eax: u32,
2403 ebx: ExtendedFeaturesEbx,
2404 ecx: ExtendedFeaturesEcx,
2405 edx: u32,
2406 }
2407
2408 impl ExtendedFeatures {
2409 check_flag!(
2410 doc = "FSGSBASE. Supports RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE if 1.",
2411 has_fsgsbase,
2412 ebx,
2413 ExtendedFeaturesEbx::FSGSBASE
2414 );
2415
2416 check_flag!(
2417 doc = "IA32_TSC_ADJUST MSR is supported if 1.",
2418 has_tsc_adjust_msr,
2419 ebx,
2420 ExtendedFeaturesEbx::ADJUST_MSR
2421 );
2422
2423 check_flag!(doc = "BMI1", has_bmi1, ebx, ExtendedFeaturesEbx::BMI1);
2424
2425 check_flag!(doc = "HLE", has_hle, ebx, ExtendedFeaturesEbx::HLE);
2426
2427 check_flag!(doc = "AVX2", has_avx2, ebx, ExtendedFeaturesEbx::AVX2);
2428
2429 check_flag!(
2430 doc = "FDP_EXCPTN_ONLY. x87 FPU Data Pointer updated only on x87 exceptions if 1.",
2431 has_fdp,
2432 ebx,
2433 ExtendedFeaturesEbx::FDP
2434 );
2435
2436 check_flag!(
2437 doc = "SMEP. Supports Supervisor-Mode Execution Prevention if 1.",
2438 has_smep,
2439 ebx,
2440 ExtendedFeaturesEbx::SMEP
2441 );
2442
2443 check_flag!(doc = "BMI2", has_bmi2, ebx, ExtendedFeaturesEbx::BMI2);
2444
2445 check_flag!(
2446 doc = "Supports Enhanced REP MOVSB/STOSB if 1.",
2447 has_rep_movsb_stosb,
2448 ebx,
2449 ExtendedFeaturesEbx::REP_MOVSB_STOSB
2450 );
2451
2452 check_flag!(
2453 doc = "INVPCID. If 1, supports INVPCID instruction for system software that \
2454 manages process-context identifiers.",
2455 has_invpcid,
2456 ebx,
2457 ExtendedFeaturesEbx::INVPCID
2458 );
2459
2460 check_flag!(doc = "RTM", has_rtm, ebx, ExtendedFeaturesEbx::RTM);
2461
2462 check_flag!(
2463 doc = "Supports Intel Resource Director Technology (RDT) Monitoring capability.",
2464 has_rdtm,
2465 ebx,
2466 ExtendedFeaturesEbx::RDTM
2467 );
2468
2469 check_flag!(
2470 doc = "Deprecates FPU CS and FPU DS values if 1.",
2471 has_fpu_cs_ds_deprecated,
2472 ebx,
2473 ExtendedFeaturesEbx::DEPRECATE_FPU_CS_DS
2474 );
2475
2476 check_flag!(
2477 doc = "MPX. Supports Intel Memory Protection Extensions if 1.",
2478 has_mpx,
2479 ebx,
2480 ExtendedFeaturesEbx::MPX
2481 );
2482
2483 check_flag!(
2484 doc = "Supports Intel Resource Director Technology (RDT) Allocation capability.",
2485 has_rdta,
2486 ebx,
2487 ExtendedFeaturesEbx::RDTA
2488 );
2489
2490 check_flag!(
2491 doc = "Supports RDSEED.",
2492 has_rdseed,
2493 ebx,
2494 ExtendedFeaturesEbx::RDSEED
2495 );
2496
2497 #[deprecated(
2498 since = "3.2",
2499 note = "Deprecated due to typo in name, users should use has_rdseed() instead."
2500 )]
2501 check_flag!(
2502 doc = "Supports RDSEED (deprecated alias).",
2503 has_rdseet,
2504 ebx,
2505 ExtendedFeaturesEbx::RDSEED
2506 );
2507
2508 check_flag!(
2509 doc = "Supports ADX.",
2510 has_adx,
2511 ebx,
2512 ExtendedFeaturesEbx::ADX
2513 );
2514
2515 check_flag!(doc = "SMAP. Supports Supervisor-Mode Access Prevention (and the CLAC/STAC instructions) if 1.",
2516 has_smap,
2517 ebx,
2518 ExtendedFeaturesEbx::SMAP);
2519
2520 check_flag!(
2521 doc = "Supports CLFLUSHOPT.",
2522 has_clflushopt,
2523 ebx,
2524 ExtendedFeaturesEbx::CLFLUSHOPT
2525 );
2526
2527 check_flag!(
2528 doc = "Supports Intel Processor Trace.",
2529 has_processor_trace,
2530 ebx,
2531 ExtendedFeaturesEbx::PROCESSOR_TRACE
2532 );
2533
2534 check_flag!(
2535 doc = "Supports SHA Instructions.",
2536 has_sha,
2537 ebx,
2538 ExtendedFeaturesEbx::SHA
2539 );
2540
2541 check_flag!(
2542 doc = "Supports Intel® Software Guard Extensions (Intel® SGX Extensions).",
2543 has_sgx,
2544 ebx,
2545 ExtendedFeaturesEbx::SGX
2546 );
2547
2548 check_flag!(
2549 doc = "Supports AVX512F.",
2550 has_avx512f,
2551 ebx,
2552 ExtendedFeaturesEbx::AVX512F
2553 );
2554
2555 check_flag!(
2556 doc = "Supports AVX512DQ.",
2557 has_avx512dq,
2558 ebx,
2559 ExtendedFeaturesEbx::AVX512DQ
2560 );
2561
2562 check_flag!(
2563 doc = "AVX512_IFMA",
2564 has_avx512_ifma,
2565 ebx,
2566 ExtendedFeaturesEbx::AVX512_IFMA
2567 );
2568
2569 check_flag!(
2570 doc = "AVX512PF",
2571 has_avx512pf,
2572 ebx,
2573 ExtendedFeaturesEbx::AVX512PF
2574 );
2575 check_flag!(
2576 doc = "AVX512ER",
2577 has_avx512er,
2578 ebx,
2579 ExtendedFeaturesEbx::AVX512ER
2580 );
2581
2582 check_flag!(
2583 doc = "AVX512CD",
2584 has_avx512cd,
2585 ebx,
2586 ExtendedFeaturesEbx::AVX512CD
2587 );
2588
2589 check_flag!(
2590 doc = "AVX512BW",
2591 has_avx512bw,
2592 ebx,
2593 ExtendedFeaturesEbx::AVX512BW
2594 );
2595
2596 check_flag!(
2597 doc = "AVX512VL",
2598 has_avx512vl,
2599 ebx,
2600 ExtendedFeaturesEbx::AVX512VL
2601 );
2602
2603 check_flag!(doc = "CLWB", has_clwb, ebx, ExtendedFeaturesEbx::CLWB);
2604
2605 check_flag!(
2606 doc = "Has PREFETCHWT1 (Intel® Xeon Phi™ only).",
2607 has_prefetchwt1,
2608 ecx,
2609 ExtendedFeaturesEcx::PREFETCHWT1
2610 );
2611
2612 check_flag!(
2613 doc = "Supports user-mode instruction prevention if 1.",
2614 has_umip,
2615 ecx,
2616 ExtendedFeaturesEcx::UMIP
2617 );
2618
2619 check_flag!(
2620 doc = "Supports protection keys for user-mode pages.",
2621 has_pku,
2622 ecx,
2623 ExtendedFeaturesEcx::PKU
2624 );
2625
2626 check_flag!(
2627 doc = "OS has set CR4.PKE to enable protection keys (and the RDPKRU/WRPKRU instructions.",
2628 has_ospke,
2629 ecx,
2630 ExtendedFeaturesEcx::OSPKE
2631 );
2632
2633 check_flag!(
2634 doc = "RDPID and IA32_TSC_AUX are available.",
2635 has_rdpid,
2636 ecx,
2637 ExtendedFeaturesEcx::RDPID
2638 );
2639
2640 check_flag!(
2641 doc = "Supports SGX Launch Configuration.",
2642 has_sgx_lc,
2643 ecx,
2644 ExtendedFeaturesEcx::SGX_LC
2645 );
2646
2647 /// The value of MAWAU used by the BNDLDX and BNDSTX instructions in 64-bit mode.
mawau_value(&self) -> u82648 pub fn mawau_value(&self) -> u8 {
2649 get_bits(self.ecx.bits(), 17, 21) as u8
2650 }
2651 }
2652
2653 bitflags! {
2654 #[derive(Default)]
2655 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
2656 struct ExtendedFeaturesEbx: u32 {
2657 /// FSGSBASE. Supports RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE if 1. (Bit 00)
2658 const FSGSBASE = 1 << 0;
2659 /// IA32_TSC_ADJUST MSR is supported if 1. (Bit 01)
2660 const ADJUST_MSR = 1 << 1;
2661 /// Bit 02: SGX. Supports Intel® Software Guard Extensions (Intel® SGX Extensions) if 1.
2662 const SGX = 1 << 2;
2663 /// BMI1 (Bit 03)
2664 const BMI1 = 1 << 3;
2665 /// HLE (Bit 04)
2666 const HLE = 1 << 4;
2667 /// AVX2 (Bit 05)
2668 const AVX2 = 1 << 5;
2669 /// FDP_EXCPTN_ONLY. x87 FPU Data Pointer updated only on x87 exceptions if 1.
2670 const FDP = 1 << 6;
2671 /// SMEP. Supports Supervisor-Mode Execution Prevention if 1. (Bit 07)
2672 const SMEP = 1 << 7;
2673 /// BMI2 (Bit 08)
2674 const BMI2 = 1 << 8;
2675 /// Supports Enhanced REP MOVSB/STOSB if 1. (Bit 09)
2676 const REP_MOVSB_STOSB = 1 << 9;
2677 /// INVPCID. If 1, supports INVPCID instruction for system software that manages process-context identifiers. (Bit 10)
2678 const INVPCID = 1 << 10;
2679 /// RTM (Bit 11)
2680 const RTM = 1 << 11;
2681 /// Supports Intel Resource Director Technology (RDT) Monitoring. (Bit 12)
2682 const RDTM = 1 << 12;
2683 /// Deprecates FPU CS and FPU DS values if 1. (Bit 13)
2684 const DEPRECATE_FPU_CS_DS = 1 << 13;
2685 /// Deprecates FPU CS and FPU DS values if 1. (Bit 14)
2686 const MPX = 1 << 14;
2687 /// Supports Intel Resource Director Technology (RDT) Allocation capability if 1.
2688 const RDTA = 1 << 15;
2689 /// Bit 16: AVX512F.
2690 const AVX512F = 1 << 16;
2691 /// Bit 17: AVX512DQ.
2692 const AVX512DQ = 1 << 17;
2693 /// Supports RDSEED.
2694 const RDSEED = 1 << 18;
2695 /// Supports ADX.
2696 const ADX = 1 << 19;
2697 /// SMAP. Supports Supervisor-Mode Access Prevention (and the CLAC/STAC instructions) if 1.
2698 const SMAP = 1 << 20;
2699 /// Bit 21: AVX512_IFMA.
2700 const AVX512_IFMA = 1 << 21;
2701 // Bit 22: Reserved.
2702 /// Bit 23: CLFLUSHOPT
2703 const CLFLUSHOPT = 1 << 23;
2704 /// Bit 24: CLWB.
2705 const CLWB = 1 << 24;
2706 /// Bit 25: Intel Processor Trace
2707 const PROCESSOR_TRACE = 1 << 25;
2708 /// Bit 26: AVX512PF. (Intel® Xeon Phi™ only.)
2709 const AVX512PF = 1 << 26;
2710 /// Bit 27: AVX512ER. (Intel® Xeon Phi™ only.)
2711 const AVX512ER = 1 << 27;
2712 /// Bit 28: AVX512CD.
2713 const AVX512CD = 1 << 28;
2714 /// Bit 29: Intel SHA Extensions
2715 const SHA = 1 << 29;
2716 /// Bit 30: AVX512BW.
2717 const AVX512BW = 1 << 30;
2718 /// Bit 31: AVX512VL.
2719 const AVX512VL = 1 << 31;
2720 }
2721 }
2722
2723 bitflags! {
2724 #[derive(Default)]
2725 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
2726 struct ExtendedFeaturesEcx: u32 {
2727 /// Bit 0: Prefetch WT1. (Intel® Xeon Phi™ only).
2728 const PREFETCHWT1 = 1 << 0;
2729
2730 // Bit 01: AVX512_VBMI
2731 const AVX512VBMI = 1 << 1;
2732
2733 /// Bit 02: UMIP. Supports user-mode instruction prevention if 1.
2734 const UMIP = 1 << 2;
2735
2736 /// Bit 03: PKU. Supports protection keys for user-mode pages if 1.
2737 const PKU = 1 << 3;
2738
2739 /// Bit 04: OSPKE. If 1, OS has set CR4.PKE to enable protection keys (and the RDPKRU/WRPKRU instruc-tions).
2740 const OSPKE = 1 << 4;
2741
2742 // Bits 16 - 5: Reserved.
2743 // Bits 21 - 17: The value of MAWAU used by the BNDLDX and BNDSTX instructions in 64-bit mode.
2744
2745
2746 /// Bit 22: RDPID. RDPID and IA32_TSC_AUX are available if 1.
2747 const RDPID = 1 << 22;
2748
2749 // Bits 29 - 23: Reserved.
2750
2751 /// Bit 30: SGX_LC. Supports SGX Launch Configuration if 1.
2752 const SGX_LC = 1 << 30;
2753 }
2754 }
2755
2756 #[derive(Debug, Default)]
2757 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
2758 pub struct DirectCacheAccessInfo {
2759 eax: u32,
2760 }
2761
2762 impl DirectCacheAccessInfo {
2763 /// Value of bits \[31:0\] of IA32_PLATFORM_DCA_CAP MSR (address 1F8H)
get_dca_cap_value(&self) -> u322764 pub fn get_dca_cap_value(&self) -> u32 {
2765 self.eax
2766 }
2767 }
2768
2769 #[derive(Debug, Default)]
2770 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
2771 pub struct PerformanceMonitoringInfo {
2772 eax: u32,
2773 ebx: PerformanceMonitoringFeaturesEbx,
2774 ecx: u32,
2775 edx: u32,
2776 }
2777
2778 impl PerformanceMonitoringInfo {
2779 /// Version ID of architectural performance monitoring. (Bits 07 - 00)
version_id(&self) -> u82780 pub fn version_id(&self) -> u8 {
2781 get_bits(self.eax, 0, 7) as u8
2782 }
2783
2784 /// Number of general-purpose performance monitoring counter per logical processor. (Bits 15- 08)
number_of_counters(&self) -> u82785 pub fn number_of_counters(&self) -> u8 {
2786 get_bits(self.eax, 8, 15) as u8
2787 }
2788
2789 /// Bit width of general-purpose, performance monitoring counter. (Bits 23 - 16)
counter_bit_width(&self) -> u82790 pub fn counter_bit_width(&self) -> u8 {
2791 get_bits(self.eax, 16, 23) as u8
2792 }
2793
2794 /// Length of EBX bit vector to enumerate architectural performance monitoring events. (Bits 31 - 24)
ebx_length(&self) -> u82795 pub fn ebx_length(&self) -> u8 {
2796 get_bits(self.eax, 24, 31) as u8
2797 }
2798
2799 /// Number of fixed-function performance counters (if Version ID > 1). (Bits 04 - 00)
fixed_function_counters(&self) -> u82800 pub fn fixed_function_counters(&self) -> u8 {
2801 get_bits(self.edx, 0, 4) as u8
2802 }
2803
2804 /// Bit width of fixed-function performance counters (if Version ID > 1). (Bits 12- 05)
fixed_function_counters_bit_width(&self) -> u82805 pub fn fixed_function_counters_bit_width(&self) -> u8 {
2806 get_bits(self.edx, 5, 12) as u8
2807 }
2808
2809 check_bit_fn!(
2810 doc = "AnyThread deprecation",
2811 has_any_thread_deprecation,
2812 edx,
2813 15
2814 );
2815
2816 check_flag!(
2817 doc = "Core cycle event not available if 1.",
2818 is_core_cyc_ev_unavailable,
2819 ebx,
2820 PerformanceMonitoringFeaturesEbx::CORE_CYC_EV_UNAVAILABLE
2821 );
2822
2823 check_flag!(
2824 doc = "Instruction retired event not available if 1.",
2825 is_inst_ret_ev_unavailable,
2826 ebx,
2827 PerformanceMonitoringFeaturesEbx::INST_RET_EV_UNAVAILABLE
2828 );
2829
2830 check_flag!(
2831 doc = "Reference cycles event not available if 1.",
2832 is_ref_cycle_ev_unavailable,
2833 ebx,
2834 PerformanceMonitoringFeaturesEbx::REF_CYC_EV_UNAVAILABLE
2835 );
2836
2837 check_flag!(
2838 doc = "Last-level cache reference event not available if 1.",
2839 is_cache_ref_ev_unavailable,
2840 ebx,
2841 PerformanceMonitoringFeaturesEbx::CACHE_REF_EV_UNAVAILABLE
2842 );
2843
2844 check_flag!(
2845 doc = "Last-level cache misses event not available if 1.",
2846 is_ll_cache_miss_ev_unavailable,
2847 ebx,
2848 PerformanceMonitoringFeaturesEbx::LL_CACHE_MISS_EV_UNAVAILABLE
2849 );
2850
2851 check_flag!(
2852 doc = "Branch instruction retired event not available if 1.",
2853 is_branch_inst_ret_ev_unavailable,
2854 ebx,
2855 PerformanceMonitoringFeaturesEbx::BRANCH_INST_RET_EV_UNAVAILABLE
2856 );
2857
2858 check_flag!(
2859 doc = "Branch mispredict retired event not available if 1.",
2860 is_branch_midpred_ev_unavailable,
2861 ebx,
2862 PerformanceMonitoringFeaturesEbx::BRANCH_MISPRED_EV_UNAVAILABLE
2863 );
2864 }
2865
2866 bitflags! {
2867 #[derive(Default)]
2868 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
2869 struct PerformanceMonitoringFeaturesEbx: u32 {
2870 /// Core cycle event not available if 1. (Bit 0)
2871 const CORE_CYC_EV_UNAVAILABLE = 1 << 0;
2872 /// Instruction retired event not available if 1. (Bit 01)
2873 const INST_RET_EV_UNAVAILABLE = 1 << 1;
2874 /// Reference cycles event not available if 1. (Bit 02)
2875 const REF_CYC_EV_UNAVAILABLE = 1 << 2;
2876 /// Last-level cache reference event not available if 1. (Bit 03)
2877 const CACHE_REF_EV_UNAVAILABLE = 1 << 3;
2878 /// Last-level cache misses event not available if 1. (Bit 04)
2879 const LL_CACHE_MISS_EV_UNAVAILABLE = 1 << 4;
2880 /// Branch instruction retired event not available if 1. (Bit 05)
2881 const BRANCH_INST_RET_EV_UNAVAILABLE = 1 << 5;
2882 /// Branch mispredict retired event not available if 1. (Bit 06)
2883 const BRANCH_MISPRED_EV_UNAVAILABLE = 1 << 6;
2884 }
2885 }
2886
2887 /// Iterates over the system topology in order to retrieve more
2888 /// system information at each level of the topology.
2889 #[derive(Debug, Default)]
2890 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
2891 pub struct ExtendedTopologyIter {
2892 level: u32,
2893 }
2894
2895 /// Gives detailed information about the current level in the topology
2896 /// (how many cores, what type etc.).
2897 #[derive(Default)]
2898 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
2899 pub struct ExtendedTopologyLevel {
2900 eax: u32,
2901 ebx: u32,
2902 ecx: u32,
2903 edx: u32,
2904 }
2905
2906 impl fmt::Debug for ExtendedTopologyLevel {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result2907 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2908 f.debug_struct("ExtendedTopologyLevel")
2909 .field("processors", &self.processors())
2910 .field("number", &self.level_number())
2911 .field("type", &self.level_type())
2912 .field("x2apic_id", &self.x2apic_id())
2913 .field("next_apic_id", &self.shift_right_for_next_apic_id())
2914 .finish()
2915 }
2916 }
2917
2918 impl ExtendedTopologyLevel {
2919 /// Number of logical processors at this level type.
2920 /// The number reflects configuration as shipped.
processors(&self) -> u162921 pub fn processors(&self) -> u16 {
2922 get_bits(self.ebx, 0, 15) as u16
2923 }
2924
2925 /// Level number.
level_number(&self) -> u82926 pub fn level_number(&self) -> u8 {
2927 get_bits(self.ecx, 0, 7) as u8
2928 }
2929
2930 // Level type.
level_type(&self) -> TopologyType2931 pub fn level_type(&self) -> TopologyType {
2932 match get_bits(self.ecx, 8, 15) {
2933 0 => TopologyType::Invalid,
2934 1 => TopologyType::SMT,
2935 2 => TopologyType::Core,
2936 _ => unreachable!(),
2937 }
2938 }
2939
2940 /// x2APIC ID the current logical processor. (Bits 31-00)
x2apic_id(&self) -> u322941 pub fn x2apic_id(&self) -> u32 {
2942 self.edx
2943 }
2944
2945 /// Number of bits to shift right on x2APIC ID to get a unique topology ID of the next level type. (Bits 04-00)
2946 /// All logical processors with the same next level ID share current level.
shift_right_for_next_apic_id(&self) -> u322947 pub fn shift_right_for_next_apic_id(&self) -> u32 {
2948 get_bits(self.eax, 0, 4)
2949 }
2950 }
2951
2952 /// What type of core we have at this level in the topology (real CPU or hyper-threaded).
2953 #[derive(PartialEq, Eq, Debug)]
2954 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
2955 pub enum TopologyType {
2956 Invalid = 0,
2957 /// Hyper-thread (Simultaneous multithreading)
2958 SMT = 1,
2959 Core = 2,
2960 }
2961
2962 impl Default for TopologyType {
default() -> TopologyType2963 fn default() -> TopologyType {
2964 TopologyType::Invalid
2965 }
2966 }
2967
2968 impl Iterator for ExtendedTopologyIter {
2969 type Item = ExtendedTopologyLevel;
2970
next(&mut self) -> Option<ExtendedTopologyLevel>2971 fn next(&mut self) -> Option<ExtendedTopologyLevel> {
2972 let res = cpuid!(EAX_EXTENDED_TOPOLOGY_INFO, self.level);
2973 self.level += 1;
2974
2975 let et = ExtendedTopologyLevel {
2976 eax: res.eax,
2977 ebx: res.ebx,
2978 ecx: res.ecx,
2979 edx: res.edx,
2980 };
2981
2982 match et.level_type() {
2983 TopologyType::Invalid => None,
2984 _ => Some(et),
2985 }
2986 }
2987 }
2988
2989 bitflags! {
2990 #[derive(Default)]
2991 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
2992 struct ExtendedStateInfoXCR0Flags: u32 {
2993 /// legacy x87 (Bit 00).
2994 const LEGACY_X87 = 1 << 0;
2995
2996 /// 128-bit SSE (Bit 01).
2997 const SSE128 = 1 << 1;
2998
2999 /// 256-bit AVX (Bit 02).
3000 const AVX256 = 1 << 2;
3001
3002 /// MPX BNDREGS (Bit 03).
3003 const MPX_BNDREGS = 1 << 3;
3004
3005 /// MPX BNDCSR (Bit 04).
3006 const MPX_BNDCSR = 1 << 4;
3007
3008 /// AVX512 OPMASK (Bit 05).
3009 const AVX512_OPMASK = 1 << 5;
3010
3011 /// AVX ZMM Hi256 (Bit 06).
3012 const AVX512_ZMM_HI256 = 1 << 6;
3013
3014 /// AVX 512 ZMM Hi16 (Bit 07).
3015 const AVX512_ZMM_HI16 = 1 << 7;
3016
3017 /// PKRU state (Bit 09).
3018 const PKRU = 1 << 9;
3019
3020 /// IA32_XSS HDC State (Bit 13).
3021 const IA32_XSS_HDC = 1 << 13;
3022 }
3023 }
3024
3025 bitflags! {
3026 #[derive(Default)]
3027 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3028 struct ExtendedStateInfoXSSFlags: u32 {
3029 /// IA32_XSS PT (Trace Packet) State (Bit 08).
3030 const PT = 1 << 8;
3031
3032 /// IA32_XSS HDC State (Bit 13).
3033 const HDC = 1 << 13;
3034 }
3035 }
3036
3037 #[derive(Debug, Default)]
3038 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3039 pub struct ExtendedStateInfo {
3040 eax: ExtendedStateInfoXCR0Flags,
3041 ebx: u32,
3042 ecx: u32,
3043 edx: u32,
3044 eax1: u32,
3045 ebx1: u32,
3046 ecx1: ExtendedStateInfoXSSFlags,
3047 edx1: u32,
3048 }
3049
3050 impl ExtendedStateInfo {
3051 check_flag!(
3052 doc = "Support for legacy x87 in XCR0.",
3053 xcr0_supports_legacy_x87,
3054 eax,
3055 ExtendedStateInfoXCR0Flags::LEGACY_X87
3056 );
3057
3058 check_flag!(
3059 doc = "Support for SSE 128-bit in XCR0.",
3060 xcr0_supports_sse_128,
3061 eax,
3062 ExtendedStateInfoXCR0Flags::SSE128
3063 );
3064
3065 check_flag!(
3066 doc = "Support for AVX 256-bit in XCR0.",
3067 xcr0_supports_avx_256,
3068 eax,
3069 ExtendedStateInfoXCR0Flags::AVX256
3070 );
3071
3072 check_flag!(
3073 doc = "Support for MPX BNDREGS in XCR0.",
3074 xcr0_supports_mpx_bndregs,
3075 eax,
3076 ExtendedStateInfoXCR0Flags::MPX_BNDREGS
3077 );
3078
3079 check_flag!(
3080 doc = "Support for MPX BNDCSR in XCR0.",
3081 xcr0_supports_mpx_bndcsr,
3082 eax,
3083 ExtendedStateInfoXCR0Flags::MPX_BNDCSR
3084 );
3085
3086 check_flag!(
3087 doc = "Support for AVX512 OPMASK in XCR0.",
3088 xcr0_supports_avx512_opmask,
3089 eax,
3090 ExtendedStateInfoXCR0Flags::AVX512_OPMASK
3091 );
3092
3093 check_flag!(
3094 doc = "Support for AVX512 ZMM Hi256 XCR0.",
3095 xcr0_supports_avx512_zmm_hi256,
3096 eax,
3097 ExtendedStateInfoXCR0Flags::AVX512_ZMM_HI256
3098 );
3099
3100 check_flag!(
3101 doc = "Support for AVX512 ZMM Hi16 in XCR0.",
3102 xcr0_supports_avx512_zmm_hi16,
3103 eax,
3104 ExtendedStateInfoXCR0Flags::AVX512_ZMM_HI16
3105 );
3106
3107 check_flag!(
3108 doc = "Support for PKRU in XCR0.",
3109 xcr0_supports_pkru,
3110 eax,
3111 ExtendedStateInfoXCR0Flags::PKRU
3112 );
3113
3114 check_flag!(
3115 doc = "Support for PT in IA32_XSS.",
3116 ia32_xss_supports_pt,
3117 ecx1,
3118 ExtendedStateInfoXSSFlags::PT
3119 );
3120
3121 check_flag!(
3122 doc = "Support for HDC in IA32_XSS.",
3123 ia32_xss_supports_hdc,
3124 ecx1,
3125 ExtendedStateInfoXSSFlags::HDC
3126 );
3127
3128 /// Maximum size (bytes, from the beginning of the XSAVE/XRSTOR save area) required by
3129 /// enabled features in XCR0. May be different than ECX if some features at the end of the XSAVE save area
3130 /// are not enabled.
xsave_area_size_enabled_features(&self) -> u323131 pub fn xsave_area_size_enabled_features(&self) -> u32 {
3132 self.ebx
3133 }
3134
3135 /// Maximum size (bytes, from the beginning of the XSAVE/XRSTOR save area) of the
3136 /// XSAVE/XRSTOR save area required by all supported features in the processor,
3137 /// i.e all the valid bit fields in XCR0.
xsave_area_size_supported_features(&self) -> u323138 pub fn xsave_area_size_supported_features(&self) -> u32 {
3139 self.ecx
3140 }
3141
3142 /// CPU has xsaveopt feature.
has_xsaveopt(&self) -> bool3143 pub fn has_xsaveopt(&self) -> bool {
3144 self.eax1 & 0x1 > 0
3145 }
3146
3147 /// Supports XSAVEC and the compacted form of XRSTOR if set.
has_xsavec(&self) -> bool3148 pub fn has_xsavec(&self) -> bool {
3149 self.eax1 & 0b10 > 0
3150 }
3151
3152 /// Supports XGETBV with ECX = 1 if set.
has_xgetbv(&self) -> bool3153 pub fn has_xgetbv(&self) -> bool {
3154 self.eax1 & 0b100 > 0
3155 }
3156
3157 /// Supports XSAVES/XRSTORS and IA32_XSS if set.
has_xsaves_xrstors(&self) -> bool3158 pub fn has_xsaves_xrstors(&self) -> bool {
3159 self.eax1 & 0b1000 > 0
3160 }
3161
3162 /// The size in bytes of the XSAVE area containing all states enabled by XCRO | IA32_XSS.
xsave_size(&self) -> u323163 pub fn xsave_size(&self) -> u32 {
3164 self.ebx1
3165 }
3166
3167 /// Iterator over extended state enumeration levels >= 2.
iter(&self) -> ExtendedStateIter3168 pub fn iter(&self) -> ExtendedStateIter {
3169 ExtendedStateIter {
3170 level: 1,
3171 supported_xcr0: self.eax.bits(),
3172 supported_xss: self.ecx1.bits(),
3173 }
3174 }
3175 }
3176
3177 #[derive(Debug, Default)]
3178 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3179 pub struct ExtendedStateIter {
3180 level: u32,
3181 supported_xcr0: u32,
3182 supported_xss: u32,
3183 }
3184
3185 /// When CPUID executes with EAX set to 0DH and ECX = n (n > 1,
3186 /// and is a valid sub-leaf index), the processor returns information
3187 /// about the size and offset of each processor extended state save area
3188 /// within the XSAVE/XRSTOR area. Software can use the forward-extendable
3189 /// technique depicted below to query the valid sub-leaves and obtain size
3190 /// and offset information for each processor extended state save area:///
3191 ///
3192 /// For i = 2 to 62 // sub-leaf 1 is reserved
3193 /// IF (CPUID.(EAX=0DH, ECX=0):VECTOR\[i\] = 1 ) // VECTOR is the 64-bit value of EDX:EAX
3194 /// Execute CPUID.(EAX=0DH, ECX = i) to examine size and offset for sub-leaf i;
3195 /// FI;
3196 impl Iterator for ExtendedStateIter {
3197 type Item = ExtendedState;
3198
next(&mut self) -> Option<ExtendedState>3199 fn next(&mut self) -> Option<ExtendedState> {
3200 self.level += 1;
3201 if self.level > 31 {
3202 return None;
3203 }
3204
3205 let bit = 1 << self.level;
3206 if (self.supported_xcr0 & bit > 0) || (self.supported_xss & bit > 0) {
3207 let res = cpuid!(EAX_EXTENDED_STATE_INFO, self.level);
3208 return Some(ExtendedState {
3209 subleaf: self.level,
3210 eax: res.eax,
3211 ebx: res.ebx,
3212 ecx: res.ecx,
3213 });
3214 }
3215
3216 self.next()
3217 }
3218 }
3219
3220 #[derive(Debug, Default)]
3221 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3222 pub struct ExtendedState {
3223 pub subleaf: u32,
3224 eax: u32,
3225 ebx: u32,
3226 ecx: u32,
3227 }
3228
3229 impl ExtendedState {
3230 /// The size in bytes (from the offset specified in EBX) of the save area
3231 /// for an extended state feature associated with a valid sub-leaf index, n.
3232 /// This field reports 0 if the sub-leaf index, n, is invalid.
size(&self) -> u323233 pub fn size(&self) -> u32 {
3234 self.eax
3235 }
3236
3237 /// The offset in bytes of this extended state components save area
3238 /// from the beginning of the XSAVE/XRSTOR area.
offset(&self) -> u323239 pub fn offset(&self) -> u32 {
3240 self.ebx
3241 }
3242
3243 /// True if the bit n (corresponding to the sub-leaf index)
3244 /// is supported in the IA32_XSS MSR;
is_in_ia32_xss(&self) -> bool3245 pub fn is_in_ia32_xss(&self) -> bool {
3246 self.ecx & 0b1 > 0
3247 }
3248
3249 /// True if bit n is supported in XCR0.
is_in_xcr0(&self) -> bool3250 pub fn is_in_xcr0(&self) -> bool {
3251 self.ecx & 0b1 == 0
3252 }
3253
3254 /// Returns true when the compacted format of an XSAVE area is used,
3255 /// this extended state component located on the next 64-byte
3256 /// boundary following the preceding state component
3257 /// (otherwise, it is located immediately following the preceding state component).
is_compacted_format(&self) -> bool3258 pub fn is_compacted_format(&self) -> bool {
3259 self.ecx & 0b10 > 0
3260 }
3261 }
3262
3263 #[derive(Debug, Default)]
3264 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3265 pub struct RdtMonitoringInfo {
3266 ebx: u32,
3267 edx: u32,
3268 }
3269
3270 /// Intel Resource Director Technology (Intel RDT) Monitoring Enumeration Sub-leaf (EAX = 0FH, ECX = 0 and ECX = 1)
3271 impl RdtMonitoringInfo {
3272 /// Maximum range (zero-based) of RMID within this physical processor of all types.
rmid_range(&self) -> u323273 pub fn rmid_range(&self) -> u32 {
3274 self.ebx
3275 }
3276
3277 check_bit_fn!(
3278 doc = "Supports L3 Cache Intel RDT Monitoring.",
3279 has_l3_monitoring,
3280 edx,
3281 1
3282 );
3283
3284 /// L3 Cache Monitoring.
l3_monitoring(&self) -> Option<L3MonitoringInfo>3285 pub fn l3_monitoring(&self) -> Option<L3MonitoringInfo> {
3286 if self.has_l3_monitoring() {
3287 let res = cpuid!(EAX_RDT_MONITORING, 1);
3288 return Some(L3MonitoringInfo {
3289 ebx: res.ebx,
3290 ecx: res.ecx,
3291 edx: res.edx,
3292 });
3293 } else {
3294 return None;
3295 }
3296 }
3297 }
3298
3299 #[derive(Debug, Default)]
3300 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3301 pub struct L3MonitoringInfo {
3302 ebx: u32,
3303 ecx: u32,
3304 edx: u32,
3305 }
3306
3307 impl L3MonitoringInfo {
3308 /// Conversion factor from reported IA32_QM_CTR value to occupancy metric (bytes).
conversion_factor(&self) -> u323309 pub fn conversion_factor(&self) -> u32 {
3310 self.ebx
3311 }
3312
3313 /// Maximum range (zero-based) of RMID of L3.
maximum_rmid_range(&self) -> u323314 pub fn maximum_rmid_range(&self) -> u32 {
3315 self.ecx
3316 }
3317
3318 check_bit_fn!(
3319 doc = "Supports occupancy monitoring.",
3320 has_occupancy_monitoring,
3321 edx,
3322 0
3323 );
3324
3325 check_bit_fn!(
3326 doc = "Supports total bandwidth monitoring.",
3327 has_total_bandwidth_monitoring,
3328 edx,
3329 1
3330 );
3331
3332 check_bit_fn!(
3333 doc = "Supports local bandwidth monitoring.",
3334 has_local_bandwidth_monitoring,
3335 edx,
3336 2
3337 );
3338 }
3339
3340 #[derive(Debug, Default)]
3341 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3342 pub struct RdtAllocationInfo {
3343 ebx: u32,
3344 }
3345
3346 impl RdtAllocationInfo {
3347 check_bit_fn!(doc = "Supports L3 Cache Allocation.", has_l3_cat, ebx, 1);
3348
3349 check_bit_fn!(doc = "Supports L2 Cache Allocation.", has_l2_cat, ebx, 2);
3350
3351 check_bit_fn!(
3352 doc = "Supports Memory Bandwidth Allocation.",
3353 has_memory_bandwidth_allocation,
3354 ebx,
3355 1
3356 );
3357
3358 /// L3 Cache Allocation Information.
l3_cat(&self) -> Option<L3CatInfo>3359 pub fn l3_cat(&self) -> Option<L3CatInfo> {
3360 if self.has_l3_cat() {
3361 let res = cpuid!(EAX_RDT_ALLOCATION, 1);
3362 return Some(L3CatInfo {
3363 eax: res.eax,
3364 ebx: res.ebx,
3365 ecx: res.ecx,
3366 edx: res.edx,
3367 });
3368 } else {
3369 return None;
3370 }
3371 }
3372
3373 /// L2 Cache Allocation Information.
l2_cat(&self) -> Option<L2CatInfo>3374 pub fn l2_cat(&self) -> Option<L2CatInfo> {
3375 if self.has_l2_cat() {
3376 let res = cpuid!(EAX_RDT_ALLOCATION, 2);
3377 return Some(L2CatInfo {
3378 eax: res.eax,
3379 ebx: res.ebx,
3380 edx: res.edx,
3381 });
3382 } else {
3383 return None;
3384 }
3385 }
3386
3387 /// Memory Bandwidth Allocation Information.
memory_bandwidth_allocation(&self) -> Option<MemBwAllocationInfo>3388 pub fn memory_bandwidth_allocation(&self) -> Option<MemBwAllocationInfo> {
3389 if self.has_l2_cat() {
3390 let res = cpuid!(EAX_RDT_ALLOCATION, 3);
3391 return Some(MemBwAllocationInfo {
3392 eax: res.eax,
3393 ecx: res.ecx,
3394 edx: res.edx,
3395 });
3396 } else {
3397 return None;
3398 }
3399 }
3400 }
3401
3402 /// L3 Cache Allocation Technology Enumeration Sub-leaf (EAX = 10H, ECX = ResID = 1).
3403 #[derive(Debug, Default)]
3404 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3405 pub struct L3CatInfo {
3406 eax: u32,
3407 ebx: u32,
3408 ecx: u32,
3409 edx: u32,
3410 }
3411
3412 impl L3CatInfo {
3413 /// Length of the capacity bit mask using minus-one notation.
capacity_mask_length(&self) -> u83414 pub fn capacity_mask_length(&self) -> u8 {
3415 get_bits(self.eax, 0, 4) as u8
3416 }
3417
3418 /// Bit-granular map of isolation/contention of allocation units.
isolation_bitmap(&self) -> u323419 pub fn isolation_bitmap(&self) -> u32 {
3420 self.ebx
3421 }
3422
3423 /// Highest COS number supported for this Leaf.
highest_cos(&self) -> u163424 pub fn highest_cos(&self) -> u16 {
3425 get_bits(self.edx, 0, 15) as u16
3426 }
3427
3428 check_bit_fn!(
3429 doc = "Is Code and Data Prioritization Technology supported?",
3430 has_code_data_prioritization,
3431 ecx,
3432 2
3433 );
3434 }
3435
3436 /// L2 Cache Allocation Technology Enumeration Sub-leaf (EAX = 10H, ECX = ResID = 2).
3437 #[derive(Debug, Default)]
3438 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3439 pub struct L2CatInfo {
3440 eax: u32,
3441 ebx: u32,
3442 edx: u32,
3443 }
3444
3445 impl L2CatInfo {
3446 /// Length of the capacity bit mask using minus-one notation.
capacity_mask_length(&self) -> u83447 pub fn capacity_mask_length(&self) -> u8 {
3448 get_bits(self.eax, 0, 4) as u8
3449 }
3450
3451 /// Bit-granular map of isolation/contention of allocation units.
isolation_bitmap(&self) -> u323452 pub fn isolation_bitmap(&self) -> u32 {
3453 self.ebx
3454 }
3455
3456 /// Highest COS number supported for this Leaf.
highest_cos(&self) -> u163457 pub fn highest_cos(&self) -> u16 {
3458 get_bits(self.edx, 0, 15) as u16
3459 }
3460 }
3461
3462 /// Memory Bandwidth Allocation Enumeration Sub-leaf (EAX = 10H, ECX = ResID = 3).
3463 #[derive(Debug, Default)]
3464 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3465 pub struct MemBwAllocationInfo {
3466 eax: u32,
3467 ecx: u32,
3468 edx: u32,
3469 }
3470
3471 impl MemBwAllocationInfo {
3472 /// Reports the maximum MBA throttling value supported for the corresponding ResID using minus-one notation.
max_hba_throttling(&self) -> u163473 pub fn max_hba_throttling(&self) -> u16 {
3474 get_bits(self.eax, 0, 11) as u16
3475 }
3476
3477 /// Highest COS number supported for this Leaf.
highest_cos(&self) -> u163478 pub fn highest_cos(&self) -> u16 {
3479 get_bits(self.edx, 0, 15) as u16
3480 }
3481
3482 check_bit_fn!(
3483 doc = "Reports whether the response of the delay values is linear.",
3484 has_linear_response_delay,
3485 ecx,
3486 2
3487 );
3488 }
3489
3490 /// Intel SGX Capability Enumeration Leaf, sub-leaf 0 (EAX = 12H, ECX = 0 and ECX = 1)
3491 #[derive(Debug, Default)]
3492 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3493 pub struct SgxInfo {
3494 eax: u32,
3495 ebx: u32,
3496 ecx: u32,
3497 edx: u32,
3498 eax1: u32,
3499 ebx1: u32,
3500 ecx1: u32,
3501 edx1: u32,
3502 }
3503
3504 impl SgxInfo {
3505 check_bit_fn!(doc = "Has SGX1 support.", has_sgx1, eax, 0);
3506 check_bit_fn!(doc = "Has SGX2 support.", has_sgx2, eax, 1);
3507
3508 check_bit_fn!(
3509 doc = "Supports ENCLV instruction leaves EINCVIRTCHILD, EDECVIRTCHILD, and ESETCONTEXT.",
3510 has_enclv_leaves_einvirtchild_edecvirtchild_esetcontext,
3511 eax,
3512 5
3513 );
3514
3515 check_bit_fn!(
3516 doc = "Supports ENCLS instruction leaves ETRACKC, ERDINFO, ELDBC, and ELDUC.",
3517 has_encls_leaves_etrackc_erdinfo_eldbc_elduc,
3518 eax,
3519 6
3520 );
3521
3522 /// Bit vector of supported extended SGX features.
miscselect(&self) -> u323523 pub fn miscselect(&self) -> u32 {
3524 self.ebx
3525 }
3526
3527 /// The maximum supported enclave size in non-64-bit mode is 2^retval.
max_enclave_size_non_64bit(&self) -> u83528 pub fn max_enclave_size_non_64bit(&self) -> u8 {
3529 get_bits(self.edx, 0, 7) as u8
3530 }
3531
3532 /// The maximum supported enclave size in 64-bit mode is 2^retval.
max_enclave_size_64bit(&self) -> u83533 pub fn max_enclave_size_64bit(&self) -> u8 {
3534 get_bits(self.edx, 8, 15) as u8
3535 }
3536
3537 /// Reports the valid bits of SECS.ATTRIBUTES\[127:0\] that software can set with ECREATE.
secs_attributes(&self) -> (u64, u64)3538 pub fn secs_attributes(&self) -> (u64, u64) {
3539 let lower = self.eax1 as u64 | (self.ebx1 as u64) << 32;
3540 let upper = self.ecx1 as u64 | (self.edx1 as u64) << 32;
3541 (lower, upper)
3542 }
3543 /// Iterator over SGX sub-leafs.
iter(&self) -> SgxSectionIter3544 pub fn iter(&self) -> SgxSectionIter {
3545 SgxSectionIter { current: 2 }
3546 }
3547 }
3548
3549 /// Iterator over the SGX sub-leafs (ECX >= 2).
3550 #[derive(Debug, Default)]
3551 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3552 pub struct SgxSectionIter {
3553 current: u32,
3554 }
3555
3556 impl Iterator for SgxSectionIter {
3557 type Item = SgxSectionInfo;
3558
next(&mut self) -> Option<SgxSectionInfo>3559 fn next(&mut self) -> Option<SgxSectionInfo> {
3560 self.current += 1;
3561 let res = cpuid!(EAX_SGX, self.current);
3562 match get_bits(res.eax, 0, 3) {
3563 0b0001 => Some(SgxSectionInfo::Epc(EpcSection {
3564 eax: res.eax,
3565 ebx: res.ebx,
3566 ecx: res.ecx,
3567 edx: res.edx,
3568 })),
3569 _ => None,
3570 }
3571 }
3572 }
3573
3574 /// Intel SGX EPC Enumeration Leaf, sub-leaves (EAX = 12H, ECX = 2 or higher)
3575 #[derive(Debug)]
3576 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3577 pub enum SgxSectionInfo {
3578 // This would be nice: https://github.com/rust-lang/rfcs/pull/1450
3579 Epc(EpcSection),
3580 }
3581
3582 impl Default for SgxSectionInfo {
default() -> SgxSectionInfo3583 fn default() -> SgxSectionInfo {
3584 SgxSectionInfo::Epc(Default::default())
3585 }
3586 }
3587
3588 /// EBX:EAX and EDX:ECX provide information on the Enclave Page Cache (EPC) section
3589 #[derive(Debug, Default)]
3590 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3591 pub struct EpcSection {
3592 eax: u32,
3593 ebx: u32,
3594 ecx: u32,
3595 edx: u32,
3596 }
3597
3598 impl EpcSection {
3599 /// The physical address of the base of the EPC section
physical_base(&self) -> u643600 pub fn physical_base(&self) -> u64 {
3601 let lower = (get_bits(self.eax, 12, 31) << 12) as u64;
3602 let upper = (get_bits(self.ebx, 0, 19) as u64) << 32;
3603 lower | upper
3604 }
3605
3606 /// Size of the corresponding EPC section within the Processor Reserved Memory.
size(&self) -> u643607 pub fn size(&self) -> u64 {
3608 let lower = (get_bits(self.ecx, 12, 31) << 12) as u64;
3609 let upper = (get_bits(self.edx, 0, 19) as u64) << 32;
3610 lower | upper
3611 }
3612 }
3613
3614 #[derive(Debug, Default)]
3615 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3616 pub struct ProcessorTraceInfo {
3617 eax: u32,
3618 ebx: u32,
3619 ecx: u32,
3620 edx: u32,
3621 leaf1: Option<CpuIdResult>,
3622 }
3623
3624 impl ProcessorTraceInfo {
3625 // EBX features
3626 check_bit_fn!(
3627 doc = "If true, Indicates that IA32_RTIT_CTL.CR3Filter can be set to 1, and \
3628 that IA32_RTIT_CR3_MATCH MSR can be accessed.",
3629 has_rtit_cr3_match,
3630 ebx,
3631 0
3632 );
3633 check_bit_fn!(
3634 doc = "If true, Indicates support of Configurable PSB and Cycle-Accurate Mode.",
3635 has_configurable_psb_and_cycle_accurate_mode,
3636 ebx,
3637 1
3638 );
3639 check_bit_fn!(
3640 doc = "If true, Indicates support of IP Filtering, TraceStop filtering, and \
3641 preservation of Intel PT MSRs across warm reset.",
3642 has_ip_tracestop_filtering,
3643 ebx,
3644 2
3645 );
3646 check_bit_fn!(
3647 doc = "If true, Indicates support of MTC timing packet and suppression of \
3648 COFI-based packets.",
3649 has_mtc_timing_packet_coefi_suppression,
3650 ebx,
3651 3
3652 );
3653
3654 check_bit_fn!(
3655 doc = "Indicates support of PTWRITE. Writes can set IA32_RTIT_CTL\\[12\\] (PTWEn \
3656 and IA32_RTIT_CTL\\[5\\] (FUPonPTW), and PTWRITE can generate packets",
3657 has_ptwrite,
3658 ebx,
3659 4
3660 );
3661
3662 check_bit_fn!(
3663 doc = "Support of Power Event Trace. Writes can set IA32_RTIT_CTL\\[4\\] (PwrEvtEn) \
3664 enabling Power Event Trace packet generation.",
3665 has_power_event_trace,
3666 ebx,
3667 5
3668 );
3669
3670 // ECX features
3671 check_bit_fn!(
3672 doc = "If true, Tracing can be enabled with IA32_RTIT_CTL.ToPA = 1, hence \
3673 utilizing the ToPA output scheme; IA32_RTIT_OUTPUT_BASE and \
3674 IA32_RTIT_OUTPUT_MASK_PTRS MSRs can be accessed.",
3675 has_topa,
3676 ecx,
3677 0
3678 );
3679 check_bit_fn!(
3680 doc = "If true, ToPA tables can hold any number of output entries, up to the \
3681 maximum allowed by the MaskOrTableOffset field of \
3682 IA32_RTIT_OUTPUT_MASK_PTRS.",
3683 has_topa_maximum_entries,
3684 ecx,
3685 1
3686 );
3687 check_bit_fn!(
3688 doc = "If true, Indicates support of Single-Range Output scheme.",
3689 has_single_range_output_scheme,
3690 ecx,
3691 2
3692 );
3693 check_bit_fn!(
3694 doc = "If true, Indicates support of output to Trace Transport subsystem.",
3695 has_trace_transport_subsystem,
3696 ecx,
3697 3
3698 );
3699 check_bit_fn!(
3700 doc = "If true, Generated packets which contain IP payloads have LIP values, \
3701 which include the CS base component.",
3702 has_lip_with_cs_base,
3703 ecx,
3704 31
3705 );
3706
3707 /// Number of configurable Address Ranges for filtering (Bits 2:0).
configurable_address_ranges(&self) -> u83708 pub fn configurable_address_ranges(&self) -> u8 {
3709 self.leaf1.map_or(0, |res| get_bits(res.eax, 0, 2) as u8)
3710 }
3711
3712 /// Bitmap of supported MTC period encodings (Bit 31:16).
supported_mtc_period_encodings(&self) -> u163713 pub fn supported_mtc_period_encodings(&self) -> u16 {
3714 self.leaf1.map_or(0, |res| get_bits(res.eax, 16, 31) as u16)
3715 }
3716
3717 /// Bitmap of supported Cycle Threshold value encodings (Bits 15-0).
supported_cycle_threshold_value_encodings(&self) -> u163718 pub fn supported_cycle_threshold_value_encodings(&self) -> u16 {
3719 self.leaf1.map_or(0, |res| get_bits(res.ebx, 0, 15) as u16)
3720 }
3721
3722 /// Bitmap of supported Configurable PSB frequency encodings (Bit 31:16)
supported_psb_frequency_encodings(&self) -> u163723 pub fn supported_psb_frequency_encodings(&self) -> u16 {
3724 self.leaf1.map_or(0, |res| get_bits(res.ebx, 16, 31) as u16)
3725 }
3726 }
3727
3728 /// Time Stamp Counter and Nominal Core Crystal Clock Information Leaf.
3729 #[derive(Default)]
3730 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3731 pub struct TscInfo {
3732 eax: u32,
3733 ebx: u32,
3734 ecx: u32,
3735 }
3736
3737 impl fmt::Debug for TscInfo {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result3738 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3739 f.debug_struct("TscInfo")
3740 .field("denominator/eax", &self.denominator())
3741 .field("numerator/ebx", &self.numerator())
3742 .field("nominal_frequency/ecx", &self.nominal_frequency())
3743 .finish()
3744 }
3745 }
3746
3747 impl TscInfo {
3748 /// An unsigned integer which is the denominator of the TSC/”core crystal clock” ratio.
denominator(&self) -> u323749 pub fn denominator(&self) -> u32 {
3750 self.eax
3751 }
3752
3753 /// An unsigned integer which is the numerator of the TSC/”core crystal clock” ratio.
3754 ///
3755 /// If this is 0, the TSC/”core crystal clock” ratio is not enumerated.
numerator(&self) -> u323756 pub fn numerator(&self) -> u32 {
3757 self.ebx
3758 }
3759
3760 /// An unsigned integer which is the nominal frequency of the core crystal clock in Hz.
3761 ///
3762 /// If this is 0, the nominal core crystal clock frequency is not enumerated.
nominal_frequency(&self) -> u323763 pub fn nominal_frequency(&self) -> u32 {
3764 self.ecx
3765 }
3766
3767 /// “TSC frequency” = “core crystal clock frequency” * EBX/EAX.
tsc_frequency(&self) -> u643768 pub fn tsc_frequency(&self) -> u64 {
3769 self.nominal_frequency() as u64 * self.numerator() as u64 / self.denominator() as u64
3770 }
3771 }
3772
3773 /// Processor Frequency Information
3774 #[derive(Debug, Default)]
3775 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3776 pub struct ProcessorFrequencyInfo {
3777 eax: u32,
3778 ebx: u32,
3779 ecx: u32,
3780 }
3781
3782 impl ProcessorFrequencyInfo {
3783 /// Processor Base Frequency (in MHz).
processor_base_frequency(&self) -> u163784 pub fn processor_base_frequency(&self) -> u16 {
3785 get_bits(self.eax, 0, 15) as u16
3786 }
3787
3788 /// Maximum Frequency (in MHz).
processor_max_frequency(&self) -> u163789 pub fn processor_max_frequency(&self) -> u16 {
3790 get_bits(self.ebx, 0, 15) as u16
3791 }
3792
3793 /// Bus (Reference) Frequency (in MHz).
bus_frequency(&self) -> u163794 pub fn bus_frequency(&self) -> u16 {
3795 get_bits(self.ecx, 0, 15) as u16
3796 }
3797 }
3798
3799 /// Deterministic Address Translation Structure Iterator
3800 #[derive(Debug, Default)]
3801 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3802 pub struct DatIter {
3803 current: u32,
3804 count: u32,
3805 }
3806
3807 impl Iterator for DatIter {
3808 type Item = DatInfo;
3809
3810 /// Iterate over each sub-leaf with an address translation structure.
next(&mut self) -> Option<DatInfo>3811 fn next(&mut self) -> Option<DatInfo> {
3812 loop {
3813 // Sub-leaf index n is invalid if n exceeds the value that sub-leaf 0 returns in EAX
3814 if self.current > self.count {
3815 return None;
3816 }
3817
3818 let res = cpuid!(EAX_DETERMINISTIC_ADDRESS_TRANSLATION_INFO, self.current);
3819 self.current += 1;
3820
3821 // A sub-leaf index is also invalid if EDX[4:0] returns 0.
3822 if get_bits(res.edx, 0, 4) == 0 {
3823 // Valid sub-leaves do not need to be contiguous or in any particular order.
3824 // A valid sub-leaf may be in a higher input ECX value than an invalid sub-leaf
3825 // or than a valid sub-leaf of a higher or lower-level struc-ture
3826 continue;
3827 }
3828
3829 return Some(DatInfo {
3830 eax: res.eax,
3831 ebx: res.ebx,
3832 ecx: res.ecx,
3833 edx: res.edx,
3834 });
3835 }
3836 }
3837 }
3838
3839 /// Deterministic Address Translation Structure
3840 #[derive(Debug, Default)]
3841 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3842 pub struct DatInfo {
3843 eax: u32,
3844 ebx: u32,
3845 ecx: u32,
3846 edx: u32,
3847 }
3848
3849 impl DatInfo {
3850 check_bit_fn!(
3851 doc = "4K page size entries supported by this structure",
3852 has_4k_entries,
3853 ebx,
3854 0
3855 );
3856
3857 check_bit_fn!(
3858 doc = "2MB page size entries supported by this structure",
3859 has_2mb_entries,
3860 ebx,
3861 1
3862 );
3863
3864 check_bit_fn!(
3865 doc = "4MB page size entries supported by this structure",
3866 has_4mb_entries,
3867 ebx,
3868 2
3869 );
3870
3871 check_bit_fn!(
3872 doc = "1GB page size entries supported by this structure",
3873 has_1gb_entries,
3874 ebx,
3875 3
3876 );
3877
3878 check_bit_fn!(
3879 doc = "Fully associative structure",
3880 is_fully_associative,
3881 edx,
3882 8
3883 );
3884
3885 /// Partitioning (0: Soft partitioning between the logical processors sharing this structure).
partitioning(&self) -> u83886 pub fn partitioning(&self) -> u8 {
3887 get_bits(self.ebx, 8, 10) as u8
3888 }
3889
3890 /// Ways of associativity.
ways(&self) -> u163891 pub fn ways(&self) -> u16 {
3892 get_bits(self.ebx, 16, 31) as u16
3893 }
3894
3895 /// Number of Sets.
sets(&self) -> u323896 pub fn sets(&self) -> u32 {
3897 self.ecx
3898 }
3899
3900 /// Translation cache type field.
cache_type(&self) -> DatType3901 pub fn cache_type(&self) -> DatType {
3902 match get_bits(self.edx, 0, 4) as u8 {
3903 0b00001 => DatType::DataTLB,
3904 0b00010 => DatType::InstructionTLB,
3905 0b00011 => DatType::UnifiedTLB,
3906 0b00000 => DatType::Null, // should never be returned as this indicates invalid struct!
3907 _ => DatType::Unknown,
3908 }
3909 }
3910
3911 /// Translation cache level (starts at 1)
cache_level(&self) -> u83912 pub fn cache_level(&self) -> u8 {
3913 get_bits(self.edx, 5, 7) as u8
3914 }
3915
3916 /// Maximum number of addressable IDs for logical processors sharing this translation cache
max_addressable_ids(&self) -> u163917 pub fn max_addressable_ids(&self) -> u16 {
3918 // Add one to the return value to get the result:
3919 (get_bits(self.edx, 14, 25) + 1) as u16
3920 }
3921 }
3922
3923 /// Deterministic Address Translation cache type (EDX bits 04 -- 00)
3924 #[derive(Debug)]
3925 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3926 pub enum DatType {
3927 /// Null (indicates this sub-leaf is not valid).
3928 Null = 0b00000,
3929 DataTLB = 0b00001,
3930 InstructionTLB = 0b00010,
3931 /// Some unified TLBs will allow a single TLB entry to satisfy data read/write
3932 /// and instruction fetches. Others will require separate entries (e.g., one
3933 /// loaded on data read/write and another loaded on an instruction fetch) .
3934 /// Please see the Intel® 64 and IA-32 Architectures Optimization Reference Manual
3935 /// for details of a particular product.
3936 UnifiedTLB = 0b00011,
3937 Unknown,
3938 }
3939
3940 impl Default for DatType {
default() -> DatType3941 fn default() -> DatType {
3942 DatType::Null
3943 }
3944 }
3945
3946 #[derive(Debug, Default)]
3947 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3948 pub struct SoCVendorInfo {
3949 /// MaxSOCID_Index
3950 eax: u32,
3951 ebx: u32,
3952 ecx: u32,
3953 edx: u32,
3954 }
3955
3956 impl SoCVendorInfo {
get_soc_vendor_id(&self) -> u163957 pub fn get_soc_vendor_id(&self) -> u16 {
3958 get_bits(self.ebx, 0, 15) as u16
3959 }
3960
get_project_id(&self) -> u323961 pub fn get_project_id(&self) -> u32 {
3962 self.ecx
3963 }
3964
get_stepping_id(&self) -> u323965 pub fn get_stepping_id(&self) -> u32 {
3966 self.edx
3967 }
3968
get_vendor_brand(&self) -> SoCVendorBrand3969 pub fn get_vendor_brand(&self) -> SoCVendorBrand {
3970 assert!(self.eax >= 3); // Leaf 17H is valid if MaxSOCID_Index >= 3.
3971 let r1 = cpuid!(EAX_SOC_VENDOR_INFO, 1);
3972 let r2 = cpuid!(EAX_SOC_VENDOR_INFO, 2);
3973 let r3 = cpuid!(EAX_SOC_VENDOR_INFO, 3);
3974 SoCVendorBrand { data: [r1, r2, r3] }
3975 }
3976
get_vendor_attributes(&self) -> Option<SoCVendorAttributesIter>3977 pub fn get_vendor_attributes(&self) -> Option<SoCVendorAttributesIter> {
3978 if self.eax > 3 {
3979 Some(SoCVendorAttributesIter {
3980 count: self.eax,
3981 current: 3,
3982 })
3983 } else {
3984 None
3985 }
3986 }
3987 }
3988
3989 #[derive(Debug, Default)]
3990 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
3991 pub struct SoCVendorAttributesIter {
3992 count: u32,
3993 current: u32,
3994 }
3995
3996 impl Iterator for SoCVendorAttributesIter {
3997 type Item = CpuIdResult;
3998
3999 /// Iterate over all SoC vendor specific attributes.
next(&mut self) -> Option<CpuIdResult>4000 fn next(&mut self) -> Option<CpuIdResult> {
4001 if self.current > self.count {
4002 return None;
4003 }
4004 self.count += 1;
4005 Some(cpuid!(EAX_SOC_VENDOR_INFO, self.count))
4006 }
4007 }
4008
4009 #[derive(Debug, Default)]
4010 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
4011 pub struct SoCVendorBrand {
4012 #[allow(dead_code)]
4013 data: [CpuIdResult; 3],
4014 }
4015
4016 impl SoCVendorBrand {
as_string<'a>(&'a self) -> &'a str4017 pub fn as_string<'a>(&'a self) -> &'a str {
4018 unsafe {
4019 let brand_string_start = self as *const SoCVendorBrand as *const u8;
4020 let slice =
4021 slice::from_raw_parts(brand_string_start, core::mem::size_of::<SoCVendorBrand>());
4022 let byte_array: &'a [u8] = transmute(slice);
4023 str::from_utf8_unchecked(byte_array)
4024 }
4025 }
4026 }
4027
4028 impl fmt::Display for SoCVendorBrand {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result4029 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4030 write!(f, "{}", self.as_string())
4031 }
4032 }
4033
4034 /// Information about Hypervisor (https://lwn.net/Articles/301888/)
4035 pub struct HypervisorInfo {
4036 res: CpuIdResult,
4037 }
4038
4039 impl fmt::Debug for HypervisorInfo {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result4040 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4041 f.debug_struct("HypervisorInfo")
4042 .field("type", &self.identify())
4043 .field("tsc_frequency", &self.tsc_frequency())
4044 .field("apic_frequency", &self.apic_frequency())
4045 .finish()
4046 }
4047 }
4048
4049 /// Identifies the different Hypervisor products.
4050 #[derive(Debug, Eq, PartialEq)]
4051 pub enum Hypervisor {
4052 Xen,
4053 VMware,
4054 HyperV,
4055 KVM,
4056 Unknown(u32, u32, u32),
4057 }
4058
4059 impl HypervisorInfo {
identify(&self) -> Hypervisor4060 pub fn identify(&self) -> Hypervisor {
4061 match (self.res.ebx, self.res.ecx, self.res.edx) {
4062 // "VMwareVMware"
4063 (0x61774d56, 0x4d566572, 0x65726177) => Hypervisor::VMware,
4064 // "XenVMMXenVMM"
4065 (0x566e6558, 0x65584d4d, 0x4d4d566e) => Hypervisor::Xen,
4066 // "Microsoft Hv"
4067 (0x7263694d, 0x666f736f, 0x76482074) => Hypervisor::HyperV,
4068 // "KVMKVMKVM\0\0\0"
4069 (0x4b4d564b, 0x564b4d56, 0x0000004d) => Hypervisor::KVM,
4070 (ebx, ecx, edx) => Hypervisor::Unknown(ebx, ecx, edx),
4071 }
4072 }
4073
4074 /// TSC frequency in kHz.
tsc_frequency(&self) -> Option<u32>4075 pub fn tsc_frequency(&self) -> Option<u32> {
4076 // vm aware tsc frequency retrieval:
4077 // # EAX: (Virtual) TSC frequency in kHz.
4078 if self.res.eax >= 0x40000010 {
4079 let virt_tinfo = cpuid!(0x40000010, 0);
4080 Some(virt_tinfo.eax)
4081 } else {
4082 None
4083 }
4084 }
4085
4086 /// (Virtual) Bus (local apic timer) frequency in kHz.
apic_frequency(&self) -> Option<u32>4087 pub fn apic_frequency(&self) -> Option<u32> {
4088 // # EBX: (Virtual) Bus (local apic timer) frequency in kHz.
4089 if self.res.eax >= 0x40000010 {
4090 let virt_tinfo = cpuid!(0x40000010, 0);
4091 Some(virt_tinfo.ebx)
4092 } else {
4093 None
4094 }
4095 }
4096 }
4097
4098 #[derive(Debug, Default)]
4099 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
4100 pub struct ExtendedFunctionInfo {
4101 max_eax_value: u32,
4102 data: [CpuIdResult; 9],
4103 }
4104
4105 #[derive(PartialEq, Eq, Debug)]
4106 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
4107 pub enum L2Associativity {
4108 Disabled = 0x0,
4109 DirectMapped = 0x1,
4110 TwoWay = 0x2,
4111 FourWay = 0x4,
4112 EightWay = 0x6,
4113 SixteenWay = 0x8,
4114 FullyAssiciative = 0xF,
4115 Unknown,
4116 }
4117
4118 impl Default for L2Associativity {
default() -> L2Associativity4119 fn default() -> L2Associativity {
4120 L2Associativity::Unknown
4121 }
4122 }
4123
4124 const EAX_EXTENDED_PROC_SIGNATURE: u32 = 0x1;
4125 const EAX_EXTENDED_BRAND_STRING: u32 = 0x4;
4126 const EAX_EXTENDED_CACHE_INFO: u32 = 0x6;
4127
4128 impl ExtendedFunctionInfo {
leaf_is_supported(&self, val: u32) -> bool4129 fn leaf_is_supported(&self, val: u32) -> bool {
4130 val <= self.max_eax_value
4131 }
4132
4133 /// Retrieve processor brand string.
processor_brand_string<'a>(&'a self) -> Option<&'a str>4134 pub fn processor_brand_string<'a>(&'a self) -> Option<&'a str> {
4135 if self.leaf_is_supported(EAX_EXTENDED_BRAND_STRING) {
4136 Some(unsafe {
4137 let brand_string_start = &self.data[2] as *const CpuIdResult as *const u8;
4138 let mut slice = slice::from_raw_parts(brand_string_start, 3 * 4 * 4);
4139
4140 match slice.iter().position(|&x| x == 0) {
4141 Some(index) => slice = slice::from_raw_parts(brand_string_start, index),
4142 None => (),
4143 }
4144
4145 let byte_array: &'a [u8] = transmute(slice);
4146 str::from_utf8_unchecked(byte_array)
4147 })
4148 } else {
4149 None
4150 }
4151 }
4152
4153 /// Extended Processor Signature and Feature Bits.
extended_signature(&self) -> Option<u32>4154 pub fn extended_signature(&self) -> Option<u32> {
4155 if self.leaf_is_supported(EAX_EXTENDED_PROC_SIGNATURE) {
4156 Some(self.data[1].eax)
4157 } else {
4158 None
4159 }
4160 }
4161
4162 /// Cache Line size in bytes
cache_line_size(&self) -> Option<u8>4163 pub fn cache_line_size(&self) -> Option<u8> {
4164 if self.leaf_is_supported(EAX_EXTENDED_CACHE_INFO) {
4165 Some(get_bits(self.data[6].ecx, 0, 7) as u8)
4166 } else {
4167 None
4168 }
4169 }
4170
4171 /// L2 Associativity field
l2_associativity(&self) -> Option<L2Associativity>4172 pub fn l2_associativity(&self) -> Option<L2Associativity> {
4173 if self.leaf_is_supported(EAX_EXTENDED_CACHE_INFO) {
4174 Some(match get_bits(self.data[6].ecx, 12, 15) {
4175 0x0 => L2Associativity::Disabled,
4176 0x1 => L2Associativity::DirectMapped,
4177 0x2 => L2Associativity::TwoWay,
4178 0x4 => L2Associativity::FourWay,
4179 0x6 => L2Associativity::EightWay,
4180 0x8 => L2Associativity::SixteenWay,
4181 0xF => L2Associativity::FullyAssiciative,
4182 _ => L2Associativity::Unknown,
4183 })
4184 } else {
4185 None
4186 }
4187 }
4188
4189 /// Cache size in 1K units
cache_size(&self) -> Option<u16>4190 pub fn cache_size(&self) -> Option<u16> {
4191 if self.leaf_is_supported(EAX_EXTENDED_CACHE_INFO) {
4192 Some(get_bits(self.data[6].ecx, 16, 31) as u16)
4193 } else {
4194 None
4195 }
4196 }
4197
4198 /// #Physical Address Bits
physical_address_bits(&self) -> Option<u8>4199 pub fn physical_address_bits(&self) -> Option<u8> {
4200 if self.leaf_is_supported(8) {
4201 Some(get_bits(self.data[8].eax, 0, 7) as u8)
4202 } else {
4203 None
4204 }
4205 }
4206
4207 /// #Linear Address Bits
linear_address_bits(&self) -> Option<u8>4208 pub fn linear_address_bits(&self) -> Option<u8> {
4209 if self.leaf_is_supported(8) {
4210 Some(get_bits(self.data[8].eax, 8, 15) as u8)
4211 } else {
4212 None
4213 }
4214 }
4215
4216 /// Is Invariant TSC available?
has_invariant_tsc(&self) -> bool4217 pub fn has_invariant_tsc(&self) -> bool {
4218 self.leaf_is_supported(7) && self.data[7].edx & (1 << 8) > 0
4219 }
4220
4221 /// Is LAHF/SAHF available in 64-bit mode?
has_lahf_sahf(&self) -> bool4222 pub fn has_lahf_sahf(&self) -> bool {
4223 self.leaf_is_supported(1)
4224 && ExtendedFunctionInfoEcx {
4225 bits: self.data[1].ecx,
4226 }
4227 .contains(ExtendedFunctionInfoEcx::LAHF_SAHF)
4228 }
4229
4230 /// Is LZCNT available?
has_lzcnt(&self) -> bool4231 pub fn has_lzcnt(&self) -> bool {
4232 self.leaf_is_supported(1)
4233 && ExtendedFunctionInfoEcx {
4234 bits: self.data[1].ecx,
4235 }
4236 .contains(ExtendedFunctionInfoEcx::LZCNT)
4237 }
4238
4239 /// Is PREFETCHW available?
has_prefetchw(&self) -> bool4240 pub fn has_prefetchw(&self) -> bool {
4241 self.leaf_is_supported(1)
4242 && ExtendedFunctionInfoEcx {
4243 bits: self.data[1].ecx,
4244 }
4245 .contains(ExtendedFunctionInfoEcx::PREFETCHW)
4246 }
4247
4248 /// Are fast system calls available.
has_syscall_sysret(&self) -> bool4249 pub fn has_syscall_sysret(&self) -> bool {
4250 self.leaf_is_supported(1)
4251 && ExtendedFunctionInfoEdx {
4252 bits: self.data[1].edx,
4253 }
4254 .contains(ExtendedFunctionInfoEdx::SYSCALL_SYSRET)
4255 }
4256
4257 /// Is there support for execute disable bit.
has_execute_disable(&self) -> bool4258 pub fn has_execute_disable(&self) -> bool {
4259 self.leaf_is_supported(1)
4260 && ExtendedFunctionInfoEdx {
4261 bits: self.data[1].edx,
4262 }
4263 .contains(ExtendedFunctionInfoEdx::EXECUTE_DISABLE)
4264 }
4265
4266 /// Is there support for 1GiB pages.
has_1gib_pages(&self) -> bool4267 pub fn has_1gib_pages(&self) -> bool {
4268 self.leaf_is_supported(1)
4269 && ExtendedFunctionInfoEdx {
4270 bits: self.data[1].edx,
4271 }
4272 .contains(ExtendedFunctionInfoEdx::GIB_PAGES)
4273 }
4274
4275 /// Check support for rdtscp instruction.
has_rdtscp(&self) -> bool4276 pub fn has_rdtscp(&self) -> bool {
4277 self.leaf_is_supported(1)
4278 && ExtendedFunctionInfoEdx {
4279 bits: self.data[1].edx,
4280 }
4281 .contains(ExtendedFunctionInfoEdx::RDTSCP)
4282 }
4283
4284 /// Check support for 64-bit mode.
has_64bit_mode(&self) -> bool4285 pub fn has_64bit_mode(&self) -> bool {
4286 self.leaf_is_supported(1)
4287 && ExtendedFunctionInfoEdx {
4288 bits: self.data[1].edx,
4289 }
4290 .contains(ExtendedFunctionInfoEdx::I64BIT_MODE)
4291 }
4292 }
4293
4294 bitflags! {
4295 #[derive(Default)]
4296 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
4297 struct ExtendedFunctionInfoEcx: u32 {
4298 /// LAHF/SAHF available in 64-bit mode.
4299 const LAHF_SAHF = 1 << 0;
4300 /// Bit 05: LZCNT
4301 const LZCNT = 1 << 5;
4302 /// Bit 08: PREFETCHW
4303 const PREFETCHW = 1 << 8;
4304 }
4305 }
4306
4307 bitflags! {
4308 #[derive(Default)]
4309 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
4310 struct ExtendedFunctionInfoEdx: u32 {
4311 /// SYSCALL/SYSRET available in 64-bit mode (Bit 11).
4312 const SYSCALL_SYSRET = 1 << 11;
4313 /// Execute Disable Bit available (Bit 20).
4314 const EXECUTE_DISABLE = 1 << 20;
4315 /// 1-GByte pages are available if 1 (Bit 26).
4316 const GIB_PAGES = 1 << 26;
4317 /// RDTSCP and IA32_TSC_AUX are available if 1 (Bit 27).
4318 const RDTSCP = 1 << 27;
4319 /// Intel ® 64 Architecture available if 1 (Bit 29).
4320 const I64BIT_MODE = 1 << 29;
4321 }
4322 }
4323
4324 #[derive(Debug, Default)]
4325 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
4326 pub struct MemoryEncryptionInfo {
4327 eax: MemoryEncryptionInfoEax,
4328 ebx: u32,
4329 ecx: u32,
4330 edx: u32,
4331 }
4332
4333 impl MemoryEncryptionInfo {
4334 check_flag!(
4335 doc = "Secure Memory Encryption is supported if set.",
4336 has_sme,
4337 eax,
4338 MemoryEncryptionInfoEax::SME
4339 );
4340
4341 check_flag!(
4342 doc = "Secure Encrypted Virtualization is supported if set.",
4343 has_sev,
4344 eax,
4345 MemoryEncryptionInfoEax::SEV
4346 );
4347
4348 check_flag!(
4349 doc = "The Page Flush MSR is available if set.",
4350 has_page_flush_msr,
4351 eax,
4352 MemoryEncryptionInfoEax::PAGE_FLUSH_MSR
4353 );
4354
4355 check_flag!(
4356 doc = "SEV Encrypted State is supported if set.",
4357 has_sev_es,
4358 eax,
4359 MemoryEncryptionInfoEax::SEV_ES
4360 );
4361
physical_address_reduction(&self) -> u84362 pub fn physical_address_reduction(&self) -> u8 {
4363 get_bits(self.ebx, 6, 11) as u8
4364 }
4365
c_bit_position(&self) -> u84366 pub fn c_bit_position(&self) -> u8 {
4367 get_bits(self.ebx, 0, 5) as u8
4368 }
4369
max_encrypted_guests(&self) -> u324370 pub fn max_encrypted_guests(&self) -> u32 {
4371 self.ecx
4372 }
4373
min_sev_no_es_asid(&self) -> u324374 pub fn min_sev_no_es_asid(&self) -> u32 {
4375 self.edx
4376 }
4377 }
4378
4379 bitflags! {
4380 #[derive(Default)]
4381 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
4382 struct MemoryEncryptionInfoEax: u32 {
4383 /// Bit 00: SME supported
4384 const SME = 1 << 0;
4385 /// Bit 01: SEV supported
4386 const SEV = 1 << 1;
4387 /// Bit 02: Page Flush MSR available
4388 const PAGE_FLUSH_MSR = 1 << 2;
4389 /// Bit 03: SEV-ES supported
4390 const SEV_ES = 1 << 3;
4391 }
4392 }
4393