From 9ff97778408289175c054f71dcf7d5349c33fa89 Mon Sep 17 00:00:00 2001 From: ZiXunHuang Date: Thu, 24 Jun 2021 01:19:45 -0400 Subject: [PATCH 1/2] lab8 done --- include/cpio.h | 4 +- include/gpio.h | 4 +- include/irq.h | 10 +++- include/mm.h | 2 + include/mmu.h | 42 +++++++++++++ include/sched.h | 11 +++- include/utils.h | 1 + src/boot.S | 5 ++ src/context.S | 10 +++- src/cpio.c | 5 +- src/fat.c | 153 ++++++++++++++++++++++++++++-------------------- src/linker.ld | 2 +- src/main.c | 34 ++++------- src/mm.c | 18 +++--- src/mmu.S | 55 +++++++++++++++++ src/sched.c | 11 +++- src/sdhost.c | 2 +- src/set_int.S | 33 ++++++++--- src/shell.c | 9 +-- src/sys.c | 138 +++++++++++++++++++++++++++++++------------ src/uart.c | 4 +- src/utils.c | 17 ++++++ src/vfs.c | 2 +- 23 files changed, 408 insertions(+), 164 deletions(-) create mode 100644 include/mmu.h create mode 100644 src/mmu.S diff --git a/include/cpio.h b/include/cpio.h index 8dd0ddc94..04b8d8ca5 100644 --- a/include/cpio.h +++ b/include/cpio.h @@ -11,13 +11,13 @@ typedef enum { typedef struct { char *file_name; char *file_content; - unsigned int file_size; + uint32_t file_size; bool_t executable; file_type_t file_type; } cpio_t; extern cpio_t file_list[20]; -extern unsigned int file_count; +extern uint32_t file_count; void read_cpio_archive(); int search_file(const char *); diff --git a/include/gpio.h b/include/gpio.h index 287e9266f..3cd0f0fdc 100644 --- a/include/gpio.h +++ b/include/gpio.h @@ -1,7 +1,9 @@ #ifndef _GPIO_H_ #define _GPIO_H_ -#define MMIO_BASE 0x3F000000 +#include "mmu.h" + +#define MMIO_BASE (KERNEL_MAPPING+0x3F000000) #define GPIO_BASE (MMIO_BASE+0x200000) #define GPFSEL0 ((volatile unsigned int*)(GPIO_BASE+0x00)) diff --git a/include/irq.h b/include/irq.h index cf3256020..33b8bd5a3 100644 --- a/include/irq.h +++ b/include/irq.h @@ -3,10 +3,18 @@ #include "gpio.h" -#define CORE0_IRQ_SRC ((volatile unsigned int*)(0x40000060)) +#define CORE0_IRQ_SRC ((volatile unsigned int*)(KERNEL_MAPPING+0x40000060)) #define BASIC_PEND ((volatile unsigned int*)(MMIO_BASE+0xb200)) #define GPU_PEND1 ((volatile unsigned int*)(MMIO_BASE+0xb204)) +/* Synchronize exception */ +#define SVC_EXCEPTION 21 +#define LOW_EL_DA_EXCEPTION 36 /* Data abort exception */ + +#ifndef __ASSEMBLER__ + void irq_route(); +#endif /* ASSEMBLER */ + #endif diff --git a/include/mm.h b/include/mm.h index 9cdc4ecc9..3797fc79d 100644 --- a/include/mm.h +++ b/include/mm.h @@ -1,6 +1,8 @@ #ifndef _MM_H_ #define _MM_H_ +#define PAGE_SIZE 4096 + void mm_init(); void* kmalloc(unsigned int); void kfree(void*); diff --git a/include/mmu.h b/include/mmu.h new file mode 100644 index 000000000..2b56d1a87 --- /dev/null +++ b/include/mmu.h @@ -0,0 +1,42 @@ +#ifndef _MMU_H_ +#define _MMU_H_ + +#define TTBR0_EL1_REGION_BIT 48 +#define TTBR1_EL1_REGION_BIT 48 +#define TTBR0_EL1_GRANULE 0b00 /* 4KB */ +#define TTBR1_EL1_GRANULE 0b10 /* 4KB */ + +#define TCR_EL1_T0SZ ((64 - TTBR0_EL1_REGION_BIT) << 0) +#define TCR_EL1_T1SZ ((64 - TTBR1_EL1_REGION_BIT) << 16) +#define TCR_EL1_TG0 (TTBR0_EL1_GRANULE << 14) +#define TCR_EL1_TG1 (TTBR1_EL1_GRANULE << 30) +#define TCR_EL1_VALUE (TCR_EL1_T0SZ | TCR_EL1_T1SZ | TCR_EL1_TG0 | TCR_EL1_TG1) + +#define MAIR_DEVICE_nGnRnE 0b00000000 +#define MAIR_NORMAL_NOCACHE 0b01000100 +#define MAIR_IDX_DEVICE_nGnRnE 0 +#define MAIR_IDX_NORMAL_NOCACHE 1 +#define MAIR_EL1_VALUE ((MAIR_DEVICE_nGnRnE << (MAIR_IDX_DEVICE_nGnRnE * 8)) | (MAIR_NORMAL_NOCACHE << (MAIR_IDX_NORMAL_NOCACHE * 8))) + +#define PGD_ADDR 0x0 +#define PUD_ADDR 0x1000 +#define PMD_ADDR 0x2000 +#define PD_TABLE 0b11 +#define PD_BLOCK 0b01 +#define PD_PAGE 0b11 +#define PD_ACCESS (1 << 10) +#define PD_EL0_ACCESS (1 << 6) +#define PGD_ATTR PD_TABLE +#define PUD_ATTR PD_TABLE +#define PMD_ATTR PD_TABLE +#define PUD_NORMAL_ATTR (PD_ACCESS | (MAIR_IDX_NORMAL_NOCACHE << 2) | PD_BLOCK) +#define PUD_DEVICE_ATTR (PD_ACCESS | (MAIR_IDX_DEVICE_nGnRnE << 2) | PD_BLOCK) +#define PMD_NORMAL_ATTR (PD_ACCESS | (MAIR_IDX_NORMAL_NOCACHE << 2) | PD_BLOCK) +#define PMD_DEVICE_ATTR (PD_ACCESS | (MAIR_IDX_DEVICE_nGnRnE << 2) | PD_BLOCK) +#define PTE_NORMAL_ATTR (PD_ACCESS | (MAIR_IDX_NORMAL_NOCACHE << 2) | PD_PAGE) +#define PTE_DEVICE_ATTR (PD_ACCESS | (MAIR_IDX_DEVICE_nGnRnE << 2) | PD_PAGE) + +#define KERNEL_MAPPING 0xffff000000000000 +#define PA_MASK 0xffffffffffff + +#endif diff --git a/include/sched.h b/include/sched.h index e6ecce72f..eaee18cd1 100644 --- a/include/sched.h +++ b/include/sched.h @@ -5,7 +5,6 @@ #include "vfs.h" #include "type.h" -#define MAX_USTACK_NUM 20 #define MAX_FD_NUM 50 typedef unsigned int pid_t; @@ -32,14 +31,20 @@ typedef struct { uint64_t fp; uint64_t lr; uint64_t sp; + uint64_t ttbr0_el1; } callee_reg_t; typedef struct { callee_reg_t reg; pid_t pid; void *kstack_addr; - void *ustack_addr[MAX_USTACK_NUM]; - uint16_t ustack_num; + void *ucode_addr; + uint32_t ucode_size; + void *ustack_addr; + void *pgd_addr; + void *pud_addr; + void *pmd_addr; + void *pte_addr; uint16_t wait_time; size_t read_size; file_t *fd_table[MAX_FD_NUM]; diff --git a/include/utils.h b/include/utils.h index 63252a70b..f6f060c8f 100644 --- a/include/utils.h +++ b/include/utils.h @@ -12,6 +12,7 @@ void strcat(char*, const char*); int strchr(const char*, char); int ctoi(char); unsigned int atoi(const char*); +uint8_t* htoa(uint64_t); unsigned long pow(unsigned int, unsigned int); void memset(void*, size_t, char); diff --git a/src/boot.S b/src/boot.S index b8f8c3013..a54665f8e 100644 --- a/src/boot.S +++ b/src/boot.S @@ -15,6 +15,11 @@ _start: 2: bl set_exception_vector_table bl core_timer_enable + bl set_mmu + ldr x2, =_virtual_start + br x2 + +_virtual_start: ldr x1, = _start mov sp, x1 diff --git a/src/context.S b/src/context.S index 00248394b..9b5051e5f 100644 --- a/src/context.S +++ b/src/context.S @@ -7,7 +7,8 @@ switch_to: stp x27, x28, [x0, 16 * 4] stp fp, lr, [x0, 16 * 5] mov x9, sp - str x9, [x0, 16 * 6] + mrs x10, ttbr0_el1 + stp x9, x10, [x0, 16 * 6] ldp x19, x20, [x1, 16 * 0] ldp x21, x22, [x1, 16 * 1] @@ -15,8 +16,13 @@ switch_to: ldp x25, x26, [x1, 16 * 3] ldp x27, x28, [x1, 16 * 4] ldp fp, lr, [x1, 16 * 5] - ldr x9, [x1, 16 * 6] + ldp x9, x10, [x1, 16 * 6] + dsb ish mov sp, x9 + msr ttbr0_el1, x10 + tlbi vmalle1is + dsb ish + isb msr tpidr_el1, x1 ret diff --git a/src/cpio.c b/src/cpio.c index 1b9803890..c4adfd786 100644 --- a/src/cpio.c +++ b/src/cpio.c @@ -1,8 +1,9 @@ #include "cpio.h" #include "utils.h" +#include "mmu.h" -#define CPIO_LOAD_ADDR 0x20000000 -//#define CPIO_LOAD_ADDR 0x8000000 /* For Qemu */ +#define CPIO_LOAD_ADDR (KERNEL_MAPPING+0x20000000) +//#define CPIO_LOAD_ADDR (KERNEL_MAPPING+0x8000000) /* For Qemu */ const unsigned int header_size = 110; diff --git a/src/fat.c b/src/fat.c index b3e422723..f09ec7dfc 100644 --- a/src/fat.c +++ b/src/fat.c @@ -57,15 +57,36 @@ typedef struct fat32_dir_entry { } fat32_de_t; typedef struct { - uint32_t start_sec; - uint32_t end_sec; + uint32_t fat_sec; + uint32_t head_sec; + uint32_t clus_pos; uint32_t size; + uint8_t sec_per_clu; uint16_t byte_per_sec; } fat32_file_t; vnode_operations_t fat32_vop; file_operations_t fat32_fop; +static inline uint32_t fat32_clus_to_sec(uint32_t head_sec, uint32_t clus_pos, + uint8_t sec_per_clu, uint8_t sec_count) { + return head_sec + sec_per_clu * (clus_pos - 2) + sec_count; +} + +static uint32_t fat32_get_next_clus(uint32_t current_clus, uint32_t fat_sec, + uint16_t byte_per_sec) { + char buf[BLOCK_SIZE]; + fat_sec += current_clus / (byte_per_sec / 4); + current_clus %= (byte_per_sec / 4); + readblock(fat_sec, buf); + uint32_t *next_clus = &buf[4 * current_clus]; + if (*next_clus < 0xffffff8) { + return *next_clus; + } else { + return 0; + } +} + static void fat32_umount_operation(vnode_t *file) { kfree(file->internal); } @@ -109,18 +130,29 @@ static void fat32_create_dir(vnode_t *dir_node, const char *dir_name) { static int fat32_read(struct file *file, void *buf, size_t len) { fat32_file_t *f = (fat32_file_t*)file->vnode->internal; - uint32_t start_sec = f->start_sec + file->f_pos / f->byte_per_sec; + uint8_t sec_count = (file->f_pos / f->byte_per_sec) % f->sec_per_clu; + uint32_t start_sec = fat32_clus_to_sec(f->head_sec, f->clus_pos, + f->sec_per_clu, sec_count); uint16_t pos = file->f_pos % f->byte_per_sec; char sd_buf[BLOCK_SIZE]; if ((file->f_pos + len) > f->size) len = f->size - file->f_pos; readblock(start_sec, sd_buf); - for (int i = 0; i < len; i++) { + for (size_t i = 0; i < len; i++) { *((char*)buf + i) = sd_buf[pos]; if (++pos == f->byte_per_sec) { - pos = 0; - start_sec++; + if (++sec_count == f->sec_per_clu) { + uint32_t next_clus = fat32_get_next_clus(f->clus_pos, f->fat_sec, + f->byte_per_sec); + f->clus_pos = next_clus; + start_sec = fat32_clus_to_sec(f->head_sec, f->clus_pos, + f->sec_per_clu, 0); + sec_count = 0; + } else { + start_sec++; + } readblock(start_sec, sd_buf); + pos = 0; } } file->f_pos += len; @@ -129,58 +161,43 @@ static int fat32_read(struct file *file, void *buf, size_t len) { static int fat32_write(struct file *file, const void *buf, size_t len) { fat32_file_t *f = (fat32_file_t*)file->vnode->internal; - size_t max_file_size = (f->end_sec - f->start_sec + 1) * f->byte_per_sec; - if ((file->f_pos + len) > max_file_size) { - len = max_file_size - file->f_pos; - if (!len) - return -1; - } - uint32_t start_sec = f->start_sec + file->f_pos / f->byte_per_sec; + if (!fat32_get_next_clus(f->clus_pos, f->fat_sec, f->byte_per_sec)) + return -1; + uint8_t sec_count = (file->f_pos / f->byte_per_sec) % f->sec_per_clu; + uint32_t start_sec = fat32_clus_to_sec(f->head_sec, f->clus_pos, + f->sec_per_clu, sec_count); uint16_t pos = file->f_pos % f->byte_per_sec; char sd_buf[BLOCK_SIZE]; + size_t count; readblock(start_sec, sd_buf); - for (int i = 0; i < len; i++) { - sd_buf[pos] = *((char*)buf + i); + for (count = 0; count < len; count++) { + sd_buf[pos] = *((char*)buf + count); if (++pos == f->byte_per_sec) { writeblock(start_sec, sd_buf); - pos = 0; - start_sec++; + if (++sec_count == f->sec_per_clu) { + uint32_t next_clus = fat32_get_next_clus(f->clus_pos, f->fat_sec, + f->byte_per_sec); + if (!next_clus) { + count++; + break; + } else { + f->clus_pos = next_clus; + start_sec = fat32_clus_to_sec(f->head_sec, f->clus_pos, + f->sec_per_clu, 0); + sec_count = 0; + } + } else { + start_sec++; + } readblock(start_sec, sd_buf); + pos = 0; } } writeblock(start_sec, sd_buf); - if ((file->f_pos + len) > f->size) - f->size += len - (f->size - file->f_pos); - file->f_pos += len; - return len; -} - -static uint32_t fat32_scan_fat(uint32_t *start_clus, uint32_t fat_sec) { - char buf[BLOCK_SIZE]; - uint32_t clus_pos = (*start_clus) % 128; - fat_sec += (*start_clus) / 128; - readblock(fat_sec, buf); - uint32_t *num = &buf[4 * clus_pos]; - while (!(*num)) { - (*start_clus)++; - if (++clus_pos == 128) { - fat_sec++; - clus_pos = 0; - readblock(fat_sec, buf); - } - num = &buf[4 * clus_pos]; - } - uint32_t end_clus = *start_clus; - while ((*num) < 0xffffff8) { - if (++clus_pos == 128) { - fat_sec++; - clus_pos = 0; - readblock(fat_sec, buf); - } - num = &buf[4 * clus_pos]; - end_clus++; - } - return end_clus + 1; + if ((file->f_pos + count) > f->size) + f->size += count - (f->size - file->f_pos); + file->f_pos += count; + return count; } int fat_set_mount(mount_t *mount, const char *device) { @@ -197,9 +214,8 @@ int fat_set_mount(mount_t *mount, const char *device) { memcpy(&bs.p2, &buf[14], sizeof(fat_bs_p2_t)); memcpy(&bs.p3, &buf[32], sizeof(fat32_bs_p3_t)); uint32_t fat_sec = mbr.sector_addr + bs.p2.bpb_rsvd_sec_cnt; - uint32_t dir_sec = fat_sec + - bs.p2.bpb_num_fats * bs.p3.bpb_fat_sz + - bs.p1.bpb_sec_per_clu * (bs.p3.bpb_root_clus - 2); + uint32_t head_sec = fat_sec + bs.p2.bpb_num_fats * bs.p3.bpb_fat_sz; + uint32_t dir_sec = head_sec + bs.p1.bpb_sec_per_clu * (bs.p3.bpb_root_clus - 2); /* Set mount */ char *fs_name = kmalloc(strlen("fat32") + 1); strcpy(fs_name, "fat32"); @@ -208,31 +224,40 @@ int fat_set_mount(mount_t *mount, const char *device) { mount->root = kmalloc(sizeof(vnode_t)); fat32_vnode_init(mount->root, "/"); /* Set content */ - uint32_t end_clus = fat32_scan_fat(&bs.p3.bpb_root_clus, fat_sec); - uint32_t start_clus = end_clus; - uint32_t head_clus = end_clus; - uint32_t head_sec = dir_sec + - (start_clus - bs.p3.bpb_root_clus) * bs.p1.bpb_sec_per_clu; + uint8_t sec_count = 0; uint16_t file_count = 0; readblock(dir_sec, buf); while (buf[file_count * 32 + 11]) { memcpy(&dir.p1, &buf[file_count * 32], sizeof(fat32_de_p1_t)); /* Only for file */ - if (dir.p1.attribute == (char)32) { - end_clus = fat32_scan_fat(&start_clus, fat_sec); + if (dir.p1.attribute == 32 && dir.p1.file_name[0] != 229) { memcpy(&dir.p2, &buf[file_count * 32 + 20], sizeof(fat32_de_p2_t)); fat32_file_t *f = kmalloc(sizeof(fat32_file_t)); - f->start_sec = head_sec + (start_clus - head_clus) * bs.p1.bpb_sec_per_clu; - f->end_sec = f->start_sec + (end_clus - start_clus) * bs.p1.bpb_sec_per_clu - 1; + f->fat_sec = fat_sec; + f->head_sec = head_sec; + f->clus_pos = dir.p2.l_clu_num + dir.p2.h_clu_num * 0x10000; f->size = dir.p2.size; + f->sec_per_clu = bs.p1.bpb_sec_per_clu; f->byte_per_sec = bs.p1.bpb_byte_per_sec; fat32_create_file_vnode(mount->root, &dir, f); - start_clus = end_clus; } if (++file_count == (bs.p1.bpb_byte_per_sec / 32)) { - file_count = 0; - dir_sec++; + if (++sec_count == bs.p1.bpb_sec_per_clu) { + uint32_t next_clus = fat32_get_next_clus(bs.p3.bpb_root_clus, fat_sec, + bs.p1.bpb_byte_per_sec); + if (!next_clus) { + break; + } else { + bs.p3.bpb_root_clus = next_clus; + dir_sec = fat32_clus_to_sec(head_sec, bs.p3.bpb_root_clus, + bs.p1.bpb_sec_per_clu, 0); + sec_count = 0; + } + } else { + dir_sec++; + } readblock(dir_sec, buf); + file_count = 0; } } return 0; diff --git a/src/linker.ld b/src/linker.ld index 1defb1e15..84e70bc4f 100644 --- a/src/linker.ld +++ b/src/linker.ld @@ -1,6 +1,6 @@ SECTIONS { - . = 0x80000; + . = 0xffff000000080000; .text : { KEEP(*(.text.boot)) diff --git a/src/main.c b/src/main.c index f63e2fe66..1331cfffe 100644 --- a/src/main.c +++ b/src/main.c @@ -8,9 +8,6 @@ #include "vfs.h" #include "utils.h" -#include "sdhost.h" -#include "fat.h" - void foo(void) { thread_t *current = get_current(); for (int i = 0; i < 5; i++) { @@ -26,14 +23,18 @@ void foo(void) { } void user_test(void) { - char *argv[] = {"argv_test", 0}; + char *argv[5]; + argv[0] = "argvtes"; + argv[1] = "-o"; + argv[2] = "arg2"; + argv[3] = 0; do_exec("argv_test.img", argv, -1); thread_exit(); } void user_test2(void) { - char *argv[] = {"fork_test", "-o", 0}; - do_exec("loop.img", argv, -1); + char *argv[] = {"fork_test"}; + do_exec("fork_test.img", argv, -1); thread_exit(); } @@ -49,26 +50,11 @@ static void kernel_init(void) { int kernel_main(void) { kernel_init(); - /*mount_t m; - fat_set_mount(&m, "sd"); - vnode_t *r = m.root; - list_head_t *pos = r->node.next; - while (pos != &r->node) { - vnode_t *t = list_entry(pos, vnode_t, node); - print(t->name); - print("\n"); - pos = pos->next; - }*/ - - /* require 1 */ - /*for (int i = 0; i < 5; i++) - thread_create(&foo); - idle();*/ - - /* require 2 */ thread_create(&user_test); - thread_create(&user_test2); + //thread_create(&user_test2); + idle(); + //run_shell(); return 0; } diff --git a/src/mm.c b/src/mm.c index c21dddc38..be6700c80 100644 --- a/src/mm.c +++ b/src/mm.c @@ -1,10 +1,12 @@ +#include "mm.h" #include "list.h" #include "uart.h" #include "utils.h" +#include "mmu.h" +#include "type.h" -#define MEM_START 0x10000000 -#define MEM_END 0x20000000 -#define PAGE_SIZE 4096 +#define MEM_START (KERNEL_MAPPING+0x10000000) +#define MEM_END (KERNEL_MAPPING+0x20000000) #define MAX_ORDER 8 #define MAX_POOL_NUM 30 #define MAX_POOL_PAGE 10 @@ -328,7 +330,11 @@ void* kmalloc(unsigned int size){ } void kfree(void *addr) { - unsigned int index = ((unsigned long)addr - MEM_START) / PAGE_SIZE; + if (addr < MEM_START || addr >= MEM_END) { + print("Invalid address 4\n"); + return ; + } + unsigned int index = ((uint64_t)addr - (uint64_t)MEM_START) / PAGE_SIZE; for (int i = 0; i < MAX_POOL_NUM; i++) { if (pool[i].used) { for (int j = 0; j < pool[i].page_used; j++) { @@ -342,9 +348,7 @@ void kfree(void *addr) { break; } } - if ((((unsigned int)addr - MEM_START) % PAGE_SIZE)!= 0 || - (unsigned int)addr < MEM_START || - (unsigned int)addr >= MEM_END) { + if ((((uint64_t)addr - (uint64_t)MEM_START) % PAGE_SIZE)!= 0) { print("Invalid address 3\n"); } else { buddy_free(&page[index]); diff --git a/src/mmu.S b/src/mmu.S new file mode 100644 index 000000000..38913dbf5 --- /dev/null +++ b/src/mmu.S @@ -0,0 +1,55 @@ +#include "mmu.h" + +.global set_mmu +set_mmu: + /* Set TC Register */ + ldr x0, =TCR_EL1_VALUE + msr tcr_el1, x0 + + /* Set MAI Register */ + ldr x0, =MAIR_EL1_VALUE + msr mair_el1, x0 + + /* Set page table and map kernel */ + ldr x0, =PGD_ADDR + ldr x1, =PUD_ADDR + ldr x2, =PMD_ADDR + + /* PGD */ + ldr x3, =PGD_ATTR + orr x3, x1, x3 + str x3, [x0] + + /* PUD */ + ldr x3, =PUD_ATTR + orr x3, x2, x3 + str x3, [x1] + ldr x3, =PUD_DEVICE_ATTR + mov x4, 0x40000000 + orr x3, x4, x3 + str x3, [x1, 8] + + /* PMD */ + mov x1, #0 +1: ldr x3, =PMD_NORMAL_ATTR + orr x3, x1, x3 + str x3, [x2], #8 + add x1, x1, 0x200000 + ldr x4, =0x3f000000 + sub x4, x4, x1 + cbnz x4, 1b +2: ldr x3, =PMD_DEVICE_ATTR + orr x3, x1, x3 + str x3, [x2], #8 + add x1, x1, 0x200000 + ldr x4, =0x40000000 + sub x4, x4, x1 + cbnz x4, 2b + + msr ttbr0_el1, x0 + msr ttbr1_el1, x0 + + mrs x2, sctlr_el1 + orr x2, x2, 1 + msr sctlr_el1, x2 + ret diff --git a/src/sched.c b/src/sched.c index b5ba2f120..aff44b1d9 100644 --- a/src/sched.c +++ b/src/sched.c @@ -37,15 +37,20 @@ static void reg_init(callee_reg_t *reg) { reg->fp = 0; reg->lr = 0; reg->sp = 0; + reg->ttbr0_el1 = 0; } static void thread_init(void) { for (int i = 0; i < MAX_THREAD_NUM; i++) { thread_pool[i].pid = i; thread_pool[i].kstack_addr = NULL; - for (int j = 0; j < MAX_USTACK_NUM; j++) - thread_pool[i].ustack_addr[j] = NULL; - thread_pool[i].ustack_num = 0; + thread_pool[i].ucode_addr = NULL; + thread_pool[i].ucode_size = 0; + thread_pool[i].ustack_addr = NULL; + thread_pool[i].pgd_addr = NULL; + thread_pool[i].pud_addr = NULL; + thread_pool[i].pmd_addr = NULL; + thread_pool[i].pte_addr = NULL; thread_pool[i].read_size = 0; thread_pool[i].wait_time = 0; for (int j = 0; j < MAX_FD_NUM; j++) diff --git a/src/sdhost.c b/src/sdhost.c index d4c0a8aaf..645c1558f 100644 --- a/src/sdhost.c +++ b/src/sdhost.c @@ -2,7 +2,7 @@ // mmio #define KVA 0xffff000000000000 -#define MMIO_BASE 0x3f000000 +#define MMIO_BASE (KVA+0x3f000000) // SD card command #define GO_IDLE_STATE 0 diff --git a/src/set_int.S b/src/set_int.S index 8a4ec6b7e..d0f3f15cd 100644 --- a/src/set_int.S +++ b/src/set_int.S @@ -1,4 +1,5 @@ #include "context.h" +#include "irq.h" .global from_el2_to_el1 from_el2_to_el1: @@ -11,15 +12,16 @@ from_el2_to_el1: .global from_el1_to_el0 from_el1_to_el0: - msr elr_el1, x3 + msr elr_el1, x2 msr sp_el0, x2 - mov x4, 0x0 - msr spsr_el1, x4 + msr ttbr0_el1, x3 + mov x3, 0x0 + msr spsr_el1, x3 eret .global set_exception_vector_table set_exception_vector_table: - adr x0, exception_vector_table + ldr x0, =exception_vector_table msr vbar_el1, x0 ret @@ -35,7 +37,7 @@ exception_vector_table: b invalid_exception .align 7 - b cur_el_svc_handler + b cur_el_exception_handler .align 7 b interrupt_handler .align 7 @@ -44,7 +46,7 @@ exception_vector_table: b invalid_exception .align 7 - b low_el_svc_handler + b low_el_exception_handler .align 7 b interrupt_handler .align 7 @@ -70,8 +72,19 @@ leave_exception: // =====Exception===== -low_el_svc_handler: +low_el_exception_handler: kernel_entry + mrs x0, esr_el1 + mov x0, x0, lsr #26 + ldr x1, =SVC_EXCEPTION + sub x1, x1, x0 + cbz x1, low_el_svc_handler + ldr x1, =LOW_EL_DA_EXCEPTION + sub x1, x1, x0 + cbz x1, low_el_da_handler + b leave_exception + +low_el_svc_handler: sub x8, x8, 2 cbz x8, check_file mov x0, sp @@ -96,6 +109,10 @@ sys_exec: mov x8, 0 bl do_exec +low_el_da_handler: + mrs x0, far_el1 + b page_fault_handler + // =====Interrupt===== interrupt_handler: @@ -105,7 +122,7 @@ interrupt_handler: // =================== -cur_el_svc_handler: +cur_el_exception_handler: kernel_entry b leave_exception diff --git a/src/shell.c b/src/shell.c index d4492aaab..774eec036 100644 --- a/src/shell.c +++ b/src/shell.c @@ -4,13 +4,14 @@ #include "type.h" #include "mm.h" #include "set_int.h" +#include "mmu.h" #define CMD_LEN 128 /* Reboot */ -#define PM_PASSWORD 0x5a000000 -#define PM_RSTC ((volatile unsigned int*)(0x3F10001c)) -#define PM_WDOG ((volatile unsigned int*)(0x3F100024)) +#define PM_PASSWORD (KERNEL_MAPPING+0x5a000000) +#define PM_RSTC ((volatile unsigned int*)(KERNEL_MAPPING+0x3F10001c)) +#define PM_WDOG ((volatile unsigned int*)(KERNEL_MAPPING+0x3F100024)) /* Key */ #define LEFT_BRACKET (char)91 @@ -20,7 +21,7 @@ #define EXEC_ADDR 0x1000000 /* Timer */ -#define CORE0_TIMER_IRQ_CTRL ((volatile unsigned int*)0x40000040) +#define CORE0_TIMER_IRQ_CTRL ((volatile unsigned int*)(KERNEL_MAPPING+0x40000040)) void *addr[100]; int addr_count; diff --git a/src/sys.c b/src/sys.c index ff16f8d40..cfaf15b6f 100644 --- a/src/sys.c +++ b/src/sys.c @@ -7,12 +7,66 @@ #include "uart.h" #include "sched.h" #include "vfs.h" +#include "mmu.h" -#define USTACK_SIZE 2048 -#define EXEC_ADDR 0x1000000 -#define MAX_PROGRAM_SIZE 0x1000 +#define USTACK_SIZE PAGE_SIZE +#define EXEC_ADDR 0x80000 -uint32_t program_num = 1; +/* System call - exit */ +static void sys_exit(void) { + thread_t *current = get_current(); + kfree(current->ucode_addr); + kfree(current->ustack_addr); + kfree(current->pgd_addr); + kfree(current->pud_addr); + kfree(current->pmd_addr); + kfree(current->pte_addr); + current->ucode_addr = NULL; + current->ucode_size = 0; + current->ustack_addr = NULL; + current->pgd_addr = NULL; + current->pud_addr = NULL; + current->pmd_addr = NULL; + current->pte_addr = NULL; + current->reg.ttbr0_el1 = 0; + thread_exit(); +} + +void page_fault_handler(uint64_t virtual_addr) { + print("Segmentation fault: 0x"); + print_hex(virtual_addr); + print("\n"); + sys_exit(); +} + +static void page_table_init(thread_t *t) { + t->pgd_addr = kmalloc(PAGE_SIZE); + t->pud_addr = kmalloc(PAGE_SIZE); + t->pmd_addr = kmalloc(PAGE_SIZE); + t->pte_addr = kmalloc(PAGE_SIZE); + + t->reg.ttbr0_el1 = (uint64_t)t->pgd_addr & PA_MASK; + uint64_t *entry = t->pgd_addr; + (*entry) = ((uint64_t)t->pud_addr & PA_MASK) | PGD_ATTR; + entry = t->pud_addr; + (*entry) = ((uint64_t)t->pmd_addr & PA_MASK) | PUD_ATTR; + entry = t->pmd_addr; + (*entry) = ((uint64_t)t->pte_addr & PA_MASK) | PMD_ATTR; +} + +static void pte_init(thread_t *t) { + uint64_t ustack_addr = EXEC_ADDR - PAGE_SIZE; + uint32_t page_count = !(t->ucode_size % PAGE_SIZE) ? (t->ucode_size / PAGE_SIZE) + : (t->ucode_size / PAGE_SIZE) + 1; + uint64_t *entry; + + entry = (char*)t->pte_addr + (ustack_addr / PAGE_SIZE) * 8; + (*entry) = ((uint64_t)t->ustack_addr & PA_MASK) | PTE_NORMAL_ATTR | PD_EL0_ACCESS; + for(int i = 0; i < page_count; i++) { + entry = (char*)t->pte_addr + (EXEC_ADDR / PAGE_SIZE + i) * 8; + (*entry) = (((uint64_t)t->ucode_addr + i * PAGE_SIZE) & PA_MASK) | PTE_NORMAL_ATTR | PD_EL0_ACCESS; + } +} /* System call - exec */ int do_exec(const char *name, char *const argv[], int pos) { @@ -23,22 +77,38 @@ int do_exec(const char *name, char *const argv[], int pos) { int argc = 0; thread_t *current = get_current(); - if (current->ustack_num > MAX_USTACK_NUM) - return -1; - /* Allocate user program address */ - current->ustack_addr[current->ustack_num] = kmalloc(USTACK_SIZE); - current->ustack_num++; + /* Allocate user stack */ + char *ustack_addr = kmalloc(USTACK_SIZE); + /* Count argc and Copy argv */ + while (argv[argc] != 0) + argc++; + char **tmp_argv = ustack_addr; + char *kaddr = ustack_addr + argc * sizeof(char*); + char *uaddr = (EXEC_ADDR - PAGE_SIZE) + argc * sizeof(char*); + for (int i = 0; i < argc; i++) { + size_t len = strlen(argv[i]) + 1; + memcpy(kaddr, argv[i], len); + tmp_argv[i] = uaddr ; + kaddr += len; + uaddr += len; + } + if (current->ustack_addr) + kfree(current->ustack_addr); + current->ustack_addr = ustack_addr; /* load user program */ - char *exec_addr = (char*)(EXEC_ADDR + MAX_PROGRAM_SIZE * (program_num - 1)); - memcpy(exec_addr, file_list[pos].file_content, file_list[pos].file_size); - program_num++; - /* Count argc */ - while (argv[argc++] != 0) {} + if (current->ucode_addr) + kfree(current->ucode_addr); + current->ucode_size = file_list[pos].file_size; + uint32_t alloc_size = !(current->ucode_size % PAGE_SIZE) ? current->ucode_size + : (current->ucode_size / PAGE_SIZE + 1) * PAGE_SIZE; + current->ucode_addr = kmalloc(alloc_size); + memcpy(current->ucode_addr, file_list[pos].file_content, file_list[pos].file_size); + if(current->pgd_addr == NULL) + page_table_init(current); + pte_init(current); - from_el1_to_el0(argc - 1, argv, - (uint64_t)current->ustack_addr[current->ustack_num - 1] + USTACK_SIZE, - (uint64_t)exec_addr); + from_el1_to_el0(argc, EXEC_ADDR - PAGE_SIZE, EXEC_ADDR, current->reg.ttbr0_el1); } /*System call - umount */ @@ -140,14 +210,6 @@ static void sys_sleep(tframe_t *frame) { schedule(); } -/* System call - exit */ -static void sys_exit(void) { - thread_t *current = get_current(); - for (int i = 0; i < current->ustack_num; i++) - kfree(current->ustack_addr[i]); - thread_exit(); -} - /* System call - fork */ static void sys_fork(tframe_t *frame) { thread_t *parent = get_current(); @@ -156,10 +218,19 @@ static void sys_fork(tframe_t *frame) { frame->x[0] = -1; return ; } + frame->x[0] = child->pid; child->reg.sp -= 272; - child->ustack_addr[child->ustack_num] = kmalloc(USTACK_SIZE); - child->ustack_num++; + child->ustack_addr = kmalloc(USTACK_SIZE); + child->ucode_size = parent->ucode_size; + uint32_t alloc_size = !(parent->ucode_size % PAGE_SIZE) ? parent->ucode_size + : (parent->ucode_size / PAGE_SIZE + 1) * PAGE_SIZE; + child->ucode_addr = kmalloc(alloc_size); + memcpy(child->ucode_addr, parent->ucode_addr, parent->ucode_size); + memcpy(child->ustack_addr, parent->ustack_addr, USTACK_SIZE); + page_table_init(child); + pte_init(child); + child->wd = parent->wd; child->fd_pos = child->fd_pos; for (int i = 0; i < MAX_FD_NUM; i++) { @@ -169,20 +240,11 @@ static void sys_fork(tframe_t *frame) { } } - /* Copy parent user stack to child user stack */ - uint64_t parent_usp_start = (uint64_t)parent->ustack_addr[parent->ustack_num - 1] + USTACK_SIZE - 1; - uint64_t child_usp_start = (uint64_t)child->ustack_addr[child->ustack_num - 1] + USTACK_SIZE - 1; - uint64_t parent_usp_end = frame->sp_el0; - uint64_t child_usp_end = child_usp_start - (parent_usp_start - parent_usp_end); - memcpy((char*)child_usp_end, (char*)parent_usp_end, (parent_usp_start - parent_usp_end + 1)); /* Copy trap frame to child kernel stack*/ - uint64_t parent_ksp_start = (uint64_t)frame; - uint64_t child_ksp_start = child->reg.sp; - memcpy((char*)child_ksp_start, (char*)parent_ksp_start, 272); + memcpy((char*)child->reg.sp, (char*)frame, 272); /* Modify trap frame */ - tframe_t *child_frame = (tframe_t*)child_ksp_start; + tframe_t *child_frame = (tframe_t*)child->reg.sp; child_frame->x[0] = 0; - child_frame->sp_el0 = child_usp_end; } /* System call - uart_write */ diff --git a/src/uart.c b/src/uart.c index 660f71fd4..00af92150 100644 --- a/src/uart.c +++ b/src/uart.c @@ -14,8 +14,8 @@ char write_buff[BUFF_SIZE]; queue_t read_queue; queue_t write_queue; -io_t *uart_in = &read_buff; -io_t *uart_out = &write_buff; +io_t *uart_in = &read_queue; +io_t *uart_out = &write_queue; void uart_init() { register unsigned int r = *GPFSEL1; diff --git a/src/utils.c b/src/utils.c index be95d9ade..fa9f349f1 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,4 +1,5 @@ #include "utils.h" +#include "mm.h" /* Delay time = time * 3~4 cycles */ void delay(uint64_t time) { @@ -72,6 +73,22 @@ unsigned int atoi(const char *s) { return num; } +uint8_t* htoa(uint64_t num) { + static uint16_t count = 0; + if (!num) { + uint8_t *s = kmalloc(16+1); + return s; + } + uint8_t *s = htoa(num / 16); + uint8_t n = num % 16; + if (n < 10) { + s[count++] = '0' + n; + } else { + s[count++] = 'A' + (n - 10); + } + return s; +} + unsigned long pow(unsigned int base, unsigned int order) { unsigned long sum = 1; diff --git a/src/vfs.c b/src/vfs.c index acba3f1c4..5ce13437f 100644 --- a/src/vfs.c +++ b/src/vfs.c @@ -213,7 +213,7 @@ int vfs_mount(const char *device, const char *pathname, if (*(p_name + len - 1) == '/') *(p_name + len - 1) = (char)0; if (vfs_lookup(dir, &target, pathname, &dir_name, DIR) >= 0) { - if (!vfs_setup_mount(&target->dentry.mount, device, filesystem)) { + if (target->dentry.prev == NULL && !vfs_setup_mount(&target->dentry.mount, device, filesystem)) { vnode_t *root = target->dentry.mount->root; root->dentry.prev = target; root->dentry.parent = target->dentry.parent; From 72b3a8b4072da3d41e523facf62243115555b7e9 Mon Sep 17 00:00:00 2001 From: ZiXunHuang Date: Thu, 24 Jun 2021 06:16:36 -0400 Subject: [PATCH 2/2] Fixed bug in fat write --- include/type.h | 4 ++++ include/vfs.h | 2 +- src/fat.c | 28 +++++++++++++++++++++++++--- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/include/type.h b/include/type.h index afa8066c7..45db576c6 100644 --- a/include/type.h +++ b/include/type.h @@ -10,6 +10,10 @@ typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; typedef unsigned long long uint64_t; +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef long long int64_t; typedef unsigned long long size_t; diff --git a/include/vfs.h b/include/vfs.h index c2187d2bc..5d211e7d2 100644 --- a/include/vfs.h +++ b/include/vfs.h @@ -26,7 +26,7 @@ typedef struct vnode { typedef struct file { uint16_t use_num; - size_t f_pos; + int64_t f_pos; struct vnode *vnode; } file_t; diff --git a/src/fat.c b/src/fat.c index f09ec7dfc..85d6bcc94 100644 --- a/src/fat.c +++ b/src/fat.c @@ -59,6 +59,8 @@ typedef struct fat32_dir_entry { typedef struct { uint32_t fat_sec; uint32_t head_sec; + uint32_t dir_sec; + uint16_t file_num; uint32_t clus_pos; uint32_t size; uint8_t sec_per_clu; @@ -87,6 +89,14 @@ static uint32_t fat32_get_next_clus(uint32_t current_clus, uint32_t fat_sec, } } +static void fat32_update_file_size(fat32_file_t *file) { + char buf[BLOCK_SIZE]; + readblock(file->dir_sec, buf); + uint32_t *size = &buf[file->file_num * 32 + 28]; + *size = file->size; + writeblock(file->dir_sec, buf); +} + static void fat32_umount_operation(vnode_t *file) { kfree(file->internal); } @@ -130,6 +140,8 @@ static void fat32_create_dir(vnode_t *dir_node, const char *dir_name) { static int fat32_read(struct file *file, void *buf, size_t len) { fat32_file_t *f = (fat32_file_t*)file->vnode->internal; + if (file->f_pos < 0) + return -1; uint8_t sec_count = (file->f_pos / f->byte_per_sec) % f->sec_per_clu; uint32_t start_sec = fat32_clus_to_sec(f->head_sec, f->clus_pos, f->sec_per_clu, sec_count); @@ -161,7 +173,7 @@ static int fat32_read(struct file *file, void *buf, size_t len) { static int fat32_write(struct file *file, const void *buf, size_t len) { fat32_file_t *f = (fat32_file_t*)file->vnode->internal; - if (!fat32_get_next_clus(f->clus_pos, f->fat_sec, f->byte_per_sec)) + if (file->f_pos < 0) return -1; uint8_t sec_count = (file->f_pos / f->byte_per_sec) % f->sec_per_clu; uint32_t start_sec = fat32_clus_to_sec(f->head_sec, f->clus_pos, @@ -169,6 +181,7 @@ static int fat32_write(struct file *file, const void *buf, size_t len) { uint16_t pos = file->f_pos % f->byte_per_sec; char sd_buf[BLOCK_SIZE]; size_t count; + bool_t no_next_clus = false; readblock(start_sec, sd_buf); for (count = 0; count < len; count++) { sd_buf[pos] = *((char*)buf + count); @@ -179,6 +192,7 @@ static int fat32_write(struct file *file, const void *buf, size_t len) { f->byte_per_sec); if (!next_clus) { count++; + no_next_clus = true; break; } else { f->clus_pos = next_clus; @@ -194,9 +208,15 @@ static int fat32_write(struct file *file, const void *buf, size_t len) { } } writeblock(start_sec, sd_buf); - if ((file->f_pos + count) > f->size) + if ((file->f_pos + count) > f->size) { f->size += count - (f->size - file->f_pos); - file->f_pos += count; + fat32_update_file_size(f); + } + if (no_next_clus == false) { + file->f_pos += count; + } else { + file->f_pos = -1; + } return count; } @@ -235,6 +255,8 @@ int fat_set_mount(mount_t *mount, const char *device) { fat32_file_t *f = kmalloc(sizeof(fat32_file_t)); f->fat_sec = fat_sec; f->head_sec = head_sec; + f->dir_sec = dir_sec; + f->file_num = file_count; f->clus_pos = dir.p2.l_clu_num + dir.p2.h_clu_num * 0x10000; f->size = dir.p2.size; f->sec_per_clu = bs.p1.bpb_sec_per_clu;