Files
RedBear-OS/local/patches/kernel/P23-sys-msr-scheme.patch
T
vasilito 56be23ce6e kernel: Add sys:msr scheme for userspace MSR read/write
Expose MSR access via /scheme/sys/msr/<cpu>/<msr> for root only.
Required for cpufreqd P-state control and thermal sensor drivers.
2026-05-20 13:38:53 +03:00

88 lines
4.2 KiB
Diff

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(());
+ }