For some reason my mmap failed with an Invalid argument message even though my offset is page aligned. Page size is 4096 bytes. Also CONFIG_S
nopat kernel command line argument
Just add that and it works, as mentioned at: https://stackoverflow.com/a/36634422/895245
Here is my test setup:
kernel module:
#include /* virt_to_phys */
#include
#include /* usleep_range */
#include
#include
#include
#include /* single_open, single_release */
#include /* kmalloc, kfree */
static volatile u32 *i;
static struct dentry *debugfs_file;
static int show(struct seq_file *m, void *v)
{
seq_printf(m,
"*i 0x%llx\n"
"i %p\n"
"virt_to_phys 0x%llx\n",
(unsigned long long)*i,
i,
(unsigned long long)virt_to_phys((void *)i)
);
return 0;
}
static int open(struct inode *inode, struct file *file)
{
return single_open(file, show, NULL);
}
static const struct file_operations fops = {
.llseek = seq_lseek,
.open = open,
.owner = THIS_MODULE,
.read = seq_read,
.release = single_release,
};
static int myinit(void)
{
i = kmalloc(sizeof(i), GFP_KERNEL);
*i = 0x12345678;
debugfs_file = debugfs_create_file(
"lkmc_virt_to_phys", S_IRUSR, NULL, NULL, &fops);
return 0;
}
static void myexit(void)
{
debugfs_remove(debugfs_file);
kfree((void *)i);
}
module_init(myinit)
module_exit(myexit)
MODULE_LICENSE("GPL");
/dev/mem userland:
#!/bin/sh
set -ex
insmod /virt_to_phys.ko
cd /sys/kernel/debug
cat lkmc_virt_to_phys
# *i = 0x12345678
addr=$(grep virt_to_phys lkmc_virt_to_phys | cut -d ' ' -f 2)
devmem2 "$addr"
devmem2 "$addr" w 0x9ABCDEF0
cat lkmc_virt_to_phys
# *i = 0x9ABCDEF0
rmmod virt_to_phys
nopat being passed at: https://github.com/cirosantilli/linux-kernel-module-cheat/blob/2eca9280e12dbab79ccb67d0640b2a0edc2c9ffc/runqemu#L65
Also try xp on QEMU monitor.
And devmem2 is upstreamed by Buildroot itself: http://free-electrons.com/pub/mirror/devmem2.c See also: Accessing physical address from user space