diff options
author | Marvin Borner | 2019-12-10 21:47:41 +0100 |
---|---|---|
committer | Marvin Borner | 2019-12-10 21:47:41 +0100 |
commit | 68915f46e66ed65ce2d32009fdfa2f5dca116842 (patch) | |
tree | 7d6df3e4dc6219422cc4b1faf909ff32a74b6edf /src/userspace | |
parent | 33bdf18dad2539aca21727e95e04bfedecd37a76 (diff) |
Some syscalls and userspace stuff
sorry for the worse-getting commit messages...
Diffstat (limited to 'src/userspace')
-rw-r--r-- | src/userspace/main.c | 39 | ||||
-rw-r--r-- | src/userspace/mlibc/stdlib/liballoc.c | 454 | ||||
-rw-r--r-- | src/userspace/mlibc/stdlib/liballoc.h | 22 | ||||
-rw-r--r-- | src/userspace/syscall.c | 18 | ||||
-rw-r--r-- | src/userspace/syscall.h | 30 |
5 files changed, 542 insertions, 21 deletions
diff --git a/src/userspace/main.c b/src/userspace/main.c index 64077eb..4e036c5 100644 --- a/src/userspace/main.c +++ b/src/userspace/main.c @@ -1,12 +1,43 @@ #include <syscall.h> +char *fb; +int vbe_bpl = 3; +int vbe_pitch = 3000; +int vbe_height = 1080; +int vbe_width = 2560; + +void vesa_draw_rectangle(int x1, int y1, int x2, int y2, const uint32_t color[3]) +{ + int pos1 = x1 * vbe_bpl + y1 * vbe_pitch; + char *draw = (char *) &fb[pos1]; + for (int i = 0; i <= y2 - y1; i++) { + for (int j = 0; j <= x2 - x1; j++) { + draw[vbe_bpl * j] = color[2]; + draw[vbe_bpl * j + 1] = color[1]; + draw[vbe_bpl * j + 2] = color[0]; + } + draw += vbe_pitch; + } +} + +void vesa_clear() +{ + vesa_draw_rectangle(0, 0, vbe_width - 1, vbe_height - 1, 0); +} + void user_main() { char hello[] = "> Successfully switched to usermode!\n"; syscall_write(hello); - while (1) { - char ch = (char) syscall_readc(); - syscall_writec(ch); - }; + // fb = (char *) 0x110048; + // vesa_clear(); + + while (1) {}; + + /*while (1) { + char *key = malloc(1); + syscall_readc(key); + syscall_writec(key); + };*/ }
\ No newline at end of file diff --git a/src/userspace/mlibc/stdlib/liballoc.c b/src/userspace/mlibc/stdlib/liballoc.c new file mode 100644 index 0000000..ceb87f6 --- /dev/null +++ b/src/userspace/mlibc/stdlib/liballoc.c @@ -0,0 +1,454 @@ +#include <stddef.h> +#include <stdint.h> +#include <syscall.h> + +int liballoc_lock() +{ + return 0; +} + +int liballoc_unlock() +{ + return 0; +} + +void *liballoc_alloc(size_t p) +{ + uint32_t ptr = syscall_paging_alloc((uint32_t) p); + return (void *) ptr; +} + +int liballoc_free(void *ptr, size_t p) +{ + syscall_paging_free((uint32_t) ptr, (uint32_t) p); + return 0; +} + +#define ALIGNMENT 16ul +#define ALIGN_TYPE char +#define ALIGN_INFO sizeof(ALIGN_TYPE) * 16 +#define USE_CASE1 +#define USE_CASE2 +#define USE_CASE3 +#define USE_CASE4 +#define USE_CASE5 + +#define ALIGN(ptr) \ + if ( ALIGNMENT > 1 ) { \ + uintptr_t diff; \ + ptr = (void*) ((uintptr_t) ptr + ALIGN_INFO); \ + diff = (uintptr_t) ptr & (ALIGNMENT - 1); \ + if (diff != 0) { \ + diff = ALIGNMENT - diff; \ + ptr = (void*) ((uintptr_t) ptr + diff); \ + } \ + *((ALIGN_TYPE*) ((uintptr_t) ptr - ALIGN_INFO)) = diff + ALIGN_INFO; \ + } + +#define UNALIGN(ptr) \ + if (ALIGNMENT > 1) { \ + uintptr_t diff = *((ALIGN_TYPE*) ((uintptr_t) ptr - ALIGN_INFO)); \ + if (diff < (ALIGNMENT + ALIGN_INFO)) { \ + ptr = (void*) ((uintptr_t) ptr - diff); \ + } \ + } + +#define LIBALLOC_MAGIC 0x900df00d +#define LIBALLOC_DEAD 0xbaadf00d + +struct liballoc_major { + struct liballoc_major *prev; + struct liballoc_major *next; + unsigned int pages; + unsigned int size; + unsigned int usage; + struct liballoc_minor *first; +}; + +struct liballoc_minor { + struct liballoc_minor *prev; + struct liballoc_minor *next; + struct liballoc_major *block; + unsigned int magic; + unsigned int size; + unsigned int req_size; +}; + +static struct liballoc_major *l_memRoot = NULL; +static struct liballoc_major *l_bestBet = NULL; + +static unsigned int l_pageSize = 4096; +static unsigned int l_pageCount = 16; +static unsigned long long l_allocated = 0; +static unsigned long long l_inuse = 0; + +static long long l_warningCount = 0; +static long long l_errorCount = 0; +static long long l_possibleOverruns = 0; + +static void *liballoc_memset(void *s, int c, size_t n) +{ + unsigned int i; + for (i = 0; i < n; i++) + ((char *) s)[i] = c; + + return s; +} + +static void *liballoc_memcpy(void *s1, const void *s2, size_t n) +{ + char *cdest; + char *csrc; + unsigned int *ldest = (unsigned int *) s1; + unsigned int *lsrc = (unsigned int *) s2; + + while (n >= sizeof(unsigned int)) { + *ldest++ = *lsrc++; + n -= sizeof(unsigned int); + } + + cdest = (char *) ldest; + csrc = (char *) lsrc; + + while (n > 0) { + *cdest++ = *csrc++; + n -= 1; + } + return s1; +} + +static struct liballoc_major *allocate_new_page(unsigned int size) +{ + unsigned int st; + struct liballoc_major *maj; + + st = size + sizeof(struct liballoc_major); + st += sizeof(struct liballoc_minor); + + if ((st % l_pageSize) == 0) + st = st / (l_pageSize); + else + st = st / (l_pageSize) + 1; + + if (st < l_pageCount) st = l_pageCount; + + maj = (struct liballoc_major *) liballoc_alloc(st); + + if (maj == NULL) { + l_warningCount += 1; + return NULL; + } + + maj->prev = NULL; + maj->next = NULL; + maj->pages = st; + maj->size = st * l_pageSize; + maj->usage = sizeof(struct liballoc_major); + maj->first = NULL; + + l_allocated += maj->size; + + return maj; +} + +void *malloc(size_t req_size) +{ + int startedBet = 0; + unsigned long long bestSize = 0; + void *p = NULL; + uintptr_t diff; + struct liballoc_major *maj; + struct liballoc_minor *min; + struct liballoc_minor *new_min; + unsigned long size = req_size; + + if (ALIGNMENT > 1) { + size += ALIGNMENT + ALIGN_INFO; + } + + liballoc_lock(); + + if (size == 0) { + l_warningCount += 1; + liballoc_unlock(); + // return malloc(1); + } + + if (l_memRoot == NULL) { + l_memRoot = allocate_new_page(size); + if (l_memRoot == NULL) { + liballoc_unlock(); + return NULL; + } + } + + maj = l_memRoot; + startedBet = 0; + + if (l_bestBet != NULL) { + bestSize = l_bestBet->size - l_bestBet->usage; + + if (bestSize > (size + sizeof(struct liballoc_minor))) { + maj = l_bestBet; + startedBet = 1; + } + } + + while (maj != NULL) { + diff = maj->size - maj->usage; + if (bestSize < diff) { + l_bestBet = maj; + bestSize = diff; + } + +#ifdef USE_CASE1 + if (diff < (size + sizeof(struct liballoc_minor))) { + if (maj->next != NULL) { + maj = maj->next; + continue; + } + + if (startedBet == 1) { + maj = l_memRoot; + startedBet = 0; + continue; + } + + maj->next = allocate_new_page(size); + if (maj->next == NULL) break; + maj->next->prev = maj; + maj = maj->next; + } +#endif + +#ifdef USE_CASE2 + if (maj->first == NULL) { + maj->first = (struct liballoc_minor *) ((uintptr_t) maj + sizeof(struct liballoc_major)); + + maj->first->magic = LIBALLOC_MAGIC; + maj->first->prev = NULL; + maj->first->next = NULL; + maj->first->block = maj; + maj->first->size = size; + maj->first->req_size = req_size; + maj->usage += size + sizeof(struct liballoc_minor); + l_inuse += size; + p = (void *) ((uintptr_t) (maj->first) + sizeof(struct liballoc_minor)); + ALIGN(p); + liballoc_unlock(); + return p; + } +#endif + +#ifdef USE_CASE3 + diff = (uintptr_t) (maj->first); + diff -= (uintptr_t) maj; + diff -= sizeof(struct liballoc_major); + + if (diff >= (size + sizeof(struct liballoc_minor))) { + maj->first->prev = (struct liballoc_minor *) ((uintptr_t) maj + sizeof(struct liballoc_major)); + maj->first->prev->next = maj->first; + maj->first = maj->first->prev; + maj->first->magic = LIBALLOC_MAGIC; + maj->first->prev = NULL; + maj->first->block = maj; + maj->first->size = size; + maj->first->req_size = req_size; + maj->usage += size + sizeof(struct liballoc_minor); + l_inuse += size; + p = (void *) ((uintptr_t) (maj->first) + sizeof(struct liballoc_minor)); + ALIGN(p); + liballoc_unlock(); + return p; + } +#endif + +#ifdef USE_CASE4 + min = maj->first; + + while (min != NULL) { + if (min->next == NULL) { + diff = (uintptr_t) (maj) + maj->size; + diff -= (uintptr_t) min; + diff -= sizeof(struct liballoc_minor); + diff -= min->size; + if (diff >= (size + sizeof(struct liballoc_minor))) { + min->next = (struct liballoc_minor *) ((uintptr_t) min + sizeof(struct liballoc_minor) + min->size); + min->next->prev = min; + min = min->next; + min->next = NULL; + min->magic = LIBALLOC_MAGIC; + min->block = maj; + min->size = size; + min->req_size = req_size; + maj->usage += size + sizeof(struct liballoc_minor); + l_inuse += size; + p = (void *) ((uintptr_t) min + sizeof(struct liballoc_minor)); + ALIGN(p); + liballoc_unlock(); + return p; + } + } + + if (min->next != NULL) { + diff = (uintptr_t) (min->next); + diff -= (uintptr_t) min; + diff -= sizeof(struct liballoc_minor); + diff -= min->size; + + if (diff >= (size + sizeof(struct liballoc_minor))) { + new_min = (struct liballoc_minor *) ((uintptr_t) min + sizeof(struct liballoc_minor) + min->size); + new_min->magic = LIBALLOC_MAGIC; + new_min->next = min->next; + new_min->prev = min; + new_min->size = size; + new_min->req_size = req_size; + new_min->block = maj; + min->next->prev = new_min; + min->next = new_min; + maj->usage += size + sizeof(struct liballoc_minor); + l_inuse += size; + p = (void *) ((uintptr_t) new_min + sizeof(struct liballoc_minor)); + ALIGN(p); + liballoc_unlock(); + return p; + } + } + + min = min->next; + } +#endif + +#ifdef USE_CASE5 + if (maj->next == NULL) { + if (startedBet == 1) { + maj = l_memRoot; + startedBet = 0; + continue; + } + maj->next = allocate_new_page(size); + if (maj->next == NULL) break; + maj->next->prev = maj; + } +#endif + maj = maj->next; + } + + liballoc_unlock(); + + return NULL; +} + +void free(void *ptr) +{ + struct liballoc_minor *min; + struct liballoc_major *maj; + + if (ptr == NULL) { + l_warningCount += 1; + return; + } + + UNALIGN(ptr); + liballoc_lock(); + + min = (struct liballoc_minor *) ((uintptr_t) ptr - sizeof(struct liballoc_minor)); + + if (min->magic != LIBALLOC_MAGIC) { + l_errorCount += 1; + + if (((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) || + ((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) || + ((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF))) { + l_possibleOverruns += 1; + } + + liballoc_unlock(); + return; + } + + maj = min->block; + l_inuse -= min->size; + maj->usage -= (min->size + sizeof(struct liballoc_minor)); + min->magic = LIBALLOC_DEAD; + + if (min->next != NULL) min->next->prev = min->prev; + if (min->prev != NULL) min->prev->next = min->next; + if (min->prev == NULL) maj->first = min->next; + if (maj->first == NULL) { + if (l_memRoot == maj) l_memRoot = maj->next; + if (l_bestBet == maj) l_bestBet = NULL; + if (maj->prev != NULL) maj->prev->next = maj->next; + if (maj->next != NULL) maj->next->prev = maj->prev; + l_allocated -= maj->size; + liballoc_free(maj, maj->pages); + } else { + if (l_bestBet != NULL) { + int bestSize = l_bestBet->size - l_bestBet->usage; + int majSize = maj->size - maj->usage; + if (majSize > bestSize) l_bestBet = maj; + } + } + liballoc_unlock(); +} + +void *calloc(size_t nobj, size_t size) +{ + int real_size; + void *p; + + real_size = nobj * size; + + p = malloc(real_size); + + liballoc_memset(p, 0, real_size); + + return p; +} + +void *realloc(void *p, size_t size) +{ + void *ptr; + struct liballoc_minor *min; + unsigned int real_size; + + if (size == 0) { + free(p); + return NULL; + } + + if (p == NULL) return malloc(size); + + ptr = p; + UNALIGN(ptr); + liballoc_lock(); + min = (struct liballoc_minor *) ((uintptr_t) ptr - sizeof(struct liballoc_minor)); + + if (min->magic != LIBALLOC_MAGIC) { + l_errorCount += 1; + if (((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) || + ((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) || + ((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF))) { + l_possibleOverruns += 1; + } + + liballoc_unlock(); + return NULL; + } + + real_size = min->req_size; + + if (real_size >= size) { + min->req_size = size; + liballoc_unlock(); + return p; + } + + liballoc_unlock(); + + ptr = malloc(size); + liballoc_memcpy(ptr, p, real_size); + free(p); + + return ptr; +} diff --git a/src/userspace/mlibc/stdlib/liballoc.h b/src/userspace/mlibc/stdlib/liballoc.h new file mode 100644 index 0000000..d21aeb4 --- /dev/null +++ b/src/userspace/mlibc/stdlib/liballoc.h @@ -0,0 +1,22 @@ +#ifndef MELVIX_ALLOC_H +#define MELVIX_ALLOC_H + +#include <stddef.h> + +int liballoc_lock(); + +int liballoc_unlock(); + +void *liballoc_alloc(size_t); + +int liballoc_free(void *, size_t); + +void *malloc(size_t); + +void *realloc(void *, size_t); + +void *calloc(size_t, size_t); + +void free(void *); + +#endif diff --git a/src/userspace/syscall.c b/src/userspace/syscall.c new file mode 100644 index 0000000..a6bdc80 --- /dev/null +++ b/src/userspace/syscall.c @@ -0,0 +1,18 @@ +#include <syscall.h> + +/** + * DEFINITIONS + */ +DEFN_SYSCALL0(halt, 0); + +DEFN_SYSCALL1(write, 1, char *); + +DEFN_SYSCALL1(read, 2, char *); + +DEFN_SYSCALL1(writec, 3, char *); + +DEFN_SYSCALL1(readc, 4, char *); + +DEFN_SYSCALL1(paging_alloc, 5, uint32_t); + +DEFN_SYSCALL2(paging_free, 6, uint32_t, uint32_t);
\ No newline at end of file diff --git a/src/userspace/syscall.h b/src/userspace/syscall.h index 4ddd9d2..5de717e 100644 --- a/src/userspace/syscall.h +++ b/src/userspace/syscall.h @@ -1,6 +1,8 @@ #ifndef MELVIX_SYSCALL_H #define MELVIX_SYSCALL_H +#include <stdint.h> + #define DECL_SYSCALL0(fn) int syscall_##fn() #define DECL_SYSCALL1(fn, p1) int syscall_##fn(p1) #define DECL_SYSCALL2(fn, p1, p2) int syscall_##fn(p1,p2) @@ -16,7 +18,7 @@ #define DEFN_SYSCALL1(fn, num, P1) \ int syscall_##fn(P1 p1) { \ - int __res; __asm__ __volatile__("push %%ebx; movl %2,%%ebx; int $0x80; pop %%ebx" \ + int __res; __asm__ __volatile__("int $0x80" \ : "=a" (__res) \ : "0" (num), "b" ((int)(p1)) \ : "memory"); \ @@ -25,7 +27,7 @@ #define DEFN_SYSCALL2(fn, num, P1, P2) \ int syscall_##fn(P1 p1, P2 p2) { \ - int __res; __asm__ __volatile__("push %%ebx; movl %2,%%ebx; int $0x80; pop %%ebx" \ + int __res; __asm__ __volatile__("int $0x80" \ : "=a" (__res) \ : "0" (num), "b" ((int)(p1)), "c"((int)(p2)) \ : "memory"); \ @@ -34,7 +36,7 @@ #define DEFN_SYSCALL3(fn, num, P1, P2, P3) \ int syscall_##fn(P1 p1, P2 p2, P3 p3) { \ - int __res; __asm__ __volatile__("push %%ebx; movl %2,%%ebx; int $0x80; pop %%ebx" \ + int __res; __asm__ __volatile__("int $0x80" \ : "=a" (__res) \ : "0" (num), "b" ((int)(p1)), "c"((p2)), "d"((int)(p3)) \ : "memory"); \ @@ -43,7 +45,7 @@ #define DEFN_SYSCALL4(fn, num, P1, P2, P3, P4) \ int syscall_##fn(P1 p1, P2 p2, P3 p3, P4 p4) { \ - int __res; __asm__ __volatile__("push %%ebx; movl %2,%%ebx; int $0x80; pop %%ebx" \ + int __res; __asm__ __volatile__("int $0x80" \ : "=a" (__res) \ : "0" (num), "b" ((int)(p1)), "c"((int)(p2)), "d"((int)(p3)), "S"((int)(p4)) \ : "memory"); \ @@ -52,7 +54,7 @@ #define DEFN_SYSCALL5(fn, num, P1, P2, P3, P4, P5) \ int syscall_##fn(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { \ - int __res; __asm__ __volatile__("push %%ebx; movl %2,%%ebx; int $0x80; pop %%ebx" \ + int __res; __asm__ __volatile__("int $0x80" \ : "=a" (__res) \ : "0" (num), "b" ((int)(p1)), "c"((int)(p2)), "d"((int)(p3)), "S"((int)(p4)), "D"((int)(p5)) \ : "memory"); \ @@ -62,24 +64,18 @@ /** * DECLARATIONS */ +DECL_SYSCALL0(halt); + DECL_SYSCALL1(write, char *); DECL_SYSCALL1(read, char *); -DECL_SYSCALL1(writec, char); - -DECL_SYSCALL0(readc); - - -/** - * DEFINITIONS - */ -DEFN_SYSCALL1(write, 1, char *); +DECL_SYSCALL1(writec, char *); -DEFN_SYSCALL1(read, 2, char *); +DECL_SYSCALL1(readc, char *); -DEFN_SYSCALL1(writec, 3, char); +DECL_SYSCALL1(paging_alloc, uint32_t); -DEFN_SYSCALL0(readc, 4); +DECL_SYSCALL2(paging_free, uint32_t, uint32_t); #endif |