init commit of lab4_1

This commit is contained in:
Zhiyuan Shao 2021-08-30 20:22:33 +08:00
parent f287fda5a6
commit f6d24eed96
17 changed files with 262 additions and 38 deletions

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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 :
{

View File

@ -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

View File

@ -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);

74
kernel/machine/uart.c Normal file
View File

@ -0,0 +1,74 @@
// See LICENSE for license details.
#include <string.h>
#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);
}

27
kernel/machine/uart.h Normal file
View File

@ -0,0 +1,27 @@
// See LICENSE for license details.
#ifndef _RISCV_UART_H
#define _RISCV_UART_H
#include <stdint.h>
//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

View File

@ -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);
}

View File

@ -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

View File

@ -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));

View File

@ -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;
}

View File

@ -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

27
user/app_polling.c Normal file
View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);