From f6d24eed96d363a54f4d29e914bc8454e2adb85d Mon Sep 17 00:00:00 2001 From: Zhiyuan Shao Date: Mon, 30 Aug 2021 20:22:33 +0800 Subject: [PATCH] init commit of lab4_1 --- LICENSE.txt | 6 ++- Makefile | 2 +- kernel/config.h | 2 +- kernel/kernel.lds | 5 ++- kernel/machine/mentry.S | 3 +- kernel/machine/minit.c | 28 +++++++++++++- kernel/machine/uart.c | 74 +++++++++++++++++++++++++++++++++++++ kernel/machine/uart.h | 27 ++++++++++++++ kernel/syscall.c | 40 ++++++++++++++++++++ kernel/syscall.h | 5 ++- kernel/vmm.c | 2 + spike_interface/dts_parse.c | 18 +++++++++ spike_interface/dts_parse.h | 6 ++- user/app_polling.c | 27 ++++++++++++++ user/app_two_long_loops.c | 28 -------------- user/user_lib.c | 22 +++++++++++ user/user_lib.h | 5 +++ 17 files changed, 262 insertions(+), 38 deletions(-) create mode 100644 kernel/machine/uart.c create mode 100644 kernel/machine/uart.h create mode 100644 user/app_polling.c delete mode 100644 user/app_two_long_loops.c diff --git a/LICENSE.txt b/LICENSE.txt index b586e63..305f013 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -4,8 +4,10 @@ Copyright License The PKE software is: Copyright (c) 2021, Zhiyuan Shao (zyshao@hust.edu.cn), - Yi Gui (gy163email@163.com), - Yan Jiao (773709579@qq.com), + Ziming Yuan (1223962053@qq.com), + Yixin Song (474309045@qq.com), + Boyang Li (liboyang_hust@163.com), + Zhenfei Huo(393900861@qq.com) Huazhong University of Science and Technology Permission is hereby granted, free of charge, to any person obtaining diff --git a/Makefile b/Makefile index 2dde5bf..fc1a2fc 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,7 @@ USER_OBJS := $(addprefix $(OBJ_DIR)/, $(patsubst %.c,%.o,$(USER_CPPS))) -USER_TARGET := $(OBJ_DIR)/app_two_long_loops +USER_TARGET := $(OBJ_DIR)/app_polling #------------------------targets------------------------ $(OBJ_DIR): @-mkdir -p $(OBJ_DIR) diff --git a/kernel/config.h b/kernel/config.h index 67f677c..79e6aeb 100644 --- a/kernel/config.h +++ b/kernel/config.h @@ -8,7 +8,7 @@ #define TIMER_INTERVAL 1000000 // the maximum memory space that PKE is allowed to manage -#define PKE_MAX_ALLOWABLE_RAM 128 * 1024 * 1024 +#define PKE_MAX_ALLOWABLE_RAM 1 * 1024 * 1024 // the ending physical address that PKE observes #define PHYS_TOP (DRAM_BASE + PKE_MAX_ALLOWABLE_RAM) diff --git a/kernel/kernel.lds b/kernel/kernel.lds index 90d730f..0814e66 100644 --- a/kernel/kernel.lds +++ b/kernel/kernel.lds @@ -14,7 +14,10 @@ SECTIONS /* Begining of code and text segment, starts from DRAM_BASE to be effective before enabling paging */ . = 0x80000000; _ftext = .; - + .text : + { + *(.text.init) + } /* text: Program code section */ .text : { diff --git a/kernel/machine/mentry.S b/kernel/machine/mentry.S index 4da7c87..b674679 100644 --- a/kernel/machine/mentry.S +++ b/kernel/machine/mentry.S @@ -9,7 +9,8 @@ # [a1] = pointer to the DTS (i.e., Device Tree String), which is stored in the memory of # RISC-V guest computer. # - + .option norvc + .section .text.init,"ax",@progbits .globl _mentry _mentry: # [mscratch] = 0; mscratch points the stack bottom of machine mode computer diff --git a/kernel/machine/minit.c b/kernel/machine/minit.c index 66fdb1a..0a573ec 100644 --- a/kernel/machine/minit.c +++ b/kernel/machine/minit.c @@ -6,7 +6,7 @@ #include "kernel/riscv.h" #include "kernel/config.h" #include "spike_interface/spike_utils.h" - +#include "uart.h" // // global variables are placed in the .data section. // stack0 is the privilege mode stack(s) of the proxy kernel on CPU(s) @@ -66,6 +66,25 @@ static void delegate_traps() { assert(read_csr(medeleg) == exceptions); } +// +// setup the Physical Memory Protection mechanism. the purpose is to make PKE runable on +// both Spike and Zedboard (especially Zedboard). the function is borrowed from PK. +// +void setup_pmp(void) { + // Set up a PMP to permit access to all of memory. + // Ignore the illegal-instruction trap if PMPs aren't supported. + uintptr_t pmpc = PMP_NAPOT | PMP_R | PMP_W | PMP_X; + asm volatile( + "la t0, 1f\n\t" + "csrrw t0, mtvec, t0\n\t" + "csrw pmpaddr0, %1\n\t" + "csrw pmpcfg0, %0\n\t" + ".align 2\n\t" + "1: csrw mtvec, t0" + : + : "r"(pmpc), "r"(-1UL) + : "t0"); +} // // enabling timer interrupt (irq) in Machine mode // @@ -83,11 +102,18 @@ void timerinit(uintptr_t hartid) { void m_start(uintptr_t hartid, uintptr_t dtb) { // init the spike file interface (stdin,stdout,stderr) spike_file_init(); + query_uart(dtb); sprint("In m_start, hartid:%d\n", hartid); // init HTIF (Host-Target InterFace) and memory by using the Device Table Blob (DTB) init_dtb(dtb); + setup_pmp(); + extern char smode_trap_vector; + write_csr(stvec, (uint64)smode_trap_vector); + write_csr(sscratch, 0); + write_csr(sie, 0); + set_csr(sstatus, SSTATUS_SUM | SSTATUS_FS); // save the address of frame for interrupt in M mode to csr "mscratch". write_csr(mscratch, &g_itrframe); diff --git a/kernel/machine/uart.c b/kernel/machine/uart.c new file mode 100644 index 0000000..54ba2e1 --- /dev/null +++ b/kernel/machine/uart.c @@ -0,0 +1,74 @@ +// See LICENSE for license details. + +#include +#include "uart.h" +//add +#include "util/types.h" +#include "spike_interface/dts_parse.h" + +volatile uint32* uart; + + +void uart_putchar(uint8 ch) +{ + volatile uint32 *status = (void*)(uintptr_t)0x60000008; + volatile uint32 *tx = (void*)(uintptr_t)0x60000004; + while (*status & 0x00000008); + *tx = ch; +} + +int uart_getchar() +{ + volatile uint32 *rx = (void*)(uintptr_t)0x60000000; + volatile uint32 *status = (void*)(uintptr_t)0x60000008; + while (!(*status & 0x00000001)); + int32_t ch = *rx; + return ch; +} + +struct uart_scan +{ + int compat; + uint64 reg; +}; + +static void uart_open(const struct fdt_scan_node *node, void *extra) +{ + struct uart_scan *scan = (struct uart_scan *)extra; + memset(scan, 0, sizeof(*scan)); +} + +static void uart_prop(const struct fdt_scan_prop *prop, void *extra) +{ + struct uart_scan *scan = (struct uart_scan *)extra; + if (!strcmp(prop->name, "compatible") && fdt_string_list_index(prop, "sifive,uart0") >= 0) { + scan->compat = 1; + } else if (!strcmp(prop->name, "reg")) { + fdt_get_address(prop->node->parent, prop->value, &scan->reg); + } +} + +static void uart_done(const struct fdt_scan_node *node, void *extra) +{ + struct uart_scan *scan = (struct uart_scan *)extra; + if (!scan->compat || !scan->reg || uart) return; + + // Enable Rx/Tx channels + uart = (void*)(uintptr_t)scan->reg; + uart[UART_REG_TXCTRL] = UART_TXEN; + uart[UART_REG_RXCTRL] = UART_RXEN; +} + +void query_uart(uintptr_t fdt) +{ + struct fdt_cb cb; + struct uart_scan scan; + + memset(&cb, 0, sizeof(cb)); + cb.open = uart_open; + cb.prop = uart_prop; + cb.done = uart_done; + cb.extra = &scan; + + fdt_scan(fdt, &cb); +} diff --git a/kernel/machine/uart.h b/kernel/machine/uart.h new file mode 100644 index 0000000..ac721cb --- /dev/null +++ b/kernel/machine/uart.h @@ -0,0 +1,27 @@ +// See LICENSE for license details. + +#ifndef _RISCV_UART_H +#define _RISCV_UART_H + +#include +//add +#include "util/types.h" + +extern volatile uint32* uart; + +#define UART_REG_TXFIFO 0 +#define UART_REG_RXFIFO 1 +#define UART_REG_TXCTRL 2 +#define UART_REG_RXCTRL 3 +#define UART_REG_IE 4 +#define UART_REG_IP 5 +#define UART_REG_DIV 6 + +#define UART_TXEN 0x1 +#define UART_RXEN 0x1 + +void uart_putchar(uint8_t ch); +int uart_getchar(); +void query_uart(uintptr_t dtb); + +#endif diff --git a/kernel/syscall.c b/kernel/syscall.c index d2b1fd1..1537e68 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -81,6 +81,40 @@ ssize_t sys_user_yield() { return 0; } +//add uart putchar getchar syscall +// +// implement the SYS_user_uart_putchar syscall +// +void sys_user_uart_putchar(uint8 ch) { + volatile uint32 *status = (void*)(uintptr_t)0x60000008; + volatile uint32 *tx = (void*)(uintptr_t)0x60000004; + while (*status & 0x00000008); + *tx = ch; +} + +ssize_t sys_user_uart_getchar() { + // TODO (lab4_1 and lab4_2): implment the syscall of sys_user_uart_getchar and modify it in lab4_2. + // hint (lab4_1): the functionality of sys_user_uart_getchar is to get data from UART address. therefore, + // we should let a pointer point, insert it in + // the rear of ready queue, and finally, schedule a READY process to run. + // hint (lab4_2): the functionality of sys_user_uart_getchar is let process sleep and wait for value. therefore, + // we should call do_sleep to let process 0 sleep. + // then we should get uartvalue and return. + panic( "You have to implement sys_user_uart_getchar to get data from UART using uartgetchar in lab4_1 and modify it in lab4_2.\n" ); + +} + + + +//car control +ssize_t sys_user_gpio_reg_write(uint8 val) { + volatile uint32_t *control_reg = (void*)(uintptr_t)0x60001004; + volatile uint32_t *data_reg = (void*)(uintptr_t)0x60001000; + //*control_reg = 0; + *data_reg = (uint32_t)val; + return 1; +} + // // [a0]: the syscall number; [a1] ... [a7]: arguments to the syscalls. // returns the code of success, (e.g., 0 means success, fail for otherwise) @@ -99,6 +133,12 @@ long do_syscall(long a0, long a1, long a2, long a3, long a4, long a5, long a6, l return sys_user_fork(); case SYS_user_yield: return sys_user_yield(); + case SYS_user_uart_putchar: + sys_user_uart_putchar(a1);return 1; + case SYS_user_uart_getchar: + return sys_user_uart_getchar(); + case SYS_user_gpio_reg_write: + return sys_user_gpio_reg_write(a1); default: panic("Unknown syscall %ld \n", a0); } diff --git a/kernel/syscall.h b/kernel/syscall.h index e4e02fe..0204966 100644 --- a/kernel/syscall.h +++ b/kernel/syscall.h @@ -12,7 +12,10 @@ #define SYS_user_free_page (SYS_user_base + 3) #define SYS_user_fork (SYS_user_base + 4) #define SYS_user_yield (SYS_user_base + 5) - +// add syscall uart putchar getchar +#define SYS_user_uart_putchar (SYS_user_base + 6) +#define SYS_user_uart_getchar (SYS_user_base + 7) +#define SYS_user_gpio_reg_write (SYS_user_base + 8) long do_syscall(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7); #endif diff --git a/kernel/vmm.c b/kernel/vmm.c index 92a977e..6844cf6 100644 --- a/kernel/vmm.c +++ b/kernel/vmm.c @@ -133,6 +133,8 @@ void kern_vm_init(void) { // also (direct) map remaining address space, to make them accessable from kernel. // this is important when kernel needs to access the memory content of user's app // without copying pages between kernel and user spaces. + kern_vm_map(t_page_dir, (uint64)0x60000000, (uint64)0x60000000, (uint64)0x60020000 - (uint64)0x60000000, + prot_to_type(PROT_READ | PROT_WRITE, 0)); kern_vm_map(t_page_dir, (uint64)_etext, (uint64)_etext, PHYS_TOP - (uint64)_etext, prot_to_type(PROT_READ | PROT_WRITE, 0)); diff --git a/spike_interface/dts_parse.c b/spike_interface/dts_parse.c index 2aec5c1..cdc02fe 100644 --- a/spike_interface/dts_parse.c +++ b/spike_interface/dts_parse.c @@ -97,3 +97,21 @@ void fdt_scan(uint64 fdt, const struct fdt_cb *cb) { fdt_scan_helper(lex, strings, 0, cb); } + +//add +uint32 fdt_get_value(const struct fdt_scan_prop *prop, uint32 index) { + return bswap(prop->value[index]); +} + +int fdt_string_list_index(const struct fdt_scan_prop *prop, const char *str) +{ + const char *list = (const char *)prop->value; + const char *end = list + prop->len; + int index = 0; + while (end - list > 0) { + if (!strcmp(list, str)) return index; + ++index; + list += strlen(list) + 1; + } + return -1; +} diff --git a/spike_interface/dts_parse.h b/spike_interface/dts_parse.h index aea977f..bbfe534 100644 --- a/spike_interface/dts_parse.h +++ b/spike_interface/dts_parse.h @@ -56,6 +56,8 @@ uint32 fdt_size(uint64 fdt); // Extract fields const uint32 *fdt_get_address(const struct fdt_scan_node *node, const uint32 *base, uint64 *value); const uint32 *fdt_get_size(const struct fdt_scan_node *node, const uint32 *base, uint64 *value); -int fdt_string_list_index(const struct fdt_scan_prop *prop, - const char *str); // -1 if not found +int fdt_string_list_index(const struct fdt_scan_prop *prop, const char *str); // -1 if not found +//add +uint32 fdt_get_value(const struct fdt_scan_prop *prop, uint32 index); + #endif diff --git a/user/app_polling.c b/user/app_polling.c new file mode 100644 index 0000000..09a2cbc --- /dev/null +++ b/user/app_polling.c @@ -0,0 +1,27 @@ +/* + * Below is the given application for lab4_1. + * The goal of this app is to control the car via Bluetooth. + */ + +#include "user_lib.h" +#include "util/types.h" + +int main(void) { + printu("please input the instruction through bluetooth!\n"); + while(1) + { + char temp = (char)uartgetchar(); + uartputchar(temp); + switch (temp) + { + case '1' : gpio_reg_write(0x2e); break; //前进 + case '2' : gpio_reg_write(0xd1); break; //后退 + case '3' : gpio_reg_write(0x63); break; //左转 + case '4' : gpio_reg_write(0x9c); break; //右转 + case 'q' : exit(0); break; + default : gpio_reg_write(0x00); break; //停止 + } + } + exit(0); + return 0; +} diff --git a/user/app_two_long_loops.c b/user/app_two_long_loops.c deleted file mode 100644 index 2568485..0000000 --- a/user/app_two_long_loops.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * The application of lab3_3. - * parent and child processes never give up their processor during execution. - */ - -#include "user/user_lib.h" -#include "util/types.h" - -int main(void) { - uint64 pid = fork(); - uint64 rounds = 100000000; - uint64 interval = 10000000; - uint64 a = 0; - if (pid == 0) { - printu("Child: Hello world! \n"); - for (uint64 i = 0; i < rounds; ++i) { - if (i % interval == 0) printu("Child running %ld \n", i); - } - } else { - printu("Parent: Hello world! \n"); - for (uint64 i = 0; i < rounds; ++i) { - if (i % interval == 0) printu("Parent running %ld \n", i); - } - } - - exit(0); - return 0; -} diff --git a/user/user_lib.c b/user/user_lib.c index 3fcb85d..2cc44cc 100644 --- a/user/user_lib.c +++ b/user/user_lib.c @@ -76,3 +76,25 @@ int fork() { void yield() { do_user_call(SYS_user_yield, 0, 0, 0, 0, 0, 0, 0); } +// add +// add syscall uart getchar putchar +// +// applications need to call uart_putchar to put a char by device +// +int uartputchar(char ch) { + return do_user_call(SYS_user_uart_putchar, ch, 0, 0, 0, 0, 0, 0); +} + +// +// applications need to call uart_getchar to get a char by device +// +int uartgetchar() { + return do_user_call(SYS_user_uart_getchar, 0, 0, 0, 0, 0, 0, 0); +} + + + +// car +int gpio_reg_write(char val) { + return do_user_call(SYS_user_gpio_reg_write, val, 0, 0, 0, 0, 0, 0); +} \ No newline at end of file diff --git a/user/user_lib.h b/user/user_lib.h index 63e2e25..d29e2d3 100644 --- a/user/user_lib.h +++ b/user/user_lib.h @@ -8,3 +8,8 @@ void* naive_malloc(); void naive_free(void* va); int fork(); void yield(); +//add +int uartputchar(char ch); +int uartgetchar(); + +int gpio_reg_write(char val);