From f94a5a7dcafdcbcd8d43af586a637148515bc86a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 8 Sep 2023 11:14:11 -0600 Subject: [PATCH] 0.4.1: custom mmio read/write functions on x86 --- Cargo.toml | 2 +- src/io/mmio.rs | 129 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 127 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bfe636e522..74b489c5fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "redox_syscall" -version = "0.4.0" +version = "0.4.1" description = "A Rust library to access raw Redox system calls" license = "MIT" authors = ["Jeremy Soller "] diff --git a/src/io/mmio.rs b/src/io/mmio.rs index 3966ab4546..ef8f603911 100644 --- a/src/io/mmio.rs +++ b/src/io/mmio.rs @@ -1,5 +1,6 @@ -use core::ptr::{read_volatile, write_volatile, addr_of, addr_of_mut}; use core::mem::MaybeUninit; +use core::ptr; +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] use core::ops::{BitAnd, BitOr, Not}; use super::io::Io; @@ -32,14 +33,136 @@ impl Mmio { } } +// Generic implementation (WARNING: requires aligned pointers!) +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] impl Io for Mmio where T: Copy + PartialEq + BitAnd + BitOr + Not { type Value = T; fn read(&self) -> T { - unsafe { read_volatile(addr_of!(self.value).cast::()) } + unsafe { ptr::read_volatile(ptr::addr_of!(self.value).cast::()) } } fn write(&mut self, value: T) { - unsafe { write_volatile(addr_of_mut!(self.value).cast::(), value) }; + unsafe { ptr::write_volatile(ptr::addr_of_mut!(self.value).cast::(), value) }; + } +} + +// x86 u8 implementation +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +impl Io for Mmio { + type Value = u8; + + fn read(&self) -> Self::Value { + unsafe { + let value: Self::Value; + let ptr: *const Self::Value = ptr::addr_of!(self.value).cast::(); + core::arch::asm!( + "mov {}, [{}]", + out(reg_byte) value, + in(reg) ptr + ); + value + } + } + + fn write(&mut self, value: Self::Value) { + unsafe { + let ptr: *mut Self::Value = ptr::addr_of_mut!(self.value).cast::(); + core::arch::asm!( + "mov [{}], {}", + in(reg) ptr, + in(reg_byte) value, + ); + } + } +} + +// x86 u16 implementation +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +impl Io for Mmio { + type Value = u16; + + fn read(&self) -> Self::Value { + unsafe { + let value: Self::Value; + let ptr: *const Self::Value = ptr::addr_of!(self.value).cast::(); + core::arch::asm!( + "mov {:x}, [{}]", + out(reg) value, + in(reg) ptr + ); + value + } + } + + fn write(&mut self, value: Self::Value) { + unsafe { + let ptr: *mut Self::Value = ptr::addr_of_mut!(self.value).cast::(); + core::arch::asm!( + "mov [{}], {:x}", + in(reg) ptr, + in(reg) value, + ); + } + } +} + +// x86 u32 implementation +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +impl Io for Mmio { + type Value = u32; + + fn read(&self) -> Self::Value { + unsafe { + let value: Self::Value; + let ptr: *const Self::Value = ptr::addr_of!(self.value).cast::(); + core::arch::asm!( + "mov {:e}, [{}]", + out(reg) value, + in(reg) ptr + ); + value + } + } + + fn write(&mut self, value: Self::Value) { + unsafe { + let ptr: *mut Self::Value = ptr::addr_of_mut!(self.value).cast::(); + core::arch::asm!( + "mov [{}], {:e}", + in(reg) ptr, + in(reg) value, + ); + } + } +} + +// x86 u64 implementation (x86_64 only) +#[cfg(target_arch = "x86_64")] +impl Io for Mmio { + type Value = u64; + + fn read(&self) -> Self::Value { + unsafe { + let value: Self::Value; + let ptr: *const Self::Value = ptr::addr_of!(self.value).cast::(); + core::arch::asm!( + "mov {:r}, [{}]", + out(reg) value, + in(reg) ptr + ); + value + } + } + + fn write(&mut self, value: Self::Value) { + unsafe { + let ptr: *mut Self::Value = ptr::addr_of_mut!(self.value).cast::(); + core::arch::asm!( + "mov [{}], {:r}", + in(reg) ptr, + in(reg) value, + ); + } } }