On Page table walk.

mind entropy mindentropy at gmail.com
Wed Oct 1 09:47:16 EDT 2014


> ------------------------------
>
> Message: 5
> Date: Mon, 29 Sep 2014 23:05:44 +0530
> From: mind entropy <mindentropy at gmail.com>
> Subject: On Page table walk.
> To: kernelnewbies <kernelnewbies at kernelnewbies.org>
> Message-ID:
>         <CAM2a4uyLDgFztL+xpos3GG76K3i71vp+63PpZKyVErrVUPU8XA at mail.gmail.com>
> Content-Type: text/plain; charset=UTF-8
>
> Hi,
>
>   I am experimenting with page table walking. I run a user space
> program and set the device attribute (of my sample device driver) in
> the sysfs. (DEVICE_ATTR) which is the address of the variable in the
> user space. I get the current->mm to get the current task memory
> descriptor and use it to walk the pages. Once I get the pte address I
> reboot and dump the memory at that point using u-boot. (md.b <addr> 1)
> but I do not find the value present there.
>
> Sample code: (This is just for illustration and experimenting and does
> not contain error checks etc.).
>
> --------------------------------------------------------------------------------------------
> ssize_t process_mem_test_attr_store(struct device *dev,
>                         struct device_attribute *attr,
>                         const char *buf,
>                         size_t count)
> {
>
>     struct task_struct *current_task;
>     unsigned long addr_res;
>     struct vm_area_struct *vmarea_struct_addr;
>     pgd_t *pgd;
>     pmd_t *pmd;
>     pud_t *pud;
>     pte_t *ptep, pte;
>     struct page *page;
>     int kval;
>     int uval;
>
>     DEFINE_SPINLOCK(test_lock);
>
>     spin_lock_irq(&test_lock);
>
>     current_task = current;
>
>     if(current_task != NULL) {
>
>         printk(KERN_ALERT "\nCurrent task pid: %d\n",
>                                 current_task->pid);
>
>         printk(KERN_ALERT "mm: 0x%lx, active_mm 0x%lx\n",
>                         current_task->mm,current_task->active_mm);
>         printk(KERN_ALERT "Page global directory : 0x%lx\n",
>                             current_task->mm->pgd);
>         printk(KERN_ALERT "mmap base : 0x%lx",
>                             current_task->mm->mmap_base);
>
>         vmarea_struct_addr = current_task->mm->mmap;
>
>         while(vmarea_struct_addr != NULL) {
>             printk(KERN_ALERT "vm_start : 0x%lx, vm_end : 0x%lx\n",
>                             vmarea_struct_addr->vm_start,
>                             vmarea_struct_addr->vm_end);
>
>             vmarea_struct_addr = vmarea_struct_addr->vm_next;
>         }
>
>
>     } else {
>         printk(KERN_ALERT "Current task NULL\n");
>     }
>
>     if(kstrtol(buf,10,&addr_res) != 0) {
>         printk(KERN_ALERT "Error converting to long\n");
>         return count;
>     }
>
>     copy_from_user(&kval,(unsigned int *)addr_res,4);
>
>     printk(KERN_ALERT "kval : %x\n",kval);
>     printk(KERN_ALERT "addr: %lx\n",addr_res);
>
>     pgd = pgd_offset(current_task->mm,addr_res);
>
>     if(pgd_none(*pgd) || pgd_bad(*pgd)) {
>         printk(KERN_ALERT "pgd bad\n");
>         return count;
>     } else {
>         printk(KERN_ALERT "pgd 0x%lx\n",pgd);
>     }
>
>     pud = pud_offset(pgd,addr_res);
>
>     if(pud_none(*pud) || pud_bad(*pud)) {
>         printk(KERN_ALERT "pud bad\n");
>         return count;
>     } else {
>         printk(KERN_ALERT "pud 0x%lx\n",pud);
>     }
>
>     pmd = pmd_offset(pud,addr_res);
>
>     if(pmd_none(*pmd) || pmd_bad(*pmd)) {
>         printk(KERN_ALERT "pmd bad\n");
>         return count;
>     } else {
>         printk(KERN_ALERT "pmd 0x%lx\n",pmd);
>     }
>
>
>     ptep = pte_offset_map(pmd,addr_res);
>     if(!ptep) {
>         printk(KERN_ALERT "ptep bad\n");
>     } else {
>         printk(KERN_ALERT "ptep 0x%lx\n",ptep);
>     }
>
>     pte = *ptep;
>
>
>     if(pte_present(pte)) {
>         printk(KERN_ALERT "pte : 0x%lx\n",pte);
>         page = pte_page(pte);
>
>     } else {
>         printk(KERN_ALERT "pte not present\n");
>     }
>
>     printk(KERN_ALERT "pte with offset 0x%lx offset : 0x%lx\n",
>             pte+((addr_res) & ((1<<PAGE_SHIFT)-1)),
>             addr_res & ((1<<PAGE_SHIFT)-1));
>
>
>     while(1)
>         ;
>
>     printk(KERN_ALERT "After lock\n"); //Should not print this.
>
>
>     return count;
> }
> --------------------------------------------------------------------------------------------
>
> I use a spinlock to prevent the process from getting swapped. I
> disable the irq and make it spin on while(1); after which I reboot.
> After doing a memoy dump I find the value in the address but at an
> offset from pte value printed. What seems to be wrong with my
> approach?
>
> Thanks in advance.
>
>
>
> ------------------------------


Hope somebody can give me some clue. My PHYS_OFFSET starts at 0x30000000.

A sample output in the dmesg is as follows:

------------------------------


Sample session:

[   92.086535] Current task pid: 2382
[   92.086632] mm: 0xc2d79480, active_mm 0xc2d79480
[   92.090522] Page global directory : 0xc2cb4000
[   92.094783] mmap base : 0xb6fe0000
[   92.097896] vm_start : 0x8000, vm_end : 0x9000
[   92.102454] vm_start : 0x10000, vm_end : 0x11000
[   92.106942] vm_start : 0xb6e7c000, vm_end : 0xb6fa5000
[   92.111983] vm_start : 0xb6fa5000, vm_end : 0xb6fac000
[   92.116995] vm_start : 0xb6fac000, vm_end : 0xb6fae000
[   92.122054] vm_start : 0xb6fae000, vm_end : 0xb6faf000
[   92.127062] vm_start : 0xb6faf000, vm_end : 0xb6fb2000
[   92.132121] vm_start : 0xb6fba000, vm_end : 0xb6fd7000
[   92.137177] vm_start : 0xb6fda000, vm_end : 0xb6fdd000
[   92.142223] vm_start : 0xb6fdd000, vm_end : 0xb6fde000
[   92.147203] vm_start : 0xb6fde000, vm_end : 0xb6fdf000
[   92.152275] vm_start : 0xb6fdf000, vm_end : 0xb6fe0000
[   92.157291] vm_start : 0xbe852000, vm_end : 0xbe874000
[   92.162345] kval : 1234
[   92.164670] addr: 10830
[   92.167145] pgd 0xc2cb4000
[   92.169705] pud 0xc2cb4000
[   92.172407] pmd 0xc2cb4000
[   92.174995] ptep 0xc3b78040
[   92.177774] pte : 0x326dc14f
[   92.180545] pte with offset 0x326dc97f offset : 0x830



More information about the Kernelnewbies mailing list