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.
_______________________________________________
Kernelnewbies mailing list
[email protected]
http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies