16 Commits

Author SHA1 Message Date
ytshih c211d8cde2 Fix: lab3 on-board problems 2025-04-01 23:38:06 +08:00
ytshih 2af52f761c Fix: lab3 bug 2025-04-01 18:34:59 +08:00
ytshih 09c2de666c Fix: enable interrupt later 2025-04-01 17:54:24 +08:00
ytshih 6998a144e5 Feat: update README 2025-04-01 17:25:34 +08:00
ytshih 5ae11ac062 Feat: lab 3 2025-04-01 17:13:46 +08:00
ytshih 96cfdc4de2 Feat: lab 3 w/o adv 2 2025-03-26 19:03:09 +08:00
ytshih c5fc7e3102 Draft: lab 3 irq wtf 2025-03-24 10:48:35 +08:00
ytshih 6156975775 Draft: start lab 3 2025-03-23 11:21:31 +08:00
ytshih a6dc454a4c Feat: lab 4 2025-03-21 03:39:25 +08:00
ytshih eb7b9199f6 Feat: add memalloc command 2025-03-18 10:11:37 +08:00
ytshih 4ca4239baa Fix: on board 2025-03-18 09:25:48 +08:00
ytshih ac0bf1639e hw2 done 2025-03-18 08:40:31 +08:00
ytshih bfcb951628 Fix: mbox output 2025-03-18 08:40:31 +08:00
ytshih 73c9fc1423 Fix: add gitignore 2025-03-18 08:40:31 +08:00
ytshih 9238177ad6 initial commit 2025-03-18 08:40:31 +08:00
github-classroom[bot] d1f60e7c82 add deadline 2025-03-18 00:37:48 +00:00
14 changed files with 85 additions and 191 deletions
+4 -4
View File
@@ -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
-2
View File
@@ -11,8 +11,6 @@ typedef struct interrupt {
uint64_t priority;
interrupt_callback_func_t func;
uint64_t param;
int is_start;
} interrupt_t;
void add_interrupt_task(uint64_t priority,
+1 -5
View File
@@ -19,11 +19,7 @@ typedef enum :uint8_t {
typedef struct {
page_state_t state;
// 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;
uint64_t maxsz;
} page_header_t;
void mman_init();
+1 -1
View File
@@ -20,7 +20,7 @@ typedef struct timer {
task_t data;
} timer_t;
void add_timer_task(task_t task);
void add_task(task_t task);
void timer_irq_handler(void);
-2
View File
@@ -6,8 +6,6 @@
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);
+1 -1
View File
@@ -21,7 +21,7 @@ void not_implemented_handler()
void synchronous_handler()
{
static int poop = 0;
if (poop++ > 10)
if (poop++ > 5)
exit(ERR_ADMINKILL);
DEBUG_EXCEP("synchronous caught");
uint64_t x0 = 0x0;
+7 -15
View File
@@ -73,27 +73,21 @@ void add_interrupt_task(uint64_t priority,
.priority = priority,
.func = func,
.param = param,
.is_start = false,
.param = param
};
global_interrupt_pool = _merge(global_interrupt_pool, newint);
while (global_interrupt_pool) {
// LOG("check interrupt"); DEBUG_EXCEP(global_interrupt_pool->priority);
if (global_interrupt_pool->is_start)
return;
global_interrupt_pool->is_start = true;
global_interrupt_pool->func(global_interrupt_pool->param);
global_interrupt_pool = _pop(global_interrupt_pool);
}
}
void init_interrupt(void)
{
_enable_interrupt();
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();
}
void irq_handler(void)
@@ -110,8 +104,6 @@ void irq_handler(void)
void wfe(void)
{
return; // do nothing for now
if (!global_interrupt_pool) {
// asm volatile("wfe");
asm volatile("nop");
+1 -1
View File
@@ -1,4 +1,4 @@
#include <logger.h>
#include <uart.h>
#include <errcode.h>
#include <utils.h>
#include <kmalloc.h>
+18 -35
View File
@@ -47,24 +47,23 @@ void _pull(int idx, size_t sz)
{
if (LCH->state == PAGE_FREE && RCH->state == PAGE_FREE) {
if (CUR->state != PAGE_FREE) {
LOG("free page merged");
LOG("node merged");
DEBUG_MEM((uint64_t)idx);
}
CUR->state = PAGE_FREE;
CUR->size = sz;
}
if (LCH->state != PAGE_FREE || RCH->state != PAGE_FREE)
CUR->state = PAGE_DIVIDED;
switch (CUR->state) {
case PAGE_FREE:
CUR->size = sz;
CUR->maxsz = sz;
break;
case PAGE_DIVIDED:
CUR->size = LCH->size | RCH->size;
CUR->maxsz = MAX(LCH->maxsz, RCH->maxsz);
break;
case PAGE_ALLOCATED:
case PAGE_RESERVED:
CUR->size = 0;
CUR->maxsz = 0;
break;
default:
exit(ERR_UNREACHABLE);
@@ -86,7 +85,7 @@ void mman_init()
mman_frame_array[0] = (page_header_t){
.state = PAGE_FREE,
.size = mman_page_cnt,
.maxsz = msb64(mman_page_cnt),
};
fdt_reserve_entry_t *entry = 0x0;
@@ -110,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->size) {
if (req > sz || req > CUR->maxsz) {
return MMAN_NO_PAGE;
}
@@ -118,15 +117,16 @@ uint64_t _allocate_page(size_t req, int idx, uint64_t l, uint64_t r)
switch (CUR->state) {
case PAGE_FREE:
if (req == sz) {
LOG("page allocated"); LOG(l); DEBUG_MEM(r);
LOG("page allocated");
LOG(l);
DEBUG_MEM(r);
CUR->state = PAGE_ALLOCATED;
CUR->size = 0;
CUR->maxsz = 0;
return l;
}
LOG("page divided"); LOG(l); DEBUG_MEM(r);
LCH->state = RCH->state = PAGE_FREE;
LCH->size = m - l;
RCH->size = r - m;
LCH->maxsz = msb64(m - l);
RCH->maxsz = msb64(r - m);
break;
case PAGE_DIVIDED:
break;
@@ -138,25 +138,10 @@ uint64_t _allocate_page(size_t req, int idx, uint64_t l, uint64_t r)
}
uint64_t ret = MMAN_NO_PAGE;
// 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)))
if (ret == MMAN_NO_PAGE && LCH->maxsz >= req)
ret = _allocate_page(req, LIDX, l, m);
else
if (ret == MMAN_NO_PAGE && RCH->maxsz >= req)
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->size >= req)
ret = _allocate_page(req, RIDX, m, r);
_pull(idx, sz);
return ret;
}
@@ -189,7 +174,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->size = sz;
CUR->maxsz = sz;
return;
}
case PAGE_DIVIDED:
@@ -233,17 +218,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->size = 0;
CUR->maxsz = 0;
return;
}
uint64_t m = l + ((msb64(sz) == sz) ? (sz >> 1) : msb64(sz));
if (CUR->state == PAGE_FREE) {
LOG("page divided"); LOG(l); DEBUG_MEM(r);
CUR->state = PAGE_DIVIDED;
LCH->state = RCH->state = PAGE_FREE;
LCH->size = m - l;
RCH->size = r - m;
LCH->maxsz = msb64(m - l);
RCH->maxsz = msb64(r - m);
}
if (ql < m)
+1 -31
View File
@@ -30,7 +30,6 @@ void _help (void)
"cat <file> : concatenate files and print" ENDL
"exec <file> : execute file in usermode" ENDL
"settimeout <sec> <message...>: pring message after a few seconds" ENDL
"time : print current time tick" ENDL
"reboot : reboot the device" ENDL
);
}
@@ -75,14 +74,6 @@ 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)
{
@@ -125,7 +116,6 @@ 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(" ");
@@ -148,22 +138,7 @@ void _settimeout(int32_t sec, vector_t *args)
.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);
add_task(task);
}
static inline
@@ -237,9 +212,6 @@ int shell(file_node_t *initrd_root)
} 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) {
@@ -251,8 +223,6 @@ 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();
}
+15 -37
View File
@@ -47,21 +47,18 @@ timer_t *_pop(timer_t *t)
}
static inline
void _check_enable_timer()
void _set_timer_interrrupt()
{
if (global_timer) {
uint64_t cntpct_el0;
R_SYSREG(cntpct_el0, cntpct_el0);
DEBUG_EXCEP(cntpct_el0);
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);
uint64_t firing_tick = MAX(global_timer->data.firing_tick, cntpct_el0);
W_SYSREG(cntp_cval_el0, firing_tick);
W_SYSREG(cntp_ctl_el0, 1);
} else
W_SYSREG(cntp_ctl_el0, 0);
_enable_timer_irq(true);
}
}
static inline
@@ -74,9 +71,9 @@ void _traverse(timer_t *t)
_traverse(t->_r);
}
void add_timer_task(task_t task)
void add_task(task_t task)
{
DEBUG_EXCEP("add timer task");
DEBUG_EXCEP("add task");
timer_t *newtimer = kmalloc(sizeof(timer_t));
*newtimer = (timer_t){
._l = (timer_t *)0x0,
@@ -88,43 +85,24 @@ void add_timer_task(task_t task)
global_timer = _merge(global_timer, newtimer);
// _traverse(global_timer);
_check_enable_timer();
}
typedef struct {
interrupt_callback_func_t func;
uint64_t param;
} _timer_task_wrapper_param_t;
static inline
void _timer_task_wrapper(uint64_t param)
{
_timer_task_wrapper_param_t *data = (void *)param;
data->func(data->param);
kfree(data);
_enable_timer_irq(true);
_traverse(global_timer);
_set_timer_interrrupt();
}
void timer_irq_handler(void)
{
_enable_timer_irq(false);
LOG("timer irq");
uint64_t cntpct_el0;
R_SYSREG(cntpct_el0, cntpct_el0);
LOG("timer irq"); DEBUG_EXCEP(cntpct_el0);
DEBUG_EXCEP(cntpct_el0);
if (global_timer) {
_timer_task_wrapper_param_t *param =
kmalloc(sizeof(_timer_task_wrapper_param_t));
*param = (_timer_task_wrapper_param_t){
.func = global_timer->data.func,
.param = global_timer->data.param,
};
add_interrupt_task(20, _timer_task_wrapper, (uint64_t)param);
add_interrupt_task(20, global_timer->data.func, global_timer->data.param);
global_timer = _pop(global_timer);
_check_enable_timer();
}
_set_timer_interrrupt();
}
+32 -40
View File
@@ -29,8 +29,6 @@ size_t (*uart_putb)(const uint8_t *bytes, size_t len) = uart_putb_sync;
size_t (*uart_getb)(uint8_t *bytes, size_t len) = uart_getb_sync;
int is_uart_inited = false;
int is_uart_in_interrupt_queue = false;
ringbuffer_t *uart_readbuf;
ringbuffer_t *uart_writebuf;
@@ -85,47 +83,37 @@ void uart_init(void)
is_uart_inited = true;
}
static inline
void _enable_uart_interrupt()
void uart_transmit_interrupt_handler()
{
_uart_enable_receive_interrupt(true);
if (uart_writebuf->size > 0)
_uart_enable_transmit_interrupt(true);
}
static inline
void _uart_transmit_interrupt_callback(uint64_t)
{
_uart_write_data(ringbuffer_bump(uart_writebuf));
is_uart_in_interrupt_queue = false;
_enable_uart_interrupt();
}
typedef struct {
ringbuffer_t *buf;
uint8_t val;
} uart_interrupt_callback_payload_t;
static inline
void _uart_transmit_interrupt_handler()
void uart_receive_interrupt_callback(uint64_t param)
{
if (uart_writebuf->size > 0) {
is_uart_in_interrupt_queue = true;
add_interrupt_task(11, _uart_transmit_interrupt_callback, 0x0);
}
uart_interrupt_callback_payload_t *payload = (void *)param;
ringbuffer_push(payload->buf, payload->val);
kfree(payload);
}
static inline
void _uart_receive_interrupt_callback(uint64_t)
{
ringbuffer_push(uart_readbuf, _uart_read_data());
is_uart_in_interrupt_queue = false;
_enable_uart_interrupt();
}
static inline
void _uart_receive_interrupt_handler()
void uart_receive_interrupt_handler()
{
if (uart_readbuf->size < uart_readbuf->cap) {
is_uart_in_interrupt_queue = true;
add_interrupt_task(12, _uart_receive_interrupt_callback, 0x0);
uint8_t b = _uart_read_data();
uart_interrupt_callback_payload_t *param = kmalloc(
sizeof(uart_interrupt_callback_payload_t));
*param = (uart_interrupt_callback_payload_t){
.buf = uart_readbuf,
.val = b,
};
add_interrupt_task(10, uart_receive_interrupt_callback, (uint64_t)param);
}
}
@@ -133,11 +121,14 @@ void uart_irq_handler(void)
{
_uart_enable_receive_interrupt(false);
_uart_enable_transmit_interrupt(false);
if (_uart_receive_interrupt())
_uart_receive_interrupt_handler();
uart_receive_interrupt_handler();
if (_uart_transmit_interrupt())
_uart_transmit_interrupt_handler();
uart_transmit_interrupt_handler();
_uart_enable_receive_interrupt(true);
if (uart_writebuf->size > 0)
_uart_enable_transmit_interrupt(true);
}
size_t uart_putb_async(const uint8_t *bytes, size_t len)
@@ -146,8 +137,8 @@ size_t uart_putb_async(const uint8_t *bytes, size_t len)
for (; sentlen < len; ++bytes, ++sentlen)
ringbuffer_push(uart_writebuf, *bytes);
if (!is_uart_in_interrupt_queue && uart_writebuf)
_enable_uart_interrupt();
if (uart_writebuf->size > 0)
_uart_enable_transmit_interrupt(true);
return sentlen;
}
@@ -209,10 +200,11 @@ void uart_puts(const char *s)
void uart_hex(uint64_t d)
{
char buf[0x11], *p = buf;
for (int c = 28, n; c >= 0; c -= 4) {
uint64_t n;
for (int c = 28; c >= 0; c -= 4) {
n = (d >> c) & 0xf;
n += (n > 9) ? 0x37 : 0x30;
*p++ = (char)n;
n += n > 9 ? (char)'A' : (char)'0';
*p++ = n;
}
*p = '\0';
uart_puts(buf);
+1 -14
View File
@@ -24,19 +24,6 @@ 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;
@@ -119,7 +106,7 @@ uint32_t atoh32(const char *s)
exit(ERR_CONVERSION);
uint32_t ret = 0;
for (int i = 8; i-- && *s != '\0'; ++s) {
for (int i = 8; i--; ++s) {
if (!isxdigit(*s))
exit(ERR_CONVERSION);
ret <<= 4, ret |= (isdigit(*s) ? *s - '0' :
+1 -1
View File
@@ -54,7 +54,7 @@ void _print_time(uint64_t)
.param = 0x0,
};
add_timer_task(task);
add_task(task);
}
void main(void *dtb)