[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250820010415.699353-8-anthony.yznaga@oracle.com>
Date: Tue, 19 Aug 2025 18:04:00 -0700
From: Anthony Yznaga <anthony.yznaga@...cle.com>
To: linux-mm@...ck.org
Cc: akpm@...ux-foundation.org, andreyknvl@...il.com, arnd@...db.de,
bp@...en8.de, brauner@...nel.org, bsegall@...gle.com, corbet@....net,
dave.hansen@...ux.intel.com, david@...hat.com,
dietmar.eggemann@....com, ebiederm@...ssion.com, hpa@...or.com,
jakub.wartak@...lbox.org, jannh@...gle.com, juri.lelli@...hat.com,
khalid@...nel.org, liam.howlett@...cle.com, linyongting@...edance.com,
lorenzo.stoakes@...cle.com, luto@...nel.org, markhemm@...glemail.com,
maz@...nel.org, mhiramat@...nel.org, mgorman@...e.de, mhocko@...e.com,
mingo@...hat.com, muchun.song@...ux.dev, neilb@...e.de,
osalvador@...e.de, pcc@...gle.com, peterz@...radead.org,
pfalcato@...e.de, rostedt@...dmis.org, rppt@...nel.org,
shakeel.butt@...ux.dev, surenb@...gle.com, tglx@...utronix.de,
vasily.averin@...ux.dev, vbabka@...e.cz, vincent.guittot@...aro.org,
viro@...iv.linux.org.uk, vschneid@...hat.com, willy@...radead.org,
x86@...nel.org, xhao@...ux.alibaba.com, linux-doc@...r.kernel.org,
linux-kernel@...r.kernel.org, linux-arch@...r.kernel.org
Subject: [PATCH v3 07/22] mm/mshare: Add mmap support
From: Khalid Aziz <khalid@...nel.org>
Add support for mapping an mshare region into a process after the
region has been established in msharefs. Disallow operations that
could split the resulting msharefs vma such as partial unmaps and
protection changes. Fault handling, mapping, unmapping, and
protection changes for objects mapped into an mshare region will
be done using the shared vmas created for them in the host mm. This
functionality will be added in later patches.
Signed-off-by: Khalid Aziz <khalid@...nel.org>
Signed-off-by: Anthony Yznaga <anthony.yznaga@...cle.com>
---
mm/mshare.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 132 insertions(+), 1 deletion(-)
diff --git a/mm/mshare.c b/mm/mshare.c
index bf859b176e09..e0dc42602f7f 100644
--- a/mm/mshare.c
+++ b/mm/mshare.c
@@ -15,16 +15,19 @@
#include <linux/fs.h>
#include <linux/fs_context.h>
+#include <linux/mman.h>
#include <uapi/linux/magic.h>
#include <linux/falloc.h>
const unsigned long mshare_align = P4D_SIZE;
+const unsigned long mshare_base = mshare_align;
#define MSHARE_INITIALIZED 0x1
struct mshare_data {
struct mm_struct *mm;
refcount_t ref;
+ unsigned long start;
unsigned long size;
unsigned long flags;
};
@@ -34,6 +37,130 @@ static inline bool mshare_is_initialized(struct mshare_data *m_data)
return test_bit(MSHARE_INITIALIZED, &m_data->flags);
}
+static int mshare_vm_op_split(struct vm_area_struct *vma, unsigned long addr)
+{
+ return -EINVAL;
+}
+
+static int mshare_vm_op_mprotect(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end, unsigned long newflags)
+{
+ return -EINVAL;
+}
+
+static const struct vm_operations_struct msharefs_vm_ops = {
+ .may_split = mshare_vm_op_split,
+ .mprotect = mshare_vm_op_mprotect,
+};
+
+/*
+ * msharefs_mmap() - mmap an mshare region
+ */
+static int
+msharefs_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct mshare_data *m_data = file->private_data;
+
+ vma->vm_private_data = m_data;
+ vm_flags_set(vma, VM_MSHARE | VM_DONTEXPAND);
+ vma->vm_ops = &msharefs_vm_ops;
+
+ return 0;
+}
+
+static unsigned long
+msharefs_get_unmapped_area_bottomup(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+ struct vm_unmapped_area_info info = {};
+
+ info.length = len;
+ info.low_limit = current->mm->mmap_base;
+ info.high_limit = arch_get_mmap_end(addr, len, flags);
+ info.align_mask = PAGE_MASK & (mshare_align - 1);
+ return vm_unmapped_area(&info);
+}
+
+static unsigned long
+msharefs_get_unmapped_area_topdown(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+ struct vm_unmapped_area_info info = {};
+
+ info.flags = VM_UNMAPPED_AREA_TOPDOWN;
+ info.length = len;
+ info.low_limit = PAGE_SIZE;
+ info.high_limit = arch_get_mmap_base(addr, current->mm->mmap_base);
+ info.align_mask = PAGE_MASK & (mshare_align - 1);
+ addr = vm_unmapped_area(&info);
+
+ /*
+ * A failed mmap() very likely causes application failure,
+ * so fall back to the bottom-up function here. This scenario
+ * can happen with large stack limits and large mmap()
+ * allocations.
+ */
+ if (unlikely(offset_in_page(addr))) {
+ VM_BUG_ON(addr != -ENOMEM);
+ info.flags = 0;
+ info.low_limit = current->mm->mmap_base;
+ info.high_limit = arch_get_mmap_end(addr, len, flags);
+ addr = vm_unmapped_area(&info);
+ }
+
+ return addr;
+}
+
+static unsigned long
+msharefs_get_unmapped_area(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+ struct mshare_data *m_data = file->private_data;
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma, *prev;
+ unsigned long mshare_start, mshare_size;
+ const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags);
+
+ mmap_assert_write_locked(mm);
+
+ if ((flags & MAP_TYPE) == MAP_PRIVATE)
+ return -EINVAL;
+
+ if (!mshare_is_initialized(m_data))
+ return -EINVAL;
+
+ mshare_start = m_data->start;
+ mshare_size = m_data->size;
+
+ if (len != mshare_size)
+ return -EINVAL;
+
+ if (len > mmap_end - mmap_min_addr)
+ return -ENOMEM;
+
+ if (flags & MAP_FIXED) {
+ if (!IS_ALIGNED(addr, mshare_align))
+ return -EINVAL;
+ return addr;
+ }
+
+ if (addr) {
+ addr = ALIGN(addr, mshare_align);
+ vma = find_vma_prev(mm, addr, &prev);
+ if (mmap_end - len >= addr && addr >= mmap_min_addr &&
+ (!vma || addr + len <= vm_start_gap(vma)) &&
+ (!prev || addr >= vm_end_gap(prev)))
+ return addr;
+ }
+
+ if (!mm_flags_test(MMF_TOPDOWN, mm))
+ return msharefs_get_unmapped_area_bottomup(file, addr, len,
+ pgoff, flags);
+ else
+ return msharefs_get_unmapped_area_topdown(file, addr, len,
+ pgoff, flags);
+}
+
static int msharefs_set_size(struct mshare_data *m_data, unsigned long size)
{
int error = -EINVAL;
@@ -87,6 +214,8 @@ static const struct inode_operations msharefs_file_inode_ops;
static const struct file_operations msharefs_file_operations = {
.open = simple_open,
+ .mmap = msharefs_mmap,
+ .get_unmapped_area = msharefs_get_unmapped_area,
.fallocate = msharefs_fallocate,
};
@@ -101,12 +230,14 @@ msharefs_fill_mm(struct inode *inode)
if (!mm)
return -ENOMEM;
- mm->mmap_base = mm->task_size = 0;
+ mm->mmap_base = mshare_base;
+ mm->task_size = 0;
m_data = kzalloc(sizeof(*m_data), GFP_KERNEL);
if (!m_data)
goto err_free;
m_data->mm = mm;
+ m_data->start = mshare_base;
refcount_set(&m_data->ref, 1);
inode->i_private = m_data;
--
2.47.1
Powered by blists - more mailing lists