On Mon, Dec 16, 2024 at 3:51 PM Andreas Hindborg <a.hindborg@xxxxxxxxxx> wrote: > > "Alice Ryhl" <aliceryhl@xxxxxxxxxx> writes: > > > The vm_insert_page method is only usable on vmas with the VM_MIXEDMAP > > flag, so we introduce a new type to keep track of such vmas. > > > > The approach used in this patch assumes that we will not need to encode > > many flag combinations in the type. I don't think we need to encode more > > than VM_MIXEDMAP and VM_PFNMAP as things are now. However, if that > > becomes necessary, using generic parameters in a single type would scale > > better as the number of flags increases. > > > > Acked-by: Lorenzo Stoakes <lorenzo.stoakes@xxxxxxxxxx> (for mm bits) > > Signed-off-by: Alice Ryhl <aliceryhl@xxxxxxxxxx> > > --- > > rust/kernel/mm/virt.rs | 71 +++++++++++++++++++++++++++++++++++++++++++++++++- > > 1 file changed, 70 insertions(+), 1 deletion(-) > > > > diff --git a/rust/kernel/mm/virt.rs b/rust/kernel/mm/virt.rs > > index 68c763169cf0..3a23854e14f4 100644 > > --- a/rust/kernel/mm/virt.rs > > +++ b/rust/kernel/mm/virt.rs > > @@ -4,7 +4,15 @@ > > > > //! Virtual memory. > > > > -use crate::{bindings, mm::MmWithUser, types::Opaque}; > > +use crate::{ > > + bindings, > > + error::{to_result, Result}, > > + mm::MmWithUser, > > + page::Page, > > + types::Opaque, > > +}; > > + > > +use core::ops::Deref; > > > > /// A wrapper for the kernel's `struct vm_area_struct` with read access. > > /// > > @@ -100,6 +108,67 @@ pub fn zap_page_range_single(&self, address: usize, size: usize) { > > ) > > }; > > } > > + > > + /// Check whether the `VM_MIXEDMAP` flag is set. > > Perhaps "Check whether the `VM_MIXEDMAP` flag is set. If so, return > `Some`, otherwise `None` ? How about If the `VM_MIXEDMAP` flag is set, returns a `VmAreaMixedMap` to this VMA, otherwise returns `None`. This follows the example of slice::as_ascii > > + /// > > + /// This can be used to access methods that require `VM_MIXEDMAP` to be set. > > + #[inline] > > + pub fn as_mixedmap_vma(&self) -> Option<&VmAreaMixedMap> { > > + if self.flags() & flags::MIXEDMAP != 0 { > > + // SAFETY: We just checked that `VM_MIXEDMAP` is set. All other requirements are > > + // satisfied by the type invariants of `VmAreaRef`. > > + Some(unsafe { VmAreaMixedMap::from_raw(self.as_ptr()) }) > > + } else { > > + None > > + } > > + } > > +} > > + > > +/// A wrapper for the kernel's `struct vm_area_struct` with read access and `VM_MIXEDMAP` set. > > +/// > > +/// It represents an area of virtual memory. > > Could we have a link to `VmAreaRef` and explain that this is a > `VmAreaRef` with an additional requirement? Ok. > > +/// > > +/// # Invariants > > +/// > > +/// The caller must hold the mmap read lock or the vma read lock. The `VM_MIXEDMAP` flag must be > > +/// set. > > +#[repr(transparent)] > > +pub struct VmAreaMixedMap { > > + vma: VmAreaRef, > > +} > > + > > +// Make all `VmAreaRef` methods available on `VmAreaMixedMap`. > > +impl Deref for VmAreaMixedMap { > > + type Target = VmAreaRef; > > + > > + #[inline] > > + fn deref(&self) -> &VmAreaRef { > > + &self.vma > > + } > > +} > > + > > +impl VmAreaMixedMap { > > + /// Access a virtual memory area given a raw pointer. > > + /// > > + /// # Safety > > + /// > > + /// Callers must ensure that `vma` is valid for the duration of 'a, and that the mmap read lock > > + /// (or stronger) is held for at least the duration of 'a. The `VM_MIXEDMAP` flag must be set. > > + #[inline] > > + pub unsafe fn from_raw<'a>(vma: *const bindings::vm_area_struct) -> &'a Self { > > + // SAFETY: The caller ensures that the invariants are satisfied for the duration of 'a. > > + unsafe { &*vma.cast() } > > + } > > + > > + /// Maps a single page at the given address within the virtual memory area. > > + /// > > + /// This operation does not take ownership of the page. > > + #[inline] > > + pub fn vm_insert_page(&self, address: usize, page: &Page) -> Result { > > + // SAFETY: The caller has read access and has verified that `VM_MIXEDMAP` is set. The page > > + // is order 0. The address is checked on the C side so it can take any value. > > Maybe something like this: "By the type invariant of `Self` caller has read > access and has verified that `VM_MIXEDMAP` is set. By invariant on > `Page` the page has order 0." Ok. Alice