Feat: lab 3

This commit is contained in:
2025-04-01 17:13:46 +08:00
parent e2ebb6cc34
commit b7da380421
10 changed files with 197 additions and 65 deletions

1
.gitignore vendored
View File

@@ -4,3 +4,4 @@
**.cpio
.gdb_history
userprog/userprog
rootfs/userprog

View File

@@ -1,5 +1,5 @@
MAKE := make
MAKEFLAGS += -j 8
MAKEFLAGS += -j8
ARCH := aarch64
GNU := $(ARCH)-linux-gnu

8
include/ctype.h Normal file
View File

@@ -0,0 +1,8 @@
#pragma once
#include <stddef.h>
int isdigit(int);
int isxdigit(int);
int isupper(int);
int isspace(int);

View File

@@ -2,44 +2,56 @@
// save general registers to stack
.macro save_all
sub sp, sp, 32 * 8
stp x0, x1, [sp ,16 * 0]
stp x2, x3, [sp ,16 * 1]
stp x4, x5, [sp ,16 * 2]
stp x6, x7, [sp ,16 * 3]
stp x8, x9, [sp ,16 * 4]
stp x10, x11, [sp ,16 * 5]
stp x12, x13, [sp ,16 * 6]
stp x14, x15, [sp ,16 * 7]
stp x16, x17, [sp ,16 * 8]
stp x18, x19, [sp ,16 * 9]
stp x20, x21, [sp ,16 * 10]
stp x22, x23, [sp ,16 * 11]
stp x24, x25, [sp ,16 * 12]
stp x26, x27, [sp ,16 * 13]
stp x28, x29, [sp ,16 * 14]
str x30, [sp, 16 * 15]
sub sp, sp, 36 * 8
stp x0, x1, [sp, 16 * 0]
stp x2, x3, [sp, 16 * 1]
stp x4, x5, [sp, 16 * 2]
stp x6, x7, [sp, 16 * 3]
stp x8, x9, [sp, 16 * 4]
stp x10, x11, [sp, 16 * 5]
stp x12, x13, [sp, 16 * 6]
stp x14, x15, [sp, 16 * 7]
stp x16, x17, [sp, 16 * 8]
stp x18, x19, [sp, 16 * 9]
stp x20, x21, [sp, 16 * 10]
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 x30, lr, [sp, 16 * 15]
mrs x0, spsr_el1
mrs x1, elr_el1
mrs x2, esr_el1
stp x0, x1, [sp, 16 * 16]
str x2, [sp, 16 * 17]
.endm
// load general registers from stack
.macro load_all
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, x29, [sp ,16 * 14]
ldr x30, [sp, 16 * 15]
add sp, sp, 32 * 8
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, x29, [sp, 16 * 14]
ldp x30, lr, [sp, 16 * 15]
mrs x0, spsr_el1
mrs x1, elr_el1
mrs x2, esr_el1
ldp x0, x1, [sp, 16 * 16]
ldr x2, [sp, 16 * 17]
add sp, sp, 36 * 8
.endm
_null_handler:

View File

@@ -2,5 +2,24 @@
#include <stddef.h>
typedef void (*interrupt_callback_func_t)(uint64_t);
typedef struct interrupt {
struct interrupt *_l, *_r;
uint32_t _d;
uint64_t priority;
interrupt_callback_func_t func;
uint64_t param;
} interrupt_t;
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);
extern interrupt_t *global_interrupt_pool;

View File

@@ -1,4 +1,5 @@
#include <interrupt.h>
#include <kmalloc.h>
#include <uart.h>
#include <timer.h>
#include <utils.h>
@@ -8,6 +9,8 @@
#define CORE0_TIMER_IRQ_CTRL ((volatile uint32_t *)0x40000040)
#define CORE0_IRQ_SOURCE ((volatile uint32_t *)0x40000060)
interrupt_t *global_interrupt_pool = (interrupt_t *)0x0;
static inline
void _enable_interrupt(void)
{ W_SYSREG_IMM(DAIFClr, 0xf); }
@@ -21,6 +24,61 @@ MMIO_W_HELPER(_enable_timer_irq, CORE0_TIMER_IRQ_CTRL, 0x1, 1);
MMIO_R_HELPER(_irq_source_timer, CORE0_IRQ_SOURCE, 0x1, 1);
MMIO_R_HELPER(_irq_source_uart, CORE0_IRQ_SOURCE, 0x1, 8);
static inline
uint32_t _d(interrupt_t *interrupt)
{ return interrupt ? interrupt->_d : 0; }
static inline
void _swap(interrupt_t **a, interrupt_t **b)
{
interrupt_t *tmp = *a;
*a = *b, *b = tmp;
}
static inline
interrupt_t *_merge(interrupt_t *a, interrupt_t *b)
{
if (!a || !b)
return a ?: b;
if (a->priority < b->priority)
_swap(&a, &b);
a->_r = _merge(a->_r, b);
if (_d(a->_l) < _d(a->_r))
_swap(&a->_l, &a->_r);
a->_d = _d(a->_r) + 1;
return a;
}
static inline
interrupt_t *_pop(interrupt_t *interrupt)
{
if (!interrupt || (!interrupt->_l && !interrupt->_r))
return (interrupt_t *)0x0;
return _merge(interrupt->_l, interrupt->_r);
}
void add_interrupt_task(uint64_t priority,
interrupt_callback_func_t func,
uint64_t param)
{
// DEBUG_EXCEP("add interrupt");
interrupt_t *newint = kmalloc(sizeof(interrupt_t));
*newint = (interrupt_t){
._l = (interrupt_t *)0x0,
._r = (interrupt_t *)0x0,
._d = 0,
.priority = priority,
.func = func,
.param = param
};
global_interrupt_pool = _merge(global_interrupt_pool, newint);
}
void init_interrupt(void)
{
uint64_t cntfrq_el0;
@@ -43,3 +101,17 @@ void irq_handler(void)
if (_irq_source_uart())
uart_irq_handler();
}
void wfe(void)
{
if (!global_interrupt_pool) {
asm volatile("wfe");
return;
}
interrupt_t *interrupt = global_interrupt_pool;
global_interrupt_pool = _merge(global_interrupt_pool->_l,
global_interrupt_pool->_r);
interrupt->func(interrupt->param);
}

View File

@@ -25,10 +25,11 @@ void _help (void)
"help : print this help menu" ENDL
"hello : print Hello World!" ENDL
"hwinfo : print hardware info" ENDL
"memalloc <size>: alloate memory and print" ENDL
"memalloc <size> : alloate memory and print" ENDL
"ls : list directory contents" ENDL
"cat <file>: concatenate files and print" ENDL
"exec <file>: execute file in usermode" ENDL
"cat <file> : concatenate files and print" ENDL
"exec <file> : execute file in usermode" ENDL
"settimeout <sec> <message...>: pring message after a few seconds" ENDL
"reboot : reboot the device" ENDL
);
}

View File

@@ -1,4 +1,5 @@
#include <timer.h>
#include <interrupt.h>
#include <logger.h>
#include <utils.h>
#include <kmalloc.h>
@@ -14,10 +15,10 @@ uint32_t _d(timer_t *t)
{ return t ? t->_d : 0; }
static inline
void _swap(timer_t *a, timer_t *b)
void _swap(timer_t **a, timer_t **b)
{
timer_t *tmp = a;
a = b, b = tmp;
timer_t *tmp = *a;
*a = *b, *b = tmp;
}
static inline
@@ -27,11 +28,11 @@ timer_t *_merge(timer_t *a, timer_t *b)
return a ?: b;
if (a->data.firing_tick > b->data.firing_tick)
_swap(a, b);
_swap(&a, &b);
a->_r = _merge(a->_r, b);
if (_d(a->_l) < _d(a->_r))
_swap(a->_l, a->_r);
_swap(&a->_l, &a->_r);
a->_d = _d(a->_r) + 1;
return a;
@@ -87,7 +88,7 @@ void timer_irq_handler(void)
DEBUG_EXCEP(cntpct_el0);
if (global_timer) {
global_timer->data.func(global_timer->data.param);
add_interrupt_task(20, global_timer->data.func, global_timer->data.param);
global_timer = _pop(global_timer);
}

View File

@@ -1,4 +1,6 @@
#include <uart.h>
#include <kmalloc.h>
#include <interrupt.h>
#include <logger.h>
#include <errcode.h>
#include <utils.h>
@@ -87,11 +89,31 @@ void uart_transmit_interrupt_handler()
_uart_write_data(ringbuffer_bump(uart_writebuf));
}
typedef struct {
ringbuffer_t *buf;
uint8_t val;
} uart_interrupt_callback_payload_t;
static inline
void uart_receive_interrupt_callback(uint64_t param)
{
uart_interrupt_callback_payload_t *payload = (void *)param;
ringbuffer_push(payload->buf, payload->val);
kfree(payload);
}
void uart_receive_interrupt_handler()
{
if (uart_readbuf->size < uart_readbuf->cap) {
uint8_t b = _uart_read_data();
ringbuffer_push(uart_readbuf, b);
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);
}
}
@@ -139,7 +161,7 @@ size_t uart_getb_async(uint8_t *bytes, size_t len)
size_t recvlen = 0;
for (; recvlen < len; ++bytes, ++recvlen) {
while (!uart_readbuf->size)
asm volatile("wfe"); // wait for interrupt
wfe(); // wait for interrupt
*bytes = ringbuffer_bump(uart_readbuf);
}

View File

@@ -42,20 +42,7 @@ 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 / cntpct_el0);
}
void main(void *dtb)
{
file_node_t *initrd_root = 0x0;
init(dtb, &initrd_root);
LOG("system booting in");
_print_time(0x0);
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,
@@ -67,6 +54,15 @@ void main(void *dtb)
};
add_task(task);
}
void main(void *dtb)
{
file_node_t *initrd_root = 0x0;
init(dtb, &initrd_root);
LOG("system booting in");
_print_time(0x0);
uint64_t el;
R_SYSREG(el, CurrentEL);