Lab3 Page Tables

0 lecture 4 & chapter 3

Lecture 4

Chapter 3 Page tables

xv6的页表映射机制

xv6 内核地址空间

xv6的页表代码

vm.c

核心数据结构:==pagetable_t==

核心函数:==walk== 和 ==mappages==

物理地址分配代码

kalloc.c

核心数据结构:==kmem==

核心函数:==kfree== 和 ==kalloc==

进程地址空间

系统调用:sbrk 和 exec

sbrk:为一个进程去减少或者增加它的内存(kernel/sysproc.c

exec:创建一个地址空间的用户部分

what is trampoline?

trampoline page存储了用户空间和内核空间相互切换的代码,无论是在内核空间还是在用户空间它都映射在相同的虚拟地址,这样在切换之后还可以继续工作。

相关文章:What is trampoline?

what is trapframe?

trapframe是存在于用户地址空间,位于trampoline下面的大小为PGSIZE(4096字节)的一块内存,用于在用户地址空间向内核地址空间切换时保存用户空间的寄存器。

1 Speed up system calls

任务描述:加速getpid()系统调用。方法是在trapframe前面映射一个只读的页,在这个页的开始,存储一个结构体syscall,结构体里存储当前进程的pid,然后通过已经提供的ugetpid()函数获得pid

思路:可以参考trapframe的构造。

1
2
3
4
5
6
// 步骤
// 1. 在proc结构体中增加一个usyscall字段
// 2. 在allocproc()函数为usyscall分配空间,并且将pid存储在usyscall中
// 3. 在proc_pagetable()函数中将p->usyscall(物理地址)映射到USYSCALL(虚拟地址)
// 4. 在freeproc()函数中将usyscall的空间释放
// 5. 在proc_freepagetable()函数中取消之前建立的映射

任务描述:如题要求打印页表。

思路:参考freewalk函数进行递归。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int level = 1;
void
vmprint(pagetable_t pagetable){
if(level > 3) return;

if(level == 1)
printf("page table %p\n", pagetable);

for(int i = 0; i < 512; i++){
pte_t pte = pagetable[i];
if(pte & PTE_V){
for(int j = 0; j < level; j++){
printf("..");
if(j != level - 1) printf(" ");
}
uint64 child = PTE2PA(pte);
printf("%d: pte %p pa %p\n", i, pte, child);
level++;
vmprint((pagetable_t)child);
level--;
}
}
}

3 Detecting which pages have been accessed

任务描述:检测页表是否被访问,实现pgaccess系统调用。

思路:通过walk函数找到虚拟地址对应的pte,检查PTE_A位即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// sysproc.c
int
sys_pgaccess(void){
uint64 base;
int len;
uint64 mask;
if(argaddr(0, &base) < 0 || argint(1, &len) < 0 || argaddr(2, &mask) < 0)
return -1;

uint64 start = PGROUNDDOWN(base);
uint64 bitmask = 0L;
for(int i = 0; i < len; i++, start += PGSIZE){
pte_t *pte = walk(myproc()->pagetable, start, 0);
if(pte == 0) return -1; // page not map
uint64 flag = (*pte & PTE_A) >> 6;
if(flag){
*pte ^= PTE_A; // clear the PTE_A
}
bitmask |= (flag << i);
}
if(copyout(myproc()->pagetable, mask, (char *)&bitmask, sizeof(uint64)) < 0)
return -1;
return 0;
}

:zap:访问页表时将PTE_A置1的工作由RISC-V硬件做了,在代码中不需要自己设置。


Lab3 Page Tables
http://example.com/2022/12/27/6.S081/6.S081-lab3-pgtbl/
作者
zhc
发布于
2022年12月27日
许可协议