Selaa lähdekoodia

Start working on memory-mapped files.

First of all, change sys$mmap to take a struct SC_mmap_params since our
sycsall calling convention can't handle more than 3 arguments.

This exposed a bug in Syscall::invoke() needing to use clobber lists.
It was a bit confusing to debug. :^)
Andreas Kling 6 vuotta sitten
vanhempi
commit
fdbd9f1e27
14 muutettua tiedostoa jossa 82 lisäystä ja 26 poistoa
  1. 9 0
      AK/Types.h
  2. 4 0
      Kernel/MemoryManager.h
  3. 13 5
      Kernel/Process.cpp
  4. 2 1
      Kernel/Process.h
  5. 2 2
      Kernel/Syscall.cpp
  6. 13 4
      Kernel/Syscall.h
  7. 5 0
      Kernel/i386.cpp
  8. 2 6
      LibC/entry.cpp
  9. 1 1
      LibC/grp.cpp
  10. 6 4
      LibC/mman.cpp
  11. 12 1
      LibC/mman.h
  12. 1 1
      LibC/pwd.cpp
  13. 1 1
      LibC/stdlib.cpp
  14. 11 0
      VirtualFileSystem/UnixTypes.h

+ 9 - 0
AK/Types.h

@@ -15,6 +15,15 @@ typedef dword size_t;
 typedef signed_dword ssize_t;
 
 typedef signed_dword ptrdiff_t;
+
+typedef byte uint8_t;
+typedef word uint16_t;
+typedef dword uint32_t;
+
+typedef signed_byte int8_t;
+typedef signed_word int16_t;
+typedef signed_dword int32_t;
+
 #else
 #include <stdint.h>
 #include <sys/types.h>

+ 4 - 0
Kernel/MemoryManager.h

@@ -9,6 +9,7 @@
 #include <AK/Vector.h>
 #include <AK/HashTable.h>
 #include <AK/String.h>
+#include <VirtualFileSystem/VirtualFileSystem.h>
 
 class Process;
 extern Process* current;
@@ -71,6 +72,9 @@ struct Region : public Retainable<Region> {
         return (laddr - linearAddress).get() / PAGE_SIZE;
     }
 
+    RetainPtr<VirtualFileSystem::Node> m_file;
+    Unix::off_t m_file_offset { 0 };
+
     LinearAddress linearAddress;
     size_t size { 0 };
     Vector<RetainPtr<PhysicalPage>> physical_pages;

+ 13 - 5
Kernel/Process.cpp

@@ -26,15 +26,17 @@
 
 // FIXME: Only do a single validation for accesses that don't span multiple pages.
 // FIXME: Some places pass strlen(arg1) as arg2. This doesn't seem entirely perfect..
-#define VALIDATE_USER_READ(b, s) \
+#define VALIDATE_USER_READ_WITH_RETURN_TYPE(b, s, ret_type) \
     do { \
         LinearAddress laddr((dword)(b)); \
         if (!validate_user_read(laddr) || !validate_user_read(laddr.offset((s) - 1))) { \
             dbgprintf("Bad read address passed to syscall: %p +%u\n", laddr.get(), (s)); \
-            return -EFAULT; \
+            return (ret_type)-EFAULT; \
         } \
     } while(0)
 
+#define VALIDATE_USER_READ(b, s) VALIDATE_USER_READ_WITH_RETURN_TYPE(b, s, int)
+
 #define VALIDATE_USER_WRITE(b, s) \
     do { \
         LinearAddress laddr((dword)(b)); \
@@ -136,15 +138,21 @@ int Process::sys$set_mmap_name(void* addr, size_t size, const char* name)
     return 0;
 }
 
-void* Process::sys$mmap(void* addr, size_t size)
+void* Process::sys$mmap(const Syscall::SC_mmap_params* params)
 {
+    VALIDATE_USER_READ_WITH_RETURN_TYPE(params, sizeof(Syscall::SC_mmap_params), void*);
     InterruptDisabler disabler;
-    // FIXME: Implement mapping at a client-preferred address.
+    void* addr = (void*)params->addr;
+    size_t size = params->size;
+    int prot = params->prot;
+    int flags = params->flags;
+    int fd = params->fd;
+    Unix::off_t offset = params->offset;
+    // FIXME: Implement mapping at a client-preferred address. Most of the support is already in plcae.
     ASSERT(addr == nullptr);
     auto* region = allocate_region(LinearAddress(), size, "mmap");
     if (!region)
         return (void*)-1;
-    MM.mapRegion(*this, *region);
     return (void*)region->linearAddress.get();
 }
 

+ 2 - 1
Kernel/Process.h

@@ -9,6 +9,7 @@
 #include <VirtualFileSystem/VirtualFileSystem.h>
 #include <VirtualFileSystem/UnixTypes.h>
 #include "TTY.h"
+#include "Syscall.h"
 
 class FileDescriptor;
 class PageDirectory;
@@ -132,7 +133,7 @@ public:
     void sys$sigreturn() NORETURN;
     pid_t sys$spawn(const char* path, const char** args, const char** envp);
     pid_t sys$waitpid(pid_t, int* wstatus, int options);
-    void* sys$mmap(void*, size_t size);
+    void* sys$mmap(const Syscall::SC_mmap_params*);
     int sys$munmap(void*, size_t size);
     int sys$set_mmap_name(void*, size_t, const char*);
     int sys$get_dir_entries(int fd, void*, size_t);

+ 2 - 2
Kernel/Syscall.cpp

@@ -8,7 +8,7 @@ extern "C" void syscall_entry(RegisterDump&);
 extern "C" void syscall_ISR();
 extern volatile RegisterDump* syscallRegDump;
 
-asm(
+asm volatile(
     ".globl syscall_ISR \n"
     "syscall_ISR:\n"
     "    pusha\n"
@@ -93,7 +93,7 @@ static DWORD handle(RegisterDump& regs, DWORD function, DWORD arg1, DWORD arg2,
     case Syscall::SC_waitpid:
         return current->sys$waitpid((pid_t)arg1, (int*)arg2, (int)arg3);
     case Syscall::SC_mmap:
-        return (dword)current->sys$mmap((void*)arg1, (size_t)arg2);
+        return (dword)current->sys$mmap((const SC_mmap_params*)arg1);
     case Syscall::SC_munmap:
         return current->sys$munmap((void*)arg1, (size_t)arg2);
     case Syscall::SC_gethostname:

+ 13 - 4
Kernel/Syscall.h

@@ -82,33 +82,42 @@ inline constexpr const char* toString(Function function)
     return "Unknown";
 }
 
+struct SC_mmap_params {
+    uint32_t addr;
+    uint32_t size;
+    int32_t prot;
+    int32_t flags;
+    int32_t fd;
+    uint32_t offset; // FIXME: 64-bit off_t?
+};
+
 void initialize();
 
 inline dword invoke(dword function)
 {
     dword result;
-    asm volatile("int $0x80":"=a"(result):"a"(function));
+    asm volatile("int $0x80":"=a"(result):"a"(function):"memory");
     return result;
 }
 
 inline dword invoke(dword function, dword arg1)
 {
     dword result;
-    asm volatile("int $0x80":"=a"(result):"a"(function),"d"(arg1));
+    asm volatile("int $0x80":"=a"(result):"a"(function),"d"(arg1):"memory");
     return result;
 }
 
 inline dword invoke(dword function, dword arg1, dword arg2)
 {
     dword result;
-    asm volatile("int $0x80":"=a"(result):"a"(function),"d"(arg1),"c"(arg2));
+    asm volatile("int $0x80":"=a"(result):"a"(function),"d"(arg1),"c"(arg2):"memory");
     return result;
 }
 
 inline dword invoke(dword function, dword arg1, dword arg2, dword arg3)
 {
     dword result;
-    asm volatile("int $0x80":"=a"(result):"a"(function),"d"(arg1),"c"(arg2),"b"(arg3));
+    asm volatile("int $0x80":"=a"(result):"a"(function),"d"(arg1),"c"(arg2),"b"(arg3):"memory");
     return result;
 }
 

+ 5 - 0
Kernel/i386.cpp

@@ -232,6 +232,11 @@ void exception_14_handler(RegisterDumpWithExceptionCode& regs)
 
     if (response == PageFaultResponse::ShouldCrash) {
         kprintf("Crashing after unresolved page fault\n");
+        kprintf("exception code: %w\n", regs.exception_code);
+        kprintf("pc=%w:%x ds=%w es=%w fs=%w gs=%w\n", regs.cs, regs.eip, regs.ds, regs.es, regs.fs, regs.gs);
+        kprintf("stk=%w:%x\n", ss, esp);
+        kprintf("eax=%x ebx=%x ecx=%x edx=%x\n", regs.eax, regs.ebx, regs.ecx, regs.edx);
+        kprintf("ebp=%x esp=%x esi=%x edi=%x\n", regs.ebp, esp, regs.esi, regs.edi);
         current->crash();
     } else if (response == PageFaultResponse::Continue) {
 #ifdef PAGE_FAULT_DEBUG

+ 2 - 6
LibC/entry.cpp

@@ -17,21 +17,17 @@ extern "C" void __malloc_init();
 
 extern "C" int _start()
 {
-    __malloc_init();
-
     errno = 0;
-
     memset(__default_streams, 0, sizeof(__default_streams));
-
     __default_streams[0].fd = 0;
     stdin = &__default_streams[0];
-
     __default_streams[1].fd = 1;
     stdout = &__default_streams[1];
-
     __default_streams[2].fd = 2;
     stderr = &__default_streams[2];
 
+    __malloc_init();
+
     StringImpl::initializeGlobals();
 
     int status = 254;

+ 1 - 1
LibC/grp.cpp

@@ -31,7 +31,7 @@ void setgrent()
             perror("open /etc/group");
         }
         assert(__grdb_stream);
-        __grdb_entry = (struct group_with_strings*)mmap(nullptr, getpagesize());
+        __grdb_entry = (struct group_with_strings*)mmap(nullptr, getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
         set_mmap_name(__grdb_entry, getpagesize(), "setgrent");
     }
 }

+ 6 - 4
LibC/mman.cpp

@@ -1,12 +1,14 @@
-#include "mman.h"
-#include "errno.h"
+#include <mman.h>
+#include <errno.h>
+#include <stdio.h>
 #include <Kernel/Syscall.h>
 
 extern "C" {
 
-void* mmap(void* addr, size_t size)
+void* mmap(void* addr, size_t size, int prot, int flags, int fd, off_t offset)
 {
-    int rc = Syscall::invoke(Syscall::SC_mmap, (dword)addr, (dword)size);
+    Syscall::SC_mmap_params params { (dword)addr, size, prot, flags, fd, offset };
+    int rc = Syscall::invoke(Syscall::SC_mmap, (dword)&params);
     __RETURN_WITH_ERRNO(rc, (void*)rc, (void*)-1);
 }
 

+ 12 - 1
LibC/mman.h

@@ -3,9 +3,20 @@
 #include <sys/cdefs.h>
 #include <sys/types.h>
 
+#define MAP_SHARED 0x01
+#define MAP_PRIVATE 0x02
+#define MAP_FIXED 0x10
+#define MAP_ANONYMOUS 0x20
+#define MAP_ANON MAP_ANONYMOUS
+
+#define PROT_READ 0x1
+#define PROT_WRITE 0x2
+#define PROT_EXEC 0x4
+#define PROT_NONE 0x0
+
 __BEGIN_DECLS
 
-void* mmap(void*, size_t);
+void* mmap(void* addr, size_t, int prot, int flags, int fd, off_t);
 int munmap(void*, size_t);
 int set_mmap_name(void*, size_t, const char*);
 

+ 1 - 1
LibC/pwd.cpp

@@ -32,7 +32,7 @@ void setpwent()
             perror("open /etc/passwd");
         }
         assert(__pwdb_stream);
-        __pwdb_entry = (struct passwd_with_strings*)mmap(nullptr, getpagesize());
+        __pwdb_entry = (struct passwd_with_strings*)mmap(nullptr, getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
         set_mmap_name(__pwdb_entry, getpagesize(), "setpwent");
     }
 }

+ 1 - 1
LibC/stdlib.cpp

@@ -18,7 +18,7 @@ static byte* endptr = nullptr;
 
 void __malloc_init()
 {
-    nextptr = (byte*)mmap(nullptr, mallocBudget);
+    nextptr = (byte*)mmap(nullptr, mallocBudget, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
     endptr = nextptr + mallocBudget;
     int rc = set_mmap_name(nextptr, mallocBudget, "malloc");
     if (rc < 0)

+ 11 - 0
VirtualFileSystem/UnixTypes.h

@@ -8,6 +8,17 @@ namespace Unix {
 #define SEEK_CUR 1
 #define SEEK_END 2
 
+#define MAP_SHARED 0x01
+#define MAP_PRIVATE 0x02
+#define MAP_FIXED 0x10
+#define MAP_ANONYMOUS 0x20
+#define MAP_ANON MAP_ANONYMOUS
+
+#define PROT_READ 0x1
+#define PROT_WRITE 0x2
+#define PROT_EXEC 0x4
+#define PROT_NONE 0x0
+
 typedef dword dev_t;
 typedef dword ino_t;
 typedef dword mode_t;