From 9b6464010f939893bdf7862e206f1704c5185cb6 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 13 Jul 2020 11:58:58 +0200 Subject: [PATCH] UserspaceEmulator: Add basic support for memory-mapped files MmapRegion now supports using an mmap'ed file descriptor as backing. --- DevTools/UserspaceEmulator/Emulator.cpp | 6 ++++-- DevTools/UserspaceEmulator/MmapRegion.cpp | 23 +++++++++++++++++++++-- DevTools/UserspaceEmulator/MmapRegion.h | 6 +++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/DevTools/UserspaceEmulator/Emulator.cpp b/DevTools/UserspaceEmulator/Emulator.cpp index a1dca6bc5c..8fdad15d16 100644 --- a/DevTools/UserspaceEmulator/Emulator.cpp +++ b/DevTools/UserspaceEmulator/Emulator.cpp @@ -309,7 +309,6 @@ u32 Emulator::virt$mmap(u32 params_addr) mmu().copy_from_vm(¶ms, params_addr, sizeof(params)); ASSERT(params.addr == 0); - ASSERT(params.flags & MAP_ANONYMOUS); // FIXME: Write a proper VM allocator static u32 next_address = 0x30000000; @@ -326,7 +325,10 @@ u32 Emulator::virt$mmap(u32 params_addr) next_address = final_address + final_size; - mmu().add_region(make(final_address, final_size, params.prot)); + if (params.flags & MAP_ANONYMOUS) + mmu().add_region(MmapRegion::create_anonymous(final_address, final_size, params.prot)); + else + mmu().add_region(MmapRegion::create_file_backed(final_address, final_size, params.prot, params.flags, params.fd, params.offset)); return final_address; } diff --git a/DevTools/UserspaceEmulator/MmapRegion.cpp b/DevTools/UserspaceEmulator/MmapRegion.cpp index 9ea41752e1..18c65f1e0d 100644 --- a/DevTools/UserspaceEmulator/MmapRegion.cpp +++ b/DevTools/UserspaceEmulator/MmapRegion.cpp @@ -30,16 +30,35 @@ namespace UserspaceEmulator { +NonnullOwnPtr MmapRegion::create_anonymous(u32 base, u32 size, u32 prot) +{ + auto region = adopt_own(*new MmapRegion(base, size, prot)); + region->m_file_backed = false; + region->m_data = (u8*)calloc(1, size); + return region; +} + +NonnullOwnPtr MmapRegion::create_file_backed(u32 base, u32 size, u32 prot, int flags, int fd, off_t offset) +{ + auto region = adopt_own(*new MmapRegion(base, size, prot)); + region->m_file_backed = true; + region->m_data = (u8*)mmap(nullptr, size, prot, flags, fd, offset); + ASSERT(region->m_data != MAP_FAILED); + return region; +} + MmapRegion::MmapRegion(u32 base, u32 size, int prot) : Region(base, size) , m_prot(prot) { - m_data = (u8*)calloc(1, size); } MmapRegion::~MmapRegion() { - free(m_data); + if (m_file_backed) + munmap(m_data, size()); + else + free(m_data); } u8 MmapRegion::read8(FlatPtr offset) diff --git a/DevTools/UserspaceEmulator/MmapRegion.h b/DevTools/UserspaceEmulator/MmapRegion.h index ed2c8f91ce..d88e325f0a 100644 --- a/DevTools/UserspaceEmulator/MmapRegion.h +++ b/DevTools/UserspaceEmulator/MmapRegion.h @@ -33,7 +33,8 @@ namespace UserspaceEmulator { class MmapRegion final : public SoftMMU::Region { public: - MmapRegion(u32 base, u32 size, int prot); + static NonnullOwnPtr create_anonymous(u32 base, u32 size, u32 prot); + static NonnullOwnPtr create_file_backed(u32 base, u32 size, u32 prot, int flags, int fd, off_t offset); virtual ~MmapRegion() override; virtual u8 read8(u32 offset) override; @@ -51,8 +52,11 @@ public: bool is_executable() const { return m_prot & PROT_EXEC; } private: + MmapRegion(u32 base, u32 size, int prot); + u8* m_data { nullptr }; int m_prot { 0 }; + bool m_file_backed { false }; }; }