diff --git a/include/logger.h b/include/logger.h index 3cec69d..f472760 100644 --- a/include/logger.h +++ b/include/logger.h @@ -101,11 +101,11 @@ logger_cur = _Generic((msg), \ // #define DEBUG_DTB(val) DEBUG(val) #define DEBUG_DTB(val) CLEAN -#define DEBUG_EXCEP(val) DEBUG(val) -// #define DEBUG_EXCEP(val) CLEAN +// #define DEBUG_EXCEP(val) DEBUG(val) +#define DEBUG_EXCEP(val) CLEAN -// #define DEBUG_MEM(val) DEBUG(val) -#define DEBUG_MEM(val) CLEAN +#define DEBUG_MEM(val) DEBUG(val) +// #define DEBUG_MEM(val) CLEAN // #define DEBUG_INITRD(val) DEBUG(val) #define DEBUG_INITRD(val) CLEAN diff --git a/kernel/include/mman.h b/kernel/include/mman.h index 1bb744f..51713d8 100644 --- a/kernel/include/mman.h +++ b/kernel/include/mman.h @@ -19,7 +19,11 @@ typedef enum :uint8_t { typedef struct { page_state_t state; - uint64_t maxsz; + + // when state == PAGE_ALLOCATED or PAGE_RESERVED, size = 0 + // when state == PAGE_FREE, size = r - l + // when state == PAGE_DIVIDED, size = LCH->size | RCH->size + uint64_t size; } page_header_t; void mman_init(); diff --git a/kernel/include/timer.h b/kernel/include/timer.h index e370931..54efbcb 100644 --- a/kernel/include/timer.h +++ b/kernel/include/timer.h @@ -20,7 +20,7 @@ typedef struct timer { task_t data; } timer_t; -void add_task(task_t task); +void add_timer_task(task_t task); void timer_irq_handler(void); diff --git a/kernel/include/utils.h b/kernel/include/utils.h index 361eb20..4c4fa92 100644 --- a/kernel/include/utils.h +++ b/kernel/include/utils.h @@ -6,6 +6,8 @@ uint32_t msb32(uint32_t); uint64_t msb64(uint64_t); +uint64_t lsb64(uint64_t); + uint32_t hton32(const uint32_t); uint32_t ntoh32(const uint32_t); diff --git a/kernel/lib/exception.c b/kernel/lib/exception.c index 390528e..3c31ac2 100644 --- a/kernel/lib/exception.c +++ b/kernel/lib/exception.c @@ -21,7 +21,7 @@ void not_implemented_handler() void synchronous_handler() { static int poop = 0; - if (poop++ > 5) + if (poop++ > 10) exit(ERR_ADMINKILL); DEBUG_EXCEP("synchronous caught"); uint64_t x0 = 0x0; diff --git a/kernel/lib/interrupt.c b/kernel/lib/interrupt.c index c174e6e..96fe077 100644 --- a/kernel/lib/interrupt.c +++ b/kernel/lib/interrupt.c @@ -81,12 +81,7 @@ void add_interrupt_task(uint64_t priority, void init_interrupt(void) { - uint64_t cntfrq_el0; W_SYSREG(cntp_ctl_el0, 1); - R_SYSREG(cntfrq_el0, cntfrq_el0); - W_SYSREG(cntp_tval_el0, cntfrq_el0); - - _enable_timer_irq(true); _enable_interrupt(); } diff --git a/kernel/lib/kmalloc.c b/kernel/lib/kmalloc.c index da1f6a6..e8dea32 100644 --- a/kernel/lib/kmalloc.c +++ b/kernel/lib/kmalloc.c @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/kernel/lib/mman.c b/kernel/lib/mman.c index db83745..9445c33 100644 --- a/kernel/lib/mman.c +++ b/kernel/lib/mman.c @@ -56,14 +56,14 @@ void _pull(int idx, size_t sz) CUR->state = PAGE_DIVIDED; switch (CUR->state) { case PAGE_FREE: - CUR->maxsz = sz; + CUR->size = sz; break; case PAGE_DIVIDED: - CUR->maxsz = MAX(LCH->maxsz, RCH->maxsz); + CUR->size = LCH->size | RCH->size; break; case PAGE_ALLOCATED: case PAGE_RESERVED: - CUR->maxsz = 0; + CUR->size = 0; break; default: exit(ERR_UNREACHABLE); @@ -85,7 +85,7 @@ void mman_init() mman_frame_array[0] = (page_header_t){ .state = PAGE_FREE, - .maxsz = msb64(mman_page_cnt), + .size = mman_page_cnt, }; fdt_reserve_entry_t *entry = 0x0; @@ -109,7 +109,7 @@ static inline uint64_t _allocate_page(size_t req, int idx, uint64_t l, uint64_t r) { uint64_t sz = r - l; - if (req > sz || req > CUR->maxsz) { + if (req > sz || req > CUR->size) { return MMAN_NO_PAGE; } @@ -121,12 +121,12 @@ uint64_t _allocate_page(size_t req, int idx, uint64_t l, uint64_t r) LOG(l); DEBUG_MEM(r); CUR->state = PAGE_ALLOCATED; - CUR->maxsz = 0; + CUR->size = 0; return l; } LCH->state = RCH->state = PAGE_FREE; - LCH->maxsz = msb64(m - l); - RCH->maxsz = msb64(r - m); + LCH->size = m - l; + RCH->size = r - m; break; case PAGE_DIVIDED: break; @@ -138,10 +138,25 @@ uint64_t _allocate_page(size_t req, int idx, uint64_t l, uint64_t r) } uint64_t ret = MMAN_NO_PAGE; - if (ret == MMAN_NO_PAGE && LCH->maxsz >= req) + + // Goto child where size >= req + // If both children can handle, choose the one that has the least significant + // bit that can handle. + // It both children are the same, choose the left one + int is_lch_valid = (LCH->size >= req); + int is_rch_valid = (RCH->size >= req); + if (is_lch_valid && is_rch_valid) { + if (lsb64(LCH->size & ~(req - 1)) <= lsb64(RCH->size & ~(req - 1))) + ret = _allocate_page(req, LIDX, l, m); + else + ret = _allocate_page(req, RIDX, m, r); + } + + if (ret == MMAN_NO_PAGE && LCH->size >= req) ret = _allocate_page(req, LIDX, l, m); - if (ret == MMAN_NO_PAGE && RCH->maxsz >= req) + if (ret == MMAN_NO_PAGE && RCH->size >= req) ret = _allocate_page(req, RIDX, m, r); + _pull(idx, sz); return ret; } @@ -174,7 +189,7 @@ void _free_page(uint64_t req, int idx, uint64_t l, uint64_t r) LOG(l); DEBUG_MEM(r); CUR->state = PAGE_FREE; - CUR->maxsz = sz; + CUR->size = sz; return; } case PAGE_DIVIDED: @@ -218,15 +233,15 @@ void _reserve_page(uint64_t ql, uint64_t qr, int idx, uint64_t l, uint64_t r) LOG(l); DEBUG_MEM(r); CUR->state = PAGE_RESERVED; - CUR->maxsz = 0; + CUR->size = 0; return; } uint64_t m = l + ((msb64(sz) == sz) ? (sz >> 1) : msb64(sz)); if (CUR->state == PAGE_FREE) { LCH->state = RCH->state = PAGE_FREE; - LCH->maxsz = msb64(m - l); - RCH->maxsz = msb64(r - m); + LCH->size = m - l; + RCH->size = r - m; } if (ql < m) diff --git a/kernel/lib/shell.c b/kernel/lib/shell.c index 6024d41..23566fe 100644 --- a/kernel/lib/shell.c +++ b/kernel/lib/shell.c @@ -30,6 +30,7 @@ void _help (void) "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 ); } @@ -74,6 +75,14 @@ void _memalloc(size_t size) 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) { @@ -138,7 +147,22 @@ void _settimeout(int32_t sec, vector_t *args) .func = _settimeout_cb_func, .param = (uint64_t)args, }; - add_task(task); + 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 @@ -209,9 +233,12 @@ int shell(file_node_t *initrd_root) _hello(); } else if (!strcmp(cmd, "hwinfo")) { _hwinfo(); - } else if (!strcmp(cmd, "memalloc") && args->size >= 2){ + } 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) { @@ -223,6 +250,8 @@ int shell(file_node_t *initrd_root) } 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(); } diff --git a/kernel/lib/timer.c b/kernel/lib/timer.c index f800b17..a3daeab 100644 --- a/kernel/lib/timer.c +++ b/kernel/lib/timer.c @@ -47,15 +47,17 @@ timer_t *_pop(timer_t *t) } static inline -void _set_timer_interrrupt() +void _set_timer_interrupt() { if (global_timer) { uint64_t cntpct_el0; R_SYSREG(cntpct_el0, cntpct_el0); DEBUG_EXCEP(cntpct_el0); - uint64_t firing_tick = MAX(global_timer->data.firing_tick, cntpct_el0); - W_SYSREG(cntp_cval_el0, firing_tick); + if (global_timer->data.firing_tick < cntpct_el0) + W_SYSREG(cntp_tval_el0, 1); + else + W_SYSREG(cntp_cval_el0, global_timer->data.firing_tick); _enable_timer_irq(true); } @@ -71,9 +73,9 @@ void _traverse(timer_t *t) _traverse(t->_r); } -void add_task(task_t task) +void add_timer_task(task_t task) { - DEBUG_EXCEP("add task"); + DEBUG_EXCEP("add timer task"); timer_t *newtimer = kmalloc(sizeof(timer_t)); *newtimer = (timer_t){ ._l = (timer_t *)0x0, @@ -86,7 +88,7 @@ void add_task(task_t task) global_timer = _merge(global_timer, newtimer); _traverse(global_timer); - _set_timer_interrrupt(); + _set_timer_interrupt(); } void timer_irq_handler(void) @@ -104,5 +106,5 @@ void timer_irq_handler(void) global_timer = _pop(global_timer); } - _set_timer_interrrupt(); + _set_timer_interrupt(); } diff --git a/kernel/lib/utils.c b/kernel/lib/utils.c index f107bd8..8e8a0ea 100644 --- a/kernel/lib/utils.c +++ b/kernel/lib/utils.c @@ -24,6 +24,19 @@ uint64_t msb64(uint64_t x) return res == 64 ? 0 : ((uint64_t)1 << (63 - res)); } +uint64_t lsb64(uint64_t x) +{ + uint64_t res = 0x0; + asm volatile( + "rbit x0, %[val]" ENDL + "clz %[res], x0" + : [res] "=r" (res) + : [val] "r" (x) + : "x0" + ); + return res == 64 ? 0 : ((uint64_t)1 << res); +} + uint32_t hton32(const uint32_t h) { const uint8_t *p = (const void *)&h; @@ -106,7 +119,7 @@ uint32_t atoh32(const char *s) exit(ERR_CONVERSION); uint32_t ret = 0; - for (int i = 8; i--; ++s) { + for (int i = 8; i-- && *s != '\0'; ++s) { if (!isxdigit(*s)) exit(ERR_CONVERSION); ret <<= 4, ret |= (isdigit(*s) ? *s - '0' : diff --git a/kernel/main.c b/kernel/main.c index 07a8602..f148785 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -54,7 +54,7 @@ void _print_time(uint64_t) .param = 0x0, }; - add_task(task); + add_timer_task(task); } void main(void *dtb)