From 5cac9acd3aedc8043d4272d93c56805c46ff6214 Mon Sep 17 00:00:00 2001 From: Alex AUVOLAT Date: Tue, 1 May 2012 12:20:45 +0200 Subject: Some cleanup ; relocated the kernel at 0xC0000000 --- .gitignore | 2 +- Makefile | 13 +- README | 7 +- bochs.cfg | 4 +- copy_fdd.sh | 2 +- doc/directories.txt | 19 +-- doc/memlayout.txt | 18 ++- doc/messaging.txt | 48 ------- doc/roadmap.txt | 22 ++-- doc/syscalls.txt | 32 ----- menu_fdd.cfg | 2 +- src/common.make | 2 +- src/common/Makefile | 8 ++ src/common/include/stdlib.h | 14 ++ src/common/include/string.h | 14 ++ src/common/include/types.h | 17 +++ src/common/string.c | 80 +++++++++++ src/include/gc/mem.h | 9 -- src/include/gc/shm.h | 16 --- src/include/gc/syscall.h | 43 ------ src/include/mutex.h | 15 --- src/include/stdlib.h | 12 -- src/include/string.h | 18 --- src/kernel/Makefile | 9 +- src/kernel/config.h | 8 +- src/kernel/core/kmain.c | 10 +- src/kernel/core/loader_.asm | 8 +- src/kernel/core/monitor.c | 4 +- src/kernel/core/sys.c | 4 +- src/kernel/ipc/shm.c | 100 -------------- src/kernel/ipc/shm.h | 22 ---- src/kernel/lib/stdlib.c | 39 ------ src/kernel/lib/stdlib.h | 15 --- src/kernel/lib/types.h | 15 --- src/kernel/link.ld | 12 +- src/kernel/mem/heap.basic.h | 2 +- src/kernel/mem/heap.std.c | 6 +- src/kernel/mem/heap.std.h | 2 +- src/kernel/mem/mem.c | 4 +- src/kernel/mem/mem.h | 4 + src/kernel/mem/paging.c | 24 ++-- src/kernel/task/syscall.c | 4 - src/kernel/task/task.c | 6 +- src/library/Makefile | 12 -- src/library/gc/mem.c | 262 ------------------------------------- src/library/gc/shm.c | 100 -------------- src/library/gc/syscall.c | 68 ---------- src/library/link.ld | 27 ---- src/library/start.c | 8 -- src/library/std/mutex.c | 22 ---- src/library/std/stdio.c | 51 -------- src/library/std/string.c | 79 ----------- src/modules/test/Makefile | 8 -- src/modules/test/main.c | 40 ------ src/user/app_common.make | 6 + src/user/lib/Makefile | 12 ++ src/user/lib/include/mutex.h | 15 +++ src/user/lib/include/tce/mem.h | 9 ++ src/user/lib/include/tce/syscall.h | 21 +++ src/user/lib/start.c | 8 ++ src/user/lib/std/mutex.c | 22 ++++ src/user/lib/std/stdio.c | 51 ++++++++ src/user/lib/tce/mem.c | 262 +++++++++++++++++++++++++++++++++++++ src/user/lib/tce/syscall.c | 68 ++++++++++ src/user/link.ld | 26 ++++ src/user/test/Makefile | 6 + src/user/test/main.c | 40 ++++++ 67 files changed, 791 insertions(+), 1147 deletions(-) delete mode 100644 doc/messaging.txt create mode 100644 src/common/Makefile create mode 100644 src/common/include/stdlib.h create mode 100644 src/common/include/string.h create mode 100644 src/common/include/types.h create mode 100644 src/common/string.c delete mode 100644 src/include/gc/mem.h delete mode 100644 src/include/gc/shm.h delete mode 100644 src/include/gc/syscall.h delete mode 100644 src/include/mutex.h delete mode 100644 src/include/stdlib.h delete mode 100644 src/include/string.h delete mode 100644 src/kernel/ipc/shm.c delete mode 100644 src/kernel/ipc/shm.h delete mode 100644 src/kernel/lib/stdlib.c delete mode 100644 src/kernel/lib/stdlib.h delete mode 100644 src/kernel/lib/types.h delete mode 100644 src/library/Makefile delete mode 100644 src/library/gc/mem.c delete mode 100644 src/library/gc/shm.c delete mode 100644 src/library/gc/syscall.c delete mode 100644 src/library/link.ld delete mode 100644 src/library/start.c delete mode 100644 src/library/std/mutex.c delete mode 100644 src/library/std/stdio.c delete mode 100644 src/library/std/string.c delete mode 100644 src/modules/test/Makefile delete mode 100644 src/modules/test/main.c create mode 100644 src/user/app_common.make create mode 100644 src/user/lib/Makefile create mode 100644 src/user/lib/include/mutex.h create mode 100644 src/user/lib/include/tce/mem.h create mode 100644 src/user/lib/include/tce/syscall.h create mode 100644 src/user/lib/start.c create mode 100644 src/user/lib/std/mutex.c create mode 100644 src/user/lib/std/stdio.c create mode 100644 src/user/lib/tce/mem.c create mode 100644 src/user/lib/tce/syscall.c create mode 100644 src/user/link.ld create mode 100644 src/user/test/Makefile create mode 100644 src/user/test/main.c diff --git a/.gitignore b/.gitignore index 66ee7db..b2dfd6b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ *.map *.elf tmp -Grapes.fl.img +TCE.fl.img diff --git a/Makefile b/Makefile index 1da4ce5..c5667d0 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,18 @@ .PHONY: clean, mrproper, Init.rfs, floppy, commit -Projects = kernel library modules/test +Projects = common kernel user/lib user/test QemuCmd = qemu-system-i386 -Floppy = Grapes.fl.img +BasePath = $(shell pwd) +SrcPath = $(BasePath)/src + +Floppy = TCE.fl.img all: @for p in $(Projects); do \ echo ""; echo "----------------------"; \ echo "=> Building $$p"; \ - make -C src/$$p; \ + BasePath=$(BasePath) SrcPath=$(SrcPath) make -C src/$$p || exit -1; \ done rebuild: mrproper all @@ -18,14 +21,14 @@ clean: @for p in $(Projects); do \ echo ""; echo "----------------------"; \ echo "=> Cleaning $$p"; \ - make -C src/$$p clean -s; \ + BasePath=$(BasePath) SrcPath=$(SrcPath) make -C src/$$p clean -s; \ done mrproper: @for p in $(Projects); do \ echo ""; echo "----------------------"; \ echo "=> Cleaning $$p"; \ - make -C src/$$p mrproper -s; \ + BasePath=$(BasePath) SrcPath=$(SrcPath) make -C src/$$p mrproper -s; \ done commit: mrproper diff --git a/README b/README index a1e5e7e..ac7682b 100644 --- a/README +++ b/README @@ -1,5 +1,8 @@ -To compile Grapes, you will need a i586-elf gcc cross-compiler. +T/CE : Trivial/Computing Environment +Yet another hobby OS project - based on my old Grapes project. + +To compile T/CE, you will need a i586-elf gcc cross-compiler. You can find some scripts to build cross-compilers here : http://github.com/Alexis211/cross-scripts -You will also need a grub floppy named Grapes.fl.img +You will also need a grub floppy named TCE.fl.img diff --git a/bochs.cfg b/bochs.cfg index c46bba8..28318f0 100644 --- a/bochs.cfg +++ b/bochs.cfg @@ -6,7 +6,7 @@ romimage: file="/usr/share/bochs/BIOS-bochs-latest" vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest" boot: floppy floppy_bootsig_check: disabled=0 -floppya: 1_44="Grapes.fl.img", status=inserted +floppya: 1_44="TCE.fl.img", status=inserted # no floppyb ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 @@ -22,7 +22,6 @@ i440fxsupport: enabled=0 vga_update_interval: 40000 vga: extension=vbe cpu: count=1, ips=2000000, reset_on_triple_fault=1 -text_snapshot_check: enabled=0 private_colormap: enabled=0 clock: sync=none, time0=local # no cmosimage @@ -37,7 +36,6 @@ panic: action=ask error: action=report info: action=report debug: action=ignore -pass: action=fatal keyboard_type: mf keyboard_serial_delay: 250 keyboard_paste_delay: 100000 diff --git a/copy_fdd.sh b/copy_fdd.sh index d154abb..ebd53c5 100755 --- a/copy_fdd.sh +++ b/copy_fdd.sh @@ -8,7 +8,7 @@ cp menu_fdd.cfg mnt/boot/menu.cfg # copy kernel cp src/kernel/kernel.elf mnt -cp src/modules/test/test.elf mnt +cp src/user/test/test.elf mnt #echo "*** Launching a BASH shell, if you want to do any maintenance ***" #bash || exit 0 diff --git a/doc/directories.txt b/doc/directories.txt index b0adf7b..c5d3208 100644 --- a/doc/directories.txt +++ b/doc/directories.txt @@ -1,11 +1,12 @@ This file explains all the directories of the source tree : -doc documentation about the system -mnt temporary folder for mounting disk images -src source code -src/include all includable headers to be used in userland -src/include/gc Grapes Core (communication with the kernel) headers -src/include/gm Grapes Modules headers -src/kernel kernel source -src/library source and linkable objects to be used by userland applications -src/modules userland applications +doc documentation about the system +mnt temporary folder for mounting disk images +src source code +src/kernel source code for everything running in kernel-land +src/common source code for stuff (libraries) that can run in kernel or user land +src/common/inc user&kernel-shared headers +src/user source code for stuff that can run only in user land +src/user/lib userland libraries +src/user/lib/inc header files for these libraries +src/user/app userland apps diff --git a/doc/memlayout.txt b/doc/memlayout.txt index 6720d00..af760ca 100644 --- a/doc/memlayout.txt +++ b/doc/memlayout.txt @@ -1,8 +1,14 @@ -This is the memory layout of a standard service : +This is the memory layout of a standard process : +This can be changed by the app : - 0x00100000 to 0x20000000 Application's code and static data -- 0x20000000 to 0x6F000000 Application's heap -- 0x70000000 to 0x80000000 Free space, can be used for mapping device memory -- 0x80000000 to 0xD0000000 Space for mapping shared memory segments -- 0xD0000000 to 0xDF000000 Stacks (automatically allocated by kernel, size 0x8000 each) -- 0xE0000000 to 0xFFFFFFFF Kernel code and heap +- 0x20000000 to 0xB0000000 Application's heap +- 0xB0000000 to 0xBF000000 Stacks (automatically allocated by kernel, size 0x8000=32k each) +This is necessary : +- 0xC0000000 to 0xFFFFFFFF Kernel code and heap + +The beginning of the kernel code at 0xC0000000 corresponds to the linker-defined +symbol k_highhalf_addr, that is used at as many places as possible. +If this address was to be changed, it would have to be changed in two places : +- link.ld, change address of k_highhalf_addr; +- loader_.asm, update the temporary GDT structure data. diff --git a/doc/messaging.txt b/doc/messaging.txt deleted file mode 100644 index 804bb5d..0000000 --- a/doc/messaging.txt +++ /dev/null @@ -1,48 +0,0 @@ -Message passing is the technique used by processes for communicating with each other. -It is based on a few basic functions : - -= msg_register = -Registers the current process as the owner of a system channel. -System channels are aliases for PIDs (negative PIDs resolve to corresponding real PID). -They range from -1 to -255. They are allocated as follows : - from -1 to -19 : drivers - -1 = keyboard - -2 = mouse - from -20 to -29 : network services - -20 = networking subsystem (may be in several parts) - from -30 to -39 : system services - -30 = virtual file system - -31 = logger - -32 = user server - from -40 to -49 : UI services - -40 = graphic server (includes VESA driver for now) - -41 = sound server -Modules for HDD drivers, network cards, sound cards, ... do not register as devices but instead -notify of their presence to the corresponding service. - -= msg_send = -Sends a message to a process. Arguments: -- Receiver PID or system channel id -- Message data (up to 64k bytes, minimum 4 bytes) -The first 4 bytes of the message data always designate the message code (function). -The kernel may intercept some special messages (as "kill process" or stuff like that). - -= msg_info = -Gets first message in the queue for current process. -Function can block waiting for a message if asked by caller and if no other function already does it. -When it is there, return the following: -- If a message has come -- The sender PID -- The message code (first 4 bytes of data) -- The length of the data - -= msg_get = -Reads the data of the first message in the queue for current process. -Is passed a pointer where the data will be written. It is supposed that enougth memory is already allocated. - -From a kernel point of view, message passing is asynchronious, -but there also are userland functions for making them look synchronious by waiting for an answer. -Usually, message codes | 0x80000000 are answers to a message. - -Most processes, most of the time, will be in a loop waiting for messages to come. -The drivers are the principal exception to that, they instead wait for an interrupt or another hardware signal. diff --git a/doc/roadmap.txt b/doc/roadmap.txt index cf14395..dabae61 100644 --- a/doc/roadmap.txt +++ b/doc/roadmap.txt @@ -1,11 +1,11 @@ -** 0.0.4 'Cat in my heart' ** -- [OK] Userland heap (meaning kernel can give memory to processes) -- [OK] Userland helper functions for objects (server and client, shared memory segment manager) -- [OK] Basic object method for knowing if object handles another method (list methods in src/include/gm) -- [OK] A manager module that manages all other running modules (the privilege of manager is given by the kernel to the first module loaded) - -** 0.0.5 'Truth is better cold' ** -- Review privilege system -- Driver processes can ask to map physical memory in their address space -- Redo all messaging stuff, simpler. -- Keyboard driver, veryveryvery simple shell module using kbd driver and printk +T/CE is a new project with a lot of ideas and not a lot of organization. + +Stuff to do : + +- remove useless code from grapes +- clean up existing code +- reorganize directories + +- document the new syscall (Interface/Class/Object) system +- basic implementation + diff --git a/doc/syscalls.txt b/doc/syscalls.txt index 28eb636..89a1003 100644 --- a/doc/syscalls.txt +++ b/doc/syscalls.txt @@ -15,38 +15,6 @@ id=eax Name Parameters Description 6 irq_wait ebx: irq number Waits for an IRQ (requires privilege PL_DRIVER) 7 proc_priv none Returns current process privilege level 8 proc_setheap - 9 shm_create ebx: offset Create a shared memory segment at offset (ret = errcode) - ecx: length - 10 shm_delete ebx: offset Delete a shared memory segment at offset (ret = errcode) - 11 msg_register ebx: service id Registers current process as owner of a system channel (ret = errcode) - 12 msg_send ebx: receiver pid Sends a message to pid or owner of system channel - ecx: message data ptr - edx: message length - 13 msg_info ebx: answer struct ptr Get info on the first message of the queue for this process - ecx: wait? - 14 msg_get ebx: pointer to data Gets the data for first message on the queue; deletes message from queue - If a processes wishes to exit with an error code, it HAS to use process_exit. thread_exit will do nothing. -====== SYSCALL DESCRIPTION ====== - -= msg_register (10) -Parameters: requested system channel id (int) -Returns: errorcode or 0 on success -Registers current process as owner of given system channel. - -= msg_send (11) -Parameters: receiver pid (signed! int), data ptr (void*), data len (unsigned) -Returns: errorcode or 0 on success -Sends a message to given PID or owner of given system channel. - -= msg_info (12) -Parameters: pointer to answer struct (msg_info_answer*), wait for request? (bool) -Returns: nothing (all is in answer struct) -Gets info on waiting messages for current process. - -= msg_get (13) -Parameters: pointer to data struct (void*) -Returns: errorcode or 0 on failure -Gets the data for a message that is in the queue. diff --git a/menu_fdd.cfg b/menu_fdd.cfg index d9654f7..2be8686 100644 --- a/menu_fdd.cfg +++ b/menu_fdd.cfg @@ -1,5 +1,5 @@ timeout 1 -title Grapes +title T/CE kernel /kernel.elf module /test.elf diff --git a/src/common.make b/src/common.make index 6aa6e4b..438ff07 100644 --- a/src/common.make +++ b/src/common.make @@ -17,7 +17,7 @@ all: $(Out) $(Out): $(Obj) echo ""; echo "- Linking $@..." - $(LD) $(LDFLAGS) $^ -o $@ + $(LD) $(LDFLAGS) $^ -o $@ $(ExtObj) # ============== GENERAL CLEAINING PROCEDURES diff --git a/src/common/Makefile b/src/common/Makefile new file mode 100644 index 0000000..ef0f6b1 --- /dev/null +++ b/src/common/Makefile @@ -0,0 +1,8 @@ +Out = _common.o +Obj = string.o +ExtObj = + +include $(SrcPath)/common.make + +LDFLAGS += -r +CFLAGS += -I $(SrcPath)/common/include diff --git a/src/common/include/stdlib.h b/src/common/include/stdlib.h new file mode 100644 index 0000000..2c5e6dd --- /dev/null +++ b/src/common/include/stdlib.h @@ -0,0 +1,14 @@ +#ifndef _DEF_STDLIB_H +#define _DEF_STDLIB_H + +#include + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +void *memcpy(void *dest, const void *src, int count); +uint8_t *memset(uint8_t *dest, uint8_t val, int count); +uint16_t *memsetw(uint16_t *dest, uint16_t val, int count); + +#endif + diff --git a/src/common/include/string.h b/src/common/include/string.h new file mode 100644 index 0000000..a41459e --- /dev/null +++ b/src/common/include/string.h @@ -0,0 +1,14 @@ +#ifndef _DEF_STRING_H +#define _DEF_STRING_H + +// #include +#include + +int strlen(const char *str); +char *strcpy(char *dest, const char *src); +// char *strdup(const char *src); // uses malloc, that's bad +char *strchr(const char *str, char c); +char *strcat(char *dest, const char *src); +int strcmp(const char *s1, const char *s2); + +#endif diff --git a/src/common/include/types.h b/src/common/include/types.h new file mode 100644 index 0000000..ec24ce5 --- /dev/null +++ b/src/common/include/types.h @@ -0,0 +1,17 @@ +#ifndef DEF_TYPES_H +#define DEF_TYPES_H + +typedef unsigned long long uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short uint16_t; +typedef unsigned char uint8_t; +typedef long long int64_t; +typedef int int32_t; +typedef short int16_t; +typedef char int8_t; + +typedef unsigned int size_t; + +#define NULL 0 + +#endif diff --git a/src/common/string.c b/src/common/string.c new file mode 100644 index 0000000..b2ec309 --- /dev/null +++ b/src/common/string.c @@ -0,0 +1,80 @@ +#include +#include + +int strlen(const char *str) { + int i = 0; + while (str[i++]); + return i; +} + +char *strchr(const char *str, char c) { + while (*str) { + if (*str == c) return (char*)str; + str++; + } + return NULL; +} + +char *strcpy(char *dest, const char *src) { + memcpy(dest, src, strlen(src) + 1); + return (char*)src; +} + +/*char *strdup(const char *src) { + char* ret = malloc(strlen(src) + 1); + if (ret == NULL) return ret; + strcpy(ret, src); + return ret; +}*/ + +char *strcat(char *dest, const char *src) { + char *dest2 = dest; + dest2 += strlen(dest) - 1; + while (*src) { + *dest2 = *src; + src++; + dest2++; + } + *dest2 = 0; + return dest; +} + +int strcmp(const char *s1, const char *s2) { + while ((*s1) && (*s1 == *s2)) { + s1++; + s2++; + } + return (* (unsigned char*)s1 - *(unsigned char*)s2); +} + +void *memcpy(void *vd, const void *vs, int count) { + uint8_t *dest = (uint8_t*)vd, *src = (uint8_t*)vs; + uint32_t f = count % 4, n = count / 4, i; + const uint32_t* s = (uint32_t*)src; + uint32_t* d = (uint32_t*)dest; + for (i = 0; i < n; i++) { + d[i] = s[i]; + } + if (f != 0) { + for (i = count - f; i < count; i++) { + dest[i] = src[i]; + } + } + return vd; +} + +uint8_t *memset(uint8_t *dest, uint8_t val, int count) { + int i; + for (i = 0; i < count; i++) { + dest[i] = val; + } + return dest; +} + +uint16_t *memsetw(uint16_t *dest, uint16_t val, int count) { + int i; + for (i = 0; i < count; i++) { + dest[i] = val; + } + return dest; +} diff --git a/src/include/gc/mem.h b/src/include/gc/mem.h deleted file mode 100644 index 2557289..0000000 --- a/src/include/gc/mem.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef DEF_HEAP_H -#define DEF_HEAP_H - -#include "gc/syscall.h" - -void* malloc(size_t size); -void free(void* p); - -#endif diff --git a/src/include/gc/shm.h b/src/include/gc/shm.h deleted file mode 100644 index 1a3f0a1..0000000 --- a/src/include/gc/shm.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef DEF_SHM_H -#define DEF_SHM_H - -#include - -/* - * This file contains headers for the shared segment mapping manager. - */ - -void* shm_alloc(size_t size); //allocates a spot in shared memory space -void shm_free(void* p); //frees a spot - -void* shm_allocNew(size_t size); //calls shm_alloc, and maps a new segment there -void shm_freeDel(void* p); //unmaps segment and calls shm_free - -#endif diff --git a/src/include/gc/syscall.h b/src/include/gc/syscall.h deleted file mode 100644 index a8928e3..0000000 --- a/src/include/gc/syscall.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef DEF_SYSCALL_H -#define DEF_SYSCALL_H - -typedef unsigned long long uint64_t; -typedef unsigned int uint32_t; -typedef unsigned short uint16_t; -typedef unsigned char uint8_t; -typedef long long int64_t; -typedef int int32_t; -typedef short int16_t; -typedef char int8_t; - -typedef unsigned size_t; - -struct user_request { - uint32_t func, params[3], shmsize[3]; - int isBlocking; // 1 : blocking request, 0 : nonblocking request (message) - int pid; //pid of caller process -}; - -struct user_sendrequest { - uint32_t func, a, b, c; - uint32_t answeri; - int64_t answerll; - int errcode; -}; - -#define NEW_STACK_SIZE 0x8000 - -void thread_exit(); -void schedule(); -void thread_sleep(int time); -void process_exit(int retval); -void printk(char* str); -void thread_new(void (*entry)(void*), void *data); -void irq_wait(int number); -int proc_priv(); - -int proc_setheap(size_t start, size_t end); -int shm_create(size_t offset, size_t length); -int shm_delete(size_t offset); - -#endif diff --git a/src/include/mutex.h b/src/include/mutex.h deleted file mode 100644 index 50b5606..0000000 --- a/src/include/mutex.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef DEF_MUTEX_H -#define DEF_MUTEX_H - -#include - -#define MUTEX_LOCKED 1 -#define MUTEX_UNLOCKED 0 - -//A mutex is just an uint32_t - -void mutex_lock(uint32_t* mutex); //wait for mutex to be free -int mutex_lockE(uint32_t* mutex); //lock mutex only if free, returns !0 if locked, 0 if was busy -void mutex_unlock(uint32_t* mutex); - -#endif diff --git a/src/include/stdlib.h b/src/include/stdlib.h deleted file mode 100644 index 3a2b42c..0000000 --- a/src/include/stdlib.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _DEF_STDLIB_H -#define _DEF_STDLIB_H - -#define NULL 0 - -//includes malloc/free -#include - -void printk_int(int number); -void printk_hex(unsigned number); - -#endif diff --git a/src/include/string.h b/src/include/string.h deleted file mode 100644 index 24ac216..0000000 --- a/src/include/string.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _DEF_STRING_H -#define _DEF_STRING_H - -#include -#include - -void *memcpy(void *dest, const void *src, int count); -uint8_t *memset(uint8_t *dest, uint8_t val, int count); -uint16_t *memsetw(uint16_t *dest, uint16_t val, int count); - -int strlen(const char *str); -char *strcpy(char *dest, const char *src); -char *strdup(const char *src); -char *strchr(const char *str, char c); -char *strcat(char *dest, const char *src); -int strcmp(const char *s1, const char *s2); - -#endif diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 5d46325..53cfc31 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -2,14 +2,15 @@ Out = kernel.elf Obj = core/loader_.o core/kmain.o core/sys.o core/test.o \ core/monitor.o task/timer.o \ task/idt.o task/idt_.o task/task.o task/task_.o task/syscall.o task/sched.o \ - lib/stdlib.o lib/bitset.o lib/mutex.o \ + lib/bitset.o lib/mutex.o \ mem/mem.o mem/paging.o mem/gdt.o mem/heap.o mem/seg.o \ - ipc/shm.o \ linker/elf.o -include ../common.make +ExtObj = $(SrcPath)/common/_common.o -CFLAGS += -I . -I ./lib -g +include $(SrcPath)/common.make + +CFLAGS += -g -I $(SrcPath)/common/include -I . -I ./lib LDFLAGS += -T link.ld -Map kernel.map diff --git a/src/kernel/config.h b/src/kernel/config.h index 38487dc..f021d9c 100644 --- a/src/kernel/config.h +++ b/src/kernel/config.h @@ -1,9 +1,9 @@ #ifndef DEF_CONFIG_H #define DEF_CONFIG_H -#define K_OS_NAME "Grapes" -#define K_OS_VER "0.0.4" -#define K_OS_CODENAME "Cat in my heart" +#define K_OS_NAME "T/CE" +#define K_OS_VER "0.0.1" +#define K_OS_CODENAME "Nyanyanya" /* HEAP CODE TO USE : Two kernel heap implementations are available : @@ -12,4 +12,6 @@ Comment the following define to use the second version */ // #define K_USE_BASIC_HEAP + + #endif diff --git a/src/kernel/core/kmain.c b/src/kernel/core/kmain.c index 8f14843..86db4ff 100644 --- a/src/kernel/core/kmain.c +++ b/src/kernel/core/kmain.c @@ -27,12 +27,12 @@ void kmain(struct multiboot_info_t* mbd, int32_t magic) { uint32_t i; mem_placementAddr = ((size_t)&end & 0xFFFFF000) + 0x1000; - mbd->cmdline += 0xE0000000; mbd->mods_addr += 0xE0000000; + mbd->cmdline += K_HIGHHALF_ADDR; mbd->mods_addr += K_HIGHHALF_ADDR; struct module_t *mods = (struct module_t*)mbd->mods_addr; for (i = 0; i < mbd->mods_count; i++) { - mods[i].mod_start += 0xE0000000; - mods[i].mod_end += 0xE0000000; - mods[i].string += 0xE0000000; + mods[i].mod_start += K_HIGHHALF_ADDR; + mods[i].mod_end += K_HIGHHALF_ADDR; + mods[i].string += K_HIGHHALF_ADDR; if (mods[i].mod_end > mem_placementAddr) mem_placementAddr = (mods[i].mod_end & 0xFFFFF000) + 0x1000; } @@ -68,7 +68,7 @@ void kmain(struct multiboot_info_t* mbd, int32_t magic) { if (pr == 0) { monitor_write(" : Error loading\n"); } else { - monitor_write(" : OK pid:"); monitor_writeDec(pr->pid); monitor_write("\n"); + monitor_write(" : OK, pid="); monitor_writeDec(pr->pid); monitor_write("\n"); } } } diff --git a/src/kernel/core/loader_.asm b/src/kernel/core/loader_.asm index 5ee998a..07de52c 100644 --- a/src/kernel/core/loader_.asm +++ b/src/kernel/core/loader_.asm @@ -1,3 +1,4 @@ +[EXTERN k_highhalf_addr] [GLOBAL loader] ; making entry point visible to linker [EXTERN kmain] ; kmain is defined in kmain.c [EXTERN tasking_tmpStack] ; a temporary 4k stack used by tasking, and used when setting up kernel stuff @@ -30,10 +31,9 @@ loader: ;here, we load our false GDT, used for having the kernel in higher half section .text higherhalf: ; now we're running in higher half - mov esp, tasking_tmpStack+0x8000 ; set up the stack push eax ; pass Multiboot magic number - add ebx, 0xE0000000 ; update the MB info structure so that it is in the new seg + add ebx, k_highhalf_addr ; update the MB info structure so that it is in the new seg push ebx ; pass Multiboot info structure call kmain ; call kernel proper @@ -51,7 +51,7 @@ trickgdt: ; our false GDT gdt: dd 0, 0 ; null GDT entry - db 0xFF, 0xFF, 0, 0, 0, 10011010b, 11001111b, 0x20 ; kernel code segment - db 0xFF, 0xFF, 0, 0, 0, 10010010b, 11001111b, 0x20 ; kernel data segment + db 0xFF, 0xFF, 0, 0, 0, 10011010b, 11001111b, 0x40 ; kernel code segment + db 0xFF, 0xFF, 0, 0, 0, 10010010b, 11001111b, 0x40 ; kernel data segment gdt_end: diff --git a/src/kernel/core/monitor.c b/src/kernel/core/monitor.c index 0d0f5eb..ba2a6df 100644 --- a/src/kernel/core/monitor.c +++ b/src/kernel/core/monitor.c @@ -1,8 +1,10 @@ #include "monitor.h" #include "sys.h" +#include "mem/mem.h" + static int cursor_x = 0, cursor_y = 0; -static uint16_t *video_memory = (uint16_t*)0xE00B8000; +static uint16_t *video_memory = (uint16_t*)((size_t)K_HIGHHALF_ADDR + 0xB8000); static uint8_t attribute = 0x07; // 0 = background = black, 7 = foreground = white diff --git a/src/kernel/core/sys.c b/src/kernel/core/sys.c index 05a7bc5..4c53d58 100644 --- a/src/kernel/core/sys.c +++ b/src/kernel/core/sys.c @@ -1,6 +1,8 @@ #include "sys.h" #include "monitor.h" +#include "mem/mem.h" + /* These four functions are wrappers around ASM operations. These functions are used when comunicating with the system hardware. */ @@ -27,7 +29,7 @@ uint16_t inw(uint16_t port) { ////// void stack_trace(size_t bp) { uint32_t *stack = (uint32_t*)bp, i; - for (i = 0; i < 5 && stack > 0xE0000000 && stack < (bp + 0x8000); i++) { + for (i = 0; i < 5 && stack > K_HIGHHALF_ADDR && stack < (bp + 0x8000); i++) { monitor_write("| "); monitor_writeHex(stack); monitor_write("\tnext:"); monitor_writeHex(stack[0]); monitor_write("\t\tret:"); monitor_writeHex(stack[1]); monitor_write("\n"); diff --git a/src/kernel/ipc/shm.c b/src/kernel/ipc/shm.c deleted file mode 100644 index 6e48613..0000000 --- a/src/kernel/ipc/shm.c +++ /dev/null @@ -1,100 +0,0 @@ -#include "shm.h" -#include -#include -#include -#include - -static struct segment_map* shmseg_map(struct segment* seg, struct page_directory *pagedir, size_t offset); -static void shmseg_unmap(struct segment_map*); -static void shmseg_delete(struct segment *seg); -static int shmseg_handleFault(struct segment_map *map, size_t addr, int write); - -/* Call this function when creating a new shared memory segment. - Creates the shmseg struct and segment struct, fills them in. */ -struct segment* shmseg_make(size_t len, struct process* owner) { - struct shmseg *ss = kmalloc(sizeof(struct shmseg)); - struct segment *se = kmalloc(sizeof(struct segment)); - unsigned i; - se->seg_data = ss; - se->mappings = 0; - se->map = shmseg_map; - se->unmap = shmseg_unmap; - se->delete = shmseg_delete; - se->handle_fault = shmseg_handleFault; - ss->len = len; - ss->owner = owner; - ss->frames = kmalloc((len / 0x1000) * sizeof(uint32_t)); - for (i = 0; i < (len / 0x1000); i++) ss->frames[i] = 0; - return se; -} - -/* For internal use only. Called when the shared memory is mapped somewhere. - Creates the segment_map struct and fills it up. */ -struct segment_map *shmseg_map(struct segment *seg, struct page_directory *pagedir, size_t offset) { - struct segment_map *sm = kmalloc(sizeof(struct segment_map)); - sm->start = offset; - sm->len = ((struct shmseg*)(seg->seg_data))->len; - return sm; -} - -/* For internal use only. Called when the shared memory is unmapped from somewhere. - Unmaps all the pages from that place. */ -void shmseg_unmap(struct segment_map *sm) { - size_t i; - for (i = 0; i < sm->len; i += 0x1000) { - struct page *page = pagedir_getPage(sm->pagedir, sm->start + i, 0); - if (page != 0) page_unmap(page); - } -} - -/* For internal use only. Called when a page fault occurs. - Maps a page at that place, possibly requesting a free frame first. */ -int shmseg_handleFault(struct segment_map *sm, size_t addr, int write) { - struct shmseg *ss = sm->seg->seg_data; - addr &= 0xFFFFF000; - struct page *p = pagedir_getPage(sm->pagedir, addr, 1); - if (p->frame != 0) return 1; - int frame_idx = (addr - sm->start) / 0x1000; - if (ss->frames[frame_idx] == 0) { - ss->frames[frame_idx] = frame_alloc(); - } - page_map(p, ss->frames[frame_idx], 1, 1); - return 0; -} - -/* For internal use only. Called when the shared memory is deleted. - Frees all the frames. */ -void shmseg_delete(struct segment *seg) { - struct shmseg *ss = seg->seg_data; - unsigned i; - for (i = 0; i < (ss->len / 0x1000); i++) { - if (ss->frames[i] != 0) frame_free(ss->frames[i]); - } - kfree(ss->frames); -} - -/* Looks through the mapped segment for a process, looking for a shared memory segment at given offset. */ -struct segment_map* shmseg_getByOff(struct process* pr, size_t offset) { - struct segment_map* m = pr->pagedir->mappedSegs; - while (m != 0) { - if (m->start == offset && m->seg->delete == shmseg_delete) return m; - m = m->next; - } - return 0; -} - -// **** **** SHM syscalls **** **** -int shm_create(size_t offset, size_t len) { - if (offset >= 0xE0000000) return -1; - if (len >= 0x10000000) return -1; - if (offset+len >= 0xE0000000) return -1; - seg_map(shmseg_make(len, current_thread->process), current_thread->process->pagedir, offset); - return 0; -} - -int shm_delete(size_t offset) { - struct segment_map *s = shmseg_getByOff(current_thread->process, offset); - if (s == 0) return -1; - seg_unmap(s); - return 0; -} diff --git a/src/kernel/ipc/shm.h b/src/kernel/ipc/shm.h deleted file mode 100644 index 5459dbb..0000000 --- a/src/kernel/ipc/shm.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef DEF_SHM_H -#define DEF_SHM_H - -#include - -struct shmseg { - size_t len; - uint32_t *frames; - struct process* owner; -}; - -//Shared memory segment stuff -struct segment* shmseg_make(size_t len, struct process* owner); - //find a shared memory segment in current address space by its offset -struct segment_map* shmseg_getByOff(struct process* pr, size_t offset); - -//Shared memory syscalls -int shm_create(size_t offset, size_t len); -int shm_delete(size_t offset); - -#endif - diff --git a/src/kernel/lib/stdlib.c b/src/kernel/lib/stdlib.c deleted file mode 100644 index c5245e7..0000000 --- a/src/kernel/lib/stdlib.c +++ /dev/null @@ -1,39 +0,0 @@ -#include "stdlib.h" - -void *memcpy(void *vd, const void *vs, int count) { - uint8_t *dest = (uint8_t*)vd, *src = (uint8_t*)vs; - uint32_t f = count % 4, n = count / 4, i; - const uint32_t* s = (uint32_t*)src; - uint32_t* d = (uint32_t*)dest; - for (i = 0; i < n; i++) { - d[i] = s[i]; - } - if (f != 0) { - for (i = count - f; i < count; i++) { - dest[i] = src[i]; - } - } - return vd; -} - -uint8_t *memset(uint8_t *dest, uint8_t val, int count) { - int i; - for (i = 0; i < count; i++) { - dest[i] = val; - } - return dest; -} - -uint16_t *memsetw(uint16_t *dest, uint16_t val, int count) { - int i; - for (i = 0; i < count; i++) { - dest[i] = val; - } - return dest; -} - -int strlen(const char *str) { - int i = 0; - while (str[i++]); - return i; -} diff --git a/src/kernel/lib/stdlib.h b/src/kernel/lib/stdlib.h deleted file mode 100644 index 319cf26..0000000 --- a/src/kernel/lib/stdlib.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef DEF_STDLIB_H -#define DEF_STDLIB_H - -#include - -void *memcpy(void *dest, const void *src, int count); -uint8_t *memset(uint8_t *dest, uint8_t val, int count); -uint16_t *memsetw(uint16_t *dest, uint16_t val, int count); -int strlen(const char *str); - -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) > (b) ? (a) : (b)) - -#endif - diff --git a/src/kernel/lib/types.h b/src/kernel/lib/types.h deleted file mode 100644 index b7b19ab..0000000 --- a/src/kernel/lib/types.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef DEF_TYPES_H -#define DEF_TYPES_H - -typedef unsigned long long uint64_t; -typedef unsigned int uint32_t; -typedef unsigned short uint16_t; -typedef unsigned char uint8_t; -typedef long long int64_t; -typedef int int32_t; -typedef short int16_t; -typedef char int8_t; - -typedef unsigned int size_t; - -#endif diff --git a/src/kernel/link.ld b/src/kernel/link.ld index 1ce17cf..fcdb0bb 100644 --- a/src/kernel/link.ld +++ b/src/kernel/link.ld @@ -1,27 +1,29 @@ ENTRY (loader) SECTIONS{ + k_highhalf_addr = 0xC0000000; + . = 0x00100000; .setup : { *(.setup) } - . += 0xE0000000; + . += k_highhalf_addr; - .text : AT(ADDR(.text) - 0xE0000000) { + .text : AT(ADDR(.text) - k_highhalf_addr) { *(.text) } - .rodata ALIGN (0x1000) : AT(ADDR(.rodata) - 0xE0000000) { + .rodata ALIGN (0x1000) : AT(ADDR(.rodata) - k_highhalf_addr) { *(.rodata) } - .data ALIGN (0x1000) : AT(ADDR(.data) - 0xE0000000) { + .data ALIGN (0x1000) : AT(ADDR(.data) - k_highhalf_addr) { *(.data) } - .bss : AT(ADDR(.bss) - 0xE0000000) { + .bss : AT(ADDR(.bss) - k_highhalf_addr) { sbss = .; *(COMMON) *(.bss) diff --git a/src/kernel/mem/heap.basic.h b/src/kernel/mem/heap.basic.h index c752750..b52be4e 100644 --- a/src/kernel/mem/heap.basic.h +++ b/src/kernel/mem/heap.basic.h @@ -3,7 +3,7 @@ /* This heap implementation is extra-simple and extra-slow. */ -#include "types.h" +#include #define HH_FREE_MAGIC 0xFEE0FEE0 #define HH_ALLOC_MAGIC 0xA110A110 diff --git a/src/kernel/mem/heap.std.c b/src/kernel/mem/heap.std.c index 5b2d025..84c11e2 100644 --- a/src/kernel/mem/heap.std.c +++ b/src/kernel/mem/heap.std.c @@ -2,7 +2,9 @@ #include "paging.h" #include -#include +#include + +#include #define HEAP_MAGIC 0xBAD0BEEF #define HEAP_MIN_SIZE 0x4000 @@ -156,7 +158,7 @@ static void heap_contract(struct heap *heap) { /* Alocate some bytes on the heap. */ void* heap_alloc(struct heap *heap, size_t sz) { - ASSERT(heap > 0xE0000000); + ASSERT(heap > K_HIGHHALF_ADDR); size_t newsize = sz + sizeof(struct heap_header) + sizeof(struct heap_footer); uint32_t iterator = 0; diff --git a/src/kernel/mem/heap.std.h b/src/kernel/mem/heap.std.h index fa146ae..2018508 100644 --- a/src/kernel/mem/heap.std.h +++ b/src/kernel/mem/heap.std.h @@ -6,7 +6,7 @@ The heap algorithm used is based on the one described here : http://www.jamesmolloy.co.uk/tutorial_html/7.-The%20Heap.html */ -#include "types.h" +#include struct heap_header { uint32_t magic; diff --git a/src/kernel/mem/mem.c b/src/kernel/mem/mem.c index c6494b7..8d814e4 100644 --- a/src/kernel/mem/mem.c +++ b/src/kernel/mem/mem.c @@ -11,6 +11,8 @@ #include "heap.std.h" #endif +#include "mem.h" + #define FREEPAGESTOKEEP 5 #define KHEAP_IDXSIZE 0x4000 // only used with heap.std.h @@ -50,7 +52,7 @@ static void get_free_pages() { mem_placementAddr += 0x1000; } freepages[freepagecount].virt = (size_t)kmalloc(0x1000); - freepages[freepagecount].phys = freepages[freepagecount].virt - 0xE0000000; + freepages[freepagecount].phys = freepages[freepagecount].virt - K_HIGHHALF_ADDR; freepagecount++; } } diff --git a/src/kernel/mem/mem.h b/src/kernel/mem/mem.h index b372fae..093545e 100644 --- a/src/kernel/mem/mem.h +++ b/src/kernel/mem/mem.h @@ -16,5 +16,9 @@ void kheap_init(); extern size_t mem_placementAddr; extern void end; //Symbol defined by linker : end of kernel code +extern void k_highhalf_addr; // Symbol defined by linker : high half position of the kerne + // Should be at 0xC0000000 +#define K_HIGHHALF_ADDR ((size_t)(&k_highhalf_addr)) + #endif diff --git a/src/kernel/mem/paging.c b/src/kernel/mem/paging.c index 4e5f33a..3e2bffa 100644 --- a/src/kernel/mem/paging.c +++ b/src/kernel/mem/paging.c @@ -7,6 +7,8 @@ #include #include +#define FIRST_KERNEL_PAGETABLE (K_HIGHHALF_ADDR >> 22) + static struct bitset frames; struct page_directory *kernel_pagedir, *current_pagedir; @@ -27,7 +29,7 @@ void frame_free(uint32_t id) { /************************* PAGING INITIALIZATION *****************************/ /* This function creates the kernel page directory. It must be called before the GDT is loaded. - It maps 0xE0000000+ to the corresponding physical kernel code, but it also maps + It maps 0xC0000000+ (k_highhalf_addr) to the corresponding physical kernel code, but it also maps 0x00000000+ to that code because with the false GDT we set up in loader_.asm, the code will be looked for at the beginning of the memory. Only when the real GDT is loaded we can de-allocate pages at 0x00000000 ; this is done by paging_cleanup. */ @@ -45,12 +47,12 @@ void paging_init(size_t totalRam) { kernel_pagedir->tablesPhysical[i] = 0; } - for (i = 0xE0000000; i < mem_placementAddr; i += 0x1000) { + for (i = K_HIGHHALF_ADDR; i < mem_placementAddr; i += 0x1000) { page_map(pagedir_getPage(kernel_pagedir, i, 1), frame_alloc(), 0, 0); } - for (i = 0; i < (mem_placementAddr - 0xE0000000) / 0x100000; i++) { - kernel_pagedir->tablesPhysical[i] = kernel_pagedir->tablesPhysical[i + 896]; - kernel_pagedir->tables[i] = kernel_pagedir->tables[i + 896]; + for (i = 0; i < (mem_placementAddr - K_HIGHHALF_ADDR) / 0x100000; i++) { + kernel_pagedir->tablesPhysical[i] = kernel_pagedir->tablesPhysical[i + FIRST_KERNEL_PAGETABLE]; + kernel_pagedir->tables[i] = kernel_pagedir->tables[i + FIRST_KERNEL_PAGETABLE]; } monitor_write("{PD: "); @@ -61,8 +63,8 @@ void paging_init(size_t totalRam) { /* De-allocates pages at 0x00000000 where kernel code was read from with the GDT from loader_.asm. */ void paging_cleanup() { - uint32_t i; - for (i = 0; i < (mem_placementAddr - 0xE0000000) / 0x100000; i++) { + size_t i; + for (i = 0; i < (mem_placementAddr - K_HIGHHALF_ADDR) / 0x100000; i++) { kernel_pagedir->tablesPhysical[i] = 0; kernel_pagedir->tables[i] = 0; } @@ -94,7 +96,7 @@ struct page_directory *pagedir_new() { pd->tables[i] = 0; pd->tablesPhysical[i] = 0; } - for (i = 896; i < 1024; i++) { + for (i = FIRST_KERNEL_PAGETABLE; i < 1024; i++) { pd->tables[i] = kernel_pagedir->tables[i]; pd->tablesPhysical[i] = kernel_pagedir->tablesPhysical[i]; } @@ -108,7 +110,7 @@ void pagedir_delete(struct page_directory *pd) { //Unmap segments while (pd->mappedSegs != 0) seg_unmap(pd->mappedSegs); //Cleanup page tables - for (i = 0; i < 896; i++) { + for (i = 0; i < FIRST_KERNEL_PAGETABLE; i++) { kfree_page(pd->tables[i]); } kfree_page(pd->tablesPhysical); @@ -130,7 +132,7 @@ uint32_t paging_fault(struct registers *regs) { } if (seg != 0) { - if (seg->seg->handle_fault(seg, addr, (regs->err_code & 0x2) && (regs->eip < 0xE0000000)) != 0) seg = 0; + if (seg->seg->handle_fault(seg, addr, (regs->err_code & 0x2) && (regs->eip < K_HIGHHALF_ADDR)) != 0) seg = 0; } if (seg == 0) { @@ -158,7 +160,7 @@ struct page *pagedir_getPage(struct page_directory *pd, uint32_t address, int ma return &pd->tables[table_idx]->pages[address % 1024]; } else if (make) { pd->tables[table_idx] = kmalloc_page(pd->tablesPhysical + table_idx); - if (table_idx >= 896) + if (table_idx >= FIRST_KERNEL_PAGETABLE) tasking_updateKernelPagetable(table_idx, pd->tables[table_idx], pd->tablesPhysical[table_idx]); memset((uint8_t*)pd->tables[table_idx], 0, 0x1000); pd->tablesPhysical[table_idx] |= 0x07; diff --git a/src/kernel/task/syscall.c b/src/kernel/task/syscall.c index 3ae546f..5d40596 100644 --- a/src/kernel/task/syscall.c +++ b/src/kernel/task/syscall.c @@ -23,8 +23,6 @@ CALL1(monitor_write, printk_sc); CALL1V(idt_waitIrq, irq_wait_sc); CALL0(proc_priv, proc_priv_sc); CALL2(process_setheapseg, proc_setheap_sc); -CALL2(shm_create, shm_create_sc); -CALL1(shm_delete, shm_delete_sc); static void thread_new_sc(struct registers* r) { cli(); @@ -42,6 +40,4 @@ int_callback syscalls[NUMBER_OF_SYSCALLS] = { irq_wait_sc, proc_priv_sc, proc_setheap_sc, - shm_create_sc, - shm_delete_sc, //10 0 }; diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c index 3d322c1..a6becdb 100644 --- a/src/kernel/task/task.c +++ b/src/kernel/task/task.c @@ -42,7 +42,7 @@ void tasking_init() { monitor_write("[Tasking] "); } -/* Called by the paging functions when a page table is allocated in the kernel space (>0xE0000000). +/* Called by the paging functions when a page table is allocated in the kernel space (>K_HIGHHALF_ADDR). Updates the page directories of all the processes. */ void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint32_t tablephysical) { if (idx < 896) return; @@ -103,7 +103,7 @@ uint32_t tasking_handleException(struct registers *regs) { "Page Fault","Unknown Interrupt","Coprocessor Fault","Alignment Check","Machine Check"}; monitor_write(exception_messages[regs->int_no]); monitor_write("'\teip:"); monitor_writeHex(regs->eip); - if (regs->eip >= 0xE0000000) { + if (regs->eip >= K_HIGHHALF_ADDR) { monitor_write("\n Exception stack trace :\n"); stack_trace(regs->ebp); PANIC("Kernel error'd."); @@ -342,7 +342,7 @@ static void process_delete(struct process *pr) { /* System call. Called by the app to define the place for the heap. */ int process_setheapseg(size_t start, size_t end) { //syscall struct process *p = current_thread->process; - if (start >= 0xE0000000 || end >= 0xE0000000) return -1; + if (start >= K_HIGHHALF_ADDR || end >= K_HIGHHALF_ADDR) return -1; if (p->heapseg == 0) { struct segment *s = simpleseg_make(start, end - start, 1); if (s == 0) return -5; diff --git a/src/library/Makefile b/src/library/Makefile deleted file mode 100644 index 6e51efd..0000000 --- a/src/library/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -Out = grapes.o -Obj = gc/syscall.o \ - gc/mem.o gc/shm.o \ - std/mutex.o std/string.o std/stdio.o \ - start.o - -include ../common.make - -CFLAGS = -I../include - -LDFLAGS += -r - diff --git a/src/library/gc/mem.c b/src/library/gc/mem.c deleted file mode 100644 index fe243ba..0000000 --- a/src/library/gc/mem.c +++ /dev/null @@ -1,262 +0,0 @@ -#include "gc/mem.h" - -struct heap_header { - uint32_t magic; - uint32_t is_hole; - size_t size; -}; - -struct heap_footer { - uint32_t magic; - struct heap_header *header; -}; - -struct heap { - struct heap_header **idx; - uint32_t idxused; - size_t start_addr, end_addr, max_end; -}; - -int heap_create(struct heap *heap, size_t start, size_t idxsize, size_t datasize, size_t maxdatasize); -void* heap_alloc(struct heap *heap, size_t sz); -void heap_free(struct heap *heap, void* ptr); - -#define HEAP_MAGIC 0xBAD0BEEF -#define HEAP_MIN_SIZE 0x4000 - -/* ******************* GENERAL MEMORY FUNCTIONS ******************** */ - -static struct heap h; -static int heap_ok = 0; - -void* malloc(size_t size) { - if (heap_ok == 0) { - if (heap_create(&h, 0x20000000, 0x00010000, 0x00100000, 0x4F000000)) return 0; - heap_ok = 1; - } - return heap_alloc(&h, size); -} - -void free(void* p) { - if (heap_ok == 0 || (size_t)p < h.start_addr || (size_t)p > h.end_addr) return; - heap_free(&h, p); -} - -static int setheapseg (struct heap *heap, size_t start, size_t end, size_t prev_end) { //returns nonzero on error - if (heap == &h) { - return proc_setheap(start, end); - } //otherwise, something else might be done. - return -1; -} - -/* ******************* HEAP HEADER ****************** */ - -static void heapIdx_insert(struct heap *heap, struct heap_header *e) { - if ((heap->idxused + sizeof(struct heap_header*) + (size_t)heap->idx) >= heap->start_addr) return; - - uint32_t iterator = 0, pos; - while (iterator < heap->idxused && heap->idx[iterator]->size < e->size) { - if (heap->idx[iterator] == e) return; - iterator++; - } - if (iterator == heap->idxused) { - heap->idx[heap->idxused++] = e; - } else { - pos = iterator; - iterator = heap->idxused; - while (iterator > pos) { - heap->idx[iterator] = heap->idx[iterator - 1]; - iterator--; - } - heap->idxused++; - heap->idx[pos] = e; - } -} - -static void heapIdx_remove(struct heap *heap, struct heap_header *e) { - uint32_t iterator; - for (iterator = 0; iterator < heap->idxused; iterator++) { - if (heap->idx[iterator] == e) break; - } - if (iterator == heap->idxused) return; - heap->idxused--; - while (iterator < heap->idxused) { - heap->idx[iterator] = heap->idx[iterator + 1]; - iterator++; - } -} - -/* ******************** HEAP CONTENTS ********************* */ - -int heap_create(struct heap *heap, size_t start, size_t idxsize, size_t datasize, size_t maxdatasize) { - if (start & 0x0FFF) start = (start & 0xFFFFF000) + 0x1000; - - heap->start_addr = start + idxsize; - heap->end_addr = start + idxsize + datasize; - heap->max_end = start + idxsize + maxdatasize; - - if (setheapseg(heap, start, heap->end_addr, 0)) return -1; - - heap->idx = (struct heap_header**)start; - heap->idxused = 0; - - struct heap_header *hole = (struct heap_header*) heap->start_addr; - hole->size = (heap->end_addr - heap->start_addr); - hole->magic = HEAP_MAGIC; - hole->is_hole = 1; - - struct heap_footer *hole_footer = (struct heap_footer*)(heap->end_addr - sizeof(struct heap_footer)); - hole_footer->header = hole; - hole_footer->magic = HEAP_MAGIC; - - heapIdx_insert(heap, hole); - return 0; -} - -static uint32_t heap_expand(struct heap *heap, size_t quantity) { - if (quantity & 0x0FFF) { - quantity = (quantity & 0xFFFFF000) + 0x1000; - } - - if (heap->end_addr + quantity > heap->max_end) return 0; - - size_t newEnd = heap->end_addr + quantity; - - if (setheapseg(heap, (size_t)heap->idx, newEnd, heap->end_addr)) return 0; //failed to bigger segment - - struct heap_footer *last_footer = (struct heap_footer*)(heap->end_addr - sizeof(struct heap_footer)); - struct heap_header *last_header = last_footer->header; - if (last_header->is_hole) { - heapIdx_remove(heap, last_header); - last_header->size += quantity; - - last_footer = (struct heap_footer*)(newEnd - sizeof(struct heap_footer)); - last_footer->magic = HEAP_MAGIC; - last_footer->header = last_header; - - heapIdx_insert(heap, last_header); - } else { - last_header = (struct heap_header*)heap->end_addr; - last_footer = (struct heap_footer*)(newEnd - sizeof(struct heap_footer)); - - last_header->is_hole = 1; - last_header->magic = HEAP_MAGIC; - last_header->size = quantity; - - last_footer->magic = HEAP_MAGIC; - last_footer->header = last_header; - - heapIdx_insert(heap, last_header); - } - - heap->end_addr = newEnd; - - return 1; -} - -static void heap_contract(struct heap *heap) { - struct heap_footer *last_footer = (struct heap_footer*)(heap->end_addr - sizeof(struct heap_footer)); - struct heap_header *last_header = last_footer->header; - - if (last_header->is_hole == 0) return; - - size_t quantity = 0; - while ((heap->end_addr - heap->start_addr) - quantity > HEAP_MIN_SIZE && - (last_header->size - quantity) > 0x1000) - quantity += 0x1000; - if (quantity == 0) return; - - size_t newEnd = heap->end_addr - quantity; - - if (setheapseg(heap, (size_t)heap->idx, newEnd, heap->end_addr)) return; //error ocurred - - heapIdx_remove(heap, last_header); - last_header->size -= quantity; - last_footer = (struct heap_footer*)((size_t)last_footer - quantity); - last_footer->magic = HEAP_MAGIC; - last_footer->header = last_header; - heapIdx_insert(heap, last_header); - - heap->end_addr = newEnd; -} - -void* heap_alloc(struct heap *heap, size_t sz) { - size_t newsize = sz + sizeof(struct heap_header) + sizeof(struct heap_footer); - uint32_t iterator = 0; - - while (iterator < heap->idxused) { - if (heap->idx[iterator]->size >= newsize) break; - iterator++; - } - - if (iterator == heap->idxused) { //No hole is big enough - if (heap_expand(heap, (sz & 0xFFFFF000) + 0x1000) == 0) return 0; //FAILED - return heap_alloc(heap, sz); - } - - struct heap_header *loc = heap->idx[iterator]; - struct heap_footer *footer = (struct heap_footer*)((size_t)loc + loc->size - sizeof(struct heap_footer)); - loc->is_hole = 0; - heapIdx_remove(heap, loc); - - //If we have enough space to create a USEFUL new hole next to the allocated block, do it. - //If we do not, we might return a block that is a few bytes bigger than neede. - if (loc->size > (newsize + sizeof(struct heap_header) + sizeof(struct heap_footer))) { - loc->size = newsize; - - //Write footer for block we return - struct heap_footer *newfooter = (struct heap_footer*)((size_t)loc + newsize - sizeof(struct heap_footer)); - newfooter->header = loc; - newfooter->magic = HEAP_MAGIC; - - //Write header for new hole we create - struct heap_header *nextloc = (struct heap_header*)((size_t)loc + newsize); - nextloc->is_hole = 1; - nextloc->magic = HEAP_MAGIC; - nextloc->size = ((size_t)footer - (size_t)nextloc + sizeof(struct heap_footer)); - footer->header = nextloc; //Update footer - footer->magic = HEAP_MAGIC; - - heapIdx_insert(heap, nextloc); - } - - return (void*)((size_t)loc + sizeof(struct heap_header)); -} - -void heap_free(struct heap *heap, void* ptr) { - if (ptr == 0) return; - if ((size_t)ptr < heap->start_addr || (size_t)ptr > heap->end_addr) return; - - struct heap_header *header = (struct heap_header*)((size_t)ptr - sizeof(struct heap_header)); - struct heap_footer *footer = (struct heap_footer*)((size_t)header + header->size - sizeof(struct heap_footer)); - if (header->magic != HEAP_MAGIC || footer->magic != HEAP_MAGIC) return; - - //Unify left - struct heap_footer *prev_footer = (struct heap_footer*)((size_t)header - sizeof(struct heap_footer)); - if (prev_footer->magic == HEAP_MAGIC && prev_footer->header->is_hole) { - header = prev_footer->header; - heapIdx_remove(heap, header); - - footer->header = header; - header->size = ((size_t)footer - (size_t)header + sizeof(struct heap_footer)); - } - - //Unify right - struct heap_header *next_header = (struct heap_header*)((size_t)footer + sizeof(struct heap_footer)); - if (next_header->magic == HEAP_MAGIC && next_header->is_hole) { - heapIdx_remove(heap, next_header); - footer = (struct heap_footer*)((size_t)footer + next_header->size); - - footer->header = header; - header->size = ((size_t)footer - (size_t)header + sizeof(struct heap_footer)); - } - - header->is_hole = 1; - - heapIdx_insert(heap, header); - - if ((size_t)footer == (heap->end_addr - sizeof(struct heap_footer)) && - header->size >= 0x2000 && (heap->end_addr - heap->start_addr > HEAP_MIN_SIZE)) { - heap_contract(heap); - } -} diff --git a/src/library/gc/shm.c b/src/library/gc/shm.c deleted file mode 100644 index 7f8609a..0000000 --- a/src/library/gc/shm.c +++ /dev/null @@ -1,100 +0,0 @@ -#include -#include -#include - -struct shm_block { - size_t start, size; - int is_hole; //1 : hole, 0 : used block - struct shm_block *prev, *next; -}; - -struct shm_block *blocks = 0; - -static uint32_t tMutex = MUTEX_UNLOCKED; - -static void shm_init() { - struct shm_block *b = malloc(sizeof(struct shm_block)); - b->start = 0x80000000; - b->size = 0xD0000000 - 0x80000000; - b->is_hole = 1; - b->prev = b->next = 0; - blocks = b; -} - -void* shm_alloc(size_t size) { - mutex_lock(&tMutex); - if (blocks == 0) shm_init(); - if (size & 0xFFF) size = (size & 0xFFFFF000) + 0x1000; - //go through all blocks, get the one with the closest size - struct shm_block *i = blocks, *block = 0; - while (i) { - if (i->size >= size && i->is_hole == 1 && (block == 0 || i->size < block->size)) block = i; - i = i->next; - } - if (block == 0) { - mutex_unlock(&tMutex); - return 0; - } - //if the block's size is bigger, reduce it and create a new one after - if (block->size > size) { - struct shm_block *newb = malloc(sizeof(struct shm_block)); - newb->start = block->start + size; - newb->size = block->size - size; - newb->is_hole = 1; - newb->prev = block; newb->next = block->next; - block->size = size; - if (block->next != 0) block->next->prev = newb; - block->next = newb; - } - //mark block as used - block->is_hole = 0; - //return block's address - mutex_unlock(&tMutex); - return (void*)block->start; -} - -static void unify (struct shm_block *b) { - if (b->next == 0 || b->is_hole == 0 || b->next->is_hole == 0) return; - struct shm_block *n = b->next; - b->size += n->size; - if (n->next != 0) n->next->prev = b; - b->next = n->next; - free(n); -} - -void shm_free(void* p) { - mutex_lock(&tMutex); - //find block - struct shm_block *bl = blocks; - while (bl) { - if (bl->start == (size_t)p) break; - bl = bl->next; - } - if (bl == 0) { - mutex_unlock(&tMutex); - return; - } - //mark it as a hole - bl->is_hole = 1; - //unify after if possible - if (bl->next != 0 && bl->next->is_hole == 1) unify(bl); - //unify before if possible - if (bl->prev != 0 && bl->prev->is_hole == 1) unify(bl->prev); - mutex_unlock(&tMutex); -} - -void* shm_allocNew(size_t size) { - if (size & 0xFFF) size = (size & 0xFFFFF000) + 0x1000; - - void* p = shm_alloc(size); - if (shm_create((size_t)p, size) != 0) { - shm_free(p); - return 0; - } - return p; -} - -void shm_freeDel(void *p) { - shm_delete((size_t)p); - shm_free(p); -} diff --git a/src/library/gc/syscall.c b/src/library/gc/syscall.c deleted file mode 100644 index 3100dd7..0000000 --- a/src/library/gc/syscall.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include - -static int call(unsigned a, unsigned b, unsigned c, unsigned d, unsigned e, unsigned f) { - unsigned ret; - asm volatile("int $64" : "=a"(ret) : "a"(a), "b"(b), "c"(c), "d"(d), "S"(e), "D"(f)); - return ret; -} - -void thread_exit() { - call(0, 0, 0, 0, 0, 0); -} - -void schedule() { - call(1, 0, 0,0, 0, 0); -} - -void thread_sleep(int time) { - call(2, time, 0, 0, 0, 0); -} - -void process_exit(int retval) { - call(3, retval, 0, 0, 0, 0); -} - -void printk(char* str) { - call(4, (unsigned)str, 0, 0, 0, 0); -} - -//THREAD CREATION -struct thread_start_data { - void (*entry)(void*); - void *data; - void *stack; -}; -void thread_start(void *data) { - struct thread_start_data *tsd = data; - tsd->entry(tsd->data); - free(tsd->stack); - thread_exit(); -} -void thread_new(void (*entry)(void*), void *data) { - struct thread_start_data *tsd = malloc(sizeof(struct thread_start_data)); - tsd->entry = entry; - tsd->data = data; - tsd->stack = malloc(NEW_STACK_SIZE); - call(5, (unsigned)thread_start, (unsigned)tsd, (unsigned)(tsd->stack + NEW_STACK_SIZE), 0, 0); -} - -void irq_wait(int number) { - call(6, number, 0, 0, 0, 0); -} - -int proc_priv() { - return call(7, 0, 0, 0, 0, 0); -} - -int proc_setheap(size_t start, size_t end) { - return call(8, start, end, 0, 0, 0); -} - -int shm_create(size_t offset, size_t length) { - return call(9, offset, length, 0, 0, 0); -} - -int shm_delete(size_t offset) { - return call(10, offset, 0, 0, 0, 0); -} diff --git a/src/library/link.ld b/src/library/link.ld deleted file mode 100644 index be5e028..0000000 --- a/src/library/link.ld +++ /dev/null @@ -1,27 +0,0 @@ -ENTRY (start) -INPUT (grapes.o) - -SECTIONS{ - . = 0x100000; - - .text : { - *(.text) - } - - .rodata ALIGN (0x1000) :{ - *(.rodata) - } - - .data ALIGN (0x1000) : { - *(.data) - } - - .bss : { - sbss = .; - *(COMMON) - *(.bss) - ebss = .; - } - - end = .; _end = .; __end = .; -} diff --git a/src/library/start.c b/src/library/start.c deleted file mode 100644 index b3c5541..0000000 --- a/src/library/start.c +++ /dev/null @@ -1,8 +0,0 @@ -#include - -extern int main(); - -void start() { - int ret = main(); - process_exit(ret); -} diff --git a/src/library/std/mutex.c b/src/library/std/mutex.c deleted file mode 100644 index ac0ee8f..0000000 --- a/src/library/std/mutex.c +++ /dev/null @@ -1,22 +0,0 @@ -#include - -static uint32_t atomic_exchange(uint32_t* ptr, uint32_t newval) { - uint32_t r; - asm volatile("xchg (%%ecx), %%eax" : "=a"(r) : "c"(ptr), "a"(newval)); - return r; -} - -void mutex_lock(uint32_t* mutex) { - while (atomic_exchange(mutex, MUTEX_LOCKED) == MUTEX_LOCKED) { - thread_sleep(1); - } -} - -int mutex_lockE(uint32_t* mutex) { - if (atomic_exchange(mutex, MUTEX_LOCKED) == MUTEX_LOCKED) return 0; - return 1; -} - -void mutex_unlock(uint32_t* mutex) { - *mutex = MUTEX_UNLOCKED; -} diff --git a/src/library/std/stdio.c b/src/library/std/stdio.c deleted file mode 100644 index 3b24da1..0000000 --- a/src/library/std/stdio.c +++ /dev/null @@ -1,51 +0,0 @@ -#include - -void printk_int(int number) { - if (number == 0) { - printk("0"); - return; - } - int negative = 0; - if (number < 0) { - negative = 1; - number = 0 - number; - } - int order = 0, temp = number, i; - char numbers[] = "0123456789"; - while (temp > 0) { - order++; - temp /= 10; - } - - char *s, *r; - s = malloc(order + (negative ? 2 : 1)); - if (negative) { - s[0] = '-'; - r = s + 1; - } else { - r = s; - } - - for (i = order; i > 0; i--) { - r[i - 1] = numbers[number % 10]; - number /= 10; - } - r[order] = 0; - printk(s); - free(s); -} - -void printk_hex(unsigned v) { - char s[11] = {'0', 'x', 0}; - - int i; - - char hexdigits[] = "0123456789ABCDEF"; - - for (i = 0; i < 8; i++) { - s[i + 2] = (hexdigits[v >> 28]); - v = v << 4; - } - s[11] = 0; - printk(s); -} diff --git a/src/library/std/string.c b/src/library/std/string.c deleted file mode 100644 index 4c374ad..0000000 --- a/src/library/std/string.c +++ /dev/null @@ -1,79 +0,0 @@ -#include - -int strlen(const char *str) { - int i = 0; - while (str[i++]); - return i; -} - -char *strchr(const char *str, char c) { - while (*str) { - if (*str == c) return (char*)str; - str++; - } - return NULL; -} - -char *strcpy(char *dest, const char *src) { - memcpy(dest, src, strlen(src) + 1); - return (char*)src; -} - -char *strdup(const char *src) { - char* ret = malloc(strlen(src) + 1); - if (ret == NULL) return ret; - strcpy(ret, src); - return ret; -} - -char *strcat(char *dest, const char *src) { - char *dest2 = dest; - dest2 += strlen(dest) - 1; - while (*src) { - *dest2 = *src; - src++; - dest2++; - } - *dest2 = 0; - return dest; -} - -int strcmp(const char *s1, const char *s2) { - while ((*s1) && (*s1 == *s2)) { - s1++; - s2++; - } - return (* (unsigned char*)s1 - *(unsigned char*)s2); -} - -void *memcpy(void *vd, const void *vs, int count) { - uint8_t *dest = (uint8_t*)vd, *src = (uint8_t*)vs; - uint32_t f = count % 4, n = count / 4, i; - const uint32_t* s = (uint32_t*)src; - uint32_t* d = (uint32_t*)dest; - for (i = 0; i < n; i++) { - d[i] = s[i]; - } - if (f != 0) { - for (i = count - f; i < count; i++) { - dest[i] = src[i]; - } - } - return vd; -} - -uint8_t *memset(uint8_t *dest, uint8_t val, int count) { - int i; - for (i = 0; i < count; i++) { - dest[i] = val; - } - return dest; -} - -uint16_t *memsetw(uint16_t *dest, uint16_t val, int count) { - int i; - for (i = 0; i < count; i++) { - dest[i] = val; - } - return dest; -} diff --git a/src/modules/test/Makefile b/src/modules/test/Makefile deleted file mode 100644 index 3b9ac14..0000000 --- a/src/modules/test/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -Obj = main.o -Out = test.elf - -include ../../common.make - -CFLAGS += -I ../../include - -LDFLAGS += -T ../../library/link.ld -L ../../library -Map test.map diff --git a/src/modules/test/main.c b/src/modules/test/main.c deleted file mode 100644 index 6c13e5a..0000000 --- a/src/modules/test/main.c +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include -#include - -void thread_cascade(void* d) { - int n = (int)d; - - if (d == 0) { - //printk("{#} 0 cascade element started => end\n"); - printk("{#}0end\t"); - } else { - if (n < 0) { - //printk("{#} - cascade element started\n"); - printk("{#}-\t"); - n = 0 - n; - } else { - //printk("{#} + cascade element started\n"); - printk("{#}+\t"); - } - //printk("{#} FORK + ...\n"); - printk("{#}F+\t"); - thread_new(thread_cascade, (void*)(n - 1)); - //printk("{#} FORK - ...\n"); - printk("{#}F-\t"); - thread_new(thread_cascade, (void*)(1 - n)); - //printk("{#} Thread cascade element finished.\n"); - printk("{#}end\t"); - } -} - -int main() { - printk("Hi world from test module !\n"); - - printk("{1} Creating thread cascade len:5\n"); - thread_new(thread_cascade, (void*)5); - - printk("{1} Thread now sleeping...\n"); - while (1) thread_sleep(1000); - return 0; -} diff --git a/src/user/app_common.make b/src/user/app_common.make new file mode 100644 index 0000000..8d7c8a8 --- /dev/null +++ b/src/user/app_common.make @@ -0,0 +1,6 @@ +ExtObj = $(SrcPath)/user/lib/_user.o + +include $(SrcPath)/common.make + +CFLAGS += -I $(SrcPath)/common/include -I $(SrcPath)/user/lib/include +LDFLAGS += -T $(SrcPath)/user/link.ld diff --git a/src/user/lib/Makefile b/src/user/lib/Makefile new file mode 100644 index 0000000..a4d68e7 --- /dev/null +++ b/src/user/lib/Makefile @@ -0,0 +1,12 @@ +Out = _user.o +Obj = tce/syscall.o tce/mem.o \ + std/mutex.o std/stdio.o \ + start.o +ExtObj = $(SrcPath)/common/_common.o + +include $(SrcPath)/common.make + +CFLAGS = -I$(SrcPath)/common/include -I$(SrcPath)/user/lib/include + +LDFLAGS += -r + diff --git a/src/user/lib/include/mutex.h b/src/user/lib/include/mutex.h new file mode 100644 index 0000000..a6b949b --- /dev/null +++ b/src/user/lib/include/mutex.h @@ -0,0 +1,15 @@ +#ifndef DEF_MUTEX_H +#define DEF_MUTEX_H + +#include + +#define MUTEX_LOCKED 1 +#define MUTEX_UNLOCKED 0 + +//A mutex is just an uint32_t + +void mutex_lock(uint32_t* mutex); //wait for mutex to be free +int mutex_lockE(uint32_t* mutex); //lock mutex only if free, returns !0 if locked, 0 if was busy +void mutex_unlock(uint32_t* mutex); + +#endif diff --git a/src/user/lib/include/tce/mem.h b/src/user/lib/include/tce/mem.h new file mode 100644 index 0000000..ab17bde --- /dev/null +++ b/src/user/lib/include/tce/mem.h @@ -0,0 +1,9 @@ +#ifndef DEF_HEAP_H +#define DEF_HEAP_H + +#include + +void* malloc(size_t size); +void free(void* p); + +#endif diff --git a/src/user/lib/include/tce/syscall.h b/src/user/lib/include/tce/syscall.h new file mode 100644 index 0000000..5257a02 --- /dev/null +++ b/src/user/lib/include/tce/syscall.h @@ -0,0 +1,21 @@ +#ifndef DEF_SYSCALL_H +#define DEF_SYSCALL_H + +#include + +#define NEW_STACK_SIZE 0x8000 + +void thread_exit(); +void schedule(); +void thread_sleep(int time); +void process_exit(int retval); +void printk(char* str); +void thread_new(void (*entry)(void*), void *data); +void irq_wait(int number); +int proc_priv(); + +int proc_setheap(size_t start, size_t end); +int shm_create(size_t offset, size_t length); +int shm_delete(size_t offset); + +#endif diff --git a/src/user/lib/start.c b/src/user/lib/start.c new file mode 100644 index 0000000..3dbb994 --- /dev/null +++ b/src/user/lib/start.c @@ -0,0 +1,8 @@ +#include + +extern int main(); + +void start() { + int ret = main(); + process_exit(ret); +} diff --git a/src/user/lib/std/mutex.c b/src/user/lib/std/mutex.c new file mode 100644 index 0000000..ac0ee8f --- /dev/null +++ b/src/user/lib/std/mutex.c @@ -0,0 +1,22 @@ +#include + +static uint32_t atomic_exchange(uint32_t* ptr, uint32_t newval) { + uint32_t r; + asm volatile("xchg (%%ecx), %%eax" : "=a"(r) : "c"(ptr), "a"(newval)); + return r; +} + +void mutex_lock(uint32_t* mutex) { + while (atomic_exchange(mutex, MUTEX_LOCKED) == MUTEX_LOCKED) { + thread_sleep(1); + } +} + +int mutex_lockE(uint32_t* mutex) { + if (atomic_exchange(mutex, MUTEX_LOCKED) == MUTEX_LOCKED) return 0; + return 1; +} + +void mutex_unlock(uint32_t* mutex) { + *mutex = MUTEX_UNLOCKED; +} diff --git a/src/user/lib/std/stdio.c b/src/user/lib/std/stdio.c new file mode 100644 index 0000000..3b24da1 --- /dev/null +++ b/src/user/lib/std/stdio.c @@ -0,0 +1,51 @@ +#include + +void printk_int(int number) { + if (number == 0) { + printk("0"); + return; + } + int negative = 0; + if (number < 0) { + negative = 1; + number = 0 - number; + } + int order = 0, temp = number, i; + char numbers[] = "0123456789"; + while (temp > 0) { + order++; + temp /= 10; + } + + char *s, *r; + s = malloc(order + (negative ? 2 : 1)); + if (negative) { + s[0] = '-'; + r = s + 1; + } else { + r = s; + } + + for (i = order; i > 0; i--) { + r[i - 1] = numbers[number % 10]; + number /= 10; + } + r[order] = 0; + printk(s); + free(s); +} + +void printk_hex(unsigned v) { + char s[11] = {'0', 'x', 0}; + + int i; + + char hexdigits[] = "0123456789ABCDEF"; + + for (i = 0; i < 8; i++) { + s[i + 2] = (hexdigits[v >> 28]); + v = v << 4; + } + s[11] = 0; + printk(s); +} diff --git a/src/user/lib/tce/mem.c b/src/user/lib/tce/mem.c new file mode 100644 index 0000000..e30e36b --- /dev/null +++ b/src/user/lib/tce/mem.c @@ -0,0 +1,262 @@ +#include + +struct heap_header { + uint32_t magic; + uint32_t is_hole; + size_t size; +}; + +struct heap_footer { + uint32_t magic; + struct heap_header *header; +}; + +struct heap { + struct heap_header **idx; + uint32_t idxused; + size_t start_addr, end_addr, max_end; +}; + +int heap_create(struct heap *heap, size_t start, size_t idxsize, size_t datasize, size_t maxdatasize); +void* heap_alloc(struct heap *heap, size_t sz); +void heap_free(struct heap *heap, void* ptr); + +#define HEAP_MAGIC 0xBAD0BEEF +#define HEAP_MIN_SIZE 0x4000 + +/* ******************* GENERAL MEMORY FUNCTIONS ******************** */ + +static struct heap h; +static int heap_ok = 0; + +void* malloc(size_t size) { + if (heap_ok == 0) { + if (heap_create(&h, 0x20000000, 0x00010000, 0x00100000, 0x4F000000)) return 0; + heap_ok = 1; + } + return heap_alloc(&h, size); +} + +void free(void* p) { + if (heap_ok == 0 || (size_t)p < h.start_addr || (size_t)p > h.end_addr) return; + heap_free(&h, p); +} + +static int setheapseg (struct heap *heap, size_t start, size_t end, size_t prev_end) { //returns nonzero on error + if (heap == &h) { + return proc_setheap(start, end); + } //otherwise, something else might be done. + return -1; +} + +/* ******************* HEAP HEADER ****************** */ + +static void heapIdx_insert(struct heap *heap, struct heap_header *e) { + if ((heap->idxused + sizeof(struct heap_header*) + (size_t)heap->idx) >= heap->start_addr) return; + + uint32_t iterator = 0, pos; + while (iterator < heap->idxused && heap->idx[iterator]->size < e->size) { + if (heap->idx[iterator] == e) return; + iterator++; + } + if (iterator == heap->idxused) { + heap->idx[heap->idxused++] = e; + } else { + pos = iterator; + iterator = heap->idxused; + while (iterator > pos) { + heap->idx[iterator] = heap->idx[iterator - 1]; + iterator--; + } + heap->idxused++; + heap->idx[pos] = e; + } +} + +static void heapIdx_remove(struct heap *heap, struct heap_header *e) { + uint32_t iterator; + for (iterator = 0; iterator < heap->idxused; iterator++) { + if (heap->idx[iterator] == e) break; + } + if (iterator == heap->idxused) return; + heap->idxused--; + while (iterator < heap->idxused) { + heap->idx[iterator] = heap->idx[iterator + 1]; + iterator++; + } +} + +/* ******************** HEAP CONTENTS ********************* */ + +int heap_create(struct heap *heap, size_t start, size_t idxsize, size_t datasize, size_t maxdatasize) { + if (start & 0x0FFF) start = (start & 0xFFFFF000) + 0x1000; + + heap->start_addr = start + idxsize; + heap->end_addr = start + idxsize + datasize; + heap->max_end = start + idxsize + maxdatasize; + + if (setheapseg(heap, start, heap->end_addr, 0)) return -1; + + heap->idx = (struct heap_header**)start; + heap->idxused = 0; + + struct heap_header *hole = (struct heap_header*) heap->start_addr; + hole->size = (heap->end_addr - heap->start_addr); + hole->magic = HEAP_MAGIC; + hole->is_hole = 1; + + struct heap_footer *hole_footer = (struct heap_footer*)(heap->end_addr - sizeof(struct heap_footer)); + hole_footer->header = hole; + hole_footer->magic = HEAP_MAGIC; + + heapIdx_insert(heap, hole); + return 0; +} + +static uint32_t heap_expand(struct heap *heap, size_t quantity) { + if (quantity & 0x0FFF) { + quantity = (quantity & 0xFFFFF000) + 0x1000; + } + + if (heap->end_addr + quantity > heap->max_end) return 0; + + size_t newEnd = heap->end_addr + quantity; + + if (setheapseg(heap, (size_t)heap->idx, newEnd, heap->end_addr)) return 0; //failed to bigger segment + + struct heap_footer *last_footer = (struct heap_footer*)(heap->end_addr - sizeof(struct heap_footer)); + struct heap_header *last_header = last_footer->header; + if (last_header->is_hole) { + heapIdx_remove(heap, last_header); + last_header->size += quantity; + + last_footer = (struct heap_footer*)(newEnd - sizeof(struct heap_footer)); + last_footer->magic = HEAP_MAGIC; + last_footer->header = last_header; + + heapIdx_insert(heap, last_header); + } else { + last_header = (struct heap_header*)heap->end_addr; + last_footer = (struct heap_footer*)(newEnd - sizeof(struct heap_footer)); + + last_header->is_hole = 1; + last_header->magic = HEAP_MAGIC; + last_header->size = quantity; + + last_footer->magic = HEAP_MAGIC; + last_footer->header = last_header; + + heapIdx_insert(heap, last_header); + } + + heap->end_addr = newEnd; + + return 1; +} + +static void heap_contract(struct heap *heap) { + struct heap_footer *last_footer = (struct heap_footer*)(heap->end_addr - sizeof(struct heap_footer)); + struct heap_header *last_header = last_footer->header; + + if (last_header->is_hole == 0) return; + + size_t quantity = 0; + while ((heap->end_addr - heap->start_addr) - quantity > HEAP_MIN_SIZE && + (last_header->size - quantity) > 0x1000) + quantity += 0x1000; + if (quantity == 0) return; + + size_t newEnd = heap->end_addr - quantity; + + if (setheapseg(heap, (size_t)heap->idx, newEnd, heap->end_addr)) return; //error ocurred + + heapIdx_remove(heap, last_header); + last_header->size -= quantity; + last_footer = (struct heap_footer*)((size_t)last_footer - quantity); + last_footer->magic = HEAP_MAGIC; + last_footer->header = last_header; + heapIdx_insert(heap, last_header); + + heap->end_addr = newEnd; +} + +void* heap_alloc(struct heap *heap, size_t sz) { + size_t newsize = sz + sizeof(struct heap_header) + sizeof(struct heap_footer); + uint32_t iterator = 0; + + while (iterator < heap->idxused) { + if (heap->idx[iterator]->size >= newsize) break; + iterator++; + } + + if (iterator == heap->idxused) { //No hole is big enough + if (heap_expand(heap, (sz & 0xFFFFF000) + 0x1000) == 0) return 0; //FAILED + return heap_alloc(heap, sz); + } + + struct heap_header *loc = heap->idx[iterator]; + struct heap_footer *footer = (struct heap_footer*)((size_t)loc + loc->size - sizeof(struct heap_footer)); + loc->is_hole = 0; + heapIdx_remove(heap, loc); + + //If we have enough space to create a USEFUL new hole next to the allocated block, do it. + //If we do not, we might return a block that is a few bytes bigger than neede. + if (loc->size > (newsize + sizeof(struct heap_header) + sizeof(struct heap_footer))) { + loc->size = newsize; + + //Write footer for block we return + struct heap_footer *newfooter = (struct heap_footer*)((size_t)loc + newsize - sizeof(struct heap_footer)); + newfooter->header = loc; + newfooter->magic = HEAP_MAGIC; + + //Write header for new hole we create + struct heap_header *nextloc = (struct heap_header*)((size_t)loc + newsize); + nextloc->is_hole = 1; + nextloc->magic = HEAP_MAGIC; + nextloc->size = ((size_t)footer - (size_t)nextloc + sizeof(struct heap_footer)); + footer->header = nextloc; //Update footer + footer->magic = HEAP_MAGIC; + + heapIdx_insert(heap, nextloc); + } + + return (void*)((size_t)loc + sizeof(struct heap_header)); +} + +void heap_free(struct heap *heap, void* ptr) { + if (ptr == 0) return; + if ((size_t)ptr < heap->start_addr || (size_t)ptr > heap->end_addr) return; + + struct heap_header *header = (struct heap_header*)((size_t)ptr - sizeof(struct heap_header)); + struct heap_footer *footer = (struct heap_footer*)((size_t)header + header->size - sizeof(struct heap_footer)); + if (header->magic != HEAP_MAGIC || footer->magic != HEAP_MAGIC) return; + + //Unify left + struct heap_footer *prev_footer = (struct heap_footer*)((size_t)header - sizeof(struct heap_footer)); + if (prev_footer->magic == HEAP_MAGIC && prev_footer->header->is_hole) { + header = prev_footer->header; + heapIdx_remove(heap, header); + + footer->header = header; + header->size = ((size_t)footer - (size_t)header + sizeof(struct heap_footer)); + } + + //Unify right + struct heap_header *next_header = (struct heap_header*)((size_t)footer + sizeof(struct heap_footer)); + if (next_header->magic == HEAP_MAGIC && next_header->is_hole) { + heapIdx_remove(heap, next_header); + footer = (struct heap_footer*)((size_t)footer + next_header->size); + + footer->header = header; + header->size = ((size_t)footer - (size_t)header + sizeof(struct heap_footer)); + } + + header->is_hole = 1; + + heapIdx_insert(heap, header); + + if ((size_t)footer == (heap->end_addr - sizeof(struct heap_footer)) && + header->size >= 0x2000 && (heap->end_addr - heap->start_addr > HEAP_MIN_SIZE)) { + heap_contract(heap); + } +} diff --git a/src/user/lib/tce/syscall.c b/src/user/lib/tce/syscall.c new file mode 100644 index 0000000..ae58e73 --- /dev/null +++ b/src/user/lib/tce/syscall.c @@ -0,0 +1,68 @@ +#include +#include + +static int call(unsigned a, unsigned b, unsigned c, unsigned d, unsigned e, unsigned f) { + unsigned ret; + asm volatile("int $64" : "=a"(ret) : "a"(a), "b"(b), "c"(c), "d"(d), "S"(e), "D"(f)); + return ret; +} + +void thread_exit() { + call(0, 0, 0, 0, 0, 0); +} + +void schedule() { + call(1, 0, 0,0, 0, 0); +} + +void thread_sleep(int time) { + call(2, time, 0, 0, 0, 0); +} + +void process_exit(int retval) { + call(3, retval, 0, 0, 0, 0); +} + +void printk(char* str) { + call(4, (unsigned)str, 0, 0, 0, 0); +} + +//THREAD CREATION +struct thread_start_data { + void (*entry)(void*); + void *data; + void *stack; +}; +void thread_start(void *data) { + struct thread_start_data *tsd = data; + tsd->entry(tsd->data); + free(tsd->stack); + thread_exit(); +} +void thread_new(void (*entry)(void*), void *data) { + struct thread_start_data *tsd = malloc(sizeof(struct thread_start_data)); + tsd->entry = entry; + tsd->data = data; + tsd->stack = malloc(NEW_STACK_SIZE); + call(5, (unsigned)thread_start, (unsigned)tsd, (unsigned)(tsd->stack + NEW_STACK_SIZE), 0, 0); +} + +void irq_wait(int number) { + call(6, number, 0, 0, 0, 0); +} + +int proc_priv() { + return call(7, 0, 0, 0, 0, 0); +} + +int proc_setheap(size_t start, size_t end) { + return call(8, start, end, 0, 0, 0); +} + +int shm_create(size_t offset, size_t length) { + return call(9, offset, length, 0, 0, 0); +} + +int shm_delete(size_t offset) { + return call(10, offset, 0, 0, 0, 0); +} diff --git a/src/user/link.ld b/src/user/link.ld new file mode 100644 index 0000000..95c2fc1 --- /dev/null +++ b/src/user/link.ld @@ -0,0 +1,26 @@ +ENTRY (start) + +SECTIONS{ + . = 0x100000; + + .text : { + *(.text) + } + + .rodata ALIGN (0x1000) :{ + *(.rodata) + } + + .data ALIGN (0x1000) : { + *(.data) + } + + .bss : { + sbss = .; + *(COMMON) + *(.bss) + ebss = .; + } + + end = .; _end = .; __end = .; +} diff --git a/src/user/test/Makefile b/src/user/test/Makefile new file mode 100644 index 0000000..5c8464a --- /dev/null +++ b/src/user/test/Makefile @@ -0,0 +1,6 @@ +Obj = main.o +Out = test.elf + +include $(SrcPath)/user/app_common.make + +LDFLAGS += -Map test.map diff --git a/src/user/test/main.c b/src/user/test/main.c new file mode 100644 index 0000000..14f6363 --- /dev/null +++ b/src/user/test/main.c @@ -0,0 +1,40 @@ +#include +#include +#include + +void thread_cascade(void* d) { + int n = (int)d; + + if (d == 0) { + //printk("{#} 0 cascade element started => end\n"); + printk("{#}0end\t"); + } else { + if (n < 0) { + //printk("{#} - cascade element started\n"); + printk("{#}-\t"); + n = 0 - n; + } else { + //printk("{#} + cascade element started\n"); + printk("{#}+\t"); + } + //printk("{#} FORK + ...\n"); + printk("{#}F+\t"); + thread_new(thread_cascade, (void*)(n - 1)); + //printk("{#} FORK - ...\n"); + printk("{#}F-\t"); + thread_new(thread_cascade, (void*)(1 - n)); + //printk("{#} Thread cascade element finished.\n"); + printk("{#}end\t"); + } +} + +int main() { + printk("Hi world from test module !\n"); + + printk("{1} Creating thread cascade len:4\n"); + thread_new(thread_cascade, (void*)4); + + printk("{1} Thread now sleeping...\n"); + while (1) thread_sleep(1000); + return 0; +} -- cgit v1.2.3