From fdbd9f1e272b97d7d28f9f610be8fbf0bdbd98d9 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 8 Nov 2018 11:37:01 +0100 Subject: [PATCH] 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. :^) --- AK/Types.h | 9 +++++++++ Kernel/MemoryManager.h | 4 ++++ Kernel/Process.cpp | 18 +++++++++++++----- Kernel/Process.h | 3 ++- Kernel/Syscall.cpp | 4 ++-- Kernel/Syscall.h | 17 +++++++++++++---- Kernel/i386.cpp | 5 +++++ LibC/entry.cpp | 8 ++------ LibC/grp.cpp | 2 +- LibC/mman.cpp | 10 ++++++---- LibC/mman.h | 13 ++++++++++++- LibC/pwd.cpp | 2 +- LibC/stdlib.cpp | 2 +- VirtualFileSystem/UnixTypes.h | 11 +++++++++++ 14 files changed, 82 insertions(+), 26 deletions(-) diff --git a/AK/Types.h b/AK/Types.h index be4fc35031..14e90e0fab 100644 --- a/AK/Types.h +++ b/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 #include diff --git a/Kernel/MemoryManager.h b/Kernel/MemoryManager.h index 9477e420d2..ca30f9d6db 100644 --- a/Kernel/MemoryManager.h +++ b/Kernel/MemoryManager.h @@ -9,6 +9,7 @@ #include #include #include +#include class Process; extern Process* current; @@ -71,6 +72,9 @@ struct Region : public Retainable { return (laddr - linearAddress).get() / PAGE_SIZE; } + RetainPtr m_file; + Unix::off_t m_file_offset { 0 }; + LinearAddress linearAddress; size_t size { 0 }; Vector> physical_pages; diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 19aec8c7bf..48fc568437 100644 --- a/Kernel/Process.cpp +++ b/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(); } diff --git a/Kernel/Process.h b/Kernel/Process.h index 13661def26..4a136b3b84 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -9,6 +9,7 @@ #include #include #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); diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 57c574e3e5..fbf41acba2 100644 --- a/Kernel/Syscall.cpp +++ b/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: diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index a9f8187769..40f952bdbd 100644 --- a/Kernel/Syscall.h +++ b/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; } diff --git a/Kernel/i386.cpp b/Kernel/i386.cpp index f7b21b504f..f6e46f7345 100644 --- a/Kernel/i386.cpp +++ b/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 diff --git a/LibC/entry.cpp b/LibC/entry.cpp index 0fd3783d73..d24be1ff07 100644 --- a/LibC/entry.cpp +++ b/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; diff --git a/LibC/grp.cpp b/LibC/grp.cpp index 405744968e..e48772627f 100644 --- a/LibC/grp.cpp +++ b/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"); } } diff --git a/LibC/mman.cpp b/LibC/mman.cpp index 5e13e8e268..ff01378aae 100644 --- a/LibC/mman.cpp +++ b/LibC/mman.cpp @@ -1,12 +1,14 @@ -#include "mman.h" -#include "errno.h" +#include +#include +#include #include 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)¶ms); __RETURN_WITH_ERRNO(rc, (void*)rc, (void*)-1); } diff --git a/LibC/mman.h b/LibC/mman.h index b587934043..16c3247591 100644 --- a/LibC/mman.h +++ b/LibC/mman.h @@ -3,9 +3,20 @@ #include #include +#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*); diff --git a/LibC/pwd.cpp b/LibC/pwd.cpp index b84f638c07..681bd93c2d 100644 --- a/LibC/pwd.cpp +++ b/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"); } } diff --git a/LibC/stdlib.cpp b/LibC/stdlib.cpp index fa6c91fb4c..342ab92e2f 100644 --- a/LibC/stdlib.cpp +++ b/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) diff --git a/VirtualFileSystem/UnixTypes.h b/VirtualFileSystem/UnixTypes.h index 02f2a3962d..811fbe476b 100644 --- a/VirtualFileSystem/UnixTypes.h +++ b/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;