HUST-OS / xv6-k210

Port XV6 to K210 board!
MIT License
131 stars 56 forks source link

关于proc页表的合并 #32

Closed ckf104 closed 3 years ago

ckf104 commented 3 years ago

既然proc的kpagetable既有用户地址空间和内核地址空间,这样显得pagetable就多余了,在限制用户地址空间小于0x80000000的前提下,删除pagetable也能正常工作?这样每个进程的pagetable的0,1项对应用户地址空间的映射,后面的项对应内核空间的映射。只保留一个页表的话可以简化vm.c的代码?

SKTT1Ryze commented 3 years ago

建议给具体代码,更加详细地描述一下,方便项目维护者理解

ckf104 commented 3 years ago

具体来说,可以删除proc结构体的kpagetable成员。然后这样实现proc_pagetable函数,该函数为进程初始化页表

int
Proc::proc_pagetable(){
    pagetable = (pagetable_t)kalloc(); // 申请页表
       if(pagetable == 0)
            return 0;

    kstack = (uint64)kalloc(); // 申请内核栈
    if(kstack == 0){
        kfree(pagetable);
        return 0;
    }
        memmove(pagetable, kernel_pagetable, PGSIZE); //现在有了映射到内核的页表项
    for(uint i=0; i < PX(2, MAXUVA); ++i){
        pagetable[i] = 0;
    }

    trapframe = (Trapframe*)kalloc();  // 申请trapframe页
    if(trapframe == 0){
        kfree(pagetable);
        kfree((void*)kstack);
        return 0;
    }
    return 1;
}

pagetable的前两项用于用户空间的映射,对应地址空间为0x0 -> 0x80000000 限制了地址空间后,省去了为每个用户进程建立trapframe和kstack的页表映射的麻烦。proc->kstack,proc->trapframe分别记录内核栈和trapframe页的物理地址,usertrapret返回时不再使用虚地址TRAMFRAME,而直接使用物理地址p->trapframe。 以后为用户空间建立地址映射时,就不需要分别为pagetable,kpagetable建立映射了,只给pagetable建立地址映射即可。

retrhelo commented 3 years ago

pagetable的前两项用于用户空间的映射,对应地址空间为0x0 -> 0x80000000 限制了地址空间后,省去了为每个用户进程建立trapframe和kstack的页表映射的麻烦。proc->kstack,proc->trapframe分别记录内核栈和trapframe页的物理地址,usertrapret返回时不再使用虚地址TRAMFRAME,而直接使用物理地址p->trapframe。

我认为使用虚地址去访问trampoline仍然是必要的,总是将trampoline放在某一特定的地址(在xv6-k210 中是虚拟地址的最高处)可以简化代码的编写,而且对于每个用户进程来说使用不同虚拟地址的trampoline似乎 也不是很有必要。

以后为用户空间建立地址映射时,就不需要分别为pagetable,kpagetable建立映射了,只给pagetable建立地址映射即可。

对的,是可以这样处理的。但前提必须是用户程序可信。如果要在用户态与内核态使用同一页表,那么就必须 要考虑如何禁止用户态程序访问内核态的地址空间————显然我们不希望用户态程序能够轻而易举地访问到内核 的地址空间并搞崩内核。RISC-V的分页机制里似乎有一些机制可以限制U态代码对内存空间的访问,但具体的实现 我也不是很清楚。

SKTT1Ryze commented 3 years ago

它这样的做法也是能保证禁止用户访问内核态的地址空间的,U 特权级只能访问有 U 权限的页表