How can I convert user virtual address to kernel virtual address and then to physical address?

Raghuram Jallipalli raghuram.jallipalli99 at gmail.com
Sun Jul 25 23:25:16 EDT 2021


Pls see if this helps

https://linux-kernel-labs.github.io/refs/heads/master/labs/memory_mapping.html

-Raghu

On Sun, Jul 25, 2021, 10:16 PM <ckim at etri.re.kr> wrote:

> Hi, all,
>
>
>
> I’m testing a simple character driver on qemu arm64 virtual machine.
>
> I have uint64_t args[32] array and I pass args to the ioctl data.
>
> By the way args[2] contains the address of test_val which is set to 77. I
> want to change this value to 78 in the driver using kernel virtual address.
>
> (ultimately I want to get the physical address of test_val and pass it to
> the qemu hardware model).
>
> I read I can change user virtual address to kernel land virtual address
> using get_user_pages function and then I can use virt_to_phys function to
> get the physical address from kernel land virtual address.
>
> (please correct me if I’m wrong)
>
> When I try to write 78 at the kernel virtual address for test_val, trap
> occurs.
>
>
>
> ## app.c ##
>
>     uint64_t __attribute__(( aligned(64) )) args[32];
>
>     uint64_t test_val = 77;
>
>     args[2] = (uint64_t) &test_val; // let's see it's changed to 78
>
>     printf("app : args[2] = %p, *args[2] = %lld\n", args[2], *(uint64_t
> *)args[2]);
>
>     ioctl(fd, CallSetBareMetalMode, (uint64_t)args);
>
>
>
> ### driver.c ###
>
>
>
>     static long my_ioctl(struct file *file, unsigned int cmd, unsigned
> long arg)
>
>     {
>
>         switch(cmd) {
>
>         case CallSetBareMetalMode:
>
>             printk("driver:cmd = %x, arg = %lx\n", cmd, arg);
>
>             copy_from_user(&args, (void __user *)arg, 8*3);
>
>             printk("args[2] = %llx\n", args[2]);
>
>             offs = args[2] % 4096;
>
>
>
>             down_read(&current->mm->mmap_sem);
>
>             res = get_user_pages( (unsigned long)args[2], 1, 1, &pages,
> NULL);
>
>             printk("get_user_pages done! args[2] = %px\n", args[2]);
>
>
>
>             if (res) {
>
>                 printk(KERN_INFO "Got mmaped.\n");
>
>                 kvpaddr = kmap(pages);
>
>                 printk("kmap done!\n");
>
>                 printk(KERN_INFO "kvpaddr = %px, ofs = %x\n", kvpaddr,
> offs);
>
>                 printk("xx = %llx\n", ((unsigned long long
> int)(kvpaddr)+offs));
>
>                 *(uint64_t *)((unsigned long long int)(kvpaddr)+offs) = 78;
>
>                 printk(KERN_INFO "changed value : %lld\n",\
>
>                  *(uint64_t *)((unsigned int)(kvpaddr)+offs));
>
>                 put_page(pages); //page_cache_release(page);
>
>                 printk("put_page done!\n");
>
>             }
>
>             else {
>
>                 printk("get_user_pages failed!\n");
>
>             }
>
>             up_read(&current->mm->mmap_sem);
>
>
>
> ### run output ###
>
>
>
>     args = 0x442f40
>
>     app : args[0] = 0x443040
>
>     app : args[2] = 0xffffd2e44d98, *args[2] = 77
>
>     [85194.544029] driver:cmd = 40086142, arg = 442f40
>
>     [85194.544822] args[2] = ffffd2e44d98
>
>     [85194.545613] get_user_pages done! args[2] = 0000ffffd2e44d98
>
>     [85194.546004] Got mmaped.
>
>     [85194.546248] kmap done!
>
>     [85194.546536] kvpaddr = ffff00001f7c0000, ofs = d98
>
>     [85194.546976] kvaddr = ffff00001f7c0d98
>
>     [85194.548645] Unable to handle kernel paging request at virtual
> address 000000001f7c0d98
>
> [85194.549245] Mem abort info:
>
>     [85194.549513]   ESR = 0x96000006
>
>     [85194.549929]   EC = 0x25: DABT (current EL), IL = 32 bits
>
>     [85194.550364]   SET = 0, FnV = 0
>
>     [85194.550719]   EA = 0, S1PTW = 0
>
>     [85194.551008] Data abort info:
>
>     [85194.551555]   ISV = 0, ISS = 0x00000006
>
>     [85194.551938]   CM = 0, WnR = 0
>
>     [85194.552609] user pgtable: 4k pages, 48-bit VAs,
> pgdp=00000000568fb000
>
>     [85194.553441] [000000001f7c0d98] pgd=0000000056209003,
> pud=0000000047b97003, pmd=0000000000000000
>
>     [85194.555783] Internal error: Oops: 96000006 [#16] SMP
>
>     [85194.556761] Modules linked in: chr_drv_ex1(OE) nls_iso8859_1
> dm_multipath scsi_dh_rdac scsi_dh_emc scsi_dh_alua qemu_fw_cfg sch_fq_codel
> ppdev lp parport drm ip_tables x_tables autofs4 btrfs zstd_compress raid10
> raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx xor
> xor_neon raid6_pq libcrc32c raid1 raid0 multipath linear crct10dif_ce
> ghash_ce sm4_ce sm4_generic sm3_ce sm3_generic sha3_ce sha3_generic
> sha512_ce sha512_arm64 sha2_ce sha256_arm64 sha1_ce virtio_net net_failover
> virtio_blk failover aes_neon_bs aes_neon_blk aes_ce_blk crypto_simd cryptd
> aes_ce_cipher [last unloaded: chr_drv_ex1]
>
>     [85194.563741] CPU: 2 PID: 4258 Comm: test_axpu_app Tainted: G      D
> W  OE     5.4.0-77-generic #86-Ubuntu
>
>     [85194.564638] Hardware name: QEMU QEMU Ab21q Virtual Machine, BIOS
> 0.0.0 02/06/2015
>
>     [85194.565687] pstate: 60400005 (nZCv daif +PAN -UAO)
>
>     [85194.568143] pc : my_ioctl+0x310/0x370 [chr_drv_ex1]
>
>     [85194.568854] lr : my_ioctl+0x300/0x370 [chr_drv_ex1]
>
>     [85194.569473] sp : ffff80001372bd30
>
>     [85194.569838] x29: ffff80001372bd30 x28: ffff000009f7bc00
>
>     [85194.570354] x27: 0000000000000000 x26: 0000000000000000
>
>     [85194.570796] x25: 0000000056000000 x24: ffff00000d3c35e0
>
>     [85194.571308] x23: ffff000016875600 x22: 0000000000000d98
>
>     [85194.571870] x21: 000000001f7c0d98 x20: 0000000000442f40
>
>     [85194.572273] x19: ffff00001f7c0000 x18: 0000000000000010
>
>     [85194.572669] x17: 0000000000000000 x16: 0000000000000000
>
>     [85194.573126] x15: ffff000009f7c128 x14: ffffffffffffffff
>
>     [85194.573632] x13: ffff80009372ba77 x12: ffff80001372ba7f
>
>     [85194.574127] x11: ffff800011b9e000 x10: 0000000000000000
>
>     [85194.574578] x9 : ffff800011db4000 x8 : 00000000000005f2
>
>     [85194.575193] x7 : 0000000000000017 x6 : ffff800011db39d4
>
>     [85194.575700] x5 : 0000000000000000 x4 : ffff00001feb5250
>
>     [85194.576139] x3 : ffff00001fec56c8 x2 : 0000000000000000
>
>     [85194.576550] x1 : 0000000000000000 x0 : ffff80000924b220
>
>     [85194.577379] Call trace:
>
>     [85194.577805]  my_ioctl+0x310/0x370 [chr_drv_ex1]
>
>     [85194.579423]  do_vfs_ioctl+0xc64/0xe60
>
>     [85194.579846]  ksys_ioctl+0x88/0xb8
>
>     [85194.580116]  __arm64_sys_ioctl+0x2c/0x228
>
>     [85194.580479]  el0_svc_common.constprop.0+0xe4/0x1f0
>
>     [85194.580929]  el0_svc_handler+0x38/0xa8
>
>     [85194.581293]  el0_svc+0x10/0x2c8
>
>     [85194.582065] Code: d28009c0 f8336ac0 b0000000 91088000 (f94002a1)
>
>     [85194.583646] ---[ end trace bd1ac75ca265aec2 ]---
>
>     [85194.590696] Device File closed..
>
>     Segmentation fault (core dumped)
>
>
>
> I thought I changed the user virtual address to kernel virtual address,
> but writing to the kernel virtual address causes trap.
>
> Can anyone help me with finding what is wrong here?
>
> Thank you for reading.
>
>
>
> Chan Kim
>
>
> _______________________________________________
> Kernelnewbies mailing list
> Kernelnewbies at kernelnewbies.org
> https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20210725/f0b813f8/attachment.html>


More information about the Kernelnewbies mailing list