8 Commits
hw3 ... hw5

Author SHA1 Message Date
7c054743ce Fix: custom signal handler not working 2025-05-06 12:49:44 +08:00
d31f5e02fe Feat: POSIX signal 2025-05-04 20:38:25 +08:00
8d1045f20d Feat: gura!!! 2025-05-03 22:29:36 +08:00
e73f90395d Draft: lab 5 failed 2025-05-03 20:45:34 +08:00
981cae803b Feat: kernel thread done 2025-04-27 11:04:28 +08:00
02b2a87fed Draft: lab 4 demo fix 2025-04-15 23:56:40 +08:00
8ea82f927b Chore: trim spaces 2025-04-15 19:51:00 +08:00
75edf55dd3 Chore: log format 2025-04-15 17:49:58 +08:00
47 changed files with 1033 additions and 619 deletions

View File

@@ -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 \

View File

@@ -19,6 +19,8 @@ static inline char *_logger_string(char *dest, const char *src)
}
static inline char *_logger_hex(char *dest, uint64_t x)
{
*dest++ = '0';
*dest++ = 'x';
for (int n, c = 60; c >= 0; c -= 4) {
n = (x >> c) & 0xf;
n += (n > 9) ? 0x37 : 0x30;
@@ -27,10 +29,43 @@ static inline char *_logger_hex(char *dest, uint64_t x)
*dest = '\0';
return dest;
}
static inline char *_logger_int(char *dest, int x)
{
char arr[12], *c = &arr[11];
arr[11] = '\0';
if (x < 0)
*dest++ = '-', x = -x;
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_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++ = '0';
*dest++ = 'x';
*dest++ = '*';
return _logger_hex(dest, (uint64_t)x);
}
@@ -51,6 +86,8 @@ logger_cur = _Generic((msg), \
char * : _logger_string, \
const char *: _logger_string, \
uint64_t : _logger_hex, \
int32_t : _logger_int, \
size_t : _logger_uint, \
default : _logger_pointer \
)(logger_cur, msg)
@@ -60,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); \
@@ -104,11 +152,19 @@ logger_cur = _Generic((msg), \
// #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
// #define DEBUG_THREAD(val) DEBUG(val)
#define DEBUG_THREAD(val) CLEAN
#define DEBUG_SIGNAL(val) DEBUG(val)
// #define DEBUG_SIGNAL(val) CLEAN
extern char logger_buf[LOGGER_BUFLEN];
extern char *logger_cur;
extern char sp_buf[LOGGER_BUFLEN];
extern char *sp_cur;

View File

@@ -1,7 +1,9 @@
#pragma once
#define bool _Bool
#define true 0x1
#define false 0x0
#define __bool_true_false_are_defined 0x1
#define ENDL "\r\n"

View File

@@ -8,4 +8,5 @@ size_t strlen(const char *str);
char *strtok_r(char *str, const char *delimiters, char **saveptr);
void *memcpy(void *dest, const void *src, size_t count);
void *memset(void *dest, int ch, size_t count);
void *memzero(void *start, void *end);

View File

@@ -1,5 +1,10 @@
#pragma once
void init_exception(void);
#include <stddef.h>
#include <process.h>
void exception_vector_table(void);
void exception_init(void);
void not_implemented_handler(void);
void synchronous_handler(void);
void synchronous_handler(trapframe_t *regs);

View File

@@ -1,3 +1,5 @@
#pragma once
void user_exec(void *text, void *sp);
#include <process.h>
void user_exec(trapframe_t *regs);

View File

@@ -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;

View File

@@ -15,11 +15,13 @@ typedef struct interrupt {
int is_start;
} interrupt_t;
void enable_interrupt(void);
void disable_interrupt(void);
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);

View File

@@ -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);

63
kernel/include/process.h Normal file
View File

@@ -0,0 +1,63 @@
#pragma once
#include <stddef.h>
#include <vector.h>
#include <signal.h>
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;
void *sigstack;
size_t sigstack_size;
bool sigstate[SIGNAL_NUM];
int32_t current_signal;
signal_handler_t sighandlers[SIGNAL_NUM];
trapframe_t *regs, *retregs;
} 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;
extern vector_t *global_processes;

View File

@@ -21,9 +21,14 @@ uint64_t queue_front(const queue_t *queue);
void queue_push_back(queue_t *queue, uint64_t val);
void queue_push_front(queue_t *queue, uint64_t val);
uint64_t queue_pop_back(queue_t *queue);
uint64_t queue_pop_front(queue_t *queue);
#define QUEUE_BACK(type, queue) ((type *)queue_back(queue))
#define QUEUE_FRONT(type, queue) ((type *)queue_front(queue))
#define QUEUE_PUSH_BACK(queue, val) \
queue_push_back(queue, (uint64_t)val)
#define QUEUE_PUSH_FRONT(queue, val) \
queue_push_front(queue, (uint64_t)val)
#define QUEUE_PUSH_BACK(queue, val) queue_push_back(queue, (uint64_t)val)
#define QUEUE_PUSH_FRONT(queue, val) queue_push_front(queue, (uint64_t)val)
#define QUEUE_POP_BACK(type, queue) ((type *)queue_pop_back(queue))
#define QUEUE_POP_FRONT(type, queue) ((type *)queue_pop_front(queue))

View File

@@ -1,7 +0,0 @@
#pragma once
#include <stddef.h>
#include <initrd.h>
int // is continue
shell(file_node_t *);

12
kernel/include/signal.h Normal file
View File

@@ -0,0 +1,12 @@
#pragma once
#include <stddef.h>
#define SIGNAL_NUM 32
#define SIGKILL 9
typedef void (*signal_handler_t)();
void run_signal(int32_t SIGNAL);
void end_signal(void);

19
kernel/include/syscall.h Normal file
View File

@@ -0,0 +1,19 @@
#pragma once
#include <stddef.h>
#include <process.h>
#include <signal.h>
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_by_id(int32_t pid);
void sys_signal(int32_t SIGNAL, signal_handler_t handler);
void sys_kill(int32_t pid, int32_t SIGNAL);
void sys_sigreturn(void);

54
kernel/include/thread.h Normal file
View File

@@ -0,0 +1,54 @@
#pragma once
#include <stddef.h>
#include <queue.h>
#include <process.h>
typedef int32_t (*thread_func_t)(uint64_t);
typedef enum: uint32_t {
THREAD_STATUS_RUNABLE = 0,
THREAD_STATUS_WAIT = 1,
THREAD_STATUS_EXIT = 2,
THREAD_STATUS_ZOMBIE = 3,
} thread_status_t;
typedef struct {
uint64_t x19, x20;
uint64_t x21, x22;
uint64_t x23, x24;
uint64_t x25, x26;
uint64_t x27, x28;
uint64_t fp, lr;
uint64_t sp;
} cpu_state_t;
typedef struct thread {
thread_func_t func;
uint64_t param;
thread_status_t status;
int32_t retcode;
void *stack;
size_t stack_size;
cpu_state_t *regs;
process_t *process;
} thread_t;
// thread.S
void context_switch(void *from, void *to, thread_t *th);
// thread.c
void thread_init(void);
void run_thread(thread_func_t func, uint64_t param);
void schedule(void);
#define yield schedule
thread_t *get_current(void);
extern queue_t *global_run_queue;
extern queue_t *global_wait_queue;
extern queue_t *global_gc_queue;

View File

@@ -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,7 +19,10 @@ typedef struct timer {
task_t data;
} timer_t;
void timer_init(void);
void add_timer_task(task_t task);
void sleep(uint64_t ms);
void timer_irq_handler(void);

View File

@@ -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))
@@ -32,6 +32,7 @@ void exit(int);
#define ALIGN4(ptr) ALIGN(ptr, 2)
#define ALIGN8(ptr) ALIGN(ptr, 3)
#define ALIGN16(ptr) ALIGN(ptr, 4)
#define ALIGN4K(ptr) ALIGN(ptr, 12)
#define BUMP(orig_type, bump_type, ptr) ( \

View File

@@ -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:

View File

@@ -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

View File

@@ -3,8 +3,10 @@
#include <stddef.h>
#include <logger.h>
#include <utils.h>
#include <syscall.h>
#include <interrupt.h>
void init_exception()
void exception_init()
{
asm volatile(
"adr x0, exception_vector_table" ENDL
@@ -18,25 +20,29 @@ 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);
LOG(x0);
uint64_t spsr_el1 = 0x0;
R_SYSREG(spsr_el1, spsr_el1);
LOG(spsr_el1);
uint64_t elr_el1 = 0x0;
R_SYSREG(elr_el1, elr_el1);
LOG(elr_el1);
uint64_t esr_el1 = 0x0;
R_SYSREG(esr_el1, esr_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:
}
}

36
kernel/lib/exec.S Normal file
View File

@@ -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

View File

@@ -1,16 +0,0 @@
#include <exec.h>
#include <utils.h>
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");
}

View File

@@ -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, &ltr, &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)

View File

@@ -11,12 +11,10 @@
interrupt_t *global_interrupt_pool = (interrupt_t *)0x0;
static inline
void _enable_interrupt(void)
void enable_interrupt(void)
{ W_SYSREG_IMM(DAIFClr, 0xf); }
static inline
void _disable_interrupt(void)
void disable_interrupt(void)
{ W_SYSREG_IMM(DAIFSet, 0xf); }
MMIO_W_HELPER(_enable_timer_irq, CORE0_TIMER_IRQ_CTRL, 0x1, 1);
@@ -65,6 +63,9 @@ void add_interrupt_task(uint64_t priority,
uint64_t param)
{
// DEBUG_EXCEP("add interrupt");
uint64_t last_priority = 0xfff;
if (global_interrupt_pool)
last_priority = global_interrupt_pool->priority;
interrupt_t *newint = kmalloc(sizeof(interrupt_t));
*newint = (interrupt_t){
._l = (interrupt_t *)0x0,
@@ -82,7 +83,7 @@ void add_interrupt_task(uint64_t priority,
while (global_interrupt_pool) {
// LOG("check interrupt"); DEBUG_EXCEP(global_interrupt_pool->priority);
if (global_interrupt_pool->is_start)
if (global_interrupt_pool->is_start && global_interrupt_pool->priority < last_priority)
return;
global_interrupt_pool->is_start = true;
global_interrupt_pool->func(global_interrupt_pool->param);
@@ -90,12 +91,6 @@ 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;

View File

@@ -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,19 +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;
}
@@ -90,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) {
@@ -103,6 +119,9 @@ void mman_free(void *ptr)
++pool->left;
++PAGE_HEADER(ptr)->left;
LOG("mman_free"); LOG((uint64_t)unit); DEBUG_MEM(ptr);
size_t cap = (PAGE_SIZE - sizeof(kmalloc_allocator_t)) / unit;
if (PAGE_HEADER(ptr)->left == cap && pool->left >= 2 * cap) {
if (PAGE_HEADER(ptr)->page_prev)

View File

@@ -25,9 +25,14 @@
#include <gpio.h>
#include <mbox.h>
#include <string.h>
#include <kmalloc.h>
#include <thread.h>
#include <logger.h>
#include <utils.h>
/* 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,27 +54,37 @@ 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 *input)
{
unsigned int r = (((unsigned int)((unsigned long)&mbox)&~0xF) | (ch&0xF));
unsigned int *_mbox = kmalloc((size_t)input[0] + 0xf), *mbox = ALIGN16(_mbox);
LOG(_mbox); LOG(mbox); DEBUG_THREAD((size_t)input[0]);
memcpy(mbox, input, (size_t)input[0]);
unsigned int r = (unsigned long)mbox | (unsigned int)(ch&0xf);
/* wait until we can write to the mailbox */
do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_FULL);
do yield();
while(*MBOX_STATUS & MBOX_FULL);
/* 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);
do yield();
while(*MBOX_STATUS & MBOX_EMPTY);
/* is it a response to our message? */
if(r == *MBOX_READ)
if(r == *MBOX_READ) {
/* is it a valid successful response? */
return mbox[1]==MBOX_RESPONSE;
if (mbox[1] == MBOX_RESPONSE)
memcpy(input, mbox, (size_t)input[0]);
kfree(_mbox);
return mbox[1] == MBOX_RESPONSE;
}
}
return 0;
}
unsigned int get_board_revision(void)
{
unsigned int __attribute__((aligned(16))) mbox[36];
mbox[0] = 36 * 4;
mbox[1] = MBOX_REQUEST;
@@ -81,13 +96,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 +116,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 +136,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];
}

View File

@@ -47,8 +47,7 @@ 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");
DEBUG_MEM((uint64_t)idx);
LOG("free page merged"); DEBUG_MEM((uint64_t)idx);
}
CUR->state = PAGE_FREE;
CUR->size = sz;
@@ -67,7 +66,7 @@ void _pull(int idx, size_t sz)
CUR->size = 0;
break;
default:
exit(ERR_UNREACHABLE);
panic(ERR_UNREACHABLE);
}
}
@@ -80,8 +79,7 @@ void mman_init()
mman_page_cnt = (mman_memory_end - mman_memory_start) >> 12;
mman_frame_array = simple_alloc((mman_page_cnt << 1) * sizeof(page_header_t));
LOG(mman_memory_start);
LOG(mman_memory_end);
LOG(mman_memory_start); LOG(mman_memory_end);
DEBUG_MEM((uint64_t)mman_page_cnt);
mman_frame_array[0] = (page_header_t){
@@ -98,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);
@@ -134,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;
@@ -156,7 +155,7 @@ uint64_t _allocate_page(size_t req, int idx, uint64_t l, uint64_t r)
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;
}
@@ -164,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);
@@ -185,9 +184,7 @@ void _free_page(uint64_t req, int idx, uint64_t l, uint64_t r)
return;
case PAGE_ALLOCATED:
if (req == l) {
LOG("page freed");
LOG(l);
DEBUG_MEM(r);
LOG("page freed"); LOG(l); DEBUG_MEM(r);
CUR->state = PAGE_FREE;
CUR->size = sz;
return;
@@ -196,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));
@@ -210,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);
@@ -227,11 +224,9 @@ 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);
LOG("page reserved"); LOG(l); DEBUG_MEM(r);
CUR->state = PAGE_RESERVED;
CUR->size = 0;
return;
@@ -258,8 +253,6 @@ void reserve_page(void *begin, void *end)
uint64_t ql = ((uint64_t)begin - (uint64_t)mman_memory_start) >> 12;
uint64_t qr = (((uint64_t)end - (uint64_t)mman_memory_start - 1) >> 12) + 1;
LOG("reserve page");
LOG(ql);
DEBUG_MEM(qr);
LOG("reserve page"); LOG(ql); DEBUG_MEM(qr);
_reserve_page(ql, qr, 0, 0, mman_page_cnt);
}

122
kernel/lib/process.c Normal file
View File

@@ -0,0 +1,122 @@
#include <process.h>
#include <utils.h>
#include <errcode.h>
#include <logger.h>
#include <thread.h>
#include <kmalloc.h>
#include <mman.h>
#include <exec.h>
#include <initrd.h>
#include <string.h>
#include <interrupt.h>
int32_t global_pid_counter = 0;
vector_t *global_processes = 0x0;
static inline
process_t *_make_process()
{
process_t *ret = kmalloc(sizeof(process_t));
if (!global_processes)
global_processes = make_vector(0);
VEC_PUSH(global_processes, ret);
*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,
.sigstack = allocate_page(256),
.sigstack_size = 256 << 12,
.current_signal = 0,
.regs = kmalloc(sizeof(trapframe_t)),
};
memset(ret->sigstate, 0x0, SIGNAL_NUM * sizeof(bool));
memset(ret->sighandlers, 0x0, SIGNAL_NUM * sizeof(signal_handler_t));
memset(ret->regs, 0x0, sizeof(trapframe_t));
return ret;
}
static inline
void _init_process(process_t *process, const char *filename)
{
file_node_t *file = initrd_get(initrd_root, filename);
if (file == 0x0)
panic(ERR_NOT_EXIST);
memcpy(process->mem, file->filecontent, file->filesize);
*process->regs = (trapframe_t){
.spsr_el1 = 0x0, // enable all interrupt
.elr_el1 = (uint64_t)process->mem,
.sp_el0 = ((uint64_t)process->stack + process->stack_size - 64),
};
}
// 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();
if (!th->process)
th->process = _make_process();
_init_process(th->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 = _make_process();
memcpy(ret->stack, from->stack, from->stack_size);
memcpy(ret->mem, from->mem, from->mem_size);
memcpy(ret->sigstack, from->sigstack, from->sigstack_size);
memcpy(ret->sighandlers, from->sighandlers, sizeof(from->sighandlers));
*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;
}

View File

@@ -6,9 +6,11 @@
queue_t *make_queue()
{
queue_t *ret = kmalloc(sizeof(queue_t));
ret->size = 0;
ret->begin = kmalloc(sizeof(queue_node_t));
ret->end = kmalloc(sizeof(queue_node_t));
*ret = (queue_t){
.size = 0,
.begin = kmalloc(sizeof(queue_node_t)),
.end = kmalloc(sizeof(queue_node_t)),
};
*ret->begin = *ret->end = (queue_node_t){
.prev = (queue_node_t *)ret->begin,
.next = (queue_node_t *)ret->end,
@@ -21,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;
}
@@ -42,6 +44,7 @@ void queue_push_back(queue_t *queue, uint64_t val)
.value = 0,
};
queue->end = queue->end->next;
++queue->size;
}
void queue_push_front(queue_t *queue, uint64_t val)
@@ -54,4 +57,31 @@ void queue_push_front(queue_t *queue, uint64_t val)
.value = 0,
};
queue->begin = queue->begin->prev;
++queue->size;
}
uint64_t queue_pop_back(queue_t *queue)
{
if (!queue->size)
panic(ERR_OUT_OF_BOUND);
uint64_t ret = queue->end->prev->value;
queue->end->prev = queue->end->prev->prev;
queue->end->prev->next = queue->end;
--queue->size;
return ret;
}
uint64_t queue_pop_front(queue_t *queue)
{
if (!queue->size)
panic(ERR_OUT_OF_BOUND);
uint64_t ret = queue->begin->next->value;
queue->begin->next = queue->begin->next->next;
queue->begin->next->prev = queue->begin;
--queue->size;
return ret;
}

View File

@@ -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;
}

View File

@@ -1,261 +0,0 @@
#include <stddef.h>
#include <logger.h>
#include <timer.h>
#include <errcode.h>
#include <kmalloc.h>
#include <utils.h>
#include <string.h>
#include <uart.h>
#include <mbox.h>
#include <shell.h>
#include <exec.h>
#include <mman.h>
#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 <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
"settimeout <sec> <message...>: 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;
}

76
kernel/lib/signal.c Normal file
View File

@@ -0,0 +1,76 @@
#include <signal.h>
#include <logger.h>
#include <string.h>
#include <process.h>
#include <thread.h>
#include <kmalloc.h>
#include <interrupt.h>
#include <exec.h>
static inline
void _sighandler_wrapper(signal_handler_t handler)
{
handler();
asm volatile(
"mov x8, #10" ENDL
"svc 0"
::: "x8"
);
}
static inline
void _sigkill_default_handler()
{
thread_t *th = get_current();
th->status = THREAD_STATUS_ZOMBIE;
}
void run_signal(int32_t SIGNAL)
{
process_t *process = get_current()->process;
process->current_signal = SIGNAL;
LOG("run_signal"); LOG(process->sighandlers[SIGNAL]); DEBUG_SIGNAL(SIGNAL);
if (!process->sighandlers[SIGNAL]) {
switch (SIGNAL) {
case SIGKILL:
_sigkill_default_handler();
break;
default:
LOG("No default handler for this signal"); DEBUG_SIGNAL(SIGNAL);
}
return;
}
DEBUG_SIGNAL(process->sighandlers[SIGNAL]);
process->retregs = process->regs;
process->regs = kmalloc(sizeof(trapframe_t));
memcpy(process->regs, process->retregs, sizeof(trapframe_t));
*process->regs = (trapframe_t){
.x0 = (uint64_t)process->sighandlers[SIGNAL],
.elr_el1 = (uint64_t)_sighandler_wrapper,
.sp_el0 = ((uint64_t)process->sigstack + process->sigstack_size - 64),
};
disable_interrupt();
process->current_signal = SIGNAL;
process->sigstate[SIGNAL] = false;
user_exec(process->regs);
__builtin_unreachable();
}
void end_signal()
{
DEBUG_SIGNAL("end_signal");
process_t *process = get_current()->process;
disable_interrupt();
process->current_signal = 0x0;
kfree(process->regs);
process->regs = process->retregs;
user_exec(process->regs);
__builtin_unreachable();
}

114
kernel/lib/syscall.c Normal file
View File

@@ -0,0 +1,114 @@
#include <syscall.h>
#include <logger.h>
#include <uart.h>
#include <thread.h>
#include <process.h>
#include <mbox.h>
#include <exec.h>
#include <signal.h>
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((int32_t)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_by_id(int32_t pid)
sys_kill_by_id((int32_t)regs->x0);
break;
case 8: // void signal(int32_t SIGNAL, signal_handler_t handler)
sys_signal((int32_t)regs->x0, (signal_handler_t)regs->x1);
break;
case 9: // void kill(int32_t pid, int32_t SIGNAL)
sys_kill((int32_t)regs->x0, (int32_t)regs->x1);
break;
case 10: // void sigreturn(void)
sys_sigreturn();
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((uint8_t *)buf, size); }
size_t sys_uart_write(const char buf[], size_t size)
{ return uart_putb((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_by_id(int32_t pid)
{
if (!global_processes || global_processes->size <= (size_t)pid) {
LOG("Process not exist"); INFOR(pid);
return;
}
process_t *process = VEC_AT(process_t, global_processes, pid);
process->th->status = THREAD_STATUS_ZOMBIE;
LOG("Process killed"); INFOR(pid);
}
void sys_signal(int32_t SIGNAL, signal_handler_t handler)
{
thread_t *th = get_current();
th->process->sighandlers[SIGNAL] = handler;
LOG(handler); LOG(SIGNAL); DEBUG_SIGNAL("registered");
}
void sys_kill(int32_t pid, int32_t SIGNAL)
{
process_t *process = VEC_AT(process_t, global_processes, pid);
process->sigstate[SIGNAL] = true;
}
void sys_sigreturn(void)
{ end_signal(); }

21
kernel/lib/thread.S Normal file
View File

@@ -0,0 +1,21 @@
.global context_switch
context_switch:
stp x19, x20, [x0, 16 * 0]
stp x21, x22, [x0, 16 * 1]
stp x23, x24, [x0, 16 * 2]
stp x25, x26, [x0, 16 * 3]
stp x27, x28, [x0, 16 * 4]
stp fp, lr, [x0, 16 * 5]
mov x9, sp
str x9, [x0, 16 * 6]
ldp x19, x20, [x1, 16 * 0]
ldp x21, x22, [x1, 16 * 1]
ldp x23, x24, [x1, 16 * 2]
ldp x25, x26, [x1, 16 * 3]
ldp x27, x28, [x1, 16 * 4]
ldp fp, lr, [x1, 16 * 5]
ldr x9, [x1, 16 * 6]
mov sp, x9
msr tpidr_el1, x2
ret

118
kernel/lib/thread.c Normal file
View File

@@ -0,0 +1,118 @@
#include <thread.h>
#include <logger.h>
#include <utils.h>
#include <kmalloc.h>
#include <mman.h>
#include <queue.h>
#include <interrupt.h>
#include <string.h>
#include <timer.h>
queue_t *global_run_queue = 0x0;
queue_t *global_wait_queue = 0x0;
queue_t *global_gc_queue = 0x0;
thread_t *get_current(void)
{
uint64_t tpidr_el1;
R_SYSREG(tpidr_el1, tpidr_el1);
return (thread_t *)tpidr_el1;
}
static inline
void _thread_wrapper()
{
enable_interrupt();
thread_t *cur = get_current();
LOG("Running thread wrapper"); DEBUG_THREAD(cur->func);
cur->func(cur->param);
cur->status = THREAD_STATUS_ZOMBIE;
schedule();
}
static inline
thread_t *_make_thread(thread_func_t func, uint64_t param)
{
thread_t *ret = (thread_t *)kmalloc(sizeof(thread_t));
*ret = (thread_t){
.func = func,
.param = param,
.status = THREAD_STATUS_RUNABLE,
.retcode = 0,
.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 + 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)
{
// Runs before enable interrupt
QUEUE_PUSH_BACK(global_run_queue, _make_thread(func, param));
}
static inline
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");
}
return 0;
}
void thread_init(void)
{
global_run_queue = make_queue();
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)
{
disable_interrupt();
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);
while (global_run_queue->size > 0 && !next) {
next = QUEUE_POP_FRONT(thread_t, global_run_queue);
if (next->status == THREAD_STATUS_ZOMBIE) {
QUEUE_PUSH_BACK(global_gc_queue, next);
next = 0x0;
} else
QUEUE_PUSH_BACK(global_run_queue, next);
}
if (next && th != next)
context_switch(th->regs, next->regs, next);
enable_interrupt();
}

View File

@@ -3,128 +3,49 @@
#include <logger.h>
#include <utils.h>
#include <kmalloc.h>
#include <thread.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)
void timer_init()
{
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 _check_enable_timer()
{
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);
W_SYSREG(cntp_ctl_el0, 1);
} else
W_SYSREG(cntp_ctl_el0, 0);
}
static inline
void _traverse(timer_t *t)
{
if (!t) return;
DEBUG_EXCEP(t->data.firing_tick);
t->data.func(t->data.param);
_traverse(t->_l);
_traverse(t->_r);
}
void add_timer_task(task_t task)
{
DEBUG_EXCEP("add timer 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);
// _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);
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 >> 5);
}
void sleep(uint64_t ms)
{
uint64_t cntpct_el0, cntfrq_el0;
R_SYSREG(cntpct_el0, cntpct_el0);
R_SYSREG(cntfrq_el0, cntfrq_el0);
uint64_t wake = cntpct_el0 + cntfrq_el0 * ms / 1000000;
for (;;) {
R_SYSREG(cntpct_el0, cntpct_el0);
if (cntpct_el0 >= wake)
break;
yield();
}
}
void timer_irq_handler(void)
{
_enable_timer_irq(false);
uint64_t cntfrq_el0;
R_SYSREG(cntfrq_el0, cntfrq_el0);
W_SYSREG(cntp_tval_el0, cntfrq_el0 >> 5);
uint64_t cntpct_el0;
R_SYSREG(cntpct_el0, cntpct_el0);
LOG("timer irq"); 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);
global_timer = _pop(global_timer);
_check_enable_timer();
thread_t *th = get_current();
for (int32_t i = 0; i < SIGNAL_NUM; ++i) {
if (th->process->sigstate[i])
run_signal(i);
}
schedule();
}

View File

@@ -8,6 +8,7 @@
#include <gpio.h>
#include <stddef.h>
#include <ringbuffer.h>
#include <thread.h>
/* Auxilary mini UART registers */
#define AUX_ENABLE ((volatile uint32_t*)(MMIO_BASE + 0x00215004))
@@ -76,8 +77,10 @@ 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;
@@ -143,11 +146,12 @@ void uart_irq_handler(void)
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 (!is_uart_in_interrupt_queue && uart_writebuf)
_enable_uart_interrupt();
for (; sentlen < len; ++bytes, ++sentlen) {
while(!_uart_transmitter_idle())
yield();
_uart_write_data(*bytes);
}
return sentlen;
}
@@ -169,10 +173,10 @@ size_t uart_getb_async(uint8_t *bytes, size_t len)
{
size_t recvlen = 0;
for (; recvlen < len; ++bytes, ++recvlen) {
while (!uart_readbuf->size)
wfe(); // wait for interrupt
*bytes = ringbuffer_bump(uart_readbuf);
while (!_uart_data_ready())
yield();
*bytes = _uart_read_data();
}
return recvlen;
@@ -203,7 +207,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)

View File

@@ -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();
}

View File

@@ -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];
}

View File

@@ -1,21 +1,23 @@
#include <logger.h>
#include <timer.h>
#include <process.h>
#include <thread.h>
#include <kmalloc.h>
#include <uart.h>
#include <dtb.h>
#include <initrd.h>
#include <mman.h>
#include <shell.h>
#include <vector.h>
#include <utils.h>
#include <timer.h>
#include <exception.h>
#include <interrupt.h>
#include <mbox.h>
void init(void *dtb, file_node_t **initrd_root)
static inline
void _init(void *dtb)
{
init_exception();
exception_init();
// UART
uart_init();
// Device tree
@@ -27,94 +29,25 @@ 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();
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);
enable_interrupt();
}
void main(void *dtb)
{
file_node_t *initrd_root = 0x0;
init(dtb, &initrd_root);
INFOR("kernel running");
// LOG("system booting in");
// _print_time(0x0);
_init(dtb);
uint64_t el;
R_SYSREG(el, CurrentEL);
INFOR(el);
INFOR("Run user process syscall.img");
run_thread(run_process_by_name, (uint64_t)&"syscall.img");
void *page1 = allocate_page(1);
INFOR(page1);
void *page2 = allocate_page(2);
INFOR(page2);
void *page4 = allocate_page(4);
INFOR(page4);
void *page16 = allocate_page(16);
INFOR(page16);
free_page(page1);
free_page(page2);
free_page(page4);
free_page(page16);
void *page32 = allocate_page(32);
INFOR(page32);
page1 = allocate_page(1);
INFOR(page1);
free_page(page1);
void *kmalloc8 = kmalloc(8);
INFOR(kmalloc8);
kfree(kmalloc8);
kmalloc8 = kmalloc(8);
INFOR(kmalloc8);
kfree(kmalloc8);
void *kmalloc7k = kmalloc(7 * (1 << 10));
INFOR(kmalloc7k);
void *kmalloc8k = kmalloc(1 << 13);
INFOR(kmalloc8k);
kfree(kmalloc7k);
kfree(kmalloc8k);
page1 = allocate_page(1);
INFOR(page1);
int shell_cont = 1;
while (shell_cont) {
shell_cont = shell(initrd_root);
}
schedule();
}

View File

@@ -2,3 +2,5 @@
char logger_buf[LOGGER_BUFLEN];
char *logger_cur = logger_buf;
char sp_buf[LOGGER_BUFLEN];
char *sp_cur = sp_buf;

View File

@@ -59,6 +59,15 @@ void *memcpy(void *dest, const void *src, size_t count)
return ret;
}
void *memset(void *dest, int ch, size_t count)
{
void *ret = dest;
for (; count > 0; --count, ++dest)
*(uint8_t *)dest = ch & 0xff;
return ret;
}
void *memzero(void *start, void *end)
{
void *ret = start;

View File

@@ -9,26 +9,22 @@ if len(sys.argv) < 2:
print("no args for serial device")
exit()
while True:
kernel = open("kernel8.img", "rb").read()
r = serialtube(sys.argv[1], convert_newlines=False)
kernel = open("kernel8.img", "rb").read()
r = serialtube(sys.argv[1], convert_newlines=False)
# send size
sz = len(kernel)
print("size:", sz)
r.send(pack("<I", sz))
print(r.recvuntil(b"$").decode())
# send size
sz = len(kernel)
print("size:", sz)
r.send(pack("<I", sz))
print(r.recvuntil(b"$").decode())
# send kernel
splitsize = 1000
for i in tqdm(range(len(kernel) // splitsize), unit="KB"):
r.send(kernel[i * splitsize : (i + 1) * splitsize])
# send kernel
splitsize = 1000
for i in tqdm(range(len(kernel) // splitsize), unit="KB"):
r.send(kernel[i * splitsize : (i + 1) * splitsize])
r.send(kernel[len(kernel) // splitsize * splitsize:])
r.send(kernel[len(kernel) // splitsize * splitsize:])
sleep(1)
r.send(b"\n")
r.interactive()
r.send(b"\nreboot\n")
sleep(10)
sleep(1)
r.send(b"\n")
r.interactive()

View File

@@ -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

View File

@@ -0,0 +1,14 @@
#pragma once
#include <stddef.h>
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);

13
userprog/lib/syscall.S Normal file
View File

@@ -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

25
userprog/lib/syscall.c Normal file
View File

@@ -0,0 +1,25 @@
#include <syscall.h>
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); }