Re: copy_from_user user space address mapping in the kernel page table.
On Mon, Nov 3, 2014 at 6:45 AM, wrote: > On Sun, 02 Nov 2014 19:57:44 +0530, mind entropy said: >> In the copy_from_user when the user passes the virtual address is >> the address mapped in the kernel page tables? > > Actually, a large part of the reason for copy_from_user()'s existence is > to deal with the possibility that the page is *not* mapped at the moment > because it's been swapped out (at which point we need to schedule a read > operation for whatever backing store the page had (filesystem, swap, or > zero-page for a never-before-referenced page), wait for it to arrive, > and then nail it down so it doesn't leave out from under us before > we finish the copy from the page. Got this part. Now the mapping will be done in the kernel page table,correct? i.e. in the swapper_pg_dir and this would be what the MMU will use to walk, correct? In short when the memcpy is being done the page table will be the kernel pgd right? > > And of course, it's even *more* fun when the copy crosses a page boundary, > and one or both of the pages isn't resident > >>In the function there is >> a source is a user virtual address(<3GB) and the destination is the > > Only for 32-bit kernels. x86_64 has a different memory layout. ___ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
copy_from_user user space address mapping in the kernel page table.
Hi, In the copy_from_user when the user passes the virtual address is the address mapped in the kernel page tables? In the function there is a source is a user virtual address(<3GB) and the destination is the kernel virtual address(3GB - 4GB) and for the MMU to access the physical page frame when in kernel space operating in behalf of the process context there should be a mapping of the virtual address to the page frame, correct? I am assuming the implementation would be to take the virtual address and walk the page table to get to the physical page frame and map the physical page frame in the kernel page table (i.e. swapper_pgd). Is this correct? If not what would be the mechanism? Thanks, Gautam. ___ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
On spin_lock_irq_save and disabling specific interrupts.
Hi, When I do spin_lock_irq it disables IRQ's which were enabled. What is the reason for disabling all the irq's rather than disabling the specific IRQ line which shares the resource? Wouldn't this be more efficient and would not lose any interrupts especially if I have a critical sensor ADC? Thanks, Gautam. ___ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
Re: On Page table walk.
On Wed, Oct 1, 2014 at 7:17 PM, mind entropy wrote: >> -- >> >> Message: 5 >> Date: Mon, 29 Sep 2014 23:05:44 +0530 >> From: mind entropy >> Subject: On Page table walk. >> To: kernelnewbies >> Message-ID: >> >> 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 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"); >> } >
Re: On Page table walk.
> -- > > Message: 5 > Date: Mon, 29 Sep 2014 23:05:44 +0530 > From: mind entropy > Subject: On Page table walk. > To: kernelnewbies > Message-ID: > > 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 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< addr_res & ((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.
On Page table walk.
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 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
Re: On virt_to_phys doubts.
Thanks. It set a byte in RAM and checked it using md.b in u-boot. -Gautam. On Sat, Sep 13, 2014 at 10:20 PM, Miles MH Chen wrote: > ok, now we can say the virt_to_phys returns a correct physical address. > 0x32d01fe0. It is a physical address, not a simple offset in dram. Your 64Mb > dram has physical address within 0x3000 ~ 0x3400. > > MH > > 2014/9/13 下午9:52 於 "mind entropy" 寫道: > >> On Sat, Sep 13, 2014 at 7:13 PM, Miles MH Chen >> wrote: >> > Kernel physical addr : 0x32d01fe0 >> > Platform phys offset : 0x3000 >> > Page offset : 0xc0553fb4 >> > >> > The page offset looks weird, since 32bit kernel has 2/2 or 3/1 or 1/3 >> > user/kernel virtual address split. It is not reasonable to have >> > 0xc0553fb4 >> > as page offset. You should c000 for 3/1 split. >> > >> >> My fault. I had done "0x%llx" in printk. Now I just did a %x and it >> shows as 0xc000. >> >> -Gautam. ___ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
Re: On virt_to_phys doubts.
On Sat, Sep 13, 2014 at 7:13 PM, Miles MH Chen wrote: > Kernel physical addr : 0x32d01fe0 > Platform phys offset : 0x3000 > Page offset : 0xc0553fb4 > > The page offset looks weird, since 32bit kernel has 2/2 or 3/1 or 1/3 > user/kernel virtual address split. It is not reasonable to have 0xc0553fb4 > as page offset. You should c000 for 3/1 split. > My fault. I had done "0x%llx" in printk. Now I just did a %x and it shows as 0xc000. -Gautam. ___ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
Re: On virt_to_phys doubts.
On Sat, Sep 13, 2014 at 2:01 PM, Miles MH Chen wrote: > Hi, > > Do you know the value of PHYS_OFFSET of your platform? > PHYS_OFFSET defines the starting physical address of your DRAM. > > physical address = kmalloc'ed address - PAGE_OFFSET + PHYS_OFFSET > > MH > > On Sat, Sep 13, 2014 at 4:02 PM, mind entropy wrote: >> >> Hi, >> >> I want to know the physical address [just for debugging and info.Not >> for DMA etc] of a particular virtual address allocated via kmalloc. >> >>I am running the below code on S3C2440 with 64MB of RAM. The >> /proc/meminfo returns >> >> MemTotal: 59164 kB >> MemFree: 35884 kB >> MemAvailable: 47148 kB >> >> >> I run the following module for printing the addresses. [This module >> is only for test. So excuse if I have cut corners]. >> >> >> >> #include >> #include >> #include >> #include >> #include >> #include >> #include >> #include >> #include >> >> static int vm_mem_test_init(void) >> { >> >> void *km; >> >> printk(KERN_ALERT "vm mem test init\n"); >> >> km = kmalloc(1,GFP_KERNEL); >> >> if(km == NULL) { >> printk(KERN_ALERT "Could not kmalloc\n"); >> return -1; >> } else { >> printk(KERN_ALERT "Allocated\n"); >> printk(KERN_ALERT "Virtual addr : %x\n",(unsigned int)km); >> printk(KERN_ALERT "Kernel physical addr : >> 0x%x\n",virt_to_phys(km)); >> kfree(km); >> } >> >> return 0; >> >> } >> >> >> The output for the following is: >> >> Virtual addr : c2c080e0 >> Kernel physical addr : 0x32c080e0 >> >> --- >> >> The kernel physical address is wrong as I only have 64MB. Should I be >> doing a kernel page table walk to get the associated physical address? >> >> Thanks >> Gautam. >> >> ___ >> Kernelnewbies mailing list >> Kernelnewbies@kernelnewbies.org >> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies > > Miles, I tried printing it. The output is as follows: Kernel physical addr : 0x32d01fe0 Platform phys offset : 0x3000 Page offset : 0xc0553fb4 The S3C2440 is an ARM9TDMI processor. -Gautam. ___ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
On virt_to_phys doubts.
Hi, I want to know the physical address [just for debugging and info.Not for DMA etc] of a particular virtual address allocated via kmalloc. I am running the below code on S3C2440 with 64MB of RAM. The /proc/meminfo returns MemTotal: 59164 kB MemFree: 35884 kB MemAvailable: 47148 kB I run the following module for printing the addresses. [This module is only for test. So excuse if I have cut corners]. #include #include #include #include #include #include #include #include #include static int vm_mem_test_init(void) { void *km; printk(KERN_ALERT "vm mem test init\n"); km = kmalloc(1,GFP_KERNEL); if(km == NULL) { printk(KERN_ALERT "Could not kmalloc\n"); return -1; } else { printk(KERN_ALERT "Allocated\n"); printk(KERN_ALERT "Virtual addr : %x\n",(unsigned int)km); printk(KERN_ALERT "Kernel physical addr : 0x%x\n",virt_to_phys(km)); kfree(km); } return 0; } The output for the following is: Virtual addr : c2c080e0 Kernel physical addr : 0x32c080e0 --- The kernel physical address is wrong as I only have 64MB. Should I be doing a kernel page table walk to get the associated physical address? Thanks Gautam. ___ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
On platform device template.
Hi, I am testing out the platform driver and would like to know the template for platform device register/unregister. The following code causes a crash whenever the device gets unregistered. --- #include #include #include #include #include #include struct test_platform_data { int x; int y; }; static struct test_platform_data test_pd = { .x = 2, .y = 3, }; static struct platform_device test_platform_device = { .name = "test-plat", .id = -1, .resource = NULL, .num_resources = 0, .dev = { .platform_data = &test_pd, } }; static int __init platform_driver_test_init(void) { int retval = 0; printk(KERN_ALERT "Platform driver init\n"); retval = platform_device_register(&test_platform_device); if(retval != 0) { printk(KERN_ALERT "Could not register platform device\n"); return retval; } else { printk(KERN_ALERT "Registered platform device\n"); printk(KERN_ALERT "Unregistering\n"); platform_device_unregister(&test_platform_device); } return 0; } static void __exit platform_driver_test_exit(void) { printk(KERN_ALERT "Platform driver exit\n"); } module_init(platform_driver_test_init); module_exit(platform_driver_test_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("TEST"); MODULE_DESCRIPTION("Platform driver test"); --- Should the platform device be created using platform_device_alloc(..) and added using platform_device_add(..) like the below code? #include #include #include #include #include #include struct test_platform_data { int x; int y; }; static struct test_platform_data test_pd = { .x = 2, .y = 3, }; static struct platform_device *test_platform_device; static int __init platform_driver_test_init(void) { int retval = 0; printk(KERN_ALERT "Platform driver init\n"); test_platform_device = platform_device_alloc("test-plat",-1); if(test_platform_device == NULL) { printk(KERN_ALERT "Could not allocate platform device\n"); return 0; } platform_device_add_data(test_platform_device,&test_pd,sizeof(test_pd)); retval = platform_device_add(test_platform_device); if(retval != 0) { printk(KERN_ALERT "Could not register platform device\n"); return retval; } else { printk(KERN_ALERT "Registered platform device\n"); printk(KERN_ALERT "Unregistering\n"); platform_device_unregister(test_platform_device); } return 0; } static void __exit platform_driver_test_exit(void) { printk(KERN_ALERT "Platform driver exit\n"); } module_init(platform_driver_test_init); module_exit(platform_driver_test_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("TEST"); MODULE_DESCRIPTION("Platform driver test"); Thanks, Gautam. ___ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
On SPI stress testing on a mini2440 board.
Hi, I have a mini2440 board to which I have connected a TI MSP430 G2553 microcontroller. I am communicating via SPI from the mini2440 master to the MSP430 microcontroller slave. I am having a problem though. I have to put a chip select delay and hence I am waiting for 500 uS using udelay. Sometimes the data seems to skip or cause glitches when the load is high I think. I had connected 2 microcontrollers and it works fine when I stress test it. In case of the mini2440 board after quite some hours of continuous transfers I get glitches. Is udelay consistent? Thanks, Gautam. ___ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies