Feat: lab 3 w/o adv 2

This commit is contained in:
2025-03-26 15:30:57 +08:00
parent c5fc7e3102
commit 924bb67417
25 changed files with 617 additions and 113 deletions

View File

@@ -20,8 +20,8 @@ void not_implemented_handler()
void synchronous_handler()
{
static int count = 0;
if (count++ > 5)
static int poop = 0;
if (poop++ > 5)
exit(ERR_ADMINKILL);
DEBUG_EXCEP("synchronous caught");
uint64_t x0 = 0x0;

View File

@@ -1,58 +1,45 @@
#include <interrupt.h>
#include <uart.h>
#include <timer.h>
#include <utils.h>
#include <logger.h>
#include <errcode.h>
#define CORE0_TIMER_IRQ_CTRL ((volatile uint32_t *)0x40000040)
#define CORE0_IRQ_SOURCE ((volatile uint32_t *)0x40000060)
static inline
void _enable_interrupt(void)
{ W_SYSREG_IMM(DAIFClr, 0xf); }
static inline
void _disable_interrupt(void)
{ W_SYSREG_IMM(DAIFSet, 0xf); }
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);
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);
*CORE0_TIMER_IRQ_CTRL = 0x2;
}
static inline
void _uart_irq_handler(void)
{
DEBUG_EXCEP("uart irq");
}
static inline
void _timer_irq_handler(void)
{
LOG("timer irq");
uint64_t cntpct_el0;
R_SYSREG(cntpct_el0, cntpct_el0);
DEBUG_EXCEP(cntpct_el0);
uint64_t cntfrq_el0;
R_SYSREG(cntfrq_el0, cntfrq_el0);
W_SYSREG(cntp_tval_el0, cntfrq_el0);
_enable_timer_irq(true);
_enable_interrupt();
}
void irq_handler(void)
{
LOG("irq caught");
uint64_t irq_source = *CORE0_IRQ_SOURCE;
DEBUG_EXCEP(irq_source);
// uint64_t core0_irq_source = *CORE0_IRQ_SOURCE;
// DEBUG_EXCEP(core0_irq_source);
*CORE0_TIMER_IRQ_CTRL = 0x0;
if (irq_source & GPU_INT)
_uart_irq_handler();
if (irq_source & CNTPNSIRQ_INT)
_timer_irq_handler();
if (_irq_source_timer())
timer_irq_handler();
*CORE0_TIMER_IRQ_CTRL = 0x2;
}
void enable_interrupt(void)
{
asm volatile("msr DAIFClr, 0xf");
}
void disable_interrupt(void)
{
asm volatile("msr DAIFSet, 0xf");
if (_irq_source_uart())
uart_irq_handler();
}

47
kernel/lib/ringbuffer.c Normal file
View File

@@ -0,0 +1,47 @@
#include <ringbuffer.h>
#include <utils.h>
#include <errcode.h>
#include <stddef.h>
#include <kmalloc.h>
ringbuffer_t *make_ringbuffer(size_t size)
{
ringbuffer_t *ret = kmalloc(sizeof(ringbuffer_t));
uint8_t *data = kmalloc(size * sizeof(uint8_t));
*ret = (ringbuffer_t){
.size = 0,
.cap = size,
.data = data,
.read = data,
.write = data,
};
return ret;
}
int ringbuffer_push(ringbuffer_t *buf, uint8_t val)
{
if (buf->size == buf->cap)
return ERR_OUT_OF_BOUND;
*buf->write++ = val;
++buf->size;
if (buf->write == buf->data + buf->cap)
buf->write = buf->data;
return NO_ERROR;
}
uint8_t ringbuffer_bump(ringbuffer_t *buf)
{
if (buf->size == 0)
exit(ERR_INVALID_OP);
uint8_t ret = *buf->read++;
--buf->size;
if (buf->read == buf->data + buf->cap)
buf->read = buf->data;
return ret;
}

View File

@@ -1,4 +1,6 @@
#include <stddef.h>
#include <logger.h>
#include <timer.h>
#include <errcode.h>
#include <kmalloc.h>
#include <utils.h>
@@ -109,6 +111,35 @@ void _exec(file_node_t *root, const char *filename)
}
}
static inline
void _settimeout_cb_func(uint64_t args)
{
vector_t *v = (void *)args;
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_task(task);
}
static inline
void _set(long addr, unsigned int value) {
volatile unsigned int* point = (unsigned int*)addr;
@@ -130,45 +161,47 @@ void _reboot(void)
int shell(file_node_t *initrd_root)
{
uart_puts("# ");
char buf[INPUT_BUFLEN], ch;
char *buf = kmalloc(INPUT_BUFLEN * sizeof(char)), ch;
int sz = 0;
while ((ch = uart_getc()) != '\n') {
buf[sz++] = ch;
uart_send(ch);
uart_putb((const uint8_t *)&ch, 1);
}
uart_puts(ENDL);
buf[sz] = '\0';
buf[sz] = ' ';
const char *i = buf;
vector_t *args = make_vector(0);
for (char *saveptr = 0x0, *tok = strtok_r(buf, " ", &saveptr);
tok; tok = strtok_r((char *)0x0, " ", &saveptr)) {
VEC_PUSH(args, tok);
LOG(tok);
}
char bin[INPUT_BUFLEN], *j;
for (j = bin; *i != '\0' && !isspace(*i); ++i, ++j)
*j = *i;
*j = '\0';
// DEBUG("ENDL");
CLEAN;
for (; *i != '\0' && isspace(*i); ++i);
char param[INPUT_BUFLEN];
for (j = param; *i != '\0' && !isspace(*i); ++i, ++j)
*j = *i;
*j = '\0';
if (!strcmp(bin, "help")) {
char *cmd = args->size ? VEC_AT(char, args, 0) : (char *)0x0;
if (!strcmp(cmd, "help")) {
_help();
} else if (!strcmp(bin, "hello")) {
} else if (!strcmp(cmd, "hello")) {
_hello();
} else if (!strcmp(bin, "hwinfo")) {
} else if (!strcmp(cmd, "hwinfo")) {
_hwinfo();
} else if (!strcmp(bin, "memalloc")){
_memalloc((size_t)atoi32(param));
} else if (!strcmp(bin, "ls")) {
} else if (!strcmp(cmd, "memalloc") && args->size >= 2){
char *p1 = VEC_AT(char, args, 1);
_memalloc((size_t)atoi32(p1));
} else if (!strcmp(cmd, "ls")) {
_ls(initrd_root);
} else if (!strcmp(bin, "cat")) {
_cat(initrd_root, param);
} else if (!strcmp(bin, "exec")) {
_exec(initrd_root, param);
} else if (!strcmp(bin, "reboot")) {
} 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, "reboot")) {
_reboot();
}

95
kernel/lib/timer.c Normal file
View File

@@ -0,0 +1,95 @@
#include <timer.h>
#include <logger.h>
#include <utils.h>
#include <kmalloc.h>
#define CORE0_TIMER_IRQ_CTRL ((volatile uint32_t *)0x40000040)
timer_t *global_timer = (timer_t *)0x0;
MMIO_W_HELPER(_enable_timer_irq, CORE0_TIMER_IRQ_CTRL, 0x1, 1);
static inline
uint32_t _d(timer_t *t)
{ return t ? t->_d : 0; }
static inline
void _swap(timer_t *a, timer_t *b)
{
timer_t *tmp = a;
a = b, b = tmp;
}
static inline
timer_t *_merge(timer_t *a, timer_t *b)
{
if (!a || !b)
return a ?: b;
if (a->data.firing_tick > b->data.firing_tick)
_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
timer_t *_pop(timer_t *t)
{
if (!t || (!t->_l && !t->_r))
return (timer_t *)0x0;
return _merge(t->_l, t->_r);
}
static inline
void _set_timer_interrrupt()
{
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);
_enable_timer_irq(true);
}
}
void add_task(task_t task)
{
DEBUG_EXCEP("add task");
timer_t *newtimer = kmalloc(sizeof(timer_t));
*newtimer = (timer_t){
._l = (timer_t *)0x0,
._r = (timer_t *)0x0,
._d = 0,
.data = task,
};
global_timer = _merge(global_timer, newtimer);
_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);
DEBUG_EXCEP(cntpct_el0);
if (global_timer) {
global_timer->data.func(global_timer->data.param);
global_timer = _pop(global_timer);
}
_set_timer_interrrupt();
}

188
kernel/lib/uart.c Normal file
View File

@@ -0,0 +1,188 @@
#include <uart.h>
#include <logger.h>
#include <errcode.h>
#include <utils.h>
#include <string.h>
#include <gpio.h>
#include <stddef.h>
#include <ringbuffer.h>
/* Auxilary mini UART registers */
#define AUX_ENABLE ((volatile uint32_t*)(MMIO_BASE + 0x00215004))
#define AUX_MU_IO ((volatile uint32_t*)(MMIO_BASE + 0x00215040))
#define AUX_MU_IER ((volatile uint32_t*)(MMIO_BASE + 0x00215044))
#define AUX_MU_IIR ((volatile uint32_t*)(MMIO_BASE + 0x00215048))
#define AUX_MU_LCR ((volatile uint32_t*)(MMIO_BASE + 0x0021504C))
#define AUX_MU_MCR ((volatile uint32_t*)(MMIO_BASE + 0x00215050))
#define AUX_MU_LSR ((volatile uint32_t*)(MMIO_BASE + 0x00215054))
#define AUX_MU_MSR ((volatile uint32_t*)(MMIO_BASE + 0x00215058))
#define AUX_MU_SCRATCH ((volatile uint32_t*)(MMIO_BASE + 0x0021505C))
#define AUX_MU_CNTL ((volatile uint32_t*)(MMIO_BASE + 0x00215060))
#define AUX_MU_STAT ((volatile uint32_t*)(MMIO_BASE + 0x00215064))
#define AUX_MU_BAUD ((volatile uint32_t*)(MMIO_BASE + 0x00215068))
#define ARMINT_En_IRQs1 ((volatile uint32_t*)(MMIO_BASE + 0x0000b210))
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;
ringbuffer_t *uart_readbuf;
ringbuffer_t *uart_writebuf;
MMIO_W_HELPER(_uart_enable_receive_interrupt, AUX_MU_IER, 0x1, 0);
MMIO_W_HELPER(_uart_enable_transmit_interrupt, AUX_MU_IER, 0x1, 1);
MMIO_W_HELPER(_uart_clear_receive_fifo, AUX_MU_IIR, 0x1, 1);
MMIO_W_HELPER(_uart_clear_transmit_fifo, AUX_MU_IIR, 0x1, 2);
MMIO_W_HELPER(_uart_write_data, AUX_MU_IO, 0xff, 0);
MMIO_W_HELPER(_uart_interrupt_controller, ARMINT_En_IRQs1, 0x1, 29);
MMIO_R_HELPER(_uart_interrupt_pending, AUX_MU_IIR, 0x1, 0);
MMIO_R_HELPER(_uart_transmit_interrupt, AUX_MU_IIR, 0x1, 1);
MMIO_R_HELPER(_uart_receive_interrupt, AUX_MU_IIR, 0x1, 2);
MMIO_R_HELPER(_uart_transmitter_idle, AUX_MU_LSR, 0x1, 5);
MMIO_R_HELPER(_uart_data_ready, AUX_MU_LSR, 0x1, 0);
MMIO_R_HELPER(_uart_read_data, AUX_MU_IO, 0xff, 0);
void uart_init(void)
{
register uint32_t r;
/* initialize UART */
*AUX_ENABLE |= 1; // enable UART1, AUX mini uart
*AUX_MU_CNTL = 0; // disable Tx, Rx
*AUX_MU_LCR = 3; // set 8 bits
*AUX_MU_MCR = 0;
*AUX_MU_IER = 0; // disable interrupt by default
*AUX_MU_IIR = 0x6; // clear tx, rx FIFO
*AUX_MU_BAUD = 270; // 115200 baud
/* map UART1 to GPIO pins */
r = *GPFSEL1;
r &= ~((7 << 12) | (7 << 15)); // gpio14, gpio15
r |= (2 << 12) | (2 << 15); // alt5
*GPFSEL1 = r;
*GPPUD = 0; // enable pins 14 and 15
r = 150; while (r--) { asm volatile("nop"); }
*GPPUDCLK0 = (1 << 14) | (1 << 15);
r = 150; while (r--) { asm volatile("nop"); }
*GPPUDCLK0 = 0; // flush GPIO setup
*AUX_MU_CNTL = 3; // enable Tx, Rx
_uart_interrupt_controller(true);
uart_readbuf = make_ringbuffer(UART_BUFLEN);
uart_writebuf = make_ringbuffer(UART_BUFLEN);
_uart_enable_receive_interrupt(true);
//uint64_t ier = *AUX_MU_IER;
uart_getb = uart_getb_async;
uart_putb = uart_putb_async;
is_uart_inited = true;
}
void uart_transmit_interrupt_handler()
{
if (uart_writebuf->size > 0)
_uart_write_data(ringbuffer_bump(uart_writebuf));
}
void uart_receive_interrupt_handler()
{
if (uart_readbuf->size < uart_readbuf->cap) {
uint8_t b = _uart_read_data();
ringbuffer_push(uart_readbuf, b);
}
}
void uart_irq_handler(void)
{
_uart_enable_receive_interrupt(false);
_uart_enable_transmit_interrupt(false);
if (_uart_receive_interrupt())
uart_receive_interrupt_handler();
if (_uart_transmit_interrupt())
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)
{
size_t sentlen = 0;
for (; sentlen < len; ++bytes, ++sentlen)
ringbuffer_push(uart_writebuf, *bytes);
if (uart_writebuf->size > 0)
_uart_enable_transmit_interrupt(true);
return sentlen;
}
size_t uart_putb_sync(const uint8_t *bytes, size_t len)
{
size_t sentlen = 0;
for (; sentlen < len; ++bytes, ++sentlen) {
do asm volatile("nop"); // busy waiting
while (!_uart_transmitter_idle());
_uart_write_data(*bytes);
}
return sentlen;
}
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
*bytes = ringbuffer_bump(uart_readbuf);
}
return recvlen;
}
size_t uart_getb_sync(uint8_t *bytes, size_t len)
{
size_t recvlen = 0;
for (; recvlen < len; ++bytes, ++recvlen) {
do asm volatile("nop");
while (!_uart_data_ready());
*bytes = _uart_read_data();
}
return recvlen;
}
char uart_getc(void)
{
char r;
uart_getb((uint8_t *)&r, 1);
return r == '\r' ? '\n' : r;
}
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);
}
void uart_hex(uint64_t d)
{
char buf[0x11], *p = buf;
uint64_t n;
for (int c = 28; c >= 0; c -= 4) {
n = (d >> c) & 0xf;
n += n > 9 ? (char)'A' : (char)'0';
*p++ = n;
}
*p = '\0';
uart_puts(buf);
}