diff --git a/Makefile b/Makefile index 32a8825..9dad6ad 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,7 @@ USER_OBJS := $(addprefix $(OBJ_DIR)/, $(patsubst %.c,%.o,$(USER_CPPS))) -USER_TARGET := $(OBJ_DIR)/app_helloworld_no_lds +USER_TARGET := $(OBJ_DIR)/app_naive_malloc #------------------------targets------------------------ $(OBJ_DIR): @-mkdir -p $(OBJ_DIR) diff --git a/kernel/memlayout.h b/kernel/memlayout.h index 48b8018..f2cc959 100644 --- a/kernel/memlayout.h +++ b/kernel/memlayout.h @@ -1,5 +1,6 @@ #ifndef _MEMLAYOUT_H #define _MEMLAYOUT_H +#include "riscv.h" // RISC-V machine places its physical memory above DRAM_BASE #define DRAM_BASE 0x80000000 @@ -13,4 +14,7 @@ // virtual address of stack top of user process #define USER_STACK_TOP 0x7ffff000 +// start virtual address (4MB) of our simple heap. added @lab2_2 +#define USER_FREE_ADDRESS_START 0x00000000 + PGSIZE * 1024 + #endif diff --git a/kernel/process.c b/kernel/process.c index 889dd19..d909533 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -24,6 +24,9 @@ extern void return_to_user(trapframe *, uint64 satp); // current points to the currently running user-mode application. process* current = NULL; +// points to the first free page in our simple heap. added @lab2_2 +uint64 g_ufree_page = USER_FREE_ADDRESS_START; + // // switch to a user-mode process // diff --git a/kernel/process.h b/kernel/process.h index 23fba62..c1278a9 100644 --- a/kernel/process.h +++ b/kernel/process.h @@ -34,4 +34,7 @@ void switch_to(process*); // current running process extern process* current; +// address of the first free page in our simple heap. added @lab2_2 +extern uint64 g_ufree_page; + #endif diff --git a/kernel/syscall.c b/kernel/syscall.c index acfdeb9..a7a9b1d 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -36,6 +36,27 @@ ssize_t sys_user_exit(uint64 code) { shutdown(code); } +// +// maybe, the simplest implementation of malloc in the world ... added @lab2_2 +// +uint64 sys_user_allocate_page() { + void* pa = alloc_page(); + uint64 va = g_ufree_page; + g_ufree_page += PGSIZE; + user_vm_map((pagetable_t)current->pagetable, va, PGSIZE, (uint64)pa, + prot_to_type(PROT_WRITE | PROT_READ, 1)); + + return va; +} + +// +// reclaim a page, indicated by "va". added @lab2_2 +// +uint64 sys_user_free_page(uint64 va) { + user_vm_unmap((pagetable_t)current->pagetable, va, PGSIZE, 1); + return 0; +} + // // [a0]: the syscall number; [a1] ... [a7]: arguments to the syscalls. // returns the code of success, (e.g., 0 means success, fail for otherwise) @@ -46,6 +67,11 @@ long do_syscall(long a0, long a1, long a2, long a3, long a4, long a5, long a6, l return sys_user_print((const char*)a1, a2); case SYS_user_exit: return sys_user_exit(a1); + // added @lab2_2 + case SYS_user_allocate_page: + return sys_user_allocate_page(); + case SYS_user_free_page: + return sys_user_free_page(a1); default: panic("Unknown syscall %ld \n", a0); } diff --git a/kernel/syscall.h b/kernel/syscall.h index 9dd228c..19aa1b6 100644 --- a/kernel/syscall.h +++ b/kernel/syscall.h @@ -8,6 +8,9 @@ #define SYS_user_base 64 #define SYS_user_print (SYS_user_base + 0) #define SYS_user_exit (SYS_user_base + 1) +// added @lab2_2 +#define SYS_user_allocate_page (SYS_user_base + 2) +#define SYS_user_free_page (SYS_user_base + 3) long do_syscall(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7); diff --git a/kernel/vmm.c b/kernel/vmm.c index 20626a3..c792f6e 100644 --- a/kernel/vmm.c +++ b/kernel/vmm.c @@ -171,3 +171,19 @@ void user_vm_map(pagetable_t page_dir, uint64 va, uint64 size, uint64 pa, int pe panic("fail to user_vm_map .\n"); } } + +// +// unmap virtual address [va, va+size] from the user app. +// reclaim the physical pages if free!=0 +// +void user_vm_unmap(pagetable_t page_dir, uint64 va, uint64 size, int free) { + // TODO (lab2_2): implement user_vm_unmap to disable the mapping of the virtual pages + // in [va, va+size], and free the corresponding physical pages used by the virtual + // addresses when if 'free' (the last parameter) is not zero. + // basic idea here is to first locate the PTEs of the virtual pages, and then reclaim + // (use free_page() defined in pmm.c) the physical pages. lastly, invalidate the PTEs. + // as naive_free reclaims only one page at a time, you only need to consider one page + // to make user/app_naive_malloc to behave correctly. + panic( "You have to implement user_vm_unmap to free pages using naive_free in lab2_2.\n" ); + +} diff --git a/kernel/vmm.h b/kernel/vmm.h index e89da48..b5bd916 100644 --- a/kernel/vmm.h +++ b/kernel/vmm.h @@ -29,5 +29,6 @@ void kern_vm_init(void); /* --- user page table --- */ void *user_va_to_pa(pagetable_t page_dir, void *va); void user_vm_map(pagetable_t page_dir, uint64 va, uint64 size, uint64 pa, int perm); +void user_vm_unmap(pagetable_t page_dir, uint64 va, uint64 size, int free); #endif diff --git a/user/app_helloworld_no_lds.c b/user/app_helloworld_no_lds.c deleted file mode 100644 index 8bb9e2d..0000000 --- a/user/app_helloworld_no_lds.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Below is the given application for lab2_1. - * This app runs in its own address space, in contrast with in direct mapping. - */ - -#include "user_lib.h" -#include "util/types.h" - -int main(void) { - printu("Hello world!\n"); - exit(0); -} diff --git a/user/app_naive_malloc.c b/user/app_naive_malloc.c new file mode 100644 index 0000000..adf40bf --- /dev/null +++ b/user/app_naive_malloc.c @@ -0,0 +1,22 @@ +/* + * Below is the given application for lab2_2. + */ + +#include "user_lib.h" +#include "util/types.h" + +struct my_structure { + char c; + int n; +}; + +int main(void) { + struct my_structure* s = (struct my_structure*)naive_malloc(); + s->c = 'a'; + s->n = 1; + + printu("s: %lx, {%c %d}\n", s, s->c, s->n); + + naive_free(s); + exit(0); +} diff --git a/user/user_lib.c b/user/user_lib.c index fff4546..819e5ea 100644 --- a/user/user_lib.c +++ b/user/user_lib.c @@ -10,7 +10,7 @@ #include "util/snprintf.h" #include "kernel/syscall.h" -int do_user_call(uint64 sysnum, uint64 a1, uint64 a2, uint64 a3, uint64 a4, uint64 a5, uint64 a6, +uint64 do_user_call(uint64 sysnum, uint64 a1, uint64 a2, uint64 a3, uint64 a4, uint64 a5, uint64 a6, uint64 a7) { int ret; @@ -49,3 +49,17 @@ int printu(const char* s, ...) { int exit(int code) { return do_user_call(SYS_user_exit, code, 0, 0, 0, 0, 0, 0); } + +// +// lib call to naive_malloc +// +void* naive_malloc() { + return (void*)do_user_call(SYS_user_allocate_page, 0, 0, 0, 0, 0, 0, 0); +} + +// +// lib call to naive_free +// +void naive_free(void* va) { + do_user_call(SYS_user_free_page, (uint64)va, 0, 0, 0, 0, 0, 0); +} diff --git a/user/user_lib.h b/user/user_lib.h index 7c53805..c1a0bec 100644 --- a/user/user_lib.h +++ b/user/user_lib.h @@ -4,3 +4,5 @@ int printu(const char *s, ...); int exit(int code); +void* naive_malloc(); +void naive_free(void* va);