diff --git a/initramfs/syscall.img b/initramfs/syscall.img new file mode 100644 index 000000000..70d4a5539 Binary files /dev/null and b/initramfs/syscall.img differ diff --git a/initramfs/user.img b/initramfs/user.img new file mode 100644 index 000000000..1adf648a4 Binary files /dev/null and b/initramfs/user.img differ diff --git a/initramfs/usr_prog.S b/initramfs/usr_prog.S new file mode 100644 index 000000000..ce7e53908 --- /dev/null +++ b/initramfs/usr_prog.S @@ -0,0 +1,11 @@ +.section ".text" +.global _start +_start: + mov x0, 0 +1: + add x0, x0, 1 + svc 0 + cmp x0, 5 + blt 1b +1: + b 1b diff --git a/initramfs/usr_prog.elf b/initramfs/usr_prog.elf new file mode 100755 index 000000000..cf66ed223 Binary files /dev/null and b/initramfs/usr_prog.elf differ diff --git a/initramfs/usr_prog.img b/initramfs/usr_prog.img new file mode 100755 index 000000000..796b17356 Binary files /dev/null and b/initramfs/usr_prog.img differ diff --git a/lab6/kernel/Makefile b/lab6/kernel/Makefile new file mode 100644 index 000000000..a4fb3bd32 --- /dev/null +++ b/lab6/kernel/Makefile @@ -0,0 +1,31 @@ +ARMGNU ?= aarch64-linux-gnu + +COPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only -O0 +ASMOPS = -Iinclude + +BUILD_DIR = build +SRC_DIR = src + +all : kernel8.img + +clean : + rm -rf $(BUILD_DIR) *.img + +$(BUILD_DIR)/%_c.o: $(SRC_DIR)/%.c + mkdir -p $(@D) + $(ARMGNU)-gcc $(COPS) -MMD -c $< -o $@ + +$(BUILD_DIR)/%_s.o: $(SRC_DIR)/%.S + $(ARMGNU)-gcc $(ASMOPS) -MMD -c $< -o $@ + +C_FILES = $(wildcard $(SRC_DIR)/*.c) +ASM_FILES = $(wildcard $(SRC_DIR)/*.S) +OBJ_FILES = $(C_FILES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%_c.o) +OBJ_FILES += $(ASM_FILES:$(SRC_DIR)/%.S=$(BUILD_DIR)/%_s.o) + +DEP_FILES = $(OBJ_FILES:%.o=%.d) +-include $(DEP_FILES) + +kernel8.img: $(SRC_DIR)/linker.ld $(OBJ_FILES) + $(ARMGNU)-ld -T $(SRC_DIR)/linker.ld -o $(BUILD_DIR)/kernel8.elf $(OBJ_FILES) + $(ARMGNU)-objcopy $(BUILD_DIR)/kernel8.elf -O binary kernel8.img diff --git "a/lab6/kernel/\\" "b/lab6/kernel/\\" new file mode 100644 index 000000000..ec17845cd --- /dev/null +++ "b/lab6/kernel/\\" @@ -0,0 +1,217 @@ +#include +#include +#include "cpio.h" +#include "mini_uart.h" +#include "helper.h" +#include "alloc.h" +#include "thread.h" +#include "mmu.h" +#include "utils.h" + +extern char* _cpio_file; +char buff[1024]; + +uint8_t hex_char_to_bin(char c) { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'a' && c <= 'f') return c - 'a' + 10; + if (c >= 'A' && c <= 'F') return c - 'A' + 10; + return 0; // Not a valid hexadecimal character +} + +uint64_t hex_to_bin(const char* hex) { + uint64_t result = 0; + for(int i = 0; i < 8; i ++) { + result = (result << 4) | hex_char_to_bin(hex[i]); + } + return result; +} + +void* cpio_find(char* name) { + char* cpio_start = _cpio_file; + struct cpio_newc_header* header = (struct cpio_newc_header*)cpio_start; + substr(buff, header -> c_magic, 0, 5); + while (same(buff, "070701")) { + // Convert c_namesize and c_filesize from ASCII hex to binary + uint64_t namesize = hex_to_bin(header->c_namesize); + uint64_t filesize = hex_to_bin(header->c_filesize); + + // Calculate the start of the file name and file data + char* filename = (char*)(header + 1); + char* filedata = filename + namesize; + filedata = (char*)((uintptr_t)filedata + ((4 - ((uintptr_t)filedata & 3)) & 3)); // Align to next 4-byte boundary + + substr(buff, filename, 0, namesize - 1); + if (same(buff, "TRAILER!!!")) { + break; // End of archive + } + + if (same(buff, name)) { + return filedata; + } + substr(buff, filename, 0, namesize - 1); + + // Move to the next header, aligning as necessary + header = (struct cpio_newc_header*)(filedata + filesize); + header = (struct cpio_newc_header*)((uintptr_t)header + ((4 - ((uintptr_t)header & 3)) & 3)); // Align to next 4-byte boundary + substr(buff, header -> c_magic, 0, 5); + } + return 0; +} + +void cpio_parse_ls() { + char* cpio_start = _cpio_file; + struct cpio_newc_header* header = (struct cpio_newc_header*)cpio_start; + substr(buff, header -> c_magic, 0, 5); + while (same(buff, "070701")) { + + // Convert c_namesize and c_filesize from ASCII hex to binary + uint64_t namesize = hex_to_bin(header->c_namesize); + uint64_t filesize = hex_to_bin(header->c_filesize); + + // Calculate the start of the file name and file data + char* filename = (char*)(header + 1); + char* filedata = filename + namesize; + filedata = (char*)((uintptr_t)filedata + ((4 - ((uintptr_t)filedata & 3)) & 3)); // Align to next 4-byte boundary + + substr(buff, filename, 0, namesize - 1); + if (same(buff, "TRAILER!!!")) { + break; // End of archive + } + uart_printf("%s\r\n", buff); + + // Move to the next header, aligning as necessary + header = (struct cpio_newc_header*)(filedata + filesize); + header = (struct cpio_newc_header*)((uintptr_t)header + ((4 - ((uintptr_t)header & 3)) & 3)); // Align to next 4-byte boundary + substr(buff, header -> c_magic, 0, 5); + } +} + +void cpio_parse_cat(char* name) { + char* cpio_start = _cpio_file; + struct cpio_newc_header* header = (struct cpio_newc_header*)cpio_start; + substr(buff, header -> c_magic, 0, 5); + while (same(buff, "070701")) { + // Convert c_namesize and c_filesize from ASCII hex to binary + uint64_t namesize = hex_to_bin(header->c_namesize); + uint64_t filesize = hex_to_bin(header->c_filesize); + + // Calculate the start of the file name and file data + char* filename = (char*)(header + 1); + char* filedata = filename + namesize; + filedata = (char*)((uintptr_t)filedata + ((4 - ((uintptr_t)filedata & 3)) & 3)); // Align to next 4-byte boundary + + substr(buff, filename, 0, namesize - 1); + if (same(buff, "TRAILER!!!")) { + break; // End of archive + } + + if (same(buff, name)) { + uart_printf ("Cat %d\r\n", filesize); + substr(buff, filedata, 0, filesize - 1); + uart_printf("%s\r\n", buff); + } + substr(buff, filename, 0, namesize - 1); + + // Move to the next header, aligning as necessary + header = (struct cpio_newc_header*)(filedata + filesize); + header = (struct cpio_newc_header*)((uintptr_t)header + ((4 - ((uintptr_t)header & 3)) & 3)); // Align to next 4-byte boundary + substr(buff, header -> c_magic, 0, 5); + } +} + +extern thread* get_current(); + +void cpio_load(char* str) { + irq(0); + thread_init(); + thread* cur = get_current(); + uart_printf ("cur: %llx\r\n", cur); + long xxx = read_sysreg(tpidr_el1); + uart_printf ("xxx: %llx\r\n", xxx); + + void* pos = cpio_find(str); + cur -> code = my_malloc(4096 * 64); + cur -> code_size = 4096 * 64; + for (int i = 0; i < cur -> code_size; i ++) { + ((char*)cur -> code)[i] = ((char*)pos)[i]; + } + + uart_printf ("%llx, %llx, %llx\r\n", cur -> PGD, pa2va(cur -> PGD), &(cur -> PGD)); + + setup_peripheral_identity(pa2va(cur -> PGD)); + for (int i = 0; i < cur -> code_size; i += 4096) { + map_page(pa2va(cur -> PGD), i, va2pa(cur -> code) + i, (1 << 6)); + } + for (int i = 0; i < 4; i ++) { + map_page (pa2va(cur -> PGD), 0xffffffffb000L + i * 4096, va2pa(cur -> stack_start) + i * 4096, (1 << 6)); + } + cur -> code = 0; + cur -> stack_start = 0xffffffffb000L; + void* sp = 0xfffffffff000L - 16; + void* el1_sp = cur -> sp; + + long ttbr1 = read_sysreg(ttbr1_el1); + long ttbr0 = read_sysreg(ttbr0_el1); + uart_printf ("TTBR0: %llx, TTBR1: %llx\r\n", ttbr0, ttbr1); + + uart_printf ("cur -> PGD %llx\r\n", cur -> PGD); + + // uart_printf("Running code from %llx, which is %llx\n", cur -> code, trans(cur -> code)); + + asm volatile("dsb ish"); + write_sysreg(ttbr0_el1, cur -> PGD); + asm volatile("tlbi vmalle1is"); + asm volatile("dsb ish"); + asm volatile("isb"); + + + uart_printf ("uart printf: %llx\r\n", uart_printf); + while (1); + + uart_printf("Running code from %llx, which is %llx\n", cur -> code, trans_el0(cur -> code)); + ttbr1 = read_sysreg(ttbr1_el1); + ttbr0 = read_sysreg(ttbr0_el1); + uart_printf ("TTBR0: %llx, TTBR1: %llx, &TTBR0: %llx\r\n", ttbr0, ttbr1, &ttbr0); + + asm volatile( + "mov x1, 0;" + "msr spsr_el1, x1;" + "mov x1, %[code];" + "mov x2, %[sp];" + "msr elr_el1, x1;" + "msr sp_el0, x2;" + "msr DAIFclr, 0xf;" + "mov sp, %[sp_el1];" + "eret;" + : + : [code] "r" (cur -> code), [sp] "r" (sp), [sp_el1] "r" (el1_sp) + : "x1", "x2", "sp" + ); +} + +char* get_cpio_end() { + char* cpio_start = _cpio_file; + struct cpio_newc_header* header = (struct cpio_newc_header*)cpio_start; + substr(buff, header -> c_magic, 0, 5); + while (same(buff, "070701")) { + uint64_t namesize = hex_to_bin(header->c_namesize); + uint64_t filesize = hex_to_bin(header->c_filesize); + + char* filename = (char*)(header + 1); + char* filedata = filename + namesize; + filedata = (char*)((uintptr_t)filedata + ((4 - ((uintptr_t)filedata & 3)) & 3)); // Align to next 4-byte boundary + + substr(buff, filename, 0, namesize - 1); + if (same(buff, "TRAILER!!!")) { + return filedata + filesize; + } + + substr(buff, filename, 0, namesize - 1); + + // Move to the next header, aligning as necessary + header = (struct cpio_newc_header*)(filedata + filesize); + header = (struct cpio_newc_header*)((uintptr_t)header + ((4 - ((uintptr_t)header & 3)) & 3)); // Align to next 4-byte boundary + substr(buff, header -> c_magic, 0, 5); + } + return header; +} diff --git a/lab6/kernel/asm_test.sh b/lab6/kernel/asm_test.sh new file mode 100755 index 000000000..4ebc6f3a2 --- /dev/null +++ b/lab6/kernel/asm_test.sh @@ -0,0 +1 @@ +qemu-system-aarch64 -M raspi3b -kernel kernel8.img -serial null -serial stdio -dtb ../../bcm2710-rpi-3-b-plus.dtb -initrd ../../initramfs.cpio -display vnc=0.0.0.0:0 -vga std -d in_asm diff --git a/lab6/kernel/build/alloc_c.d b/lab6/kernel/build/alloc_c.d new file mode 100644 index 000000000..8a63d0860 --- /dev/null +++ b/lab6/kernel/build/alloc_c.d @@ -0,0 +1,3 @@ +build/alloc_c.o: src/alloc.c include/alloc.h include/mini_uart.h \ + include/fdt.h include/set.h include/mini_uart.h include/alloc.h \ + include/cpio.h include/mmu.h diff --git a/lab6/kernel/build/alloc_c.o b/lab6/kernel/build/alloc_c.o new file mode 100644 index 000000000..6e0f76c64 Binary files /dev/null and b/lab6/kernel/build/alloc_c.o differ diff --git a/lab6/kernel/build/boot_s.d b/lab6/kernel/build/boot_s.d new file mode 100644 index 000000000..1bbe62f69 --- /dev/null +++ b/lab6/kernel/build/boot_s.d @@ -0,0 +1 @@ +build/boot_s.o: src/boot.S include/mmu_regs.h diff --git a/lab6/kernel/build/boot_s.o b/lab6/kernel/build/boot_s.o new file mode 100644 index 000000000..eb4bc3b61 Binary files /dev/null and b/lab6/kernel/build/boot_s.o differ diff --git a/lab6/kernel/build/cpio_c.d b/lab6/kernel/build/cpio_c.d new file mode 100644 index 000000000..a47c162b4 --- /dev/null +++ b/lab6/kernel/build/cpio_c.d @@ -0,0 +1,3 @@ +build/cpio_c.o: src/cpio.c include/cpio.h include/mini_uart.h \ + include/helper.h include/alloc.h include/thread.h include/mmu.h \ + include/utils.h diff --git a/lab6/kernel/build/cpio_c.o b/lab6/kernel/build/cpio_c.o new file mode 100644 index 000000000..8c3105d2b Binary files /dev/null and b/lab6/kernel/build/cpio_c.o differ diff --git a/lab6/kernel/build/exception_c.d b/lab6/kernel/build/exception_c.d new file mode 100644 index 000000000..bedaffbad --- /dev/null +++ b/lab6/kernel/build/exception_c.d @@ -0,0 +1,4 @@ +build/exception_c.o: src/exception.c include/exception.h \ + include/mini_uart.h include/utils.h include/mmio.h include/DEFINE.h \ + include/timer.h include/task.h include/system_call.h include/exception.h \ + include/thread.h diff --git a/lab6/kernel/build/exception_c.o b/lab6/kernel/build/exception_c.o new file mode 100644 index 000000000..9ab4e06da Binary files /dev/null and b/lab6/kernel/build/exception_c.o differ diff --git a/lab6/kernel/build/fdt_c.d b/lab6/kernel/build/fdt_c.d new file mode 100644 index 000000000..b4593fc62 --- /dev/null +++ b/lab6/kernel/build/fdt_c.d @@ -0,0 +1,2 @@ +build/fdt_c.o: src/fdt.c include/fdt.h include/mini_uart.h \ + include/utils.h include/helper.h diff --git a/lab6/kernel/build/fdt_c.o b/lab6/kernel/build/fdt_c.o new file mode 100644 index 000000000..835c41c39 Binary files /dev/null and b/lab6/kernel/build/fdt_c.o differ diff --git a/lab6/kernel/build/helper_c.d b/lab6/kernel/build/helper_c.d new file mode 100644 index 000000000..cb268cdc7 --- /dev/null +++ b/lab6/kernel/build/helper_c.d @@ -0,0 +1 @@ +build/helper_c.o: src/helper.c include/mini_uart.h diff --git a/lab6/kernel/build/helper_c.o b/lab6/kernel/build/helper_c.o new file mode 100644 index 000000000..1e8938374 Binary files /dev/null and b/lab6/kernel/build/helper_c.o differ diff --git a/lab6/kernel/build/kernel8.elf b/lab6/kernel/build/kernel8.elf new file mode 100755 index 000000000..94b26740c Binary files /dev/null and b/lab6/kernel/build/kernel8.elf differ diff --git a/lab6/kernel/build/kernel_start_c.d b/lab6/kernel/build/kernel_start_c.d new file mode 100644 index 000000000..4b6ad01e5 --- /dev/null +++ b/lab6/kernel/build/kernel_start_c.d @@ -0,0 +1,3 @@ +build/kernel_start_c.o: src/kernel_start.c include/mini_uart.h \ + include/shell.h include/fdt.h include/cpio.h include/alloc.h \ + include/thread.h include/mmu.h diff --git a/lab6/kernel/build/kernel_start_c.o b/lab6/kernel/build/kernel_start_c.o new file mode 100644 index 000000000..ea354cd2f Binary files /dev/null and b/lab6/kernel/build/kernel_start_c.o differ diff --git a/lab6/kernel/build/mail_c.d b/lab6/kernel/build/mail_c.d new file mode 100644 index 000000000..99d78e84d --- /dev/null +++ b/lab6/kernel/build/mail_c.d @@ -0,0 +1 @@ +build/mail_c.o: src/mail.c include/mini_uart.h include/mail.h diff --git a/lab6/kernel/build/mail_c.o b/lab6/kernel/build/mail_c.o new file mode 100644 index 000000000..21f892467 Binary files /dev/null and b/lab6/kernel/build/mail_c.o differ diff --git a/lab6/kernel/build/mini_uart_c.d b/lab6/kernel/build/mini_uart_c.d new file mode 100644 index 000000000..d6054bce7 --- /dev/null +++ b/lab6/kernel/build/mini_uart_c.d @@ -0,0 +1,2 @@ +build/mini_uart_c.o: src/mini_uart.c include/utils.h include/helper.h \ + include/mmio.h include/DEFINE.h diff --git a/lab6/kernel/build/mini_uart_c.o b/lab6/kernel/build/mini_uart_c.o new file mode 100644 index 000000000..f5da91883 Binary files /dev/null and b/lab6/kernel/build/mini_uart_c.o differ diff --git a/lab6/kernel/build/mm_s.d b/lab6/kernel/build/mm_s.d new file mode 100644 index 000000000..6749a99b3 --- /dev/null +++ b/lab6/kernel/build/mm_s.d @@ -0,0 +1 @@ +build/mm_s.o: src/mm.S diff --git a/lab6/kernel/build/mm_s.o b/lab6/kernel/build/mm_s.o new file mode 100644 index 000000000..5f5830933 Binary files /dev/null and b/lab6/kernel/build/mm_s.o differ diff --git a/lab6/kernel/build/mmio_c.d b/lab6/kernel/build/mmio_c.d new file mode 100644 index 000000000..e7a32746f --- /dev/null +++ b/lab6/kernel/build/mmio_c.d @@ -0,0 +1 @@ +build/mmio_c.o: src/mmio.c include/mmio.h diff --git a/lab6/kernel/build/mmio_c.o b/lab6/kernel/build/mmio_c.o new file mode 100644 index 000000000..cef85b4db Binary files /dev/null and b/lab6/kernel/build/mmio_c.o differ diff --git a/lab6/kernel/build/mmu_c.d b/lab6/kernel/build/mmu_c.d new file mode 100644 index 000000000..ae73bc493 --- /dev/null +++ b/lab6/kernel/build/mmu_c.d @@ -0,0 +1,2 @@ +build/mmu_c.o: src/mmu.c include/mmu.h include/helper.h include/utils.h \ + include/alloc.h include/thread.h include/mmu_regs.h include/mini_uart.h diff --git a/lab6/kernel/build/mmu_c.o b/lab6/kernel/build/mmu_c.o new file mode 100644 index 000000000..1cb8bdd96 Binary files /dev/null and b/lab6/kernel/build/mmu_c.o differ diff --git a/lab6/kernel/build/shell_c.d b/lab6/kernel/build/shell_c.d new file mode 100644 index 000000000..91b9f6d00 --- /dev/null +++ b/lab6/kernel/build/shell_c.d @@ -0,0 +1,5 @@ +build/shell_c.o: src/shell.c include/shell.h include/mini_uart.h \ + include/reboot.h include/mail.h include/helper.h include/loader.h \ + include/cpio.h include/alloc.h include/fdt.h include/timer.h \ + include/exception.h include/thread.h include/system_call.h \ + include/exception.h include/signal.h include/mmu.h diff --git a/lab6/kernel/build/shell_c.o b/lab6/kernel/build/shell_c.o new file mode 100644 index 000000000..a9b3abb01 Binary files /dev/null and b/lab6/kernel/build/shell_c.o differ diff --git a/lab6/kernel/build/signal_c.d b/lab6/kernel/build/signal_c.d new file mode 100644 index 000000000..8dcdcdec8 --- /dev/null +++ b/lab6/kernel/build/signal_c.d @@ -0,0 +1 @@ +build/signal_c.o: src/signal.c include/thread.h include/signal.h diff --git a/lab6/kernel/build/signal_c.o b/lab6/kernel/build/signal_c.o new file mode 100644 index 000000000..8b8635648 Binary files /dev/null and b/lab6/kernel/build/signal_c.o differ diff --git a/lab6/kernel/build/system_call_c.d b/lab6/kernel/build/system_call_c.d new file mode 100644 index 000000000..7acba592f --- /dev/null +++ b/lab6/kernel/build/system_call_c.d @@ -0,0 +1,4 @@ +build/system_call_c.o: src/system_call.c include/system_call.h \ + include/exception.h include/alloc.h include/thread.h include/mail.h \ + include/cpio.h include/mini_uart.h include/helper.h include/exception.h \ + include/utils.h include/mmu.h diff --git a/lab6/kernel/build/system_call_c.o b/lab6/kernel/build/system_call_c.o new file mode 100644 index 000000000..12dd77fbc Binary files /dev/null and b/lab6/kernel/build/system_call_c.o differ diff --git a/lab6/kernel/build/system_call_s.d b/lab6/kernel/build/system_call_s.d new file mode 100644 index 000000000..36807c754 --- /dev/null +++ b/lab6/kernel/build/system_call_s.d @@ -0,0 +1 @@ +build/system_call_s.o: src/system_call.S diff --git a/lab6/kernel/build/system_call_s.o b/lab6/kernel/build/system_call_s.o new file mode 100644 index 000000000..555ba6157 Binary files /dev/null and b/lab6/kernel/build/system_call_s.o differ diff --git a/lab6/kernel/build/task_c.d b/lab6/kernel/build/task_c.d new file mode 100644 index 000000000..36a5b99a8 --- /dev/null +++ b/lab6/kernel/build/task_c.d @@ -0,0 +1,2 @@ +build/task_c.o: src/task.c include/task.h include/alloc.h \ + include/mini_uart.h include/utils.h diff --git a/lab6/kernel/build/task_c.o b/lab6/kernel/build/task_c.o new file mode 100644 index 000000000..61a1c132c Binary files /dev/null and b/lab6/kernel/build/task_c.o differ diff --git a/lab6/kernel/build/thread_c.d b/lab6/kernel/build/thread_c.d new file mode 100644 index 000000000..9aa5c3c31 --- /dev/null +++ b/lab6/kernel/build/thread_c.d @@ -0,0 +1,3 @@ +build/thread_c.o: src/thread.c include/thread.h include/alloc.h \ + include/mini_uart.h include/helper.h include/exception.h \ + include/signal.h include/mmu.h include/utils.h diff --git a/lab6/kernel/build/thread_c.o b/lab6/kernel/build/thread_c.o new file mode 100644 index 000000000..96096ac4d Binary files /dev/null and b/lab6/kernel/build/thread_c.o differ diff --git a/lab6/kernel/build/timer_c.d b/lab6/kernel/build/timer_c.d new file mode 100644 index 000000000..b7ed93425 --- /dev/null +++ b/lab6/kernel/build/timer_c.d @@ -0,0 +1,2 @@ +build/timer_c.o: src/timer.c include/timer.h include/alloc.h \ + include/mini_uart.h diff --git a/lab6/kernel/build/timer_c.o b/lab6/kernel/build/timer_c.o new file mode 100644 index 000000000..35ae2964e Binary files /dev/null and b/lab6/kernel/build/timer_c.o differ diff --git a/lab6/kernel/build/utils_s.d b/lab6/kernel/build/utils_s.d new file mode 100644 index 000000000..5af69aba7 --- /dev/null +++ b/lab6/kernel/build/utils_s.d @@ -0,0 +1 @@ +build/utils_s.o: src/utils.S diff --git a/lab6/kernel/build/utils_s.o b/lab6/kernel/build/utils_s.o new file mode 100644 index 000000000..81addeb90 Binary files /dev/null and b/lab6/kernel/build/utils_s.o differ diff --git a/lab6/kernel/include/DEFINE.h b/lab6/kernel/include/DEFINE.h new file mode 100644 index 000000000..43c55152d --- /dev/null +++ b/lab6/kernel/include/DEFINE.h @@ -0,0 +1,58 @@ +#define MMIO_BASE 0xffff00003F000000 +#define PBASE MMIO_BASE + +#define AUX_IRQ ((volatile unsigned int*)(MMIO_BASE + 0x00215000)) +// Auxiliary enables +#define AUX_ENABLE ((volatile unsigned int*)(MMIO_BASE + 0x00215004)) +// Mini Uart I/O Data +#define AUX_MU_IO_REG ((volatile unsigned int*)(MMIO_BASE + 0x00215040)) +// Mini Uart Interrupt Enable +#define AUX_MU_IER_REG ((volatile unsigned int*)(MMIO_BASE + 0x00215044)) +// Mini Uart Interrupt Identity +#define AUX_MU_IIR_REG ((volatile unsigned int*)(MMIO_BASE + 0x00215048)) +// Mini Uart Line Control +#define AUX_MU_LCR_REG ((volatile unsigned int*)(MMIO_BASE + 0x0021504C)) +// Mini Uart Modem Control +#define AUX_MU_MCR_REG ((volatile unsigned int*)(MMIO_BASE + 0x00215050)) +// Mini Uart Line Status +#define AUX_MU_LSR_REG ((volatile unsigned int*)(MMIO_BASE + 0x00215054)) +// Mini Uart Modem Status +#define AUX_MU_MSR_REG ((volatile unsigned int*)(MMIO_BASE + 0x00215058)) +// Mini Uart Scratch +#define AUX_MU_SCRATCH ((volatile unsigned int*)(MMIO_BASE + 0x0021505C)) +// Mini Uart Scratch +#define AUX_MU_CNTL_REG ((volatile unsigned int*)(MMIO_BASE + 0x00215060)) +// Mini Uart Extra Status +#define AUX_MU_STAT_REG ((volatile unsigned int*)(MMIO_BASE + 0x00215064)) +// Mini Uart Baudrate +#define AUX_MU_BAUD_REG ((volatile unsigned int*)(MMIO_BASE + 0x00215068)) + +#define IRQ_basic_pending ((volatile unsigned int*)(MMIO_BASE + 0x0000B200)) +#define IRQ_pending_1 ((volatile unsigned int*)(MMIO_BASE + 0x0000B204)) +#define IRQ_pending_2 ((volatile unsigned int*)(MMIO_BASE + 0x0000B208)) +#define FIQ_control ((volatile unsigned int*)(MMIO_BASE + 0x0000B20C)) +#define Enable_IRQs_1 ((volatile unsigned int*)(MMIO_BASE + 0x0000B210)) +#define Enable_IRQs_2 ((volatile unsigned int*)(MMIO_BASE + 0x0000B214)) +#define Enable_Basic_IRQs ((volatile unsigned int*)(MMIO_BASE + 0x0000B218)) +#define Disable_IRQs_1 ((volatile unsigned int*)(MMIO_BASE + 0x0000B21C)) +#define Disable_IRQs_2 ((volatile unsigned int*)(MMIO_BASE + 0x0000B220)) +#define Disable_Basic_IRQs ((volatile unsigned int*)(MMIO_BASE + 0x0000B224)) +#define CORE0_INT_SRC (volatile unsigned int*)(0xffff000040000060) +#define CORE0_TIMER_IRQ_CTRL (volatile unsigned int*)(0xffff000040000040) + +#define GPFSEL1 (PBASE+0x00200004) +#define GPSET0 (PBASE+0x0020001C) +#define GPCLR0 (PBASE+0x00200028) +#define GPPUD (PBASE+0x00200094) +#define GPPUDCLK0 (PBASE+0x00200098) + +#define UART_DR ( (volatile unsigned int *) ( MMIO_BASE + 0x00201000 ) ) /* Data Register */ +#define UART_FR ( (volatile unsigned int *) ( MMIO_BASE + 0x00201018 ) ) /* Flag register */ +#define UART_IBRD ( (volatile unsigned int *) ( MMIO_BASE + 0x00201024 ) ) /* Integer Baud Rate Divisor */ +#define UART_FBRD ( (volatile unsigned int *) ( MMIO_BASE + 0x00201028 ) ) /* RFractional Baud Rate Divisor */ +#define UART_LCRH ( (volatile unsigned int *) ( MMIO_BASE + 0x0020102C ) ) /* Line Control Register */ +#define UART_CR ( (volatile unsigned int *) ( MMIO_BASE + 0x00201030 ) ) /* Control Register */ +#define UART_RIS ( (volatile unsigned int *) ( MMIO_BASE + 0x0020103C ) ) +#define UART_IMSC ( (volatile unsigned int *) ( MMIO_BASE + 0x00201038 ) ) /* Interupt FIFO Level Select Register */ +#define UART_MIS ( (volatile unsigned int *) ( MMIO_BASE + 0x00201040 ) ) +#define UART_ICR ( (volatile unsigned int *) ( MMIO_BASE + 0x00201044 ) ) /* Interupt Clear Register */ diff --git a/lab6/kernel/include/alloc.h b/lab6/kernel/include/alloc.h new file mode 100644 index 000000000..4ad1da9ab --- /dev/null +++ b/lab6/kernel/include/alloc.h @@ -0,0 +1,22 @@ +#ifndef ALLOC_H +#define ALLOC_H + +#include + +void* simple_malloc(int, int); + +void reserve(unsigned long l, unsigned long r); +void frame_init(); + +void* frame_malloc(size_t size); +void* my_malloc(size_t size); + +void frame_free(char*); +void my_free(char*); + +void print_node_list(); +void print_pool(); + +void manage_init (); + +#endif diff --git a/lab6/kernel/include/cpio.h b/lab6/kernel/include/cpio.h new file mode 100644 index 000000000..2e6a3a252 --- /dev/null +++ b/lab6/kernel/include/cpio.h @@ -0,0 +1,29 @@ +#ifndef CPIO_H +#define CPIO_H + +struct cpio_newc_header { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; + }; + + +void cpio_parse_ls(); +void cpio_parse_cat(char*); +void cpio_load(char*); +void* cpio_find(char*); + +char* get_cpio_end(); + +#endif diff --git a/lab6/kernel/include/exception.h b/lab6/kernel/include/exception.h new file mode 100644 index 000000000..49e60c3b2 --- /dev/null +++ b/lab6/kernel/include/exception.h @@ -0,0 +1,16 @@ +#ifndef EXCEPTION_H +#define EXCEPTION_H + +typedef struct trapframe_t{ + unsigned long long x[32]; + // x[31] is empty + unsigned long long spsr_el1; + unsigned long long elr_el1; + unsigned long long sp_el0; +} trapframe_t; +// basically all the shits stored by save_all + +void exception_entry(); +void core_timer_entry(); + +#endif diff --git a/lab6/kernel/include/fdt.h b/lab6/kernel/include/fdt.h new file mode 100644 index 000000000..b90850855 --- /dev/null +++ b/lab6/kernel/include/fdt.h @@ -0,0 +1,113 @@ +// Ref: https://elixir.bootlin.com/linux/v5.16.14/source/scripts/dtc/libfdt/fdt.h +#ifndef _FDT_H +#define _FDT_H + +#include +#include + +typedef int (*fdt_parser)(int level, char *cur, char *dt_strings); + +void fdt_traversal(char *dtb); +void parse_dtb(char *dtb, fdt_parser parser); + +typedef uint32_t fdt32_t; +typedef uint64_t fdt64_t; + +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright 2012 Kim Phillips, Freescale Semiconductor. + */ + +#ifndef __ASSEMBLY__ + +struct fdt_header { + fdt32_t magic; /* magic word FDT_MAGIC */ + fdt32_t totalsize; /* total size of DT block */ + fdt32_t off_dt_struct; /* offset to structure */ + fdt32_t off_dt_strings; /* offset to strings */ + fdt32_t off_mem_rsvmap; /* offset to memory reserve map */ + fdt32_t version; /* format version */ + fdt32_t last_comp_version; /* last compatible version */ + + /* version 2 fields below */ + fdt32_t boot_cpuid_phys; /* Which physical CPU id we're + booting on */ + /* version 3 fields below */ + fdt32_t size_dt_strings; /* size of the strings block */ + + /* version 17 fields below */ + fdt32_t size_dt_struct; /* size of the structure block */ +}; + +struct fdt_node_header { + fdt32_t tag; + char name[0]; +}; + +struct fdt_property { + fdt32_t tag; + fdt32_t len; + fdt32_t nameoff; + char data[0]; +}; + +#endif /* !__ASSEMBLY */ + +#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ +#define FDT_TAGSIZE sizeof(fdt32_t) + +#define FDT_BEGIN_NODE 0x1 /* Start node: full name */ +#define FDT_END_NODE 0x2 /* End node */ +#define FDT_PROP 0x3 /* Property: name off, size, content */ +#define FDT_NOP 0x4 /* nop */ +#define FDT_END 0x9 + +#define FDT_V1_SIZE (7*sizeof(fdt32_t)) +#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(fdt32_t)) +#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t)) +#define FDT_V16_SIZE FDT_V3_SIZE +#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t)) + +// Ref: https://elixir.bootlin.com/linux/v5.16.14/source/scripts/dtc/libfdt/libfdt.h#L249 +#define fdt_get_header(fdt, field) \ + (fdt32_ld(&((const struct fdt_header *)(fdt))->field)) +#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) +#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) +#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) +#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) +#define fdt_version(fdt) (fdt_get_header(fdt, version)) +#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) +#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) +#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) + +#define fdtn_get_header(fdtn, field) \ + (fdt32_ld(&((const struct fdt_node_header *)(fdtn))->field)) +#define fdtn_tag(fdtn) (fdtn_get_header(fdtn, tag)) + +#define fdtp_get_header(fdtp, field) \ + (fdt32_ld(&((const struct fdt_property *)(fdtp))->field)) +#define fdtp_tag(fdtp) (fdtp_get_header(fdtp, tag)) +#define fdtp_len(fdtp) (fdtp_get_header(fdtp, len)) +#define fdtp_nameoff(fdtp) (fdtp_get_header(fdtp, nameoff)) + +// Load fdt32 (big-endian) +static inline uint32_t fdt32_ld(const fdt32_t *p) +{ + const uint8_t *bp = (const uint8_t *)p; + + return ((uint32_t)bp[0] << 24) + | ((uint32_t)bp[1] << 16) + | ((uint32_t)bp[2] << 8) + | bp[3]; +} + +typedef uint32_t (*fdt_callback)(int type, char *name, char *data, uint32_t size); +uint32_t print_dtb(int type, char *name, char *data, uint32_t size) ; +uint32_t get_initramfs_addr(int type, char *name, char *data, uint32_t size); +uint32_t fdt_traverse(fdt_callback cb); + +long get_fdt_end(); + + +#endif /* _FDT_H */ diff --git a/lab6/kernel/include/helper.h b/lab6/kernel/include/helper.h new file mode 100644 index 000000000..5b6a6d69d --- /dev/null +++ b/lab6/kernel/include/helper.h @@ -0,0 +1,16 @@ +#ifndef HELPER_H +#define HELPER_H + +void hex_to_string(unsigned int, char*); +int same(char*, char*); + +void substr(char*, char*, int, int); +int strlen(char*); +void strcpy(char*, char*, int); + +unsigned long stoi(char*); +void delay (unsigned long long); + +void memset(char*, char, int); + +#endif diff --git a/lab6/kernel/include/kernel.h b/lab6/kernel/include/kernel.h new file mode 100644 index 000000000..d2e9fcc54 --- /dev/null +++ b/lab6/kernel/include/kernel.h @@ -0,0 +1,6 @@ +#ifndef KERNEL_H +#define KERNEL_H + +void kernel_begin(char*); + +#endif diff --git a/lab6/kernel/include/loader.h b/lab6/kernel/include/loader.h new file mode 100644 index 000000000..70dcbe9d7 --- /dev/null +++ b/lab6/kernel/include/loader.h @@ -0,0 +1,6 @@ +#ifndef LOADER_H +#define LOADER_H + +void load_kernel(); + +#endif diff --git a/lab6/kernel/include/mail.h b/lab6/kernel/include/mail.h new file mode 100644 index 000000000..38340b34c --- /dev/null +++ b/lab6/kernel/include/mail.h @@ -0,0 +1,23 @@ +#define MMIO_BASE 0x3F000000 + 0xffff000000000000 +#define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880) +#define MAILBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0)) +#define MAILBOX_POLL ((volatile unsigned int*)(VIDEOCORE_MBOX+0x10)) +#define MAILBOX_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX+0x14)) +#define MAILBOX_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX+0x18)) +#define MAILBOX_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX+0x1C)) +#define MAILBOX_WRITE ((volatile unsigned int*)(VIDEOCORE_MBOX+0x20)) +#define MAILBOX_RESPONSE 0x80000000 +#define MAILBOX_FULL 0x80000000 +#define MAILBOX_EMPTY 0x40000000 + +#define GET_BOARD_REVISION 0x00010002 +#define GET_ARM_MEMORY 0x00010005 +#define REQUEST_CODE 0x00000000 +#define REQUEST_SUCCEED 0x80000000 +#define REQUEST_FAILED 0x80000001 +#define TAG_REQUEST_CODE 0x00000000 +#define END_TAG 0x00000000 + +unsigned int get_board_revision(); +int get_arm_memory(unsigned int*); +int mailbox_call(unsigned int*, unsigned char); diff --git a/lab6/kernel/include/mini_uart.h b/lab6/kernel/include/mini_uart.h new file mode 100644 index 000000000..853929005 --- /dev/null +++ b/lab6/kernel/include/mini_uart.h @@ -0,0 +1,28 @@ +#ifndef _MINI_UART_H +#define _MINI_UART_H + +#include +#include + +void uart_init ( void ); +char uart_recv ( void ); +void uart_send ( char c ); +void uart_recv_string( char* buf ); +uint32_t uart_recv_uint(void); +void uart_printf(char* fmt, ...); +void uart_send_num(int64_t, int, int); + +void uart_irq_on(); +void uart_irq_off(); +void uart_irq_send(char*, int); +char uart_irq_read(); + +void change_read_irq(int); +void change_write_irq(int); + +void irq(int); + +void recv_handler(); +void write_handler(); + +#endif /*_MINI_UART_H */ diff --git a/lab6/kernel/include/mm.h b/lab6/kernel/include/mm.h new file mode 100644 index 000000000..784ac4b88 --- /dev/null +++ b/lab6/kernel/include/mm.h @@ -0,0 +1,19 @@ +#ifndef _MM_H +#define _MM_H + +#define PAGE_SHIFT 12 +#define TABLE_SHIFT 9 +#define SECTION_SHIFT (PAGE_SHIFT + TABLE_SHIFT) + +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define SECTION_SIZE (1 << SECTION_SHIFT) + +#define LOW_MEMORY (2 * SECTION_SIZE) + +#ifndef __ASSEMBLER__ + +void memzero(unsigned long src, unsigned long n); + +#endif + +#endif /*_MM_H */ diff --git a/lab6/kernel/include/mmio.h b/lab6/kernel/include/mmio.h new file mode 100644 index 000000000..c272df237 --- /dev/null +++ b/lab6/kernel/include/mmio.h @@ -0,0 +1,8 @@ +#ifndef MMIO_H +#define MMIO_H + +void mmio_write(long reg, unsigned int data); + +unsigned int mmio_read(long reg); + +#endif diff --git a/lab6/kernel/include/mmu.h b/lab6/kernel/include/mmu.h new file mode 100644 index 000000000..8bfa0eb1b --- /dev/null +++ b/lab6/kernel/include/mmu.h @@ -0,0 +1,20 @@ +#ifndef MMU_H +#define MMU_H + +void set_up_identity_paging(); +void kernel_finer_gran(); + +void map_page(long*, long, long, long); +void switch_page(); + +long pa2va (long); +long va2pa (long); + +long trans(long); +long trans_el0(long); + +void setup_peripheral_identity(long*); + +void three_level_translation_init(); + +#endif diff --git a/lab6/kernel/include/mmu_regs.h b/lab6/kernel/include/mmu_regs.h new file mode 100644 index 000000000..9b97b70f1 --- /dev/null +++ b/lab6/kernel/include/mmu_regs.h @@ -0,0 +1,20 @@ +#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_ACCESS (1 << 10) +#define PD_KERNEL_USER_ACCESS (1 << 6) +#define BOOT_PGD_ATTR PD_TABLE +#define BOOT_PUD_ATTR (PD_ACCESS | (MAIR_IDX_DEVICE_nGnRnE << 2) | PD_BLOCK) + +#define VT_OFFSET 0xffff000000000000 + +//reference +#define ENTRY_ADDR_MASK 0xfffffffff000L diff --git a/lab6/kernel/include/peripherals/base.h b/lab6/kernel/include/peripherals/base.h new file mode 100644 index 000000000..ff5bda485 --- /dev/null +++ b/lab6/kernel/include/peripherals/base.h @@ -0,0 +1,6 @@ +#ifndef _P_BASE_H +#define _P_BASE_H + +#define PBASE 0xffff00003F000000 + +#endif /*_P_BASE_H */ diff --git a/lab6/kernel/include/peripherals/gpio.h b/lab6/kernel/include/peripherals/gpio.h new file mode 100644 index 000000000..5e9af26af --- /dev/null +++ b/lab6/kernel/include/peripherals/gpio.h @@ -0,0 +1,12 @@ +#ifndef _P_GPIO_H +#define _P_GPIO_H + +#include "peripherals/base.h" + +#define GPFSEL1 (PBASE+0x00200004) +#define GPSET0 (PBASE+0x0020001C) +#define GPCLR0 (PBASE+0x00200028) +#define GPPUD (PBASE+0x00200094) +#define GPPUDCLK0 (PBASE+0x00200098) + +#endif /*_P_GPIO_H */ diff --git a/lab6/kernel/include/peripherals/mini_uart.h b/lab6/kernel/include/peripherals/mini_uart.h new file mode 100644 index 000000000..af95a3bee --- /dev/null +++ b/lab6/kernel/include/peripherals/mini_uart.h @@ -0,0 +1,19 @@ +#ifndef _P_MINI_UART_H +#define _P_MINI_UART_H + +#include "peripherals/base.h" + +#define AUX_ENABLES (PBASE+0x00215004) +#define AUX_MU_IO_REG (PBASE+0x00215040) +#define AUX_MU_IER_REG (PBASE+0x00215044) +#define AUX_MU_IIR_REG (PBASE+0x00215048) +#define AUX_MU_LCR_REG (PBASE+0x0021504C) +#define AUX_MU_MCR_REG (PBASE+0x00215050) +#define AUX_MU_LSR_REG (PBASE+0x00215054) +#define AUX_MU_MSR_REG (PBASE+0x00215058) +#define AUX_MU_SCRATCH (PBASE+0x0021505C) +#define AUX_MU_CNTL_REG (PBASE+0x00215060) +#define AUX_MU_STAT_REG (PBASE+0x00215064) +#define AUX_MU_BAUD_REG (PBASE+0x00215068) + +#endif /*_P_MINI_UART_H */ diff --git a/lab6/kernel/include/reboot.h b/lab6/kernel/include/reboot.h new file mode 100644 index 000000000..43e0ed91e --- /dev/null +++ b/lab6/kernel/include/reboot.h @@ -0,0 +1,22 @@ +#ifndef REBOOT_H +#define REBOOT_H + +#define PM_PASSWORD 0x5a000000 +#define PM_RSTC 0x3F10001c +#define PM_WDOG 0x3F100024 + +void set(long addr, unsigned int value) { + volatile unsigned int* point = (unsigned int*)addr; + *point = value; +} + +void reset(int tick) { // reboot after watchdog timer expire + set(PM_RSTC, PM_PASSWORD | 0x20); // full reset + set(PM_WDOG, PM_PASSWORD | tick); // number of watchdog tick +} + +void cancel_reset() { + set(PM_RSTC, PM_PASSWORD | 0); // cancel reset + set(PM_WDOG, PM_PASSWORD | 0); // number of watchdog tick +} +#endif diff --git a/lab6/kernel/include/set.h b/lab6/kernel/include/set.h new file mode 100644 index 000000000..3e87e51b6 --- /dev/null +++ b/lab6/kernel/include/set.h @@ -0,0 +1,168 @@ +#ifndef SET_H +#define SET_H + +#include "mini_uart.h" +#include "alloc.h" + +typedef struct nodeList { + int key; + struct nodeList *left; + struct nodeList *right; + int height; +} nodeList; + +int height(nodeList *N) { + if (N == NULL) return 0; + return N->height; +} + +int max(int a, int b) { + return (a > b) ? a : b; +} + +nodeList* newNode(int key) { + nodeList *node = (nodeList*) simple_malloc(1, sizeof(nodeList)); + node->key = key; + node->left = NULL; + node->right = NULL; + node->height = 1; + return(node); +} + +nodeList* rightRotate(nodeList *y) { + nodeList *x = y->left; + nodeList *T2 = x->right; + + x->right = y; + y->left = T2; + + y->height = max(height(y->left), height(y->right)) + 1; + x->height = max(height(x->left), height(x->right)) + 1; + + return x; +} + +nodeList* leftRotate(nodeList *x) { + nodeList *y = x->right; + nodeList *T2 = y->left; + + y->left = x; + x->right = T2; + + x->height = max(height(x->left), height(x->right)) + 1; + y->height = max(height(y->left), height(y->right)) + 1; + + return y; +} + +int getBalance(nodeList *N) { + if (N == NULL) return 0; + return height(N->left) - height(N->right); +} + +nodeList* insert(nodeList* node, int key) { + if (node == NULL) return newNode(key); + + if (key < node->key) + node->left = insert(node->left, key); + else if (key > node->key) + node->right = insert(node->right, key); + else + return node; + + node->height = 1 + max(height(node->left), height(node->right)); + int balance = getBalance(node); + + if (balance > 1 && key < node->left->key) + return rightRotate(node); + + if (balance < -1 && key > node->right->key) + return leftRotate(node); + + if (balance > 1 && key > node->left->key) { + node->left = leftRotate(node->left); + return rightRotate(node); + } + + if (balance < -1 && key < node->right->key) { + node->right = rightRotate(node->right); + return leftRotate(node); + } + + return node; +} + +nodeList * minValueNode(nodeList* node) { + nodeList* current = node; + + while (current->left != NULL) + current = current->left; + + return current; +} + +nodeList* deleteNode(nodeList* root, int key) { + if (root == NULL) return root; + + if ( key < root->key ) + root->left = deleteNode(root->left, key); + else if( key > root->key ) + root->right = deleteNode(root->right, key); + else { + if( (root->left == NULL) || (root->right == NULL) ) { + nodeList *temp = root->left ? root->left : root->right; + + if (temp == NULL) { + temp = root; + root = NULL; + } else + *root = *temp; + } else { + nodeList* temp = minValueNode(root->right); + root->key = temp->key; + root->right = deleteNode(root->right, temp->key); + } + } + + if (root == NULL) + return root; + + root->height = 1 + max(height(root->left), height(root->right)); + int balance = getBalance(root); + + if (balance > 1 && getBalance(root->left) >= 0) + return rightRotate(root); + + if (balance > 1 && getBalance(root->left) < 0) { + root->left = leftRotate(root->left); + return rightRotate(root); + } + + if (balance < -1 && getBalance(root->right) <= 0) + return leftRotate(root); + + if (balance < -1 && getBalance(root->right) > 0) { + root->right = rightRotate(root->right); + return leftRotate(root); + } + + return root; +} + +// Function to get any arbitrary element +int getAnyElement(nodeList* root) { + if (root != NULL) { + return root->key; // Simply returns the root key as an arbitrary element + } + return -1; // or handle appropriately if the tree is empty +} + +void preOrder(nodeList* root) { + if (root != NULL) { + uart_printf("%d ", root->key); + preOrder(root->left); + preOrder(root->right); + } +} + +#endif diff --git a/lab6/kernel/include/shell.h b/lab6/kernel/include/shell.h new file mode 100644 index 000000000..43d937d48 --- /dev/null +++ b/lab6/kernel/include/shell.h @@ -0,0 +1,3 @@ + + +void shell_begin(char*); diff --git a/lab6/kernel/include/signal.h b/lab6/kernel/include/signal.h new file mode 100644 index 000000000..3cbec92d3 --- /dev/null +++ b/lab6/kernel/include/signal.h @@ -0,0 +1,8 @@ +#ifndef SIGNAL_H +#define SIGNAL_H + +void handle_signal(void*); +void sigkill(); +void signal_handler_wrapper(void*); + +#endif diff --git a/lab6/kernel/include/system_call.h b/lab6/kernel/include/system_call.h new file mode 100644 index 000000000..72722f7ab --- /dev/null +++ b/lab6/kernel/include/system_call.h @@ -0,0 +1,29 @@ +#ifndef SYSTEM_CALL_H +#define SYSTEM_CALL_H + +#include "exception.h" +#include + +typedef void (*handler) (void); + +int do_getpid(); +size_t do_uart_read(char buf[], size_t size); +size_t do_uart_write(char buf[], size_t size); +int do_exec(char* name, char *argv[]); +int do_fork(trapframe_t*); +void do_exit(); +int do_mbox_call(unsigned char ch, unsigned int *mbox); +void do_kill(int pid); +void do_signal(int, handler); +void do_sigkill(int, int); + +void from_el1_to_fork_test(); +void simple_fork_test(); + +// for debug purpose +void get_sp(); +void output_sp(void*); + +void im_fineee(); + +#endif diff --git a/lab6/kernel/include/task.h b/lab6/kernel/include/task.h new file mode 100644 index 000000000..7eda77a58 --- /dev/null +++ b/lab6/kernel/include/task.h @@ -0,0 +1,16 @@ +#ifndef TASKLIST_H +#define TASKLIST_H + +typedef void(*task_callback)(void); + +typedef struct task { + struct task *next; + task_callback callback; + int p, started; +} task; + +void execute_tasks(); +void create_task(task_callback callback,int priority); +void enqueue_task(task *new_task); + +#endif diff --git a/lab6/kernel/include/thread.h b/lab6/kernel/include/thread.h new file mode 100644 index 000000000..710d71698 --- /dev/null +++ b/lab6/kernel/include/thread.h @@ -0,0 +1,30 @@ +#ifndef THREAD_H +#define THREAD_H + +typedef struct thread { + unsigned long long reg[10]; + void* fp; + void* lr; + void* sp; + long* PGD; + void* stack_start; + void* kstack_start; + void* sstack_start; + int state, id; + struct thread* next; + struct thread* prev; + void* signal_handler[10]; // sigid at most 9 + int signal[10]; + void* code; + int code_size; +} thread; + +void thread_init(); +void thread_test(); +void kill_zombies(); +void idle(); +void schedule(); +int thread_create(void*); +void kill_thread(int); + +#endif diff --git a/lab6/kernel/include/timer.h b/lab6/kernel/include/timer.h new file mode 100644 index 000000000..cafc570b3 --- /dev/null +++ b/lab6/kernel/include/timer.h @@ -0,0 +1,17 @@ +#ifndef TIMER_H +#define TIMER_H + +typedef void (*timer_callback)(char*); + +typedef struct timer { + struct timer* next; + char data[100]; + timer_callback callback; + unsigned long long exp; +} timer; + +timer* create_timer(unsigned long long exp, char* str); +void print_data(char* str); +void set_timeout(unsigned long long s, char* str); + +#endif diff --git a/lab6/kernel/include/utils.h b/lab6/kernel/include/utils.h new file mode 100644 index 000000000..95dcbaa5e --- /dev/null +++ b/lab6/kernel/include/utils.h @@ -0,0 +1,17 @@ +#ifndef _BOOT_H +#define _BOOT_H + +extern void put32 ( unsigned long, unsigned int ); +extern unsigned int get32 ( unsigned long ); + +#define write_sysreg(r, __val) ({ \ + asm volatile("msr " #r ", %0" ::"r"(__val)); \ +}) + +#define read_sysreg(r) ({ \ + unsigned long __val; \ + asm volatile("mrs %0, " #r : "=r" (__val)); \ + __val; \ +}) + +#endif /*_BOOT_H */ diff --git a/lab6/kernel/kernel8.img b/lab6/kernel/kernel8.img new file mode 100755 index 000000000..f5a3fe282 Binary files /dev/null and b/lab6/kernel/kernel8.img differ diff --git a/lab6/kernel/src/alloc.c b/lab6/kernel/src/alloc.c new file mode 100644 index 000000000..e1ecc2dae --- /dev/null +++ b/lab6/kernel/src/alloc.c @@ -0,0 +1,258 @@ +#include "alloc.h" +#include "mini_uart.h" +#include "fdt.h" +#include "set.h" +#include "cpio.h" +#include "mmu.h" + +/* +total: [0x0, 0x3c000000] +each page is 4KB, thus 0x3c000 pages +kernel: [0x80000, 0x100000] +Spin tables for multicore boot [0x0000, 0x1000] +initramfs: determined after parsing +devicetree: determined after parsing +size for managing: starting from 0x100001 +*/ + + +extern char* _cpio_file; +extern char* fdt_addr; + +struct node { + int sz, par; +}; + +/* +struct nodeList { + struct nodeList* next; + int pos; +}; + +struct nodeList* node_arr[21]; +// node_arr[20] for pool +*/ + + +nodeList* node_arr[21]; + +char* manage_start = (char*)0x100001; +char* now = (char*)0x100001; +char* limit; +char* frame_sz; +int* frame_par; + +char* frame_pool; + +const int arr_size = 0x3c000; + +void reserve(unsigned long l, unsigned long r) { + + if (frame_par == 0) { + uart_printf ("manager have not initialized\r\n"); + return; + } + + unsigned long l_frame = l >> 12; + unsigned long r_frame = r >> 12; + + for (unsigned long i = l_frame; i <= r_frame; i ++) { + frame_par[i] = -1; + } +} + +void* simple_malloc(int num, int size) { + if ((int)now % size != 0) now += size - (int)now % size; // align + if (limit && now + num * size >= limit) { + uart_printf ("you're allocator is going to fuck you\r\n"); + } + now += num * size; + return pa2va((char*)(now - num * size)); +} + +void print_node_list() { + for (int i = 0; i < 6; i ++) { + uart_printf("size %d: \r\n", i); + preOrder(node_arr[i]); + uart_printf("\r\n"); + } +} + +void print_pool() { + uart_printf("cur pool:\r\n"); + preOrder(node_arr[20]); + uart_printf("\r\n"); +} + +void add_node_list(int ind, int pos) { + node_arr[ind] = insert(node_arr[ind], pos); +} + +void remove_node_list(int ind, int pos) { + node_arr[ind] = deleteNode(node_arr[ind], pos); +} + +int pop_node_list(int ind) { + int t = getAnyElement(node_arr[ind]); + if (t == -1) { + return t; + } + node_arr[ind] = deleteNode(node_arr[ind], t); + return t; +} + + +void manage_init() { + frame_pool = simple_malloc(arr_size, sizeof(char)); + for (int i = 0; i < arr_size; i ++) { + frame_pool[i] = 0; + } + frame_par = simple_malloc(arr_size, sizeof(int)); + frame_sz = simple_malloc(arr_size, sizeof(char)); + for (int i = 0; i < arr_size; i ++) { + frame_par[i] = i; + frame_sz[i] = 0; + } + for (int i = 0; i <= 20; i ++) { + node_arr[i] = NULL; + } + + reserve (0, 0x1000); + reserve (0x1000, 0x1fff); // ttbr1 + reserve (0x2000, 0x2fff); + reserve (0x3000, 0x3fff); + reserve (0x4000, 0x4fff); + reserve (0x80000, 0x100000); + reserve (manage_start, now + sizeof(struct nodeList) * 10000); + limit = now + sizeof(struct nodeList) * 10000; + // TODO This is SHIT, might potentially cause problem + uart_printf ("%llx %llx %llx %llx\r\n", fdt_addr, get_fdt_end(), _cpio_file, get_cpio_end); + reserve (va2pa(fdt_addr), va2pa(get_fdt_end())); + reserve (va2pa(_cpio_file), va2pa(get_cpio_end())); + + for (int i = 1; (1 << i) <= arr_size ; i ++) { + for (int j = 0; j + (1 << i) <= arr_size; j += (1 << i)) { + int l = j, r = j + (1 << (i - 1)); + if (frame_par[l] == l && frame_par[r] == r) { + frame_par[r] = l; + frame_sz[l] ++; + } + } + } + // build the initial layout + + for (int i = 0; i < arr_size; i ++) { + if (frame_par[i] == i) { + int sz = frame_sz[i]; + add_node_list(sz, i); + } + } +} + +void* frame_malloc(size_t size) { + int sz = 0, t = 1; + while (t < size) { + t <<= 1; + sz ++; + } + + int pos = 0, tsz; + for (tsz = sz; tsz < 20; tsz ++) { + pos = pop_node_list(tsz); + if (pos != -1) { + break; + } + } + + if (pos == -1) { + return 0; + } + + while (tsz > sz) { + int pt = pos + (1 << (tsz - 1)); + frame_par[pt] = pt; + frame_sz[pos] --; + + remove_node_list(tsz, pos); + tsz --; + add_node_list(tsz, pos); + add_node_list(tsz, pt); + + } + + if (frame_sz[pos] != sz) { + uart_printf("Something went wrong at malloc...\r\n"); + } + remove_node_list(sz, pos); + frame_par[pos] = -1; + return (void*)(pos << 12); +} + +void frame_free(char* addr) { + int p = (int)addr >> 12; + frame_par[p] = p; + add_node_list (frame_sz[p], p); + while (1) { + int sz = frame_sz[p]; + if ((p / (1 << sz)) % 2) { + p -= (1 << sz); + } + + int l = p, r = p + (1 << sz); + if (r >= arr_size) { + break; + } + + if (frame_par[l] == l && frame_par[r] == r) { + remove_node_list(sz, l); + remove_node_list(sz, r); + frame_sz[l] ++; + add_node_list(sz + 1, l); + p = l; + } + else { + break; + } + } +} + +const int chunk_size = 512; +// should be divisor of 4096 + +void* my_malloc(size_t size) { + if (size > chunk_size) { + return pa2va(frame_malloc((size + 4096 - 1) / 4096)); + } + if (node_arr[20] == NULL) { + char* t = frame_malloc(1); + for (char* i = t; i < t + 4096; i += chunk_size) { + add_node_list(20, i); + } + } + int pos = pop_node_list(20); + if (pos == -1) { + uart_printf ("Failing to get a small chunk\r\n"); + return 0; + } + frame_pool[pos >> 12] ++; + if (pos == 0) { + uart_printf ("something wrong\r\n"); + } + return pa2va(pos); +} + +void my_free(char* addr) { + int pos = (int)addr >> 12; + if (!frame_pool[pos]) { + frame_free(addr); + return; + } + add_node_list(20, addr); + frame_pool[pos] --; + if (frame_pool[pos] == 0) { + for (int i = pos << 12; i < (pos << 12) + 4096; i += chunk_size) { + remove_node_list(20, i); + } + frame_free(pos << 12); + } +} diff --git a/lab6/kernel/src/boot.S b/lab6/kernel/src/boot.S new file mode 100644 index 000000000..836568cd9 --- /dev/null +++ b/lab6/kernel/src/boot.S @@ -0,0 +1,301 @@ +#include "mmu_regs.h" + +#define CORE0_TIMER_IRQ_CTRL 0xffff000040000040 + +.section ".text.boot" + +.globl _start +_start: + mov x19, x0 + + mrs x0, mpidr_el1 + and x0, x0,#0xFF // Check processor id + cbz x0, setup_tcr_el1 // Hang for all non-primary CPU + b proc_hang + +proc_hang: + b proc_hang + +setup_tcr_el1: + bl from_el2_to_el1 + + 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 // PGD's page frame at 0x1000 + mov x1, 0x2000 // PUD's page frame at 0x2000 + + ldr x2, = BOOT_PGD_ATTR + orr x2, x1, x2 // combine the physical address of next level page with attribute. + str x2, [x0] + + ldr x2, = BOOT_PUD_ATTR + mov x3, 0x00000000 + orr x3, x2, x3 + str x3, [x1] // 1st 1GB mapped by the 1st entry of PUD + mov x3, 0x40000000 + orr x3, x2, x3 + str x3, [x1, 8] // 2nd 1GB mapped by the 2nd entry of PUD + + msr ttbr0_el1, x0 // load PGD to the bottom translation-based register. + msr ttbr1_el1, x0 // also load PGD to the upper translation based register. + + mov sp, 0x100000 + bl three_level_translation_init + + mrs x2, sctlr_el1 + orr x2 , x2, 1 + msr sctlr_el1, x2 // enable MMU, cache remains disabled + + ldr x2,= boot_rest + br x2 + +boot_rest: + + + ldr x1, =0xffff000000100000 + mov sp, x1 + + adr x0, bss_begin + adr x1, bss_end + sub x1, x1, x0 + bl memzero + + bl set_exception_vector_table + + // bl from_el1_to_el0 + + // bl core_timer_enable + + msr daifclr, 0xf // enable el1 interrupt + + mov x0, x19 // get fdt back + bl kernel_begin + b proc_hang // should never come here + + +from_el2_to_el1: + mov x0, (1 << 31) + msr hcr_el2, x0 + mov x0, 5 + msr spsr_el2, x0 + msr elr_el2, lr + eret + +// save general registers to stack +.macro save_all + sub sp, sp, 32 * 10 + stp x0, x1, [sp ,16 * 0] + stp x2, x3, [sp ,16 * 1] + stp x4, x5, [sp ,16 * 2] + stp x6, x7, [sp ,16 * 3] + stp x8, x9, [sp ,16 * 4] + stp x10, x11, [sp ,16 * 5] + stp x12, x13, [sp ,16 * 6] + stp x14, x15, [sp ,16 * 7] + stp x16, x17, [sp ,16 * 8] + stp x18, x19, [sp ,16 * 9] + stp x20, x21, [sp ,16 * 10] + stp x22, x23, [sp ,16 * 11] + stp x24, x25, [sp ,16 * 12] + stp x26, x27, [sp ,16 * 13] + stp x28, x29, [sp ,16 * 14] + str x30, [sp, 16 * 15] + // empty 8 bytes + + mrs x0, SPSR_EL1 + mrs x1, ELR_EL1 + stp x0, x1, [sp, 16 * 16] + mrs x0, sp_el0 + str x0, [sp, 16 * 17] + // nested shit + +.endm + +// load general registers from stack +.macro load_all + ldp x0, x1, [sp, 16 * 16] + msr SPSR_EL1, x0 + msr ELR_EL1, x1 + ldr x0, [sp, 16 * 17] + msr sp_el0, 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] + 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] + ldr x30, [sp, 16 * 15] + + add sp, sp, 32 * 10 +.endm + +exception_handler: + save_all + mov x0, sp + bl exception_entry + load_all + eret + +.global core_timer_enable +core_timer_enable: + mov x0, 1 + msr cntp_ctl_el0, x0 + // mrs x0, cntfrq_el0 + mov x0, 0 + msr cntp_tval_el0, x0 + mov x0, 2 + ldr x1, =CORE0_TIMER_IRQ_CTRL + str w0, [x1] + mrs x0, cntkctl_el1 + orr x0, x0, #1 + msr cntkctl_el1, x0 + + ret + +core_timer_handler: + save_all + bl core_timer_entry + load_all + eret + +general_irq_handler: + save_all + // mov x0, sp + // bl debug + bl c_general_irq_handler + // mov x0, sp + // bl debug + // bl handle_signal + load_all + eret + +system_call_handler: + cmp x8, #10 + beq system_call_handler_end + save_all + mov x0, sp + bl c_system_call_handler +system_call_handler_end: + load_all + eret + +sig_return_handler: + load_all + eret + +undefined_exception: + bl c_undefined_exception + +.align 11 +.global exception_vector_table +exception_vector_table: + b undefined_exception + .align 7 + b undefined_exception + .align 7 + b undefined_exception + .align 7 + b undefined_exception + .align 7 + + b system_call_handler + .align 7 + b general_irq_handler + .align 7 + b undefined_exception + .align 7 + b undefined_exception + .align 7 + + b system_call_handler + .align 7 + b general_irq_handler + .align 7 + b undefined_exception + .align 7 + b undefined_exception + .align 7 + + b undefined_exception + .align 7 + b undefined_exception + .align 7 + b undefined_exception + .align 7 + b undefined_exception + .align 7 + +set_exception_vector_table: + adr x0, exception_vector_table + msr vbar_el1, x0 + ret + +/* +.global to_el0_with_timer +to_el0_with_timer: + mov x29, lr + bl from_el1_to_el0 + bl core_timer_enable + b proc_hang + mov lr, x29 + ret +*/ + +.global switch_to +switch_to: + stp x19, x20, [x0, 16 * 0] + stp x21, x22, [x0, 16 * 1] + stp x23, x24, [x0, 16 * 2] + stp x25, x26, [x0, 16 * 3] + stp x27, x28, [x0, 16 * 4] + stp fp, lr, [x0, 16 * 5] + mov x9, sp + str x9, [x0, 16 * 6] + + ldp x19, x20, [x1, 16 * 0] + ldp x21, x22, [x1, 16 * 1] // x0, x1 are 0xffff shits + ldp x23, x24, [x1, 16 * 2] + ldp x25, x26, [x1, 16 * 3] + ldp x27, x28, [x1, 16 * 4] + ldp fp, lr, [x1, 16 * 5] + ldr x9, [x1, 16 * 6] + mov sp, x9 + msr tpidr_el1, x1 + + ldr x2, [x1, 16 * 6 + 8] + dsb ish // ensure write has completed + msr ttbr0_el1, x2 // switch translation based address. + tlbi vmalle1is // invalidate all TLB entries + dsb ish // ensure completion of TLB invalidatation + isb // clear pipeline + + ret + +.global get_current +get_current: + mrs x0, tpidr_el1 + ret + +.global ret_from_fork_child +ret_from_fork_child: + load_all + // bl im_fineee + // msr DAIFclr, 0xf + eret diff --git a/lab6/kernel/src/config.txt b/lab6/kernel/src/config.txt new file mode 100644 index 000000000..279349696 --- /dev/null +++ b/lab6/kernel/src/config.txt @@ -0,0 +1,2 @@ +kernel_old=1 +disable_commandline_tags=1 diff --git a/lab6/kernel/src/cpio.c b/lab6/kernel/src/cpio.c new file mode 100644 index 000000000..e395d2df4 --- /dev/null +++ b/lab6/kernel/src/cpio.c @@ -0,0 +1,217 @@ +#include +#include +#include "cpio.h" +#include "mini_uart.h" +#include "helper.h" +#include "alloc.h" +#include "thread.h" +#include "mmu.h" +#include "utils.h" + +extern char* _cpio_file; +char buff[1024]; + +uint8_t hex_char_to_bin(char c) { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'a' && c <= 'f') return c - 'a' + 10; + if (c >= 'A' && c <= 'F') return c - 'A' + 10; + return 0; // Not a valid hexadecimal character +} + +uint64_t hex_to_bin(const char* hex) { + uint64_t result = 0; + for(int i = 0; i < 8; i ++) { + result = (result << 4) | hex_char_to_bin(hex[i]); + } + return result; +} + +void* cpio_find(char* name) { + char* cpio_start = _cpio_file; + struct cpio_newc_header* header = (struct cpio_newc_header*)cpio_start; + substr(buff, header -> c_magic, 0, 5); + while (same(buff, "070701")) { + // Convert c_namesize and c_filesize from ASCII hex to binary + uint64_t namesize = hex_to_bin(header->c_namesize); + uint64_t filesize = hex_to_bin(header->c_filesize); + + // Calculate the start of the file name and file data + char* filename = (char*)(header + 1); + char* filedata = filename + namesize; + filedata = (char*)((uintptr_t)filedata + ((4 - ((uintptr_t)filedata & 3)) & 3)); // Align to next 4-byte boundary + + substr(buff, filename, 0, namesize - 1); + if (same(buff, "TRAILER!!!")) { + break; // End of archive + } + + if (same(buff, name)) { + return filedata; + } + substr(buff, filename, 0, namesize - 1); + + // Move to the next header, aligning as necessary + header = (struct cpio_newc_header*)(filedata + filesize); + header = (struct cpio_newc_header*)((uintptr_t)header + ((4 - ((uintptr_t)header & 3)) & 3)); // Align to next 4-byte boundary + substr(buff, header -> c_magic, 0, 5); + } + return 0; +} + +void cpio_parse_ls() { + char* cpio_start = _cpio_file; + struct cpio_newc_header* header = (struct cpio_newc_header*)cpio_start; + substr(buff, header -> c_magic, 0, 5); + while (same(buff, "070701")) { + + // Convert c_namesize and c_filesize from ASCII hex to binary + uint64_t namesize = hex_to_bin(header->c_namesize); + uint64_t filesize = hex_to_bin(header->c_filesize); + + // Calculate the start of the file name and file data + char* filename = (char*)(header + 1); + char* filedata = filename + namesize; + filedata = (char*)((uintptr_t)filedata + ((4 - ((uintptr_t)filedata & 3)) & 3)); // Align to next 4-byte boundary + + substr(buff, filename, 0, namesize - 1); + if (same(buff, "TRAILER!!!")) { + break; // End of archive + } + uart_printf("%s\r\n", buff); + + // Move to the next header, aligning as necessary + header = (struct cpio_newc_header*)(filedata + filesize); + header = (struct cpio_newc_header*)((uintptr_t)header + ((4 - ((uintptr_t)header & 3)) & 3)); // Align to next 4-byte boundary + substr(buff, header -> c_magic, 0, 5); + } +} + +void cpio_parse_cat(char* name) { + char* cpio_start = _cpio_file; + struct cpio_newc_header* header = (struct cpio_newc_header*)cpio_start; + substr(buff, header -> c_magic, 0, 5); + while (same(buff, "070701")) { + // Convert c_namesize and c_filesize from ASCII hex to binary + uint64_t namesize = hex_to_bin(header->c_namesize); + uint64_t filesize = hex_to_bin(header->c_filesize); + + // Calculate the start of the file name and file data + char* filename = (char*)(header + 1); + char* filedata = filename + namesize; + filedata = (char*)((uintptr_t)filedata + ((4 - ((uintptr_t)filedata & 3)) & 3)); // Align to next 4-byte boundary + + substr(buff, filename, 0, namesize - 1); + if (same(buff, "TRAILER!!!")) { + break; // End of archive + } + + if (same(buff, name)) { + uart_printf ("Cat %d\r\n", filesize); + substr(buff, filedata, 0, filesize - 1); + uart_printf("%s\r\n", buff); + } + substr(buff, filename, 0, namesize - 1); + + // Move to the next header, aligning as necessary + header = (struct cpio_newc_header*)(filedata + filesize); + header = (struct cpio_newc_header*)((uintptr_t)header + ((4 - ((uintptr_t)header & 3)) & 3)); // Align to next 4-byte boundary + substr(buff, header -> c_magic, 0, 5); + } +} + +extern thread* get_current(); + +void cpio_load(char* str) { + irq(0); + thread_init(); + thread* cur = get_current(); + uart_printf ("cur: %llx\r\n", cur); + long xxx = read_sysreg(tpidr_el1); + uart_printf ("xxx: %llx\r\n", xxx); + + void* pos = cpio_find(str); + cur -> code = my_malloc(4096 * 128); + cur -> code_size = 4096 * 128; + for (int i = 0; i < cur -> code_size; i ++) { + ((char*)cur -> code)[i] = ((char*)pos)[i]; + } + + uart_printf ("%llx, %llx, %llx\r\n", cur -> PGD, pa2va(cur -> PGD), &(cur -> PGD)); + + setup_peripheral_identity(pa2va(cur -> PGD)); + for (int i = 0; i < cur -> code_size; i += 4096) { + map_page(pa2va(cur -> PGD), i, va2pa(cur -> code) + i, (1 << 6)); + } + for (int i = 0; i < 4; i ++) { + map_page (pa2va(cur -> PGD), 0xffffffffb000L + i * 4096, va2pa(cur -> stack_start) + i * 4096, (1 << 6)); + } + + uart_printf ("%llx\r\n", cur -> PGD); + asm volatile("dsb ish"); + write_sysreg(ttbr0_el1, cur -> PGD); + asm volatile("dsb ish"); + asm volatile("tlbi vmalle1is"); + asm volatile("dsb ish"); + asm volatile("isb"); + + cur -> code = 0; + cur -> stack_start = 0xffffffffb000L; + + long ttbr1 = read_sysreg(ttbr1_el1); + long ttbr0 = read_sysreg(ttbr0_el1); + uart_printf ("TTBR0: %llx, TTBR1: %llx\r\n", ttbr0, ttbr1); + + uart_printf ("cur -> PGD %llx\r\n", cur -> PGD); + + // uart_printf("Running code from %llx, which is %llx\n", cur -> code, trans(cur -> code)); + + + uart_printf ("uart printf: %llx\r\n", uart_printf); + + uart_printf("Running code from %llx, which is %llx\n", cur -> code, trans_el0(cur -> code)); + ttbr1 = read_sysreg(ttbr1_el1); + ttbr0 = read_sysreg(ttbr0_el1); + uart_printf ("TTBR0: %llx, TTBR1: %llx, &TTBR0: %llx\r\n", ttbr0, ttbr1, &ttbr0); + + write_sysreg(spsr_el1, 0); + write_sysreg(elr_el1, cur -> code); + write_sysreg(sp_el0, 0xfffffffff000L); + uart_printf ("sp %llx\r\n",cur -> sp); + asm volatile ( + "mov sp, %0;" + // "msr DAIFclr, 0xf;" + "eret;" + : + : "r" (cur -> sp) + ); + long tt = read_sysreg(elr_el1); + uart_printf ("should go to %llx, but instead %llx\r\n", 0, tt); + while (1); +} + +char* get_cpio_end() { + char* cpio_start = _cpio_file; + struct cpio_newc_header* header = (struct cpio_newc_header*)cpio_start; + substr(buff, header -> c_magic, 0, 5); + while (same(buff, "070701")) { + uint64_t namesize = hex_to_bin(header->c_namesize); + uint64_t filesize = hex_to_bin(header->c_filesize); + + char* filename = (char*)(header + 1); + char* filedata = filename + namesize; + filedata = (char*)((uintptr_t)filedata + ((4 - ((uintptr_t)filedata & 3)) & 3)); // Align to next 4-byte boundary + + substr(buff, filename, 0, namesize - 1); + if (same(buff, "TRAILER!!!")) { + return filedata + filesize; + } + + substr(buff, filename, 0, namesize - 1); + + // Move to the next header, aligning as necessary + header = (struct cpio_newc_header*)(filedata + filesize); + header = (struct cpio_newc_header*)((uintptr_t)header + ((4 - ((uintptr_t)header & 3)) & 3)); // Align to next 4-byte boundary + substr(buff, header -> c_magic, 0, 5); + } + return header; +} diff --git a/lab6/kernel/src/exception.c b/lab6/kernel/src/exception.c new file mode 100644 index 000000000..956610b16 --- /dev/null +++ b/lab6/kernel/src/exception.c @@ -0,0 +1,196 @@ +#include "exception.h" +#include "mini_uart.h" +#include "utils.h" +#include "mmio.h" +#include "DEFINE.h" +#include "timer.h" +#include "task.h" +#include "system_call.h" +#include "thread.h" + +#include + +/* +extern char* write_buffer; +extern int write_ind; +extern int write_tail; + +extern char* recv_buffer; +extern int recv_ind; +extern int recv_tail; +extern int flag; +*/ + +extern timer* head; + +void exception_entry(){ + uart_printf("Entering exception handler\r\n"); + + void *spsr1; + void *elr1; + void *esr1; + + asm volatile( + "mrs %[var1], spsr_el1;" + "mrs %[var2], elr_el1;" + "mrs %[var3], esr_el1;" + : [var1] "=r" (spsr1),[var2] "=r" (elr1),[var3] "=r" (esr1) + ); + + uart_printf("SPSR_EL1: %x\r\n", spsr1); + uart_printf("ELR_EL1: %x\r\n", elr1); + uart_printf("ESR_EL1: %x\r\n", esr1); + + return; +} + +void core_timer_entry() { + unsigned long long cur_cnt, cnt_freq; + + asm volatile( + "mrs %[var1], cntpct_el0;" + "mrs %[var2], cntfrq_el0;" + :[var1] "=r" (cur_cnt), [var2] "=r" (cnt_freq) + ); + + asm volatile("msr cntp_ctl_el0,%0"::"r"(0)); + irq(0); + + if (head == NULL) { + irq(1); + unsigned int* address = (unsigned int*) CORE0_TIMER_IRQ_CTRL; + *address = 2; + return; + } + while (head -> next != NULL && head -> next -> exp <= cur_cnt) { + head -> next -> callback(head -> next -> data); + head = head -> next; + } + if (head -> next != NULL) { + asm volatile("msr cntp_cval_el0, %0"::"r"(head -> next -> exp)); + asm volatile("msr cntp_ctl_el0,%0"::"r"(1)); + } + + irq(1); + unsigned int* address = (unsigned int*) CORE0_TIMER_IRQ_CTRL; + *address = 2; +} + +void simple_core_timer_entry() { + // irq closed before getting in + long cur_cnt = read_sysreg(cntpct_el0); + long cnt_freq = read_sysreg(cntfrq_el0); + + write_sysreg(cntp_tval_el0, cnt_freq >> 5); + + // asm volatile("msr cntp_tval_el0, %0"::"r"(cnt_freq >> 5)); + // unsigned int* address = (unsigned int*) CORE0_TIMER_IRQ_CTRL; + // *address = 2; + + schedule(); + // uart_printf ("I'm back\r\n"); +} + + +void c_general_irq_handler(){ + unsigned int gpu_irq_src = mmio_read((long)IRQ_pending_1); + unsigned int cpu_irq_src = mmio_read((long)CORE0_INT_SRC); + + irq(0); + + if(gpu_irq_src & (1 << 29)){ + + unsigned int irq_status = mmio_read((long)AUX_MU_IIR_REG); + if(irq_status & 0x4){ + // uart_printf ("[DEBUG] irq read\r\n"); + // change_read_irq(0); + // create_task(recv_handler, 5); + recv_handler(); + } + else if(irq_status & 0x2){ + // uart_printf ("[DEBUG] irq write\r\n"); + // change_write_irq(0); + // create_task(write_handler, 5); + write_handler(); + } + } + else if (cpu_irq_src & (0x1 << 1)) { + // unsigned int* address = (unsigned int*) CORE0_TIMER_IRQ_CTRL; + // *address = 0; + // create_task(simple_core_timer_entry, 5); + simple_core_timer_entry(); + } + irq(1); + // execute_tasks(); + +} + +void c_undefined_exception() { + uart_printf("This is a undefined exception. Proc hang\r\n"); + while (1); +} + +#define ESR_ELx_EC(esr) ((esr & 0xFC000000) >> 26) + +void c_system_call_handler(trapframe_t* tf) { + irq(0); + + unsigned long esr = read_sysreg(esr_el1); // cause of that exception + unsigned int ec = ESR_ELx_EC(esr); + + if (ec == 0b100100) { + uart_printf ("data aboart el0\r\n"); + while (1); + } + if (ec == 0b100000) { + uart_printf ("ins \r\n"); + while (1); + } + if (ec == 0b100101) { + uart_printf ("data aboard el1\r\n"); + while (1); + } + + int id = tf -> x[8]; + if (id == 0) { + tf -> x[0] = do_getpid(); + } + else if (id == 1) { + irq(1); + tf -> x[0] = do_uart_read(tf -> x[0], tf -> x[1]); + } + else if (id == 2) { + irq(1); + tf -> x[0] = do_uart_write(tf -> x[0], tf -> x[1]); + } + else if (id == 3) { + tf -> x[0] = do_exec(tf -> x[0], tf -> x[1]); + } + else if (id == 4) { + tf -> x[0] = do_fork(tf); + } + else if (id == 5) { + do_exit(); + } + else if (id == 6) { + tf -> x[0] = do_mbox_call(tf -> x[0], tf -> x[1]); + } + else if (id == 7) { + do_kill(tf -> x[0]); + } + else if (id == 8) { + uart_printf ("Do a register\r\n"); + do_signal(tf -> x[0], tf -> x[1]); + } + else if (id == 9) { + uart_printf ("Do a kill\r\n"); + do_sigkill(tf -> x[0], tf -> x[1]); + } + else { + uart_printf ("This is unexpected systemcall, proc hang\r\n"); + while (1); + } + // uart_printf ("Exception ended with return value = %d\r\n", tf -> x[0]); + irq(1); +} + diff --git a/lab6/kernel/src/fdt.c b/lab6/kernel/src/fdt.c new file mode 100644 index 000000000..7c03396db --- /dev/null +++ b/lab6/kernel/src/fdt.c @@ -0,0 +1,131 @@ +#include "fdt.h" +#include "mini_uart.h" +#include +#include "helper.h" + +char* _cpio_file; +char* _fdt_end; +extern char* fdt_addr; + +void _print_tab(int level) +{ + while (level--) { + uart_printf("\t"); + } +} + +void _dump(char *start, int len) +{ + for(int i = 0; i < len; i ++) { + if (start[i] >= 0x20 && start[i] <= 0x7e) uart_send(start[i]); + else uart_printf("%x", start[i]); + } +} + +char* ALIGN(uint64_t ptr, int x) { + if (ptr & 3) { + ptr = (ptr + (4 - (ptr & 3))); + } + return (char*)ptr; +} + +uint32_t print_dtb(int type, char *name, char *data, uint32_t size) +{ + static int tb = 0; + if (type == FDT_BEGIN_NODE) { + _print_tab(tb); + uart_printf("[*] Node: %s\r\n", name); + tb ++; + } + else if(type == FDT_END_NODE) { + tb --; + _print_tab(tb); + uart_printf("[*] Node: end\r\n"); + } + else if(type == FDT_PROP) { + _print_tab(tb); + uart_printf("[*] %s: ", name); + _dump(data, size); + uart_printf("\r\n"); + } + else if(type == FDT_NOP) { + + } + else { + uart_printf("[*] END!\r\n"); + } + + return 0; +} + +uint32_t get_initramfs_addr(int type, char* name, char* data, uint32_t size) +{ + if (type == FDT_PROP && same(name, "linux,initrd-start")) { + _cpio_file=(char *)(uintptr_t)fdt32_ld((void*)data); + _cpio_file += 0xffff000000000000; + } + return 0; +} + +uint32_t parse_dt_struct(fdt_callback cb, char *dt_struct, char *dt_strings) { + // inside a struct + char *cur = dt_struct; + + while (1) { + cur = (char *)ALIGN((uint64_t)cur, 4); + struct fdt_node_header *nodehdr = (struct fdt_node_header *)cur; + uint32_t tag = fdtn_tag(nodehdr), t = 0; + + if (tag == FDT_BEGIN_NODE) { + t = cb(FDT_BEGIN_NODE, "", nodehdr -> name, -1); + cur += sizeof(struct fdt_node_header) + strlen(nodehdr->name) + 1; + } + else if (tag == FDT_END_NODE) { + t = cb(FDT_END_NODE, "", "", -1); + cur += sizeof(struct fdt_node_header); + } + else if (tag == FDT_PROP) { + struct fdt_property *prop = (struct fdt_property *)nodehdr; + t = cb(FDT_PROP, dt_strings + fdtp_nameoff(prop), prop -> data, fdtp_len(prop)); + cur += sizeof(struct fdt_property); + cur += fdtp_len(prop); + } + else if (tag == FDT_NOP) { + t = cb(FDT_NOP, "", "", -1); + cur += sizeof(struct fdt_node_header); + } + else { + t = cb(FDT_END, "", "", -1); + cur += sizeof(struct fdt_node_header); + break; + } + if ( t != 0 ) return t; + } + _fdt_end = cur; + return 0; +} + +uint32_t fdt_traverse(fdt_callback cb) +{ + struct fdt_header *hdr = (struct fdt_header *)fdt_addr; + + uart_printf ("%llx\r\n", fdt_addr); + + if (fdt_magic(hdr) != FDT_MAGIC) { + uart_printf("[x] Not valid fdt_header\r\n"); + } + + char *dt_struct = fdt_addr + fdt_off_dt_struct(hdr); + char *dt_strings = fdt_addr + fdt_off_dt_strings(hdr); + + uint32_t r = parse_dt_struct(cb, dt_struct, dt_strings); + + return r; +} + +long get_fdt_end() { + if (_fdt_end == 0) { + uart_printf ("You haven't get fdt_end\r\n"); + } + return _fdt_end; +} diff --git a/lab6/kernel/src/helper.c b/lab6/kernel/src/helper.c new file mode 100644 index 000000000..a3c6c359f --- /dev/null +++ b/lab6/kernel/src/helper.c @@ -0,0 +1,57 @@ +#include "mini_uart.h" + +void hex_to_string(unsigned int x, char* buf) { + buf[0] = '0'; buf[1] = 'x'; + char arr[16] = "0123456789abcdef"; + for (int i = 0; i < 8; i++) { + unsigned char ch = (x >> ((32-4) - i*4)) & 0xF; + buf[i + 2] = arr[ch]; + } + buf[10] = '\0'; +} + +int same (char* one, char* two) { + for(int i = 0; ; i ++) { + if(one[i] == '\0' && two[i] == '\0') return 1; + if(one[i] != two[i]) return 0; + } +} + +void substr(char* to, char* from, int l, int r) { + for(int i = l; i <= r; i ++) { + to[i - l] = from[i]; + } + to[r - l + 1] = '\0'; +} + +int strlen(char* str) { + int t = 0; + while(str[t] != '\0') { + t ++; + } + return t; +} + +unsigned long stoi(char* str) { + unsigned long res = 0; + for(int i = 0; str[i] != '\0'; i ++) { + res = res * 10 + str[i] - '0'; + } + return res; +} + +void strcpy(char* from, char* to, int size) { + for (int i = 0; i < size; i ++) { + to[i] = from[i]; + } +} + +void delay (unsigned long long t) { + while (t --); +} + +void memset(char* arr, char t, int size) { + for (int i = 0; i < size; i ++) { + arr[i] = t; + } +} diff --git a/lab6/kernel/src/kernel_start.c b/lab6/kernel/src/kernel_start.c new file mode 100644 index 000000000..f647e1d76 --- /dev/null +++ b/lab6/kernel/src/kernel_start.c @@ -0,0 +1,38 @@ +#include +#include +#include "fdt.h" +#include "cpio.h" +#include "alloc.h" +#include "thread.h" +#include "mmu.h" + +extern void core_timer_enable(); +extern char _code_start[]; +extern char _code_end[]; + +extern thread* get_current(); + +char* fdt_addr; + +void kernel_begin(char* fdt) { + fdt_addr = pa2va(fdt); + uart_init(); + long t = 0xffff000000000000; + uart_printf ("%llx translated to %llx\r\n", t, trans(t)); + + uart_printf ("Hello world\r\n"); + + fdt_traverse(get_initramfs_addr); // also set _cpio_file + manage_init(); + + thread_init(); + get_current() -> code = _code_start; + get_current() -> code_size = (_code_end - _code_start + 1); + get_current() -> PGD = 0x1000; + + long x = 0xffff000000000000; + uart_printf ("0x%llx\r\n", &x); + + shell_begin(fdt); + return; +} diff --git a/lab6/kernel/src/linker.ld b/lab6/kernel/src/linker.ld new file mode 100644 index 000000000..2d7e67ba1 --- /dev/null +++ b/lab6/kernel/src/linker.ld @@ -0,0 +1,17 @@ + + +SECTIONS +{ + . = 0xffff000000000000; + . += 0x80000; + _code_start = . ; + .text.boot : { *(.text.boot) } + .text : { *(.text) } + _code_end = .; + .rodata : { *(.rodata) } + .data : { *(.data) } + . = ALIGN(0x8); + bss_begin = .; + .bss : { *(.bss*) } + bss_end = .; +} diff --git a/lab6/kernel/src/mail.c b/lab6/kernel/src/mail.c new file mode 100644 index 000000000..fef31238e --- /dev/null +++ b/lab6/kernel/src/mail.c @@ -0,0 +1,57 @@ +#include "mini_uart.h" +#include "mail.h" + +int mailbox_call(unsigned int *mailbox, unsigned char ch) { + unsigned int r = (unsigned int)(((unsigned long)mailbox) & (~0xF)) | (ch & 0xF); + while(*MAILBOX_STATUS & MAILBOX_FULL); + *MAILBOX_WRITE = r; + while(1) { + while(*MAILBOX_STATUS & MAILBOX_EMPTY); + // uart_send_string("Trying to get the result from mailbox...\r\n"); + if(r == *MAILBOX_READ) + return mailbox[1] == REQUEST_SUCCEED; + } + return 0; +} + +unsigned int get_board_revision(){ + unsigned int __attribute__((aligned(16))) mailbox[7]; + mailbox[0] = 7 * 4; // buffer size in bytes + mailbox[1] = REQUEST_CODE; + // tags begin + mailbox[2] = GET_BOARD_REVISION; // tag identifier + mailbox[3] = 4; // maximum of request and response value buffer's length. + mailbox[4] = TAG_REQUEST_CODE; + mailbox[5] = 0; // value buffer + // tags end + mailbox[6] = END_TAG; + + if (mailbox_call(mailbox, 8) ) { + return mailbox[5]; + } + else { + return 0; + } +} + +int get_arm_memory(unsigned int* arr) { + unsigned int __attribute__((aligned(16))) mailbox[8]; + mailbox[0] = 8 * 4; // buffer size in bytes + mailbox[1] = REQUEST_CODE; + // tags begin + mailbox[2] = GET_ARM_MEMORY; // tag identifier + mailbox[3] = 8; // maximum of request and response value buffer's length. + mailbox[4] = TAG_REQUEST_CODE; + mailbox[5] = 0; // value buffer + mailbox[6] = 0; // value buffer + // tags end + mailbox[7] = END_TAG; + + if (mailbox_call(mailbox, 8)) { + arr[0] = mailbox[5]; arr[1] = mailbox[6]; + return 0; + } + else { + return -1; + } +} diff --git a/lab6/kernel/src/mini_uart.c b/lab6/kernel/src/mini_uart.c new file mode 100644 index 000000000..396e1019e --- /dev/null +++ b/lab6/kernel/src/mini_uart.c @@ -0,0 +1,280 @@ +#include "utils.h" +#include "helper.h" +#include "mmio.h" + +#include "DEFINE.h" + +#include +#include + + +#define SIGN 1 + +char write_buffer[1024]; +int write_tail = 0, write_ind = 0; +char recv_buffer[1024]; +int recv_tail = 0, recv_ind = 0; + +void uart_send ( char c ) +{ + while(1) { + if(get32(AUX_MU_LSR_REG)&0x20) + break; + } + put32(AUX_MU_IO_REG,c); +} + +char uart_recv ( void ) +{ + while(1) { + if(get32(AUX_MU_LSR_REG)&0x01) + break; + } + return(get32(AUX_MU_IO_REG)&0xFF); +} + +void uart_recv_string( char* buf ) { + int m = 0; + while(1) { + while(1) { + if(get32(AUX_MU_LSR_REG)&0x01) + break; + } + buf[m ++] = get32(AUX_MU_IO_REG) & 0xFF; + if (buf[m - 1] == '\r') { + m --; + break; + } + if (buf[m - 1] == 127) { + m --; + continue; + } + uart_send(buf[m - 1]); + } + buf[m] = '\0'; +} + +uint32_t uart_recv_uint(void) +{ + char buf[4]; + + for (int i = 0; i < 4; ++i) { + buf[i] = uart_recv(); + } + + return *((uint32_t*)buf); +} + +void uart_send_string(char* str) { + for(int i = 0; str[i] != '\0'; i ++) { + uart_send(str[i]); + } +} + + +void uart_send_num(int64_t num, int base, int type) +{ + const char digits[16] = "0123456789ABCDEF"; + char tmp[66]; + int i; + + if (type & SIGN) { + if (num < 0) { + uart_send('-'); + } + } + + i = 0; + + if (num == 0) { + tmp[i++] = '0'; + } else { + while (num != 0) { + uint8_t r = ((uint64_t)num) % base; + num = ((uint64_t)num) / base; + tmp[i++] = digits[r]; + } + } + + while (--i >= 0) { + uart_send(tmp[i]); + } +} + +// Ref: https://elixir.bootlin.com/linux/v3.5/source/arch/x86/boot/printf.c#L115 +void uart_printf(char *fmt, ...) +{ + const char *s; + char c; + uint64_t num; + char width; + + va_list args; + va_start(args, fmt); + + for (; *fmt; ++fmt) { + if (*fmt != '%') { + uart_send(*fmt); + continue; + } + + ++fmt; + + // Get width + width = 0; + if (fmt[0] == 'l' && fmt[1] == 'l') { + width = 1; + fmt += 2; + } + + switch (*fmt) { + case 'c': + c = va_arg(args, uint32_t) & 0xff; + uart_send(c); + continue; + case 'd': + if (width) { + num = va_arg(args, int64_t); + } else { + num = va_arg(args, int32_t); + } + uart_send_num(num, 10, SIGN); + continue; + case 's': + s = va_arg(args, char *); + uart_send_string((char*)s); + continue; + case 'x': + if (width) { + num = va_arg(args, uint64_t); + } else { + num = va_arg(args, uint32_t); + } + uart_send_num(num, 16, 0); + continue; + } + } +} + + +void uart_init ( void ) +{ + unsigned int selector; + + selector = get32(GPFSEL1); + selector &= ~(7<<12); // clean gpio14 + selector |= 2<<12; // set alt5 for gpio14 + selector &= ~(7<<15); // clean gpio15 + selector |= 2<<15; // set alt5 for gpio15 + put32(GPFSEL1,selector); + + put32(GPPUD,0); + delay(150); + put32(GPPUDCLK0,(1<<14)|(1<<15)); + delay(150); + put32(GPPUDCLK0,0); + + + + put32(AUX_ENABLE,1); //Enable mini uart (this also enables access to its registers) + put32(AUX_MU_CNTL_REG,0); //Disable auto flow control and disable receiver and transmitter (for now) + put32(AUX_MU_IER_REG,0); //Disable receive and transmit interrupts + put32(AUX_MU_LCR_REG,3); //Enable 8 bit mode + put32(AUX_MU_MCR_REG,0); //Set RTS line to be always high + put32(AUX_MU_BAUD_REG,270); //Set baud rate to 115200 + + put32(AUX_MU_CNTL_REG,3); //Finally, enable transmitter and receiver + + *UART_ICR = 0x7FF; /* clear interrupts */ + *UART_FBRD = 0xB; + *UART_LCRH = 0b11 << 5; /* 8n1 */ + *UART_CR = 0x301; /* enable Tx, Rx, FIFO */ + *UART_IMSC = 3 << 4; /* Tx, Rx */ +} + +void irq(int d) { + if (d) { + asm volatile ("msr DAIFclr, 0xf"); + // uart_printf ("IRQ is on\r\n"); + } + else { + asm volatile ("msr DAIFset, 0xf"); + // uart_printf ("IRQ is off\r\n"); + } +} + +void change_read_irq(int d) { + if (d) { + mmio_write((long)AUX_MU_IER_REG, *AUX_MU_IER_REG | (0x1)); + } + else { + mmio_write((long)AUX_MU_IER_REG, *AUX_MU_IER_REG & ~(0x1)); + } +} + +void change_write_irq(int d) { + if (d) { + mmio_write((long)AUX_MU_IER_REG, *AUX_MU_IER_REG | (0x2)); + } + else { + mmio_write((long)AUX_MU_IER_REG, *AUX_MU_IER_REG & ~(0x2)); + } +} + +void uart_irq_on(){ + change_read_irq(1); + *Enable_IRQs_1 |= (1<<29); +} + +void uart_irq_off(){ + change_read_irq(0); + *Disable_IRQs_1 |= (1<<29); +} + +void uart_irq_send(char* c, int siz) { + for (int i = 0; i < siz; i ++) { + if (c[i] == 0) continue; + write_buffer[write_tail ++] = c[i]; + } + if (write_tail > write_ind) { + change_write_irq(1); + } +} + +char uart_irq_read() { + // uart_printf ("%d, %d\r\n", recv_ind, recv_tail); + if (recv_ind >= recv_tail) { + return 0; + } + else { + return recv_buffer[recv_ind ++]; + } +} +void write_handler(){ + change_write_irq(0); + irq(0); + + while(write_ind != write_tail){ + char c = write_buffer[write_ind++]; + while (!(*AUX_MU_LSR_REG & (1 << 5))) { + asm volatile ( "nop;" ); + } + *AUX_MU_IO_REG = (unsigned int)c; + } + irq(1); +} + +void recv_handler(){ + + irq(0); + + while ((*AUX_MU_LSR_REG & 1)) { + char c = (char)(*AUX_MU_IO_REG); + if (c != 0) { + recv_buffer[recv_tail ++] = c; + } + } + // change_read_irq(1); + + irq(1); +} diff --git a/lab6/kernel/src/mm.S b/lab6/kernel/src/mm.S new file mode 100644 index 000000000..1bd32ff37 --- /dev/null +++ b/lab6/kernel/src/mm.S @@ -0,0 +1,6 @@ +.globl memzero +memzero: + str xzr, [x0], #8 + subs x1, x1, #8 + b.gt memzero + ret diff --git a/lab6/kernel/src/mmio.c b/lab6/kernel/src/mmio.c new file mode 100644 index 000000000..ffa7a16ec --- /dev/null +++ b/lab6/kernel/src/mmio.c @@ -0,0 +1,9 @@ +#include "mmio.h" + +inline void mmio_write(long reg, unsigned int data){ + *(volatile unsigned int*)reg = data; +} + +inline unsigned int mmio_read(long reg){ + return *(volatile unsigned int*)reg; +} diff --git a/lab6/kernel/src/mmu.c b/lab6/kernel/src/mmu.c new file mode 100644 index 000000000..47cd2d9e8 --- /dev/null +++ b/lab6/kernel/src/mmu.c @@ -0,0 +1,214 @@ +#include "mmu.h" +#include "helper.h" +#include "utils.h" +#include "alloc.h" +#include "thread.h" +#include "mmu_regs.h" +#include "mini_uart.h" + +#define PERIPHERAL_START 0x3c000000L +#define PERIPHERAL_END 0x40000000L + +#define DEVICE_BASE 0x3F000000L + + +const int page_size = 4096; + +void three_level_translation_init(){ + unsigned long *pmd_1 = (unsigned long *) 0x3000; + for(unsigned long i=0; i<512; i++){ + unsigned long base = 0x200000L * i; // 2 * 16^5 -> 2MB + if(base >= DEVICE_BASE){ + //map as device + pmd_1[i] = PD_ACCESS + PD_BLOCK + base + (MAIR_IDX_DEVICE_nGnRnE << 2) + PD_KERNEL_USER_ACCESS; + } + else{ + //map as normal + pmd_1[i] = PD_ACCESS + PD_BLOCK + base + (MAIR_IDX_NORMAL_NOCACHE << 2); + } + } + + unsigned long *pmd_2 = (unsigned long *) 0x4000; + for(unsigned long i=0; i<512; i++){ + unsigned long base = 0x40000000L + 0x200000L * i; + pmd_2[i] = PD_ACCESS + PD_BLOCK + base + (MAIR_IDX_NORMAL_NOCACHE << 2); + } + + unsigned long * pud = (unsigned long *) 0x2000; + *pud = PD_TABLE + (unsigned long) pmd_1; + pud[1] = PD_TABLE + (unsigned long) pmd_2; +} + +/* +void set_up_identity_paging() { + write_sysreg(tcr_el1, TCR_CONFIG_DEFAULT); + + long attr = + (MAIR_DEVICE_nGnRnE << (MAIR_IDX_DEVICE_nGnRnE * 8)) | + (MAIR_NORMAL_NOCACHE << (MAIR_IDX_NORMAL_NOCACHE * 8)); + write_sysreg(mair_el1, attr); + + long* l0 = (long*)0x1000L; + long* l1 = (long*)0x2000L; + + memset(l0, 0, 0x1000); + memset(l1, 0, 0x1000); // clears the page table: + + long *p0 = (long*)0x3000; + for (int i = 0; i < 504; i++) { + p0[i] = (i << 21) | PD_ACCESS | (MAIR_IDX_NORMAL_NOCACHE << 2) | PD_BLOCK, (1 << 6); + } + // [0x3F000000 ~ 0x80000000] device memory + for (int i = 504; i < 1024; i++) { + p0[i] = (i << 21) | PD_ACCESS | (MAIR_IDX_DEVICE_nGnRnE << 2) | PD_BLOCK; + } + + l0[0] = (long)l1 | BOOT_PGD_ATTR; + l1[0] = 0x3000L | PD_TABLE; + l1[1] = 0x4000L | PD_TABLE; + + write_sysreg(ttbr0_el1, l0); + write_sysreg(ttbr1_el1, l0); + + unsigned long sctlr = read_sysreg(sctlr_el1); + write_sysreg(sctlr_el1, sctlr | 1); +} +*/ + +/* +void kernel_finer_gran() { + // [0x00000000, 0x3F000000] normal memory + asm volatile ( "dsb ish;" ); + + long* l1 = pa2va(0x2000L); + + asm volatile ( "dsb ish;" ); + + l1[0] = 0x3000L | PD_TABLE; + l1[1] = 0x4000L | PD_TABLE; + asm volatile ( "dsb ish;" ); +} +*/ + +void map_page(long * pgd, long va, long pa, long flag){ + for(int i=0; i<4; i++){ + unsigned int offset = (va >> (39 - i * 9)) & 0x1ff; + + if(i == 3){ + pgd[offset] = pa; + pgd[offset] |= PD_ACCESS | PD_TABLE | (MAIR_IDX_NORMAL_NOCACHE << 2) | flag; + return; + } + + if(pgd[offset] == 0){ + unsigned long * new_page_table = my_malloc(4096); + for(int j=0; j<4096; j++){ + ((char *) (new_page_table))[j] = 0; + } + pgd[offset] = va2pa(new_page_table); + pgd[offset] |= PD_TABLE; + } + + pgd = (long*) (((long) (pgd[offset] & ENTRY_ADDR_MASK)) + 0xffff000000000000); + } +} + +/* +void map_page(long* pt, long va, long pa, long flag) { + if (pa < 0x3c000000) { + uart_printf ("mapping from %llx to %llx, pt is %llx\r\n", pa, va, pt); + } + for (int level = 0; level < 4; level ++) { + // uart_printf ("%d\r\n", level); + long id = (va >> (39 - 9 * level)) & 0b111111111; + if (pt[id] != 0) { + if (level == 3) { + uart_printf ("exited mapping\r\n"); + } + pt = pa2va(pt[id] & (0xfffffffff000L)); + } + else { + if (level == 3) { + pt[id] = pa | PD_ACCESS | PD_PAGE | flag | (MAIR_IDX_NORMAL_NOCACHE << 2); + break; + } + else { + long* t = my_malloc(page_size); + for (int i = 0; i < 4096; i ++) { + ((char*)t)[i] = 0; + } + pt[id] = va2pa(t) | PD_TABLE; + pt = pa2va(pt[id] & (0xfffffffff000L)); + } + } + } +} +*/ + + +void setup_peripheral_identity(long* table) +{ + for (long i = PERIPHERAL_START; i < PERIPHERAL_END; i += 4096) { + map_page(table, i, i, (1 << 6)); + } +} + +long pa2va(long x) { + return x + 0xffff000000000000; +} +long va2pa(long x) { + return x - 0xffff000000000000; +} + +long trans(long x) { + long res; + asm volatile ( + "mov x0, %[input];" + "AT S1E1R, x0;" + "MRS %[res], PAR_EL1;" + // "isb;" + : [res] "=r" (res) + : [input] "r" (x) + : "x0" + ); + if (res & (0x1)) { + uart_printf ("trans failed, res: %x\r\n", res & 0xfff); + } + return (res & 0xfffffffff000) | (x & 0xfff); +} + +long trans_el0(long x) { + long res; + asm volatile ( + "mov x0, %[input];" + "AT S1E0R, x0;" + "MRS %[res], PAR_EL1;" + // "isb;" + : [res] "=r" (res) + : [input] "r" (x) + : "x0" + ); + if (res & (0x1)) { + uart_printf ("trans failed, res: %x\r\n", res & 0xfff); + } + return (res & 0xfffffffff000) | (x & 0xfff); +} + +extern thread* get_current(); + +void switch_page() { + uart_printf ("switching\r\n"); + asm volatile( + "dsb ish;" + "msr ttbr0_el1, %0;" + "dsb ish;" + "tlbi vmalle1is;" + "dsb ish;" + "isb;" + : + : "r" (get_current() -> PGD) + : "x0" + ); + uart_printf ("switching done\r\n"); +} + diff --git a/lab6/kernel/src/shell.c b/lab6/kernel/src/shell.c new file mode 100644 index 000000000..9f564b5d3 --- /dev/null +++ b/lab6/kernel/src/shell.c @@ -0,0 +1,267 @@ +#include "shell.h" +#include "mini_uart.h" +#include "reboot.h" +#include "mail.h" +#include "helper.h" +#include "loader.h" +#include "cpio.h" +#include "alloc.h" +#include "fdt.h" +#include "timer.h" +#include "exception.h" +#include "thread.h" +#include "system_call.h" +#include "signal.h" +#include "thread.h" +#include "mmu.h" + +char buf[1024]; +extern thread* get_current(); +extern thread** threads; +extern void** thread_fn; + +extern char _code_start[]; + +extern void core_timer_enable(); + +void help() { + uart_printf("help : print this help menu\r\n"); + uart_printf("hello : print Hello World!\r\n"); + uart_printf("reboot : reboot the device\r\n"); + uart_printf("revision : get the revision number\r\n"); + uart_printf("memory : get the ARM memory info\r\n"); + uart_printf("ls : ls the initial ramdisk\r\n"); + uart_printf("cat : cat the initial ramdisk\r\n"); + uart_printf("initramd : use devicetree to get initial ramdisk\r\n"); + uart_printf("dtb : output the device tree\r\n"); + uart_printf("async : test for async uart\r\n"); + uart_printf("timeout : set timeout (ms)\r\n"); +} + +void handle_timeout() { + char* buf = my_malloc(512); + uart_printf("Input time(ms): "); + uart_recv_string(buf); + unsigned long t = stoi(buf); + uart_printf("\n"); + uart_printf("Input data to output: "); + uart_recv_string(buf); + uart_printf("\n"); + set_timeout(t, buf); +} + +void async_test() { + uart_irq_on(); + + uart_irq_send("Test\n", 5); + + int t = 100000000; + while (t --); + + char* str = my_malloc(512); + int len; + for (len = 0; ; len ++) { + str[len] = uart_irq_read(); + if (str[len] == 0) break; + } + + uart_irq_off(); + uart_printf("%s, End\n", str); +} + +void page_test() { + print_node_list(); + int* arr0 = (int*)my_malloc(4096 * 1); + int* arr1 = (int*)my_malloc(4096 * 2); + int* arr2 = (int*)my_malloc(4096 * 2); + int* arr3 = (int*)my_malloc(4096 * 4); + int* arr4 = (int*)my_malloc(4096 * 8); + print_node_list(); + int* arr5 = (int*)my_malloc(4096 * 1); + for (int i = 0; i < 4096; i += sizeof(int)){ + arr0[i] = 1; + } + for (int i = 0; i < 4096 * 2; i += sizeof(int)){ + arr1[i] = 1; + } + for (int i = 0; i < 4096 * 2; i += sizeof(int)){ + arr2[i] = 1; + } + for (int i = 0; i < 4096 * 4; i += sizeof(int)){ + arr3[i] = 1; + } + for (int i = 0; i < 4096 * 8; i += sizeof(int)){ + arr4[i] = 1; + } + for (int i = 0; i < 4096; i += sizeof(int)){ + arr5[i] = 1; + } + print_node_list(); + my_free(arr5); + print_node_list(); +} + +void malloc_test() { + print_node_list(); + char* arr[17]; + for (int i = 0; i < 17; i ++) { + arr[i] = my_malloc(512); + for (int j = 0; j < 512; j ++) { + arr[i][j] = 'a'; + } + } + print_node_list(); + print_pool(); + for (int i = 0; i < 17; i ++) { + my_free(arr[i]); + } + print_node_list(); + print_pool(); +} + +void do_simple_fork_test() { + irq(0); + int id = thread_create(from_el1_to_fork_test); + thread* child = threads[id]; + thread* cur = get_current(); + int t = (cur -> code_size + 4096 - 1) / 4096 * 4096; + child -> code = my_malloc(t); + child -> code_size = cur -> code_size; + + uart_printf ("Child code physical: %llx\r\n", child -> code); + + uart_printf ("simple fork test: "); + for (int j = 0; j < t / 4096; j ++) { + for (int i = 0; i < 10; i ++) { + uart_printf ("%d ", (_code_start + 4096 * j)[i]); + } + uart_printf ("\r\n"); + } + + uart_printf ("copying code of size %d\r\n", t); + strcpy(cur -> code, child -> code, t); + uart_printf ("fuck: "); + for (int i = 0; i < 10; i ++) { + uart_printf ("%d ", ((char*)(child -> code + 4096))[i]); + } + uart_printf ("\r\n"); + uart_printf ("t / 4096 : %d\r\n", t / 4096); + for (int i = 0; i < t / 4096; i ++) { + map_page(pa2va(child -> PGD), i * 4096, va2pa(child -> code) + i * 4096, (1 << 6)); + } + + for (int i = 0; i < 4; i ++) { + map_page(pa2va(child -> PGD), 0xffffffffb000L + i * 4096, va2pa(child -> stack_start) + i * 4096, (1 << 6)); + } + + setup_peripheral_identity(pa2va(child -> PGD)); + + child -> code = 0; + child -> stack_start = 0xffffffffb000; + + uart_printf ("%llx\r\n", child -> PGD); + + uart_printf ("thread_fn[%d]: %llx\r\n", id, thread_fn[id]); + + irq(1); +} + +void shell_begin(char* fdt) +{ + fdt += 0xffff000000000000; + while (1) { + uart_recv_string(buf); + uart_printf("\r\n"); + if (same(buf, "hello")) { + uart_printf("Hello World!\n"); + } + else if (same(buf, "tt")) { + uart_printf("Input:\r\n"); + uart_recv_string(buf); + uart_printf("\r\n"); + unsigned long t = stoi(buf); + uart_printf("started countind from %d\r\n", t); + while (t--) { + + } + uart_printf("end\r\n"); + } + else if (same(buf, "timeout")) { + handle_timeout(); + } + else if (same(buf, "help")) { + help(); + } + else if (same(buf, "async")) { + async_test(); + } + else if(same(buf, "initramd")) { + fdt_traverse(get_initramfs_addr); + } + else if (same(buf, "ls")) { + cpio_parse_ls(); + } + else if (same(buf, "cat")) { + uart_printf("Filename: "); + uart_recv_string(buf); + uart_printf("\n"); + cpio_parse_cat(buf); + } + else if (same(buf, "dtb")) { + fdt_traverse(print_dtb); + } + else if(same(buf, "revision")) { + unsigned int rev = get_board_revision(); + if (rev) { + uart_printf("%x", rev); + } + else { + uart_printf("Failed to get board revision\n"); + } + } + else if(same(buf, "memory")) { + unsigned int arr[2]; + arr[0] = arr[1] = 0; + if(!get_arm_memory(arr)) { + uart_printf("Your ARM memory address base is: %x", arr[0]); + uart_printf("Your ARM memory size is: %x", arr[1]); + } + else { + uart_printf("Failed getting ARM memory info\n"); + } + } + else if (same(buf, "reboot")) { + uart_printf("Rebooting\n"); + reset(100); + } + else if (same(buf, "exit")) { + break; + } + else if (same(buf, "page")) { + page_test(); + } + else if (same(buf, "malloc")) { + malloc_test(); + } + else if (same(buf, "load")) { + uart_printf("Filename: "); + uart_recv_string(buf); + uart_printf("\n"); + cpio_load(buf); + } + else if (same(buf, "thread")) { + thread_test(); + } + else if (same(buf, "fork")) { + do_simple_fork_test(); + while (1); + } + else if (same(buf, "timer")) { + core_timer_enable(); + } + else { + uart_printf("Command not found\n"); + help(); + } + } +} diff --git a/lab6/kernel/src/signal.c b/lab6/kernel/src/signal.c new file mode 100644 index 000000000..1aed70de1 --- /dev/null +++ b/lab6/kernel/src/signal.c @@ -0,0 +1,77 @@ +#include +#include +#include + +extern thread* get_current(); + +void sigkill() { + kill_thread(get_current() -> id); +} + +void test_handler() { + uart_printf ("This is test handler\r\n"); +} + +void signal_handler_wrapper(void* func_ptr) { + // in el0 + uart_printf ("In user mode\r\n"); + void (*func) (void) = func_ptr; + func(); + + // while (1); + + asm volatile ( + "mov x8, 10;" + "svc #0;" + ); +} + +void handle_signal(void* tf) { + thread* t = get_current(); + + for (int i = 0; i < 10; i ++) { + if (t -> signal[i] == 0) continue; + uart_printf ("found signal\r\n"); + t -> signal[i] = 0; + if (t -> signal_handler[i] == NULL) { + kill_thread(t -> id); + uart_printf ("never back\r\n"); + } + void* func = signal_handler_wrapper; + uart_printf ("Going to usermode\r\n"); + uart_printf ("%x :(:(:(\r\n", func); + irq(0); + t -> sstack_start = my_malloc(4096); + void* sp = t -> sstack_start + 4096 - 16; + /* + asm volatile ( + "mov x0, %0;" + "bl signal_handler_wrapper;" + : + : "r" (i) + : "x0" + ); + */ + asm volatile ( + "mov x1, 0;" + "msr spsr_el1, x1;" + "mov x1, %[func];" + "mov x2, %[sp];" + "msr elr_el1, x1;" + "msr sp_el0, x2;" + "mov x0, %[handler];" + "mov sp, %[ori_sp];" + "msr DAIFclr, 0xf;" + "eret;" + : + : [func] "r" (func), + [sp] "r" (sp), + [ori_sp] "r" (tf), + [handler] "r" (t -> signal_handler[i]) + : "x0", "x1", "x2", "sp" + ); + uart_printf ("should not be here\r\n"); + while (1); + } + +} diff --git a/lab6/kernel/src/system_call.S b/lab6/kernel/src/system_call.S new file mode 100644 index 000000000..334161a07 --- /dev/null +++ b/lab6/kernel/src/system_call.S @@ -0,0 +1,47 @@ +.global getpid +getpid: + mov x8, 0 + svc #0 + ret + +.global uart_read +uart_read: + mov x8, 1 + svc #0 + ret + +.global uart_write +uart_write: + mov x8, 2 + svc #0 + ret + +.global exec +exec: + mov x8, 3 + svc #0 + ret + +.global fork +fork: + mov x8, #4 + svc #0 + ret + +.global exit +exit: + mov x8, 5 + svc #0 + +.global mbox_call +mbox_call: + mov x8, 6 + svc #0 + ret + +.global kill +kill: + mov x8, 7 + svc #0 + ret + diff --git a/lab6/kernel/src/system_call.c b/lab6/kernel/src/system_call.c new file mode 100644 index 000000000..3accb0233 --- /dev/null +++ b/lab6/kernel/src/system_call.c @@ -0,0 +1,347 @@ +#include "system_call.h" +#include "alloc.h" +#include "thread.h" +#include "mail.h" +#include "cpio.h" +#include "mini_uart.h" +#include "helper.h" +#include "exception.h" +#include "utils.h" +#include "mmu.h" + +extern thread* get_current(); +extern thread** threads; +extern void** thread_fn; + +#define stack_size 4096 + +int do_getpid() { + return get_current() -> id; +} + +size_t do_uart_read(char buf[], size_t size) { + buf[0] = uart_recv(); + return 1; +} + +size_t do_uart_write(char buf[], size_t size) { + uart_send (buf[0]); + return 1; +} + +int do_exec(char* name, char *argv[]) { + cpio_load(name); +} + +extern void ret_from_fork_child(); + +typedef unsigned long long ull; + +uint64_t get_sp_el0() { + uint64_t value; + asm volatile("mrs %0, sp_el0" : "=r" (value)); + return value; +} +uint64_t get_sp_el1() { + uint64_t value; + asm volatile("mov %0, sp" : "=r" (value)); + return value; +} + + + +// tf is the sp +int do_fork(trapframe_t* tf) { + switch_page(); + + uart_printf ("Started do fork\r\n"); + int id = thread_create(NULL); // later set by thread_fn + + thread* cur = get_current(); + thread* child = threads[id]; + + uart_printf ("PGD for child %d is %llx\r\n", child -> id, child -> PGD); + + + for (int i = 0; i < 10; i ++) { + child -> reg[i] = cur -> reg[i]; + } + + for (int i = 0; i < stack_size; i ++) { + ((char*) child -> kstack_start)[i] = ((char*)(cur -> kstack_start))[i]; + } + // uart_printf ("finish copying kernel stack\r\n"); + for (int i = 0; i < stack_size * 4; i ++) { + ((char*) child -> stack_start)[i] = ((char*)(cur -> stack_start))[i]; + } + // uart_printf ("finish copying user stack\r\n"); + + int t = (cur -> code_size + 4096 - 1) / 4096 * 4096; + child -> code = my_malloc(t); + child -> code_size = cur -> code_size; + + for (int i = 0; i < t; i ++) { + ((char*)child -> code)[i] = ((char*)(cur -> code))[i]; + } + // uart_printf ("finish copying code\r\n"); + + setup_peripheral_identity(pa2va(child -> PGD)); + // uart_printf ("finish mapping peripheral\r\n"); + for (int i = 0; i < t / 4096; i ++) { + map_page(pa2va(child -> PGD), i * 4096, va2pa(child -> code) + i * 4096, (1 << 6)); + } + // uart_printf ("finish mapping code\r\n"); + for (int i = 0; i < 4; i ++) { + map_page(pa2va(child -> PGD), 0xffffffffb000L + i * 4096, va2pa(child -> stack_start) + i * 4096, (1 << 6)); + } + // uart_printf ("finish mapping stack\r\n"); + + child -> stack_start = 0xffffffffb000; + child -> code = 0; + + child -> sp = (void*)((char*)tf - (char*)cur -> kstack_start + (char*)child -> kstack_start); + child -> fp = child -> sp; + // on el1 stack + thread_fn[id] = ret_from_fork_child; + + for (int i = 0; i < 10; i ++) { + child -> signal_handler[i] = cur -> signal_handler[i]; + } + + if (get_current() -> id == id) { + uart_printf ("Child should not be here%d, %d\r\n", get_current() -> id, id); + } + + void* sp_el0 = get_sp_el0(); + void* sp_el1 = get_sp_el1(); + uart_printf ("CUR SPEL0: %llx, CUR SPEL1: %llx\r\n", sp_el0, sp_el1); + + trapframe_t* child_tf = (trapframe_t*)child -> sp; + child_tf -> x[0] = 0; + child_tf -> sp_el0 += child -> stack_start - cur -> stack_start; + + //elr_el1 should be the same + + uart_printf ("Child tf should be at %llx should jump to %llx\r\n", child -> sp, thread_fn[id], child_tf -> elr_el1); + uart_printf ("And then to %llx, ori is %llx :(:(:(:(:\r\n", child_tf -> elr_el1, tf -> elr_el1); + + // uart_printf ("diff1 %x, diff2 %x\r\n", (void*)tf - (cur -> kstack_start), (void*)child_tf - (child -> kstack_start)); + + return id; +} + +void do_exit() { + kill_thread(get_current() -> id); +} + +int do_mbox_call(unsigned char ch, unsigned int *mbox) { + int* t = my_malloc(4096); + for (int i = 0; i < 144; i ++) { + ((char*)t)[i] = ((char*)mbox)[i]; + } + int res = mailbox_call(t, ch); + for (int i = 0; i < 144; i ++) { + ((char*)mbox)[i] = ((char*)t)[i]; + } + return res; + + // return mailbox_call(mbox, ch); +} + +void do_kill(int pid) { + kill_thread(pid); +} + +void do_signal(int sig, handler func) { + uart_printf ("Registered %d\r\n", sig); + if (sig >= 10) { + uart_printf ("this sig num is greater then I can handle\r\n"); + return; + } + get_current() -> signal_handler[sig] = (void*)func; +} + +void do_sigkill(int pid, int sig) { + uart_printf ("DO sigkill %d, %d\r\n", pid, sig); + if (sig >= 10) { + uart_printf ("this sig num is greater then I can handle\r\n"); + return; + } + threads[pid] -> signal[sig] = 1; +} + +extern int fork(); +extern int getpid(); +extern void exit(); +extern void core_timer_enable(); +extern int mbox_call(unsigned char, unsigned int*); +extern void test_syscall(); + +void given_fork_test(){ + uart_printf("\nFork Test, pid %d\n", getpid()); + int cnt = 1; + int ret = 0; + if ((ret = fork()) == 0) { // child + long long cur_sp; + asm volatile("mov %0, sp" : "=r"(cur_sp)); + uart_printf("first child pid: %d, cnt: %d, ptr: %x, sp : %x\n", getpid(), cnt, &cnt, cur_sp); + ++cnt; + + if ((ret = fork()) != 0){ + asm volatile("mov %0, sp" : "=r"(cur_sp)); + uart_printf("first child pid: %d, cnt: %d, ptr: %x, sp : %x\n", getpid(), cnt, &cnt, cur_sp); + } + else{ + while (cnt < 5) { + asm volatile("mov %0, sp" : "=r"(cur_sp)); + uart_printf("second child pid: %d, cnt: %d, ptr: %x, sp : %x\n", getpid(), cnt, &cnt, cur_sp); + delay(1000000); + ++cnt; + } + } + exit(); + } + else { + uart_printf("parent here, pid %d, child %d\n", getpid(), ret); + } + while (1) { + uart_printf ("This is main create fork shit\r\n"); + delay(1e7); + } +} + +void fork_test_func() { + for (int i = 0; i < 3; i ++) { + int ret = fork(); + if (ret) { + uart_printf ("This is father %d with child of pid %d\r\n", getpid(), ret); + } + else { + uart_printf ("This is child forked, my pid is %d\r\n", getpid()); + } + } + exit(); + /* + while (1) { + delay(1e7); + } + */ +} + +extern void uart_write(char); +void simple_fork_test() { + uart_write('f'); + while (1); + // uart_printf ("In simple fork test\r\n"); + + /* + for (int i = 0; i < 1; i ++) { + // uart_printf ("%d: %d\r\n", getpid(), i); + int t = fork(); + if (t) { + uart_printf ("This is parent with child %d\r\n", t); + } + else { + uart_printf ("This is child with pid %d\r\n", getpid()); + } + } + exit(); + */ +} +void fork_test_idle() { + while(1) { + unsigned int __attribute__((aligned(16))) mailbox[7]; + mailbox[0] = 7 * 4; // buffer size in bytes + mailbox[1] = REQUEST_CODE; + // tags begin + mailbox[2] = GET_BOARD_REVISION; // tag identifier + mailbox[3] = 4; // maximum of request and response value buffer's length. + mailbox[4] = TAG_REQUEST_CODE; + mailbox[5] = 0; // value buffer + // tags end + mailbox[6] = END_TAG; + + if (mbox_call(8, mailbox)) { + uart_printf ("%x\r\n", mailbox[5]); + } + else { + uart_printf ("Fail getting mailbox\r\n"); + } + + uart_printf ("This is idle, pid %d, %d\r\n", getpid(), threads[1] -> next -> id); + delay(1e7); + } +} + +extern char _code_start[]; + +void im_fineee() { + long elr_el1 = read_sysreg(elr_el1); + long sp_el0 = read_sysreg(sp_el0); + + uart_printf ("im fine, elr_el1 %llx, sp_el0 %llx\r\n", elr_el1, sp_el0); +} + +void from_el1_to_fork_test() { + irq(0); + switch_page(); + uart_printf ("%llx\r\n", get_current() -> PGD); + long ttbr0 = read_sysreg(ttbr0_el1); + long ttbr1 = read_sysreg(ttbr1_el1); + uart_printf ("ttbr0: %llx, ttbr1: %llx\r\n", ttbr0, ttbr1); + void* sp = 0xfffffffff000 - 16; + void* code = (char*)fork_test_idle - _code_start; + + long test = code; + uart_printf ("%llx translated to %llx\r\n", test, trans(test)); + uart_printf ("%llx translated to %llx\r\n", test, trans_el0(test)); + + uart_printf ("stack: %llx code: %llx\r\n", sp, code); + + /* + for (int i = 0; i < 100; i ++) { + uart_printf ("%d ", ((char*)code)[i]); + } + uart_printf ("\r\n"); + */ + + /* + for (int i = 0; i < 100; i ++) { + uart_printf ("%d ", ((char*)simple_fork_test)[i]); + } + uart_printf ("\r\n"); + */ + + // simple_fork_test(); + + /* + void (*func)() = code; + func(); + */ + + asm volatile( + "mov x1, 0;" + "msr spsr_el1, x1;" + "mov x1, %[code];" + "mov x2, %[stack];" + "msr elr_el1, x1;" + "msr sp_el0, x2;" + // "msr DAIFclr, 0xf;" // irq(1); + "eret;" + : + : [code] "r" (code), [stack] "r" (sp) + : "x1", "x2" + ); + + uart_printf ("fuck you\r\n"); + asm volatile ( "eret;" ); +} + +void debug(trapframe_t* tf) { + uart_printf ("%d: ", get_current() -> id); + uart_printf ("sp: %llx, code: %llx\r\n", tf -> sp_el0, tf -> elr_el1); + long ttbr0 = read_sysreg(ttbr0_el1); + long ttbr1 = read_sysreg(ttbr1_el1); + uart_printf ("ttbr0: %llx, ttbr1: %llx\r\n", ttbr0, ttbr1); + +} diff --git a/lab6/kernel/src/task.c b/lab6/kernel/src/task.c new file mode 100644 index 000000000..1137cde43 --- /dev/null +++ b/lab6/kernel/src/task.c @@ -0,0 +1,47 @@ +#include "task.h" +#include "alloc.h" +#include "mini_uart.h" +#include "utils.h" + +#include + +task *task_head; + +void push_task(task *t) { + asm volatile("msr DAIFSet, 0xf"); + + if (task_head == NULL) { + task_head = my_malloc(1 * sizeof(task)); + task_head -> next = NULL; + } + + task* cur = task_head; + while (cur -> next != NULL && cur -> next -> p > t -> p) { + cur = cur -> next; + } + + t -> next = cur -> next; + cur -> next = t; + + asm volatile("msr DAIFClr, 0xf"); +} + +void create_task(task_callback callback, int priority) { + task* t = my_malloc(1 * sizeof(task)); + + t -> callback = callback; + t -> p = priority; + t -> started = 0; + + push_task(t); +} + +void execute_tasks() { + while (task_head -> next != NULL && !task_head -> next -> started) { + irq(0); + task_head -> next -> started = 1; + irq(1); + task_head -> next -> callback(); + task_head = task_head -> next; + } +} diff --git a/lab6/kernel/src/thread.c b/lab6/kernel/src/thread.c new file mode 100644 index 000000000..f38c66f6a --- /dev/null +++ b/lab6/kernel/src/thread.c @@ -0,0 +1,231 @@ +#include "thread.h" +#include "alloc.h" +#include "mini_uart.h" +#include "helper.h" +#include "exception.h" +#include "signal.h" +#include "mmu.h" +#include "utils.h" + +#define stack_size 4096 +#define max_thread_num 500 + +thread* thread_start; +thread* thread_tail; + +thread** threads; + +void** thread_fn; + +extern thread* get_current(); +extern void switch_to(thread*, thread*); + +void thread_init() { + + threads = (thread**)my_malloc(sizeof(thread) * max_thread_num); + thread_fn = (void**)my_malloc(sizeof(void*) * max_thread_num); + + for (int i = 0; i < max_thread_num; i ++) { + threads[i] = NULL; + } + + thread* x = my_malloc(sizeof(thread)); + threads[0] = x; + x -> id = 0; + x -> state = 1; + x -> kstack_start = my_malloc(stack_size); + x -> sp = x -> kstack_start + stack_size - 16; + x -> fp = x -> sp; + + x -> stack_start = my_malloc(stack_size * 4); + + long* PGD = my_malloc(4096); + for (int i = 0; i < 4096; i ++) { + ((char*)PGD)[i] = 0; + } + x -> PGD = va2pa(PGD); + + for (int i = 0; i < 10; i ++) { + x -> signal[i] = 0; + x -> signal_handler[i] = NULL; + } + + write_sysreg(tpidr_el1, x); + + thread_start = x; + thread_tail = thread_start; + thread_start -> next = NULL; + thread_start -> prev = NULL; +} + +void kill_zombies() { + irq(0); + for (int i = 1; i < max_thread_num; i ++) { + if (threads[i] -> state == 0) { + my_free(threads[i] -> stack_start); + my_free(threads[i]); + threads[i] = NULL; + } + } + irq(1); +} + +void idle() { + while (1) { + uart_printf ("In idle\r\n"); + kill_zombies(); + schedule(1); + // can't be called in el0 + delay(1e7); + } +} +void im_fine() { + uart_printf ("I'm fine\r\n"); +} + +void schedule() { + // uart_printf ("thread_start: %llx\r\n", &thread_start); + if (thread_start -> next == NULL) { + // uart_printf ("No next thread job\r\n"); + return; + } + thread_start = thread_start -> next; + if (thread_start -> id == get_current() -> id) return; + + if (get_current() -> state) { + thread_tail -> next = get_current(); + get_current() -> prev = thread_tail; + get_current() -> next = NULL; + thread_tail = thread_tail -> next; + } + thread_start -> prev = NULL; + // uart_printf ("[DEBUG] Scheduled From %d to %d\r\n", get_current() -> id, thread_start -> id); + switch_to(get_current(), thread_start); + // switch_page(); + long PGD = read_sysreg(ttbr0_el1); + // uart_printf ("id is now %d, PGD is now %llx, cur -> PGD is %llx\r\n", get_current() -> id, PGD, get_current() -> PGD); + // after successfully switched, ending of irq handler do irq(1) + return; +} + +void kill_thread(int id) { + irq(0); + uart_printf ("Killing child %d\r\n", id); + if (thread_tail -> id == id) { + if (thread_tail == thread_start) { + uart_printf ("You're killing the last shit and I won't let you do that\r\n"); + return; + } + thread_tail = thread_tail -> prev; + } + if (threads[id] -> prev != NULL) { + threads[id] -> prev -> next = threads[id] -> next; + } + if (threads[id] -> next != NULL) { + threads[id] -> next -> prev = threads[id] -> prev; + } + threads[id] -> state = 0; + irq(1); + if (id == get_current() -> id) { + while (1); + } + // wait for being scheduled away + // schedule(); +} + +trapframe_t* sp; + +void thread_func_handler() { + asm volatile ( + "mov %0, sp;" + : "=r" (sp) + : + : "sp" + ); + /* + // uncommenting the upper shit will affect the sp, need to modify them in the ret_from_fork shit + int id = get_current() -> id; + void* func = thread_fn[id]; + */ + uart_printf ("Jumping to %llx with sp %llx\r\n", thread_fn[get_current() -> id], (char*)sp + 16 * 2); + asm volatile ( + "add sp, sp, 16 * 2;" + // "mov x0, sp;" + // "bl output_sp;" + : + : + : "sp" + ); + asm volatile ( + "mov x0, %0;" + "blr x0;" + : + : "r" (thread_fn[get_current() -> id]) + : "x0", "x30" + ); + kill_thread(get_current() -> id); +} + +int thread_create(void* func) { + uart_printf ("creating thread\r\n"); + long ttbr1 = read_sysreg(ttbr1_el1); + uart_printf ("TTBR1: %llx\r\n", ttbr1); + uart_printf ("my_malloc: %llx, is at %llx\r\n", my_malloc, trans(my_malloc)); + thread* x = my_malloc(sizeof(thread)); + x -> stack_start = my_malloc(stack_size * 4); + x -> kstack_start = my_malloc(stack_size); + x -> sp = x -> kstack_start + stack_size - 16; + x -> fp = x -> sp; + x -> lr = thread_func_handler; + x -> state = 1; + + x -> PGD = va2pa(my_malloc(4096)); + memset(pa2va(x -> PGD), 0, 4096); + + for (int i = 0; i < 10; i ++) { + x -> signal_handler[i] = NULL; + x -> signal[i] = 0; + } + + for (int i = 1; i < max_thread_num; i ++) { + if (threads[i] == NULL) { + threads[i] = x; + thread_fn[i] = func; + x -> id = i; + break; + } + if (i == max_thread_num - 1) { + uart_printf ("Not enough thread resources\r\n"); + return -1; + } + } + + x -> next = NULL; + x -> prev = thread_tail; + thread_tail -> next = x; + thread_tail = thread_tail -> next; + uart_printf ("Created %d, prev: %d\r\n", x -> id, x -> prev -> id); + return x -> id; +} + +void foo(){ + for(int i = 0; i < 3; ++i) { + uart_printf("Thread id: %d %d\n", get_current() -> id, i); + delay(1e7); + schedule(); + } + // kill_thread(); + // uart_printf ("should not come here\r\n"); + // while(1); +} + +void thread_test() { + irq(0); + uart_printf ("started thread testing\r\n"); + thread_create(idle); + for (int i = 0; i < 3; i ++) { + thread_create(foo); + } + irq(1); + // schedule(); +} diff --git a/lab6/kernel/src/timer.c b/lab6/kernel/src/timer.c new file mode 100644 index 000000000..afe99e80d --- /dev/null +++ b/lab6/kernel/src/timer.c @@ -0,0 +1,56 @@ +#include "timer.h" +#include "alloc.h" +#include "mini_uart.h" +#include + + +void print_data(char* str) { + uart_printf("%s\r\n", str); +} + +timer* head; + +void push_timer(unsigned long long exp, char* str) { + + irq(0); + + timer* t = my_malloc(sizeof(timer)); + + t -> exp = exp; + for (int i = 0; ; i ++) { + t -> data[i] = str[i]; + if (str[i] == '\0') break; + } + t -> callback = print_data; + + if (head == NULL) { + head = my_malloc(sizeof(timer)); + head -> next = NULL; + } + + timer* cur = head; + while (cur -> next != NULL && cur -> next -> exp < t -> exp) { + cur = cur -> next; + } + + t -> next = cur -> next; + cur -> next = t; + + if (head -> next != NULL) { + asm volatile ("msr cntp_cval_el0, %0"::"r" (head -> next -> exp)); + asm volatile("msr cntp_ctl_el0,%0"::"r"(1)); + } + irq(1); +} + +void set_timeout(unsigned long long s, char* str) { + + asm volatile("msr DAIFSet, 0xf"); + unsigned long long cur_cnt, cnt_freq; + asm volatile ( "mrs %[x], cntpct_el0" :[x] "=r" (cur_cnt)); + asm volatile ( "mrs %[x], cntfrq_el0" :[x] "=r" (cnt_freq)); + // uart_printf("freqeucy: %d\n", cnt_freq); + cur_cnt += s * cnt_freq / 1000; + push_timer(cur_cnt, str); + asm volatile("msr DAIFClr, 0xf"); +} diff --git a/lab6/kernel/src/utils.S b/lab6/kernel/src/utils.S new file mode 100644 index 000000000..503f69b17 --- /dev/null +++ b/lab6/kernel/src/utils.S @@ -0,0 +1,9 @@ +.globl put32 +put32: + str w1,[x0] + ret + +.globl get32 +get32: + ldr w0,[x0] + ret diff --git a/lab6/kernel/test.sh b/lab6/kernel/test.sh new file mode 100755 index 000000000..b1dde6947 --- /dev/null +++ b/lab6/kernel/test.sh @@ -0,0 +1,2 @@ +#! /bin/bash +qemu-system-aarch64 -M raspi3b -kernel kernel8.img -serial null -serial stdio -dtb ../../bcm2710-rpi-3-b-plus.dtb -initrd ../../initramfs.cpio -display vnc=0.0.0.0:0 -vga std diff --git a/lab7/kernel/Makefile b/lab7/kernel/Makefile new file mode 100644 index 000000000..a4fb3bd32 --- /dev/null +++ b/lab7/kernel/Makefile @@ -0,0 +1,31 @@ +ARMGNU ?= aarch64-linux-gnu + +COPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only -O0 +ASMOPS = -Iinclude + +BUILD_DIR = build +SRC_DIR = src + +all : kernel8.img + +clean : + rm -rf $(BUILD_DIR) *.img + +$(BUILD_DIR)/%_c.o: $(SRC_DIR)/%.c + mkdir -p $(@D) + $(ARMGNU)-gcc $(COPS) -MMD -c $< -o $@ + +$(BUILD_DIR)/%_s.o: $(SRC_DIR)/%.S + $(ARMGNU)-gcc $(ASMOPS) -MMD -c $< -o $@ + +C_FILES = $(wildcard $(SRC_DIR)/*.c) +ASM_FILES = $(wildcard $(SRC_DIR)/*.S) +OBJ_FILES = $(C_FILES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%_c.o) +OBJ_FILES += $(ASM_FILES:$(SRC_DIR)/%.S=$(BUILD_DIR)/%_s.o) + +DEP_FILES = $(OBJ_FILES:%.o=%.d) +-include $(DEP_FILES) + +kernel8.img: $(SRC_DIR)/linker.ld $(OBJ_FILES) + $(ARMGNU)-ld -T $(SRC_DIR)/linker.ld -o $(BUILD_DIR)/kernel8.elf $(OBJ_FILES) + $(ARMGNU)-objcopy $(BUILD_DIR)/kernel8.elf -O binary kernel8.img diff --git "a/lab7/kernel/\\" "b/lab7/kernel/\\" new file mode 100644 index 000000000..ec17845cd --- /dev/null +++ "b/lab7/kernel/\\" @@ -0,0 +1,217 @@ +#include +#include +#include "cpio.h" +#include "mini_uart.h" +#include "helper.h" +#include "alloc.h" +#include "thread.h" +#include "mmu.h" +#include "utils.h" + +extern char* _cpio_file; +char buff[1024]; + +uint8_t hex_char_to_bin(char c) { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'a' && c <= 'f') return c - 'a' + 10; + if (c >= 'A' && c <= 'F') return c - 'A' + 10; + return 0; // Not a valid hexadecimal character +} + +uint64_t hex_to_bin(const char* hex) { + uint64_t result = 0; + for(int i = 0; i < 8; i ++) { + result = (result << 4) | hex_char_to_bin(hex[i]); + } + return result; +} + +void* cpio_find(char* name) { + char* cpio_start = _cpio_file; + struct cpio_newc_header* header = (struct cpio_newc_header*)cpio_start; + substr(buff, header -> c_magic, 0, 5); + while (same(buff, "070701")) { + // Convert c_namesize and c_filesize from ASCII hex to binary + uint64_t namesize = hex_to_bin(header->c_namesize); + uint64_t filesize = hex_to_bin(header->c_filesize); + + // Calculate the start of the file name and file data + char* filename = (char*)(header + 1); + char* filedata = filename + namesize; + filedata = (char*)((uintptr_t)filedata + ((4 - ((uintptr_t)filedata & 3)) & 3)); // Align to next 4-byte boundary + + substr(buff, filename, 0, namesize - 1); + if (same(buff, "TRAILER!!!")) { + break; // End of archive + } + + if (same(buff, name)) { + return filedata; + } + substr(buff, filename, 0, namesize - 1); + + // Move to the next header, aligning as necessary + header = (struct cpio_newc_header*)(filedata + filesize); + header = (struct cpio_newc_header*)((uintptr_t)header + ((4 - ((uintptr_t)header & 3)) & 3)); // Align to next 4-byte boundary + substr(buff, header -> c_magic, 0, 5); + } + return 0; +} + +void cpio_parse_ls() { + char* cpio_start = _cpio_file; + struct cpio_newc_header* header = (struct cpio_newc_header*)cpio_start; + substr(buff, header -> c_magic, 0, 5); + while (same(buff, "070701")) { + + // Convert c_namesize and c_filesize from ASCII hex to binary + uint64_t namesize = hex_to_bin(header->c_namesize); + uint64_t filesize = hex_to_bin(header->c_filesize); + + // Calculate the start of the file name and file data + char* filename = (char*)(header + 1); + char* filedata = filename + namesize; + filedata = (char*)((uintptr_t)filedata + ((4 - ((uintptr_t)filedata & 3)) & 3)); // Align to next 4-byte boundary + + substr(buff, filename, 0, namesize - 1); + if (same(buff, "TRAILER!!!")) { + break; // End of archive + } + uart_printf("%s\r\n", buff); + + // Move to the next header, aligning as necessary + header = (struct cpio_newc_header*)(filedata + filesize); + header = (struct cpio_newc_header*)((uintptr_t)header + ((4 - ((uintptr_t)header & 3)) & 3)); // Align to next 4-byte boundary + substr(buff, header -> c_magic, 0, 5); + } +} + +void cpio_parse_cat(char* name) { + char* cpio_start = _cpio_file; + struct cpio_newc_header* header = (struct cpio_newc_header*)cpio_start; + substr(buff, header -> c_magic, 0, 5); + while (same(buff, "070701")) { + // Convert c_namesize and c_filesize from ASCII hex to binary + uint64_t namesize = hex_to_bin(header->c_namesize); + uint64_t filesize = hex_to_bin(header->c_filesize); + + // Calculate the start of the file name and file data + char* filename = (char*)(header + 1); + char* filedata = filename + namesize; + filedata = (char*)((uintptr_t)filedata + ((4 - ((uintptr_t)filedata & 3)) & 3)); // Align to next 4-byte boundary + + substr(buff, filename, 0, namesize - 1); + if (same(buff, "TRAILER!!!")) { + break; // End of archive + } + + if (same(buff, name)) { + uart_printf ("Cat %d\r\n", filesize); + substr(buff, filedata, 0, filesize - 1); + uart_printf("%s\r\n", buff); + } + substr(buff, filename, 0, namesize - 1); + + // Move to the next header, aligning as necessary + header = (struct cpio_newc_header*)(filedata + filesize); + header = (struct cpio_newc_header*)((uintptr_t)header + ((4 - ((uintptr_t)header & 3)) & 3)); // Align to next 4-byte boundary + substr(buff, header -> c_magic, 0, 5); + } +} + +extern thread* get_current(); + +void cpio_load(char* str) { + irq(0); + thread_init(); + thread* cur = get_current(); + uart_printf ("cur: %llx\r\n", cur); + long xxx = read_sysreg(tpidr_el1); + uart_printf ("xxx: %llx\r\n", xxx); + + void* pos = cpio_find(str); + cur -> code = my_malloc(4096 * 64); + cur -> code_size = 4096 * 64; + for (int i = 0; i < cur -> code_size; i ++) { + ((char*)cur -> code)[i] = ((char*)pos)[i]; + } + + uart_printf ("%llx, %llx, %llx\r\n", cur -> PGD, pa2va(cur -> PGD), &(cur -> PGD)); + + setup_peripheral_identity(pa2va(cur -> PGD)); + for (int i = 0; i < cur -> code_size; i += 4096) { + map_page(pa2va(cur -> PGD), i, va2pa(cur -> code) + i, (1 << 6)); + } + for (int i = 0; i < 4; i ++) { + map_page (pa2va(cur -> PGD), 0xffffffffb000L + i * 4096, va2pa(cur -> stack_start) + i * 4096, (1 << 6)); + } + cur -> code = 0; + cur -> stack_start = 0xffffffffb000L; + void* sp = 0xfffffffff000L - 16; + void* el1_sp = cur -> sp; + + long ttbr1 = read_sysreg(ttbr1_el1); + long ttbr0 = read_sysreg(ttbr0_el1); + uart_printf ("TTBR0: %llx, TTBR1: %llx\r\n", ttbr0, ttbr1); + + uart_printf ("cur -> PGD %llx\r\n", cur -> PGD); + + // uart_printf("Running code from %llx, which is %llx\n", cur -> code, trans(cur -> code)); + + asm volatile("dsb ish"); + write_sysreg(ttbr0_el1, cur -> PGD); + asm volatile("tlbi vmalle1is"); + asm volatile("dsb ish"); + asm volatile("isb"); + + + uart_printf ("uart printf: %llx\r\n", uart_printf); + while (1); + + uart_printf("Running code from %llx, which is %llx\n", cur -> code, trans_el0(cur -> code)); + ttbr1 = read_sysreg(ttbr1_el1); + ttbr0 = read_sysreg(ttbr0_el1); + uart_printf ("TTBR0: %llx, TTBR1: %llx, &TTBR0: %llx\r\n", ttbr0, ttbr1, &ttbr0); + + asm volatile( + "mov x1, 0;" + "msr spsr_el1, x1;" + "mov x1, %[code];" + "mov x2, %[sp];" + "msr elr_el1, x1;" + "msr sp_el0, x2;" + "msr DAIFclr, 0xf;" + "mov sp, %[sp_el1];" + "eret;" + : + : [code] "r" (cur -> code), [sp] "r" (sp), [sp_el1] "r" (el1_sp) + : "x1", "x2", "sp" + ); +} + +char* get_cpio_end() { + char* cpio_start = _cpio_file; + struct cpio_newc_header* header = (struct cpio_newc_header*)cpio_start; + substr(buff, header -> c_magic, 0, 5); + while (same(buff, "070701")) { + uint64_t namesize = hex_to_bin(header->c_namesize); + uint64_t filesize = hex_to_bin(header->c_filesize); + + char* filename = (char*)(header + 1); + char* filedata = filename + namesize; + filedata = (char*)((uintptr_t)filedata + ((4 - ((uintptr_t)filedata & 3)) & 3)); // Align to next 4-byte boundary + + substr(buff, filename, 0, namesize - 1); + if (same(buff, "TRAILER!!!")) { + return filedata + filesize; + } + + substr(buff, filename, 0, namesize - 1); + + // Move to the next header, aligning as necessary + header = (struct cpio_newc_header*)(filedata + filesize); + header = (struct cpio_newc_header*)((uintptr_t)header + ((4 - ((uintptr_t)header & 3)) & 3)); // Align to next 4-byte boundary + substr(buff, header -> c_magic, 0, 5); + } + return header; +} diff --git a/lab7/kernel/asm_test.sh b/lab7/kernel/asm_test.sh new file mode 100755 index 000000000..4ebc6f3a2 --- /dev/null +++ b/lab7/kernel/asm_test.sh @@ -0,0 +1 @@ +qemu-system-aarch64 -M raspi3b -kernel kernel8.img -serial null -serial stdio -dtb ../../bcm2710-rpi-3-b-plus.dtb -initrd ../../initramfs.cpio -display vnc=0.0.0.0:0 -vga std -d in_asm diff --git a/lab7/kernel/build/alloc_c.d b/lab7/kernel/build/alloc_c.d new file mode 100644 index 000000000..8a63d0860 --- /dev/null +++ b/lab7/kernel/build/alloc_c.d @@ -0,0 +1,3 @@ +build/alloc_c.o: src/alloc.c include/alloc.h include/mini_uart.h \ + include/fdt.h include/set.h include/mini_uart.h include/alloc.h \ + include/cpio.h include/mmu.h diff --git a/lab7/kernel/build/alloc_c.o b/lab7/kernel/build/alloc_c.o new file mode 100644 index 000000000..6e0f76c64 Binary files /dev/null and b/lab7/kernel/build/alloc_c.o differ diff --git a/lab7/kernel/build/boot_s.d b/lab7/kernel/build/boot_s.d new file mode 100644 index 000000000..1bbe62f69 --- /dev/null +++ b/lab7/kernel/build/boot_s.d @@ -0,0 +1 @@ +build/boot_s.o: src/boot.S include/mmu_regs.h diff --git a/lab7/kernel/build/boot_s.o b/lab7/kernel/build/boot_s.o new file mode 100644 index 000000000..eb4bc3b61 Binary files /dev/null and b/lab7/kernel/build/boot_s.o differ diff --git a/lab7/kernel/build/cpio_c.d b/lab7/kernel/build/cpio_c.d new file mode 100644 index 000000000..90cce564a --- /dev/null +++ b/lab7/kernel/build/cpio_c.d @@ -0,0 +1,3 @@ +build/cpio_c.o: src/cpio.c include/cpio.h include/mini_uart.h \ + include/helper.h include/alloc.h include/thread.h include/vfs.h \ + include/mmu.h include/utils.h include/vfs.h include/initramfs.h diff --git a/lab7/kernel/build/cpio_c.o b/lab7/kernel/build/cpio_c.o new file mode 100644 index 000000000..55b6af6ba Binary files /dev/null and b/lab7/kernel/build/cpio_c.o differ diff --git a/lab7/kernel/build/exception_c.d b/lab7/kernel/build/exception_c.d new file mode 100644 index 000000000..098f97a2d --- /dev/null +++ b/lab7/kernel/build/exception_c.d @@ -0,0 +1,4 @@ +build/exception_c.o: src/exception.c include/exception.h \ + include/mini_uart.h include/utils.h include/mmio.h include/DEFINE.h \ + include/timer.h include/task.h include/system_call.h include/exception.h \ + include/thread.h include/vfs.h diff --git a/lab7/kernel/build/exception_c.o b/lab7/kernel/build/exception_c.o new file mode 100644 index 000000000..bc759d4ad Binary files /dev/null and b/lab7/kernel/build/exception_c.o differ diff --git a/lab7/kernel/build/fdt_c.d b/lab7/kernel/build/fdt_c.d new file mode 100644 index 000000000..b4593fc62 --- /dev/null +++ b/lab7/kernel/build/fdt_c.d @@ -0,0 +1,2 @@ +build/fdt_c.o: src/fdt.c include/fdt.h include/mini_uart.h \ + include/utils.h include/helper.h diff --git a/lab7/kernel/build/fdt_c.o b/lab7/kernel/build/fdt_c.o new file mode 100644 index 000000000..835c41c39 Binary files /dev/null and b/lab7/kernel/build/fdt_c.o differ diff --git a/lab7/kernel/build/framebuffer_c.d b/lab7/kernel/build/framebuffer_c.d new file mode 100644 index 000000000..730d36f60 --- /dev/null +++ b/lab7/kernel/build/framebuffer_c.d @@ -0,0 +1,2 @@ +build/framebuffer_c.o: src/framebuffer.c include/vfs.h \ + include/framebuffer.h include/vfs.h include/alloc.h include/helper.h diff --git a/lab7/kernel/build/framebuffer_c.o b/lab7/kernel/build/framebuffer_c.o new file mode 100644 index 000000000..00148e6bb Binary files /dev/null and b/lab7/kernel/build/framebuffer_c.o differ diff --git a/lab7/kernel/build/framebufferfs_c.d b/lab7/kernel/build/framebufferfs_c.d new file mode 100644 index 000000000..45d3b04fd --- /dev/null +++ b/lab7/kernel/build/framebufferfs_c.d @@ -0,0 +1,3 @@ +build/framebufferfs_c.o: src/framebufferfs.c include/vfs.h \ + include/framebufferfs.h include/vfs.h include/alloc.h include/helper.h \ + include/mail.h diff --git a/lab7/kernel/build/framebufferfs_c.o b/lab7/kernel/build/framebufferfs_c.o new file mode 100644 index 000000000..29f1c3dd7 Binary files /dev/null and b/lab7/kernel/build/framebufferfs_c.o differ diff --git a/lab7/kernel/build/helper_c.d b/lab7/kernel/build/helper_c.d new file mode 100644 index 000000000..cb268cdc7 --- /dev/null +++ b/lab7/kernel/build/helper_c.d @@ -0,0 +1 @@ +build/helper_c.o: src/helper.c include/mini_uart.h diff --git a/lab7/kernel/build/helper_c.o b/lab7/kernel/build/helper_c.o new file mode 100644 index 000000000..46a8017d0 Binary files /dev/null and b/lab7/kernel/build/helper_c.o differ diff --git a/lab7/kernel/build/initramfs_c.d b/lab7/kernel/build/initramfs_c.d new file mode 100644 index 000000000..7d5b104af --- /dev/null +++ b/lab7/kernel/build/initramfs_c.d @@ -0,0 +1,3 @@ +build/initramfs_c.o: src/initramfs.c include/initramfs.h include/vfs.h \ + include/alloc.h include/vfs.h include/mini_uart.h include/helper.h \ + include/fdt.h include/cpio.h diff --git a/lab7/kernel/build/initramfs_c.o b/lab7/kernel/build/initramfs_c.o new file mode 100644 index 000000000..10c04844a Binary files /dev/null and b/lab7/kernel/build/initramfs_c.o differ diff --git a/lab7/kernel/build/kernel8.elf b/lab7/kernel/build/kernel8.elf new file mode 100755 index 000000000..08383ff33 Binary files /dev/null and b/lab7/kernel/build/kernel8.elf differ diff --git a/lab7/kernel/build/kernel_start_c.d b/lab7/kernel/build/kernel_start_c.d new file mode 100644 index 000000000..beaa37f34 --- /dev/null +++ b/lab7/kernel/build/kernel_start_c.d @@ -0,0 +1,3 @@ +build/kernel_start_c.o: src/kernel_start.c include/mini_uart.h \ + include/shell.h include/fdt.h include/cpio.h include/alloc.h \ + include/thread.h include/vfs.h include/mmu.h diff --git a/lab7/kernel/build/kernel_start_c.o b/lab7/kernel/build/kernel_start_c.o new file mode 100644 index 000000000..28c0f0684 Binary files /dev/null and b/lab7/kernel/build/kernel_start_c.o differ diff --git a/lab7/kernel/build/mail_c.d b/lab7/kernel/build/mail_c.d new file mode 100644 index 000000000..99d78e84d --- /dev/null +++ b/lab7/kernel/build/mail_c.d @@ -0,0 +1 @@ +build/mail_c.o: src/mail.c include/mini_uart.h include/mail.h diff --git a/lab7/kernel/build/mail_c.o b/lab7/kernel/build/mail_c.o new file mode 100644 index 000000000..21f892467 Binary files /dev/null and b/lab7/kernel/build/mail_c.o differ diff --git a/lab7/kernel/build/mini_uart_c.d b/lab7/kernel/build/mini_uart_c.d new file mode 100644 index 000000000..d6054bce7 --- /dev/null +++ b/lab7/kernel/build/mini_uart_c.d @@ -0,0 +1,2 @@ +build/mini_uart_c.o: src/mini_uart.c include/utils.h include/helper.h \ + include/mmio.h include/DEFINE.h diff --git a/lab7/kernel/build/mini_uart_c.o b/lab7/kernel/build/mini_uart_c.o new file mode 100644 index 000000000..f5da91883 Binary files /dev/null and b/lab7/kernel/build/mini_uart_c.o differ diff --git a/lab7/kernel/build/mm_s.d b/lab7/kernel/build/mm_s.d new file mode 100644 index 000000000..6749a99b3 --- /dev/null +++ b/lab7/kernel/build/mm_s.d @@ -0,0 +1 @@ +build/mm_s.o: src/mm.S diff --git a/lab7/kernel/build/mm_s.o b/lab7/kernel/build/mm_s.o new file mode 100644 index 000000000..5f5830933 Binary files /dev/null and b/lab7/kernel/build/mm_s.o differ diff --git a/lab7/kernel/build/mmio_c.d b/lab7/kernel/build/mmio_c.d new file mode 100644 index 000000000..e7a32746f --- /dev/null +++ b/lab7/kernel/build/mmio_c.d @@ -0,0 +1 @@ +build/mmio_c.o: src/mmio.c include/mmio.h diff --git a/lab7/kernel/build/mmio_c.o b/lab7/kernel/build/mmio_c.o new file mode 100644 index 000000000..cef85b4db Binary files /dev/null and b/lab7/kernel/build/mmio_c.o differ diff --git a/lab7/kernel/build/mmu_c.d b/lab7/kernel/build/mmu_c.d new file mode 100644 index 000000000..c6630756b --- /dev/null +++ b/lab7/kernel/build/mmu_c.d @@ -0,0 +1,3 @@ +build/mmu_c.o: src/mmu.c include/mmu.h include/helper.h include/utils.h \ + include/alloc.h include/thread.h include/vfs.h include/mmu_regs.h \ + include/mini_uart.h diff --git a/lab7/kernel/build/mmu_c.o b/lab7/kernel/build/mmu_c.o new file mode 100644 index 000000000..1cb8bdd96 Binary files /dev/null and b/lab7/kernel/build/mmu_c.o differ diff --git a/lab7/kernel/build/shell_c.d b/lab7/kernel/build/shell_c.d new file mode 100644 index 000000000..2df705ec3 --- /dev/null +++ b/lab7/kernel/build/shell_c.d @@ -0,0 +1,5 @@ +build/shell_c.o: src/shell.c include/shell.h include/mini_uart.h \ + include/reboot.h include/mail.h include/helper.h include/loader.h \ + include/cpio.h include/alloc.h include/fdt.h include/timer.h \ + include/exception.h include/thread.h include/vfs.h include/system_call.h \ + include/exception.h include/signal.h include/mmu.h diff --git a/lab7/kernel/build/shell_c.o b/lab7/kernel/build/shell_c.o new file mode 100644 index 000000000..a9b3abb01 Binary files /dev/null and b/lab7/kernel/build/shell_c.o differ diff --git a/lab7/kernel/build/signal_c.d b/lab7/kernel/build/signal_c.d new file mode 100644 index 000000000..32c3ae705 --- /dev/null +++ b/lab7/kernel/build/signal_c.d @@ -0,0 +1,2 @@ +build/signal_c.o: src/signal.c include/thread.h include/vfs.h \ + include/signal.h diff --git a/lab7/kernel/build/signal_c.o b/lab7/kernel/build/signal_c.o new file mode 100644 index 000000000..8b8635648 Binary files /dev/null and b/lab7/kernel/build/signal_c.o differ diff --git a/lab7/kernel/build/system_call_c.d b/lab7/kernel/build/system_call_c.d new file mode 100644 index 000000000..7ba360c7e --- /dev/null +++ b/lab7/kernel/build/system_call_c.d @@ -0,0 +1,5 @@ +build/system_call_c.o: src/system_call.c include/system_call.h \ + include/exception.h include/alloc.h include/thread.h include/vfs.h \ + include/mail.h include/cpio.h include/mini_uart.h include/helper.h \ + include/exception.h include/utils.h include/mmu.h \ + include/framebufferfs.h diff --git a/lab7/kernel/build/system_call_c.o b/lab7/kernel/build/system_call_c.o new file mode 100644 index 000000000..c6f01f890 Binary files /dev/null and b/lab7/kernel/build/system_call_c.o differ diff --git a/lab7/kernel/build/system_call_s.d b/lab7/kernel/build/system_call_s.d new file mode 100644 index 000000000..36807c754 --- /dev/null +++ b/lab7/kernel/build/system_call_s.d @@ -0,0 +1 @@ +build/system_call_s.o: src/system_call.S diff --git a/lab7/kernel/build/system_call_s.o b/lab7/kernel/build/system_call_s.o new file mode 100644 index 000000000..555ba6157 Binary files /dev/null and b/lab7/kernel/build/system_call_s.o differ diff --git a/lab7/kernel/build/task_c.d b/lab7/kernel/build/task_c.d new file mode 100644 index 000000000..36a5b99a8 --- /dev/null +++ b/lab7/kernel/build/task_c.d @@ -0,0 +1,2 @@ +build/task_c.o: src/task.c include/task.h include/alloc.h \ + include/mini_uart.h include/utils.h diff --git a/lab7/kernel/build/task_c.o b/lab7/kernel/build/task_c.o new file mode 100644 index 000000000..61a1c132c Binary files /dev/null and b/lab7/kernel/build/task_c.o differ diff --git a/lab7/kernel/build/thread_c.d b/lab7/kernel/build/thread_c.d new file mode 100644 index 000000000..3453c12bb --- /dev/null +++ b/lab7/kernel/build/thread_c.d @@ -0,0 +1,4 @@ +build/thread_c.o: src/thread.c include/thread.h include/vfs.h \ + include/alloc.h include/mini_uart.h include/helper.h include/exception.h \ + include/signal.h include/mmu.h include/utils.h include/system_call.h \ + include/exception.h diff --git a/lab7/kernel/build/thread_c.o b/lab7/kernel/build/thread_c.o new file mode 100644 index 000000000..1723e03a7 Binary files /dev/null and b/lab7/kernel/build/thread_c.o differ diff --git a/lab7/kernel/build/timer_c.d b/lab7/kernel/build/timer_c.d new file mode 100644 index 000000000..b7ed93425 --- /dev/null +++ b/lab7/kernel/build/timer_c.d @@ -0,0 +1,2 @@ +build/timer_c.o: src/timer.c include/timer.h include/alloc.h \ + include/mini_uart.h diff --git a/lab7/kernel/build/timer_c.o b/lab7/kernel/build/timer_c.o new file mode 100644 index 000000000..35ae2964e Binary files /dev/null and b/lab7/kernel/build/timer_c.o differ diff --git a/lab7/kernel/build/tmpfs_c.d b/lab7/kernel/build/tmpfs_c.d new file mode 100644 index 000000000..ee47449a4 --- /dev/null +++ b/lab7/kernel/build/tmpfs_c.d @@ -0,0 +1,2 @@ +build/tmpfs_c.o: src/tmpfs.c include/tmpfs.h include/vfs.h include/vfs.h \ + include/mini_uart.h include/helper.h include/alloc.h diff --git a/lab7/kernel/build/tmpfs_c.o b/lab7/kernel/build/tmpfs_c.o new file mode 100644 index 000000000..8c1612221 Binary files /dev/null and b/lab7/kernel/build/tmpfs_c.o differ diff --git a/lab7/kernel/build/uartfs_c.d b/lab7/kernel/build/uartfs_c.d new file mode 100644 index 000000000..087cb7e9f --- /dev/null +++ b/lab7/kernel/build/uartfs_c.d @@ -0,0 +1,2 @@ +build/uartfs_c.o: src/uartfs.c include/vfs.h include/uartfs.h \ + include/vfs.h include/mini_uart.h include/alloc.h include/helper.h diff --git a/lab7/kernel/build/uartfs_c.o b/lab7/kernel/build/uartfs_c.o new file mode 100644 index 000000000..092f76e35 Binary files /dev/null and b/lab7/kernel/build/uartfs_c.o differ diff --git a/lab7/kernel/build/utils_s.d b/lab7/kernel/build/utils_s.d new file mode 100644 index 000000000..5af69aba7 --- /dev/null +++ b/lab7/kernel/build/utils_s.d @@ -0,0 +1 @@ +build/utils_s.o: src/utils.S diff --git a/lab7/kernel/build/utils_s.o b/lab7/kernel/build/utils_s.o new file mode 100644 index 000000000..81addeb90 Binary files /dev/null and b/lab7/kernel/build/utils_s.o differ diff --git a/lab7/kernel/build/vfs_c.d b/lab7/kernel/build/vfs_c.d new file mode 100644 index 000000000..6c4df116b --- /dev/null +++ b/lab7/kernel/build/vfs_c.d @@ -0,0 +1,3 @@ +build/vfs_c.o: src/vfs.c include/vfs.h include/tmpfs.h include/vfs.h \ + include/initramfs.h include/framebufferfs.h include/uartfs.h \ + include/mini_uart.h include/helper.h include/alloc.h diff --git a/lab7/kernel/build/vfs_c.o b/lab7/kernel/build/vfs_c.o new file mode 100644 index 000000000..ed06c7c38 Binary files /dev/null and b/lab7/kernel/build/vfs_c.o differ diff --git a/lab7/kernel/include/DEFINE.h b/lab7/kernel/include/DEFINE.h new file mode 100644 index 000000000..43c55152d --- /dev/null +++ b/lab7/kernel/include/DEFINE.h @@ -0,0 +1,58 @@ +#define MMIO_BASE 0xffff00003F000000 +#define PBASE MMIO_BASE + +#define AUX_IRQ ((volatile unsigned int*)(MMIO_BASE + 0x00215000)) +// Auxiliary enables +#define AUX_ENABLE ((volatile unsigned int*)(MMIO_BASE + 0x00215004)) +// Mini Uart I/O Data +#define AUX_MU_IO_REG ((volatile unsigned int*)(MMIO_BASE + 0x00215040)) +// Mini Uart Interrupt Enable +#define AUX_MU_IER_REG ((volatile unsigned int*)(MMIO_BASE + 0x00215044)) +// Mini Uart Interrupt Identity +#define AUX_MU_IIR_REG ((volatile unsigned int*)(MMIO_BASE + 0x00215048)) +// Mini Uart Line Control +#define AUX_MU_LCR_REG ((volatile unsigned int*)(MMIO_BASE + 0x0021504C)) +// Mini Uart Modem Control +#define AUX_MU_MCR_REG ((volatile unsigned int*)(MMIO_BASE + 0x00215050)) +// Mini Uart Line Status +#define AUX_MU_LSR_REG ((volatile unsigned int*)(MMIO_BASE + 0x00215054)) +// Mini Uart Modem Status +#define AUX_MU_MSR_REG ((volatile unsigned int*)(MMIO_BASE + 0x00215058)) +// Mini Uart Scratch +#define AUX_MU_SCRATCH ((volatile unsigned int*)(MMIO_BASE + 0x0021505C)) +// Mini Uart Scratch +#define AUX_MU_CNTL_REG ((volatile unsigned int*)(MMIO_BASE + 0x00215060)) +// Mini Uart Extra Status +#define AUX_MU_STAT_REG ((volatile unsigned int*)(MMIO_BASE + 0x00215064)) +// Mini Uart Baudrate +#define AUX_MU_BAUD_REG ((volatile unsigned int*)(MMIO_BASE + 0x00215068)) + +#define IRQ_basic_pending ((volatile unsigned int*)(MMIO_BASE + 0x0000B200)) +#define IRQ_pending_1 ((volatile unsigned int*)(MMIO_BASE + 0x0000B204)) +#define IRQ_pending_2 ((volatile unsigned int*)(MMIO_BASE + 0x0000B208)) +#define FIQ_control ((volatile unsigned int*)(MMIO_BASE + 0x0000B20C)) +#define Enable_IRQs_1 ((volatile unsigned int*)(MMIO_BASE + 0x0000B210)) +#define Enable_IRQs_2 ((volatile unsigned int*)(MMIO_BASE + 0x0000B214)) +#define Enable_Basic_IRQs ((volatile unsigned int*)(MMIO_BASE + 0x0000B218)) +#define Disable_IRQs_1 ((volatile unsigned int*)(MMIO_BASE + 0x0000B21C)) +#define Disable_IRQs_2 ((volatile unsigned int*)(MMIO_BASE + 0x0000B220)) +#define Disable_Basic_IRQs ((volatile unsigned int*)(MMIO_BASE + 0x0000B224)) +#define CORE0_INT_SRC (volatile unsigned int*)(0xffff000040000060) +#define CORE0_TIMER_IRQ_CTRL (volatile unsigned int*)(0xffff000040000040) + +#define GPFSEL1 (PBASE+0x00200004) +#define GPSET0 (PBASE+0x0020001C) +#define GPCLR0 (PBASE+0x00200028) +#define GPPUD (PBASE+0x00200094) +#define GPPUDCLK0 (PBASE+0x00200098) + +#define UART_DR ( (volatile unsigned int *) ( MMIO_BASE + 0x00201000 ) ) /* Data Register */ +#define UART_FR ( (volatile unsigned int *) ( MMIO_BASE + 0x00201018 ) ) /* Flag register */ +#define UART_IBRD ( (volatile unsigned int *) ( MMIO_BASE + 0x00201024 ) ) /* Integer Baud Rate Divisor */ +#define UART_FBRD ( (volatile unsigned int *) ( MMIO_BASE + 0x00201028 ) ) /* RFractional Baud Rate Divisor */ +#define UART_LCRH ( (volatile unsigned int *) ( MMIO_BASE + 0x0020102C ) ) /* Line Control Register */ +#define UART_CR ( (volatile unsigned int *) ( MMIO_BASE + 0x00201030 ) ) /* Control Register */ +#define UART_RIS ( (volatile unsigned int *) ( MMIO_BASE + 0x0020103C ) ) +#define UART_IMSC ( (volatile unsigned int *) ( MMIO_BASE + 0x00201038 ) ) /* Interupt FIFO Level Select Register */ +#define UART_MIS ( (volatile unsigned int *) ( MMIO_BASE + 0x00201040 ) ) +#define UART_ICR ( (volatile unsigned int *) ( MMIO_BASE + 0x00201044 ) ) /* Interupt Clear Register */ diff --git a/lab7/kernel/include/alloc.h b/lab7/kernel/include/alloc.h new file mode 100644 index 000000000..4ad1da9ab --- /dev/null +++ b/lab7/kernel/include/alloc.h @@ -0,0 +1,22 @@ +#ifndef ALLOC_H +#define ALLOC_H + +#include + +void* simple_malloc(int, int); + +void reserve(unsigned long l, unsigned long r); +void frame_init(); + +void* frame_malloc(size_t size); +void* my_malloc(size_t size); + +void frame_free(char*); +void my_free(char*); + +void print_node_list(); +void print_pool(); + +void manage_init (); + +#endif diff --git a/lab7/kernel/include/cpio.h b/lab7/kernel/include/cpio.h new file mode 100644 index 000000000..2acf77ef2 --- /dev/null +++ b/lab7/kernel/include/cpio.h @@ -0,0 +1,35 @@ +#ifndef CPIO_H +#define CPIO_H + +#include +#include + +struct cpio_newc_header { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; + }; + + +void cpio_parse_ls(); +void cpio_parse_cat(char*); +void cpio_load(char*); +void* cpio_find(char*); + +char* get_cpio_end(); + +uint8_t hex_char_to_bin(char c); +uint64_t hex_to_bin(const char* hex); + +#endif diff --git a/lab7/kernel/include/exception.h b/lab7/kernel/include/exception.h new file mode 100644 index 000000000..49e60c3b2 --- /dev/null +++ b/lab7/kernel/include/exception.h @@ -0,0 +1,16 @@ +#ifndef EXCEPTION_H +#define EXCEPTION_H + +typedef struct trapframe_t{ + unsigned long long x[32]; + // x[31] is empty + unsigned long long spsr_el1; + unsigned long long elr_el1; + unsigned long long sp_el0; +} trapframe_t; +// basically all the shits stored by save_all + +void exception_entry(); +void core_timer_entry(); + +#endif diff --git a/lab7/kernel/include/fdt.h b/lab7/kernel/include/fdt.h new file mode 100644 index 000000000..b90850855 --- /dev/null +++ b/lab7/kernel/include/fdt.h @@ -0,0 +1,113 @@ +// Ref: https://elixir.bootlin.com/linux/v5.16.14/source/scripts/dtc/libfdt/fdt.h +#ifndef _FDT_H +#define _FDT_H + +#include +#include + +typedef int (*fdt_parser)(int level, char *cur, char *dt_strings); + +void fdt_traversal(char *dtb); +void parse_dtb(char *dtb, fdt_parser parser); + +typedef uint32_t fdt32_t; +typedef uint64_t fdt64_t; + +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright 2012 Kim Phillips, Freescale Semiconductor. + */ + +#ifndef __ASSEMBLY__ + +struct fdt_header { + fdt32_t magic; /* magic word FDT_MAGIC */ + fdt32_t totalsize; /* total size of DT block */ + fdt32_t off_dt_struct; /* offset to structure */ + fdt32_t off_dt_strings; /* offset to strings */ + fdt32_t off_mem_rsvmap; /* offset to memory reserve map */ + fdt32_t version; /* format version */ + fdt32_t last_comp_version; /* last compatible version */ + + /* version 2 fields below */ + fdt32_t boot_cpuid_phys; /* Which physical CPU id we're + booting on */ + /* version 3 fields below */ + fdt32_t size_dt_strings; /* size of the strings block */ + + /* version 17 fields below */ + fdt32_t size_dt_struct; /* size of the structure block */ +}; + +struct fdt_node_header { + fdt32_t tag; + char name[0]; +}; + +struct fdt_property { + fdt32_t tag; + fdt32_t len; + fdt32_t nameoff; + char data[0]; +}; + +#endif /* !__ASSEMBLY */ + +#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ +#define FDT_TAGSIZE sizeof(fdt32_t) + +#define FDT_BEGIN_NODE 0x1 /* Start node: full name */ +#define FDT_END_NODE 0x2 /* End node */ +#define FDT_PROP 0x3 /* Property: name off, size, content */ +#define FDT_NOP 0x4 /* nop */ +#define FDT_END 0x9 + +#define FDT_V1_SIZE (7*sizeof(fdt32_t)) +#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(fdt32_t)) +#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t)) +#define FDT_V16_SIZE FDT_V3_SIZE +#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t)) + +// Ref: https://elixir.bootlin.com/linux/v5.16.14/source/scripts/dtc/libfdt/libfdt.h#L249 +#define fdt_get_header(fdt, field) \ + (fdt32_ld(&((const struct fdt_header *)(fdt))->field)) +#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) +#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) +#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) +#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) +#define fdt_version(fdt) (fdt_get_header(fdt, version)) +#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) +#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) +#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) + +#define fdtn_get_header(fdtn, field) \ + (fdt32_ld(&((const struct fdt_node_header *)(fdtn))->field)) +#define fdtn_tag(fdtn) (fdtn_get_header(fdtn, tag)) + +#define fdtp_get_header(fdtp, field) \ + (fdt32_ld(&((const struct fdt_property *)(fdtp))->field)) +#define fdtp_tag(fdtp) (fdtp_get_header(fdtp, tag)) +#define fdtp_len(fdtp) (fdtp_get_header(fdtp, len)) +#define fdtp_nameoff(fdtp) (fdtp_get_header(fdtp, nameoff)) + +// Load fdt32 (big-endian) +static inline uint32_t fdt32_ld(const fdt32_t *p) +{ + const uint8_t *bp = (const uint8_t *)p; + + return ((uint32_t)bp[0] << 24) + | ((uint32_t)bp[1] << 16) + | ((uint32_t)bp[2] << 8) + | bp[3]; +} + +typedef uint32_t (*fdt_callback)(int type, char *name, char *data, uint32_t size); +uint32_t print_dtb(int type, char *name, char *data, uint32_t size) ; +uint32_t get_initramfs_addr(int type, char *name, char *data, uint32_t size); +uint32_t fdt_traverse(fdt_callback cb); + +long get_fdt_end(); + + +#endif /* _FDT_H */ diff --git a/lab7/kernel/include/framebufferfs.h b/lab7/kernel/include/framebufferfs.h new file mode 100644 index 000000000..3cdbc702f --- /dev/null +++ b/lab7/kernel/include/framebufferfs.h @@ -0,0 +1,25 @@ +#ifndef FRAMEBUFFER_H +#define FRAMEBUFFER_H + +#include "vfs.h" + +typedef struct framebuffer_node{ + char name[MAX_PATH_SIZE]; + int type; // directory, mount, file + unsigned int width, height, pitch, isrgb; + char* lfb; +} framebuffer_node; + +int framebuffer_write(struct file *file, const char *buf, size_t len); +int framebuffer_read(struct file *file, char *buf, size_t len); +int framebuffer_open(struct vnode *file_node, struct file **target); +int framebuffer_close(struct file *file); + +int framebuffer_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name); +int framebuffer_create(struct vnode *dir_node, struct vnode **target, const char *component_name); +int framebuffer_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name); + +int framebuffer_mount(filesystem*, mount*); + + +#endif diff --git a/lab7/kernel/include/helper.h b/lab7/kernel/include/helper.h new file mode 100644 index 000000000..ca59ae019 --- /dev/null +++ b/lab7/kernel/include/helper.h @@ -0,0 +1,17 @@ +#ifndef HELPER_H +#define HELPER_H + +void hex_to_string(unsigned int, char*); +int same(char*, char*); + +void substr(char*, char*, int, int); +int strlen(char*); +void strcpy(char*, char*, int); +void strcpy_to0(char*, char*); + +unsigned long stoi(char*); +void delay (unsigned long long); + +void memset(char*, char, int); + +#endif diff --git a/lab7/kernel/include/initramfs.h b/lab7/kernel/include/initramfs.h new file mode 100644 index 000000000..fd3940a6f --- /dev/null +++ b/lab7/kernel/include/initramfs.h @@ -0,0 +1,25 @@ +#ifndef INITRAMFS_H +#define INITRAMFS_H + +#include "vfs.h" + +typedef struct initramfs_node{ + char name[MAX_PATH_SIZE]; + struct vnode * entry[MAX_ENTRY_SIZE]; + char * data; // simply point to the place in initramfs + int size; // get by the code +} initramfs_node; + +int reg_initramfs(); +int initramfs_write(struct file *file, const void *buf, size_t len); +int initramfs_read(struct file *file, void *buf, size_t len); +int initramfs_open(struct vnode *file_node, struct file **target); +int initramfs_close(struct file *file); + +int initramfs_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name); +int initramfs_create(struct vnode *dir_node, struct vnode **target, const char *component_name); +int initramfs_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name); + +int initramfs_mount (struct filesystem *_fs, struct mount *mt); + +#endif diff --git a/lab7/kernel/include/kernel.h b/lab7/kernel/include/kernel.h new file mode 100644 index 000000000..d2e9fcc54 --- /dev/null +++ b/lab7/kernel/include/kernel.h @@ -0,0 +1,6 @@ +#ifndef KERNEL_H +#define KERNEL_H + +void kernel_begin(char*); + +#endif diff --git a/lab7/kernel/include/loader.h b/lab7/kernel/include/loader.h new file mode 100644 index 000000000..70dcbe9d7 --- /dev/null +++ b/lab7/kernel/include/loader.h @@ -0,0 +1,6 @@ +#ifndef LOADER_H +#define LOADER_H + +void load_kernel(); + +#endif diff --git a/lab7/kernel/include/mail.h b/lab7/kernel/include/mail.h new file mode 100644 index 000000000..38340b34c --- /dev/null +++ b/lab7/kernel/include/mail.h @@ -0,0 +1,23 @@ +#define MMIO_BASE 0x3F000000 + 0xffff000000000000 +#define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880) +#define MAILBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0)) +#define MAILBOX_POLL ((volatile unsigned int*)(VIDEOCORE_MBOX+0x10)) +#define MAILBOX_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX+0x14)) +#define MAILBOX_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX+0x18)) +#define MAILBOX_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX+0x1C)) +#define MAILBOX_WRITE ((volatile unsigned int*)(VIDEOCORE_MBOX+0x20)) +#define MAILBOX_RESPONSE 0x80000000 +#define MAILBOX_FULL 0x80000000 +#define MAILBOX_EMPTY 0x40000000 + +#define GET_BOARD_REVISION 0x00010002 +#define GET_ARM_MEMORY 0x00010005 +#define REQUEST_CODE 0x00000000 +#define REQUEST_SUCCEED 0x80000000 +#define REQUEST_FAILED 0x80000001 +#define TAG_REQUEST_CODE 0x00000000 +#define END_TAG 0x00000000 + +unsigned int get_board_revision(); +int get_arm_memory(unsigned int*); +int mailbox_call(unsigned int*, unsigned char); diff --git a/lab7/kernel/include/mini_uart.h b/lab7/kernel/include/mini_uart.h new file mode 100644 index 000000000..853929005 --- /dev/null +++ b/lab7/kernel/include/mini_uart.h @@ -0,0 +1,28 @@ +#ifndef _MINI_UART_H +#define _MINI_UART_H + +#include +#include + +void uart_init ( void ); +char uart_recv ( void ); +void uart_send ( char c ); +void uart_recv_string( char* buf ); +uint32_t uart_recv_uint(void); +void uart_printf(char* fmt, ...); +void uart_send_num(int64_t, int, int); + +void uart_irq_on(); +void uart_irq_off(); +void uart_irq_send(char*, int); +char uart_irq_read(); + +void change_read_irq(int); +void change_write_irq(int); + +void irq(int); + +void recv_handler(); +void write_handler(); + +#endif /*_MINI_UART_H */ diff --git a/lab7/kernel/include/mm.h b/lab7/kernel/include/mm.h new file mode 100644 index 000000000..784ac4b88 --- /dev/null +++ b/lab7/kernel/include/mm.h @@ -0,0 +1,19 @@ +#ifndef _MM_H +#define _MM_H + +#define PAGE_SHIFT 12 +#define TABLE_SHIFT 9 +#define SECTION_SHIFT (PAGE_SHIFT + TABLE_SHIFT) + +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define SECTION_SIZE (1 << SECTION_SHIFT) + +#define LOW_MEMORY (2 * SECTION_SIZE) + +#ifndef __ASSEMBLER__ + +void memzero(unsigned long src, unsigned long n); + +#endif + +#endif /*_MM_H */ diff --git a/lab7/kernel/include/mmio.h b/lab7/kernel/include/mmio.h new file mode 100644 index 000000000..c272df237 --- /dev/null +++ b/lab7/kernel/include/mmio.h @@ -0,0 +1,8 @@ +#ifndef MMIO_H +#define MMIO_H + +void mmio_write(long reg, unsigned int data); + +unsigned int mmio_read(long reg); + +#endif diff --git a/lab7/kernel/include/mmu.h b/lab7/kernel/include/mmu.h new file mode 100644 index 000000000..8bfa0eb1b --- /dev/null +++ b/lab7/kernel/include/mmu.h @@ -0,0 +1,20 @@ +#ifndef MMU_H +#define MMU_H + +void set_up_identity_paging(); +void kernel_finer_gran(); + +void map_page(long*, long, long, long); +void switch_page(); + +long pa2va (long); +long va2pa (long); + +long trans(long); +long trans_el0(long); + +void setup_peripheral_identity(long*); + +void three_level_translation_init(); + +#endif diff --git a/lab7/kernel/include/mmu_regs.h b/lab7/kernel/include/mmu_regs.h new file mode 100644 index 000000000..9b97b70f1 --- /dev/null +++ b/lab7/kernel/include/mmu_regs.h @@ -0,0 +1,20 @@ +#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_ACCESS (1 << 10) +#define PD_KERNEL_USER_ACCESS (1 << 6) +#define BOOT_PGD_ATTR PD_TABLE +#define BOOT_PUD_ATTR (PD_ACCESS | (MAIR_IDX_DEVICE_nGnRnE << 2) | PD_BLOCK) + +#define VT_OFFSET 0xffff000000000000 + +//reference +#define ENTRY_ADDR_MASK 0xfffffffff000L diff --git a/lab7/kernel/include/peripherals/base.h b/lab7/kernel/include/peripherals/base.h new file mode 100644 index 000000000..ff5bda485 --- /dev/null +++ b/lab7/kernel/include/peripherals/base.h @@ -0,0 +1,6 @@ +#ifndef _P_BASE_H +#define _P_BASE_H + +#define PBASE 0xffff00003F000000 + +#endif /*_P_BASE_H */ diff --git a/lab7/kernel/include/peripherals/gpio.h b/lab7/kernel/include/peripherals/gpio.h new file mode 100644 index 000000000..5e9af26af --- /dev/null +++ b/lab7/kernel/include/peripherals/gpio.h @@ -0,0 +1,12 @@ +#ifndef _P_GPIO_H +#define _P_GPIO_H + +#include "peripherals/base.h" + +#define GPFSEL1 (PBASE+0x00200004) +#define GPSET0 (PBASE+0x0020001C) +#define GPCLR0 (PBASE+0x00200028) +#define GPPUD (PBASE+0x00200094) +#define GPPUDCLK0 (PBASE+0x00200098) + +#endif /*_P_GPIO_H */ diff --git a/lab7/kernel/include/peripherals/mini_uart.h b/lab7/kernel/include/peripherals/mini_uart.h new file mode 100644 index 000000000..af95a3bee --- /dev/null +++ b/lab7/kernel/include/peripherals/mini_uart.h @@ -0,0 +1,19 @@ +#ifndef _P_MINI_UART_H +#define _P_MINI_UART_H + +#include "peripherals/base.h" + +#define AUX_ENABLES (PBASE+0x00215004) +#define AUX_MU_IO_REG (PBASE+0x00215040) +#define AUX_MU_IER_REG (PBASE+0x00215044) +#define AUX_MU_IIR_REG (PBASE+0x00215048) +#define AUX_MU_LCR_REG (PBASE+0x0021504C) +#define AUX_MU_MCR_REG (PBASE+0x00215050) +#define AUX_MU_LSR_REG (PBASE+0x00215054) +#define AUX_MU_MSR_REG (PBASE+0x00215058) +#define AUX_MU_SCRATCH (PBASE+0x0021505C) +#define AUX_MU_CNTL_REG (PBASE+0x00215060) +#define AUX_MU_STAT_REG (PBASE+0x00215064) +#define AUX_MU_BAUD_REG (PBASE+0x00215068) + +#endif /*_P_MINI_UART_H */ diff --git a/lab7/kernel/include/reboot.h b/lab7/kernel/include/reboot.h new file mode 100644 index 000000000..43e0ed91e --- /dev/null +++ b/lab7/kernel/include/reboot.h @@ -0,0 +1,22 @@ +#ifndef REBOOT_H +#define REBOOT_H + +#define PM_PASSWORD 0x5a000000 +#define PM_RSTC 0x3F10001c +#define PM_WDOG 0x3F100024 + +void set(long addr, unsigned int value) { + volatile unsigned int* point = (unsigned int*)addr; + *point = value; +} + +void reset(int tick) { // reboot after watchdog timer expire + set(PM_RSTC, PM_PASSWORD | 0x20); // full reset + set(PM_WDOG, PM_PASSWORD | tick); // number of watchdog tick +} + +void cancel_reset() { + set(PM_RSTC, PM_PASSWORD | 0); // cancel reset + set(PM_WDOG, PM_PASSWORD | 0); // number of watchdog tick +} +#endif diff --git a/lab7/kernel/include/set.h b/lab7/kernel/include/set.h new file mode 100644 index 000000000..3e87e51b6 --- /dev/null +++ b/lab7/kernel/include/set.h @@ -0,0 +1,168 @@ +#ifndef SET_H +#define SET_H + +#include "mini_uart.h" +#include "alloc.h" + +typedef struct nodeList { + int key; + struct nodeList *left; + struct nodeList *right; + int height; +} nodeList; + +int height(nodeList *N) { + if (N == NULL) return 0; + return N->height; +} + +int max(int a, int b) { + return (a > b) ? a : b; +} + +nodeList* newNode(int key) { + nodeList *node = (nodeList*) simple_malloc(1, sizeof(nodeList)); + node->key = key; + node->left = NULL; + node->right = NULL; + node->height = 1; + return(node); +} + +nodeList* rightRotate(nodeList *y) { + nodeList *x = y->left; + nodeList *T2 = x->right; + + x->right = y; + y->left = T2; + + y->height = max(height(y->left), height(y->right)) + 1; + x->height = max(height(x->left), height(x->right)) + 1; + + return x; +} + +nodeList* leftRotate(nodeList *x) { + nodeList *y = x->right; + nodeList *T2 = y->left; + + y->left = x; + x->right = T2; + + x->height = max(height(x->left), height(x->right)) + 1; + y->height = max(height(y->left), height(y->right)) + 1; + + return y; +} + +int getBalance(nodeList *N) { + if (N == NULL) return 0; + return height(N->left) - height(N->right); +} + +nodeList* insert(nodeList* node, int key) { + if (node == NULL) return newNode(key); + + if (key < node->key) + node->left = insert(node->left, key); + else if (key > node->key) + node->right = insert(node->right, key); + else + return node; + + node->height = 1 + max(height(node->left), height(node->right)); + int balance = getBalance(node); + + if (balance > 1 && key < node->left->key) + return rightRotate(node); + + if (balance < -1 && key > node->right->key) + return leftRotate(node); + + if (balance > 1 && key > node->left->key) { + node->left = leftRotate(node->left); + return rightRotate(node); + } + + if (balance < -1 && key < node->right->key) { + node->right = rightRotate(node->right); + return leftRotate(node); + } + + return node; +} + +nodeList * minValueNode(nodeList* node) { + nodeList* current = node; + + while (current->left != NULL) + current = current->left; + + return current; +} + +nodeList* deleteNode(nodeList* root, int key) { + if (root == NULL) return root; + + if ( key < root->key ) + root->left = deleteNode(root->left, key); + else if( key > root->key ) + root->right = deleteNode(root->right, key); + else { + if( (root->left == NULL) || (root->right == NULL) ) { + nodeList *temp = root->left ? root->left : root->right; + + if (temp == NULL) { + temp = root; + root = NULL; + } else + *root = *temp; + } else { + nodeList* temp = minValueNode(root->right); + root->key = temp->key; + root->right = deleteNode(root->right, temp->key); + } + } + + if (root == NULL) + return root; + + root->height = 1 + max(height(root->left), height(root->right)); + int balance = getBalance(root); + + if (balance > 1 && getBalance(root->left) >= 0) + return rightRotate(root); + + if (balance > 1 && getBalance(root->left) < 0) { + root->left = leftRotate(root->left); + return rightRotate(root); + } + + if (balance < -1 && getBalance(root->right) <= 0) + return leftRotate(root); + + if (balance < -1 && getBalance(root->right) > 0) { + root->right = rightRotate(root->right); + return leftRotate(root); + } + + return root; +} + +// Function to get any arbitrary element +int getAnyElement(nodeList* root) { + if (root != NULL) { + return root->key; // Simply returns the root key as an arbitrary element + } + return -1; // or handle appropriately if the tree is empty +} + +void preOrder(nodeList* root) { + if (root != NULL) { + uart_printf("%d ", root->key); + preOrder(root->left); + preOrder(root->right); + } +} + +#endif diff --git a/lab7/kernel/include/shell.h b/lab7/kernel/include/shell.h new file mode 100644 index 000000000..43d937d48 --- /dev/null +++ b/lab7/kernel/include/shell.h @@ -0,0 +1,3 @@ + + +void shell_begin(char*); diff --git a/lab7/kernel/include/signal.h b/lab7/kernel/include/signal.h new file mode 100644 index 000000000..3cbec92d3 --- /dev/null +++ b/lab7/kernel/include/signal.h @@ -0,0 +1,8 @@ +#ifndef SIGNAL_H +#define SIGNAL_H + +void handle_signal(void*); +void sigkill(); +void signal_handler_wrapper(void*); + +#endif diff --git a/lab7/kernel/include/system_call.h b/lab7/kernel/include/system_call.h new file mode 100644 index 000000000..491f31dca --- /dev/null +++ b/lab7/kernel/include/system_call.h @@ -0,0 +1,41 @@ +#ifndef SYSTEM_CALL_H +#define SYSTEM_CALL_H + +#include "exception.h" +#include + +typedef void (*handler) (void); + +int do_getpid(); +size_t do_uart_read(char buf[], size_t size); +size_t do_uart_write(char buf[], size_t size); +int do_exec(char* name, char *argv[]); +int do_fork(trapframe_t*); +void do_exit(); +int do_mbox_call(unsigned char ch, unsigned int *mbox); +void do_kill(int pid); +void do_signal(int, handler); +void do_sigkill(int, int); + +void from_el1_to_fork_test(); +void simple_fork_test(); + +// for debug purpose +void get_sp(); +void output_sp(void*); + +void im_fineee(); + +#define O_CREAT 00000100 +int do_open(const char *pathname, int flags); +int do_close(int fd); +long do_write(int fd, const void *buf, unsigned long count); +long do_read(int fd, void *buf, unsigned long count); +int do_mkdir(const char *pathname, unsigned mode); +int do_mount(const char *src, const char *target, const char *filesystem, unsigned long flags, const void *data); +int do_chdir(const char *path); + +long do_lseek64(int fd, long offset, int whence); +int do_ioctl(); + +#endif diff --git a/lab7/kernel/include/task.h b/lab7/kernel/include/task.h new file mode 100644 index 000000000..7eda77a58 --- /dev/null +++ b/lab7/kernel/include/task.h @@ -0,0 +1,16 @@ +#ifndef TASKLIST_H +#define TASKLIST_H + +typedef void(*task_callback)(void); + +typedef struct task { + struct task *next; + task_callback callback; + int p, started; +} task; + +void execute_tasks(); +void create_task(task_callback callback,int priority); +void enqueue_task(task *new_task); + +#endif diff --git a/lab7/kernel/include/thread.h b/lab7/kernel/include/thread.h new file mode 100644 index 000000000..89f92c716 --- /dev/null +++ b/lab7/kernel/include/thread.h @@ -0,0 +1,34 @@ +#ifndef THREAD_H +#define THREAD_H + +#include "vfs.h" + +typedef struct thread { + unsigned long long reg[10]; + void* fp; + void* lr; + void* sp; + long* PGD; + void* stack_start; + void* kstack_start; + void* sstack_start; + int state, id; + struct thread* next; + struct thread* prev; + void* signal_handler[10]; // sigid at most 9 + int signal[10]; + void* code; + int code_size; + file* fds[16]; + char cwd[256]; +} thread; + +void thread_init(); +void thread_test(); +void kill_zombies(); +void idle(); +void schedule(); +int thread_create(void*); +void kill_thread(int); + +#endif diff --git a/lab7/kernel/include/timer.h b/lab7/kernel/include/timer.h new file mode 100644 index 000000000..cafc570b3 --- /dev/null +++ b/lab7/kernel/include/timer.h @@ -0,0 +1,17 @@ +#ifndef TIMER_H +#define TIMER_H + +typedef void (*timer_callback)(char*); + +typedef struct timer { + struct timer* next; + char data[100]; + timer_callback callback; + unsigned long long exp; +} timer; + +timer* create_timer(unsigned long long exp, char* str); +void print_data(char* str); +void set_timeout(unsigned long long s, char* str); + +#endif diff --git a/lab7/kernel/include/tmpfs.h b/lab7/kernel/include/tmpfs.h new file mode 100644 index 000000000..55c8a1fff --- /dev/null +++ b/lab7/kernel/include/tmpfs.h @@ -0,0 +1,26 @@ +#ifndef TMPFS_H +#define TMPFS_H + +#include "vfs.h" + +typedef struct tmpfs_node { + char data[MAX_DATA_SIZE]; + char name[MAX_NAME_SIZE]; + vnode* entry[MAX_ENTRY_SIZE]; + int type; // 1: directory, 2: file + int size; +} tmpfs_node; + +int tmpfs_write(struct file *file, const void *buf, size_t len); +int tmpfs_read(struct file *file, void *buf, size_t len); +int tmpfs_open(struct vnode *file_node, struct file **target); +int tmpfs_close(struct file *file); +long tmpfs_lseek64(int fd, long offset, int whence); + +int tmpfs_lookup(struct vnode *dir_node, struct vnode **target, const char *component_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 *component_name); + +int tmpfs_mount(struct filesystem *fs, struct mount *mt); + +#endif diff --git a/lab7/kernel/include/uartfs.h b/lab7/kernel/include/uartfs.h new file mode 100644 index 000000000..2ad00f752 --- /dev/null +++ b/lab7/kernel/include/uartfs.h @@ -0,0 +1,23 @@ +#ifndef UARTFS_H +#define UARTFS_H + +#include "vfs.h" + +typedef struct uart_dev_node{ + char name[MAX_PATH_SIZE]; + int type; // directory, mount, file +} uart_dev_node; + +int uart_dev_write(struct file *file, const char *buf, size_t len); +int uart_dev_read(struct file *file, char *buf, size_t len); +int uart_dev_open(struct vnode *file_node, struct file **target); +int uart_dev_close(struct file *file); + +int uart_dev_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name); +int uart_dev_create(struct vnode *dir_node, struct vnode **target, const char *component_name); +int uart_dev_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name); + +int uart_dev_mount(filesystem*, mount*); + + +#endif diff --git a/lab7/kernel/include/utils.h b/lab7/kernel/include/utils.h new file mode 100644 index 000000000..95dcbaa5e --- /dev/null +++ b/lab7/kernel/include/utils.h @@ -0,0 +1,17 @@ +#ifndef _BOOT_H +#define _BOOT_H + +extern void put32 ( unsigned long, unsigned int ); +extern unsigned int get32 ( unsigned long ); + +#define write_sysreg(r, __val) ({ \ + asm volatile("msr " #r ", %0" ::"r"(__val)); \ +}) + +#define read_sysreg(r) ({ \ + unsigned long __val; \ + asm volatile("mrs %0, " #r : "=r" (__val)); \ + __val; \ +}) + +#endif /*_BOOT_H */ diff --git a/lab7/kernel/include/vfs.h b/lab7/kernel/include/vfs.h new file mode 100644 index 000000000..4e3a96c8f --- /dev/null +++ b/lab7/kernel/include/vfs.h @@ -0,0 +1,89 @@ +#ifndef VFS_H +#define VFS_H + +#include + +#define O_CREAT 00000100 + +#define MAX_FS_NUM 100 +#define MAX_PATH_SIZE 255 +#define MAX_DATA_SIZE 4096 +#define MAX_NAME_SIZE 15 +#define MAX_ENTRY_SIZE 16 + +typedef struct vnode { + struct mount* mount; + struct vnode_operations* v_ops; + struct file_operations* f_ops; + void* internal; +} vnode; + +// file handle +typedef struct file { + struct vnode* vnode; + unsigned long f_pos; // RW position of this file handle + struct file_operations* f_ops; + int flags; + int ref; // not used +} file; + +typedef struct mount { + struct vnode* root; + struct filesystem* fs; +} mount; + +typedef struct filesystem { + char* name; + int (*setup_mount)(struct filesystem* fs, struct mount* mount); +} filesystem; + +typedef struct file_operations { + int (*write)(struct file* file, const void* buf, size_t len); + int (*read)(struct file* file, void* buf, size_t len); + int (*open)(struct vnode* file_node, struct file** target); + int (*close)(struct file* file); + // long lseek64(struct file* file, long offset, int whence); +} file_operations; + +typedef 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); +} vnode_operations; + +int register_filesystem(struct filesystem* fs); + // register the file system to the kernel. + // you can also initialize memory pool of the file system here. + +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 + +int vfs_close(struct file* file); + // 1. release the file handle + // 2. Return error code if fails + +int vfs_write(struct file* file, const void* buf, size_t len); + // 1. write len byte from buf to the opened file. + // 2. return written size or error code if an error occurs. + +int vfs_read(struct file* file, 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_mkdir(const char* pathname); +int vfs_mount(const char* target, const char* filesystem); +int vfs_lookup(const char* pathname, struct vnode** target); + +void filesystem_init(); + +const char* to_absolute(char*, char*); + +#endif diff --git a/lab7/kernel/kernel8.img b/lab7/kernel/kernel8.img new file mode 100755 index 000000000..63f9109f3 Binary files /dev/null and b/lab7/kernel/kernel8.img differ diff --git a/lab7/kernel/src/alloc.c b/lab7/kernel/src/alloc.c new file mode 100644 index 000000000..e1ecc2dae --- /dev/null +++ b/lab7/kernel/src/alloc.c @@ -0,0 +1,258 @@ +#include "alloc.h" +#include "mini_uart.h" +#include "fdt.h" +#include "set.h" +#include "cpio.h" +#include "mmu.h" + +/* +total: [0x0, 0x3c000000] +each page is 4KB, thus 0x3c000 pages +kernel: [0x80000, 0x100000] +Spin tables for multicore boot [0x0000, 0x1000] +initramfs: determined after parsing +devicetree: determined after parsing +size for managing: starting from 0x100001 +*/ + + +extern char* _cpio_file; +extern char* fdt_addr; + +struct node { + int sz, par; +}; + +/* +struct nodeList { + struct nodeList* next; + int pos; +}; + +struct nodeList* node_arr[21]; +// node_arr[20] for pool +*/ + + +nodeList* node_arr[21]; + +char* manage_start = (char*)0x100001; +char* now = (char*)0x100001; +char* limit; +char* frame_sz; +int* frame_par; + +char* frame_pool; + +const int arr_size = 0x3c000; + +void reserve(unsigned long l, unsigned long r) { + + if (frame_par == 0) { + uart_printf ("manager have not initialized\r\n"); + return; + } + + unsigned long l_frame = l >> 12; + unsigned long r_frame = r >> 12; + + for (unsigned long i = l_frame; i <= r_frame; i ++) { + frame_par[i] = -1; + } +} + +void* simple_malloc(int num, int size) { + if ((int)now % size != 0) now += size - (int)now % size; // align + if (limit && now + num * size >= limit) { + uart_printf ("you're allocator is going to fuck you\r\n"); + } + now += num * size; + return pa2va((char*)(now - num * size)); +} + +void print_node_list() { + for (int i = 0; i < 6; i ++) { + uart_printf("size %d: \r\n", i); + preOrder(node_arr[i]); + uart_printf("\r\n"); + } +} + +void print_pool() { + uart_printf("cur pool:\r\n"); + preOrder(node_arr[20]); + uart_printf("\r\n"); +} + +void add_node_list(int ind, int pos) { + node_arr[ind] = insert(node_arr[ind], pos); +} + +void remove_node_list(int ind, int pos) { + node_arr[ind] = deleteNode(node_arr[ind], pos); +} + +int pop_node_list(int ind) { + int t = getAnyElement(node_arr[ind]); + if (t == -1) { + return t; + } + node_arr[ind] = deleteNode(node_arr[ind], t); + return t; +} + + +void manage_init() { + frame_pool = simple_malloc(arr_size, sizeof(char)); + for (int i = 0; i < arr_size; i ++) { + frame_pool[i] = 0; + } + frame_par = simple_malloc(arr_size, sizeof(int)); + frame_sz = simple_malloc(arr_size, sizeof(char)); + for (int i = 0; i < arr_size; i ++) { + frame_par[i] = i; + frame_sz[i] = 0; + } + for (int i = 0; i <= 20; i ++) { + node_arr[i] = NULL; + } + + reserve (0, 0x1000); + reserve (0x1000, 0x1fff); // ttbr1 + reserve (0x2000, 0x2fff); + reserve (0x3000, 0x3fff); + reserve (0x4000, 0x4fff); + reserve (0x80000, 0x100000); + reserve (manage_start, now + sizeof(struct nodeList) * 10000); + limit = now + sizeof(struct nodeList) * 10000; + // TODO This is SHIT, might potentially cause problem + uart_printf ("%llx %llx %llx %llx\r\n", fdt_addr, get_fdt_end(), _cpio_file, get_cpio_end); + reserve (va2pa(fdt_addr), va2pa(get_fdt_end())); + reserve (va2pa(_cpio_file), va2pa(get_cpio_end())); + + for (int i = 1; (1 << i) <= arr_size ; i ++) { + for (int j = 0; j + (1 << i) <= arr_size; j += (1 << i)) { + int l = j, r = j + (1 << (i - 1)); + if (frame_par[l] == l && frame_par[r] == r) { + frame_par[r] = l; + frame_sz[l] ++; + } + } + } + // build the initial layout + + for (int i = 0; i < arr_size; i ++) { + if (frame_par[i] == i) { + int sz = frame_sz[i]; + add_node_list(sz, i); + } + } +} + +void* frame_malloc(size_t size) { + int sz = 0, t = 1; + while (t < size) { + t <<= 1; + sz ++; + } + + int pos = 0, tsz; + for (tsz = sz; tsz < 20; tsz ++) { + pos = pop_node_list(tsz); + if (pos != -1) { + break; + } + } + + if (pos == -1) { + return 0; + } + + while (tsz > sz) { + int pt = pos + (1 << (tsz - 1)); + frame_par[pt] = pt; + frame_sz[pos] --; + + remove_node_list(tsz, pos); + tsz --; + add_node_list(tsz, pos); + add_node_list(tsz, pt); + + } + + if (frame_sz[pos] != sz) { + uart_printf("Something went wrong at malloc...\r\n"); + } + remove_node_list(sz, pos); + frame_par[pos] = -1; + return (void*)(pos << 12); +} + +void frame_free(char* addr) { + int p = (int)addr >> 12; + frame_par[p] = p; + add_node_list (frame_sz[p], p); + while (1) { + int sz = frame_sz[p]; + if ((p / (1 << sz)) % 2) { + p -= (1 << sz); + } + + int l = p, r = p + (1 << sz); + if (r >= arr_size) { + break; + } + + if (frame_par[l] == l && frame_par[r] == r) { + remove_node_list(sz, l); + remove_node_list(sz, r); + frame_sz[l] ++; + add_node_list(sz + 1, l); + p = l; + } + else { + break; + } + } +} + +const int chunk_size = 512; +// should be divisor of 4096 + +void* my_malloc(size_t size) { + if (size > chunk_size) { + return pa2va(frame_malloc((size + 4096 - 1) / 4096)); + } + if (node_arr[20] == NULL) { + char* t = frame_malloc(1); + for (char* i = t; i < t + 4096; i += chunk_size) { + add_node_list(20, i); + } + } + int pos = pop_node_list(20); + if (pos == -1) { + uart_printf ("Failing to get a small chunk\r\n"); + return 0; + } + frame_pool[pos >> 12] ++; + if (pos == 0) { + uart_printf ("something wrong\r\n"); + } + return pa2va(pos); +} + +void my_free(char* addr) { + int pos = (int)addr >> 12; + if (!frame_pool[pos]) { + frame_free(addr); + return; + } + add_node_list(20, addr); + frame_pool[pos] --; + if (frame_pool[pos] == 0) { + for (int i = pos << 12; i < (pos << 12) + 4096; i += chunk_size) { + remove_node_list(20, i); + } + frame_free(pos << 12); + } +} diff --git a/lab7/kernel/src/boot.S b/lab7/kernel/src/boot.S new file mode 100644 index 000000000..836568cd9 --- /dev/null +++ b/lab7/kernel/src/boot.S @@ -0,0 +1,301 @@ +#include "mmu_regs.h" + +#define CORE0_TIMER_IRQ_CTRL 0xffff000040000040 + +.section ".text.boot" + +.globl _start +_start: + mov x19, x0 + + mrs x0, mpidr_el1 + and x0, x0,#0xFF // Check processor id + cbz x0, setup_tcr_el1 // Hang for all non-primary CPU + b proc_hang + +proc_hang: + b proc_hang + +setup_tcr_el1: + bl from_el2_to_el1 + + 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 // PGD's page frame at 0x1000 + mov x1, 0x2000 // PUD's page frame at 0x2000 + + ldr x2, = BOOT_PGD_ATTR + orr x2, x1, x2 // combine the physical address of next level page with attribute. + str x2, [x0] + + ldr x2, = BOOT_PUD_ATTR + mov x3, 0x00000000 + orr x3, x2, x3 + str x3, [x1] // 1st 1GB mapped by the 1st entry of PUD + mov x3, 0x40000000 + orr x3, x2, x3 + str x3, [x1, 8] // 2nd 1GB mapped by the 2nd entry of PUD + + msr ttbr0_el1, x0 // load PGD to the bottom translation-based register. + msr ttbr1_el1, x0 // also load PGD to the upper translation based register. + + mov sp, 0x100000 + bl three_level_translation_init + + mrs x2, sctlr_el1 + orr x2 , x2, 1 + msr sctlr_el1, x2 // enable MMU, cache remains disabled + + ldr x2,= boot_rest + br x2 + +boot_rest: + + + ldr x1, =0xffff000000100000 + mov sp, x1 + + adr x0, bss_begin + adr x1, bss_end + sub x1, x1, x0 + bl memzero + + bl set_exception_vector_table + + // bl from_el1_to_el0 + + // bl core_timer_enable + + msr daifclr, 0xf // enable el1 interrupt + + mov x0, x19 // get fdt back + bl kernel_begin + b proc_hang // should never come here + + +from_el2_to_el1: + mov x0, (1 << 31) + msr hcr_el2, x0 + mov x0, 5 + msr spsr_el2, x0 + msr elr_el2, lr + eret + +// save general registers to stack +.macro save_all + sub sp, sp, 32 * 10 + stp x0, x1, [sp ,16 * 0] + stp x2, x3, [sp ,16 * 1] + stp x4, x5, [sp ,16 * 2] + stp x6, x7, [sp ,16 * 3] + stp x8, x9, [sp ,16 * 4] + stp x10, x11, [sp ,16 * 5] + stp x12, x13, [sp ,16 * 6] + stp x14, x15, [sp ,16 * 7] + stp x16, x17, [sp ,16 * 8] + stp x18, x19, [sp ,16 * 9] + stp x20, x21, [sp ,16 * 10] + stp x22, x23, [sp ,16 * 11] + stp x24, x25, [sp ,16 * 12] + stp x26, x27, [sp ,16 * 13] + stp x28, x29, [sp ,16 * 14] + str x30, [sp, 16 * 15] + // empty 8 bytes + + mrs x0, SPSR_EL1 + mrs x1, ELR_EL1 + stp x0, x1, [sp, 16 * 16] + mrs x0, sp_el0 + str x0, [sp, 16 * 17] + // nested shit + +.endm + +// load general registers from stack +.macro load_all + ldp x0, x1, [sp, 16 * 16] + msr SPSR_EL1, x0 + msr ELR_EL1, x1 + ldr x0, [sp, 16 * 17] + msr sp_el0, 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] + 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] + ldr x30, [sp, 16 * 15] + + add sp, sp, 32 * 10 +.endm + +exception_handler: + save_all + mov x0, sp + bl exception_entry + load_all + eret + +.global core_timer_enable +core_timer_enable: + mov x0, 1 + msr cntp_ctl_el0, x0 + // mrs x0, cntfrq_el0 + mov x0, 0 + msr cntp_tval_el0, x0 + mov x0, 2 + ldr x1, =CORE0_TIMER_IRQ_CTRL + str w0, [x1] + mrs x0, cntkctl_el1 + orr x0, x0, #1 + msr cntkctl_el1, x0 + + ret + +core_timer_handler: + save_all + bl core_timer_entry + load_all + eret + +general_irq_handler: + save_all + // mov x0, sp + // bl debug + bl c_general_irq_handler + // mov x0, sp + // bl debug + // bl handle_signal + load_all + eret + +system_call_handler: + cmp x8, #10 + beq system_call_handler_end + save_all + mov x0, sp + bl c_system_call_handler +system_call_handler_end: + load_all + eret + +sig_return_handler: + load_all + eret + +undefined_exception: + bl c_undefined_exception + +.align 11 +.global exception_vector_table +exception_vector_table: + b undefined_exception + .align 7 + b undefined_exception + .align 7 + b undefined_exception + .align 7 + b undefined_exception + .align 7 + + b system_call_handler + .align 7 + b general_irq_handler + .align 7 + b undefined_exception + .align 7 + b undefined_exception + .align 7 + + b system_call_handler + .align 7 + b general_irq_handler + .align 7 + b undefined_exception + .align 7 + b undefined_exception + .align 7 + + b undefined_exception + .align 7 + b undefined_exception + .align 7 + b undefined_exception + .align 7 + b undefined_exception + .align 7 + +set_exception_vector_table: + adr x0, exception_vector_table + msr vbar_el1, x0 + ret + +/* +.global to_el0_with_timer +to_el0_with_timer: + mov x29, lr + bl from_el1_to_el0 + bl core_timer_enable + b proc_hang + mov lr, x29 + ret +*/ + +.global switch_to +switch_to: + stp x19, x20, [x0, 16 * 0] + stp x21, x22, [x0, 16 * 1] + stp x23, x24, [x0, 16 * 2] + stp x25, x26, [x0, 16 * 3] + stp x27, x28, [x0, 16 * 4] + stp fp, lr, [x0, 16 * 5] + mov x9, sp + str x9, [x0, 16 * 6] + + ldp x19, x20, [x1, 16 * 0] + ldp x21, x22, [x1, 16 * 1] // x0, x1 are 0xffff shits + ldp x23, x24, [x1, 16 * 2] + ldp x25, x26, [x1, 16 * 3] + ldp x27, x28, [x1, 16 * 4] + ldp fp, lr, [x1, 16 * 5] + ldr x9, [x1, 16 * 6] + mov sp, x9 + msr tpidr_el1, x1 + + ldr x2, [x1, 16 * 6 + 8] + dsb ish // ensure write has completed + msr ttbr0_el1, x2 // switch translation based address. + tlbi vmalle1is // invalidate all TLB entries + dsb ish // ensure completion of TLB invalidatation + isb // clear pipeline + + ret + +.global get_current +get_current: + mrs x0, tpidr_el1 + ret + +.global ret_from_fork_child +ret_from_fork_child: + load_all + // bl im_fineee + // msr DAIFclr, 0xf + eret diff --git a/lab7/kernel/src/config.txt b/lab7/kernel/src/config.txt new file mode 100644 index 000000000..279349696 --- /dev/null +++ b/lab7/kernel/src/config.txt @@ -0,0 +1,2 @@ +kernel_old=1 +disable_commandline_tags=1 diff --git a/lab7/kernel/src/cpio.c b/lab7/kernel/src/cpio.c new file mode 100644 index 000000000..e850096b4 --- /dev/null +++ b/lab7/kernel/src/cpio.c @@ -0,0 +1,232 @@ +#include +#include +#include "cpio.h" +#include "mini_uart.h" +#include "helper.h" +#include "alloc.h" +#include "thread.h" +#include "mmu.h" +#include "utils.h" +#include "vfs.h" +#include "initramfs.h" + +extern char* _cpio_file; +char buff[1024]; + +uint8_t hex_char_to_bin(char c) { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'a' && c <= 'f') return c - 'a' + 10; + if (c >= 'A' && c <= 'F') return c - 'A' + 10; + return 0; // Not a valid hexadecimal character +} + +uint64_t hex_to_bin(const char* hex) { + uint64_t result = 0; + for(int i = 0; i < 8; i ++) { + result = (result << 4) | hex_char_to_bin(hex[i]); + } + return result; +} + +void* cpio_find(char* name) { + char* cpio_start = _cpio_file; + struct cpio_newc_header* header = (struct cpio_newc_header*)cpio_start; + substr(buff, header -> c_magic, 0, 5); + while (same(buff, "070701")) { + // Convert c_namesize and c_filesize from ASCII hex to binary + uint64_t namesize = hex_to_bin(header->c_namesize); + uint64_t filesize = hex_to_bin(header->c_filesize); + + // Calculate the start of the file name and file data + char* filename = (char*)(header + 1); + char* filedata = filename + namesize; + filedata = (char*)((uintptr_t)filedata + ((4 - ((uintptr_t)filedata & 3)) & 3)); // Align to next 4-byte boundary + + substr(buff, filename, 0, namesize - 1); + if (same(buff, "TRAILER!!!")) { + break; // End of archive + } + + if (same(buff, name)) { + return filedata; + } + substr(buff, filename, 0, namesize - 1); + + // Move to the next header, aligning as necessary + header = (struct cpio_newc_header*)(filedata + filesize); + header = (struct cpio_newc_header*)((uintptr_t)header + ((4 - ((uintptr_t)header & 3)) & 3)); // Align to next 4-byte boundary + substr(buff, header -> c_magic, 0, 5); + } + return 0; +} + +void cpio_parse_ls() { + char* cpio_start = _cpio_file; + struct cpio_newc_header* header = (struct cpio_newc_header*)cpio_start; + substr(buff, header -> c_magic, 0, 5); + while (same(buff, "070701")) { + + // Convert c_namesize and c_filesize from ASCII hex to binary + uint64_t namesize = hex_to_bin(header->c_namesize); + uint64_t filesize = hex_to_bin(header->c_filesize); + + // Calculate the start of the file name and file data + char* filename = (char*)(header + 1); + char* filedata = filename + namesize; + filedata = (char*)((uintptr_t)filedata + ((4 - ((uintptr_t)filedata & 3)) & 3)); // Align to next 4-byte boundary + + substr(buff, filename, 0, namesize - 1); + if (same(buff, "TRAILER!!!")) { + break; // End of archive + } + uart_printf("%s\r\n", buff); + + // Move to the next header, aligning as necessary + header = (struct cpio_newc_header*)(filedata + filesize); + header = (struct cpio_newc_header*)((uintptr_t)header + ((4 - ((uintptr_t)header & 3)) & 3)); // Align to next 4-byte boundary + substr(buff, header -> c_magic, 0, 5); + } +} + +void cpio_parse_cat(char* name) { + char* cpio_start = _cpio_file; + struct cpio_newc_header* header = (struct cpio_newc_header*)cpio_start; + substr(buff, header -> c_magic, 0, 5); + while (same(buff, "070701")) { + // Convert c_namesize and c_filesize from ASCII hex to binary + uint64_t namesize = hex_to_bin(header->c_namesize); + uint64_t filesize = hex_to_bin(header->c_filesize); + + // Calculate the start of the file name and file data + char* filename = (char*)(header + 1); + char* filedata = filename + namesize; + filedata = (char*)((uintptr_t)filedata + ((4 - ((uintptr_t)filedata & 3)) & 3)); // Align to next 4-byte boundary + + substr(buff, filename, 0, namesize - 1); + if (same(buff, "TRAILER!!!")) { + break; // End of archive + } + + if (same(buff, name)) { + uart_printf ("Cat %d\r\n", filesize); + substr(buff, filedata, 0, filesize - 1); + uart_printf("%s\r\n", buff); + } + substr(buff, filename, 0, namesize - 1); + + // Move to the next header, aligning as necessary + header = (struct cpio_newc_header*)(filedata + filesize); + header = (struct cpio_newc_header*)((uintptr_t)header + ((4 - ((uintptr_t)header & 3)) & 3)); // Align to next 4-byte boundary + substr(buff, header -> c_magic, 0, 5); + } +} + +extern thread* get_current(); + +void cpio_load(char* str) { + irq(0); + thread_init(); + thread* cur = get_current(); + uart_printf ("cur: %llx\r\n", cur); + long xxx = read_sysreg(tpidr_el1); + uart_printf ("xxx: %llx\r\n", xxx); + + vnode* t; + if (vfs_lookup(str, &t) != 0) { + uart_printf ("Fail to get exec program\r\n"); + return; + } + initramfs_node* inode = t -> internal; + uart_printf ("t -> internal: %llx\r\n", t -> internal); + int sz = (inode -> size + 4096 - 1) / 4096 * 4096; + uart_printf ("loading size %d\r\n", sz); + + void* pos = cpio_find(str); + cur -> code = my_malloc(sz); + cur -> code_size = sz; + + uart_printf ("inode data size: %d\r\n", inode -> size); + + for (int i = 0; i < cur -> code_size; i ++) { + ((char*)cur -> code)[i] = inode -> data[i]; + } + + uart_printf ("%llx, %llx, %llx\r\n", cur -> PGD, pa2va(cur -> PGD), &(cur -> PGD)); + + setup_peripheral_identity(pa2va(cur -> PGD)); + for (int i = 0; i < cur -> code_size; i += 4096) { + map_page(pa2va(cur -> PGD), i, va2pa(cur -> code) + i, (1 << 6)); + } + for (int i = 0; i < 4; i ++) { + map_page (pa2va(cur -> PGD), 0xffffffffb000L + i * 4096, va2pa(cur -> stack_start) + i * 4096, (1 << 6)); + } + + uart_printf ("%llx\r\n", cur -> PGD); + asm volatile("dsb ish"); + write_sysreg(ttbr0_el1, cur -> PGD); + asm volatile("dsb ish"); + asm volatile("tlbi vmalle1is"); + asm volatile("dsb ish"); + asm volatile("isb"); + + cur -> code = 0; + cur -> stack_start = 0xffffffffb000L; + + long ttbr1 = read_sysreg(ttbr1_el1); + long ttbr0 = read_sysreg(ttbr0_el1); + uart_printf ("TTBR0: %llx, TTBR1: %llx\r\n", ttbr0, ttbr1); + + uart_printf ("cur -> PGD %llx\r\n", cur -> PGD); + + // uart_printf("Running code from %llx, which is %llx\n", cur -> code, trans(cur -> code)); + + + uart_printf ("uart printf: %llx\r\n", uart_printf); + + uart_printf("Running code from %llx, which is %llx\n", cur -> code, trans_el0(cur -> code)); + ttbr1 = read_sysreg(ttbr1_el1); + ttbr0 = read_sysreg(ttbr0_el1); + uart_printf ("TTBR0: %llx, TTBR1: %llx, &TTBR0: %llx\r\n", ttbr0, ttbr1, &ttbr0); + + write_sysreg(spsr_el1, 0); + write_sysreg(elr_el1, cur -> code); + write_sysreg(sp_el0, 0xfffffffff000L); + uart_printf ("sp %llx\r\n",cur -> sp); + asm volatile ( + "mov sp, %0;" + // "msr DAIFclr, 0xf;" + "eret;" + : + : "r" (cur -> sp) + ); + long tt = read_sysreg(elr_el1); + uart_printf ("should go to %llx, but instead %llx\r\n", 0, tt); + while (1); +} + +char* get_cpio_end() { + char* cpio_start = _cpio_file; + struct cpio_newc_header* header = (struct cpio_newc_header*)cpio_start; + substr(buff, header -> c_magic, 0, 5); + while (same(buff, "070701")) { + uint64_t namesize = hex_to_bin(header->c_namesize); + uint64_t filesize = hex_to_bin(header->c_filesize); + + char* filename = (char*)(header + 1); + char* filedata = filename + namesize; + filedata = (char*)((uintptr_t)filedata + ((4 - ((uintptr_t)filedata & 3)) & 3)); // Align to next 4-byte boundary + + substr(buff, filename, 0, namesize - 1); + if (same(buff, "TRAILER!!!")) { + return filedata + filesize; + } + + substr(buff, filename, 0, namesize - 1); + + // Move to the next header, aligning as necessary + header = (struct cpio_newc_header*)(filedata + filesize); + header = (struct cpio_newc_header*)((uintptr_t)header + ((4 - ((uintptr_t)header & 3)) & 3)); // Align to next 4-byte boundary + substr(buff, header -> c_magic, 0, 5); + } + return header; +} diff --git a/lab7/kernel/src/exception.c b/lab7/kernel/src/exception.c new file mode 100644 index 000000000..45d91adaa --- /dev/null +++ b/lab7/kernel/src/exception.c @@ -0,0 +1,223 @@ +#include "exception.h" +#include "mini_uart.h" +#include "utils.h" +#include "mmio.h" +#include "DEFINE.h" +#include "timer.h" +#include "task.h" +#include "system_call.h" +#include "thread.h" + +#include + +/* +extern char* write_buffer; +extern int write_ind; +extern int write_tail; + +extern char* recv_buffer; +extern int recv_ind; +extern int recv_tail; +extern int flag; +*/ + +extern timer* head; + +void exception_entry(){ + uart_printf("Entering exception handler\r\n"); + + void *spsr1; + void *elr1; + void *esr1; + + asm volatile( + "mrs %[var1], spsr_el1;" + "mrs %[var2], elr_el1;" + "mrs %[var3], esr_el1;" + : [var1] "=r" (spsr1),[var2] "=r" (elr1),[var3] "=r" (esr1) + ); + + uart_printf("SPSR_EL1: %x\r\n", spsr1); + uart_printf("ELR_EL1: %x\r\n", elr1); + uart_printf("ESR_EL1: %x\r\n", esr1); + + return; +} + +void core_timer_entry() { + unsigned long long cur_cnt, cnt_freq; + + asm volatile( + "mrs %[var1], cntpct_el0;" + "mrs %[var2], cntfrq_el0;" + :[var1] "=r" (cur_cnt), [var2] "=r" (cnt_freq) + ); + + asm volatile("msr cntp_ctl_el0,%0"::"r"(0)); + irq(0); + + if (head == NULL) { + irq(1); + unsigned int* address = (unsigned int*) CORE0_TIMER_IRQ_CTRL; + *address = 2; + return; + } + while (head -> next != NULL && head -> next -> exp <= cur_cnt) { + head -> next -> callback(head -> next -> data); + head = head -> next; + } + if (head -> next != NULL) { + asm volatile("msr cntp_cval_el0, %0"::"r"(head -> next -> exp)); + asm volatile("msr cntp_ctl_el0,%0"::"r"(1)); + } + + irq(1); + unsigned int* address = (unsigned int*) CORE0_TIMER_IRQ_CTRL; + *address = 2; +} + +void simple_core_timer_entry() { + // irq closed before getting in + long cur_cnt = read_sysreg(cntpct_el0); + long cnt_freq = read_sysreg(cntfrq_el0); + + write_sysreg(cntp_tval_el0, cnt_freq >> 5); + + // asm volatile("msr cntp_tval_el0, %0"::"r"(cnt_freq >> 5)); + // unsigned int* address = (unsigned int*) CORE0_TIMER_IRQ_CTRL; + // *address = 2; + + schedule(); + // uart_printf ("I'm back\r\n"); +} + + +void c_general_irq_handler(){ + unsigned int gpu_irq_src = mmio_read((long)IRQ_pending_1); + unsigned int cpu_irq_src = mmio_read((long)CORE0_INT_SRC); + + irq(0); + + if(gpu_irq_src & (1 << 29)){ + + unsigned int irq_status = mmio_read((long)AUX_MU_IIR_REG); + if(irq_status & 0x4){ + // uart_printf ("[DEBUG] irq read\r\n"); + // change_read_irq(0); + // create_task(recv_handler, 5); + recv_handler(); + } + else if(irq_status & 0x2){ + // uart_printf ("[DEBUG] irq write\r\n"); + // change_write_irq(0); + // create_task(write_handler, 5); + write_handler(); + } + } + else if (cpu_irq_src & (0x1 << 1)) { + // unsigned int* address = (unsigned int*) CORE0_TIMER_IRQ_CTRL; + // *address = 0; + // create_task(simple_core_timer_entry, 5); + simple_core_timer_entry(); + } + irq(1); + // execute_tasks(); + +} + +void c_undefined_exception() { + uart_printf("This is a undefined exception. Proc hang\r\n"); + while (1); +} + +#define ESR_ELx_EC(esr) ((esr & 0xFC000000) >> 26) + +void c_system_call_handler(trapframe_t* tf) { + irq(0); + + unsigned long esr = read_sysreg(esr_el1); // cause of that exception + unsigned int ec = ESR_ELx_EC(esr); + + if (ec == 0b100100) { + uart_printf ("data aboart el0\r\n"); + while (1); + } + if (ec == 0b100000) { + uart_printf ("ins \r\n"); + while (1); + } + if (ec == 0b100101) { + uart_printf ("data aboard el1\r\n"); + while (1); + } + + int id = tf -> x[8]; + if (id == 0) { + tf -> x[0] = do_getpid(); + } + else if (id == 1) { + irq(1); + tf -> x[0] = do_uart_read(tf -> x[0], tf -> x[1]); + } + else if (id == 2) { + irq(1); + tf -> x[0] = do_uart_write(tf -> x[0], tf -> x[1]); + } + else if (id == 3) { + tf -> x[0] = do_exec(tf -> x[0], tf -> x[1]); + } + else if (id == 4) { + tf -> x[0] = do_fork(tf); + } + else if (id == 5) { + do_exit(); + } + else if (id == 6) { + tf -> x[0] = do_mbox_call(tf -> x[0], tf -> x[1]); + } + else if (id == 7) { + do_kill(tf -> x[0]); + } + else if (id == 8) { + uart_printf ("Do a register\r\n"); + do_signal(tf -> x[0], tf -> x[1]); + } + else if (id == 9) { + uart_printf ("Do a kill\r\n"); + do_sigkill(tf -> x[0], tf -> x[1]); + } + else if (id == 11) { + tf -> x[0] = do_open(tf -> x[0], tf -> x[1]); + } + else if (id == 12) { + tf -> x[0] = do_close(tf -> x[0]); + } + else if (id == 13) { + tf -> x[0] = do_write(tf -> x[0], tf -> x[1], tf -> x[2]); + } + else if(id == 14) { + tf -> x[0] = do_read(tf -> x[0], tf -> x[1], tf -> x[2]); + } + else if(id == 15) { + tf -> x[0] = do_mkdir(tf -> x[0], tf -> x[1]); + } + else if(id == 16) { + tf -> x[0] = do_mount(tf -> x[0], tf -> x[1], tf -> x[2], tf -> x[3], tf -> x[4]); + } + else if(id == 17) { + tf -> x[0] = do_chdir(tf -> x[0]); + } + else if(id == 18) { + tf -> x[0] = do_lseek64(tf -> x[0], tf -> x[1], tf -> x[2]); + } + else if(id == 19) { + tf -> x[0] = do_ioctl(tf -> x[0], tf -> x[1], tf -> x[2]); + } + else { + uart_printf ("This is unexpected systemcall, proc hang\r\n"); + while (1); + } + // uart_printf ("Exception ended with return value = %d\r\n", tf -> x[0]); + irq(1); +} + diff --git a/lab7/kernel/src/fdt.c b/lab7/kernel/src/fdt.c new file mode 100644 index 000000000..7c03396db --- /dev/null +++ b/lab7/kernel/src/fdt.c @@ -0,0 +1,131 @@ +#include "fdt.h" +#include "mini_uart.h" +#include +#include "helper.h" + +char* _cpio_file; +char* _fdt_end; +extern char* fdt_addr; + +void _print_tab(int level) +{ + while (level--) { + uart_printf("\t"); + } +} + +void _dump(char *start, int len) +{ + for(int i = 0; i < len; i ++) { + if (start[i] >= 0x20 && start[i] <= 0x7e) uart_send(start[i]); + else uart_printf("%x", start[i]); + } +} + +char* ALIGN(uint64_t ptr, int x) { + if (ptr & 3) { + ptr = (ptr + (4 - (ptr & 3))); + } + return (char*)ptr; +} + +uint32_t print_dtb(int type, char *name, char *data, uint32_t size) +{ + static int tb = 0; + if (type == FDT_BEGIN_NODE) { + _print_tab(tb); + uart_printf("[*] Node: %s\r\n", name); + tb ++; + } + else if(type == FDT_END_NODE) { + tb --; + _print_tab(tb); + uart_printf("[*] Node: end\r\n"); + } + else if(type == FDT_PROP) { + _print_tab(tb); + uart_printf("[*] %s: ", name); + _dump(data, size); + uart_printf("\r\n"); + } + else if(type == FDT_NOP) { + + } + else { + uart_printf("[*] END!\r\n"); + } + + return 0; +} + +uint32_t get_initramfs_addr(int type, char* name, char* data, uint32_t size) +{ + if (type == FDT_PROP && same(name, "linux,initrd-start")) { + _cpio_file=(char *)(uintptr_t)fdt32_ld((void*)data); + _cpio_file += 0xffff000000000000; + } + return 0; +} + +uint32_t parse_dt_struct(fdt_callback cb, char *dt_struct, char *dt_strings) { + // inside a struct + char *cur = dt_struct; + + while (1) { + cur = (char *)ALIGN((uint64_t)cur, 4); + struct fdt_node_header *nodehdr = (struct fdt_node_header *)cur; + uint32_t tag = fdtn_tag(nodehdr), t = 0; + + if (tag == FDT_BEGIN_NODE) { + t = cb(FDT_BEGIN_NODE, "", nodehdr -> name, -1); + cur += sizeof(struct fdt_node_header) + strlen(nodehdr->name) + 1; + } + else if (tag == FDT_END_NODE) { + t = cb(FDT_END_NODE, "", "", -1); + cur += sizeof(struct fdt_node_header); + } + else if (tag == FDT_PROP) { + struct fdt_property *prop = (struct fdt_property *)nodehdr; + t = cb(FDT_PROP, dt_strings + fdtp_nameoff(prop), prop -> data, fdtp_len(prop)); + cur += sizeof(struct fdt_property); + cur += fdtp_len(prop); + } + else if (tag == FDT_NOP) { + t = cb(FDT_NOP, "", "", -1); + cur += sizeof(struct fdt_node_header); + } + else { + t = cb(FDT_END, "", "", -1); + cur += sizeof(struct fdt_node_header); + break; + } + if ( t != 0 ) return t; + } + _fdt_end = cur; + return 0; +} + +uint32_t fdt_traverse(fdt_callback cb) +{ + struct fdt_header *hdr = (struct fdt_header *)fdt_addr; + + uart_printf ("%llx\r\n", fdt_addr); + + if (fdt_magic(hdr) != FDT_MAGIC) { + uart_printf("[x] Not valid fdt_header\r\n"); + } + + char *dt_struct = fdt_addr + fdt_off_dt_struct(hdr); + char *dt_strings = fdt_addr + fdt_off_dt_strings(hdr); + + uint32_t r = parse_dt_struct(cb, dt_struct, dt_strings); + + return r; +} + +long get_fdt_end() { + if (_fdt_end == 0) { + uart_printf ("You haven't get fdt_end\r\n"); + } + return _fdt_end; +} diff --git a/lab7/kernel/src/framebufferfs.c b/lab7/kernel/src/framebufferfs.c new file mode 100644 index 000000000..99972ba8f --- /dev/null +++ b/lab7/kernel/src/framebufferfs.c @@ -0,0 +1,161 @@ +#include "vfs.h" +#include "framebufferfs.h" +#include "alloc.h" +#include "helper.h" +#include "mail.h" + +extern char* cpio_base; + +struct file_operations framebuffer_file_operations = {framebuffer_write,framebuffer_read,framebuffer_open,framebuffer_close}; +struct vnode_operations framebuffer_vnode_operations = {framebuffer_lookup,framebuffer_create,framebuffer_mkdir}; + +vnode * framebuffer_create_vnode(const char* name, char* data, int size, + unsigned int width, unsigned int height, unsigned int pitch, + unsigned int isrgb, char* lfb) { + vnode* node = my_malloc(sizeof(vnode)); + memset(node, 0, sizeof(vnode)); + node -> f_ops = &framebuffer_file_operations; + node -> v_ops = &framebuffer_vnode_operations; + + framebuffer_node* inode = my_malloc(sizeof(framebuffer_node)); + memset(inode, 0, sizeof(framebuffer_node)); + strcpy(name, inode -> name, strlen(name)); + inode -> width = width; + inode -> height = height; + inode -> pitch = pitch; + inode -> isrgb = isrgb; + inode -> lfb = lfb; + node -> internal = inode; + // not necessary tho + + return node; +} + +#define MBOX_REQUEST 0 +#define MBOX_CH_PROP 8 +#define MBOX_TAG_LAST 0 + + +int framebuffer_mount(struct filesystem *_fs, struct mount *mt){ + + unsigned int __attribute__((aligned(16))) mbox[36]; + mbox[0] = 35 * 4; + mbox[1] = MBOX_REQUEST; + + mbox[2] = 0x48003; // set phy wh + mbox[3] = 8; + mbox[4] = 8; + mbox[5] = 1024; // FrameBufferInfo.width + mbox[6] = 768; // FrameBufferInfo.height + + mbox[7] = 0x48004; // set virt wh + mbox[8] = 8; + mbox[9] = 8; + mbox[10] = 1024; // FrameBufferInfo.virtual_width + mbox[11] = 768; // FrameBufferInfo.virtual_height + + mbox[12] = 0x48009; // set virt offset + mbox[13] = 8; + mbox[14] = 8; + mbox[15] = 0; // FrameBufferInfo.x_offset + mbox[16] = 0; // FrameBufferInfo.y.offset + + mbox[17] = 0x48005; // set depth + mbox[18] = 4; + mbox[19] = 4; + mbox[20] = 32; // FrameBufferInfo.depth + + mbox[21] = 0x48006; // set pixel order + mbox[22] = 4; + mbox[23] = 4; + mbox[24] = 1; // RGB, not BGR preferably + + mbox[25] = 0x40001; // get framebuffer, gets alignment on request + mbox[26] = 8; + mbox[27] = 8; + mbox[28] = 4096; // FrameBufferInfo.pointer + mbox[29] = 0; // FrameBufferInfo.size + + mbox[30] = 0x40008; // get pitch + mbox[31] = 4; + mbox[32] = 4; + mbox[33] = 0; // FrameBufferInfo.pitch + + mbox[34] = MBOX_TAG_LAST; + + uart_printf ("wait for mailbox setup\r\n"); + + // this might not return exactly what we asked for, could be + // the closest supported resolution instead + if (mailbox_call(mbox, MBOX_CH_PROP) && mbox[20] == 32 && mbox[28] != 0) { + mbox[28] &= 0x3FFFFFFF; // convert GPU address to ARM address + mt -> fs = _fs; + const char * fname = "framebuffer"; + mt -> root = framebuffer_create_vnode(fname, 0, 0, + mbox[5], mbox[6], mbox[33], mbox[24], mbox[28] + 0xffff000000000000); + uart_printf ("lfb: %llx\r\n", mbox[28] + 0xffff000000000000); + /* + m_width = mbox[5]; // get actual physical width + m_height = mbox[6]; // get actual physical height + m_pitch = mbox[33]; // get number of bytes per line + m_isrgb = mbox[24]; // get the actual channel order + lfb = (void *)((unsigned long)mbox[28]); + */ + } + else { + uart_printf ("Unable to set screen resolution to 1024x768x32\n"); + } + + uart_printf ("finish mailbox setup\r\n"); + + return 0; +} + +int framebuffer_write(struct file *file, const char *buf, size_t len){ + // uart_printf ("lol: "); + char* lfb = ((framebuffer_node*)(file -> vnode -> internal)) -> lfb; + char* f = lfb + file -> f_pos; + // uart_printf ("[FRAMEBUFFER]Writing to %llx\r\n", f); + for (int i = 0; i < len; i ++) { + f[i] = buf[i]; + } + file -> f_pos += len; + return len; +} + +int framebuffer_read(struct file *file, char *buf, size_t len){ + char* lfb = ((framebuffer_node*)(file -> vnode -> internal)) -> lfb; + char* f = lfb + file -> f_pos; + // uart_printf ("[FRAMEBUFFER]Reading from %llx\r\n", f); + for (int i = 0; i < len; i++) { + buf[i] = f[i]; + } + file -> f_pos += len; + return len; +} +// 27b81c +int framebuffer_open(struct vnode *file_node, struct file **target){ + (*target) -> vnode = file_node; + (*target) -> f_ops = file_node -> f_ops; + (*target) -> f_pos = 0; + (*target) -> ref = 1; + return 0; +} + +int framebuffer_close(struct file *file){ + // my_free(file); + uart_printf ("Shouldn't happen\r\n"); + return -1; +} + +int framebuffer_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name){ + return -1; +} + +int framebuffer_create(struct vnode *dir_node, struct vnode **target, const char *component_name){ + return -1; +} + +int framebuffer_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name){ + return -1; +} diff --git a/lab7/kernel/src/helper.c b/lab7/kernel/src/helper.c new file mode 100644 index 000000000..e7f1bc68f --- /dev/null +++ b/lab7/kernel/src/helper.c @@ -0,0 +1,64 @@ +#include "mini_uart.h" + +void hex_to_string(unsigned int x, char* buf) { + buf[0] = '0'; buf[1] = 'x'; + char arr[16] = "0123456789abcdef"; + for (int i = 0; i < 8; i++) { + unsigned char ch = (x >> ((32-4) - i*4)) & 0xF; + buf[i + 2] = arr[ch]; + } + buf[10] = '\0'; +} + +int same (char* one, char* two) { + for(int i = 0; ; i ++) { + if(one[i] == '\0' && two[i] == '\0') return 1; + if(one[i] != two[i]) return 0; + } +} + +void substr(char* to, char* from, int l, int r) { + for(int i = l; i <= r; i ++) { + to[i - l] = from[i]; + } + to[r - l + 1] = '\0'; +} + +int strlen(char* str) { + int t = 0; + while(str[t] != '\0') { + t ++; + } + return t; +} + +unsigned long stoi(char* str) { + unsigned long res = 0; + for(int i = 0; str[i] != '\0'; i ++) { + res = res * 10 + str[i] - '0'; + } + return res; +} + +void strcpy(char* from, char* to, int size) { + for (int i = 0; i < size; i ++) { + to[i] = from[i]; + } + to[size] = '\0'; +} +void strcpy_to0(char* from, char* to) { + for (int i = 0; ; i ++) { + to[i] = from[i]; + if (to[i] == '\0') break; + } +} + +void delay (unsigned long long t) { + while (t --); +} + +void memset(char* arr, char t, int size) { + for (int i = 0; i < size; i ++) { + arr[i] = t; + } +} diff --git a/lab7/kernel/src/initramfs.c b/lab7/kernel/src/initramfs.c new file mode 100644 index 000000000..ecf1590b6 --- /dev/null +++ b/lab7/kernel/src/initramfs.c @@ -0,0 +1,123 @@ +#include "initramfs.h" +#include "alloc.h" +#include "vfs.h" +#include "mini_uart.h" +#include "helper.h" +#include "fdt.h" +#include "cpio.h" + +extern char* _cpio_file; + +struct file_operations initramfs_file_operations = {initramfs_write,initramfs_read,initramfs_open,initramfs_close}; +struct vnode_operations initramfs_vnode_operations = {initramfs_lookup,initramfs_create,initramfs_mkdir}; + +struct vnode * initramfs_create_vnode(const char* name, char * data, int size){ + vnode* node = my_malloc(sizeof(vnode)); + memset(node, 0, sizeof(vnode)); + node -> f_ops = &initramfs_file_operations; + node -> v_ops = &initramfs_vnode_operations; + initramfs_node* inode = my_malloc(sizeof(initramfs_node)); + memset(inode, 0, sizeof(inode)); + strcpy(name, inode -> name, strlen(name)); + inode -> data = data; + inode -> size = size; + node -> internal = inode; + uart_printf ("created %s\r\n", ((struct initramfs_node *) node -> internal) -> name); + return node; +} + +int initramfs_mount(struct filesystem *_fs, struct mount *mt){ + //initialize all entries + mt -> fs = _fs; + //set root + const char * fname = "initramfs"; + mt -> root = initramfs_create_vnode(fname, 0, 0); + + //create all entries for files + struct initramfs_node* inode = mt -> root -> internal; + struct cpio_newc_header *fs = (struct cpio_newc_header *)_cpio_file; + char *current = (char *)_cpio_file; + int idx = 0; + + while(1){ + fs = (struct cpio_newc_header *)current; + int name_size = hex_to_bin(fs->c_namesize); + int file_size = hex_to_bin(fs->c_filesize); + current += 110; // size of cpio_newc_header + + if (same(current, "TRAILER!!!")) + break; + + char * name = current; + current += name_size; + if((current - (char *)fs) % 4 != 0) + current += (4 - (current - (char *)fs) % 4); + + char * data = current; + if(!same(name, ".")){ + inode -> entry[idx] = initramfs_create_vnode(name, data, file_size); + idx++; + } + + current += file_size; + if((current - (char *)fs) % 4 != 0) + current += (4 - (current - (char *)fs) % 4); + } + + return 0; +} + + +int initramfs_write(struct file *file, const void *buf, size_t len){ + uart_printf ("[INITRAMFS]Trying to write to initramfs\r\n"); + return -1; +} + +int initramfs_read(struct file *file, void *buf, size_t len){ + struct initramfs_node * internal = file -> vnode -> internal; + if(file -> f_pos + len > internal -> size) + len = internal -> size - file -> f_pos; + for(int i=0; i data[i + file -> f_pos]; + } + file -> f_pos += len; + return len; +} + +int initramfs_open(struct vnode *file_node, struct file **target){ + (*target) -> vnode = file_node; + (*target) -> f_ops = file_node -> f_ops; + (*target) -> f_pos = 0; + (*target) -> ref = 1; + return 0; +} + +int initramfs_close(struct file *file){ + // uart_printf ("Shouldn't happen\r\n"); + my_free(file); + return -1; +} + +int initramfs_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name){ + int idx = 0; + struct initramfs_node * internal = dir_node -> internal; + while(internal -> entry[idx]){ + struct initramfs_node * entry_node = internal -> entry[idx] -> internal; + if(same(entry_node -> name, component_name)){ + *target = internal -> entry[idx]; + return 0; + } + idx++; + } + return -1; +} + +int initramfs_create(struct vnode *dir_node, struct vnode **target, const char *component_name){ + uart_printf ("[INITRAMFS]Trying to create to initramfs\r\n"); + return -1; +} + +int initramfs_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name){ + uart_printf ("[INITRAMFS]Trying to mkdir to initramfs\r\n"); + return -1; +} diff --git a/lab7/kernel/src/kernel_start.c b/lab7/kernel/src/kernel_start.c new file mode 100644 index 000000000..c214d3ae1 --- /dev/null +++ b/lab7/kernel/src/kernel_start.c @@ -0,0 +1,40 @@ +#include +#include +#include "fdt.h" +#include "cpio.h" +#include "alloc.h" +#include "thread.h" +#include "mmu.h" + +extern void core_timer_enable(); +extern char _code_start[]; +extern char _code_end[]; + +extern thread* get_current(); + +char* fdt_addr; + +void kernel_begin(char* fdt) { + fdt_addr = pa2va(fdt); + uart_init(); + long t = 0xffff000000000000; + uart_printf ("%llx translated to %llx\r\n", t, trans(t)); + + uart_printf ("Hello world\r\n"); + + fdt_traverse(get_initramfs_addr); // also set _cpio_file + manage_init(); + + filesystem_init(); + + thread_init(); + get_current() -> code = _code_start; + get_current() -> code_size = (_code_end - _code_start + 1); + get_current() -> PGD = 0x1000; + + long x = 0xffff000000000000; + uart_printf ("0x%llx\r\n", &x); + + shell_begin(fdt); + return; +} diff --git a/lab7/kernel/src/linker.ld b/lab7/kernel/src/linker.ld new file mode 100644 index 000000000..2d7e67ba1 --- /dev/null +++ b/lab7/kernel/src/linker.ld @@ -0,0 +1,17 @@ + + +SECTIONS +{ + . = 0xffff000000000000; + . += 0x80000; + _code_start = . ; + .text.boot : { *(.text.boot) } + .text : { *(.text) } + _code_end = .; + .rodata : { *(.rodata) } + .data : { *(.data) } + . = ALIGN(0x8); + bss_begin = .; + .bss : { *(.bss*) } + bss_end = .; +} diff --git a/lab7/kernel/src/mail.c b/lab7/kernel/src/mail.c new file mode 100644 index 000000000..fef31238e --- /dev/null +++ b/lab7/kernel/src/mail.c @@ -0,0 +1,57 @@ +#include "mini_uart.h" +#include "mail.h" + +int mailbox_call(unsigned int *mailbox, unsigned char ch) { + unsigned int r = (unsigned int)(((unsigned long)mailbox) & (~0xF)) | (ch & 0xF); + while(*MAILBOX_STATUS & MAILBOX_FULL); + *MAILBOX_WRITE = r; + while(1) { + while(*MAILBOX_STATUS & MAILBOX_EMPTY); + // uart_send_string("Trying to get the result from mailbox...\r\n"); + if(r == *MAILBOX_READ) + return mailbox[1] == REQUEST_SUCCEED; + } + return 0; +} + +unsigned int get_board_revision(){ + unsigned int __attribute__((aligned(16))) mailbox[7]; + mailbox[0] = 7 * 4; // buffer size in bytes + mailbox[1] = REQUEST_CODE; + // tags begin + mailbox[2] = GET_BOARD_REVISION; // tag identifier + mailbox[3] = 4; // maximum of request and response value buffer's length. + mailbox[4] = TAG_REQUEST_CODE; + mailbox[5] = 0; // value buffer + // tags end + mailbox[6] = END_TAG; + + if (mailbox_call(mailbox, 8) ) { + return mailbox[5]; + } + else { + return 0; + } +} + +int get_arm_memory(unsigned int* arr) { + unsigned int __attribute__((aligned(16))) mailbox[8]; + mailbox[0] = 8 * 4; // buffer size in bytes + mailbox[1] = REQUEST_CODE; + // tags begin + mailbox[2] = GET_ARM_MEMORY; // tag identifier + mailbox[3] = 8; // maximum of request and response value buffer's length. + mailbox[4] = TAG_REQUEST_CODE; + mailbox[5] = 0; // value buffer + mailbox[6] = 0; // value buffer + // tags end + mailbox[7] = END_TAG; + + if (mailbox_call(mailbox, 8)) { + arr[0] = mailbox[5]; arr[1] = mailbox[6]; + return 0; + } + else { + return -1; + } +} diff --git a/lab7/kernel/src/mini_uart.c b/lab7/kernel/src/mini_uart.c new file mode 100644 index 000000000..396e1019e --- /dev/null +++ b/lab7/kernel/src/mini_uart.c @@ -0,0 +1,280 @@ +#include "utils.h" +#include "helper.h" +#include "mmio.h" + +#include "DEFINE.h" + +#include +#include + + +#define SIGN 1 + +char write_buffer[1024]; +int write_tail = 0, write_ind = 0; +char recv_buffer[1024]; +int recv_tail = 0, recv_ind = 0; + +void uart_send ( char c ) +{ + while(1) { + if(get32(AUX_MU_LSR_REG)&0x20) + break; + } + put32(AUX_MU_IO_REG,c); +} + +char uart_recv ( void ) +{ + while(1) { + if(get32(AUX_MU_LSR_REG)&0x01) + break; + } + return(get32(AUX_MU_IO_REG)&0xFF); +} + +void uart_recv_string( char* buf ) { + int m = 0; + while(1) { + while(1) { + if(get32(AUX_MU_LSR_REG)&0x01) + break; + } + buf[m ++] = get32(AUX_MU_IO_REG) & 0xFF; + if (buf[m - 1] == '\r') { + m --; + break; + } + if (buf[m - 1] == 127) { + m --; + continue; + } + uart_send(buf[m - 1]); + } + buf[m] = '\0'; +} + +uint32_t uart_recv_uint(void) +{ + char buf[4]; + + for (int i = 0; i < 4; ++i) { + buf[i] = uart_recv(); + } + + return *((uint32_t*)buf); +} + +void uart_send_string(char* str) { + for(int i = 0; str[i] != '\0'; i ++) { + uart_send(str[i]); + } +} + + +void uart_send_num(int64_t num, int base, int type) +{ + const char digits[16] = "0123456789ABCDEF"; + char tmp[66]; + int i; + + if (type & SIGN) { + if (num < 0) { + uart_send('-'); + } + } + + i = 0; + + if (num == 0) { + tmp[i++] = '0'; + } else { + while (num != 0) { + uint8_t r = ((uint64_t)num) % base; + num = ((uint64_t)num) / base; + tmp[i++] = digits[r]; + } + } + + while (--i >= 0) { + uart_send(tmp[i]); + } +} + +// Ref: https://elixir.bootlin.com/linux/v3.5/source/arch/x86/boot/printf.c#L115 +void uart_printf(char *fmt, ...) +{ + const char *s; + char c; + uint64_t num; + char width; + + va_list args; + va_start(args, fmt); + + for (; *fmt; ++fmt) { + if (*fmt != '%') { + uart_send(*fmt); + continue; + } + + ++fmt; + + // Get width + width = 0; + if (fmt[0] == 'l' && fmt[1] == 'l') { + width = 1; + fmt += 2; + } + + switch (*fmt) { + case 'c': + c = va_arg(args, uint32_t) & 0xff; + uart_send(c); + continue; + case 'd': + if (width) { + num = va_arg(args, int64_t); + } else { + num = va_arg(args, int32_t); + } + uart_send_num(num, 10, SIGN); + continue; + case 's': + s = va_arg(args, char *); + uart_send_string((char*)s); + continue; + case 'x': + if (width) { + num = va_arg(args, uint64_t); + } else { + num = va_arg(args, uint32_t); + } + uart_send_num(num, 16, 0); + continue; + } + } +} + + +void uart_init ( void ) +{ + unsigned int selector; + + selector = get32(GPFSEL1); + selector &= ~(7<<12); // clean gpio14 + selector |= 2<<12; // set alt5 for gpio14 + selector &= ~(7<<15); // clean gpio15 + selector |= 2<<15; // set alt5 for gpio15 + put32(GPFSEL1,selector); + + put32(GPPUD,0); + delay(150); + put32(GPPUDCLK0,(1<<14)|(1<<15)); + delay(150); + put32(GPPUDCLK0,0); + + + + put32(AUX_ENABLE,1); //Enable mini uart (this also enables access to its registers) + put32(AUX_MU_CNTL_REG,0); //Disable auto flow control and disable receiver and transmitter (for now) + put32(AUX_MU_IER_REG,0); //Disable receive and transmit interrupts + put32(AUX_MU_LCR_REG,3); //Enable 8 bit mode + put32(AUX_MU_MCR_REG,0); //Set RTS line to be always high + put32(AUX_MU_BAUD_REG,270); //Set baud rate to 115200 + + put32(AUX_MU_CNTL_REG,3); //Finally, enable transmitter and receiver + + *UART_ICR = 0x7FF; /* clear interrupts */ + *UART_FBRD = 0xB; + *UART_LCRH = 0b11 << 5; /* 8n1 */ + *UART_CR = 0x301; /* enable Tx, Rx, FIFO */ + *UART_IMSC = 3 << 4; /* Tx, Rx */ +} + +void irq(int d) { + if (d) { + asm volatile ("msr DAIFclr, 0xf"); + // uart_printf ("IRQ is on\r\n"); + } + else { + asm volatile ("msr DAIFset, 0xf"); + // uart_printf ("IRQ is off\r\n"); + } +} + +void change_read_irq(int d) { + if (d) { + mmio_write((long)AUX_MU_IER_REG, *AUX_MU_IER_REG | (0x1)); + } + else { + mmio_write((long)AUX_MU_IER_REG, *AUX_MU_IER_REG & ~(0x1)); + } +} + +void change_write_irq(int d) { + if (d) { + mmio_write((long)AUX_MU_IER_REG, *AUX_MU_IER_REG | (0x2)); + } + else { + mmio_write((long)AUX_MU_IER_REG, *AUX_MU_IER_REG & ~(0x2)); + } +} + +void uart_irq_on(){ + change_read_irq(1); + *Enable_IRQs_1 |= (1<<29); +} + +void uart_irq_off(){ + change_read_irq(0); + *Disable_IRQs_1 |= (1<<29); +} + +void uart_irq_send(char* c, int siz) { + for (int i = 0; i < siz; i ++) { + if (c[i] == 0) continue; + write_buffer[write_tail ++] = c[i]; + } + if (write_tail > write_ind) { + change_write_irq(1); + } +} + +char uart_irq_read() { + // uart_printf ("%d, %d\r\n", recv_ind, recv_tail); + if (recv_ind >= recv_tail) { + return 0; + } + else { + return recv_buffer[recv_ind ++]; + } +} +void write_handler(){ + change_write_irq(0); + irq(0); + + while(write_ind != write_tail){ + char c = write_buffer[write_ind++]; + while (!(*AUX_MU_LSR_REG & (1 << 5))) { + asm volatile ( "nop;" ); + } + *AUX_MU_IO_REG = (unsigned int)c; + } + irq(1); +} + +void recv_handler(){ + + irq(0); + + while ((*AUX_MU_LSR_REG & 1)) { + char c = (char)(*AUX_MU_IO_REG); + if (c != 0) { + recv_buffer[recv_tail ++] = c; + } + } + // change_read_irq(1); + + irq(1); +} diff --git a/lab7/kernel/src/mm.S b/lab7/kernel/src/mm.S new file mode 100644 index 000000000..1bd32ff37 --- /dev/null +++ b/lab7/kernel/src/mm.S @@ -0,0 +1,6 @@ +.globl memzero +memzero: + str xzr, [x0], #8 + subs x1, x1, #8 + b.gt memzero + ret diff --git a/lab7/kernel/src/mmio.c b/lab7/kernel/src/mmio.c new file mode 100644 index 000000000..ffa7a16ec --- /dev/null +++ b/lab7/kernel/src/mmio.c @@ -0,0 +1,9 @@ +#include "mmio.h" + +inline void mmio_write(long reg, unsigned int data){ + *(volatile unsigned int*)reg = data; +} + +inline unsigned int mmio_read(long reg){ + return *(volatile unsigned int*)reg; +} diff --git a/lab7/kernel/src/mmu.c b/lab7/kernel/src/mmu.c new file mode 100644 index 000000000..47cd2d9e8 --- /dev/null +++ b/lab7/kernel/src/mmu.c @@ -0,0 +1,214 @@ +#include "mmu.h" +#include "helper.h" +#include "utils.h" +#include "alloc.h" +#include "thread.h" +#include "mmu_regs.h" +#include "mini_uart.h" + +#define PERIPHERAL_START 0x3c000000L +#define PERIPHERAL_END 0x40000000L + +#define DEVICE_BASE 0x3F000000L + + +const int page_size = 4096; + +void three_level_translation_init(){ + unsigned long *pmd_1 = (unsigned long *) 0x3000; + for(unsigned long i=0; i<512; i++){ + unsigned long base = 0x200000L * i; // 2 * 16^5 -> 2MB + if(base >= DEVICE_BASE){ + //map as device + pmd_1[i] = PD_ACCESS + PD_BLOCK + base + (MAIR_IDX_DEVICE_nGnRnE << 2) + PD_KERNEL_USER_ACCESS; + } + else{ + //map as normal + pmd_1[i] = PD_ACCESS + PD_BLOCK + base + (MAIR_IDX_NORMAL_NOCACHE << 2); + } + } + + unsigned long *pmd_2 = (unsigned long *) 0x4000; + for(unsigned long i=0; i<512; i++){ + unsigned long base = 0x40000000L + 0x200000L * i; + pmd_2[i] = PD_ACCESS + PD_BLOCK + base + (MAIR_IDX_NORMAL_NOCACHE << 2); + } + + unsigned long * pud = (unsigned long *) 0x2000; + *pud = PD_TABLE + (unsigned long) pmd_1; + pud[1] = PD_TABLE + (unsigned long) pmd_2; +} + +/* +void set_up_identity_paging() { + write_sysreg(tcr_el1, TCR_CONFIG_DEFAULT); + + long attr = + (MAIR_DEVICE_nGnRnE << (MAIR_IDX_DEVICE_nGnRnE * 8)) | + (MAIR_NORMAL_NOCACHE << (MAIR_IDX_NORMAL_NOCACHE * 8)); + write_sysreg(mair_el1, attr); + + long* l0 = (long*)0x1000L; + long* l1 = (long*)0x2000L; + + memset(l0, 0, 0x1000); + memset(l1, 0, 0x1000); // clears the page table: + + long *p0 = (long*)0x3000; + for (int i = 0; i < 504; i++) { + p0[i] = (i << 21) | PD_ACCESS | (MAIR_IDX_NORMAL_NOCACHE << 2) | PD_BLOCK, (1 << 6); + } + // [0x3F000000 ~ 0x80000000] device memory + for (int i = 504; i < 1024; i++) { + p0[i] = (i << 21) | PD_ACCESS | (MAIR_IDX_DEVICE_nGnRnE << 2) | PD_BLOCK; + } + + l0[0] = (long)l1 | BOOT_PGD_ATTR; + l1[0] = 0x3000L | PD_TABLE; + l1[1] = 0x4000L | PD_TABLE; + + write_sysreg(ttbr0_el1, l0); + write_sysreg(ttbr1_el1, l0); + + unsigned long sctlr = read_sysreg(sctlr_el1); + write_sysreg(sctlr_el1, sctlr | 1); +} +*/ + +/* +void kernel_finer_gran() { + // [0x00000000, 0x3F000000] normal memory + asm volatile ( "dsb ish;" ); + + long* l1 = pa2va(0x2000L); + + asm volatile ( "dsb ish;" ); + + l1[0] = 0x3000L | PD_TABLE; + l1[1] = 0x4000L | PD_TABLE; + asm volatile ( "dsb ish;" ); +} +*/ + +void map_page(long * pgd, long va, long pa, long flag){ + for(int i=0; i<4; i++){ + unsigned int offset = (va >> (39 - i * 9)) & 0x1ff; + + if(i == 3){ + pgd[offset] = pa; + pgd[offset] |= PD_ACCESS | PD_TABLE | (MAIR_IDX_NORMAL_NOCACHE << 2) | flag; + return; + } + + if(pgd[offset] == 0){ + unsigned long * new_page_table = my_malloc(4096); + for(int j=0; j<4096; j++){ + ((char *) (new_page_table))[j] = 0; + } + pgd[offset] = va2pa(new_page_table); + pgd[offset] |= PD_TABLE; + } + + pgd = (long*) (((long) (pgd[offset] & ENTRY_ADDR_MASK)) + 0xffff000000000000); + } +} + +/* +void map_page(long* pt, long va, long pa, long flag) { + if (pa < 0x3c000000) { + uart_printf ("mapping from %llx to %llx, pt is %llx\r\n", pa, va, pt); + } + for (int level = 0; level < 4; level ++) { + // uart_printf ("%d\r\n", level); + long id = (va >> (39 - 9 * level)) & 0b111111111; + if (pt[id] != 0) { + if (level == 3) { + uart_printf ("exited mapping\r\n"); + } + pt = pa2va(pt[id] & (0xfffffffff000L)); + } + else { + if (level == 3) { + pt[id] = pa | PD_ACCESS | PD_PAGE | flag | (MAIR_IDX_NORMAL_NOCACHE << 2); + break; + } + else { + long* t = my_malloc(page_size); + for (int i = 0; i < 4096; i ++) { + ((char*)t)[i] = 0; + } + pt[id] = va2pa(t) | PD_TABLE; + pt = pa2va(pt[id] & (0xfffffffff000L)); + } + } + } +} +*/ + + +void setup_peripheral_identity(long* table) +{ + for (long i = PERIPHERAL_START; i < PERIPHERAL_END; i += 4096) { + map_page(table, i, i, (1 << 6)); + } +} + +long pa2va(long x) { + return x + 0xffff000000000000; +} +long va2pa(long x) { + return x - 0xffff000000000000; +} + +long trans(long x) { + long res; + asm volatile ( + "mov x0, %[input];" + "AT S1E1R, x0;" + "MRS %[res], PAR_EL1;" + // "isb;" + : [res] "=r" (res) + : [input] "r" (x) + : "x0" + ); + if (res & (0x1)) { + uart_printf ("trans failed, res: %x\r\n", res & 0xfff); + } + return (res & 0xfffffffff000) | (x & 0xfff); +} + +long trans_el0(long x) { + long res; + asm volatile ( + "mov x0, %[input];" + "AT S1E0R, x0;" + "MRS %[res], PAR_EL1;" + // "isb;" + : [res] "=r" (res) + : [input] "r" (x) + : "x0" + ); + if (res & (0x1)) { + uart_printf ("trans failed, res: %x\r\n", res & 0xfff); + } + return (res & 0xfffffffff000) | (x & 0xfff); +} + +extern thread* get_current(); + +void switch_page() { + uart_printf ("switching\r\n"); + asm volatile( + "dsb ish;" + "msr ttbr0_el1, %0;" + "dsb ish;" + "tlbi vmalle1is;" + "dsb ish;" + "isb;" + : + : "r" (get_current() -> PGD) + : "x0" + ); + uart_printf ("switching done\r\n"); +} + diff --git a/lab7/kernel/src/shell.c b/lab7/kernel/src/shell.c new file mode 100644 index 000000000..9f564b5d3 --- /dev/null +++ b/lab7/kernel/src/shell.c @@ -0,0 +1,267 @@ +#include "shell.h" +#include "mini_uart.h" +#include "reboot.h" +#include "mail.h" +#include "helper.h" +#include "loader.h" +#include "cpio.h" +#include "alloc.h" +#include "fdt.h" +#include "timer.h" +#include "exception.h" +#include "thread.h" +#include "system_call.h" +#include "signal.h" +#include "thread.h" +#include "mmu.h" + +char buf[1024]; +extern thread* get_current(); +extern thread** threads; +extern void** thread_fn; + +extern char _code_start[]; + +extern void core_timer_enable(); + +void help() { + uart_printf("help : print this help menu\r\n"); + uart_printf("hello : print Hello World!\r\n"); + uart_printf("reboot : reboot the device\r\n"); + uart_printf("revision : get the revision number\r\n"); + uart_printf("memory : get the ARM memory info\r\n"); + uart_printf("ls : ls the initial ramdisk\r\n"); + uart_printf("cat : cat the initial ramdisk\r\n"); + uart_printf("initramd : use devicetree to get initial ramdisk\r\n"); + uart_printf("dtb : output the device tree\r\n"); + uart_printf("async : test for async uart\r\n"); + uart_printf("timeout : set timeout (ms)\r\n"); +} + +void handle_timeout() { + char* buf = my_malloc(512); + uart_printf("Input time(ms): "); + uart_recv_string(buf); + unsigned long t = stoi(buf); + uart_printf("\n"); + uart_printf("Input data to output: "); + uart_recv_string(buf); + uart_printf("\n"); + set_timeout(t, buf); +} + +void async_test() { + uart_irq_on(); + + uart_irq_send("Test\n", 5); + + int t = 100000000; + while (t --); + + char* str = my_malloc(512); + int len; + for (len = 0; ; len ++) { + str[len] = uart_irq_read(); + if (str[len] == 0) break; + } + + uart_irq_off(); + uart_printf("%s, End\n", str); +} + +void page_test() { + print_node_list(); + int* arr0 = (int*)my_malloc(4096 * 1); + int* arr1 = (int*)my_malloc(4096 * 2); + int* arr2 = (int*)my_malloc(4096 * 2); + int* arr3 = (int*)my_malloc(4096 * 4); + int* arr4 = (int*)my_malloc(4096 * 8); + print_node_list(); + int* arr5 = (int*)my_malloc(4096 * 1); + for (int i = 0; i < 4096; i += sizeof(int)){ + arr0[i] = 1; + } + for (int i = 0; i < 4096 * 2; i += sizeof(int)){ + arr1[i] = 1; + } + for (int i = 0; i < 4096 * 2; i += sizeof(int)){ + arr2[i] = 1; + } + for (int i = 0; i < 4096 * 4; i += sizeof(int)){ + arr3[i] = 1; + } + for (int i = 0; i < 4096 * 8; i += sizeof(int)){ + arr4[i] = 1; + } + for (int i = 0; i < 4096; i += sizeof(int)){ + arr5[i] = 1; + } + print_node_list(); + my_free(arr5); + print_node_list(); +} + +void malloc_test() { + print_node_list(); + char* arr[17]; + for (int i = 0; i < 17; i ++) { + arr[i] = my_malloc(512); + for (int j = 0; j < 512; j ++) { + arr[i][j] = 'a'; + } + } + print_node_list(); + print_pool(); + for (int i = 0; i < 17; i ++) { + my_free(arr[i]); + } + print_node_list(); + print_pool(); +} + +void do_simple_fork_test() { + irq(0); + int id = thread_create(from_el1_to_fork_test); + thread* child = threads[id]; + thread* cur = get_current(); + int t = (cur -> code_size + 4096 - 1) / 4096 * 4096; + child -> code = my_malloc(t); + child -> code_size = cur -> code_size; + + uart_printf ("Child code physical: %llx\r\n", child -> code); + + uart_printf ("simple fork test: "); + for (int j = 0; j < t / 4096; j ++) { + for (int i = 0; i < 10; i ++) { + uart_printf ("%d ", (_code_start + 4096 * j)[i]); + } + uart_printf ("\r\n"); + } + + uart_printf ("copying code of size %d\r\n", t); + strcpy(cur -> code, child -> code, t); + uart_printf ("fuck: "); + for (int i = 0; i < 10; i ++) { + uart_printf ("%d ", ((char*)(child -> code + 4096))[i]); + } + uart_printf ("\r\n"); + uart_printf ("t / 4096 : %d\r\n", t / 4096); + for (int i = 0; i < t / 4096; i ++) { + map_page(pa2va(child -> PGD), i * 4096, va2pa(child -> code) + i * 4096, (1 << 6)); + } + + for (int i = 0; i < 4; i ++) { + map_page(pa2va(child -> PGD), 0xffffffffb000L + i * 4096, va2pa(child -> stack_start) + i * 4096, (1 << 6)); + } + + setup_peripheral_identity(pa2va(child -> PGD)); + + child -> code = 0; + child -> stack_start = 0xffffffffb000; + + uart_printf ("%llx\r\n", child -> PGD); + + uart_printf ("thread_fn[%d]: %llx\r\n", id, thread_fn[id]); + + irq(1); +} + +void shell_begin(char* fdt) +{ + fdt += 0xffff000000000000; + while (1) { + uart_recv_string(buf); + uart_printf("\r\n"); + if (same(buf, "hello")) { + uart_printf("Hello World!\n"); + } + else if (same(buf, "tt")) { + uart_printf("Input:\r\n"); + uart_recv_string(buf); + uart_printf("\r\n"); + unsigned long t = stoi(buf); + uart_printf("started countind from %d\r\n", t); + while (t--) { + + } + uart_printf("end\r\n"); + } + else if (same(buf, "timeout")) { + handle_timeout(); + } + else if (same(buf, "help")) { + help(); + } + else if (same(buf, "async")) { + async_test(); + } + else if(same(buf, "initramd")) { + fdt_traverse(get_initramfs_addr); + } + else if (same(buf, "ls")) { + cpio_parse_ls(); + } + else if (same(buf, "cat")) { + uart_printf("Filename: "); + uart_recv_string(buf); + uart_printf("\n"); + cpio_parse_cat(buf); + } + else if (same(buf, "dtb")) { + fdt_traverse(print_dtb); + } + else if(same(buf, "revision")) { + unsigned int rev = get_board_revision(); + if (rev) { + uart_printf("%x", rev); + } + else { + uart_printf("Failed to get board revision\n"); + } + } + else if(same(buf, "memory")) { + unsigned int arr[2]; + arr[0] = arr[1] = 0; + if(!get_arm_memory(arr)) { + uart_printf("Your ARM memory address base is: %x", arr[0]); + uart_printf("Your ARM memory size is: %x", arr[1]); + } + else { + uart_printf("Failed getting ARM memory info\n"); + } + } + else if (same(buf, "reboot")) { + uart_printf("Rebooting\n"); + reset(100); + } + else if (same(buf, "exit")) { + break; + } + else if (same(buf, "page")) { + page_test(); + } + else if (same(buf, "malloc")) { + malloc_test(); + } + else if (same(buf, "load")) { + uart_printf("Filename: "); + uart_recv_string(buf); + uart_printf("\n"); + cpio_load(buf); + } + else if (same(buf, "thread")) { + thread_test(); + } + else if (same(buf, "fork")) { + do_simple_fork_test(); + while (1); + } + else if (same(buf, "timer")) { + core_timer_enable(); + } + else { + uart_printf("Command not found\n"); + help(); + } + } +} diff --git a/lab7/kernel/src/signal.c b/lab7/kernel/src/signal.c new file mode 100644 index 000000000..1aed70de1 --- /dev/null +++ b/lab7/kernel/src/signal.c @@ -0,0 +1,77 @@ +#include +#include +#include + +extern thread* get_current(); + +void sigkill() { + kill_thread(get_current() -> id); +} + +void test_handler() { + uart_printf ("This is test handler\r\n"); +} + +void signal_handler_wrapper(void* func_ptr) { + // in el0 + uart_printf ("In user mode\r\n"); + void (*func) (void) = func_ptr; + func(); + + // while (1); + + asm volatile ( + "mov x8, 10;" + "svc #0;" + ); +} + +void handle_signal(void* tf) { + thread* t = get_current(); + + for (int i = 0; i < 10; i ++) { + if (t -> signal[i] == 0) continue; + uart_printf ("found signal\r\n"); + t -> signal[i] = 0; + if (t -> signal_handler[i] == NULL) { + kill_thread(t -> id); + uart_printf ("never back\r\n"); + } + void* func = signal_handler_wrapper; + uart_printf ("Going to usermode\r\n"); + uart_printf ("%x :(:(:(\r\n", func); + irq(0); + t -> sstack_start = my_malloc(4096); + void* sp = t -> sstack_start + 4096 - 16; + /* + asm volatile ( + "mov x0, %0;" + "bl signal_handler_wrapper;" + : + : "r" (i) + : "x0" + ); + */ + asm volatile ( + "mov x1, 0;" + "msr spsr_el1, x1;" + "mov x1, %[func];" + "mov x2, %[sp];" + "msr elr_el1, x1;" + "msr sp_el0, x2;" + "mov x0, %[handler];" + "mov sp, %[ori_sp];" + "msr DAIFclr, 0xf;" + "eret;" + : + : [func] "r" (func), + [sp] "r" (sp), + [ori_sp] "r" (tf), + [handler] "r" (t -> signal_handler[i]) + : "x0", "x1", "x2", "sp" + ); + uart_printf ("should not be here\r\n"); + while (1); + } + +} diff --git a/lab7/kernel/src/system_call.S b/lab7/kernel/src/system_call.S new file mode 100644 index 000000000..334161a07 --- /dev/null +++ b/lab7/kernel/src/system_call.S @@ -0,0 +1,47 @@ +.global getpid +getpid: + mov x8, 0 + svc #0 + ret + +.global uart_read +uart_read: + mov x8, 1 + svc #0 + ret + +.global uart_write +uart_write: + mov x8, 2 + svc #0 + ret + +.global exec +exec: + mov x8, 3 + svc #0 + ret + +.global fork +fork: + mov x8, #4 + svc #0 + ret + +.global exit +exit: + mov x8, 5 + svc #0 + +.global mbox_call +mbox_call: + mov x8, 6 + svc #0 + ret + +.global kill +kill: + mov x8, 7 + svc #0 + ret + diff --git a/lab7/kernel/src/system_call.c b/lab7/kernel/src/system_call.c new file mode 100644 index 000000000..16cc155c3 --- /dev/null +++ b/lab7/kernel/src/system_call.c @@ -0,0 +1,465 @@ +#include "system_call.h" +#include "alloc.h" +#include "thread.h" +#include "mail.h" +#include "cpio.h" +#include "mini_uart.h" +#include "helper.h" +#include "exception.h" +#include "utils.h" +#include "mmu.h" +#include "framebufferfs.h" + +extern thread* get_current(); +extern thread** threads; +extern void** thread_fn; + +#define stack_size 4096 + +long do_lseek64(int fd, long offset, int whence) { + if (get_current() -> fds[fd] == NULL) { + uart_printf ("lseeked a NULL\r\n"); + return -1; + } + if (whence == 0) { + get_current() -> fds[fd] -> f_pos = offset; + } + return 0; +} + +typedef struct framebuffer_info { + unsigned int width; + unsigned int height; + unsigned int pitch; + unsigned int isrgb; +} framebuffer_info; + +int do_ioctl(int fd, unsigned long request, void* info) { + if (get_current() -> fds[fd] == NULL) { + uart_printf ("[IOCTL] no such fd %d\r\n", fd); + return -1; + } + framebuffer_node* inode = get_current() -> fds[fd] -> vnode -> internal; + if (request == 0) { + ((framebuffer_info*)info) -> width = inode -> width; + ((framebuffer_info*)info) -> height = inode -> height; + ((framebuffer_info*)info) -> pitch = inode -> pitch; + ((framebuffer_info*)info) -> isrgb = inode -> isrgb; + } + return 0; +} + +int do_open(const char* pathname, int flags) { + const char* path = to_absolute(pathname, get_current() -> cwd); + uart_printf ("[OPEN] %s, %s, %d\r\n", pathname, path, flags); + for (int i = 0; i < 16; i ++) { + if (get_current() -> fds[i] == NULL) { + get_current() -> fds[i] = my_malloc(sizeof(file*)); + if (vfs_open(path, flags, &(get_current() -> fds[i])) < 0) { + uart_printf ("fail to open file %s\r\n", path); + my_free(get_current() -> fds[i]); + return -1; + } + uart_printf ("[OPEN] %s as %d, fs[%d] = %llx\r\n", path, i, i, get_current() -> fds[i]); + return i; + } + } + uart_printf ("not enough fds\r\n"); + return -1; +} + +int do_close(int fd) { + uart_printf ("[CLOSE] %d\r\n", fd); + if (fd < 0 || fd >= 16) { + uart_printf ("invalid fd when closing\r\n"); + } + vfs_close(get_current() -> fds[fd]); + get_current() -> fds[fd] = NULL; + return 0; +} + +long do_write(int fd, const void* buf, unsigned long count) { + if (fd < 0 || fd >= 16) { + uart_printf ("[WRITE] fd %d out of bound\r\n", fd); + return -1; + } + // uart_printf ("[WRITE] to %d, size: %d\r\n", fd, count); + if (get_current() -> fds[fd] == NULL) { + uart_printf ("[WRITE] no fd %d, fail\r\n"); + return -1; + } + return vfs_write(get_current() -> fds[fd], buf, count); +} + +long do_read(int fd, void* buf, unsigned long count) { + if (fd < 0 || fd >= 16) { + uart_printf ("[READ] fd %d out of bound, fail\r\n", fd); + return -1; + } + uart_printf ("[READ] from %d, size: %d\r\n", fd, count); + if (get_current() -> fds[fd] == NULL) { + uart_printf ("read: no fd, fail\r\n"); + return -1; + } + return vfs_read(get_current() -> fds[fd], buf, count); +} + +int do_mkdir(const char* pathname, unsigned mode) { + const char* path = to_absolute(pathname, get_current() -> cwd); + uart_printf ("[MKDIR] %s\r\n", path); + return vfs_mkdir(path); +} + +int do_mount(const char* src, const char* target, const char* filesystem, unsigned long flags, const void* data) { + const char* path = to_absolute(target, get_current() -> cwd); + uart_printf ("[MOUNT] %s, %s\r\n", path, filesystem); + return vfs_mount(path, filesystem); +} + +int do_chdir(const char* path) { + const char* p = to_absolute(path, get_current() -> cwd); + uart_printf ("[CHDIR]%s\r\n", p); + uart_printf ("Ori: %s, new: %s\r\n",get_current() -> cwd, p); + strcpy(p, get_current() -> cwd, strlen(p)); + return 0; +} + +int do_getpid() { + return get_current() -> id; +} + +size_t do_uart_read(char buf[], size_t size) { + buf[0] = uart_recv(); + return 1; +} + +size_t do_uart_write(char buf[], size_t size) { + uart_send (buf[0]); + return 1; +} + +int do_exec(char* name, char *argv[]) { + cpio_load(name); +} + +extern void ret_from_fork_child(); + +typedef unsigned long long ull; + +uint64_t get_sp_el0() { + uint64_t value; + asm volatile("mrs %0, sp_el0" : "=r" (value)); + return value; +} +uint64_t get_sp_el1() { + uint64_t value; + asm volatile("mov %0, sp" : "=r" (value)); + return value; +} + + + +// tf is the sp +int do_fork(trapframe_t* tf) { + switch_page(); + + uart_printf ("Started do fork\r\n"); + int id = thread_create(NULL); // later set by thread_fn + + thread* cur = get_current(); + thread* child = threads[id]; + + uart_printf ("PGD for child %d is %llx\r\n", child -> id, child -> PGD); + + + for (int i = 0; i < 10; i ++) { + child -> reg[i] = cur -> reg[i]; + } + + for (int i = 0; i < 16; i ++) { + if (cur -> fds[i] != NULL) { + child -> fds[i] = my_malloc(sizeof(file)); + strcpy(cur -> fds[i], child -> fds[i], sizeof(file)); + } + } + + strcpy(cur -> cwd, child -> cwd, strlen(cur -> cwd)); + + for (int i = 0; i < stack_size; i ++) { + ((char*) child -> kstack_start)[i] = ((char*)(cur -> kstack_start))[i]; + } + // uart_printf ("finish copying kernel stack\r\n"); + for (int i = 0; i < stack_size * 4; i ++) { + ((char*) child -> stack_start)[i] = ((char*)(cur -> stack_start))[i]; + } + // uart_printf ("finish copying user stack\r\n"); + + int t = (cur -> code_size + 4096 - 1) / 4096 * 4096; + child -> code = my_malloc(t); + child -> code_size = cur -> code_size; + + for (int i = 0; i < t; i ++) { + ((char*)child -> code)[i] = ((char*)(cur -> code))[i]; + } + // uart_printf ("finish copying code\r\n"); + + setup_peripheral_identity(pa2va(child -> PGD)); + // uart_printf ("finish mapping peripheral\r\n"); + for (int i = 0; i < t / 4096; i ++) { + map_page(pa2va(child -> PGD), i * 4096, va2pa(child -> code) + i * 4096, (1 << 6)); + } + // uart_printf ("finish mapping code\r\n"); + for (int i = 0; i < 4; i ++) { + map_page(pa2va(child -> PGD), 0xffffffffb000L + i * 4096, va2pa(child -> stack_start) + i * 4096, (1 << 6)); + } + // uart_printf ("finish mapping stack\r\n"); + + child -> stack_start = 0xffffffffb000; + child -> code = 0; + + child -> sp = (void*)((char*)tf - (char*)cur -> kstack_start + (char*)child -> kstack_start); + child -> fp = child -> sp; + // on el1 stack + thread_fn[id] = ret_from_fork_child; + + for (int i = 0; i < 10; i ++) { + child -> signal_handler[i] = cur -> signal_handler[i]; + } + + if (get_current() -> id == id) { + uart_printf ("Child should not be here%d, %d\r\n", get_current() -> id, id); + } + + void* sp_el0 = get_sp_el0(); + void* sp_el1 = get_sp_el1(); + uart_printf ("CUR SPEL0: %llx, CUR SPEL1: %llx\r\n", sp_el0, sp_el1); + + trapframe_t* child_tf = (trapframe_t*)child -> sp; + child_tf -> x[0] = 0; + child_tf -> sp_el0 += child -> stack_start - cur -> stack_start; + + //elr_el1 should be the same + + uart_printf ("Child tf should be at %llx should jump to %llx\r\n", child -> sp, thread_fn[id], child_tf -> elr_el1); + uart_printf ("And then to %llx, ori is %llx :(:(:(:(:\r\n", child_tf -> elr_el1, tf -> elr_el1); + + // uart_printf ("diff1 %x, diff2 %x\r\n", (void*)tf - (cur -> kstack_start), (void*)child_tf - (child -> kstack_start)); + + return id; +} + +void do_exit() { + kill_thread(get_current() -> id); +} + +int do_mbox_call(unsigned char ch, unsigned int *mbox) { + int* t = my_malloc(4096); + for (int i = 0; i < 144; i ++) { + ((char*)t)[i] = ((char*)mbox)[i]; + } + int res = mailbox_call(t, ch); + for (int i = 0; i < 144; i ++) { + ((char*)mbox)[i] = ((char*)t)[i]; + } + return res; + + // return mailbox_call(mbox, ch); +} + +void do_kill(int pid) { + kill_thread(pid); +} + +void do_signal(int sig, handler func) { + uart_printf ("Registered %d\r\n", sig); + if (sig >= 10) { + uart_printf ("this sig num is greater then I can handle\r\n"); + return; + } + get_current() -> signal_handler[sig] = (void*)func; +} + +void do_sigkill(int pid, int sig) { + uart_printf ("DO sigkill %d, %d\r\n", pid, sig); + if (sig >= 10) { + uart_printf ("this sig num is greater then I can handle\r\n"); + return; + } + threads[pid] -> signal[sig] = 1; +} + +extern int fork(); +extern int getpid(); +extern void exit(); +extern void core_timer_enable(); +extern int mbox_call(unsigned char, unsigned int*); +extern void test_syscall(); + +void given_fork_test(){ + uart_printf("\nFork Test, pid %d\n", getpid()); + int cnt = 1; + int ret = 0; + if ((ret = fork()) == 0) { // child + long long cur_sp; + asm volatile("mov %0, sp" : "=r"(cur_sp)); + uart_printf("first child pid: %d, cnt: %d, ptr: %x, sp : %x\n", getpid(), cnt, &cnt, cur_sp); + ++cnt; + + if ((ret = fork()) != 0){ + asm volatile("mov %0, sp" : "=r"(cur_sp)); + uart_printf("first child pid: %d, cnt: %d, ptr: %x, sp : %x\n", getpid(), cnt, &cnt, cur_sp); + } + else{ + while (cnt < 5) { + asm volatile("mov %0, sp" : "=r"(cur_sp)); + uart_printf("second child pid: %d, cnt: %d, ptr: %x, sp : %x\n", getpid(), cnt, &cnt, cur_sp); + delay(1000000); + ++cnt; + } + } + exit(); + } + else { + uart_printf("parent here, pid %d, child %d\n", getpid(), ret); + } + while (1) { + uart_printf ("This is main create fork shit\r\n"); + delay(1e7); + } +} + +void fork_test_func() { + for (int i = 0; i < 3; i ++) { + int ret = fork(); + if (ret) { + uart_printf ("This is father %d with child of pid %d\r\n", getpid(), ret); + } + else { + uart_printf ("This is child forked, my pid is %d\r\n", getpid()); + } + } + exit(); + /* + while (1) { + delay(1e7); + } + */ +} + +extern void uart_write(char); +void simple_fork_test() { + uart_write('f'); + while (1); + // uart_printf ("In simple fork test\r\n"); + + /* + for (int i = 0; i < 1; i ++) { + // uart_printf ("%d: %d\r\n", getpid(), i); + int t = fork(); + if (t) { + uart_printf ("This is parent with child %d\r\n", t); + } + else { + uart_printf ("This is child with pid %d\r\n", getpid()); + } + } + exit(); + */ +} +void fork_test_idle() { + while(1) { + unsigned int __attribute__((aligned(16))) mailbox[7]; + mailbox[0] = 7 * 4; // buffer size in bytes + mailbox[1] = REQUEST_CODE; + // tags begin + mailbox[2] = GET_BOARD_REVISION; // tag identifier + mailbox[3] = 4; // maximum of request and response value buffer's length. + mailbox[4] = TAG_REQUEST_CODE; + mailbox[5] = 0; // value buffer + // tags end + mailbox[6] = END_TAG; + + if (mbox_call(8, mailbox)) { + uart_printf ("%x\r\n", mailbox[5]); + } + else { + uart_printf ("Fail getting mailbox\r\n"); + } + + uart_printf ("This is idle, pid %d, %d\r\n", getpid(), threads[1] -> next -> id); + delay(1e7); + } +} + +extern char _code_start[]; + +void im_fineee() { + long elr_el1 = read_sysreg(elr_el1); + long sp_el0 = read_sysreg(sp_el0); + + uart_printf ("im fine, elr_el1 %llx, sp_el0 %llx\r\n", elr_el1, sp_el0); +} + +void from_el1_to_fork_test() { + irq(0); + switch_page(); + uart_printf ("%llx\r\n", get_current() -> PGD); + long ttbr0 = read_sysreg(ttbr0_el1); + long ttbr1 = read_sysreg(ttbr1_el1); + uart_printf ("ttbr0: %llx, ttbr1: %llx\r\n", ttbr0, ttbr1); + void* sp = 0xfffffffff000 - 16; + void* code = (char*)fork_test_idle - _code_start; + + long test = code; + uart_printf ("%llx translated to %llx\r\n", test, trans(test)); + uart_printf ("%llx translated to %llx\r\n", test, trans_el0(test)); + + uart_printf ("stack: %llx code: %llx\r\n", sp, code); + + /* + for (int i = 0; i < 100; i ++) { + uart_printf ("%d ", ((char*)code)[i]); + } + uart_printf ("\r\n"); + */ + + /* + for (int i = 0; i < 100; i ++) { + uart_printf ("%d ", ((char*)simple_fork_test)[i]); + } + uart_printf ("\r\n"); + */ + + // simple_fork_test(); + + /* + void (*func)() = code; + func(); + */ + + asm volatile( + "mov x1, 0;" + "msr spsr_el1, x1;" + "mov x1, %[code];" + "mov x2, %[stack];" + "msr elr_el1, x1;" + "msr sp_el0, x2;" + // "msr DAIFclr, 0xf;" // irq(1); + "eret;" + : + : [code] "r" (code), [stack] "r" (sp) + : "x1", "x2" + ); + + uart_printf ("fuck you\r\n"); + asm volatile ( "eret;" ); +} + +void debug(trapframe_t* tf) { + uart_printf ("%d: ", get_current() -> id); + uart_printf ("sp: %llx, code: %llx\r\n", tf -> sp_el0, tf -> elr_el1); + long ttbr0 = read_sysreg(ttbr0_el1); + long ttbr1 = read_sysreg(ttbr1_el1); + uart_printf ("ttbr0: %llx, ttbr1: %llx\r\n", ttbr0, ttbr1); + +} diff --git a/lab7/kernel/src/task.c b/lab7/kernel/src/task.c new file mode 100644 index 000000000..1137cde43 --- /dev/null +++ b/lab7/kernel/src/task.c @@ -0,0 +1,47 @@ +#include "task.h" +#include "alloc.h" +#include "mini_uart.h" +#include "utils.h" + +#include + +task *task_head; + +void push_task(task *t) { + asm volatile("msr DAIFSet, 0xf"); + + if (task_head == NULL) { + task_head = my_malloc(1 * sizeof(task)); + task_head -> next = NULL; + } + + task* cur = task_head; + while (cur -> next != NULL && cur -> next -> p > t -> p) { + cur = cur -> next; + } + + t -> next = cur -> next; + cur -> next = t; + + asm volatile("msr DAIFClr, 0xf"); +} + +void create_task(task_callback callback, int priority) { + task* t = my_malloc(1 * sizeof(task)); + + t -> callback = callback; + t -> p = priority; + t -> started = 0; + + push_task(t); +} + +void execute_tasks() { + while (task_head -> next != NULL && !task_head -> next -> started) { + irq(0); + task_head -> next -> started = 1; + irq(1); + task_head -> next -> callback(); + task_head = task_head -> next; + } +} diff --git a/lab7/kernel/src/thread.c b/lab7/kernel/src/thread.c new file mode 100644 index 000000000..c55ec4ac9 --- /dev/null +++ b/lab7/kernel/src/thread.c @@ -0,0 +1,257 @@ +#include "thread.h" +#include "alloc.h" +#include "mini_uart.h" +#include "helper.h" +#include "exception.h" +#include "signal.h" +#include "mmu.h" +#include "utils.h" +#include "system_call.h" + +#define stack_size 4096 +#define max_thread_num 500 + +thread* thread_start; +thread* thread_tail; + +thread** threads; + +void** thread_fn; + +extern thread* get_current(); +extern void switch_to(thread*, thread*); + +void thread_init() { + + threads = (thread**)my_malloc(sizeof(thread) * max_thread_num); + thread_fn = (void**)my_malloc(sizeof(void*) * max_thread_num); + + for (int i = 0; i < max_thread_num; i ++) { + threads[i] = NULL; + } + + thread* x = my_malloc(sizeof(thread)); + threads[0] = x; + x -> id = 0; + x -> state = 1; + x -> kstack_start = my_malloc(stack_size); + x -> sp = x -> kstack_start + stack_size - 16; + x -> fp = x -> sp; + + x -> stack_start = my_malloc(stack_size * 4); + + for (int i = 0; i < 16; i ++) { + x -> fds[i] = NULL; + } + x -> cwd[0] = '/'; + x -> cwd[1] = '\0'; + + long* PGD = my_malloc(4096); + for (int i = 0; i < 4096; i ++) { + ((char*)PGD)[i] = 0; + } + x -> PGD = va2pa(PGD); + + for (int i = 0; i < 10; i ++) { + x -> signal[i] = 0; + x -> signal_handler[i] = NULL; + } + + for (int i = 0; i < 16; i ++) { + x -> fds[i] = NULL; + } + for (int i = 0; i < 3; i ++) { + x -> fds[i] = my_malloc(sizeof(file*)); + vfs_open("/dev/uart", O_CREAT, &(x -> fds[i])); + } + + write_sysreg(tpidr_el1, x); + + thread_start = x; + thread_tail = thread_start; + thread_start -> next = NULL; + thread_start -> prev = NULL; +} + +void kill_zombies() { + irq(0); + for (int i = 1; i < max_thread_num; i ++) { + if (threads[i] -> state == 0) { + my_free(threads[i] -> stack_start); + my_free(threads[i]); + threads[i] = NULL; + } + } + irq(1); +} + +void idle() { + while (1) { + uart_printf ("In idle\r\n"); + kill_zombies(); + schedule(1); + // can't be called in el0 + delay(1e7); + } +} +void im_fine() { + uart_printf ("I'm fine\r\n"); +} + +void schedule() { + // uart_printf ("thread_start: %llx\r\n", &thread_start); + if (thread_start -> next == NULL) { + // uart_printf ("No next thread job\r\n"); + return; + } + thread_start = thread_start -> next; + if (thread_start -> id == get_current() -> id) return; + + if (get_current() -> state) { + thread_tail -> next = get_current(); + get_current() -> prev = thread_tail; + get_current() -> next = NULL; + thread_tail = thread_tail -> next; + } + thread_start -> prev = NULL; + // uart_printf ("[DEBUG] Scheduled From %d to %d\r\n", get_current() -> id, thread_start -> id); + switch_to(get_current(), thread_start); + // switch_page(); + long PGD = read_sysreg(ttbr0_el1); + // uart_printf ("id is now %d, PGD is now %llx, cur -> PGD is %llx\r\n", get_current() -> id, PGD, get_current() -> PGD); + // after successfully switched, ending of irq handler do irq(1) + return; +} + +void kill_thread(int id) { + irq(0); + uart_printf ("Killing child %d\r\n", id); + if (thread_tail -> id == id) { + if (thread_tail == thread_start) { + uart_printf ("You're killing the last shit and I won't let you do that\r\n"); + return; + } + thread_tail = thread_tail -> prev; + } + if (threads[id] -> prev != NULL) { + threads[id] -> prev -> next = threads[id] -> next; + } + if (threads[id] -> next != NULL) { + threads[id] -> next -> prev = threads[id] -> prev; + } + threads[id] -> state = 0; + irq(1); + if (id == get_current() -> id) { + while (1); + } + // wait for being scheduled away + // schedule(); +} + +trapframe_t* sp; + +void thread_func_handler() { + asm volatile ( + "mov %0, sp;" + : "=r" (sp) + : + : "sp" + ); + /* + // uncommenting the upper shit will affect the sp, need to modify them in the ret_from_fork shit + int id = get_current() -> id; + void* func = thread_fn[id]; + */ + uart_printf ("Jumping to %llx with sp %llx\r\n", thread_fn[get_current() -> id], (char*)sp + 16 * 2); + asm volatile ( + "add sp, sp, 16 * 2;" + // "mov x0, sp;" + // "bl output_sp;" + : + : + : "sp" + ); + asm volatile ( + "mov x0, %0;" + "blr x0;" + : + : "r" (thread_fn[get_current() -> id]) + : "x0", "x30" + ); + kill_thread(get_current() -> id); +} + +int thread_create(void* func) { + uart_printf ("creating thread\r\n"); + long ttbr1 = read_sysreg(ttbr1_el1); + uart_printf ("TTBR1: %llx\r\n", ttbr1); + uart_printf ("my_malloc: %llx, is at %llx\r\n", my_malloc, trans(my_malloc)); + thread* x = my_malloc(sizeof(thread)); + x -> stack_start = my_malloc(stack_size * 4); + x -> kstack_start = my_malloc(stack_size); + x -> sp = x -> kstack_start + stack_size - 16; + x -> fp = x -> sp; + x -> lr = thread_func_handler; + x -> state = 1; + + x -> PGD = va2pa(my_malloc(4096)); + memset(pa2va(x -> PGD), 0, 4096); + + for (int i = 0; i < 10; i ++) { + x -> signal_handler[i] = NULL; + x -> signal[i] = 0; + } + + for (int i = 1; i < max_thread_num; i ++) { + if (threads[i] == NULL) { + threads[i] = x; + thread_fn[i] = func; + x -> id = i; + break; + } + if (i == max_thread_num - 1) { + uart_printf ("Not enough thread resources\r\n"); + return -1; + } + } + + for (int i = 0; i < 16; i ++) { + x -> fds[i] = NULL; + } + /* + for (int i = 0; i < 3; i ++) { + x -> fds[i] = my_malloc(sizeof(file*)); + vfs_open("/dev/uart", O_CREAT, &(x -> fds[i])); + } + */ + + + x -> next = NULL; + x -> prev = thread_tail; + thread_tail -> next = x; + thread_tail = thread_tail -> next; + uart_printf ("Created %d, prev: %d\r\n", x -> id, x -> prev -> id); + return x -> id; +} + +void foo(){ + for(int i = 0; i < 3; ++i) { + uart_printf("Thread id: %d %d\n", get_current() -> id, i); + delay(1e7); + schedule(); + } + // kill_thread(); + // uart_printf ("should not come here\r\n"); + // while(1); +} + +void thread_test() { + irq(0); + uart_printf ("started thread testing\r\n"); + thread_create(idle); + for (int i = 0; i < 3; i ++) { + thread_create(foo); + } + irq(1); + // schedule(); +} diff --git a/lab7/kernel/src/timer.c b/lab7/kernel/src/timer.c new file mode 100644 index 000000000..afe99e80d --- /dev/null +++ b/lab7/kernel/src/timer.c @@ -0,0 +1,56 @@ +#include "timer.h" +#include "alloc.h" +#include "mini_uart.h" +#include + + +void print_data(char* str) { + uart_printf("%s\r\n", str); +} + +timer* head; + +void push_timer(unsigned long long exp, char* str) { + + irq(0); + + timer* t = my_malloc(sizeof(timer)); + + t -> exp = exp; + for (int i = 0; ; i ++) { + t -> data[i] = str[i]; + if (str[i] == '\0') break; + } + t -> callback = print_data; + + if (head == NULL) { + head = my_malloc(sizeof(timer)); + head -> next = NULL; + } + + timer* cur = head; + while (cur -> next != NULL && cur -> next -> exp < t -> exp) { + cur = cur -> next; + } + + t -> next = cur -> next; + cur -> next = t; + + if (head -> next != NULL) { + asm volatile ("msr cntp_cval_el0, %0"::"r" (head -> next -> exp)); + asm volatile("msr cntp_ctl_el0,%0"::"r"(1)); + } + irq(1); +} + +void set_timeout(unsigned long long s, char* str) { + + asm volatile("msr DAIFSet, 0xf"); + unsigned long long cur_cnt, cnt_freq; + asm volatile ( "mrs %[x], cntpct_el0" :[x] "=r" (cur_cnt)); + asm volatile ( "mrs %[x], cntfrq_el0" :[x] "=r" (cnt_freq)); + // uart_printf("freqeucy: %d\n", cnt_freq); + cur_cnt += s * cnt_freq / 1000; + push_timer(cur_cnt, str); + asm volatile("msr DAIFClr, 0xf"); +} diff --git a/lab7/kernel/src/tmpfs.c b/lab7/kernel/src/tmpfs.c new file mode 100644 index 000000000..ca155a828 --- /dev/null +++ b/lab7/kernel/src/tmpfs.c @@ -0,0 +1,148 @@ +#include "tmpfs.h" +#include "vfs.h" +#include "mini_uart.h" +#include "helper.h" +#include "alloc.h" + +struct file_operations tmpfs_file_operations = {tmpfs_write,tmpfs_read,tmpfs_open,tmpfs_close}; +struct vnode_operations tmpfs_vnode_operations = {tmpfs_lookup,tmpfs_create,tmpfs_mkdir}; + +int tmpfs_write(struct file *file, const void *buf, size_t len){ + tmpfs_node* internal = file -> vnode -> internal; + for(int i = 0; i < len; i++){ + (internal -> data)[file -> f_pos + i] = ((char*)buf)[i]; + } + file -> f_pos += len; + if(internal -> size < file -> f_pos) { + internal -> size = file -> f_pos; + } + return len; +} + +int tmpfs_read(struct file *file, void *buf, size_t len){ + tmpfs_node* internal = file -> vnode -> internal; + if(file -> f_pos + len > internal -> size) { + len = internal -> size - file -> f_pos; + } // read only to end + for(int i = 0; i < len; i ++){ + ((char *)buf)[i] = internal -> data[i + file -> f_pos]; + } + file -> f_pos += len; + return len; +} + +int tmpfs_open(struct vnode *file_node, struct file **target){ + (*target) -> vnode = file_node; + (*target) -> f_ops = file_node -> f_ops; + (*target) -> f_pos = 0; + (*target) -> ref = 1; + return 0; +} + +int tmpfs_close(struct file *file){ + my_free(file); + return 0; +} + +int tmpfs_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name){ + // only below dir_node + int idx = 0; + tmpfs_node* internal = dir_node -> internal; + while(internal -> entry[idx]){ + tmpfs_node* entry_node = internal -> entry[idx] -> internal; + if(same(entry_node -> name, component_name)){ + *target = internal -> entry[idx]; + return 0; + } + idx++; + } + return -1; +} + + +vnode *tmpfs_create_vnode(int type){ + void* t = my_malloc(sizeof(vnode)); + struct vnode* node = t; + memset(node, 0, sizeof(vnode)); + node -> f_ops = &tmpfs_file_operations; + node -> v_ops = &tmpfs_vnode_operations; + + tmpfs_node *tnode = my_malloc(sizeof(tmpfs_node)); + memset(tnode, 0, sizeof(tmpfs_node)); + tnode -> type = type; + tnode -> size = 0; + node -> internal = tnode; + return node; +} + +int tmpfs_create(struct vnode *dir_node, struct vnode **target, const char *component_name){ + //find an empty entry and initialize a vnode for it and set the name. + tmpfs_node* internal = dir_node -> internal; + if(internal -> type != 1) { + uart_printf("not a dir\r\n"); + return -1; + } + + int idx = -1; + for(int i = 0; i < MAX_ENTRY_SIZE; i++){ + if(internal -> entry[i] == 0){ + idx = i; + break; + } + struct tmpfs_node* infile = internal -> entry[i] -> internal; + if(same(infile -> name, component_name)){ + uart_printf("file exisited\r\n"); + return -1; + } + } + + if(idx == -1){ + uart_printf ("dir full\r\n"); + } + + vnode* node = tmpfs_create_vnode(2); + int t = strlen(component_name); + strcpy(component_name, ((tmpfs_node*)node -> internal) -> name, t); + internal -> entry[idx] = node; + *target = node; + return 0; +} + +int tmpfs_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name){ + //same as create + struct tmpfs_node * internal = dir_node -> internal; + if(internal -> type != 1) { + uart_printf("not a dir\r\n"); + return -1; + } + + int idx = -1; + for(int i = 0; i < MAX_ENTRY_SIZE; i ++){ + if(internal -> entry[i] == 0){ + idx = i; + break; + } + struct tmpfs_node* infile = internal -> entry[i] -> internal; + if(same(infile -> name, component_name)){ + uart_printf("file exisited\r\n"); + return -1; + } + } + + if(idx == -1){ + uart_printf ("dir full\r\n"); + } + + vnode* node = tmpfs_create_vnode(1); + tmpfs_node* inode = node -> internal; + strcpy(component_name, inode -> name, strlen(component_name)); + internal -> entry[idx] = node; + *target = node; + return 0; +} + +int tmpfs_mount(struct filesystem *fs, struct mount *mt){ + mt -> fs = fs; + mt -> root = tmpfs_create_vnode(1); + return 0; +} diff --git a/lab7/kernel/src/uartfs.c b/lab7/kernel/src/uartfs.c new file mode 100644 index 000000000..e01387ab9 --- /dev/null +++ b/lab7/kernel/src/uartfs.c @@ -0,0 +1,71 @@ +#include "vfs.h" +#include "uartfs.h" +#include "mini_uart.h" +#include "alloc.h" +#include "helper.h" + +extern char* cpio_base; + +struct file_operations uart_dev_file_operations = {uart_dev_write,uart_dev_read,uart_dev_open,uart_dev_close}; +struct vnode_operations uart_dev_vnode_operations = {uart_dev_lookup,uart_dev_create,uart_dev_mkdir}; + +vnode * uart_dev_create_vnode(const char* name, char* data, int size){ + vnode* node = my_malloc(sizeof(vnode)); + memset(node, 0, sizeof(vnode)); + node -> f_ops = &uart_dev_file_operations; + node -> v_ops = &uart_dev_vnode_operations; + + uart_dev_node* inode = my_malloc(sizeof(uart_dev_node)); + memset(inode, 0, sizeof(uart_dev_node)); + strcpy(name, inode -> name, strlen(name)); + node -> internal = inode; + + return node; +} + +int uart_dev_mount(struct filesystem *_fs, struct mount *mt){ + mt -> fs = _fs; + //set root + const char * fname = "uart"; + mt -> root = uart_dev_create_vnode(fname, 0, 0); + return 0; +} + +int uart_dev_write(struct file *file, const char *buf, size_t len){ + for (int i = 0; i < len; i++) { + uart_send(buf[i]); + } + return len; +} + +int uart_dev_read(struct file *file, char *buf, size_t len){ + for (int i = 0; i < len; i++) { + buf[i] = uart_recv(); + } + return len; +} + +int uart_dev_open(struct vnode *file_node, struct file **target){ + (*target) -> vnode = file_node; + (*target) -> f_ops = file_node -> f_ops; + (*target) -> f_pos = 0; + (*target) -> ref = 1; + return 0; +} + +int uart_dev_close(struct file *file){ + uart_printf ("shouldn't happen\r\n"); + return -1; +} + +int uart_dev_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name){ + return -1; +} + +int uart_dev_create(struct vnode *dir_node, struct vnode **target, const char *component_name){ + return -1; +} + +int uart_dev_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name){ + return -1; +} diff --git a/lab7/kernel/src/utils.S b/lab7/kernel/src/utils.S new file mode 100644 index 000000000..503f69b17 --- /dev/null +++ b/lab7/kernel/src/utils.S @@ -0,0 +1,9 @@ +.globl put32 +put32: + str w1,[x0] + ret + +.globl get32 +get32: + ldr w0,[x0] + ret diff --git a/lab7/kernel/src/vfs.c b/lab7/kernel/src/vfs.c new file mode 100644 index 000000000..80052f966 --- /dev/null +++ b/lab7/kernel/src/vfs.c @@ -0,0 +1,267 @@ +#include "vfs.h" +#include "tmpfs.h" +#include "initramfs.h" +#include "framebufferfs.h" +#include "uartfs.h" +#include "mini_uart.h" +#include "helper.h" +#include "alloc.h" +#include + +filesystem* fs_list[MAX_FS_NUM]; +mount* rootfs; + +void filesystem_init() { + for (int i = 0; i < MAX_FS_NUM; i ++) { + fs_list[i] = NULL; + } + fs_list[0] = my_malloc(sizeof(filesystem)); + fs_list[0] -> name = "tmpfs"; + fs_list[0] -> setup_mount = tmpfs_mount; + + rootfs = my_malloc(sizeof(mount)); + fs_list[0] -> setup_mount(fs_list[0], rootfs); + + fs_list[1] = my_malloc(sizeof(filesystem)); + fs_list[1] -> name = "initramfs"; + fs_list[1] -> setup_mount = initramfs_mount; + + vfs_mkdir("/initramfs"); + vfs_mount("/initramfs", "initramfs"); + + fs_list[2] = my_malloc(sizeof(filesystem)); + fs_list[2] -> name = "uartfs"; + fs_list[2] -> setup_mount = uart_dev_mount; + + vfs_mkdir("/dev"); + vfs_mkdir("/dev/uart"); + vfs_mount("/dev/uart", "uartfs"); + + fs_list[3] = my_malloc(sizeof(filesystem)); + fs_list[3] -> name = "framebufferfs"; + fs_list[3] -> setup_mount = framebuffer_mount; + + vfs_mkdir("/dev/framebuffer"); + vfs_mount("/dev/framebuffer", "framebufferfs"); +} + +int register_filesystem(filesystem* fs) { + for (int i = 0; i < MAX_FS_NUM; i ++) { + if (fs_list[i] == NULL) { + fs_list[i] = fs; + return i; + } + } + uart_printf ("Fail to register fs\r\n"); + return -1; +} + +int vfs_lookup(const char* pathname, struct vnode** target) { + uart_printf ("[VFS]looking up %s\r\n", pathname); + if (pathname[0] == 0 || same(pathname, "/")) { + *target = rootfs -> root; + return 0; + } + int idx = 0; + char vnode_name[MAX_PATH_SIZE]; + vnode* cur_node = rootfs -> root; + for(int i = 1; i < strlen(pathname); i ++){ + if(pathname[i] == '/'){ + vnode_name[idx] = '\0'; + if(cur_node -> v_ops -> lookup(cur_node, &cur_node, vnode_name) != 0) { + uart_printf ("Parent lookup failed\n\r"); + return -1; + } + while(cur_node -> mount){ + cur_node = cur_node -> mount -> root; + } + idx = 0; + } + else{ + vnode_name[idx ++] = pathname[i]; + } + } + + vnode_name[idx] = '\0'; + if(cur_node -> v_ops -> lookup(cur_node, &cur_node, vnode_name) != 0) { //not found + uart_printf ("File not found\n\r"); + return -1; + } + + while(cur_node -> mount) { + cur_node = cur_node -> mount -> root; + } + + *target = cur_node; + return 0; +} + +int vfs_mount(const char* target, const char* filesystem){ + //mount filesystem on target's vnode -> mount + vnode* temp; + struct filesystem *fs = 0; + for(int i = 0; i < MAX_FS_NUM; i ++) { + if (fs_list[i] == NULL) continue; + if (same(fs_list[i] -> name, filesystem)) { + fs = fs_list[i]; + } + } + if(!fs){ + uart_printf ("No such filesystem!\n\r"); + return -1; + } + + if(vfs_lookup(target, &temp) != 0){ + uart_printf ("No such directory!\n\r"); + return -1; + } + + temp -> mount = my_malloc(sizeof(mount)); + + return fs -> setup_mount(fs, temp -> mount); +} + +int vfs_mkdir(const char* pathname) { + int idx = -1; + char path_dir[MAX_PATH_SIZE]; + strcpy(pathname, path_dir, strlen(pathname)); + for (int i = 0; i < strlen(pathname); i ++) { + if (path_dir[i] == '/') { + idx = i; + } + } + if (idx == -1) { + uart_printf ("vfs_mkdir find string without /\r\n"); + return -1; + } + path_dir[idx] = '\0'; + vnode* temp; + if (vfs_lookup(path_dir, &temp) != 0) { + uart_printf ("mkdir vnode doesn't exist\r\n"); + return -1; + } + return temp -> v_ops -> mkdir(temp, &temp, pathname + idx + 1); +} + +int vfs_open(const char* pathname, int flags, file** target) { + vnode *temp; + if(vfs_lookup(pathname, &temp) != 0) { + if(!(flags & O_CREAT)){ + uart_printf ("[VFS]Not exist and no OCREATE\r\n"); + return -1; + } + + uart_printf ("[VFS]Fail to find %s, create one\r\n", pathname); + + char path_dir[MAX_PATH_SIZE]; + strcpy(pathname, path_dir, strlen(pathname)); + int idx = -1; + for(int i = 0; i < strlen(pathname); i++){ + if(pathname[i] == '/') { + idx = i; + } + } + if (idx == -1) { + uart_printf ("[VFS]vfs_open find string without /\r\n"); + return -1; + } + path_dir[idx] = '\0'; + // to seperate file to create and directory + if (vfs_lookup(path_dir, &temp) != 0) { + uart_printf ("[VFS]directory not found\r\n"); + return -1; + } + + temp -> v_ops -> create(temp, &temp, pathname + idx + 1); + } + + *target = my_malloc(sizeof(file)); + temp -> f_ops -> open(temp, target); + (*target) -> flags = flags; + return 0; +} + + +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) { + // 1. write len byte from buf to the opened file. + // 2. return written size or error code if an error occurs. + return file -> f_ops -> write(file, buf, len); +} + +int vfs_read(struct file* file, 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. + return file -> f_ops -> read(file, buf, len); +} + + +const char* to_absolute(char* relative, char* work_dir){ + //case absolute + if(relative[0] == '/'){ + return relative; + } + + char temp[256]; + const char * ret = my_malloc(255); + //case current folder + if(relative[0] == '.' && relative[1] == '/'){ + //copy workdir + for(int i=0;i