diff --git a/Makefile b/Makefile index 60f9d99..ad49e4f 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ GNU := $(ARCH)-linux-gnu GDB := $(GNU)-gdb QEMU := qemu-system-$(ARCH) -QEMUFLAGS += -M raspi3b -display none -serial null +QEMUFLAGS += -M raspi3b -display gtk -serial null CC := $(GNU)-gcc CCFLAGS += -Wall -Wextra -O0 \ diff --git a/include/logger.h b/include/logger.h index cb22fb7..842cbe1 100644 --- a/include/logger.h +++ b/include/logger.h @@ -47,6 +47,22 @@ static inline char *_logger_int(char *dest, int x) *dest = '\0'; return dest; } +static inline char *_logger_uint(char *dest, size_t x) +{ + char arr[12], *c = &arr[11]; + arr[11] = '\0'; + + if (x == 0) + *dest++ = '0'; + + while (x > 0) + *--c = x % 10 + '0', x /= 10; + + for (int i = 0; c[i] != '\0'; ++i) + *dest++ = c[i]; + *dest = '\0'; + return dest; +} static inline char *_logger_pointer(char *dest, void *x) { *dest++ = '*'; @@ -71,6 +87,7 @@ logger_cur = _Generic((msg), \ const char *: _logger_string, \ uint64_t : _logger_hex, \ int32_t : _logger_int, \ + size_t : _logger_uint, \ default : _logger_pointer \ )(logger_cur, msg) @@ -80,7 +97,18 @@ logger_cur = _Generic((msg), \ _I_HATE_C_LANG(val); \ } +static inline +uint64_t _r_sp() +{ + uint64_t ret; + asm volatile("mov %[a], sp" : [a] "=r" (ret)); + return ret; +} + #define FLUSH(prefix) { \ + _logger_hex(sp_cur, _r_sp()); \ + _uart_puts_sync(sp_buf); \ + _uart_puts_sync(" | "); \ _uart_puts_sync(prefix); \ _uart_puts_sync(logger_buf); \ _uart_puts_sync(ENDL); \ @@ -130,7 +158,10 @@ logger_cur = _Generic((msg), \ // #define DEBUG_INITRD(val) DEBUG(val) #define DEBUG_INITRD(val) CLEAN -#define DEBUG_THREAD(val) DEBUG(val) +// #define DEBUG_THREAD(val) DEBUG(val) +#define DEBUG_THREAD(val) CLEAN extern char logger_buf[LOGGER_BUFLEN]; extern char *logger_cur; +extern char sp_buf[LOGGER_BUFLEN]; +extern char *sp_cur; diff --git a/kernel/include/exception.h b/kernel/include/exception.h index 253088a..579ff67 100644 --- a/kernel/include/exception.h +++ b/kernel/include/exception.h @@ -1,5 +1,10 @@ #pragma once -void init_exception(void); +#include +#include + +void exception_vector_table(void); + +void exception_init(void); void not_implemented_handler(void); -void synchronous_handler(void); +void synchronous_handler(trapframe_t *regs); diff --git a/kernel/include/exec.h b/kernel/include/exec.h index 5e9d58e..980f9e8 100644 --- a/kernel/include/exec.h +++ b/kernel/include/exec.h @@ -1,3 +1,5 @@ #pragma once -void user_exec(void *text, void *sp); +#include + +void user_exec(trapframe_t *regs); diff --git a/kernel/include/initrd.h b/kernel/include/initrd.h index 5ae1c2e..04bf868 100644 --- a/kernel/include/initrd.h +++ b/kernel/include/initrd.h @@ -45,7 +45,7 @@ typedef struct file_node { typedef void (*initrd_callback_func_t)(file_node_t *); -file_node_t *initrd_init(void); +void initrd_init(void); void initrd_fdt_callback(const vector_t *props); file_node_t *initrd_get(file_node_t *root, const char *filename); void initrd_traverse(file_node_t *tr, initrd_callback_func_t func); @@ -53,3 +53,4 @@ void initrd_traverse(file_node_t *tr, initrd_callback_func_t func); extern fdt_callback_t initrd_dtb_cb; extern void *initrd_start; extern void *initrd_end; +extern file_node_t *initrd_root; diff --git a/kernel/include/interrupt.h b/kernel/include/interrupt.h index 3f976cf..e83094e 100644 --- a/kernel/include/interrupt.h +++ b/kernel/include/interrupt.h @@ -22,7 +22,6 @@ void add_interrupt_task(uint64_t priority, interrupt_callback_func_t func, uint64_t param); -void init_interrupt(void); void irq_handler(void); void wfe(void); diff --git a/kernel/include/mbox.h b/kernel/include/mbox.h index 605a549..d40cbed 100644 --- a/kernel/include/mbox.h +++ b/kernel/include/mbox.h @@ -24,7 +24,7 @@ */ /* a properly aligned buffer */ -extern volatile unsigned int mbox[36]; +// extern volatile unsigned int mbox[36]; #define MBOX_REQUEST 0 @@ -45,7 +45,7 @@ extern volatile unsigned int mbox[36]; #define MBOX_TAG_GETSERIAL 0x00010004 #define MBOX_TAG_ARM_MEMORY 0x00010005 -int mbox_call(unsigned char ch); +int mbox_call(unsigned char ch, unsigned int *mbox); unsigned int get_board_revision(void); unsigned int get_memory_base_addr(void); unsigned int get_memory_size(void); diff --git a/kernel/include/process.h b/kernel/include/process.h new file mode 100644 index 0000000..e1c93da --- /dev/null +++ b/kernel/include/process.h @@ -0,0 +1,53 @@ +#pragma once + +#include + +typedef struct { + uint64_t x0, x1; + uint64_t x2, x3; + uint64_t x4, x5; + uint64_t x6, x7; + uint64_t x8, x9; + uint64_t x10, x11; + uint64_t x12, x13; + uint64_t x14, x15; + uint64_t x16, x17; + uint64_t x18, x19; + uint64_t x20, x21; + uint64_t x22, x23; + uint64_t x24, x25; + uint64_t x26, x27; + uint64_t x28, fp; + uint64_t lr, spsr_el1; + uint64_t elr_el1; + uint64_t esr_el1; + uint64_t sp_el0; +} trapframe_t; + +struct thread; + +typedef struct process { + int32_t pid; + struct thread *th; + + int32_t exitcode; + + void *stack; + size_t stack_size; + + void *mem; + size_t mem_size; + + trapframe_t *regs; +} process_t; + +// thread_func_t, cast from +// void run_process_by_name(const char *filename) +int32_t run_process_by_name(uint64_t filename); + +// void run_process(process_t *) +int32_t run_process(uint64_t process); + +process_t *fork_process(const process_t *from); + +extern int32_t global_pid_counter; diff --git a/kernel/include/shell.h b/kernel/include/shell.h deleted file mode 100644 index b5014b7..0000000 --- a/kernel/include/shell.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include -#include - -int // is continue -shell(file_node_t *); diff --git a/kernel/include/syscall.h b/kernel/include/syscall.h new file mode 100644 index 0000000..3ddf064 --- /dev/null +++ b/kernel/include/syscall.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +void syscall_handler(trapframe_t *regs); + +int32_t sys_getpid(void); +size_t sys_uart_read(char buf[], size_t size); +size_t sys_uart_write(const char buf[], size_t size); +int32_t sys_exec(const char *name, char *const argv[]); +int32_t sys_fork(void); +void sys_exit(int32_t status); +int32_t sys_mbox_call(uint8_t ch, uint32_t *mbox); +void sys_kill(int32_t pid); diff --git a/kernel/include/thread.h b/kernel/include/thread.h index 99b26be..7430b74 100644 --- a/kernel/include/thread.h +++ b/kernel/include/thread.h @@ -2,6 +2,7 @@ #include #include +#include typedef int32_t (*thread_func_t)(uint64_t); @@ -20,21 +21,21 @@ typedef struct { uint64_t x27, x28; uint64_t fp, lr; uint64_t sp; - uint64_t sp_el0; - uint64_t elr_el1; } cpu_state_t; -typedef struct { +typedef struct thread { thread_func_t func; uint64_t param; thread_status_t status; int32_t retcode; - void *stack_pointer; + void *stack; size_t stack_size; - cpu_state_t regs; + cpu_state_t *regs; + + process_t *process; } thread_t; // thread.S diff --git a/kernel/include/timer.h b/kernel/include/timer.h index 2b8ee06..96480a9 100644 --- a/kernel/include/timer.h +++ b/kernel/include/timer.h @@ -7,7 +7,6 @@ typedef void (*task_callback_func_t)(uint64_t); typedef struct { uint64_t firing_tick; uint64_t interval; - uint64_t repeat; task_callback_func_t func; uint64_t param; @@ -20,6 +19,8 @@ typedef struct timer { task_t data; } timer_t; +void timer_init(void); + void add_timer_task(task_t task); void sleep(uint64_t ms); diff --git a/kernel/include/utils.h b/kernel/include/utils.h index 4c4fa92..7f41a16 100644 --- a/kernel/include/utils.h +++ b/kernel/include/utils.h @@ -22,7 +22,7 @@ int isspace(int); int32_t atoi32(const char *); uint32_t atoh32(const char *); -void exit(int); +void panic(int errno); #define MIN(x, y) (((x) < (y)) ? (x) : (y)) #define MAX(x, y) (((x) < (y)) ? (y) : (x)) diff --git a/kernel/lib/dtb.c b/kernel/lib/dtb.c index 0b888b4..8fb21fa 100644 --- a/kernel/lib/dtb.c +++ b/kernel/lib/dtb.c @@ -85,7 +85,7 @@ void _struct_traverse(const char *path, const vector_t *cbs) case FDT_END: return; default: - exit(ERR_UNREACHABLE); + panic(ERR_UNREACHABLE); } } traverse_struct_callback: diff --git a/kernel/exception_table.S b/kernel/lib/exception.S similarity index 84% rename from kernel/exception_table.S rename to kernel/lib/exception.S index e41b73d..7bb9557 100644 --- a/kernel/exception_table.S +++ b/kernel/lib/exception.S @@ -2,7 +2,7 @@ // save general registers to stack .macro save_all - sub sp, sp, 34 * 8 + sub sp, sp, 36 * 8 stp x0, x1, [sp, 16 * 0] stp x2, x3, [sp, 16 * 1] stp x4, x5, [sp, 16 * 2] @@ -17,22 +17,26 @@ stp x22, x23, [sp, 16 * 11] stp x24, x25, [sp, 16 * 12] stp x26, x27, [sp, 16 * 13] - stp x28, x29, [sp, 16 * 14] + stp x28, fp, [sp, 16 * 14] mrs x0, spsr_el1 mrs x1, elr_el1 mrs x2, esr_el1 - stp x0, x1, [sp, 16 * 15] - stp x2, lr, [sp, 16 * 16] + mrs x3, sp_el0 + stp lr, x0, [sp, 16 * 15] + stp x1, x2, [sp, 16 * 16] + str x3, [sp, 16 * 17] .endm // load general registers from stack .macro load_all - ldp x0, x1, [sp, 16 * 15] - ldp x2, lr, [sp, 16 * 16] + ldp lr, x0, [sp, 16 * 15] + ldp x1, x2, [sp, 16 * 16] + ldr x3, [sp, 16 * 17] msr spsr_el1, x0 msr elr_el1, x1 msr esr_el1, x2 + msr sp_el0, x3 ldp x0, x1, [sp, 16 * 0] ldp x2, x3, [sp, 16 * 1] @@ -48,9 +52,9 @@ ldp x22, x23, [sp, 16 * 11] ldp x24, x25, [sp, 16 * 12] ldp x26, x27, [sp, 16 * 13] - ldp x28, x29, [sp, 16 * 14] + ldp x28, fp, [sp, 16 * 14] - add sp, sp, 34 * 8 + add sp, sp, 36 * 8 .endm _null_handler: @@ -61,6 +65,7 @@ _null_handler: _synchronous_handler: save_all + mov x0, sp bl synchronous_handler load_all eret diff --git a/kernel/lib/exception.c b/kernel/lib/exception.c index 91c95ce..f0260ea 100644 --- a/kernel/lib/exception.c +++ b/kernel/lib/exception.c @@ -3,8 +3,10 @@ #include #include #include +#include +#include -void init_exception() +void exception_init() { asm volatile( "adr x0, exception_vector_table" ENDL @@ -18,11 +20,10 @@ void not_implemented_handler() DEBUG_EXCEP("not implemented caught"); } -void synchronous_handler() +void synchronous_handler(trapframe_t *regs) { - static int poop = 0; - if (poop++ > 10) - exit(ERR_ADMINKILL); + disable_interrupt(); + DEBUG_EXCEP("synchronous caught"); uint64_t x0 = 0x0; R_REG(x0, x0); @@ -36,5 +37,12 @@ void synchronous_handler() uint64_t esr_el1 = 0x0; R_SYSREG(esr_el1, esr_el1); - LOG(x0); LOG(spsr_el1); LOG(elr_el1); DEBUG_EXCEP(esr_el1); + LOG(x0); LOG(spsr_el1); LOG(elr_el1); DEBUG_EXCEP(esr_el1) + + switch ((esr_el1 >> 26) & 0x7f) { + case 0b010101: + syscall_handler(regs); + break; + default: + } } diff --git a/kernel/lib/exec.S b/kernel/lib/exec.S new file mode 100644 index 0000000..da76f54 --- /dev/null +++ b/kernel/lib/exec.S @@ -0,0 +1,36 @@ +.global user_exec +user_exec: + + sub sp, sp, 36 * 8 + mov x1, x0 + mov x0, sp + mov x2, 36 * 8 + bl memcpy + + ldp lr, x0, [sp, 16 * 15] + ldp x1, x2, [sp, 16 * 16] + ldr x3, [sp, 16 * 17] + msr spsr_el1, x0 + msr elr_el1, x1 + msr esr_el1, x2 + msr sp_el0, x3 + + ldp x0, x1, [sp, 16 * 0] + ldp x2, x3, [sp, 16 * 1] + ldp x4, x5, [sp, 16 * 2] + ldp x6, x7, [sp, 16 * 3] + ldp x8, x9, [sp, 16 * 4] + ldp x10, x11, [sp, 16 * 5] + ldp x12, x13, [sp, 16 * 6] + ldp x14, x15, [sp, 16 * 7] + ldp x16, x17, [sp, 16 * 8] + ldp x18, x19, [sp, 16 * 9] + ldp x20, x21, [sp, 16 * 10] + ldp x22, x23, [sp, 16 * 11] + ldp x24, x25, [sp, 16 * 12] + ldp x26, x27, [sp, 16 * 13] + ldp x28, fp, [sp, 16 * 14] + + add sp, sp, 36 * 8 + + eret diff --git a/kernel/lib/exec.c b/kernel/lib/exec.c deleted file mode 100644 index 0cb24a2..0000000 --- a/kernel/lib/exec.c +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include - -void user_exec(void *text, void *sp) -{ - // enable core timer - uint64_t cntkctl_el1 = 0x0; - R_SYSREG(cntkctl_el1, cntkctl_el1); - W_SYSREG(cntkctl_el1, cntkctl_el1 | 1); - W_SYSREG(cntp_ctl_el0, 1); - - W_SYSREG(spsr_el1, 0); - W_SYSREG(elr_el1, text); - W_SYSREG(sp_el0, sp); - asm volatile("eret"); -} diff --git a/kernel/lib/initrd.c b/kernel/lib/initrd.c index a47f94e..a2b179b 100644 --- a/kernel/lib/initrd.c +++ b/kernel/lib/initrd.c @@ -17,6 +17,8 @@ fdt_callback_t initrd_dtb_cb = { void *initrd_start = 0x0; void *initrd_end = 0x0; +file_node_t *initrd_root = 0x0; + void initrd_fdt_callback(const vector_t *props) { for (int i = 0; i < (int)props->size; ++i) { @@ -87,7 +89,7 @@ static inline void _split(file_node_t *rt, const char *s, cpio_newc_header_t *initrd_cur; -file_node_t *initrd_init(void) +void initrd_init(void) { cpio_newc_header_t *header; char *filename; @@ -128,8 +130,8 @@ file_node_t *initrd_init(void) _split(root, filename, <r, &rtr); root = _merge(ltr, _merge(newnode, rtr)); } - - return root; + + initrd_root = root; } static inline file_node_t *_node_bs(file_node_t *cur, const char *s) diff --git a/kernel/lib/interrupt.c b/kernel/lib/interrupt.c index fa6cc69..a0f9b3f 100644 --- a/kernel/lib/interrupt.c +++ b/kernel/lib/interrupt.c @@ -91,19 +91,11 @@ void add_interrupt_task(uint64_t priority, } } -void init_interrupt(void) -{ - enable_interrupt(); - _enable_timer_irq(true); -} - void irq_handler(void) { // uint64_t core0_irq_source = *CORE0_IRQ_SOURCE; // DEBUG_EXCEP(core0_irq_source); - // TODO: turnoff global interrupt - if (_irq_source_timer()) timer_irq_handler(); diff --git a/kernel/lib/kmalloc.c b/kernel/lib/kmalloc.c index 3892ee5..1be3d42 100644 --- a/kernel/lib/kmalloc.c +++ b/kernel/lib/kmalloc.c @@ -37,7 +37,7 @@ void *simple_alloc(size_t size) size = (size_t)ALIGN8(size); if ((uint64_t)_heap_top + size >= (uint64_t)&__heap_end) - exit(ERR_NO_MEM); + panic(ERR_NO_MEM); void *ret = _heap_top; _heap_top = (void *)((uint64_t)_heap_top + size); @@ -49,17 +49,19 @@ void *simple_alloc(size_t size) void *mman_alloc(size_t unit) { + LOG("mman_alloc called"); DEBUG_MEM(unit); unit = (size_t)ALIGN8(unit); if (unit > (KMALLOC_MAX_ALLOCATOR_SIZE << 3)) return allocate_page(((unit - 1) >> 12) + 1); kmalloc_allocator_t *pool = &mman_kmalloc_pool[unit >> 3]; - if (!pool->left) { - void *page = allocate_page(1), *ptr = page + sizeof(kmalloc_header_t); + if (!pool->page_begin || !pool->left) { + void *page = allocate_page(1); + *(kmalloc_header_t *)page = (kmalloc_header_t){ .unit = unit, .left = (PAGE_SIZE - sizeof(kmalloc_header_t)) / unit, - .begin = page + sizeof(kmalloc_header_t), + .begin = (void *)((uint64_t)page + sizeof(kmalloc_header_t)), .page_prev = (kmalloc_header_t *)0x0, .page_next = (kmalloc_header_t *)0x0, }; @@ -67,20 +69,31 @@ void *mman_alloc(size_t unit) .left = ((kmalloc_header_t *)page)->left, .page_begin = (kmalloc_header_t *)page, }; + LOG(page); LOG(sizeof(kmalloc_header_t)); DEBUG_MEM(pool->page_begin->begin); - for (; ptr + unit <= page + PAGE_SIZE; ptr += unit) - *(void **)ptr = ptr + unit; + uint64_t ptr = (uint64_t)page + sizeof(kmalloc_header_t); + for (; ptr + unit <= (uint64_t)page + PAGE_SIZE; ptr += unit) + *(uint64_t *)ptr = ptr + unit; } void *ret = pool->page_begin->begin; + LOG(pool); LOG(pool->page_begin); DEBUG_MEM(pool->left); + LOG(pool->page_begin->left); DEBUG_MEM(pool->page_begin->begin); pool->page_begin->begin = *(void **)pool->page_begin->begin; - --pool->left; - --pool->page_begin->left; - if (!pool->page_begin->left) - pool->page_begin = *(void **)pool->page_begin->page_next; + pool->left--; + pool->page_begin->left--; + if (!pool->left) + pool->page_begin = 0x0; + while (pool->page_begin && !pool->page_begin->left) { + pool->page_begin = pool->page_begin->page_next; + if (pool->page_begin) + pool->page_begin->page_prev = 0x0; + } LOG("mman_alloc"); LOG((uint64_t)unit); DEBUG_MEM(ret); + LOG(pool->page_begin); LOG(pool->page_begin->left); + DEBUG_MEM(pool->page_begin->begin); return ret; } @@ -91,6 +104,8 @@ void mman_free(void *ptr) return; } + return; // early return for debugging + size_t unit = PAGE_HEADER(ptr)->unit; kmalloc_allocator_t *pool = &mman_kmalloc_pool[unit >> 3]; if (!PAGE_HEADER(ptr)->left) { diff --git a/kernel/lib/mbox.c b/kernel/lib/mbox.c index a0240de..97ef397 100644 --- a/kernel/lib/mbox.c +++ b/kernel/lib/mbox.c @@ -27,7 +27,7 @@ #include /* mailbox message buffer */ -volatile unsigned int __attribute__((aligned(16))) mbox[36]; +// volatile unsigned int __attribute__((aligned(16))) mbox[36]; #define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880) #define MBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0)) @@ -49,7 +49,7 @@ volatile unsigned int __attribute__((aligned(16))) mbox[36]; /** * Make a mailbox call. Returns 0 on failure, non-zero on success */ -int mbox_call(unsigned char ch) +int mbox_call(unsigned char ch, unsigned int *mbox) { unsigned int r = (((unsigned int)((unsigned long)&mbox)&~0xF) | (ch&0xF)); /* wait until we can write to the mailbox */ @@ -57,7 +57,7 @@ int mbox_call(unsigned char ch) /* write the address of our message to the mailbox with channel identifier */ *MBOX_WRITE = r; /* now wait for the response */ - while(1) { + for (;;) { /* is there a response? */ do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_EMPTY); /* is it a response to our message? */ @@ -70,6 +70,7 @@ int mbox_call(unsigned char ch) unsigned int get_board_revision(void) { + unsigned int __attribute__((aligned(16))) mbox[36]; mbox[0] = 36 * 4; mbox[1] = MBOX_REQUEST; @@ -81,13 +82,14 @@ unsigned int get_board_revision(void) mbox[6] = MBOX_TAG_LAST; - mbox_call(MBOX_CH_PROP); + mbox_call(MBOX_CH_PROP, mbox); return mbox[5]; } unsigned int get_memory_base_addr(void) { + unsigned int __attribute__((aligned(16))) mbox[36]; mbox[0] = 36 * 4; mbox[1] = MBOX_REQUEST; @@ -100,13 +102,14 @@ unsigned int get_memory_base_addr(void) mbox[7] = MBOX_TAG_LAST; - mbox_call(MBOX_CH_PROP); + mbox_call(MBOX_CH_PROP, mbox); return mbox[5]; } unsigned int get_memory_size(void) { + unsigned int __attribute__((aligned(16))) mbox[36]; mbox[0] = 36 * 4; mbox[1] = MBOX_REQUEST; @@ -119,7 +122,7 @@ unsigned int get_memory_size(void) mbox[7] = MBOX_TAG_LAST; - mbox_call(MBOX_CH_PROP); + mbox_call(MBOX_CH_PROP, mbox); return mbox[6]; } diff --git a/kernel/lib/mman.c b/kernel/lib/mman.c index 9aee0a8..6414e76 100644 --- a/kernel/lib/mman.c +++ b/kernel/lib/mman.c @@ -66,7 +66,7 @@ void _pull(int idx, size_t sz) CUR->size = 0; break; default: - exit(ERR_UNREACHABLE); + panic(ERR_UNREACHABLE); } } @@ -96,6 +96,7 @@ void mman_init() (void *)ntoh64(entry->address) + ntoh64(entry->size)); } + reserve_page((void *)0x00000000, (void *)0x00001000); reserve_page(&__kernel_start, &__kernel_end); reserve_page(&__heap_start, &__stack_end); reserve_page(dtb_start, dtb_end); @@ -132,7 +133,7 @@ uint64_t _allocate_page(size_t req, int idx, uint64_t l, uint64_t r) case PAGE_RESERVED: return MMAN_NO_PAGE; default: - exit(ERR_UNREACHABLE); + panic(ERR_UNREACHABLE); } uint64_t ret = MMAN_NO_PAGE; @@ -162,12 +163,12 @@ uint64_t _allocate_page(size_t req, int idx, uint64_t l, uint64_t r) void *allocate_page(size_t page_cnt) { if (msb64(page_cnt) != page_cnt) - exit(ERR_INVALID_OP); + panic(ERR_INVALID_OP); uint64_t offset = _allocate_page(page_cnt, 0, 0, mman_page_cnt); if (offset == MMAN_NO_PAGE) - exit(ERR_NO_MEM); + panic(ERR_NO_MEM); // return (void *)0x0; return mman_memory_start + offset * (1 << 12); @@ -192,7 +193,7 @@ void _free_page(uint64_t req, int idx, uint64_t l, uint64_t r) break; case PAGE_RESERVED: default: - exit(ERR_UNREACHABLE); + panic(ERR_UNREACHABLE); } uint64_t m = l + ((msb64(sz) == sz) ? (sz >> 1) : msb64(sz)); @@ -206,7 +207,7 @@ void _free_page(uint64_t req, int idx, uint64_t l, uint64_t r) void free_page(void *page) { if (ALIGN4K(page) != page) - exit(ERR_INVALID_OP); + panic(ERR_INVALID_OP); uint64_t start = ((uint64_t)page - (uint64_t)mman_memory_start) >> 12; _free_page(start, 0, 0, mman_page_cnt); @@ -223,7 +224,7 @@ void _reserve_page(uint64_t ql, uint64_t qr, int idx, uint64_t l, uint64_t r) if (CUR->state == PAGE_RESERVED) return; if (CUR->state != PAGE_FREE) - exit(ERR_INVALID_MEM); + panic(ERR_INVALID_MEM); LOG("page reserved"); LOG(l); DEBUG_MEM(r); CUR->state = PAGE_RESERVED; diff --git a/kernel/lib/process.c b/kernel/lib/process.c new file mode 100644 index 0000000..00351c2 --- /dev/null +++ b/kernel/lib/process.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int32_t global_pid_counter = 0; + +static inline +process_t *_make_process(const char *filename) +{ + process_t *ret = kmalloc(sizeof(process_t)); + + file_node_t *file = initrd_get(initrd_root, filename); + if (file == 0x0) + panic(ERR_NOT_EXIST); + + *ret = (process_t){ + .pid = global_pid_counter++, + .th = 0x0, + + .exitcode = 0, + + .stack = allocate_page(256), + .stack_size = 256 << 12, + + .mem = allocate_page(256), + .mem_size = 256 << 12, + + .regs = kmalloc(sizeof(trapframe_t)), + }; + memcpy(ret->mem, file->filecontent, file->filesize); + memset(ret->regs, 0x0, sizeof(trapframe_t)); + *ret->regs = (trapframe_t){ + .spsr_el1 = 0x0, // enable all interrupt + .elr_el1 = (uint64_t)ret->mem, + .sp_el0 = ((uint64_t)ret->stack + ret->stack_size - 64), + }; + + return ret; +} + +// void run_process_by_name(const char *filename) +int32_t run_process_by_name(uint64_t param) +{ + const char *filename = (void *)param; + thread_t *th = get_current(); + + th->process = _make_process(filename); + th->process->th = th; + LOG("Run process by name"); DEBUG_THREAD(filename); + LOG(th->process->stack); DEBUG_THREAD(th->process->regs->sp_el0); + LOG(th->process->mem); DEBUG_THREAD(th->process->regs->elr_el1); + + disable_interrupt(); + user_exec(th->process->regs); + + __builtin_unreachable(); + return 0; +} + +// void run_process(process_t *) +int32_t run_process(uint64_t param) +{ + process_t *process = (void *)param; + thread_t *th = get_current(); + + th->process = process; + th->process->th = th; + LOG("Run process"); DEBUG_THREAD(process->pid); + + disable_interrupt(); + user_exec(th->process->regs); + + __builtin_unreachable(); + return 0; +} + +process_t *fork_process(const process_t *from) +{ + process_t *ret = kmalloc(sizeof(process_t)); + *ret = (process_t){ + .pid = global_pid_counter++, + .th = 0x0, + + .exitcode = from->exitcode, + + .stack = allocate_page(256), + .stack_size = 256 << 12, + + .mem = allocate_page(256), + .mem_size = 256 << 12, + + .regs = kmalloc(sizeof(trapframe_t)), + }; + memcpy(ret->stack, from->stack, from->stack_size); + memcpy(ret->mem, from->mem, from->mem_size); + *ret->regs = (trapframe_t){ + .x0 = 0, // fork return value + .fp = from->regs->fp - (uint64_t)from->stack + (uint64_t)ret->stack, + .lr = from->regs->lr - (uint64_t)from->mem + (uint64_t)ret->mem, + .sp_el0 = from->regs->sp_el0 - (uint64_t)from->stack + (uint64_t)ret->stack, + .elr_el1 = from->regs->elr_el1 - (uint64_t)from->mem + (uint64_t)ret->mem, + }; + + return ret; +} diff --git a/kernel/lib/queue.c b/kernel/lib/queue.c index fd31463..60c1ebc 100644 --- a/kernel/lib/queue.c +++ b/kernel/lib/queue.c @@ -23,14 +23,14 @@ queue_t *make_queue() uint64_t queue_back(const queue_t *queue) { if (!queue->size) - exit(ERR_OUT_OF_BOUND); + panic(ERR_OUT_OF_BOUND); return queue->end->prev->value; } uint64_t queue_front(const queue_t *queue) { if (!queue->size) - exit(ERR_OUT_OF_BOUND); + panic(ERR_OUT_OF_BOUND); return queue->begin->next->value; } @@ -63,7 +63,7 @@ void queue_push_front(queue_t *queue, uint64_t val) uint64_t queue_pop_back(queue_t *queue) { if (!queue->size) - exit(ERR_OUT_OF_BOUND); + panic(ERR_OUT_OF_BOUND); uint64_t ret = queue->end->prev->value; queue->end->prev = queue->end->prev->prev; @@ -76,7 +76,7 @@ uint64_t queue_pop_back(queue_t *queue) uint64_t queue_pop_front(queue_t *queue) { if (!queue->size) - exit(ERR_OUT_OF_BOUND); + panic(ERR_OUT_OF_BOUND); uint64_t ret = queue->begin->next->value; queue->begin->next = queue->begin->next->next; diff --git a/kernel/lib/ringbuffer.c b/kernel/lib/ringbuffer.c index db62c88..0e0f312 100644 --- a/kernel/lib/ringbuffer.c +++ b/kernel/lib/ringbuffer.c @@ -35,7 +35,7 @@ int ringbuffer_push(ringbuffer_t *buf, uint8_t val) uint8_t ringbuffer_bump(ringbuffer_t *buf) { if (buf->size == 0) - exit(ERR_INVALID_OP); + panic(ERR_INVALID_OP); uint8_t ret = *buf->read++; @@ -49,7 +49,7 @@ uint8_t ringbuffer_bump(ringbuffer_t *buf) uint8_t ringbuffer_peek(ringbuffer_t *buf) { if (buf->size == 0) - exit(ERR_INVALID_OP); + panic(ERR_INVALID_OP); return *buf->read; } diff --git a/kernel/lib/shell.c b/kernel/lib/shell.c deleted file mode 100644 index 8d29ef4..0000000 --- a/kernel/lib/shell.c +++ /dev/null @@ -1,256 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define INPUT_BUFLEN 1000 - -#define PM_PASSWORD 0x5a000000 - -#define PM_RSTC 0x3F10001c -#define PM_WDOG 0x3F100024 - -static inline -void _help (void) -{ - uart_puts( - "help : print this help menu" ENDL - "hello : print Hello World!" ENDL - "hwinfo : print hardware info" ENDL - "memalloc : alloate memory and print" ENDL - "ls : list directory contents" ENDL - "cat : concatenate files and print" ENDL - "exec : execute file in usermode" ENDL - "settimeout : pring message after a few seconds" ENDL - "time : print current time tick" ENDL - "reboot : reboot the device" ENDL - ); -} - -static inline -void _hello (void) -{ - uart_puts("hello, world" ENDL); -} - -static inline -void _hwinfo (void) -{ - uart_puts( - "hwinfo: " ENDL - "board revision: " - ); - uart_hex(get_board_revision()); - uart_puts( - ENDL - "memory base addr: " - ); - uart_hex(get_memory_base_addr()); - uart_puts( - ENDL - "memory size: " - ); - uart_hex(get_memory_size()); - uart_puts(ENDL); -} - -static inline -void _memalloc(size_t size) -{ - void *addr = kmalloc(size); - uart_puts("size: "); - uart_hex(size); - uart_puts(ENDL); - - uart_puts("addr: "); - uart_hex((uint64_t)addr); - uart_puts(ENDL); -} - -static inline -void _free(uint64_t ptr) -{ - kfree((void *)ptr); - LOG(ptr); INFOR("has been freed"); -} - -static inline -void _ls_initrd_callback(file_node_t *tr) -{ - uart_puts(tr->filename); - uart_puts(ENDL); -} - -static inline -void _ls(file_node_t *root) -{ - initrd_traverse(root, _ls_initrd_callback); -} - -static inline -void _cat(file_node_t *root, const char *filename) -{ - file_node_t *tr = initrd_get(root, filename); - if (tr) { - uart_puts((char *)tr->filecontent); - } else { - exit(ERR_NOT_EXIST); - } -} - -static inline -void _exec(file_node_t *root, const char *filename) -{ - file_node_t *tr = initrd_get(root, filename); - if (tr) { - void *userspace = allocate_page(1 << 6); - memcpy(userspace, tr->filecontent, tr->filesize); - user_exec(userspace, userspace + (1 << (12 + 6)) - 8); - kfree(userspace); - } else { - exit(ERR_NOT_EXIST); - } -} - -static inline -void _settimeout_cb_func(uint64_t args) -{ - vector_t *v = (void *)args; - uart_puts("timeout: "); - for (int i = 2; i < (int)v->size; ++i) { - uart_puts(VEC_AT(char, v, i)); - uart_puts(" "); - } - uart_puts(ENDL); -} - -static inline -void _settimeout(int32_t sec, vector_t *args) -{ - uint64_t cntpct_el0, cntfrq_el0; - R_SYSREG(cntpct_el0, cntpct_el0); - R_SYSREG(cntfrq_el0, cntfrq_el0); - - task_t task = (task_t){ - .firing_tick = cntpct_el0 + sec * cntfrq_el0, - .interval = sec * cntfrq_el0, - .repeat = 1, - - .func = _settimeout_cb_func, - .param = (uint64_t)args, - }; - add_timer_task(task); -} - -static inline -void _time() -{ - uint64_t cntpct_el0, cntfrq_el0, cntp_cval_el0, cntp_tval_el0; - R_SYSREG(cntpct_el0, cntpct_el0); - R_SYSREG(cntfrq_el0, cntfrq_el0); - R_SYSREG(cntp_cval_el0, cntp_cval_el0); - R_SYSREG(cntp_tval_el0, cntp_tval_el0); - - LOG(cntpct_el0); LOG(cntfrq_el0); LOG(cntp_cval_el0); INFOR(cntp_tval_el0); -} - -static inline -void _set(long addr, unsigned int value) { - volatile unsigned int* point = (unsigned int*)addr; - *point = value; -} - -static inline -void _reset(int tick) { // reboot after watchdog timer expire - _set(PM_RSTC, PM_PASSWORD | 0x20); // full reset - _set(PM_WDOG, PM_PASSWORD | tick); // number of watchdog tick -} - -static inline -void _reboot(void) -{ - _reset(1 << 16); -} - -char *_shell_buf = (char *)0x0; -int _shell_sz = 0; - -static inline -int _shell_operations(char ch) -{ - switch (ch) { - case 0x7f: - if (_shell_sz > 0) { - --_shell_sz; - uart_puts("\b \b"); - } - return true; - default: - } - return false; -} - -int shell(file_node_t *initrd_root) -{ - uart_puts("# "); - char ch; - _shell_buf = kmalloc(INPUT_BUFLEN * sizeof(char)); - _shell_sz = 0; - while ((ch = uart_getc()) != '\n') { - if (_shell_operations(ch)) - continue; - _shell_buf[_shell_sz++] = ch; - uart_putb((const uint8_t *)&ch, 1); - } - uart_puts(ENDL); - _shell_buf[_shell_sz] = ' '; - - vector_t *args = make_vector(0); - for (char *saveptr = 0x0, *tok = strtok_r(_shell_buf, " ", &saveptr); - tok; tok = strtok_r((char *)0x0, " ", &saveptr)) { - VEC_PUSH(args, tok); - LOG(tok); - } - // DEBUG("ENDL"); - CLEAN; - - char *cmd = args->size ? VEC_AT(char, args, 0) : (char *)0x0; - if (!strcmp(cmd, "help")) { - _help(); - } else if (!strcmp(cmd, "hello")) { - _hello(); - } else if (!strcmp(cmd, "hwinfo")) { - _hwinfo(); - } else if (!strcmp(cmd, "memalloc") && args->size >= 2) { - char *p1 = VEC_AT(char, args, 1); - _memalloc((size_t)atoi32(p1)); - } else if (!strcmp(cmd, "free") && args->size >= 2) { - char *p1 = VEC_AT(char, args, 1); - _free((uint64_t)atoh32(p1)); - } else if (!strcmp(cmd, "ls")) { - _ls(initrd_root); - } else if (!strcmp(cmd, "cat") && args->size >= 2) { - char *p1 = VEC_AT(char, args, 1); - _cat(initrd_root, p1); - } else if (!strcmp(cmd, "exec") && args->size >= 2) { - char *p1 = VEC_AT(char, args, 1); - _exec(initrd_root, p1); - } else if (!strcmp(cmd, "settimeout") && args->size >= 2) { - char *p1 = VEC_AT(char, args, 1); - _settimeout(atoi32(p1), args); - } else if (!strcmp(cmd, "time")) { - _time(); - } else if (!strcmp(cmd, "reboot")) { - _reboot(); - } - - return true; -} diff --git a/kernel/lib/syscall.c b/kernel/lib/syscall.c new file mode 100644 index 0000000..aec2ea0 --- /dev/null +++ b/kernel/lib/syscall.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include +#include + +void syscall_handler(trapframe_t *regs) +{ + thread_t *th = get_current(); + th->process->regs = regs; + + switch (regs->x8) { + case 0: // int32_t getpid(void) + regs->x0 = sys_getpid(); + break; + case 1: // size_t uart_read(char buf[], size_t size) + regs->x0 = sys_uart_read((char *)regs->x0, (size_t)regs->x1); + break; + case 2: // size_t uart_write(const char buf[], size_t size) + regs->x0 = sys_uart_write((const char *)regs->x0, (size_t)regs->x1); + break; + case 3: // int32_t exec(const char *name, char *const argv[]) + regs->x0 = sys_exec((const char *)regs->x0, (char *const *)regs->x1); + break; + case 4: // int32_t fork(void) + regs->x0 = sys_fork(); + break; + case 5: // void exit(int32_t status) + sys_exit((int)regs->x0); + break; + case 6: // int32_t mbox_call(uint8_t ch, uint32_t *mbox) + regs->x0 = sys_mbox_call((uint8_t)regs->x0, (uint32_t *)regs->x1); + break; + case 7: // void kill(int32_t pid) + sys_kill((int)regs->x0); + break; + default: + LOG("unsupported syscall"); ERROR(regs->x8); + } +} + +int32_t sys_getpid(void) +{ + thread_t *th = get_current(); + if (th->process == 0x0) + return -1; + return th->process->pid; +} + +size_t sys_uart_read(char buf[], size_t size) +{ return uart_getb_sync((uint8_t *)buf, size); } + +size_t sys_uart_write(const char buf[], size_t size) +{ return uart_putb_sync((const uint8_t *)buf, size); } + +int32_t sys_exec(const char *name, char *const argv[]) +{ return run_process_by_name((uint64_t)name); /* ignore argv for now */ } + +int32_t sys_fork(void) +{ + thread_t *cur = get_current(); + process_t *newproc = fork_process(cur->process); + run_thread(run_process, (uint64_t)newproc); + return newproc->pid; +} + +void sys_exit(int32_t status) +{ + thread_t *th = get_current(); + th->status = THREAD_STATUS_ZOMBIE; +} + +int32_t sys_mbox_call(uint8_t ch, uint32_t *mbox) +{ return mbox_call(ch, mbox); } + +void sys_kill(int32_t pid) +{ +} diff --git a/kernel/lib/thread.c b/kernel/lib/thread.c index 3f6ea4e..386ee6c 100644 --- a/kernel/lib/thread.c +++ b/kernel/lib/thread.c @@ -6,6 +6,7 @@ #include #include #include +#include queue_t *global_run_queue = 0x0; queue_t *global_wait_queue = 0x0; @@ -21,9 +22,11 @@ thread_t *get_current(void) static inline void _thread_wrapper() { + enable_interrupt(); + thread_t *cur = get_current(); - LOG("Running"); DEBUG_THREAD(cur->func); + LOG("Running thread wrapper"); DEBUG_THREAD(cur->func); cur->func(cur->param); cur->status = THREAD_STATUS_ZOMBIE; @@ -43,19 +46,26 @@ thread_t *_make_thread(thread_func_t func, uint64_t param) .status = THREAD_STATUS_RUNABLE, .retcode = 0, - .stack_pointer = allocate_page(256), + .stack = allocate_page(256), .stack_size = 256 << 12, + + .regs = kmalloc(sizeof(cpu_state_t)), + + .process = 0x0, }; - memset(&ret->regs, 0, sizeof(cpu_state_t)); - ret->regs.sp = (uint64_t)ret->stack_pointer + ret->stack_size - 64; - ret->regs.lr = (uint64_t)_thread_wrapper; - ret->regs.fp = ret->regs.sp; + memset(ret->regs, 0, sizeof(cpu_state_t)); + ret->regs->sp = (uint64_t)ret->stack + ret->stack_size - 64; + ret->regs->lr = (uint64_t)_thread_wrapper; + ret->regs->fp = ret->regs->sp; return ret; } void run_thread(thread_func_t func, uint64_t param) -{ QUEUE_PUSH_BACK(global_run_queue, _make_thread(func, param)); } +{ + // Runs before enable interrupt + QUEUE_PUSH_BACK(global_run_queue, _make_thread(func, param)); +} static inline int32_t _idle(uint64_t) @@ -63,7 +73,9 @@ int32_t _idle(uint64_t) DEBUG_THREAD("enter idle thread"); for (;;) { + enable_interrupt(); schedule(); + DEBUG_THREAD(global_gc_queue->size); // DEBUG_THREAD("back to idle thread"); } @@ -76,23 +88,20 @@ void thread_init(void) global_wait_queue = make_queue(); global_gc_queue = make_queue(); + thread_t *th = kmalloc(sizeof(thread_t)); + W_SYSREG(tpidr_el1, th); + run_thread(_idle, 0x0); } void schedule(void) { - // DEBUG_THREAD("schedule!"); disable_interrupt(); - // DEBUG_THREAD("run queue:"); - for (queue_node_t *n = global_run_queue->begin->next; - n != global_run_queue->end; - n = n->next) { + thread_t *th = get_current(), *next = 0x0; + LOG("Run thread"); LOG(global_run_queue->size); DEBUG_THREAD(th); + LOG(th->stack); DEBUG_THREAD(th->regs->sp); - // LOG(n); DEBUG_THREAD(n->value); - } - - thread_t *cur = get_current(), *next = 0x0; while (global_run_queue->size > 0 && !next) { next = QUEUE_POP_FRONT(thread_t, global_run_queue); if (next->status == THREAD_STATUS_ZOMBIE) { @@ -102,8 +111,8 @@ void schedule(void) QUEUE_PUSH_BACK(global_run_queue, next); } - if (next && cur != next) - context_switch(&cur->regs, &next->regs, next); + if (next && th != next) + context_switch(th->regs, next->regs, next); enable_interrupt(); } diff --git a/kernel/lib/timer.c b/kernel/lib/timer.c index 8ed4929..0296e06 100644 --- a/kernel/lib/timer.c +++ b/kernel/lib/timer.c @@ -11,6 +11,45 @@ timer_t *global_timer = (timer_t *)0x0; MMIO_W_HELPER(_enable_timer_irq, CORE0_TIMER_IRQ_CTRL, 0x1, 1); +static inline +task_t _make_timer_task(uint64_t interval_s, task_callback_func_t func, + uint64_t param) +{ + uint64_t cntpct_el0, cntfrq_el0; + R_SYSREG(cntpct_el0, cntpct_el0); + R_SYSREG(cntfrq_el0, cntfrq_el0); + + return (task_t){ + .firing_tick = cntpct_el0 + interval_s * cntfrq_el0, + .interval = interval_s * cntfrq_el0, + + .func = func, + .param = param, + }; +} + +static inline +void _scheduler_timeout(uint64_t) +{ + add_timer_task(_make_timer_task(1, _scheduler_timeout, 0x0)); + schedule(); +} + +void timer_init() +{ + uint64_t cntkctl_el1, cntfrq_el0; + R_SYSREG(cntkctl_el1, cntkctl_el1); + W_SYSREG(cntkctl_el1, cntkctl_el1 | 1); + W_SYSREG(cntp_ctl_el0, 1); + _enable_timer_irq(true); + + R_SYSREG(cntfrq_el0, cntfrq_el0); + W_SYSREG(cntp_tval_el0, cntfrq_el0 >> 1); + + return; + add_timer_task(_make_timer_task(1, _scheduler_timeout, 0x0)); +} + static inline uint32_t _d(timer_t *t) { return t ? t->_d : 0; } @@ -42,8 +81,10 @@ timer_t *_merge(timer_t *a, timer_t *b) static inline timer_t *_pop(timer_t *t) { - if (!t || (!t->_l && !t->_r)) + if (!t || (!t->_l && !t->_r)) { + kfree(t); return (timer_t *)0x0; + } return _merge(t->_l, t->_r); } @@ -126,6 +167,9 @@ void _timer_task_wrapper(uint64_t param) void timer_irq_handler(void) { _enable_timer_irq(false); + schedule(); + _enable_timer_irq(true); + return; uint64_t cntpct_el0; R_SYSREG(cntpct_el0, cntpct_el0); diff --git a/kernel/lib/uart.c b/kernel/lib/uart.c index 369275d..3e6144b 100644 --- a/kernel/lib/uart.c +++ b/kernel/lib/uart.c @@ -76,11 +76,13 @@ void uart_init(void) uart_readbuf = make_ringbuffer(UART_BUFLEN); uart_writebuf = make_ringbuffer(UART_BUFLEN); - _uart_enable_receive_interrupt(true); - //uint64_t ier = *AUX_MU_IER; + // _uart_enable_receive_interrupt(true); + _uart_enable_receive_interrupt(false); + _uart_enable_transmit_interrupt(false); + // uint64_t ier = *AUX_MU_IER; - uart_getb = uart_getb_async; - uart_putb = uart_putb_async; + // uart_getb = uart_getb_async; + // uart_putb = uart_putb_async; is_uart_inited = true; } @@ -203,7 +205,7 @@ void uart_puts(const char *s) size_t len = strlen(s); size_t ret = uart_putb((const uint8_t *)s, len); if (ret != len) - exit(ERR_IO_FAILED); + panic(ERR_IO_FAILED); } void uart_hex(uint64_t d) diff --git a/kernel/lib/utils.c b/kernel/lib/utils.c index 8e8a0ea..4fe9bce 100644 --- a/kernel/lib/utils.c +++ b/kernel/lib/utils.c @@ -97,7 +97,7 @@ int isupper(int c) int32_t atoi32(const char *s) { if (!s) - exit(ERR_CONVERSION); + panic(ERR_CONVERSION); int is_neg = 0; if (*s != '\0' && *s == '-') @@ -106,7 +106,7 @@ int32_t atoi32(const char *s) int32_t ret = 0; for (; *s != '\0'; ++s) { if (!isdigit(*s)) - exit(ERR_CONVERSION); + panic(ERR_CONVERSION); ret *= 10, ret += *s - '0'; } @@ -116,12 +116,12 @@ int32_t atoi32(const char *s) uint32_t atoh32(const char *s) { if (!s) - exit(ERR_CONVERSION); + panic(ERR_CONVERSION); uint32_t ret = 0; for (int i = 8; i-- && *s != '\0'; ++s) { if (!isxdigit(*s)) - exit(ERR_CONVERSION); + panic(ERR_CONVERSION); ret <<= 4, ret |= (isdigit(*s) ? *s - '0' : (isupper(*s) ? *s - 'A' + 10 : *s - 'a' + 10)); @@ -130,7 +130,7 @@ uint32_t atoh32(const char *s) return ret; } -void exit(int exit_code) +void panic(int exitcode) { static int print = 0; if (!print) { @@ -138,14 +138,14 @@ void exit(int exit_code) "OOPS! YOUR KERNEL DEAD" ENDL "ERROR CODE: " ); - uart_hex(exit_code); + uart_hex(exitcode); uart_puts(ENDL); print = 1; } asm volatile( "wfe\n" - "b exit" + "b panic" ); __builtin_unreachable(); } diff --git a/kernel/lib/vector.c b/kernel/lib/vector.c index c2af653..f9cdf82 100644 --- a/kernel/lib/vector.c +++ b/kernel/lib/vector.c @@ -21,7 +21,7 @@ vector_t *make_vector(size_t size) uint64_t vec_at(const vector_t *vec, size_t idx) { if (idx >= vec->size) - exit(ERR_OUT_OF_BOUND); + panic(ERR_OUT_OF_BOUND); return vec->data[idx]; } diff --git a/kernel/main.c b/kernel/main.c index 5431c2c..3b22926 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -1,23 +1,22 @@ #include -#include +#include +#include #include #include #include #include #include -#include #include #include -#include +#include #include #include static inline -void _init(void *dtb, file_node_t **initrd_root) +void _init(void *dtb) { - init_exception(); + exception_init(); - // UART uart_init(); // Device tree @@ -29,56 +28,22 @@ void _init(void *dtb, file_node_t **initrd_root) fdt_traverse(dtb_struct_cbs); DEBUG_DTB("device tree parse done"); - // Initramfs - DEBUG_INITRD(initrd_start); - *initrd_root = initrd_init(); + initrd_init(); - // Memory (Buddy system) mman_init(); - // Threads thread_init(); - init_interrupt(); -} + timer_init(); -static inline -void _print_time(uint64_t) -{ - uint64_t cntpct_el0, cntfrq_el0; - R_SYSREG(cntpct_el0, cntpct_el0); - R_SYSREG(cntfrq_el0, cntfrq_el0); - DEBUG_EXCEP(cntpct_el0 / cntfrq_el0); - - task_t task = { - .firing_tick = cntpct_el0 + 2 * cntfrq_el0, - .interval = 2 * cntfrq_el0, - .repeat = 1, - - .func = _print_time, - .param = 0x0, - }; - - add_timer_task(task); -} - -static inline -int32_t _test(uint64_t) -{ - for (int i = 0; i < 10; ++i) { - LOG(i); DEBUG_THREAD(get_current()); - sleep(1000000); - } - return 0; + enable_interrupt(); } void main(void *dtb) { - file_node_t *initrd_root = 0x0; - _init(dtb, &initrd_root); + _init(dtb); - for (int i = 0; i < 3; ++i) - run_thread(_test, 0x0); + run_thread(run_process_by_name, (uint64_t)&"syscall.img"); schedule(); } diff --git a/lib/logger.c b/lib/logger.c index 8f412d1..d26fd53 100644 --- a/lib/logger.c +++ b/lib/logger.c @@ -2,3 +2,5 @@ char logger_buf[LOGGER_BUFLEN]; char *logger_cur = logger_buf; +char sp_buf[LOGGER_BUFLEN]; +char *sp_cur = sp_buf; diff --git a/userprog/Makefile b/userprog/Makefile index e5dd716..2c0c8f8 100644 --- a/userprog/Makefile +++ b/userprog/Makefile @@ -13,6 +13,8 @@ LD := $(GNU)-ld LDFLAGS += -g -nostdlib -no-pie OBJCOPY := $(GNU)-objcopy +INCLUDE := -I../include -Iinclude + LD_SCRIPT := linker.ld SRCS := $(shell find . -name '*.[cS]') OBJS := $(SRCS:%=%.o) @@ -29,11 +31,11 @@ userprog.elf: $(LD_SCRIPT) $(OBJS) %.S.o: %.S mkdir -p $(dir $@) - $(CC) -c $< -o $@ $(CCFLAGS) + $(CC) -c $< -o $@ $(INCLUDE) $(CCFLAGS) %.c.o: %.c mkdir -p $(dir $@) - $(CC) -c $< -o $@ $(CCFLAGS) + $(CC) -c $< -o $@ $(INCLUDE) $(CCFLAGS) clean: -rm $(OBJS) userprog userprog.elf diff --git a/userprog/include/syscall.h b/userprog/include/syscall.h new file mode 100644 index 0000000..d416e69 --- /dev/null +++ b/userprog/include/syscall.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +uint64_t syscall(int32_t num, ...); + +int32_t getpid(void); +size_t uart_read(char buf[], size_t size); +size_t uart_write(const char buf[], size_t size); +int32_t exec(const char *name, char *const argv[]); +int32_t fork(void); +void exit(int32_t status); +int32_t mbox_call(uint8_t ch, uint32_t *mbox); +void kill(int32_t pid); diff --git a/userprog/lib/syscall.S b/userprog/lib/syscall.S new file mode 100644 index 0000000..01109bd --- /dev/null +++ b/userprog/lib/syscall.S @@ -0,0 +1,13 @@ +.global syscall +syscall: + mov x8, x0 + mov x0, x1 + mov x1, x2 + mov x2, x3 + mov x3, x4 + mov x4, x5 + mov x5, x6 + mov x6, x7 + + svc 0 + ret diff --git a/userprog/lib/syscall.c b/userprog/lib/syscall.c new file mode 100644 index 0000000..01f6b24 --- /dev/null +++ b/userprog/lib/syscall.c @@ -0,0 +1,25 @@ +#include + +int32_t getpid() +{ return (int32_t)syscall(0); } + +size_t uart_read(char buf[], size_t size) +{ return (size_t)syscall(1, buf, size); } + +size_t uart_write(const char buf[], size_t size) +{ return (size_t)syscall(2, buf, size); } + +int32_t exec(const char *name, char *const argv[]) +{ return (int32_t)syscall(3, name, argv); } + +int32_t fork(void) +{ return (int32_t)syscall(4); } + +void exit(int32_t status) +{ syscall(5); __builtin_unreachable(); } + +int32_t mbox_call(uint8_t ch, uint32_t *mbox) +{ return (int32_t)syscall(6, ch, mbox); } + +void kill(int32_t pid) +{ syscall(7, pid); }