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