diff --git a/Makefile b/Makefile index 4f74a1aa2..f5276750f 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ INITRAMFS_SRC_DIR = $(SRC_DIR)/initramfs MAKE = make -COPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only -ggdb +COPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only -ggdb -std=gnu11 ASMOPS = -Iinclude -ggdb -mtune=cortex-a53 @@ -37,7 +37,7 @@ DEP_FILES += $(BOOTLOADER_OBJ_FILES:%.o=%.d) .DEFAULT_GOAL=all -.PHONY: default all clean kernel bootloader debug send $(INITRAMFS_BUILD_DIR) +.PHONY: default all clean kernel bootloader debug send $(INITRAMFS_BUILD_DIR) lab5 lab6 default: all all : kernel8.img bootloader.img $(INITRAMFS_BUILD_DIR) @@ -56,7 +56,22 @@ run: kernel8.img bootloader.img $(INITRAMFS_BUILD_DIR) boot: kernel8.img bootloader.img $(INITRAMFS_BUILD_DIR) cd build/initramfs && find . | cpio -o -H newc > ../../initramfs.cpio - qemu-system-aarch64 -M raspi3b -cpu cortex-a72 -serial null -serial pty -kernel bootloader.img -display none -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb -d int + qemu-system-aarch64 -M raspi3b -cpu cortex-a72 -serial null -serial pty -kernel bootloader.img -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb -d int -display none + # qemu-system-aarch64 -M raspi3b -kernel bootloader.img -initrd ./initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb -serial null -serial pty -d int + +lab5: + qemu-system-aarch64 -M raspi3b -cpu cortex-a72 -serial null -serial pty -kernel bootloader.img -display vnc=0.0.0.0:0 -initrd lab5.cpio -dtb bcm2710-rpi-3-b-plus.dtb -d int -vga std -drive if=sd,file=sfn_nctuos.img,format=raw + +lab6: + qemu-system-aarch64 -M raspi3b -cpu cortex-a72 -serial null -serial pty -kernel bootloader.img -display vnc=0.0.0.0:0 -initrd lab6.cpio -dtb bcm2710-rpi-3-b-plus.dtb -d int -vga std -drive if=sd,file=sfn_nctuos.img,format=raw + # qemu-system-aarch64 -M raspi3b -cpu cortex-a72 -serial null -serial pty -kernel bootloader.img -display gtk -initrd lab6.cpio -dtb bcm2710-rpi-3-b-plus.dtb -d int -vga std + +lab7: + qemu-system-aarch64 -M raspi3b -cpu cortex-a72 -serial null -serial pty -kernel bootloader.img -display vnc=0.0.0.0:0 -initrd lab7.cpio -dtb bcm2710-rpi-3-b-plus.dtb -d int -vga std -drive if=sd,file=sfn_nctuos.img,format=raw + + +lab8: + qemu-system-aarch64 -M raspi3b -cpu cortex-a72 -serial null -serial pty -kernel bootloader.img -display vnc=0.0.0.0:0 -initrd lab8.cpio -dtb bcm2710-rpi-3-b-plus.dtb -d int -vga std -drive if=sd,file=sfn_nctuos.img,format=raw copy: make && sudo ./copy_kernel.sh ./bootloader.img && sudo ./copy_ramdisk.sh build/initramfs diff --git a/Makefile.old b/Makefile.old new file mode 100755 index 000000000..94f55085e --- /dev/null +++ b/Makefile.old @@ -0,0 +1,84 @@ +ARMGNU ?= aarch64-linux-gnu + +INITRAMFS_BUILD_DIR = $(BUILD_DIR)/initramfs +INITRAMFS_SRC_DIR = $(SRC_DIR)/initramfs + +MAKE = make + +COPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only -ggdb +ASMOPS = -Iinclude -ggdb -mtune=cortex-a53 + +SRC_DIR = src +BUILD_DIR = build +KERNEL_BUILD_DIR = $(BUILD_DIR)/kernel +KERNEL_SRC_DIR = $(SRC_DIR)/kernel + +BOOTLOADER_BUILD_DIR = $(BUILD_DIR)/bootloader +BOOTLOADER_SRC_DIR = $(SRC_DIR)/bootloader + + +.PHONY: all clean kernel bootloader debug send $(INITRAMFS_BUILD_DIR) +all : kernel8.img bootloader.img $(INITRAMFS_BUILD_DIR) + +kernel: kernel8.img + +bootloader: bootloader.img + +clean : + rm -rf $(KERNEL_BUILD_DIR) $(BOOTLOADER_BUILD_DIR) $(BUILD_DIR) $(INITRAMFS_BUILD_DIR) *.img + +# run : +# make && qemu-system-aarch64 -M raspi3b -cpu cortex-a72 -dtb bcm2710-rpi-3-b-plus.dtb -m 1G -smp 4 -serial null -serial stdio -kernel kernel8.img -display none +run: kernel8.img bootloader.img $(INITRAMFS_BUILD_DIR) + qemu-system-aarch64 -M raspi3b -serial null -serial stdio -kernel kernel8.img -display none + +boot: kernel8.img bootloader.img $(INITRAMFS_BUILD_DIR) + cd build/initramfs && find . | cpio -o -H newc > ../../initramfs.cpio + qemu-system-aarch64 -M raspi3b -cpu cortex-a72 -serial null -serial pty -kernel bootloader.img -display none -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb -d int + +copy: + make && sudo ./copy_kernel.sh ./bootloader.img && sudo ./copy_ramdisk.sh build/initramfs + +send: + make kernel && sudo python3 send_kernel.py $(SER_DEV) + +$(KERNEL_BUILD_DIR)/%_s.o: $(KERNEL_SRC_DIR)/%.S + $(ARMGNU)-gcc $(ASMOPS) -MMD -c -o $@ $< + +$(BOOTLOADER_BUILD_DIR)/%_s.o: $(BOOTLOADER_SRC_DIR)/%.S + $(ARMGNU)-gcc $(ASMOPS) -MMD -c -o $@ $< + +$(KERNEL_BUILD_DIR)/%_c.o: $(KERNEL_SRC_DIR)/%.c + $(ARMGNU)-gcc $(COPS) -MMD -c -o $@ $< + +$(BOOTLOADER_BUILD_DIR)/%_c.o: $(BOOTLOADER_SRC_DIR)/%.c + $(ARMGNU)-gcc $(COPS) -MMD -c -o $@ $< + +KERNEL_C_FILES = $(wildcard $(KERNEL_SRC_DIR)/*.c) +KERNEL_ASM_FILES = $(wildcard $(KERNEL_SRC_DIR)/*.S) +KERNEL_OBJ_FILES = $(KERNEL_C_FILES:$(KERNEL_SRC_DIR)/%.c=$(KERNEL_BUILD_DIR)/%_c.o) +KERNEL_OBJ_FILES += $(KERNEL_ASM_FILES:$(KERNEL_SRC_DIR)/%.S=$(KERNEL_BUILD_DIR)/%_s.o) +BOOTLOADER_C_FILES += $(wildcard $(BOOTLOADER_SRC_DIR)/*.c) +BOOTLOADER_ASM_FILES += $(wildcard $(BOOTLOADER_SRC_DIR)/*.S) +BOOTLOADER_OBJ_FILES += $(BOOTLOADER_C_FILES:$(BOOTLOADER_SRC_DIR)/%.c=$(BOOTLOADER_BUILD_DIR)/%_c.o) +BOOTLOADER_OBJ_FILES += $(BOOTLOADER_ASM_FILES:$(BOOTLOADER_SRC_DIR)/%.S=$(BOOTLOADER_BUILD_DIR)/%_s.o) + +DEP_FILES = $(KERNEL_OBJ_FILES:%.o=%.d) +DEP_FILES += $(BOOTLOADER_OBJ_FILES:%.o=%.d) +-include $(DEP_FILES) + +kernel8.img: $(KERNEL_SRC_DIR)/linker.ld $(KERNEL_OBJ_FILES) + mkdir -p $(KERNEL_BUILD_DIR) + $(ARMGNU)-ld -T $(KERNEL_SRC_DIR)/linker.ld -o $(KERNEL_BUILD_DIR)/kernel8.elf $(KERNEL_OBJ_FILES) + $(ARMGNU)-objcopy $(KERNEL_BUILD_DIR)/kernel8.elf -O binary kernel8.img + +bootloader.img: $(BOOTLOADER_SRC_DIR)/linker.ld $(BOOTLOADER_OBJ_FILES) + $(ARMGNU)-ld -T $(BOOTLOADER_SRC_DIR)/linker.ld -o $(BOOTLOADER_BUILD_DIR)/bootloader.elf $(BOOTLOADER_OBJ_FILES) + $(ARMGNU)-objcopy $(BOOTLOADER_BUILD_DIR)/bootloader.elf -O binary bootloader.img + +$(INITRAMFS_BUILD_DIR): + $(MAKE) -C $(INITRAMFS_SRC_DIR) + +$(shell mkdir -p $(KERNEL_BUILD_DIR)) +$(shell mkdir -p $(BOOTLOADER_BUILD_DIR)) +$(shell mkdir -p $(INITRAMFS_BUILD_DIR)) diff --git a/config.txt b/config.txt deleted file mode 100644 index 933de3548..000000000 --- a/config.txt +++ /dev/null @@ -1,3 +0,0 @@ -kernel=bootloader.img -arm_64bit=1 -initramfs initramfs.cpio 0x20000000 \ No newline at end of file diff --git a/include/cpio/cpio.h b/include/cpio/cpio.h index 520c981d7..485b9926a 100644 --- a/include/cpio/cpio.h +++ b/include/cpio/cpio.h @@ -1,9 +1,17 @@ -#include "type.h" - #ifndef __CPIO_H - #define __CPIO_H +#include "type.h" +#include "fs/vfs.h" + +#define C_FMASK 0170000 +#define C_SOCK 0140000 // File type value for sockets. +#define C_SYMBOL 0120000 // File type value for symbolic links. +#define C_REG 0100000 // File type value for regular files. +#define C_BLKDEV 0060000 // File type value for block special devices. +#define C_DIR 0040000 // File type value for directories. +#define C_CHDEV 0020000 // File type value for character special devices. +#define C_FIFO 0010000 // File type value for named pipes or FIFOs. // char *_cpio_buf = (char *)INITRAMFS_ADDR; @@ -29,5 +37,8 @@ void list_files(); unsigned int cat_file(const char *file); void set_initramfs_addr(uint32_t addr); unsigned int load_program(const char *file); +uint8_t get_file(const char *filename, char **content, unsigned int *c_filesize); +void mount_initramfs(); +int init_cpio_fs(struct filesystem *fs); #endif \ No newline at end of file diff --git a/include/dtb/dtb.h b/include/dtb/dtb.h index a46a06645..841a398cf 100644 --- a/include/dtb/dtb.h +++ b/include/dtb/dtb.h @@ -1,7 +1,7 @@ -#include "type.h" #ifndef __DTB_H #define __DTB_H +#include "type.h" struct fdt_header { uint32_t magic; uint32_t totalsize; diff --git a/include/framebuffer.h b/include/framebuffer.h new file mode 100644 index 000000000..82e5c7e72 --- /dev/null +++ b/include/framebuffer.h @@ -0,0 +1,12 @@ +#ifndef __FRAMEBUFFER_H +#define __FRAMEBUFFER_H + +int init_framebuffer(struct filesystem* fs); +int framebuffer_setup_mount(struct filesystem* fs, struct mount *mnt); +int framebuffer_close(struct file *f); +int framebuffer_lseek64(struct file *f, int offset, int whence); +int framebuffer_open(struct vnode *file_node, struct file **target); +int framebuffer_write(struct file *f, void *buf, long len); +int framebuffer_ioctl(struct file *f, unsigned long request, void *buf); +void setup_dev_framebuffer(); +#endif \ No newline at end of file diff --git a/include/fs/fat32.h b/include/fs/fat32.h new file mode 100644 index 000000000..29ad39938 --- /dev/null +++ b/include/fs/fat32.h @@ -0,0 +1,103 @@ +#ifndef __FAT32_H +#define __FAT32_H +#include "sd.h" +#include "type.h" +#include "fs/vfs.h" +#define ATTR_READ_ONLY 0x01 +#define ATTR_HIDDEN 0x02 +#define ATTR_SYSTEM 0x04 +#define ATTR_VOLUME_ID 0x08 +#define ATTR_DIRECTORY 0x10 +#define ATTR_ARCHIVE 0x20 +#define ATTR_LONG_NAME 0xf /* should be examined first */ + +#define END_OF_CLUSTER 0x0ffffff8 + +#define FAT_DIR_CACHE_NUM 16 + +struct fat32_file_cache { + char name[16]; + uint32_t filesize; + uint32_t *FAT; + uint32_t FAT_cnt; + // unsigned int root_index; + uint32_t dir_ent_clus_idx; + uint32_t dir_idx; + void *tmpdata; + uint32_t data_cluster_index; + uint32_t maxsize; + uint8_t dirty; + uint8_t cached; + uint8_t opening; +}; + +struct fat32_dir_cache { + char dir_name[16]; + uint32_t *FAT; + uint32_t dir_clus_idx; + uint32_t FAT_cnt; +}; + +struct partition_entry { + uint8_t state; + uint8_t beg_head; + uint16_t beg_cly_sec; + uint8_t type; + uint8_t end_head; + uint16_t end_cly_sec; + uint32_t num_between; + uint32_t num_sec; +}__attribute__((__packed__)); + +struct fat_boot_sector { + uint8_t jmpcode[3]; + uint8_t oemname[8]; + uint16_t n_bytes_per_sec; + uint8_t n_sec_per_clus; + uint16_t n_reserve_sec; + uint8_t n_copy; + uint16_t n_root_dir_ent; + uint16_t tot_sec_not_used; + uint8_t media_desc; + uint16_t n_sec_per_fat_not_used; + uint16_t n_sec_per_track; + uint16_t n_head; + uint32_t n_hidden_sec; + uint32_t tot_sec; + uint32_t n_sec_per_fat; + uint16_t mirror_flags; + uint16_t fs_version; + uint32_t first_cluster_of_root; + uint16_t fs_info_reserve; + uint16_t backup_sec; + uint8_t reserve[12]; + uint8_t driver_num; + uint8_t cur_head; + uint8_t extend_sig; + uint32_t serial_num; + uint8_t label[11]; + uint8_t fs_type[8]; +}__attribute__((__packed__)); + +struct fat32_dir_entry { + uint8_t filename[8]; + uint8_t ext[3]; + uint8_t attr; + uint8_t reserve[8]; + uint16_t beg_clus_h; + uint16_t mod_time; + uint16_t mod_date; + uint16_t beg_clus_l; + uint32_t file_size; +}__attribute__((__packed__)); +int fat32_init(struct filesystem *fs); +int fat32_setup_mount(struct filesystem *fs, struct mount *mnt); +int fat32_lookup(struct vnode* dir_node, struct vnode **target, const char *component); +int fat32_open(struct vnode* node, struct file **target); +int fat32_read(struct file *f, void *buf, long len); +int fat32_write(struct file *f, void *buf, long len); +int fat32_create(struct vnode *dir_node, struct vnode **target, const char *comp); +void fat32_sync(); +int fat32_close(struct file *f); +void setup_boot(); +#endif \ No newline at end of file diff --git a/include/fs/tmpfs.h b/include/fs/tmpfs.h new file mode 100644 index 000000000..c6d99346c --- /dev/null +++ b/include/fs/tmpfs.h @@ -0,0 +1,33 @@ +#ifndef __TMPFS_H +#define __TMPFS_H + +#include "vfs.h" + +#define TMPFS_MAX_CONTENT_SIZE 4096 + +struct tmpfs_vinfo { + char name[16]; + int namesize; + int filesize; + // make this pointer + // we may store the absolute address from initramfs + char *content; +}; +int mount_tmpfs(struct filesystem *fs, struct mount *mnt); + +int tmpfs_lookup(struct vnode* dir_node, struct vnode** target, const char * componenet_name); + +int tmpfs_create(struct vnode* dir_node, struct vnode** target, const char *component_name); + +int tmpfs_mkdir(struct vnode* dir_node, struct vnode** target, const char *componenet_name); +int tmpfs_write(struct file* file, const void *buf, size_t len); +int tmpfs_read(struct file* file, const void *buf, size_t len); +int tmpfs_open(struct vnode* file_node, struct file** target); +int tmpfs_close(struct file* file); +long tmpfs_lseek64(struct file* file, long offset, int whence); +void tmpfs_print_name(struct vnode* node); +void init_fs(); +struct vnode* new_tmpfs_node(const char *name, struct vnode *dir_node); +int init_tmpfs(struct filesystem *fs); +int tmpfs_stat(struct file *f, struct fstat *stat); +#endif \ No newline at end of file diff --git a/include/fs/vfs.h b/include/fs/vfs.h new file mode 100644 index 000000000..3276c18ee --- /dev/null +++ b/include/fs/vfs.h @@ -0,0 +1,123 @@ +#ifndef __VFS_H +#define __VFS_H + +#define O_CREAT 000000100 +#define O_READ 000000010 +#define O_WRITE 000000001 + +#define VFS_DIR 0 +#define VFS_FILE 1 + +# define SEEK_SET 0 +#define VFS_NOT_FOUND -1 +#define VFS_NOT_DIR -2 +#define VFS_MOUNTED -3 +#define VFS_CAN_CREATE -4 +#define VFS_EXIST -5 +#define VFS_NOT_SUPPORT -6 +#define VFS_CANNOT_OPEN_DIR -7 +#define HANDLE_NOT_USED -1 + +#include "ds/list.h" +typedef unsigned long size_t; +typedef void (*apply_dir_func)(struct vnode*); + +struct vnode { + // if mount is not NULL + // that means the vnode is being mounted + // we can use and must use the mount->root as new vnode for operations + struct mount* mount; + struct vnode* parent; + struct vnode_operations* v_ops; + struct file_operations* f_ops; + // list for store child vnode + // should only be used if vnode is for directory + struct ds_list_head ch_list; + // list for being link to be as child + struct ds_list_head v_head; + int flag; + 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 fstat { + long filesize; + long namesize; +}; + +struct mount { + struct vnode* root; + struct vnode* mountpoint; + struct filesystem* fs; +}; + +struct filesystem { + const char* name; + struct vnode *root; + int (*init_fs)(struct filesystem *fs); + int (*setup_mount)(struct filesystem* fs, struct mount* mount); + struct ds_list_head fs_head; +}; + +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); + int (*stat)(struct file *file, struct fstat *stat); + long (*lseek64)(struct file* file, long offset, int whence); + int (*ioctl)(struct file *file, unsigned long request, void *buf); +}; + +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); +}; + + +// register the file system to the kernel. +// you can also initialize memory pool of the file system here. +int register_filesystem(struct filesystem* fs); + +// 1. Lookup pathname +// 2. Create a new file handle for this vnode if found. +// 3. Create a new file if O_CREAT is specified in flags and vnode not found +// lookup error code shows if file exist or not or other error occurs +// 4. Return error code if fails +int vfs_open(const char* pathname, int flags, struct file** target); + +// 1. release the file handle +// 2. Return error code if fails +int vfs_close(struct file* file); + +// 1. write len byte from buf to the opened file. +// 2. return written size or error code if an error occurs. +int vfs_write(struct file* file, const void* buf, size_t len); + +// 1. read min(len, readable size) byte to buf from the opened file. +// 2. block if nothing to read for FIFO type +// 2. return read size or error code if an error occurs. +int vfs_read(struct file* file, void* buf, size_t len); +int vfs_mkdir(const char* pathname); +int vfs_mount(const char* target, const char* filesystem); +int vfs_lookup(const char* pathname, struct vnode** target); + +struct filesystem *find_fs_by_name(const char *name); +void vfs_apply_dir(struct vnode* dir_node, apply_dir_func func); +int vfs_create(const char *pathname, int flags, struct vnode** target); +int vfs_stat(struct file *f, struct fstat *stat); +int vfs_lseek64(struct file *f, long offset, int whence); +int vops_not_support(); +int fops_not_support(); +#endif \ No newline at end of file diff --git a/include/interrupt.h b/include/interrupt.h index 0eafdb61c..ea8578c41 100644 --- a/include/interrupt.h +++ b/include/interrupt.h @@ -12,6 +12,44 @@ #define DISABLE_IRQ1 (PBASE+0x0000B21C) #define DISABLE_IRQ2 (PBASE+0x0000B220) +struct Trapframe_t{ + uint64_t x0; + uint64_t x1; + uint64_t x2; + uint64_t x3; + uint64_t x4; + uint64_t x5; + uint64_t x6; + uint64_t x7; + uint64_t x8; + uint64_t x9; + uint64_t x10; + uint64_t x11; + uint64_t x12; + uint64_t x13; + uint64_t x14; + uint64_t x15; + uint64_t x16; + uint64_t x17; + uint64_t x18; + uint64_t x19; + uint64_t x20; + uint64_t x21; + uint64_t x22; + uint64_t x23; + uint64_t x24; + uint64_t x25; + uint64_t x26; + uint64_t x27; + uint64_t x28; + uint64_t x29; + uint64_t x30; + uint64_t elr_el1; + uint64_t sp; + uint64_t spsr_el1; + uint64_t esr_el1; +}; + void exception_entry(); void enable_interrupt(); void disable_interrupt(); @@ -20,5 +58,8 @@ void irqhandler_dec(); int irqhandler_cnt_get(); uint64_t interrupt_disable_save(); void interrupt_enable_restore(uint64_t flag); +void lower_irq_handler(struct Trapframe_t *frame); +void spx_irq_handler(struct Trapframe_t *frame, uint64_t esr); +void svc_handler(struct Trapframe_t *frame); extern struct k_event_queue event_queue; #endif \ No newline at end of file diff --git a/include/mbox/mbox.h b/include/mbox/mbox.h index db176fb34..0b9059a7a 100644 --- a/include/mbox/mbox.h +++ b/include/mbox/mbox.h @@ -4,7 +4,7 @@ // #define MBOX_GET_FIRMWARE_REVISION (0x00000001) -extern volatile unsigned int mbox_buf[16]; +extern volatile unsigned int mbox_buf[256]; #define MBOX_CH_PROPERTY_TAG (8) @@ -31,4 +31,5 @@ extern volatile unsigned int mbox_buf[16]; #define MAIL_WRITE (MAIL_BASE + 0x20) int mbox_call_func(unsigned char prop_tag); +int mbox_call(unsigned char prop_tag, unsigned int *buf); #endif diff --git a/include/mem/mem.h b/include/mem/mem.h index 842bbf16f..0b24cba92 100644 --- a/include/mem/mem.h +++ b/include/mem/mem.h @@ -1,14 +1,16 @@ - #ifndef __MEM_H #define __MEM_H #include "type.h" -#define NULL (0) +#ifndef NULL + #define NULL (0) +#endif void *simple_malloc(uint32_t size); void simple_free(void *ptr); void smem_init(); void *kmalloc(uint32_t size); +void *cmalloc(uint32_t size); void kfree(void *ptr); void set_init_mem_region(char *name, char *prop_name, char *data); diff --git a/include/mem/page.h b/include/mem/page.h index a1fdb0217..da2d63737 100644 --- a/include/mem/page.h +++ b/include/mem/page.h @@ -9,7 +9,7 @@ #define PAGE_SIZE_ORDER (12) #define PAGE_SIZE (1 << PAGE_SIZE_ORDER) -#define PAGE_MAX_ORDER (10) +#define PAGE_MAX_ORDER (20) #define PAGE_CONTAINED (255) #define PAGE_ALLOCATED (254) @@ -19,8 +19,9 @@ struct frame_entry { uint32_t idx; uint8_t order; int8_t flag; + uint8_t used_cnt; + uint8_t dyn_ord; uint32_t dyn_count; - uint64_t dyn_ord; struct mem_region *mem_region; struct ds_list_head head; struct ds_list_head chunk_head; diff --git a/include/mmu/mmu-def.h b/include/mmu/mmu-def.h new file mode 100644 index 000000000..9fb1bf4b7 --- /dev/null +++ b/include/mmu/mmu-def.h @@ -0,0 +1,40 @@ +#ifndef __MMU_DEF_H +#define __MMU_DEF_H +// #include "type.h" + +#define TCR_CONFIG_REGION_48bit (((64 - 48) << 0) | ((64 - 48) << 16)) +#define TCR_CONFIG_4KB ((0b00 << 14) | (0b10 << 30)) +#define TCR_CONFIG_DEFAULT (TCR_CONFIG_REGION_48bit | TCR_CONFIG_4KB) +#define MAIR_DEVICE_nGnRnE 0b00000000 +#define MAIR_NORMAL_NOCACHE 0b01000100 +#define MAIR_IDX_DEVICE_nGnRnE 0 +#define MAIR_IDX_NORMAL_NOCACHE 1 +#define PD_TABLE 0b11 +#define PD_BLOCK 0b01 +#define PD_PAGE 0b11 +#define PD_UNX (1 << 54) +#define PD_PNX (1 << 53) +#define PD_USERACCESS (1 << 6) +#define PD_ACCESS (1 << 10) +#define BOOT_PGD_ATTR PD_TABLE +#define BOOT_PUD_ATTR_DEVICE (PD_ACCESS | (MAIR_IDX_DEVICE_nGnRnE << 2) | PD_BLOCK) +#define BOOT_PUD_ATTR_NORMAL (PD_ACCESS | (MAIR_IDX_NORMAL_NOCACHE << 2) | PD_BLOCK) +#define BOOT_PUD_TABLE PD_TABLE +#define BOOT_PUD_ATTR BOOT_PUD_ATTR_DEVICE +#define BOOT_PMD_ATTR_NORMAL (PD_ACCESS | (MAIR_IDX_NORMAL_NOCACHE << 2) | PD_BLOCK) +#define BOOT_PMD_ATTR_DEVICE (PD_ACCESS | (MAIR_IDX_DEVICE_nGnRnE << 2) | PD_BLOCK) +#define PROC_PTE_ATTR_NORMAL (PD_ACCESS | (MAIR_IDX_NORMAL_NOCACHE << 2) | PD_PAGE) +#define PROC_PTE_ATTR_DEVICE (PD_ACCESS | (MAIR_IDX_DEVICE_nGnRnE << 2) | PD_PAGE) + +#define kernel_va2pa(x) ((unsigned long long)(x) & (~(0xffff000000000000ULL))) +#define kernel_pa2va(x) ((unsigned long long)(x) | (0xffff000000000000ULL)) +// #define user_va2pa(x) ((unsigned long long)(x) & (0xffffffffULL)) +// #define user_pa2va(x) ((unsigned long long)(x) | (0x0000ffff00000000ULL)) + +#define PROT_READ (1) +#define PROT_WRITE (2) +#define PROT_EXEC (4) + +#define KERNEL_SPACE_OFFSET 0xffff000000000000 + +#endif \ No newline at end of file diff --git a/include/mmu/mmu.h b/include/mmu/mmu.h new file mode 100644 index 000000000..8d01c646b --- /dev/null +++ b/include/mmu/mmu.h @@ -0,0 +1,8 @@ + +#ifndef __MMU_H +#define __MMU_H +#include "mmu/mmu-def.h" +#include "type.h" + +uint64_t mappages(void *pgd, uint64_t va, uint64_t size, uint64_t pa); +#endif \ No newline at end of file diff --git a/include/peripherals/base.h b/include/peripherals/base.h index ae88e7840..8ad945bcd 100644 --- a/include/peripherals/base.h +++ b/include/peripherals/base.h @@ -1,6 +1,6 @@ #ifndef _P_BASE_H #define _P_BASE_H -#define PBASE 0x3F000000 +#define PBASE 0xffff00003F000000 #endif \ No newline at end of file diff --git a/include/peripherals/mini_uart.h b/include/peripherals/mini_uart.h index b38105bf5..59f89eb32 100644 --- a/include/peripherals/mini_uart.h +++ b/include/peripherals/mini_uart.h @@ -2,6 +2,8 @@ #define _P_MINI_UART_H #include "peripherals/base.h" +#include "type.h" +#include "fs/vfs.h" #define AUX_IQR (PBASE + 0x00215000) #define AUX_ENABLES (PBASE + 0x00215004) #define AUX_MU_IO_REG (PBASE + 0x00215040) @@ -15,7 +17,7 @@ #define AUX_MU_CNTL_REG (PBASE + 0x00215060) #define AUX_MU_STAT_REG (PBASE + 0x00215064) #define AUX_MU_BAUD_REG (PBASE + 0x00215068) -#define UART_QUEUE_SIZE (1024) +#define UART_QUEUE_SIZE (40) #define UART_ASYNC 0 #define UART_DEFAULT 1 @@ -26,7 +28,7 @@ void uart_send(char c); void uart_send_string(const char *c); void uart_send_u32(unsigned int u32); void uart_send_u64(unsigned long u64); -void uart_send_n(const char *c, unsigned long long n); +uint64_t uart_send_n(const char *c, unsigned long long n); void uart_send_dec(unsigned long dec); void uart_int_trans_handler(); void uart_int_recv_handler(); @@ -34,6 +36,7 @@ void enable_aux_interrupt(); void disable_aux_interrupt(); char async_uart_recv(void); void async_uart_send(char c); +uint64_t async_uart_rx_buf(char buf[], uint64_t sz); void async_uart_send_seting(const char *buf); void uart_switch_func(unsigned int func); struct Uart_MSG_Queue { @@ -43,6 +46,13 @@ struct Uart_MSG_Queue { char buf[UART_QUEUE_SIZE]; }; + +int uart_file_write(struct file *f, const void *buf, long len); + +int uart_file_read(struct file *f, const void *buf, long len) ; + +int uart_file_open(struct vnode *f, struct file **target); +int uart_file_close(struct file *f); // static struct Uart_MSG_Queue txbuf; // static struct Uart_MSG_Queue rxbuf; #endif \ No newline at end of file diff --git a/include/power.h b/include/power.h index 5242ab284..d2387c24b 100644 --- a/include/power.h +++ b/include/power.h @@ -1,5 +1,8 @@ +#ifndef __POWER_H +#define __POWER_H #define PM_PASSWORD 0x5a000000 #define PM_RSTC 0x3F10001c #define PM_WDOG 0x3F100024 -void reset(int tick); \ No newline at end of file +void reset(int tick); +#endif \ No newline at end of file diff --git a/include/process.h b/include/process.h new file mode 100755 index 000000000..2d73228a3 --- /dev/null +++ b/include/process.h @@ -0,0 +1,63 @@ +#ifndef __PROCESS_H +#define __PROCESS_H + +#include "signal.h" +#include "type.h" +#include "ds/list.h" +#include "thread.h" +#include "interrupt.h" +#include "mmu/mmu.h" +#include "fs/vfs.h" + +#define PID_MAX 2048 +#define P_FD_MAX 20 +typedef enum PStatus_ { + P_INIT=0, + P_RUNNING, + P_WAIT, + P_EXIT, + P_ZOMBIE +}PStatus; + +// struct ProcMemReg_t{ +// void *addr; +// uint64_t sz; +// // struct ds_list_head reg_head; +// }; +struct Process_t { + // uint64_t pid; + // PStatus status; + // char *filename; + // struct ds_list_head pq_head; + // struct ds_list_head mem_reg_list; + // pde_t* pgdir; // not used in this lab + PStatus status; + uint32_t pid; + uint32_t exit_code; + struct Process_t *parent; + struct ds_list_head th_list; + struct ds_list_head pl_head; + // struct File_t *ofile[] // not used in this lab + // struct inode *cwd; // not used in this lab + uint8_t signal[10 + 1]; + uint8_t handling_signal; + struct ds_list_head sig_list; + void *share_section; + uint64_t share_section_sz; + uint64_t ttbr0_el1; + char name[16]; + struct vnode* cur_vnode; + struct mount *mnt; + struct file *files[P_FD_MAX]; +}; +struct Process_t *process_get_current(); +struct Process_t* process_load(const char *filename); +uint64_t process_fork(struct Trapframe_t *frame); +void process_control_init(); +uint64_t process_exec(const char* name, char *const argv[], uint8_t kernel); +struct Thread_t* process_thread_create(void * func, void *arg, struct Process_t* proc, uint8_t kernel); +struct Process_t *create_process_instance(); +void process_free(struct Process_t *proc); +struct Process_t *get_process_from_pid(uint32_t pid); +void run_user_thread(); +#endif \ No newline at end of file diff --git a/include/sd.h b/include/sd.h new file mode 100644 index 000000000..6fa4e836c --- /dev/null +++ b/include/sd.h @@ -0,0 +1,12 @@ +#ifndef __SD_H +#define __SD_H + +#include "type.h" + +#define SECTOR_SIZE 512 + +void sd_init(); +void writeblock(int block_idx, void* buf); +void readblock(int block_idx, void* buf); + +#endif \ No newline at end of file diff --git a/include/signal.h b/include/signal.h new file mode 100755 index 000000000..e237014ee --- /dev/null +++ b/include/signal.h @@ -0,0 +1,26 @@ +#ifndef __SIGNAL_H +#define __SIGNAL_H + +#include "ds/list.h" +#include "thread.h" + +#define SIGNUMS 10 + +typedef void (*signal_handler)(); + +struct Signal_t { + uint8_t sig_num; + signal_handler handler; + void *sig_return; + struct Thread_t *th; + struct ds_list_head sig_head; +}; + +void signal_register(uint8_t signum, signal_handler handler); +void signal_kill(uint32_t pid, uint8_t signum); +void signal_sigreturn(); +void signal_handler_exec(uint8_t signum); +void signal_check(); + + +#endif \ No newline at end of file diff --git a/include/syscall.h b/include/syscall.h new file mode 100755 index 000000000..5adfb6db2 --- /dev/null +++ b/include/syscall.h @@ -0,0 +1,44 @@ +#ifndef __SYSCALL_H +#define __SYSCALL_H + +#include "type.h" + +# define SEEK_SET 0 + + +int sys_get_pid(); +uint64_t sys_uartread(char buf[], uint64_t size); +uint64_t sys_uartwrite(const char buf[], uint64_t size); +int sys_exec(const char* name, char *const argv[]); +int sys_fork(); +void sys_exit(int status); +int sys_mbox_call(unsigned char ch, unsigned int *mbox); +void sys_kill(int pid); +void syscall_handler(struct Trapframe_t *frame); +int sys_open(const char *pathname, int flags); + +// syscall number : 12 +int sys_close(int fd); + +// syscall number : 13 +// remember to return read size or error code +long sys_write(int fd, const void *buf, unsigned long count); + +// syscall number : 14 +// remember to return read size or error code +long sys_read(int fd, void *buf, unsigned long count); + +// syscall number : 15 +// you can ignore mode, since there is no access control +int sys_mkdir(const char *pathname, unsigned mode); + +// syscall number : 16 +// you can ignore arguments other than target (where to mount) and filesystem (fs name) +int sys_mount(const char *src, const char *target, const char *filesystem, unsigned long flags, const void *data); + +// syscall number : 17 +int sys_chdir(const char *path); +long sys_lseek64(int fd, long offset, int whence); +int sys_ioctl(int fd, unsigned long request, void *buf); + +#endif \ No newline at end of file diff --git a/include/test/demo.h b/include/test/demo.h index 8782e9374..47360de9f 100644 --- a/include/test/demo.h +++ b/include/test/demo.h @@ -1,6 +1,6 @@ -#include "type.h" #ifndef __DEMO_H #define __DEMO_H +#include "type.h" #include "test/demo_page.h" #include "test/test_simple_alloc.h" #include "test/test_kmalloc.h" diff --git a/include/test/demo_page.h b/include/test/demo_page.h index 8d386876b..2c49ba110 100644 --- a/include/test/demo_page.h +++ b/include/test/demo_page.h @@ -1,6 +1,5 @@ #ifndef __DEMO_PAGE_H #define __DEMO_PAGE_H #include "random.h" -#define MEM_DEMO void demo_page(); #endif \ No newline at end of file diff --git a/include/thread.h b/include/thread.h new file mode 100755 index 000000000..b41d10f20 --- /dev/null +++ b/include/thread.h @@ -0,0 +1,75 @@ +#ifndef __THREAD_H +#define __THREAD_H +#include "process.h" +#include "waitqueue.h" + +#define DEFAULT_STACK_SZ ((1 << 14)) +typedef void (*thread_func)(void*); +typedef enum THStatus_{ + TH_IN_RUNNING=0, + TH_RUNNING, + TH_WAIT, + TH_EXIT, + TH_ZOMBIE +} THStatus; +struct RegState_t { + uint64_t x0; + uint64_t x1; + uint64_t x2; + uint64_t x3; + uint64_t x4; + uint64_t x5; + uint64_t x6; + uint64_t x7; + uint64_t x8; + uint64_t x9; + uint64_t x10; + uint64_t x11; + uint64_t x12; + uint64_t x13; + uint64_t x14; + uint64_t x15; + uint64_t x16; + uint64_t x17; + uint64_t x18; + uint64_t x19; + uint64_t x20; + uint64_t x21; + uint64_t x22; + uint64_t x23; + uint64_t x24; + uint64_t x25; + uint64_t x26; + uint64_t x27; + uint64_t x28; + uint64_t fp; + uint64_t lr; + uint64_t sp; + uint64_t ttbr0_el1; + uint64_t pad; + uint64_t tcb_addr; +}; +struct Thread_t{ + uint64_t tid; + THStatus status; + struct Process_t *proc; + void *arg; + // for adding thread to run_queue or wait_queue + struct ds_list_head tq_head; + // for adding thread to process list + struct ds_list_head th_head; + thread_func entry; + void *sp; + void *sig_sp; + uint64_t stack_sz; + struct RegState_t saved_reg; + struct waitqueue_t* waitqueue; +}; +struct Thread_t * thread_create(thread_func func, void *arg); +void schedule(uint8_t preempt); +void thread_control_init(); +struct Thread_t *thread_get_current_instance(); +void handle_time_schedule(struct Trapframe_t *frame); +void schedule_init(); +void thread_exec_wrapper(); +#endif \ No newline at end of file diff --git a/include/type.h b/include/type.h index 0e97e5321..518424c5c 100644 --- a/include/type.h +++ b/include/type.h @@ -1,6 +1,6 @@ - #ifndef __TYPE_H #define __TYPE_H + typedef unsigned long long uint64_t; typedef long long int64_t; typedef unsigned int uint32_t; @@ -9,5 +9,9 @@ typedef unsigned short uint16_t; typedef short int16_t; typedef unsigned char uint8_t; typedef char int8_t; +// typedef unsigned char bool; +// typedef uint8_t bool; +// #define false (0) +// #define true (1) #endif \ No newline at end of file diff --git a/include/utils.h b/include/utils.h index 0de44d023..ca0d7c742 100644 --- a/include/utils.h +++ b/include/utils.h @@ -1,7 +1,7 @@ -#include "type.h" #ifndef _UTILS_H #define _UTILS_H +#include "type.h" #include #define container_of(ptr, type, mem) ({\ diff --git a/include/waitqueue.h b/include/waitqueue.h new file mode 100755 index 000000000..3369c3d00 --- /dev/null +++ b/include/waitqueue.h @@ -0,0 +1,13 @@ +#ifndef __WAITQUEUE_H +#define __WAITQUEUE_H + +#include "thread.h" +#include "ds/list.h" +struct waitqueue_t { + struct ds_list_head th_list; +}; + +void waitqueue_init(struct waitqueue_t *queue); +void wait(struct waitqueue_t *queue); + +#endif \ No newline at end of file diff --git a/initramfs.cpio b/initramfs.cpio index b3a221a36..18f2f4873 100644 Binary files a/initramfs.cpio and b/initramfs.cpio differ diff --git a/lab5.cpio b/lab5.cpio new file mode 100755 index 000000000..0676fb158 Binary files /dev/null and b/lab5.cpio differ diff --git a/lab6.cpio b/lab6.cpio new file mode 100644 index 000000000..b96c5be52 Binary files /dev/null and b/lab6.cpio differ diff --git a/lab7.cpio b/lab7.cpio new file mode 100644 index 000000000..cc23b7810 Binary files /dev/null and b/lab7.cpio differ diff --git a/lab8.cpio b/lab8.cpio new file mode 100644 index 000000000..d129e21cc Binary files /dev/null and b/lab8.cpio differ diff --git a/send_kernel.py b/send_kernel.py index c2cd0907d..c513feb42 100644 --- a/send_kernel.py +++ b/send_kernel.py @@ -1,3 +1,26 @@ +# import sys +# with open('kernel8.img', 'rb') as f: +# kernel = f.read() + + +# path = '/dev/ttyUSB0' + +# if len(sys.argv) > 1: +# path = sys.argv[1] + + + +# print(hex(len(kernel))) +# with open(path, 'wb') as tty: +# kernel_len = len(kernel) +# tty.write(b'S') +# tty.write(bytes([(kernel_len & 0xff000000) >> 24])) +# tty.write(bytes([(kernel_len & 0x00ff0000) >> 16])) +# tty.write(bytes([(kernel_len & 0x0000ff00) >> 8])) +# tty.write(bytes([kernel_len & 0x000000ff])) +# tty.write(kernel) + +import serial import sys with open('kernel8.img', 'rb') as f: kernel = f.read() @@ -7,15 +30,13 @@ if len(sys.argv) > 1: path = sys.argv[1] +ser = serial.Serial(path, baudrate=115200) - - -print(hex(len(kernel))) -with open(path, 'wb') as tty: +if ser.is_open: kernel_len = len(kernel) - tty.write(b'S') - tty.write(bytes([(kernel_len & 0xff000000) >> 24])) - tty.write(bytes([(kernel_len & 0x00ff0000) >> 16])) - tty.write(bytes([(kernel_len & 0x0000ff00) >> 8])) - tty.write(bytes([kernel_len & 0x000000ff])) - tty.write(kernel) + ser.write(b'S') + ser.write(bytes([(kernel_len & 0xff000000) >> 24])) + ser.write(bytes([(kernel_len & 0x00ff0000) >> 16])) + ser.write(bytes([(kernel_len & 0x0000ff00) >> 8])) + ser.write(bytes([kernel_len & 0x000000ff])) + ser.write(kernel) \ No newline at end of file diff --git a/src/bootloader/mini_uart.c b/src/bootloader/mini_uart.c index 8eb8edc56..51921f6dc 100644 --- a/src/bootloader/mini_uart.c +++ b/src/bootloader/mini_uart.c @@ -4,6 +4,8 @@ static char hex_char[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; +#define PBASE 0x3F000000 + void uart_init() { unsigned int selector; diff --git a/src/initramfs/Makefile b/src/initramfs/Makefile index 7cb4ad3f6..d073f441d 100644 --- a/src/initramfs/Makefile +++ b/src/initramfs/Makefile @@ -1,18 +1,20 @@ ARMGNU ?= aarch64-linux-gnu MAKE := make -COPS = -Wall -nostdlib -nostartfiles -ffreestanding -I../include -mgeneral-regs-only -ggdb -ASMOPS = -I ../include -ggdb +COPS = -Wall -nostdlib -nostartfiles -ffreestanding -I../include -mgeneral-regs-only -ggdb -mcmodel=tiny -std=gnu11 +ASMOPS = -I../include -ggdb INITRAMFS_BUILD_DIR = ../../build/initramfs KERNEL_BUILD_DIR = ../../build/kernel -all: $(INITRAMFS_BUILD_DIR)/int $(INITRAMFS_BUILD_DIR)/time +all: $(INITRAMFS_BUILD_DIR)/int $(INITRAMFS_BUILD_DIR)/time $(INITRAMFS_BUILD_DIR)/sys_test $(INITRAMFS_BUILD_DIR)/test $(INITRAMFS_BUILD_DIR)/hello $(INITRAMFS_BUILD_DIR)/%_s.o: %.S $(ARMGNU)-gcc $(ASMOPS) -c -o $@ $< +$(INITRAMFS_BUILD_DIR)/%_c.o: %.c + $(ARMGNU)-gcc $(COPS) -c -o $@ $< # INT_DEP = $(INITRAMFS_BUILD_DIR)/int_s.o # -include($(INT_DEP)) @@ -31,4 +33,22 @@ $(INITRAMFS_BUILD_DIR)/time: $(INITRAMFS_BUILD_DIR)/time_s.o $(ARMGNU)-ld -T linker.ld -o $@.elf $< $(ARMGNU)-objcopy $@.elf -O binary $@ rm $< - rm $@.elf \ No newline at end of file + rm $@.elf + +$(INITRAMFS_BUILD_DIR)/sys_test: $(INITRAMFS_BUILD_DIR)/sys_test_c.o + $(ARMGNU)-ld -T linker.ld -o $@.elf $< + $(ARMGNU)-objcopy $@.elf -O binary $@ + rm $< + # rm $@.elf + +$(INITRAMFS_BUILD_DIR)/test: $(INITRAMFS_BUILD_DIR)/test_s.o + $(ARMGNU)-ld -T linker.ld -o $@.elf $< + $(ARMGNU)-objcopy $@.elf -O binary $@ + rm $< + # rm $@.elf + +$(INITRAMFS_BUILD_DIR)/hello: $(INITRAMFS_BUILD_DIR)/hello_s.o + $(ARMGNU)-ld -T linker.ld -o $@.elf $< + $(ARMGNU)-objcopy $@.elf -O binary $@ + rm $< + # rm $@.elf \ No newline at end of file diff --git a/src/initramfs/hello.S b/src/initramfs/hello.S new file mode 100755 index 000000000..54108518c --- /dev/null +++ b/src/initramfs/hello.S @@ -0,0 +1,10 @@ +.section ".data" + hello: .string "hello: " + +.section ".text" + adr x0, hello + mov x1, #5 + mov x8, 2 + svc 0 +func: + b func \ No newline at end of file diff --git a/src/initramfs/linker.ld b/src/initramfs/linker.ld index 004d68856..d0421049f 100644 --- a/src/initramfs/linker.ld +++ b/src/initramfs/linker.ld @@ -1,15 +1,16 @@ ENTRY(start) SECTIONS { - . = 0x100000; - .text : { *(.text) } - .rodata : { *(.rodata) } - .data : { *(.data) } + . = 0x200000; + .entry : { *(.entry) } + .text : { *(.text*) } + .rodata : { *(.rodata*) } + .data : { *(.data*) } . = ALIGN(0x8); _bss_begin = .; .bss : { *(.bss*) } . = ALIGN(0x8); _bss_end = .; - _heap_begin = . + 0x5000; - _stack_begin = . + 0x10000; + _heap_begin = . + 0x1000; + _stack_begin = 0x280000; } \ No newline at end of file diff --git a/src/initramfs/sys_test.c b/src/initramfs/sys_test.c new file mode 100755 index 000000000..e229e8319 --- /dev/null +++ b/src/initramfs/sys_test.c @@ -0,0 +1,181 @@ +#include "syscall.h" + +char hello[] = "hello\r\n"; + +char hex_char[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + +unsigned long long write(unsigned int fd, char buf[], unsigned long long len); +unsigned long long write_dec(unsigned long long val); +unsigned long long write_u64(unsigned long long val); +unsigned long long fork(); +unsigned long long getpid(); +unsigned long long read(char buf[], unsigned long long len); +unsigned long long exec(char name[], char *arg); +unsigned long long dec2buf(unsigned long long val, char *buf); +unsigned long long u642buf(unsigned long long val, char *buf); + // unsigned long long x = write(buf, 7); +unsigned long long pid; + +char buf[20]; +int start(){ + unsigned long long pid = getpid(); + write(1, "\nPID=",5); + write_dec(pid); + pid = fork(); + write(1, "\nPID=",5); + write_dec(pid); + while(1) { + + } + return; + // unsigned long long pid = getpid(); + // write("\nFork Test, pid ", 16); + // write_dec(pid); + // write("\n", 1); + // int cnt = 1; + // int ret = 0; + // if ((ret = fork()) == 0) { // child + // long long cur_sp; + // asm volatile("mov %0, sp" : "=r"(cur_sp)); + // write("first child pid: ", 17); + // write_dec(getpid()); + // write(", cnt: ", 6); + // write_dec(cnt); + // write(", ptr: ", 7); + // write_u64(&cnt); + // write(", sp: ", 7); + // write_u64(cur_sp); + // write("\n", 1); + // ++cnt; + + // if ((ret = fork()) != 0){ + // asm volatile("mov %0, sp" : "=r"(cur_sp)); + // write("first child pid: ", 17); + // write_dec(getpid()); + // write(", cnt: ", 6); + // write_dec(cnt); + // write(", ptr: ", 7); + // write_u64(&cnt); + // write(", sp: ", 7); + // write_u64(cur_sp); + // write("\n", 1); + // // printf("first child pid: %d, cnt: %d, ptr: %x, sp : %x\n", get_pid(), cnt, &cnt, cur_sp); + // } + // else{ + // while (cnt < 5) { + // asm volatile("mov %0, sp" : "=r"(cur_sp)); + // // printf("second child pid: %d, cnt: %d, ptr: %x, sp : %x\n", get_pid(), cnt, &cnt, cur_sp); + // write("Second child pid: ", 17); + // write_dec(getpid()); + // write(", cnt: ", 6); + // write_dec(cnt); + // write(", ptr: ", 7); + // write_u64(&cnt); + // write(", sp: ", 7); + // write_u64(cur_sp); + // write("\n", 1); + // long x = 1000000; + // while(x --) { + // asm volatile("nop"); + // } + // ++cnt; + // } + // } + // // exit(); + // } + // else { + // write("parent\n", 7); + // // printf("parent here, pid %d, child %d\n", get_pid(), ret); + + // } + // +} + +unsigned long long dec2buf(unsigned long long val, char *buf) { + unsigned long long cnt = 0; + unsigned long long ret = 1; + while(ret <= val) { + ret *= 10; + cnt += 1; + } + ret /= 10; + if(ret == 0) { + buf[0] = '0'; + return 1; + } + for(int i = 0; i < cnt; i ++) { + buf[i] = val / ret + '0'; + val -= ret; + ret /= 10; + } + return cnt; +} +unsigned long long write(unsigned int fd, char buf[], unsigned long long len){ + asm volatile( + "mov x8, 13\n" + "svc 0\n" + ); + unsigned long long val; + asm volatile( + "mov %0, x0\n":"=r"(val) + ); + return val; +} +unsigned long long read(char buf[], unsigned long long x) { + asm volatile( + "mov x8, 1\n" + "svc 0\n" + ); + unsigned long long val; + asm volatile( + "mov %0, x0\n":"=r"(val) + ); + return val; +} +unsigned long long fork() { + asm volatile( + "mov x8, 4\n" + "svc 0\n" + ); + unsigned long long val; + asm volatile( + "mov %0, x0\n":"=r"(val) + ); + return val; +} +unsigned long long getpid() { + asm volatile( + "mov x8, 0\n" + "svc 0\n" + ); + unsigned long long val; + asm volatile( + "mov %0, x0\n":"=r"(val) + ); + return val; +} +unsigned long long exec(char name[], char *arg) { + asm volatile( + "mov x8, 3\n" + "svc 0\n" + ); + unsigned long long val; + asm volatile( + "mov %0, x0\n":"=r"(val) + ); + return val; +} + +unsigned long long write_dec(unsigned long long val) { + + unsigned long long n = dec2buf(val, buf); + write(1, buf, n); + + return 0; +} +unsigned long long write_u64(unsigned long long val) { + for(int cnt = 60; cnt >= 0; cnt -= 4) { + write(1, &(hex_char[(val >> cnt) & 0xF]), 1); + } + return 0; +} \ No newline at end of file diff --git a/src/initramfs/test.S b/src/initramfs/test.S new file mode 100755 index 000000000..2f5e02b46 --- /dev/null +++ b/src/initramfs/test.S @@ -0,0 +1,22 @@ +.section ".data" + bad: .string "BAD: " + hello: .string "hello" + +.section ".text" + sub sp, sp, 16 + stp x29, x30, [sp] + adr x1, bad + mov x2, #5 + mov x0, 2 + svc 0 + mov x0, 4 + svc 0 + ldp x29, x30, [sp] + ret + // ldr x3, [sp] + // strb w3, [x1] + // mov x0, 2 + // svc 0 +// func: + // b func + diff --git a/src/kernel/boot.S b/src/kernel/boot.S index dca0e68d4..49ad2ad17 100644 --- a/src/kernel/boot.S +++ b/src/kernel/boot.S @@ -1,7 +1,13 @@ -#define CORE0_TIMER_IRQ_CTRL 0x40000040 -#define CORE1_TIMER_IRQ_CTRL 0x40000044 -#define CORE2_TIMER_IRQ_CTRL 0x40000048 -#define CORE3_TIMER_IRQ_CTRL 0x4000004C +// #define CORE0_TIMER_IRQ_CTRL 0x40000040 +// #define CORE1_TIMER_IRQ_CTRL 0x40000044 +// #define CORE2_TIMER_IRQ_CTRL 0x40000048 +// #define CORE3_TIMER_IRQ_CTRL 0x4000004C +#define CORE0_TIMER_IRQ_CTRL 0xffff000040000040 +#define CORE1_TIMER_IRQ_CTRL 0xffff000040000044 +#define CORE2_TIMER_IRQ_CTRL 0xffff000040000048 +#define CORE3_TIMER_IRQ_CTRL 0xffff00004000004C + + .extern exception_entry .extern spx_irq_handler @@ -9,6 +15,10 @@ .extern enable_interrupt .extern disable_interrupt .extern event_queue_handle +.extern svc_handler +.extern check_exception_depth +.extern enable_kernel_mmu +.extern load_all_eret_log .section ".text.boot" .globl _start @@ -17,7 +27,14 @@ _start: mov x11, x1 mov x12, x2 mov x13, x3 + bl from_el2_to_el1 + ldr x0, =boot_rest + b enable_kernel_mmu + br x0 + + +boot_rest: mrs x0, mpidr_el1 and x0, x0, #0xFF cbz x0, master @@ -25,9 +42,12 @@ _start: // switch to el1 from_el2_to_el1: - mov x0, (1 << 31) + ldr x0, =(1 << 31 | 1 << 34) // make execution state for el1 is aarch64 msr hcr_el2, x0 + mrs x0, SCTLR_EL1 + orr x0, x0, #512 + msr sctlr_el1, x0 mov x0, 0x3c5 msr spsr_el2, x0 msr elr_el2, lr @@ -86,17 +106,16 @@ master: stp x28, x29, [sp ,16 * 14] mrs x0, elr_el1 stp x30, x0, [sp, 16 * 15] - mrs x0, spsr_el1 - str x0, [sp, 16 * 16] + // mov x0, sp + mrs x0, sp_el0 + mrs x1, spsr_el1 + stp x0, x1, [sp, 16 * 16] + mrs x1, esr_el1 + str x1, [sp, 16 * 17] .endm // load general registers from stack .macro load_all - ldr x0, [sp, 16 * 16] - msr spsr_el1, x0 - ldp x30, x0, [sp, 16 * 15] - msr elr_el1, x0 - ldp x0, x1, [sp ,16 * 0] ldp x2, x3, [sp ,16 * 1] ldp x4, x5, [sp ,16 * 2] ldp x6, x7, [sp ,16 * 3] @@ -111,6 +130,13 @@ master: ldp x24, x25, [sp ,16 * 12] ldp x26, x27, [sp ,16 * 13] ldp x28, x29, [sp ,16 * 14] + ldp x0, x1, [sp, 16 * 16] + // mov sp, x0 + msr sp_el0, x0 + msr spsr_el1, x1 + ldp x30, x0, [sp, 16 * 15] + msr elr_el1, x0 + ldp x0, x1, [sp ,16 * 0] // ldr x30, [sp, 16 * 15] add sp, sp, 32 * 9 .endm @@ -137,7 +163,7 @@ exception_vector_table: .balign 0x80 b exception_handler .balign 0x80 - b exception_handler + b _sync_handler .balign 0x80 b el_aarch64_irq_epx .balign 0x80 @@ -145,9 +171,10 @@ exception_vector_table: .balign 0x80 b exception_handler .balign 0x80 - b exception_handler + b _sync_handler .balign 0x80 - b _lower_el_aarch64_irq + b el_aarch64_irq_epx + //b _lower_el_aarch64_irq .balign 0x80 b exception_handler .balign 0x80 @@ -192,30 +219,79 @@ core_timer_handler: msr cntp_tval_el0, x0 ret el_aarch64_irq_epx: - msr DAIFSet, 0xf save_all - mrs x0, esr_el1 - mrs x1, elr_el1 - mrs x2, spsr_el1 + msr DAIFSet, 0xf + mov x0, sp + mrs x1, esr_el1 bl spx_irq_handler - msr DAIFClr, 0xf + // msr DAIFClr, 0xf bl event_queue_handle - msr DAIFSet, 0xf - load_all + // msr DAIFSet, 0xf + bl check_exception_depth msr DAIFClr, 0xf + load_all eret _lower_el_aarch64_irq: - msr DAIFSet, 0xf save_all - mrs x0, esr_el1 - mrs x1, elr_el1 - mrs x2, spsr_el1 + msr DAIFSet, 0xf + mov x0, sp + // msr DAIFClr, 0xf bl lower_irq_handler - msr DAIFClr, 0xf bl event_queue_handle - msr DAIFSet, 0xf + // msr DAIFSet, 0xf + msr DAIFClr, 0xf load_all + eret + +_sync_handler: + save_all + msr DAIFSet, 0xf + // bl check_exception_depth + mov x0, sp + bl svc_handler + // msr DAIFClr, 0xf + + // bl event_queue_handle + // msr DAIFSet, 0xf + // bl check_exception_depth msr DAIFClr, 0xf - eret \ No newline at end of file + load_all + eret + +.global load_all_eret +load_all_eret: + // bl load_all_eret_log + 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, x29, [sp ,16 * 14] + ldp x0, x1, [sp, 16 * 16] + // mov sp, x0 + msr sp_el0, x0 + msr spsr_el1, x1 + ldp x30, x0, [sp, 16 * 15] + msr elr_el1, x0 + ldp x0, x1, [sp ,16 * 0] + add sp, sp, 32 * 9 + // ldr x30, [sp, 16 * 15] + eret + +.global back_el1 +back_el1: + msr elr_el1, lr + mov x0, 0x345 + msr spsr_el1, x0 + eret + diff --git a/src/kernel/context_switch.S b/src/kernel/context_switch.S new file mode 100755 index 000000000..bb8711e7f --- /dev/null +++ b/src/kernel/context_switch.S @@ -0,0 +1,35 @@ +.global context_switch_to +context_switch_to: + str x19, [x0, 16 * 9 + 8] + stp x20, x21, [x0, 16 * 10] + stp x22, x23, [x0, 16 * 11] + stp x24, x25, [x0, 16 * 12] + stp x26, x27, [x0, 16 * 13] + stp x28, fp, [x0, 16 * 14] + mov x3, sp + mrs x12, ttbr0_el1 + stp lr, x3, [x0, 16 * 15] + str x12, [x0, 16 * 16] + + ldr x12, [x1, 16 * 16] + ldr x19, [x1, 16 * 9 + 8] + ldp x20, x21, [x1, 16 * 10] + ldp x22, x23, [x1, 16 * 11] + ldp x24, x25, [x1, 16 * 12] + ldp x26, x27, [x1, 16 * 13] + ldp x28, fp, [x1, 16 * 14] + ldp lr, x3, [x1, 16 * 15] + mov sp, x3 + msr tpidr_el1, x2 + + dsb ish + msr ttbr0_el1, x12 + tlbi vmalle1is + dsb ish + isb + ret + +.global thread_get_current +thread_get_current: + mrs x0, tpidr_el1 + ret \ No newline at end of file diff --git a/src/kernel/cpio/cpio.c b/src/kernel/cpio/cpio.c index 1a3c759b7..a8809ae73 100644 --- a/src/kernel/cpio/cpio.c +++ b/src/kernel/cpio/cpio.c @@ -1,11 +1,16 @@ #include "cpio/cpio.h" #include "utils.h" #include "peripherals/mini_uart.h" +#include "process.h" +#include "fs/tmpfs.h" +#include "fs/vfs.h" +#include "mmu/mmu-def.h" +// extern void thread_exec_wrapper; char *initramfs_addr; void set_initramfs_addr(uint32_t addr) { - initramfs_addr = (char*)addr; + initramfs_addr = (char*)kernel_pa2va(addr); } unsigned int hex_to_uint(char* c) { @@ -30,12 +35,11 @@ void list_files() { for(;;) { unsigned int namesize = hex_to_uint(((cpio_newc_header*)tmp)->c_namesize); unsigned int filesize = hex_to_uint(((cpio_newc_header*)tmp)->c_filesize); + unsigned int filemode = hex_to_uint(((cpio_newc_header*)tmp)->c_mode); if(strncmp(tmp + offset, "TRAILER!!!", 10) == 0) { break; } - uart_send_n(tmp + offset, namesize); - uart_send_string("\r\n"); tmp += (((((namesize + offset) & 0x3) ^ 0x3) + 1) & 0x3) + namesize + offset; tmp += ((((filesize & 0x3) ^ 0x3) + 1) & 0x3) + filesize; } @@ -47,6 +51,7 @@ unsigned int cat_file(const char *filename) { unsigned int namesize = hex_to_uint(((cpio_newc_header*)tmp)->c_namesize); unsigned int filesize = hex_to_uint(((cpio_newc_header*)tmp)->c_filesize); + if(strncmp(tmp + offset, "TRAILER!!!", 10) == 0) { uart_send_string("file not found!\r\n"); return 255; @@ -63,8 +68,12 @@ unsigned int cat_file(const char *filename) { } unsigned int load_program(const char *filename) { - uint64_t program_addr = 0x100000; - char *tmp = (char *)initramfs_addr; + process_exec(filename, NULL, 0); +} + +uint8_t get_file(const char *filename, char **content, unsigned int *c_filesize) { + uart_send_string("in get file\r\n"); + char *tmp = (char *)kernel_pa2va(initramfs_addr); int offset = sizeof(cpio_newc_header); for(;;) { unsigned int namesize = hex_to_uint(((cpio_newc_header*)tmp)->c_namesize); @@ -76,16 +85,8 @@ unsigned int load_program(const char *filename) { } if(strncmp(tmp + offset, filename, namesize) == 0) { uint64_t content_offset = (((((namesize + offset) & 0x3) ^ 0x3) + 1) & 0x3) + namesize + offset; - memcpy((char*)program_addr, tmp + content_offset, filesize); - asm volatile( - "mov x0, 0x340\n" - "msr spsr_el1, x0\n" - "mov x0, 0x100000\n" - "msr elr_el1, x0\n" - "mov x0, 0x110000\n" - "msr sp_el0, x0\n" - "eret\n" - ); + *content = (char *)(content_offset + tmp); + *c_filesize = filesize; return 0; } // Since the (name + offset) size will be pad to align 4bytes @@ -93,4 +94,88 @@ unsigned int load_program(const char *filename) { // Since the filesize will be pad to align 4 bytes tmp += ((((filesize & 0x3) ^ 0x3) + 1) & 0x3) + filesize; } +} + + + +struct filesystem cpio_fs = { + .name = "cpio_fs", + .root = NULL, + // .init_fs = &init_tmpfs, + .init_fs = &init_cpio_fs, + .setup_mount = &mount_tmpfs +}; + +struct vnode_operations cpio_vops = { + .create = &vops_not_support, + .lookup = &tmpfs_lookup, + .mkdir = &vops_not_support +}; + +struct file_operations cpio_fops = { + .close = &tmpfs_close, + .ioctl = &fops_not_support, + .lseek64 = &tmpfs_lseek64, + .open = &tmpfs_open, + .read = &tmpfs_read, + .stat = &tmpfs_stat, + .write = &fops_not_support +}; + +int init_cpio_fs(struct filesystem *fs) { + init_tmpfs(fs); + return 0; +} + +void parse_cpio() { + struct vnode* cpio_root = cpio_fs.root; + cpio_root->flag = VFS_DIR; + + char *tmp = (char *)initramfs_addr; + int offset = sizeof(cpio_newc_header); + char name[100]; + for(;;) { + unsigned int namesize = hex_to_uint(((cpio_newc_header*)tmp)->c_namesize); + unsigned int filesize = hex_to_uint(((cpio_newc_header*)tmp)->c_filesize); + unsigned int filemode = hex_to_uint(((cpio_newc_header*)tmp)->c_mode) & C_FMASK; + + if(strncmp(tmp + offset, "TRAILER!!!", 10) == 0) { + break; + } + + if(strncmp(tmp + offset, ".", 1) != 0) { + if(filemode == C_REG) { + struct vnode *newnode; + memcpy(name, "/initramfs/", 11); + memcpy(name + 11, tmp + offset, namesize); + name[12 + namesize] = '\0'; + vfs_create(name, 0777, &newnode); + struct tmpfs_vinfo* info = newnode->internal; + uint64_t content_offset = (((((namesize + offset) & 0x3) ^ 0x3) + 1) & 0x3) + namesize + offset; + info->content = (char *)(content_offset + tmp); + info->filesize = filesize; + } else if(filemode == C_DIR) { + strncpy(name, "/initramfs/", 12); + strncpy(name + 12, tmp + offset, namesize); + name[12 + namesize] = '\0'; + vfs_mkdir(name); + } + } + tmp += (((((namesize + offset) & 0x3) ^ 0x3) + 1) & 0x3) + namesize + offset; + tmp += ((((filesize & 0x3) ^ 0x3) + 1) & 0x3) + filesize; + } + cpio_fs.root->f_ops = &cpio_fops; + cpio_fs.root->v_ops = &cpio_vops; + +} + + +void mount_initramfs() { + vfs_mkdir("/initramfs"); + register_filesystem(&cpio_fs); + vfs_mount("/initramfs", "cpio_fs"); + + parse_cpio(); + + return; } \ No newline at end of file diff --git a/src/kernel/event.c b/src/kernel/event.c index 050796fc3..f6790cc8e 100644 --- a/src/kernel/event.c +++ b/src/kernel/event.c @@ -44,7 +44,7 @@ struct k_event* k_event_front() { int flag = interrupt_disable_save(); struct k_event *ke; if(event_queue.heap.size == 0) { - ke == NULL; + ke = NULL; goto ret; } ke = ds_heap_front(&(event_queue.heap)); @@ -75,7 +75,6 @@ void event_queue_handle() { return; } if(event->preempt == 3) return; - // uart_send_dec(event->pri); event->preempt = 3; event->cb(event->ptr, event->ptr_len); @@ -84,5 +83,7 @@ void event_queue_handle() { if(irqhandler_cnt_get() == 0) { event_queue.cur_max_event_pri = -0x7fffffffffffffff; } + counter += 1; + } } \ No newline at end of file diff --git a/src/kernel/framebuffer.c b/src/kernel/framebuffer.c new file mode 100644 index 000000000..f0ebec1b3 --- /dev/null +++ b/src/kernel/framebuffer.c @@ -0,0 +1,157 @@ +#include "mbox/mbox.h" +#include "fs/vfs.h" +#include "mem/mem.h" +#include "framebuffer.h" +#include "mmu/mmu-def.h" + +#define MBOX_REQUEST 0 +#define MBOX_CH_PROP 8 +#define MBOX_TAG_LAST 0 + +unsigned int __attribute__((aligned(16))) framebuffer_mbox[36]; +unsigned int width, height, pitch, isrgb; /* dimensions and channel order */ +unsigned char *lfb; /* raw frame buffer address */ + +struct filesystem framebuffer_fs = { + .name = "framebuffer", + .init_fs = &init_framebuffer, + .root = NULL, + .setup_mount = &framebuffer_setup_mount +}; + + +struct file_operations framebuffer_fops = { + .close = &framebuffer_close, + .lseek64 = &framebuffer_lseek64, + .open = &framebuffer_open, + .read = &vops_not_support, + .stat = &vops_not_support, + .write = &framebuffer_write, + .ioctl = &framebuffer_ioctl +}; + +struct vnode_operations framebuffer_vops = { + .create = &fops_not_support, + .lookup = &fops_not_support, + .mkdir = &fops_not_support +}; + +int init_framebuffer(struct filesystem* fs) { + fs->root = (struct vnode*)kmalloc(sizeof(struct vnode)); + ds_list_head_init(&(fs->root->ch_list)); + ds_list_head_init(&(fs->root->v_head)); + fs->root->flag = VFS_FILE; + fs->root->internal = NULL; + fs->root->v_ops = &framebuffer_vops; + fs->root->f_ops = &framebuffer_fops; + fs->root->mount = NULL; + + framebuffer_mbox[0] = 35 * 4; + framebuffer_mbox[1] = MBOX_REQUEST; + + framebuffer_mbox[2] = 0x48003; // set phy wh + framebuffer_mbox[3] = 8; + framebuffer_mbox[4] = 8; + framebuffer_mbox[5] = 1024; // FrameBufferInfo.width + framebuffer_mbox[6] = 768; // FrameBufferInfo.height + + framebuffer_mbox[7] = 0x48004; // set virt wh + framebuffer_mbox[8] = 8; + framebuffer_mbox[9] = 8; + framebuffer_mbox[10] = 1024; // FrameBufferInfo.virtual_width + framebuffer_mbox[11] = 768; // FrameBufferInfo.virtual_height + + framebuffer_mbox[12] = 0x48009; // set virt offset + framebuffer_mbox[13] = 8; + framebuffer_mbox[14] = 8; + framebuffer_mbox[15] = 0; // FrameBufferInfo.x_offset + framebuffer_mbox[16] = 0; // FrameBufferInfo.y.offset + + framebuffer_mbox[17] = 0x48005; // set depth + framebuffer_mbox[18] = 4; + framebuffer_mbox[19] = 4; + framebuffer_mbox[20] = 32; // FrameBufferInfo.depth + + framebuffer_mbox[21] = 0x48006; // set pixel order + framebuffer_mbox[22] = 4; + framebuffer_mbox[23] = 4; + framebuffer_mbox[24] = 1; // RGB, not BGR preferably + + framebuffer_mbox[25] = 0x40001; // get framebuffer, gets alignment on request + framebuffer_mbox[26] = 8; + framebuffer_mbox[27] = 8; + framebuffer_mbox[28] = 4096; // FrameBufferInfo.pointer + framebuffer_mbox[29] = 0; // FrameBufferInfo.size + + framebuffer_mbox[30] = 0x40008; // get pitch + framebuffer_mbox[31] = 4; + framebuffer_mbox[32] = 4; + framebuffer_mbox[33] = 0; // FrameBufferInfo.pitch + + framebuffer_mbox[34] = MBOX_TAG_LAST; + + // this might not return exactly what we asked for, could be + // the closest supported resolution instead + if (mbox_call(MBOX_CH_PROP, framebuffer_mbox) && framebuffer_mbox[20] == 32 && framebuffer_mbox[28] != 0) { + framebuffer_mbox[28] &= 0x3FFFFFFF; // convert GPU address to ARM address + width = framebuffer_mbox[5]; // get actual physical width + height = framebuffer_mbox[6]; // get actual physical height + pitch = framebuffer_mbox[33]; // get number of bytes per line + isrgb = framebuffer_mbox[24]; // get the actual channel order + lfb = (void *)((unsigned long)framebuffer_mbox[28]); + lfb = kernel_pa2va(lfb); + } else { + uart_send_string("Unable to set screen resolution to 1024x768x32\n"); + } +} + +int framebuffer_ioctl(struct file *f, unsigned long request, void *buf) { + return 0; +} + +int framebuffer_close(struct file *f) { + kfree(f); + return 0; +} +int framebuffer_lseek64(struct file *f, int offset, int whence) { + if(whence == SEEK_SET) { + f->f_pos = offset; + return 0; + } else { + return 0; + } +} + +int framebuffer_open(struct vnode *file_node, struct file **target) { + struct file *ret = (struct file *)kmalloc(sizeof(struct file)); + ret->f_ops = &framebuffer_fops; + ret->f_pos = 0; + ret->flags = 0777; + ret->vnode = framebuffer_fs.root; + *target = ret; + return 0; +} + + +int framebuffer_write(struct file *f, void *buf, long len) { + for(int i = 0; i < len; i ++, f->f_pos ++) { + *(char*)(lfb + f->f_pos) = *(char*)(buf + i); + } + return len; +} + +int framebuffer_setup_mount(struct filesystem* fs, struct mount *mnt) { + ds_list_head_init(&(fs->root->ch_list)); + ds_list_head_init(&(fs->root->v_head)); + fs->root->flag = VFS_FILE; + fs->root->mount = mnt; + mnt->root = fs->root; + mnt->fs = fs; +} + + +void setup_dev_framebuffer() { + register_filesystem(&framebuffer_fs); + vfs_mkdir("/dev/framebuffer"); + vfs_mount("/dev/framebuffer", "framebuffer"); +} diff --git a/src/kernel/fs/fat32.c b/src/kernel/fs/fat32.c new file mode 100644 index 000000000..2da81555a --- /dev/null +++ b/src/kernel/fs/fat32.c @@ -0,0 +1,570 @@ +#include "fs/fat32.h" +#include "sd.h" +#include "fs/vfs.h" +#include "mem/mem.h" +#include "mem/page.h" +#include "peripherals/mini_uart.h" +#include "utils.h" + + +struct partition_entry pe[4]; +unsigned int fat_base_idx; +unsigned int fat_blk_idx; +unsigned int fat_data_region_idx; + +struct filesystem fat32_fs = { + .name = "fat32_boot", + .init_fs = &fat32_init, + .root = NULL, + .setup_mount = &fat32_setup_mount +}; + +struct file_operations fat32_fops = { + .close = fat32_close, + .ioctl = fops_not_support, + .lseek64 = fops_not_support, + .open = fat32_open, + .read = fat32_read, + .write = fat32_write, + .stat = fops_not_support +}; +struct vnode_operations fat32_vops = { + .create = fat32_create, + .mkdir = vops_not_support, + .lookup = fat32_lookup +}; + +int end_of_cluster(unsigned int val) { + if(val >= END_OF_CLUSTER) { + return 1; + } else { + return 0; + } +} + +int fat32_close(struct file *f) { + struct fat32_file_cache *f_cache = f->vnode->internal; + f_cache->opening -= 1; + kfree(f); + return 0; +} +int dirent2filename(struct fat32_dir_entry *ent, char *buf) { + int ridx = 7; + for(;ridx >= 0; ridx --) { + if(ent->filename[ridx] != ' ') { + break; + } + } + if(ridx < 0) return 0; + memcpy(buf, ent->filename, ridx + 1); + int ext_ridx = 2; + for(; ext_ridx >= 0; ext_ridx --) { + if(ent->ext[ext_ridx] != ' ') { + break; + } + } + + if(ext_ridx >= 0) { + buf[ridx + 1] = '.'; + memcpy(buf + ridx + 2, ent->ext, ext_ridx + 1); + buf[ridx + 2 + ext_ridx + 1] = '\0'; + return ridx + 2 + ext_ridx + 1; + } else { + buf[ridx + 1] = '\0'; + return ridx + 1; + } +} + +int clusteridx2datablkidx(int clus_idx) { + return clus_idx - 2 + fat_data_region_idx; +} + +int build_up_fat(uint8_t **FAT, int beg_clus_idx) { + int cnt = 0; + int cur_clus_idx = beg_clus_idx; + int old_clus_idx = cur_clus_idx - (cur_clus_idx & 0x7f); + unsigned int buf[150]; + readblock(fat_blk_idx + (old_clus_idx >> 7),&(buf[0])); + while(!end_of_cluster(cur_clus_idx)) { + if(cur_clus_idx - old_clus_idx >= 0x80 || cur_clus_idx - old_clus_idx <= -0x80) { + old_clus_idx = cur_clus_idx - (cur_clus_idx & 0x7f); + readblock(fat_blk_idx + (old_clus_idx >> 7), &(buf[0])); + } + cur_clus_idx = buf[cur_clus_idx % 128]; + cnt += 1; + } + uint32_t *new_FAT = (unsigned int*)kmalloc(cnt * 4); + + *FAT = new_FAT; + cur_clus_idx = beg_clus_idx; + old_clus_idx = cur_clus_idx - (cur_clus_idx & 0x7f); + cnt = 0; + readblock(fat_blk_idx + (old_clus_idx >> 7),&(buf[0])); + while(!end_of_cluster(cur_clus_idx)) { + + if(cur_clus_idx - old_clus_idx >= 0x80 || cur_clus_idx - old_clus_idx <= -0x80) { + old_clus_idx = cur_clus_idx - (cur_clus_idx & 0x7f); + readblock(fat_blk_idx + (old_clus_idx >> 7), &(buf[0])); + } + cur_clus_idx = buf[cur_clus_idx % 128]; + new_FAT[cnt++] = cur_clus_idx; + } + return cnt; +} + +void init_fat32_dir_vnode(struct vnode *node, struct fat32_dir_entry *ent, const char *comp) { + node->internal = kmalloc(sizeof(struct fat32_dir_cache)); + node->flag = VFS_DIR; + node->f_ops = &fat32_fops; + node->v_ops = &fat32_vops; + node->mount = NULL; + node->parent = NULL; + ds_list_head_init(&(node->ch_list)); + ds_list_head_init(&(node->v_head)); + struct fat32_dir_cache *dir_cache = node->internal; + if(comp != NULL) { + memcpy(dir_cache->dir_name, comp, strlen(comp)); + } + + dir_cache->dir_clus_idx = ent->beg_clus_l - 2; + + dir_cache->FAT_cnt = build_up_fat(&(dir_cache->FAT), dir_cache->dir_clus_idx); +} + +void init_fat32_file_vnode(struct vnode* node, struct fat32_dir_entry *ent, const char *comp) { + node->internal = kmalloc(sizeof(struct fat32_file_cache)); + node->flag = VFS_FILE; + node->f_ops = &fat32_fops; + node->v_ops = &fat32_vops; + node->mount = NULL; + node->parent = NULL; + ds_list_head_init(&(node->ch_list)); + ds_list_head_init(&(node->v_head)); + struct fat32_file_cache *file_cache = node->internal; + if(comp != NULL) { + memcpy(file_cache->name, comp, strlen(comp)); + } + file_cache->filesize = ent->file_size; + file_cache->data_cluster_index = ent->beg_clus_l; + + int cur_clus_idx = file_cache->data_cluster_index; + file_cache->dirty = 0; + file_cache->cached = 0; + file_cache->opening = 0; + + file_cache->FAT_cnt = build_up_fat(&(file_cache->FAT), file_cache->data_cluster_index); + +} + + +int fat32_lookup(struct vnode* dir_node, struct vnode **target, const char *component) { + struct fat32_dir_cache *dir_cache = dir_node->internal; + + + struct ds_list_head *head = dir_node->ch_list.next; + while(head != &(dir_node->ch_list)) { + struct fat32_file_cache *f_cache; + struct vnode *node = container_of(head, struct vnode, v_head); + f_cache = node->internal; + if(strncmp(component, f_cache->name, strlen(component)) == 0) { + *target = node; + return 0; + } + head = ds_list_front(head); + } + + char filename[12]; + + // if not found + char buf[768]; + readblock(clusteridx2datablkidx(dir_cache->dir_clus_idx), buf); + int cur_clus_idx = dir_cache->dir_clus_idx; + struct fat32_dir_entry *ent = buf; + int fat_idx = 0; + while(!end_of_cluster(cur_clus_idx)) { + + for(int i = 0; i < 16; i ++) { + int len = dirent2filename(ent, filename); + if(strncmp(filename, component, strlen(component)) == 0){ + struct vnode *cur_node = (struct vnode*)kmalloc(sizeof(struct vnode)); + if(ent->attr == ATTR_DIRECTORY) { + init_fat32_dir_vnode(cur_node, ent, component); + cur_node->parent = dir_node; + } else { + init_fat32_file_vnode(cur_node, ent, component); + struct fat32_file_cache *f_cache = cur_node->internal; + f_cache->dir_ent_clus_idx = cur_clus_idx; + f_cache->dir_idx = i; + cur_node->parent = dir_node; + } + + ds_list_addprev(&(dir_node->ch_list), &(cur_node->v_head)); + *target = cur_node; + return 0; + } + ent = (buf + 32 * i); + } + cur_clus_idx = dir_cache->FAT[fat_idx ++]; + } + return VFS_NOT_FOUND; +} + +int fat32_init(struct filesystem *fs) { + fs->root = (struct vnode*)kmalloc(sizeof(struct vnode)); + + ds_list_head_init(&(fs->root->ch_list)); + ds_list_head_init(&(fs->root->v_head)); + fs->root->flag = VFS_DIR; + fs->root->v_ops = &fat32_vops; + fs->root->f_ops = &fat32_fops; + fs->root->internal = (struct fat32_dir_cache*)kmalloc(sizeof(struct fat32_dir_cache)); + struct fat32_dir_cache *dir_cache = fs->root->internal; + // dir_cache->dir_clus_idx = fat_blk_idx + fat_base_idx; + dir_cache->dir_clus_idx = 2; + // int cur_clus_idx = dir_cache->dir_clus_idx; + // int old_clus_idx = cur_clus_idx - (cur_clus_idx & 0x7f); + + dir_cache->FAT_cnt = build_up_fat(&(dir_cache->FAT), dir_cache->dir_clus_idx); + return 0; +} + +int fat32_open(struct vnode* node, struct file **target) { + if(node->flag == VFS_DIR) return VFS_CANNOT_OPEN_DIR; + struct file *file = (struct file*)kmalloc(sizeof(struct file)); + struct fat32_file_cache *file_cache = node->internal; + file_cache->opening += 1; + + file->f_ops = &fat32_fops; + file->f_pos = 0; + file->vnode = node; + + *target = file; + return 0; +} + +uint32_t bin_align(uint32_t val) { + int ret = 4096; + while(ret < val) { + ret *= 2; + } + return ret; +} +void build_up_cache(struct fat32_file_cache *file_cache) { + file_cache->maxsize = bin_align(file_cache->filesize); + file_cache->tmpdata = cmalloc(file_cache->maxsize); + int cur_clus_idx = file_cache->data_cluster_index; + int cnt = 0; + + while(!end_of_cluster(cur_clus_idx)) { + readblock(clusteridx2datablkidx(cur_clus_idx), file_cache->tmpdata + cnt * SECTOR_SIZE); + cur_clus_idx = file_cache->FAT[cnt ++]; + } +} + +int fat32_read(struct file *f, void *buf, long len) { + struct vnode* node = f->vnode; + + struct fat32_file_cache *file_cache = node->internal; + if(file_cache->cached == 0) { + // load the file into cache + // fully cache for each file + // maybe not very good implementation + build_up_cache(file_cache); + file_cache->cached = 1; + } + + + for(int i = 0; i < len; i ++, f->f_pos ++) { + if(f->f_pos == file_cache->filesize) { + return i; + } + *(char *)(buf + i) = *(char *)(file_cache->tmpdata + f->f_pos); + } + + return len; +} + +int fat32_write(struct file *f, void *buf, long len) { + struct vnode* node = f->vnode; + + struct fat32_file_cache *file_cache = node->internal; + if(file_cache->cached == 0) { + // load the file into cache + // fully cache for each file + // maybe not very good implementation + build_up_cache(file_cache); + file_cache->cached = 1; + } + file_cache->dirty = 1; + + for(int i = 0; i < len; i ++, f->f_pos ++) { + if(f->f_pos == file_cache->maxsize) { + // if hit maxsize, alloc new cache and free old one + void *newcache = cmalloc(file_cache->maxsize << 1); + memcpy(newcache, file_cache->tmpdata, file_cache->maxsize); + kfree(file_cache->tmpdata); + file_cache->tmpdata = newcache; + file_cache->maxsize <<= 1; + } + if(f->f_pos >= file_cache->filesize) { + file_cache->filesize = f->f_pos + 1; + } + *(char *)(file_cache->tmpdata + f->f_pos) = *(char *)(buf + i); + } + + return len; +} + +int fat32_create(struct vnode *dir_node, struct vnode **target, const char *comp) { + // uart_send_string("In fat32 create\r\n"); + struct vnode *new_node = (struct vnode*)kmalloc(sizeof(struct vnode)); + + new_node->internal = kmalloc(sizeof(struct fat32_file_cache)); + new_node->flag = VFS_FILE; + new_node->f_ops = &fat32_fops; + new_node->v_ops = &fat32_vops; + new_node->mount = NULL; + new_node->parent = NULL; + ds_list_head_init(&(new_node->ch_list)); + ds_list_head_init(&(new_node->v_head)); + struct fat32_file_cache *file_cache = new_node->internal; + if(comp != NULL) { + memcpy(file_cache->name, comp, strlen(comp)); + } + file_cache->name[strlen(comp)] = '\0'; + file_cache->filesize = 0; + + int cur_clus_idx = file_cache->data_cluster_index; + file_cache->dirty = 1; + file_cache->cached = 1; + file_cache->opening = 0; + file_cache->tmpdata = cmalloc(PAGE_SIZE); + file_cache->maxsize = PAGE_SIZE; + file_cache->filesize = 1; + struct fat32_dir_cache *dir_cache = dir_node->internal; + file_cache->dir_ent_clus_idx = dir_cache->dir_clus_idx; + file_cache->dir_idx = 0xffffffff; + file_cache->FAT_cnt = 0xffffffff; + file_cache->FAT = NULL; + + ds_list_addprev(&(dir_node->ch_list), &(new_node->v_head)); + new_node->parent = dir_node; + + *target = new_node; + + return 0; +} + +int fat32_setup_mount(struct filesystem *fs, struct mount *mnt) { + // uart_send_string("In fat32 setup mount\r\n"); + mnt->root = fs->root; + mnt->fs = fs; + if(fs->root->mount == NULL) { + fs->root->mount = mnt; + } + return 0; +} + +void setup_boot() { + char buf[1024]; + readblock(0, buf); + for(int i = 0; i < 4; i ++) { + memcpy(&pe[i], buf + (446 + 16 * i), 16); + } + + // read first partition + struct fat_boot_sector partition1; + + readblock(pe[0].num_between, buf); + fat_base_idx = pe[0].num_between; + memcpy(&partition1, buf, sizeof(struct fat_boot_sector)); + + fat_blk_idx = partition1.n_reserve_sec + fat_base_idx; + fat_data_region_idx = partition1.n_copy * partition1.n_sec_per_fat + partition1.n_reserve_sec + fat_base_idx; + + register_filesystem(&fat32_fs); + vfs_mkdir("/boot"); + vfs_mount("/boot", "fat32_boot"); +} + +void fat32_sync_dir(struct vnode* dir_node) { + struct ds_list_head *head = dir_node->ch_list.next; + while(head != &(dir_node->ch_list)) { + struct vnode *node = container_of(head, struct vnode, v_head); + if(node->flag == VFS_FILE) { + fat32_sync_file(node, dir_node); + } else { + fat32_sync_dir(node); + } + head = ds_list_front(head); + } +} + +void gen_new_fat(struct fat32_file_cache *f_cache, uint32_t new_fat_cnt) { + uint32_t *new_fat = kmalloc(new_fat_cnt * 4); + int cnt = 0; + if(f_cache->FAT_cnt != 0xffffffff) { + for(; cnt < f_cache->FAT_cnt - 1; cnt ++) { + new_fat[cnt] = f_cache->FAT[cnt]; + } + } else { + cnt = -1; + } + + + + uint32_t buf[150]; + int idx = 0; + + while(cnt < (int)(new_fat_cnt - 1)) { + readblock(idx + fat_blk_idx, &(buf[0])); + for(int i = 0; i < 128; i ++) { + if(buf[i] == 0) { + if(f_cache->FAT_cnt == 0xffffffff) { + f_cache->data_cluster_index = idx * 128 + i; + f_cache->FAT_cnt = new_fat_cnt; + cnt ++; + } else { + new_fat[cnt] = idx * 128 + i; + cnt ++; + } + if(cnt >= new_fat_cnt - 1) break; + } + } + idx ++; + } + new_fat[new_fat_cnt - 1] = END_OF_CLUSTER; + kfree(f_cache->FAT); + f_cache->FAT = new_fat; + f_cache->FAT_cnt = new_fat_cnt; +} + +void flush_new_fat(struct fat32_file_cache *f_cache) { + uint32_t cur_clus_idx = f_cache->data_cluster_index; + uint32_t buf[150]; + int cnt = 0; + while(!end_of_cluster(cur_clus_idx)) { + readblock((cur_clus_idx >> 7) + fat_blk_idx, &(buf[0])); + buf[cur_clus_idx & 0x7f] = f_cache->FAT[cnt]; + writeblock((cur_clus_idx >> 7) + fat_blk_idx, &(buf[0])); + cur_clus_idx = f_cache->FAT[cnt]; + cnt += 1; + } +} +void flush_data(struct fat32_file_cache *f_cache) { + uint32_t cur_clus_idx = f_cache->data_cluster_index; + int cnt = 0; + while(!end_of_cluster(cur_clus_idx)) { + writeblock(clusteridx2datablkidx(cur_clus_idx), (f_cache->tmpdata + 512 * cnt)); + cur_clus_idx = f_cache->FAT[cnt]; + cnt += 1; + } +} + +void copy_name(struct fat32_dir_entry *ent, struct fat32_file_cache *f_cache) { + uint8_t found = 0; + int i; + for(i = 0; i < 8; i ++) { + if(f_cache->name[i] == '.') { + found = i; + } + if(found) { + ent->filename[i] = ' '; + } else { + if(f_cache->name[i] >= 'a' && f_cache->name[i] <= 'z') { + ent->filename[i] = f_cache->name[i] + ('A' - 'a'); + } else { + ent->filename[i] = f_cache->name[i]; + } + } + } + if(found == 0) return; + for(i = found + 1; i <= found + 3; i ++) { + if(f_cache->name[i] == '\0') { + break; + } + if(f_cache->name[i] >= 'a' && f_cache->name[i] <= 'z') { + ent->ext[i - found - 1] = f_cache->name[i] + ('A' - 'a'); + } else { + ent->ext[i - found - 1] = f_cache->name[i]; + } + } +} + +void fat32_sync_file(struct vnode* file_node, struct vnode *dir_node) { + + struct fat32_file_cache *f_cache = file_node->internal; + if(!f_cache->dirty) return; + + char buf[768]; + if(f_cache->dir_idx != 0xffffffff) { + // update the dir entry for the file + readblock(clusteridx2datablkidx(f_cache->dir_ent_clus_idx), buf); + struct fat32_dir_entry *ent = ((void*)(buf + 32 * f_cache->dir_idx)); + ent->file_size = f_cache->filesize; + writeblock(clusteridx2datablkidx(f_cache->dir_ent_clus_idx), buf); + + // update the file entry for the file + uint32_t new_fat_cnt = (f_cache->filesize + SECTOR_SIZE - 1) / SECTOR_SIZE; + if(f_cache->FAT_cnt < new_fat_cnt) { + gen_new_fat(f_cache, new_fat_cnt); + flush_new_fat(f_cache); + } + flush_data(f_cache); + } else { + uint32_t new_fat_cnt = (f_cache->filesize + SECTOR_SIZE - 1) / SECTOR_SIZE; + gen_new_fat(f_cache, new_fat_cnt); + flush_new_fat(f_cache); + int cur_clus_idx = f_cache->dir_ent_clus_idx; + struct fat32_dir_cache *dir_cache = dir_node->internal; + int cnt = 0; + while(!end_of_cluster(cur_clus_idx)) { + readblock(clusteridx2datablkidx(cur_clus_idx), buf); + struct fat32_dir_entry *ent; + for(int i = 0; i < 16; i ++) { + ent = ((void*)(buf + 32 * i)); + if(*(uint64_t*)(ent) == 0) { + ent->attr = ATTR_ARCHIVE; + ent->beg_clus_l = f_cache->data_cluster_index & 0xffff; + ent->file_size = f_cache->filesize; + copy_name(ent, f_cache); + writeblock(clusteridx2datablkidx(cur_clus_idx), buf); + goto find; + } + } + cur_clus_idx = dir_cache->FAT[cnt ++]; + } + + struct fat32_file_cache tmp; + tmp.FAT_cnt = dir_cache->FAT_cnt; + tmp.FAT = dir_cache->FAT; + tmp.data_cluster_index = dir_cache->dir_clus_idx; + + // if not found, find a new fat table + // this implementation is not very good + // but I don't wanna spend more time on this + gen_new_fat(&(tmp), dir_cache->FAT_cnt + 1); + dir_cache->FAT_cnt = tmp.FAT_cnt; + dir_cache->FAT = tmp.FAT; + flush_new_fat(&(tmp)); + cur_clus_idx = tmp.FAT[tmp.FAT_cnt - 2]; + readblock(clusteridx2datablkidx(cur_clus_idx), buf); + + struct fat32_dir_entry *ent; + ent = buf; + ent->attr = ATTR_ARCHIVE; + ent->beg_clus_l = f_cache->data_cluster_index & 0xffff; + ent->beg_clus_h = (f_cache->data_cluster_index >> 16) & 0xffff; + ent->file_size = f_cache->filesize; + copy_name(ent, f_cache); + writeblock(clusteridx2datablkidx(cur_clus_idx), buf); + + find:; + flush_data(f_cache); + } + +} + +void fat32_sync() { + fat32_sync_dir(fat32_fs.root); +} \ No newline at end of file diff --git a/src/kernel/fs/tmpfs.c b/src/kernel/fs/tmpfs.c new file mode 100644 index 000000000..efa511de3 --- /dev/null +++ b/src/kernel/fs/tmpfs.c @@ -0,0 +1,224 @@ +#include "fs/vfs.h" +#include "fs/tmpfs.h" +#include "mem/mem.h" +#include "utils.h" + + +struct file tmpfs_filehandle[24]; +static uint8_t tmpfs_first_mount = 0; + +struct filesystem tmpfs = { + .name = "tmpfs", + .root = NULL, + .init_fs = &init_tmpfs, + .setup_mount = &mount_tmpfs +}; + +struct vnode_operations tmpfs_vnode_ops = { + .lookup = &tmpfs_lookup, + .create = &tmpfs_create, + .mkdir = &tmpfs_mkdir +}; + +struct file_operations tmpfs_file_ops = { + .write = &tmpfs_write, + .read = &tmpfs_read, + .open = &tmpfs_open, + .close = &tmpfs_close, + .lseek64 = &tmpfs_lseek64, + .stat = &tmpfs_stat, + .ioctl = &fops_not_support +}; + +int init_tmpfs(struct filesystem *fs) { + fs->root = (struct vnode*)kmalloc(sizeof(struct vnode)); + fs->root->v_ops = &tmpfs_vnode_ops; + fs->root->f_ops = &tmpfs_file_ops; + ds_list_head_init(&(fs->root->ch_list)); + ds_list_head_init(&(fs->root->v_head)); + fs->root->flag = VFS_DIR; + fs->root->mount = NULL; + fs->root->internal = (struct tmpfs_vinfo*)kmalloc(sizeof(struct tmpfs_vinfo)); + struct tmpfs_vinfo *info = fs->root->internal; + info->content = NULL; + strncpy((info->name), "/", 2); + info->namesize = 1; + return 0; +} + +int mount_tmpfs(struct filesystem *fs, struct mount *mnt) { + // general version of mount + + mnt->root = fs->root; + if(fs->root->mount == NULL) { + fs->root->mount = mnt; + } + + mnt->fs = fs; + if(tmpfs_first_mount == 0) { + for(int i = 0; i < 24; i ++) { + tmpfs_filehandle[i].flags = HANDLE_NOT_USED; + } + tmpfs_first_mount = 1; + } + return 0; +} + +int tmpfs_lookup(struct vnode* dir_node, struct vnode** target, const char * componenet_name) { + + struct ds_list_head *cur = dir_node->ch_list.next; + struct vnode* v; + struct tmpfs_vinfo *info; + while(cur != &(dir_node->ch_list)) { + v = container_of(cur, struct vnode, v_head); + info = v->internal; + if(strncmp(info->name, componenet_name, strlen(componenet_name)) == 0) { + *target = v; + return 0; + } + + cur = ds_list_front(cur); + if(cur == NULL) { + return VFS_NOT_FOUND; + } + } + return VFS_NOT_FOUND; +} + +struct vnode* new_tmpfs_node(const char *name, struct vnode *dir_node) { + struct vnode* ret = (struct vnode*)kmalloc(sizeof(struct vnode)); + + + if(dir_node != NULL) { + ret->f_ops = dir_node->f_ops; + ret->v_ops = dir_node->v_ops; + ret->parent = dir_node; + } else { + ret->f_ops = &tmpfs_file_ops; + ret->v_ops = &tmpfs_vnode_ops; + ret->parent = NULL; + } + + ret->mount = NULL; + ds_list_head_init(&(ret->ch_list)); + ds_list_head_init(&(ret->v_head)); + ret->internal = (struct tmpfs_vinfo*)kmalloc(sizeof(struct tmpfs_vinfo)); + struct tmpfs_vinfo *ptr = ret->internal; + int len = strlen(name); + memcpy(&(ptr->name), name, len); + ptr->namesize = len; + ptr->content = NULL; + ptr->filesize = 0; + ptr->name[len] = '\0'; + return ret; +} + + +int tmpfs_create(struct vnode* dir_node, struct vnode** target, const char *component_name) { + + struct vnode* ret; + int err = tmpfs_lookup(dir_node, &ret, component_name); + if(err == VFS_NOT_FOUND) { + ret = new_tmpfs_node(component_name, dir_node); + } else { + struct tmpfs_vinfo *info = ret->internal; + kfree(info->content); + info->filesize = 0; + info->content = NULL; + } + ds_list_addprev(&(dir_node->ch_list), &(ret->v_head)); + ret->parent = dir_node; + *target = ret; + return 0; +} + +int tmpfs_mkdir(struct vnode* dir_node, struct vnode** target, const char *componenet_name) { + struct vnode* ret = new_tmpfs_node(componenet_name, dir_node); + ret->flag = VFS_DIR; + ds_list_addprev(&(dir_node->ch_list), &(ret->v_head)); + ret->parent = dir_node; + + *target = ret; + return 0; +} + +void init_fs() { + register_filesystem(&tmpfs); + vfs_mount("/", "tmpfs"); + return; +} + + +int tmpfs_read(struct file* file, const void *buf, size_t len) { + struct vnode *vn = file->vnode; + struct tmpfs_vinfo *info = vn->internal; + + for(int i = 0; i < len; i ++, file->f_pos ++) { + if(file->f_pos == info->filesize) { + return i; + } + *(char *)(buf + i) = *(char *)(info->content + file->f_pos); + } + return len; +} + +int tmpfs_open(struct vnode* file_node, struct file** target) { + // uart_send_string("In tmpfs open\r\n"); + + + tmpfs_print_name(file_node); + for(int i = 0; i < 24; i ++) { + if(tmpfs_filehandle[i].flags == HANDLE_NOT_USED) { + tmpfs_filehandle[i].vnode = file_node; + tmpfs_filehandle[i].f_ops = &tmpfs_file_ops; + tmpfs_filehandle[i].f_pos = 0; + tmpfs_filehandle[i].flags = 0; + *(target) = &(tmpfs_filehandle[i]); + return i; + } + } + return -1; +} + +int tmpfs_close(struct file* file) { + file->flags = HANDLE_NOT_USED; + file->vnode = NULL; + return 0; +} + +long tmpfs_lseek64(struct file* file, long offset, int whence) { + return 0; +} + +int tmpfs_write(struct file *file, const void *buf, size_t len) { + struct vnode* vn = file->vnode; + struct tmpfs_vinfo *info = (struct tmpfs_vinfo*)file->vnode->internal; + if(info->content == NULL) { + info->content = (void*)cmalloc((1 << 12)); + } + + for(int j = 0; j < len; j ++, file->f_pos ++) { + if(file->f_pos == TMPFS_MAX_CONTENT_SIZE) { + return j; + } + *(char *)(info->content + file->f_pos) = *(char*)(buf + j); + if(info->filesize <= file->f_pos) { + info->filesize = file->f_pos + 1; + } + } + return len; +} + +void tmpfs_print_name(struct vnode* node) { + struct tmpfs_vinfo *info = node->internal; + + uart_send_string(info->name); + uart_send_string("\r\n"); +} + +int tmpfs_stat(struct file *f, struct fstat *stat) { + struct tmpfs_vinfo *info = f->vnode->internal; + (stat)->filesize = info->filesize; + (stat)->namesize = info->namesize; + return 0; +} \ No newline at end of file diff --git a/src/kernel/fs/vfs.c b/src/kernel/fs/vfs.c new file mode 100644 index 000000000..d791674bd --- /dev/null +++ b/src/kernel/fs/vfs.c @@ -0,0 +1,308 @@ +#include "fs/vfs.h" +#include "mem/mem.h" +#include "utils.h" +#include "ds/list.h" +#include "interrupt.h" +#include "peripherals/mini_uart.h" +#include "process.h" + + +struct mount* rootfs; +struct ds_list_head fs_list; +void vfs_init(){ + rootfs = NULL; + ds_list_head_init(&fs_list); + return; +} + +struct vnode* get_parent_vnode(struct vnode* node) { + return node->parent; +} + +struct filesystem *find_fs_by_name(const char *name) { + // struct ds_list_head *head = ds_list_front(&fs_list); + struct ds_list_head *head = fs_list.next; + // if(head == NULL) { + // return NULL; + // } + while(head != &fs_list) { + struct filesystem *fs = container_of(head, struct filesystem, fs_head); + // uart_send_string(fs->name); + if(strncmp(name, fs->name, strlen(fs->name)) == 0) { + return fs; + } + head = ds_list_front(head); + if(head == NULL) { + return NULL; + } + } + return NULL; +} + +int register_filesystem(struct filesystem* fs) { + + struct filesystem *same = find_fs_by_name(fs->name); + if(same == NULL) { + if(fs->init_fs != NULL) { + fs->init_fs(fs); + } + ds_list_head_init(&(fs->fs_head)); + ds_list_addprev(&fs_list, &(fs->fs_head)); + return 0; + } else { + return VFS_NOT_FOUND; + } +} + + +// this is very bad implementation +// can only fit comp[20][20] array +int split_path(const char* pathname, char comp[][20]) { + + int len = strlen(pathname); + int beg = 0; + int end = 0; + int idx = 0; + + for(int i = 0; i < len; i ++) { + if(pathname[i] == '/') { + end = i; + if(end - beg > 0) { + memcpy(comp[idx], pathname + beg, end - beg); + comp[idx][end - beg] = '\0'; + idx ++; + } + beg = i + 1; + } + } + char *ptr = comp[idx]; + if(len != beg) { + memcpy(ptr, pathname + beg, len - beg); + *(char *)(ptr + len - beg) = '\0'; + idx += 1; + } + return idx; +} + + +int vfs_lookup(const char* pathname, struct vnode** target) { + + + + struct vnode* vnode_itr; + + if(pathname[0] == '/') { + // uart_send_string("From root\r\n"); + vnode_itr = rootfs->root; + } else { + struct Process_t *proc = process_get_current(); + vnode_itr = proc->cur_vnode; + } + + char comp[20][20]; + + int num = split_path(pathname, &comp); + *target = NULL; + + for(int i = 0; i < num; i ++) { + // uart_send_string(comp[i]); + // int x = strncmp(comp[i], "..", 2); + // uart_send_dec(x); + if(strncmp(comp[i], "..", 2) == 0) { + vnode_itr = vnode_itr->parent; + continue; + } else if(strncmp(comp[i], ".", 1) == 0) { + continue; + } + struct vnode* next_vnode; + // uart_send_u64(vnode_itr); + // uart_send_string("before this\r\n"); + struct vnode* ret = vnode_itr->v_ops->lookup(vnode_itr, &next_vnode, comp[i]); + // uart_send_string("After this\r\n"); + if(ret != 0) { + // if this is last one + if(i == num - 1) { + *target = vnode_itr; + return VFS_CAN_CREATE; + } + return ret; + } + if(next_vnode->mount != NULL) { + // uart_send_string("Jump to mounted vnode \r\n"); + // uart_send_u64(next_vnode->mount->root); + // uart_send_string("\r\n"); + vnode_itr = next_vnode->mount->root; + } else { + vnode_itr = next_vnode; + } + } + + *target = vnode_itr; + return 0; +} + +// api spec: +// different filesystem should provide its own root vnode. +int vfs_mount(const char *target, const char *filesystem) { + // uart_send_string(target); + // uart_send_string("\r\n"); + // uart_send_string(filesystem); + // uart_send_string("\r\n"); + struct filesystem* fs = find_fs_by_name(filesystem); + if(fs == NULL) { + // uart_send_string(filesystem); + // uart_send_string(" not found\r\n"); + return VFS_NOT_FOUND; + } + if(rootfs == NULL) { + rootfs = (struct mount *)kmalloc(sizeof(struct mount)); + rootfs->mountpoint = NULL; + int err = fs->setup_mount(fs, rootfs); + rootfs->root->parent = rootfs->root; + return err; + } else { + struct vnode *v; + int err = vfs_lookup(target, &v); + if(v->flag != VFS_DIR) { + return VFS_NOT_DIR; + } + + if(v->mount != NULL) { + return VFS_MOUNTED; + } + if(err) { + // uart_send_string("Error when mounting\r\n"); + return err; + } + v->mount = (struct mount *)kmalloc(sizeof(struct mount)); + err = fs->setup_mount(fs, v->mount); + if(err == 0) { + if(v->mount == fs->root->mount) { + v->mount->root->parent = v->parent; + v->mount->mountpoint = v; + } + } + return err; + } +} + +int vfs_open(const char* pathname, int flags, struct file** target) { + // 1. Lookup pathname + // 2. Create a new file handle for this vnode if found. + // 3. Create a new file if O_CREAT is specified in flags and vnode not found + // lookup error code shows if file exist or not or other error occurs + // 4. Return error code if fails + // uart_send_string("OPening flags\r\n"); + // uart_send_dec(flags); + // uart_send_string("\r\n"); + struct vnode *v; + // uart_send_string("hello\r\n"); + int err = vfs_lookup(pathname, &v); + char comp[20][20]; + // uart_send_string("hello\r\n"); + int num = split_path(pathname, comp); + if(err) { + if(err == VFS_CAN_CREATE && (flags & O_CREAT)) { + struct vnode *tmpv = v; + err = tmpv->v_ops->create(tmpv, &v, comp[num - 1]); + if(err) { + return err; + } + } else { + return err; + } + } else { + if(flags & O_CREAT) { + struct vnode *tmpv = v; + err = tmpv->parent->v_ops->create(tmpv->parent, &v, comp[num - 1]); + if(err) { + return err; + } + } + } + int fd = v->f_ops->open(v, target); + if(fd > 0) { + (*target)->flags = flags; + return 0; + } + return fd; +} + +int vfs_close(struct file* file) { + // 1. release the file handle + // 2. Return error code if fails + return file->f_ops->close(file); +} + +int vfs_write(struct file* file, const void* buf, size_t len) { + return file->f_ops->write(file, buf, len); +} + +int vfs_read(struct file* file, void* buf, size_t len) { + return file->f_ops->read(file, buf, len); +} + +void vfs_apply_dir(struct vnode* dir_node, apply_dir_func func) { + struct ds_list_head *head = ds_list_front(&(dir_node->ch_list)); + if(head == NULL) { + return; + } + + while(head != &(dir_node->ch_list)) { + struct vnode* node = container_of(head, struct vnode, v_head); + func(node); + head = ds_list_front(head); + } +} + +int vfs_create(const char *pathname, int flags, struct vnode** target) { + struct vnode *ret; + int err = vfs_lookup(pathname, &ret); + + + if(err == 0) { + *(target) = ret; + return VFS_EXIST; + } else if(err == VFS_CAN_CREATE) { + char comp[20][20]; + int num = split_path(pathname, comp); + struct vnode *tmpret = ret; + err = tmpret->v_ops->create(tmpret, &ret, comp[num - 1]); + *(target) = ret; + return err; + } else { + return err; + } +} + +int vfs_mkdir(const char *pathname) { + + struct vnode *v; + + int err = vfs_lookup(pathname, &v); + if(err == 0) { + return VFS_EXIST; + } else if(err == VFS_CAN_CREATE) { + char comp[20][20]; + int num = split_path(pathname, comp); + err = v->v_ops->mkdir(v, &v, comp[num - 1]); + return err; + } else { + return err; + } +} + +int vfs_stat(struct file *f, struct fstat *stat) { + return f->f_ops->stat(f, stat); +} + +int vops_not_support() { + return VFS_NOT_SUPPORT; +} +int fops_not_support() { + return VFS_NOT_SUPPORT; +} + +int vfs_lseek64(struct file *f, long offset, int whence) { + return f->f_ops->lseek64(f, offset, whence); +} \ No newline at end of file diff --git a/src/kernel/interrupt.c b/src/kernel/interrupt.c index 9b358034e..acf573900 100644 --- a/src/kernel/interrupt.c +++ b/src/kernel/interrupt.c @@ -7,11 +7,14 @@ #include "time.h" #include "type.h" #include "event.h" +#include "thread.h" +#include "process.h" +#include "syscall.h" #define IRQ_BASIC_PENDING (PBASE + 0xB200) #define IRQ_GPU_PENDING1 (PBASE + 0xB204) #define IRQ_GPU_PENDING2 (PBASE + 0xB208) -#define CORE_IRQ_SOURCE (0x40000060) +#define CORE_IRQ_SOURCE (0xffff000040000060) #define GPU_INTERRUPT (0x100) #define AUX_INT (1 << 29) @@ -21,7 +24,6 @@ extern struct k_event demo_timer_event; int demo_state = 0; void irqhandler_inc() { - // asm volatile ("msr DAIFSet, 0xf\n"); int flag = interrupt_disable_save(); interrupt_handler_counter += 1; interrupt_enable_restore(flag); @@ -37,15 +39,10 @@ int irqhandler_cnt_get() { } void enable_interrupt() { - interrupt_counter -= 1; - if(interrupt_counter < 0) interrupt_counter = 0; - if(interrupt_counter == 0) { - asm volatile ("msr DAIFClr, 0xf\n"); - } + asm volatile ("msr DAIFClr, 0xf\n"); } void disable_interrupt() { asm volatile ("msr DAIFSet, 0xf\n"); - interrupt_counter += 1; } void exception_entry(unsigned long esr, unsigned long elr, unsigned long spsr) { @@ -60,18 +57,19 @@ void exception_entry(unsigned long esr, unsigned long elr, unsigned long spsr) { uart_send_u64(spsr); uart_send_string("\r\n"); uart_switch_func(UART_ASYNC); + while(1) { + asm volatile("nop\n"); + } return; } -void time_interrupt_handler() { +void time_interrupt_handler(struct Trapframe_t *frame) { struct k_timeout *t; uint64_t tick; while(1) { - // uart_send_string("xxxx\r\n"); asm volatile("mrs %0, cntpct_el0\n":"=r"(tick)); t = k_timeout_queue_front(); if(t == NULL) { - uint64_t x = 0x3f3f3f3fLL; asm volatile( "ldr x0, =0xffffffffff\n" "msr cntp_cval_el0, x0\n" @@ -90,6 +88,7 @@ void time_interrupt_handler() { break; } } + handle_time_schedule(frame); } void uart_handler() { @@ -97,8 +96,8 @@ void uart_handler() { if(pending & AUX_INT) { unsigned int IER_REG = *(volatile unsigned int*)(AUX_MU_IER_REG); if(IER_REG & 1) { + // only recv can delay the work irqhandler_inc(); - // uart_send_dec(irqhandler_cnt_get()); uart_int_recv_handler(); } if(IER_REG & 2) { @@ -106,26 +105,32 @@ void uart_handler() { } } } -void spx_irq_handler(unsigned long esr, unsigned long elr, unsigned long spsr) { +void spx_irq_handler(struct Trapframe_t *frame, uint64_t esr) { unsigned int pending = read_reg_32(CORE_IRQ_SOURCE); - if(pending & 0x2) { - time_interrupt_handler(); - } if(pending & GPU_INTERRUPT) { + uart_handler(); } + else if(pending & 0x2) { + time_interrupt_handler(frame); + } + else { + // uint64_t dfsr_value; + // asm volatile ("mrs %0, dfsr_el1" : "=r" (dfsr_value)); + + } + return; } -void lower_irq_handler(unsigned long esr, unsigned long elr, unsigned long spsr) { +void lower_irq_handler(struct Trapframe_t *frame) { unsigned int pending = read_reg_32(CORE_IRQ_SOURCE); if(pending & GPU_INTERRUPT) { uart_handler(); } - if(pending & 0x2) { - irqhandler_inc(); - demo_state = 1; - k_event_submit(&demo_timer_event, NULL, 0, 100); + else if(pending & 0x2) { + + time_interrupt_handler(frame); } return; } @@ -145,4 +150,60 @@ uint64_t interrupt_disable_save() { "msr DAIFSet, 0xf\n" ); return flag; +} + + +struct Trapframe_t anoFrame; +void svc_handler(struct Trapframe_t *frame) { + if(frame->esr_el1 >> 26 == 0b010101) { + // memcpy(&anoFrame, frame, sizeof(struct Trapframe_t)); + uint16_t svcnum = frame->esr_el1 & 0xffff; + if(svcnum == 0) { + syscall_handler(frame); + } + // for(int i = 0; i < sizeof(struct Trapframe_t) >> 3; i ++) { + // if(*((uint64_t*)(&anoFrame) + i) != *((uint64_t*)(frame) + i)) { + // uart_switch_func(UART_DEFAULT); + // // uart_send_string("fucked\r\n"); + // uart_send_string("In i = "); + // uart_send_dec(i); + // uart_send_string("\r\n"); + // uart_switch_func(UART_ASYNC); + // } + // } + } else { + // uart_switch_func(UART_DEFAULT); + // uart_send_string("\r\nOther interrupt\r\n"); + // // uart_send_u64(frame->esr_el1); + // // uart_send_string("\r\n"); + // // uart_send_u64(frame->elr_el1); + // uart_send_u64(thread_get_current_instance()->tid); + // uart_send_string("\r\n"); + // // } + // uart_switch_func(UART_ASYNC); + } +} + +uint64_t check_exception_depth() { + struct Thread_t *th = thread_get_current_instance(); + uint64_t sp; + uint64_t lr; + asm volatile( + "mov x0, sp\n" + "mov %[sp], x0\n" + "mrs %[lr], elr_el1\n":[sp]"=r"(sp), [lr]"=r"(lr) + ); + uint64_t val = ((uint64_t)th->sp - sp) / (32 * 9); + // if(th->sp < sp) { + // uart_switch_func(UART_DEFAULT); + // uart_send_string("Except Fucked\r\n"); + // uart_send_u64(th->sp); + // uart_send_string("\r\n"); + // uart_send_u64(sp); + // uart_send_string("\r\n"); + // uart_send_u64(lr); + // uart_send_string("\r\n"); + // uart_switch_func(UART_ASYNC); + // } + return val; } \ No newline at end of file diff --git a/src/kernel/kernel_main.c b/src/kernel/kernel_main.c index e931ca1b9..a5b954c48 100644 --- a/src/kernel/kernel_main.c +++ b/src/kernel/kernel_main.c @@ -2,6 +2,7 @@ #include "mbox/mbox.h" #include "power.h" #include "utils.h" +#include "ds/list.h" #include "cpio/cpio.h" #include "dtb/dtb.h" #include "mem/mem.h" @@ -10,7 +11,17 @@ #include "ds/heap.h" #include "test/demo.h" #include "mem/page.h" - +#include "process.h" +#include "thread.h" +#include "mmu/mmu.h" +#include "fs/tmpfs.h" +#include "fs/vfs.h" +#include "framebuffer.h" +#include "sd.h" +#include "fs/fat32.h" + +extern struct Trapframe_t *gen_trapframe(); +extern struct ds_list_head process_list; #define SHELL_BUFSIZE 64 #define REPLY_BUFSIZE 128 @@ -95,7 +106,7 @@ unsigned int _info_cb(char *arg) { uart_send_u32(mbox_buf[5]); uart_send_string("\r\n"); } else { - uart_send_string("Error when gather info!!\r\n"); + uart_send_string("Error when gather info!!\r\n"); } mbox_buf[0] = 8 * 4; mbox_buf[1] = 0; @@ -113,7 +124,7 @@ unsigned int _info_cb(char *arg) { uart_send_u32(mbox_buf[6]); uart_send_string("\r\n"); } else { - uart_send_string("Error when gather info!!\r\n"); + uart_send_string("Error when gather info!!\r\n"); } return 0; } @@ -125,17 +136,36 @@ unsigned int _reboot_cb(char *arg) { } unsigned int _ls_cb(char *arg) { - list_files(); + // list_files(); + struct Process_t *cur_proc = process_get_current(); + vfs_apply_dir(cur_proc->cur_vnode, &tmpfs_print_name); return 0; } unsigned int _cat_cb(char *arg) { - cat_file(arg); - return 0; + // cat_file(arg); + + struct file *f; + // uart_send_string(arg); + int err = vfs_open(arg, O_READ, &f); + + char _buf[100]; + int n; + if(err == 0) { + while(n = vfs_read(f, _buf, 100)) { + uart_send_n(_buf, n); + } + vfs_close(f); + } else { + uart_send_dec(-err); + uart_send_string("Error when opening the file\r\n"); + return err; + } } unsigned int _load_cb(char *arg) { load_program(arg); + // process_load(arg); return 0; } @@ -170,26 +200,143 @@ unsigned int _test_uart_cb(char *arg) { } return 0; } -void *ptr[128]; -static unsigned int k_malloc_cnt = 0; -unsigned int str_to_int(char *arg) { - unsigned int ret = 0; - while(*arg != '\0') { - if(*arg >= '0' && *arg <= '9') { - ret = ret * 10 + (*arg - '0'); +void _test_thread_get_current() { + return; + // uart_send_u64(thread_get_current()); +} +void _test_thread_set_current() { + asm volatile( + "mov x0, 1\n" + "msr tpidr_el1, x0\n" + ); +} + +void foo() { + for(int i = 0; i < 10; i ++) { + uart_send_string("Thread id: "); + uart_send_dec(thread_get_current()); + uart_send_string(" "); + uart_send_dec(i); + uart_send_string("\r\n"); + delay(1000000); + schedule(0); + } + return; +} + +static void _test_thread() { + int N = 3; + for(int i = 0; i < N; ++i) { // N should > 2 + thread_create(foo, NULL); + } + schedule(0); +} + +static void _test_fork() { + // uint64_t n = process_fork(); + // if(n == 0) { + // while(1) { + // asm volatile("nop"); + // } + // } + asm volatile( + "mov x8, 4\n" + "svc 0\n" + ); + uint64_t pid; + asm volatile( + "mov %[pid], x0":[pid]"=r"(pid) + ); + if(pid == 0) { + uart_send_string("after fork\r\n"); + while(1) { + asm volatile("nop"); + } + } + // uart_send_string("What happen\r\n"); + // while(1){ + // schedule(0); + // } +} +unsigned int _touch(char *arg) { + // cat_file(arg); + // struct file *f; + struct vnode* target; + int err = vfs_create(arg, O_CREAT, &target); + + // int err = vfs_open(arg, O_CREAT, &f); + // err = vfs_close(f); + // uart_send_dec(err); + return 0; +} +unsigned int _open(char *arg) { + struct file *f; + int err = vfs_open(arg, O_READ, &f); + uart_send_dec(err); + return 0; +} +unsigned int _test_write(char *arg) { + struct file *f; + int err = vfs_open(arg, O_WRITE, &f); + char _buf[] = "TETSTING WRITE\r\n"; + if(err == 0) { + for(int i = 0; i < 10; i ++) { + err = vfs_write(f, _buf, strlen(_buf)); + if(err < 0) { + uart_send_string("Error when writing\r\n"); + } } - arg ++; + err = vfs_close(f); + if(err < 0) { + uart_send_string("Error when closing\r\n"); + } + } else { + uart_send_string("Error when opening file\r\n"); } - return ret; } -unsigned int _kmalloc(char *arg) { - uart_send_string(arg); - uint32_t sz = str_to_int(arg); - ptr[++k_malloc_cnt] = kmalloc(sz); +unsigned int _test_read(char *arg) { + struct file *f; + int err = vfs_open(arg, O_READ, &f); + char _buf[10]; + if(err == 0) { + int n = vfs_read(f, _buf, 5); + while(n > 0) { + uart_send_n(_buf, n); + n = vfs_read(f, _buf, 5); + } + err = vfs_close(f); + if(err < 0) { + uart_send_string("Error when closing\r\n"); + } + } else { + uart_send_string("Error when opening file\r\n"); + } +} +unsigned int _mkdir(char *arg) { + int err = vfs_mkdir(arg); + if(err) { + uart_send_string("Error happen when creating dir\r\n"); + } + return 0; } -unsigned int _kfree(char *arg) { - unsigned int x = str_to_int(arg); - kfree(ptr[x]); + +unsigned int _cd(char *arg) { + struct vnode *dir; + int err = vfs_lookup(arg, &dir); + + if(err != 0) { + uart_send_string("Error when switching directory\r\n"); + } else { + struct Process_t *proc = process_get_current(); + proc->cur_vnode = dir; + proc->mnt = dir->mount; + } +} +unsigned int _mount(char *arg) { + char *mntpoint, *fsname; + split_comm_arg(arg, &mntpoint, &fsname); + // vfs_mkdir(mntpoint); + vfs_mount(mntpoint, fsname); } struct CmdNode cmds[] = { { @@ -199,7 +346,7 @@ struct CmdNode cmds[] = { { .comm = "help", .cb = _help_cb - }, + }, { .comm = "info", .cb = _info_cb @@ -211,7 +358,7 @@ struct CmdNode cmds[] = { { .comm = "ls", .cb = _ls_cb - }, + }, { .comm = "cat", .cb = _cat_cb @@ -235,11 +382,11 @@ struct CmdNode cmds[] = { { .comm = "setTimeout", .cb = _setTimeout_cb - }, + }, { .comm = "demo_page", .cb = demo_page - }, + }, { .comm = "test_simple_alloc", .cb = test_simple_alloc @@ -253,22 +400,69 @@ struct CmdNode cmds[] = { .cb = test_kmalloc }, { - .comm = "kmalloc", - .cb = _kmalloc + .comm = "get_t", + .cb = _test_thread_get_current + }, { + .comm = "set_t", + .cb = _test_thread_set_current + }, + { + .comm = "sched", + .cb = schedule + }, + { + .comm = "test_thread", + .cb = _test_thread + }, + { + .comm = "test_fork", + .cb = _test_fork + }, + { + .comm = "touch", + .cb = _touch + }, + { + .comm = "test_write", + .cb = _test_write + }, + { + .comm = "test_read", + .cb = _test_read }, { - .comm = "kfree", - .cb = _kfree + .comm = "open", + .cb = _open + }, + { + .comm = "mkdir", + .cb = _mkdir + }, + { + .comm = "cd", + .cb = _cd + }, + { + .comm = "mount", + .cb = _mount + }, + { + .comm = "sync", + .cb = fat32_sync } + // { + // .comm = "close", + // .cb = _close + // } }; - - - int handle_input(char *buf) { // uart_send_string(buf); int tot_len = strlen(buf); + if(tot_len == 0) { + return 0; + } // discard tailing space while(tot_len && buf[tot_len - 1] <= ' ') { buf[tot_len - 1] = '\0'; @@ -311,9 +505,7 @@ const char shell_beg[] = "______________________\r\n" void get_initramfs_addr(char *name, char *prop_name, char *data) { if(strncmp(name, "chosen", 6) == 0) { if(strncmp(prop_name, "linux,initrd-start", 18) == 0) { - unsigned long long x = ntohi(*(unsigned int*)(data)); - set_initramfs_addr(x); - memory_reserve(x, x + 0x10000); + set_initramfs_addr(ntohi(*(unsigned int*)(data))); } } } @@ -322,28 +514,8 @@ void print_msg(void *arg) { uart_send_string(arg); } -void kernel_main(void* dtb_addr) { - // uart_send_string("fucked\r\n"); - smem_init(); - fdt_param_init(dtb_addr); - k_event_queue_init(); - demo_init(); - uart_init(); - k_timeout_init(&msg, &print_msg); - enable_interrupt(); - enable_aux_interrupt(); - // frame_init(0x3c000000); - fdt_traverse(&set_init_mem_region); - kmalloc_init(); - // memory_reserve(0, 0x10000000); - memory_reserve(0, 0x1000); - memory_reserve(0x80000, 0x150000); - memory_reserve(dtb_addr, dtb_addr + 40000); - fdt_traverse(&get_initramfs_addr); - uart_send_string(shell_beg); - uart_send_string("# "); - - +void shell() { + // uart_send_string("Inside SHELL\r\n"); char cur; char *buf = simple_malloc(256); @@ -351,7 +523,8 @@ void kernel_main(void* dtb_addr) { int idx = 0; memset(buf, 0, 64); while(1) { - cur = uart_recv(); + // cur = uart_recv(); + uint32_t n = async_uart_rx_buf(&cur, 1); if(cur == 255) continue; if(cur == 127 || cur == 8) { if(idx == 0) continue; @@ -378,5 +551,74 @@ void kernel_main(void* dtb_addr) { buf[idx++] = cur; if(idx == 63) idx = 0; uart_send(cur); + // schedule(); } } + +extern struct Process_t init_process; +void go_el0() { + // uint64_t x, y, z; + // asm volatile( + // // "mrs x10, sp_el0\n" + // "mov %0, lr\n":"=r"(x) + // ); + // uart_send_u64(x); + // uart_send_string("\r\n"); + asm volatile( + "mov x10, 0x340\n" + "msr spsr_el1, x10\n" + "mov x10, lr\n" + "msr elr_el1, x10\n" + "eret\n" + ); +} +void kernel_main(void* dtb_addr) { + // uart_send_string("fucked\r\n"); + smem_init(); + fdt_param_init(dtb_addr); + k_event_queue_init(); + demo_init(); + uart_init(); + k_timeout_init(&msg, &print_msg); + kmalloc_init(); + memory_reserve(0 + KERNEL_SPACE_OFFSET, 0x15000000 + KERNEL_SPACE_OFFSET); + memory_reserve(0x20000000 + KERNEL_SPACE_OFFSET, 0x21000000 + KERNEL_SPACE_OFFSET); + memory_reserve(0x2f000000 + KERNEL_SPACE_OFFSET, 0x2f100000 + KERNEL_SPACE_OFFSET); + memory_reserve(0x3a000000 + KERNEL_SPACE_OFFSET, 0x3c000000 + KERNEL_SPACE_OFFSET); + fdt_traverse(&get_initramfs_addr); + fdt_traverse(&set_init_mem_region); + enable_interrupt(); + uart_switch_func(UART_DEFAULT); + enable_aux_interrupt(); + vfs_init(); + init_fs(); + uart_switch_func(UART_ASYNC); + mount_initramfs(); + thread_control_init(); + process_control_init(); + uart_send_string(shell_beg); + uart_send_string("# "); + + vfs_mkdir("/dev"); + vfs_mkdir("/tmp"); + setup_dev_uart(); + setup_dev_framebuffer(); + + sd_init(); + + + setup_boot(); + + struct Process_t *shell_proc = create_process_instance(); + shell_proc->ttbr0_el1 = 0x1000; + memcpy(shell_proc->name, "shell", 6); + + struct Thread_t *th = process_thread_create(shell, NULL, shell_proc, 1); + + // struct ds_list_head *front = ds_list_front(&(process_list)); + // while(front != &(process_list)) { + // struct Process_t *proc = container_of(front, struct Process_t, pl_head); + // front = ds_list_front(front); + // } + schedule_init(); +} diff --git a/src/kernel/linker.ld b/src/kernel/linker.ld index 9db0109b2..a6740ec6c 100644 --- a/src/kernel/linker.ld +++ b/src/kernel/linker.ld @@ -1,7 +1,8 @@ ENTRY(_start) SECTIONS { - . = 0x80000; + . = 0xffff000000000000; + . += 0x80000; .text.boot : { *(.text.boot*) } .text : { *(.text*) } .rodata : { *(.rodata*) } @@ -11,7 +12,7 @@ SECTIONS .bss : { *(.bss*) } . = ALIGN(0x10); _bss_end = .; - _stack_begin = 0x98000; - _heap_begin = . + 0x1000; - _heap_end = . + 0x1010000; + _stack_begin = 0xffff000000380000; + _heap_begin = 0xffff000000380000; + _heap_end = 0xffff000001010000; } \ No newline at end of file diff --git a/src/kernel/lock.c b/src/kernel/lock.c index 213e9aa69..f31295a62 100644 --- a/src/kernel/lock.c +++ b/src/kernel/lock.c @@ -11,7 +11,11 @@ struct k_lock* k_lock_new() { void k_lock_get(struct k_lock *lock) { uint64_t flag = interrupt_disable_save(); - while(lock->lock){asm volatile("nop");} + while(lock->lock){ + enable_interrupt(); + // asm volatile("nop"); + } + disable_interrupt(); lock->lock = 1; interrupt_enable_restore(flag); } diff --git a/src/kernel/mbox.c b/src/kernel/mbox.c index 533dbadd2..2a1b98a21 100644 --- a/src/kernel/mbox.c +++ b/src/kernel/mbox.c @@ -1,8 +1,10 @@ #include "mbox/mbox.h" #include "utils.h" #include "peripherals/mini_uart.h" +#include "mem/mem.h" +#include "mmu/mmu.h" -volatile unsigned int mbox_buf[16]__attribute__((aligned(16))); +volatile unsigned int mbox_buf[256]__attribute__((aligned(16))); int mbox_call_func(unsigned char prop_tag) { @@ -21,8 +23,35 @@ int mbox_call_func(unsigned char prop_tag) { break; } } + if(addr == read_reg_32(MAIL_READ)) { return mbox_buf[1] == MAIL_RESPONSE; } } } + +int mbox_call(unsigned char prop_tag, unsigned int *buf) { + + memcpy(&mbox_buf, buf, (size_t)buf[0]); + unsigned int addr = (((unsigned long)kernel_va2pa(mbox_buf)) & (~(0xF))) | prop_tag; + while(1) { + if((read_reg_32(MAIL_STATUS) & MAIL_FULL) == 0) { + break; + } + } + write_reg_32(MAIL_WRITE, addr); + + //fill mbox request + while(1) { + while(1) { + if((read_reg_32(MAIL_STATUS) & MAIL_EMPTY) == 0) { + break; + } + } + if(addr == read_reg_32(MAIL_READ)) { + + memcpy(buf, &mbox_buf, (size_t)mbox_buf[0]); + return buf[1] == MAIL_RESPONSE; + } + } +} \ No newline at end of file diff --git a/src/kernel/mem/mem.c b/src/kernel/mem/mem.c index c11a5488d..983a8e35a 100644 --- a/src/kernel/mem/mem.c +++ b/src/kernel/mem/mem.c @@ -8,6 +8,9 @@ #define SMALL_CHUNK_MAX_ORDER (PAGE_SIZE_ORDER) #define SMEM_CHUNK_MAX 31 #define ALLOC_MIN_ORD 5 +#define MIN_FREE_PAGE_CNT 20 + +// #define MEM_DEMO extern uint32_t _heap_begin; void* cur_mem_offset = &_heap_begin; @@ -49,9 +52,7 @@ void smem_init() { void *simple_malloc(uint32_t size) { // pad to align 8 bytes - // uint32_t offset = ((((size & 0x7) ^ 0x7) + 1) & 0x7) + size; - // cur_mem_offset += offset; - // return (cur_mem_offset - offset); + uint32_t flag = interrupt_disable_save(); uint8_t ord = size2ord(size); if(ord < 5) { @@ -87,7 +88,6 @@ void simple_free(void *ptr) { void kmalloc_init() { - // frame_init(); for(int i = 0; i < SMALL_CHUNK_MAX_ORDER + 1; i ++) { ds_list_head_init(&(kmem_pool[i])); } @@ -112,8 +112,9 @@ void *kmalloc(uint32_t size) { if(size == 0){ goto _r; } + void *ret; - if(size > (PAGE_SIZE >> 1)) { + if(size >= (PAGE_SIZE >> 1)) { ret = page_alloc(size); goto _r; } @@ -128,8 +129,7 @@ void *kmalloc(uint32_t size) { front = ds_list_front(&(ent->chunk_head)); struct kmem_node *node = container_of(front, struct kmem_node, head); ret = node->addr; - // uart_send_u64(ret); - // uart_send_string("\r\n"); + // remove from page pool ds_list_remove(&(node->head)); ent->dyn_count -= 1; @@ -154,7 +154,7 @@ void *kmalloc(uint32_t size) { init_page_chunk(ptr, ent, ord); #ifdef MEM_DEMO uart_send_string("\r\n"); - uart_send_string("Small Chunk new Base"); + uart_send_string("Small Chunk new Base\r\n"); uart_send_u64(ptr); uart_send_string("\r\n"); uart_send_u64(ent); @@ -169,6 +169,14 @@ void *kmalloc(uint32_t size) { } _r: interrupt_enable_restore(flag); + #ifdef MEM_DEMO + uart_send_string("size = "); + uart_send_dec(size); + uart_send_string("\r\n"); + uart_send_string("ret = "); + uart_send_u64(ret); + uart_send_string("\r\n"); + #endif return ret; } @@ -184,6 +192,12 @@ void free_chunk(struct frame_entry *ent) { } void kfree(void *ptr) { + #ifdef MEM_DEMO + uart_send_string("kfree ptr = "); + uart_send_u64(ptr); + uart_send_string("\r\n"); + #endif + if(ptr == NULL) return; uint32_t flag = interrupt_disable_save(); struct frame_entry *ent = get_entry_from_addr(ptr); // We does not handle the address freed is not valid @@ -195,10 +209,14 @@ void kfree(void *ptr) { } ent->dyn_count += 1; if(ent->dyn_count == (1 << (PAGE_SIZE_ORDER - ord))) { - ds_list_remove(&(ent->head)); - free_chunk(ent); - page_free((uint64_t)ptr & (~((1LL << PAGE_SIZE_ORDER) - 1))); - goto _r; + if(ent->used_cnt < MIN_FREE_PAGE_CNT) { + ent->used_cnt += 1; + } else { + ds_list_remove(&(ent->head)); + free_chunk(ent); + page_free((uint64_t)ptr & (~((1LL << PAGE_SIZE_ORDER) - 1))); + goto _r; + } } // need to add back the frame entry to kmem_pool struct kmem_node *node = simple_malloc(sizeof(struct kmem_node)); @@ -224,4 +242,15 @@ void set_init_mem_region(char *name, char *prop_name, char *data) { frame_init(sz); } } +} +void *cmalloc(uint32_t size) { + void *ret = kmalloc(size); + for(uint32_t k = 0; k < (size >> 3); k ++) { + *((uint64_t*)(ret) + k) = 0; + } + uint32_t tmp = ((size >> 3) << 3); + for(int i = tmp; i < size; i ++) { + *(char *)(ret + i) = 0; + } + return ret; } \ No newline at end of file diff --git a/src/kernel/mem/page.c b/src/kernel/mem/page.c index 453b2103c..7ce24c8c3 100644 --- a/src/kernel/mem/page.c +++ b/src/kernel/mem/page.c @@ -5,11 +5,12 @@ #include "utils.h" #include "peripherals/mini_uart.h" #include "dtb/dtb.h" +#include "mmu/mmu.h" -#define MEM_DEMO // #define ENTRY_NUM (PAGE_END - PAGE_BEGIN) / PAGE_SIZE +// #define MEM_DEMO 1 // struct frame_entry entry[ENTRY_NUM]; struct ds_list_head frame_list[PAGE_MAX_ORDER + 1]; @@ -36,7 +37,7 @@ uint64_t order_to_size(uint8_t order) { } static uint32_t addr2idx(uint64_t addr, uint64_t base) { - return (addr - base) >> PAGE_SIZE_ORDER; + return ((addr - base) >> PAGE_SIZE_ORDER); } static uint64_t idx2addr(uint32_t idx, uint64_t base) { @@ -45,8 +46,11 @@ static uint64_t idx2addr(uint32_t idx, uint64_t base) { struct frame_entry* get_entry_from_addr(void *ptr) { uint64_t addr = (uint64_t)ptr; + + for(struct ds_list_head *head = mem_list.next; head != &mem_list; head = head->next) { struct mem_region *region = container_of(head, struct mem_region, head); + if(addr >= region->begin_addr && addr <= region->begin_addr + region->size) { uint64_t idx = addr2idx(addr, region->begin_addr); return &(region->entries[idx]); @@ -59,17 +63,21 @@ void init_mem_region(struct mem_region* ptr, uint64_t begin, uint64_t end) { uint8_t ord = 0; while(ptr->size >> ord) { ord += 1; - if(ord > PAGE_MAX_ORDER + PAGE_SIZE_ORDER)break; + if(ord > (PAGE_MAX_ORDER + PAGE_SIZE_ORDER))break; } ord -= 1; + if((begin & ((1 << ord) - 1)) || (end & ((1 << ord) - 1))) { + ord -= 1; + } + ptr->max_ord = ord - PAGE_SIZE_ORDER; } void frame_init(uint64_t full_sz) { struct mem_region *new_region = simple_malloc(sizeof(struct mem_region)); - init_mem_region(new_region, 0x0, full_sz); + init_mem_region(new_region, 0x0 + KERNEL_SPACE_OFFSET, full_sz + KERNEL_SPACE_OFFSET); ds_list_head_init(&(new_region->head)); - ds_list_addnext(&mem_list, &(new_region->head)); + ds_list_addprev(&mem_list, &(new_region->head)); for(struct ds_list_head *tmp = reserve_list.next; tmp != &reserve_list; tmp = tmp->next) { struct reserve_node *node = container_of(tmp, struct reserve_node, head); for(struct ds_list_head *region = mem_list.next; region != &mem_list; region = region->next) { @@ -89,7 +97,8 @@ void frame_init(uint64_t full_sz) { struct mem_region *new_reg = simple_malloc(sizeof(struct mem_region)); init_mem_region(new_reg, node->e, end); ds_list_head_init(&(new_reg->head)); - ds_list_addnext(region, &(new_reg->head)); + ds_list_addprev(region, &(new_reg->head)); + // ds_list_addnext(region, &(new_reg->head)); } init_mem_region(old_region, start, node->s); if(node->s - start < PAGE_SIZE) { @@ -135,6 +144,8 @@ void frame_init(uint64_t full_sz) { ds_list_head_init(&(region->entries[i].head)); region->entries[i].flag = region->max_ord; region->entries[i].order = region->max_ord; + region->entries[i].used_cnt = 0; + // ds_list_addprev(&frame_list[region->max_ord], &(region->entries[i].head)); ds_list_addnext(&frame_list[region->max_ord], &(region->entries[i].head)); } } @@ -149,9 +160,9 @@ uint8_t page_size_to_order(uint64_t sz) { } } if((sz & ((1 << i) - 1)) == 0) { - return (i >> PAGE_SIZE_ORDER); + return (i - PAGE_SIZE_ORDER); } - return (i + 1) >> PAGE_SIZE_ORDER; + return (i + 1) - PAGE_SIZE_ORDER; } void *_split_page(uint8_t cur_order, uint8_t target_order) { @@ -200,8 +211,8 @@ void *_split_page(uint8_t cur_order, uint8_t target_order) { // push entries into list ds_list_head_init(&(region->entries[right_idx].head)); ds_list_head_init(&(region->entries[ent->idx].head)); - ds_list_addnext(&frame_list[cur_order - 1], &(region->entries[ent->idx].head)); - ds_list_addnext(&frame_list[cur_order - 1], &(region->entries[right_idx].head)); + ds_list_addprev(&frame_list[cur_order - 1], &(region->entries[ent->idx].head)); + ds_list_addprev(&frame_list[cur_order - 1], &(region->entries[right_idx].head)); return _split_page(cur_order - 1, target_order); } @@ -213,7 +224,8 @@ void *_find_page(uint8_t order) { struct frame_entry *ent = container_of(head, struct frame_entry, head); ent->flag = PAGE_ALLOCATED; ds_list_remove(frame_list[order].next); - uart_send_string("Successfully find page\r\n"); + // uart_send_u64(ent->idx); + // uart_send_u64(ent->mem_region->begin_addr); return (void*)idx2addr(ent->idx, ent->mem_region->begin_addr); } @@ -234,27 +246,21 @@ void *_find_page(uint8_t order) { void *page_alloc(uint64_t size) { int order = page_size_to_order(size); - uart_send_dec(order); - uart_send_string("\r\n"); if(order > PAGE_MAX_ORDER) { return NULL; } void *ptr = _find_page(order); - uart_send_string("Allocated page: "); - uart_send_u64((uint64_t)ptr); - uart_send_string("\r\n"); return ptr; } void _merge_page(void *addr, uint8_t cur_order, struct mem_region *region) { - // if(cur_order >= PAGE_MAX_ORDER) { - // return; - // } uint32_t idx = addr2idx((uint64_t)addr, region->begin_addr); uint64_t ano_addr = (uint64_t)addr ^ (1LL << (cur_order + PAGE_SIZE_ORDER)); uint32_t ano_idx = addr2idx((uint64_t)ano_addr, region->begin_addr); + if(cur_order < region->max_ord && region->entries[ano_idx].flag == cur_order) { #ifdef MEM_DEMO + uart_switch_func(UART_DEFAULT); uart_send_string("Merge Page addr, addr, size "); uart_send_u64((uint64_t)addr); uart_send_string(", "); @@ -262,6 +268,7 @@ void _merge_page(void *addr, uint8_t cur_order, struct mem_region *region) { uart_send_string(", "); uart_send_u64((1LL << (cur_order + PAGE_SIZE_ORDER))); uart_send_string("\r\n"); + uart_switch_func(UART_ASYNC); #endif ds_list_remove(&(region->entries[ano_idx].head)); // happen when addr is left @@ -276,11 +283,12 @@ void _merge_page(void *addr, uint8_t cur_order, struct mem_region *region) { region->entries[idx].flag = cur_order; region->entries[idx].order = cur_order; ds_list_head_init(&(region->entries[idx].head)); - ds_list_addnext(&frame_list[cur_order], &(region->entries[idx].head)); + ds_list_addprev(&frame_list[cur_order], &(region->entries[idx].head)); } } void page_free(void *addr) { + struct mem_region *region; for(struct ds_list_head *head = mem_list.next; head != &(mem_list); head = head->next) { region = container_of(head, struct mem_region, head); @@ -289,6 +297,7 @@ void page_free(void *addr) { } } uint32_t idx = addr2idx((uint64_t)addr, region->begin_addr); + _merge_page(addr, region->entries[idx].order, region); } void memory_reserve(uint64_t start, uint64_t end) { diff --git a/src/kernel/mini_uart.c b/src/kernel/mini_uart.c index 4bca9a90e..87f2ff2f0 100644 --- a/src/kernel/mini_uart.c +++ b/src/kernel/mini_uart.c @@ -5,6 +5,9 @@ #include "interrupt.h" #include "mem/mem.h" #include "event.h" +#include "power.h" +#include "waitqueue.h" +#include "fs/vfs.h" #define QUEUE_FULL 1 #define QUEUE_EMPTY 2 @@ -14,12 +17,15 @@ static char hex_char[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; static int uart_func; -static char rx_copy_buf[1024]; +static char rx_copy_buf[4096]; struct k_event uart_recv_event; + extern int demo_state; +struct waitqueue_t uart_rx_wait_queue; + struct Uart_MSG_Queue* Uart_MSG_Queue_init() { // init Uart MSG Queue struct Uart_MSG_Queue *ret = (struct Uart_MSG_Queue*)simple_malloc(sizeof(struct Uart_MSG_Queue)); @@ -38,6 +44,30 @@ void disable_transmit_interrupt() { write_reg_32(AUX_MU_IER_REG, 1); } +void _putchar(char c) { + uint16_t val = 0; + while(1) { + if(read_reg_32(AUX_MU_LSR_REG) & 0x20) { + break; + } + val += 1; + if(val > 1000) { + reset(100); + } + } + write_reg_32(AUX_MU_IO_REG, c); +} + +char _getchar() { + while(1) { + if(read_reg_32(AUX_MU_LSR_REG) & 0x01) { + break; + } + } + return (read_reg_32(AUX_MU_IO_REG) & 0xff); +} + + unsigned int uart_pop(struct Uart_MSG_Queue *que, unsigned int *res) { @@ -76,41 +106,42 @@ static struct Uart_MSG_Queue *txbuf; // static uint16_t* uart_func_sw; -void _putchar(char c) { - while(1) { - if(read_reg_32(AUX_MU_LSR_REG) & 0x20) { - break; - } - } - write_reg_32(AUX_MU_IO_REG, c); -} - -char _getchar() { - while(1) { - if(read_reg_32(AUX_MU_LSR_REG) & 0x01) { - break; - } - } - return (read_reg_32(AUX_MU_IO_REG) & 0xff); -} +static uint16_t ena; +static uint16_t dis; // not very good implement // should implement the same way as interrupt_disable_save void enable_aux_interrupt() { + ena += 1; + // if(ena > 20000) { + // uart_switch_func(UART_DEFAULT); + // uart_send_string("Enabling\r\n"); + // uart_switch_func(UART_ASYNC); + // } write_reg_32(ENABLE_IRQ1, (1 << 29)); } void disable_aux_interrupt() { + dis += 1; + // if(dis > 20000) { + // uart_switch_func(UART_DEFAULT); + // uart_send_string("Disabling\r\n"); + // uart_switch_func(UART_ASYNC); + // } write_reg_32(DISABLE_IRQ1, (1 << 29)); } void uart_rx_to_buf(void* ptr, uint32_t sz) { // TODO reconstruct demo codes - if(demo_state) { - uart_send(*(char*)ptr); - } + // if(demo_state) { + // uart_send(*(char*)ptr); + // } for(int i = 0; i < sz; i ++) { + disable_aux_interrupt(); uart_push(rxbuf, *(char*)ptr); + enable_aux_interrupt(); } + simple_free(ptr); + wakeup(&uart_rx_wait_queue); } void uart_init() { @@ -118,6 +149,7 @@ void uart_init() { // uart_func_sw = (uint16_t*)simple_malloc(sizeof(uart_func_sw)); // set the selected function for pin14,15 to mini uart + disable_aux_interrupt(); selector = read_reg_32(GPFSEL1); selector &= ~(7 << 12); @@ -153,6 +185,7 @@ void uart_init() { txbuf = Uart_MSG_Queue_init(); uart_func = UART_ASYNC; k_event_init(&uart_recv_event, &uart_rx_to_buf); + waitqueue_init(&uart_rx_wait_queue); // uart_func = UART_DEFAULT; } @@ -186,6 +219,34 @@ char async_uart_recv(void) { } return (val & 0xff); } +uint64_t async_uart_rx_buf(char *buf, uint64_t sz) { + int err; + unsigned int val; + int i; + // uart_send_dec(sz); + // uart_send_string("\r\n"); + for(i = 0; i < sz; i ++) { + disable_aux_interrupt(); + int err = uart_pop(rxbuf, &val); + enable_aux_interrupt(); + if(err == QUEUE_EMPTY) { + if(i == 0) { + wait(&uart_rx_wait_queue); + i-= 1; + continue; + } else { + goto _r; + } + } else { + buf[i] = (val & 0xff); + } + } +_r:; + // uart_send_string("ffff "); + // uart_send_u64(i); + // uart_send_string("\r\n"); + return i; +} void async_uart_send(char c) { // first disable aux interrupt so that txbuf won't race @@ -197,6 +258,7 @@ void async_uart_send(char c) { void async_uart_send_string(const char *buf) { // first disable aux interrupt so that txbuf won't race + // uart_send_string("send string for user\r\n"); disable_aux_interrupt(); for(const char *ch = buf; *ch != '\0'; ch ++) { uart_push(txbuf, *ch); @@ -218,7 +280,7 @@ void uart_send_u32(unsigned int u32) { } void uart_send_string(const char *c) { - if(uart_func == UART_ASYNC) { + if(0 && uart_func == UART_ASYNC) { async_uart_send_string(c); } else { for(const char *ch = c; *ch != '\0'; ch ++) { @@ -226,17 +288,30 @@ void uart_send_string(const char *c) { } } } -void uart_send_n(const char *c, unsigned long long n) { - for(int i = 0; i < n; i ++) { +uint64_t uart_send_n(const char *c, unsigned long long n) { + uint64_t i; + // uart_switch_func(UART_DEFAULT); + // uart_send_dec(ena); + // uart_send_string(" "); + // uart_send_dec(dis); + // uart_send_string("\r\n"); + // uart_switch_func(UART_ASYNC); + for(i = 0; i < n; i ++) { if(c[i] == '\n') { uart_send('\r'); } uart_send(c[i]); } + // uart_send_string("after send\r\n"); + return i; } void uart_send_dec(unsigned long dec) { char buf[20]; int idx = 0; + uint8_t s = 0; + if(dec == 0) { + s = 1; + } while(dec) { buf[idx ++] = (dec % 10) + '0'; dec /= 10; @@ -244,30 +319,122 @@ void uart_send_dec(unsigned long dec) { for(int i = idx - 1; i >= 0; i --) { uart_send(buf[i]); } + if(s) { + uart_send('0'); + } } void uart_int_trans_handler() { unsigned int val; int err; + disable_aux_interrupt(); while(read_reg_32(AUX_MU_LSR_REG) & 0x20) { err = uart_pop(txbuf, &val); if(err == 0) { - write_reg_32(AUX_MU_IO_REG, val % 0xff); + write_reg_32(AUX_MU_IO_REG, (val & 0xff)); } else { + // uart_switch_func(UART_DEFAULT); + // uart_send_string("After send\r\n"); + // uart_switch_func(UART_ASYNC); + uint64_t elr; + asm volatile ( + "mrs %[elr], elr_el1\n":[elr]"=r"(elr) + ); + // uart_send_u64(elr); disable_transmit_interrupt(); + // uart_switch_func(UART_DEFAULT); + // uart_send_string("disalbe transmit interrupt\r\n"); + // uart_switch_func(UART_ASYNC); break; } } + enable_aux_interrupt(); } void uart_int_recv_handler() { int idx = 0; unsigned int val; + char *ptr = (char*)simple_malloc(64); while(read_reg_32(AUX_MU_LSR_REG) & 0x01) { val = read_reg_32(AUX_MU_IO_REG); - rx_copy_buf[idx ++] = (val & 0xff); + // uart_push(rxbuf, (val & 0xff)); + // wakeup(&uart_rx_wait_queue); + ptr[idx ++] = (val & 0xff); } - k_event_submit(&uart_recv_event, rx_copy_buf, idx, 200); + + + k_event_submit(&uart_recv_event, ptr, idx, 200); } void uart_switch_func(unsigned int func) { uart_func = func; +} + +struct file uart_file; +int uart_init_fs(struct filesystem* fs) { + fs->root = (struct vnode *)kmalloc(sizeof(struct vnode)); + return 0; +} + +struct file_operations uart_fops = { + .close = &fops_not_support, + .open = &uart_file_open, + .lseek64 = &fops_not_support, + .stat = &fops_not_support, + .write = &uart_file_write, + .read = &uart_file_read, + .ioctl = &fops_not_support +}; + +struct vnode_operations uart_vops = { + .create = &vops_not_support, + .lookup = &vops_not_support, + .mkdir = &vops_not_support +}; + +int uart_setup_mount(struct filesystem* fs, struct mount *mnt) { + ds_list_head_init(&(fs->root->ch_list)); + ds_list_head_init(&(fs->root->v_head)); + uart_file.f_ops = &uart_fops; + uart_file.f_pos = 0; + uart_file.flags = 0777; + uart_file.vnode = fs->root; + fs->root->flag = VFS_FILE; + fs->root->mount = mnt; + mnt->root = fs->root; + mnt->fs = fs; +} + + +struct filesystem uart_fs = { + .name = "uartfs", + .init_fs = &uart_init_fs, + .root = NULL, + .setup_mount = &uart_setup_mount +}; + +int uart_file_write(struct file *f, const void *buf, long len) { + int n = uart_send_n(buf, len); + return n; +} + +int uart_file_read(struct file *f, const void *buf, long len) { + int n = async_uart_rx_buf(buf, len); + return n; +} + +int uart_file_open(struct vnode *f, struct file **target) { + *target = &uart_file; + return 0; +} + +int uart_file_close(struct file *f) { + return 0; +} + +// int uart_v_lookup(struct vnode *dir_node, ) + +void setup_dev_uart() { + register_filesystem(&uart_fs); + vfs_mkdir("/dev/uart"); + vfs_mount("/dev/uart", "uartfs"); + return; } \ No newline at end of file diff --git a/src/kernel/mmu.S b/src/kernel/mmu.S new file mode 100644 index 000000000..f202b1e3f --- /dev/null +++ b/src/kernel/mmu.S @@ -0,0 +1,68 @@ +#include "mmu/mmu-def.h" + +.section ".text.mmu" +.global enable_kernel_mmu +enable_kernel_mmu: + // setup kernel virtaul memory + mov x4, x0 + ldr x0, =TCR_CONFIG_DEFAULT + msr tcr_el1, x0 + + ldr x0, =(\ + (MAIR_DEVICE_nGnRnE << (MAIR_IDX_DEVICE_nGnRnE * 8)) | \ + (MAIR_NORMAL_NOCACHE << (MAIR_IDX_NORMAL_NOCACHE * 8)) \ + ) + msr mair_el1, x0 + + mov x0, 0x1000 // kernel PGD + mov x1, 0x2000 // kernel PUD + mov x5, 0x3000 // kernel PMD + + // set PGD entry + ldr x2, =BOOT_PGD_ATTR + orr x2, x1, x2 + str x2, [x0] + + + ldr x2, =BOOT_PUD_TABLE + orr x3, x5, x2 + str x3, [x1] + ldr x2, =BOOT_PMD_ATTR_NORMAL + + mov x6, 0 + mov x7, 0 + .setup_normal_kernel_PMD: + orr x3, x6, x2 + str x3, [x5], 8 + add x6, x6, 0x200000 + add x7, x7, 1 + cmp x7, #480 + blt .setup_normal_kernel_PMD + + ldr x2, =BOOT_PMD_ATTR_DEVICE + + .setup_device_kernel_PMD: + orr x3, x6, x2 + str x3, [x5], 8 + add x6, x6, 0x200000 + add x7, x7, 1 + cmp x7, 512 + blt .setup_device_kernel_PMD + + // ldr x2, =BOOT_PUD_ATTR_NORMAL + // mov x3, 0x00000000 + // orr x3, x2, x3 + // str x3, [x1] + + ldr x2, =BOOT_PUD_ATTR_DEVICE + mov x3, 0x40000000 + orr x3, x2, x3 + str x3, [x1, 8] + + msr ttbr0_el1, x0 + msr ttbr1_el1, x0 + + mrs x2, sctlr_el1 + orr x2, x2, 1 + msr sctlr_el1, x2 + br x4 \ No newline at end of file diff --git a/src/kernel/mmu.c b/src/kernel/mmu.c new file mode 100644 index 000000000..2654496bb --- /dev/null +++ b/src/kernel/mmu.c @@ -0,0 +1,54 @@ +#include "mmu/mmu.h" +#include "type.h" +#include "mem/mem.h" + + +uint64_t* find_pte(void *pgd, unsigned long long va, uint8_t create) { + pgd = kernel_pa2va(pgd); + + uint64_t *PGD = pgd; + + uint64_t pud_idx = (va >> 39) & 0b111111111; + if((PGD[pud_idx] & 1) == 0) { + if(!create) return 0; + uint64_t new_PUD = (uint64_t)cmalloc((1 << 12)); + PGD[pud_idx] = (uint64_t)kernel_va2pa((new_PUD | PD_TABLE)); + } + uint64_t *PUD = (uint64_t*)kernel_pa2va((PGD[pud_idx] >> 12) << 12); + uint64_t pmd_idx = (va >> 30) & 0b111111111; + if((PUD[pmd_idx] & 1) == 0) { + if(!create) return 0; + uint64_t new_PMD = (uint64_t)cmalloc(1 << 12); + PUD[pmd_idx] = (uint64_t)kernel_va2pa(new_PMD | PD_TABLE); + } + uint64_t *PMD = (uint64_t*)kernel_pa2va((PUD[pmd_idx] >> 12) << 12); + uint64_t pte_idx = (va >> 21) & 0b111111111; + if((PMD[pte_idx] & 1) == 0) { + if(!create) return 0; + uint64_t new_PTE = (uint64_t)cmalloc(1 << 12); + PMD[pte_idx] = (uint64_t)kernel_va2pa(new_PTE | PD_TABLE); + } + + uint64_t *PTE = (uint64_t*)kernel_pa2va((PMD[pte_idx] >> 12) << 12); + uint64_t pe_idx = (va >> 12) & 0b111111111; + + return &PTE[pe_idx]; +} + +uint64_t mappages(void *pgd, uint64_t va, uint64_t size, uint64_t pa) { + + for(uint64_t i = 0; i < size; i += (1 << 12)) { + uint64_t *pte_entry = find_pte(pgd, va + i, 1); + + uint64_t page_attr = PROC_PTE_ATTR_NORMAL; + page_attr |= PD_USERACCESS; + *pte_entry = ((pa + i) | page_attr); + } +} +int mmu_map_peripheral(uint64_t ttbr0_el1) { + for(uint64_t va = 0x30000000; va < 0x40010000; va += (1 << 12)) { + uint64_t *PTE = find_pte(ttbr0_el1, va, 1); + uint64_t newPTE = (va | PROC_PTE_ATTR_DEVICE | PD_USERACCESS); + *PTE = newPTE; + } +} \ No newline at end of file diff --git a/src/kernel/process.c b/src/kernel/process.c new file mode 100755 index 000000000..3af12a726 --- /dev/null +++ b/src/kernel/process.c @@ -0,0 +1,417 @@ +#include "process.h" +#include "ds/list.h" +#include "mem/mem.h" +#include "thread.h" +#include "utils.h" +#include "peripherals/mini_uart.h" +#include "interrupt.h" +#include "type.h" +#include "mmu/mmu.h" +#include "fs/vfs.h" + +struct Process_t init_process; +struct ds_list_head process_list; +extern long long _bss_end; +extern void load_all_eret(); +extern struct filesystem tmpfs; +extern struct mount *rootfs; + +extern void thread_exit(); +extern void thread_check_zombie(void *); + +extern struct file uart_file; +static uint32_t pid_counter = 0; + +struct Thread_t * process_thread_create(void * func, void *arg, struct Process_t* proc, uint8_t kernel) { + struct Thread_t *th = thread_create(func, arg); + if(kernel == 1) { + } else if(kernel == 0) { + mappages(proc->ttbr0_el1, 0xffffffffb000ULL, (1 << 14), kernel_va2pa(th->sp - DEFAULT_STACK_SZ)); + } else if (kernel == 2) { + // uart_send_string("Mapping Signal\r\n"); + mappages(proc->ttbr0_el1, 0xffffffff7000ULL, (1 << 14), kernel_va2pa(th->sp - DEFAULT_STACK_SZ)); + } + // mappages(proc->ttbr0_el1, th->sp, ) + ds_list_addprev(&(proc->th_list), &(th->th_head)); + // th->sp = 0xfffffffff000ULL; + // uart_send_string("In process thread create \r\n"); + // uart_send_u64(proc->ttbr0_el1); + // uart_send_string("\r\n"); + th->proc = proc; + th->saved_reg.ttbr0_el1 = proc->ttbr0_el1; + return th; +} + +void process_control_init() { + ds_list_head_init(&(init_process.pl_head)); + ds_list_head_init(&(init_process.th_list)); + ds_list_head_init(&process_list); + // create a init process, although in kernel space is weird; + // the init process contain a idle thread that clean zombie thread and process + init_process.ttbr0_el1 = 0x1000; + struct Thread_t *th = process_thread_create(&thread_check_zombie, NULL, &init_process, 1); + init_process.parent = NULL; + init_process.pid = pid_counter ++; + init_process.share_section = (void *)0x80000; + init_process.share_section_sz = _bss_end; + strncpy(init_process.name, "initd", 5); + init_process.status = P_INIT; + for(int i = 0; i < SIGNUMS; i ++) { + init_process.signal[i] = 0; + } + + for(int i = 0; i < P_FD_MAX; i ++) { + init_process.files[i] = NULL; + } + init_process.cur_vnode = tmpfs.root; + init_process.mnt = rootfs; + ds_list_head_init(&(init_process.sig_list)); + ds_list_addnext(&(init_process.th_list), &(th->th_head)); + ds_list_addprev(&(process_list), &(init_process.pl_head)); + th->proc = &(init_process); +} +void _run_user_thread(void *prog, void *ret, void *stackbase) { + void *base = (uint64_t)stackbase - 32 * 360; + // disable_interrupt(); + + // uart_switch_func(UART_DEFAULT); + // uart_send_string("in _run user thread\r\n"); + // uart_switch_func(UART_ASYNC); + struct Thread_t *cur = thread_get_current_instance(); + uint64_t ttbr0_el1 = cur->saved_reg.ttbr0_el1; + asm volatile( + "mov x0, #0\n" + "mov x1, #0\n" + "mov x2, #0\n" + "mov x3, #0\n" + "mov x4, #0\n" + "mov x5, #0\n" + "mov x6, #0\t\n" + "mov x7, #0\t\n" + "mov x8, #0\t\n" + "mov x9, #0\t\n" + "mov x10, #0\t\n" + "mov x11, #0\t\n" + "mov x12, #0\t\n" + "mov x13, #0\t\n" + "mov x14, #0\t\n" + "mov x15, #0\t\n" + "mov x16, #0\t\n" + "mov x17, #0\t\n" + "mov x18, #0\t\n" + "mov x19, #0\t\n" + "mov x20, #0\t\n" + "mov x21, #0\t\n" + "mov x22, #0\t\n" + "mov x23, #0\t\n" + "mov x24, #0\t\n" + "mov x25, #0\t\n" + "mov x26, #0\t\n" + "mov x27, #0\t\n" + "mov x28, #0\t\n" + ); + asm volatile( + "dsb ish\n" + "msr ttbr0_el1, %[ttbr0]\n" + "tlbi vmalle1is\n" + "dsb ish\n" + "isb\n" + "mov sp, %[sp]\n" + "mov lr, %[ret]\n" + "msr elr_el1, %[elr]\n" + "msr sp_el0, %[base_addr]\n" + "mov x0, 0x0\n" + "msr spsr_el1, x0\n" + "eret"::[ret]"r"(ret), [elr]"r"(prog), [base_addr]"r"(base), [ttbr0]"r"(ttbr0_el1), [sp]"r"(stackbase) + ); +} +void run_user_thread() { + struct Thread_t *th = thread_get_current_instance(); + + _run_user_thread(th->entry, &thread_exit, 0xfffffffff000); +} + + + + +uint64_t process_exec(const char* name, char *const argv[], uint8_t kernel) { + + char *content; + uint32_t filesize; + + struct file *f; + int err = vfs_open(name, 0, &f); + if(err) { + return err; + } + struct fstat stat; + err = vfs_stat(f, &stat); + uint64_t flag = interrupt_disable_save(); + struct Thread_t *th = thread_get_current_instance(); + struct Process_t* cur_proc = th->proc; + struct Process_t* new_proc = (struct Process_t*)kmalloc(sizeof(struct Process_t)); + + filesize = stat.filesize; + + // setup fs info + new_proc->cur_vnode = cur_proc->cur_vnode; + new_proc->mnt = cur_proc->mnt; + + + + void *share_section = (void *)kmalloc((1 << 13) + filesize); + new_proc->share_section_sz = (1 << 13) + filesize; + new_proc->share_section = share_section; + + new_proc->parent = cur_proc->parent; + new_proc->pid = pid_counter ++; + + + for(int i = 0; i < P_FD_MAX; i ++) { + if(i < 3) { + new_proc->files[i] = &uart_file; + } else { + new_proc->files[i] = NULL; + } + } + + // copy code, data and bss + int n = 0; + while(n = vfs_read(f, new_proc->share_section + n, filesize)) { + + continue; + } + if(kernel == 0) { + new_proc->ttbr0_el1 = kernel_va2pa((void *)cmalloc((1 << 12))); + uint64_t addr = kernel_va2pa(new_proc->share_section); + mappages(new_proc->ttbr0_el1, 0x0, new_proc->share_section_sz, addr); + } else { + new_proc->ttbr0_el1 = 0x1000; + } + + ds_list_head_init(&(new_proc->sig_list)); + + for(int i = 0; i < SIGNUMS; i ++) { + new_proc->signal[i] = 0; + } + + uint32_t namelen = strlen(name); + memcpy(new_proc->name, name, namelen); + new_proc->name[namelen] = '\0'; + // create a main thread for process + // currently set argv NULL + ds_list_head_init(&(new_proc->th_list)); + struct Thread_t *new_th = process_thread_create((thread_func)0, NULL, new_proc, kernel); + new_th->proc= new_proc; + + new_th->entry = 0; + + + new_th->saved_reg.lr = run_user_thread; + + new_proc->exit_code = 0; + new_proc->handling_signal = 0; + + if(pid_counter > PID_MAX) { + pid_counter = 1; + } + new_proc->status = P_INIT; + + // freeing all the thread belongs to original process + struct ds_list_head *front = ds_list_front(&(cur_proc->th_list)); + struct Thread_t *th_en; + while(front != &(cur_proc->th_list)) { + th_en = container_of(front, struct Thread_t, th_head); + th_en->status = TH_ZOMBIE; + front = ds_list_front(front); + } + + // add process to list + ds_list_head_init(&(new_proc->pl_head)); + ds_list_addprev(&(process_list), &(new_proc->pl_head)); + + interrupt_enable_restore(flag); + while(1) { + enable_interrupt(); + asm volatile("nop"); + } +} +void process_exit(int status) { + uint64_t flag = interrupt_disable_save(); + struct Process_t *proc = process_get_current(); + struct ds_list_head *front = ds_list_front(&(proc->th_list)); + while(front != &(proc->th_list)) { + struct Thread_t *th = container_of(front, struct Thread_t, th_head); + th->status = TH_ZOMBIE; + front = ds_list_front(front); + } + // enable_interrupt(); + // while(1) { + // asm volatile("nop"); + // } + schedule(0); + interrupt_enable_restore(flag); +} +void load_all_eret_log() { + uart_send_string("In load all eret\r\n"); +} + +uint64_t process_fork(struct Trapframe_t *frame) { + uint64_t flag = interrupt_disable_save(); + struct Thread_t *th = thread_get_current_instance(); + struct Process_t* cur_proc = th->proc; + struct Process_t* new_proc = (struct Process_t*)kmalloc(sizeof(struct Process_t)); + new_proc->share_section = (char *)kmalloc(cur_proc->share_section_sz); + new_proc->share_section_sz = cur_proc->share_section_sz; + memcpy(new_proc->share_section, cur_proc->share_section, cur_proc->share_section_sz); + + + + // setup fs info + new_proc->cur_vnode = cur_proc->cur_vnode; + new_proc->mnt = cur_proc->mnt; + + for(int i = 0; i < P_FD_MAX; i ++) { + new_proc->files[i] = cur_proc->files[i]; + } + + new_proc->ttbr0_el1 = kernel_va2pa((void *)cmalloc((1 << 12))); + uint64_t addr = kernel_va2pa(new_proc->share_section); + mappages(new_proc->ttbr0_el1, 0x0, cur_proc->share_section_sz, addr); + + new_proc->parent = cur_proc; + + // copy code, data and bss + uint32_t namelen = strlen(cur_proc->name); + memcpy(new_proc->name, cur_proc->name, namelen); + new_proc->name[namelen] = '\0'; + + ds_list_head_init(&(new_proc->th_list)); + + struct Thread_t *new_th = process_thread_create((thread_func)0, NULL, new_proc, 0); + new_proc->parent = cur_proc; + new_proc->exit_code = 0; + new_proc->pid = pid_counter ++; + if(pid_counter > PID_MAX) { + pid_counter = 1; + } + + new_proc->status = P_INIT; + + + ds_list_head_init(&(new_proc->pl_head)); + ds_list_addprev(&(process_list), &(new_proc->pl_head)); + + + + // copy signal handler; + ds_list_head_init(&(new_proc->sig_list)); + struct ds_list_head *front = ds_list_front(&(cur_proc->sig_list)); + if(front != NULL) { + while(front != &(cur_proc->sig_list)) { + struct Signal_t *sig = container_of(front, struct Signal_t, sig_head); + struct Signal_t *new_sig = (struct Signal_t *)kmalloc(sizeof(struct Signal_t)); + new_sig->sig_num = sig->sig_num; + new_sig->handler = sig->handler; + new_sig->th = NULL; + ds_list_head_init(&(new_sig->sig_head)); + ds_list_addprev(&(new_proc->sig_list), &(new_sig->sig_head)); + front = ds_list_front(front); + } + } + + for(int i = 0; i < SIGNUMS; i ++) { + new_proc->signal[i] = 0; + } + + + // we need to set the reg + // copy stack + memcpy(new_th->sp - th->stack_sz, th->sp - th->stack_sz, th->stack_sz); + uint64_t sp_offset = (uint64_t)(0xfffffffff000ULL) - (uint64_t)frame->sp; + new_th->saved_reg.sp = (uint64_t)(0xfffffffff000ULL) - (uint64_t)sp_offset; + + uint64_t tmp = frame->elr_el1; + uint64_t tmp_sp = frame->sp; + frame->elr_el1 = frame->elr_el1; + + frame->sp = new_th->saved_reg.sp; + new_th->saved_reg.sp = (0xfffffffff000ULL) - 32 * 10; + uint64_t tmp_x0 = frame->x0; + frame->x0 = 0; + memcpy((void *)new_th->sp - 32 * 10, frame, 32 * 9); + frame->elr_el1 = tmp; + frame->sp = tmp_sp; + frame->x0 = tmp_x0; + + + new_proc->handling_signal = 0; + new_th->saved_reg.lr = &load_all_eret; + + mmu_map_peripheral(new_proc->ttbr0_el1); + + interrupt_enable_restore(flag); + + return new_proc->pid; +} + +struct Process_t *process_get_current() { + struct Thread_t *th = thread_get_current_instance(); + + return th->proc; +} + +struct Process_t *create_process_instance() { + uint64_t flag = interrupt_disable_save(); + struct Process_t *ret = (struct Process_t*)kmalloc(sizeof(struct Process_t)); + ret->exit_code = 0; + ret->pid = pid_counter ++; + ds_list_head_init(&(ret->pl_head)); + ds_list_head_init(&(ret->sig_list)); + ret->cur_vnode = tmpfs.root; + ret->mnt = rootfs; + for(int i = 0; i < SIGNUMS; i ++) { + ret->signal[i] = 0; + } + for(int i = 0; i < P_FD_MAX; i ++) { + ret->files[i] = NULL; + } + ds_list_addprev(&(process_list), &(ret->pl_head)); + ds_list_head_init(&(ret->th_list)); + interrupt_enable_restore(flag); + return ret; +} + +void process_free(struct Process_t *proc) { + struct ds_list_head *front = ds_list_front(&(proc->th_list)); + if(front == NULL) { + uint64_t flag = interrupt_disable_save(); + + ds_list_remove(&(proc->pl_head)); + proc->exit_code = 0; + + kfree(proc); + interrupt_enable_restore(flag); + } +} + +struct Process_t *get_process_from_pid(uint32_t pid) { + struct ds_list_head *front = ds_list_front(&process_list); + if(front == NULL) { + return NULL; + } + + uint64_t val = 0; + while(front != (&(process_list))) { + struct Process_t *proc = container_of(front, struct Process_t, pl_head); + + if(proc->pid == pid) { + return proc; + } + front = ds_list_front(front); + val += 1; + + } + + return NULL; +} \ No newline at end of file diff --git a/src/kernel/sd.c b/src/kernel/sd.c new file mode 100644 index 000000000..96b13b913 --- /dev/null +++ b/src/kernel/sd.c @@ -0,0 +1,244 @@ +#include "sd.h" +// mmio +#define KVA 0xffff000000000000 +#define MMIO_BASE (KVA + 0x3f000000) + +// SD card command +#define GO_IDLE_STATE 0 +#define SEND_OP_CMD 1 +#define ALL_SEND_CID 2 +#define SEND_RELATIVE_ADDR 3 +#define SELECT_CARD 7 +#define SEND_IF_COND 8 + #define VOLTAGE_CHECK_PATTERN 0x1aa +#define STOP_TRANSMISSION 12 +#define SET_BLOCKLEN 16 +#define READ_SINGLE_BLOCK 17 +#define WRITE_SINGLE_BLOCK 24 +#define SD_APP_OP_COND 41 + #define SDCARD_3_3V (1 << 21) + #define SDCARD_ISHCS (1 << 30) + #define SDCARD_READY (1 << 31) +#define APP_CMD 55 + +// gpio +#define GPIO_BASE (MMIO_BASE + 0x200000) +#define GPIO_GPFSEL4 (GPIO_BASE + 0x10) +#define GPIO_GPFSEL5 (GPIO_BASE + 0x14) +#define GPIO_GPPUD (GPIO_BASE + 0x94) +#define GPIO_GPPUDCLK1 (GPIO_BASE + 0x9c) + +// sdhost +#define SDHOST_BASE (MMIO_BASE + 0x202000) +#define SDHOST_CMD (SDHOST_BASE + 0) + #define SDHOST_READ 0x40 + #define SDHOST_WRITE 0x80 + #define SDHOST_LONG_RESPONSE 0x200 + #define SDHOST_NO_REPONSE 0x400 + #define SDHOST_BUSY 0x800 + #define SDHOST_NEW_CMD 0x8000 +#define SDHOST_ARG (SDHOST_BASE + 0x4) +#define SDHOST_TOUT (SDHOST_BASE + 0x8) + #define SDHOST_TOUT_DEFAULT 0xf00000 +#define SDHOST_CDIV (SDHOST_BASE + 0xc) + #define SDHOST_CDIV_MAXDIV 0x7ff + #define SDHOST_CDIV_DEFAULT 0x148 +#define SDHOST_RESP0 (SDHOST_BASE + 0x10) +#define SDHOST_RESP1 (SDHOST_BASE + 0x14) +#define SDHOST_RESP2 (SDHOST_BASE + 0x18) +#define SDHOST_RESP3 (SDHOST_BASE + 0x1c) +#define SDHOST_HSTS (SDHOST_BASE + 0x20) + #define SDHOST_HSTS_MASK (0x7f8) + #define SDHOST_HSTS_ERR_MASK (0xf8) + #define SDHOST_HSTS_DATA (1 << 0) +#define SDHOST_PWR (SDHOST_BASE + 0x30) +#define SDHOST_DBG (SDHOST_BASE + 0x34) + #define SDHOST_DBG_FSM_DATA 1 + #define SDHOST_DBG_FSM_MASK 0xf + #define SDHOST_DBG_MASK (0x1f << 14 | 0x1f << 9) + #define SDHOST_DBG_FIFO (0x4 << 14 | 0x4 << 9) +#define SDHOST_CFG (SDHOST_BASE + 0x38) + #define SDHOST_CFG_DATA_EN (1 << 4) + #define SDHOST_CFG_SLOW (1 << 3) + #define SDHOST_CFG_INTBUS (1 << 1) +#define SDHOST_SIZE (SDHOST_BASE + 0x3c) +#define SDHOST_DATA (SDHOST_BASE + 0x40) +#define SDHOST_CNT (SDHOST_BASE + 0x50) + +// helper +#define set(io_addr, val) \ + asm volatile("str %w1, [%0]" ::"r"(io_addr), "r"(val) : "memory"); + +#define get(io_addr, val) \ + asm volatile("ldr %w0, [%1]" : "=r"(val) : "r"(io_addr) : "memory"); + +static inline void delay(unsigned long tick) { + while (tick--) { + asm volatile("nop"); + } +} + +static int is_hcs; // high capcacity(SDHC) + +static void pin_setup() { + set(GPIO_GPFSEL4, 0x24000000); + set(GPIO_GPFSEL5, 0x924); + set(GPIO_GPPUD, 0); + delay(15000); + set(GPIO_GPPUDCLK1, 0xffffffff); + delay(15000); + set(GPIO_GPPUDCLK1, 0); +} + +static void sdhost_setup() { + unsigned int tmp; + set(SDHOST_PWR, 0); + set(SDHOST_CMD, 0); + set(SDHOST_ARG, 0); + set(SDHOST_TOUT, SDHOST_TOUT_DEFAULT); + set(SDHOST_CDIV, 0); + set(SDHOST_HSTS, SDHOST_HSTS_MASK); + set(SDHOST_CFG, 0); + set(SDHOST_CNT, 0); + set(SDHOST_SIZE, 0); + get(SDHOST_DBG, tmp); + tmp &= ~SDHOST_DBG_MASK; + tmp |= SDHOST_DBG_FIFO; + set(SDHOST_DBG, tmp); + delay(250000); + set(SDHOST_PWR, 1); + delay(250000); + set(SDHOST_CFG, SDHOST_CFG_SLOW | SDHOST_CFG_INTBUS | SDHOST_CFG_DATA_EN); + set(SDHOST_CDIV, SDHOST_CDIV_DEFAULT); +} + +static int wait_sd() { + int cnt = 1000000; + unsigned int cmd; + do { + if (cnt == 0) { + return -1; + } + get(SDHOST_CMD, cmd); + --cnt; + } while (cmd & SDHOST_NEW_CMD); + return 0; +} + +static int sd_cmd(unsigned cmd, unsigned int arg) { + set(SDHOST_ARG, arg); + set(SDHOST_CMD, cmd | SDHOST_NEW_CMD); + return wait_sd(); +} + +static int sdcard_setup() { + unsigned int tmp; + sd_cmd(GO_IDLE_STATE | SDHOST_NO_REPONSE, 0); + sd_cmd(SEND_IF_COND, VOLTAGE_CHECK_PATTERN); + get(SDHOST_RESP0, tmp); + if (tmp != VOLTAGE_CHECK_PATTERN) { + return -1; + } + while (1) { + if (sd_cmd(APP_CMD, 0) == -1) { + // MMC card or invalid card status + // currently not support + continue; + } + sd_cmd(SD_APP_OP_COND, SDCARD_3_3V | SDCARD_ISHCS); + get(SDHOST_RESP0, tmp); + if (tmp & SDCARD_READY) { + break; + } + delay(1000000); + } + + is_hcs = tmp & SDCARD_ISHCS; + sd_cmd(ALL_SEND_CID | SDHOST_LONG_RESPONSE, 0); + sd_cmd(SEND_RELATIVE_ADDR, 0); + get(SDHOST_RESP0, tmp); + sd_cmd(SELECT_CARD, tmp); + sd_cmd(SET_BLOCKLEN, 512); + return 0; +} + +static int wait_fifo() { + int cnt = 1000000; + unsigned int hsts; + do { + if (cnt == 0) { + return -1; + } + get(SDHOST_HSTS, hsts); + --cnt; + } while ((hsts & SDHOST_HSTS_DATA) == 0); + return 0; +} + +static void set_block(int size, int cnt) { + set(SDHOST_SIZE, size); + set(SDHOST_CNT, cnt); +} + +static void wait_finish() { + unsigned int dbg; + do { + get(SDHOST_DBG, dbg); + } while ((dbg & SDHOST_DBG_FSM_MASK) != SDHOST_HSTS_DATA); +} + +void readblock(int block_idx, void* buf) { + unsigned int* buf_u = (unsigned int*)buf; + int succ = 0; + if (!is_hcs) { + block_idx <<= 9; + } + do{ + set_block(512, 1); + sd_cmd(READ_SINGLE_BLOCK | SDHOST_READ, block_idx); + for (int i = 0; i < 128; ++i) { + wait_fifo(); + get(SDHOST_DATA, buf_u[i]); + } + unsigned int hsts; + get(SDHOST_HSTS, hsts); + if (hsts & SDHOST_HSTS_ERR_MASK) { + set(SDHOST_HSTS, SDHOST_HSTS_ERR_MASK); + sd_cmd(STOP_TRANSMISSION | SDHOST_BUSY, 0); + } else { + succ = 1; + } + } while(!succ); + wait_finish(); +} + +void writeblock(int block_idx, void* buf) { + unsigned int* buf_u = (unsigned int*)buf; + int succ = 0; + if (!is_hcs) { + block_idx <<= 9; + } + do{ + set_block(512, 1); + sd_cmd(WRITE_SINGLE_BLOCK | SDHOST_WRITE, block_idx); + for (int i = 0; i < 128; ++i) { + wait_fifo(); + set(SDHOST_DATA, buf_u[i]); + } + unsigned int hsts; + get(SDHOST_HSTS, hsts); + if (hsts & SDHOST_HSTS_ERR_MASK) { + set(SDHOST_HSTS, SDHOST_HSTS_ERR_MASK); + sd_cmd(STOP_TRANSMISSION | SDHOST_BUSY, 0); + } else { + succ = 1; + } + } while(!succ); + wait_finish(); +} + +void sd_init() { + pin_setup(); + sdhost_setup(); + sdcard_setup(); +} diff --git a/src/kernel/signal.S b/src/kernel/signal.S new file mode 100755 index 000000000..670861685 --- /dev/null +++ b/src/kernel/signal.S @@ -0,0 +1,4 @@ +.global syscall_sigreturn +syscall_sigreturn: + mov x8, #10 + svc 0 \ No newline at end of file diff --git a/src/kernel/signal.c b/src/kernel/signal.c new file mode 100755 index 000000000..c09f31ed0 --- /dev/null +++ b/src/kernel/signal.c @@ -0,0 +1,133 @@ +#include "signal.h" +#include "thread.h" +#include "ds/list.h" +#include "utils.h" +#include "peripherals/mini_uart.h" +#include "interrupt.h" +#include "process.h" +#include "waitqueue.h" +#include "process.h" + +extern void syscall_sigreturn(); + + + + +struct Signal_t *signum2handler(uint8_t signal, struct Process_t *proc) { + struct ds_list_head *front = ds_list_front(&(proc->sig_list)); + if(front == NULL) { + return NULL; + } + + while(front != (&(proc->sig_list))) { + struct Signal_t *sig = container_of(front, struct Signal_t, sig_head); + if(sig->sig_num == signal) { + return sig; + } + front = ds_list_front(front); + } + return NULL; +} + +void signal_register(uint8_t signal, signal_handler handler) { + + struct Process_t *proc = process_get_current(); + struct Signal_t *sig = signum2handler(signal, proc); + if(sig != NULL) { + sig->handler = handler; + } else { + + sig = (struct Signal_t *)kmalloc(sizeof(struct Signal_t)); + ds_list_head_init(&(sig->sig_head)); + sig->sig_num = signal; + sig->handler = handler; + ds_list_addprev(&(proc->sig_list), &(sig->sig_head)); + } +} + +void signal_kill(unsigned int pid, uint8_t signal) { + struct Process_t *proc = get_process_from_pid(pid); +; + if(proc == NULL) { + return; + } + if(signal > SIGNUMS || signal < 1) { + return; + } + + proc->signal[signal] += 1; +} + +void signal_handler_default() { + uart_send_string("Default handler\r\n"); + return; +} + +void signal_kill_default() { + process_exit(0); + return; +} + +void run_signal_thread() { + + struct Thread_t *th = thread_get_current_instance(); + + _run_user_thread(th->entry, 0xffffffff6000ULL, 0xffffffffb000ULL); + // _run_user_thread(th->entry, &syscall_sigreturn, 0xffffffffb000ULL); +} +void signal_call_handler(struct Process_t *proc, uint8_t signum) { + struct Signal_t *sig = signum2handler(signum, proc); + signal_handler handler; + if(sig == NULL) { + if(signum == 9) { + handler = signal_kill_default; + } else { + handler = signal_handler_default; + } + // run default handler in el1 + uint64_t flag = interrupt_disable_save(); + handler(); + interrupt_enable_restore(flag); + // syscall_sigreturn(); + } else { + handler = sig->handler; + struct Thread_t *th = process_thread_create(handler, NULL, proc, 2); + sig->sig_return = (void*)kmalloc((1 << 12)); + memcpy(sig->sig_return, &syscall_sigreturn, (1 << 8)); + mappages(th->saved_reg.ttbr0_el1, 0xffffffff6000, (1 << 12), kernel_va2pa(sig->sig_return)); + th->saved_reg.lr = run_signal_thread; + struct Thread_t *wait_th = thread_get_current_instance(); + sig->th = wait_th; + waitthread(thread_get_current_instance()); + } + return; +} + +void signal_check() { + struct Process_t *proc = process_get_current(); + if(proc->handling_signal != 0) return; + for(int i = 0; i < SIGNUMS; i ++) { + if(proc->signal[i] > 0) { + // first set to 0 otherwise other thread for the same process may run the same handler + + proc->handling_signal = i; + signal_call_handler(proc, i); + } + } +} + +void signal_sigreturn() { + uint64_t flag = interrupt_disable_save(); + struct Thread_t *th = thread_get_current_instance(); + struct Process_t *proc = th->proc; + struct Signal_t *sig = signum2handler(proc->handling_signal, proc); + wakeupthread(sig->th); + sig->th = NULL; + th->status = TH_ZOMBIE; + proc->handling_signal = 0; + proc->signal[sig->sig_num] -= 1; + schedule(0); + interrupt_disable_save(flag); +} + + diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c new file mode 100755 index 000000000..53b86f10b --- /dev/null +++ b/src/kernel/syscall.c @@ -0,0 +1,209 @@ +#include "process.h" +#include "thread.h" +#include "syscall.h" +#include "interrupt.h" +#include "peripherals/mini_uart.h" +#include "mbox/mbox.h" +#include "fs/vfs.h" +#include "fs/fat32.h" + +int sys_get_pid() { + struct Process_t *proc = process_get_current(); + + return proc->pid; +} +uint64_t sys_uartread(char buf[], uint64_t size) { + uint64_t ret = async_uart_rx_buf(buf, size); + return ret; +} +uint64_t sys_uartwrite(const char buf[], uint64_t size) { + uint64_t ret = uart_send_n(buf, size); + return ret; +} +int sys_exec(const char* name, char *const argv[]) { + uint64_t ret = process_exec(name, argv, 0); + return ret; +} +int sys_fork(struct Trapframe_t *frame) { + uint64_t ret = process_fork(frame); + + return ret; +} +void sys_exit(int status) { + process_exit(status); + return; +} + +int sys_mbox_call(unsigned char ch, unsigned int *mbox) { + uint64_t x = mbox_call(ch, mbox); + return x; +} + +void sys_kill(int pid) { + signal_kill(pid, 9); + return; +} + +int sys_open(const char *pathname, int flags) { + struct file *f; + int err = vfs_open(pathname, flags, &f); + if(err) return err; + struct Process_t *cur_proc = process_get_current(); + for(int i = 0; i < P_FD_MAX; i ++) { + if(cur_proc->files[i] == NULL) { + cur_proc->files[i] = f; + return i; + } + } + return -1; +} + +int sys_close(int fd) { + struct file *f; + struct Process_t *cur_proc = process_get_current(); + int err = vfs_close(cur_proc->files[fd]); + if(err) return err; + cur_proc->files[fd] = NULL; + return err; +} + +// syscall number : 13 +// remember to return read size or error code +long sys_write(int fd, const void *buf, unsigned long count) { + struct Process_t *cur_proc = process_get_current(); + int err = vfs_write(cur_proc->files[fd], buf, count); + return err; +} + +// syscall number : 14 +// remember to return read size or error code +long sys_read(int fd, void *buf, unsigned long count) { + struct Process_t *cur_proc = process_get_current(); + int err = vfs_read(cur_proc->files[fd], buf, count); + return err; +} + +// syscall number : 15 +// you can ignore mode, since there is no access control +int sys_mkdir(const char *pathname, unsigned mode) { + int err = vfs_mkdir(pathname); + return err; +} + + +// syscall number : 16 +// you can ignore arguments other than target (where to mount) and filesystem (fs name) +int sys_mount(const char *src, const char *target, const char *filesystem, unsigned long flags, const void *data) { + int err = vfs_mount(target, filesystem); + return err; +} + + +// syscall number : 17 +int sys_chdir(const char *path) { + struct vnode *dir; + int err = vfs_lookup(path, &dir); + + if(err != 0) { + return err; + } else { + struct Process_t *proc = process_get_current(); + proc->cur_vnode = dir; + proc->mnt = dir->mount; + } + return err; +} + +int sys_lseek(int fd, long offset, int whence) { + struct Process_t *proc = process_get_current(); + struct file *f = proc->files[fd]; + + return f->f_ops->lseek64(f, offset, whence); +} + +int sys_ioctl(int fd, unsigned long request, void *buf) { + struct Process_t *proc = process_get_current(); + struct file *f = proc->files[fd]; + + return f->f_ops->ioctl(f, request, buf); +} + +void syscall_handler(struct Trapframe_t *frame) { + + switch(frame->x8) { + case 0: + frame->x0 = sys_get_pid(); + break; + case 1: + frame->x0 = sys_uartread(frame->x0, frame->x1); + break; + case 2: + frame->x0 = sys_uartwrite(frame->x0, frame->x1); + break; + case 3: + frame->x0 = sys_exec(frame->x0, frame->x1); + break; + case 4: + unsigned long long val = sys_fork(frame); + frame->x0 = val; + break; + case 5: + sys_exit(frame->x1); + break; + case 6: + frame->x0 = sys_mbox_call(frame->x0, frame->x1); + break; + case 7: + sys_kill(frame->x0); + break; + + case 8: + signal_register(frame->x0, frame->x1); + break; + case 9: + signal_kill(frame->x0, frame->x1); + break; + case 10: + signal_sigreturn(); + break; + + case 11: + frame->x0 = sys_open(frame->x0, frame->x1); + break; + case 12: + frame->x0 = sys_close(frame->x0); + break; + case 13: + frame->x0 = sys_write(frame->x0, frame->x1, frame->x2); + break; + case 14: + frame->x0 = sys_read(frame->x0, frame->x1, frame->x2); + break; + + case 15: + frame->x0 = sys_mkdir(frame->x0, frame->x1); + break; + + case 16: + + sys_mount(frame->x0, frame->x1, frame->x2, frame->x3, frame->x4); + break; + + case 17: + frame->x0 = sys_chdir(frame->x0); + break; + + case 18: + frame->x0 = sys_lseek(frame->x0, frame->x1, frame->x2); + break; + + case 19: + frame->x0 = sys_ioctl(frame->x0, frame->x1, frame->x2); + break; + + case 20: + fat32_sync(); + + } + +} diff --git a/src/kernel/thread.c b/src/kernel/thread.c new file mode 100755 index 000000000..c566dcd32 --- /dev/null +++ b/src/kernel/thread.c @@ -0,0 +1,244 @@ +#include "thread.h" +#include "ds/list.h" +#include "utils.h" +#include +#include "interrupt.h" +#include "peripherals/mini_uart.h" + +// 8 different pri +struct ds_list_head run_queue; +struct ds_list_head zombie_queue; +static bool _inited = 0; +static uint64_t thread_num = 0; + +#define CHECK_ZNUM 3 + +struct RegState_t kernel_state; + +void thread_clean(struct Thread_t *th) { + + kfree(th->sp - DEFAULT_STACK_SZ); + kfree(th->arg); + ds_list_remove(&(th->th_head)); + process_free(th->proc); + kfree(th); +} + +void thread_check_zombie(void * arg) { + while(true) { + struct ds_list_head *front = ds_list_front(&zombie_queue); + for(int i = 0; i < CHECK_ZNUM && front != NULL; i ++) { + uint64_t flag = interrupt_disable_save(); + struct Thread_t *th = container_of(front, struct Thread_t, tq_head); + ds_list_remove(&(th->tq_head)); + + interrupt_enable_restore(flag); + front = ds_list_front(&zombie_queue); + asm volatile("nop"); + } + } +} +void thread_control_init() { + if(_inited) { + return; + } + _inited = 1; + ds_list_head_init(&run_queue); + ds_list_head_init(&zombie_queue); +} + + +extern void back_el1(); +void thread_exit() { + + back_el1(); + struct Thread_t *th = thread_get_current_instance(); + th->status = TH_ZOMBIE; + + + // wait for interrupt + // This make sure that the scheudle is called in el1 + enable_interrupt(); + while(1) { + asm volatile("nop"); + } +} + + +void _thread_exit() { + struct ds_list_head *front = ds_list_front(&(run_queue)); + // front should not be NULL, since we have idle thread + struct Thread_t *th = container_of(front, struct Thread_t, tq_head); + thread_exit(); +} + +void sys_call_exit() { + asm volatile( + "mov x0, 5\n" + "svc 0\n" + ); + return; +} + +void thread_exec_wrapper() { + + uint64_t flag = interrupt_disable_save(); + struct Thread_t *cur_thread = thread_get_current_instance(); + interrupt_enable_restore(flag); + cur_thread->entry(cur_thread->arg); + + flag = interrupt_disable_save(); + thread_exit(); + interrupt_enable_restore(flag); +} + +struct Thread_t * thread_create(thread_func func, void *arg) { + struct Thread_t *th = (struct Thread_t *)kmalloc(sizeof(struct Thread_t)); + if(arg == NULL) { + th->arg = NULL; + } else { + uint32_t arg_len = strlen(arg); + th->arg = (void *)kmalloc(arg_len + 1); + memcpy(th->arg, arg, arg_len); + *(char*)(th->arg + arg_len) = '\0'; + } + // TID may races, + uint64_t flag = interrupt_disable_save(); + th->tid = ++ thread_num; + th->entry = func; + // 4KB stack + ds_list_head_init(&(th->tq_head)); + ds_list_head_init(&(th->th_head)); + th->sp = (void *)kmalloc(DEFAULT_STACK_SZ) + (DEFAULT_STACK_SZ); + th->stack_sz = DEFAULT_STACK_SZ; + th->status = TH_IN_RUNNING; + ds_list_addprev(&run_queue, &(th->tq_head)); + memset(&th->saved_reg, 0, sizeof(struct RegState_t)); + th->saved_reg.fp = th->sp; + th->saved_reg.sp = th->sp; + // this should make the function end will jump to cleanup function + th->saved_reg.lr = thread_exec_wrapper; + th->saved_reg.tcb_addr = th; + interrupt_enable_restore(flag); + return th; +} +static uint64_t switch_time; + +void schedule_init() { + uint64_t freq, clock; + asm volatile("mrs %0, cntfrq_el0\n":"=r"(freq)); + asm volatile("mrs %0, cntpct_el0\n":"=r"(clock)); + freq >>= 5; + asm volatile("msr cntp_tval_el0, %0": "=r"(freq)); + switch_time = freq + clock; +} + + +static uint8_t first_schedule = 1; + +void schedule(uint8_t preempt) { + uint64_t flag = interrupt_disable_save(); + struct ds_list_head *front = ds_list_front(&(run_queue)); + // front should not be NULL, since we have idle thread + struct Thread_t *cur_thread = container_of(front, struct Thread_t, tq_head); + ds_list_remove(&(cur_thread->tq_head)); + ds_list_head_init(&(cur_thread->tq_head)); + + + //setup next timer + uint64_t freq; + if(preempt) { + asm volatile("mrs %0, cntfrq_el0\n":"=r"(freq)); + freq >>= 5; + asm volatile("msr cntp_tval_el0, %0": "=r"(freq)); + } + + if(first_schedule) { + cur_thread->status = TH_RUNNING; + first_schedule = 0; + // Make first context switch push front + // so that the status of the run queue is correct + // namely, the first thread instance should be running. + ds_list_addnext(&run_queue, &(cur_thread->tq_head)); + enable_interrupt(); + context_switch_to(&(kernel_state), &(cur_thread->saved_reg), cur_thread->tid); + return; + } + + + else { + front = ds_list_front(&(run_queue)); + if(front == NULL) { + goto _r; + } + struct Thread_t *next_thread = container_of(front, struct Thread_t, tq_head); + while(next_thread->status != TH_IN_RUNNING) { + + if(next_thread == cur_thread) { + break; + } + ds_list_remove(&(next_thread->tq_head)); + ds_list_head_init(&(next_thread->tq_head)); + if(next_thread == TH_WAIT) { + if(next_thread->waitqueue != NULL) { + ds_list_addprev(&(next_thread->waitqueue->th_list), &(next_thread->tq_head)); + } + } else if(next_thread->status == TH_ZOMBIE) { + ds_list_addprev(&(zombie_queue), &(next_thread->tq_head)); + } + front = ds_list_front(&(run_queue)); + if(front == NULL) { + goto _r; + } + next_thread = container_of(front, struct Thread_t, tq_head); + } + if(cur_thread->status != TH_RUNNING) { + if(cur_thread->status == TH_WAIT) { + if(cur_thread->waitqueue != NULL) { + ds_list_addprev(&(cur_thread->waitqueue->th_list), &(cur_thread->tq_head)); + } + } else if(cur_thread->status == TH_ZOMBIE) { + ds_list_addprev(&(zombie_queue), &(cur_thread->tq_head)); + } else{ + } + } else{ + cur_thread->status = TH_IN_RUNNING; + ds_list_addprev(&(run_queue), &(cur_thread->tq_head)); + } + next_thread->status = TH_RUNNING; + + + + enable_interrupt(); + context_switch_to(&(cur_thread->saved_reg), &(next_thread->saved_reg), next_thread->tid); + signal_check(); + return; + } + _r: + + ds_list_addprev(&(run_queue), &(cur_thread->tq_head)); + interrupt_enable_restore(flag); + signal_check(); + return; +} + +struct Thread_t *thread_get_current_instance() { + struct ds_list_head *front = ds_list_front(&(run_queue)); + struct Thread_t *cur_thread = container_of(front, struct Thread_t, tq_head); + return cur_thread; +} + +void handle_time_schedule(struct Trapframe_t *frame) { + // return; + uint64_t freq, clock; + asm volatile("mrs %0, cntfrq_el0\n":"=r"(freq)); + asm volatile("mrs %0, cntpct_el0\n":"=r"(clock)); + + if(switch_time > clock) { + return; + } + switch_time = clock + (freq >> 5); + struct Thread_t *cur_th = thread_get_current_instance(); + // Since we won't do eret after schedule, we need to enable the interrupt first + schedule(1); +} \ No newline at end of file diff --git a/src/kernel/utils.S b/src/kernel/utils.S index 92768a1bd..d5a3a1b6e 100644 --- a/src/kernel/utils.S +++ b/src/kernel/utils.S @@ -20,4 +20,30 @@ delay_test: mov x1, 0x65 bne delay // bl uart_send - ret \ No newline at end of file + ret + +.global gen_trapframe +gen_trapframe: + mov x0, 272 + mov x1, lr; + bl kmalloc + stp x0, x1, [x0 ,16 * 0] + stp x2, x3, [x0 ,16 * 1] + stp x4, x5, [x0 ,16 * 2] + stp x6, x7, [x0 ,16 * 3] + stp x8, x9, [x0 ,16 * 4] + stp x10, x11, [x0 ,16 * 5] + stp x12, x13, [x0 ,16 * 6] + stp x14, x15, [x0 ,16 * 7] + stp x16, x17, [x0 ,16 * 8] + stp x18, x19, [x0 ,16 * 9] + stp x20, x21, [x0 ,16 * 10] + stp x22, x23, [x0 ,16 * 11] + stp x24, x25, [x0 ,16 * 12] + stp x26, x27, [x0 ,16 * 13] + stp x28, x29, [x0 ,16 * 14] + stp x30, x0, [x0, 16 * 15] + mov x2, sp + stp x1, x2, [x0, 16 * 16] + mov lr, x1 + ret \ No newline at end of file diff --git a/src/kernel/utils.c b/src/kernel/utils.c index 053e7d530..95b96d99f 100644 --- a/src/kernel/utils.c +++ b/src/kernel/utils.c @@ -1,11 +1,18 @@ #include "type.h" #include "utils.h" +#include "peripherals/mini_uart.h" void memcpy(void* dest, void *src, unsigned long long size) { + // if(dest <= 0x3bffa000 && dest + size >= 0x3bffa000) { + // uart_send_string("copying\r\n"); + // } for(int i = 0; i < size; i ++) { *(char*)(dest + i) = *(char*)(src + i); } } void memset(void *dest, char val, unsigned int size) { + // if(dest <= 0x3bffa000 && dest + size >= 0x3bffa000) { + // uart_send_string("setting\r\n"); + // } for(int i = 0; i < size; i ++) { *(char*)(dest + i) = val; } diff --git a/src/kernel/waitqueue.c b/src/kernel/waitqueue.c new file mode 100755 index 000000000..726653c84 --- /dev/null +++ b/src/kernel/waitqueue.c @@ -0,0 +1,56 @@ +#include "waitqueue.h" +#include "thread.h" +#include "ds/list.h" +#include "type.h" +#include "utils.h" +#include "peripherals/mini_uart.h" + +extern struct ds_list_head run_queue; + +void waitqueue_init(struct waitqueue_t *queue) { + ds_list_head_init(&(queue->th_list)); +} + +void wait(struct waitqueue_t *queue) { + uint64_t flag = interrupt_disable_save(); + struct Thread_t* th = thread_get_current_instance(); + + signal_check(); + th->status = TH_WAIT; + th->waitqueue = queue; + schedule(0); + interrupt_enable_restore(flag); + return; +} + +void waitthread(struct Thread_t *th) { + uint64_t flag = interrupt_disable_save(); + + th->status = TH_WAIT; + th->waitqueue = NULL; + schedule(0); + interrupt_enable_restore(flag); + return; +} + +void wakeupthread(struct Thread_t *th) { + th->status = TH_IN_RUNNING; + ds_list_head_init(&(th->tq_head)); + ds_list_addprev(&(run_queue), &(th->tq_head)); + return; +} + +void wakeup(struct waitqueue_t *queue) { + struct ds_list_head *front = ds_list_front(&(queue->th_list)); + if(front == NULL) { + return; + } + struct Thread_t *th = container_of(front, struct Thread_t, tq_head); + + ds_list_remove(&(th->tq_head)); + th->status = TH_IN_RUNNING; + th->waitqueue = NULL; + ds_list_head_init(&(th->tq_head)); + ds_list_addprev(&(run_queue), &(th->tq_head)); + return; +} \ No newline at end of file