Mapping kmalloc memory to user space - c

I want to create a single kernel module driver for my application.
It interfaces with an AXIS FIFO in Programmable logic and I need to send the physical addresses of allocated memory to this device to be used in programmable logic.
My platform driver recognises the AXIS FIFO device, and using mmap makes its registers available to my user space app. (previous post of mine)
I also want to allocate memory to be used by the programmable logic, and do this by using and IOCTL command which calls a kmalloc with the given size as argument. Since I want to use the physical address - I get the physical address using __pa(x).
If I want to access this allocated memory to verify that the correct info was stored in RAM, how do I do this? Through
fd = open("/dev/mem", ...)
va = mmap (phys_address, ....)
The problem I have with this is that I can still wrongfully access parts of memory that I shouldn't. Is there a better way to do this?
Thanks.

I think the best way to do this is to create a /proc device file that maps to the allocated memory. Your kernel module kmalloc's the memory, creates the proc device, and services all the I/O calls to the device. Your userspace program reads and writes to this device, or possibly mmaps to it (if that will work, I'm not sure...).

Related

How to avoid copy_from_user and copy_to_user in linux device driver

I am writing a device driver which uses character device file to copy data from user space buffer which is allocated by using malloc to kernel buffer. Currently using copy_from_user api to copy user data to kernel buffer. Trying to find a way to avoid data copying between user and kernel spaces. Is there any way to access user space buffer (allocated by malloc) in kernel space without using copy_from_user?
Let's start by answering the question you've asked. Yes, you can access memory malloced by the userspace from the kernel. I'm not sure of the technicalities of how, but if your kernel code runs in the context of the calling thread, it might be possible to simply use the user space pointer given to you.
Please don't do that, however.
The reason you shouldn't do that is that if the user space pointer is bad, or the memory is too short, or any other problem exists, the user space process may need to crash with a segmentation fault. Sadly, you are not running user space code, you are running kernel space. The kernel equivalent of segmentation fault is a kernel panic. Don't inflict that on your users.
A better approach is to use a mechanism where userspace writes the data once, and then the character device can simply use it. Having user space mmap the page was mentioned in the comments. A method that might be more standard to the way file descriptors work would be to implement splice_read in the device's fileops struct.
Now, splice is not an easy interface to work with, but the main advantage is that if your source is also splice aware, the user can pass data directly from the source to your driver without it ever passing through user space.
If you want to save the copies, I suggest you go with one of those solutions. Again, do not access the user supplied pointer directly unless you know what you're doing.
get_user_pages() API can be used to pin the user pages from swapped out from physical memory and kernel can access this memory area by accessing physical pages of corresponding virtual address.

how to pass a pointer to physical memory from kernel space to user space and map it to virtual space

I'm working on a driver-like code for a PCI device which. The communication is done through a buffer, i.e. I write to a buffer and device grabs data from it. Device writes to a buffer and I grad data from it. Here is where the problem occurs. In order for a device to write to this buffer it needs to have its physical address (not virtual one). My boss told me it is possible to do it if I write a kernel module and allocate memory using kmalloc.
Here are my questions.
How do I get access to this buffer from a user space, i.e. how do I pass a pointer to this buffer from a kernel space to a user space? Since all addresses in user space are virtual addresses, how do I convert a physical pointer to this buffer to a virtual one? As far as I understand I need to use ioctl but I don't how.
Any help is appreciated.
If this is a PCI device then it already has a physical address than you need to map. Your device has a class and a subclass id. Spin through all of your pci devices until you get a match on your class and subclass id then pull the bus address from that.
You then map the physical address using mmap
C++ app to talk to an FPGA over PCI in userland using mmap
I hope this helps.
Maybe you could use Netlink Socket API. This link could be of help to you How to use netlink socket to communicate with a kernel module?

How is the anatomy of memory mapped Kernel space

I try to understand the mechanism in Linux of mapping kernel mode space into user mode space using mmap.
First I have a loadable kernel module (LKM) which provides a character device with mmap-functionality. Then a user space application open the device and calls mmap the LKM allocate memory space on the heap of the LKM inside the kernel mode space (virtual high address). On user space side the data pointer points to a virtual low address.
The following picture shows how I imagine the anatomy of memory is. Is this right?
Please let me know if question is not clear, I will try to add more details.
Edit: The picture was edited regarding to Gil Hamilton. The black arrow now points to a physical address.
The drawing is missing out a few important underlying assumptions.
The kernel does not need to mmap() to access user space memory. If a user process has the memory, it's already mapped in the address space by definition. In that sense, the memory is already shared between user and kernel.
mmap() creates a new region in user's virtual address space, so that the address region can be populated by physical memory if later accessed. The actual allocation of memory and modifying the page table entry is done by the kernel.
mmap() only makes sense for managing user-half of the virtual address space. Kernel-half of the address space is managed completely differently.
Also, the kernel-half is shared by all processes in the system. Each process has its dedicated virtual address space, but the page tables are programmed in such a way that the page table entries for the kernel-half are set exactly the same for all processes.
Again, the kernel does not mmap() in order to access user space memory. mmap() is rather a service provided by kernel to user to modify the current mapping in user's virtual address space.
BTW, the kernel actually has a few ways to access user memory if it wants to.
First of all, the kernel has a dedicated region of kernel address space (as part of its kernel space) which maps the entirety of the physical memory present in consecutive fashion. (This is true in all 64-bit system. In 32-bit system the kernel has to 'remap' on-the-fly to achieve this.)
Second, if the kernel is entered via a system call or exception, not by hardware interrupt, you have valid process context, so the kernel can directly "dereference" user space pointer to get the correct value.
Third, if kernel wants to deference a user space pointer of a process while executing in a borrowed context such as in an interrupt handler, kernel can trace process's virtual address by traversing the vm_area_struct tree for permission and walking the page table to find out actual physical page frame.
You can check the memory regions by iterating through vma's "struct vm_area_struct" through current.
If you walk pagetables and derive mapped physical addresses for virtual addresses which is not related to user space then memory layout will be more clear.
Apart from this minor correction in this figure,
BSS is not a segment but section which is embed to Data segment, refer ELF specification for more details, linker script

How to make disk-based buffer just like memory?

I have seen a similar question on this site, but there is no helpful answer.
Scenario:
Following is the data transmission process ,
embedded devices-------->buffer-------->AWS(Cloud Storage)
Conditions:
Owing to the limit of embedded device, there is not enough memory to store the data.
My idea:
Using mmap() to allocate "memory" on disk, and manage the data relay on another lib, which is a opensource lib on github.
Problem:
However, I discover it just now that the it will occupy memory in the real memory. This method seems cannot solve my condition.
What's your idea ? Buddy...
All mmmap(2) does is to avoid an extra data copy operation between the user-space application's buffer and a kernel holding buffer. The portion of the real file which is mapped becomes part of the application's virtual address space and occupies physical memory in the block cache, even if you are using an anonymous map (a map without a backing file, the fd arg is set to -1).
So, by moving the mmap(2) window you can gain direct access to the kernel's buffer cache holding the file data. Use a 4K map window to correspond to the virtual memory map hardware feature and your file can be arbitrary size but only use a 4K map window into the file.
The good thing about mmap(2) is that you can open the file, create the mmap(2) window, and then close the file. Now you can access the file data using loads/stores treating the mapped window as a data array object.

Share memory from a Linux kernel module for a userspace process to access

I have a Linux kernel module that during it's initilisation routine writes a struct, 4KB in size into kernel memory. What I would like to do is make this memory shared, so that a single userspace process can have read-only access to this struct.
I've been told to avoid using IOCTLS as they aren't the best way to go about doing this, so from what I've read the best way to do it would be to use the function mmap, however I'm a bit confused over how to implement what I need in C.
I did look at using the function shmget, but it seems that this is designed for userspace apps that need IPC functionality.
Any advice, or even better a simple example would be greatly appreciated.
Thanks!
You cannot do this securely with a direct access mechanism like mmap, because then anyone can use it.
In Linux, user memory and kernel memory are independent and implemented in separate address spaces. The address spaces are virtualized, meaning that the addresses are abstracted from physical memory. Because the address spaces are virtualized, many can exist. In fact, the kernel itself resides in one address space, and each process resides in its own address space. These address spaces consist of virtual memory addresses, permitting many processes with independent address spaces to refer to a considerably smaller physical address space (the physical memory in the machine). Not only is this convenient, but it's also secure, because each address space is independent and isolated and therefore secure.
But there's a cost associated with this security. Because each process (and the kernel) can have identical addresses that refer to different regions of physical memory, it's not immediately possible to share memory. (source)

Resources