diff --git a/Makefile b/Makefile index 01b26d2..46ce829 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ ifneq (,) mabi := -mabi=$(if $(is_32bit),ilp32,lp64) endif -CFLAGS := -Wall -Werror -fno-builtin -nostdlib -D__NO_INLINE__ -mcmodel=medany -g -Og -std=gnu99 -Wno-unused -Wno-attributes -fno-delete-null-pointer-checks -fno-PIE $(march) +CFLAGS := -Wall -Werror -fno-builtin -nostdlib -D__NO_INLINE__ -mcmodel=medany -g -O0 -std=gnu99 -Wno-unused -Wno-attributes -fno-delete-null-pointer-checks -fno-PIE $(march) COMPILE := $(CC) -MMD -MP $(CFLAGS) $(SPROJS_INCLUDE) #--------------------- utils ----------------------- @@ -63,21 +63,24 @@ SPIKE_INF_LIB := $(OBJ_DIR)/spike_interface.a #--------------------- user ----------------------- -USER_CPPS := user/*.c +USER_CPP0 := user/app_alloc0.c user/user_lib.c +USER_CPP1 := user/app_alloc1.c user/user_lib.c -USER_CPPS := $(wildcard $(USER_CPPS)) -USER_OBJS := $(addprefix $(OBJ_DIR)/, $(patsubst %.c,%.o,$(USER_CPPS))) +USER_CPP0 := $(wildcard $(USER_CPP0)) +USER_CPP1 := $(wildcard $(USER_CPP1)) +USER_OBJ0 := $(addprefix $(OBJ_DIR)/, $(patsubst %.c,%.o,$(USER_CPP0))) +USER_OBJ1 := $(addprefix $(OBJ_DIR)/, $(patsubst %.c,%.o,$(USER_CPP1))) - - -USER_TARGET := $(OBJ_DIR)/app_sum_sequence +USER_TARGET0 := $(OBJ_DIR)/app_alloc0 +USER_TARGET1 := $(OBJ_DIR)/app_alloc1 #------------------------targets------------------------ $(OBJ_DIR): @-mkdir -p $(OBJ_DIR) @-mkdir -p $(dir $(UTIL_OBJS)) @-mkdir -p $(dir $(SPIKE_INF_OBJS)) @-mkdir -p $(dir $(KERNEL_OBJS)) - @-mkdir -p $(dir $(USER_OBJS)) + @-mkdir -p $(dir $(USER_OBJ0)) + @-mkdir -p $(dir $(USER_OBJ1)) $(OBJ_DIR)/%.o : %.c @echo "compiling" $< @@ -102,9 +105,14 @@ $(KERNEL_TARGET): $(OBJ_DIR) $(UTIL_LIB) $(SPIKE_INF_LIB) $(KERNEL_OBJS) $(KERNE @$(COMPILE) $(KERNEL_OBJS) $(UTIL_LIB) $(SPIKE_INF_LIB) -o $@ -T $(KERNEL_LDS) @echo "PKE core has been built into" \"$@\" -$(USER_TARGET): $(OBJ_DIR) $(UTIL_LIB) $(USER_OBJS) +$(USER_TARGET0): $(OBJ_DIR) $(UTIL_LIB) $(USER_OBJ0) + @echo "linking" $@ ... + @$(COMPILE) --entry=main $(USER_OBJ0) $(UTIL_LIB) -o $@ + @echo "User app has been built into" \"$@\" + +$(USER_TARGET1): $(OBJ_DIR) $(UTIL_LIB) $(USER_OBJ1) @echo "linking" $@ ... - @$(COMPILE) --entry=main $(USER_OBJS) $(UTIL_LIB) -o $@ + @$(COMPILE) --entry=main $(USER_OBJ1) $(UTIL_LIB) -o $@ @echo "User app has been built into" \"$@\" -include $(wildcard $(OBJ_DIR)/*/*.d) @@ -112,16 +120,16 @@ $(USER_TARGET): $(OBJ_DIR) $(UTIL_LIB) $(USER_OBJS) .DEFAULT_GOAL := $(all) -all: $(KERNEL_TARGET) $(USER_TARGET) +all: $(KERNEL_TARGET) $(USER_TARGET0) $(USER_TARGET1) .PHONY:all -run: $(KERNEL_TARGET) $(USER_TARGET) +run: $(KERNEL_TARGET) $(USER_TARGET0) $(USER_TARGET1) @echo "********************HUST PKE********************" - spike $(KERNEL_TARGET) $(USER_TARGET) + spike -p2 $(KERNEL_TARGET) $(USER_TARGET0) $(USER_TARGET1) # need openocd! -gdb:$(KERNEL_TARGET) $(USER_TARGET) - spike --rbb-port=9824 -H $(KERNEL_TARGET) $(USER_TARGET) & +gdb:$(KERNEL_TARGET) $(USER_TARGET0) $(USER_TARGET1) + spike --rbb-port=9824 -H -p2 $(KERNEL_TARGET) $(USER_TARGET0) $(USER_TARGET1) & @sleep 1 openocd -f ./.spike.cfg & @sleep 1 @@ -135,7 +143,8 @@ gdb_clean: objdump: riscv64-unknown-elf-objdump -d $(KERNEL_TARGET) > $(OBJ_DIR)/kernel_dump - riscv64-unknown-elf-objdump -d $(USER_TARGET) > $(OBJ_DIR)/user_dump + riscv64-unknown-elf-objdump -d $(USER_TARGET0) > $(OBJ_DIR)/app_alloc0_dump + riscv64-unknown-elf-objdump -d $(USER_TARGET1) > $(OBJ_DIR)/app_alloc1_dump cscope: find ./ -name "*.c" > cscope.files @@ -148,4 +157,4 @@ format: @python ./format.py ./ clean: - rm -fr ${OBJ_DIR} + rm -fr ${OBJ_DIR} \ No newline at end of file diff --git a/kernel/config.h b/kernel/config.h index bdc8270..13f51c2 100644 --- a/kernel/config.h +++ b/kernel/config.h @@ -1,8 +1,8 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ -// we use only one HART (cpu) in fundamental experiments -#define NCPU 1 +// we use two HART (cpu) in challenge3 +#define NCPU 2 //interval of timer interrupt. added @lab1_3 #define TIMER_INTERVAL 1000000 diff --git a/kernel/elf.c b/kernel/elf.c index 7d7fa94..245c840 100644 --- a/kernel/elf.c +++ b/kernel/elf.c @@ -123,7 +123,7 @@ void load_bincode_from_host_elf(process *p) { size_t argc = parse_args(&arg_bug_msg); if (!argc) panic("You need to specify the application program!\n"); - sprint("Application: %s\n", arg_bug_msg.argv[0]); + sprint("hartid = ?: Application: %s\n", arg_bug_msg.argv[0]); //elf loading. elf_ctx is defined in kernel/elf.h, used to track the loading process. elf_ctx elfloader; @@ -148,5 +148,5 @@ void load_bincode_from_host_elf(process *p) { // close the host spike file spike_file_close( info.f ); - sprint("Application program entry point (virtual address): 0x%lx\n", p->trapframe->epc); + sprint("hartid = ?: Application program entry point (virtual address): 0x%lx\n", p->trapframe->epc); } diff --git a/kernel/kernel.c b/kernel/kernel.c index d633654..1edbf7c 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -52,7 +52,7 @@ void load_user_program(process *proc) { // USER_STACK_TOP = 0x7ffff000, defined in kernel/memlayout.h proc->trapframe->regs.sp = USER_STACK_TOP; //virtual address of user stack top - sprint("user frame 0x%lx, user stack 0x%lx, user kstack 0x%lx \n", proc->trapframe, + sprint("hartid = ?: user frame 0x%lx, user stack 0x%lx, user kstack 0x%lx \n", proc->trapframe, proc->trapframe->regs.sp, proc->kstack); // load_bincode_from_host_elf() is defined in kernel/elf.c @@ -77,7 +77,7 @@ void load_user_program(process *proc) { // s_start: S-mode entry point of riscv-pke OS kernel. // int s_start(void) { - sprint("Enter supervisor mode...\n"); + sprint("hartid = ?: Enter supervisor mode...\n"); // in the beginning, we use Bare mode (direct) memory mapping as in lab1. // but now, we are going to switch to the paging mode @lab2_1. // note, the code still works in Bare mode when calling pmm_init() and kern_vm_init(). @@ -97,7 +97,11 @@ int s_start(void) { // the application code (elf) is first loaded into memory, and then put into execution load_user_program(&user_app); - sprint("Switch to user mode...\n"); + sprint("hartid = ?: Switch to user mode...\n"); + + uint64 hartid = 0; + + vm_alloc_stage[hartid] = 1; // switch_to() is defined in kernel/process.c switch_to(&user_app); diff --git a/kernel/machine/mtrap.c b/kernel/machine/mtrap.c index 72566ba..e85069f 100644 --- a/kernel/machine/mtrap.c +++ b/kernel/machine/mtrap.c @@ -16,7 +16,7 @@ static void handle_misaligned_store() { panic("Misaligned AMO!"); } // added @lab1_3 static void handle_timer() { - int cpuid = 0; + int cpuid = read_csr(mhartid); // setup the timer fired at next time (TIMER_INTERVAL from now) *(uint64*)CLINT_MTIMECMP(cpuid) = *(uint64*)CLINT_MTIMECMP(cpuid) + TIMER_INTERVAL; diff --git a/kernel/pmm.c b/kernel/pmm.c index c10e007..9517d2a 100644 --- a/kernel/pmm.c +++ b/kernel/pmm.c @@ -15,6 +15,7 @@ extern uint64 g_mem_size; static uint64 free_mem_start_addr; //beginning address of free memory static uint64 free_mem_end_addr; //end address of free memory (not included) +int vm_alloc_stage[NCPU] = { 0 }; // 0 for kernel alloc, 1 for user alloc typedef struct node { struct node *next; } list_node; @@ -51,8 +52,11 @@ void free_page(void *pa) { // void *alloc_page(void) { list_node *n = g_free_mem_list.next; + uint64 hartid = 0; + if (vm_alloc_stage[hartid]) { + sprint("hartid = %ld: alloc page 0x%x\n", hartid, n); + } if (n) g_free_mem_list.next = n->next; - return (void *)n; } diff --git a/kernel/pmm.h b/kernel/pmm.h index bce9075..bd5ba21 100644 --- a/kernel/pmm.h +++ b/kernel/pmm.h @@ -1,6 +1,8 @@ #ifndef _PMM_H_ #define _PMM_H_ +#include "config.h" + // Initialize phisical memeory manager void pmm_init(); // Allocate a free phisical page @@ -8,4 +10,6 @@ void* alloc_page(); // Free an allocated page void free_page(void* pa); +extern int vm_alloc_stage[NCPU]; + #endif \ No newline at end of file diff --git a/kernel/sync_utils.h b/kernel/sync_utils.h new file mode 100644 index 0000000..988fc4c --- /dev/null +++ b/kernel/sync_utils.h @@ -0,0 +1,20 @@ +#ifndef _SYNC_UTILS_H_ +#define _SYNC_UTILS_H_ + +static inline void sync_barrier(volatile int *counter, int all) { + + int local; + + asm volatile("amoadd.w %0, %2, (%1)\n" + : "=r"(local) + : "r"(counter), "r"(1) + : "memory"); + + if (local + 1 < all) { + do { + asm volatile("lw %0, (%1)\n" : "=r"(local) : "r"(counter) : "memory"); + } while (local < all); + } +} + +#endif \ No newline at end of file diff --git a/kernel/syscall.c b/kernel/syscall.c index a7a9b1d..2d666d6 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -30,9 +30,10 @@ ssize_t sys_user_print(const char* buf, size_t n) { // implement the SYS_user_exit syscall // ssize_t sys_user_exit(uint64 code) { - sprint("User exit with code:%d.\n", code); + sprint("hartid = ?: User exit with code:%d.\n", code); // in lab1, PKE considers only one app (one process). // therefore, shutdown the system when the app calls exit() + sprint("hartid = ?: shutdown with code:%d.\n", code); shutdown(code); } @@ -45,7 +46,7 @@ uint64 sys_user_allocate_page() { g_ufree_page += PGSIZE; user_vm_map((pagetable_t)current->pagetable, va, PGSIZE, (uint64)pa, prot_to_type(PROT_WRITE | PROT_READ, 1)); - + sprint("hartid = ?: vaddr 0x%x is mapped to paddr 0x%x\n", va, pa); return va; } diff --git a/user/app_alloc0.c b/user/app_alloc0.c new file mode 100644 index 0000000..6e491c9 --- /dev/null +++ b/user/app_alloc0.c @@ -0,0 +1,24 @@ +#include "user_lib.h" +#include "util/types.h" + +#define N 5 +#define BASE 0 + +int main(void) { + void *p[N]; + + for (int i = 0; i < N; i++) { + p[i] = naive_malloc(); + int *pi = p[i]; + *pi = BASE + i; + printu("=== user alloc 0 @ vaddr 0x%x\n", p[i]); + } + + for (int i = 0; i < N; i++) { + int *pi = p[i]; + printu("=== user0: %d\n", *pi); + naive_free(p[i]); + } + + exit(0); +} \ No newline at end of file diff --git a/user/app_alloc1.c b/user/app_alloc1.c new file mode 100644 index 0000000..440765f --- /dev/null +++ b/user/app_alloc1.c @@ -0,0 +1,24 @@ +#include "user_lib.h" +#include "util/types.h" + +#define N 5 +#define BASE 5 + +int main(void) { + void *p[N]; + + for (int i = 0; i < N; i++) { + p[i] = naive_malloc(); + int *pi = p[i]; + *pi = BASE + i; + printu(">>> user alloc 1 @ vaddr 0x%x\n", p[i]); + } + + for (int i = 0; i < N; i++) { + int *pi = p[i]; + printu(">>> user 1: %d\n", *pi); + naive_free(p[i]); + } + + exit(0); +} \ No newline at end of file diff --git a/user/app_sum_sequence.c b/user/app_sum_sequence.c deleted file mode 100644 index 809d341..0000000 --- a/user/app_sum_sequence.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * The application of lab2_3. - */ - -#include "user_lib.h" -#include "util/types.h" - -// -// compute the summation of an arithmetic sequence. for a given "n", compute -// result = n + (n-1) + (n-2) + ... + 0 -// sum_sequence() calls itself recursively till 0. The recursive call, however, -// may consume more memory (from stack) than a physical 4KB page, leading to a page fault. -// PKE kernel needs to improved to handle such page fault by expanding the stack. -// -uint64 sum_sequence(uint64 n) { - if (n == 0) - return 0; - else - return sum_sequence( n-1 ) + n; -} - -int main(void) { - // we need a large enough "n" to trigger pagefaults in the user stack - uint64 n = 1000; - - printu("Summation of an arithmetic sequence from 0 to %ld is: %ld \n", n, sum_sequence(1000) ); - exit(0); -}