# Meeting 2024-01-31 <!-- Leave your topic starting with ### in the relevant sections below --> ## Critical <!-- bugs, soundness issues, urgent patches/reviews etc. --> ## Status Reports <!-- You want to report on something you are working on/request reviews. Or you want to know the status of something someone else is doing --> ### Experiment changing FFI integer types https://github.com/nbdd0121/linux/commit/b604a43db56f149a90084fa8aed7988a8066894b ```rust! +/// Some assumptions about types that hold for all current kernel architectures. +/// +/// Other code can rely on these. However, in such a case, the assertion should be written nearby +/// as needed, even if these are here as a reference. +mod assumptions { + use crate::{implies, static_assert}; + + // Very unlikely to ever change, even in future kernel architectures. + static_assert!(core::mem::size_of::<core::ffi::c_char>() == 1); + static_assert!(core::mem::size_of::<core::ffi::c_schar>() == 1); + static_assert!(core::mem::size_of::<core::ffi::c_uchar>() == 1); + static_assert!(core::mem::size_of::<core::ffi::c_short>() == 2); + static_assert!(core::mem::size_of::<core::ffi::c_ushort>() == 2); + static_assert!(core::mem::size_of::<core::ffi::c_int>() == 4); + static_assert!(core::mem::size_of::<core::ffi::c_uint>() == 4); + static_assert!( + core::mem::size_of::<core::ffi::c_long>() == core::mem::size_of::<core::ffi::c_ulong>() + ); + static_assert!( + core::mem::size_of::<core::ffi::c_longlong>() + == core::mem::size_of::<core::ffi::c_ulonglong>() + ); + static_assert!( + core::mem::size_of::<usize>() == 4 + || core::mem::size_of::<usize>() == 8 + || core::mem::size_of::<usize>() == 16 + ); + + // It is undecided whether C's `long` will be 64-bits or 128-bits in future 128-bit kernel + // architectures. However, the kernel currently assumes `long` is the same size of a pointer, + // thus assume it here too, which helps with interoperability. This means that, in order to + // pick 64-bits in the future, it will likely require changes in both the C and Rust sides. + static_assert!(core::mem::size_of::<core::ffi::c_ulong>() == core::mem::size_of::<usize>()); + + // C's `long long` will likely be 128-bits in future 128-bit kernel architectures, thus new code + // should avoid assuming that it is always 64-bit (as it happens for all current architectures). + static_assert!( + core::mem::size_of::<core::ffi::c_longlong>() == 8 + || core::mem::size_of::<core::ffi::c_longlong>() == 16 + ); + + // In particular: + static_assert!(implies( + core::mem::size_of::<usize>() == 4, + core::mem::size_of::<core::ffi::c_longlong>() == 8 + )); + static_assert!(implies( + core::mem::size_of::<usize>() == 8, + core::mem::size_of::<core::ffi::c_longlong>() == 8 + )); + static_assert!(implies( + core::mem::size_of::<usize>() == 16, + core::mem::size_of::<core::ffi::c_longlong>() == 16 + )); +} ``` ```diff diff --git a/rust/Makefile b/rust/Makefile index 543b37f6c77f..acce32f17a4a 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -330,7 +330,7 @@ bindgen_c_flags_final = $(bindgen_c_flags_lto) -D__BINDGEN__ quiet_cmd_bindgen = BINDGEN $@ cmd_bindgen = \ $(BINDGEN) $< $(bindgen_target_flags) \ - --use-core --with-derive-default --ctypes-prefix core::ffi --no-layout-tests \ + --use-core --with-derive-default --ctypes-prefix ctypes --no-layout-tests \ --no-debug '.*' \ -o $@ -- $(bindgen_c_flags_final) -DMODULE \ $(bindgen_target_cflags) $(bindgen_target_extra) @@ -450,8 +450,10 @@ $(obj)/bindings.o: $(src)/bindings/lib.rs \ $(obj)/bindings/bindings_helpers_generated.rs FORCE $(call if_changed_dep,rustc_library) +$(obj)/uapi.o: private rustc_target_flags = --extern bindings $(obj)/uapi.o: $(src)/uapi/lib.rs \ $(obj)/compiler_builtins.o \ + $(obj)/bindings.o \ $(obj)/uapi/uapi_generated.rs FORCE $(call if_changed_dep,rustc_library) diff --git a/rust/bindings/lib.rs b/rust/bindings/lib.rs index 9bcbea04dac3..54ab1ff71bb4 100644 --- a/rust/bindings/lib.rs +++ b/rust/bindings/lib.rs @@ -24,10 +24,36 @@ unsafe_op_in_unsafe_fn )] +pub mod ctypes { + pub type c_void = core::ffi::c_void; + + // Since commit 3bc753c06dd0 ("kbuild: treat char as always unsigned"), the kernel is compiled + // with `-funsigned-char` explicitly. + pub type c_char = u8; + + pub type c_schar = i8; + pub type c_uchar = u8; + + pub type c_short = i16; + pub type c_ushort = u16; + + pub type c_int = i32; + pub type c_uint = u32; + + // See `kernel::types::assumptions`. + pub type c_long = isize; + pub type c_ulong = usize; + + // See `kernel::types::assumptions`. + pub type c_longlong = i64; + pub type c_ulonglong = u64; +} + mod bindings_raw { // Use glob import here to expose all helpers. // Symbols defined within the module will take precedence to the glob import. pub use super::bindings_helper::*; + use super::ctypes; include!(concat!( env!("OBJTREE"), "/rust/bindings/bindings_generated.rs" @@ -41,6 +67,7 @@ mod bindings_raw { mod bindings_helper { // Import the generated bindings for types. use super::bindings_raw::*; + use super::ctypes; include!(concat!( env!("OBJTREE"), "/rust/bindings/bindings_helpers_generated.rs" diff --git a/rust/uapi/lib.rs b/rust/uapi/lib.rs index 0caad902ba40..679f1d003633 100644 --- a/rust/uapi/lib.rs +++ b/rust/uapi/lib.rs @@ -23,4 +23,5 @@ unsafe_op_in_unsafe_fn )] +use bindings::ctypes; include!(concat!(env!("OBJTREE"), "/rust/uapi/uapi_generated.rs")); ``` Gary: https://elixir.bootlin.com/linux/latest/source/include/uapi/asm-generic/posix_types.h#L63 Maybe we should change C code so that `size_t` is always `unsigned long`? Want to change the typedef to avoid casts when compiling in 32-bit (so bindgen outputs usize for kernel size_t instead of u32). ## Discussion Questions <!-- Anything that requires lengthy discussion/more general questions also fit here --> ### Discuss inheritance/subclassing pattern DRM has requested we make a recommendation in relation to this discussion: https://hackmd.io/W_kJ1kRsS3mX8vpk5Cpbzg ## Miscellaneous <!-- stuff that does not fit into other categories --> ### const_refs_to_static Add [`const_refs_to_static`](https://github.com/rust-lang/rust/issues/119618) to [Rust unstable features needed for the kernel](https://github.com/Rust-for-Linux/linux/issues/2) to support storing pointer to owning module in `const struct` vtables: ```rust const TABLE: bindings::block_device_operations = bindings::block_device_operations { submit_bio: None, open: None, release: None, ioctl: None, compat_ioctl: None, check_events: None, unlock_native_capacity: None, getgeo: None, set_read_only: None, swap_slot_free_notify: None, report_zones: None, devnode: None, alternative_gpt_sector: None, get_unique_id: None, owner: core::ptr::null_mut(), // TODO: Set to THIS_MODULE <-- here pr_ops: core::ptr::null_mut(), free_disk: None, poll_bio: None, }; ``` ### Submitting patches with not upstream dependencies Looking for the official guide