导致usertests死循环,实际的内容差不多,我懒得再改一遍了uint64 fault_va=r_stval();// 产生页面错误的虚拟地址char*pa;// 分配的物理地址if(PGROUNDUP(p->trapframe->
page fault handler应该分配物理内存页面,并将新分配的物理内存页面映射到发生page fault的地址,然后返回用户空间让进程继续执行。 您可以通过查看 usertrap() 中的 r_scause() 是 13 还是 15 来检查错误是否是页面错误。(见上表) r_stval()返回 RISC-V stval寄存器,它是发生page fault的虚拟地址。 可以借鉴...
decref设计原本是为了在分配新页面后,递减原页面引用计数,这个任务直接交给kfree,来确保计数为0的页面能被立即释放,而使用decref可能导致页面无法正常释放的问题(three中分配了很多页面,第三次中kalloc会出错,没有剩余空间)。 // trap.celseif(r_scause() ==15){interr = CowHandler(r_stval());if(err <0...
第二,ecall将程序计数器的值保存在了SEPC寄存器。 第三,ecall会跳转到STVEC寄存器指向的指令。 sscrath(S-mode sratch:S态下可以临时使用的寄存器) 这个寄存器用户是看不到的,在刚刚进入trap的时候操作系统把trapframe的地址放在了里面 satp (S-mode address translation and protection) Trampoline(跳板): 对ec...
printf(" sepc=%p stval=%p\n", r_sepc(), r_stval()); p->killed = 1; } if(p->killed) exit(-1); // give up the CPU if this is a timer interrupt. if(which_dev == 2) yield(); usertrapret(); } usertrap函数是中断处理的核心函数,但理解不难,所以简要提几个细节: ...
先是通过stval寄存器里面的值来确定页的出错地方// 2.使用向下取整的方法得到起始地址uint64err_va=r...
mmap() 和 munmap() 这两个系统调用本身是类 UNIX 系统中才有的,这个实验只是仿照着实现它的一部分文件内存映射的功能(玩具)。具体 mmap() 的作用可以看看...
=0){// ok}else{printf("usertrap(): unexpected scause %p pid=%d\n",r_scause(),p->pid);printf(" sepc=%p stval=%p\n",r_sepc(),r_stval());p->killed=1;}if(p->killed)exit(-1);// give up the CPU if this is a timer interrupt.if(which_dev==2)yield();usertrapret()...
=0){// ok}else{printf("usertrap(): unexpected scause %p pid=%d\n",r_scause(),p->pid);printf(" sepc=%p stval=%p\n",r_sepc(),r_stval());p->killed=1;}if(p->killed)exit(-1);// give up the CPU if this is a timer interrupt.if(which_dev==2)yield();//返回user...
return (void*)r; } 在usertrap中加入判断语句,这里只需要处理scause==15的情况,因为13是页面读错误,而COW是不会引起读错误的。 void usertrap(void) { ... } else if(r_scause() == 15){ // page write fault uint64 va = r_stval(); ...