mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 00:50:22 +00:00
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. :^)
This commit is contained in:
parent
41a751c90c
commit
fdbd9f1e27
Notes:
sideshowbarker
2024-07-19 18:31:47 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/fdbd9f1e272
14 changed files with 82 additions and 26 deletions
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)¶ms);
|
||||
__RETURN_WITH_ERRNO(rc, (void*)rc, (void*)-1);
|
||||
}
|
||||
|
||||
|
|
13
LibC/mman.h
13
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*);
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue