mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-24 09:53:24 +00:00
Export /proc/cpuinfo
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
16a319a8ea
commit
561516df98
@ -1,7 +1,13 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
use alloc::{
|
||||||
|
format,
|
||||||
|
string::{String, ToString},
|
||||||
|
vec::Vec,
|
||||||
|
};
|
||||||
|
|
||||||
use ostd::{
|
use ostd::{
|
||||||
cpu::{CpuException, CpuExceptionInfo, RawGeneralRegs, UserContext},
|
cpu::{cpuid, CpuException, CpuExceptionInfo, RawGeneralRegs, UserContext},
|
||||||
Pod,
|
Pod,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -128,3 +134,389 @@ impl TryFrom<&CpuExceptionInfo> for PageFaultInfo {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// CPU Information structure
|
||||||
|
///
|
||||||
|
/// Reference:
|
||||||
|
/// - https://www.felixcloutier.com/x86/cpuid
|
||||||
|
///
|
||||||
|
/// FIXME: The crate x86 works not well on AMD CPUs, so some information may be missing.
|
||||||
|
pub struct CpuInfo {
|
||||||
|
processor: u32,
|
||||||
|
vendor_id: String,
|
||||||
|
cpu_family: u32,
|
||||||
|
model: u32,
|
||||||
|
model_name: String,
|
||||||
|
stepping: u32,
|
||||||
|
microcode: u32,
|
||||||
|
cpu_mhz: u32,
|
||||||
|
cache_size: u32,
|
||||||
|
tlb_size: u32,
|
||||||
|
physical_id: u32,
|
||||||
|
siblings: u32,
|
||||||
|
core_id: u32,
|
||||||
|
cpu_cores: u32,
|
||||||
|
apicid: u32,
|
||||||
|
initial_apicid: u32,
|
||||||
|
cpuid_level: u32,
|
||||||
|
flags: String,
|
||||||
|
bugs: String,
|
||||||
|
clflush_size: u8,
|
||||||
|
cache_alignment: u32,
|
||||||
|
address_sizes: String,
|
||||||
|
power_management: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CpuInfo {
|
||||||
|
pub fn new(processor_id: u32) -> Self {
|
||||||
|
Self {
|
||||||
|
processor: processor_id,
|
||||||
|
vendor_id: Self::get_vendor_id(),
|
||||||
|
cpu_family: Self::get_cpu_family(),
|
||||||
|
model: Self::get_model(),
|
||||||
|
model_name: Self::get_model_name(),
|
||||||
|
stepping: Self::get_stepping(),
|
||||||
|
microcode: Self::get_microcode(),
|
||||||
|
cpu_mhz: Self::get_clock_speed().unwrap_or(0),
|
||||||
|
cache_size: Self::get_cache_size().unwrap_or(0),
|
||||||
|
tlb_size: Self::get_tlb_size().unwrap_or(0),
|
||||||
|
physical_id: Self::get_physical_id().unwrap_or(0),
|
||||||
|
siblings: Self::get_siblings_count().unwrap_or(0),
|
||||||
|
core_id: Self::get_core_id(),
|
||||||
|
cpu_cores: Self::get_cpu_cores(),
|
||||||
|
apicid: Self::get_apicid(),
|
||||||
|
initial_apicid: Self::get_initial_apicid(),
|
||||||
|
cpuid_level: Self::get_cpuid_level(),
|
||||||
|
flags: Self::get_cpu_flags(),
|
||||||
|
bugs: Self::get_cpu_bugs(),
|
||||||
|
// bogomips: Self::get_bogomips(),
|
||||||
|
clflush_size: Self::get_clflush_size(),
|
||||||
|
cache_alignment: Self::get_cache_alignment(),
|
||||||
|
address_sizes: Self::get_address_sizes(),
|
||||||
|
power_management: Self::get_power_management(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collect and format CPU information into a `String`
|
||||||
|
pub fn collect_cpu_info(&self) -> String {
|
||||||
|
format!(
|
||||||
|
"processor\t: {}\n\
|
||||||
|
vendor_id\t: {}\n\
|
||||||
|
cpu family\t: {}\n\
|
||||||
|
model\t\t: {}\n\
|
||||||
|
model name\t: {}\n\
|
||||||
|
stepping\t: {}\n\
|
||||||
|
microcode\t: 0x{:x}\n\
|
||||||
|
cpu MHz\t\t: {}\n\
|
||||||
|
cache size\t: {} KB\n\
|
||||||
|
TLB size\t: {} 4K pages\n\
|
||||||
|
physical id\t: {}\n\
|
||||||
|
siblings\t: {}\n\
|
||||||
|
core id\t\t: {}\n\
|
||||||
|
cpu cores\t: {}\n\
|
||||||
|
apicid\t\t: {}\n\
|
||||||
|
initial apicid\t: {}\n\
|
||||||
|
cpuid level\t: {}\n\
|
||||||
|
flags\t\t: {}\n\
|
||||||
|
bugs\t\t: {}\n\
|
||||||
|
clflush size\t: {} bytes\n\
|
||||||
|
cache_alignment\t: {} bytes\n\
|
||||||
|
address sizes\t: {}\n\
|
||||||
|
power management: {}\n",
|
||||||
|
self.processor,
|
||||||
|
self.vendor_id,
|
||||||
|
self.cpu_family,
|
||||||
|
self.model,
|
||||||
|
self.model_name,
|
||||||
|
self.stepping,
|
||||||
|
self.microcode,
|
||||||
|
self.cpu_mhz,
|
||||||
|
self.cache_size / 1024,
|
||||||
|
self.tlb_size,
|
||||||
|
self.physical_id,
|
||||||
|
self.siblings,
|
||||||
|
self.core_id,
|
||||||
|
self.cpu_cores,
|
||||||
|
self.apicid,
|
||||||
|
self.initial_apicid,
|
||||||
|
self.cpuid_level,
|
||||||
|
self.flags,
|
||||||
|
self.bugs,
|
||||||
|
self.clflush_size,
|
||||||
|
self.cache_alignment,
|
||||||
|
self.address_sizes,
|
||||||
|
self.power_management
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_vendor_id() -> String {
|
||||||
|
let cpuid = cpuid::CpuId::new();
|
||||||
|
cpuid.get_vendor_info().unwrap().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_cpu_family() -> u32 {
|
||||||
|
let cpuid = cpuid::CpuId::new();
|
||||||
|
let feature_info = cpuid.get_feature_info().unwrap();
|
||||||
|
feature_info.family_id().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_model() -> u32 {
|
||||||
|
let cpuid = cpuid::CpuId::new();
|
||||||
|
let feature_info = cpuid.get_feature_info().unwrap();
|
||||||
|
feature_info.model_id().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_stepping() -> u32 {
|
||||||
|
let cpuid = cpuid::CpuId::new();
|
||||||
|
let feature_info = cpuid.get_feature_info().unwrap();
|
||||||
|
feature_info.stepping_id().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_model_name() -> String {
|
||||||
|
let cpuid = cpuid::CpuId::new();
|
||||||
|
let brand_string = cpuid.get_processor_brand_string().unwrap();
|
||||||
|
brand_string.as_str().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_microcode() -> u32 {
|
||||||
|
let cpuid = cpuid::cpuid!(0x1);
|
||||||
|
cpuid.ecx
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_clock_speed() -> Option<u32> {
|
||||||
|
let cpuid = cpuid::CpuId::new();
|
||||||
|
let tsc_info = cpuid.get_tsc_info()?;
|
||||||
|
Some(
|
||||||
|
(tsc_info.tsc_frequency().unwrap_or(0) / 1_000_000)
|
||||||
|
.try_into()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get cache size in KB
|
||||||
|
fn get_cache_size() -> Option<u32> {
|
||||||
|
let cpuid = cpuid::CpuId::new();
|
||||||
|
let cache_info = cpuid.get_cache_info()?;
|
||||||
|
|
||||||
|
for cache in cache_info {
|
||||||
|
let desc = cache.desc();
|
||||||
|
if let Some(size) = desc.split_whitespace().find(|word| {
|
||||||
|
word.ends_with("KBytes") || word.ends_with("MBytes") || word.ends_with("GBytes")
|
||||||
|
}) {
|
||||||
|
let size_str = size
|
||||||
|
.trim_end_matches(&['K', 'M', 'G'][..])
|
||||||
|
.trim_end_matches("Bytes");
|
||||||
|
let cache_size = size_str.parse::<u32>().unwrap_or(0);
|
||||||
|
|
||||||
|
let cache_size = match size.chars().last().unwrap() {
|
||||||
|
'K' => cache_size * 1024,
|
||||||
|
'M' => cache_size * 1024 * 1024,
|
||||||
|
'G' => cache_size * 1024 * 1024 * 1024,
|
||||||
|
_ => cache_size,
|
||||||
|
};
|
||||||
|
|
||||||
|
return Some(cache_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_tlb_size() -> Option<u32> {
|
||||||
|
let cpuid = cpuid::CpuId::new();
|
||||||
|
let cache_info = cpuid.get_cache_info()?;
|
||||||
|
|
||||||
|
for cache in cache_info {
|
||||||
|
let desc = cache.desc();
|
||||||
|
if let Some(size) = desc.split_whitespace().find(|word| word.ends_with("pages")) {
|
||||||
|
let size_str = size.trim_end_matches("pages");
|
||||||
|
let tlb_size = size_str.parse::<u32>().unwrap_or(0);
|
||||||
|
return Some(tlb_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_physical_id() -> Option<u32> {
|
||||||
|
let cpuid = cpuid::CpuId::new();
|
||||||
|
let feature_info = cpuid.get_feature_info()?;
|
||||||
|
Some(feature_info.initial_local_apic_id().into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_siblings_count() -> Option<u32> {
|
||||||
|
let cpuid = cpuid::CpuId::new();
|
||||||
|
let feature_info = cpuid.get_feature_info()?;
|
||||||
|
Some(feature_info.max_logical_processor_ids().into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_core_id() -> u32 {
|
||||||
|
let cpuid = cpuid::CpuId::new();
|
||||||
|
let feature_info = cpuid.get_feature_info().unwrap();
|
||||||
|
feature_info.initial_local_apic_id().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_cpu_cores() -> u32 {
|
||||||
|
let cpuid = cpuid::CpuId::new();
|
||||||
|
let feature_info = cpuid.get_feature_info().unwrap();
|
||||||
|
feature_info.max_logical_processor_ids().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_apicid() -> u32 {
|
||||||
|
let cpuid = cpuid::CpuId::new();
|
||||||
|
let feature_info = cpuid.get_feature_info().unwrap();
|
||||||
|
feature_info.initial_local_apic_id().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_initial_apicid() -> u32 {
|
||||||
|
Self::get_apicid()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_cpuid_level() -> u32 {
|
||||||
|
let cpuid = cpuid::CpuId::new();
|
||||||
|
if let Some(basic_info) = cpuid.get_tsc_info() {
|
||||||
|
basic_info.denominator()
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_cpu_flags() -> String {
|
||||||
|
let cpuid = cpuid::CpuId::new();
|
||||||
|
let feature_info = cpuid.get_feature_info().unwrap();
|
||||||
|
let mut flags = Vec::new();
|
||||||
|
if feature_info.has_fpu() {
|
||||||
|
flags.push("fpu");
|
||||||
|
}
|
||||||
|
if feature_info.has_vme() {
|
||||||
|
flags.push("vme");
|
||||||
|
}
|
||||||
|
if feature_info.has_de() {
|
||||||
|
flags.push("de");
|
||||||
|
}
|
||||||
|
if feature_info.has_pse() {
|
||||||
|
flags.push("pse");
|
||||||
|
}
|
||||||
|
if feature_info.has_tsc() {
|
||||||
|
flags.push("tsc");
|
||||||
|
}
|
||||||
|
if feature_info.has_msr() {
|
||||||
|
flags.push("msr");
|
||||||
|
}
|
||||||
|
if feature_info.has_pae() {
|
||||||
|
flags.push("pae");
|
||||||
|
}
|
||||||
|
if feature_info.has_mce() {
|
||||||
|
flags.push("mce");
|
||||||
|
}
|
||||||
|
if feature_info.has_cmpxchg8b() {
|
||||||
|
flags.push("cx8");
|
||||||
|
}
|
||||||
|
if feature_info.has_apic() {
|
||||||
|
flags.push("apic");
|
||||||
|
}
|
||||||
|
if feature_info.has_de() {
|
||||||
|
flags.push("sep");
|
||||||
|
}
|
||||||
|
if feature_info.has_mtrr() {
|
||||||
|
flags.push("mtrr");
|
||||||
|
}
|
||||||
|
if feature_info.has_pge() {
|
||||||
|
flags.push("pge");
|
||||||
|
}
|
||||||
|
if feature_info.has_mca() {
|
||||||
|
flags.push("mca");
|
||||||
|
}
|
||||||
|
if feature_info.has_cmov() {
|
||||||
|
flags.push("cmov");
|
||||||
|
}
|
||||||
|
if feature_info.has_pat() {
|
||||||
|
flags.push("pat");
|
||||||
|
}
|
||||||
|
if feature_info.has_pse36() {
|
||||||
|
flags.push("pse-36");
|
||||||
|
}
|
||||||
|
if feature_info.has_psn() {
|
||||||
|
flags.push("psn");
|
||||||
|
}
|
||||||
|
if feature_info.has_clflush() {
|
||||||
|
flags.push("clfsh");
|
||||||
|
}
|
||||||
|
if feature_info.has_ds() {
|
||||||
|
flags.push("ds");
|
||||||
|
}
|
||||||
|
if feature_info.has_acpi() {
|
||||||
|
flags.push("acpi");
|
||||||
|
}
|
||||||
|
if feature_info.has_mmx() {
|
||||||
|
flags.push("mmx");
|
||||||
|
}
|
||||||
|
if feature_info.has_ds() {
|
||||||
|
flags.push("fxsr");
|
||||||
|
}
|
||||||
|
if feature_info.has_sse() {
|
||||||
|
flags.push("sse");
|
||||||
|
}
|
||||||
|
if feature_info.has_sse2() {
|
||||||
|
flags.push("sse2");
|
||||||
|
}
|
||||||
|
if feature_info.has_ss() {
|
||||||
|
flags.push("ss");
|
||||||
|
}
|
||||||
|
if feature_info.has_htt() {
|
||||||
|
flags.push("ht");
|
||||||
|
}
|
||||||
|
if feature_info.has_tm() {
|
||||||
|
flags.push("tm");
|
||||||
|
}
|
||||||
|
if feature_info.has_pbe() {
|
||||||
|
flags.push("pbe");
|
||||||
|
}
|
||||||
|
flags.join(" ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: https://github.com/torvalds/linux/blob/master/tools/arch/x86/include/asm/cpufeatures.h#L505
|
||||||
|
fn get_cpu_bugs() -> String {
|
||||||
|
" ".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_clflush_size() -> u8 {
|
||||||
|
let cpuid = cpuid::CpuId::new();
|
||||||
|
cpuid.get_feature_info().unwrap().cflush_cache_line_size()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_cache_alignment() -> u32 {
|
||||||
|
let cpuid = cpuid::CpuId::new();
|
||||||
|
if let Some(cache_info) = cpuid.get_cache_info() {
|
||||||
|
for cache in cache_info {
|
||||||
|
let desc = cache.desc();
|
||||||
|
if let Some(alignment) = desc
|
||||||
|
.split_whitespace()
|
||||||
|
.find(|word| word.ends_with("byte line size"))
|
||||||
|
{
|
||||||
|
let alignment_str = alignment.trim_end_matches(" byte line size");
|
||||||
|
if let Ok(alignment) = alignment_str.parse::<u32>() {
|
||||||
|
return alignment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_address_sizes() -> String {
|
||||||
|
let leaf = cpuid::cpuid!(0x80000008); // Extended Function CPUID Information
|
||||||
|
let physical_address_bits = (leaf.eax & 0xFF) as u32;
|
||||||
|
let virtual_address_bits = ((leaf.eax >> 8) & 0xFF) as u32;
|
||||||
|
format!(
|
||||||
|
"{} bits physical, {} bits virtual",
|
||||||
|
physical_address_bits, virtual_address_bits
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: add power management information
|
||||||
|
fn get_power_management() -> String {
|
||||||
|
" ".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
49
kernel/src/fs/procfs/cpuinfo.rs
Normal file
49
kernel/src/fs/procfs/cpuinfo.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
//! This module offers `/proc/cpuinfo` file support, which provides
|
||||||
|
//! information about the CPU architecture, cores, and other details.
|
||||||
|
//!
|
||||||
|
//! Reference: <https://man7.org/linux/man-pages/man5/proc_cpuinfo.5.html>
|
||||||
|
|
||||||
|
use ostd::cpu::num_cpus;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
arch::cpu::CpuInfo,
|
||||||
|
fs::{
|
||||||
|
procfs::template::{FileOps, ProcFileBuilder},
|
||||||
|
utils::Inode,
|
||||||
|
},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Represents the inode at `/proc/cpuinfo`.
|
||||||
|
pub struct CpuInfoFileOps;
|
||||||
|
|
||||||
|
impl CpuInfoFileOps {
|
||||||
|
/// Create a new inode for `/proc/cpuinfo`.
|
||||||
|
pub fn new_inode(parent: Weak<dyn Inode>) -> Arc<dyn Inode> {
|
||||||
|
ProcFileBuilder::new(Self).parent(parent).build().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collect and format CPU information for all cores.
|
||||||
|
fn collect_cpu_info() -> String {
|
||||||
|
let num_cpus = num_cpus() as u32;
|
||||||
|
|
||||||
|
// Iterate over each core and collect CPU information
|
||||||
|
(0..num_cpus)
|
||||||
|
.map(|core_id| {
|
||||||
|
let cpuinfo = CpuInfo::new(core_id);
|
||||||
|
cpuinfo.collect_cpu_info()
|
||||||
|
})
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join("\n\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileOps for CpuInfoFileOps {
|
||||||
|
/// Retrieve the data for `/proc/cpuinfo`.
|
||||||
|
fn data(&self) -> Result<Vec<u8>> {
|
||||||
|
let output = Self::collect_cpu_info();
|
||||||
|
Ok(output.into_bytes())
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@ use loadavg::LoadAvgFileOps;
|
|||||||
use sys::SysDirOps;
|
use sys::SysDirOps;
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
|
cpuinfo::CpuInfoFileOps,
|
||||||
meminfo::MemInfoFileOps,
|
meminfo::MemInfoFileOps,
|
||||||
pid::PidDirOps,
|
pid::PidDirOps,
|
||||||
self_::SelfSymOps,
|
self_::SelfSymOps,
|
||||||
@ -21,6 +22,7 @@ use crate::{
|
|||||||
process::{process_table, process_table::PidEvent, Pid},
|
process::{process_table, process_table::PidEvent, Pid},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mod cpuinfo;
|
||||||
mod filesystems;
|
mod filesystems;
|
||||||
mod loadavg;
|
mod loadavg;
|
||||||
mod meminfo;
|
mod meminfo;
|
||||||
@ -110,6 +112,8 @@ impl DirOps for RootDirOps {
|
|||||||
MemInfoFileOps::new_inode(this_ptr.clone())
|
MemInfoFileOps::new_inode(this_ptr.clone())
|
||||||
} else if name == "loadavg" {
|
} else if name == "loadavg" {
|
||||||
LoadAvgFileOps::new_inode(this_ptr.clone())
|
LoadAvgFileOps::new_inode(this_ptr.clone())
|
||||||
|
} else if name == "cpuinfo" {
|
||||||
|
CpuInfoFileOps::new_inode(this_ptr.clone())
|
||||||
} else if let Ok(pid) = name.parse::<Pid>() {
|
} else if let Ok(pid) = name.parse::<Pid>() {
|
||||||
let process_ref =
|
let process_ref =
|
||||||
process_table::get_process(pid).ok_or_else(|| Error::new(Errno::ENOENT))?;
|
process_table::get_process(pid).ok_or_else(|| Error::new(Errno::ENOENT))?;
|
||||||
@ -135,7 +139,8 @@ impl DirOps for RootDirOps {
|
|||||||
.put_entry_if_not_found("meminfo", || MemInfoFileOps::new_inode(this_ptr.clone()));
|
.put_entry_if_not_found("meminfo", || MemInfoFileOps::new_inode(this_ptr.clone()));
|
||||||
cached_children
|
cached_children
|
||||||
.put_entry_if_not_found("loadavg", || LoadAvgFileOps::new_inode(this_ptr.clone()));
|
.put_entry_if_not_found("loadavg", || LoadAvgFileOps::new_inode(this_ptr.clone()));
|
||||||
|
cached_children
|
||||||
|
.put_entry_if_not_found("cpuinfo", || CpuInfoFileOps::new_inode(this_ptr.clone()));
|
||||||
for process in process_table::process_table_mut().iter() {
|
for process in process_table::process_table_mut().iter() {
|
||||||
let pid = process.pid().to_string();
|
let pid = process.pid().to_string();
|
||||||
cached_children.put_entry_if_not_found(&pid, || {
|
cached_children.put_entry_if_not_found(&pid, || {
|
||||||
|
@ -15,6 +15,7 @@ use log::debug;
|
|||||||
use num_derive::FromPrimitive;
|
use num_derive::FromPrimitive;
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
use x86::bits64::segmentation::wrfsbase;
|
use x86::bits64::segmentation::wrfsbase;
|
||||||
|
pub use x86::cpuid;
|
||||||
use x86_64::registers::rflags::RFlags;
|
use x86_64::registers::rflags::RFlags;
|
||||||
|
|
||||||
pub use super::trap::GeneralRegs as RawGeneralRegs;
|
pub use super::trap::GeneralRegs as RawGeneralRegs;
|
||||||
|
Reference in New Issue
Block a user