lab2_练习2/3

 

物理地址分布
page_{0}page_{1}...   page_{I - 1}page_{i}...page_{npage - 1}        

^

0x00000

 

        ^

start of ucore

(0x100000)

   ^

end of ucore

 

首地址为pages的npage个struc Page用于管理page    

    ^

maxpa

 

extern char end[]: 虚拟地址,指向ucore在内存的末尾,定义在ld链接文件中

pages:由end[]计算得出,也是虚拟地址,用于管理page的struct Page数组的头指针

alloc_page:申请一个page,返回的struct Page* 是虚拟地址

page2pa:根据struct Page* 相对头指针pages的偏移计算对应的page的起始物理地址

memset:需要使用虚拟地址进行操作

页目录表项和页表项保存的是物理地址,注意物理地址和虚拟地址的转换

static inline ppn_t
page2ppn(struct Page *page) {
    return page - pages;
}

static inline uintptr_t
page2pa(struct Page *page) {
    return page2ppn(page) << PGSHIFT;
}

 

pte_t *
get_pte(pde_t *pgdir, uintptr_t la, bool create) {
    /* LAB2 EXERCISE 2: YOUR CODE
     *
     * If you need to visit a physical address, please use KADDR()
     * please read pmm.h for useful macros
     *
     * Maybe you want help comment, BELOW comments can help you finish the code
     *
     * Some Useful MACROs and DEFINEs, you can use them in below implementation.
     * MACROs or Functions:
     *   PDX(la) = the index of page directory entry of VIRTUAL ADDRESS la.
     *   KADDR(pa) : takes a physical address and returns the corresponding kernel virtual address.
     *   set_page_ref(page,1) : means the page be referenced by one time
     *   page2pa(page): get the physical address of memory which this (struct Page *) page  manages
     *   struct Page * alloc_page() : allocation a page
     *   memset(void *s, char c, size_t n) : sets the first n bytes of the memory area pointed by s
     *                                       to the specified value c.
     * DEFINEs:
     *   PTE_P           0x001                   // page table/directory entry flags bit : Present
     *   PTE_W           0x002                   // page table/directory entry flags bit : Writeable
     *   PTE_U           0x004                   // page table/directory entry flags bit : User can access
     */
    pde_t *pdep = NULL;   // (1) find page directory entry
    pdep = pgdir + PDX(la);
    struct Page* pt = NULL;
    pte_t *ptep = NULL;    // virtual

    if (((*pdep) & PTE_P) == 0) {              // (2) check if entry is not present
        if (create && (pt = alloc_page()))      //allocate a page as page table, return pt that manages the mem
        {
 
            set_page_ref(pt, 1);

            ptep = page2pa(pt);  // ptep points to the mem of page table(physical addr)
            memset(KADDR(ptep), 0, PGSIZE);     // using va in program
            
            *pdep = (uintptr_t)ptep | PTE_P | PTE_W | PTE_U;   // using physical addr in pd/pt
           

        }
        else
            return NULL;
    } 
    else
    {
        ptep = PDE_ADDR(*pdep); 
    }


    return (pte_t *)KADDR(ptep) + PTX(la);
}


static inline void
page_remove_pte(pde_t *pgdir, uintptr_t la, pte_t *ptep) {
    pde_t *pdep = pgdir + PDX(la);    //获得页目录项
    if ((*pdep) & PTE_P == 0)    //判断是否在内存
        return;

    ptep = (pte_t*)PDE_ADDR(*pdep) + PTX(la);   //获得对应页表项物理地址(页目录保存物理地址)
    ptep = KADDR(ptep);    //转虚拟地址 程序中只能使用虚拟地址
    if ((*ptep) & PTE_P == 0)    //判断页是否在内存
        return;
    struct Page* page = pa2page(PTE_ADDR(*ptep));    //获得页的物理地址 通过pa2page获得struct Page的虚拟地址
    page_ref_dec(page);    //减引用数



    if (page->ref == 0)
    {
        free_page(page);    //释放页
        *ptep = 0;
        tlb_invalidate(pgdir, la);
    }
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值