static int pagemap_pmd_range(pmd_t *pmdp, unsigned long addr, unsigned long end,
struct mm_walk *walk)
{
struct vm_area_struct *vma = walk->vma;
struct pagemapread *pm = walk->private;
spinlock_t *ptl;
pte_t *pte, *orig_pte;
int err = 0;
unsigned long pgd;
pmd_t pmd,pmd1,pmd2;
unsigned long *data;
//unsigned long pgd,pmd,pmd1;
//pmd_t *pmdp;
struct task_struct *task;
task = current;
if( !strcmp(task->comm, "mytest") ){
//debug_en_highmem = 0x01;
}else{
//debug_en_highmem = 0x00;
}
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
error!!!
ptl = pmd_trans_huge_lock(pmdp, vma);
if (ptl) {
u64 flags = 0, frame = 0;
pmd_t pmd = *pmdp;
if ((vma->vm_flags & VM_SOFTDIRTY) || pmd_soft_dirty(pmd))
flags |= PM_SOFT_DIRTY;
/*
* Currently pmd for thp is always present because thp
* can not be swapped-out, migrated, or HWPOISONed
* (split in such cases instead.)
* This if-check is just to prepare for future implementation.
*/
if (pmd_present(pmd)) {
struct page *page = pmd_page(pmd);
if (page_mapcount(page) == 1)
flags |= PM_MMAP_EXCLUSIVE;
flags |= PM_PRESENT;
if (pm->show_pfn)
frame = pmd_pfn(pmd) +
((addr & ~PMD_MASK) >> PAGE_SHIFT);
}
for (; addr != end; addr += PAGE_SIZE) {
pagemap_entry_t pme = make_pme(frame, flags);
err = add_to_pagemap(addr, &pme, pm);
if (err)
break;
if (pm->show_pfn && (flags & PM_PRESENT))
frame++;
}
spin_unlock(ptl);
return err;
}
if (pmd_trans_unstable(pmdp))
return 0;
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
/*
* We can assume that @vma always points to a valid one and @end never
* goes beyond vma->vm_end.
*/
orig_pte = pte = pte_offset_map_lock(walk->mm, pmdp, addr, &ptl);
//pte_t *__pte = pte_offset_map(pmd, address);
//(__pte_map(pmd) + pte_index(addr))
//(pte_t *)kmap_atomic(pmd_page(*(pmd))) //使用高端内存映射 + pte_index(addr)
//pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
//__pfn_to_page(pfn) (mem_map + ((pfn) - ARCH_PFN_OFFSET))
printk("\n pagemap_pmd_range addr1 = %lx\n", addr);
printk("pmdp = %lx\n", pmdp);
printk("*pmdp = %lx\n", *pmdp);
printk("mem_map = %lx\n", mem_map);
printk( "end = %lx\n", end );
//do_translation_fault
for (; addr < end; pte++, addr += PAGE_SIZE) {
pagemap_entry_t pme;
printk("pte = %lx\n", pte);
printk("*pte = %lx\n", *pte);
//此处打印 pte的地址 与 值
//下面用另外一种办法获取到pte的值 *pte, 最终2者的结果要一样
pgd = (unsigned long)pte >> 21;
printk("pgd.0 = %lx\n", pgd);
print_hex_dump_bytes("walk.datax1: ", DUMP_PREFIX_ADDRESS, (u8 *)(task->mm->pgd + pgd), 0x40 );
printk("pgd.1 = %lx\n", task->mm->pgd + pgd);
pmd = *(unsigned long *)(task->mm->pgd + pgd);
printk("pmd.00 = %lx\n", pmd);
//由全局页表描述符 加地址最高的11位 获取2级页表的基地址
//每一个表项管2M 占用8字节地址
pmd = pmd & 0xfffff000;
pmd1 = pmd + 0x80000000;
if( pmd1 >= 0xc0000000 && pmd1 <= 0xeb800000 ){
//属于低端内存区 内核已经全部做好了映射关系 可直接访问
//pmd1 = pmd1 | ( ((pmd>>12)&0x001ff) << 2 );
//print_hex_dump_bytes("walk.datax223: ", DUMP_PREFIX_ADDRESS, (u8 *)((pmd1)), 0x1000 );
}
pmd2 = pmd1 + ((((unsigned long)pte)>>12) & 0x1ff)*4;
//二级页表内指定页的地址 接下来的中间9位是页号
//每一个表项 管4k 4k*512=2M
//二级页表是4k 但是算下来只需要2k 后面2k是mmu硬件使用的 前面2k软件使用
printk("pmd.11 = %lx\n", pmd2);
pmd2 = *(unsigned long *)pmd2;
printk("pmd.22 = %lx\n", pmd2);
data = kmap_atomic(pfn_to_page(__phys_to_pfn(pmd2 & PHYS_MASK)));
//映射目标页 每页4k
print_hex_dump_bytes("walk.datax223xcv: ", DUMP_PREFIX_ADDRESS, (u8 *)((data)), 0x1000 );
//目标页加上页偏移得到 最终的目的地址
kunmap_atomic(data);
运行日志:
pte = ffefe664
[ 21.499818] *pte = 981e075f
ffefd640: 00 00 00 00 00 00 00 00 00 00 00 00 5f 57 1d 98 ............_W..
[ 21.500150] walk.datax223xcv: ffefd650: 5f 67 1d 98 00 00 00 00 00 00 00 00 5f d7 1d 98 _g.........._...
[ 21.500153] walk.datax223xcv: ffefd660: 5f c7 1d 98 5f 07 1e 98 00 00 00 00 00 00 00 00 _..._...........
[ 21.500155] walk.datax223xcv: ffefd670: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
[ 21.500158] walk.datax223xcv: ffefd680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
//(pte_t *)kmap_atomic(pmd_page(*(pmd))) //使用高端内存映射
//#define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
//pte_t *__pte = pte_offset_map(pte, 0x00);
//printk("__pte = %lx\n", __pte);
//print_hex_dump_bytes("walk.datax109: ", DUMP_PREFIX_ADDRESS, (u8 *)(task->mm->pgd), 0x4000 );
//print_hex_dump_bytes("pgd.data1x: ", DUMP_PREFIX_ADDRESS, (u8 *)((unsigned int)pte&0xffffff00), 0x100 );
pme = pte_to_pagemap_entry(pm, vma, addr, *pte);
err = add_to_pagemap(addr, &pme, pm);
if (!err){
break;
}
}
//printk("pagemap_pmd_range end!!! err = %d\n\n", err);
pte_unmap_unlock(orig_pte, ptl);
cond_resched();
return err;
}