diff --git a/kernel/pmm/pmm.c b/kernel/pmm/pmm.c index 2e14710..d8b742c 100644 --- a/kernel/pmm/pmm.c +++ b/kernel/pmm/pmm.c @@ -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; } diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index f4d38e5..7c518c2 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -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); diff --git a/kernel/proc/proc.h b/kernel/proc/proc.h index abdf333..65f2749 100644 --- a/kernel/proc/proc.h +++ b/kernel/proc/proc.h @@ -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 { diff --git a/kernel/syscall/mman.c b/kernel/syscall/mman.c new file mode 100644 index 0000000..5b59721 --- /dev/null +++ b/kernel/syscall/mman.c @@ -0,0 +1,99 @@ +#include +#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; +} diff --git a/kernel/syscall/mman.h b/kernel/syscall/mman.h new file mode 100644 index 0000000..91bb445 --- /dev/null +++ b/kernel/syscall/mman.h @@ -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_ diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index 696df84..c02eeaf 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -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, }; diff --git a/share/sysdefs/mman.h b/share/sysdefs/mman.h new file mode 100644 index 0000000..1fd42ff --- /dev/null +++ b/share/sysdefs/mman.h @@ -0,0 +1,12 @@ +#ifndef SHARE_SYSDEFS_MMAN_H_ +#define SHARE_SYSDEFS_MMAN_H_ + +enum { + MMAN_MAP_PF_RW = (1<<0), +}; + +enum { + MMAN_MAP_F_FIXED = (1<<0), +}; + +#endif // SHARE_SYSDEFS_MMAN_H_ diff --git a/share/sysdefs/syscall.h b/share/sysdefs/syscall.h index 23a3606..8cac4e6 100644 --- a/share/sysdefs/syscall.h +++ b/share/sysdefs/syscall.h @@ -6,6 +6,8 @@ enum { SYS_PROCESSCTL = 2, SYS_IOCTL = 3, SYS_IPCPIPE = 4, + SYS_MMAN_MAP = 5, + SYS_MMAN_UNMAP = 6, }; #endif // SHARE_HDRS_SYSCALL_H_ diff --git a/ulib/Makefile b/ulib/Makefile index bc27d06..b6d7f07 100644 --- a/ulib/Makefile +++ b/ulib/Makefile @@ -10,10 +10,12 @@ SRCFILES := $(call GRABSRC, \ string \ system \ printf \ + dlmalloc \ + sync \ ) CFLAGS += -isystem $(ROOT)/share -isystem $(ROOT)/ulib -isystem $(ROOT)/std/include \ - -DPRINTF_INCLUDE_CONFIG_H=1 + -DPRINTF_INCLUDE_CONFIG_H=1 -DLACKS_STRING_H=1 -include $(ROOT)/ulib/string/string.h ASFILES := $(call GET_ASFILES, $(SRCFILES)) CFILES := $(call GET_CFILES, $(SRCFILES)) diff --git a/ulib/dlmalloc/dlmalloc_port.inc b/ulib/dlmalloc/dlmalloc_port.inc new file mode 100644 index 0000000..8f64f58 --- /dev/null +++ b/ulib/dlmalloc/dlmalloc_port.inc @@ -0,0 +1,76 @@ +// Config + +#include +#include +#include +#include +#include +#include +#include +#include + +#define USE_DL_PREFIX 1 +#define LACKS_SYS_TYPES_H 1 +#define NO_MALLOC_STATS 1 +#define LACKS_ERRNO_H 1 +#define LACKS_TIME_H 1 +#define LACKS_STDLIB_H 1 +#define LACKS_SYS_MMAN_H 1 +#define LACKS_FCNTL_H 1 +#define LACKS_UNISTD_H 1 +#define LACKS_SYS_PARAM_H 1 +#define LACKS_STRINGS_H 1 +#define LACKS_SCHED_H 1 +#define HAVE_MMAP 0 +#define ABORT \ + do { \ + uprintf("dlmalloc: Aborting...\n"); \ + } while(0) +#define MALLOC_FAILURE_ACTION +#define HAVE_MORECORE 1 +#define USE_LOCKS 2 +#define malloc_getpagesize 0x1000 +#define EINVAL E_INVALIDARGUMENT +#define ENOMEM E_NOMEMORY + +#define MLOCK_T SpinLock + +int ACQUIRE_LOCK(SpinLock *sl) { + spinlock_acquire(sl); + return 0; +} + +int RELEASE_LOCK(SpinLock *sl) { + spinlock_release(sl); + return 0; +} + +int INITIAL_LOCK(SpinLock *sl) { + spinlock_release(sl); + return 0; +} + +static MLOCK_T malloc_global_mutex = { 0 }; + +#define PAGE_SIZE 0x1000 +static uint8_t *heap_end = NULL; + +void *sbrk(long inc) { + if (inc == 0) { + return heap_end; + } + + uint8_t *new_heap_end = heap_end + inc; + if (new_heap_end > heap_end) { + size_t size = new_heap_end - heap_end; + + uint8_t *out = NULL; + int32_t ret = mman_map(heap_end, size, MMAN_MAP_PF_RW, 0, &out); + if (ret != E_OK) { + return (void *)-1; + } + string_memset(out, 0, size); + } + heap_end = new_heap_end; + return (void *)heap_end; +} diff --git a/ulib/dlmalloc/malloc.c b/ulib/dlmalloc/malloc.c new file mode 120000 index 0000000..1ec360b --- /dev/null +++ b/ulib/dlmalloc/malloc.c @@ -0,0 +1 @@ +../../dlmalloc/malloc.c \ No newline at end of file diff --git a/ulib/dlmalloc/malloc.h b/ulib/dlmalloc/malloc.h new file mode 120000 index 0000000..ee86eca --- /dev/null +++ b/ulib/dlmalloc/malloc.h @@ -0,0 +1 @@ +../../dlmalloc/malloc.h \ No newline at end of file diff --git a/ulib/string/string.c b/ulib/string/string.c index 84b5f3c..d8410eb 100644 --- a/ulib/string/string.c +++ b/ulib/string/string.c @@ -9,3 +9,105 @@ size_t string_len(const char *s) { } return l; } + +void *string_memset(void *p, int c, size_t n) { + char *cp = p; + for (size_t i = 0; i < n; i++) cp[i] = c; + return p; +} + +void *string_memcpy(void *dst, const void *src, size_t n) { + char *a = dst; + const char *b = src; + for (size_t i = 0; i < n; i++) a[i] = b[i]; + return dst; +} + +// https://aticleworld.com/memcmp-in-c/ +int string_memcmp(const void *s1, const void *s2, int len) +{ + unsigned char *p = s1; + unsigned char *q = s2; + int charCompareStatus = 0; + //If both pointer pointing same memory block + if (s1 == s2) + { + return charCompareStatus; + } + while (len > 0) + { + if (*p != *q) + { //compare the mismatching character + charCompareStatus = (*p >*q)?1:-1; + break; + } + len--; + p++; + q++; + } + return charCompareStatus; +} + +int string_strcmp(const char *a, const char *b) { + while (*a && (*a == *b)) { + a++, b++; + } + return (unsigned char)*a - (unsigned char)*b; +} + +size_t string_strcspn(const char *s, const char *reject) { + size_t count = 0; + for (; *s != '\0'; ++s) { + const char *r = reject; + while (*r != '\0') { + if (*s == *r) { + return count; + } + r++; + } + count++; + } + return count; +} + +size_t string_strspn(const char *s, const char *accept) { + size_t count = 0; + for (; *s != '\0'; ++s) { + const char *a = accept; + int matched = 0; + while (*a != '\0') { + if (*s == *a) { + matched = 1; + break; + } + a++; + } + if (!matched) { + return count; + } + count++; + } + return count; +} + +char *string_strcpy(char *dest, const char *src) { + char *d = dest; + while ((*d++ = *src++) != '\0') { + ; + } + return dest; +} + +char *string_strchr(const char *s, int c) { + char ch = (char)c; + while (*s != '\0') { + if (*s == ch) { + return (char *)s; + } + s++; + } + if (ch == '\0') { + return (char *)s; + } + return NULL; +} diff --git a/ulib/string/string.h b/ulib/string/string.h index f2cbcff..97895c7 100644 --- a/ulib/string/string.h +++ b/ulib/string/string.h @@ -1,8 +1,24 @@ #ifndef ULIB_STRING_STRING_H_ #define ULIB_STRING_STRING_H_ +#if !defined(__ASSEMBLER__) + #include +#include + +#define memset string_memset +#define memcpy string_memcpy size_t string_len(const char *s); +void *string_memset(void *p, int c, size_t n); +void *string_memcpy(void *dst, const void *src, size_t n); +int string_memcmp(const void *s1, const void *s2, int len); +int string_strcmp(const char *a, const char *b); +size_t string_strcspn(const char *s, const char *reject); +size_t string_strspn(const char *s, const char *accept); +char *string_strcpy(char *dest, const char *src); +char *string_strchr(const char *s, int c); + +#endif #endif // ULIB_STRING_STRING_H_ diff --git a/ulib/sync/spinlock.c b/ulib/sync/spinlock.c new file mode 100644 index 0000000..d750f18 --- /dev/null +++ b/ulib/sync/spinlock.c @@ -0,0 +1,18 @@ +#include +#include + +#define HINT() asm volatile("pause"); + +void spinlock_init(SpinLock *sl) { + atomic_store(&sl->lock, false); +} + +void spinlock_acquire(SpinLock *sl) { + while (atomic_test_and_set_explicit(&sl->lock, memory_order_release)) { + HINT(); + } +} + +void spinlock_release(SpinLock *sl) { + atomic_clear_flag_explicit(&sl->lock, memory_order_release); +} diff --git a/ulib/sync/spinlock.h b/ulib/sync/spinlock.h new file mode 100644 index 0000000..19b5fbc --- /dev/null +++ b/ulib/sync/spinlock.h @@ -0,0 +1,14 @@ +#ifndef ULIB_SYNC_SPINLOCK_H_ +#define ULIB_SYNC_SPINLOCK_H_ + +#include + +typedef struct { + atomic_bool lock; +} SpinLock; + +void spinlock_init(SpinLock *sl); +void spinlock_acquire(SpinLock *sl); +void spinlock_release(SpinLock *sl); + +#endif // ULIB_SYNC_SPINLOCK_H_ diff --git a/ulib/system/system.c b/ulib/system/system.c index 981783e..7a9e90a 100644 --- a/ulib/system/system.c +++ b/ulib/system/system.c @@ -18,3 +18,11 @@ int32_t processctl(uint64_t pid, uint64_t cmd, uint64_t arg1) { int32_t ipcpipe(uint64_t pid, uint64_t pipenum, uint64_t cmd, uint8_t *buffer, size_t len) { return syscall(SYS_IPCPIPE, pid, pipenum, cmd, (uint64_t)buffer, (uint64_t)len, 0); } + +int32_t mman_map(uint8_t *addr, size_t size, uint64_t prot, uint64_t flags, uint8_t **out) { + return syscall(SYS_MMAN_MAP, (uint64_t)addr, (uint64_t)size, prot, flags, (uint64_t)out, 0); +} + +int32_t mman_unmap(uint8_t *addr) { + return syscall(SYS_MMAN_UNMAP, (uint64_t)addr, 0, 0, 0, 0, 0); +} diff --git a/ulib/system/system.h b/ulib/system/system.h index 8ce2f3f..483769d 100644 --- a/ulib/system/system.h +++ b/ulib/system/system.h @@ -8,5 +8,7 @@ void debugprint(const char *string); int32_t ioctl(uint64_t ioh, uint64_t cmd, uint64_t arg1, uint64_t arg2, uint64_t arg3); int32_t processctl(uint64_t pid, uint64_t cmd, uint64_t arg1); int32_t ipcpipe(uint64_t pid, uint64_t pipenum, uint64_t cmd, uint8_t *buffer, size_t len); +int32_t mman_map(uint8_t *addr, size_t size, uint64_t prot, uint64_t flags, uint8_t **out); +int32_t mman_unmap(uint8_t *addr); #endif // ULIB_SYSTEM_SYSTEM_H_ diff --git a/user/tb/main.c b/user/tb/main.c index 04ddc31..d0ac596 100644 --- a/user/tb/main.c +++ b/user/tb/main.c @@ -1,5 +1,11 @@ #include +#include void main(void) { uprintf("Hello from tb!\n"); + + int *tmp = dlmalloc(sizeof(*tmp) * 1024); + *tmp = 123456; + uprintf("*tmp = %d\n", *tmp); + dlfree(tmp); }