Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
4f6780b
Fix user stack
LJP-TW Apr 19, 2022
c55a00c
Update README.md
LJP-TW Apr 19, 2022
8b09383
Add save_and_disable_interrupt and restore_interrupt
LJP-TW Apr 21, 2022
277f3ff
Implement kernel thread
LJP-TW Apr 22, 2022
9df4883
Implement the mechanism for kernel thread termination
LJP-TW Apr 25, 2022
be23b64
Implement user process, syscall exit
LJP-TW Apr 25, 2022
73b8039
Implement syscall getpid, uart_write
LJP-TW Apr 25, 2022
3b848b1
Implement syscall uart_read
LJP-TW Apr 25, 2022
20c80b8
Implement syscall mbox_call
LJP-TW Apr 25, 2022
d307f36
Implement syscall kill_pid
LJP-TW Apr 26, 2022
4b8c7a8
Implement syscall exec
LJP-TW Apr 26, 2022
a38f9e0
Implement syscall fork
LJP-TW Apr 26, 2022
c6b2fc4
Video player (syscall.img) can work
LJP-TW Apr 26, 2022
5b6721d
Adjust the frequency of rescheduling
LJP-TW Apr 26, 2022
862ab47
Implement POSIX signal
LJP-TW Apr 29, 2022
cb56a87
Fix: adjust x30 (lr) in fork
LJP-TW Apr 29, 2022
7d6e592
Fix bug in uart_send_num
LJP-TW May 16, 2022
9b645e5
Map kernel space, MMU is enable with identity paging
LJP-TW May 16, 2022
451a9a6
Adjust newline
LJP-TW May 17, 2022
1168561
Implement mapping of user address space
LJP-TW May 17, 2022
ae62b96
Remove some comment
LJP-TW May 18, 2022
6c93feb
Map 0x3c000000 ~ 0x3f000000 identity paging for mailbox
LJP-TW May 18, 2022
3a19963
Fix signal related problem caused by enabling MMU
LJP-TW May 18, 2022
adea556
Implement demand paging
LJP-TW May 19, 2022
d9edd98
Implement mmap
LJP-TW May 19, 2022
ee84b3f
Implement VFS & tmpfs & cpiofs
LJP-TW Jun 6, 2022
78068c8
Implement uartfs
LJP-TW Jun 7, 2022
eb9fdd7
Implement framebufferfs
LJP-TW Jun 7, 2022
2524465
Add user programs given by TA
LJP-TW Jun 7, 2022
2128ecf
Implement fat32fs. Support open and read file from sdcard
LJP-TW Jun 14, 2022
1abb06a
Support create and write file for fat32fs cache
LJP-TW Jun 15, 2022
c6b907a
Support fat32 sync
LJP-TW Jun 16, 2022
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
13 changes: 9 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,12 @@ LIB_ASM_FILES += $(shell find "$(SRC_DIR)/$(LIB_DIR)" -name "*.S")
LIB_OBJ_FILES = $(patsubst $(SRC_DIR)/$(LIB_DIR)/%.c,$(BUILD_DIR)/$(LIB_DIR)/%_c.o,$(LIB_C_FILES))
LIB_OBJ_FILES += $(patsubst $(SRC_DIR)/$(LIB_DIR)/%.S,$(BUILD_DIR)/$(LIB_DIR)/%_s.o,$(LIB_ASM_FILES))

ifdef DEBUG
CFLAGS += -g -DDEBUG
ifdef MM_DEBUG
CFLAGS += -g -DMM_DEBUG
endif

ifdef DEMANDING_PAGE_DEBUG
CFLAGS += -g -DDEMANDING_PAGE_DEBUG
endif

all: $(KERNEL_IMG) $(BOOTLOADER_IMG)
Expand Down Expand Up @@ -88,9 +92,10 @@ $(BUILD_DIR)/$(LIB_DIR)/%_c.o: $(SRC_DIR)/$(LIB_DIR)/%.c
$(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: all $(INITRAMFS_CPIO) $(RPI3_DTB) $(IMG_NAME)
qemu-system-aarch64 -M raspi3 -kernel $(BOOTLOADER_IMG) \
-initrd $(INITRAMFS_CPIO) \
-drive if=sd,file=$(IMG_NAME),format=raw \
-dtb $(RPI3_DTB) \
-chardev pty,id=pty0,logfile=pty.log,signal=off \
-serial null -serial chardev:pty0 -s -S
Expand Down
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ make

* Build kernel8.img with some debug information:
```
make DEBUG=1
# Options:
# MM_DEBUG
# DEMANDING_PAGE_DEBUG
make MM_DEBUG=1
make DEMANDING_PAGE_DEBUG=1
```

* Build myos.img (which you can dd to SD card):
Expand All @@ -35,6 +39,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
1 change: 1 addition & 0 deletions img/FAT_R.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fat_r test
File renamed without changes.
1 change: 1 addition & 0 deletions include/lib/rpi3.h → include/bootloader/rpi3.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ struct arm_memory_info {
unsigned int size;
};

void mailbox_call(unsigned char channel, unsigned int *mb);
unsigned int get_board_revision(void);
void get_arm_memory(struct arm_memory_info *);

Expand Down
54 changes: 54 additions & 0 deletions include/kernel/BCM2837.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#ifndef _BCM2837_H
#define _BCM2837_H
// Ref: https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf

#define PERIPHERALS_BASE 0x3f000000
#define BUS_BASE 0x7e000000

#define BUS_TO_PERIPHERALS(addr) (addr - BUS_BASE + PERIPHERALS_BASE)

// Auxiliaries: UART1 & SPI1, SPI2
#define AUX_IRQ BUS_TO_PERIPHERALS(0x7E215000)
#define AUX_ENABLES BUS_TO_PERIPHERALS(0x7E215004)
#define AUX_MU_IO_REG BUS_TO_PERIPHERALS(0x7E215040)
#define AUX_MU_IER_REG BUS_TO_PERIPHERALS(0x7E215044)
#define AUX_MU_IIR_REG BUS_TO_PERIPHERALS(0x7E215048)
#define AUX_MU_LCR_REG BUS_TO_PERIPHERALS(0x7E21504c)
#define AUX_MU_MCR_REG BUS_TO_PERIPHERALS(0x7E215050)
#define AUX_MU_LSR_REG BUS_TO_PERIPHERALS(0x7E215054)
#define AUX_MU_MSR_REG BUS_TO_PERIPHERALS(0x7E215058)
#define AUX_MU_SCRATCH BUS_TO_PERIPHERALS(0x7E21505c)
#define AUX_MU_CNTL_REG BUS_TO_PERIPHERALS(0x7E215060)
#define AUX_MU_STAT_REG BUS_TO_PERIPHERALS(0x7E215064)
#define AUX_MU_BAUD_REG BUS_TO_PERIPHERALS(0x7E215068)
#define AUX_SPI0_CNTL0_REG BUS_TO_PERIPHERALS(0x7E215080)
#define AUX_SPI0_CNTL1_REG BUS_TO_PERIPHERALS(0x7E215084)
#define AUX_SPI0_STAT_REG BUS_TO_PERIPHERALS(0x7E215088)
#define AUX_SPI0_IO_REG BUS_TO_PERIPHERALS(0x7E215090)
#define AUX_SPI0_PEEK_REG BUS_TO_PERIPHERALS(0x7E215094)
#define AUX_SPI1_CNTL0_REG BUS_TO_PERIPHERALS(0x7E2150c0)
#define AUX_SPI1_CNTL1_REG BUS_TO_PERIPHERALS(0x7E2150c4)
#define AUX_SPI1_STAT_REG BUS_TO_PERIPHERALS(0x7E2150c8)
#define AUX_SPI1_IO_REG BUS_TO_PERIPHERALS(0x7E2150d0)
#define AUX_SPI1_PEEK_REG BUS_TO_PERIPHERALS(0x7E2150d4)

// GPIO
#define GPFSEL0 BUS_TO_PERIPHERALS(0x7E200000)
#define GPFSEL1 BUS_TO_PERIPHERALS(0x7E200004)
#define GPFSEL2 BUS_TO_PERIPHERALS(0x7E200008)
#define GPFSEL3 BUS_TO_PERIPHERALS(0x7E20000c)
#define GPFSEL4 BUS_TO_PERIPHERALS(0x7E200010)
#define GPFSEL5 BUS_TO_PERIPHERALS(0x7E200014)

#define GPPUD BUS_TO_PERIPHERALS(0x7E200094)
#define GPPUDCLK0 BUS_TO_PERIPHERALS(0x7E200098)
#define GPPUDCLK1 BUS_TO_PERIPHERALS(0x7E20009c)

// Interrupt
#define IRQ_ENABLE_1_REG BUS_TO_PERIPHERALS(0x7E00B210)

void BCM2837_reset(int tick);
void BCM2837_cancel_reset();


#endif /* _BCM2837_H */
28 changes: 28 additions & 0 deletions include/kernel/arm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef _ARM_H
#define _ARM_H

/* ==== PAR_EL1 related ==== */
#define PAR_FAILED(par) (par & 1)
#define PAR_PA(par) (par & 0x0000fffffffff000)

/* ==== ESR_EL1 related ==== */
#define EC_SVC_64 0x15
#define EC_IA_LE 0x20
#define EC_DA_LE 0x24

#define ISS_FSC(esr) (esr->iss & 0x3f)

#define FSC_TF_L0 0b000100
#define FSC_TF_L1 0b000101
#define FSC_TF_L2 0b000110
#define FSC_TF_L3 0b000111

#define ISS_WnR(esr) (esr->iss & 0x40)

typedef struct {
unsigned int iss:25, // Instruction specific syndrome
il:1, // Instruction length bit
ec:6; // Exception class
} esr_el1_t;

#endif /* _ARM_H */
12 changes: 0 additions & 12 deletions include/kernel/cpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,6 @@
extern void *initramfs_base;
extern void *initramfs_end;

void cpio_ls(char *cpio);
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.
*
* Return NULL if failed.
*/
char *cpio_load_prog(char *cpio, char *filename);

void initramfs_init(void);

#endif /* _CPIO_H */
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: 9 additions & 0 deletions include/kernel/entry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef _ENTRY_H
#define _ENTRY_H

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

void el0_sync_handler(trapframe *regs, uint32 syn);

#endif /* _ENTRY_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 */
8 changes: 8 additions & 0 deletions include/kernel/fs/cpiofs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef _CPIOFS_H
#define _CPIOFS_H

#include <fs/vfs.h>

struct filesystem *cpiofs_init(void);

#endif /* _CPIOFS_H */
8 changes: 8 additions & 0 deletions include/kernel/fs/fat32fs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef _FAT32FS_H
#define _FAT32FS_H

#include <fs/vfs.h>

struct filesystem *fat32fs_init(void);

#endif /* _FAT32FS_H */
8 changes: 8 additions & 0 deletions include/kernel/fs/framebufferfs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef _FRAMEBUFFERFS_H
#define _FRAMEBUFFERFS_H

#include <fs/vfs.h>

struct filesystem *framebufferfs_init(void);

#endif /* _FRAMEBUFFERFS_H */
13 changes: 13 additions & 0 deletions include/kernel/fs/fsinit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef _FSINIT_H
#define _FSINIT_H

#include <fs/vfs.h>
#include <fs/tmpfs.h>
#include <fs/cpiofs.h>
#include <fs/uartfs.h>
#include <fs/framebufferfs.h>
#include <fs/fat32fs.h>

void fs_init(void);

#endif /* _FSINIT_H */
8 changes: 8 additions & 0 deletions include/kernel/fs/tmpfs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef _TMPFS_H
#define _TMPFS_H

#include <fs/vfs.h>

struct filesystem *tmpfs_init(void);

#endif /* _TMPFS_H */
8 changes: 8 additions & 0 deletions include/kernel/fs/uartfs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef _UARTFS_H
#define _UARTFS_H

#include <fs/vfs.h>

struct filesystem *uartfs_init(void);

#endif /* _UARTFS_H */
96 changes: 96 additions & 0 deletions include/kernel/fs/vfs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#ifndef _VFS_H
#define _VFS_H

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

#define O_CREAT 00000100

#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2

/* File metadata */
struct vnode {
struct mount *mount;
struct vnode_operations *v_ops;
struct file_operations *f_ops;
struct vnode *parent;
void *internal;
};

/* File handle */
struct file {
struct vnode *vnode;
size_t f_pos; // RW position of this file handle
struct file_operations *f_ops;
int flags;
};

struct mount {
struct vnode *root;
struct filesystem *fs;
};

struct filesystem {
const char *name;
/* Link all filesystems */
struct list_head fs_list;
int (*mount)(struct filesystem *fs, struct mount *mount);
int (*alloc_vnode)(struct filesystem *fs, struct vnode **target);
int (*sync)(struct filesystem *fs);
};

struct file_operations {
int (*write)(struct file *file, const void *buf, size_t len);
int (*read)(struct file *file, void *buf, size_t len);
int (*open)(struct vnode *file_node, struct file *target);
int (*close)(struct file *file);
long (*lseek64)(struct file *file, long offset, int whence);
int (*ioctl)(struct file *file, uint64 request, va_list args);
};

struct vnode_operations {
int (*lookup)(struct vnode *dir_node, struct vnode **target,
const char *component_name);
int (*create)(struct vnode *dir_node, struct vnode **target,
const char *component_name);
int (*mkdir)(struct vnode *dir_node, struct vnode **target,
const char *component_name);
int (*isdir)(struct vnode *dir_node);
int (*getname)(struct vnode *dir_node, const char **name);
int (*getsize)(struct vnode *dir_node);
};

extern struct mount *rootmount;

void vfs_init(void);
void vfs_init_rootmount(struct filesystem *fs);

int register_filesystem(struct filesystem *fs);
int vfs_open(const char *pathname, int flags, struct file *target);
int vfs_close(struct file *file);
int vfs_write(struct file *file, const void *buf, size_t len);
int vfs_read(struct file *file, void *buf, size_t len);
long vfs_lseek64(struct file *file, long offset, int whence);
int vfs_ioctl(struct file *file, uint64 request, va_list args);
int vfs_mkdir(const char *pathname);
int vfs_mount(const char *mountpath, const char *filesystem);
int vfs_lookup(const char *pathname, struct vnode **target);
int vfs_sync(struct filesystem *fs);

void syscall_open(trapframe *frame, const char *pathname, int flags);
void syscall_close(trapframe *frame, int fd);
void syscall_write(trapframe *frame, int fd, const void *buf, uint64 count);
void syscall_read(trapframe *frame, int fd, void *buf, uint64 count);
void syscall_mkdir(trapframe *frame, const char *pathname, uint32 mode);
void syscall_mount(trapframe *frame, const char *src, const char *target,
const char *filesystem, uint64 flags, const void *data);
void syscall_chdir(trapframe *frame, const char *path);
void syscall_lseek64(trapframe *frame, int fd, int64 offset, int whence);
void syscall_ioctl(trapframe *frame, int fd, uint64 request, ...);
void syscall_sync(trapframe *frame);

#endif /* _VFS_H */
Loading