Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

310555003 lab5 #164

Open
wants to merge 16 commits into
base: 310555003
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ $(INITRAMFS_CPIO): $(INITRAMFS_FILES)
cd initramfs; find . | cpio -o -H newc > ../$(INITRAMFS_CPIO)

qemu: all $(INITRAMFS_CPIO) $(RPI3_DTB)
qemu-system-aarch64 -M raspi3 -kernel $(BOOTLOADER_IMG) -display none \
qemu-system-aarch64 -M raspi3 -kernel $(BOOTLOADER_IMG) \
-initrd $(INITRAMFS_CPIO) \
-dtb $(RPI3_DTB) \
-chardev pty,id=pty0,logfile=pty.log,signal=off \
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ make image
make qemu
```

* You should either attach gdb to qemu, or just remove the arugments `-s -S` passed to qemu in the Makefile

* Qemu will emulate the bootloader and you can then attach to the bootloader shell with:
```
sudo screen /dev/pts/<pts_idx>
```

* In the bootloader shell, you can use the command `load` to ask the bootloader to load the kernel image. After entering the `load` command, you can send the kernel image to the bootloader with the following command:
```
sudo ./tools/loadkernel.py /dev/pts/<pts_id> build/kernel8.img
```

## How to burn it into pi3

```
Expand Down
8 changes: 4 additions & 4 deletions include/kernel/cpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ void cpio_cat(char *cpio, char *filename);

/*
* Allocate a memory chunk and load the @filename program onto it. Then return
* the address of the chunk. This memory chunk needs to be passed to kfree()
* manually.
* the address of the chunk by @output_data. @output_data needs to be passed
* to kfree() manually.
*
* Return NULL if failed.
* Return output_data length, return 0 if no such file.
*/
char *cpio_load_prog(char *cpio, char *filename);
uint32 cpio_load_prog(char *cpio, const char *filename, char **output_data);

void initramfs_init(void);

Expand Down
20 changes: 20 additions & 0 deletions include/kernel/current.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef _CURRENT_H
#define _CURRENT_H

#include <utils.h>

struct _task_struct;

static inline struct _task_struct *get_current(void)
{
return (struct _task_struct *)read_sysreg(tpidr_el1);
}

static inline void set_current(struct _task_struct *task)
{
write_sysreg(tpidr_el1, task);
}

#define current get_current()

#endif /* _CURRENT_H */
9 changes: 6 additions & 3 deletions include/kernel/exec.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#ifndef _EXEC_H
#define _EXEC_H

// Change current EL to EL0 and execute the user program at @mem
// Set user stack to @user_sp
void exec_user_prog(char *mem, char *user_sp);
// TODO: Add argv & envp
void sched_new_user_prog(char *filename);

void exit_user_prog(void);

void exec_user_prog(void *entry, char *user_sp, char *kernel_sp);

#endif /* _EXEC_H */
5 changes: 4 additions & 1 deletion include/kernel/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ void irq_init();
/*
* On success, 0 is returned
*/
int irq_add_tasks(void (*task)(void *), void *args, uint32 prio);
int irq_run_task(void (*task)(void *),
void *args,
void (*fini)(void),
uint32 prio);

void irq_handler();
void exception_default_handler(uint32 n);
Expand Down
15 changes: 15 additions & 0 deletions include/kernel/kthread.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef _KTHREAD_H
#define _KTHREAD_H

#include <task.h>

void kthread_init(void);

void kthread_create(void (*start)(void));
void kthread_fini(void);

void kthread_add_wait_queue(task_struct *task);

void kthread_kill_zombies(void);

#endif /* _KTHREAD_H */
10 changes: 5 additions & 5 deletions include/kernel/mini_uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
uint32 uart_recvline(char *buff, int maxlen);
void uart_init(void);
char uart_recv(void);
void uart_recvn(char *buff, int n);
uint32 uart_recv_uint(void);
void uart_send(char c);
void uart_sendn(char *str, int n);
void uart_printf(char *fmt, ...);
void uart_sendn(const char *str, int n);
void uart_printf(const char *fmt, ...);

void uart_sync_printf(char *fmt, ...);
void uart_sync_printf(const char *fmt, ...);

void uart_irq_check(void);
void uart_irq_handler(void);
int uart_irq_check(void);

/* Switch asynchronous/synchronous mode for uart RW */
int uart_switch_mode(void);
Expand Down
8 changes: 8 additions & 0 deletions include/kernel/mode_switch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef _MODE_SWITCH_H
#define _MODE_SWITCH_H

#include <trapframe.h>

void exit_to_user_mode(trapframe regs);

#endif /* _MODE_SWITCH_H */
7 changes: 7 additions & 0 deletions include/kernel/preempt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#ifndef _PREEMPT_H
#define _PREEMPT_H

void preempt_disable(void);
void preempt_enable(void);

#endif /* _PREEMPT_H */
18 changes: 18 additions & 0 deletions include/kernel/sched.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef _SCHED_H
#define _SCHED_H

#include <task.h>

void switch_to(task_struct *from, task_struct *to);

void scheduler_init(void);

void schedule(void);

void schedule_tick(void);

void sched_add_task(task_struct *task);

void sched_del_task(task_struct *task);

#endif /* _SCHED_H */
89 changes: 89 additions & 0 deletions include/kernel/signal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#ifndef _SIGNAL_H
#define _SIGNAL_H

#include <types.h>
#include <list.h>
#include <trapframe.h>

// https://man7.org/linux/man-pages/man7/signal.7.html
// 0 means no signal
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define SIGILL 4
#define SIGTRAP 5
#define SIGABRT 6
#define SIGIOT 6
#define SIGBUS 7
#define SIGFPE 8
#define SIGKILL 9
#define SIGUSR1 10
#define SIGSEGV 11
#define SIGUSR2 12
#define SIGPIPE 13
#define SIGALRM 14
#define SIGTERM 15
#define SIGSTKFLT 16
#define SIGCHLD 17
#define SIGCONT 18
#define SIGSTOP 19
#define SIGTSTP 20
#define SIGTTIN 21
#define SIGTTOU 22
#define SIGURG 23
#define SIGXCPU 24
#define SIGXFSZ 25
#define SIGVTALRM 26
#define SIGPROF 27
#define SIGWINCH 28
#define SIGIO 29
#define SIGPOLL 29
#define SIGPWR 30
#define SIGSYS 31
#define SIGUNUSED 31

#define NSIG 32

struct signal_head_t {
/* Link signal_t */
struct list_head list;
};

struct signal_t {
struct list_head list;
uint32 signum;
};

typedef void (*sighandler_t)(int);

struct sigaction_t {
sighandler_t sighand;

/* flags */
uint32 kernel_hand;
};

struct sighand_t {
// 0-th sigaction_t is not used
struct sigaction_t sigactions[NSIG];
};

struct signal_head_t *signal_head_create(void);
void signal_head_free(struct signal_head_t *head);
void signal_head_reset(struct signal_head_t *head);

void handle_signal(trapframe *_);

struct sighand_t *sighand_create(void);
void sighand_free(struct sighand_t *sighand);
void sighand_reset(struct sighand_t *sighand);

/* Copy current signal handler to @sighand */
void sighand_copy(struct sighand_t *sighand, void *addrbase);

/* syscalls */
void syscall_signal(trapframe *_, uint32 signal, void (*handler)(int));
void syscall_kill(trapframe *_, int pid, int signal);
void syscall_sigreturn(trapframe *_);

#endif /* _SIGNAL_H */
3 changes: 2 additions & 1 deletion include/kernel/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
#define _SYSCALL_H

#include <types.h>
#include <trapframe.h>

// @syn: syndrome information for an synchronous exception
// One should pass esr_el1 register value to @syn
void syscall_handler(uint32 syn);
void syscall_handler(trapframe regs, uint32 syn);

#endif /* _SYSCALL_H */
75 changes: 75 additions & 0 deletions include/kernel/task.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#ifndef _TASK_H
#define _TASK_H

#include <types.h>
#include <list.h>

#define STACK_SIZE (2 * PAGE_SIZE)

/* Task status */
#define TASK_NEW 0
#define TASK_RUNNING 1
#define TASK_DEAD 2

/* Define in include/kernel/signal.h */
struct signal_head_t;
struct sighand_t;

struct pt_regs {
void *x19;
void *x20;
void *x21;
void *x22;
void *x23;
void *x24;
void *x25;
void *x26;
void *x27;
void *x28;
void *fp;
void *lr;
void *sp;
};

typedef struct _task_struct {
/* This must be the first element */
struct pt_regs regs;
void *kernel_stack;
void *user_stack;
/* TODO: Update to address_space */
void *data;
uint32 datalen;
/* @list is used by run_queue / wait_queue */
struct list_head list;
/* @task_list links all tasks */
struct list_head task_list;
uint16 status;
uint16 need_resched:1;
uint32 tid;
uint32 preempt;
/* Signal */
struct signal_head_t *signal;
struct sighand_t *sighand;
} task_struct;

#define SAVE_REGS(task) \
asm volatile ( \
"stp x19, x20, [%x0, 16 * 0]\n" \
"stp x21, x22, [%x0, 16 * 1]\n" \
"stp x23, x24, [%x0, 16 * 2]\n" \
"stp x25, x26, [%x0, 16 * 3]\n" \
"stp x27, x28, [%x0, 16 * 4]\n" \
"stp fp, lr, [%x0, 16 * 5]\n" \
"mov x9, sp\n" \
"str x9, [%x0, 16 * 6]\n" \
: : "r" (&task->regs) \
);

void task_init(void);

task_struct *task_create(void);
void task_free(task_struct *task);

task_struct *task_get_by_tid(uint32 tid);

#endif /* _TASK_H */
8 changes: 5 additions & 3 deletions include/kernel/timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
#include <types.h>

void timer_init();
void timer_irq_check();
void timer_irq_handler();
int timer_irq_check();
void timer_switch_info();

/* Call @proc(@args) after @after seconds. */
void timer_add_proc(void (*proc)(void *), void *args, uint32 after);
void timer_add_proc_after(void (*proc)(void *), void *args, uint32 after);

/* Call @proc(@args) after 1/@freq second. */
void timer_add_proc_freq(void (*proc)(void *), void *args, uint32 freq);

#endif /* _TIMER_H */
Loading