Problems accessing physical memory from linux kernel
by masternick from LinuxQuestions.org on (#5DE2F)
Hi to all,
I'm writing a kernel module that needs access to a memory region outside the Kernel and User spaces. I know the physical address and the size of such a memory. I've tried with ioremap(), but the virtual address returned by such a function points to a phisical address different from the one I gave as an argument to ioremap(). Then I tried to use phys_to_virt() after ioremap(), this time the virtual address obtained points to the correct physical one, however when I try to access an element inside such memory area I get the following error: Unable to handle kernel paging request at virtual address ffffff801400000f What I'm wrong?
Code snippet:
Code:res = ioremap_nocache(MEMORY_ADDR, BUF_SIZE*ELEM_SIZE);
void *virt = phys_to_virt(MEMORY_ADDR);
printk(KERN_INFO "Physical address %d mapped in virtual address %d\n", virt_to_phys(virt), virt);
// DEBUG: print buffers content
char *flags = virt + BUF_SIZE*ELEM_SIZE;
for(i=0; i < hyp_ret.a3; i++){
printk(KERN_INFO "row %d [flag: %c]: %d\n", i, flags + i, virt + i*ELEM_SIZE);
}where: -MEMORY_ADDR: is the physical address -BUF_SIZE: number of elements in the buffer -ELEM_SIZE: size of the elements
The flags buffers is an array of chars at the end of such memory region
The full outputs returned are:
Code:Physical address 1409286144 mapped in virtual address 335544320
Unable to handle kernel paging request at virtual address ffffff801400000f
Mem abort info:
ESR = 0x96000006
EC = 0x25: DABT (current EL), IL = 32 bits
SET = 0, FnV = 0
EA = 0, S1PTW = 0
Data abort info:
ISV = 0, ISS = 0x00000006
CM = 0, WnR = 0
swapper pgtable: 4k pages, 39-bit VAs, pgdp=00000000407c8000
[ffffff801400000f] pgd=000000004fffb003, pud=000000004fffb003, pmd=0000000000000000
Internal error: Oops: 96000006 [#1] SMP
Modules linked in: source(O)
CPU: 1 PID: 107 Comm: ifconfig Tainted: G O 5.4.88 #1
Hardware name: linux,dummy-virt (DT)
pstate: 20000005 (nzCv daif -PAN -UAO)
pc : getFlag+0x24/0x40 [source]
lr : shmem_net_open+0x168/0x2c0 [source]
sp : ffffffc010b4b9d0
x29: ffffffc010b4b9d0 x28: 0000000000001043
x27: ffffff800e2b4c00 x26: ffffffc01077c000
x25: 0000000000000005 x24: ffffffc008661158
x23: 0000000000000004 x22: 0000000000000000
x21: ffffff800e24e200 x20: ffffff800e255000
x19: ffffff800e255858 x18: 0000000000020000
x17: 000000004a0b804e x16: 0000000031b76cb0
x15: ffffffc010859c40 x14: 0720072007200720
x13: 0720073007320733 x12: 0734073407350735
x11: 0733073307200773 x10: 0773076507720764
x9 : 076407610720076c x8 : 000000000000006f
x7 : 076907760720076e x6 : 0000000000000001
x5 : ffffff800e255840 x4 : 0000000000000005
x3 : 0000008040000000 x2 : 0000000000000000
x1 : 000000000000000f x0 : ffffff801400000f
Call trace:
getFlag+0x24/0x40 [source]
__dev_open+0xe4/0x160
__dev_change_flags+0x160/0x1c0
dev_change_flags+0x20/0x60
devinet_ioctl+0x63c/0x700
inet_ioctl+0x2f4/0x360
sock_do_ioctl+0x44/0x2b0
sock_ioctl+0x1c8/0x510
do_vfs_ioctl+0x984/0xb70
ksys_ioctl+0x44/0x90
__arm64_sys_ioctl+0x1c/0xc0
el0_svc_common.constprop.0+0x68/0x160
el0_svc_handler+0x6c/0x90
el0_svc+0x8/0x1fc
Code: 1b047c21 8b21c041 8b010000 cb030000 (39400000)
---[ end trace 5a219c0b95978c47 ]---
Segmentation fault


I'm writing a kernel module that needs access to a memory region outside the Kernel and User spaces. I know the physical address and the size of such a memory. I've tried with ioremap(), but the virtual address returned by such a function points to a phisical address different from the one I gave as an argument to ioremap(). Then I tried to use phys_to_virt() after ioremap(), this time the virtual address obtained points to the correct physical one, however when I try to access an element inside such memory area I get the following error: Unable to handle kernel paging request at virtual address ffffff801400000f What I'm wrong?
Code snippet:
Code:res = ioremap_nocache(MEMORY_ADDR, BUF_SIZE*ELEM_SIZE);
void *virt = phys_to_virt(MEMORY_ADDR);
printk(KERN_INFO "Physical address %d mapped in virtual address %d\n", virt_to_phys(virt), virt);
// DEBUG: print buffers content
char *flags = virt + BUF_SIZE*ELEM_SIZE;
for(i=0; i < hyp_ret.a3; i++){
printk(KERN_INFO "row %d [flag: %c]: %d\n", i, flags + i, virt + i*ELEM_SIZE);
}where: -MEMORY_ADDR: is the physical address -BUF_SIZE: number of elements in the buffer -ELEM_SIZE: size of the elements
The flags buffers is an array of chars at the end of such memory region
The full outputs returned are:
Code:Physical address 1409286144 mapped in virtual address 335544320
Unable to handle kernel paging request at virtual address ffffff801400000f
Mem abort info:
ESR = 0x96000006
EC = 0x25: DABT (current EL), IL = 32 bits
SET = 0, FnV = 0
EA = 0, S1PTW = 0
Data abort info:
ISV = 0, ISS = 0x00000006
CM = 0, WnR = 0
swapper pgtable: 4k pages, 39-bit VAs, pgdp=00000000407c8000
[ffffff801400000f] pgd=000000004fffb003, pud=000000004fffb003, pmd=0000000000000000
Internal error: Oops: 96000006 [#1] SMP
Modules linked in: source(O)
CPU: 1 PID: 107 Comm: ifconfig Tainted: G O 5.4.88 #1
Hardware name: linux,dummy-virt (DT)
pstate: 20000005 (nzCv daif -PAN -UAO)
pc : getFlag+0x24/0x40 [source]
lr : shmem_net_open+0x168/0x2c0 [source]
sp : ffffffc010b4b9d0
x29: ffffffc010b4b9d0 x28: 0000000000001043
x27: ffffff800e2b4c00 x26: ffffffc01077c000
x25: 0000000000000005 x24: ffffffc008661158
x23: 0000000000000004 x22: 0000000000000000
x21: ffffff800e24e200 x20: ffffff800e255000
x19: ffffff800e255858 x18: 0000000000020000
x17: 000000004a0b804e x16: 0000000031b76cb0
x15: ffffffc010859c40 x14: 0720072007200720
x13: 0720073007320733 x12: 0734073407350735
x11: 0733073307200773 x10: 0773076507720764
x9 : 076407610720076c x8 : 000000000000006f
x7 : 076907760720076e x6 : 0000000000000001
x5 : ffffff800e255840 x4 : 0000000000000005
x3 : 0000008040000000 x2 : 0000000000000000
x1 : 000000000000000f x0 : ffffff801400000f
Call trace:
getFlag+0x24/0x40 [source]
__dev_open+0xe4/0x160
__dev_change_flags+0x160/0x1c0
dev_change_flags+0x20/0x60
devinet_ioctl+0x63c/0x700
inet_ioctl+0x2f4/0x360
sock_do_ioctl+0x44/0x2b0
sock_ioctl+0x1c8/0x510
do_vfs_ioctl+0x984/0xb70
ksys_ioctl+0x44/0x90
__arm64_sys_ioctl+0x1c/0xc0
el0_svc_common.constprop.0+0x68/0x160
el0_svc_handler+0x6c/0x90
el0_svc+0x8/0x1fc
Code: 1b047c21 8b21c041 8b010000 cb030000 (39400000)
---[ end trace 5a219c0b95978c47 ]---
Segmentation fault