Draft: lab 5 failed
This commit is contained in:
2
Makefile
2
Makefile
@@ -6,7 +6,7 @@ GNU := $(ARCH)-linux-gnu
|
|||||||
GDB := $(GNU)-gdb
|
GDB := $(GNU)-gdb
|
||||||
|
|
||||||
QEMU := qemu-system-$(ARCH)
|
QEMU := qemu-system-$(ARCH)
|
||||||
QEMUFLAGS += -M raspi3b -display none -serial null
|
QEMUFLAGS += -M raspi3b -display gtk -serial null
|
||||||
|
|
||||||
CC := $(GNU)-gcc
|
CC := $(GNU)-gcc
|
||||||
CCFLAGS += -Wall -Wextra -O0 \
|
CCFLAGS += -Wall -Wextra -O0 \
|
||||||
|
|||||||
@@ -47,6 +47,22 @@ static inline char *_logger_int(char *dest, int x)
|
|||||||
*dest = '\0';
|
*dest = '\0';
|
||||||
return dest;
|
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)
|
static inline char *_logger_pointer(char *dest, void *x)
|
||||||
{
|
{
|
||||||
*dest++ = '*';
|
*dest++ = '*';
|
||||||
@@ -71,6 +87,7 @@ logger_cur = _Generic((msg), \
|
|||||||
const char *: _logger_string, \
|
const char *: _logger_string, \
|
||||||
uint64_t : _logger_hex, \
|
uint64_t : _logger_hex, \
|
||||||
int32_t : _logger_int, \
|
int32_t : _logger_int, \
|
||||||
|
size_t : _logger_uint, \
|
||||||
default : _logger_pointer \
|
default : _logger_pointer \
|
||||||
)(logger_cur, msg)
|
)(logger_cur, msg)
|
||||||
|
|
||||||
@@ -80,7 +97,18 @@ logger_cur = _Generic((msg), \
|
|||||||
_I_HATE_C_LANG(val); \
|
_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) { \
|
#define FLUSH(prefix) { \
|
||||||
|
_logger_hex(sp_cur, _r_sp()); \
|
||||||
|
_uart_puts_sync(sp_buf); \
|
||||||
|
_uart_puts_sync(" | "); \
|
||||||
_uart_puts_sync(prefix); \
|
_uart_puts_sync(prefix); \
|
||||||
_uart_puts_sync(logger_buf); \
|
_uart_puts_sync(logger_buf); \
|
||||||
_uart_puts_sync(ENDL); \
|
_uart_puts_sync(ENDL); \
|
||||||
@@ -130,7 +158,10 @@ logger_cur = _Generic((msg), \
|
|||||||
// #define DEBUG_INITRD(val) DEBUG(val)
|
// #define DEBUG_INITRD(val) DEBUG(val)
|
||||||
#define DEBUG_INITRD(val) CLEAN
|
#define DEBUG_INITRD(val) CLEAN
|
||||||
|
|
||||||
#define DEBUG_THREAD(val) DEBUG(val)
|
// #define DEBUG_THREAD(val) DEBUG(val)
|
||||||
|
#define DEBUG_THREAD(val) CLEAN
|
||||||
|
|
||||||
extern char logger_buf[LOGGER_BUFLEN];
|
extern char logger_buf[LOGGER_BUFLEN];
|
||||||
extern char *logger_cur;
|
extern char *logger_cur;
|
||||||
|
extern char sp_buf[LOGGER_BUFLEN];
|
||||||
|
extern char *sp_cur;
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
#pragma once
|
#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 not_implemented_handler(void);
|
||||||
void synchronous_handler(void);
|
void synchronous_handler(trapframe_t *regs);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
void user_exec(void *text, void *sp);
|
#include <process.h>
|
||||||
|
|
||||||
|
void user_exec(trapframe_t *regs);
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ typedef struct file_node {
|
|||||||
|
|
||||||
typedef void (*initrd_callback_func_t)(file_node_t *);
|
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);
|
void initrd_fdt_callback(const vector_t *props);
|
||||||
file_node_t *initrd_get(file_node_t *root, const char *filename);
|
file_node_t *initrd_get(file_node_t *root, const char *filename);
|
||||||
void initrd_traverse(file_node_t *tr, initrd_callback_func_t func);
|
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 fdt_callback_t initrd_dtb_cb;
|
||||||
extern void *initrd_start;
|
extern void *initrd_start;
|
||||||
extern void *initrd_end;
|
extern void *initrd_end;
|
||||||
|
extern file_node_t *initrd_root;
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ void add_interrupt_task(uint64_t priority,
|
|||||||
interrupt_callback_func_t func,
|
interrupt_callback_func_t func,
|
||||||
uint64_t param);
|
uint64_t param);
|
||||||
|
|
||||||
void init_interrupt(void);
|
|
||||||
void irq_handler(void);
|
void irq_handler(void);
|
||||||
|
|
||||||
void wfe(void);
|
void wfe(void);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* a properly aligned buffer */
|
/* a properly aligned buffer */
|
||||||
extern volatile unsigned int mbox[36];
|
// extern volatile unsigned int mbox[36];
|
||||||
|
|
||||||
#define MBOX_REQUEST 0
|
#define MBOX_REQUEST 0
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ extern volatile unsigned int mbox[36];
|
|||||||
#define MBOX_TAG_GETSERIAL 0x00010004
|
#define MBOX_TAG_GETSERIAL 0x00010004
|
||||||
#define MBOX_TAG_ARM_MEMORY 0x00010005
|
#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_board_revision(void);
|
||||||
unsigned int get_memory_base_addr(void);
|
unsigned int get_memory_base_addr(void);
|
||||||
unsigned int get_memory_size(void);
|
unsigned int get_memory_size(void);
|
||||||
|
|||||||
53
kernel/include/process.h
Normal file
53
kernel/include/process.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.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;
|
||||||
|
|
||||||
|
trapframe_t *regs;
|
||||||
|
} 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;
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <initrd.h>
|
|
||||||
|
|
||||||
int // is continue
|
|
||||||
shell(file_node_t *);
|
|
||||||
15
kernel/include/syscall.h
Normal file
15
kernel/include/syscall.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <process.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(int32_t pid);
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <queue.h>
|
#include <queue.h>
|
||||||
|
#include <process.h>
|
||||||
|
|
||||||
typedef int32_t (*thread_func_t)(uint64_t);
|
typedef int32_t (*thread_func_t)(uint64_t);
|
||||||
|
|
||||||
@@ -20,21 +21,21 @@ typedef struct {
|
|||||||
uint64_t x27, x28;
|
uint64_t x27, x28;
|
||||||
uint64_t fp, lr;
|
uint64_t fp, lr;
|
||||||
uint64_t sp;
|
uint64_t sp;
|
||||||
uint64_t sp_el0;
|
|
||||||
uint64_t elr_el1;
|
|
||||||
} cpu_state_t;
|
} cpu_state_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct thread {
|
||||||
thread_func_t func;
|
thread_func_t func;
|
||||||
uint64_t param;
|
uint64_t param;
|
||||||
|
|
||||||
thread_status_t status;
|
thread_status_t status;
|
||||||
int32_t retcode;
|
int32_t retcode;
|
||||||
|
|
||||||
void *stack_pointer;
|
void *stack;
|
||||||
size_t stack_size;
|
size_t stack_size;
|
||||||
|
|
||||||
cpu_state_t regs;
|
cpu_state_t *regs;
|
||||||
|
|
||||||
|
process_t *process;
|
||||||
} thread_t;
|
} thread_t;
|
||||||
|
|
||||||
// thread.S
|
// thread.S
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ typedef void (*task_callback_func_t)(uint64_t);
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t firing_tick;
|
uint64_t firing_tick;
|
||||||
uint64_t interval;
|
uint64_t interval;
|
||||||
uint64_t repeat;
|
|
||||||
|
|
||||||
task_callback_func_t func;
|
task_callback_func_t func;
|
||||||
uint64_t param;
|
uint64_t param;
|
||||||
@@ -20,6 +19,8 @@ typedef struct timer {
|
|||||||
task_t data;
|
task_t data;
|
||||||
} timer_t;
|
} timer_t;
|
||||||
|
|
||||||
|
void timer_init(void);
|
||||||
|
|
||||||
void add_timer_task(task_t task);
|
void add_timer_task(task_t task);
|
||||||
void sleep(uint64_t ms);
|
void sleep(uint64_t ms);
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ int isspace(int);
|
|||||||
int32_t atoi32(const char *);
|
int32_t atoi32(const char *);
|
||||||
uint32_t atoh32(const char *);
|
uint32_t atoh32(const char *);
|
||||||
|
|
||||||
void exit(int);
|
void panic(int errno);
|
||||||
|
|
||||||
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||||
#define MAX(x, y) (((x) < (y)) ? (y) : (x))
|
#define MAX(x, y) (((x) < (y)) ? (y) : (x))
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ void _struct_traverse(const char *path, const vector_t *cbs)
|
|||||||
case FDT_END:
|
case FDT_END:
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
exit(ERR_UNREACHABLE);
|
panic(ERR_UNREACHABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
traverse_struct_callback:
|
traverse_struct_callback:
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
// save general registers to stack
|
// save general registers to stack
|
||||||
.macro save_all
|
.macro save_all
|
||||||
sub sp, sp, 34 * 8
|
sub sp, sp, 36 * 8
|
||||||
stp x0, x1, [sp, 16 * 0]
|
stp x0, x1, [sp, 16 * 0]
|
||||||
stp x2, x3, [sp, 16 * 1]
|
stp x2, x3, [sp, 16 * 1]
|
||||||
stp x4, x5, [sp, 16 * 2]
|
stp x4, x5, [sp, 16 * 2]
|
||||||
@@ -17,22 +17,26 @@
|
|||||||
stp x22, x23, [sp, 16 * 11]
|
stp x22, x23, [sp, 16 * 11]
|
||||||
stp x24, x25, [sp, 16 * 12]
|
stp x24, x25, [sp, 16 * 12]
|
||||||
stp x26, x27, [sp, 16 * 13]
|
stp x26, x27, [sp, 16 * 13]
|
||||||
stp x28, x29, [sp, 16 * 14]
|
stp x28, fp, [sp, 16 * 14]
|
||||||
|
|
||||||
mrs x0, spsr_el1
|
mrs x0, spsr_el1
|
||||||
mrs x1, elr_el1
|
mrs x1, elr_el1
|
||||||
mrs x2, esr_el1
|
mrs x2, esr_el1
|
||||||
stp x0, x1, [sp, 16 * 15]
|
mrs x3, sp_el0
|
||||||
stp x2, lr, [sp, 16 * 16]
|
stp lr, x0, [sp, 16 * 15]
|
||||||
|
stp x1, x2, [sp, 16 * 16]
|
||||||
|
str x3, [sp, 16 * 17]
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
// load general registers from stack
|
// load general registers from stack
|
||||||
.macro load_all
|
.macro load_all
|
||||||
ldp x0, x1, [sp, 16 * 15]
|
ldp lr, x0, [sp, 16 * 15]
|
||||||
ldp x2, lr, [sp, 16 * 16]
|
ldp x1, x2, [sp, 16 * 16]
|
||||||
|
ldr x3, [sp, 16 * 17]
|
||||||
msr spsr_el1, x0
|
msr spsr_el1, x0
|
||||||
msr elr_el1, x1
|
msr elr_el1, x1
|
||||||
msr esr_el1, x2
|
msr esr_el1, x2
|
||||||
|
msr sp_el0, x3
|
||||||
|
|
||||||
ldp x0, x1, [sp, 16 * 0]
|
ldp x0, x1, [sp, 16 * 0]
|
||||||
ldp x2, x3, [sp, 16 * 1]
|
ldp x2, x3, [sp, 16 * 1]
|
||||||
@@ -48,9 +52,9 @@
|
|||||||
ldp x22, x23, [sp, 16 * 11]
|
ldp x22, x23, [sp, 16 * 11]
|
||||||
ldp x24, x25, [sp, 16 * 12]
|
ldp x24, x25, [sp, 16 * 12]
|
||||||
ldp x26, x27, [sp, 16 * 13]
|
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
|
.endm
|
||||||
|
|
||||||
_null_handler:
|
_null_handler:
|
||||||
@@ -61,6 +65,7 @@ _null_handler:
|
|||||||
|
|
||||||
_synchronous_handler:
|
_synchronous_handler:
|
||||||
save_all
|
save_all
|
||||||
|
mov x0, sp
|
||||||
bl synchronous_handler
|
bl synchronous_handler
|
||||||
load_all
|
load_all
|
||||||
eret
|
eret
|
||||||
@@ -3,8 +3,10 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <logger.h>
|
#include <logger.h>
|
||||||
#include <utils.h>
|
#include <utils.h>
|
||||||
|
#include <syscall.h>
|
||||||
|
#include <interrupt.h>
|
||||||
|
|
||||||
void init_exception()
|
void exception_init()
|
||||||
{
|
{
|
||||||
asm volatile(
|
asm volatile(
|
||||||
"adr x0, exception_vector_table" ENDL
|
"adr x0, exception_vector_table" ENDL
|
||||||
@@ -18,11 +20,10 @@ void not_implemented_handler()
|
|||||||
DEBUG_EXCEP("not implemented caught");
|
DEBUG_EXCEP("not implemented caught");
|
||||||
}
|
}
|
||||||
|
|
||||||
void synchronous_handler()
|
void synchronous_handler(trapframe_t *regs)
|
||||||
{
|
{
|
||||||
static int poop = 0;
|
disable_interrupt();
|
||||||
if (poop++ > 10)
|
|
||||||
exit(ERR_ADMINKILL);
|
|
||||||
DEBUG_EXCEP("synchronous caught");
|
DEBUG_EXCEP("synchronous caught");
|
||||||
uint64_t x0 = 0x0;
|
uint64_t x0 = 0x0;
|
||||||
R_REG(x0, x0);
|
R_REG(x0, x0);
|
||||||
@@ -36,5 +37,12 @@ void synchronous_handler()
|
|||||||
uint64_t esr_el1 = 0x0;
|
uint64_t esr_el1 = 0x0;
|
||||||
R_SYSREG(esr_el1, esr_el1);
|
R_SYSREG(esr_el1, esr_el1);
|
||||||
|
|
||||||
LOG(x0); LOG(spsr_el1); LOG(elr_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
36
kernel/lib/exec.S
Normal 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
|
||||||
@@ -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");
|
|
||||||
}
|
|
||||||
@@ -17,6 +17,8 @@ fdt_callback_t initrd_dtb_cb = {
|
|||||||
void *initrd_start = 0x0;
|
void *initrd_start = 0x0;
|
||||||
void *initrd_end = 0x0;
|
void *initrd_end = 0x0;
|
||||||
|
|
||||||
|
file_node_t *initrd_root = 0x0;
|
||||||
|
|
||||||
void initrd_fdt_callback(const vector_t *props)
|
void initrd_fdt_callback(const vector_t *props)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < (int)props->size; ++i) {
|
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;
|
cpio_newc_header_t *initrd_cur;
|
||||||
|
|
||||||
file_node_t *initrd_init(void)
|
void initrd_init(void)
|
||||||
{
|
{
|
||||||
cpio_newc_header_t *header;
|
cpio_newc_header_t *header;
|
||||||
char *filename;
|
char *filename;
|
||||||
@@ -128,8 +130,8 @@ file_node_t *initrd_init(void)
|
|||||||
_split(root, filename, <r, &rtr);
|
_split(root, filename, <r, &rtr);
|
||||||
root = _merge(ltr, _merge(newnode, 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)
|
static inline file_node_t *_node_bs(file_node_t *cur, const char *s)
|
||||||
|
|||||||
@@ -91,19 +91,11 @@ void add_interrupt_task(uint64_t priority,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_interrupt(void)
|
|
||||||
{
|
|
||||||
enable_interrupt();
|
|
||||||
_enable_timer_irq(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void irq_handler(void)
|
void irq_handler(void)
|
||||||
{
|
{
|
||||||
// uint64_t core0_irq_source = *CORE0_IRQ_SOURCE;
|
// uint64_t core0_irq_source = *CORE0_IRQ_SOURCE;
|
||||||
// DEBUG_EXCEP(core0_irq_source);
|
// DEBUG_EXCEP(core0_irq_source);
|
||||||
|
|
||||||
// TODO: turnoff global interrupt
|
|
||||||
|
|
||||||
if (_irq_source_timer())
|
if (_irq_source_timer())
|
||||||
timer_irq_handler();
|
timer_irq_handler();
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ void *simple_alloc(size_t size)
|
|||||||
size = (size_t)ALIGN8(size);
|
size = (size_t)ALIGN8(size);
|
||||||
|
|
||||||
if ((uint64_t)_heap_top + size >= (uint64_t)&__heap_end)
|
if ((uint64_t)_heap_top + size >= (uint64_t)&__heap_end)
|
||||||
exit(ERR_NO_MEM);
|
panic(ERR_NO_MEM);
|
||||||
|
|
||||||
void *ret = _heap_top;
|
void *ret = _heap_top;
|
||||||
_heap_top = (void *)((uint64_t)_heap_top + size);
|
_heap_top = (void *)((uint64_t)_heap_top + size);
|
||||||
@@ -49,17 +49,19 @@ void *simple_alloc(size_t size)
|
|||||||
|
|
||||||
void *mman_alloc(size_t unit)
|
void *mman_alloc(size_t unit)
|
||||||
{
|
{
|
||||||
|
LOG("mman_alloc called"); DEBUG_MEM(unit);
|
||||||
unit = (size_t)ALIGN8(unit);
|
unit = (size_t)ALIGN8(unit);
|
||||||
if (unit > (KMALLOC_MAX_ALLOCATOR_SIZE << 3))
|
if (unit > (KMALLOC_MAX_ALLOCATOR_SIZE << 3))
|
||||||
return allocate_page(((unit - 1) >> 12) + 1);
|
return allocate_page(((unit - 1) >> 12) + 1);
|
||||||
|
|
||||||
kmalloc_allocator_t *pool = &mman_kmalloc_pool[unit >> 3];
|
kmalloc_allocator_t *pool = &mman_kmalloc_pool[unit >> 3];
|
||||||
if (!pool->left) {
|
if (!pool->page_begin || !pool->left) {
|
||||||
void *page = allocate_page(1), *ptr = page + sizeof(kmalloc_header_t);
|
void *page = allocate_page(1);
|
||||||
|
|
||||||
*(kmalloc_header_t *)page = (kmalloc_header_t){
|
*(kmalloc_header_t *)page = (kmalloc_header_t){
|
||||||
.unit = unit,
|
.unit = unit,
|
||||||
.left = (PAGE_SIZE - sizeof(kmalloc_header_t)) / 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_prev = (kmalloc_header_t *)0x0,
|
||||||
.page_next = (kmalloc_header_t *)0x0,
|
.page_next = (kmalloc_header_t *)0x0,
|
||||||
};
|
};
|
||||||
@@ -67,20 +69,31 @@ void *mman_alloc(size_t unit)
|
|||||||
.left = ((kmalloc_header_t *)page)->left,
|
.left = ((kmalloc_header_t *)page)->left,
|
||||||
.page_begin = (kmalloc_header_t *)page,
|
.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)
|
uint64_t ptr = (uint64_t)page + sizeof(kmalloc_header_t);
|
||||||
*(void **)ptr = ptr + unit;
|
for (; ptr + unit <= (uint64_t)page + PAGE_SIZE; ptr += unit)
|
||||||
|
*(uint64_t *)ptr = ptr + unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ret = pool->page_begin->begin;
|
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->page_begin->begin = *(void **)pool->page_begin->begin;
|
||||||
|
|
||||||
--pool->left;
|
pool->left--;
|
||||||
--pool->page_begin->left;
|
pool->page_begin->left--;
|
||||||
if (!pool->page_begin->left)
|
if (!pool->left)
|
||||||
pool->page_begin = *(void **)pool->page_begin->page_next;
|
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("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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,6 +104,8 @@ void mman_free(void *ptr)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return; // early return for debugging
|
||||||
|
|
||||||
size_t unit = PAGE_HEADER(ptr)->unit;
|
size_t unit = PAGE_HEADER(ptr)->unit;
|
||||||
kmalloc_allocator_t *pool = &mman_kmalloc_pool[unit >> 3];
|
kmalloc_allocator_t *pool = &mman_kmalloc_pool[unit >> 3];
|
||||||
if (!PAGE_HEADER(ptr)->left) {
|
if (!PAGE_HEADER(ptr)->left) {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
#include <mbox.h>
|
#include <mbox.h>
|
||||||
|
|
||||||
/* mailbox message buffer */
|
/* 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 VIDEOCORE_MBOX (MMIO_BASE+0x0000B880)
|
||||||
#define MBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0))
|
#define MBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0))
|
||||||
@@ -49,7 +49,7 @@ volatile unsigned int __attribute__((aligned(16))) mbox[36];
|
|||||||
/**
|
/**
|
||||||
* Make a mailbox call. Returns 0 on failure, non-zero on success
|
* 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 *mbox)
|
||||||
{
|
{
|
||||||
unsigned int r = (((unsigned int)((unsigned long)&mbox)&~0xF) | (ch&0xF));
|
unsigned int r = (((unsigned int)((unsigned long)&mbox)&~0xF) | (ch&0xF));
|
||||||
/* wait until we can write to the mailbox */
|
/* wait until we can write to the mailbox */
|
||||||
@@ -57,7 +57,7 @@ int mbox_call(unsigned char ch)
|
|||||||
/* write the address of our message to the mailbox with channel identifier */
|
/* write the address of our message to the mailbox with channel identifier */
|
||||||
*MBOX_WRITE = r;
|
*MBOX_WRITE = r;
|
||||||
/* now wait for the response */
|
/* now wait for the response */
|
||||||
while(1) {
|
for (;;) {
|
||||||
/* is there a response? */
|
/* is there a response? */
|
||||||
do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_EMPTY);
|
do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_EMPTY);
|
||||||
/* is it a response to our message? */
|
/* is it a response to our message? */
|
||||||
@@ -70,6 +70,7 @@ int mbox_call(unsigned char ch)
|
|||||||
|
|
||||||
unsigned int get_board_revision(void)
|
unsigned int get_board_revision(void)
|
||||||
{
|
{
|
||||||
|
unsigned int __attribute__((aligned(16))) mbox[36];
|
||||||
mbox[0] = 36 * 4;
|
mbox[0] = 36 * 4;
|
||||||
mbox[1] = MBOX_REQUEST;
|
mbox[1] = MBOX_REQUEST;
|
||||||
|
|
||||||
@@ -81,13 +82,14 @@ unsigned int get_board_revision(void)
|
|||||||
|
|
||||||
mbox[6] = MBOX_TAG_LAST;
|
mbox[6] = MBOX_TAG_LAST;
|
||||||
|
|
||||||
mbox_call(MBOX_CH_PROP);
|
mbox_call(MBOX_CH_PROP, mbox);
|
||||||
|
|
||||||
return mbox[5];
|
return mbox[5];
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int get_memory_base_addr(void)
|
unsigned int get_memory_base_addr(void)
|
||||||
{
|
{
|
||||||
|
unsigned int __attribute__((aligned(16))) mbox[36];
|
||||||
mbox[0] = 36 * 4;
|
mbox[0] = 36 * 4;
|
||||||
mbox[1] = MBOX_REQUEST;
|
mbox[1] = MBOX_REQUEST;
|
||||||
|
|
||||||
@@ -100,13 +102,14 @@ unsigned int get_memory_base_addr(void)
|
|||||||
|
|
||||||
mbox[7] = MBOX_TAG_LAST;
|
mbox[7] = MBOX_TAG_LAST;
|
||||||
|
|
||||||
mbox_call(MBOX_CH_PROP);
|
mbox_call(MBOX_CH_PROP, mbox);
|
||||||
|
|
||||||
return mbox[5];
|
return mbox[5];
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int get_memory_size(void)
|
unsigned int get_memory_size(void)
|
||||||
{
|
{
|
||||||
|
unsigned int __attribute__((aligned(16))) mbox[36];
|
||||||
mbox[0] = 36 * 4;
|
mbox[0] = 36 * 4;
|
||||||
mbox[1] = MBOX_REQUEST;
|
mbox[1] = MBOX_REQUEST;
|
||||||
|
|
||||||
@@ -119,7 +122,7 @@ unsigned int get_memory_size(void)
|
|||||||
|
|
||||||
mbox[7] = MBOX_TAG_LAST;
|
mbox[7] = MBOX_TAG_LAST;
|
||||||
|
|
||||||
mbox_call(MBOX_CH_PROP);
|
mbox_call(MBOX_CH_PROP, mbox);
|
||||||
|
|
||||||
return mbox[6];
|
return mbox[6];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ void _pull(int idx, size_t sz)
|
|||||||
CUR->size = 0;
|
CUR->size = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
exit(ERR_UNREACHABLE);
|
panic(ERR_UNREACHABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +96,7 @@ void mman_init()
|
|||||||
(void *)ntoh64(entry->address) + ntoh64(entry->size));
|
(void *)ntoh64(entry->address) + ntoh64(entry->size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reserve_page((void *)0x00000000, (void *)0x00001000);
|
||||||
reserve_page(&__kernel_start, &__kernel_end);
|
reserve_page(&__kernel_start, &__kernel_end);
|
||||||
reserve_page(&__heap_start, &__stack_end);
|
reserve_page(&__heap_start, &__stack_end);
|
||||||
reserve_page(dtb_start, dtb_end);
|
reserve_page(dtb_start, dtb_end);
|
||||||
@@ -132,7 +133,7 @@ uint64_t _allocate_page(size_t req, int idx, uint64_t l, uint64_t r)
|
|||||||
case PAGE_RESERVED:
|
case PAGE_RESERVED:
|
||||||
return MMAN_NO_PAGE;
|
return MMAN_NO_PAGE;
|
||||||
default:
|
default:
|
||||||
exit(ERR_UNREACHABLE);
|
panic(ERR_UNREACHABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t ret = MMAN_NO_PAGE;
|
uint64_t ret = MMAN_NO_PAGE;
|
||||||
@@ -162,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)
|
void *allocate_page(size_t page_cnt)
|
||||||
{
|
{
|
||||||
if (msb64(page_cnt) != 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);
|
uint64_t offset = _allocate_page(page_cnt, 0, 0, mman_page_cnt);
|
||||||
|
|
||||||
if (offset == MMAN_NO_PAGE)
|
if (offset == MMAN_NO_PAGE)
|
||||||
exit(ERR_NO_MEM);
|
panic(ERR_NO_MEM);
|
||||||
// return (void *)0x0;
|
// return (void *)0x0;
|
||||||
|
|
||||||
return mman_memory_start + offset * (1 << 12);
|
return mman_memory_start + offset * (1 << 12);
|
||||||
@@ -192,7 +193,7 @@ void _free_page(uint64_t req, int idx, uint64_t l, uint64_t r)
|
|||||||
break;
|
break;
|
||||||
case PAGE_RESERVED:
|
case PAGE_RESERVED:
|
||||||
default:
|
default:
|
||||||
exit(ERR_UNREACHABLE);
|
panic(ERR_UNREACHABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t m = l + ((msb64(sz) == sz) ? (sz >> 1) : msb64(sz));
|
uint64_t m = l + ((msb64(sz) == sz) ? (sz >> 1) : msb64(sz));
|
||||||
@@ -206,7 +207,7 @@ void _free_page(uint64_t req, int idx, uint64_t l, uint64_t r)
|
|||||||
void free_page(void *page)
|
void free_page(void *page)
|
||||||
{
|
{
|
||||||
if (ALIGN4K(page) != 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;
|
uint64_t start = ((uint64_t)page - (uint64_t)mman_memory_start) >> 12;
|
||||||
_free_page(start, 0, 0, mman_page_cnt);
|
_free_page(start, 0, 0, mman_page_cnt);
|
||||||
@@ -223,7 +224,7 @@ void _reserve_page(uint64_t ql, uint64_t qr, int idx, uint64_t l, uint64_t r)
|
|||||||
if (CUR->state == PAGE_RESERVED)
|
if (CUR->state == PAGE_RESERVED)
|
||||||
return;
|
return;
|
||||||
if (CUR->state != PAGE_FREE)
|
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->state = PAGE_RESERVED;
|
||||||
|
|||||||
113
kernel/lib/process.c
Normal file
113
kernel/lib/process.c
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
#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;
|
||||||
|
|
||||||
|
static inline
|
||||||
|
process_t *_make_process(const char *filename)
|
||||||
|
{
|
||||||
|
process_t *ret = kmalloc(sizeof(process_t));
|
||||||
|
|
||||||
|
file_node_t *file = initrd_get(initrd_root, filename);
|
||||||
|
if (file == 0x0)
|
||||||
|
panic(ERR_NOT_EXIST);
|
||||||
|
|
||||||
|
*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,
|
||||||
|
|
||||||
|
.regs = kmalloc(sizeof(trapframe_t)),
|
||||||
|
};
|
||||||
|
memcpy(ret->mem, file->filecontent, file->filesize);
|
||||||
|
memset(ret->regs, 0x0, sizeof(trapframe_t));
|
||||||
|
*ret->regs = (trapframe_t){
|
||||||
|
.spsr_el1 = 0x0, // enable all interrupt
|
||||||
|
.elr_el1 = (uint64_t)ret->mem,
|
||||||
|
.sp_el0 = ((uint64_t)ret->stack + ret->stack_size - 64),
|
||||||
|
};
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
th->process = _make_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 = kmalloc(sizeof(process_t));
|
||||||
|
*ret = (process_t){
|
||||||
|
.pid = global_pid_counter++,
|
||||||
|
.th = 0x0,
|
||||||
|
|
||||||
|
.exitcode = from->exitcode,
|
||||||
|
|
||||||
|
.stack = allocate_page(256),
|
||||||
|
.stack_size = 256 << 12,
|
||||||
|
|
||||||
|
.mem = allocate_page(256),
|
||||||
|
.mem_size = 256 << 12,
|
||||||
|
|
||||||
|
.regs = kmalloc(sizeof(trapframe_t)),
|
||||||
|
};
|
||||||
|
memcpy(ret->stack, from->stack, from->stack_size);
|
||||||
|
memcpy(ret->mem, from->mem, from->mem_size);
|
||||||
|
*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;
|
||||||
|
}
|
||||||
@@ -23,14 +23,14 @@ queue_t *make_queue()
|
|||||||
uint64_t queue_back(const queue_t *queue)
|
uint64_t queue_back(const queue_t *queue)
|
||||||
{
|
{
|
||||||
if (!queue->size)
|
if (!queue->size)
|
||||||
exit(ERR_OUT_OF_BOUND);
|
panic(ERR_OUT_OF_BOUND);
|
||||||
return queue->end->prev->value;
|
return queue->end->prev->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t queue_front(const queue_t *queue)
|
uint64_t queue_front(const queue_t *queue)
|
||||||
{
|
{
|
||||||
if (!queue->size)
|
if (!queue->size)
|
||||||
exit(ERR_OUT_OF_BOUND);
|
panic(ERR_OUT_OF_BOUND);
|
||||||
return queue->begin->next->value;
|
return queue->begin->next->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ void queue_push_front(queue_t *queue, uint64_t val)
|
|||||||
uint64_t queue_pop_back(queue_t *queue)
|
uint64_t queue_pop_back(queue_t *queue)
|
||||||
{
|
{
|
||||||
if (!queue->size)
|
if (!queue->size)
|
||||||
exit(ERR_OUT_OF_BOUND);
|
panic(ERR_OUT_OF_BOUND);
|
||||||
|
|
||||||
uint64_t ret = queue->end->prev->value;
|
uint64_t ret = queue->end->prev->value;
|
||||||
queue->end->prev = queue->end->prev->prev;
|
queue->end->prev = queue->end->prev->prev;
|
||||||
@@ -76,7 +76,7 @@ uint64_t queue_pop_back(queue_t *queue)
|
|||||||
uint64_t queue_pop_front(queue_t *queue)
|
uint64_t queue_pop_front(queue_t *queue)
|
||||||
{
|
{
|
||||||
if (!queue->size)
|
if (!queue->size)
|
||||||
exit(ERR_OUT_OF_BOUND);
|
panic(ERR_OUT_OF_BOUND);
|
||||||
|
|
||||||
uint64_t ret = queue->begin->next->value;
|
uint64_t ret = queue->begin->next->value;
|
||||||
queue->begin->next = queue->begin->next->next;
|
queue->begin->next = queue->begin->next->next;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ int ringbuffer_push(ringbuffer_t *buf, uint8_t val)
|
|||||||
uint8_t ringbuffer_bump(ringbuffer_t *buf)
|
uint8_t ringbuffer_bump(ringbuffer_t *buf)
|
||||||
{
|
{
|
||||||
if (buf->size == 0)
|
if (buf->size == 0)
|
||||||
exit(ERR_INVALID_OP);
|
panic(ERR_INVALID_OP);
|
||||||
|
|
||||||
uint8_t ret = *buf->read++;
|
uint8_t ret = *buf->read++;
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ uint8_t ringbuffer_bump(ringbuffer_t *buf)
|
|||||||
uint8_t ringbuffer_peek(ringbuffer_t *buf)
|
uint8_t ringbuffer_peek(ringbuffer_t *buf)
|
||||||
{
|
{
|
||||||
if (buf->size == 0)
|
if (buf->size == 0)
|
||||||
exit(ERR_INVALID_OP);
|
panic(ERR_INVALID_OP);
|
||||||
|
|
||||||
return *buf->read;
|
return *buf->read;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,256 +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;
|
|
||||||
}
|
|
||||||
79
kernel/lib/syscall.c
Normal file
79
kernel/lib/syscall.c
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#include <syscall.h>
|
||||||
|
#include <logger.h>
|
||||||
|
#include <uart.h>
|
||||||
|
#include <thread.h>
|
||||||
|
#include <process.h>
|
||||||
|
#include <mbox.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((int)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(int32_t pid)
|
||||||
|
sys_kill((int)regs->x0);
|
||||||
|
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_sync((uint8_t *)buf, size); }
|
||||||
|
|
||||||
|
size_t sys_uart_write(const char buf[], size_t size)
|
||||||
|
{ return uart_putb_sync((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(int32_t pid)
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <queue.h>
|
#include <queue.h>
|
||||||
#include <interrupt.h>
|
#include <interrupt.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <timer.h>
|
||||||
|
|
||||||
queue_t *global_run_queue = 0x0;
|
queue_t *global_run_queue = 0x0;
|
||||||
queue_t *global_wait_queue = 0x0;
|
queue_t *global_wait_queue = 0x0;
|
||||||
@@ -21,9 +22,11 @@ thread_t *get_current(void)
|
|||||||
static inline
|
static inline
|
||||||
void _thread_wrapper()
|
void _thread_wrapper()
|
||||||
{
|
{
|
||||||
|
enable_interrupt();
|
||||||
|
|
||||||
thread_t *cur = get_current();
|
thread_t *cur = get_current();
|
||||||
|
|
||||||
LOG("Running"); DEBUG_THREAD(cur->func);
|
LOG("Running thread wrapper"); DEBUG_THREAD(cur->func);
|
||||||
cur->func(cur->param);
|
cur->func(cur->param);
|
||||||
|
|
||||||
cur->status = THREAD_STATUS_ZOMBIE;
|
cur->status = THREAD_STATUS_ZOMBIE;
|
||||||
@@ -43,19 +46,26 @@ thread_t *_make_thread(thread_func_t func, uint64_t param)
|
|||||||
.status = THREAD_STATUS_RUNABLE,
|
.status = THREAD_STATUS_RUNABLE,
|
||||||
.retcode = 0,
|
.retcode = 0,
|
||||||
|
|
||||||
.stack_pointer = allocate_page(256),
|
.stack = allocate_page(256),
|
||||||
.stack_size = 256 << 12,
|
.stack_size = 256 << 12,
|
||||||
|
|
||||||
|
.regs = kmalloc(sizeof(cpu_state_t)),
|
||||||
|
|
||||||
|
.process = 0x0,
|
||||||
};
|
};
|
||||||
memset(&ret->regs, 0, sizeof(cpu_state_t));
|
memset(ret->regs, 0, sizeof(cpu_state_t));
|
||||||
ret->regs.sp = (uint64_t)ret->stack_pointer + ret->stack_size - 64;
|
ret->regs->sp = (uint64_t)ret->stack + ret->stack_size - 64;
|
||||||
ret->regs.lr = (uint64_t)_thread_wrapper;
|
ret->regs->lr = (uint64_t)_thread_wrapper;
|
||||||
ret->regs.fp = ret->regs.sp;
|
ret->regs->fp = ret->regs->sp;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_thread(thread_func_t func, uint64_t param)
|
void run_thread(thread_func_t func, uint64_t param)
|
||||||
{ QUEUE_PUSH_BACK(global_run_queue, _make_thread(func, param)); }
|
{
|
||||||
|
// Runs before enable interrupt
|
||||||
|
QUEUE_PUSH_BACK(global_run_queue, _make_thread(func, param));
|
||||||
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
int32_t _idle(uint64_t)
|
int32_t _idle(uint64_t)
|
||||||
@@ -63,7 +73,9 @@ int32_t _idle(uint64_t)
|
|||||||
DEBUG_THREAD("enter idle thread");
|
DEBUG_THREAD("enter idle thread");
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
enable_interrupt();
|
||||||
schedule();
|
schedule();
|
||||||
|
DEBUG_THREAD(global_gc_queue->size);
|
||||||
// DEBUG_THREAD("back to idle thread");
|
// DEBUG_THREAD("back to idle thread");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,23 +88,20 @@ void thread_init(void)
|
|||||||
global_wait_queue = make_queue();
|
global_wait_queue = make_queue();
|
||||||
global_gc_queue = make_queue();
|
global_gc_queue = make_queue();
|
||||||
|
|
||||||
|
thread_t *th = kmalloc(sizeof(thread_t));
|
||||||
|
W_SYSREG(tpidr_el1, th);
|
||||||
|
|
||||||
run_thread(_idle, 0x0);
|
run_thread(_idle, 0x0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void schedule(void)
|
void schedule(void)
|
||||||
{
|
{
|
||||||
// DEBUG_THREAD("schedule!");
|
|
||||||
disable_interrupt();
|
disable_interrupt();
|
||||||
|
|
||||||
// DEBUG_THREAD("run queue:");
|
thread_t *th = get_current(), *next = 0x0;
|
||||||
for (queue_node_t *n = global_run_queue->begin->next;
|
LOG("Run thread"); LOG(global_run_queue->size); DEBUG_THREAD(th);
|
||||||
n != global_run_queue->end;
|
LOG(th->stack); DEBUG_THREAD(th->regs->sp);
|
||||||
n = n->next) {
|
|
||||||
|
|
||||||
// LOG(n); DEBUG_THREAD(n->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
thread_t *cur = get_current(), *next = 0x0;
|
|
||||||
while (global_run_queue->size > 0 && !next) {
|
while (global_run_queue->size > 0 && !next) {
|
||||||
next = QUEUE_POP_FRONT(thread_t, global_run_queue);
|
next = QUEUE_POP_FRONT(thread_t, global_run_queue);
|
||||||
if (next->status == THREAD_STATUS_ZOMBIE) {
|
if (next->status == THREAD_STATUS_ZOMBIE) {
|
||||||
@@ -102,8 +111,8 @@ void schedule(void)
|
|||||||
QUEUE_PUSH_BACK(global_run_queue, next);
|
QUEUE_PUSH_BACK(global_run_queue, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next && cur != next)
|
if (next && th != next)
|
||||||
context_switch(&cur->regs, &next->regs, next);
|
context_switch(th->regs, next->regs, next);
|
||||||
|
|
||||||
enable_interrupt();
|
enable_interrupt();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,45 @@ timer_t *global_timer = (timer_t *)0x0;
|
|||||||
|
|
||||||
MMIO_W_HELPER(_enable_timer_irq, CORE0_TIMER_IRQ_CTRL, 0x1, 1);
|
MMIO_W_HELPER(_enable_timer_irq, CORE0_TIMER_IRQ_CTRL, 0x1, 1);
|
||||||
|
|
||||||
|
static inline
|
||||||
|
task_t _make_timer_task(uint64_t interval_s, task_callback_func_t func,
|
||||||
|
uint64_t param)
|
||||||
|
{
|
||||||
|
uint64_t cntpct_el0, cntfrq_el0;
|
||||||
|
R_SYSREG(cntpct_el0, cntpct_el0);
|
||||||
|
R_SYSREG(cntfrq_el0, cntfrq_el0);
|
||||||
|
|
||||||
|
return (task_t){
|
||||||
|
.firing_tick = cntpct_el0 + interval_s * cntfrq_el0,
|
||||||
|
.interval = interval_s * cntfrq_el0,
|
||||||
|
|
||||||
|
.func = func,
|
||||||
|
.param = param,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _scheduler_timeout(uint64_t)
|
||||||
|
{
|
||||||
|
add_timer_task(_make_timer_task(1, _scheduler_timeout, 0x0));
|
||||||
|
schedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_init()
|
||||||
|
{
|
||||||
|
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 >> 1);
|
||||||
|
|
||||||
|
return;
|
||||||
|
add_timer_task(_make_timer_task(1, _scheduler_timeout, 0x0));
|
||||||
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
uint32_t _d(timer_t *t)
|
uint32_t _d(timer_t *t)
|
||||||
{ return t ? t->_d : 0; }
|
{ return t ? t->_d : 0; }
|
||||||
@@ -42,8 +81,10 @@ timer_t *_merge(timer_t *a, timer_t *b)
|
|||||||
static inline
|
static inline
|
||||||
timer_t *_pop(timer_t *t)
|
timer_t *_pop(timer_t *t)
|
||||||
{
|
{
|
||||||
if (!t || (!t->_l && !t->_r))
|
if (!t || (!t->_l && !t->_r)) {
|
||||||
|
kfree(t);
|
||||||
return (timer_t *)0x0;
|
return (timer_t *)0x0;
|
||||||
|
}
|
||||||
return _merge(t->_l, t->_r);
|
return _merge(t->_l, t->_r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,6 +167,9 @@ void _timer_task_wrapper(uint64_t param)
|
|||||||
void timer_irq_handler(void)
|
void timer_irq_handler(void)
|
||||||
{
|
{
|
||||||
_enable_timer_irq(false);
|
_enable_timer_irq(false);
|
||||||
|
schedule();
|
||||||
|
_enable_timer_irq(true);
|
||||||
|
return;
|
||||||
|
|
||||||
uint64_t cntpct_el0;
|
uint64_t cntpct_el0;
|
||||||
R_SYSREG(cntpct_el0, cntpct_el0);
|
R_SYSREG(cntpct_el0, cntpct_el0);
|
||||||
|
|||||||
@@ -76,11 +76,13 @@ void uart_init(void)
|
|||||||
uart_readbuf = make_ringbuffer(UART_BUFLEN);
|
uart_readbuf = make_ringbuffer(UART_BUFLEN);
|
||||||
uart_writebuf = make_ringbuffer(UART_BUFLEN);
|
uart_writebuf = make_ringbuffer(UART_BUFLEN);
|
||||||
|
|
||||||
_uart_enable_receive_interrupt(true);
|
// _uart_enable_receive_interrupt(true);
|
||||||
//uint64_t ier = *AUX_MU_IER;
|
_uart_enable_receive_interrupt(false);
|
||||||
|
_uart_enable_transmit_interrupt(false);
|
||||||
|
// uint64_t ier = *AUX_MU_IER;
|
||||||
|
|
||||||
uart_getb = uart_getb_async;
|
// uart_getb = uart_getb_async;
|
||||||
uart_putb = uart_putb_async;
|
// uart_putb = uart_putb_async;
|
||||||
|
|
||||||
is_uart_inited = true;
|
is_uart_inited = true;
|
||||||
}
|
}
|
||||||
@@ -203,7 +205,7 @@ void uart_puts(const char *s)
|
|||||||
size_t len = strlen(s);
|
size_t len = strlen(s);
|
||||||
size_t ret = uart_putb((const uint8_t *)s, len);
|
size_t ret = uart_putb((const uint8_t *)s, len);
|
||||||
if (ret != len)
|
if (ret != len)
|
||||||
exit(ERR_IO_FAILED);
|
panic(ERR_IO_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_hex(uint64_t d)
|
void uart_hex(uint64_t d)
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ int isupper(int c)
|
|||||||
int32_t atoi32(const char *s)
|
int32_t atoi32(const char *s)
|
||||||
{
|
{
|
||||||
if (!s)
|
if (!s)
|
||||||
exit(ERR_CONVERSION);
|
panic(ERR_CONVERSION);
|
||||||
|
|
||||||
int is_neg = 0;
|
int is_neg = 0;
|
||||||
if (*s != '\0' && *s == '-')
|
if (*s != '\0' && *s == '-')
|
||||||
@@ -106,7 +106,7 @@ int32_t atoi32(const char *s)
|
|||||||
int32_t ret = 0;
|
int32_t ret = 0;
|
||||||
for (; *s != '\0'; ++s) {
|
for (; *s != '\0'; ++s) {
|
||||||
if (!isdigit(*s))
|
if (!isdigit(*s))
|
||||||
exit(ERR_CONVERSION);
|
panic(ERR_CONVERSION);
|
||||||
ret *= 10, ret += *s - '0';
|
ret *= 10, ret += *s - '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,12 +116,12 @@ int32_t atoi32(const char *s)
|
|||||||
uint32_t atoh32(const char *s)
|
uint32_t atoh32(const char *s)
|
||||||
{
|
{
|
||||||
if (!s)
|
if (!s)
|
||||||
exit(ERR_CONVERSION);
|
panic(ERR_CONVERSION);
|
||||||
|
|
||||||
uint32_t ret = 0;
|
uint32_t ret = 0;
|
||||||
for (int i = 8; i-- && *s != '\0'; ++s) {
|
for (int i = 8; i-- && *s != '\0'; ++s) {
|
||||||
if (!isxdigit(*s))
|
if (!isxdigit(*s))
|
||||||
exit(ERR_CONVERSION);
|
panic(ERR_CONVERSION);
|
||||||
ret <<= 4, ret |= (isdigit(*s) ? *s - '0' :
|
ret <<= 4, ret |= (isdigit(*s) ? *s - '0' :
|
||||||
(isupper(*s) ? *s - 'A' + 10 :
|
(isupper(*s) ? *s - 'A' + 10 :
|
||||||
*s - 'a' + 10));
|
*s - 'a' + 10));
|
||||||
@@ -130,7 +130,7 @@ uint32_t atoh32(const char *s)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void exit(int exit_code)
|
void panic(int exitcode)
|
||||||
{
|
{
|
||||||
static int print = 0;
|
static int print = 0;
|
||||||
if (!print) {
|
if (!print) {
|
||||||
@@ -138,14 +138,14 @@ void exit(int exit_code)
|
|||||||
"OOPS! YOUR KERNEL DEAD" ENDL
|
"OOPS! YOUR KERNEL DEAD" ENDL
|
||||||
"ERROR CODE: "
|
"ERROR CODE: "
|
||||||
);
|
);
|
||||||
uart_hex(exit_code);
|
uart_hex(exitcode);
|
||||||
uart_puts(ENDL);
|
uart_puts(ENDL);
|
||||||
print = 1;
|
print = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
asm volatile(
|
asm volatile(
|
||||||
"wfe\n"
|
"wfe\n"
|
||||||
"b exit"
|
"b panic"
|
||||||
);
|
);
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ vector_t *make_vector(size_t size)
|
|||||||
uint64_t vec_at(const vector_t *vec, size_t idx)
|
uint64_t vec_at(const vector_t *vec, size_t idx)
|
||||||
{
|
{
|
||||||
if (idx >= vec->size)
|
if (idx >= vec->size)
|
||||||
exit(ERR_OUT_OF_BOUND);
|
panic(ERR_OUT_OF_BOUND);
|
||||||
|
|
||||||
return vec->data[idx];
|
return vec->data[idx];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,22 @@
|
|||||||
#include <logger.h>
|
#include <logger.h>
|
||||||
#include <timer.h>
|
#include <process.h>
|
||||||
|
#include <thread.h>
|
||||||
#include <kmalloc.h>
|
#include <kmalloc.h>
|
||||||
#include <uart.h>
|
#include <uart.h>
|
||||||
#include <dtb.h>
|
#include <dtb.h>
|
||||||
#include <initrd.h>
|
#include <initrd.h>
|
||||||
#include <mman.h>
|
#include <mman.h>
|
||||||
#include <shell.h>
|
|
||||||
#include <vector.h>
|
#include <vector.h>
|
||||||
#include <utils.h>
|
#include <utils.h>
|
||||||
#include <thread.h>
|
#include <timer.h>
|
||||||
#include <exception.h>
|
#include <exception.h>
|
||||||
#include <interrupt.h>
|
#include <interrupt.h>
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
void _init(void *dtb, file_node_t **initrd_root)
|
void _init(void *dtb)
|
||||||
{
|
{
|
||||||
init_exception();
|
exception_init();
|
||||||
|
|
||||||
// UART
|
|
||||||
uart_init();
|
uart_init();
|
||||||
|
|
||||||
// Device tree
|
// Device tree
|
||||||
@@ -29,56 +28,22 @@ void _init(void *dtb, file_node_t **initrd_root)
|
|||||||
fdt_traverse(dtb_struct_cbs);
|
fdt_traverse(dtb_struct_cbs);
|
||||||
DEBUG_DTB("device tree parse done");
|
DEBUG_DTB("device tree parse done");
|
||||||
|
|
||||||
// Initramfs
|
initrd_init();
|
||||||
DEBUG_INITRD(initrd_start);
|
|
||||||
*initrd_root = initrd_init();
|
|
||||||
|
|
||||||
// Memory (Buddy system)
|
|
||||||
mman_init();
|
mman_init();
|
||||||
|
|
||||||
// Threads
|
|
||||||
thread_init();
|
thread_init();
|
||||||
|
|
||||||
init_interrupt();
|
timer_init();
|
||||||
}
|
|
||||||
|
|
||||||
static inline
|
enable_interrupt();
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline
|
|
||||||
int32_t _test(uint64_t)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 10; ++i) {
|
|
||||||
LOG(i); DEBUG_THREAD(get_current());
|
|
||||||
sleep(1000000);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void main(void *dtb)
|
void main(void *dtb)
|
||||||
{
|
{
|
||||||
file_node_t *initrd_root = 0x0;
|
_init(dtb);
|
||||||
_init(dtb, &initrd_root);
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i)
|
run_thread(run_process_by_name, (uint64_t)&"syscall.img");
|
||||||
run_thread(_test, 0x0);
|
|
||||||
|
|
||||||
schedule();
|
schedule();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,3 +2,5 @@
|
|||||||
|
|
||||||
char logger_buf[LOGGER_BUFLEN];
|
char logger_buf[LOGGER_BUFLEN];
|
||||||
char *logger_cur = logger_buf;
|
char *logger_cur = logger_buf;
|
||||||
|
char sp_buf[LOGGER_BUFLEN];
|
||||||
|
char *sp_cur = sp_buf;
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ LD := $(GNU)-ld
|
|||||||
LDFLAGS += -g -nostdlib -no-pie
|
LDFLAGS += -g -nostdlib -no-pie
|
||||||
OBJCOPY := $(GNU)-objcopy
|
OBJCOPY := $(GNU)-objcopy
|
||||||
|
|
||||||
|
INCLUDE := -I../include -Iinclude
|
||||||
|
|
||||||
LD_SCRIPT := linker.ld
|
LD_SCRIPT := linker.ld
|
||||||
SRCS := $(shell find . -name '*.[cS]')
|
SRCS := $(shell find . -name '*.[cS]')
|
||||||
OBJS := $(SRCS:%=%.o)
|
OBJS := $(SRCS:%=%.o)
|
||||||
@@ -29,11 +31,11 @@ userprog.elf: $(LD_SCRIPT) $(OBJS)
|
|||||||
|
|
||||||
%.S.o: %.S
|
%.S.o: %.S
|
||||||
mkdir -p $(dir $@)
|
mkdir -p $(dir $@)
|
||||||
$(CC) -c $< -o $@ $(CCFLAGS)
|
$(CC) -c $< -o $@ $(INCLUDE) $(CCFLAGS)
|
||||||
|
|
||||||
%.c.o: %.c
|
%.c.o: %.c
|
||||||
mkdir -p $(dir $@)
|
mkdir -p $(dir $@)
|
||||||
$(CC) -c $< -o $@ $(CCFLAGS)
|
$(CC) -c $< -o $@ $(INCLUDE) $(CCFLAGS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
-rm $(OBJS) userprog userprog.elf
|
-rm $(OBJS) userprog userprog.elf
|
||||||
|
|||||||
14
userprog/include/syscall.h
Normal file
14
userprog/include/syscall.h
Normal 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
13
userprog/lib/syscall.S
Normal 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
25
userprog/lib/syscall.c
Normal 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); }
|
||||||
Reference in New Issue
Block a user