pte; spinlock_t *ptl; struct page *page; struct mm_struct *mm = vma->vm_mm; page = follow_huge_addr(mm, address, flags & FOLL_WRITE); if (!IS_ERR(page)) { BUG_ON(flags & FOLL_GET); goto out; }
高20 bits 用于物理寻址,低 12 bits 则是内存标志位,对于 linux 软件页表而言,高 20 bits 相同,而低 12 bits 用于 pte_dirty、pte_young 等标志位,这些标志位被定义在 arch/arm/include/asm/pgtable-2level.h 中: #define L_PTE_VALID (_AT(pteval_t, 1) << 0)/* Valid */#define L_PTE_PRES...
#definepte_accessible(mm,pte)(mm_tlb_flush_pending(mm)?pte_present(pte):pte_valid(pte)) #definepte_write(pte)(pte_isclear((pte),L_PTE_RDONLY))//pte是否可写 #definepte_dirty(pte)(pte_isset((pte),L_PTE_DIRTY))//pte是否有脏数据 #definepte_young(pte)(pte_isset((pte),L_PTE_YOU...
实际上,Linux 内核的 LRU 在算法成本上可能极高,一个简单的事实是,现代 CPU 通常会在页表 Page Table Entry(PTE)中含有一个 reference bit,如果硬件访问过这一页,这个 bit 会被硬件自动设置,这个 PTE 对应的 page 会被内核识别为 young(青春年少)。在 LRU 算法的 active、inactive 变迁,以及页面回收时,我们...
.prot_pte= L_PTE_PRESENT | L_PTE_YOUNG |L_PTE_DIRTY,---注意这里都是L_PTE_*类型,需要在写入MMU对应PTE时进行转换。.prot_l1=PMD_TYPE_TABLE, .prot_sect= PMD_TYPE_SECT |PMD_SECT_AP_WRITE, .domain=DOMAIN_KERNEL, }, [MT_MEMORY_RW]={ .prot...
简单来说,我们既然通过反向映射好不容易找到了那个进程的 PTE,那么访问这个 PTE 周围的 PTE 是比较快的,我们就一起看,看完发现这个周围的 PTE 是 young 的,则升级它们到 max_seq。简单来说,你在武汉,你大伯父在上海,你坐高铁去上海看你大伯父。但是你二伯父正好也是在上海,你肯定把你二伯父也一起看一看。
核心思想是利用反响映射系统来统计访问引用pte的用户个数。 page_referenced()主要工作如下: 利用RMAP系统遍历所有映射该页面的pte。 对每个pte,如果L_PTE_YOUNG比特位置位,说明之前被访问过,referenced计数加1;然后清空L_PTE_YOUNG。对ARM32来说,会清空硬件页表项内容,人为制造一个缺页中断,当再次访问该pte时,在缺...
if (pte_young(*ptep)) ret = test_and_clear_bit(_PAGE_BIT_ACCESSED, (unsigned long *) &ptep->pte);//检查页表项的年轻标志,使用 pte_young 函数检查页表项是否被标记为“年轻”。如果是,调用 test_and_clear_bit 函数清除访问标志,并将结果存储在 ret 中。
根据这个思路,二级页表中的一个 PTE 本质上指向的还是一个物理内存页,只不过这个物理内存页比较特殊,它是一张页表(一级页表),一级页表是用来映射真正的物理内存的,一张一级页表可以映射 4M 物理内存。 这也就是说二级页表中的一个 PTE 就可以映射 4M 物理内存,同样的道理,二级页表中也包含了 1024 个 PTE,所...
实际上,Linux 内核的 LRU 在算法成本上可能极高,一个简单的事实是,现代 CPU 通常会在页表 Page Table Entry(PTE)中含有一个 reference bit,如果硬件访问过这一页,这个 bit 会被硬件自动设置,这个 PTE 对应的 page 会被内核识别为 young(青春年少)。在 LRU 算法的 active、inactive 变迁,以及页面回收时,我们...