/* * Utility functions for process management. * * Note: in Lab1, only one process (i.e., our user application) exists. Therefore, * PKE OS at this stage will set "current" to the loaded user application, and also * switch to the old "current" process after trap handling. */ #include "riscv.h" #include "strap.h" #include "config.h" #include "process.h" #include "elf.h" #include "string.h" #include "vmm.h" #include "pmm.h" #include "memlayout.h" #include "spike_interface/spike_utils.h" //Two functions defined in kernel/usertrap.S extern char smode_trap_vector[]; 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 // void switch_to(process* proc) { assert(proc); current = proc; // write the smode_trap_vector (64-bit func. address) defined in kernel/strap_vector.S // to the stvec privilege register, such that trap handler pointed by smode_trap_vector // will be triggered when an interrupt occurs in S mode. write_csr(stvec, (uint64)smode_trap_vector); // set up trapframe values (in process structure) that smode_trap_vector will need when // the process next re-enters the kernel. proc->trapframe->kernel_sp = proc->kstack; // process's kernel stack proc->trapframe->kernel_satp = read_csr(satp); // kernel page table proc->trapframe->kernel_trap = (uint64)smode_trap_handler; // SSTATUS_SPP and SSTATUS_SPIE are defined in kernel/riscv.h // set S Previous Privilege mode (the SSTATUS_SPP bit in sstatus register) to User mode. unsigned long x = read_csr(sstatus); x &= ~SSTATUS_SPP; // clear SPP to 0 for user mode x |= SSTATUS_SPIE; // enable interrupts in user mode // write x back to 'sstatus' register to enable interrupts, and sret destination mode. write_csr(sstatus, x); // set S Exception Program Counter (sepc register) to the elf entry pc. write_csr(sepc, proc->trapframe->epc); // make user page table. macro MAKE_SATP is defined in kernel/riscv.h. added @lab2_1 uint64 user_satp = MAKE_SATP(proc->pagetable); // return_to_user() is defined in kernel/strap_vector.S. switch to user mode with sret. // note, return_to_user takes two parameters @ and after lab2_1. return_to_user(proc->trapframe, user_satp); }