mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	rust: map long to isize and char to u8
				
					
				
			The following FFI types are replaced compared to `core::ffi`: 1. `char` type is now always mapped to `u8`, since kernel uses `-funsigned-char` on the C code. `core::ffi` maps it to platform default ABI, which can be either signed or unsigned. 2. `long` is now always mapped to `isize`. It's very common in the kernel to use `long` to represent a pointer-sized integer, and in fact `intptr_t` is a typedef of `long` in the kernel. Enforce this mapping rather than mapping to `i32/i64` depending on platform can save us a lot of unnecessary casts. Signed-off-by: Gary Guo <gary@garyguo.net> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Link: https://lore.kernel.org/r/20240913213041.395655-5-gary@garyguo.net [ Moved `uaccess` changes from the next commit, since they were irrefutable patterns that Rust >= 1.82.0 warns about. Reworded slightly and reformatted a few documentation comments. Rebased on top of `rust-next`. Added the removal of two casts to avoid Clippy warnings. - Miguel ] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
		
							parent
							
								
									27c7518e7f
								
							
						
					
					
						commit
						1bae8729e5
					
				
					 5 changed files with 47 additions and 28 deletions
				
			
		
							
								
								
									
										37
									
								
								rust/ffi.rs
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								rust/ffi.rs
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -10,4 +10,39 @@
 | 
			
		|||
 | 
			
		||||
#![no_std]
 | 
			
		||||
 | 
			
		||||
pub use core::ffi::*;
 | 
			
		||||
macro_rules! alias {
 | 
			
		||||
    ($($name:ident = $ty:ty;)*) => {$(
 | 
			
		||||
        #[allow(non_camel_case_types, missing_docs)]
 | 
			
		||||
        pub type $name = $ty;
 | 
			
		||||
 | 
			
		||||
        // Check size compatibility with `core`.
 | 
			
		||||
        const _: () = assert!(
 | 
			
		||||
            core::mem::size_of::<$name>() == core::mem::size_of::<core::ffi::$name>()
 | 
			
		||||
        );
 | 
			
		||||
    )*}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
alias! {
 | 
			
		||||
    // `core::ffi::c_char` is either `i8` or `u8` depending on architecture. In the kernel, we use
 | 
			
		||||
    // `-funsigned-char` so it's always mapped to `u8`.
 | 
			
		||||
    c_char = u8;
 | 
			
		||||
 | 
			
		||||
    c_schar = i8;
 | 
			
		||||
    c_uchar = u8;
 | 
			
		||||
 | 
			
		||||
    c_short = i16;
 | 
			
		||||
    c_ushort = u16;
 | 
			
		||||
 | 
			
		||||
    c_int = i32;
 | 
			
		||||
    c_uint = u32;
 | 
			
		||||
 | 
			
		||||
    // In the kernel, `intptr_t` is defined to be `long` in all platforms, so we can map the type to
 | 
			
		||||
    // `isize`.
 | 
			
		||||
    c_long = isize;
 | 
			
		||||
    c_ulong = usize;
 | 
			
		||||
 | 
			
		||||
    c_longlong = i64;
 | 
			
		||||
    c_ulonglong = u64;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub use core::ffi::c_void;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -153,11 +153,8 @@ pub(crate) fn to_blk_status(self) -> bindings::blk_status_t {
 | 
			
		|||
 | 
			
		||||
    /// Returns the error encoded as a pointer.
 | 
			
		||||
    pub fn to_ptr<T>(self) -> *mut T {
 | 
			
		||||
        #[cfg_attr(target_pointer_width = "32", allow(clippy::useless_conversion))]
 | 
			
		||||
        // SAFETY: `self.0` is a valid error due to its invariant.
 | 
			
		||||
        unsafe {
 | 
			
		||||
            bindings::ERR_PTR(self.0.get().into()) as *mut _
 | 
			
		||||
        }
 | 
			
		||||
        unsafe { bindings::ERR_PTR(self.0.get() as _) as *mut _ }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns a string representing the error, if one exists.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@
 | 
			
		|||
/// One of the following: `bindings::request_firmware`, `bindings::firmware_request_nowarn`,
 | 
			
		||||
/// `bindings::firmware_request_platform`, `bindings::request_firmware_direct`.
 | 
			
		||||
struct FwFunc(
 | 
			
		||||
    unsafe extern "C" fn(*mut *const bindings::firmware, *const i8, *mut bindings::device) -> i32,
 | 
			
		||||
    unsafe extern "C" fn(*mut *const bindings::firmware, *const u8, *mut bindings::device) -> i32,
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
impl FwFunc {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -225,7 +225,7 @@ impl<T: MiscDevice> VtableHelper<T> {
 | 
			
		|||
    // SAFETY: Ioctl calls can borrow the private data of the file.
 | 
			
		||||
    let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };
 | 
			
		||||
 | 
			
		||||
    match T::ioctl(device, cmd, arg as usize) {
 | 
			
		||||
    match T::ioctl(device, cmd, arg) {
 | 
			
		||||
        Ok(ret) => ret as c_long,
 | 
			
		||||
        Err(err) => err.to_errno() as c_long,
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -245,7 +245,7 @@ impl<T: MiscDevice> VtableHelper<T> {
 | 
			
		|||
    // SAFETY: Ioctl calls can borrow the private data of the file.
 | 
			
		||||
    let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };
 | 
			
		||||
 | 
			
		||||
    match T::compat_ioctl(device, cmd, arg as usize) {
 | 
			
		||||
    match T::compat_ioctl(device, cmd, arg) {
 | 
			
		||||
        Ok(ret) => ret as c_long,
 | 
			
		||||
        Err(err) => err.to_errno() as c_long,
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@
 | 
			
		|||
    alloc::Flags,
 | 
			
		||||
    bindings,
 | 
			
		||||
    error::Result,
 | 
			
		||||
    ffi::{c_ulong, c_void},
 | 
			
		||||
    ffi::c_void,
 | 
			
		||||
    prelude::*,
 | 
			
		||||
    transmute::{AsBytes, FromBytes},
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -224,13 +224,9 @@ pub fn read_raw(&mut self, out: &mut [MaybeUninit<u8>]) -> Result {
 | 
			
		|||
        if len > self.length {
 | 
			
		||||
            return Err(EFAULT);
 | 
			
		||||
        }
 | 
			
		||||
        let Ok(len_ulong) = c_ulong::try_from(len) else {
 | 
			
		||||
            return Err(EFAULT);
 | 
			
		||||
        };
 | 
			
		||||
        // SAFETY: `out_ptr` points into a mutable slice of length `len_ulong`, so we may write
 | 
			
		||||
        // SAFETY: `out_ptr` points into a mutable slice of length `len`, so we may write
 | 
			
		||||
        // that many bytes to it.
 | 
			
		||||
        let res =
 | 
			
		||||
            unsafe { bindings::copy_from_user(out_ptr, self.ptr as *const c_void, len_ulong) };
 | 
			
		||||
        let res = unsafe { bindings::copy_from_user(out_ptr, self.ptr as *const c_void, len) };
 | 
			
		||||
        if res != 0 {
 | 
			
		||||
            return Err(EFAULT);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -259,9 +255,6 @@ pub fn read<T: FromBytes>(&mut self) -> Result<T> {
 | 
			
		|||
        if len > self.length {
 | 
			
		||||
            return Err(EFAULT);
 | 
			
		||||
        }
 | 
			
		||||
        let Ok(len_ulong) = c_ulong::try_from(len) else {
 | 
			
		||||
            return Err(EFAULT);
 | 
			
		||||
        };
 | 
			
		||||
        let mut out: MaybeUninit<T> = MaybeUninit::uninit();
 | 
			
		||||
        // SAFETY: The local variable `out` is valid for writing `size_of::<T>()` bytes.
 | 
			
		||||
        //
 | 
			
		||||
| 
						 | 
				
			
			@ -272,7 +265,7 @@ pub fn read<T: FromBytes>(&mut self) -> Result<T> {
 | 
			
		|||
            bindings::_copy_from_user(
 | 
			
		||||
                out.as_mut_ptr().cast::<c_void>(),
 | 
			
		||||
                self.ptr as *const c_void,
 | 
			
		||||
                len_ulong,
 | 
			
		||||
                len,
 | 
			
		||||
            )
 | 
			
		||||
        };
 | 
			
		||||
        if res != 0 {
 | 
			
		||||
| 
						 | 
				
			
			@ -335,12 +328,9 @@ pub fn write_slice(&mut self, data: &[u8]) -> Result {
 | 
			
		|||
        if len > self.length {
 | 
			
		||||
            return Err(EFAULT);
 | 
			
		||||
        }
 | 
			
		||||
        let Ok(len_ulong) = c_ulong::try_from(len) else {
 | 
			
		||||
            return Err(EFAULT);
 | 
			
		||||
        };
 | 
			
		||||
        // SAFETY: `data_ptr` points into an immutable slice of length `len_ulong`, so we may read
 | 
			
		||||
        // SAFETY: `data_ptr` points into an immutable slice of length `len`, so we may read
 | 
			
		||||
        // that many bytes from it.
 | 
			
		||||
        let res = unsafe { bindings::copy_to_user(self.ptr as *mut c_void, data_ptr, len_ulong) };
 | 
			
		||||
        let res = unsafe { bindings::copy_to_user(self.ptr as *mut c_void, data_ptr, len) };
 | 
			
		||||
        if res != 0 {
 | 
			
		||||
            return Err(EFAULT);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -359,9 +349,6 @@ pub fn write<T: AsBytes>(&mut self, value: &T) -> Result {
 | 
			
		|||
        if len > self.length {
 | 
			
		||||
            return Err(EFAULT);
 | 
			
		||||
        }
 | 
			
		||||
        let Ok(len_ulong) = c_ulong::try_from(len) else {
 | 
			
		||||
            return Err(EFAULT);
 | 
			
		||||
        };
 | 
			
		||||
        // SAFETY: The reference points to a value of type `T`, so it is valid for reading
 | 
			
		||||
        // `size_of::<T>()` bytes.
 | 
			
		||||
        //
 | 
			
		||||
| 
						 | 
				
			
			@ -372,7 +359,7 @@ pub fn write<T: AsBytes>(&mut self, value: &T) -> Result {
 | 
			
		|||
            bindings::_copy_to_user(
 | 
			
		||||
                self.ptr as *mut c_void,
 | 
			
		||||
                (value as *const T).cast::<c_void>(),
 | 
			
		||||
                len_ulong,
 | 
			
		||||
                len,
 | 
			
		||||
            )
 | 
			
		||||
        };
 | 
			
		||||
        if res != 0 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue