Speed up system calls

第一个任务,是加快系统调用
正常情况下,我们要getPid什么的,需要去调用内核函数才能获取,但是我们把这些信息直接放进page中。
即在proc中去添加可以映射到USYSCALL的页,这个USYSCALL其实是一个只包含pid的结构体
使得我们从用户态就可以直接快速访问pid,就不需要再进行用户态到内核态的转换了

Detecting which pages have been accessed

这个练习要求我们写一个检测某个页面是否已经访问过的系统调用
实验要求:从一个用户页表地址开始,搜索所有被访问过的页并返回一个bitmap来显示这些页是否被访问过。比如说,如果第二个页被访问过了,bitmap里从右往左数第二个bit就是1。
我们需要明确,PTE_A标志位虽然是我们自己新添加的,但是只要访问过该页,硬件会自动把它置为1
核心代码

  1. int
  2. sys_pgaccess(void) {
  3. // lab pgtbl: your code here.
  4. uint64 addr;
  5. int len;
  6. int bitmask;
  7. if (argaddr(0, &addr) < 0) { // 内核函数取调用者的参数方法就是这样
  8. return -1;
  9. }
  10. if (argint(1, &len) < 0) {
  11. return -1;
  12. }
  13. if (argint(2, &bitmask) < 0) {
  14. return -1;
  15. }
  16. if (len > 32 || len < 0) {
  17. return -1;
  18. }
  19. /**
  20. * 核心代码
  21. * 用int va = addr + i * PGSIZE表示某个页表的第i个的虚拟地址
  22. * 使用vm_pgaccess去找这个虚拟地址对应的标志位
  23. * 用res | abit << i把标志位加到res中对应i的位置
  24. * 最后再把res拷贝到bitmap中,返回给调用的用户进程
  25. */
  26. int res = 0;
  27. struct proc *p = myproc();
  28. for (int i = 0;i < len;i++) {
  29. int va = addr + i * PGSIZE;
  30. int abit = vm_pgaccess(p->pagetable, va);
  31. res = res | abit << i;
  32. }
  33. if (copyout(p->pagetable, bitmask, (char *)&res, sizeof(res)) < 0) { // Copy from kernel to user.
  34. return -1;
  35. }
  36. return 0;
  37. }
  1. int vm_pgaccess(pagetable_t pagetable, uint64 va) {
  2. pte_t *pte;
  3. if (va >= MAXVA) {
  4. return 0;
  5. }
  6. pte = walk(pagetable, va, 0);
  7. if (pte == 0) {
  8. return 0;
  9. }
  10. if ((*pte & PTE_A) != 0) {
  11. *pte = *pte & (~PTE_A); // clear 6th flag(PTE_A)
  12. return 1;
  13. }
  14. return 0;
  15. }