Compare commits
No commits in common. "7293d47bf08d74e24530f82b3a84725af57a83f7" and "3aaf1c5d842d9e305b6e95b17f7f8511be345cf7" have entirely different histories.
7293d47bf0
...
3aaf1c5d84
@ -45,4 +45,3 @@ luna_app(buffer-test.cpp buffer-test)
|
|||||||
luna_app(socket-test.cpp socket-test)
|
luna_app(socket-test.cpp socket-test)
|
||||||
luna_app(socket-client.cpp socket-client)
|
luna_app(socket-client.cpp socket-client)
|
||||||
luna_app(input.cpp input)
|
luna_app(input.cpp input)
|
||||||
luna_app(shmem-test.cpp shmem-test)
|
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
void* address = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
|
|
||||||
if (address == MAP_FAILED)
|
|
||||||
{
|
|
||||||
perror("mmap");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int* ptr = (int*)address;
|
|
||||||
*ptr = 16;
|
|
||||||
|
|
||||||
pid_t child = fork();
|
|
||||||
if (child < 0)
|
|
||||||
{
|
|
||||||
perror("fork");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (child == 0)
|
|
||||||
{
|
|
||||||
*ptr = 32;
|
|
||||||
_exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
waitpid(child, NULL, 0);
|
|
||||||
|
|
||||||
printf("the value is %d\n", *ptr);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -14,7 +14,6 @@ set(SOURCES
|
|||||||
src/memory/KernelVM.cpp
|
src/memory/KernelVM.cpp
|
||||||
src/memory/AddressSpace.cpp
|
src/memory/AddressSpace.cpp
|
||||||
src/memory/MemoryMap.cpp
|
src/memory/MemoryMap.cpp
|
||||||
src/memory/SharedMemory.cpp
|
|
||||||
src/boot/Init.cpp
|
src/boot/Init.cpp
|
||||||
src/arch/Serial.cpp
|
src/arch/Serial.cpp
|
||||||
src/arch/Timer.cpp
|
src/arch/Timer.cpp
|
||||||
|
@ -29,15 +29,15 @@ namespace MMU
|
|||||||
|
|
||||||
u64 translate_physical_address(u64 phys);
|
u64 translate_physical_address(u64 phys);
|
||||||
|
|
||||||
|
Result<void> map(u64 virt, u64 phys, int flags, UseHugePages use_huge_pages);
|
||||||
|
Result<u64> unmap(u64 virt);
|
||||||
|
Result<u64> get_physical(u64 virt);
|
||||||
|
Result<int> get_flags(u64 virt);
|
||||||
|
Result<void> remap(u64 virt, int flags);
|
||||||
|
|
||||||
void switch_page_directory(PageDirectory* dir);
|
void switch_page_directory(PageDirectory* dir);
|
||||||
PageDirectory* get_page_directory();
|
PageDirectory* get_page_directory();
|
||||||
|
|
||||||
Result<void> map(u64 virt, u64 phys, int flags, UseHugePages use_huge_pages, PageDirectory* directory = nullptr);
|
|
||||||
Result<u64> unmap(u64 virt, PageDirectory* directory = nullptr);
|
|
||||||
Result<u64> get_physical(u64 virt, PageDirectory* directory = nullptr);
|
|
||||||
Result<int> get_flags(u64 virt, PageDirectory* directory = nullptr);
|
|
||||||
Result<void> remap(u64 virt, int flags);
|
|
||||||
|
|
||||||
void flush_all();
|
void flush_all();
|
||||||
|
|
||||||
Result<PageDirectory*> create_page_directory_for_userspace();
|
Result<PageDirectory*> create_page_directory_for_userspace();
|
||||||
|
@ -110,11 +110,10 @@ namespace MMU
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PageTableEntry& l4_entry(u64 virt, PageDirectory* directory = nullptr)
|
PageTableEntry& l4_entry(u64 virt)
|
||||||
{
|
{
|
||||||
auto index = l4_index(virt);
|
auto index = l4_index(virt);
|
||||||
auto* vdir = directory ? translate_physical(directory) : get_virtual_page_directory();
|
return get_virtual_page_directory()->entries[index];
|
||||||
return vdir->entries[index];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PageDirectory& page_table(const PageTableEntry& entry)
|
PageDirectory& page_table(const PageTableEntry& entry)
|
||||||
@ -140,9 +139,9 @@ namespace MMU
|
|||||||
return page_table(entry).entries[index];
|
return page_table(entry).entries[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<PageTableEntry*> find_entry(u64 virt, PageDirectory* directory = nullptr)
|
Result<PageTableEntry*> find_entry(u64 virt)
|
||||||
{
|
{
|
||||||
const auto& l4 = l4_entry(virt, directory);
|
const auto& l4 = l4_entry(virt);
|
||||||
if (!l4.present) return err(EFAULT);
|
if (!l4.present) return err(EFAULT);
|
||||||
auto& l3 = l3_entry(l4, virt);
|
auto& l3 = l3_entry(l4, virt);
|
||||||
if (!l3.present) return err(EFAULT);
|
if (!l3.present) return err(EFAULT);
|
||||||
@ -153,9 +152,9 @@ namespace MMU
|
|||||||
return &l1_entry(l2, virt);
|
return &l1_entry(l2, virt);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<PageTableEntry*> apply_cascading_flags(u64 virt, int flags, PageDirectory* directory = nullptr)
|
Result<PageTableEntry*> apply_cascading_flags(u64 virt, int flags)
|
||||||
{
|
{
|
||||||
auto& l4 = l4_entry(virt, directory);
|
auto& l4 = l4_entry(virt);
|
||||||
if (!l4.present) return err(EFAULT);
|
if (!l4.present) return err(EFAULT);
|
||||||
if (flags & Flags::ReadWrite) l4.read_write = true;
|
if (flags & Flags::ReadWrite) l4.read_write = true;
|
||||||
if (flags & Flags::User) l4.user = true;
|
if (flags & Flags::User) l4.user = true;
|
||||||
@ -184,9 +183,9 @@ namespace MMU
|
|||||||
entry.set_address(phys);
|
entry.set_address(phys);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> map(u64 virt, u64 phys, int flags, UseHugePages use_huge_pages, PageDirectory* directory)
|
Result<void> map(u64 virt, u64 phys, int flags, UseHugePages use_huge_pages)
|
||||||
{
|
{
|
||||||
auto& l4 = l4_entry(virt, directory);
|
auto& l4 = l4_entry(virt);
|
||||||
if (!l4.present)
|
if (!l4.present)
|
||||||
{
|
{
|
||||||
const u64 addr = TRY(MemoryManager::alloc_frame());
|
const u64 addr = TRY(MemoryManager::alloc_frame());
|
||||||
@ -253,9 +252,9 @@ namespace MMU
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<u64> unmap(u64 virt, PageDirectory* directory)
|
Result<u64> unmap(u64 virt)
|
||||||
{
|
{
|
||||||
auto& l1 = *TRY(find_entry(virt, directory));
|
auto& l1 = *TRY(find_entry(virt));
|
||||||
if (!l1.present) return err(EFAULT);
|
if (!l1.present) return err(EFAULT);
|
||||||
const u64 address = l1.get_address();
|
const u64 address = l1.get_address();
|
||||||
l1.clear();
|
l1.clear();
|
||||||
@ -263,16 +262,16 @@ namespace MMU
|
|||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<u64> get_physical(u64 virt, PageDirectory* directory)
|
Result<u64> get_physical(u64 virt)
|
||||||
{
|
{
|
||||||
const auto& l1 = *TRY(find_entry(virt, directory));
|
const auto& l1 = *TRY(find_entry(virt));
|
||||||
if (!l1.present) return err(EFAULT);
|
if (!l1.present) return err(EFAULT);
|
||||||
return l1.get_address();
|
return l1.get_address();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<int> get_flags(u64 virt, PageDirectory* directory)
|
Result<int> get_flags(u64 virt)
|
||||||
{
|
{
|
||||||
const auto& l1 = *TRY(find_entry(virt, directory));
|
const auto& l1 = *TRY(find_entry(virt));
|
||||||
if (!l1.present) return err(EFAULT);
|
if (!l1.present) return err(EFAULT);
|
||||||
return arch_flags_to_mmu(l1);
|
return arch_flags_to_mmu(l1);
|
||||||
}
|
}
|
||||||
@ -441,8 +440,12 @@ namespace MMU
|
|||||||
|
|
||||||
for (u64 l = 0; l < 512; l++)
|
for (u64 l = 0; l < 512; l++)
|
||||||
{
|
{
|
||||||
|
PageTableEntry& old_l1 = old_pt->entries[l];
|
||||||
|
if (!old_l1.present) continue;
|
||||||
PageTableEntry& new_l1 = new_pt->entries[l];
|
PageTableEntry& new_l1 = new_pt->entries[l];
|
||||||
new_l1.present = false; // The entry must be filled in by the caller.
|
new_l1.set_address(TRY(MemoryManager::alloc_frame()));
|
||||||
|
|
||||||
|
memcpy(&page_table(new_l1), &page_table(old_l1), ARCH_PAGE_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include "arch/CPU.h"
|
#include "arch/CPU.h"
|
||||||
#include "arch/MMU.h"
|
#include "arch/MMU.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include <bits/mmap-flags.h>
|
|
||||||
#include <luna/Alignment.h>
|
#include <luna/Alignment.h>
|
||||||
#include <luna/Alloc.h>
|
#include <luna/Alloc.h>
|
||||||
#include <luna/CString.h>
|
#include <luna/CString.h>
|
||||||
@ -109,13 +108,8 @@ Result<u64> ELFLoader::load(AddressSpace* space)
|
|||||||
if (can_write_segment(program_header.p_flags)) flags |= MMU::ReadWrite;
|
if (can_write_segment(program_header.p_flags)) flags |= MMU::ReadWrite;
|
||||||
if (can_execute_segment(program_header.p_flags)) flags &= ~MMU::NoExecute;
|
if (can_execute_segment(program_header.p_flags)) flags &= ~MMU::NoExecute;
|
||||||
|
|
||||||
int prot = PROT_READ;
|
|
||||||
if (can_write_segment(program_header.p_flags)) prot |= PROT_WRITE;
|
|
||||||
if (can_execute_segment(program_header.p_flags)) prot |= PROT_EXEC;
|
|
||||||
|
|
||||||
if (!TRY(space->test_and_alloc_region(
|
if (!TRY(space->test_and_alloc_region(
|
||||||
base_vaddr, get_blocks_from_size(program_header.p_memsz + vaddr_diff, ARCH_PAGE_SIZE), prot,
|
base_vaddr, get_blocks_from_size(program_header.p_memsz + vaddr_diff, ARCH_PAGE_SIZE), true)))
|
||||||
MAP_ANONYMOUS | MAP_PRIVATE, 0, true)))
|
|
||||||
return err(ENOMEM);
|
return err(ENOMEM);
|
||||||
|
|
||||||
// Allocate physical memory for the segment
|
// Allocate physical memory for the segment
|
||||||
|
@ -113,11 +113,6 @@ namespace VFS
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Result<u64> query_shared_memory(off_t, usize)
|
|
||||||
{
|
|
||||||
return err(EACCES);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Directory-specific methods
|
// Directory-specific methods
|
||||||
virtual Result<SharedPtr<Inode>> find(const char* name) const = 0;
|
virtual Result<SharedPtr<Inode>> find(const char* name) const = 0;
|
||||||
|
|
||||||
@ -191,7 +186,6 @@ namespace VFS
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
mutable InodeMetadata m_metadata;
|
mutable InodeMetadata m_metadata;
|
||||||
Option<u64> m_shmid {};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileInode : public Inode
|
class FileInode : public Inode
|
||||||
|
@ -34,11 +34,6 @@ namespace Ext2
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<u64> query_shared_memory(off_t, usize) override
|
|
||||||
{
|
|
||||||
return err(ENOTSUP);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> set_metadata(const VFS::InodeMetadata&) override
|
Result<void> set_metadata(const VFS::InodeMetadata&) override
|
||||||
{
|
{
|
||||||
return err(EROFS);
|
return err(EROFS);
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
#include "fs/tmpfs/Inode.h"
|
#include "fs/tmpfs/Inode.h"
|
||||||
#include "arch/MMU.h"
|
|
||||||
#include "memory/SharedMemory.h"
|
|
||||||
|
|
||||||
namespace TmpFS
|
namespace TmpFS
|
||||||
{
|
{
|
||||||
@ -129,28 +127,4 @@ namespace TmpFS
|
|||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<u64> FileInode::query_shared_memory(off_t offset, usize count)
|
|
||||||
{
|
|
||||||
if (offset + (count * ARCH_PAGE_SIZE) > m_data_buffer.size()) return err(EINVAL);
|
|
||||||
|
|
||||||
if (!m_shmid.has_value())
|
|
||||||
{
|
|
||||||
u64 shmid = TRY(SharedMemory::create(m_data_buffer.data() + offset, offset, count));
|
|
||||||
m_shmid = shmid;
|
|
||||||
return shmid;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* shm = g_shared_memory_map.try_get_ref(*m_shmid);
|
|
||||||
if (shm->offset > offset)
|
|
||||||
{
|
|
||||||
TRY(shm->grow_backward(m_data_buffer.data() + offset, (shm->offset - offset) / ARCH_PAGE_SIZE));
|
|
||||||
}
|
|
||||||
if (shm->frames.size() < count)
|
|
||||||
{
|
|
||||||
TRY(shm->grow_forward(m_data_buffer.data() + offset + (shm->frames.size() * ARCH_PAGE_SIZE),
|
|
||||||
count - shm->frames.size()));
|
|
||||||
}
|
|
||||||
return *m_shmid;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,6 @@ namespace TmpFS
|
|||||||
|
|
||||||
Result<void> truncate(usize size) override;
|
Result<void> truncate(usize size) override;
|
||||||
|
|
||||||
Result<u64> query_shared_memory(off_t offset, usize count) override;
|
|
||||||
|
|
||||||
void did_link() override
|
void did_link() override
|
||||||
{
|
{
|
||||||
m_metadata.nlinks++;
|
m_metadata.nlinks++;
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
#include "memory/AddressSpace.h"
|
#include "memory/AddressSpace.h"
|
||||||
|
#include "Log.h"
|
||||||
#include "arch/MMU.h"
|
#include "arch/MMU.h"
|
||||||
#include "memory/Heap.h"
|
#include "memory/Heap.h"
|
||||||
#include "memory/MemoryManager.h"
|
|
||||||
#include "memory/SharedMemory.h"
|
|
||||||
#include <bits/mmap-flags.h>
|
|
||||||
#include <luna/CString.h>
|
#include <luna/CString.h>
|
||||||
#include <luna/ScopeGuard.h>
|
#include <luna/ScopeGuard.h>
|
||||||
|
|
||||||
@ -51,26 +49,15 @@ Result<OwnedPtr<AddressSpace>> AddressSpace::clone()
|
|||||||
{
|
{
|
||||||
OwnedPtr<AddressSpace> ptr = TRY(make_owned<AddressSpace>());
|
OwnedPtr<AddressSpace> ptr = TRY(make_owned<AddressSpace>());
|
||||||
|
|
||||||
ptr->m_directory = TRY(MMU::clone_userspace_page_directory(m_directory));
|
|
||||||
|
|
||||||
for (const auto* region : m_regions)
|
for (const auto* region : m_regions)
|
||||||
{
|
{
|
||||||
auto* new_region = TRY(make<VMRegion>());
|
auto* new_region = TRY(make<VMRegion>());
|
||||||
memcpy(new_region, region, sizeof(*region));
|
memcpy(new_region, region, sizeof(*region));
|
||||||
ptr->m_regions.append(new_region);
|
ptr->m_regions.append(new_region);
|
||||||
|
|
||||||
if (new_region->used && new_region->prot != 0 && new_region->flags & MAP_SHARED)
|
|
||||||
{
|
|
||||||
TRY(MemoryManager::copy_region(new_region->start, new_region->count, m_directory, ptr->m_directory));
|
|
||||||
auto* shm = g_shared_memory_map.try_get_ref(new_region->shmid);
|
|
||||||
if (shm) shm->refs++;
|
|
||||||
}
|
|
||||||
else if (new_region->used && new_region->prot != 0)
|
|
||||||
{
|
|
||||||
TRY(MemoryManager::copy_region_data(new_region->start, new_region->count, m_directory, ptr->m_directory));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ptr->m_directory = TRY(MMU::clone_userspace_page_directory(m_directory));
|
||||||
|
|
||||||
return move(ptr);
|
return move(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,16 +81,8 @@ AddressSpace& AddressSpace::operator=(AddressSpace&& other)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<u64> AddressSpace::alloc_region(usize count, int prot, int flags, u64 shmid, bool persistent)
|
Result<u64> AddressSpace::alloc_region(usize count, bool persistent)
|
||||||
{
|
{
|
||||||
auto update_region = [=](VMRegion* region) {
|
|
||||||
region->used = true;
|
|
||||||
region->persistent = persistent;
|
|
||||||
region->prot = prot;
|
|
||||||
region->flags = flags;
|
|
||||||
region->shmid = shmid;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (auto* region = m_regions.expect_last(); region; region = m_regions.previous(region).value_or(nullptr))
|
for (auto* region = m_regions.expect_last(); region; region = m_regions.previous(region).value_or(nullptr))
|
||||||
{
|
{
|
||||||
if (!region->used)
|
if (!region->used)
|
||||||
@ -111,7 +90,8 @@ Result<u64> AddressSpace::alloc_region(usize count, int prot, int flags, u64 shm
|
|||||||
if (region->count < count) continue;
|
if (region->count < count) continue;
|
||||||
if (region->count == count)
|
if (region->count == count)
|
||||||
{
|
{
|
||||||
update_region(region);
|
region->used = true;
|
||||||
|
region->persistent = persistent;
|
||||||
u64 address = region->start;
|
u64 address = region->start;
|
||||||
try_merge_region_with_neighbors(region);
|
try_merge_region_with_neighbors(region);
|
||||||
return address;
|
return address;
|
||||||
@ -120,7 +100,8 @@ Result<u64> AddressSpace::alloc_region(usize count, int prot, int flags, u64 shm
|
|||||||
u64 boundary = region->end - (count * ARCH_PAGE_SIZE);
|
u64 boundary = region->end - (count * ARCH_PAGE_SIZE);
|
||||||
|
|
||||||
auto* new_region = TRY(split_region(region, boundary));
|
auto* new_region = TRY(split_region(region, boundary));
|
||||||
update_region(new_region);
|
new_region->used = true;
|
||||||
|
new_region->persistent = persistent;
|
||||||
try_merge_region_with_neighbors(new_region);
|
try_merge_region_with_neighbors(new_region);
|
||||||
|
|
||||||
return boundary;
|
return boundary;
|
||||||
@ -130,22 +111,12 @@ Result<u64> AddressSpace::alloc_region(usize count, int prot, int flags, u64 shm
|
|||||||
return err(ENOMEM);
|
return err(ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<bool> AddressSpace::set_region(u64 address, usize count, bool used, int prot, int flags, u64 shmid,
|
Result<bool> AddressSpace::set_region(u64 address, usize count, bool used, bool persistent)
|
||||||
bool persistent)
|
|
||||||
{
|
{
|
||||||
if (address >= VM_END) return err(EINVAL);
|
if (address >= VM_END) return err(EINVAL);
|
||||||
|
|
||||||
u64 end = address + (count * ARCH_PAGE_SIZE);
|
u64 end = address + (count * ARCH_PAGE_SIZE);
|
||||||
|
|
||||||
auto update_region = [=](VMRegion* region) {
|
|
||||||
if (!used) region->cleanup_shared();
|
|
||||||
region->used = used;
|
|
||||||
region->persistent = persistent;
|
|
||||||
region->prot = prot;
|
|
||||||
region->flags = flags;
|
|
||||||
region->shmid = shmid;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (auto* region : m_regions)
|
for (auto* region : m_regions)
|
||||||
{
|
{
|
||||||
if (region->end < address) continue;
|
if (region->end < address) continue;
|
||||||
@ -160,13 +131,13 @@ Result<bool> AddressSpace::set_region(u64 address, usize count, bool used, int p
|
|||||||
|
|
||||||
if (region->start >= address && region->end <= end)
|
if (region->start >= address && region->end <= end)
|
||||||
{
|
{
|
||||||
update_region(region);
|
region->used = used;
|
||||||
|
region->persistent = persistent;
|
||||||
if (region->start == address && region->end == end)
|
if (region->start == address && region->end == end)
|
||||||
{
|
{
|
||||||
try_merge_region_with_neighbors(region);
|
try_merge_region_with_neighbors(region);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
try_merge_region_with_neighbors(region);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +145,8 @@ Result<bool> AddressSpace::set_region(u64 address, usize count, bool used, int p
|
|||||||
{
|
{
|
||||||
auto* middle_region = TRY(split_region(region, address));
|
auto* middle_region = TRY(split_region(region, address));
|
||||||
TRY(split_region(middle_region, end));
|
TRY(split_region(middle_region, end));
|
||||||
update_region(middle_region);
|
middle_region->used = used;
|
||||||
|
middle_region->persistent = persistent;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +154,8 @@ Result<bool> AddressSpace::set_region(u64 address, usize count, bool used, int p
|
|||||||
{
|
{
|
||||||
bool finished = region->end == end;
|
bool finished = region->end == end;
|
||||||
auto* split = TRY(split_region(region, address));
|
auto* split = TRY(split_region(region, address));
|
||||||
update_region(split);
|
split->used = used;
|
||||||
|
split->persistent = persistent;
|
||||||
try_merge_region_with_neighbors(split);
|
try_merge_region_with_neighbors(split);
|
||||||
if (!finished) continue;
|
if (!finished) continue;
|
||||||
return true;
|
return true;
|
||||||
@ -191,7 +164,8 @@ Result<bool> AddressSpace::set_region(u64 address, usize count, bool used, int p
|
|||||||
if (region->end > end)
|
if (region->end > end)
|
||||||
{
|
{
|
||||||
TRY(split_region(region, end));
|
TRY(split_region(region, end));
|
||||||
update_region(region);
|
region->used = used;
|
||||||
|
region->persistent = persistent;
|
||||||
try_merge_region_with_neighbors(region);
|
try_merge_region_with_neighbors(region);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -210,24 +184,18 @@ void AddressSpace::merge_contiguous_regions(VMRegion* a, VMRegion* b)
|
|||||||
|
|
||||||
void AddressSpace::try_merge_region_with_neighbors(VMRegion* region)
|
void AddressSpace::try_merge_region_with_neighbors(VMRegion* region)
|
||||||
{
|
{
|
||||||
auto equals = [](VMRegion* a, VMRegion* b) {
|
|
||||||
if (a->used != b->used) return false;
|
|
||||||
if (a->persistent != b->persistent) return false;
|
|
||||||
if (a->prot != b->prot) return false;
|
|
||||||
if (a->flags != b->flags) return false;
|
|
||||||
if (a->shmid != b->shmid) return false;
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto prev = m_regions.previous(region);
|
auto prev = m_regions.previous(region);
|
||||||
if (prev.has_value() && equals(*prev, region))
|
if (prev.has_value() && (*prev)->used == region->used && (*prev)->persistent == region->persistent)
|
||||||
{
|
{
|
||||||
merge_contiguous_regions(*prev, region);
|
merge_contiguous_regions(*prev, region);
|
||||||
region = *prev;
|
region = *prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto next = m_regions.next(region);
|
auto next = m_regions.next(region);
|
||||||
if (next.has_value() && equals(*next, region)) { merge_contiguous_regions(region, *next); }
|
if (next.has_value() && (*next)->used == region->used && (*next)->persistent == region->persistent)
|
||||||
|
{
|
||||||
|
merge_contiguous_regions(region, *next);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<VMRegion*> AddressSpace::split_region(VMRegion* parent, u64 boundary)
|
Result<VMRegion*> AddressSpace::split_region(VMRegion* parent, u64 boundary)
|
||||||
@ -239,9 +207,6 @@ Result<VMRegion*> AddressSpace::split_region(VMRegion* parent, u64 boundary)
|
|||||||
region->count = (region->end - region->start) / ARCH_PAGE_SIZE;
|
region->count = (region->end - region->start) / ARCH_PAGE_SIZE;
|
||||||
region->used = parent->used;
|
region->used = parent->used;
|
||||||
region->persistent = parent->persistent;
|
region->persistent = parent->persistent;
|
||||||
region->prot = parent->prot;
|
|
||||||
region->flags = parent->flags;
|
|
||||||
region->shmid = parent->shmid;
|
|
||||||
m_regions.add_after(parent, region);
|
m_regions.add_after(parent, region);
|
||||||
|
|
||||||
parent->end = boundary;
|
parent->end = boundary;
|
||||||
@ -252,30 +217,6 @@ Result<VMRegion*> AddressSpace::split_region(VMRegion* parent, u64 boundary)
|
|||||||
|
|
||||||
AddressSpace::~AddressSpace()
|
AddressSpace::~AddressSpace()
|
||||||
{
|
{
|
||||||
auto* directory = MMU::get_page_directory();
|
m_regions.consume([](VMRegion* region) { delete region; });
|
||||||
MMU::switch_page_directory(this->m_directory);
|
|
||||||
m_regions.consume([this](VMRegion* region) {
|
|
||||||
region->cleanup_shared();
|
|
||||||
delete region;
|
|
||||||
});
|
|
||||||
MMU::switch_page_directory(directory);
|
|
||||||
|
|
||||||
if (m_directory) MMU::delete_userspace_page_directory(m_directory);
|
if (m_directory) MMU::delete_userspace_page_directory(m_directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VMRegion::cleanup_shared()
|
|
||||||
{
|
|
||||||
if (used && (flags & MAP_SHARED))
|
|
||||||
{
|
|
||||||
SharedMemory* shmem = g_shared_memory_map.try_get_ref(shmid);
|
|
||||||
if (shmem)
|
|
||||||
{
|
|
||||||
for (u64 addr = start; addr < end; addr += ARCH_PAGE_SIZE) { MMU::unmap(addr); }
|
|
||||||
if (--shmem->refs == 0)
|
|
||||||
{
|
|
||||||
shmem->free();
|
|
||||||
g_shared_memory_map.try_remove(shmid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -12,11 +12,6 @@ class VMRegion : LinkedListNode<VMRegion>
|
|||||||
usize count;
|
usize count;
|
||||||
bool used { true };
|
bool used { true };
|
||||||
bool persistent { false };
|
bool persistent { false };
|
||||||
int flags { 0 };
|
|
||||||
int prot { 0 };
|
|
||||||
u64 shmid;
|
|
||||||
|
|
||||||
void cleanup_shared();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AddressSpace
|
class AddressSpace
|
||||||
@ -27,17 +22,16 @@ class AddressSpace
|
|||||||
|
|
||||||
AddressSpace& operator=(AddressSpace&& other);
|
AddressSpace& operator=(AddressSpace&& other);
|
||||||
|
|
||||||
Result<u64> alloc_region(usize count, int prot, int flags, u64 shmid = 0, bool persistent = false);
|
Result<u64> alloc_region(usize count, bool persistent = false);
|
||||||
|
|
||||||
Result<bool> test_and_alloc_region(u64 address, usize count, int prot, int flags, u64 shmid = 0,
|
Result<bool> test_and_alloc_region(u64 address, usize count, bool persistent = false)
|
||||||
bool persistent = false)
|
|
||||||
{
|
{
|
||||||
return set_region(address, count, true, prot, flags, shmid, persistent);
|
return set_region(address, count, true, persistent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<bool> free_region(u64 address, usize count)
|
Result<bool> free_region(u64 address, usize count)
|
||||||
{
|
{
|
||||||
return set_region(address, count, false, 0, 0, 0, false);
|
return set_region(address, count, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result<OwnedPtr<AddressSpace>> try_create();
|
static Result<OwnedPtr<AddressSpace>> try_create();
|
||||||
@ -50,7 +44,7 @@ class AddressSpace
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Result<bool> set_region(u64 address, usize count, bool used, int prot, int flags, u64 shmid, bool persistent);
|
Result<bool> set_region(u64 address, usize count, bool used, bool persistent);
|
||||||
Result<void> create_default_region();
|
Result<void> create_default_region();
|
||||||
Result<void> create_null_region();
|
Result<void> create_null_region();
|
||||||
void try_merge_region_with_neighbors(VMRegion* region);
|
void try_merge_region_with_neighbors(VMRegion* region);
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "Log.h"
|
|
||||||
#include "arch/MMU.h"
|
#include "arch/MMU.h"
|
||||||
#include "memory/KernelVM.h"
|
#include "memory/KernelVM.h"
|
||||||
#include "memory/MemoryMap.h"
|
#include "memory/MemoryMap.h"
|
||||||
@ -227,57 +226,6 @@ namespace MemoryManager
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> copy_region(u64 virt, usize count, PageDirectory* oldpd, PageDirectory* newpd)
|
|
||||||
{
|
|
||||||
CHECK_PAGE_ALIGNED(virt);
|
|
||||||
|
|
||||||
usize pages_mapped = 0;
|
|
||||||
|
|
||||||
// Let's clean up after ourselves if we fail.
|
|
||||||
auto guard = make_scope_guard(
|
|
||||||
[=, &pages_mapped] { kwarnln("copy_region failed, sorry! cannot reclaim already copied pages"); });
|
|
||||||
|
|
||||||
while (pages_mapped < count)
|
|
||||||
{
|
|
||||||
u64 phys = TRY(MMU::get_physical(virt, oldpd));
|
|
||||||
int flags = TRY(MMU::get_flags(virt, oldpd));
|
|
||||||
TRY(MMU::map(virt, phys, flags, MMU::UseHugePages::No, newpd));
|
|
||||||
virt += ARCH_PAGE_SIZE;
|
|
||||||
pages_mapped++;
|
|
||||||
}
|
|
||||||
|
|
||||||
guard.deactivate();
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> copy_region_data(u64 virt, usize count, PageDirectory* oldpd, PageDirectory* newpd)
|
|
||||||
{
|
|
||||||
CHECK_PAGE_ALIGNED(virt);
|
|
||||||
|
|
||||||
usize pages_mapped = 0;
|
|
||||||
|
|
||||||
// Let's clean up after ourselves if we fail.
|
|
||||||
auto guard = make_scope_guard(
|
|
||||||
[=, &pages_mapped] { kwarnln("copy_region_data failed, sorry! cannot reclaim already copied pages"); });
|
|
||||||
|
|
||||||
while (pages_mapped < count)
|
|
||||||
{
|
|
||||||
u64 frame = TRY(alloc_frame());
|
|
||||||
u64 phys = TRY(MMU::get_physical(virt, oldpd));
|
|
||||||
int flags = TRY(MMU::get_flags(virt, oldpd));
|
|
||||||
memcpy((void*)MMU::translate_physical_address(frame), (void*)MMU::translate_physical_address(phys),
|
|
||||||
ARCH_PAGE_SIZE);
|
|
||||||
TRY(MMU::map(virt, frame, flags, MMU::UseHugePages::No, newpd));
|
|
||||||
virt += ARCH_PAGE_SIZE;
|
|
||||||
pages_mapped++;
|
|
||||||
}
|
|
||||||
|
|
||||||
guard.deactivate();
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> map_huge_frames_at(u64 virt, u64 phys, usize count, int flags)
|
Result<void> map_huge_frames_at(u64 virt, u64 phys, usize count, int flags)
|
||||||
{
|
{
|
||||||
CHECK_PAGE_ALIGNED(virt);
|
CHECK_PAGE_ALIGNED(virt);
|
||||||
@ -410,20 +358,6 @@ namespace MemoryManager
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> unmap_owned_if_possible(u64 virt, usize count)
|
|
||||||
{
|
|
||||||
CHECK_PAGE_ALIGNED(virt);
|
|
||||||
|
|
||||||
while (count--)
|
|
||||||
{
|
|
||||||
const auto frame = MMU::unmap(virt);
|
|
||||||
if (frame.has_value()) TRY(free_frame(frame.value()));
|
|
||||||
virt += ARCH_PAGE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> unmap_owned_and_free_vm(u64 virt, usize count)
|
Result<void> unmap_owned_and_free_vm(u64 virt, usize count)
|
||||||
{
|
{
|
||||||
CHECK_PAGE_ALIGNED(virt);
|
CHECK_PAGE_ALIGNED(virt);
|
||||||
|
@ -67,9 +67,6 @@ namespace MemoryManager
|
|||||||
Result<void> map_frames_at(u64 virt, u64 phys, usize count, int flags);
|
Result<void> map_frames_at(u64 virt, u64 phys, usize count, int flags);
|
||||||
Result<void> map_huge_frames_at(u64 virt, u64 phys, usize count, int flags);
|
Result<void> map_huge_frames_at(u64 virt, u64 phys, usize count, int flags);
|
||||||
|
|
||||||
Result<void> copy_region(u64 virt, usize count, PageDirectory* oldpd, PageDirectory* newpd);
|
|
||||||
Result<void> copy_region_data(u64 virt, usize count, PageDirectory* oldpd, PageDirectory* newpd);
|
|
||||||
|
|
||||||
Result<u64> alloc_at(u64 virt, usize count, int flags);
|
Result<u64> alloc_at(u64 virt, usize count, int flags);
|
||||||
Result<u64> alloc_at_zeroed(u64, usize count, int flags);
|
Result<u64> alloc_at_zeroed(u64, usize count, int flags);
|
||||||
Result<u64> alloc_for_kernel(usize count, int flags);
|
Result<u64> alloc_for_kernel(usize count, int flags);
|
||||||
@ -78,7 +75,6 @@ namespace MemoryManager
|
|||||||
|
|
||||||
Result<void> unmap_owned(u64 virt, usize count);
|
Result<void> unmap_owned(u64 virt, usize count);
|
||||||
Result<void> unmap_owned_and_free_vm(u64 virt, usize count);
|
Result<void> unmap_owned_and_free_vm(u64 virt, usize count);
|
||||||
Result<void> unmap_owned_if_possible(u64 virt, usize count);
|
|
||||||
Result<void> unmap_weak(u64 virt, usize count);
|
Result<void> unmap_weak(u64 virt, usize count);
|
||||||
Result<void> unmap_weak_and_free_vm(u64 virt, usize count);
|
Result<void> unmap_weak_and_free_vm(u64 virt, usize count);
|
||||||
|
|
||||||
|
@ -1,120 +0,0 @@
|
|||||||
#include "memory/SharedMemory.h"
|
|
||||||
#include "memory/MemoryManager.h"
|
|
||||||
#include <bits/mmap-flags.h>
|
|
||||||
#include <luna/ScopeGuard.h>
|
|
||||||
|
|
||||||
HashMap<u64, SharedMemory> g_shared_memory_map;
|
|
||||||
Atomic<u64> g_next_shmem_id;
|
|
||||||
|
|
||||||
Result<u64> SharedMemory::create(u8* mem, off_t offset, usize count)
|
|
||||||
{
|
|
||||||
SharedMemory shmem;
|
|
||||||
shmem.offset = offset;
|
|
||||||
|
|
||||||
auto guard = make_scope_guard([&shmem] {
|
|
||||||
for (u64 frame : shmem.frames) { MemoryManager::free_frame(frame); }
|
|
||||||
});
|
|
||||||
|
|
||||||
while (count--)
|
|
||||||
{
|
|
||||||
u64 frame = TRY(MemoryManager::alloc_frame());
|
|
||||||
TRY(shmem.frames.try_append(frame));
|
|
||||||
if (mem)
|
|
||||||
{
|
|
||||||
memcpy((void*)MMU::translate_physical_address(frame), mem, ARCH_PAGE_SIZE);
|
|
||||||
mem += ARCH_PAGE_SIZE;
|
|
||||||
}
|
|
||||||
else { memset((void*)MMU::translate_physical_address(frame), 0, ARCH_PAGE_SIZE); }
|
|
||||||
}
|
|
||||||
|
|
||||||
const u64 id = g_next_shmem_id++;
|
|
||||||
|
|
||||||
check(TRY(g_shared_memory_map.try_set(id, move(shmem))));
|
|
||||||
|
|
||||||
guard.deactivate();
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> SharedMemory::grow_forward(u8* mem, usize count)
|
|
||||||
{
|
|
||||||
u64 old_count = frames.size();
|
|
||||||
|
|
||||||
auto guard = make_scope_guard([old_count, this] {
|
|
||||||
while (old_count < this->frames.size()) { MemoryManager::free_frame(*this->frames.try_pop()); }
|
|
||||||
});
|
|
||||||
|
|
||||||
while (count--)
|
|
||||||
{
|
|
||||||
u64 frame = TRY(MemoryManager::alloc_frame());
|
|
||||||
TRY(frames.try_append(frame));
|
|
||||||
if (mem)
|
|
||||||
{
|
|
||||||
memcpy((void*)MMU::translate_physical_address(frame), mem, ARCH_PAGE_SIZE);
|
|
||||||
mem += ARCH_PAGE_SIZE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
guard.deactivate();
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> SharedMemory::grow_backward(u8* mem, usize count)
|
|
||||||
{
|
|
||||||
Vector<u64> new_frames;
|
|
||||||
|
|
||||||
const usize bytes = count * ARCH_PAGE_SIZE;
|
|
||||||
|
|
||||||
auto guard = make_scope_guard([&new_frames, count] {
|
|
||||||
for (u64 i = 0; i < count && i < new_frames.size(); i++) { MemoryManager::free_frame(new_frames[i]); }
|
|
||||||
});
|
|
||||||
|
|
||||||
while (count--)
|
|
||||||
{
|
|
||||||
u64 frame = TRY(MemoryManager::alloc_frame());
|
|
||||||
TRY(new_frames.try_append(frame));
|
|
||||||
if (mem)
|
|
||||||
{
|
|
||||||
memcpy((void*)MMU::translate_physical_address(frame), mem, ARCH_PAGE_SIZE);
|
|
||||||
mem += ARCH_PAGE_SIZE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u64 frame : frames) { TRY(new_frames.try_append(frame)); }
|
|
||||||
|
|
||||||
frames = move(new_frames);
|
|
||||||
offset -= bytes;
|
|
||||||
|
|
||||||
guard.deactivate();
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> SharedMemory::map(u64 virt, int flags, off_t _offset, usize count)
|
|
||||||
{
|
|
||||||
usize off = _offset / ARCH_PAGE_SIZE;
|
|
||||||
if (off + count > frames.size()) return err(EINVAL);
|
|
||||||
|
|
||||||
for (usize i = off; i < count; i++)
|
|
||||||
{
|
|
||||||
TRY(MMU::map(virt, frames[i], flags, MMU::UseHugePages::No));
|
|
||||||
virt += ARCH_PAGE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
void SharedMemory::free()
|
|
||||||
{
|
|
||||||
if (inode && (prot & PROT_WRITE))
|
|
||||||
{
|
|
||||||
for (u64 i = 0; i < frames.size(); i++)
|
|
||||||
{
|
|
||||||
inode->write((u8*)MMU::translate_physical_address(frames[i]), offset + (i * ARCH_PAGE_SIZE),
|
|
||||||
ARCH_PAGE_SIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u64 frame : frames) { MemoryManager::free_frame(frame); }
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "fs/VFS.h"
|
|
||||||
#include <luna/HashMap.h>
|
|
||||||
#include <luna/Vector.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
struct SharedMemory
|
|
||||||
{
|
|
||||||
Vector<u64> frames;
|
|
||||||
off_t offset;
|
|
||||||
int prot;
|
|
||||||
SharedPtr<VFS::Inode> inode {};
|
|
||||||
int refs { 0 };
|
|
||||||
|
|
||||||
static Result<u64> create(u8* mem, off_t offset, usize count);
|
|
||||||
|
|
||||||
Result<void> grow_forward(u8* mem, usize count);
|
|
||||||
Result<void> grow_backward(u8* mem, usize count);
|
|
||||||
|
|
||||||
Result<void> map(u64 virt, int flags, off_t offset, usize count);
|
|
||||||
|
|
||||||
void free();
|
|
||||||
};
|
|
||||||
|
|
||||||
extern HashMap<u64, SharedMemory> g_shared_memory_map;
|
|
@ -1,90 +1,62 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "arch/MMU.h"
|
#include "arch/MMU.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "memory/SharedMemory.h"
|
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
#include <bits/mmap-flags.h>
|
#include <bits/mmap-flags.h>
|
||||||
#include <bits/mmap.h>
|
|
||||||
#include <bits/open-flags.h>
|
|
||||||
#include <luna/Alignment.h>
|
#include <luna/Alignment.h>
|
||||||
|
|
||||||
constexpr uintptr_t USERSPACE_HEAP_BASE = 0x3000000;
|
constexpr uintptr_t USERSPACE_HEAP_BASE = 0x3000000;
|
||||||
|
|
||||||
Result<u64> sys_mmap(Registers*, SyscallArgs args)
|
Result<u64> sys_mmap(Registers*, SyscallArgs args)
|
||||||
{
|
{
|
||||||
mmap_params params;
|
void* addr = (void*)args[0];
|
||||||
if (!MemoryManager::copy_from_user_typed((const mmap_params*)args[0], ¶ms)) return err(EFAULT);
|
usize len = (usize)args[1];
|
||||||
|
int prot = (int)args[2];
|
||||||
|
int flags = (int)args[3];
|
||||||
|
|
||||||
kdbgln("mmap: address=%p, len=%zu, prot=%d, flags=%d, fd=%d, offset=%lu", params.addr, params.len, params.prot,
|
if (len == 0) return err(EINVAL);
|
||||||
params.flags, params.fd, params.offset);
|
|
||||||
|
|
||||||
if (params.len == 0) return err(EINVAL);
|
if (flags < 0) return err(EINVAL);
|
||||||
|
|
||||||
if (params.flags < 0) return err(EINVAL);
|
// We support only anonymous mappings for now.
|
||||||
|
if ((flags & MAP_ANONYMOUS) != MAP_ANONYMOUS)
|
||||||
|
{
|
||||||
|
kwarnln("mmap: FIXME: attempt to mmap file instead of anonymous memory");
|
||||||
|
return err(ENOTSUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & MAP_SHARED)
|
||||||
|
{
|
||||||
|
kwarnln("mmap: FIXME: attempt to mmap shared memory");
|
||||||
|
return err(ENOTSUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
len = align_up<ARCH_PAGE_SIZE>(len);
|
||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
|
||||||
SharedPtr<OpenFileDescription> description;
|
|
||||||
if ((params.flags & MAP_ANONYMOUS) != MAP_ANONYMOUS)
|
|
||||||
{
|
|
||||||
description = TRY(current->resolve_fd(params.fd))->description;
|
|
||||||
if (!(description->flags & O_RDONLY)) return err(EACCES);
|
|
||||||
if (description->flags & O_APPEND) return err(EACCES);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_aligned<ARCH_PAGE_SIZE>(params.offset)) return err(EINVAL);
|
|
||||||
|
|
||||||
params.len = align_up<ARCH_PAGE_SIZE>(params.len);
|
|
||||||
|
|
||||||
SharedMemory* shmem = nullptr;
|
|
||||||
u64 shmid = 0;
|
|
||||||
if (params.flags & MAP_SHARED)
|
|
||||||
{
|
|
||||||
if (!description)
|
|
||||||
{
|
|
||||||
params.offset = 0;
|
|
||||||
shmid = TRY(SharedMemory::create(nullptr, 0, params.len / ARCH_PAGE_SIZE));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((params.prot & PROT_WRITE) && !(description->flags & O_WRONLY)) return err(EACCES);
|
|
||||||
shmid = TRY(description->inode->query_shared_memory(params.offset, params.len));
|
|
||||||
}
|
|
||||||
shmem = g_shared_memory_map.try_get_ref(shmid);
|
|
||||||
shmem->refs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 address;
|
u64 address;
|
||||||
if (!params.addr)
|
if (!addr) address = TRY(current->address_space->alloc_region(get_blocks_from_size(len, ARCH_PAGE_SIZE)));
|
||||||
address = TRY(current->address_space->alloc_region(get_blocks_from_size(params.len, ARCH_PAGE_SIZE),
|
|
||||||
params.prot, params.flags, shmid));
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// FIXME: We should be more flexible if MAP_FIXED was not specified.
|
// FIXME: We should be more flexible if MAP_FIXED was not specified.
|
||||||
address = align_down<ARCH_PAGE_SIZE>((u64)params.addr);
|
address = align_down<ARCH_PAGE_SIZE>((u64)addr);
|
||||||
if (!TRY(current->address_space->test_and_alloc_region(
|
if (!TRY(current->address_space->test_and_alloc_region(address, get_blocks_from_size(len, ARCH_PAGE_SIZE))))
|
||||||
address, get_blocks_from_size(params.len, ARCH_PAGE_SIZE), params.prot, params.flags, shmid)))
|
|
||||||
return err(ENOMEM);
|
return err(ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mmu_flags = MMU::User | MMU::NoExecute;
|
int mmu_flags = MMU::User | MMU::NoExecute;
|
||||||
if (params.prot & PROT_WRITE) mmu_flags |= MMU::ReadWrite;
|
if (prot & PROT_WRITE) mmu_flags |= MMU::ReadWrite;
|
||||||
if (params.prot & PROT_EXEC) mmu_flags &= ~MMU::NoExecute;
|
if (prot & PROT_EXEC) mmu_flags &= ~MMU::NoExecute;
|
||||||
if (params.prot == PROT_NONE) mmu_flags = MMU::NoExecute;
|
if (prot == PROT_NONE) mmu_flags = MMU::NoExecute;
|
||||||
|
|
||||||
#ifdef MMAP_DEBUG
|
#ifdef MMAP_DEBUG
|
||||||
kdbgln("mmap: mapping memory at %#lx, size=%zu", address, len);
|
kdbgln("mmap: mapping memory at %#lx, size=%zu", address, len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (shmem) { TRY(shmem->map(address, mmu_flags, params.offset, get_blocks_from_size(params.len, ARCH_PAGE_SIZE))); }
|
// FIXME: This leaks VM if it fails.
|
||||||
else
|
return MemoryManager::alloc_at_zeroed(address, get_blocks_from_size(len, ARCH_PAGE_SIZE), mmu_flags);
|
||||||
{
|
|
||||||
TRY(MemoryManager::alloc_at_zeroed(address, get_blocks_from_size(params.len, ARCH_PAGE_SIZE), mmu_flags));
|
|
||||||
if (description) { TRY(description->inode->read((u8*)address, params.offset, params.len)); }
|
|
||||||
}
|
|
||||||
|
|
||||||
return address;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<u64> sys_munmap(Registers*, SyscallArgs args)
|
Result<u64> sys_munmap(Registers*, SyscallArgs args)
|
||||||
@ -106,7 +78,7 @@ Result<u64> sys_munmap(Registers*, SyscallArgs args)
|
|||||||
kdbgln("munmap: unmapping memory at %#lx, size=%zu", address, size);
|
kdbgln("munmap: unmapping memory at %#lx, size=%zu", address, size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TRY(MemoryManager::unmap_owned_if_possible(address, get_blocks_from_size(size, ARCH_PAGE_SIZE)));
|
TRY(MemoryManager::unmap_owned(address, get_blocks_from_size(size, ARCH_PAGE_SIZE)));
|
||||||
|
|
||||||
return { 0 };
|
return { 0 };
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include "thread/ThreadImage.h"
|
#include "thread/ThreadImage.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "thread/Thread.h"
|
#include "thread/Thread.h"
|
||||||
#include <bits/mmap-flags.h>
|
|
||||||
#include <luna/Alignment.h>
|
#include <luna/Alignment.h>
|
||||||
#include <luna/CString.h>
|
#include <luna/CString.h>
|
||||||
|
|
||||||
@ -16,9 +15,7 @@ static Result<void> create_user_stack(Stack& user_stack, AddressSpace* space)
|
|||||||
|
|
||||||
auto guard = make_scope_guard([] { MemoryManager::unmap_owned(THREAD_STACK_BASE, DEFAULT_USER_STACK_PAGES); });
|
auto guard = make_scope_guard([] { MemoryManager::unmap_owned(THREAD_STACK_BASE, DEFAULT_USER_STACK_PAGES); });
|
||||||
|
|
||||||
if (!TRY(space->test_and_alloc_region(THREAD_STACK_BASE, DEFAULT_USER_STACK_PAGES, PROT_READ | PROT_WRITE,
|
if (!TRY(space->test_and_alloc_region(THREAD_STACK_BASE, DEFAULT_USER_STACK_PAGES, true))) return err(ENOMEM);
|
||||||
MAP_ANONYMOUS | MAP_PRIVATE, 0, true)))
|
|
||||||
return err(ENOMEM);
|
|
||||||
|
|
||||||
guard.deactivate();
|
guard.deactivate();
|
||||||
|
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
struct mmap_params
|
|
||||||
{
|
|
||||||
void* addr;
|
|
||||||
size_t len;
|
|
||||||
int prot;
|
|
||||||
int flags;
|
|
||||||
int fd;
|
|
||||||
off_t offset;
|
|
||||||
};
|
|
@ -1,5 +1,4 @@
|
|||||||
#include <bits/errno-return.h>
|
#include <bits/errno-return.h>
|
||||||
#include <bits/mmap.h>
|
|
||||||
#include <luna/Heap.h>
|
#include <luna/Heap.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
@ -7,10 +6,9 @@
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
void* mmap(void* addr, size_t len, int prot, int flags, int fd, off_t offset)
|
void* mmap(void* addr, size_t len, int prot, int flags, int, off_t)
|
||||||
{
|
{
|
||||||
const mmap_params params { addr, len, prot, flags, fd, offset };
|
long rc = syscall(SYS_mmap, addr, len, prot, flags);
|
||||||
long rc = syscall(SYS_mmap, ¶ms);
|
|
||||||
__errno_return(rc, void*);
|
__errno_return(rc, void*);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,11 +20,6 @@ template <typename K, typename V> u64 hash(const HashPair<K, V>& value, u64 salt
|
|||||||
template <typename K, typename V> struct HashMap
|
template <typename K, typename V> struct HashMap
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Result<bool> try_set(const K& key, V&& value)
|
|
||||||
{
|
|
||||||
return m_table.try_set(HashPair<K, V> { key, move(value) });
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<bool> try_set(const K& key, const V& value)
|
Result<bool> try_set(const K& key, const V& value)
|
||||||
{
|
{
|
||||||
return m_table.try_set(HashPair<K, V> { key, value });
|
return m_table.try_set(HashPair<K, V> { key, value });
|
||||||
|
Loading…
Reference in New Issue
Block a user