Skip to content

[Tracking/Asahi] Upstream-ready Rust changes #952

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 31 commits into
base: rust-next
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
38717bd
rust: kernel: Mark rust_fmt_argument as extern "C"
sulix Feb 14, 2023
bcfd851
soc: apple: rtkit: Add a private pointer to apple_rtkit_shmem
asahilina Jan 21, 2023
5f9a6ba
soc: apple: rtkit: Export non-devm init/free functions
asahilina Jan 21, 2023
3c3f227
drm/gem-shmem: Fix locking for drm_gem_shmem_get_pages_sgt()
asahilina Sep 7, 2022
a38c023
arm64: rust: Enable Rust support for AArch64
ojeda Jan 25, 2023
135e133
arm64: rust: Enable PAC support for Rust.
JamieCunliffe Jan 25, 2023
3ca7478
arm64: rust: Disable neon and fp target features.
JamieCunliffe Jan 25, 2023
4c9658b
rust: sync: impl {Debug,Display} for {Unique,}Arc
fbq Feb 7, 2023
a0fe4ac
sample: rust: print: Add sampe code for Arc printing
fbq Feb 7, 2023
d9eead4
rust: time: New module for timekeeping functions
asahilina Oct 19, 2022
dcc390a
rust: macros: Make expect_punct() return the Punct directly
asahilina Jan 26, 2023
02ce81c
rust: concat_idents: Allow :: paths in first argument
asahilina Nov 4, 2022
8c01902
rust: macros: Allow specifying multiple module aliases
asahilina Dec 5, 2022
3c3ce10
rust: ioctl: Add ioctl number manipulation functions
asahilina Sep 24, 2022
1a2e724
rust: sync: arc: implement Arc<dyn Any + Send + Sync>::downcast()
asahilina Feb 15, 2023
d5bbcf9
rust: Enable feature new_uninit for the kernel crate
asahilina Feb 11, 2023
051bf80
rust: sync: arc: Add UniqueArc<MaybeUninit<T>::assume_init()
asahilina Nov 11, 2022
5e05f75
rust: error: Add Error::to_ptr()
asahilina Sep 7, 2022
a1944a0
rust: error: Add Error::from_kernel_errno()
asahilina Feb 5, 2023
a901500
rust: error: Add to_result() helper
asahilina Feb 5, 2023
27f80ac
rust: error: Add a helper to convert a C ERR_PTR to a `Result`
May 13, 2021
7674653
rust: error: Add from_kernel_result!() macro
asahilina Feb 16, 2023
7400397
rust: Import upstream `alloc::vec::set_len_on_drop` module
asahilina Feb 16, 2023
a556d07
rust: Import upstream `alloc::vec::spec_extend` module
asahilina Feb 16, 2023
164f721
rust: alloc: vec: Add some try_* methods we need
ojeda Feb 16, 2023
38cd356
rust: xarray: Add an abstraction for XArray
asahilina Jan 11, 2023
0133449
rust: Add a Sealed trait
asahilina Feb 5, 2023
3653148
rust: device: Add an abstraction for devices
wedsonaf Nov 18, 2021
f476b2b
rust: io_pgtable: Add io_pgtable abstraction
asahilina Sep 7, 2022
f7708d0
rust: soc: apple: rtkit: Add Apple RTKit abstraction
asahilina Aug 17, 2022
b72447f
rust: Add `container_of` and `offset_of` macros
wedsonaf Apr 1, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Documentation/rust/arch-support.rst
Original file line number Diff line number Diff line change
@@ -15,5 +15,6 @@ support corresponds to ``S`` values in the ``MAINTAINERS`` file.
============ ================ ==============================================
Architecture Level of support Constraints
============ ================ ==============================================
``arm64`` Maintained None.
``x86`` Maintained ``x86_64`` only.
============ ================ ==============================================
1 change: 1 addition & 0 deletions arch/arm64/Kconfig
Original file line number Diff line number Diff line change
@@ -207,6 +207,7 @@ config ARM64
select HAVE_FUNCTION_ARG_ACCESS_API
select MMU_GATHER_RCU_TABLE_FREE
select HAVE_RSEQ
select HAVE_RUST
select HAVE_STACKPROTECTOR
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_KPROBES
4 changes: 4 additions & 0 deletions arch/arm64/Makefile
Original file line number Diff line number Diff line change
@@ -41,6 +41,8 @@ KBUILD_CFLAGS += -mgeneral-regs-only \
KBUILD_CFLAGS += $(call cc-disable-warning, psabi)
KBUILD_AFLAGS += $(compat_vdso)

KBUILD_RUSTFLAGS += -C target-feature="-neon,-fp-armv8"

KBUILD_CFLAGS += $(call cc-option,-mabi=lp64)
KBUILD_AFLAGS += $(call cc-option,-mabi=lp64)

@@ -85,8 +87,10 @@ PACRET-$(CONFIG_UNWIND_PATCH_PAC_INTO_SCS) := pac-ret

ifeq ($(CONFIG_ARM64_BTI_KERNEL),y)
branch-prot-flags-$(CONFIG_CC_HAS_BRANCH_PROT_PAC_RET_BTI) := -mbranch-protection=$(PACRET-y)+bti
KBUILD_RUSTFLAGS += -Z branch-protection=bti,pac-ret,leaf
else
branch-prot-flags-$(CONFIG_CC_HAS_BRANCH_PROT_PAC_RET) := -mbranch-protection=$(PACRET-y)
KBUILD_RUSTFLAGS += -Z branch-protection=pac-ret,leaf
endif
# -march=armv8.3-a enables the non-nops instructions for PAC, to avoid the
# compiler to generate them and consequently to break the single image contract
56 changes: 35 additions & 21 deletions drivers/gpu/drm/drm_gem_shmem_helper.c
Original file line number Diff line number Diff line change
@@ -681,23 +681,7 @@ struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_shmem_object *shmem)
}
EXPORT_SYMBOL_GPL(drm_gem_shmem_get_sg_table);

/**
* drm_gem_shmem_get_pages_sgt - Pin pages, dma map them, and return a
* scatter/gather table for a shmem GEM object.
* @shmem: shmem GEM object
*
* This function returns a scatter/gather table suitable for driver usage. If
* the sg table doesn't exist, the pages are pinned, dma-mapped, and a sg
* table created.
*
* This is the main function for drivers to get at backing storage, and it hides
* and difference between dma-buf imported and natively allocated objects.
* drm_gem_shmem_get_sg_table() should not be directly called by drivers.
*
* Returns:
* A pointer to the scatter/gather table of pinned pages or errno on failure.
*/
struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_shmem_object *shmem)
static struct sg_table *drm_gem_shmem_get_pages_sgt_locked(struct drm_gem_shmem_object *shmem)
{
struct drm_gem_object *obj = &shmem->base;
int ret;
@@ -706,9 +690,9 @@ struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_shmem_object *shmem)
if (shmem->sgt)
return shmem->sgt;

WARN_ON(obj->import_attach);
WARN_ON(shmem->base.import_attach);

ret = drm_gem_shmem_get_pages(shmem);
ret = drm_gem_shmem_get_pages_locked(shmem);
if (ret)
return ERR_PTR(ret);

@@ -730,10 +714,40 @@ struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_shmem_object *shmem)
sg_free_table(sgt);
kfree(sgt);
err_put_pages:
drm_gem_shmem_put_pages(shmem);
drm_gem_shmem_put_pages_locked(shmem);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(drm_gem_shmem_get_pages_sgt);

/**
* drm_gem_shmem_get_pages_sgt - Pin pages, dma map them, and return a
* scatter/gather table for a shmem GEM object.
* @shmem: shmem GEM object
*
* This function returns a scatter/gather table suitable for driver usage. If
* the sg table doesn't exist, the pages are pinned, dma-mapped, and a sg
* table created.
*
* This is the main function for drivers to get at backing storage, and it hides
* and difference between dma-buf imported and natively allocated objects.
* drm_gem_shmem_get_sg_table() should not be directly called by drivers.
*
* Returns:
* A pointer to the scatter/gather table of pinned pages or errno on failure.
*/
struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_shmem_object *shmem)
{
int ret;
struct sg_table *sgt;

ret = mutex_lock_interruptible(&shmem->pages_lock);
if (ret)
return ERR_PTR(ret);
sgt = drm_gem_shmem_get_pages_sgt_locked(shmem);
mutex_unlock(&shmem->pages_lock);

return sgt;
}
EXPORT_SYMBOL(drm_gem_shmem_get_pages_sgt);

/**
* drm_gem_shmem_prime_import_sg_table - Produce a shmem GEM object from
15 changes: 10 additions & 5 deletions drivers/soc/apple/rtkit.c
Original file line number Diff line number Diff line change
@@ -698,7 +698,7 @@ static int apple_rtkit_request_mbox_chan(struct apple_rtkit *rtk)
return 0;
}

static struct apple_rtkit *apple_rtkit_init(struct device *dev, void *cookie,
struct apple_rtkit *apple_rtkit_init(struct device *dev, void *cookie,
const char *mbox_name, int mbox_idx,
const struct apple_rtkit_ops *ops)
{
@@ -750,6 +750,7 @@ static struct apple_rtkit *apple_rtkit_init(struct device *dev, void *cookie,
kfree(rtk);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(apple_rtkit_init);

static int apple_rtkit_wait_for_completion(struct completion *c)
{
@@ -926,10 +927,8 @@ int apple_rtkit_wake(struct apple_rtkit *rtk)
}
EXPORT_SYMBOL_GPL(apple_rtkit_wake);

static void apple_rtkit_free(void *data)
void apple_rtkit_free(struct apple_rtkit *rtk)
{
struct apple_rtkit *rtk = data;

mbox_free_channel(rtk->mbox_chan);
destroy_workqueue(rtk->wq);

@@ -940,6 +939,12 @@ static void apple_rtkit_free(void *data)
kfree(rtk->syslog_msg_buffer);
kfree(rtk);
}
EXPORT_SYMBOL_GPL(apple_rtkit_free);

static void apple_rtkit_free_wrapper(void *data)
{
apple_rtkit_free(data);
}

struct apple_rtkit *devm_apple_rtkit_init(struct device *dev, void *cookie,
const char *mbox_name, int mbox_idx,
@@ -952,7 +957,7 @@ struct apple_rtkit *devm_apple_rtkit_init(struct device *dev, void *cookie,
if (IS_ERR(rtk))
return rtk;

ret = devm_add_action_or_reset(dev, apple_rtkit_free, rtk);
ret = devm_add_action_or_reset(dev, apple_rtkit_free_wrapper, rtk);
if (ret)
return ERR_PTR(ret);

21 changes: 21 additions & 0 deletions include/linux/soc/apple/rtkit.h
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
* @size: Size of the shared memory buffer.
* @iova: Device VA of shared memory buffer.
* @is_mapped: Shared memory buffer is managed by the co-processor.
* @private: Private data pointer for the parent driver.
*/

struct apple_rtkit_shmem {
@@ -30,6 +31,7 @@ struct apple_rtkit_shmem {
size_t size;
dma_addr_t iova;
bool is_mapped;
void *private;
};

/*
@@ -77,6 +79,25 @@ struct apple_rtkit *devm_apple_rtkit_init(struct device *dev, void *cookie,
const char *mbox_name, int mbox_idx,
const struct apple_rtkit_ops *ops);

/*
* Non-devm version of devm_apple_rtkit_init. Must be freed with
* apple_rtkit_free.
*
* @dev: Pointer to the device node this coprocessor is assocated with
* @cookie: opaque cookie passed to all functions defined in rtkit_ops
* @mbox_name: mailbox name used to communicate with the co-processor
* @mbox_idx: mailbox index to be used if mbox_name is NULL
* @ops: pointer to rtkit_ops to be used for this co-processor
*/
struct apple_rtkit *apple_rtkit_init(struct device *dev, void *cookie,
const char *mbox_name, int mbox_idx,
const struct apple_rtkit_ops *ops);

/*
* Free an instance of apple_rtkit.
*/
void apple_rtkit_free(struct apple_rtkit *rtk);

/*
* Reinitialize internal structures. Must only be called with the co-processor
* is held in reset.
137 changes: 134 additions & 3 deletions rust/alloc/vec/mod.rs
Original file line number Diff line number Diff line change
@@ -122,10 +122,8 @@ use self::spec_from_elem::SpecFromElem;
#[cfg(not(no_global_oom_handling))]
mod spec_from_elem;

#[cfg(not(no_global_oom_handling))]
use self::set_len_on_drop::SetLenOnDrop;

#[cfg(not(no_global_oom_handling))]
mod set_len_on_drop;

#[cfg(not(no_global_oom_handling))]
@@ -149,7 +147,8 @@ mod spec_from_iter;
#[cfg(not(no_global_oom_handling))]
use self::spec_extend::SpecExtend;

#[cfg(not(no_global_oom_handling))]
use self::spec_extend::TrySpecExtend;

mod spec_extend;

/// A contiguous growable array type, written as `Vec<T>`, short for 'vector'.
@@ -1919,6 +1918,17 @@ impl<T, A: Allocator> Vec<T, A> {
self.len += count;
}

/// Tries to append elements to `self` from other buffer.
#[inline]
unsafe fn try_append_elements(&mut self, other: *const [T]) -> Result<(), TryReserveError> {
let count = unsafe { (*other).len() };
self.try_reserve(count)?;
let len = self.len();
unsafe { ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count) };
self.len += count;
Ok(())
}

/// Removes the specified range from the vector in bulk, returning all
/// removed elements as an iterator. If the iterator is dropped before
/// being fully consumed, it drops the remaining removed elements.
@@ -2340,6 +2350,45 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
}
}

/// Tries to resize the `Vec` in-place so that `len` is equal to `new_len`.
///
/// If `new_len` is greater than `len`, the `Vec` is extended by the
/// difference, with each additional slot filled with `value`.
/// If `new_len` is less than `len`, the `Vec` is simply truncated.
///
/// This method requires `T` to implement [`Clone`],
/// in order to be able to clone the passed value.
/// If you need more flexibility (or want to rely on [`Default`] instead of
/// [`Clone`]), use [`Vec::resize_with`].
/// If you only need to resize to a smaller size, use [`Vec::truncate`].
///
/// # Examples
///
/// ```
/// let mut vec = vec!["hello"];
/// vec.try_resize(3, "world").unwrap();
/// assert_eq!(vec, ["hello", "world", "world"]);
///
/// let mut vec = vec![1, 2, 3, 4];
/// vec.try_resize(2, 0).unwrap();
/// assert_eq!(vec, [1, 2]);
///
/// let mut vec = vec![42];
/// let result = vec.try_resize(usize::MAX, 0);
/// assert!(result.is_err());
/// ```
#[stable(feature = "kernel", since = "1.0.0")]
pub fn try_resize(&mut self, new_len: usize, value: T) -> Result<(), TryReserveError> {
let len = self.len();

if new_len > len {
self.try_extend_with(new_len - len, ExtendElement(value))
} else {
self.truncate(new_len);
Ok(())
}
}

/// Clones and appends all elements in a slice to the `Vec`.
///
/// Iterates over the slice `other`, clones each element, and then appends
@@ -2365,6 +2414,30 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
self.spec_extend(other.iter())
}

/// Tries to clone and append all elements in a slice to the `Vec`.
///
/// Iterates over the slice `other`, clones each element, and then appends
/// it to this `Vec`. The `other` slice is traversed in-order.
///
/// Note that this function is same as [`extend`] except that it is
/// specialized to work with slices instead. If and when Rust gets
/// specialization this function will likely be deprecated (but still
/// available).
///
/// # Examples
///
/// ```
/// let mut vec = vec![1];
/// vec.try_extend_from_slice(&[2, 3, 4]).unwrap();
/// assert_eq!(vec, [1, 2, 3, 4]);
/// ```
///
/// [`extend`]: Vec::extend
#[stable(feature = "kernel", since = "1.0.0")]
pub fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), TryReserveError> {
self.try_spec_extend(other.iter())
}

/// Copies elements from `src` range to the end of the vector.
///
/// # Panics
@@ -2504,6 +2577,36 @@ impl<T, A: Allocator> Vec<T, A> {
// len set by scope guard
}
}

/// Try to extend the vector by `n` values, using the given generator.
fn try_extend_with<E: ExtendWith<T>>(&mut self, n: usize, mut value: E) -> Result<(), TryReserveError> {
self.try_reserve(n)?;

unsafe {
let mut ptr = self.as_mut_ptr().add(self.len());
// Use SetLenOnDrop to work around bug where compiler
// might not realize the store through `ptr` through self.set_len()
// don't alias.
let mut local_len = SetLenOnDrop::new(&mut self.len);

// Write all elements except the last one
for _ in 1..n {
ptr::write(ptr, value.next());
ptr = ptr.add(1);
// Increment the length in every step in case next() panics
local_len.increment_len(1);
}

if n > 0 {
// We can write the last element directly without cloning needlessly
ptr::write(ptr, value.last());
local_len.increment_len(1);
}

// len set by scope guard
Ok(())
}
}
}

impl<T: PartialEq, A: Allocator> Vec<T, A> {
@@ -2838,6 +2941,34 @@ impl<T, A: Allocator> Vec<T, A> {
}
}

// leaf method to which various SpecFrom/SpecExtend implementations delegate when
// they have no further optimizations to apply
fn try_extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) -> Result<(), TryReserveError> {
// This is the case for a general iterator.
//
// This function should be the moral equivalent of:
//
// for item in iterator {
// self.push(item);
// }
while let Some(element) = iterator.next() {
let len = self.len();
if len == self.capacity() {
let (lower, _) = iterator.size_hint();
self.try_reserve(lower.saturating_add(1))?;
}
unsafe {
ptr::write(self.as_mut_ptr().add(len), element);
// Since next() executes user code which can panic we have to bump the length
// after each step.
// NB can't overflow since we would have had to alloc the address space
self.set_len(len + 1);
}
}

Ok(())
}

/// Creates a splicing iterator that replaces the specified range in the vector
/// with the given `replace_with` iterator and yields the removed items.
/// `replace_with` does not need to be the same length as `range`.
Loading