summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2018-11-03 11:28:23 +0100
committerAndreas Kling <awesomekling@gmail.com>2018-11-03 11:29:30 +0100
commitaa6d06b47ee7f510f153fa2971be75533a9295ee (patch)
treec62b83dab7d2d883659a86374ca4627ea168af93 /Kernel
parentdd060d0fa895baa16eb465f2e7cedfb52534df5e (diff)
downloadserenity-aa6d06b47ee7f510f153fa2971be75533a9295ee.zip
Use ELF program headers to load executables smarter.
This turned out way better than the old code. ELF loading is now quite straightforward, and we don't need the weird concept of subregions anymore. Next step is to respect the is_writable flag.
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/MemoryManager.cpp43
-rw-r--r--Kernel/MemoryManager.h14
-rw-r--r--Kernel/ProcFileSystem.cpp14
-rw-r--r--Kernel/Process.cpp86
-rw-r--r--Kernel/Process.h9
-rw-r--r--Kernel/types.h2
6 files changed, 25 insertions, 143 deletions
diff --git a/Kernel/MemoryManager.cpp b/Kernel/MemoryManager.cpp
index 4e7c0421f0..f86cbd315b 100644
--- a/Kernel/MemoryManager.cpp
+++ b/Kernel/MemoryManager.cpp
@@ -385,49 +385,6 @@ bool MemoryManager::unmapRegion(Process& process, Region& region)
return true;
}
-bool MemoryManager::unmapSubregion(Process& process, Subregion& subregion)
-{
- InterruptDisabler disabler;
- size_t numPages = subregion.size / PAGE_SIZE;
- ASSERT(numPages);
- for (size_t i = 0; i < numPages; ++i) {
- auto laddr = subregion.linearAddress.offset(i * PAGE_SIZE);
- auto pte = ensurePTE(process.m_page_directory, laddr);
- pte.setPhysicalPageBase(0);
- pte.setPresent(false);
- pte.setWritable(false);
- pte.setUserAllowed(false);
- flushTLB(laddr);
-#ifdef MM_DEBUG
- //dbgprintf("MM: >> Unmapped subregion %s L%x => P%x <<\n", subregion.name.characters(), laddr, zone.m_pages[i].get());
-#endif
- }
- return true;
-}
-
-bool MemoryManager::mapSubregion(Process& process, Subregion& subregion)
-{
- InterruptDisabler disabler;
- auto& region = *subregion.region;
- auto& zone = *region.zone;
- size_t firstPage = subregion.offset / PAGE_SIZE;
- size_t numPages = subregion.size / PAGE_SIZE;
- ASSERT(numPages);
- for (size_t i = 0; i < numPages; ++i) {
- auto laddr = subregion.linearAddress.offset(i * PAGE_SIZE);
- auto pte = ensurePTE(process.m_page_directory, laddr);
- pte.setPhysicalPageBase(zone.m_pages[firstPage + i].get());
- pte.setPresent(true);
- pte.setWritable(true);
- pte.setUserAllowed(true);
- flushTLB(laddr);
-#ifdef MM_DEBUG
- //dbgprintf("MM: >> Mapped subregion %s L%x => P%x (%u into region)\n", subregion.name.characters(), laddr, zone.m_pages[firstPage + i].get(), subregion.offset);
-#endif
- }
- return true;
-}
-
bool MemoryManager::mapRegion(Process& process, Region& region)
{
map_region_at_address(process.m_page_directory, region, region.linearAddress, true);
diff --git a/Kernel/MemoryManager.h b/Kernel/MemoryManager.h
index 4a1c77b140..3c3df0d58d 100644
--- a/Kernel/MemoryManager.h
+++ b/Kernel/MemoryManager.h
@@ -48,17 +48,6 @@ struct Region : public Retainable<Region> {
String name;
};
-struct Subregion {
- Subregion(Region&, dword offset, size_t, LinearAddress, String&& name);
- ~Subregion();
-
- RetainPtr<Region> region;
- dword offset;
- size_t size { 0 };
- LinearAddress linearAddress;
- String name;
-};
-
#define MM MemoryManager::the()
class MemoryManager {
@@ -75,9 +64,6 @@ public:
RetainPtr<Zone> createZone(size_t);
- bool mapSubregion(Process&, Subregion&);
- bool unmapSubregion(Process&, Subregion&);
-
bool mapRegion(Process&, Region&);
bool unmapRegion(Process&, Region&);
diff --git a/Kernel/ProcFileSystem.cpp b/Kernel/ProcFileSystem.cpp
index f7c221f1cb..8ad761fbea 100644
--- a/Kernel/ProcFileSystem.cpp
+++ b/Kernel/ProcFileSystem.cpp
@@ -49,7 +49,7 @@ ByteBuffer procfs$pid_vm(Process& process)
{
ProcessInspectionScope scope(process);
char* buffer;
- auto stringImpl = StringImpl::createUninitialized(80 + process.regionCount() * 80 + 80 + process.subregionCount() * 80, buffer);
+ auto stringImpl = StringImpl::createUninitialized(80 + process.regionCount() * 80, buffer);
memset(buffer, 0, stringImpl->length());
char* ptr = buffer;
ptr += ksprintf(ptr, "BEGIN END SIZE NAME\n");
@@ -60,18 +60,6 @@ ByteBuffer procfs$pid_vm(Process& process)
region->size,
region->name.characters());
}
- if (process.subregionCount()) {
- ptr += ksprintf(ptr, "\nREGION OFFSET BEGIN END SIZE NAME\n");
- for (auto& subregion : process.subregions()) {
- ptr += ksprintf(ptr, "%x %x %x -- %x %x %s\n",
- subregion->region->linearAddress.get(),
- subregion->offset,
- subregion->linearAddress.get(),
- subregion->linearAddress.offset(subregion->size - 1).get(),
- subregion->size,
- subregion->name.characters());
- }
- }
*ptr = '\0';
return ByteBuffer::copy((byte*)buffer, ptr - buffer);
}
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index 21de6a640c..1f622fc2c1 100644
--- a/Kernel/Process.cpp
+++ b/Kernel/Process.cpp
@@ -134,19 +134,26 @@ Vector<Process*> Process::allProcesses()
return processes;
}
-Region* Process::allocateRegion(size_t size, String&& name)
+Region* Process::allocate_region(LinearAddress laddr, size_t size, String&& name, bool is_readable, bool is_writable)
{
// FIXME: This needs sanity checks. What if this overlaps existing regions?
+ if (laddr.is_null()) {
+ laddr = m_nextRegion;
+ m_nextRegion = m_nextRegion.offset(size).offset(PAGE_SIZE);
+ }
+
+ laddr.mask(0xfffff000);
auto zone = MM.createZone(size);
ASSERT(zone);
- m_regions.append(adopt(*new Region(m_nextRegion, size, move(zone), move(name))));
- m_nextRegion = m_nextRegion.offset(size).offset(16384);
+
+ m_regions.append(adopt(*new Region(laddr, size, move(zone), move(name))));
+
MM.mapRegion(*this, *m_regions.last());
return m_regions.last().ptr();
}
-bool Process::deallocateRegion(Region& region)
+bool Process::deallocate_region(Region& region)
{
InterruptDisabler disabler;
for (size_t i = 0; i < m_regions.size(); ++i) {
@@ -183,7 +190,7 @@ void* Process::sys$mmap(void* addr, size_t size)
InterruptDisabler disabler;
// FIXME: Implement mapping at a client-preferred address.
ASSERT(addr == nullptr);
- auto* region = allocateRegion(size, "mmap");
+ auto* region = allocate_region(LinearAddress(), size, "mmap");
if (!region)
return (void*)-1;
MM.mapRegion(*this, *region);
@@ -196,7 +203,7 @@ int Process::sys$munmap(void* addr, size_t size)
auto* region = regionFromRange(LinearAddress((dword)addr), size);
if (!region)
return -1;
- if (!deallocateRegion(*region))
+ if (!deallocate_region(*region))
return -1;
return 0;
}
@@ -229,17 +236,6 @@ Process* Process::fork(RegisterDump& regs)
dbgprintf("fork: cloning Region{%p}\n", region.ptr());
#endif
auto cloned_region = region->clone();
- // FIXME: Move subregions into Region?
- for (auto& subregion : m_subregions) {
- if (subregion->region.ptr() != region.ptr())
- continue;
-#ifdef FORK_DEBUG
- dbgprintf("fork: cloning Subregion{%p}\n", subregion.ptr());
-#endif
- auto cloned_subregion = make<Subregion>(*cloned_region, subregion->offset, subregion->size, subregion->linearAddress, String(subregion->name));
- child->m_subregions.append(move(cloned_subregion));
- MM.mapSubregion(*child, *child->m_subregions.last());
- }
child->m_regions.append(move(cloned_region));
MM.mapRegion(*child, *child->m_regions.last());
}
@@ -312,18 +308,16 @@ int Process::exec(const String& path, Vector<String>&& arguments, Vector<String>
InterruptDisabler disabler;
// Okay, here comes the sleight of hand, pay close attention..
auto old_regions = move(m_regions);
- auto old_subregions = move(m_subregions);
old_page_directory = m_page_directory;
new_page_directory = reinterpret_cast<PageDirectory*>(kmalloc_page_aligned(sizeof(PageDirectory)));
MM.populate_page_directory(*new_page_directory);
m_page_directory = new_page_directory;
MM.enter_process_paging_scope(*this);
- space.hookableAlloc = [&] (const String& name, size_t size) {
- if (!size)
- return (void*)nullptr;
+ space.alloc_section_hook = [&] (LinearAddress laddr, size_t size, size_t alignment, bool is_readable, bool is_writable, const String& name) {
+ ASSERT(size);
size = ((size / 4096) + 1) * 4096; // FIXME: Use ceil_div?
- region = allocateRegion(size, String(name));
- return (void*)region->linearAddress.get();
+ region = allocate_region(laddr, size, String(name), is_readable, is_writable);
+ return laddr.asPtr();
};
bool success = space.loadELF(move(elfData));
if (!success) {
@@ -331,29 +325,16 @@ int Process::exec(const String& path, Vector<String>&& arguments, Vector<String>
MM.enter_process_paging_scope(*this);
MM.release_page_directory(*new_page_directory);
m_regions = move(old_regions);
- m_subregions = move(old_subregions);
kprintf("sys$execve: Failure loading %s\n", path.characters());
return -ENOEXEC;
}
- space.forEachArea([&] (const String& name, dword offset, size_t size, LinearAddress laddr) {
- if (laddr.isNull())
- return;
- dword roundedOffset = offset & 0xfffff000;
- size_t roundedSize = 4096 * ceilDiv((offset - roundedOffset) + size, 4096u);
- LinearAddress roundedLaddr = laddr;
- roundedLaddr.mask(0xfffff000);
- m_subregions.append(make<Subregion>(*region, roundedOffset, roundedSize, roundedLaddr, String(name)));
- MM.mapSubregion(*this, *m_subregions.last());
- });
-
entry_eip = (dword)space.symbolPtr("_start");
if (!entry_eip) {
m_page_directory = old_page_directory;
MM.enter_process_paging_scope(*this);
MM.release_page_directory(*new_page_directory);
m_regions = move(old_regions);
- m_subregions = move(old_subregions);
return -ENOEXEC;
}
}
@@ -375,7 +356,7 @@ int Process::exec(const String& path, Vector<String>&& arguments, Vector<String>
m_tss.fs = 0x23;
m_tss.ss = 0x23;
m_tss.cr3 = (dword)m_page_directory;
- auto* stack_region = allocateRegion(defaultStackSize, "stack");
+ auto* stack_region = allocate_region(LinearAddress(), defaultStackSize, "stack");
ASSERT(stack_region);
m_stackTop3 = stack_region->linearAddress.offset(defaultStackSize).get() & 0xfffffff8;
m_tss.esp = m_stackTop3;
@@ -512,7 +493,7 @@ Process* Process::create_user_process(const String& path, uid_t uid, gid_t gid,
int Process::sys$get_environment(char*** environ)
{
- auto* region = allocateRegion(4096, "environ");
+ auto* region = allocate_region(LinearAddress(), PAGE_SIZE, "environ");
if (!region)
return -ENOMEM;
MM.mapRegion(*this, *region);
@@ -531,7 +512,7 @@ int Process::sys$get_environment(char*** environ)
int Process::sys$get_arguments(int* argc, char*** argv)
{
- auto* region = allocateRegion(4096, "argv");
+ auto* region = allocate_region(LinearAddress(), PAGE_SIZE, "argv");
if (!region)
return -ENOMEM;
MM.mapRegion(*this, *region);
@@ -656,7 +637,7 @@ Process::Process(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel
if (fork_parent) {
m_stackTop3 = fork_parent->m_stackTop3;
} else {
- auto* region = allocateRegion(defaultStackSize, "stack");
+ auto* region = allocate_region(LinearAddress(), defaultStackSize, "stack");
ASSERT(region);
m_stackTop3 = region->linearAddress.offset(defaultStackSize).get() & 0xfffffff8;
m_tss.esp = m_stackTop3;
@@ -703,18 +684,6 @@ void Process::dumpRegions()
region->size,
region->name.characters());
}
-
- kprintf("Process %s(%u) subregions:\n", name().characters(), pid());
- kprintf("REGION OFFSET BEGIN END SIZE NAME\n");
- for (auto& subregion : m_subregions) {
- kprintf("%x %x %x -- %x %x %s\n",
- subregion->region->linearAddress.get(),
- subregion->offset,
- subregion->linearAddress.get(),
- subregion->linearAddress.offset(subregion->size - 1).get(),
- subregion->size,
- subregion->name.characters());
- }
}
void Process::notify_waiters(pid_t waitee, int exit_status, int signal)
@@ -1303,19 +1272,6 @@ Region::~Region()
{
}
-Subregion::Subregion(Region& r, dword o, size_t s, LinearAddress l, String&& n)\
- : region(r)
- , offset(o)
- , size(s)
- , linearAddress(l)
- , name(move(n))
-{
-}
-
-Subregion::~Subregion()
-{
-}
-
bool Process::isValidAddressForKernel(LinearAddress laddr) const
{
// We check extra carefully here since the first 4MB of the address space is identity-mapped.
diff --git a/Kernel/Process.h b/Kernel/Process.h
index 031dcf1a08..2d8acee68c 100644
--- a/Kernel/Process.h
+++ b/Kernel/Process.h
@@ -12,7 +12,6 @@
class FileHandle;
class PageDirectory;
class Region;
-class Subregion;
class Zone;
class Process : public InlineLinkedListNode<Process> {
@@ -130,8 +129,6 @@ public:
size_t regionCount() const { return m_regions.size(); }
const Vector<RetainPtr<Region>>& regions() const { return m_regions; }
- size_t subregionCount() const { return m_regions.size(); }
- const Vector<OwnPtr<Subregion>>& subregions() const { return m_subregions; }
void dumpRegions();
void didSchedule() { ++m_timesScheduled; }
@@ -203,14 +200,12 @@ private:
TTY* m_tty { nullptr };
- Region* allocateRegion(size_t, String&& name);
- Region* allocateRegion(size_t, String&& name, LinearAddress);
- bool deallocateRegion(Region& region);
+ Region* allocate_region(LinearAddress, size_t, String&& name, bool is_readable = true, bool is_writable = true);
+ bool deallocate_region(Region& region);
Region* regionFromRange(LinearAddress, size_t);
Vector<RetainPtr<Region>> m_regions;
- Vector<OwnPtr<Subregion>> m_subregions;
// FIXME: Implement some kind of ASLR?
LinearAddress m_nextRegion;
diff --git a/Kernel/types.h b/Kernel/types.h
index c0d37ed6e4..8a61b405a5 100644
--- a/Kernel/types.h
+++ b/Kernel/types.h
@@ -84,7 +84,7 @@ public:
LinearAddress() { }
explicit LinearAddress(dword address) : m_address(address) { }
- bool isNull() const { return m_address == 0; }
+ bool is_null() const { return m_address == 0; }
LinearAddress offset(dword o) const { return LinearAddress(m_address + o); }
dword get() const { return m_address; }