Selaa lähdekoodia

Kernel: Hoist VM range allocation up to sys$mmap() itself

Instead of letting each File subclass do range allocation in their
mmap() override, do it up front in sys$mmap().

This makes us honor alignment requests for file-backed memory mappings
and simplifies the code somwhat.
Andreas Kling 4 vuotta sitten
vanhempi
commit
ab14b0ac64

+ 3 - 4
Kernel/Devices/BXVGADevice.cpp

@@ -172,19 +172,18 @@ u32 BXVGADevice::find_framebuffer_address()
     return framebuffer_address;
 }
 
-KResultOr<Region*> BXVGADevice::mmap(Process& process, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot, bool shared)
+KResultOr<Region*> BXVGADevice::mmap(Process& process, FileDescription&, const Range& range, size_t offset, int prot, bool shared)
 {
     REQUIRE_PROMISE(video);
     if (!shared)
         return ENODEV;
     ASSERT(offset == 0);
-    ASSERT(size == framebuffer_size_in_bytes());
+    ASSERT(range.size() == framebuffer_size_in_bytes());
     auto vmobject = AnonymousVMObject::create_for_physical_range(m_framebuffer_address, framebuffer_size_in_bytes());
     if (!vmobject)
         return ENOMEM;
     return process.allocate_region_with_vmobject(
-        preferred_vaddr,
-        framebuffer_size_in_bytes(),
+        range,
         vmobject.release_nonnull(),
         0,
         "BXVGA Framebuffer",

+ 1 - 1
Kernel/Devices/BXVGADevice.h

@@ -42,7 +42,7 @@ public:
     BXVGADevice();
 
     virtual int ioctl(FileDescription&, unsigned request, FlatPtr arg) override;
-    virtual KResultOr<Region*> mmap(Process&, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t, int prot, bool shared) override;
+    virtual KResultOr<Region*> mmap(Process&, FileDescription&, const Range&, size_t offset, int prot, bool shared) override;
 
     // ^Device
     virtual mode_t required_mode() const override { return 0660; }

+ 3 - 4
Kernel/Devices/MBVGADevice.cpp

@@ -51,19 +51,18 @@ MBVGADevice::MBVGADevice(PhysicalAddress addr, size_t pitch, size_t width, size_
     s_the = this;
 }
 
-KResultOr<Region*> MBVGADevice::mmap(Process& process, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot, bool shared)
+KResultOr<Region*> MBVGADevice::mmap(Process& process, FileDescription&, const Range& range, size_t offset, int prot, bool shared)
 {
     REQUIRE_PROMISE(video);
     if (!shared)
         return ENODEV;
     ASSERT(offset == 0);
-    ASSERT(size == framebuffer_size_in_bytes());
+    ASSERT(range.size() == framebuffer_size_in_bytes());
     auto vmobject = AnonymousVMObject::create_for_physical_range(m_framebuffer_address, framebuffer_size_in_bytes());
     if (!vmobject)
         return ENOMEM;
     return process.allocate_region_with_vmobject(
-        preferred_vaddr,
-        framebuffer_size_in_bytes(),
+        range,
         vmobject.release_nonnull(),
         0,
         "MBVGA Framebuffer",

+ 1 - 1
Kernel/Devices/MBVGADevice.h

@@ -41,7 +41,7 @@ public:
     MBVGADevice(PhysicalAddress addr, size_t pitch, size_t width, size_t height);
 
     virtual int ioctl(FileDescription&, unsigned request, FlatPtr arg) override;
-    virtual KResultOr<Region*> mmap(Process&, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t, int prot, bool shared) override;
+    virtual KResultOr<Region*> mmap(Process&, FileDescription&, const Range&, size_t offset, int prot, bool shared) override;
 
     // ^Device
     virtual mode_t required_mode() const override { return 0660; }

+ 3 - 3
Kernel/FileSystem/AnonymousFile.cpp

@@ -39,15 +39,15 @@ AnonymousFile::~AnonymousFile()
 {
 }
 
-KResultOr<Region*> AnonymousFile::mmap(Process& process, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot, bool shared)
+KResultOr<Region*> AnonymousFile::mmap(Process& process, FileDescription&, const Range& range, size_t offset, int prot, bool shared)
 {
     if (offset != 0)
         return EINVAL;
 
-    if (size != m_vmobject->size())
+    if (range.size() != m_vmobject->size())
         return EINVAL;
 
-    return process.allocate_region_with_vmobject(preferred_vaddr, size, m_vmobject, offset, {}, prot, shared);
+    return process.allocate_region_with_vmobject(range, m_vmobject, offset, {}, prot, shared);
 }
 
 }

+ 1 - 1
Kernel/FileSystem/AnonymousFile.h

@@ -39,7 +39,7 @@ public:
 
     virtual ~AnonymousFile() override;
 
-    virtual KResultOr<Region*> mmap(Process&, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot, bool shared) override;
+    virtual KResultOr<Region*> mmap(Process&, FileDescription&, const Range&, size_t offset, int prot, bool shared) override;
 
 private:
     virtual const char* class_name() const override { return "AnonymousFile"; }

+ 1 - 1
Kernel/FileSystem/File.cpp

@@ -59,7 +59,7 @@ int File::ioctl(FileDescription&, unsigned, FlatPtr)
     return -ENOTTY;
 }
 
-KResultOr<Region*> File::mmap(Process&, FileDescription&, VirtualAddress, size_t, size_t, int, bool)
+KResultOr<Region*> File::mmap(Process&, FileDescription&, const Range&, size_t, int, bool)
 {
     return ENODEV;
 }

+ 1 - 1
Kernel/FileSystem/File.h

@@ -114,7 +114,7 @@ public:
     virtual KResultOr<size_t> read(FileDescription&, size_t, UserOrKernelBuffer&, size_t) = 0;
     virtual KResultOr<size_t> write(FileDescription&, size_t, const UserOrKernelBuffer&, size_t) = 0;
     virtual int ioctl(FileDescription&, unsigned request, FlatPtr arg);
-    virtual KResultOr<Region*> mmap(Process&, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot, bool shared);
+    virtual KResultOr<Region*> mmap(Process&, FileDescription&, const Range&, size_t offset, int prot, bool shared);
     virtual KResult stat(::stat&) const { return EBADF; }
 
     virtual String absolute_path(const FileDescription&) const = 0;

+ 2 - 2
Kernel/FileSystem/FileDescription.cpp

@@ -328,10 +328,10 @@ InodeMetadata FileDescription::metadata() const
     return {};
 }
 
-KResultOr<Region*> FileDescription::mmap(Process& process, VirtualAddress vaddr, size_t offset, size_t size, int prot, bool shared)
+KResultOr<Region*> FileDescription::mmap(Process& process, const Range& range, size_t offset, int prot, bool shared)
 {
     LOCKER(m_lock);
-    return m_file->mmap(process, *this, vaddr, offset, size, prot, shared);
+    return m_file->mmap(process, *this, range, offset, prot, shared);
 }
 
 KResult FileDescription::truncate(u64 length)

+ 1 - 1
Kernel/FileSystem/FileDescription.h

@@ -108,7 +108,7 @@ public:
     Custody* custody() { return m_custody.ptr(); }
     const Custody* custody() const { return m_custody.ptr(); }
 
-    KResultOr<Region*> mmap(Process&, VirtualAddress, size_t offset, size_t, int prot, bool shared);
+    KResultOr<Region*> mmap(Process&, const Range&, size_t offset, int prot, bool shared);
 
     bool is_blocking() const { return m_is_blocking; }
     void set_blocking(bool b) { m_is_blocking = b; }

+ 2 - 2
Kernel/FileSystem/InodeFile.cpp

@@ -69,7 +69,7 @@ KResultOr<size_t> InodeFile::write(FileDescription& description, size_t offset,
     return nwritten;
 }
 
-KResultOr<Region*> InodeFile::mmap(Process& process, FileDescription& description, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot, bool shared)
+KResultOr<Region*> InodeFile::mmap(Process& process, FileDescription& description, const Range& range, size_t offset, int prot, bool shared)
 {
     // FIXME: If PROT_EXEC, check that the underlying file system isn't mounted noexec.
     RefPtr<InodeVMObject> vmobject;
@@ -79,7 +79,7 @@ KResultOr<Region*> InodeFile::mmap(Process& process, FileDescription& descriptio
         vmobject = PrivateInodeVMObject::create_with_inode(inode());
     if (!vmobject)
         return ENOMEM;
-    return process.allocate_region_with_vmobject(preferred_vaddr, size, *vmobject, offset, description.absolute_path(), prot, shared);
+    return process.allocate_region_with_vmobject(range, vmobject.release_nonnull(), offset, description.absolute_path(), prot, shared);
 }
 
 String InodeFile::absolute_path(const FileDescription& description) const

+ 1 - 1
Kernel/FileSystem/InodeFile.h

@@ -49,7 +49,7 @@ public:
 
     virtual KResultOr<size_t> read(FileDescription&, size_t, UserOrKernelBuffer&, size_t) override;
     virtual KResultOr<size_t> write(FileDescription&, size_t, const UserOrKernelBuffer&, size_t) override;
-    virtual KResultOr<Region*> mmap(Process&, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot, bool shared) override;
+    virtual KResultOr<Region*> mmap(Process&, FileDescription&, const Range&, size_t offset, int prot, bool shared) override;
 
     virtual String absolute_path(const FileDescription&) const override;
 

+ 6 - 14
Kernel/Syscalls/mmap.cpp

@@ -133,16 +133,13 @@ void* Process::sys$mmap(Userspace<const Syscall::SC_mmap_params*> user_params)
         return (void*)-EINVAL;
 
     Region* region = nullptr;
-    Optional<Range> range;
-    if (map_noreserve || map_anonymous) {
-        range = allocate_range(VirtualAddress(addr), size, alignment);
-        if (!range.value().is_valid())
-            return (void*)-ENOMEM;
-    }
+    auto range = allocate_range(VirtualAddress(addr), size, alignment);
+    if (!range.is_valid())
+        return (void*)-ENOMEM;
 
     if (map_anonymous) {
         auto strategy = map_noreserve ? AllocationStrategy::None : AllocationStrategy::Reserve;
-        auto region_or_error = allocate_region(range.value(), !name.is_null() ? name : "mmap", prot, strategy);
+        auto region_or_error = allocate_region(range, !name.is_null() ? name : "mmap", prot, strategy);
         if (region_or_error.is_error() && (!map_fixed && addr != 0))
             region_or_error = allocate_region(allocate_range({}, size), !name.is_null() ? name : "mmap", prot, strategy);
         if (region_or_error.is_error())
@@ -169,13 +166,8 @@ void* Process::sys$mmap(Userspace<const Syscall::SC_mmap_params*> user_params)
             if (!validate_inode_mmap_prot(*this, prot, *description->inode(), map_shared))
                 return (void*)-EACCES;
         }
-        auto region_or_error = description->mmap(*this, VirtualAddress(addr), static_cast<size_t>(offset), size, prot, map_shared);
-        if (region_or_error.is_error()) {
-            // Fail if MAP_FIXED or address is 0, retry otherwise
-            if (map_fixed || addr == 0)
-                return (void*)region_or_error.error().error();
-            region_or_error = description->mmap(*this, {}, static_cast<size_t>(offset), size, prot, map_shared);
-        }
+
+        auto region_or_error = description->mmap(*this, range, static_cast<size_t>(offset), prot, map_shared);
         if (region_or_error.is_error())
             return (void*)region_or_error.error().error();
         region = region_or_error.value();