diff --git a/src/scheme/sys/mod.rs b/src/scheme/sys/mod.rs index 8f26187a..9eb35644 100644 --- a/src/scheme/sys/mod.rs +++ b/src/scheme/sys/mod.rs @@ -47,0 +48,5 @@ enum Handle { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + Msr { + cpu: usize, + msr: u32, + }, @@ -135,0 +141,22 @@ impl KernelScheme for SysScheme { + } else if path.starts_with("msr/") { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + if ctx.uid != 0 { + return Err(Error::new(EPERM)); + } + let rest = &path[4..]; + let mut parts = rest.split('/'); + let cpu_str = parts.next().ok_or(Error::new(EINVAL))?; + let msr_str = parts.next().ok_or(Error::new(EINVAL))?; + if parts.next().is_some() { + return Err(Error::new(EINVAL)); + } + let cpu: usize = cpu_str.parse().map_err(|_| Error::new(EINVAL))?; + let msr: u32 = u32::from_str_radix(msr_str, 16).map_err(|_| Error::new(EINVAL))?; + let id = HANDLES.write(token.token()).insert(Handle::Msr { cpu, msr }); + Ok(OpenResult::SchemeLocal(id, InternalFlags::POSITIONED)) + } + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + Err(Error::new(ENOENT)) + } @@ -162,0 +190,2 @@ impl KernelScheme for SysScheme { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + Handle::Msr { .. } => return Ok(0), @@ -190,0 +220,10 @@ impl KernelScheme for SysScheme { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + Handle::Msr { cpu, msr } => { + const FIRST: &[u8] = b"sys:msr/"; + let mut bytes_read = buf.copy_common_bytes_from_slice(FIRST)?; + let suffix = format!("{}/{:x}", cpu, msr); + if let Some(remaining) = buf.advance(FIRST.len()) { + bytes_read += remaining.copy_common_bytes_from_slice(suffix.as_bytes())?; + } + return Ok(bytes_read); + } @@ -217,0 +257,9 @@ impl KernelScheme for SysScheme { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + Handle::Msr { cpu, msr } => { + if *cpu != crate::cpu_id().get() as usize { + return Err(Error::new(EINVAL)); + } + let val = unsafe { x86::msr::rdmsr(*msr) }; + let data = format!("{:016x}\n", val).into_bytes(); + return buffer.copy_common_bytes_from_slice(&data[pos..]); + } @@ -255,0 +304,12 @@ impl KernelScheme for SysScheme { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + Handle::Msr { cpu, msr } => { + if *cpu != crate::cpu_id().get() as usize { + return Err(Error::new(EINVAL)); + } + let mut intermediate = [0_u8; 32]; + let len = buffer.copy_common_bytes_to_slice(&mut intermediate)?; + let val_str = core::str::from_utf8(&intermediate[..len]).map_err(|_| Error::new(EINVAL))?; + let val = u64::from_str_radix(val_str.trim(), 16).map_err(|_| Error::new(EINVAL))?; + unsafe { x86::msr::wrmsr(*msr, val); } + return Ok(len); + } @@ -272 +332,2 @@ impl KernelScheme for SysScheme { - Handle::Resource { .. } => Err(Error::new(ENOTDIR)), + Handle::Resource { .. } + | Handle::Msr { .. } => Err(Error::new(ENOTDIR)), @@ -295,0 +357,12 @@ impl KernelScheme for SysScheme { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + Handle::Msr { .. } => { + let stat = Stat { + st_mode: 0o600 | MODE_FILE, + st_uid: 0, + st_gid: 0, + st_size: 0, + ..Default::default() + }; + buf.copy_exactly(&stat)?; + return Ok(()); + }