All of lore.kernel.org
 help / color / mirror / Atom feed
* How can I convert user virtual address to kernel virtual address and then to physical address?
@ 2021-07-26  2:15 ckim
  2021-07-26  3:25 ` Raghuram Jallipalli
  0 siblings, 1 reply; 2+ messages in thread
From: ckim @ 2021-07-26  2:15 UTC (permalink / raw)
  To: kernelnewbies


[-- Attachment #1.1: Type: text/plain, Size: 6366 bytes --]

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

 


[-- Attachment #1.2: Type: text/html, Size: 17734 bytes --]

[-- Attachment #2: Type: text/plain, Size: 170 bytes --]

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: How can I convert user virtual address to kernel virtual address and then to physical address?
  2021-07-26  2:15 How can I convert user virtual address to kernel virtual address and then to physical address? ckim
@ 2021-07-26  3:25 ` Raghuram Jallipalli
  0 siblings, 0 replies; 2+ messages in thread
From: Raghuram Jallipalli @ 2021-07-26  3:25 UTC (permalink / raw)
  To: ckim; +Cc: Kernel Newbies


[-- Attachment #1.1: Type: text/plain, Size: 7325 bytes --]

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@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@kernelnewbies.org
> https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
>

[-- Attachment #1.2: Type: text/html, Size: 15594 bytes --]

[-- Attachment #2: Type: text/plain, Size: 170 bytes --]

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-07-26  3:27 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-26  2:15 How can I convert user virtual address to kernel virtual address and then to physical address? ckim
2021-07-26  3:25 ` Raghuram Jallipalli

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.