浏览代码

Add /proc/mm and a /bin/mm utility that just dumps it.

This shows some info about the MM. Right now it's just the zone count
and the number of free physical pages. Lots more can be added.

Also added "exit" to sh so we can nest shells and exit from them.

I also noticed that we were leaking all the physical pages, so fixed that.
Andreas Kling 6 年之前
父节点
当前提交
c76dc9a047
共有 10 个文件被更改,包括 115 次插入21 次删除
  1. 15 0
      AK/Vector.h
  2. 32 10
      Kernel/MemoryManager.cpp
  3. 8 7
      Kernel/MemoryManager.h
  4. 13 0
      Kernel/ProcFileSystem.cpp
  5. 1 0
      Kernel/sync-sh
  6. 1 0
      Userland/.gitignore
  7. 7 2
      Userland/Makefile
  8. 25 0
      Userland/mm.cpp
  9. 2 2
      Userland/ps.cpp
  10. 11 0
      Userland/sh.cpp

+ 15 - 0
AK/Vector.h

@@ -116,6 +116,21 @@ public:
         m_impl->remove(index);
         m_impl->remove(index);
     }
     }
 
 
+    void append(Vector<T>&& other)
+    {
+        Vector<T> tmp = move(other);
+        ensureCapacity(size() + tmp.size());
+        for (auto&& v : tmp) {
+            uncheckedAppend(move(v));
+        }
+    }
+
+    void uncheckedAppend(T&& value)
+    {
+        new (m_impl->slot(m_impl->m_size)) T(move(value));
+        ++m_impl->m_size;
+    }
+
     void append(T&& value)
     void append(T&& value)
     {
     {
         ensureCapacity(size() + 1);
         ensureCapacity(size() + 1);

+ 32 - 10
Kernel/MemoryManager.cpp

@@ -34,9 +34,7 @@ void MemoryManager::initializePaging()
     memset(m_pageTableOne, 0, 4096);
     memset(m_pageTableOne, 0, 4096);
     memset(m_pageDirectory, 0, 4096);
     memset(m_pageDirectory, 0, 4096);
 
 
-    kprintf("MM: Page directory @ %p\n", m_pageDirectory);
-    kprintf("MM: Page table zero @ %p\n", m_pageTableZero);
-    kprintf("MM: Page table one @ %p\n", m_pageTableOne);
+    kprintf("[MM] Page directory @ %p\n", m_pageDirectory);
 
 
     // Make null dereferences crash.
     // Make null dereferences crash.
     protectMap(LinearAddress(0), 4 * KB);
     protectMap(LinearAddress(0), 4 * KB);
@@ -72,7 +70,7 @@ auto MemoryManager::ensurePTE(LinearAddress linearAddress) -> PageTableEntry
 
 
     PageDirectoryEntry pde = PageDirectoryEntry(&m_pageDirectory[pageDirectoryIndex]);
     PageDirectoryEntry pde = PageDirectoryEntry(&m_pageDirectory[pageDirectoryIndex]);
     if (!pde.isPresent()) {
     if (!pde.isPresent()) {
-        kprintf("PDE %u !present, allocating\n", pageDirectoryIndex);
+        kprintf("[MM] PDE %u not present, allocating\n", pageDirectoryIndex);
         if (pageDirectoryIndex == 0) {
         if (pageDirectoryIndex == 0) {
             pde.setPageTableBase((dword)m_pageTableZero);
             pde.setPageTableBase((dword)m_pageTableZero);
             pde.setUserAllowed(true);
             pde.setUserAllowed(true);
@@ -85,7 +83,7 @@ auto MemoryManager::ensurePTE(LinearAddress linearAddress) -> PageTableEntry
             pde.setWritable(true);
             pde.setWritable(true);
         } else {
         } else {
             auto* pageTable = allocatePageTable();
             auto* pageTable = allocatePageTable();
-            kprintf("allocated page table %u (for laddr=%p) at %p\n", pageDirectoryIndex, linearAddress.get(), pageTable);
+            kprintf("[MM] Allocated page table #%u (for laddr=%p) at %p\n", pageDirectoryIndex, linearAddress.get(), pageTable);
             memset(pageTable, 0, 4096);
             memset(pageTable, 0, 4096);
             pde.setPageTableBase((dword)pageTable);
             pde.setPageTableBase((dword)pageTable);
             pde.setUserAllowed(true);
             pde.setUserAllowed(true);
@@ -134,7 +132,7 @@ void MemoryManager::initialize()
 PageFaultResponse MemoryManager::handlePageFault(const PageFault& fault)
 PageFaultResponse MemoryManager::handlePageFault(const PageFault& fault)
 {
 {
     ASSERT_INTERRUPTS_DISABLED();
     ASSERT_INTERRUPTS_DISABLED();
-    kprintf("MM: handlePageFault(%w) at laddr=%p\n", fault.code(), fault.address().get());
+    kprintf("[MM] handlePageFault(%w) at laddr=%p\n", fault.code(), fault.address().get());
     if (fault.isNotPresent()) { 
     if (fault.isNotPresent()) { 
         kprintf("  >> NP fault!\n");
         kprintf("  >> NP fault!\n");
     } else if (fault.isProtectionViolation()) {
     } else if (fault.isProtectionViolation()) {
@@ -143,11 +141,36 @@ PageFaultResponse MemoryManager::handlePageFault(const PageFault& fault)
     return PageFaultResponse::ShouldCrash;
     return PageFaultResponse::ShouldCrash;
 }
 }
 
 
+void MemoryManager::registerZone(Zone& zone)
+{
+    ASSERT_INTERRUPTS_DISABLED();
+    m_zones.set(&zone);
+}
+
+void MemoryManager::unregisterZone(Zone& zone)
+{
+    ASSERT_INTERRUPTS_DISABLED();
+    m_zones.remove(&zone);
+    m_freePages.append(move(zone.m_pages));
+}
+
+Zone::Zone(Vector<PhysicalAddress>&& pages)
+    : m_pages(move(pages))
+{
+    MM.registerZone(*this);
+}
+
+Zone::~Zone()
+{
+    MM.unregisterZone(*this);
+}
+
 RetainPtr<Zone> MemoryManager::createZone(size_t size)
 RetainPtr<Zone> MemoryManager::createZone(size_t size)
 {
 {
+    InterruptDisabler disabler;
     auto pages = allocatePhysicalPages(ceilDiv(size, PAGE_SIZE));
     auto pages = allocatePhysicalPages(ceilDiv(size, PAGE_SIZE));
     if (pages.isEmpty()) {
     if (pages.isEmpty()) {
-        kprintf("MM: createZone: no physical pages for size %u", size);
+        kprintf("[MM] createZone: no physical pages for size %u", size);
         return nullptr;
         return nullptr;
     }
     }
     return adopt(*new Zone(move(pages)));
     return adopt(*new Zone(move(pages)));
@@ -170,7 +193,7 @@ byte* MemoryManager::quickMapOnePage(PhysicalAddress physicalAddress)
 {
 {
     ASSERT_INTERRUPTS_DISABLED();
     ASSERT_INTERRUPTS_DISABLED();
     auto pte = ensurePTE(LinearAddress(4 * MB));
     auto pte = ensurePTE(LinearAddress(4 * MB));
-    kprintf("quickmap %x @ %x {pte @ %p}\n", physicalAddress.get(), 4*MB, pte.ptr());
+    kprintf("[MM] quickmap %x @ %x {pte @ %p}\n", physicalAddress.get(), 4*MB, pte.ptr());
     pte.setPhysicalPageBase(physicalAddress.pageBase());
     pte.setPhysicalPageBase(physicalAddress.pageBase());
     pte.setPresent(true);
     pte.setPresent(true);
     pte.setWritable(true);
     pte.setWritable(true);
@@ -297,7 +320,7 @@ bool MemoryManager::mapRegionsForTask(Task& task)
 bool copyToZone(Zone& zone, const void* data, size_t size)
 bool copyToZone(Zone& zone, const void* data, size_t size)
 {
 {
     if (zone.size() < size) {
     if (zone.size() < size) {
-        kprintf("copyToZone: can't fit %u bytes into zone with size %u\n", size, zone.size());
+        kprintf("[MM] copyToZone: can't fit %u bytes into zone with size %u\n", size, zone.size());
         return false;
         return false;
     }
     }
 
 
@@ -314,4 +337,3 @@ bool copyToZone(Zone& zone, const void* data, size_t size)
 
 
     return true;
     return true;
 }
 }
-

+ 8 - 7
Kernel/MemoryManager.h

@@ -5,7 +5,7 @@
 #include <AK/Retainable.h>
 #include <AK/Retainable.h>
 #include <AK/RetainPtr.h>
 #include <AK/RetainPtr.h>
 #include <AK/Vector.h>
 #include <AK/Vector.h>
-#include <AK/HashMap.h>
+#include <AK/HashTable.h>
 #include "Task.h"
 #include "Task.h"
 
 
 class Task;
 class Task;
@@ -17,7 +17,7 @@ enum class PageFaultResponse {
 
 
 struct Zone : public Retainable<Zone> {
 struct Zone : public Retainable<Zone> {
 public:
 public:
-    ~Zone() { }
+    ~Zone();
     size_t size() const { return m_pages.size() * PAGE_SIZE; }
     size_t size() const { return m_pages.size() * PAGE_SIZE; }
 
 
     const Vector<PhysicalAddress>& pages() const { return m_pages; }
     const Vector<PhysicalAddress>& pages() const { return m_pages; }
@@ -25,10 +25,7 @@ public:
 private:
 private:
     friend class MemoryManager;
     friend class MemoryManager;
     friend bool copyToZone(Zone&, const void* data, size_t);
     friend bool copyToZone(Zone&, const void* data, size_t);
-    explicit Zone(Vector<PhysicalAddress>&& pages)
-        : m_pages(move(pages))
-    {
-    }
+    explicit Zone(Vector<PhysicalAddress>&&);
 
 
     Vector<PhysicalAddress> m_pages;
     Vector<PhysicalAddress> m_pages;
 };
 };
@@ -38,6 +35,7 @@ bool copyToZone(Zone&, const void* data, size_t);
 #define MM MemoryManager::the()
 #define MM MemoryManager::the()
 
 
 class MemoryManager {
 class MemoryManager {
+    friend ByteBuffer procfs$mm();
 public:
 public:
     static MemoryManager& the() PURE;
     static MemoryManager& the() PURE;
 
 
@@ -62,6 +60,9 @@ public:
     bool mapRegionsForTask(Task&);
     bool mapRegionsForTask(Task&);
     bool unmapRegionsForTask(Task&);
     bool unmapRegionsForTask(Task&);
 
 
+    void registerZone(Zone&);
+    void unregisterZone(Zone&);
+
 private:
 private:
     MemoryManager();
     MemoryManager();
     ~MemoryManager();
     ~MemoryManager();
@@ -161,7 +162,7 @@ private:
     dword* m_pageTableZero;
     dword* m_pageTableZero;
     dword* m_pageTableOne;
     dword* m_pageTableOne;
 
 
-    HashMap<int, RetainPtr<Zone>> m_zones;
+    HashTable<Zone*> m_zones;
 
 
     Vector<PhysicalAddress> m_freePages;
     Vector<PhysicalAddress> m_freePages;
 };
 };

+ 13 - 0
Kernel/ProcFileSystem.cpp

@@ -118,6 +118,18 @@ void ProcFileSystem::removeProcess(Task& task)
     m_pid2inode.remove(pid);
     m_pid2inode.remove(pid);
 }
 }
 
 
+ByteBuffer procfs$mm()
+{
+    InterruptDisabler disabler;
+    auto buffer = ByteBuffer::createUninitialized(1024);
+    char* ptr = (char*)buffer.pointer();
+    ptr += ksprintf(ptr, "Zone count: %u\n", MM.m_zones.size());
+    ptr += ksprintf(ptr, "Free physical pages: %u\n", MM.m_freePages.size());
+    buffer.trim(ptr - (char*)buffer.pointer());
+    return buffer;
+}
+
+
 ByteBuffer procfs$mounts()
 ByteBuffer procfs$mounts()
 {
 {
     InterruptDisabler disabler;
     InterruptDisabler disabler;
@@ -171,6 +183,7 @@ ByteBuffer procfs$summary()
 bool ProcFileSystem::initialize()
 bool ProcFileSystem::initialize()
 {
 {
     SyntheticFileSystem::initialize();
     SyntheticFileSystem::initialize();
+    addFile(createGeneratedFile("mm", procfs$mm));
     addFile(createGeneratedFile("mounts", procfs$mounts));
     addFile(createGeneratedFile("mounts", procfs$mounts));
     addFile(createGeneratedFile("kmalloc", procfs$kmalloc));
     addFile(createGeneratedFile("kmalloc", procfs$kmalloc));
     addFile(createGeneratedFile("summary", procfs$summary));
     addFile(createGeneratedFile("summary", procfs$summary));

+ 1 - 0
Kernel/sync-sh

@@ -15,6 +15,7 @@ cp ../Userland/cat mnt/bin/cat
 cp ../Userland/uname mnt/bin/uname
 cp ../Userland/uname mnt/bin/uname
 cp ../Userland/clear mnt/bin/clear
 cp ../Userland/clear mnt/bin/clear
 cp ../Userland/tst mnt/bin/tst
 cp ../Userland/tst mnt/bin/tst
+cp ../Userland/mm mnt/bin/mm
 cp kernel.map mnt/
 cp kernel.map mnt/
 umount mnt
 umount mnt
 sync
 sync

+ 1 - 0
Userland/.gitignore

@@ -13,3 +13,4 @@ cat
 uname
 uname
 clear
 clear
 tst
 tst
+mm

+ 7 - 2
Userland/Makefile

@@ -12,7 +12,8 @@ OBJS = \
        cat.o \
        cat.o \
        uname.o \
        uname.o \
        clear.o \
        clear.o \
-       tst.o
+       tst.o \
+       mm.o
 
 
 APPS = \
 APPS = \
        id \
        id \
@@ -28,7 +29,8 @@ APPS = \
        cat \
        cat \
        uname \
        uname \
        clear \
        clear \
-       tst
+       tst \
+       mm
 
 
 ARCH_FLAGS =
 ARCH_FLAGS =
 STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib
 STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib
@@ -90,6 +92,9 @@ clear: clear.o
 tst: tst.o
 tst: tst.o
 	$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
 	$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
 
 
+mm: mm.o
+	$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
+
 .cpp.o:
 .cpp.o:
 	@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
 	@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
 
 

+ 25 - 0
Userland/mm.cpp

@@ -0,0 +1,25 @@
+#include <LibC/stdio.h>
+#include <LibC/unistd.h>
+
+int main(int c, char** v)
+{
+    int fd = open("/proc/mm");
+    if (fd == -1) {
+        perror("failed to open /proc/mm");
+        return 1;
+    }
+    for (;;) {
+        char buf[128];
+        ssize_t nread = read(fd, buf, sizeof(buf));
+        if (nread == 0)
+            break;
+        if (nread < 0) {
+            perror("failed to read");
+            return 2;
+        }
+        for (ssize_t i = 0; i < nread; ++i) {
+            putchar(buf[i]);
+        }
+    }
+    return 0;
+}

+ 2 - 2
Userland/ps.cpp

@@ -5,7 +5,7 @@ int main(int c, char** v)
 {
 {
     int fd = open("/proc/summary");
     int fd = open("/proc/summary");
     if (fd == -1) {
     if (fd == -1) {
-        printf("failed to open /proc/summary :(\n");
+        perror("failed to open /proc/summary");
         return 1;
         return 1;
     }
     }
     for (;;) {
     for (;;) {
@@ -14,7 +14,7 @@ int main(int c, char** v)
         if (nread == 0)
         if (nread == 0)
             break;
             break;
         if (nread < 0) {
         if (nread < 0) {
-            printf("failed to read :(\n");
+            perror("failed to read");
             return 2;
             return 2;
         }
         }
         for (ssize_t i = 0; i < nread; ++i) {
         for (ssize_t i = 0; i < nread; ++i) {

+ 11 - 0
Userland/sh.cpp

@@ -26,6 +26,13 @@ static int sh_pwd(int, const char**)
     return 0;
     return 0;
 }
 }
 
 
+static int sh_exit(int, const char**)
+{
+    printf("Good-bye!\n");
+    exit(0);
+    return 0;
+}
+
 static int sh_cd(int argc, const char** argv)
 static int sh_cd(int argc, const char** argv)
 {
 {
     if (argc == 1) {
     if (argc == 1) {
@@ -77,6 +84,10 @@ static bool handle_builtin(int argc, const char** argv, int& retval)
         retval = sh_pwd(argc, argv);
         retval = sh_pwd(argc, argv);
         return true;
         return true;
     }
     }
+    if (!strcmp(argv[0], "exit")) {
+        retval = sh_exit(argc, argv);
+        return true;
+    }
     return false;
     return false;
 }
 }