mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
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.
This commit is contained in:
parent
0a6a2521e8
commit
c76dc9a047
Notes:
sideshowbarker
2024-07-19 18:37:02 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/c76dc9a047c
10 changed files with 115 additions and 21 deletions
15
AK/Vector.h
15
AK/Vector.h
|
@ -116,6 +116,21 @@ public:
|
|||
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)
|
||||
{
|
||||
ensureCapacity(size() + 1);
|
||||
|
|
|
@ -34,9 +34,7 @@ void MemoryManager::initializePaging()
|
|||
memset(m_pageTableOne, 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.
|
||||
protectMap(LinearAddress(0), 4 * KB);
|
||||
|
@ -72,7 +70,7 @@ auto MemoryManager::ensurePTE(LinearAddress linearAddress) -> PageTableEntry
|
|||
|
||||
PageDirectoryEntry pde = PageDirectoryEntry(&m_pageDirectory[pageDirectoryIndex]);
|
||||
if (!pde.isPresent()) {
|
||||
kprintf("PDE %u !present, allocating\n", pageDirectoryIndex);
|
||||
kprintf("[MM] PDE %u not present, allocating\n", pageDirectoryIndex);
|
||||
if (pageDirectoryIndex == 0) {
|
||||
pde.setPageTableBase((dword)m_pageTableZero);
|
||||
pde.setUserAllowed(true);
|
||||
|
@ -85,7 +83,7 @@ auto MemoryManager::ensurePTE(LinearAddress linearAddress) -> PageTableEntry
|
|||
pde.setWritable(true);
|
||||
} else {
|
||||
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);
|
||||
pde.setPageTableBase((dword)pageTable);
|
||||
pde.setUserAllowed(true);
|
||||
|
@ -134,7 +132,7 @@ void MemoryManager::initialize()
|
|||
PageFaultResponse MemoryManager::handlePageFault(const PageFault& fault)
|
||||
{
|
||||
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()) {
|
||||
kprintf(" >> NP fault!\n");
|
||||
} else if (fault.isProtectionViolation()) {
|
||||
|
@ -143,11 +141,36 @@ PageFaultResponse MemoryManager::handlePageFault(const PageFault& fault)
|
|||
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)
|
||||
{
|
||||
InterruptDisabler disabler;
|
||||
auto pages = allocatePhysicalPages(ceilDiv(size, PAGE_SIZE));
|
||||
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 adopt(*new Zone(move(pages)));
|
||||
|
@ -170,7 +193,7 @@ byte* MemoryManager::quickMapOnePage(PhysicalAddress physicalAddress)
|
|||
{
|
||||
ASSERT_INTERRUPTS_DISABLED();
|
||||
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.setPresent(true);
|
||||
pte.setWritable(true);
|
||||
|
@ -297,7 +320,7 @@ bool MemoryManager::mapRegionsForTask(Task& task)
|
|||
bool copyToZone(Zone& zone, const void* data, size_t 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;
|
||||
}
|
||||
|
||||
|
@ -314,4 +337,3 @@ bool copyToZone(Zone& zone, const void* data, size_t size)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include <AK/Retainable.h>
|
||||
#include <AK/RetainPtr.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <AK/HashMap.h>
|
||||
#include <AK/HashTable.h>
|
||||
#include "Task.h"
|
||||
|
||||
class Task;
|
||||
|
@ -17,7 +17,7 @@ enum class PageFaultResponse {
|
|||
|
||||
struct Zone : public Retainable<Zone> {
|
||||
public:
|
||||
~Zone() { }
|
||||
~Zone();
|
||||
size_t size() const { return m_pages.size() * PAGE_SIZE; }
|
||||
|
||||
const Vector<PhysicalAddress>& pages() const { return m_pages; }
|
||||
|
@ -25,10 +25,7 @@ public:
|
|||
private:
|
||||
friend class MemoryManager;
|
||||
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;
|
||||
};
|
||||
|
@ -38,6 +35,7 @@ bool copyToZone(Zone&, const void* data, size_t);
|
|||
#define MM MemoryManager::the()
|
||||
|
||||
class MemoryManager {
|
||||
friend ByteBuffer procfs$mm();
|
||||
public:
|
||||
static MemoryManager& the() PURE;
|
||||
|
||||
|
@ -62,6 +60,9 @@ public:
|
|||
bool mapRegionsForTask(Task&);
|
||||
bool unmapRegionsForTask(Task&);
|
||||
|
||||
void registerZone(Zone&);
|
||||
void unregisterZone(Zone&);
|
||||
|
||||
private:
|
||||
MemoryManager();
|
||||
~MemoryManager();
|
||||
|
@ -161,7 +162,7 @@ private:
|
|||
dword* m_pageTableZero;
|
||||
dword* m_pageTableOne;
|
||||
|
||||
HashMap<int, RetainPtr<Zone>> m_zones;
|
||||
HashTable<Zone*> m_zones;
|
||||
|
||||
Vector<PhysicalAddress> m_freePages;
|
||||
};
|
||||
|
|
|
@ -118,6 +118,18 @@ void ProcFileSystem::removeProcess(Task& task)
|
|||
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()
|
||||
{
|
||||
InterruptDisabler disabler;
|
||||
|
@ -171,6 +183,7 @@ ByteBuffer procfs$summary()
|
|||
bool ProcFileSystem::initialize()
|
||||
{
|
||||
SyntheticFileSystem::initialize();
|
||||
addFile(createGeneratedFile("mm", procfs$mm));
|
||||
addFile(createGeneratedFile("mounts", procfs$mounts));
|
||||
addFile(createGeneratedFile("kmalloc", procfs$kmalloc));
|
||||
addFile(createGeneratedFile("summary", procfs$summary));
|
||||
|
|
|
@ -15,6 +15,7 @@ cp ../Userland/cat mnt/bin/cat
|
|||
cp ../Userland/uname mnt/bin/uname
|
||||
cp ../Userland/clear mnt/bin/clear
|
||||
cp ../Userland/tst mnt/bin/tst
|
||||
cp ../Userland/mm mnt/bin/mm
|
||||
cp kernel.map mnt/
|
||||
umount mnt
|
||||
sync
|
||||
|
|
1
Userland/.gitignore
vendored
1
Userland/.gitignore
vendored
|
@ -13,3 +13,4 @@ cat
|
|||
uname
|
||||
clear
|
||||
tst
|
||||
mm
|
||||
|
|
|
@ -12,7 +12,8 @@ OBJS = \
|
|||
cat.o \
|
||||
uname.o \
|
||||
clear.o \
|
||||
tst.o
|
||||
tst.o \
|
||||
mm.o
|
||||
|
||||
APPS = \
|
||||
id \
|
||||
|
@ -28,7 +29,8 @@ APPS = \
|
|||
cat \
|
||||
uname \
|
||||
clear \
|
||||
tst
|
||||
tst \
|
||||
mm
|
||||
|
||||
ARCH_FLAGS =
|
||||
STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib
|
||||
|
@ -90,6 +92,9 @@ clear: clear.o
|
|||
tst: tst.o
|
||||
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
|
||||
|
||||
mm: mm.o
|
||||
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
|
||||
|
||||
.cpp.o:
|
||||
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||
|
||||
|
|
25
Userland/mm.cpp
Normal file
25
Userland/mm.cpp
Normal file
|
@ -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;
|
||||
}
|
|
@ -5,7 +5,7 @@ int main(int c, char** v)
|
|||
{
|
||||
int fd = open("/proc/summary");
|
||||
if (fd == -1) {
|
||||
printf("failed to open /proc/summary :(\n");
|
||||
perror("failed to open /proc/summary");
|
||||
return 1;
|
||||
}
|
||||
for (;;) {
|
||||
|
@ -14,7 +14,7 @@ int main(int c, char** v)
|
|||
if (nread == 0)
|
||||
break;
|
||||
if (nread < 0) {
|
||||
printf("failed to read :(\n");
|
||||
perror("failed to read");
|
||||
return 2;
|
||||
}
|
||||
for (ssize_t i = 0; i < nread; ++i) {
|
||||
|
|
|
@ -26,6 +26,13 @@ static int sh_pwd(int, const char**)
|
|||
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)
|
||||
{
|
||||
if (argc == 1) {
|
||||
|
@ -77,6 +84,10 @@ static bool handle_builtin(int argc, const char** argv, int& retval)
|
|||
retval = sh_pwd(argc, argv);
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(argv[0], "exit")) {
|
||||
retval = sh_exit(argc, argv);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue