Userspace dlmalloc port, supporting syscalls mman_map()/mman_unmap()
This commit is contained in:
@ -57,7 +57,7 @@ void *pmm_alloc(size_t pages) {
|
||||
|
||||
if (!phys) {
|
||||
ERR("pmm", "phys memory ran out\n");
|
||||
hal_hang();
|
||||
return NULL;
|
||||
}
|
||||
return (void *)phys;
|
||||
}
|
||||
|
@ -169,6 +169,7 @@ Proc *proc_spawnuser(char *mountpoint, char *path) {
|
||||
proc->platformdata.trapframe.rip = aux.entry;
|
||||
proc->state = PROC_EMBRYO;
|
||||
proc->pid = pids++;
|
||||
proc->mman_map_base = PROC_MMAN_MAP_BASE;
|
||||
spinlock_init(&proc->bcast_pipes.spinlock);
|
||||
spinlock_init(&proc->pipes_spinlock);
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
||||
#define PROC_VFSHANDLES_MAX 0x80
|
||||
#define PROC_PIPEHANDLES_MAX 0x20
|
||||
|
||||
#define PROC_MMAN_MAP_BASE 0xC000000000
|
||||
|
||||
typedef struct {
|
||||
IntrStackFrame trapframe;
|
||||
uint8_t *kstack;
|
||||
@ -51,6 +53,8 @@ typedef struct Proc {
|
||||
IpcPipe *list;
|
||||
SpinLock spinlock;
|
||||
} bcast_pipes;
|
||||
|
||||
uint64_t mman_map_base;
|
||||
} Proc;
|
||||
|
||||
typedef struct {
|
||||
|
99
kernel/syscall/mman.c
Normal file
99
kernel/syscall/mman.c
Normal file
@ -0,0 +1,99 @@
|
||||
#include <stdint.h>
|
||||
#include "syscall.h"
|
||||
#include "mman.h"
|
||||
#include "spinlock/spinlock.h"
|
||||
#include "proc/proc.h"
|
||||
#include "hal/hal.h"
|
||||
#include "pmm/pmm.h"
|
||||
#include "util/util.h"
|
||||
#include "errors.h"
|
||||
#include "sysdefs/mman.h"
|
||||
#include "bootinfo/bootinfo.h"
|
||||
#include "dlmalloc/malloc.h"
|
||||
|
||||
int32_t SYSCALL5(sys_mman_map, addr1, size1, prot1, flags1, out1) {
|
||||
uint8_t *addr = (uint8_t *)addr1;
|
||||
size_t size = size1;
|
||||
uint64_t prot = prot1;
|
||||
uint64_t flags = flags1;
|
||||
uint8_t **out = (uint8_t **)out1;
|
||||
|
||||
if (size % HAL_PAGE_SIZE != 0) {
|
||||
if (out != NULL) {
|
||||
*out = NULL;
|
||||
}
|
||||
return E_INVALIDARGUMENT;
|
||||
}
|
||||
|
||||
size_t pages = _DIV_ROUNDUP(size, HAL_PAGE_SIZE);
|
||||
uint8_t *phys = (uint8_t *)pmm_alloc(pages);
|
||||
if (phys == NULL) {
|
||||
return E_NOMEMORY;
|
||||
}
|
||||
hal_memset(VIRT(phys), 0, pages * HAL_PAGE_SIZE);
|
||||
|
||||
spinlock_acquire(&PROCS.spinlock);
|
||||
Proc *proc = PROCS.current;
|
||||
spinlock_release(&PROCS.spinlock);
|
||||
|
||||
uint8_t *virt = NULL;
|
||||
if (flags & MMAN_MAP_F_FIXED && addr != NULL) {
|
||||
virt = addr;
|
||||
} else {
|
||||
virt = (uint8_t *)proc->mman_map_base;
|
||||
proc->mman_map_base += size;
|
||||
}
|
||||
|
||||
uint64_t pflags = HAL_PG_USER | HAL_PG_PRESENT;
|
||||
if (prot & MMAN_MAP_PF_RW) {
|
||||
pflags |= HAL_PG_RW;
|
||||
}
|
||||
|
||||
hal_vmm_map_range(VIRT(proc->platformdata.cr3), virt, phys, size, pflags);
|
||||
VasRange *range = dlmalloc(sizeof(*range));
|
||||
range->virtstart = virt;
|
||||
range->physstart = phys;
|
||||
range->size = size * HAL_PAGE_SIZE;
|
||||
range->pgflags = pflags;
|
||||
LL_APPEND(proc->vas, range);
|
||||
|
||||
if (out != NULL) {
|
||||
*out = virt;
|
||||
}
|
||||
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
int32_t SYSCALL1(sys_mman_unmap, addr1) {
|
||||
uint8_t *addr = (uint8_t *)addr1;
|
||||
|
||||
if (addr == NULL) {
|
||||
return E_INVALIDARGUMENT;
|
||||
}
|
||||
|
||||
spinlock_acquire(&PROCS.spinlock);
|
||||
Proc *proc = PROCS.current;
|
||||
spinlock_release(&PROCS.spinlock);
|
||||
|
||||
uint8_t *virt = NULL;
|
||||
VasRange *tofree = NULL;
|
||||
|
||||
VasRange *range = proc->vas;
|
||||
while (range) {
|
||||
if (range->virtstart == addr) {
|
||||
tofree = range;
|
||||
break;
|
||||
}
|
||||
range = range->next;
|
||||
}
|
||||
|
||||
if (tofree == NULL) {
|
||||
return E_INVALIDARGUMENT;
|
||||
}
|
||||
|
||||
hal_vmm_unmap_range(VIRT(proc->platformdata.cr3), tofree->virtstart, tofree->physstart, tofree->size);
|
||||
LL_REMOVE(proc->vas, tofree);
|
||||
pmm_free((uintptr_t)tofree->physstart, tofree->size / HAL_PAGE_SIZE);
|
||||
dlfree(tofree);
|
||||
return E_OK;
|
||||
}
|
9
kernel/syscall/mman.h
Normal file
9
kernel/syscall/mman.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef SYSCALL_MMAN_H_
|
||||
#define SYSCALL_MMAN_H_
|
||||
|
||||
#include "syscall.h"
|
||||
|
||||
int32_t SYSCALL5(sys_mman_map, addr1, size1, prot1, flags1, out1);
|
||||
int32_t SYSCALL1(sys_mman_unmap, addr1);
|
||||
|
||||
#endif // SYSCALL_MMAN_H_
|
@ -6,6 +6,7 @@
|
||||
#include "sysdefs/syscall.h"
|
||||
#include "ioctl.h"
|
||||
#include "ipcpipe.h"
|
||||
#include "mman.h"
|
||||
|
||||
int32_t SYSCALL1(sys_debugprint, string) {
|
||||
char *p = (char *)string;
|
||||
@ -18,4 +19,6 @@ SyscallFn SYSCALL_TABLE[SYSCALLS_MAX] = {
|
||||
[SYS_PROCESSCTL] = &sys_processctl,
|
||||
[SYS_IOCTL] = &sys_ioctl,
|
||||
[SYS_IPCPIPE] = &sys_ipcpipe,
|
||||
[SYS_MMAN_MAP] = &sys_mman_map,
|
||||
[SYS_MMAN_UNMAP] = &sys_mman_unmap,
|
||||
};
|
||||
|
Reference in New Issue
Block a user